Net.Like.Xue.Tokyo/Assets/Plugins/MonKey Commander/Editor/MonKey/Sample Commands/MoveUtilities.cs

1153 lines
43 KiB
C#

#if UNITY_EDITOR
using MonKey.Editor.Internal;
using MonKey.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace MonKey.Editor.Commands
{
public static class MoveUtilities
{
[Command("Move Under Mouse",
Help = "Moves the selected objects to the position raycasted from the mouse",
QuickName = "MM", AlwaysShow = true,
DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "MoveMouseRaycast",
MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform")]
public static void MoveObjectUnderMouse()
{
MonkeyEditorUtils.AddSceneCommand(new RaycastSceneCommand(Selection.gameObjects, 0,
DirectionAxis.UP));
}
public class RaycastSceneCommand : ConfirmedCommand
{
public GameObject[] CachedObjectsToMove;
public float Offset = 0;
public float AngleOffset = 0;
public DirectionAxis AlignToNormal;
public DirectionAxis ForwardAlign;
public bool IgnoreInvisibleColliders;
private Transform[] selfAndChildren;
struct PositionRotation
{
public readonly Vector3 Position;
public readonly Quaternion Rotation;
public PositionRotation(Vector3 position, Quaternion rotation)
{
this.Position = position;
this.Rotation = rotation;
}
}
private readonly List<PositionRotation> previousPosRot = new List<PositionRotation>();
public RaycastSceneCommand(GameObject[] cachedObjectsToMove, float offset,
DirectionAxis alignToNormal)
{
// HideGUI = true;
ConfirmationMode = ActionConfirmationMode.ENTER_AND_CLICK;
SceneCommandName = "RayCast Mouse Position";
IgnoreInvisibleColliders = true;
CachedObjectsToMove = cachedObjectsToMove;
Offset = offset;
AlignToNormal = alignToNormal;
ForwardAlign = DirectionAxis.FORWARD;
List<Transform> allChildren = new List<Transform>();
foreach (GameObject gameObject in cachedObjectsToMove)
{
previousPosRot.Add(
new PositionRotation(gameObject.transform.position,
gameObject.transform.rotation));
allChildren.AddRange(gameObject.GetComponentsInChildren<Transform>());
}
selfAndChildren = allChildren.ToArray();
}
public override void DisplayParameters()
{
base.DisplayParameters();
DisplayFloatOption("Collision Offset", ref Offset);
DisplayFloatOption("Angle Offset", ref AngleOffset);
Enum en = AlignToNormal;
DisplayEnumOption("Up Axis", ref en);
AlignToNormal = (DirectionAxis) en;
en = ForwardAlign;
DisplayEnumOption("Forward Axis", ref en);
ForwardAlign = (DirectionAxis) en;
DisplayBoolOption("Ignore Invisible Colliders", ref IgnoreInvisibleColliders);
}
public override void Update()
{
base.Update();
bool collision = false;
Vector3 normal;
selfAndChildren = selfAndChildren.Where(_ => _).ToArray();
var position = MonkeyEditorUtils.GetMouseRayCastedPosition(selfAndChildren, Offset,
out collision, out normal, IgnoreInvisibleColliders);
if (collision)
{
// CachedObjectsToMove = CachedObjectsToMove.Where(_ => _).ToArray();
foreach (GameObject gameObject in CachedObjectsToMove)
{
if (!gameObject)
continue;
gameObject.transform.AlignTransformToCollision(position, normal, true, AlignToNormal,
ForwardAlign);
gameObject.transform.rotation =
Quaternion.AngleAxis(AngleOffset, normal) * gameObject.transform.rotation;
}
}
}
public override void Stop()
{
base.Stop();
List<PositionRotation> newPosRot =
new List<PositionRotation>(CachedObjectsToMove.Length);
foreach (var gameObject in CachedObjectsToMove)
{
if (!gameObject)
continue;
newPosRot.Add(
new PositionRotation(gameObject.transform.position,
gameObject.transform.rotation));
}
for (int i = 0; i < previousPosRot.Count; i++)
{
if (! CachedObjectsToMove[i])
continue;
CachedObjectsToMove[i].transform.position = previousPosRot[i].Position;
CachedObjectsToMove[i].transform.rotation = previousPosRot[i].Rotation;
}
int undoIndex = MonkeyEditorUtils.CreateUndoGroup("Mouse Raycast");
for (int i = 0; i < newPosRot.Count; i++)
{
if (! CachedObjectsToMove[i])
continue;
Undo.RecordObject(CachedObjectsToMove[i].transform, "Applying new position");
CachedObjectsToMove[i].transform.position = newPosRot[i].Position;
CachedObjectsToMove[i].transform.rotation = newPosRot[i].Rotation;
}
CachedObjectsToMove = CachedObjectsToMove.Where(_ => _).ToArray();
Selection.objects = CachedObjectsToMove.Convert(_ => _ as Object).ToArray();
Undo.CollapseUndoOperations(undoIndex);
}
}
[Command("Copy Position",
Help = "Copies the position of an object, by default the first object selected",
QuickName = "CP", DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "CopyPosition",
MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform")]
public static void CopyPosition()
{
MonkeyEditorUtils.AddSceneCommand(new TransformCopyCommand(Selection.gameObjects) {CopyPosition = true,});
}
public class TransformCopyCommand : TimedSceneCommand
{
public Transform TransformToCopy;
public bool LocalValuesOnly;
public bool CopyPosition;
public bool CopyRotation;
public bool CopyScale;
public List<GameObject> Targets = new List<GameObject>();
public TransformCopyCommand(params GameObject[] objs) : base(0)
{
Targets = new List<GameObject>(objs);
}
public override void DisplayParameters()
{
base.DisplayParameters();
SceneCommandName = "Copy Transform";
DisplayObjectOption("Transform To Copy", ref TransformToCopy);
DisplayBoolOption("Local Values Only", ref LocalValuesOnly);
DisplayBoolOption("Copy Position", ref CopyPosition);
DisplayBoolOption("Copy Rotation", ref CopyRotation);
DisplayBoolOption("Copy Scale", ref CopyScale);
DisplayObjectListOption("Targets", Targets);
}
public override void Update()
{
base.Update();
if (!TransformToCopy)
return;
foreach (GameObject o in Targets)
{
if (!o)
continue;
if (CopyPosition)
{
if (!LocalValuesOnly)
o.transform.position = TransformToCopy.position;
else
o.transform.localPosition = TransformToCopy.localPosition;
}
if (CopyRotation)
{
if (!LocalValuesOnly)
o.transform.rotation = TransformToCopy.rotation;
else
o.transform.localRotation = TransformToCopy.localRotation;
}
if (CopyScale)
{
if (!LocalValuesOnly)
o.transform.SetLossyGlobalScale(TransformToCopy.lossyScale);
else
o.transform.localScale = TransformToCopy.localScale;
}
}
}
}
[Command("Copy Rotation",
Help = "Copies the rotation of an object, by default the first object selected",
QuickName = "CR", DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "CopyRotation", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform")]
public static void CopyRotation()
{
MonkeyEditorUtils.AddSceneCommand(new TransformCopyCommand(Selection.gameObjects) {CopyRotation = true});
}
[Command("Copy Transform",
Help = "Copies the transform (scale ignored) of an object," +
" by default the first object selected",
QuickName = "CT", DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "CopyTransform", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform")]
public static void CopyTransform()
{
MonkeyEditorUtils.AddSceneCommand(new TransformCopyCommand(Selection.gameObjects)
{CopyPosition = true, CopyRotation = true, CopyScale = true});
}
private static GameObject ActiveObject()
{
return DefaultValuesUtilities.DefaultFirstGameObjectSelected();
}
public static void RaycastDirection(bool local, Transform t, Vector3 direction,
DirectionAxis axisToHitNormal)
{
RaycastHit hit;
if (Physics.Raycast(t.position, local ? t.TransformDirection(direction) : direction,
out hit))
{
Undo.RecordObject(t, "movement");
t.AlignTransformToCollision(hit.point, hit.normal, true, axisToHitNormal);
}
}
public static void RaycastDirection2D(bool local, Transform t, Vector3 direction,
DirectionAxis axisToHitNormal, GameObject[] objectsToIgnore)
{
RaycastHit2D[] hits = Physics2D.RaycastAll(t.position, local ? t.TransformDirection(direction) : direction)
.OrderByDescending(_ => (_.point - (Vector2) t.position).magnitude).ToArray();
foreach (var hit in hits)
{
if (objectsToIgnore.Contains(hit.transform.gameObject)
|| objectsToIgnore.Any(_ => _.GetComponentsInChildren<Transform>().Contains(hit.transform)))
continue;
if (hit)
{
Undo.RecordObject(t, "movement");
t.AlignTransformToCollision(hit.point, hit.normal, true, axisToHitNormal);
}
else
{
Debug.Log("Nope");
}
}
}
public static Axis[] DefaultLockedAxis()
{
return new[] {Axis.NONE};
}
public static GameObject FirstSelected()
{
if (!MonkeyEditorUtils.OrderedSelectedGameObjects.Any())
return null;
return MonkeyEditorUtils.OrderedSelectedGameObjects.ElementAt(0);
}
public static Vector3 ZeroVector()
{
return Vector3.zero;
}
[Command("Rotate Around",
"Rotates the selected objects around a specified one (by default the first selected)," +
" on one of its local axes", QuickName = "RA",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_GAME_OBJECT,
Category = "Transform")]
public static void RotateAround()
{
MonkeyEditorUtils.AddSceneCommand(new RotateAroundSceneCommand(Selection.gameObjects.ToList()));
}
public class RotateAroundSceneCommand : TimedSceneCommand
{
public float Angle = 90;
public GameObject ReferenceObject;
public Axis RotationAxis = Axis.Y;
public List<GameObject> ObjectsToRotate;
public RotateAroundSceneCommand(List<GameObject> objectsToRotate) : base(0)
{
ObjectsToRotate = objectsToRotate;
SceneCommandName = "Rotate Around";
}
public void Rotate()
{
int undoID = MonkeyEditorUtils.CreateUndoGroup("Rotate Around");
foreach (var gameObject in ObjectsToRotate)
{
if (gameObject == ReferenceObject)
continue;
Undo.RecordObject(gameObject.transform, "rotated");
gameObject.transform.RotateAround(ReferenceObject.transform.position,
ReferenceObject.transform.AxisToVector(RotationAxis, true), Angle);
}
Undo.CollapseUndoOperations(undoID);
}
public override void DisplayParameters()
{
base.DisplayParameters();
DisplayObjectOption("Rotation Center", ref ReferenceObject);
Enum en = RotationAxis;
DisplayEnumOption("Rotation Axis", ref en);
RotationAxis = (Axis) en;
DisplayFloatOption("Angle", ref Angle);
DisplayObjectListOption("Objects To Rotate", ObjectsToRotate);
DisplayButton("Rotate", Rotate);
}
}
[Command("Rotate",
"Rotates the selected objects on their own axes", QuickName = "RO",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_GAME_OBJECT,
Category = "Transform/Set")]
public static void Rotate(
[CommandParameter("The axis of rotation, as the local axis of the object")]
Axis rotationAxis = Axis.Y,
[CommandParameter("The angle of rotation, in degrees")]
float angle = 90,
[CommandParameter("Should the rotation be according to local axes")]
bool local = true)
{
int undoID = MonkeyEditorUtils.CreateUndoGroup("Rotate");
foreach (GameObject o in Selection.gameObjects)
{
Undo.RecordObject(o.transform, "rotated");
o.transform.Rotate(o.transform.AxisToVector(rotationAxis, local), angle);
}
Undo.CollapseUndoOperations(undoID);
}
[Command("Reset Transforms",
"Sets all the local values of the selected transform to default",
QuickName = "RT", DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "ResetTransforms", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform/Set")]
public static void ResetTransforms()
{
int undoID = MonkeyEditorUtils.CreateUndoGroup("Reset Transforms");
foreach (Transform transform in Selection.transforms)
{
Undo.RecordObject(transform, "reset");
transform.Reset();
}
Undo.CollapseUndoOperations(undoID);
}
[Command("Reset Rotation",
"Sets all the local rotations of the selected transform to default",
QuickName = "RR", DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "ResetRotations", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform/Set")]
public static void ResetRotations()
{
int undoID = MonkeyEditorUtils.CreateUndoGroup("Reset Transforms");
foreach (Transform transform in Selection.transforms)
{
Undo.RecordObject(transform, "reset");
transform.rotation = Quaternion.identity;
}
Undo.CollapseUndoOperations(undoID);
}
[Command("Set Parent", "Sets the parent of the selected objects", QuickName = "SP",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "SetParent", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform/Set")]
public static void SetParent(
[CommandParameter(Help = "The new parent of the selected objects",
ForceAutoCompleteUsage = true, PreventDefaultValueUsage = true)]
GameObject newParent)
{
int undoGroup = MonkeyEditorUtils.CreateUndoGroup("Change Parent");
foreach (var go in Selection.gameObjects)
{
Undo.SetTransformParent(go.transform, newParent.transform, "Reparent");
}
Undo.CollapseUndoOperations(undoGroup);
EditorGUIUtility.PingObject(newParent);
}
[Command("Set Parent Dynamic", "Sets the parent of the selected objects, as a scene command", QuickName = "SPD",
Category = "Transform/Set")]
public static void SetParentDynamic()
{
MonkeyEditorUtils.AddSceneCommand(new SetParentCommand(Selection.activeGameObject));
}
public class SetParentCommand : SceneCommand
{
public GameObject Parent;
public bool PreservePositionOnParenting = true;
public SetParentCommand(GameObject parent)
{
Parent = parent;
SceneCommandName = "Set Parent Dynamic";
}
public override void Update()
{
//do nothing
}
public override void DisplayParameters()
{
base.DisplayParameters();
base.DisplayObjectOption("Parent Object", ref Parent);
DisplayBoolOption("Preserve Position On Parenting", ref PreservePositionOnParenting);
DisplayMessage("Reparents Selected Objects under the specified parent");
DisplayButton("Reparent", ApplyFunction);
}
public void ApplyFunction()
{
foreach (var gameObject in Selection.gameObjects)
{
gameObject.transform.SetParent(Parent ? Parent.transform : null, PreservePositionOnParenting);
}
}
}
[Command("Set Pivot On Transform", QuickName = "MP",
Help = "set the position and rotation of the selected transforms as pivot, " +
"which means that their children will not move or rotate",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "MovePivot", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform")]
public static void MoveAsPivot()
{
MonkeyEditorUtils.AddSceneCommand(new PivotMoveSceneCommand(Selection.gameObjects));
}
public class PivotMoveSceneCommand : TimedSceneCommand
{
public List<GameObject> PivotsToMove = new List<GameObject>();
public Transform ToCopyOn;
public bool CopyRotation;
private Vector3 lastPosition;
private Quaternion lastRotation;
public PivotMoveSceneCommand(params GameObject[] pivots) : base(0)
{
SceneCommandName = "Move Pivot";
PivotsToMove.AddRange(pivots);
lastRotation = Quaternion.identity;
}
public override void DisplayParameters()
{
Transform previous = ToCopyOn;
DisplayObjectOption("Transform To Copy", ref ToCopyOn);
if (!ToCopyOn == previous)
{
Copy();
}
DisplayBoolOption("Copy Rotation", ref CopyRotation);
DisplayObjectListOption("Pivots To Move", PivotsToMove);
}
public override void Update()
{
if (!ToCopyOn)
return;
Vector3 distance = ToCopyOn.position - lastPosition;
var angle = Quaternion.Angle(ToCopyOn.rotation, lastRotation);
if (!ToCopyOn || !ToCopyOn.hasChanged ||
(distance.magnitude < 0.001f && (!CopyRotation || angle < 0.01f)))
return;
Copy();
}
private void Copy()
{
lastPosition = ToCopyOn.position;
lastRotation = ToCopyOn.rotation;
int undoID = MonkeyEditorUtils.CreateUndoGroup("Move Pivot");
foreach (var go in Selection.gameObjects)
{
if (go == ToCopyOn)
continue;
Transform[] children = go.GetComponentsInChildren<Transform>()
.Where(_ => _ != go.transform).ToArray();
foreach (Transform child in children)
{
Vector3 position = child.position;
Quaternion rotation = child.rotation;
Undo.SetTransformParent(child, null, "movedObjectsOut");
child.position = position;
child.rotation = rotation;
}
Undo.RecordObject(go.transform, "moving pivot");
go.transform.position = ToCopyOn.transform.position;
if (CopyRotation)
go.transform.rotation = ToCopyOn.transform.rotation;
foreach (Transform child in children)
{
Vector3 position = child.position;
Quaternion rotation = child.rotation;
Undo.SetTransformParent(child, go.transform, "movedObjectsOut");
child.position = position;
child.rotation = rotation;
}
}
Undo.CollapseUndoOperations(undoID);
}
}
[Command("Center Pivot", QuickName = "CPI",
Help = "Moves the selected transforms as pivot " +
"to the center of all their children transform",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_TRANSFORM,
MenuItemLink = "CenterPivot", MenuItemLinkTypeOwner = "MonkeyMenuItems",
Category = "Transform")]
public static void MovePivotToChildrenCenter()
{
int undoID = MonkeyEditorUtils.CreateUndoGroup("Move Pivot");
foreach (var go in Selection.gameObjects)
{
Transform[] children = go.GetComponentsInChildren<Transform>()
.Where(_ => _ != go.transform).ToArray();
Vector3[] childrenPos = children.Convert(_ => _.position).ToArray();
Vector3 weightCenter = new Vector3();
foreach (Transform child in children)
{
weightCenter += child.position;
}
weightCenter /= children.Length;
Undo.RecordObject(go.transform, "moving pivot");
go.transform.position = weightCenter;
for (int i = 0; i < children.Length; i++)
{
Undo.RecordObject(children[i], "moving");
children[i].position = childrenPos[i];
}
}
Undo.CollapseUndoOperations(undoID);
}
[Command("Move Assets To Folder", "Moves the selected asset to the specified folder",
QuickName = "MA", DefaultValidation = DefaultValidation.AT_LEAST_ONE_ASSET,
Category = "Assets")]
public static void MoveAssetToFolder(
[CommandParameter(Help = "The name of the folder to which the selection will be moved",
ForceAutoCompleteUsage = true, PreventDefaultValueUsage = true,
AutoCompleteMethodName = "FolderAutoComplete")]
string folderName)
{
foreach (var o in Selection.objects.Where(AssetDatabase.Contains))
{
string objectName = AssetDatabase.GetAssetPath(o).GetAssetNameFromPath(true);
string newFolder = folderName + "/" + objectName;
if (AssetDatabase.ValidateMoveAsset(AssetDatabase.GetAssetPath(o), newFolder).IsNullOrEmpty())
{
AssetDatabase.MoveAsset(AssetDatabase.GetAssetPath(o), newFolder);
EditorGUIUtility.PingObject(o);
}
else
{
Debug.LogWarningFormat("Monkey Warning: The asset {0} " +
"could not be moved to {1}.", o.name, newFolder);
Debug.LogWarning(AssetDatabase.ValidateMoveAsset(AssetDatabase.GetAssetPath(o), folderName));
}
}
}
[Command("Position In Circle",
Help =
"Positions all the selected objects in circle around the specified object (by default the first selected)",
QuickName = "PIC",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_GAME_OBJECT,
Category = "Transform")]
public static void PositionInCircle()
{
MonkeyEditorUtils.AddSceneCommand(new PositionInCircleSceneCommand(
MonkeyEditorUtils.OrderedSelectedGameObjects.ToList()
));
}
[Command("Resolve Intersections", "Moves the selected objects so that they do not overlap each other",
QuickName = "RI"
, DefaultValidation = DefaultValidation.AT_LEAST_TWO_GAME_OBJECTS)]
public static void ResolveIntersections(int iterations = 5)
{
var addedColliders = new List<Collider>();
TransformUndo undo = new TransformUndo();
undo.Register(Selection.gameObjects.Convert(_ => _.transform).ToArray());
foreach (var gameObject in Selection.gameObjects)
{
var renderers = gameObject.GetComponentsInChildren<MeshRenderer>();
if (renderers.Length == 0)
continue;
foreach (var renderer in renderers)
{
if (!renderer.GetComponent<Collider>())
{
var col = renderer.gameObject.AddComponent<MeshCollider>();
col.sharedMesh = renderer.GetComponent<MeshFilter>().sharedMesh;
col.convex = true;
addedColliders.Add(col);
}
}
}
for (int i = 0; i < iterations; i++)
{
EditorUtility.DisplayProgressBar("Resolving Intersection...",
"MonKey is resolving the intersections", (float) i / iterations);
foreach (var gameObject in Selection.gameObjects)
{
var renderers = gameObject.GetComponentsInChildren<MeshRenderer>();
foreach (var otherObj in Selection.gameObjects)
{
var otherRenderers = otherObj.GetComponentsInChildren<MeshRenderer>();
foreach (var renderer in renderers)
{
if (!renderer.gameObject.activeInHierarchy)
continue;
var collider = renderer.GetComponent<Collider>();
foreach (var otherRenderer in otherRenderers)
{
if (otherRenderer == renderer)
continue;
if (!otherRenderer.gameObject.activeInHierarchy)
continue;
var otherCollider = otherRenderer.GetComponent<Collider>();
if (Physics.ComputePenetration(collider, renderer.transform.position,
renderer.transform.rotation,
otherCollider, otherRenderer.transform.position, otherRenderer.transform.rotation,
out var dir, out var distance))
{
gameObject.transform.position += dir * distance;
}
}
}
}
}
EditorUtility.ClearProgressBar();
}
foreach (var collider in addedColliders)
{
Object.DestroyImmediate(collider);
}
int id = MonkeyEditorUtils.CreateUndoGroup("MonKey - Resolve Intersections");
undo.RecordUndo();
Undo.CollapseUndoOperations(id);
}
public class PositionInCircleSceneCommand : TimedSceneCommand
{
public GameObject CircleCenter;
public Axis CircleAxis;
public float CircleRadius = 1;
public float StartAngle = 0;
public float EndAngle = 360;
public bool LookAtCenter = false;
public Vector3 UpVector;
public Vector3 Offset;
public bool useLocal;
public List<GameObject> ObjectsToPosition;
public PositionInCircleSceneCommand(List<GameObject> objectsToPosition) : base(0)
{
SceneCommandName = "Position In Circle";
ObjectsToPosition = objectsToPosition;
TimeBetweenUpdate = 0.1f;
EndAngle = 360;
UpVector = Vector3.up;
}
public override void Update()
{
base.Update();
if (!CircleCenter || Mathf.Approximately(CircleRadius, 0))
return;
float angle = StartAngle * Mathf.Deg2Rad;
foreach (var gameObject in ObjectsToPosition)
{
if (gameObject == CircleCenter)
continue;
float xValue = CircleRadius * Mathf.Cos(angle);
float yValue = CircleRadius * Mathf.Sin(angle);
Vector3 radius = Vector3.zero;
Vector3 offset = Offset;
switch (CircleAxis)
{
case Axis.X:
radius = new Vector3(0, yValue, xValue);
break;
case Axis.Y:
radius = new Vector3(xValue, 0, yValue);
break;
case Axis.Z:
radius = new Vector3(xValue, yValue, 0);
break;
case Axis.NONE:
break;
default:
throw new ArgumentOutOfRangeException("circleAxis", CircleAxis, null);
}
offset += Offset;
gameObject.transform.position = CircleCenter.transform.position +
(useLocal
? CircleCenter.transform.TransformDirection(radius)
: radius) + (useLocal
? CircleCenter.transform.TransformDirection(offset)
: offset);
if (LookAtCenter)
{
gameObject.transform.LookAt(CircleCenter.transform.position,
(useLocal ? CircleCenter.transform.TransformDirection(UpVector) : UpVector));
}
angle += (EndAngle * Mathf.Deg2Rad) / (ObjectsToPosition.Count);
}
}
public override void DisplayParameters()
{
base.DisplayParameters();
DisplayObjectOption("Circle Center", ref CircleCenter);
Enum en = CircleAxis;
DisplayEnumOption("Circle Axis", ref en);
DisplayBoolOption("Use Local Axes", ref useLocal);
CircleAxis = (Axis) en;
DisplayFloatOption("Circle Radius", ref CircleRadius);
if (CircleRadius <= 0)
{
CircleRadius = 0.1f;
}
DisplayVectorOption("Offset", ref Offset);
DisplayBoolOption("Look At Center", ref LookAtCenter);
if (LookAtCenter)
DisplayVectorOption("Look At Up Axis", ref UpVector);
DisplayFloatOption("Start Angle", ref StartAngle);
DisplayFloatOption("End Angle", ref EndAngle);
DisplayObjectListOption("Objects To Position", ObjectsToPosition);
}
}
public static GameObject DefaultCenter()
{
return MonkeyEditorUtils.OrderedSelectedGameObjects.ElementAt(0);
}
/*
[Command("Move To Mouse Nearest Vertex",
"Moves the selected objects to the closest vertex to the mouse")]
public static void MoveToNearestVector()
{
MonkeyEditorUtils.AddSceneCommand(new VertexMoveSceneCommand(Selection.gameObjects));
}
public class VertexMoveSceneCommand : ConfirmedCommand
{
private Transform[] toMove;
private MethodInfo vertexFind;
public VertexMoveSceneCommand(GameObject[] toMove)
{
this.toMove = toMove.Convert(_=>_.transform).ToArray();
vertexFind = typeof(HandleUtility).GetMethod("FindNearestVertex",
BindingFlags.NonPublic | BindingFlags.Static);
}
public override void Update()
{
base.Update();
Vector3 nearestVertex=new Vector3();
//TODO not working: try to find a solution
object[] parameters = { MonkeyEditorUtils.MousePosition, toMove, nearestVertex };
object result = vertexFind.Invoke(null, parameters);
bool blResult = (bool)result;
if (blResult)
{
nearestVertex = (Vector3)parameters[2];
toMove = toMove.Where(_ => _).ToArray();
foreach (var transform in toMove)
{
transform.position = nearestVertex;
}
}
}
}
*/
[Command("Move Mirror",
"allows you to move selected objects mirrored relative to the distance of the active object to the centroid",
Category = "Transform")]
public static void MoveRelatedToCentroid()
{
MonkeyEditorUtils.AddSceneCommand(new MirrorRelatedToCentroidSceneCommand());
}
public class MirrorRelatedToCentroidSceneCommand : TimedSceneCommand
{
public GameObject ReferenceObject;
public List<GameObject> InfluencedObjects;
public Vector3 Centroid;
public Vector3 ReferenceDistance;
public MirrorRelatedToCentroidSceneCommand() : base(-1)
{
InfluencedObjects = new List<GameObject>(Selection.gameObjects);
Centroid = Vector3.zero;
for (int i = 0; i < InfluencedObjects.Count; i++)
{
Centroid += InfluencedObjects[i].transform.position;
}
Centroid /= InfluencedObjects.Count;
}
public override void Update()
{
base.Update();
if (Selection.activeGameObject != ReferenceObject)
{
ReferenceObject = Selection.activeGameObject;
ReferenceDistance = ReferenceObject.transform.position - Centroid;
return;
}
if (!ReferenceObject)
return;
var newDistance = ReferenceObject.transform.position - Centroid;
ReferenceDistance = newDistance;
for (var index = 0; index < InfluencedObjects.Count; index++)
{
var gameObject = InfluencedObjects[index];
if (gameObject != ReferenceObject && gameObject)
{
var distance = -ReferenceDistance;
gameObject.transform.position = Centroid + distance;
}
}
}
public override void OnSceneGUI()
{
base.OnSceneGUI();
Centroid = Handles.PositionHandle(Centroid, Quaternion.identity);
Handles.Label(Centroid + Vector3.up * 0.1f, "Centroid");
foreach (var gameObject in InfluencedObjects)
{
Handles.DrawDottedLine(gameObject.transform.position, Centroid, 0.1f);
}
}
public override void DisplayParameters()
{
base.DisplayParameters();
DisplayObjectListOption("Objects to Move", InfluencedObjects);
}
}
public static AssetNameAutoComplete FolderAutoComplete()
{
return new AssetNameAutoComplete() {DirectoryMode = true};
}
[MenuItem("Tools/MonKey Commander/Commands/Game Object/Move Up %&-")]
[Command("Move Siblings Up", Category = "BFT", QuickName = "MU")]
public static void MoveObjectUpInSiblings()
{
foreach (var o in Selection.gameObjects)
{
o.transform.SetSiblingIndex(Mathf.Max(0, o.transform.GetSiblingIndex() - 1));
}
}
[MenuItem("Tools/MonKey Commander/Commands/Game Object/Move Down %&=")]
[Command("Move Siblings Down", Category = "BFT", QuickName = "MD")]
public static void MoveObjectDownInSiblings()
{
foreach (var o in Selection.gameObjects)
{
o.transform.SetSiblingIndex(Mathf.Min(
o.transform.parent ? o.transform.parent.childCount - 1 : o.scene.rootCount - 1,
o.transform.GetSiblingIndex() + 1));
}
}
[Command("Move Pivot On Bounding Box",
"Moves the pivot transform anywhere within the bounding box of the object", QuickName = "MPB",
DefaultValidation = DefaultValidation.AT_LEAST_ONE_GAME_OBJECT)]
public static void MovePivotOnBoundingBox()
{
if (Selection.activeGameObject.transform.childCount == 0)
{
Debug.LogWarning("MonKey Warning:" +
" You are trying to move a a game object as a pivot " +
"but it is not a pivot since it doesn't have children objects: " +
"this command will not be executed");
return;
}
MonkeyEditorUtils.AddSceneCommand(new MovePivotSceneCommand());
}
public class MovePivotSceneCommand : TimedSceneCommand
{
public enum BoundingBoxSide
{
TOP,
BOTTOM,
LEFT,
RIGHT,
FRONT,
BACK
}
public enum BoundingBoxCorner
{
TOP_LEFT,
TOP_RIGHT,
TOP_CENTER,
BOTTOM_LEFT,
BOTTOM_RIGHT,
BOTTOM_CENTER,
CENTER_RIGHT,
CENTER_LEFT,
CENTER
}
public GameObject PivotToMove;
private Vector3 previousPosition;
// public BoundingBoxSide BoxSide;
public float XPercent = 0.5f;
public float YPercent = 0.5f;
public float ZPercent = 0.5f;
private Vector3 newPivot;
private Bounds bounds;
public MovePivotSceneCommand() : base(0)
{
SceneCommandName = "Move Pivot On BBox";
PivotToMove = Selection.activeGameObject;
TimeBetweenUpdate = 0;
}
public override void Update()
{
base.Update();
if (!PivotToMove)
return;
bounds = GetMaxBounds(PivotToMove);
var children = new List<Transform>(PivotToMove.GetComponentsInChildren<Transform>());
children.Remove(PivotToMove.transform);
List<Vector3> previousPos = new List<Vector3>(children.Count);
foreach (var transform in children)
{
previousPos.Add(transform.position);
}
newPivot = bounds.center + bounds.size.x * (XPercent - 0.5f) * Vector3.right +
bounds.size.y * (YPercent - 0.5f) * Vector3.up
+ bounds.size.z * (ZPercent - 0.5f) * Vector3.forward;
PivotToMove.transform.position = newPivot;
for (var i = 0; i < children.Count; i++)
{
var transform = children[i];
transform.position = previousPos[i];
}
}
public override void OnSceneGUI()
{
base.OnSceneGUI();
Handles.color = Color.blue;
Handles.SphereHandleCap(-1, newPivot, Quaternion.identity, .1f, EventType.Ignore);
Handles.DrawWireCube(bounds.center, bounds.size);
}
public override void DisplayParameters()
{
base.DisplayParameters();
DisplayObjectOption("Pivot To Move", ref PivotToMove);
DisplayFloatPercentOption("X Percent", ref XPercent);
DisplayFloatPercentOption("Y Percent", ref YPercent);
DisplayFloatPercentOption("Z Percent", ref ZPercent);
}
private Bounds GetMaxBounds(GameObject g)
{
var renderers = g.GetComponentsInChildren<Renderer>();
if (renderers.Length == 0)
{
return new Bounds(g.transform.position, Vector3.zero);
}
var first = renderers.First();
var b = first.bounds;
foreach (Renderer r in renderers)
{
if (r == first)
continue;
b.Encapsulate(r.bounds);
}
return b;
}
}
}
}
#endif