2026-05-07 10:14:44 +02:00

240 lines
7.7 KiB
C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
namespace Wing.Gizmos
{
public delegate Vector3 GizmosValueChangedHandler(Vector3 before);
public class GizmosBase : MonoBehaviour
{
public event Action<EGizmosAxisType> AxisSelectedEvent;
public GameObject _lastSelected;
public float scale = 1.0f;
private Vector3 _lastMousePt;
private bool dirty = false;
private float _distanceFactor = 1.0f;
protected Dictionary<GameObject, EGizmosAxisType> _axisMap = new Dictionary<GameObject, EGizmosAxisType>();
// Use this for initialization
void Awake()
{
transform.localScale = Vector3.zero;
OnInit();
}
protected void ConstructAxis(string axisRoot, EGizmosAxisType type)
{
Transform go = transform.Find(axisRoot);
for (int i = 0; i < go.childCount; ++i)
{
GameObject obj = go.GetChild(i).gameObject;
obj.AddComponent<GizmosAxis>();
MeshRenderer r = obj.GetComponent<MeshRenderer>();
SetColor(r.material, type, false);
_axisMap[obj] = type;
}
}
private void SetColor(Material mat, EGizmosAxisType type, bool highlight)
{
if (!highlight)
{
float lightness = 1.0f;
if (type == EGizmosAxisType.X)
{
mat.color = new Color(lightness, 0.0f, 0.0f, 0.5f);
}
else if (type == EGizmosAxisType.Y)
{
mat.color = new Color(0.0f, lightness, 0.0f, 0.5f);
}
else if (type == EGizmosAxisType.Z)
{
mat.color = new Color(0.0f, 0.0f, lightness, 0.5f);
}
else if (type == EGizmosAxisType.LockX)
{
mat.color = new Color(lightness, 0.0f, 0.0f, 0.5f);
}
else if (type == EGizmosAxisType.LockY)
{
mat.color = new Color(0.0f, lightness, 0.0f, 0.5f);
}
else if (type == EGizmosAxisType.LockZ)
{
mat.color = new Color(0.0f, 0.0f, lightness, 0.5f);
}
else
{
mat.color = new Color(lightness, lightness, lightness, 1.0f);
}
}
else
{
mat.color = new Color(1.0f, 1.0f, 0.0f, 1.0f);
}
}
// Update is called once per frame
void Update()
{
Vector3 diff = transform.position - Camera.main.transform.position;
float d = diff.magnitude * scale * 0.05f;
_distanceFactor = ComputeScaleFactor(d);
transform.localScale = new Vector3(d, d, d);
}
protected virtual float ComputeScaleFactor(float d)
{
return d * 1.4f;
}
private void ChangeColor(GameObject go, bool highlight)
{
Transform root = go.transform.parent;
for (int i = 0; i < root.childCount; ++i)
{
GameObject childGO = root.GetChild(i).gameObject;
MeshRenderer r = childGO.GetComponent<MeshRenderer>();
EGizmosAxisType type = _axisMap[childGO];
SetColor(r.material, type, highlight);
}
}
public void OnMouseEnter(GameObject go)
{
if(_lastSelected != null)
{
ChangeColor(_lastSelected, false);
}
ChangeColor(go, true);
//Debug.Log("OnMouseEnter");
_lastSelected = go;
OnAxisSelected(_axisMap[go]);
}
public void OnMouseExit(GameObject go)
{
//ChangeColor(go, false);
// Debug.Log("OnMouse Exit");
}
public void OnMouseDown(GameObject go)
{
_lastMousePt = Input.mousePosition;
// Debug.Log("OnMouseDown");
OnAxisSelected(_axisMap[go]);
}
public void OnMouseUp(GameObject go)
{
OnDragEnd(go);
dirty = false;
}
public void OnMouseDrag(GameObject go)
{
Vector3 mousePt = Input.mousePosition;
Vector3 diff = mousePt - _lastMousePt;
if (diff.x + diff.y == 0)
{
return;
}
dirty = true;
EGizmosAxisType type = _axisMap[go];
float dx = 0;
float dy = 0;
float dz = 0;
float scensitivity = 0.02f;
Vector3 ogrinPos = transform.position;
Vector3 start = Camera.main.WorldToScreenPoint(ogrinPos);
start.z = 0;
if (type != EGizmosAxisType.CENTER)
{
Vector3 end = Camera.main.WorldToScreenPoint(ogrinPos + transform.right * 2);
end.z = 0;
Vector3 axisDir = end - start;
axisDir.Normalize();
dx = (axisDir.x * diff.x + axisDir.y * diff.y) * scensitivity;
end = Camera.main.WorldToScreenPoint(ogrinPos + transform.up * 2);
end.z = 0;
axisDir = end - start;
axisDir.Normalize();
dy = (axisDir.x * diff.x + axisDir.y * diff.y) * scensitivity;
end = Camera.main.WorldToScreenPoint(ogrinPos + transform.forward * 2);
end.z = 0;
axisDir = end - start;
axisDir.Normalize();
dz = (axisDir.x * diff.x + axisDir.y * diff.y) * scensitivity;
}
else
{
Vector3 end = start + Vector3.one;
end.z = 0;
Vector3 axisDir = end - start;
axisDir.Normalize();
dx = dy = dz = (axisDir.x * diff.x + axisDir.y * diff.y) * scensitivity;
}
Vector3 axisMask = Vector3.zero;
switch (type)
{
case EGizmosAxisType.X:
axisMask.x = 1;
break;
case EGizmosAxisType.Y:
axisMask.y = 1;
break;
case EGizmosAxisType.Z:
axisMask.z = 1;
break;
case EGizmosAxisType.LockX:
axisMask.y = 1;
axisMask.z = 1;
break;
case EGizmosAxisType.LockY:
axisMask.x = 1;
axisMask.z = 1;
break;
case EGizmosAxisType.LockZ:
axisMask.x = 1;
axisMask.y = 1;
break;
case EGizmosAxisType.CENTER:
axisMask.x = 1;
axisMask.y = 1;
axisMask.z = 1;
break;
}
dx = dx * axisMask.x * _distanceFactor;
dy = dy * axisMask.y * _distanceFactor;
dz = dz * axisMask.z * _distanceFactor;
OnDragDelta(go, dx, dy, dz);
_lastMousePt = mousePt;
}
protected virtual void OnInit() { }
protected virtual void OnDragDelta(GameObject go,float dx, float dy, float dz) { }
protected virtual void OnDragEnd(GameObject go) { }
protected virtual void OnAxisSelected(EGizmosAxisType type)
{
if(AxisSelectedEvent != null)
{
AxisSelectedEvent(type);
}
}
}
}