multiple worlds support done

This commit is contained in:
2016-12-19 02:30:30 +07:00
parent c5084b1596
commit 236e72d879
12 changed files with 2767 additions and 636 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ namespace IsoTools.Examples.Kenney {
static IsoRaycastHit[] _raycastBuffer = new IsoRaycastHit[16];
void Update () {
var iso_world = IsoWorld.Instance;
var iso_world = IsoWorld.GetWorld(0);
if ( iso_world && Input.GetMouseButtonDown(0) ) {
var iso_mouse_pos = iso_world.MouseIsoPosition();
var ray_from_iso_camera = iso_world.RayFromIsoCameraToIsoPoint(iso_mouse_pos);

View File

@@ -1,8 +1,17 @@
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
namespace IsoTools.Internal {
static class IsoEditorUtils {
// ---------------------------------------------------------------------
//
// Inspector
//
// ---------------------------------------------------------------------
public static void DoWithMixedValue(bool mixed, System.Action act) {
var last_show_mixed_value = EditorGUI.showMixedValue;
EditorGUI.showMixedValue = mixed;
@@ -21,5 +30,298 @@ namespace IsoTools.Internal {
EditorGUI.EndDisabledGroup();
}
}
public static void DrawWorldProperties(IsoWorld[] iso_worlds) {
if ( iso_worlds.Length > 0 ) {
var so = new SerializedObject(iso_worlds);
var so_prop = so.GetIterator();
if ( so_prop.NextVisible(true) ) {
while ( so_prop.NextVisible(true) ) {
EditorGUILayout.PropertyField(so_prop);
}
}
if ( GUI.changed ) {
so.ApplyModifiedProperties();
}
}
}
public static void DrawSelfWorldProperty(IsoWorld[] iso_worlds, string type_name) {
if ( iso_worlds.Length > 0 ) {
var mixed_world = iso_worlds.GroupBy(p => p).Count() > 1;
EditorGUILayout.Space();
IsoEditorUtils.DoWithEnabledGUI(false, () => {
IsoEditorUtils.DoWithMixedValue(mixed_world, () => {
EditorGUILayout.ObjectField(
"Current IsoWorld",
iso_worlds.First(),
typeof(IsoWorld),
true);
});
});
} else {
EditorGUILayout.HelpBox(
string.Format(
"Detached {0}\nNeed to be a child of IsoWorld",
type_name),
MessageType.Warning,
true);
}
}
// ---------------------------------------------------------------------
//
// Editor
//
// ---------------------------------------------------------------------
public static float ZMoveIsoObjects(
bool move,
IsoWorld iso_world,
Dictionary<IsoWorld, List<IsoObject>> all_iso_objects,
Dictionary<IsoWorld, List<IsoObject>> all_other_objects,
float delta)
{
List<IsoObject> iso_objects;
if ( all_iso_objects.TryGetValue(iso_world, out iso_objects) ) {
if ( move ) {
Undo.RecordObjects(
iso_objects.ToArray(),
iso_objects.Count > 1 ? "Move IsoObjects" : "Move IsoObject");
}
List<IsoObject> other_objects;
if ( all_other_objects.TryGetValue(iso_world, out other_objects) && other_objects.Count > 0 ) {
var snapping_z = false;
if ( IsSnapByObjectsEnabled(iso_world) ) {
foreach ( var iso_object in iso_objects ) {
var iso_orig_z = iso_object.positionZ;
var result_p_z = iso_orig_z + delta;
foreach ( var other in other_objects ) {
if ( IsoEditorUtils.IsSnapOverlaps(iso_object.positionX, iso_object.sizeX, other.positionX, other.sizeX) &&
IsoEditorUtils.IsSnapOverlaps(iso_object.positionY, iso_object.sizeY, other.positionY, other.sizeY) )
{
var new_snapping_z = !snapping_z && IsoEditorUtils.IsSnapOverlaps(result_p_z, iso_object.sizeZ, other.positionZ, other.sizeZ)
? IsoEditorUtils.SnapProcess(ref result_p_z, iso_object.sizeZ, other.positionZ, other.sizeZ)
: false;
if ( new_snapping_z ) {
delta = result_p_z - iso_orig_z;
snapping_z = true;
break;
}
}
}
if ( snapping_z ) {
break;
}
}
}
if ( IsSnapByCellsEnabled(iso_world) && !snapping_z ) {
foreach ( var iso_object in iso_objects ) {
var iso_orig_z = iso_object.positionZ;
var result_p_z = iso_orig_z + delta;
var new_snapping_z = IsoEditorUtils.SnapProcess(ref result_p_z, iso_object.sizeZ, iso_object.tilePositionZ, 1.0f);
if ( new_snapping_z ) {
delta = result_p_z - iso_orig_z;
snapping_z = true;
break;
}
}
}
}
return iso_objects.Aggregate(0.0f, (AccIn, iso_object) => {
var iso_orig_z = iso_object.positionZ;
var result_p_z = iso_orig_z + delta;
if ( move ) {
iso_object.positionZ = IsoUtils.FloatBeautifier(result_p_z);
}
var z_delta = result_p_z - iso_orig_z;
return Mathf.Abs(z_delta) > Mathf.Abs(AccIn) ? z_delta : AccIn;
});
}
return delta;
}
public static Vector3 XYMoveIsoObjects(
bool move,
IsoWorld iso_world,
Dictionary<IsoWorld, List<IsoObject>> all_iso_objects,
Dictionary<IsoWorld, List<IsoObject>> all_other_objects,
Vector3 iso_delta)
{
List<IsoObject> iso_objects;
if ( all_iso_objects.TryGetValue(iso_world, out iso_objects) ) {
if ( move ) {
Undo.RecordObjects(
iso_objects.ToArray(),
iso_objects.Count > 1 ? "Move IsoObjects" : "Move IsoObject");
}
List<IsoObject> other_objects;
if ( all_other_objects.TryGetValue(iso_world, out other_objects) && other_objects.Count > 0 ) {
var snapping_x = false;
var snapping_y = false;
if ( IsSnapByObjectsEnabled(iso_world) ) {
foreach ( var iso_object in iso_objects ) {
var iso_orig_p = iso_object.position;
var result_pos_iso = iso_orig_p + iso_delta;
foreach ( var other in other_objects ) {
if ( IsoEditorUtils.IsSnapOverlaps(iso_object.positionZ, iso_object.sizeZ, other.positionZ, other.sizeZ) ) {
var new_snapping_x = !snapping_x && IsoEditorUtils.IsSnapOverlaps(result_pos_iso.y, iso_object.sizeY, other.positionY, other.sizeY)
? IsoEditorUtils.SnapProcess(ref result_pos_iso.x, iso_object.sizeX, other.positionX, other.sizeX)
: false;
var new_snapping_y = !snapping_y && IsoEditorUtils.IsSnapOverlaps(result_pos_iso.x, iso_object.sizeX, other.positionX, other.sizeX)
? IsoEditorUtils.SnapProcess(ref result_pos_iso.y, iso_object.sizeY, other.positionY, other.sizeY)
: false;
if ( new_snapping_x || new_snapping_y ) {
if ( new_snapping_x ) {
snapping_x = true;
iso_delta.x = result_pos_iso.x - iso_orig_p.x;
iso_delta.y = result_pos_iso.y - iso_orig_p.y;
}
if ( new_snapping_y ) {
snapping_y = true;
iso_delta.x = result_pos_iso.x - iso_orig_p.x;
iso_delta.y = result_pos_iso.y - iso_orig_p.y;
}
if ( snapping_x && snapping_y ) {
break;
}
}
}
}
if ( snapping_x && snapping_y ) {
break;
}
}
}
if ( IsSnapByCellsEnabled(iso_world) && !snapping_x && !snapping_y ) {
foreach ( var iso_object in iso_objects ) {
var iso_orig_p = iso_object.position;
var result_pos_iso = iso_orig_p + iso_delta;
var new_snapping_x = IsoEditorUtils.SnapProcess(ref result_pos_iso.x, iso_object.sizeX, iso_object.tilePositionX, 1.0f);
var new_snapping_y = IsoEditorUtils.SnapProcess(ref result_pos_iso.y, iso_object.sizeY, iso_object.tilePositionY, 1.0f);
if ( new_snapping_x || new_snapping_y ) {
if ( new_snapping_x ) {
iso_delta.x = result_pos_iso.x - iso_orig_p.x;
iso_delta.y = result_pos_iso.y - iso_orig_p.y;
snapping_x = true;
}
if ( new_snapping_y ) {
iso_delta.x = result_pos_iso.x - iso_orig_p.x;
iso_delta.y = result_pos_iso.y - iso_orig_p.y;
snapping_y = true;
}
if ( snapping_x && snapping_y ) {
break;
}
}
}
}
}
return iso_objects.Aggregate(Vector3.zero, (AccIn, iso_object) => {
var iso_orig_p = iso_object.position;
var result_pos_iso = iso_orig_p + iso_delta;
if ( move ) {
iso_object.position = IsoUtils.VectorBeautifier(result_pos_iso);
}
var pos_delta = result_pos_iso - iso_orig_p;
return pos_delta.magnitude > AccIn.magnitude ? pos_delta : AccIn;
});
}
return iso_delta;
}
// ---------------------------------------------------------------------
//
// Gizmos
//
// ---------------------------------------------------------------------
public static Vector3 GizmoRectangle(Vector3 center) {
Handles.color = new Color(
Handles.zAxisColor.r,
Handles.zAxisColor.g,
Handles.zAxisColor.b,
0.3f);
Handles.DotCap(
0,
center,
Quaternion.identity,
HandleUtility.GetHandleSize(center) * 0.15f);
Handles.color = Handles.zAxisColor;
Handles.ArrowCap(
0,
center,
Quaternion.identity,
HandleUtility.GetHandleSize(center));
Handles.color = Handles.zAxisColor;
return Handles.FreeMoveHandle(
center,
Quaternion.identity,
HandleUtility.GetHandleSize(center) * 0.15f,
Vector3.zero,
Handles.RectangleCap);
}
public static Vector3 GizmoSlider(Color color, Vector3 pos, Vector3 dir) {
Handles.color = color;
return Handles.Slider(pos, dir);
}
// ---------------------------------------------------------------------
//
// Snapping
//
// ---------------------------------------------------------------------
const float SnapDistance = 0.2f;
public static bool SnapProcess(ref float min_a, float size_a, float min_b, float size_b) {
var max_a = min_a + size_a;
var max_b = min_b + size_b;
var result = false;
if ( IsSnapOverlaps(min_a, size_a, min_b, size_b) ) {
// |min_a max_a|min_b max_b|
if ( Mathf.Abs(max_a - min_b) < SnapDistance ) {
min_a = min_b - size_a;
result = true;
}
// |min_b max_b|min_a max_a|
if ( Mathf.Abs(max_b - min_a) < SnapDistance ) {
min_a = max_b;
result = true;
}
// |min_a_____max_a|
// |min_b__max_b|
if ( Mathf.Abs(min_a - min_b) < SnapDistance ) {
min_a = min_b;
result = true;
}
// |min_a_____max_a|
// |min_b__max_b|
if ( Mathf.Abs(max_a - max_b) < SnapDistance ) {
min_a = max_b - size_a;
result = true;
}
}
return result;
}
public static bool IsSnapOverlaps(float min_a, float size_a, float min_b, float size_b) {
return
min_a + size_a + SnapDistance >= min_b &&
min_a - SnapDistance <= min_b + size_b;
}
public static bool IsSnapByCellsEnabled(IsoWorld iso_world) {
return
iso_world &&
(iso_world.isSnapByCells != Event.current.control);
}
public static bool IsSnapByObjectsEnabled(IsoWorld iso_world) {
return
iso_world &&
(iso_world.isSnapByObjects != Event.current.control);
}
}
}

View File

@@ -7,42 +7,138 @@ namespace IsoTools.Internal {
[CustomEditor(typeof(IsoObject)), CanEditMultipleObjects]
class IsoObjectEditor : Editor {
IDictionary<IsoObject, Vector3> _positions = new Dictionary<IsoObject, Vector3>();
IDictionary<IsoObject, float> _isoZPositions = new Dictionary<IsoObject, float>();
IList<IsoObject> _otherObjects = new List<IsoObject>();
Vector3 _center = Vector3.zero;
Vector3 _viewCenter = Vector3.zero;
Dictionary<IsoWorld, List<IsoObject>> _isoObjects = new Dictionary<IsoWorld, List<IsoObject>>();
Dictionary<IsoWorld, List<IsoObject>> _otherObjects = new Dictionary<IsoWorld, List<IsoObject>>();
Dictionary<IsoWorld, Vector3> _viewCenters = new Dictionary<IsoWorld, Vector3>();
public static readonly float SnappingDistance = 0.2f;
// ---------------------------------------------------------------------
//
//
//
// ---------------------------------------------------------------------
static bool IsSnappingEnabled() {
var iso_world = IsoWorld.Instance;
return iso_world && (iso_world.isSnappingEnabled != Event.current.control);
}
void GrabPositions() {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
_positions = targets
void PrepareTargets() {
_isoObjects = targets
.OfType<IsoObject>()
.ToDictionary(p => p, p => p.transform.position);
_isoZPositions = targets
.OfType<IsoObject>()
.ToDictionary(p => p, p => p.position.z);
_center = _viewCenter = _positions.Aggregate(Vector3.zero, (AccIn, p) => {
return AccIn + IsoUtils.Vec3FromVec2(iso_world.IsoToScreen(p.Key.position + p.Key.size * 0.5f));
}) / _positions.Count;
} else {
_positions.Clear();
_isoZPositions.Clear();
}
.Where(p => p.isoWorld)
.GroupBy(p => p.isoWorld)
.ToDictionary(p => p.Key, p => p.ToList());
_viewCenters = _isoObjects.ToDictionary(
pair => pair.Key,
pair => {
var iso_world = pair.Key;
return pair.Value.Aggregate(Vector3.zero, (AccIn, p) => {
return AccIn + IsoUtils.Vec3FromVec2(
iso_world.IsoToScreen(p.position + p.size * 0.5f));
}) / pair.Value.Count;
});
_otherObjects = FindObjectsOfType<IsoObject>()
.Where(p => p.gameObject.activeInHierarchy && !_positions.ContainsKey(p))
.ToList();
.Where(p => p.IsActive() && p.isoWorld)
.Where(p => _isoObjects.ContainsKey(p.isoWorld))
.Where(p => !_isoObjects[p.isoWorld].Contains(p))
.GroupBy(p => p.isoWorld)
.ToDictionary(p => p.Key, p => p.ToList());
}
void DrawCustomInspector() {
var iso_worlds = _isoObjects.Keys.ToArray();
IsoEditorUtils.DrawWorldProperties(iso_worlds);
IsoEditorUtils.DrawSelfWorldProperty(iso_worlds, "IsoObject");
}
// ---------------------------------------------------------------------
//
//
//
// ---------------------------------------------------------------------
void DisableCustomTools() {
if ( Tools.hidden ) {
Tools.hidden = false;
Tools.current = Tool.Move;
}
}
void DrawCustomTools() {
if ( Tools.current == Tool.Move ) {
Tools.hidden = true;
ZMoveSliderTool();
XYMoveSliderTool(Handles.xAxisColor, IsoUtils.vec3OneX);
XYMoveSliderTool(Handles.yAxisColor, IsoUtils.vec3OneY);
XYMoveRectangleTool();
} else {
Tools.hidden = false;
}
}
void ZMoveSliderTool() {
foreach ( var iso_world in _viewCenters.Keys.ToList() ) {
EditorGUI.BeginChangeCheck();
var old_center = _viewCenters[iso_world];
var new_center = IsoEditorUtils.GizmoSlider(
Handles.zAxisColor,
old_center,
IsoUtils.vec3OneY);
if ( EditorGUI.EndChangeCheck() ) {
var old_delta = new_center - old_center;
var new_delta = IsoEditorUtils.ZMoveIsoObjects(
true,
iso_world,
_isoObjects,
_otherObjects,
old_delta.y / iso_world.tileHeight) * iso_world.tileHeight;
_viewCenters[iso_world] = old_center + IsoUtils.Vec3FromY(new_delta);
}
}
}
void XYMoveSliderTool(Color color, Vector3 dir) {
foreach ( var iso_world in _viewCenters.Keys.ToList() ) {
EditorGUI.BeginChangeCheck();
var old_center = _viewCenters[iso_world];
var new_center = IsoEditorUtils.GizmoSlider(
color,
old_center,
iso_world.IsoToScreen(dir));
if ( EditorGUI.EndChangeCheck() ) {
var old_delta = new_center - old_center;
var new_delta = iso_world.IsoToScreen(IsoEditorUtils.XYMoveIsoObjects(
true,
iso_world,
_isoObjects,
_otherObjects,
iso_world.ScreenToIso(old_delta)));
_viewCenters[iso_world] = old_center + IsoUtils.Vec3FromVec2(new_delta);
}
}
}
void XYMoveRectangleTool() {
foreach ( var iso_world in _viewCenters.Keys.ToList() ) {
EditorGUI.BeginChangeCheck();
var old_center = _viewCenters[iso_world];
var new_center = IsoEditorUtils.GizmoRectangle(old_center);
if ( EditorGUI.EndChangeCheck() ) {
var old_delta = new_center - old_center;
var new_delta = iso_world.IsoToScreen(IsoEditorUtils.XYMoveIsoObjects(
true,
iso_world,
_isoObjects,
_otherObjects,
iso_world.ScreenToIso(old_delta)));
_viewCenters[iso_world] = old_center + IsoUtils.Vec3FromVec2(new_delta);
}
}
}
// ---------------------------------------------------------------------
//
//
//
// ---------------------------------------------------------------------
void DirtyTargetPosition() {
if ( targets.Length == 1 && (target is IsoObject) && (target as IsoObject).gameObject.activeInHierarchy ) {
if ( targets.Length == 1 && (target is IsoObject) && (target as IsoObject).IsActive() ) {
var position_prop = serializedObject.FindProperty("_position");
if ( position_prop != null ) {
var last_value = position_prop.vector3Value;
@@ -56,311 +152,29 @@ namespace IsoTools.Internal {
}
}
void DrawWorldEditorProperties() {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
var so = new SerializedObject(iso_world);
EditorGUILayout.PropertyField(so.FindProperty("_showIsoBounds"));
EditorGUILayout.PropertyField(so.FindProperty("_showScreenBounds"));
EditorGUILayout.PropertyField(so.FindProperty("_showDepends"));
EditorGUILayout.PropertyField(so.FindProperty("_snappingEnabled"));
if ( GUI.changed ) {
so.ApplyModifiedProperties();
}
}
}
void DrawSelfInfoProperties() {
var iso_objects = targets.OfType<IsoObject>();
if ( iso_objects.Count() > 0 ) {
var mixed_world = iso_objects.GroupBy(p => p.isoWorld).Count() > 1;
IsoEditorUtils.DoWithEnabledGUI(false, () => {
IsoEditorUtils.DoWithMixedValue(mixed_world, () => {
EditorGUILayout.ObjectField("Current Object World", iso_objects.First().isoWorld, typeof(IsoWorld), true);
});
});
}
}
static bool SnappingProcess(ref float min_a, float size_a, float min_b, float size_b) {
var max_a = min_a + size_a;
var max_b = min_b + size_b;
var result = false;
if ( IsSnappingIntersect(min_a, size_a, min_b, size_b) ) {
// |min_a max_a|min_b max_b|
if ( Mathf.Abs(max_a - min_b) < SnappingDistance ) {
min_a = min_b - size_a;
result = true;
}
// |min_b max_b|min_a max_a|
if ( Mathf.Abs(max_b - min_a) < SnappingDistance ) {
min_a = max_b;
result = true;
}
// |min_a_____max_a|
// |min_b__max_b|
if ( Mathf.Abs(min_a - min_b) < SnappingDistance ) {
min_a = min_b;
result = true;
}
// |min_a_____max_a|
// |min_b__max_b|
if ( Mathf.Abs(max_a - max_b) < SnappingDistance ) {
min_a = max_b - size_a;
result = true;
}
}
return result;
}
static bool IsSnappingIntersect(float min_a, float size_a, float min_b, float size_b) {
return
min_a + size_a + SnappingDistance >= min_b &&
min_a - SnappingDistance <= min_b + size_b;
}
public static float ZMoveIsoObjects(
bool move,
float delta,
IDictionary<IsoObject, float> iso_z_positions,
IList<IsoObject> other_objects)
{
if ( move ) {
Undo.RecordObjects(
iso_z_positions.Keys.ToArray(),
iso_z_positions.Count > 1 ? "Move IsoObjects" : "Move IsoObject");
}
if ( IsSnappingEnabled() ) {
var snapping_z = false;
foreach ( var pair in iso_z_positions ) {
var iso_object = pair.Key;
var iso_orig_z = pair.Value;
var result_p_z = iso_orig_z + delta;
foreach ( var other in other_objects ) {
if ( IsSnappingIntersect(iso_object.positionX, iso_object.sizeX, other.positionX, other.sizeX) &&
IsSnappingIntersect(iso_object.positionY, iso_object.sizeY, other.positionY, other.sizeY) )
{
var new_snapping_z = !snapping_z && IsSnappingIntersect(result_p_z, iso_object.sizeZ, other.positionZ, other.sizeZ)
? SnappingProcess(ref result_p_z, iso_object.sizeZ, other.positionZ, other.sizeZ)
: false;
if ( new_snapping_z ) {
delta = result_p_z - iso_orig_z;
snapping_z = true;
}
}
}
if ( snapping_z ) {
break;
}
}
if ( !snapping_z ) {
var pair = iso_z_positions.First();
var iso_object = pair.Key;
var iso_orig_z = pair.Value;
var result_p_z = iso_orig_z + delta;
var new_snapping_z = SnappingProcess(ref result_p_z, iso_object.sizeZ, iso_object.tilePositionZ, 1.0f);
if ( new_snapping_z ) {
delta = result_p_z - iso_orig_z;
snapping_z = true;
}
}
}
return iso_z_positions.Aggregate(0.0f, (AccIn, pair) => {
var iso_object = pair.Key;
var iso_orig_z = pair.Value;
var result_p_z = iso_orig_z + delta;
if ( move ) {
iso_object.positionZ = IsoUtils.FloatBeautifier(result_p_z);
}
var z_delta = result_p_z - iso_orig_z;
return Mathf.Abs(z_delta) > Mathf.Abs(AccIn) ? z_delta : AccIn;
});
}
public static Vector3 XYMoveIsoObjects(
bool move,
Vector3 delta,
IDictionary<IsoObject, Vector3> positions,
IList<IsoObject> other_objects)
{
if ( move ) {
Undo.RecordObjects(
positions.Keys.ToArray(),
positions.Count > 1 ? "Move IsoObjects" : "Move IsoObject");
}
if ( IsSnappingEnabled() ) {
var snapping_x = false;
var snapping_y = false;
foreach ( var pair in positions ) {
var iso_object = pair.Key;
var iso_orig_p = pair.Value;
var result_pos = iso_orig_p + delta;
var result_pos_iso = IsoWorld.Instance.ScreenToIso(result_pos, iso_object.positionZ);
foreach ( var other in other_objects ) {
if ( IsSnappingIntersect(iso_object.positionZ, iso_object.sizeZ, other.positionZ, other.sizeZ) ) {
var new_snapping_x = !snapping_x && IsSnappingIntersect(result_pos_iso.y, iso_object.sizeY, other.positionY, other.sizeY)
? SnappingProcess(ref result_pos_iso.x, iso_object.sizeX, other.positionX, other.sizeX)
: false;
var new_snapping_y = !snapping_y && IsSnappingIntersect(result_pos_iso.x, iso_object.sizeX, other.positionX, other.sizeX)
? SnappingProcess(ref result_pos_iso.y, iso_object.sizeY, other.positionY, other.sizeY)
: false;
if ( new_snapping_x || new_snapping_y ) {
result_pos = IsoWorld.Instance.IsoToScreen(result_pos_iso);
if ( new_snapping_x ) {
delta.x = result_pos.x - iso_orig_p.x;
delta.y = result_pos.y - iso_orig_p.y;
snapping_x = true;
}
if ( new_snapping_y ) {
delta.x = result_pos.x - iso_orig_p.x;
delta.y = result_pos.y - iso_orig_p.y;
snapping_y = true;
}
}
}
}
if ( snapping_x && snapping_y ) {
break;
}
}
if ( !snapping_x && !snapping_y ) {
var pair = positions.First();
var iso_object = pair.Key;
var iso_orig_p = pair.Value;
var result_pos = iso_orig_p + delta;
var result_pos_iso = IsoWorld.Instance.ScreenToIso(result_pos, iso_object.positionZ);
var new_snapping_x = SnappingProcess(ref result_pos_iso.x, iso_object.sizeX, iso_object.tilePositionX, 1.0f);
var new_snapping_y = SnappingProcess(ref result_pos_iso.y, iso_object.sizeY, iso_object.tilePositionY, 1.0f);
if ( new_snapping_x || new_snapping_y ) {
result_pos = IsoWorld.Instance.IsoToScreen(result_pos_iso);
if ( new_snapping_x ) {
delta.x = result_pos.x - iso_orig_p.x;
delta.y = result_pos.y - iso_orig_p.y;
snapping_x = true;
}
if ( new_snapping_y ) {
delta.x = result_pos.x - iso_orig_p.x;
delta.y = result_pos.y - iso_orig_p.y;
snapping_y = true;
}
}
}
}
return positions.Aggregate(Vector3.zero, (AccIn, pair) => {
var iso_object = pair.Key;
var iso_orig_p = pair.Value;
var result_pos = iso_orig_p + delta;
if ( move ) {
var new_iso_pos = IsoWorld.Instance.ScreenToIso(
result_pos,
iso_object.positionZ);
iso_object.position = IsoUtils.VectorBeautifier(new_iso_pos);
}
var pos_delta = result_pos - iso_orig_p;
return pos_delta.magnitude > AccIn.magnitude ? pos_delta : AccIn;
});
}
void ZMoveSlider() {
var iso_world = IsoWorld.Instance;
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(
true,
(_viewCenter.y - _center.y + delta.y) / iso_world.tileHeight,
_isoZPositions,
_otherObjects);
_viewCenter = _center + IsoUtils.Vec3FromY(tmp_y * iso_world.tileHeight);
}
}
}
void XYMoveSlider(Color color, Vector3 dir) {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
Handles.color = color;
var delta = Handles.Slider(_viewCenter, iso_world.IsoToScreen(dir)) - _viewCenter;
if ( delta.magnitude > Mathf.Epsilon ) {
_viewCenter = _center + XYMoveIsoObjects(
true,
_viewCenter - _center + delta,
_positions,
_otherObjects);
}
}
}
void XYMoveRectangle() {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
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(
true,
_viewCenter - _center + delta,
_positions,
_otherObjects);
}
}
}
//
// ---------------------------------------------------------------------
//
// Messages
//
// ---------------------------------------------------------------------
void OnEnable() {
GrabPositions();
PrepareTargets();
}
void OnDisable() {
if ( Tools.hidden ) {
Tools.hidden = false;
Tools.current = Tool.Move;
}
DisableCustomTools();
}
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;
}
DrawCustomTools();
}
public override void OnInspectorGUI() {
DrawDefaultInspector();
GrabPositions();
PrepareTargets();
DirtyTargetPosition();
DrawWorldEditorProperties();
DrawSelfInfoProperties();
DrawDefaultInspector();
DrawCustomInspector();
}
}
}

