Files
XRLib/Assets/Runtime Transform Gizmos/Scripts/Gizmos/Gizmo.cs
2025-06-19 19:24:30 +09:00

465 lines
20 KiB
C#

using UnityEngine;
using System;
using System.Collections.Generic;
namespace RTG
{
public delegate void GizmoPostEnabledHandler(Gizmo gizmo);
public delegate void GizmoPostDisabledHandler(Gizmo gizmo);
public delegate void GizmoPreUpdateBeginHandler(Gizmo gizmo);
public delegate void GizmoPostUpdateEndHandler(Gizmo gizmo);
public delegate void GizmoPreHoverEnterHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostHoverEnterHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPreHoverExitHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostHoverExitHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPreDragBeginHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostDragBeginHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPreDragUpdateHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostDragUpdateHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPreDragEndHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostDragEndHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPreHandlePickedHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostHandlePickedHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPreDragBeginAttemptHandler(Gizmo gizmo, int handleId);
public delegate void GizmoPostDragBeginAttemptHandler(Gizmo gizmo, int handleId);
public delegate Vector3 GizmoOffsetDragAxisModifyHandler(Gizmo gizmo, Vector3 relativeDragAxis, int handleId);
[Serializable]
public class Gizmo
{
public event GizmoPostEnabledHandler PostEnabled;
public event GizmoPostDisabledHandler PostDisabled;
public event GizmoPreUpdateBeginHandler PreUpdateBegin;
public event GizmoPostUpdateEndHandler PostUpdateEnd;
public event GizmoPreHoverEnterHandler PreHoverEnter;
public event GizmoPostHoverEnterHandler PostHoverEnter;
public event GizmoPreHoverExitHandler PreHoverExit;
public event GizmoPostHoverExitHandler PostHoverExit;
public event GizmoPreDragBeginHandler PreDragBegin;
public event GizmoPostDragBeginHandler PostDragBegin;
public event GizmoPreDragEndHandler PreDragEnd;
public event GizmoPostDragEndHandler PostDragEnd;
public event GizmoPreDragUpdateHandler PreDragUpdate;
public event GizmoPostDragUpdateHandler PostDragUpdate;
public event GizmoPreHandlePickedHandler PreHandlePicked;
public event GizmoPostHandlePickedHandler PostHandlePicked;
public event GizmoPreDragBeginAttemptHandler PreDragBeginAttempt;
public event GizmoPostDragBeginAttemptHandler PostDragBeginAttempt;
public event GizmoOffsetDragAxisModifyHandler OffsetDragAxisModify;
private bool _isEnabled = true;
private GizmoHandleCollection _handles;
private GizmoBehaviourCollection _behaviours = new GizmoBehaviourCollection();
private GizmoHoverInfo _hoverInfo = new GizmoHoverInfo();
private GizmoDragInfo _dragInfo = new GizmoDragInfo();
private IGizmoHandle _hoveredHandle;
private Priority _genericHoverPriority = new Priority();
private Priority _hoverPriority3D = new Priority();
private Priority _hoverPriority2D = new Priority();
private IGizmoDragSession _activeDragSession;
private GizmoTransform _transform = new GizmoTransform();
[NonSerialized]
private MoveGizmo _moveGizmo;
[NonSerialized]
private RotationGizmo _rotationGizmo;
[NonSerialized]
private ScaleGizmo _scaleGizmo;
[NonSerialized]
private UniversalGizmo _universalGizmo;
[NonSerialized]
private ObjectTransformGizmo _objectTransformGizmo;
[NonSerialized]
private SceneGizmo _sceneGizmo;
public static int InputDeviceDragButtonIndex { get { return 0; } }
public int NumHandles { get { return _handles.Count; } }
public Camera FocusCamera { get { return SceneGizmo == null ? RTFocusCamera.Get.TargetCamera : SceneGizmo.SceneGizmoCamera.Camera; } }
public bool IsEnabled { get { return _isEnabled; } }
public Priority GenericHoverPriority { get { return _genericHoverPriority; } }
public Priority HoverPriority3D { get { return _hoverPriority3D; } }
public Priority HoverPriority2D { get { return _hoverPriority2D; } }
public GizmoTransform Transform { get { return _transform; } }
public GizmoHoverInfo HoverInfo { get { return _hoverInfo; } }
public bool IsHovered { get { return _hoverInfo.IsHovered; } }
public int HoverHandleId { get { return _hoverInfo.HandleId; } }
public GizmoDimension HoverHandleDimension { get { return _hoverInfo.HandleDimension; } }
public Vector3 HoverPoint { get { return _hoverInfo.HoverPoint; } }
public GizmoDragInfo DragInfo { get { return _dragInfo; } }
public bool IsDragged { get { return _dragInfo.IsDragged; } }
public GizmoDragChannel ActiveDragChannel { get { return _dragInfo.DragChannel; } }
public int DragHandleId { get { return _dragInfo.HandleId; } }
public Vector3 DragBeginPoint { get { return _dragInfo.DragBeginPoint; } }
public GizmoDimension DragHandleDimension { get { return _dragInfo.HandleDimension; } }
public Vector3 TotalDragOffset { get { return _dragInfo.TotalOffset; } }
public Quaternion TotalDragRotation { get { return _dragInfo.TotalRotation; } }
public Vector3 TotalDragScale { get { return _dragInfo.TotalScale; } }
public Vector3 RelativeDragOffset { get { return _dragInfo.RelativeOffset; } }
public Quaternion RelativeDragRotation { get { return _dragInfo.RelativeRotation; } }
public Vector3 RelativeDragScale { get { return _dragInfo.RelativeScale; } }
public MoveGizmo MoveGizmo { get { return _moveGizmo; } }
public RotationGizmo RotationGizmo { get { return _rotationGizmo; } }
public ScaleGizmo ScaleGizmo { get { return _scaleGizmo; } }
public UniversalGizmo UniversalGizmo { get { return _universalGizmo; } }
public ObjectTransformGizmo ObjectTransformGizmo { get { return _objectTransformGizmo; } }
public SceneGizmo SceneGizmo { get { return _sceneGizmo; } }
public Gizmo()
{
_handles = new GizmoHandleCollection(this);
_hoverInfo.Reset();
_dragInfo.Reset();
}
public Camera GetWorkCamera()
{
return RTGizmosEngine.Get.PipelineStage == GizmosEnginePipelineStage.Render ?
RTGizmosEngine.Get.RenderStageCamera : FocusCamera;
}
public GizmoHandle CreateHandle(int id)
{
if (_handles.Contains(id)) return null;
var handle = new GizmoHandle(this, id);
_handles.Add(handle);
return handle;
}
public void SetEnabled(bool enabled)
{
if (enabled == _isEnabled) return;
if (!enabled)
{
EndDragSession();
_hoverInfo.Reset();
_hoveredHandle = null;
_isEnabled = false;
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoDisabled();
if (PostDisabled != null) PostDisabled(this);
}
else
{
_isEnabled = true;
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoEnabled();
if (PostEnabled != null) PostEnabled(this);
}
}
public BehaviourType AddBehaviour<BehaviourType>()
where BehaviourType : class, IGizmoBehaviour, new()
{
var newBehaviour = new BehaviourType();
AddBehaviour(newBehaviour);
return newBehaviour;
}
public bool AddBehaviour(IGizmoBehaviour behaviour)
{
if (behaviour == null || behaviour.Gizmo != null) return false;
GizmoBehaviorInitParams initParams = new GizmoBehaviorInitParams();
initParams.Gizmo = this;
behaviour.Init_SystemCall(initParams);
if (!_behaviours.Add(behaviour)) return false;
Type behaviourType = behaviour.GetType();
if (behaviourType == typeof(MoveGizmo)) _moveGizmo = behaviour as MoveGizmo;
else if (behaviourType == typeof(RotationGizmo)) _rotationGizmo = behaviour as RotationGizmo;
else if (behaviourType == typeof(ScaleGizmo)) _scaleGizmo = behaviour as ScaleGizmo;
else if (behaviourType == typeof(UniversalGizmo)) _universalGizmo = behaviour as UniversalGizmo;
else if (behaviourType == typeof(SceneGizmo)) _sceneGizmo = behaviour as SceneGizmo;
else if (behaviourType == typeof(ObjectTransformGizmo)) _objectTransformGizmo = behaviour as ObjectTransformGizmo;
behaviour.OnAttached();
behaviour.OnEnabled();
return true;
}
public bool RemoveBehaviour(IGizmoBehaviour behaviour)
{
if (behaviour == null ) return false;
if (behaviour == _moveGizmo) _moveGizmo = null;
else if (behaviour == _rotationGizmo) _rotationGizmo = null;
else if (behaviour == _scaleGizmo) _scaleGizmo = null;
else if (behaviour == _universalGizmo) _universalGizmo = null;
else if (behaviour == _sceneGizmo) _sceneGizmo = null;
else if (behaviour == _objectTransformGizmo) _objectTransformGizmo = null;
return _behaviours.Remove(behaviour);
}
public List<BehaviourType> GetBehavioursOfType<BehaviourType>()
where BehaviourType : class, IGizmoBehaviour
{
return _behaviours.GetBehavioursOfType<BehaviourType>();
}
public BehaviourType GetFirstBehaviourOfType<BehaviourType>()
where BehaviourType : class, IGizmoBehaviour
{
return _behaviours.GetFirstBehaviourOfType<BehaviourType>();
}
public IGizmoBehaviour GetFirstBehaviourOfType(Type behaviourType)
{
return _behaviours.GetFirstBehaviourOfType(behaviourType);
}
public List<GizmoHandleHoverData> GetAllHandlesHoverData(Ray hoverRay)
{
return _handles.GetAllHandlesHoverData(hoverRay);
}
public IGizmoHandle GetHandleById_SystemCall(int handleId)
{
return _handles.GetHandleById(handleId);
}
public void OnGUI_SystemCall()
{
if (!IsEnabled) return;
foreach (var behaviour in _behaviours)
if(behaviour.IsEnabled) behaviour.OnGUI();
}
public void OnUpdateBegin_SystemCall()
{
if (!IsEnabled) return;
if (PreUpdateBegin != null) PreUpdateBegin(this);
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoUpdateBegin();
}
public void OnUpdateEnd_SystemCall()
{
if (!IsEnabled) return;
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoUpdateEnd();
if (PostUpdateEnd != null) PostUpdateEnd(this);
}
public void UpdateHandleHoverInfo_SystemCall(GizmoHoverInfo hoverInfo)
{
if (!IsEnabled || IsDragged) return;
bool wasHovered = _hoverInfo.IsHovered;
int prevHoveredHandleId = _hoverInfo.HandleId;
_hoverInfo.Reset();
_hoveredHandle = null;
if (hoverInfo.IsHovered && hoverInfo.HandleId != GizmoHandleId.None)
{
_hoverInfo.IsHovered = true;
_hoverInfo.HandleId = hoverInfo.HandleId;
_hoverInfo.HoverPoint = hoverInfo.HoverPoint;
_hoveredHandle = _handles.GetHandleById(hoverInfo.HandleId);
_hoverInfo.HandleDimension = hoverInfo.HandleDimension;
}
if (wasHovered && !_hoverInfo.IsHovered)
{
if (PreHoverExit != null) PreHoverExit(this, prevHoveredHandleId);
foreach (var behaviour in _behaviours)
{
if (behaviour.IsEnabled)
behaviour.OnGizmoHoverExit(prevHoveredHandleId);
}
if (PostHoverExit != null) PostHoverExit(this, prevHoveredHandleId);
}
else if (!wasHovered && _hoverInfo.IsHovered)
{
if (PreHoverEnter != null) PreHoverEnter(this, _hoverInfo.HandleId);
foreach (var behaviour in _behaviours)
{
if (behaviour.IsEnabled)
behaviour.OnGizmoHoverEnter(_hoverInfo.HandleId);
}
if (PostHoverEnter != null) PostHoverEnter(this, _hoverInfo.HandleId);
}
else
if (wasHovered && _hoverInfo.IsHovered)
{
if (prevHoveredHandleId != _hoverInfo.HandleId)
{
if (PreHoverExit != null) PreHoverExit(this, prevHoveredHandleId);
foreach (var behaviour in _behaviours)
{
if (behaviour.IsEnabled)
behaviour.OnGizmoHoverExit(prevHoveredHandleId);
}
if (PostHoverExit != null) PostHoverExit(this, prevHoveredHandleId);
}
if (PreHoverEnter != null) PreHoverEnter(this, _hoverInfo.HandleId);
foreach (var behaviour in _behaviours)
{
if (behaviour.IsEnabled)
behaviour.OnGizmoHoverEnter(_hoverInfo.HandleId);
}
if (PostHoverEnter != null) PostHoverEnter(this, _hoverInfo.HandleId);
}
}
public void Render_SystemCall(Camera camera, Plane[] worldFrustumPlanes)
{
if (!IsEnabled || NumHandles == 0) return;
bool isSceneGizmoCamera = RTGizmosEngine.Get.IsSceneGizmoCamera(camera);
if (SceneGizmo == null && isSceneGizmoCamera) return;
else if (SceneGizmo != null && !isSceneGizmoCamera) return;
foreach (var behaviour in _behaviours)
if(behaviour.IsEnabled) behaviour.OnGizmoRender(camera);
}
public void HandleInputDeviceEvents_SystemCall()
{
if (!IsEnabled) return;
IInputDevice inputDevice = RTInputDevice.Get.Device;
if (inputDevice.WasButtonPressedInCurrentFrame(InputDeviceDragButtonIndex)) OnInputDevicePickButtonDown();
else if (inputDevice.WasButtonReleasedInCurrentFrame(InputDeviceDragButtonIndex)) OnInputDevicePickButtonUp();
if (inputDevice.WasMoved()) OnInputDeviceMoved();
}
private void OnInputDevicePickButtonDown()
{
if (_hoveredHandle != null)
{
if (PreHandlePicked != null) PreHandlePicked(this, _hoveredHandle.Id);
foreach (var behaviour in _behaviours)
{
if(behaviour.IsEnabled)
behaviour.OnGizmoHandlePicked(_hoveredHandle.Id);
}
if (PostHandlePicked != null) PostHandlePicked(this, _hoveredHandle.Id);
TryActivateDragSession();
}
}
private void OnInputDevicePickButtonUp()
{
EndDragSession();
}
private void EndDragSession()
{
if (_activeDragSession != null)
{
_activeDragSession.End();
_dragInfo.IsDragged = false;
if (PreDragEnd != null) PreDragEnd(this, _dragInfo.HandleId);
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoDragEnd(_dragInfo.HandleId);
int dragHandleId = _dragInfo.HandleId;
_dragInfo.Reset();
if (PostDragEnd != null) PostDragEnd(this, dragHandleId);
}
_activeDragSession = null;
}
private void OnInputDeviceMoved()
{
if (RTInputDevice.Get.Device.IsButtonPressed(InputDeviceDragButtonIndex))
{
if (_activeDragSession != null && _activeDragSession.IsActive)
{
if(_activeDragSession.Update())
{
_dragInfo.TotalOffset = _activeDragSession.TotalDragOffset;
_dragInfo.RelativeOffset = _activeDragSession.RelativeDragOffset;
_dragInfo.TotalRotation = _activeDragSession.TotalDragRotation;
_dragInfo.TotalScale = _activeDragSession.TotalDragScale;
_dragInfo.RelativeRotation = _activeDragSession.RelativeDragRotation;
_dragInfo.RelativeScale = _activeDragSession.RelativeDragScale;
float relativeDragOffset = _activeDragSession.TotalDragOffset.magnitude;
if (relativeDragOffset != 0.0f && OffsetDragAxisModify != null)
{
Vector3 relativeDragAxis = _activeDragSession.RelativeDragOffset.normalized;
relativeDragAxis = OffsetDragAxisModify(this, relativeDragAxis, _hoveredHandle.Id);
_dragInfo.RelativeOffset = relativeDragAxis * _activeDragSession.RelativeDragOffset.magnitude;
_dragInfo.TotalOffset = _activeDragSession.TotalDragOffset - _activeDragSession.RelativeDragOffset + _dragInfo.RelativeOffset;
}
if (PreDragUpdate != null) PreDragUpdate(this, _dragInfo.HandleId);
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoDragUpdate(_dragInfo.HandleId);
if (PostDragUpdate != null) PostDragUpdate(this, _dragInfo.HandleId);
}
}
}
}
private void TryActivateDragSession()
{
if (_hoveredHandle != null && _hoveredHandle.DragSession != null)
{
foreach (var behaviour in _behaviours)
{
if (behaviour.IsEnabled)
{
if (!behaviour.OnGizmoCanBeginDrag(_hoveredHandle.Id)) return;
}
}
if (PreDragBeginAttempt != null) PreDragBeginAttempt(this, _hoveredHandle.Id);
foreach (var behaviour in _behaviours)
{
if (behaviour.IsEnabled)
behaviour.OnGizmoAttemptHandleDragBegin(_hoveredHandle.Id);
}
if (PostDragBeginAttempt != null) PostDragBeginAttempt(this, _hoveredHandle.Id);
if (_hoveredHandle.DragSession.Begin())
{
_activeDragSession = _hoveredHandle.DragSession;
_dragInfo.IsDragged = true;
_dragInfo.DragChannel = _activeDragSession.DragChannel;
_dragInfo.HandleDimension = _hoverInfo.HandleDimension;
_dragInfo.HandleId = _hoverInfo.HandleId;
_dragInfo.DragBeginPoint = _hoverInfo.HoverPoint;
if (PreDragBegin != null) PreDragBegin(this, _dragInfo.HandleId);
foreach (var behaviour in _behaviours)
if (behaviour.IsEnabled) behaviour.OnGizmoDragBegin(_dragInfo.HandleId);
if (PostDragBegin != null) PostDragBegin(this, _dragInfo.HandleId);
}
}
}
}
}