From 40349a896af40831c8a318d531be34351a0bd875 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 24 Apr 2016 20:11:37 +0600 Subject: [PATCH] snapping first impl --- .../Examples/Prefabs/Kenney/Building.prefab | 1 - .../Examples/Prefabs/Kenney/Building2.prefab | 1 - .../Examples/Prefabs/Kenney/Building3.prefab | 1 - .../Examples/Prefabs/Kenney/Fence.prefab | 1 - .../Examples/Prefabs/Kenney/Fence2.prefab | 1 - .../Examples/Prefabs/Kenney/Road.prefab | 1 - .../Examples/Prefabs/Kenney/Road2.prefab | 1 - .../Examples/Prefabs/Kenney/Road3.prefab | 1 - .../Examples/Prefabs/Kenney/Road4.prefab | 1 - .../Examples/Prefabs/Kenney/Tile.prefab | 1 - .../Examples/Prefabs/Kenney/Tree.prefab | 1 - .../Examples/Prefabs/Kenney/Water.prefab | 1 - .../Examples/Prefabs/Kenney/Water2.prefab | 1 - .../Examples/Prefabs/Kenney/Water3.prefab | 1 - .../Examples/Prefabs/Kenney/Water4.prefab | 1 - .../Examples/Prefabs/Tests/Cube_1x1x1.prefab | 1 - .../Examples/Prefabs/Tests/Cube_1x3x1.prefab | 1 - .../Examples/Prefabs/Tests/Cube_3x1x1.prefab | 1 - .../Examples/Prefabs/Tests/Floor_3x3.prefab | 1 - .../Internal/Editor/IsoObjectEditor.cs | 150 ++++++++++++++---- Assets/IsoTools/Scripts/IsoObject.cs | 11 -- 21 files changed, 121 insertions(+), 59 deletions(-) diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Building.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Building.prefab index 6328f02..32cdff6 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Building.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Building.prefab @@ -164,7 +164,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21224890 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Building2.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Building2.prefab index 7e1bdd7..8fa318a 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Building2.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Building2.prefab @@ -178,7 +178,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!114 &11453236 MonoBehaviour: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Building3.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Building3.prefab index 9be7da7..25c0e42 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Building3.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Building3.prefab @@ -164,7 +164,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21269568 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Fence.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Fence.prefab index 3b490c3..86b2f62 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Fence.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Fence.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 0 _isShowBounds: 0 --- !u!212 &21295688 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Fence2.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Fence2.prefab index 520f612..ce8b970 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Fence2.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Fence2.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 0 _isShowBounds: 0 --- !u!212 &21245702 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Road.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Road.prefab index 9f2721b..3b57e41 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Road.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Road.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21221408 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Road2.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Road2.prefab index 9f5f444..658baa5 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Road2.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Road2.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21228980 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Road3.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Road3.prefab index 6a31ad3..f1920f3 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Road3.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Road3.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21298190 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Road4.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Road4.prefab index 5e9e96e..0064e96 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Road4.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Road4.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21274934 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Tile.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Tile.prefab index 5af1131..c908683 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Tile.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Tile.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21238442 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Tree.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Tree.prefab index 682a63a..ee120ce 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Tree.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Tree.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 0 _isShowBounds: 0 --- !u!212 &21283090 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Water.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Water.prefab index 904c9b2..ecdfdc3 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Water.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Water.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21257916 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Water2.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Water2.prefab index faa7cc1..fc79fb0 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Water2.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Water2.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21267074 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Water3.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Water3.prefab index 8e36ebc..06e32ca 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Water3.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Water3.prefab @@ -72,7 +72,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21210472 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Kenney/Water4.prefab b/Assets/IsoTools/Examples/Prefabs/Kenney/Water4.prefab index 64e982e..5e84d3b 100644 --- a/Assets/IsoTools/Examples/Prefabs/Kenney/Water4.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Kenney/Water4.prefab @@ -102,7 +102,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!198 &19803878 ParticleSystem: diff --git a/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x1x1.prefab b/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x1x1.prefab index e2cea2f..60f4d1b 100644 --- a/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x1x1.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x1x1.prefab @@ -44,7 +44,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21217528 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x3x1.prefab b/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x3x1.prefab index 3362039..2932b28 100644 --- a/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x3x1.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Tests/Cube_1x3x1.prefab @@ -44,7 +44,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21253620 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Tests/Cube_3x1x1.prefab b/Assets/IsoTools/Examples/Prefabs/Tests/Cube_3x1x1.prefab index 6ce4c10..d356d66 100644 --- a/Assets/IsoTools/Examples/Prefabs/Tests/Cube_3x1x1.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Tests/Cube_3x1x1.prefab @@ -44,7 +44,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21262204 SpriteRenderer: diff --git a/Assets/IsoTools/Examples/Prefabs/Tests/Floor_3x3.prefab b/Assets/IsoTools/Examples/Prefabs/Tests/Floor_3x3.prefab index dc42579..4a35db8 100644 --- a/Assets/IsoTools/Examples/Prefabs/Tests/Floor_3x3.prefab +++ b/Assets/IsoTools/Examples/Prefabs/Tests/Floor_3x3.prefab @@ -44,7 +44,6 @@ MonoBehaviour: _position: {x: 0, y: 0, z: 0} _mode: 0 _cacheRenderers: 1 - _isAlignment: 1 _isShowBounds: 0 --- !u!212 &21253404 SpriteRenderer: diff --git a/Assets/IsoTools/Scripts/Internal/Editor/IsoObjectEditor.cs b/Assets/IsoTools/Scripts/Internal/Editor/IsoObjectEditor.cs index 9bc9483..2f2825e 100644 --- a/Assets/IsoTools/Scripts/Internal/Editor/IsoObjectEditor.cs +++ b/Assets/IsoTools/Scripts/Internal/Editor/IsoObjectEditor.cs @@ -7,10 +7,17 @@ namespace IsoTools.Internal { [CustomEditor(typeof(IsoObject)), CanEditMultipleObjects] class IsoObjectEditor : Editor { - IDictionary _positions = new Dictionary(); - IDictionary _iso_zpositions = new Dictionary(); - Vector3 _center = Vector3.zero; - Vector3 _viewCenter = Vector3.zero; + IDictionary _positions = new Dictionary(); + IDictionary _isoZPositions = new Dictionary(); + IList _otherObjects = new List(); + Vector3 _center = Vector3.zero; + Vector3 _viewCenter = Vector3.zero; + + static public readonly float SnappingDistance = 0.2f; + + static bool IsSnappingEnabled() { + return !Event.current.control; + } void GrabPositions() { var iso_world = IsoWorld.Instance; @@ -19,7 +26,7 @@ namespace IsoTools.Internal { .Where(p => p is IsoObject) .Select(p => p as IsoObject) .ToDictionary(p => p, p => p.transform.position); - _iso_zpositions = targets + _isoZPositions = targets .Where(p => p is IsoObject) .Select(p => p as IsoObject) .ToDictionary(p => p, p => p.position.z); @@ -29,6 +36,12 @@ namespace IsoTools.Internal { } } + void GrabOtherIsoObjects() { + _otherObjects = FindObjectsOfType() + .Where(p => p.gameObject.activeInHierarchy && !targets.Contains(p)) + .ToList(); + } + void DirtyTargetPosition() { if ( targets.Length == 1 && (target is IsoObject) && (target as IsoObject).gameObject.activeInHierarchy ) { var position_prop = serializedObject.FindProperty("_position"); @@ -44,35 +57,79 @@ namespace IsoTools.Internal { } } - bool isAnyAlignment { - get { return _positions.Keys.Any(p => p.isAlignment); } - } - - void AlignmentSelection() { - foreach ( var iso_object in _positions.Keys ) { - AlignmentIsoObject(iso_object); + 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; + } } - GrabPositions(); + return result; } - void AlignmentIsoObject(IsoObject iso_object) { - iso_object.position = iso_object.tilePosition; - iso_object.FixTransform(); + 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; } float ZMoveIsoObjects(float delta) { Undo.RecordObjects( - _iso_zpositions.Keys.ToArray(), - _iso_zpositions.Count > 1 ? "Move IsoObjects" : "Move IsoObject"); - var is_any_alignment = isAnyAlignment; - return _iso_zpositions.Aggregate(0.0f, (AccIn, pair) => { + _isoZPositions.Keys.ToArray(), + _isoZPositions.Count > 1 ? "Move IsoObjects" : "Move IsoObject"); + if ( IsSnappingEnabled() ) { + var snapping_z = false; + foreach ( var pair in _isoZPositions ) { + var iso_object = pair.Key; + var iso_orig_z = pair.Value; + var result_p_z = iso_orig_z + delta; + foreach ( var other in _otherObjects ) { + 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 ) { + if ( new_snapping_z ) { + delta = result_p_z - iso_orig_z; + snapping_z = true; + } + } + } + } + if ( snapping_z ) { + break; + } + } + } + return _isoZPositions.Aggregate(0.0f, (AccIn, pair) => { var iso_object = pair.Key; var iso_orig_z = pair.Value; - iso_object.positionZ = iso_orig_z + delta; + var result_p_z = iso_orig_z + delta; + iso_object.positionZ = result_p_z; iso_object.FixTransform(); - if ( is_any_alignment ) { - AlignmentIsoObject(iso_object); - } var z_delta = iso_object.position.z - iso_orig_z; return Mathf.Abs(z_delta) > Mathf.Abs(AccIn) ? z_delta : AccIn; }); @@ -82,15 +139,48 @@ namespace IsoTools.Internal { Undo.RecordObjects( _positions.Keys.ToArray(), _positions.Count > 1 ? "Move IsoObjects" : "Move IsoObject"); - var is_any_alignment = isAnyAlignment; + 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 _otherObjects ) { + 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; + } + } + } 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; + var result_pos = iso_orig_p + delta; + iso_object.transform.position = result_pos; iso_object.FixIsoPosition(); - if ( is_any_alignment ) { - AlignmentIsoObject(iso_object); - } var pos_delta = iso_object.transform.position - iso_orig_p; return pos_delta.magnitude > AccIn.magnitude ? pos_delta : AccIn; }); @@ -150,6 +240,7 @@ namespace IsoTools.Internal { void OnEnable() { GrabPositions(); + GrabOtherIsoObjects(); } void OnDisable() { @@ -174,6 +265,7 @@ namespace IsoTools.Internal { public override void OnInspectorGUI() { DrawDefaultInspector(); GrabPositions(); + GrabOtherIsoObjects(); DirtyTargetPosition(); } } diff --git a/Assets/IsoTools/Scripts/IsoObject.cs b/Assets/IsoTools/Scripts/IsoObject.cs index ecc03f5..991a336 100644 --- a/Assets/IsoTools/Scripts/IsoObject.cs +++ b/Assets/IsoTools/Scripts/IsoObject.cs @@ -217,14 +217,8 @@ namespace IsoTools { bool _lastCacheRenderers = false; [Space(10)] - [SerializeField] bool _isAlignment = true; [SerializeField] bool _isShowBounds = false; - public bool isAlignment { - get { return _isAlignment; } - set { _isAlignment = value; } - } - public bool isShowBounds { get { return _isShowBounds; } set { _isShowBounds = value; } @@ -248,11 +242,6 @@ namespace IsoTools { } public void FixTransform() { - #if UNITY_EDITOR - if ( !Application.isPlaying && isAlignment ) { - _position = tilePosition; - } - #endif if ( isoWorld ) { transform.position = IsoUtils.Vec3ChangeZ( isoWorld.IsoToScreen(position),