diff --git a/CHANGELOG.md b/CHANGELOG.md index c50f667..1f8f4d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +## [4.0.2] - 2023-08-21 +### Fixed +- [GameObjectBrush] Use cell offset to determine location of GameObject when painting and erasing + ## [4.0.1] - 2023-04-26 ### Fixed - [GameObjectBrush] Set HideFlags of instantiated GameObject to HideFlags.None when painting diff --git a/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs b/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs index e96b1ee..e209b80 100644 --- a/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs +++ b/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs @@ -1,5 +1,5 @@ using System; -using System.Linq; +using System.Collections.Generic; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; @@ -137,8 +137,8 @@ public void Init(Vector3Int size, Vector3Int pivot) /// The coordinates of the cell to paint data to. public override void Paint(GridLayout gridLayout, GameObject brushTarget, Vector3Int position) { - Vector3Int min = position - pivot; - BoundsInt bounds = new BoundsInt(min, m_Size); + var min = position - pivot; + var bounds = new BoundsInt(min, m_Size); BoxFill(gridLayout, brushTarget, bounds); } @@ -148,7 +148,7 @@ private void PaintCell(GridLayout grid, Vector3Int position, Transform parent, B if (cell.gameObject == null) return; - var existingGO = GetObjectInCell(grid, parent, position, m_Anchor); + var existingGO = GetObjectInCell(grid, parent, position, m_Anchor, cell.offset); if (existingGO == null) { SetSceneCell(grid, parent, position, cell.gameObject, cell.offset, cell.scale, cell.orientation, m_Anchor); @@ -164,16 +164,16 @@ private void PaintCell(GridLayout grid, Vector3Int position, Transform parent, B /// The coordinates of the cell to erase data from. public override void Erase(GridLayout gridLayout, GameObject brushTarget, Vector3Int position) { - Vector3Int min = position - pivot; - BoundsInt bounds = new BoundsInt(min, m_Size); + var min = position - pivot; + var bounds = new BoundsInt(min, m_Size); GetGrid(ref gridLayout, ref brushTarget); BoxErase(gridLayout, brushTarget, bounds); } - private void EraseCell(GridLayout grid, Vector3Int position, Transform parent) + private void EraseCell(GridLayout grid, Vector3Int position, Transform parent, BrushCell cell) { - ClearSceneCell(grid, parent, position); + ClearSceneCell(grid, parent, position, cell); } /// @@ -187,10 +187,10 @@ public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, Boun { GetGrid(ref gridLayout, ref brushTarget); - foreach (Vector3Int location in position.allPositionsWithin) + foreach (var location in position.allPositionsWithin) { - Vector3Int local = location - position.min; - BrushCell cell = m_Cells[GetCellIndexWrapAround(local.x, local.y, local.z)]; + var local = location - position.min; + var cell = m_Cells[GetCellIndexWrapAround(local.x, local.y, local.z)]; PaintCell(gridLayout, location, brushTarget != null ? brushTarget.transform : null, cell); } } @@ -206,14 +206,16 @@ public override void BoxErase(GridLayout gridLayout, GameObject brushTarget, Bou { GetGrid(ref gridLayout, ref brushTarget); - foreach (Vector3Int location in position.allPositionsWithin) + foreach (var location in position.allPositionsWithin) { - EraseCell(gridLayout, location, brushTarget != null ? brushTarget.transform : null); + var local = location - position.min; + var cell = m_Cells[GetCellIndexWrapAround(local.x, local.y, local.z)]; + EraseCell(gridLayout, location, brushTarget != null ? brushTarget.transform : null, cell); } } /// - /// This is not supported but it should floodfill GameObjects starting from a given position within the selected layers. + /// This is not supported but it should flood-fill GameObjects starting from a given position within the selected layers. /// /// Grid used for layout. /// Target of the flood fill operation. By default the currently selected GameObject. @@ -230,22 +232,22 @@ public override void FloodFill(GridLayout gridLayout, GameObject brushTarget, Ve /// Cell Layout for rotating. public override void Rotate(RotationDirection direction, GridLayout.CellLayout layout) { - Vector3Int oldSize = m_Size; - BrushCell[] oldCells = m_Cells.Clone() as BrushCell[]; + var oldSize = m_Size; + var oldCells = m_Cells.Clone() as BrushCell[]; size = new Vector3Int(oldSize.y, oldSize.x, oldSize.z); - BoundsInt oldBounds = new BoundsInt(Vector3Int.zero, oldSize); + var oldBounds = new BoundsInt(Vector3Int.zero, oldSize); foreach (Vector3Int oldPos in oldBounds.allPositionsWithin) { - int newX = direction == RotationDirection.Clockwise ? oldSize.y - oldPos.y - 1 : oldPos.y; - int newY = direction == RotationDirection.Clockwise ? oldPos.x : oldSize.x - oldPos.x - 1; - int toIndex = GetCellIndex(newX, newY, oldPos.z); - int fromIndex = GetCellIndex(oldPos.x, oldPos.y, oldPos.z, oldSize.x, oldSize.y, oldSize.z); + var newX = direction == RotationDirection.Clockwise ? oldSize.y - oldPos.y - 1 : oldPos.y; + var newY = direction == RotationDirection.Clockwise ? oldPos.x : oldSize.x - oldPos.x - 1; + var toIndex = GetCellIndex(newX, newY, oldPos.z); + var fromIndex = GetCellIndex(oldPos.x, oldPos.y, oldPos.z, oldSize.x, oldSize.y, oldSize.z); m_Cells[toIndex] = oldCells[fromIndex]; } - int newPivotX = direction == RotationDirection.Clockwise ? oldSize.y - pivot.y - 1 : pivot.y; - int newPivotY = direction == RotationDirection.Clockwise ? pivot.x : oldSize.x - pivot.x - 1; + var newPivotX = direction == RotationDirection.Clockwise ? oldSize.y - pivot.y - 1 : pivot.y; + var newPivotY = direction == RotationDirection.Clockwise ? pivot.x : oldSize.x - pivot.x - 1; pivot = new Vector3Int(newPivotX, newPivotY, pivot.z); Quaternion orientation = Quaternion.Euler(0f, 0f, direction != RotationDirection.Clockwise ? 90f : -90f); @@ -288,13 +290,17 @@ public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsI private void PickCell(Vector3Int position, Vector3Int brushPosition, GridLayout grid, Transform parent, bool withoutAnchor = false) { - var go = GetObjectInCell(grid, parent, position, m_Anchor); + GameObject go = null; + if (!withoutAnchor) + go = GetObjectInCell(grid, parent, position, m_Anchor, Vector3.zero); if (go == null) - { - go = GetObjectInCell(grid, parent, position, Vector3.zero); - } + go = GetObjectInCell(grid, parent, position, Vector3.zero, Vector3.zero); + var anchorRatio = GetAnchorRatio(grid, m_Anchor); - var cellCenter = grid.LocalToWorld(grid.CellToLocalInterpolated(position) + grid.CellToLocalInterpolated(anchorRatio)); + + var cellLocalPosition = grid.CellToLocalInterpolated(position); + var anchorLocalPosition = grid.CellToLocalInterpolated(anchorRatio); + var cellCenter = grid.LocalToWorld(cellLocalPosition + anchorLocalPosition); if (go != null) { @@ -332,11 +338,12 @@ public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, Bo GetGrid(ref gridLayout, ref brushTarget); var targetTransform = brushTarget != null ? brushTarget.transform : null; - foreach (Vector3Int pos in position.allPositionsWithin) + foreach (var pos in position.allPositionsWithin) { - Vector3Int brushPosition = new Vector3Int(pos.x - position.x, pos.y - position.y, 0); + var brushPosition = new Vector3Int(pos.x - position.x, pos.y - position.y, 0); PickCell(pos, brushPosition, gridLayout, targetTransform); - ClearSceneCell(gridLayout, targetTransform, pos); + var cell = m_Cells[GetCellIndex(brushPosition)]; + ClearSceneCell(gridLayout, targetTransform, pos, cell); } } @@ -382,10 +389,10 @@ public void Reset() private void FlipX() { - BrushCell[] oldCells = m_Cells.Clone() as BrushCell[]; - BoundsInt oldBounds = new BoundsInt(Vector3Int.zero, m_Size); + var oldCells = m_Cells.Clone() as BrushCell[]; + var oldBounds = new BoundsInt(Vector3Int.zero, m_Size); - foreach (Vector3Int oldPos in oldBounds.allPositionsWithin) + foreach (var oldPos in oldBounds.allPositionsWithin) { var newX = m_Size.x - oldPos.x - 1; var toIndex = GetCellIndex(newX, oldPos.y, oldPos.z); @@ -401,10 +408,10 @@ private void FlipX() private void FlipY() { - BrushCell[] oldCells = m_Cells.Clone() as BrushCell[]; - BoundsInt oldBounds = new BoundsInt(Vector3Int.zero, m_Size); + var oldCells = m_Cells.Clone() as BrushCell[]; + var oldBounds = new BoundsInt(Vector3Int.zero, m_Size); - foreach (Vector3Int oldPos in oldBounds.allPositionsWithin) + foreach (var oldPos in oldBounds.allPositionsWithin) { var newY = m_Size.y - oldPos.y - 1; var toIndex = GetCellIndex(oldPos.x, newY, oldPos.z); @@ -521,7 +528,7 @@ public int GetCellIndexWrapAround(int x, int y, int z) return (x % m_Size.x) + m_Size.x * (y % m_Size.y) + m_Size.x * m_Size.y * (z % m_Size.z); } - private GameObject GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position, Vector3 anchor) + private GameObject GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position, Vector3 anchor, Vector3 offset) { int childCount; GameObject[] sceneChildren = null; @@ -537,11 +544,11 @@ private GameObject GetObjectInCell(GridLayout grid, Transform parent, Vector3Int } var anchorRatio = GetAnchorRatio(grid, anchor); - var anchorWorld = grid.CellToLocalInterpolated(anchorRatio); + var anchorLocal = grid.CellToLocalInterpolated(anchorRatio); for (var i = 0; i < childCount; i++) { var child = sceneChildren == null ? parent.GetChild(i) : sceneChildren[i].transform; - var childCell = grid.LocalToCell(grid.WorldToLocal(child.position) - anchorWorld); + var childCell = grid.LocalToCell(grid.WorldToLocal(child.position) - anchorLocal - offset); if (position == childCell) return child.gameObject; } @@ -564,7 +571,7 @@ internal void SizeUpdated(bool keepContents = false) OnValidate(); Array.Resize(ref m_Cells, sizeCount); var bounds = new BoundsInt(Vector3Int.zero, m_Size); - foreach (Vector3Int pos in bounds.allPositionsWithin) + foreach (var pos in bounds.allPositionsWithin) { if (keepContents || m_Cells[GetCellIndex(pos)] == null) m_Cells[GetCellIndex(pos)] = new BrushCell(); @@ -617,9 +624,9 @@ private static Vector3 GetAnchorRatio(GridLayout grid, Vector3 cellAnchor) return anchorRatio; } - private void ClearSceneCell(GridLayout grid, Transform parent, Vector3Int position) + private void ClearSceneCell(GridLayout grid, Transform parent, Vector3Int position, BrushCell cell) { - var erased = GetObjectInCell(grid, parent, position, m_Anchor); + var erased = GetObjectInCell(grid, parent, position, m_Anchor, cell.offset); if (erased != null) Undo.DestroyObjectImmediate(erased); } @@ -659,19 +666,36 @@ public class BrushCell /// /// GameObject to be placed when painting. /// - public GameObject gameObject { get { return m_GameObject; } set { m_GameObject = value; } } + public GameObject gameObject + { + get => m_GameObject; + set => m_GameObject = value; + } + /// /// Position offset of the GameObject when painted. /// - public Vector3 offset { get { return m_Offset; } set { m_Offset = value; } } + public Vector3 offset + { + get => m_Offset; + set => m_Offset = value; + } /// /// Scale of the GameObject when painted. /// - public Vector3 scale { get { return m_Scale; } set { m_Scale = value; } } + public Vector3 scale + { + get => m_Scale; + set => m_Scale = value; + } /// - /// Orientatio of the GameObject when painted. + /// Orientation of the GameObject when painted. /// - public Quaternion orientation { get { return m_Orientation; } set { m_Orientation = value; } } + public Quaternion orientation + { + get => m_Orientation; + set => m_Orientation = value; + } [SerializeField] private GameObject m_GameObject; @@ -722,8 +746,8 @@ public class GameObjectBrushEditor : GridBrushEditorBase /// Whether the GridBrush can change Z Position. public override bool canChangeZPosition { - get { return brush.canChangeZPosition; } - set { brush.canChangeZPosition = value; } + get => brush.canChangeZPosition; + set => brush.canChangeZPosition = value; } /// @@ -756,7 +780,7 @@ public override bool shouldSaveBrushForSelection /// Whether brush is being used. public override void OnPaintSceneGUI(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing) { - BoundsInt gizmoRect = position; + var gizmoRect = position; if (tool == GridBrushBase.Tool.Paint || tool == GridBrushBase.Tool.Erase) gizmoRect = new BoundsInt(position.min - brush.pivot, brush.size); @@ -809,14 +833,15 @@ public override GameObject[] validTargets { get { - StageHandle currentStageHandle = StageUtility.GetCurrentStageHandle(); - var results = currentStageHandle.FindComponentsOfType().Where(x => + var currentStageHandle = StageUtility.GetCurrentStageHandle(); + var results = currentStageHandle.FindComponentsOfType(); + var validGridLayouts = new List(results.Length + 1) { brush.hiddenGrid }; + foreach (var result in results) { - GameObject gameObject; - return (gameObject = x.gameObject).scene.isLoaded - && gameObject.activeInHierarchy; - }).Select(x => x.gameObject); - return results.Prepend(brush.hiddenGrid).ToArray(); + if (result.gameObject.scene.isLoaded && result.gameObject.activeInHierarchy) + validGridLayouts.Add(result.gameObject); + } + return validGridLayouts.ToArray(); } } diff --git a/package.json b/package.json index b60fc44..097f49c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.2d.tilemap.extras", "displayName": "2D Tilemap Extras", - "version": "4.0.1", + "version": "4.0.2", "unity": "2023.1", "description": "2D Tilemap Extras is a package that contains extra scripts for use with 2D Tilemap features in Unity. These include custom Tiles and Brushes for the Tilemap feature.\n\nThe following are included in the package:\nBrushes: GameObject Brush, Group Brush, Line Brush, Random Brush\nTiles: Animated Tile, Rule Tile, Rule Override Tile\nOther: Grid Information, Custom Rules for Rule Tile", "keywords": [ @@ -15,7 +15,7 @@ "com.unity.modules.jsonserialize": "1.0.0" }, "relatedPackages": { - "com.unity.2d.tilemap.extras.tests": "4.0.1" + "com.unity.2d.tilemap.extras.tests": "4.0.2" }, "samples": [ { @@ -35,15 +35,15 @@ } ], "_upm": { - "changelog": "### Fixed\n- [GameObjectBrush] Set HideFlags of instantiated GameObject to HideFlags.None when painting\n- [GridInformation] Fix serialization of GridInformationKey/Value" + "changelog": "### Fixed\n- [GameObjectBrush] Use cell offset to determine location of GameObject when painting and erasing" }, "upmCi": { - "footprint": "e48f8942babb511d4a959a658cbe96fcbc536dfc" + "footprint": "1dc77b3f9a7dc9ec88a1b175812698bd0c8714ff" }, "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@4.0/manual/index.html", "repository": { "url": "https://github.com/Unity-Technologies/2d-extras.git", "type": "git", - "revision": "5c1725c663304c56eb3b1612a8dae90f4a0b9fa5" + "revision": "21a24803135ec4fbe47be9ccd27fb06e47d06d88" } }