View File

@@ -0,0 +1,165 @@
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
namespace IsoTools.Internal {
[CustomEditor(typeof(IsoParent)), CanEditMultipleObjects]
public class IsoParentEditor : Editor {
Dictionary<IsoWorld, List<IsoParent>> _isoParents = new Dictionary<IsoWorld, List<IsoParent>>();
Dictionary<IsoWorld, List<IsoObject>> _isoObjects = new Dictionary<IsoWorld, List<IsoObject>>();
Dictionary<IsoWorld, List<IsoObject>> _otherObjects = new Dictionary<IsoWorld, List<IsoObject>>();
Dictionary<IsoWorld, Vector3> _viewCenters = new Dictionary<IsoWorld, Vector3>();
// ---------------------------------------------------------------------
//
//
//
// ---------------------------------------------------------------------
void PrepareTargets() {
_isoParents = targets
.OfType<IsoParent>()
.Where(p => p.isoWorld)
.GroupBy(p => p.isoWorld)
.ToDictionary(p => p.Key, p => p.ToList());
_isoObjects = _isoParents.ToDictionary(
p => p.Key,
p => p.Value.SelectMany(t => t.GetComponentsInChildren<IsoObject>(true)).ToList());
_otherObjects = FindObjectsOfType<IsoObject>()
.Where(p => p.IsActive() && p.isoWorld)
.Where(p => _isoObjects.ContainsKey(p.isoWorld))
.Where(p => !_isoObjects[p.isoWorld].Contains(p))
.GroupBy(p => p.isoWorld)
.ToDictionary(p => p.Key, p => p.ToList());
_viewCenters = _isoParents.ToDictionary(
pair => pair.Key,
pair => {
var iso_world = pair.Key;
return pair.Value.Aggregate(Vector3.zero, (AccIn, p) => {
return AccIn + p.transform.position;
}) / pair.Value.Count;
});
}
void DrawCustomInspector() {
var iso_worlds = _isoParents.Keys.ToArray();
IsoEditorUtils.DrawWorldProperties(iso_worlds);
IsoEditorUtils.DrawSelfWorldProperty(iso_worlds, "IsoParent");
}
// ---------------------------------------------------------------------
//
//
//
// ---------------------------------------------------------------------
void XYMoveSliderTool(Color color, Vector3 dir) {
foreach ( var iso_world in _viewCenters.Keys.ToList() ) {
EditorGUI.BeginChangeCheck();
var old_center = _viewCenters[iso_world];
var new_center = IsoEditorUtils.GizmoSlider(
color,
old_center,
iso_world.IsoToScreen(dir));
if ( EditorGUI.EndChangeCheck() ) {
Undo.RecordObjects(
_isoParents[iso_world].Select(p => p.transform).ToArray(),
_isoParents[iso_world].Count > 1 ? "Move IsoParents" : "Move IsoParent");
var old_delta = new_center - old_center;
var new_delta = iso_world.IsoToScreen(IsoEditorUtils.XYMoveIsoObjects(
false,
iso_world,
_isoObjects,
_otherObjects,
iso_world.ScreenToIso(old_delta)));
_viewCenters[iso_world] = old_center + IsoUtils.Vec3FromVec2(new_delta);
foreach ( var parent in _isoParents[iso_world] ) {
parent.transform.position += IsoUtils.Vec3FromVec2(new_delta);
}
foreach ( var iso_object in _isoObjects[iso_world] ) {
iso_object.FixIsoPosition();
iso_object.positionXY = IsoUtils.VectorBeautifier(iso_object.positionXY);
}
}
}
}
void XYMoveRectangleTool() {
foreach ( var iso_world in _viewCenters.Keys.ToList() ) {
EditorGUI.BeginChangeCheck();
var old_center = _viewCenters[iso_world];
var new_center = IsoEditorUtils.GizmoRectangle(old_center);
if ( EditorGUI.EndChangeCheck() ) {
Undo.RecordObjects(
_isoParents[iso_world].Select(p => p.transform).ToArray(),
_isoParents[iso_world].Count > 1 ? "Move IsoParents" : "Move IsoParent");
var old_delta = new_center - old_center;
var new_delta = iso_world.IsoToScreen(IsoEditorUtils.XYMoveIsoObjects(
false,
iso_world,
_isoObjects,
_otherObjects,
iso_world.ScreenToIso(old_delta)));
_viewCenters[iso_world] = old_center + IsoUtils.Vec3FromVec2(new_delta);
foreach ( var parent in _isoParents[iso_world] ) {
parent.transform.position += IsoUtils.Vec3FromVec2(new_delta);
}
foreach ( var iso_object in _isoObjects[iso_world] ) {
iso_object.FixIsoPosition();
iso_object.positionXY = IsoUtils.VectorBeautifier(iso_object.positionXY);
}
}
}
}
// ---------------------------------------------------------------------
//
//
//
// ---------------------------------------------------------------------
void DisableCustomTools() {
if ( Tools.hidden ) {
Tools.hidden = false;
Tools.current = Tool.Move;
}
}
void DrawCustomTools() {
if ( Tools.current == Tool.Move ) {
Tools.hidden = true;
XYMoveSliderTool(Handles.xAxisColor, IsoUtils.vec3OneX);
XYMoveSliderTool(Handles.yAxisColor, IsoUtils.vec3OneY);
XYMoveRectangleTool();
} else {
Tools.hidden = false;
}
}
// ---------------------------------------------------------------------
//
// Messages
//
// ---------------------------------------------------------------------
void OnEnable() {
PrepareTargets();
}
void OnDisable() {
DisableCustomTools();
}
void OnSceneGUI() {
DrawCustomTools();
}
public override void OnInspectorGUI() {
PrepareTargets();
DrawDefaultInspector();
DrawCustomInspector();
}
}
}

