123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- using System;
- using System.Reflection;
- using UnityEngine;
- namespace MeidoPhotoStudio.Plugin;
- public class CustomGizmo : GizmoRender
- {
- public GizmoMode Mode;
- private static readonly Camera Camera = GameMain.Instance.MainCamera.camera;
- #pragma warning disable SA1310, SA1311
- // TODO: Refactor reflection to using private members directly.
- private static new readonly FieldInfo is_drag_ = Utility.GetFieldInfo<GizmoRender>("is_drag_");
- #pragma warning restore SA1310, SA1311
- private new readonly FieldInfo beSelectedType = Utility.GetFieldInfo<GizmoRender>("beSelectedType");
- private GizmoType gizmoType;
- private Transform target;
- private bool hasAlternateTarget;
- private Transform positionTransform;
- private Vector3 positionOld = Vector3.zero;
- private Vector3 deltaPosition = Vector3.zero;
- private Vector3 deltaLocalPosition = Vector3.zero;
- private Quaternion rotationOld = Quaternion.identity;
- private Quaternion deltaRotation = Quaternion.identity;
- private Quaternion deltaLocalRotation = Quaternion.identity;
- private Vector3 deltaScale = Vector3.zero;
- private Vector3 scaleOld = Vector3.one;
- private GizmoType gizmoTypeOld;
- public event EventHandler GizmoDrag;
- public enum GizmoType
- {
- Rotate,
- Move,
- Scale,
- }
- public enum GizmoMode
- {
- Local,
- World,
- Global,
- }
- public static bool IsDrag
- {
- get => (bool)is_drag_.GetValue(null);
- private set => is_drag_.SetValue(null, value);
- }
- public GizmoType CurrentGizmoType
- {
- get => gizmoType;
- set
- {
- gizmoType = value;
- if (gizmoTypeOld == gizmoType)
- return;
- gizmoTypeOld = gizmoType;
- eAxis = gizmoType is GizmoType.Move;
- eScal = gizmoType is GizmoType.Scale;
- eRotate = gizmoType is GizmoType.Rotate;
- }
- }
- public bool IsGizmoDrag =>
- GizmoVisible && IsDrag && SelectedType is not 0;
- public bool GizmoVisible
- {
- get => Visible;
- set
- {
- if (value && IsDrag)
- IsDrag = false;
- Visible = value;
- }
- }
- private int SelectedType =>
- (int)beSelectedType.GetValue(this);
- public static CustomGizmo Make(Transform target, float scale = 0.25f, GizmoMode mode = GizmoMode.Local)
- {
- var gizmoGo = new GameObject($"[MPS Gizmo {target.gameObject.name}]");
- gizmoGo.transform.SetParent(target);
- var gizmo = gizmoGo.AddComponent<CustomGizmo>();
- gizmo.target = target;
- gizmo.lineRSelectedThick = 0.25f;
- gizmo.offsetScale = scale;
- gizmo.Mode = mode;
- gizmo.CurrentGizmoType = GizmoType.Rotate;
- return gizmo;
- }
- public override void Update()
- {
- BeginUpdate();
- base.Update();
- if (IsGizmoDrag)
- SetTargetTransform();
- SetTransform();
- EndUpdate();
- }
- public void SetAlternateTarget(Transform trans)
- {
- positionTransform = trans;
- hasAlternateTarget = trans != null;
- }
- private void BeginUpdate()
- {
- var rotation = transform.rotation;
- deltaPosition = transform.position - positionOld;
- deltaRotation = rotation * Quaternion.Inverse(rotationOld);
- deltaLocalPosition = transform.InverseTransformVector(deltaPosition);
- deltaLocalRotation = Quaternion.Inverse(rotationOld) * rotation;
- deltaScale = transform.localScale - scaleOld;
- }
- private void EndUpdate()
- {
- var transform = this.transform;
- positionOld = transform.position;
- rotationOld = transform.rotation;
- scaleOld = transform.localScale;
- }
- private void SetTargetTransform()
- {
- bool dragged;
- switch (Mode)
- {
- case GizmoMode.Local:
- target.position += target.transform.TransformVector(deltaLocalPosition).normalized
- * deltaLocalPosition.magnitude;
- target.rotation *= deltaLocalRotation;
- target.localScale += deltaScale;
- dragged = deltaLocalRotation != Quaternion.identity || deltaLocalPosition != Vector3.zero
- || deltaScale != Vector3.zero;
- break;
- case GizmoMode.World:
- case GizmoMode.Global:
- target.position += deltaPosition;
- target.rotation = deltaRotation * target.rotation;
- dragged = deltaRotation != Quaternion.identity || deltaPosition != Vector3.zero;
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- if (dragged)
- OnGizmoDrag();
- }
- private void SetTransform()
- {
- var transform = this.transform;
- transform.position = (hasAlternateTarget ? positionTransform : target).position;
- transform.localScale = Vector3.one;
- transform.rotation = Mode switch
- {
- GizmoMode.Local => target.rotation,
- GizmoMode.World => Quaternion.identity,
- GizmoMode.Global => Quaternion.LookRotation(transform.position - Camera.transform.position),
- _ => target.rotation,
- };
- }
- private void OnGizmoDrag() =>
- GizmoDrag?.Invoke(this, EventArgs.Empty);
- }
|