240 lines
7.7 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|