View File

@@ -1,157 +0,0 @@
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
namespace IsoTools.Internal {
[CustomEditor(typeof(IsoSnappingParent)), CanEditMultipleObjects]
public class IsoSnappingParentEditor : Editor {
IDictionary<IsoSnappingParent, Vector3> _parents = new Dictionary<IsoSnappingParent, Vector3>();
IDictionary<IsoObject, Vector3> _positions = new Dictionary<IsoObject, Vector3>();
IList<IsoObject> _otherObjects = new List<IsoObject>();
Vector3 _center = Vector3.zero;
Vector3 _viewCenter = Vector3.zero;
void GrabPositions() {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
_parents = targets
.OfType<IsoSnappingParent>()
.ToDictionary(p => p, p => p.transform.position);
foreach ( var parent in _parents ) {
var iso_objects = parent.Key.GetComponentsInChildren<IsoObject>(true);
foreach ( var iso_object in iso_objects ) {
_positions[iso_object] = iso_object.transform.position;
}
}
_center = _viewCenter = _parents.Aggregate(Vector3.zero, (AccIn, p) => {
return AccIn + p.Key.transform.position;
}) / _parents.Count;
} else {
_parents.Clear();
_positions.Clear();
}
_otherObjects = FindObjectsOfType<IsoObject>()
.Where(p => p.gameObject.activeInHierarchy && !_positions.ContainsKey(p))
.ToList();
}
void DrawWorldEditorProperties() {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
var so = new SerializedObject(iso_world);
EditorGUILayout.PropertyField(so.FindProperty("_showIsoBounds"));
EditorGUILayout.PropertyField(so.FindProperty("_showScreenBounds"));
EditorGUILayout.PropertyField(so.FindProperty("_showDepends"));
EditorGUILayout.PropertyField(so.FindProperty("_snappingEnabled"));
if ( GUI.changed ) {
so.ApplyModifiedProperties();
}
}
}
void XYMoveSlider(Color color, Vector3 dir) {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
Handles.color = color;
var delta = Handles.Slider(_viewCenter, iso_world.IsoToScreen(dir)) - _viewCenter;
if ( delta.magnitude > Mathf.Epsilon ) {
Undo.RecordObjects(
_parents.Select(p => p.Key.transform).ToArray(),
_parents.Count > 1 ? "Move IsoSnappingParents" : "Move IsoSnappingParent");
_viewCenter = _center + IsoObjectEditor.XYMoveIsoObjects(
false,
_viewCenter - _center + delta,
_positions,
_otherObjects);
foreach ( var parent in _parents ) {
parent.Key.transform.position = parent.Value + (_viewCenter - _center);
}
foreach ( var pos in _positions ) {
pos.Key.FixIsoPosition();
pos.Key.positionXY = IsoUtils.VectorBeautifier(pos.Key.positionXY);
}
}
}
}
void XYMoveRectangle() {
var iso_world = IsoWorld.Instance;
if ( iso_world ) {
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 ) {
Undo.RecordObjects(
_parents.Select(p => p.Key.transform).ToArray(),
_parents.Count > 1 ? "Move IsoSnappingParents" : "Move IsoSnappingParent");
_viewCenter = _center + IsoObjectEditor.XYMoveIsoObjects(
false,
_viewCenter - _center + delta,
_positions,
_otherObjects);
foreach ( var parent in _parents ) {
parent.Key.transform.position = parent.Value + (_viewCenter - _center);
}
foreach ( var pos in _positions ) {
pos.Key.FixIsoPosition();
pos.Key.positionXY = IsoUtils.VectorBeautifier(pos.Key.positionXY);
}
}
}
}
//
//
//
void OnEnable() {
GrabPositions();
}
void OnDisable() {
if ( Tools.hidden ) {
Tools.hidden = false;
Tools.current = Tool.Move;
}
}
void OnSceneGUI() {
if ( Tools.current == Tool.Move ) {
Tools.hidden = true;
XYMoveSlider(Handles.xAxisColor, IsoUtils.vec3OneX);
XYMoveSlider(Handles.yAxisColor, IsoUtils.vec3OneY);
XYMoveRectangle();
} else {
Tools.hidden = false;
}
}
public override void OnInspectorGUI() {
DrawDefaultInspector();
GrabPositions();
DrawWorldEditorProperties();
}
}
}

