Created
February 20, 2019 17:08
-
-
Save dimmduh/0d8c0e697d57a330c8bfc78eb90d3d29 to your computer and use it in GitHub Desktop.
Unity - Rotate around point tool - test 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEditor; | |
using UnityEngine; | |
[InitializeOnLoad] | |
public class RotationHelper | |
{ | |
private static bool enabled; | |
static RotationHelper() | |
{ | |
EditorApplication.update += Update; | |
SceneView.onSceneGUIDelegate += OnSceneGUIDelegate; | |
} | |
private static int selectedAxis = 2; | |
private static Event lastEvent; | |
static void OnSceneGUIDelegate(SceneView sceneView) | |
{ | |
var e = Event.current; | |
if (e == null) | |
return; | |
lastEvent = e; | |
var controlId = 0; | |
if (enabled) | |
{ | |
controlId = GUIUtility.GetControlID(FocusType.Passive); | |
DrawUI(); | |
} | |
switch (e.type) | |
{ | |
case EventType.MouseDown: | |
if (e.button == 0 && enabled) | |
{ | |
GUIUtility.hotControl = controlId; | |
Event.current.Use(); | |
if (rotating) | |
{ | |
} | |
else | |
{ | |
rotating = true; | |
selectedPoint = lastSelectedPoint; | |
} | |
} | |
break; | |
case EventType.MouseDrag: | |
if (rotating && e.button == 0) | |
{ | |
var axis = Vector3.up; | |
if (selectedAxis == 1) | |
axis = selectedGo.transform.right; | |
if (selectedAxis == 3) | |
axis = selectedGo.transform.forward; | |
selectedGo.transform.RotateAround(selectedPoint, axis, 20f * e.delta.x * Time.smoothDeltaTime); | |
} | |
break; | |
case EventType.KeyDown: | |
if (e.keyCode == KeyCode.J) | |
{ | |
enabled = !enabled; | |
if (!enabled) | |
rotating = false; | |
} | |
if (e.keyCode == KeyCode.Alpha1) | |
selectedAxis = 1; | |
if (e.keyCode == KeyCode.Alpha2) | |
{ | |
selectedAxis = 2; | |
GUIUtility.hotControl = controlId; | |
Event.current.Use(); | |
} | |
if (e.keyCode == KeyCode.Alpha3) | |
selectedAxis = 3; | |
if (e.keyCode == KeyCode.Escape) | |
{ | |
if (rotating) | |
rotating = false; | |
else | |
enabled = false; | |
} | |
break; | |
} | |
} | |
static void Update() | |
{ | |
if (enabled) | |
HandleActiveMode(); | |
} | |
private static bool rotating; | |
private static Vector3 selectedPoint; | |
private static Vector3 lastSelectedPoint; | |
private static GameObject selectedGo; | |
private static Camera camera; | |
private static void HandleActiveMode() | |
{ | |
if (Selection.activeGameObject == null) | |
return; | |
if (Camera.current == null || lastEvent == null) | |
return; | |
camera = Camera.current; | |
selectedGo = Selection.activeGameObject; | |
var mousePos = new Vector3(lastEvent.mousePosition.x, camera.pixelHeight - lastEvent.mousePosition.y, 0); | |
if (!rotating) | |
{ | |
var ray = HandleUtility.GUIPointToWorldRay(mousePos); | |
// Debug.DrawRay(ray.origin, ray.direction * 2000f, Color.red, 2f); | |
var ray2 = camera.ScreenPointToRay(mousePos); | |
// Debug.DrawRay(ray2.origin, ray2.direction * 2000f, Color.blue, 2f); | |
lastSelectedPoint = FindClosestPoint(selectedGo, ray2); | |
} | |
} | |
private static void DrawUI() | |
{ | |
if (camera == null) | |
return; | |
Vector3 point; | |
if (rotating) | |
{ | |
Handles.color = Color.red; | |
point = selectedPoint; | |
} | |
else | |
{ | |
Handles.color = Color.blue; | |
point = lastSelectedPoint; | |
} | |
Handles.DrawSolidDisc(point, camera.transform.forward * -1f, 0.1f); | |
} | |
private static float DistanceToRay(Vector3 point, Ray ray) | |
{ | |
var distance = Vector3.Distance(ray.origin, point); | |
var angle = Vector3.Angle(ray.direction, point - ray.origin); | |
return (distance * Mathf.Sin(angle * Mathf.Deg2Rad)); | |
} | |
private static Vector3 FindClosestPoint(GameObject go, Ray ray) | |
{ | |
//collect vertices | |
var meshFilters = go.GetComponentsInChildren<MeshFilter>(); | |
var vertices = new List<Vector3>(); | |
foreach (var meshFilter in meshFilters) | |
{ | |
if (meshFilter.sharedMesh == null) | |
continue; | |
foreach (var vertex in meshFilter.sharedMesh.vertices) | |
{ | |
vertices.Add(meshFilter.transform.TransformPoint(vertex)); | |
} | |
} | |
//find | |
var closestVertex = Vector3.zero; | |
var minDistance = float.MaxValue; | |
foreach (var vertex in vertices) | |
{ | |
var dist = DistanceToRay(vertex, ray); | |
// Debug.Log(vertexPos + " d = " + dist); | |
if (dist < minDistance) | |
{ | |
closestVertex = vertex; | |
minDistance = dist; | |
} | |
} | |
return closestVertex; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment