BITFALL/Assets/GSpawn - Level Designer/Scripts/Level Design/Gizmos/Object Transform Gizmos/ObjectTransformGizmo.cs

227 lines
7.7 KiB
C#

#if UNITY_EDITOR
using UnityEngine;
using System;
using System.Collections.Generic;
namespace GSpawn
{
public enum ObjectGizmoTransformPivot
{
Mesh = 0,
Center
}
public enum ObjectGizmoTransformSpace
{
Local = 0,
Global
}
[Serializable]
public abstract class ObjectTransformGizmo : PluginGizmo
{
[Flags]
protected enum Channels
{
None = 0,
Position = 1,
Rotation = 2,
Scale = 4,
}
protected Vector3 _newPosition;
protected Quaternion _newRotation;
protected Vector3 _newScale;
private Vector3 _centerPivot = Vector3.zero;
private ObjectScaleStartDataMap _scaleStartDataMap = new ObjectScaleStartDataMap();
private ObjectScale.ScaleConfig _scaleConfig = new ObjectScale.ScaleConfig();
[SerializeField]
private ObjectGizmoTransformPivot _transformPivot = ObjectGizmoTransformPivot.Center;
[SerializeField]
private ObjectGizmoTransformSpace _transformSpace = ObjectGizmoTransformSpace.Global;
[SerializeField]
protected GameObject _pivotObject;
[NonSerialized]
private List<GameObject> _targetObjects;
[NonSerialized]
private List<GameObject> _targetParents = new List<GameObject>();
public ObjectGizmoTransformPivot transformPivot { get { return _transformPivot; } set { _transformPivot = value; refreshPositionAndRotation(); } }
public ObjectGizmoTransformSpace transformSpace { get { return _transformSpace; } set { _transformSpace = value; refreshPositionAndRotation(); } }
public int calcNumTargetParents()
{
GameObjectEx.getParents(_targetObjects, _targetParents);
int numParents = _targetParents.Count;
_targetParents.Clear();
return numParents;
}
public void bindTargetObjects(List<GameObject> targetObjects)
{
_targetObjects = targetObjects;
refreshPositionAndRotation();
}
public void onTargetObjectTransformsChanged()
{
refreshPosition();
refreshRotation();
}
public void refreshPositionAndRotation()
{
refreshPosition();
refreshRotation();
}
public void refreshPosition()
{
if (_targetObjects == null) return;
if (_transformPivot == ObjectGizmoTransformPivot.Center ||
_pivotObject == null) position = calcTargetObjectsCenter();
else
if (_transformPivot == ObjectGizmoTransformPivot.Mesh)
position = _pivotObject.transform.position;
}
public virtual void refreshRotation()
{
if (_targetObjects == null) return;
if (_transformSpace == ObjectGizmoTransformSpace.Global ||
_pivotObject == null) rotation = Quaternion.identity;
else
if (_transformSpace == ObjectGizmoTransformSpace.Local)
rotation = _pivotObject.transform.rotation;
}
public void onTargetObjectsUpdated(GameObject pivotObject)
{
_pivotObject = pivotObject;
refreshPositionAndRotation();
}
public Vector3 calcTargetObjectsCenter()
{
if (_targetObjects == null) return Vector3.zero;
ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
boundsQConfig.volumelessSize = Vector3.zero;
boundsQConfig.objectTypes = GameObjectType.All;
Vector3 center = Vector3.zero;
int numObjects = 0;
foreach (var go in _targetObjects)
{
++numObjects;
OBB obb = ObjectBounds.calcWorldOBB(go, boundsQConfig);
if (obb.isValid) center += obb.center;
}
return numObjects != 0 ? center * (1.0f / (float)numObjects) : Vector3.zero;
}
protected override void doOnSceneGUI()
{
if (_targetObjects != null)
{
if (Event.current.type == EventType.MouseDown)
{
scale = Vector3.one;
_scaleStartDataMap.clear();
_centerPivot = position;
}
GameObjectEx.getParents(_targetObjects, _targetParents);
if (_targetObjects.Count != 0)
{
Channels channels = draw();
if ((channels & Channels.Position) != 0) moveObjects();
if ((channels & Channels.Rotation) != 0) rotateObjects();
if ((channels & Channels.Scale) != 0) scaleObjects();
if (channels != Channels.None) ObjectEvents.onObjectsTransformedByGizmo(this);
}
}
}
protected abstract Channels draw();
private void moveObjects()
{
Vector3 moveVector = _newPosition - position;
UndoEx.recordGameObjectTransforms(_targetParents);
foreach (var go in _targetParents)
go.transform.position += moveVector;
UndoEx.record(this);
position = _newPosition;
}
private void rotateObjects()
{
Quaternion rotQuat = QuaternionEx.createRelativeRotation(rotation, _newRotation);
if (transformPivot == ObjectGizmoTransformPivot.Center)
{
UndoEx.recordGameObjectTransforms(_targetParents);
foreach (var go in _targetParents)
go.transform.rotateAround(rotQuat, _centerPivot);
}
else
if (transformPivot == ObjectGizmoTransformPivot.Mesh)
{
UndoEx.recordGameObjectTransforms(_targetParents);
foreach (var go in _targetParents)
go.transform.rotation *= rotQuat;
}
UndoEx.record(this);
rotation = _newRotation;
}
private void scaleObjects()
{
if (_scaleStartDataMap.empty) _scaleStartDataMap.get(_targetParents, _centerPivot);
_scaleConfig.scaleFactor = Vector3.Scale(_newScale, scale.replaceZero(1.0f).getInverse());
_scaleConfig.scaleAxesRotation = rotation;
_scaleConfig.alignScaleFactorToScaleAxes = true;
if (transformPivot == ObjectGizmoTransformPivot.Center)
{
_scaleConfig.pivot = _centerPivot;
UndoEx.recordGameObjectTransforms(_targetParents);
foreach (var go in _targetParents)
{
_scaleConfig.scaleStartData = _scaleStartDataMap.getData(go);
ObjectScale.scale(go, _scaleConfig);
}
}
else
if (transformPivot == ObjectGizmoTransformPivot.Mesh)
{
UndoEx.recordGameObjectTransforms(_targetParents);
foreach (var go in _targetParents)
{
_scaleConfig.scaleStartData.localScale = _scaleStartDataMap.getLocalScale(go);
_scaleConfig.scaleStartData.pivotToPosition = Vector3.zero;
_scaleConfig.pivot = go.transform.position;
ObjectScale.scale(go, _scaleConfig);
}
}
UndoEx.record(this);
scale = _newScale;
}
}
}
#endif