View File

@@ -1,10 +1,12 @@
using UnityEngine;
using System.Collections.Generic;
namespace IsoTools.Internal {
public abstract class IsoBehaviour<T> : MonoBehaviour
where T : IsoBehaviour<T>
{
static IsoAssocList<T> _behaviours = new IsoAssocList<T>();
static List<IsoWorld> _tempWorlds = new List<IsoWorld>();
// ---------------------------------------------------------------------
//
@@ -16,6 +18,20 @@ namespace IsoTools.Internal {
return isActiveAndEnabled && gameObject.activeInHierarchy;
}
protected IsoWorld FindFirstActiveParentWorld() {
IsoWorld ret_value = null;
GetComponentsInParent<IsoWorld>(false, _tempWorlds);
for ( int i = 0, e = _tempWorlds.Count; i < e; ++i ) {
var iso_world = _tempWorlds[i];
if ( iso_world.IsActive() ) {
ret_value = iso_world;
break;
}
}
_tempWorlds.Clear();
return ret_value;
}
protected static int AllBehaviourCount {
get { return _behaviours.Count; }
}

View File

@@ -0,0 +1,14 @@
using UnityEngine;
using IsoTools.Internal;
namespace IsoTools {
[SelectionBase]
[ExecuteInEditMode, DisallowMultipleComponent]
public sealed class IsoParent : IsoBehaviour<IsoParent> {
public IsoWorld isoWorld {
get {
return FindFirstActiveParentWorld();
}
}
}
}

View File

@@ -1,8 +0,0 @@
using UnityEngine;
namespace IsoTools {
[SelectionBase]
[ExecuteInEditMode, DisallowMultipleComponent]
public class IsoSnappingParent : MonoBehaviour {
}
}

View File

@@ -14,8 +14,6 @@ namespace IsoTools {
[ExecuteInEditMode, DisallowMultipleComponent]
public sealed class IsoWorld : IsoHolder<IsoWorld, IsoObject> {
static IsoWorld _instance = null;
bool _dirty = false;
Vector2 _minXY = Vector2.zero;
IsoAssocList<IsoObject> _visibles = new IsoAssocList<IsoObject>();
@@ -75,6 +73,7 @@ namespace IsoTools {
//
// ---------------------------------------------------------------------
[Header("World Settings")]
[SerializeField]
public float _tileSize = DefTileSize;
public float tileSize {
@@ -137,17 +136,16 @@ namespace IsoTools {
// ---------------------------------------------------------------------
//
// Instance
// Instances
//
// ---------------------------------------------------------------------
public static IsoWorld Instance {
get {
if ( !_instance ) {
_instance = GameObject.FindObjectOfType<IsoWorld>();
}
return _instance;
public static int AllWorldCount {
get { return AllBehaviourCount; }
}
public static IsoWorld GetWorld(int index) {
return GetBehaviourByIndex(index);
}
// ---------------------------------------------------------------------
@@ -332,10 +330,15 @@ namespace IsoTools {
get { return _showDepends; }
set { _showDepends = value; }
}
[SerializeField] bool _snappingEnabled = true;
public bool isSnappingEnabled {
get { return _snappingEnabled; }
set { _snappingEnabled = value; }
[SerializeField] bool _snapByCells = true;
public bool isSnapByCells {
get { return _snapByCells; }
set { _snapByCells = value; }
}
[SerializeField] bool _snapByObjects = true;
public bool isSnapByObjects {
get { return _snapByObjects; }
set { _snapByObjects = value; }
}
#endif