Skip to content

Instantly share code, notes, and snippets.

@kraj0t
Last active February 26, 2022 20:29
Show Gist options
  • Save kraj0t/4abd0d3466fc38acd555f5d1cd8c5ab6 to your computer and use it in GitHub Desktop.
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)
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