Files
unity-iso-tools/Assets/IsoTools/Editor/IsoObjectEditor.cs
2015-06-03 23:05:53 +06:00

181 lines
5.5 KiB
C#

using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
namespace IsoTools {
[CustomEditor(typeof(IsoObject)), CanEditMultipleObjects]
class IsoObjectEditor : Editor {
IDictionary<IsoObject, Vector3> _positions = new Dictionary<IsoObject, Vector3>();
IDictionary<IsoObject, float> _iso_zpositions = new Dictionary<IsoObject, float>();
Vector3 _center = Vector3.zero;
Vector3 _viewCenter = Vector3.zero;
void GrabPositions() {
_positions = targets
.Where(p => p as IsoObject)
.Select(p => p as IsoObject)
.ToDictionary(p => p, p => p.transform.position);
_iso_zpositions = targets
.Where(p => p as IsoObject)
.Select(p => p as IsoObject)
.ToDictionary(p => p, p => p.Position.z);
_center = _viewCenter = _positions.Aggregate(Vector3.zero, (AccIn, p) => {
return AccIn + p.Value;
}) / _positions.Count;
}
void AlignmentIsoObject(IsoObject iso_object) {
if ( IsoEditorWindow.Alignment ) {
iso_object.Position = iso_object.TilePosition;
iso_object.FixTransform();
}
}
float ZMoveIsoObjects(float delta) {
Undo.RecordObjects(_iso_zpositions.Keys.ToArray(), "Move");
return _iso_zpositions.Aggregate(0.0f, (AccIn, pair) => {
var iso_object = pair.Key;
var iso_orig_z = pair.Value;
iso_object.PositionZ = iso_orig_z + delta;
iso_object.FixTransform();
AlignmentIsoObject(iso_object);
var z_delta = iso_object.Position.z - iso_orig_z;
return Mathf.Abs(z_delta) > Mathf.Abs(AccIn) ? z_delta : AccIn;
});
}
Vector3 XYMoveIsoObjects(Vector3 delta) {
Undo.RecordObjects(_positions.Keys.ToArray(), "Move");
return _positions.Aggregate(Vector3.zero, (AccIn, pair) => {
var iso_object = pair.Key;
var iso_orig_p = pair.Value;
iso_object.transform.position = iso_orig_p + delta;
iso_object.FixIsoPosition();
AlignmentIsoObject(iso_object);
var pos_delta = iso_object.transform.position - iso_orig_p;
return pos_delta.magnitude > AccIn.magnitude ? pos_delta : AccIn;
});
}
void ZMoveSlider() {
var iso_world = GameObject.FindObjectOfType<IsoWorld>();
if ( iso_world ) {
Handles.color = Handles.zAxisColor;
var delta = Handles.Slider(_viewCenter, IsoUtils.Vec3OneY) - _viewCenter;
if ( Mathf.Abs(delta.y) > Mathf.Epsilon ) {
float tmp_y = ZMoveIsoObjects((_viewCenter.y - _center.y + delta.y) / iso_world.TileSize);
_viewCenter = _center + IsoUtils.Vec3FromY(tmp_y * iso_world.TileSize);
}
}
}
void XYMoveSlider(Color color, Vector3 dir) {
var iso_world = GameObject.FindObjectOfType<IsoWorld>();
if ( iso_world ) {
Handles.color = color;
var delta = Handles.Slider(_viewCenter, iso_world.IsoToScreen(dir)) - _viewCenter;
if ( delta.magnitude > Mathf.Epsilon ) {
_viewCenter = _center + XYMoveIsoObjects(_viewCenter - _center + delta);
}
}
}
void XYMoveRectangle() {
Handles.color = new Color(
Handles.zAxisColor.r,
Handles.zAxisColor.g,
Handles.zAxisColor.b,
0.3f);
Handles.DotCap(
0,
_viewCenter,
Quaternion.identity,
HandleUtility.GetHandleSize(_viewCenter) * 0.15f);
Handles.color = Handles.zAxisColor;
Handles.ArrowCap(
0,
_viewCenter,
Quaternion.identity,
HandleUtility.GetHandleSize(_viewCenter));
Handles.color = Handles.zAxisColor;
var delta = Handles.FreeMoveHandle(
_viewCenter,
Quaternion.identity,
HandleUtility.GetHandleSize(_viewCenter) * 0.15f,
Vector3.zero,
Handles.RectangleCap) - _viewCenter;
if ( delta.magnitude > Mathf.Epsilon ) {
_viewCenter = _center + XYMoveIsoObjects(_viewCenter - _center + delta);
}
}
void DrawTop(Vector3 pos, Vector3 size) {
var iso_world = GameObject.FindObjectOfType<IsoWorld>();
if ( iso_world ) {
var points = new Vector3[]{
iso_world.IsoToScreen(pos),
iso_world.IsoToScreen(pos + IsoUtils.Vec3FromX(size.x)),
iso_world.IsoToScreen(pos + IsoUtils.Vec3FromXY(size.x, size.y)),
iso_world.IsoToScreen(pos + IsoUtils.Vec3FromY(size.y)),
iso_world.IsoToScreen(pos)
};
Handles.DrawPolyLine(points);
}
}
void DrawVert(Vector3 pos, Vector3 size) {
var iso_world = GameObject.FindObjectOfType<IsoWorld>();
if ( iso_world ) {
Handles.DrawLine(
iso_world.IsoToScreen(pos),
iso_world.IsoToScreen(pos + IsoUtils.Vec3FromZ(size.z)));
}
}
void DrawCube(Vector3 pos, Vector3 size) {
Handles.color = Color.green;
DrawTop (pos - IsoUtils.Vec3FromZ(0.5f), size);
DrawTop (pos + IsoUtils.Vec3FromZ(size.z - 0.5f), size);
DrawVert(pos - IsoUtils.Vec3FromZ(0.5f), size);
DrawVert(pos - IsoUtils.Vec3FromZ(0.5f) + IsoUtils.Vec3FromX(size.x), size);
DrawVert(pos - IsoUtils.Vec3FromZ(0.5f) + IsoUtils.Vec3FromY(size.y), size);
}
void DrawTargetBounds() {
if ( IsoEditorWindow.ShowBounds ) {
var iso_object = target as IsoObject;
if ( iso_object ) {
DrawCube(iso_object.Position, iso_object.Size);
}
}
}
void OnEnable() {
GrabPositions();
}
void OnDisable() {
Tools.hidden = false;
}
void OnSceneGUI() {
if ( Tools.current == Tool.Move ) {
Tools.hidden = true;
ZMoveSlider();
XYMoveSlider(Handles.xAxisColor, IsoUtils.Vec3OneX);
XYMoveSlider(Handles.yAxisColor, IsoUtils.Vec3OneY);
XYMoveRectangle();
} else {
Tools.hidden = false;
}
DrawTargetBounds();
}
public override void OnInspectorGUI() {
DrawDefaultInspector();
GrabPositions();
}
}
} // namespace IsoTools