Last active
February 26, 2022 20:29
-
-
Save kraj0t/4abd0d3466fc38acd555f5d1cd8c5ab6 to your computer and use it in GitHub Desktop.
OrbitParentTool - a Unity EditorTool to orbit selected objects around their parents (my first test with EditorTools)
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 UnityEngine; | |
using UnityEditor; | |
using UnityEditor.EditorTools; | |
[EditorTool("Orbit Parent Tool", typeof(Transform))] | |
class OrbitParentTool : EditorTool | |
{ | |
[SerializeField] | |
private Texture2D _toolIcon; | |
private GUIContent _iconContent; | |
public override GUIContent toolbarIcon => _iconContent; | |
private void OnEnable() | |
{ | |
_iconContent = new GUIContent() | |
{ | |
image = _toolIcon, | |
text = "Orbit Parent Tool", | |
tooltip = "Orbit selected objects around their parents" | |
}; | |
} | |
// This is called for each window that your tool is active in. Put the functionality of your tool here. | |
public override void OnToolGUI(EditorWindow window) | |
{ | |
if (Selection.activeTransform == null) | |
{ | |
return; | |
} | |
var didUserInput = DrawAllHandles(out var deltaHandleRotation); | |
if (didUserInput) | |
{ | |
Undo.RecordObjects(Selection.transforms, "Orbit Parent"); | |
foreach (var transform in Selection.transforms) | |
{ | |
OrbitAroundParent(transform, deltaHandleRotation); | |
} | |
} | |
} | |
private bool DrawAllHandles(out Quaternion deltaHandleRotation) | |
{ | |
var didUserInput = false; | |
deltaHandleRotation = Quaternion.identity; | |
foreach (var t in Selection.transforms) | |
{ | |
var parentPos = t.parent.position; | |
var fromParent = t.position - parentPos; | |
var fromParentDir = fromParent.normalized; | |
float orbitDistance = Vector3.Dot(fromParentDir, fromParent); | |
if (Mathf.Approximately(orbitDistance, 0)) | |
{ | |
continue; | |
} | |
var handleDir = Vector3.Cross(fromParentDir, Vector3.forward); | |
var reconstructedForwardVector = Vector3.Cross(fromParentDir, handleDir); | |
var rotFromParent = Quaternion.LookRotation(fromParentDir, handleDir); | |
var oldHandleRotation = rotFromParent; | |
var newHandleRotation = rotFromParent; | |
EditorGUI.BeginChangeCheck(); | |
using (new Handles.DrawingScope(Color.green)) | |
{ | |
newHandleRotation = Handles.RotationHandle(oldHandleRotation, parentPos); | |
Handles.DrawWireArc(parentPos, reconstructedForwardVector, fromParentDir, 45, orbitDistance); | |
} | |
if (EditorGUI.EndChangeCheck()) | |
{ | |
deltaHandleRotation = newHandleRotation * Quaternion.Inverse(oldHandleRotation); | |
didUserInput = true; | |
} | |
} | |
return didUserInput; | |
} | |
private bool DrawAllHandles__(out Quaternion deltaHandleRotation) | |
{ | |
deltaHandleRotation = Quaternion.identity; | |
var t = Selection.activeTransform; | |
var parentPos = t.parent.position; | |
var fromParent = t.position - parentPos; | |
var fromParentDir = fromParent.normalized; | |
float orbitDistance = Vector3.Dot(fromParentDir, fromParent); | |
if (Mathf.Approximately(orbitDistance, 0)) | |
{ | |
return false; | |
} | |
var handleDir = Vector3.Cross(fromParentDir, Vector3.forward); | |
var reconstructedForwardVector = Vector3.Cross(fromParentDir, handleDir); | |
var rotFromParent = Quaternion.LookRotation(fromParentDir, handleDir); | |
var oldHandleRotation = rotFromParent; | |
var newHandleRotation = rotFromParent; | |
EditorGUI.BeginChangeCheck(); | |
using (new Handles.DrawingScope(Color.green)) | |
{ | |
newHandleRotation = Handles.RotationHandle(oldHandleRotation, parentPos); | |
Handles.DrawWireArc(parentPos, reconstructedForwardVector, fromParentDir, 45, orbitDistance); | |
} | |
if (EditorGUI.EndChangeCheck()) | |
{ | |
deltaHandleRotation = newHandleRotation * Quaternion.Inverse(oldHandleRotation); | |
return true; | |
} | |
return false; | |
} | |
private void OrbitAroundParent(Transform t, Quaternion deltaRotation) | |
{ | |
var parentPos = t.parent.position; | |
var fromParent = t.position - parentPos; | |
var rotatedFromParent = deltaRotation * fromParent; | |
t.position = parentPos + rotatedFromParent; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment