diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f8f4d8..e4e48c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,45 @@ # Changelog + 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.1.0] - 2024-09-18 + +### Fixed + +- [GameObjectBrush] Allow expansion of SceneRoot Grid foldout when clicking on label +- [GridInformation] Fix exception when serializing GridInformation component if component is part of a Prefab +- Remove dependency on com.unity.ugui + ## [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 - [GridInformation] Fix serialization of GridInformationKey/Value ## [4.0.0] - 2023-03-07 + ### Added -- [RuleTile] Add RotatedMirror rule which checks neighbors using both the mirror and rotation Rule in addition to the standard rotation Rule + +- [RuleTile] Add RotatedMirror rule which checks neighbors using both the mirror and rotation Rule in addition to the + standard rotation Rule ### Fixed + - [GameObjectBrush] Validate size of GameObjectBrush when it changes ## [4.0.0-pre.3] - 2022-11-23 + ### Fixed + - [TintBrush] Replace obsolete method calls. - [TintBrushSmooth] Replace obsolete method calls. - [GameObjectBrush] Fix placement of GameObjects for Hexagon Layouts with Anchor @@ -28,13 +47,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [RandomBrush] Use default color and transform when painting over with RandomBrush ### Added + - [AnimatedTileEditor] Add field to change TileAnimationFlags ### Changed + - [AnimatedTileEditor] Moved to Unity.2d.Tilemap.Extras.Editor ## [4.0.0-pre.2] - 2022-11-03 + ### Changed + - [RandomBrush] Add RenderStaticPreview for RandomBrush - [TintBrush] Add RenderStaticPreview for TintBrush - [GameObjectBrush] Add RenderStaticPreview for GameObjectBrush @@ -42,33 +65,44 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [GridBrush] Add icons for brushes ### Fixed + - [LineBrush] Do not serialize lineStartActive ## [4.0.0-pre.1] - 2022-10-04 + - Update version to 4.0.0-pre.1 for Unity 2023.1 ### Fixed -- [GridInformation] Implement IEquatable for GridInformationKey + +- [GridInformation] Implement IEquatable for GridInformationKey - [PrefabRandomBrush] Fix possible NullReferenceException in PrefabRandomBrush - [GameObjectBrush] Fix placement of GameObjects when Cell Gap is set ## [3.0.2] - 2022-04-01 + ### Fixed -- [RuleOverrideTile] -Mark RuleOverrideTile InstanceTile as dirty when overriding RuleTile for the RuleOverrideTile changes + +- [RuleOverrideTile] -Mark RuleOverrideTile InstanceTile as dirty when overriding RuleTile for the RuleOverrideTile + changes - [RuleOverrideTile] -Fix undo for RuleOverrideTile when overriding RuleTile has changed - [RuleTileEditor] -Fix height for ReorderableList when extending the view for marking Rules ## [3.0.1] - 2022-03-03 + ### Fixed + - [AnimatedTileEditor] -Fix undo when setting number of Sprites for Animated Tile -- [RuleTile] -Fix data for custom container fields not being transferred in RuleOverrideTiles overriding a Custom Rule Tile +- [RuleTile] -Fix data for custom container fields not being transferred in RuleOverrideTiles overriding a Custom Rule + Tile - [RuleTileEditor] -Fix undo when setting number of Rules for Rule Tile - [RuleTileEditor] -Use different text color for Extend Neighbors with dark and light skin ## [3.0.0] - 2021-08-06 + - Update version to 3.0.0 for Unity 2022.1 ### Changed + - [GameObjectBrush] Add canChangePosition - [GameObjectBrush] Use GridLayout from BrushTarget if it has one - [HexagonalRuleTile] Fix GetOffsetPositionReverse @@ -83,26 +117,34 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [TintBrush] Add k_ScaleFactor for better precision when painting on non-rectangular Tilemaps ### Fixed + - [RuleTile] Fixed error in RuleTileEditor when removing all Rules and adding a new Rule ## [2.2.0] - 2021-06-01 + ### Changed + - [RuleTileEditor] Add tooltips to fields - Add required package dependencies ## [2.1.0] - 2021-05-06 + ### Changed + - [RuleTile] Improve performance of RuleTile caching - [RuleTileEditor] Allow non-public fields with the SerializeField attribute as custom fields for RuleTile - Make U2DExtrasPlaceholder internal ### Fixed + - [RuleTileEditor] Fix exception when adding a new Rule when no Rule is selected ## [2.0.0] - 2021-03-17 + - Update version to 2.0.0 ## [2.0.0-pre.3] - 2021-02-19 + - [HexagonalRuleTile] Fix issue with mirror rule - [RuleTile] Add min and max animation speedup - [RuleOverrideTile] Fix import issue when upgrading from a previous version of RuleOverrideTile @@ -110,36 +152,46 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [RuleTileEditor] Add dropdown to duplicate Rule ## [2.0.0-pre.2] - 2020-11-26 + ### Changed + - Update documentation - Add contribution notice in README.md - Update Third Party Notices.md - [PrefabBush] Add pick - [PrefabBush] Add tooltip for "Erase Any Objects" field - [PrefabBrush][GameObjectBrush] Account for Anchor when using GetObjectsInCell in PrefabBrush and GameObjectBrush -- [CustomRuleTileScript] Allow Custom Rule Tile template script to be created regardless of where template script is installed (from a package or in the project) +- [CustomRuleTileScript] Allow Custom Rule Tile template script to be created regardless of where template script is + installed (from a package or in the project) ## [2.0.0-pre.1] - 2020-10-14 + - Update version to 2.0.0-pre.1 ## [1.6.2-preview] - 2020-09-25 + ### Changed + - [RuleTile/RuleOverrideTile/AdvancedRuleOverrideTile] Renamed Game Object to GameObject - [RuleTile] Fix menu order for RuleOverrideTile - [RuleOverrideTile] Fix menu order for RuleOverrideTile - [AdvancedRuleOverrideTile] Fix Rule toggle for AdvancedRuleOverrideTile -- [GameObjectBrush] Use correct position when ClearSceneCell +- [GameObjectBrush] Use correct position when ClearSceneCell - [GameObjectBrush] Update cells when size changes - [GameObjectBrush] Clear cell for Prefabs - [LineBrush] Clear previews from base.OnPaintSceneGUI - [PrefabBrush] Fix box erase ## [1.6.1-preview] - 2020-08-11 + ### Changed + - Update samples ## [1.6.0-preview] - 2020-05-27 + ### Changed + - Updated for Unity 2020.1 - [GameObjectBrush] Allow painting, erasing and picking on Tile Palette - [GameObjectBrush] Add Paint on Scene view to GameObjectBrush @@ -148,22 +200,30 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - Consolidated menu items ## [1.5.0-preview] - 2020-02-14 + ### Added + - Added CONTRIBUTING.md - Updated LICENSE.md ### Added + - [PrefabRandomBrush] Split functionality of PrefabBrush to PrefabBrush and PrefabRandomBrush -- [PrefabBrush/PrefabRandomBrush] Add Erase Any Objects toggle to choose between erasing any Objects or Objects in the Brush +- [PrefabBrush/PrefabRandomBrush] Add Erase Any Objects toggle to choose between erasing any Objects or Objects in the + Brush ### Changed + - Consolidated menu items ### Fixed + - [WeightedRandomTile] Fixed WeightedRandomTile messing up Random.seed! ## [1.4.0] - 2020-01-07 + ### Added + - [RuleTile / HexagonalRuleTile / IsometricRuleTile / RuleOverrideTile] Added Asset Preview for TilingRules - [RuleTile] Hidden Rule field - [CustomRuleTile] Support custom field of Object type @@ -180,17 +240,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [AnimatedTile] Added Animation Start Frame which helps to calculate the Animation Start Time for a given Tilemap ### Fixed + - [RuleTile] Fixed RuleTile InstantiatedGameObject rotation/scale - [RuleTile] Fixed override tiles have not update when default properties changed - [AdvancedRuleOverrideTile] Fix override rule lost reference when source rule reorder - [PrefabBrush] Use WorldToCell comparison when getting GameObjects using PrefabBrush ## [1.3.1] - 2019-11-06 + ### Changed + - [RuleTile] Simplified - [RuleTile] Caching all RuleTile neighbor positions for Tilemap to speedup refresh affected tiles ### Fixed + - [RuleTile] Fix remote positions missing of MirrorXY (#148) - [HexagonalRuleTile] Fix ApplyRandomTransform() of HexagonalRuleTile missing MirrorXY case - [RuleOverrideTile] Fix RuleOverrideTile does not refresh when add/remove rule @@ -198,21 +262,26 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [RuleTile] Fix cache data will not update when rule change ## [1.3.0] - 2019-11-01 + ### Changed + - [RuleTile] changed from using index to using position. - [RuleTile] Additional storage rule position. - [RuleTile] Delete DontCare rule. - [RuleTile] Rule list increased Extend Neighbor toggle. When selected, it will increase the rule range that can be set. - [RuleTile] No longer fixed to checking around 8 rules. - [RuleTile] RefreshTile() will refresh affected remote Tiles. -- [RuleTile] Delete GetMatchingNeighboringTiles(), no longer get nearby Tiles in advance, the performance is affected. (may be changed to cache later) +- [RuleTile] Delete GetMatchingNeighboringTiles(), no longer get nearby Tiles in advance, the performance is affected. ( + may be changed to cache later) - [IsometricRuleTile] Rewrite. - [HexagonalRuleTile] Rewrite. - [LineBrush] Fix for Tiles disappear after selection and drag with LineBrush - [RuleTile] Add MirrorXY Transform Rule ## [1.2.0] - 2019-10-17 + ### Changed + - [PrefabBrush] Erase GameObjects at target position before painting - [RuleTileEditor] Made RuleTileEditor and children public - [RuleTile] Roll back m_Self to this. @@ -221,22 +290,30 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - [RuleOverrideTile] Change m_RuntimeTile to m_InstanceTile. ## [1.1.0] - 2019-08-23 + ### Changed + - Validate Gap and Limit for GroupBrush - Fix z iterator for RandomBrush - Check randomTileSets on addToRandomTiles - Add Anchor to GameObjectBrush and PrefabBrush ## [1.1.0] - 2019-03-22 + ### Changed + - Copy GameObject when copying TilingRule in RuleOverrideTile ## [1.1.0] - 2019-03-08 + ### Added + - Added com.unity.2d.tilemap as a dependency of com.unity.2d.tilemap.extras ### Changed + - Custom Grid Brushes have been updated to the UnityEditor.Tilemaps namespace ## [1.0.0] - 2019-01-02 + ### This is the first release of Tilemap Extras, as a Package diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 0c3a58b..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,6 +0,0 @@ -# Contributing - -## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement) -By making a pull request, you are confirming agreement to the terms and conditions of the UCA, including that your Contributions are your original creation and that you have complete right and authority to make your Contributions. - -## Once you have a change ready following these ground rules. Simply make a pull request! \ No newline at end of file diff --git a/CONTRIBUTING.md.meta b/CONTRIBUTING.md.meta deleted file mode 100644 index ee2ec1b..0000000 --- a/CONTRIBUTING.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6227377cf86ed2341ba50b1d9889f2f7 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Documentation~/AdvancedRuleOverrideTile.md b/Documentation~/AdvancedRuleOverrideTile.md index 915633a..f507ec8 100644 --- a/Documentation~/AdvancedRuleOverrideTile.md +++ b/Documentation~/AdvancedRuleOverrideTile.md @@ -2,24 +2,33 @@ __Contributions by:__ [johnsoncodehk](https://github.com/johnsoncodehk), [Autofire](https://github.com/Autofire) -__Advanced Rule Override Tiles__ are Tiles which can override a subset of Rules for a given [Rule Tile](RuleTile.md) while maintaining most of the other set Rules of the Rule Tile. This allows you to create Tiles that provide specialized behavior in specific scenarios. +__Advanced Rule Override Tiles__ are Tiles which can override a subset of Rules for a given [Rule Tile](RuleTile.md) +while maintaining most of the other set Rules of the Rule Tile. This allows you to create Tiles that provide specialized +behavior in specific scenarios. ## Properties -| Property | Function | -| ----------------- | ------------------------------------------------------------ | -| __Tile__ | The Rule Tile to override. | +| Property | Function | +|----------|----------------------------| +| __Tile__ | The Rule Tile to override. | -Depending on the Rule Tile that is overridden, there may be further properties which you can override here. Any public property in the Rule Tile that does not have a `RuleTile.DontOverride` attribute will be shown here and can be overridden. +Depending on the Rule Tile that is overridden, there may be further properties which you can override here. Any public +property in the Rule Tile that does not have a `RuleTile.DontOverride` attribute will be shown here and can be +overridden. ## Usage -First select the Rule Tile to be overridden in the __Tile__ property. The Rule Override Tile editor then displays the different rules in the selected Rule Tile which you can override. +First select the Rule Tile to be overridden in the __Tile__ property. The Rule Override Tile editor then displays the +different rules in the selected Rule Tile which you can override. -Select the Rule which you want to override by toggling the Rule. This will allow you to modify the output of the Rule, such as the Sprite, the GameObject or the Collider Type. The outputs are the same as the original [Rule Tile](RuleTile.md) and are detailed there. The matching Rule itself cannot be changed here and is displayed here to help identify it. +Select the Rule which you want to override by toggling the Rule. This will allow you to modify the output of the Rule, +such as the Sprite, the GameObject or the Collider Type. The outputs are the same as the +original [Rule Tile](RuleTile.md) and are detailed there. The matching Rule itself cannot be changed here and is +displayed here to help identify it. ![Advanced Rule Override Tile Editor](images/AdvancedRuleOverrideTileEditor.png) -Paint with the Advanced Rule Override Tile using the [Tile Palette](https://docs.unity3d.com/Manual/Tilemap-Painting.html) tools. +Paint with the Advanced Rule Override Tile using +the [Tile Palette](https://docs.unity3d.com/Manual/Tilemap-Painting.html) tools. ![Scene View with Advanced Rule Override Tile](images/AdvancedRuleOverrideTile.png) \ No newline at end of file diff --git a/Documentation~/AnimatedTile.md b/Documentation~/AnimatedTile.md index 2297d56..16cd98b 100644 --- a/Documentation~/AnimatedTile.md +++ b/Documentation~/AnimatedTile.md @@ -8,22 +8,24 @@ An Animated Tile runs through and displays a list of Sprites in sequence to crea ### Properties -| Property | Function | -| ------------------------------ | ------------------------------------------------------------ | -| __Number of Animated Sprites__ | Number of Animated Sprites in the Animated Tile. | +| Property | Function | +|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| __Number of Animated Sprites__ | Number of Animated Sprites in the Animated Tile. | | __Sprite list__ | The list displaying the current order of Sprites for this Animated Tile’s animation which plays in sequence. Set a Sprite by selecting the **Select** button at the bottom right of the Sprite preview, then choosing the Sprite from the dialog box. Select and hold the **=** next to each Sprite to reorder their place in the animation sequence. | -| __Minimum Speed__ | The minimum possible speed at which the Animation of the Tile is played. A speed value will be randomly chosen between the minimum and maximum speed. | -| __Maximum Speed__ | The maximum possible speed at which the Animation of the Tile is played. A speed value will be randomly chosen between the minimum and maximum speed. | -| __Start Time__ | The starting time of this Animated Tile. This allows you to start the Animation from a particular time. | -| __Start Frame__ | The starting frame of this Animated Tile. This allows you to start the Animation from a particular Sprite in the list of Animated Sprites. | -| __Collider Type__ | The [Collider](https://docs.unity3d.com/Manual/Collider2D.html) shape generated by the Tile. | -| __Flags__ | The Flags which control the Tile Animation. | -| Loop Once | The Tile Animation will loop through once and stop at the last Sprite of the animation. | -| Pause Animation | The Tile Animation will pause and not run. | -| Update Physics | The Tile Animation will update the Physics Shape in the TilemapCollider2D whenever it switches to the next Sprite in the animation. | +| __Minimum Speed__ | The minimum possible speed at which the Animation of the Tile is played. A speed value will be randomly chosen between the minimum and maximum speed. | +| __Maximum Speed__ | The maximum possible speed at which the Animation of the Tile is played. A speed value will be randomly chosen between the minimum and maximum speed. | +| __Start Time__ | The starting time of this Animated Tile. This allows you to start the Animation from a particular time. | +| __Start Frame__ | The starting frame of this Animated Tile. This allows you to start the Animation from a particular Sprite in the list of Animated Sprites. | +| __Collider Type__ | The [Collider](https://docs.unity3d.com/Manual/Collider2D.html) shape generated by the Tile. | +| __Flags__ | The Flags which control the Tile Animation. | +| Loop Once | The Tile Animation will loop through once and stop at the last Sprite of the animation. | +| Pause Animation | The Tile Animation will pause and not run. | +| Update Physics | The Tile Animation will update the Physics Shape in the TilemapCollider2D whenever it switches to the next Sprite in the animation. | ### Usage -Create the Animated Tile by selecting and ordering the Sprites that makes up its animation sequence in the Animated Tile editor, then paint the Animated Tile with the [Tile Palette tools](https://docs.unity3d.com/Manual/Tilemap-Painting.html). +Create the Animated Tile by selecting and ordering the Sprites that makes up its animation sequence in the Animated Tile +editor, then paint the Animated Tile with +the [Tile Palette tools](https://docs.unity3d.com/Manual/Tilemap-Painting.html). ![](images/AnimatedTile.png)
Game view, painted with the [Group Brush](GroupBrush.md). \ No newline at end of file diff --git a/Documentation~/Brushes.md b/Documentation~/Brushes.md index 1f7241c..f996e9f 100644 --- a/Documentation~/Brushes.md +++ b/Documentation~/Brushes.md @@ -1,6 +1,7 @@ # Scriptable Brushes -You can script Brushes to paint items based on the position and conditions of the cell it targets on the Grid Layout. Brush paint behavior can be further modified by the selected editing Tool, such as __Erase__ or __Floodfill__. +You can script Brushes to paint items based on the position and conditions of the cell it targets on the Grid Layout. +Brush paint behavior can be further modified by the selected editing Tool, such as __Erase__ or __Floodfill__. Here are some implementations of **Scriptable Brushes** which can help save time when designing your Tilemap: @@ -9,5 +10,6 @@ Here are some implementations of **Scriptable Brushes** which can help save time - [Line Brush](LineBrush.md) - [Group Brush](GroupBrush.md) -Refer to the [Scriptable Brushes](https://docs.unity3d.com/Manual/Tilemap-ScriptableBrushes.html) documentation for more information. +Refer to the [Scriptable Brushes](https://docs.unity3d.com/Manual/Tilemap-ScriptableBrushes.html) documentation for more +information. diff --git a/Documentation~/CustomRulesForRuleTile.md b/Documentation~/CustomRulesForRuleTile.md index 401edbf..c4e0c45 100644 --- a/Documentation~/CustomRulesForRuleTile.md +++ b/Documentation~/CustomRulesForRuleTile.md @@ -1,8 +1,10 @@ -# Custom Rules for Rule Tile +# Custom Rules for Rule Tile __Contribution by:__ [johnsoncodehk](https://github.com/johnsoncodehk) -Use this template script to create new custom [Rule Tiles](RuleTile.md) with matching options that differ from the Rule Tile’s [default options](RuleTile.md#Usage) (namely **This** and **Not This**). This creates selectable options for each Rule in your custom __Rule Tile__. +Use this template script to create new custom [Rule Tiles](RuleTile.md) with matching options that differ from the Rule +Tile’s [default options](RuleTile.md#Usage) (namely **This** and **Not This**). This creates selectable options for each +Rule in your custom __Rule Tile__. ## Template features @@ -16,7 +18,9 @@ Use this template script to create new custom [Rule Tiles](RuleTile.md) with mat ## Creating a custom Rule Tile script -Create a Custom Rule Tile script by going to __Assets > Create > Custom Rule Tile Script__. Name the newly created file when prompted. After creating the file, you can edit it to add new matching options and custom algorithms for testing matches. +Create a Custom Rule Tile script by going to __Assets > Create > Custom Rule Tile Script__. Name the newly created file +when prompted. After creating the file, you can edit it to add new matching options and custom algorithms for testing +matches. ### Examples @@ -24,8 +28,8 @@ Create a Custom Rule Tile script by going to __Assets > Create > Custom Rule Til ```csharp public class MyTile : RuleTile { - public string tileId; - public bool isWater; + public string tileId; + public bool isWater; } ``` @@ -33,17 +37,17 @@ public class MyTile : RuleTile { ```csharp public class MyTile : RuleTile { - public class Neighbor { - public const int MyRule1 = 0; - public const int MyRule2 = 1; - } - public override bool RuleMatch(int neighbor, TileBase tile) { - switch (neighbor) { - case Neighbor.MyRule1: return false; - case Neighbor.MyRule2: return true; - } - return true; - } + public class Neighbor { + public const int MyRule1 = 0; + public const int MyRule2 = 1; + } + public override bool RuleMatch(int neighbor, TileBase tile) { + switch (neighbor) { + case Neighbor.MyRule1: return false; + case Neighbor.MyRule2: return true; + } + return true; + } } ``` @@ -51,18 +55,18 @@ public class MyTile : RuleTile { ```csharp public class MyTile : RuleTile { - public class Neighbor : RuleTile.TilingRule.Neighbor { - // 0, 1, 2 is using in RuleTile.TilingRule.Neighbor - public const int MyRule1 = 3; - public const int MyRule2 = 4; - } - public override bool RuleMatch(int neighbor, TileBase tile) { - switch (neighbor) { - case Neighbor.MyRule1: return false; - case Neighbor.MyRule2: return true; - } - return base.RuleMatch(neighbor, tile); - } + public class Neighbor : RuleTile.TilingRule.Neighbor { + // 0, 1, 2 is using in RuleTile.TilingRule.Neighbor + public const int MyRule1 = 3; + public const int MyRule2 = 4; + } + public override bool RuleMatch(int neighbor, TileBase tile) { + switch (neighbor) { + case Neighbor.MyRule1: return false; + case Neighbor.MyRule2: return true; + } + return base.RuleMatch(neighbor, tile); + } } ``` @@ -70,16 +74,16 @@ public class MyTile : RuleTile { ```csharp public class MyTile : RuleTile { - public List sibings = new List(); - public class Neighbor : RuleTile.TilingRule.Neighbor { - public const int Sibing = 3; - } - public override bool RuleMatch(int neighbor, TileBase tile) { - switch (neighbor) { - case Neighbor.Sibing: return sibings.Contains(tile); - } - return base.RuleMatch(neighbor, tile); - } + public List sibings = new List(); + public class Neighbor : RuleTile.TilingRule.Neighbor { + public const int Sibing = 3; + } + public override bool RuleMatch(int neighbor, TileBase tile) { + switch (neighbor) { + case Neighbor.Sibing: return sibings.Contains(tile); + } + return base.RuleMatch(neighbor, tile); + } } ``` @@ -87,16 +91,16 @@ public class MyTile : RuleTile { ```csharp public class MyTile : RuleTile { - public int siblingGroup; - public class Neighbor : RuleTile.TilingRule.Neighbor { - public const int Sibing = 3; - } - public override bool RuleMatch(int neighbor, TileBase tile) { - MyTile myTile = tile as MyTile; - switch (neighbor) { - case Neighbor.Sibing: return myTile && myTile.siblingGroup == siblingGroup; - } - return base.RuleMatch(neighbor, tile); - } + public int siblingGroup; + public class Neighbor : RuleTile.TilingRule.Neighbor { + public const int Sibing = 3; + } + public override bool RuleMatch(int neighbor, TileBase tile) { + MyTile myTile = tile as MyTile; + switch (neighbor) { + case Neighbor.Sibing: return myTile && myTile.siblingGroup == siblingGroup; + } + return base.RuleMatch(neighbor, tile); + } } ``` \ No newline at end of file diff --git a/Documentation~/GameObjectBrush.md b/Documentation~/GameObjectBrush.md index 4c57f8a..ed83e89 100644 --- a/Documentation~/GameObjectBrush.md +++ b/Documentation~/GameObjectBrush.md @@ -1,10 +1,16 @@ # GameObject Brush ![GameObject Brush Icon](images/GameObjectBrushIcon.png) -This Brush instances, places and manipulates GameObjects onto the Scene. Use this Brush as an example for creating custom Brushes which can target and manipulate other GameObjects beside Tiles. +This Brush instances, places and manipulates GameObjects onto the Scene. Use this Brush as an example for creating +custom Brushes which can target and manipulate other GameObjects beside Tiles. ## Usage -First select the GameObject Brush from the Brush drop-down menu. With the Brush selected, then select the [Picker Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Picker) from the [Tile Palette](https://docs.unity3d.com/Manual/Tilemap-Painting.html) toolbar. Use the [Select Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Select) to select GameObjects from the Scene that you want the GameObject Brush to paint with. Note that these GameObjects must be a child of the active Grid to be selectable with this Brush. +First select the GameObject Brush from the Brush drop-down menu. With the Brush selected, then select +the [Picker Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Picker) from +the [Tile Palette](https://docs.unity3d.com/Manual/Tilemap-Painting.html) toolbar. Use +the [Select Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Select) to select GameObjects from the Scene +that you want the GameObject Brush to paint with. Note that these GameObjects must be a child of the active Grid to be +selectable with this Brush. When painting with the GameObject Brush, the Brush will instantiate GameObjects picked onto the Scene. @@ -12,10 +18,12 @@ When painting with the GameObject Brush, the Brush will instantiate GameObjects ## Implementation -The GameObjectBrush inherits from the GridBrush and overrides several methods when implemented. The following methods are overridden: +The GameObjectBrush inherits from the GridBrush and overrides several methods when implemented. The following methods +are overridden: -- It overrides the `Paint` method to paint a GameObject. -- It overrides the `Erase` method to erase the GameObjects from the Scene. -- It overrides the `BoxFill` method to paint a GameObject in each cell defined by the [Box Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Rec). -- It overrides the `Move` methods to move GameObjects in the Scene. +- It overrides the `Paint` method to paint a GameObject. +- It overrides the `Erase` method to erase the GameObjects from the Scene. +- It overrides the `BoxFill` method to paint a GameObject in each cell defined by + the [Box Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Rec). +- It overrides the `Move` methods to move GameObjects in the Scene. - It overrides the `Flip` methods to flip GameObjects in the picked selection. \ No newline at end of file diff --git a/Documentation~/GridInformation.md b/Documentation~/GridInformation.md index 5571eba..958d4f9 100644 --- a/Documentation~/GridInformation.md +++ b/Documentation~/GridInformation.md @@ -4,7 +4,8 @@ This is a simple component that stores and provides information based on Grid po ## Usage -Add this Component to a GameObject with a Grid component. To store information on to the Grid Information component, use the following APIs: +Add this Component to a GameObject with a Grid component. To store information on to the Grid Information component, use +the following APIs: ```C# public bool SetPositionProperty(Vector3Int position, String name, int positionProperty) @@ -20,22 +21,22 @@ public bool SetPositionProperty(Vector3Int position, String name, UnityEngine.Ob public bool SetPositionProperty(Vector3Int position, String name, Color positionProperty) ``` - - To retrieve information from the Grid Information component, use the following APIs: ```C# public T GetPositionProperty(Vector3Int position, String name, T defaultValue) where T : UnityEngine.Object public int GetPositionProperty(Vector3Int position, String name, int defaultValue) - + public string GetPositionProperty(Vector3Int position, String name, string defaultValue) - + public float GetPositionProperty(Vector3Int position, String name, float defaultValue) - + public double GetPositionProperty(Vector3Int position, String name, double defaultValue) - + public Color GetPositionProperty(Vector3Int position, String name, Color defaultValue) ``` -You can use this in combination with [Scriptable Tiles](https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles.html) to get the right [TileData](https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles-TileData.html) when creating the layout of your Tilemap. \ No newline at end of file +You can use this in combination with [Scriptable Tiles](https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles.html) to +get the right [TileData](https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles-TileData.html) when creating the layout +of your Tilemap. \ No newline at end of file diff --git a/Documentation~/GroupBrush.md b/Documentation~/GroupBrush.md index 23493be..8c0bab2 100644 --- a/Documentation~/GroupBrush.md +++ b/Documentation~/GroupBrush.md @@ -1,20 +1,24 @@ # Group Brush ![Group Brush Icon](images/GroupBrushIcon.png) -This Brush picks Tiles which are grouped together according to their position and its set properties. Set the __Gap__ value to identify which Tiles belong to the group, and set the __Limit__ value to ensure that the picked group remains within the desired size. Use this Brush as an example to create your own Brushes that can choose and pick specific Tiles +This Brush picks Tiles which are grouped together according to their position and its set properties. Set the __Gap__ +value to identify which Tiles belong to the group, and set the __Limit__ value to ensure that the picked group remains +within the desired size. Use this Brush as an example to create your own Brushes that can choose and pick specific Tiles ## Properties -| Property | Function | -| --------- | ------------------------------------------------------------ | +| Property | Function | +|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | __Gap__ | This value represents the minimum number of cells that must be in between picked Tiles. Only Tiles that are at least this many cells apart are picked by the Brush and placed in the group. Set this value to 0 to pick up all Tiles that are directly adjacent to each other in the group. | -| __Limit__ | This value represents the maximum number of cells around the initial picked position. Only Tiles within this range of cells are picked by the Brush and placed in the group. | +| __Limit__ | This value represents the maximum number of cells around the initial picked position. Only Tiles within this range of cells are picked by the Brush and placed in the group. | ## Usage -Select the Group Brush, and use the [Picker Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Picker) and pick a position on the Tilemap. The Group Brush selects a group of Tiles based on its set properties and creates a Group. +Select the Group Brush, and use the [Picker Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Picker) and pick +a position on the Tilemap. The Group Brush selects a group of Tiles based on its set properties and creates a Group. ![Scene View with Group Brush](images/GroupBrush.png) ## Implementation -The Group Brush inherits from the Grid Brush. It overrides the `Pick` method when picking a group of Tiles based on their position and its set properties. \ No newline at end of file +The Group Brush inherits from the Grid Brush. It overrides the `Pick` method when picking a group of Tiles based on +their position and its set properties. \ No newline at end of file diff --git a/Documentation~/LineBrush.md b/Documentation~/LineBrush.md index 49e9871..f728e9d 100644 --- a/Documentation~/LineBrush.md +++ b/Documentation~/LineBrush.md @@ -2,20 +2,25 @@ __Contribution by :__ [CraigGraff](https://github.com/CraigGraff) -This Brush draws a line of Tiles onto a Tilemap. With this Brush selected, click once to set the starting point of the line and click again at another position to set the ending point of the line. This Brush then draws a line of Tiles between the two points. +This Brush draws a line of Tiles onto a Tilemap. With this Brush selected, click once to set the starting point of the +line and click again at another position to set the ending point of the line. This Brush then draws a line of Tiles +between the two points. Use this as an example to create custom Brush behavior to make painting more efficient. ## Properties -| Property | Function | -| --------------------- | ------------------------------------------------------------ | -| __Line Start Active__ | Indicates whether the Line Brush has started drawing a line. | +| Property | Function | +|-----------------------|-------------------------------------------------------------------------------------------------------------| +| __Line Start Active__ | Indicates whether the Line Brush has started drawing a line. | | __Fill Gaps__ | Ensures that there are orthogonal connections between all Tiles that connect the start and end of the line. | -| __Line Start__ | The current starting point of the line. | +| __Line Start__ | The current starting point of the line. | ## Usage -Select the Line Brush, then click once on a cell of the Tilemap to set the starting point of the line, then click on a second cell to set the ending point of the line. The Brush then draws the line of Tiles between the two set points. When the Line Brush is active, a blue outline will indicate the starting point of the line. + +Select the Line Brush, then click once on a cell of the Tilemap to set the starting point of the line, then click on a +second cell to set the ending point of the line. The Brush then draws the line of Tiles between the two set points. When +the Line Brush is active, a blue outline will indicate the starting point of the line. ![Scene View with Line Brush](images/LineBrush.png) @@ -25,4 +30,5 @@ To have Tiles which are orthogonally connected from start to end, enable the __F ## Implementation -The Line Brush inherits from the Grid Brush and overrides the `Paint` method to implement the line painting functionality. \ No newline at end of file +The Line Brush inherits from the Grid Brush and overrides the `Paint` method to implement the line painting +functionality. \ No newline at end of file diff --git a/Documentation~/RandomBrush.md b/Documentation~/RandomBrush.md index 0fba72c..8b74f80 100644 --- a/Documentation~/RandomBrush.md +++ b/Documentation~/RandomBrush.md @@ -1,27 +1,36 @@ # Random Brush ![Random Brush Icon](images/RandomBrushIcon.png) -This Brush places random Tiles onto a Tilemap by selecting from defined **Tile Sets** while painting onto the the Tilemap. Use this as an example to create custom Brushes which store specific data per Brush, and to make Brushes with randomized painting behavior. +This Brush places random Tiles onto a Tilemap by selecting from defined **Tile Sets** while painting onto the the +Tilemap. Use this as an example to create custom Brushes which store specific data per Brush, and to make Brushes with +randomized painting behavior. ## Properties -| Property | Function | -| ----------------------- | ------------------------------------------------------------ | -| __Pick Random Tiles__ | Enable this property to pick the Tiles from the current selection as a random Tile Set. | +| Property | Function | +|-------------------------|---------------------------------------------------------------------------------------------------| +| __Pick Random Tiles__ | Enable this property to pick the Tiles from the current selection as a random Tile Set. | | __Add To Random Tiles__ | Enable this property to add the picked Tile Sets to existing Tile Sets instead of replacing them. | -| __Tile Set Size__ | Set the size of the Tile Set that is painted by this Brush. | -| __Number of Tiles__ | The number of Tile Sets. | -| __Tile Set__ | The Tile Set to randomize from | -| __Tiles__ | The Tiles in the Tile Set. | +| __Tile Set Size__ | Set the size of the Tile Set that is painted by this Brush. | +| __Number of Tiles__ | The number of Tile Sets. | +| __Tile Set__ | The Tile Set to randomize from | +| __Tiles__ | The Tiles in the Tile Set. | ## Usage -To create a **Tile Set**, first define the size of the Tile Set you want to paint by setting its size values in the **Tile Set Size** property. Then you can add Tile Sets manually with the Brush Editor or select them from an existing Tile Palette. +To create a **Tile Set**, first define the size of the Tile Set you want to paint by setting its size values in the * +*Tile Set Size** property. Then you can add Tile Sets manually with the Brush Editor or select them from an existing +Tile Palette. -To select Tile Sets from an existing [Tile Palette](https://docs.unity3d.com/Manual/Tilemap-Palette.html), enable the __Pick Random Tiles__ property and select the Tile Sets using the [Picker Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Picker). This will create a Tile Set, or multiple Sets if the picked size is larger than the size set in the **Tile Set Size** property. Enable the __Add To Random Tiles__ property to add a picked selection of Tiles onto new or existing Tile Sets instead of replacing them. +To select Tile Sets from an existing [Tile Palette](https://docs.unity3d.com/Manual/Tilemap-Palette.html), enable the _ +_Pick Random Tiles__ property and select the Tile Sets using +the [Picker Tool](https://docs.unity3d.com/Manual/Tilemap-Painting.html#Picker). This will create a Tile Set, or +multiple Sets if the picked size is larger than the size set in the **Tile Set Size** property. Enable the __Add To +Random Tiles__ property to add a picked selection of Tiles onto new or existing Tile Sets instead of replacing them. ![Brush Editor with Random Brush](images/RandomBrushTileSet.png)
In this example, 3 Tile Sets of 1x2 are created. -When painting with the Random Brush, the Random Brush will randomly pick from the available Tile Sets while painting the Tiles. +When painting with the Random Brush, the Random Brush will randomly pick from the available Tile Sets while painting the +Tiles. ![Scene View with Random Brush](images/RandomBrush.png) @@ -29,5 +38,5 @@ When painting with the Random Brush, the Random Brush will randomly pick from th The Random Brush inherits from the Grid Brush and implements the following overrides: -- It overrides the Paint method to paint random selections of Tiles from chosen Tile Sets. +- It overrides the Paint method to paint random selections of Tiles from chosen Tile Sets. - It overrides the Pick method to be able to pick selections of Tiles for the random Tile Sets. diff --git a/Documentation~/RuleOverrideTile.md b/Documentation~/RuleOverrideTile.md index 912b994..97592fd 100644 --- a/Documentation~/RuleOverrideTile.md +++ b/Documentation~/RuleOverrideTile.md @@ -2,27 +2,38 @@ __Contributions by:__ [johnsoncodehk](https://github.com/johnsoncodehk), [Autofire](https://github.com/Autofire) -__Rule Override Tiles__ are Tiles which can override the Sprites and GameObjects for a given [Rule Tile](RuleTile.md) while maintaining the Rule set of the Rule Tile. This allows you to create Tiles that provide variations of a Rule Tile without setting new Rules. +__Rule Override Tiles__ are Tiles which can override the Sprites and GameObjects for a given [Rule Tile](RuleTile.md) +while maintaining the Rule set of the Rule Tile. This allows you to create Tiles that provide variations of a Rule Tile +without setting new Rules. ## Properties -| Property | Function | -| ----------------- | ------------------------------------------------------------ | -| __Tile__ | The Rule Tile to override. | +| Property | Function | +|----------|----------------------------| +| __Tile__ | The Rule Tile to override. | -Depending on the Rule Tile that is overridden, there may be further properties which you can override here. Any public property in the Rule Tile that does not have a `RuleTile.DontOverride` attribute will be shown here and can be overridden. +Depending on the Rule Tile that is overridden, there may be further properties which you can override here. Any public +property in the Rule Tile that does not have a `RuleTile.DontOverride` attribute will be shown here and can be +overridden. ## Usage -First select the Rule Tile to be overridden in the __Tile__ property. The Editor then displays the different Sprites and GameObjects in the selected Rule Tile which you can override. +First select the Rule Tile to be overridden in the __Tile__ property. The Editor then displays the different Sprites and +GameObjects in the selected Rule Tile which you can override. -The editor displays the original Sprites that are used in the Rule Tile in the left column. Select the Sprites that override each of the respective original Sprites on the right ‘Override’ column. When the Rule Tile has a match that would usually output the original Sprite, it will instead output the override Sprite. +The editor displays the original Sprites that are used in the Rule Tile in the left column. Select the Sprites that +override each of the respective original Sprites on the right ‘Override’ column. When the Rule Tile has a match that +would usually output the original Sprite, it will instead output the override Sprite. -Below that, the editor displays the original GameObjects that are used in the Rule Tile in the left column. Select the GameObjects that override each of the respective original GameObjects on the right ‘Override’ column. When the Rule Tile has a match that would usually output the original GameObject, it will instead output the override GameObject. +Below that, the editor displays the original GameObjects that are used in the Rule Tile in the left column. Select the +GameObjects that override each of the respective original GameObjects on the right ‘Override’ column. When the Rule Tile +has a match that would usually output the original GameObject, it will instead output the override GameObject. ![Rule Override Tile Editor](images/RuleOverrideTileEditor.png) -If you have modified the original Rule Tile and changed the Sprites there, the Rule Override Tile will note that the original Sprites are missing. You can check the original Rule Tile to see if it is set up correctly or set the Override Sprites to None to remove the override. +If you have modified the original Rule Tile and changed the Sprites there, the Rule Override Tile will note that the +original Sprites are missing. You can check the original Rule Tile to see if it is set up correctly or set the Override +Sprites to None to remove the override. ![Rule Override Tile Editor with Missing Original Sprites](images/RuleOverrideTileEditorMissing.png) diff --git a/Documentation~/RuleTile.md b/Documentation~/RuleTile.md index ade85f4..40f92be 100644 --- a/Documentation~/RuleTile.md +++ b/Documentation~/RuleTile.md @@ -1,101 +1,130 @@ -# Rule Tile +# Rule Tile -__Contributions by:__ [johnsoncodehk](https://github.com/johnsoncodehk), [DreadBoy](https://github.com/DreadBoy), [AVChemodanov](https://github.com/AVChemodanov), [DoctorShinobi](https://github.com/DoctorShinobi), [n4n0lix](https://github.com/n4n0lix) +__Contributions by: +__ [johnsoncodehk](https://github.com/johnsoncodehk), [DreadBoy](https://github.com/DreadBoy), [AVChemodanov](https://github.com/AVChemodanov), [DoctorShinobi](https://github.com/DoctorShinobi), [n4n0lix](https://github.com/n4n0lix) -This is a generic visual Tile that other Tiles such as the [Terrain Tiles](TerrainTile.md), [Pipeline Tile](PipelineTile.md), [Random Tile](RandomTile.md) or [Animated Tiles](AnimatedTile.md) are based on. There are specific types of Rule Tiles for each of the [Tilemap grid types](https://docs.unity3d.com/Manual/class-Grid.html). The default Rule Tile is for the default [Rectangle Grid](https://docs.unity3d.com/Manual/Tilemap-CreatingTilemaps.html) type; the Hexagonal Rule Tile is for the [Hexagonal Grid](https://docs.unity3d.com/Manual/Tilemap-Hexagonal.html) type; and the Isometric Rule Tile is for the [Isometric Grid](https://docs.unity3d.com/Manual/Tilemap-Isometric.html) types. The different types of Rule Tiles all possess the same properties. +This is a generic visual Tile that other Tiles such as +the [Terrain Tiles](TerrainTile.md), [Pipeline Tile](PipelineTile.md), [Random Tile](RandomTile.md) +or [Animated Tiles](AnimatedTile.md) are based on. There are specific types of Rule Tiles for each of +the [Tilemap grid types](https://docs.unity3d.com/Manual/class-Grid.html). The default Rule Tile is for the +default [Rectangle Grid](https://docs.unity3d.com/Manual/Tilemap-CreatingTilemaps.html) type; the Hexagonal Rule Tile is +for the [Hexagonal Grid](https://docs.unity3d.com/Manual/Tilemap-Hexagonal.html) type; and the Isometric Rule Tile is +for the [Isometric Grid](https://docs.unity3d.com/Manual/Tilemap-Isometric.html) types. The different types of Rule +Tiles all possess the same properties. ## Properties ![](images/RuleTileEditor.png)
The Rule Tile editor of a Terrain Tile. -| Property | Function | -| ----------------------- | ------------------------------------------------------- | -| __Default Sprite__ | The default Sprite set when creating a new Rule. | +| Property | Function | +|------------------------|---------------------------------------------------------| +| __Default Sprite__ | The default Sprite set when creating a new Rule. | | __Default GameObject__ | The default GameObject set when creating a new Rule. | -| __Default Collider__ | The default Collider Type set when creating a new Rule. | +| __Default Collider__ | The default Collider Type set when creating a new Rule. | ### Tiling Rules ![](images/RuleTileRule.png)
Tiling Rules properties -| Property | Function | -| -------------- | ------------------------------------------------------------ | -| __Rule__ | The Rule Type for this Rule. | -| __GameObject__ | The GameObject for the Tile which fits this Rule. | -| __Collider__ | The Collider Type for the Tile which fits this Rule | +| Property | Function | +|----------------|----------------------------------------------------------------------------------------| +| __Rule__ | The Rule Type for this Rule. | +| __GameObject__ | The GameObject for the Tile which fits this Rule. | +| __Collider__ | The Collider Type for the Tile which fits this Rule | | __Output__ | The Output for the Tile which fits this Rule. Each Output type has its own properties. | ### Output: Fixed | Property | Function | -| ---------- | -------------------------------------------------- | +|------------|----------------------------------------------------| | __Sprite__ | Display this Sprite for Tiles which fit this Rule. | ### Output: Random -| Property | Function | -| ----------- | ------------------------------------------------------------ | -| __Noise__ | The [Perlin noise](https://en.wikipedia.org/wiki/Perlin_noise) factor when placing the Tile. | -| __Shuffle__ | The randomized transform given to the Tile when placing it. | -| __Size__ | The number of Sprites to randomize from. | +| Property | Function | +|-------------|-----------------------------------------------------------------------------------------------------------------| +| __Noise__ | The [Perlin noise](https://en.wikipedia.org/wiki/Perlin_noise) factor when placing the Tile. | +| __Shuffle__ | The randomized transform given to the Tile when placing it. | +| __Size__ | The number of Sprites to randomize from. | | __Sprite__ | The Sprite for the Tile which fits this Rule. A random Sprite will be chosen out of this when placing the Tile. | ### Output: Animation -| Property | Function | -| ---------- | ------------------------------------------------------------ | -| __MinSpeed__ | The minimum speed at which the animation is played. | -| __MaxSpeed__ | The maximum speed at which the animation is played. | -| __Size__ | The number of Sprites in the animation. | -| __Sprite__ | The Sprite for the Tile which fits this Rule. Sprites will be shown in sequence based on the order of the list. | +| Property | Function | +|--------------|-----------------------------------------------------------------------------------------------------------------| +| __MinSpeed__ | The minimum speed at which the animation is played. | +| __MaxSpeed__ | The maximum speed at which the animation is played. | +| __Size__ | The number of Sprites in the animation. | +| __Sprite__ | The Sprite for the Tile which fits this Rule. Sprites will be shown in sequence based on the order of the list. | ## Editor Properties -| Property | Function | -| ----------------------- | ------------------------------------------------------- | -| __Extend Neighbor__ | Enabling this allows you to increase the range of neighbors beyond the 3x3 box. | +| Property | Function | +|---------------------|---------------------------------------------------------------------------------| +| __Extend Neighbor__ | Enabling this allows you to increase the range of neighbors beyond the 3x3 box. | ## Setting up a Rule Tile -Set up the Rule Tile with the required rules with the __Rule Tile editor__. In the Rule Tile editor, you can change, add, duplicate or remove Rules in the **Tiling Rules** list. Click on the + or - buttons to add or remove Rules. If you have a Rule selected, clicking on the + button will allow you to choose between adding a new Rule or duplicating the selected Rule. The newly created Rule will be placed after the current selected Rule. Select and hold the top left corner of each row to drag them up or down to change the order of the Rules in the list. +Set up the Rule Tile with the required rules with the __Rule Tile editor__. In the Rule Tile editor, you can change, +add, duplicate or remove Rules in the **Tiling Rules** list. Click on the + or - buttons to add or remove Rules. If you +have a Rule selected, clicking on the + button will allow you to choose between adding a new Rule or duplicating the +selected Rule. The newly created Rule will be placed after the current selected Rule. Select and hold the top left +corner of each row to drag them up or down to change the order of the Rules in the list. ![](images/RuleTileEditor.png)
Rule Tile Editor -When you add a new Rule, the Rule editor displays the following: the list of Rule properties, a 3x3 box that visualizes the behavior of the set Rules, and a Sprite selector that displays a preview of the selected Sprite. +When you add a new Rule, the Rule editor displays the following: the list of Rule properties, a 3x3 box that visualizes +the behavior of the set Rules, and a Sprite selector that displays a preview of the selected Sprite. ![](images/RuleTileRule.png) -The 3x3 box represents the neighbors a Tile can have, where the center represents the Tile itself, and the eight bordering cells are its neighboring Tiles in their relative positions to the Tile. Each of the neighboring cells can be set with one of three options: **Don't Care**, **This** and **Not This**. These define the behavior of the Rule Tile towards these Tiles. Edit the 3x3 box to set up the Rule the Tile must match. +The 3x3 box represents the neighbors a Tile can have, where the center represents the Tile itself, and the eight +bordering cells are its neighboring Tiles in their relative positions to the Tile. Each of the neighboring cells can be +set with one of three options: **Don't Care**, **This** and **Not This**. These define the behavior of the Rule Tile +towards these Tiles. Edit the 3x3 box to set up the Rule the Tile must match. -| Options | Rule Tile behavior | -| -------------- | ------------------------------------------------------------ | -| __Don't Care__ | The Rule Tile ignores the contents in this cell. | -| __This__ | The Rule Tile checks if the contents of this cell is an instance of this Rule Tile. If it is an instance, the rule passes. If it is not an instance, the rule fails. | +| Options | Rule Tile behavior | +|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| __Don't Care__ | The Rule Tile ignores the contents in this cell. | +| __This__ | The Rule Tile checks if the contents of this cell is an instance of this Rule Tile. If it is an instance, the rule passes. If it is not an instance, the rule fails. | | __Not This__ | The Rule Tile checks if the contents of this cell is not an instance of this Rule Tile. If it is not an instance, the rule passes. If it is an instance, the rule fails. | -If all of the neighbors of the Rule Tile match the options set for their respective directions, then the Rule is considered matched and the rest of the Rule properties are applied. +If all of the neighbors of the Rule Tile match the options set for their respective directions, then the Rule is +considered matched and the rest of the Rule properties are applied. -When the Rule is set to Fixed, the Rule will only match exactly the conditions set for its neighbors. The example below will only match if there are the same Rule Tiles to the left and right of it. +When the Rule is set to Fixed, the Rule will only match exactly the conditions set for its neighbors. The example below +will only match if there are the same Rule Tiles to the left and right of it. ![Rule Tile with Fixed Rule](images/RuleTileRuleFixed.png) -When the Rule is set to ‘Rotated’, the 3x3 box will be rotated 90 degrees each time the Rule fails to match and it will try to match again with this rotated 3x3 box. If the Rule now matches, the contents of this Rule will be applied as well as the rotation required to match the Rule. Use this if you want the Rule to match for the four 90 degree rotations if rotation is possible. +When the Rule is set to ‘Rotated’, the 3x3 box will be rotated 90 degrees each time the Rule fails to match and it will +try to match again with this rotated 3x3 box. If the Rule now matches, the contents of this Rule will be applied as well +as the rotation required to match the Rule. Use this if you want the Rule to match for the four 90 degree rotations if +rotation is possible. ![Rule Tile with Rotated Rule](images/RuleTileRuleRotated.png) -When the Rule is set to Mirror X, Mirror Y or Mirror XY, the 3x3 box will be mirrored in that axis each time the Rule fails to match and it will try to match again with this mirrored 3x3 box. If the Rule now matches, the contents of this Rule will be applied as well as the mirroring required to match the Rule. Use this if you want the Rule to match for the mirrored locations if mirroring is possible. +When the Rule is set to Mirror X, Mirror Y or Mirror XY, the 3x3 box will be mirrored in that axis each time the Rule +fails to match and it will try to match again with this mirrored 3x3 box. If the Rule now matches, the contents of this +Rule will be applied as well as the mirroring required to match the Rule. Use this if you want the Rule to match for the +mirrored locations if mirroring is possible. ![Rule Tile with Mirror XY Rule](images/RuleTileRuleMirror.png) -If you want the Rule Tile to have a Random output, you can set the Output to Random. This will allow you to specify a number of input Sprites to randomize from. The rotation of the Sprites can be randomized as well by changing the __Shuffle__ property. +If you want the Rule Tile to have a Random output, you can set the Output to Random. This will allow you to specify a +number of input Sprites to randomize from. The rotation of the Sprites can be randomized as well by changing the _ +_Shuffle__ property. ![Rule Tile with Random Output](images/RuleTileOutputRandom.png) -If you want the Rule Tile to output a Sprite Animation, you can set the Output to Animation. This will allow you to specify a number of Sprites to animate sequentially. The speed of the Animation can be randomized as well by changing the __Speed__ property. +If you want the Rule Tile to output a Sprite Animation, you can set the Output to Animation. This will allow you to +specify a number of Sprites to animate sequentially. The speed of the Animation can be randomized as well by changing +the __Speed__ property. ![Rule Tile with Animation Output](images/RuleTileOutputAnimation.png) -When Extend Neighbors is enabled, the 3x3 box can be extended to allow for more specific neighbor matching. The Transform rule matching (eg. Rotated, Mirror) will apply for the extended neighbors set. +When Extend Neighbors is enabled, the 3x3 box can be extended to allow for more specific neighbor matching. The +Transform rule matching (eg. Rotated, Mirror) will apply for the extended neighbors set. ![Rule Tile with Animation Output](images/RuleTileRuleExtendNeighbor.png) @@ -103,4 +132,6 @@ Paint with the Rule Tile in the same way as other Tiles by using the Tile Palett ![Scene View with Rule Tile](images/RuleTile.png) -For optimization, please set the most common Rule at the top of the list of Rules and follow with next most common Rule and so on. When matching Rules during the placement of the Tile, the Rule Tile algorithm will check the first Rule first, before proceeding with the next Rules. \ No newline at end of file +For optimization, please set the most common Rule at the top of the list of Rules and follow with next most common Rule +and so on. When matching Rules during the placement of the Tile, the Rule Tile algorithm will check the first Rule +first, before proceeding with the next Rules. \ No newline at end of file diff --git a/Documentation~/TableOfContents.md b/Documentation~/TableOfContents.md index f110307..1f823c8 100644 --- a/Documentation~/TableOfContents.md +++ b/Documentation~/TableOfContents.md @@ -1,14 +1,14 @@ * [Overview](index.md) * [Scriptable Brushes](Brushes.md) - * [GameObject Brush](GameObjectBrush.md) - * [Group Brush](GroupBrush.md) - * [Line Brush](LineBrush.md) - * [Random Brush](RandomBrush.md) +* [GameObject Brush](GameObjectBrush.md) +* [Group Brush](GroupBrush.md) +* [Line Brush](LineBrush.md) +* [Random Brush](RandomBrush.md) * [Scriptable Tiles](Tiles.md) - * [Animated Tile](AnimatedTile.md) - * [Rule Tile](RuleTile.md) - * [Rule Override Tile](RuleOverrideTile.md) +* [Animated Tile](AnimatedTile.md) +* [Rule Tile](RuleTile.md) +* [Rule Override Tile](RuleOverrideTile.md) * [Other](Other.md) - * [Grid Information](GridInformation.md) - * [Custom Rules for Rule Tile](CustomRulesForRuleTile.md) - * [Contributors](Contributors.md) +* [Grid Information](GridInformation.md) +* [Custom Rules for Rule Tile](CustomRulesForRuleTile.md) +* [Contributors](Contributors.md) diff --git a/Documentation~/Tiles.md b/Documentation~/Tiles.md index 30445b4..f5c3fdb 100644 --- a/Documentation~/Tiles.md +++ b/Documentation~/Tiles.md @@ -1,9 +1,12 @@ # Scriptable Tiles -You can script Tiles to adapt to different criteria and conditions, such as its position on the Tilemap. It then displays the Sprite which meets its scripted requirements. This allows you to create different Tiles that can help you save time and be more efficient when creating Tilemaps. Refer to the [Scriptable Tiles](https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles.html) page for more information. - -The following **Scriptable Tiles** are included in this package, with examples of how they are implemented. You can use these Tiles as the base for your own custom Tiles as well. +You can script Tiles to adapt to different criteria and conditions, such as its position on the Tilemap. It then +displays the Sprite which meets its scripted requirements. This allows you to create different Tiles that can help you +save time and be more efficient when creating Tilemaps. Refer to +the [Scriptable Tiles](https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles.html) page for more information. +The following **Scriptable Tiles** are included in this package, with examples of how they are implemented. You can use +these Tiles as the base for your own custom Tiles as well. - [Animated Tile](AnimatedTile.md) - [Rule Tile](RuleTile.md) diff --git a/Documentation~/index.md b/Documentation~/index.md index 105e0e3..2b4767b 100644 --- a/Documentation~/index.md +++ b/Documentation~/index.md @@ -1,33 +1,58 @@ # 2D Tilemap Extras -The 2D Tilemap Extras package contains reusable 2D and Tilemap editor scripts which you can use for your own Projects, and as the basis for your own custom Brushes and Tiles. You can freely customize the behavior of the scripts to create new Brushes that suit different uses or scenarios. To find these additional Brushes, open the Tile Palette window (menu: __Window > 2D > Tile Palette__) and open the Brush drop-down menu near the bottom of the editor. Select from the available Brush options for different effects. +The 2D Tilemap Extras package contains reusable 2D and Tilemap editor scripts which you can use for your own Projects, +and as the basis for your own custom Brushes and Tiles. You can freely customize the behavior of the scripts to create +new Brushes that suit different uses or scenarios. To find these additional Brushes, open the Tile Palette window (menu: +__Window > 2D > Tile Palette__) and open the Brush drop-down menu near the bottom of the editor. Select from the +available Brush options for different effects. ![](images/BrushDropdown.png) -The source code for these scripts can be found in the repository [2d-extras](https://github.com/Unity-Technologies/2d-extras "2d-extras: Extras for 2d features"), and examples of the implemented scripts can be found in the sister repository [2d-techdemos](https://github.com/Unity-Technologies/2d-techdemos "2d-techdemos: Examples for 2d features"). +The source code for these scripts can be found in the +repository [2d-extras](https://github.com/Unity-Technologies/2d-extras "2d-extras: Extras for 2d features"), and +examples of the implemented scripts can be found in the sister +repository [2d-techdemos](https://github.com/Unity-Technologies/2d-techdemos "2d-techdemos: Examples for 2d features"). ## Scriptable Brushes -- [GameObject](GameObjectBrush.md): This Brush instances, places and manipulates GameObjects onto the Scene. Use this as an example to create Brushes which targets GameObjects, other than Tiles, for instancing and manipulation. +- [GameObject](GameObjectBrush.md): This Brush instances, places and manipulates GameObjects onto the Scene. Use this as + an example to create Brushes which targets GameObjects, other than Tiles, for instancing and manipulation. -- [Group](GroupBrush.md): This Brush picks groups of Tiles based on their positions relative to each other. Adjust the size of groups the Brush picks by setting the Gap and Limit properties. Use this Brush as an example to create Brushes that pick Tiles based on specific criteria. +- [Group](GroupBrush.md): This Brush picks groups of Tiles based on their positions relative to each other. Adjust the + size of groups the Brush picks by setting the Gap and Limit properties. Use this Brush as an example to create Brushes + that pick Tiles based on specific criteria. -- [Line](LineBrush.md): This Brush draws a line of Tiles between two points onto a Tilemap. Use this as an example to modify Brush painting behavior to make painting more efficient. +- [Line](LineBrush.md): This Brush draws a line of Tiles between two points onto a Tilemap. Use this as an example to + modify Brush painting behavior to make painting more efficient. -- [Random](RandomBrush.md): This Brush places random Tiles onto a Tilemap. Use this as an example to create Brushes which store specific data per Brush and to make Brushes which randomize behavior. +- [Random](RandomBrush.md): This Brush places random Tiles onto a Tilemap. Use this as an example to create Brushes + which store specific data per Brush and to make Brushes which randomize behavior. ## Scriptable Tiles -The following are the [Scriptable Tiles](Tiles.md) included in this package. You can create (menu: __Create > Tiles__ ) the following additional Tile types that are included with this package. - -- [Animated](AnimatedTile.md): This Tile runs through and displays a list of Sprites in sequence to create a frame-by-frame animation. -- [Rule Tile](RuleTile.md): This is a generic visual Tile that accepts rules you create with the __Tiling Rules__ editor to create different Tilesets. Rule Tiles are the basis of the Terrain, Pipeline, Random or Animated Tiles. There are different types of Rule Tiles for each of the [Tilemap grid types](https://docs.unity3d.com/Manual/class-Grid.html). The default Rule Tile is only used with the Rectangle Grid type Tilemap, while the Hexagonal and Isometric Rule Tiles are used with their respective Grid types. -- __Hexagonal Rule Tile__: A Rule Tile for [Hexagonal Grids](https://docs.unity3d.com/Documentation/Manual/Tilemap-Hexagonal.html). Enable the **Flat Top** property for a Flat Top Hexagonal Grid, or clear it for a Pointed Top Hexagonal Grid. -- __Isometric Rule Tile__: A Rule Tile for use with [Isometric Grids](https://docs.unity3d.com/Documentation/Manual/Tilemap-Isometric-CreateIso.html). -- [Rule Override Tile](RuleOverrideTile.md): This Tile can override Sprites and GameObjects for a given [Rule Tile](RuleTile.md) to provide different behaviour without changing the original Rules. -- [Advanced Rule Override Tile](AdvancedRuleOverrideTile.md): This Tile can override a subset of Rules for a given [Rule Tile](RuleTile.md) to provide specialized behavior, while keeping the rest of the original Rules intact. +The following are the [Scriptable Tiles](Tiles.md) included in this package. You can create (menu: __Create > Tiles__ ) +the following additional Tile types that are included with this package. + +- [Animated](AnimatedTile.md): This Tile runs through and displays a list of Sprites in sequence to create a + frame-by-frame animation. +- [Rule Tile](RuleTile.md): This is a generic visual Tile that accepts rules you create with the __Tiling Rules__ editor + to create different Tilesets. Rule Tiles are the basis of the Terrain, Pipeline, Random or Animated Tiles. There are + different types of Rule Tiles for each of the [Tilemap grid types](https://docs.unity3d.com/Manual/class-Grid.html). + The default Rule Tile is only used with the Rectangle Grid type Tilemap, while the Hexagonal and Isometric Rule Tiles + are used with their respective Grid types. +- __Hexagonal Rule Tile__: A Rule Tile + for [Hexagonal Grids](https://docs.unity3d.com/Documentation/Manual/Tilemap-Hexagonal.html). Enable the **Flat Top** + property for a Flat Top Hexagonal Grid, or clear it for a Pointed Top Hexagonal Grid. +- __Isometric Rule Tile__: A Rule Tile for use + with [Isometric Grids](https://docs.unity3d.com/Documentation/Manual/Tilemap-Isometric-CreateIso.html). +- [Rule Override Tile](RuleOverrideTile.md): This Tile can override Sprites and GameObjects for a + given [Rule Tile](RuleTile.md) to provide different behaviour without changing the original Rules. +- [Advanced Rule Override Tile](AdvancedRuleOverrideTile.md): This Tile can override a subset of Rules for a + given [Rule Tile](RuleTile.md) to provide specialized behavior, while keeping the rest of the original Rules intact. ## Other -- [GridInformation](GridInformation.md): A simple MonoBehavior that stores and provides information based on Grid positions and keywords. -- [Custom Rules for RuleTile](CustomRulesForRuleTile.md): This helps to create new custom Rules for the Rule Tile with more options. \ No newline at end of file +- [GridInformation](GridInformation.md): A simple MonoBehavior that stores and provides information based on Grid + positions and keywords. +- [Custom Rules for RuleTile](CustomRulesForRuleTile.md): This helps to create new custom Rules for the Rule Tile with + more options. \ No newline at end of file diff --git a/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs b/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs index e209b80..28a68af 100644 --- a/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs +++ b/Editor/Brushes/GameObjectBrush/GameObjectBrush.cs @@ -8,76 +8,88 @@ namespace UnityEditor.Tilemaps { /// - /// This Brush instances, places and manipulates GameObjects onto the scene. - /// Use this as an example to create brushes which targets objects other than tiles for manipulation. + /// This Brush instances, places and manipulates GameObjects onto the scene. + /// Use this as an example to create brushes which targets objects other than tiles for manipulation. /// - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GameObjectBrush.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GameObjectBrush.html")] [CustomGridBrush(true, false, false, "GameObject Brush")] public class GameObjectBrush : GridBrushBase { - [Serializable] - internal class HiddenGridLayout - { - public Vector3 cellSize = Vector3.one; - public Vector3 cellGap = Vector3.zero; - public GridLayout.CellLayout cellLayout = GridLayout.CellLayout.Rectangle; - public GridLayout.CellSwizzle cellSwizzle = GridLayout.CellSwizzle.XYZ; - } + [SerializeField] private BrushCell[] m_Cells; - [SerializeField] - private BrushCell[] m_Cells; + [SerializeField] private Vector3Int m_Size; - [SerializeField] - private Vector3Int m_Size; + [SerializeField] private Vector3Int m_Pivot; - [SerializeField] - private Vector3Int m_Pivot; + [SerializeField] [HideInInspector] private bool m_CanChangeZPosition; - [SerializeField] - [HideInInspector] - private bool m_CanChangeZPosition; + [SerializeField] [HideInInspector] internal HiddenGridLayout hiddenGridLayout = new(); - [SerializeField] - [HideInInspector] - internal HiddenGridLayout hiddenGridLayout = new HiddenGridLayout(); + /// + /// GameObject used for painting onto the Scene root + /// + [HideInInspector] public GameObject hiddenGrid; /// - /// GameObject used for painting onto the Scene root + /// Anchor Point of the Instantiated GameObject in the cell when painting /// - [HideInInspector] - public GameObject hiddenGrid; + public Vector3 m_Anchor = new(0.5f, 0.5f, 0.0f); /// - /// Anchor Point of the Instantiated GameObject in the cell when painting + /// This Brush instances, places and manipulates GameObjects onto the scene. /// - public Vector3 m_Anchor = new Vector3(0.5f, 0.5f, 0.0f); + public GameObjectBrush() + { + Init(Vector3Int.one, Vector3Int.zero); + SizeUpdated(); + } + /// Size of the brush in cells. - public Vector3Int size { get { return m_Size; } set { m_Size = value; SizeUpdated(); } } + public Vector3Int size + { + get => m_Size; + set + { + m_Size = value; + SizeUpdated(); + } + } + /// Pivot of the brush. - public Vector3Int pivot { get { return m_Pivot; } set { m_Pivot = value; } } + public Vector3Int pivot + { + get => m_Pivot; + set => m_Pivot = value; + } + /// All the brush cells the brush holds. - public BrushCell[] cells { get { return m_Cells; } } + public BrushCell[] cells => m_Cells; + /// Number of brush cells in the brush. - public int cellCount { get { return m_Cells != null ? m_Cells.Length : 0; } } + public int cellCount => m_Cells != null ? m_Cells.Length : 0; + /// Number of brush cells based on size. - public int sizeCount - { - get { return m_Size.x * m_Size.y * m_Size.z; } - } + public int sizeCount => m_Size.x * m_Size.y * m_Size.z; + /// Whether the brush can change Z Position public bool canChangeZPosition { - get { return m_CanChangeZPosition; } - set { m_CanChangeZPosition = value; } + get => m_CanChangeZPosition; + set => m_CanChangeZPosition = value; } - - /// - /// This Brush instances, places and manipulates GameObjects onto the scene. - /// - public GameObjectBrush() + + /// Clears all data of the brush. + public void Reset() { - Init(Vector3Int.one, Vector3Int.zero); - SizeUpdated(); + foreach (var cell in m_Cells) + { + if (cell.gameObject != null && !EditorUtility.IsPersistent(cell.gameObject)) + DestroyImmediate(cell.gameObject); + cell.gameObject = null; + } + + UpdateSizeAndPivot(Vector3Int.one, Vector3Int.zero); } private void OnEnable() @@ -109,7 +121,7 @@ private void OnValidate() } /// - /// Initializes the content of the GameObjectBrush. + /// Initializes the content of the GameObjectBrush. /// /// Size of the GameObjectBrush. public void Init(Vector3Int size) @@ -129,8 +141,8 @@ public void Init(Vector3Int size, Vector3Int pivot) } /// - /// Paints GameObjects into a given position within the selected layers. - /// The GameObjectBrush overrides this to provide GameObject painting functionality. + /// Paints GameObjects into a given position within the selected layers. + /// The GameObjectBrush overrides this to provide GameObject painting functionality. /// /// Grid used for layout. /// Target of the paint operation. By default the currently selected GameObject. @@ -150,14 +162,13 @@ private void PaintCell(GridLayout grid, Vector3Int position, Transform parent, B 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); - } + SetSceneCell(grid, parent, position, cell.gameObject, cell.offset, cell.scale, cell.orientation, + m_Anchor); } /// - /// Erases GameObjects in a given position within the selected layers. - /// The GameObjectBrush overrides this to provide GameObject erasing functionality. + /// Erases GameObjects in a given position within the selected layers. + /// The GameObjectBrush overrides this to provide GameObject erasing functionality. /// /// Grid used for layout. /// Target of the erase operation. By default the currently selected GameObject. @@ -177,8 +188,8 @@ private void EraseCell(GridLayout grid, Vector3Int position, Transform parent, B } /// - /// Box fills GameObjects into given bounds within the selected layers. - /// The GameObjectBrush overrides this to provide GameObject box-filling functionality. + /// Box fills GameObjects into given bounds within the selected layers. + /// The GameObjectBrush overrides this to provide GameObject box-filling functionality. /// /// Grid to box fill data to. /// Target of the box fill operation. By default the currently selected GameObject. @@ -186,7 +197,7 @@ private void EraseCell(GridLayout grid, Vector3Int position, Transform parent, B public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) { GetGrid(ref gridLayout, ref brushTarget); - + foreach (var location in position.allPositionsWithin) { var local = location - position.min; @@ -196,8 +207,8 @@ public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, Boun } /// - /// Erases GameObjects from given bounds within the selected layers. - /// The GameObjectBrush overrides this to provide GameObject box-erasing functionality. + /// Erases GameObjects from given bounds within the selected layers. + /// The GameObjectBrush overrides this to provide GameObject box-erasing functionality. /// /// Grid to erase data from. /// Target of the erase operation. By default the currently selected GameObject. @@ -205,7 +216,7 @@ public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, Boun public override void BoxErase(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) { GetGrid(ref gridLayout, ref brushTarget); - + foreach (var location in position.allPositionsWithin) { var local = location - position.min; @@ -215,7 +226,8 @@ public override void BoxErase(GridLayout gridLayout, GameObject brushTarget, Bou } /// - /// This is not supported but it should flood-fill 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. @@ -226,7 +238,7 @@ public override void FloodFill(GridLayout gridLayout, GameObject brushTarget, Ve } /// - /// Rotates the brush by 90 degrees in the given direction. + /// Rotates the brush by 90 degrees in the given direction. /// /// Direction to rotate by. /// Cell Layout for rotating. @@ -237,7 +249,7 @@ public override void Rotate(RotationDirection direction, GridLayout.CellLayout l size = new Vector3Int(oldSize.y, oldSize.x, oldSize.z); var oldBounds = new BoundsInt(Vector3Int.zero, oldSize); - foreach (Vector3Int oldPos in oldBounds.allPositionsWithin) + foreach (var oldPos in oldBounds.allPositionsWithin) { var newX = direction == RotationDirection.Clockwise ? oldSize.y - oldPos.y - 1 : oldPos.y; var newY = direction == RotationDirection.Clockwise ? oldPos.x : oldSize.x - oldPos.x - 1; @@ -250,8 +262,8 @@ public override void Rotate(RotationDirection direction, GridLayout.CellLayout l 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); - foreach (BrushCell cell in m_Cells) + var orientation = Quaternion.Euler(0f, 0f, direction != RotationDirection.Clockwise ? 90f : -90f); + foreach (var cell in m_Cells) cell.orientation = cell.orientation * orientation; } @@ -267,8 +279,8 @@ public override void Flip(FlipAxis flip, GridLayout.CellLayout layout) } /// - /// Picks child GameObjects given the coordinates of the cells. - /// The GameObjectBrush overrides this to provide GameObject picking functionality. + /// Picks child GameObjects given the coordinates of the cells. + /// The GameObjectBrush overrides this to provide GameObject picking functionality. /// /// Grid to pick data from. /// Target of the picking operation. By default the currently selected GameObject. @@ -277,18 +289,20 @@ public override void Flip(FlipAxis flip, GridLayout.CellLayout layout) public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, Vector3Int pivot) { Reset(); - UpdateSizeAndPivot(new Vector3Int(position.size.x, position.size.y, 1), new Vector3Int(pivot.x, pivot.y, 0)); + UpdateSizeAndPivot(new Vector3Int(position.size.x, position.size.y, 1), + new Vector3Int(pivot.x, pivot.y, 0)); GetGrid(ref gridLayout, ref brushTarget); - - 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, brushTarget != null ? brushTarget.transform : null, true); } } - private void PickCell(Vector3Int position, Vector3Int brushPosition, GridLayout grid, Transform parent, bool withoutAnchor = false) + private void PickCell(Vector3Int position, Vector3Int brushPosition, GridLayout grid, Transform parent, + bool withoutAnchor = false) { GameObject go = null; if (!withoutAnchor) @@ -307,11 +321,11 @@ private void PickCell(Vector3Int position, Vector3Int brushPosition, GridLayout Object prefab = PrefabUtility.GetCorrespondingObjectFromSource(go); if (prefab) { - SetGameObject(brushPosition, (GameObject) prefab); + SetGameObject(brushPosition, (GameObject)prefab); } else { - GameObject newInstance = Instantiate(go); + var newInstance = Instantiate(go); newInstance.hideFlags = HideFlags.HideAndDontSave; newInstance.SetActive(false); SetGameObject(brushPosition, newInstance); @@ -324,8 +338,8 @@ private void PickCell(Vector3Int position, Vector3Int brushPosition, GridLayout } /// - /// MoveStart is called when user starts moving the area previously selected with the selection marquee. - /// The GameObjectBrush overrides this to provide GameObject moving functionality. + /// MoveStart is called when user starts moving the area previously selected with the selection marquee. + /// The GameObjectBrush overrides this to provide GameObject moving functionality. /// /// Grid used for layout. /// Target of the move operation. By default the currently selected GameObject. @@ -348,8 +362,8 @@ public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, Bo } /// - /// MoveEnd is called when user has ended the move of the area previously selected with the selection marquee. - /// The GameObjectBrush overrides this to provide GameObject moving functionality. + /// MoveEnd is called when user has ended the move of the area previously selected with the selection marquee. + /// The GameObjectBrush overrides this to provide GameObject moving functionality. /// /// Grid used for layout. /// Target of the move operation. By default the currently selected GameObject. @@ -372,20 +386,6 @@ private void GetGrid(ref GridLayout gridLayout, ref GameObject brushTarget) gridLayout = targetGridLayout; } } - - /// Clears all data of the brush. - public void Reset() - { - foreach (var cell in m_Cells) - { - if (cell.gameObject != null && !EditorUtility.IsPersistent(cell.gameObject)) - { - DestroyImmediate(cell.gameObject); - } - cell.gameObject = null; - } - UpdateSizeAndPivot(Vector3Int.one, Vector3Int.zero); - } private void FlipX() { @@ -402,7 +402,7 @@ private void FlipX() var newPivotX = m_Size.x - pivot.x - 1; pivot = new Vector3Int(newPivotX, pivot.y, pivot.z); - + FlipCells(ref m_Cells, new Vector3(-1f, 1f, 1f)); } @@ -424,13 +424,10 @@ private void FlipY() FlipCells(ref m_Cells, new Vector3(1f, -1f, 1f)); } - + private static void FlipCells(ref BrushCell[] cells, Vector3 scale) { - foreach (BrushCell cell in cells) - { - cell.scale = Vector3.Scale(cell.scale, scale); - } + foreach (var cell in cells) cell.scale = Vector3.Scale(cell.scale, scale); } /// Updates the size, pivot and the number of layers of the brush. @@ -444,7 +441,7 @@ public void UpdateSizeAndPivot(Vector3Int size, Vector3Int pivot) } /// - /// Sets a GameObject at the position in the brush. + /// Sets a GameObject at the position in the brush. /// /// Position to set the GameObject in the brush. /// GameObject to set in the brush. @@ -455,7 +452,7 @@ public void SetGameObject(Vector3Int position, GameObject go) } /// - /// Sets a position offset at the position in the brush. + /// Sets a position offset at the position in the brush. /// /// Position to set the offset in the brush. /// Offset to set in the brush. @@ -466,7 +463,7 @@ public void SetOffset(Vector3Int position, Vector3 offset) } /// - /// Sets an orientation at the position in the brush. + /// Sets an orientation at the position in the brush. /// /// Position to set the orientation in the brush. /// Orientation to set in the brush. @@ -477,7 +474,7 @@ public void SetOrientation(Vector3Int position, Quaternion orientation) } /// - /// Sets a scale at the position in the brush. + /// Sets a scale at the position in the brush. /// /// Position to set the scale in the brush. /// Scale to set in the brush. @@ -518,17 +515,21 @@ public int GetCellIndex(int x, int y, int z, int sizex, int sizey, int sizez) return x + sizex * y + sizex * sizey * z; } - /// Gets the index to the GameObjectBrush::ref::BrushCell based on the position of the BrushCell. Wraps each coordinate if it is larger than the size of the GameObjectBrush. + /// + /// Gets the index to the GameObjectBrush::ref::BrushCell based on the position of the BrushCell. Wraps each + /// coordinate if it is larger than the size of the GameObjectBrush. + /// /// X Position of the BrushCell. /// Y Position of the BrushCell. /// Z Position of the BrushCell. /// The cell index for the position of the BrushCell. 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); + 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, Vector3 offset) + private GameObject GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position, Vector3 anchor, + Vector3 offset) { int childCount; GameObject[] sceneChildren = null; @@ -552,6 +553,7 @@ private GameObject GetObjectInCell(GridLayout grid, Transform parent, Vector3Int if (position == childCell) return child.gameObject; } + return null; } @@ -562,7 +564,9 @@ private bool ValidateCellPosition(Vector3Int position) position.y >= 0 && position.y < size.y && position.z >= 0 && position.z < size.z; if (!valid) - throw new ArgumentException(string.Format("Position {0} is an invalid cell position. Valid range is between [{1}, {2}).", position, Vector3Int.zero, size)); + throw new ArgumentException(string.Format( + "Position {0} is an invalid cell position. Valid range is between [{1}, {2}).", position, + Vector3Int.zero, size)); return true; } @@ -572,13 +576,12 @@ internal void SizeUpdated(bool keepContents = false) Array.Resize(ref m_Cells, sizeCount); var bounds = new BoundsInt(Vector3Int.zero, m_Size); foreach (var pos in bounds.allPositionsWithin) - { if (keepContents || m_Cells[GetCellIndex(pos)] == null) m_Cells[GetCellIndex(pos)] = new BrushCell(); - } } - private static void SetSceneCell(GridLayout grid, Transform parent, Vector3Int position, GameObject go, Vector3 offset, Vector3 scale, Quaternion orientation, Vector3 anchor) + private static void SetSceneCell(GridLayout grid, Transform parent, Vector3Int position, GameObject go, + Vector3 offset, Vector3 scale, Quaternion orientation, Vector3 anchor) { if (go == null) return; @@ -586,7 +589,8 @@ private static void SetSceneCell(GridLayout grid, Transform parent, Vector3Int p GameObject instance; if (PrefabUtility.IsPartOfPrefabAsset(go)) { - instance = (GameObject) PrefabUtility.InstantiatePrefab(go, parent != null ? parent.root.gameObject.scene : SceneManager.GetActiveScene()); + instance = (GameObject)PrefabUtility.InstantiatePrefab(go, + parent != null ? parent.root.gameObject.scene : SceneManager.GetActiveScene()); instance.transform.parent = parent; } else @@ -594,16 +598,15 @@ private static void SetSceneCell(GridLayout grid, Transform parent, Vector3Int p instance = Instantiate(go, parent); instance.name = go.name; instance.SetActive(true); - foreach (var renderer in instance.GetComponentsInChildren()) - { - renderer.enabled = true; - } + foreach (var renderer in instance.GetComponentsInChildren()) renderer.enabled = true; } + instance.hideFlags = HideFlags.None; Undo.RegisterCreatedObjectUndo(instance, "Paint GameObject"); var anchorRatio = GetAnchorRatio(grid, anchor); - instance.transform.position = grid.LocalToWorld(grid.CellToLocalInterpolated(position) + grid.CellToLocalInterpolated(anchorRatio)); + instance.transform.position = + grid.LocalToWorld(grid.CellToLocalInterpolated(position) + grid.CellToLocalInterpolated(anchorRatio)); instance.transform.localRotation = orientation; instance.transform.localScale = scale; instance.transform.Translate(offset); @@ -623,7 +626,7 @@ private static Vector3 GetAnchorRatio(GridLayout grid, Vector3 cellAnchor) ); return anchorRatio; } - + private void ClearSceneCell(GridLayout grid, Transform parent, Vector3Int position, BrushCell cell) { var erased = GetObjectInCell(grid, parent, position, m_Anchor, cell.offset); @@ -632,19 +635,17 @@ private void ClearSceneCell(GridLayout grid, Transform parent, Vector3Int positi } /// - /// Hashes the contents of the brush. + /// Hashes the contents of the brush. /// /// A hash code of the brush public override int GetHashCode() { - int hash = 0; + var hash = 0; unchecked { - foreach (var cell in cells) - { - hash = hash * 33 + cell.GetHashCode(); - } + foreach (var cell in cells) hash = hash * 33 + cell.GetHashCode(); } + return hash; } @@ -657,14 +658,31 @@ internal void UpdateHiddenGridLayout() hiddenGridLayout.cellLayout = grid.cellLayout; } + [Serializable] + internal class HiddenGridLayout + { + public Vector3 cellSize = Vector3.one; + public Vector3 cellGap = Vector3.zero; + public GridLayout.CellLayout cellLayout = GridLayout.CellLayout.Rectangle; + public GridLayout.CellSwizzle cellSwizzle = GridLayout.CellSwizzle.XYZ; + } + /// - ///Brush Cell stores the data to be painted in a grid cell. + /// Brush Cell stores the data to be painted in a grid cell. /// [Serializable] public class BrushCell { + [SerializeField] private GameObject m_GameObject; + + [SerializeField] private Vector3 m_Offset = Vector3.zero; + + [SerializeField] private Vector3 m_Scale = Vector3.one; + + [SerializeField] private Quaternion m_Orientation = Quaternion.identity; + /// - /// GameObject to be placed when painting. + /// GameObject to be placed when painting. /// public GameObject gameObject { @@ -673,41 +691,34 @@ public GameObject gameObject } /// - /// Position offset of the GameObject when painted. + /// Position offset of the GameObject when painted. /// public Vector3 offset { get => m_Offset; set => m_Offset = value; } + /// - /// Scale of the GameObject when painted. + /// Scale of the GameObject when painted. /// - public Vector3 scale - { + public Vector3 scale + { get => m_Scale; set => m_Scale = value; } + /// - /// Orientation of the GameObject when painted. + /// Orientation of the GameObject when painted. /// - public Quaternion orientation + public Quaternion orientation { get => m_Orientation; set => m_Orientation = value; } - - [SerializeField] - private GameObject m_GameObject; - [SerializeField] - Vector3 m_Offset = Vector3.zero; - [SerializeField] - Vector3 m_Scale = Vector3.one; - [SerializeField] - Quaternion m_Orientation = Quaternion.identity; /// - /// Hashes the contents of the brush cell. + /// Hashes the contents of the brush cell. /// /// A hash code of the brush cell. public override int GetHashCode() @@ -720,28 +731,31 @@ public override int GetHashCode() hash = hash * 33 + scale.GetHashCode(); hash = hash * 33 + orientation.GetHashCode(); } + return hash; } } } /// - /// The Brush Editor for a GameObject Brush. + /// The Brush Editor for a GameObject Brush. /// [CustomEditor(typeof(GameObjectBrush))] public class GameObjectBrushEditor : GridBrushEditorBase { - private static readonly string iconPath = "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/GameObjectBrush/GameObjectBrush.png"; - - private Texture2D m_BrushIcon; - - private bool hiddenGridFoldout; + private static readonly string iconPath = + "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/GameObjectBrush/GameObjectBrush.png"; + private Editor hiddenGridEditor; + private bool hiddenGridFoldout; + + private Texture2D m_BrushIcon; + /// - /// The GameObjectBrush for this Editor + /// The GameObjectBrush for this Editor /// - public GameObjectBrush brush { get { return target as GameObjectBrush; } } + public GameObjectBrush brush => target as GameObjectBrush; /// Whether the GridBrush can change Z Position. public override bool canChangeZPosition @@ -749,68 +763,95 @@ public override bool canChangeZPosition get => brush.canChangeZPosition; set => brush.canChangeZPosition = value; } - + /// - /// Whether the Brush is in a state that should be saved for selection. + /// Whether the Brush is in a state that should be saved for selection. /// public override bool shouldSaveBrushForSelection { get { if (brush.cells != null) - { foreach (var cell in brush.cells) - { if (cell != null && cell.gameObject != null) return true; - } - } return false; } } - + /// - /// Callback for painting the GUI for the GridBrush in the Scene View. - /// The GameObjectBrush Editor overrides this to draw the preview of the brush when drawing lines. + /// The targets that the GameObjectBrush can paint on + /// + public override GameObject[] validTargets + { + get + { + var currentStageHandle = StageUtility.GetCurrentStageHandle(); + var results = currentStageHandle.FindComponentsOfType(); + var validGridLayouts = new List(results.Length + 1) { brush.hiddenGrid }; + foreach (var result in results) + if (result.gameObject.scene.isLoaded && result.gameObject.activeInHierarchy) + validGridLayouts.Add(result.gameObject); + return validGridLayouts.ToArray(); + } + } + + /// Returns an icon identifying the GameObject Brush. + public override Texture2D icon + { + get + { + if (m_BrushIcon == null) + { + var gui = EditorGUIUtility.TrIconContent(iconPath); + m_BrushIcon = gui.image as Texture2D; + } + + return m_BrushIcon; + } + } + + /// + /// Callback for painting the GUI for the GridBrush in the Scene View. + /// The GameObjectBrush Editor overrides this to draw the preview of the brush when drawing lines. /// /// Grid that the brush is being used on. - /// Target of the GameObjectBrush::ref::Tool operation. By default the currently selected GameObject. + /// + /// Target of the GameObjectBrush::ref::Tool operation. By default the currently selected + /// GameObject. + /// /// Current selected location of the brush. /// Current GameObjectBrush::ref::Tool selected. /// Whether brush is being used. - public override void OnPaintSceneGUI(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing) + public override void OnPaintSceneGUI(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, + GridBrushBase.Tool tool, bool executing) { var gizmoRect = position; if (tool == GridBrushBase.Tool.Paint || tool == GridBrushBase.Tool.Erase) gizmoRect = new BoundsInt(position.min - brush.pivot, brush.size); - + base.OnPaintSceneGUI(gridLayout, brushTarget, gizmoRect, tool, executing); } /// - /// Callback for painting the inspector GUI for the GameObjectBrush in the tilemap palette. - /// The GameObjectBrush Editor overrides this to show the usage of this Brush. + /// Callback for painting the inspector GUI for the GameObjectBrush in the tilemap palette. + /// The GameObjectBrush Editor overrides this to show the usage of this Brush. /// public override void OnPaintInspectorGUI() { EditorGUI.BeginChangeCheck(); base.OnInspectorGUI(); - if (EditorGUI.EndChangeCheck() && brush.cellCount != brush.sizeCount) - { - brush.SizeUpdated(true); - } + if (EditorGUI.EndChangeCheck() && brush.cellCount != brush.sizeCount) brush.SizeUpdated(true); - hiddenGridFoldout = EditorGUILayout.Foldout(hiddenGridFoldout, "SceneRoot Grid"); + hiddenGridFoldout = EditorGUILayout.Foldout(hiddenGridFoldout, "SceneRoot Grid", true); if (hiddenGridFoldout) { EditorGUI.indentLevel++; using (new EditorGUI.DisabledScope(GridPaintingState.scenePaintTarget != brush.hiddenGrid)) { if (hiddenGridEditor == null) - { - hiddenGridEditor = Editor.CreateEditor(brush.hiddenGrid.GetComponent()); - } + hiddenGridEditor = CreateEditor(brush.hiddenGrid.GetComponent()); brush.hiddenGrid.hideFlags = HideFlags.None; EditorGUI.BeginChangeCheck(); hiddenGridEditor.OnInspectorGUI(); @@ -820,50 +861,33 @@ public override void OnPaintInspectorGUI() EditorUtility.SetDirty(brush); SceneView.RepaintAll(); } + brush.hiddenGrid.hideFlags = HideFlags.HideAndDontSave; } - EditorGUI.indentLevel--; - } - } - /// - /// The targets that the GameObjectBrush can paint on - /// - public override GameObject[] validTargets - { - get - { - var currentStageHandle = StageUtility.GetCurrentStageHandle(); - var results = currentStageHandle.FindComponentsOfType(); - var validGridLayouts = new List(results.Length + 1) { brush.hiddenGrid }; - foreach (var result in results) - { - if (result.gameObject.scene.isLoaded && result.gameObject.activeInHierarchy) - validGridLayouts.Add(result.gameObject); - } - return validGridLayouts.ToArray(); + EditorGUI.indentLevel--; } } /// - /// Creates a static preview of the GameObjectBrush with its current selection. + /// Creates a static preview of the GameObjectBrush with its current selection. /// /// The asset to operate on. /// An array of all Assets at assetPath. /// Width of the created texture. /// Height of the created texture. /// Generated texture or null. - public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Object[] subAssets, int width, int height) + public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) { if (brush == null) return null; var previewInstance = new GameObject("Brush Preview", typeof(Grid)); var previewGrid = previewInstance.GetComponent(); - + brush.Paint(previewGrid, previewInstance, Vector3Int.zero); - var center = ((Vector3) brush.size * 0.5f) - (Vector3) brush.pivot; + var center = (Vector3)brush.size * 0.5f - brush.pivot; center.z -= 10f; var rect = new Rect(0, 0, width, height); @@ -883,19 +907,5 @@ public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Obje return tex; } - - /// Returns an icon identifying the GameObject Brush. - public override Texture2D icon - { - get - { - if (m_BrushIcon == null) - { - var gui = EditorGUIUtility.TrIconContent(iconPath); - m_BrushIcon = gui.image as Texture2D; - } - return m_BrushIcon; - } - } } } \ No newline at end of file diff --git a/Editor/Brushes/GroupBrush/GroupBrush.cs b/Editor/Brushes/GroupBrush/GroupBrush.cs index 821ae58..d21a6d4 100644 --- a/Editor/Brushes/GroupBrush/GroupBrush.cs +++ b/Editor/Brushes/GroupBrush/GroupBrush.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; @@ -6,18 +6,29 @@ namespace UnityEditor.Tilemaps { /// - /// This Brush helps to pick Tiles which are grouped together by position. Gaps can be set to identify if Tiles belong to a Group. Limits can be set to ensure that an over-sized Group will not be picked. Use this as an example to create brushes that have the ability to choose and pick whichever Tiles it is interested in. + /// This Brush helps to pick Tiles which are grouped together by position. Gaps can be set to identify if Tiles belong + /// to a Group. Limits can be set to ensure that an over-sized Group will not be picked. Use this as an example to + /// create brushes that have the ability to choose and pick whichever Tiles it is interested in. /// - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GroupBrush.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GroupBrush.html")] [CustomGridBrush(true, false, false, "Group Brush")] public class GroupBrush : GridBrush { + [SerializeField] private Vector3Int m_Gap = Vector3Int.one; + + [SerializeField] private Vector3Int m_Limit = Vector3Int.one * 3; + + [SerializeField] private readonly Stack m_NextPosition = new(); + + [SerializeField] private BitArray m_VisitedLocations = new(7 * 7 * 7); + /// - /// The gap in cell count before stopping to consider a Tile in a Group + /// The gap in cell count before stopping to consider a Tile in a Group /// public Vector3Int gap { - get { return m_Gap; } + get => m_Gap; set { m_Gap = value; @@ -26,11 +37,11 @@ public Vector3Int gap } /// - /// The count in cells beyond the initial position before stopping to consider a Tile in a Group + /// The count in cells beyond the initial position before stopping to consider a Tile in a Group /// public Vector3Int limit { - get { return m_Limit; } + get => m_Limit; set { m_Limit = value; @@ -38,19 +49,7 @@ public Vector3Int limit } } - private int visitedLocationsSize - { - get { return (m_Limit.x * 2 + 1) * (m_Limit.y * 2 + 1) * (m_Limit.z * 2 + 1); } - } - - [SerializeField] - private Vector3Int m_Gap = Vector3Int.one; - [SerializeField] - private Vector3Int m_Limit = Vector3Int.one * 3; - [SerializeField] - private BitArray m_VisitedLocations = new BitArray(7 * 7 * 7); - [SerializeField] - private Stack m_NextPosition = new Stack(); + private int visitedLocationsSize => (m_Limit.x * 2 + 1) * (m_Limit.y * 2 + 1) * (m_Limit.z * 2 + 1); private void OnValidate() { @@ -71,8 +70,8 @@ private void OnValidate() } /// - /// Picks tiles from selected Tilemaps and child GameObjects, given the coordinates of the cells. - /// The GroupBrush overrides this to locate groups of Tiles from the picking position. + /// Picks tiles from selected Tilemaps and child GameObjects, given the coordinates of the cells. + /// The GroupBrush overrides this to locate groups of Tiles from the picking position. /// /// Grid to pick data from. /// Target of the picking operation. By default the currently selected GameObject. @@ -87,18 +86,18 @@ public override void Pick(GridLayout grid, GameObject brushTarget, BoundsInt pos return; } - Tilemap tilemap = brushTarget.GetComponent(); + var tilemap = brushTarget.GetComponent(); if (tilemap == null) return; Reset(); // Determine size of picked locations based on gap and limit - Vector3Int limitOrigin = position.position - limit; - Vector3Int limitSize = Vector3Int.one + limit * 2; - BoundsInt limitBounds = new BoundsInt(limitOrigin, limitSize); - BoundsInt pickBounds = new BoundsInt(position.position, Vector3Int.one); - + var limitOrigin = position.position - limit; + var limitSize = Vector3Int.one + limit * 2; + var limitBounds = new BoundsInt(limitOrigin, limitSize); + var pickBounds = new BoundsInt(position.position, Vector3Int.one); + m_VisitedLocations.SetAll(false); m_VisitedLocations.Set(GetIndex(position.position, limitOrigin, limitSize), true); m_NextPosition.Clear(); @@ -106,16 +105,16 @@ public override void Pick(GridLayout grid, GameObject brushTarget, BoundsInt pos while (m_NextPosition.Count > 0) { - Vector3Int next = m_NextPosition.Pop(); + var next = m_NextPosition.Pop(); if (tilemap.GetTile(next) != null) { Encapsulate(ref pickBounds, next); - BoundsInt gapBounds = new BoundsInt(next - gap, Vector3Int.one + gap * 2); + var gapBounds = new BoundsInt(next - gap, Vector3Int.one + gap * 2); foreach (var gapPosition in gapBounds.allPositionsWithin) { if (!limitBounds.Contains(gapPosition)) continue; - int index = GetIndex(gapPosition, limitOrigin, limitSize); + var index = GetIndex(gapPosition, limitOrigin, limitSize); if (!m_VisitedLocations.Get(index)) { m_NextPosition.Push(gapPosition); @@ -127,13 +126,11 @@ public override void Pick(GridLayout grid, GameObject brushTarget, BoundsInt pos UpdateSizeAndPivot(pickBounds.size, position.position - pickBounds.position); - foreach (Vector3Int pos in pickBounds.allPositionsWithin) + foreach (var pos in pickBounds.allPositionsWithin) { - Vector3Int brushPosition = new Vector3Int(pos.x - pickBounds.x, pos.y - pickBounds.y, pos.z - pickBounds.z); + var brushPosition = new Vector3Int(pos.x - pickBounds.x, pos.y - pickBounds.y, pos.z - pickBounds.z); if (m_VisitedLocations.Get(GetIndex(pos, limitOrigin, limitSize))) - { PickCell(pos, brushPosition, tilemap); - } } } @@ -148,35 +145,40 @@ private void Encapsulate(ref BoundsInt bounds, Vector3Int position) bounds.position = new Vector3Int(position.x, bounds.y, bounds.z); bounds.size = new Vector3Int(bounds.size.x + increase, bounds.size.y, bounds.size.z); } + if (position.x >= bounds.xMax) { var increase = position.x - bounds.xMax + 1; bounds.size = new Vector3Int(bounds.size.x + increase, bounds.size.y, bounds.size.z); } + if (position.y < bounds.position.y) { var increase = bounds.y - position.y; bounds.position = new Vector3Int(bounds.x, position.y, bounds.z); bounds.size = new Vector3Int(bounds.size.x, bounds.size.y + increase, bounds.size.z); } + if (position.y >= bounds.yMax) { var increase = position.y - bounds.yMax + 1; bounds.size = new Vector3Int(bounds.size.x, bounds.size.y + increase, bounds.size.z); } + if (position.z < bounds.position.z) { var increase = bounds.z - position.z; bounds.position = new Vector3Int(bounds.x, bounds.y, position.z); bounds.size = new Vector3Int(bounds.size.x, bounds.size.y, bounds.size.z + increase); } + if (position.z >= bounds.zMax) { var increase = position.z - bounds.zMax + 1; bounds.size = new Vector3Int(bounds.size.x, bounds.size.y, bounds.size.z + increase); } } - + private int GetIndex(Vector3Int position, Vector3Int origin, Vector3Int size) { return (position.z - origin.z) * size.y * size.x @@ -196,15 +198,16 @@ private void PickCell(Vector3Int position, Vector3Int brushPosition, Tilemap til } /// - /// The Brush Editor for a Group Brush. + /// The Brush Editor for a Group Brush. /// [CustomEditor(typeof(GroupBrush))] public class GroupBrushEditor : GridBrushEditor { - private static readonly string iconPath = "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/GroupBrush/GroupBrush.png"; - + private static readonly string iconPath = + "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/GroupBrush/GroupBrush.png"; + private Texture2D m_BrushIcon; - + /// Returns an icon identifying the Group Brush. public override Texture2D icon { @@ -215,6 +218,7 @@ public override Texture2D icon var gui = EditorGUIUtility.TrIconContent(iconPath); m_BrushIcon = gui.image as Texture2D; } + return m_BrushIcon; } } diff --git a/Editor/Brushes/LineBrush/LineBrush.cs b/Editor/Brushes/LineBrush/LineBrush.cs index d06692b..42d4128 100644 --- a/Editor/Brushes/LineBrush/LineBrush.cs +++ b/Editor/Brushes/LineBrush/LineBrush.cs @@ -1,49 +1,51 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using UnityEngine; using UnityEngine.Tilemaps; -using System.Linq; namespace UnityEditor.Tilemaps { /// - /// This Brush helps draw lines of Tiles onto a Tilemap. - /// Use this as an example to modify brush painting behaviour to making painting quicker with less actions. + /// This Brush helps draw lines of Tiles onto a Tilemap. + /// Use this as an example to modify brush painting behaviour to making painting quicker with less actions. /// - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/LineBrush.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/LineBrush.html")] [CustomGridBrush(true, false, false, "Line Brush")] public class LineBrush : GridBrush { /// - /// Whether the Line Brush has started drawing a line. - /// - [NonSerialized] - public bool lineStartActive; - /// - /// Ensures that there are orthogonal connections of Tiles from the start of the line to the end. + /// Ensures that there are orthogonal connections of Tiles from the start of the line to the end. /// public bool fillGaps; + /// - /// The current starting point of the line. + /// The current starting point of the line. /// public Vector3Int lineStart = Vector3Int.zero; /// - /// Indicates whether the brush is currently - /// moving something using the "Move selection with active brush" tool. + /// Whether the Line Brush has started drawing a line. + /// + [NonSerialized] public bool lineStartActive; + + /// + /// Indicates whether the brush is currently + /// moving something using the "Move selection with active brush" tool. /// public bool IsMoving { get; private set; } - + private void OnEnable() { lineStartActive = false; } /// - /// Paints tiles and GameObjects into a given position within the selected layers. - /// The LineBrush overrides this to provide line painting functionality. - /// The first paint action sets the starting point of the line. - /// The next paint action sets the ending point of the line and paints Tile from start to end. + /// Paints tiles and GameObjects into a given position within the selected layers. + /// The LineBrush overrides this to provide line painting functionality. + /// The first paint action sets the starting point of the line. + /// The next paint action sets the ending point of the line and paints Tile from start to end. /// /// Grid used for layout. /// Target of the paint operation. By default the currently selected GameObject. @@ -52,18 +54,17 @@ public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int p { if (lineStartActive) { - Vector2Int startPos = new Vector2Int(lineStart.x, lineStart.y); - Vector2Int endPos = new Vector2Int(position.x, position.y); + var startPos = new Vector2Int(lineStart.x, lineStart.y); + var endPos = new Vector2Int(position.x, position.y); if (startPos == endPos) - base.Paint(grid, brushTarget, position); + base.Paint(grid, brushTarget, position); else - { foreach (var point in GetPointsOnLine(startPos, endPos, fillGaps)) { - Vector3Int paintPos = new Vector3Int(point.x, point.y, position.z); + var paintPos = new Vector3Int(point.x, point.y, position.z); base.Paint(grid, brushTarget, paintPos); } - } + lineStartActive = false; } else if (IsMoving) @@ -78,7 +79,7 @@ public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int p } /// - /// Starts the movement of tiles and GameObjects from a given position within the selected layers. + /// Starts the movement of tiles and GameObjects from a given position within the selected layers. /// /// Grid used for layout. /// Target of the Move operation. By default the currently selected GameObject. @@ -90,7 +91,7 @@ public override void MoveStart(GridLayout grid, GameObject brushTarget, BoundsIn } /// - /// Ends the movement of tiles and GameObjects to a given position within the selected layers. + /// Ends the movement of tiles and GameObjects to a given position within the selected layers. /// /// Grid used for layout. /// Target of the Move operation. By default the currently selected GameObject. @@ -102,15 +103,19 @@ public override void MoveEnd(GridLayout grid, GameObject brushTarget, BoundsInt } /// - /// Enumerates all the points between the start and end position which are - /// linked diagonally or orthogonally. + /// Enumerates all the points between the start and end position which are + /// linked diagonally or orthogonally. /// /// Start position of the line. /// End position of the line. - /// Fills any gaps between the start and end position so that - /// all points are linked only orthogonally. - /// Returns an IEnumerable which enumerates all the points between the start and end position which are - /// linked diagonally or orthogonally. + /// + /// Fills any gaps between the start and end position so that + /// all points are linked only orthogonally. + /// + /// + /// Returns an IEnumerable which enumerates all the points between the start and end position which are + /// linked diagonally or orthogonally. + /// public static IEnumerable GetPointsOnLine(Vector2Int startPos, Vector2Int endPos, bool fillGaps) { var points = GetPointsOnLine(startPos, endPos); @@ -136,14 +141,12 @@ public static IEnumerable GetPointsOnLine(Vector2Int startPos, Vecto // down else // rise < 0 { - extraStart.y -= 1; extraEnd.y -= 1; } } else // Mathf.Abs(rise) < Mathf.Abs(run) { - // right if (run > 0) { @@ -162,27 +165,26 @@ public static IEnumerable GetPointsOnLine(Vector2Int startPos, Vecto extraPoints = extraPoints.Except(new[] { extraEnd }); points = points.Union(extraPoints); } - } return points; } /// - /// Gets an enumerable for all the cells directly between two points - /// http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html + /// Gets an enumerable for all the cells directly between two points + /// http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html /// /// A starting point of a line /// An ending point of a line /// Gets an enumerable for all the cells directly between two points public static IEnumerable GetPointsOnLine(Vector2Int p1, Vector2Int p2) { - int x0 = p1.x; - int y0 = p1.y; - int x1 = p2.x; - int y1 = p2.y; + var x0 = p1.x; + var y0 = p1.y; + var x1 = p2.x; + var y1 = p2.y; - bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); + var steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); if (steep) { int t; @@ -193,6 +195,7 @@ public static IEnumerable GetPointsOnLine(Vector2Int p1, Vector2Int x1 = y1; y1 = t; } + if (x0 > x1) { int t; @@ -203,14 +206,15 @@ public static IEnumerable GetPointsOnLine(Vector2Int p1, Vector2Int y0 = y1; y1 = t; } - int dx = x1 - x0; - int dy = Math.Abs(y1 - y0); - int error = dx / 2; - int ystep = (y0 < y1) ? 1 : -1; - int y = y0; - for (int x = x0; x <= x1; x++) + + var dx = x1 - x0; + var dy = Math.Abs(y1 - y0); + var error = dx / 2; + var ystep = y0 < y1 ? 1 : -1; + var y = y0; + for (var x = x0; x <= x1; x++) { - yield return new Vector2Int((steep ? y : x), (steep ? x : y)); + yield return new Vector2Int(steep ? y : x, steep ? x : y); error = error - dy; if (error < 0) { @@ -218,37 +222,57 @@ public static IEnumerable GetPointsOnLine(Vector2Int p1, Vector2Int error += dx; } } - yield break; } } /// - /// The Brush Editor for a Line Brush. + /// The Brush Editor for a Line Brush. /// [CustomEditor(typeof(LineBrush))] public class LineBrushEditor : GridBrushEditor { - private static readonly string iconPath = "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/LineBrush/LineBrush.png"; - - private Texture2D m_BrushIcon; - private LineBrush lineBrush { get { return target as LineBrush; } } + private static readonly string iconPath = + "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/LineBrush/LineBrush.png"; + private Tilemap lastTilemap; + private Texture2D m_BrushIcon; + private LineBrush lineBrush => target as LineBrush; + + /// Returns an icon identifying the Line Brush. + public override Texture2D icon + { + get + { + if (m_BrushIcon == null) + { + var gui = EditorGUIUtility.TrIconContent(iconPath); + m_BrushIcon = gui.image as Texture2D; + } + + return m_BrushIcon; + } + } + /// - /// Callback for painting the GUI for the GridBrush in the Scene View. - /// The CoordinateBrush Editor overrides this to draw the preview of the brush when drawing lines. + /// Callback for painting the GUI for the GridBrush in the Scene View. + /// The CoordinateBrush Editor overrides this to draw the preview of the brush when drawing lines. /// /// Grid that the brush is being used on. - /// Target of the GridBrushBase::ref::Tool operation. By default the currently selected GameObject. + /// + /// Target of the GridBrushBase::ref::Tool operation. By default the currently selected + /// GameObject. + /// /// Current selected location of the brush. /// Current GridBrushBase::ref::Tool selected. /// Whether brush is being used. - public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing) + public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, BoundsInt position, + GridBrushBase.Tool tool, bool executing) { base.OnPaintSceneGUI(grid, brushTarget, position, tool, executing); if (lineBrush.lineStartActive && brushTarget != null) { - Tilemap tilemap = brushTarget.GetComponent(); + var tilemap = brushTarget.GetComponent(); if (tilemap != null) { tilemap.ClearAllEditorPreviewTiles(); @@ -256,18 +280,16 @@ public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, Bo } // Draw preview tiles for tilemap - Vector2Int startPos = new Vector2Int(lineBrush.lineStart.x, lineBrush.lineStart.y); - Vector2Int endPos = new Vector2Int(position.x, position.y); + var startPos = new Vector2Int(lineBrush.lineStart.x, lineBrush.lineStart.y); + var endPos = new Vector2Int(position.x, position.y); if (startPos == endPos) PaintPreview(grid, brushTarget, position.min); else - { foreach (var point in LineBrush.GetPointsOnLine(startPos, endPos, lineBrush.fillGaps)) { - Vector3Int paintPos = new Vector3Int(point.x, point.y, position.z); + var paintPos = new Vector3Int(point.x, point.y, position.z); PaintPreview(grid, brushTarget, paintPos); } - } if (Event.current.type == EventType.Repaint) { @@ -290,7 +312,7 @@ public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, Bo } /// - /// Clears all line previews. + /// Clears all line previews. /// public override void ClearPreview() { @@ -301,19 +323,5 @@ public override void ClearPreview() lastTilemap = null; } } - - /// Returns an icon identifying the Line Brush. - public override Texture2D icon - { - get - { - if (m_BrushIcon == null) - { - var gui = EditorGUIUtility.TrIconContent(iconPath); - m_BrushIcon = gui.image as Texture2D; - } - return m_BrushIcon; - } - } } -} +} \ No newline at end of file diff --git a/Editor/Brushes/RandomBrush/RandomBrush.cs b/Editor/Brushes/RandomBrush/RandomBrush.cs index 1c8889f..b8f2023 100644 --- a/Editor/Brushes/RandomBrush/RandomBrush.cs +++ b/Editor/Brushes/RandomBrush/RandomBrush.cs @@ -1,126 +1,56 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; -using UnityEngine.UI; +using Object = UnityEngine.Object; +using Random = UnityEngine.Random; namespace UnityEditor.Tilemaps { /// - /// This Brush helps to place random Tiles onto a Tilemap. - /// Use this as an example to create brushes which store specific data per brush and to make brushes which randomize behaviour. + /// This Brush helps to place random Tiles onto a Tilemap. + /// Use this as an example to create brushes which store specific data per brush and to make brushes which randomize + /// behaviour. /// - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RandomBrush.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RandomBrush.html")] [CustomGridBrush(false, false, false, "Random Brush")] public class RandomBrush : GridBrush { - internal struct SizeEnumerator : IEnumerator - { - private readonly Vector3Int _min, _max, _delta; - private Vector3Int _current; - - public SizeEnumerator(Vector3Int min, Vector3Int max, Vector3Int delta) - { - _min = _current = min; - _max = max; - _delta = delta; - Reset(); - } - - public SizeEnumerator GetEnumerator() - { - return this; - } - - public bool MoveNext() - { - if (_current.z >= _max.z) - return false; - - _current.x += _delta.x; - if (_current.x >= _max.x) - { - _current.x = _min.x; - _current.y += _delta.y; - if (_current.y >= _max.y) - { - _current.y = _min.y; - _current.z += _delta.z; - if (_current.z >= _max.z) - return false; - } - } - return true; - } - - public void Reset() - { - _current = _min; - _current.x -= _delta.x; - } - - public Vector3Int Current { get { return _current; } } - - object IEnumerator.Current { get { return Current; } } - - void IDisposable.Dispose() {} - } - /// - /// A data structure for storing a set of Tiles used for randomization - /// - [Serializable] - public struct RandomTileSet - { - /// - /// A set of tiles to be painted as a set - /// - public TileBase[] randomTiles; - } - - [Serializable] - public struct RandomTileChangeDataSet - { - /// - /// A set of tiles to be painted as a set with transform and color data - /// - public TileChangeData[] randomTileChangeData; - } - - /// - /// The size of a RandomTileSet + /// The size of a RandomTileSet /// public Vector3Int randomTileSetSize = Vector3Int.one; /// - /// An array of RandomTileSets to choose from when randomizing + /// An array of RandomTileSets to choose from when randomizing /// public RandomTileSet[] randomTileSets; /// - /// An array of RandomTileSets to choose from when randomizing + /// An array of RandomTileSets to choose from when randomizing /// public RandomTileChangeDataSet[] randomTileChangeDataSets; - + /// - /// A flag to determine if picking will add new RandomTileSets + /// A flag to determine if picking will add new RandomTileSets /// public bool pickRandomTiles; /// - /// A flag to determine if picking will add to existing RandomTileSets + /// A flag to determine if picking will add to existing RandomTileSets /// public bool addToRandomTiles; - + private void OnEnable() { // Update brush from original randomTileSet - if (randomTileSets == null + if (randomTileSets == null || (randomTileChangeDataSets != null - && randomTileChangeDataSets.Length == randomTileSets.Length)) + && randomTileChangeDataSets.Length == randomTileSets.Length)) return; - + randomTileChangeDataSets = new RandomTileChangeDataSet[randomTileSets.Length]; for (var i = 0; i < randomTileSets.Length; ++i) { @@ -134,10 +64,10 @@ private void OnEnable() } } } - + /// - /// Paints RandomTileSets into a given position within the selected layers. - /// The RandomBrush overrides this to provide randomized painting functionality. + /// Paints RandomTileSets into a given position within the selected layers. + /// The RandomBrush overrides this to provide randomized painting functionality. /// /// Grid used for layout. /// Target of the paint operation. By default the currently selected GameObject. @@ -152,17 +82,16 @@ public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int p var tilemap = brushTarget.GetComponent(); if (tilemap == null) return; - + var min = position - pivot; foreach (var startLocation in new SizeEnumerator(min, min + size, randomTileSetSize)) { - var randomTileChangeDataSet = randomTileChangeDataSets[(int) (randomTileChangeDataSets.Length * UnityEngine.Random.value)]; + var randomTileChangeDataSet = + randomTileChangeDataSets[(int)(randomTileChangeDataSets.Length * Random.value)]; var randomBounds = new BoundsInt(startLocation, randomTileSetSize); var i = 0; foreach (var pos in randomBounds.allPositionsWithin) - { randomTileChangeDataSet.randomTileChangeData[i++].position = pos; - } tilemap.SetTiles(randomTileChangeDataSet.randomTileChangeData, false); } } @@ -173,8 +102,8 @@ public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int p } /// - /// Picks RandomTileSets given the coordinates of the cells. - /// The RandomBrush overrides this to provide picking functionality for RandomTileSets. + /// Picks RandomTileSets given the coordinates of the cells. + /// The RandomBrush overrides this to provide picking functionality for RandomTileSets. /// /// Grid to pick data from. /// Target of the picking operation. By default the currently selected GameObject. @@ -191,7 +120,7 @@ public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsI return; var i = 0; - var count = ((bounds.size.x + randomTileSetSize.x - 1) / randomTileSetSize.x) + var count = (bounds.size.x + randomTileSetSize.x - 1) / randomTileSetSize.x * ((bounds.size.y + randomTileSetSize.y - 1) / randomTileSetSize.y) * ((bounds.size.z + randomTileSetSize.z - 1) / randomTileSetSize.z); if (addToRandomTiles) @@ -199,13 +128,16 @@ public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsI i = randomTileSets != null ? randomTileSets.Length : 0; count += i; } + Array.Resize(ref randomTileSets, count); Array.Resize(ref randomTileChangeDataSets, count); foreach (var startLocation in new SizeEnumerator(bounds.min, bounds.max, randomTileSetSize)) { - randomTileSets[i].randomTiles = new TileBase[randomTileSetSize.x * randomTileSetSize.y * randomTileSetSize.z]; - randomTileChangeDataSets[i].randomTileChangeData = new TileChangeData[randomTileSetSize.x * randomTileSetSize.y * randomTileSetSize.z]; + randomTileSets[i].randomTiles = + new TileBase[randomTileSetSize.x * randomTileSetSize.y * randomTileSetSize.z]; + randomTileChangeDataSets[i].randomTileChangeData = + new TileChangeData[randomTileSetSize.x * randomTileSetSize.y * randomTileSetSize.z]; var randomBounds = new BoundsInt(startLocation, randomTileSetSize); var j = 0; foreach (var pos in randomBounds.allPositionsWithin) @@ -214,30 +146,129 @@ public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsI var tile = inBounds ? tilemap.GetTile(pos) : null; randomTileSets[i].randomTiles[j] = tile; randomTileChangeDataSets[i].randomTileChangeData[j].tile = tile; - randomTileChangeDataSets[i].randomTileChangeData[j].transform = inBounds ? tilemap.GetTransformMatrix(pos) : Matrix4x4.identity; - randomTileChangeDataSets[i].randomTileChangeData[j].color = inBounds ? tilemap.GetColor(pos) : Color.white; + randomTileChangeDataSets[i].randomTileChangeData[j].transform = + inBounds ? tilemap.GetTransformMatrix(pos) : Matrix4x4.identity; + randomTileChangeDataSets[i].randomTileChangeData[j].color = + inBounds ? tilemap.GetColor(pos) : Color.white; j++; } + i++; } } + + internal struct SizeEnumerator : IEnumerator + { + private readonly Vector3Int _min, _max, _delta; + private Vector3Int _current; + + public SizeEnumerator(Vector3Int min, Vector3Int max, Vector3Int delta) + { + _min = _current = min; + _max = max; + _delta = delta; + Reset(); + } + + public SizeEnumerator GetEnumerator() + { + return this; + } + + public bool MoveNext() + { + if (_current.z >= _max.z) + return false; + + _current.x += _delta.x; + if (_current.x >= _max.x) + { + _current.x = _min.x; + _current.y += _delta.y; + if (_current.y >= _max.y) + { + _current.y = _min.y; + _current.z += _delta.z; + if (_current.z >= _max.z) + return false; + } + } + + return true; + } + + public void Reset() + { + _current = _min; + _current.x -= _delta.x; + } + + public Vector3Int Current => _current; + + object IEnumerator.Current => Current; + + void IDisposable.Dispose() + { + } + } + + /// + /// A data structure for storing a set of Tiles used for randomization + /// + [Serializable] + public struct RandomTileSet + { + /// + /// A set of tiles to be painted as a set + /// + public TileBase[] randomTiles; + } + + /// + /// Container for storing Tile changes for Random Tile. + /// + [Serializable] + public struct RandomTileChangeDataSet + { + /// + /// A set of tiles to be painted as a set with transform and color data + /// + public TileChangeData[] randomTileChangeData; + } } /// - /// The Brush Editor for a Random Brush. + /// The Brush Editor for a Random Brush. /// [CustomEditor(typeof(RandomBrush))] public class RandomBrushEditor : GridBrushEditor { - private static readonly string iconPath = "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/RandomBrush/RandomBrush.png"; - - private Texture2D m_BrushIcon; - private RandomBrush randomBrush { get { return target as RandomBrush; } } + private static readonly string iconPath = + "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/RandomBrush/RandomBrush.png"; + private GameObject lastBrushTarget; + private Texture2D m_BrushIcon; + private RandomBrush randomBrush => target as RandomBrush; + + /// Returns an icon identifying the Random Brush. + public override Texture2D icon + { + get + { + if (m_BrushIcon == null) + { + var gui = EditorGUIUtility.TrIconContent(iconPath); + m_BrushIcon = gui.image as Texture2D; + } + + return m_BrushIcon; + } + } + /// - /// Paints preview data into a cell of a grid given the coordinates of the cell. - /// The RandomBrush Editor overrides this to draw the preview of the brush for RandomTileSets + /// Paints preview data into a cell of a grid given the coordinates of the cell. + /// The RandomBrush Editor overrides this to draw the preview of the brush for RandomTileSets /// /// Grid to paint data to. /// Target of the paint operation. By default the currently selected GameObject. @@ -255,19 +286,24 @@ public override void PaintPreview(GridLayout grid, GameObject brushTarget, Vecto return; var min = position - randomBrush.pivot; - foreach (var startLocation in new RandomBrush.SizeEnumerator(min, min + randomBrush.size, randomBrush.randomTileSetSize)) + foreach (var startLocation in new RandomBrush.SizeEnumerator(min, min + randomBrush.size, + randomBrush.randomTileSetSize)) { - var randomTileChangeDataSet = randomBrush.randomTileChangeDataSets[(int) (randomBrush.randomTileChangeDataSets.Length * UnityEngine.Random.value)]; + var randomTileChangeDataSet = + randomBrush.randomTileChangeDataSets[ + (int)(randomBrush.randomTileChangeDataSets.Length * Random.value)]; var randomBounds = new BoundsInt(startLocation, randomBrush.randomTileSetSize); var j = 0; - foreach (Vector3Int pos in randomBounds.allPositionsWithin) + foreach (var pos in randomBounds.allPositionsWithin) { tilemap.SetEditorPreviewTile(pos, randomTileChangeDataSet.randomTileChangeData[j].tile); - tilemap.SetEditorPreviewTransformMatrix(pos, randomTileChangeDataSet.randomTileChangeData[j].transform); + tilemap.SetEditorPreviewTransformMatrix(pos, + randomTileChangeDataSet.randomTileChangeData[j].transform); tilemap.SetEditorPreviewColor(pos, randomTileChangeDataSet.randomTileChangeData[j].color); j++; } } + lastBrushTarget = brushTarget; } else @@ -277,7 +313,7 @@ public override void PaintPreview(GridLayout grid, GameObject brushTarget, Vecto } /// - /// Clears all RandomTileSet previews. + /// Clears all RandomTileSet previews. /// public override void ClearPreview() { @@ -286,9 +322,9 @@ public override void ClearPreview() var tilemap = lastBrushTarget.GetComponent(); if (tilemap == null) return; - + tilemap.ClearAllEditorPreviewTiles(); - + lastBrushTarget = null; } else @@ -298,8 +334,8 @@ public override void ClearPreview() } /// - /// Callback for painting the inspector GUI for the RandomBrush in the Tile Palette. - /// The RandomBrush Editor overrides this to have a custom inspector for this Brush. + /// Callback for painting the inspector GUI for the RandomBrush in the Tile Palette. + /// The RandomBrush Editor overrides this to have a custom inspector for this Brush. /// public override void OnPaintInspectorGUI() { @@ -307,13 +343,14 @@ public override void OnPaintInspectorGUI() randomBrush.pickRandomTiles = EditorGUILayout.Toggle("Pick Random Tiles", randomBrush.pickRandomTiles); using (new EditorGUI.DisabledScope(!randomBrush.pickRandomTiles)) { - randomBrush.addToRandomTiles = EditorGUILayout.Toggle("Add To Random Tiles", randomBrush.addToRandomTiles); + randomBrush.addToRandomTiles = + EditorGUILayout.Toggle("Add To Random Tiles", randomBrush.addToRandomTiles); } EditorGUI.BeginChangeCheck(); - randomBrush.randomTileSetSize = EditorGUILayout.Vector3IntField("Tile Set Size", randomBrush.randomTileSetSize); + randomBrush.randomTileSetSize = + EditorGUILayout.Vector3IntField("Tile Set Size", randomBrush.randomTileSetSize); if (EditorGUI.EndChangeCheck()) - { for (var i = 0; i < randomBrush.randomTileSets.Length; ++i) { var sizeCount = randomBrush.randomTileSetSize.x * randomBrush.randomTileSetSize.y * @@ -322,13 +359,15 @@ public override void OnPaintInspectorGUI() randomBrush.randomTileChangeDataSets[i].randomTileChangeData = new TileChangeData[sizeCount]; for (var j = 0; j < sizeCount; ++j) { - randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].tile = randomBrush.randomTileSets[i].randomTiles[j]; + randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].tile = + randomBrush.randomTileSets[i].randomTiles[j]; randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].transform = Matrix4x4.identity; randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].color = Color.white; } } - } - int randomTileSetCount = EditorGUILayout.DelayedIntField("Number of Tiles", randomBrush.randomTileSets != null ? randomBrush.randomTileSets.Length : 0); + + var randomTileSetCount = EditorGUILayout.DelayedIntField("Number of Tiles", + randomBrush.randomTileSets != null ? randomBrush.randomTileSets.Length : 0); if (randomTileSetCount < 0) randomTileSetCount = 0; if (randomBrush.randomTileSets == null || randomBrush.randomTileSets.Length != randomTileSetCount) @@ -346,8 +385,10 @@ public override void OnPaintInspectorGUI() randomBrush.randomTileChangeDataSets[i].randomTileChangeData = new TileChangeData[sizeCount]; for (var j = 0; j < sizeCount; ++j) { - randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].tile = randomBrush.randomTileSets[i].randomTiles[j]; - randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].transform = Matrix4x4.identity; + randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].tile = + randomBrush.randomTileSets[i].randomTiles[j]; + randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].transform = + Matrix4x4.identity; randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].color = Color.white; } } @@ -361,36 +402,36 @@ public override void OnPaintInspectorGUI() for (var i = 0; i < randomTileSetCount; i++) { - EditorGUILayout.LabelField("Tile Set " + (i+1)); + EditorGUILayout.LabelField("Tile Set " + (i + 1)); for (var j = 0; j < randomBrush.randomTileSets[i].randomTiles.Length; ++j) { - randomBrush.randomTileSets[i].randomTiles[j] = (TileBase) EditorGUILayout.ObjectField("Tile " + (j+1), randomBrush.randomTileSets[i].randomTiles[j], typeof(TileBase), false, null); + randomBrush.randomTileSets[i].randomTiles[j] = (TileBase)EditorGUILayout.ObjectField( + "Tile " + (j + 1), randomBrush.randomTileSets[i].randomTiles[j], typeof(TileBase), false, + null); if (randomBrush.randomTileChangeDataSets != null && randomBrush.randomTileChangeDataSets.Length > i) { randomBrush.randomTileChangeDataSets[i].randomTileChangeData ??= new TileChangeData[randomBrush.randomTileSets[i].randomTiles.Length]; - randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].tile = randomBrush.randomTileSets[i].randomTiles[j]; + randomBrush.randomTileChangeDataSets[i].randomTileChangeData[j].tile = + randomBrush.randomTileSets[i].randomTiles[j]; } } } } - if (EditorGUI.EndChangeCheck()) - { - EditorUtility.SetDirty(randomBrush); - } + if (EditorGUI.EndChangeCheck()) EditorUtility.SetDirty(randomBrush); } - + /// - /// Creates a static preview of the RandomBrush with its current selection. + /// Creates a static preview of the RandomBrush with its current selection. /// /// The asset to operate on. /// An array of all Assets at assetPath. /// Width of the created texture. /// Height of the created texture. /// Generated texture or null. - public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Object[] subAssets, int width, int height) + public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) { if (brush == null) return null; @@ -398,8 +439,9 @@ public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Obje var count = randomBrush.randomTileSets.Length; if (count == 0) return null; - - var previewInstance = new GameObject("Brush Preview", typeof(Grid), typeof(Tilemap), typeof(TilemapRenderer)); + + var previewInstance = + new GameObject("Brush Preview", typeof(Grid), typeof(Tilemap), typeof(TilemapRenderer)); var previewGrid = previewInstance.GetComponent(); previewGrid.cellLayout = brush.lastPickedCellLayout; previewGrid.cellSize = brush.lastPickedCellSize; @@ -411,21 +453,19 @@ public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Obje var root = Mathf.CeilToInt(Mathf.Sqrt(count)); var i = 0; for (var y = 0; y < root; ++y) + for (var x = 0; x < root; ++x) { - for (var x = 0; x < root; ++x) - { - if (i >= count) - break; - - var bounds = new BoundsInt(x * (randomBrush.randomTileSetSize.x + 1) - , 1 - (y + 1) * (randomBrush.randomTileSetSize.y + 1), 0 - , randomBrush.randomTileSetSize.x, randomBrush.randomTileSetSize.y, 1); - previewTilemap.SetTilesBlock(bounds, randomBrush.randomTileSets[i++].randomTiles); - } + if (i >= count) + break; + + var bounds = new BoundsInt(x * (randomBrush.randomTileSetSize.x + 1) + , 1 - (y + 1) * (randomBrush.randomTileSetSize.y + 1), 0 + , randomBrush.randomTileSetSize.x, randomBrush.randomTileSetSize.y, 1); + previewTilemap.SetTilesBlock(bounds, randomBrush.randomTileSets[i++].randomTiles); } var extents = (randomBrush.randomTileSetSize + new Vector3Int(1, 1, 0)) * root - new Vector3Int(1, 1, 0); - var center = (Vector3) extents * 0.5f; + var center = (Vector3)extents * 0.5f; center.y = -center.y; center.z -= 10; @@ -446,19 +486,5 @@ public override Texture2D RenderStaticPreview(string assetPath, UnityEngine.Obje return tex; } - - /// Returns an icon identifying the Random Brush. - public override Texture2D icon - { - get - { - if (m_BrushIcon == null) - { - var gui = EditorGUIUtility.TrIconContent(iconPath); - m_BrushIcon = gui.image as Texture2D; - } - return m_BrushIcon; - } - } } } \ No newline at end of file diff --git a/Editor/Menu/CustomRuleTileMenu.cs b/Editor/Menu/CustomRuleTileMenu.cs index a57a60d..8f47146 100644 --- a/Editor/Menu/CustomRuleTileMenu.cs +++ b/Editor/Menu/CustomRuleTileMenu.cs @@ -1,15 +1,12 @@ -using System; using System.IO; using UnityEditor.Tilemaps; -using UnityEngine; namespace UnityEditor { - static class CustomRuleTileMenu + internal static class CustomRuleTileMenu { - private static string tempCustomRuleTilePath; private const string customRuleTileScript = -@"using System.Collections; + @"using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; @@ -32,13 +29,15 @@ public override bool RuleMatch(int neighbor, TileBase tile) { } }"; + private static string tempCustomRuleTilePath; + [MenuItem("Assets/Create/2D/Tiles/Custom Rule Tile Script", false, (int)ETilesMenuItemOrder.CustomRuleTile)] - static void CreateCustomRuleTile() + private static void CreateCustomRuleTile() { - if (String.IsNullOrEmpty(tempCustomRuleTilePath) || !File.Exists(tempCustomRuleTilePath)) + if (string.IsNullOrEmpty(tempCustomRuleTilePath) || !File.Exists(tempCustomRuleTilePath)) tempCustomRuleTilePath = FileUtil.GetUniqueTempPathInProject(); File.WriteAllText(tempCustomRuleTilePath, customRuleTileScript); ProjectWindowUtil.CreateScriptAssetFromTemplateFile(tempCustomRuleTilePath, "NewCustomRuleTile.cs"); } } -} +} \ No newline at end of file diff --git a/Editor/Menu/MenuItemOrder.cs b/Editor/Menu/MenuItemOrder.cs index 41dd3e4..07046ff 100644 --- a/Editor/Menu/MenuItemOrder.cs +++ b/Editor/Menu/MenuItemOrder.cs @@ -15,52 +15,57 @@ internal enum ETilesMenuItemOrder RandomTile = 200, WeightedRandomTile, PipelineTile, - TerrainTile, + TerrainTile } + internal enum EBrushMenuItemOrder { RandomBrush = 3, PrefabBrush, PrefabRandomBrush } - - static internal partial class AssetCreation + + internal static partial class AssetCreation { - - [MenuItem("Assets/Create/2D/Tiles/Animated Tile", priority = (int) ETilesMenuItemOrder.AnimatedTile)] - static void CreateAnimatedTile() + [MenuItem("Assets/Create/2D/Tiles/Animated Tile", priority = (int)ETilesMenuItemOrder.AnimatedTile)] + private static void CreateAnimatedTile() { ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), "New Animated Tile.asset"); } - - [MenuItem( "Assets/Create/2D/Tiles/Hexagonal Rule Tile", priority = (int)ETilesMenuItemOrder.HexagonalRuleTile)] - static void CreateHexagonalRuleTile() + + [MenuItem("Assets/Create/2D/Tiles/Hexagonal Rule Tile", priority = (int)ETilesMenuItemOrder.HexagonalRuleTile)] + private static void CreateHexagonalRuleTile() { - ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), "New Hexagonal Rule Tile.asset"); + ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), + "New Hexagonal Rule Tile.asset"); } [MenuItem("Assets/Create/2D/Tiles/Isometric Rule Tile", priority = (int)ETilesMenuItemOrder.IsometricRuleTile)] - static void CreateIsometricRuleTile() + private static void CreateIsometricRuleTile() { - ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), "New Isometric Rule Tile.asset"); + ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), + "New Isometric Rule Tile.asset"); } - [MenuItem("Assets/Create/2D/Tiles/Advanced Rule Override Tile", priority = (int)ETilesMenuItemOrder.AdvanceRuleOverrideTile)] - static void CreateAdvancedRuleOverrideTile() + [MenuItem("Assets/Create/2D/Tiles/Advanced Rule Override Tile", + priority = (int)ETilesMenuItemOrder.AdvanceRuleOverrideTile)] + private static void CreateAdvancedRuleOverrideTile() { - ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), "New Advanced Rule Override Tile.asset"); + ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), + "New Advanced Rule Override Tile.asset"); } [MenuItem("Assets/Create/2D/Tiles/Rule Override Tile", priority = (int)ETilesMenuItemOrder.RuleOverrideTile)] - static void CreateRuleOverrideTile() + private static void CreateRuleOverrideTile() { - ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), "New Rule Override Tile.asset"); + ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), + "New Rule Override Tile.asset"); } - + [MenuItem("Assets/Create/2D/Tiles/Rule Tile", priority = (int)ETilesMenuItemOrder.RuleTile)] - static void CreateRuleTile() + private static void CreateRuleTile() { ProjectWindowUtil.CreateAsset(ScriptableObject.CreateInstance(), "New Rule Tile.asset"); } } -} +} \ No newline at end of file diff --git a/Editor/Tiles/AnimatedTile/AnimatedTileEditor.cs b/Editor/Tiles/AnimatedTile/AnimatedTileEditor.cs index caa3e3e..e3c2e23 100644 --- a/Editor/Tiles/AnimatedTile/AnimatedTileEditor.cs +++ b/Editor/Tiles/AnimatedTile/AnimatedTileEditor.cs @@ -1,46 +1,35 @@ -using System; -using UnityEditorInternal; -using UnityEngine.Scripting.APIUpdating; +using System; using System.Collections.Generic; using System.Linq; +using UnityEditorInternal; using UnityEngine; +using UnityEngine.Scripting.APIUpdating; using UnityEngine.Tilemaps; using Object = UnityEngine.Object; namespace UnityEditor.Tilemaps { + /// + /// The Editor for an AnimatedTile. + /// [CustomEditor(typeof(AnimatedTile))] [MovedFrom(true, "UnityEngine.Tilemaps", "Unity.2D.Tilemap.Extras")] public class AnimatedTileEditor : Editor { - private static class Styles - { - public static readonly GUIContent orderAnimatedTileSpritesInfo = - EditorGUIUtility.TrTextContent("Place sprites shown based on the order of animation."); - public static readonly GUIContent emptyAnimatedTileInfo = - EditorGUIUtility.TrTextContent( - "Drag Sprite or Sprite Texture assets \n" + - " to start creating an Animated Tile."); - public static readonly GUIContent minimumSpeedLabel = EditorGUIUtility.TrTextContent("Minimum Speed", - "The minimum possible speed at which the Animation of the Tile will be played. A speed value will be randomly chosen between the minimum and maximum speed."); - public static readonly GUIContent maximumSpeedLabel = EditorGUIUtility.TrTextContent("Maximum Speed", - "The maximum possible speed at which the Animation of the Tile will be played. A speed value will be randomly chosen between the minimum and maximum speed."); - public static readonly GUIContent startTimeLabel = EditorGUIUtility.TrTextContent("Start Time", "The starting time of this Animated Tile. This allows you to start the Animation from a particular time."); - public static readonly GUIContent startFrameLabel = EditorGUIUtility.TrTextContent("Start Frame", "The starting frame of this Animated Tile. This allows you to start the Animation from a particular Sprite in the list of Animated Sprites."); - public static readonly GUIContent colliderTypeLabel = EditorGUIUtility.TrTextContent("Collider Type", "The Collider Shape generated by the Tile."); - public static readonly GUIContent flagsLabel = EditorGUIUtility.TrTextContent("Flags", "Flags for controlling the Tile Animation."); - } - private static readonly string k_UndoName = L10n.Tr("Change AnimatedTile"); - private SerializedProperty m_AnimatedSprites; - - private AnimatedTile tile { get { return (target as AnimatedTile); } } - private List dragAndDropSprites; + private SerializedProperty m_AnimatedSprites; + private ReorderableList reorderableList; + private AnimatedTile tile => target as AnimatedTile; + + private bool dragAndDropActive => + dragAndDropSprites != null + && dragAndDropSprites.Count > 0; + private void OnEnable() { reorderableList = new ReorderableList(tile.m_AnimatedSprites, typeof(Sprite), true, true, true, true); @@ -64,7 +53,7 @@ private void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused) if (tile.m_AnimatedSprites != null && index < tile.m_AnimatedSprites.Length) { var spriteName = tile.m_AnimatedSprites[index] != null ? tile.m_AnimatedSprites[index].name : "Null"; - tile.m_AnimatedSprites[index] = (Sprite) EditorGUI.ObjectField(rect + tile.m_AnimatedSprites[index] = (Sprite)EditorGUI.ObjectField(rect , $"Sprite {index + 1}: {spriteName}" , tile.m_AnimatedSprites[index] , typeof(Sprite) @@ -80,12 +69,13 @@ private float GetElementHeight(int index) private void OnAddElement(ReorderableList list) { - var count = tile.m_AnimatedSprites != null ? tile.m_AnimatedSprites.Length + 1 : 1; + var count = tile.m_AnimatedSprites != null ? tile.m_AnimatedSprites.Length + 1 : 1; ResizeAnimatedSpriteList(count); - - if (list.index == 0 || list.index < list.count) + + if (list.index == 0 || list.index < list.count) { - Array.Copy(tile.m_AnimatedSprites, list.index + 1, tile.m_AnimatedSprites, list.index + 2, list.count - list.index - 1); + Array.Copy(tile.m_AnimatedSprites, list.index + 1, tile.m_AnimatedSprites, list.index + 2, + list.count - list.index - 1); tile.m_AnimatedSprites[list.index + 1] = null; if (list.IsSelected(list.index)) list.index += 1; @@ -98,7 +88,8 @@ private void OnAddElement(ReorderableList list) private void OnRemoveElement(ReorderableList list) { - if (tile.m_AnimatedSprites != null && tile.m_AnimatedSprites.Length > 0 && list.index < tile.m_AnimatedSprites.Length) + if (tile.m_AnimatedSprites != null && tile.m_AnimatedSprites.Length > 0 && + list.index < tile.m_AnimatedSprites.Length) { var sprites = tile.m_AnimatedSprites.ToList(); sprites.RemoveAt(list.index); @@ -111,13 +102,13 @@ private void OnReorderElement(ReorderableList list) // Fix for 2020.1, which does not track changes when reordering in the list EditorUtility.SetDirty(tile); } - + private void DisplayClipboardText(GUIContent clipboardText, Rect position) { - Color old = GUI.color; + var old = GUI.color; GUI.color = Color.gray; var infoSize = GUI.skin.label.CalcSize(clipboardText); - Rect rect = new Rect(position.center.x - infoSize.x * .5f + var rect = new Rect(position.center.x - infoSize.x * .5f , position.center.y - infoSize.y * .5f , infoSize.x , infoSize.y); @@ -125,15 +116,6 @@ private void DisplayClipboardText(GUIContent clipboardText, Rect position) GUI.color = old; } - private bool dragAndDropActive - { - get - { - return dragAndDropSprites != null - && dragAndDropSprites.Count > 0; - } - } - private void DragAndDropClear() { dragAndDropSprites = null; @@ -143,40 +125,32 @@ private void DragAndDropClear() private static List GetSpritesFromTexture(Texture2D texture) { - string path = AssetDatabase.GetAssetPath(texture); - Object[] assets = AssetDatabase.LoadAllAssetsAtPath(path); - List sprites = new List(); + var path = AssetDatabase.GetAssetPath(texture); + var assets = AssetDatabase.LoadAllAssetsAtPath(path); + var sprites = new List(); - foreach (Object asset in assets) - { + foreach (var asset in assets) if (asset is Sprite) - { sprites.Add(asset as Sprite); - } - } return sprites; } private static List GetValidSingleSprites(Object[] objects) { - List result = new List(); - foreach (Object obj in objects) - { + var result = new List(); + foreach (var obj in objects) if (obj is Sprite) { result.Add(obj as Sprite); } else if (obj is Texture2D) { - Texture2D texture = obj as Texture2D; - List sprites = GetSpritesFromTexture(texture); - if (sprites.Count > 0) - { - result.AddRange(sprites); - } + var texture = obj as Texture2D; + var sprites = GetSpritesFromTexture(texture); + if (sprites.Count > 0) result.AddRange(sprites); } - } + return result; } @@ -197,7 +171,7 @@ private void HandleDragAndDrop(Rect guiRect) GUI.changed = true; } } - break; + break; case EventType.DragPerform: { if (!dragAndDropActive) @@ -211,30 +185,29 @@ private void HandleDragAndDrop(Rect guiRect) EditorUtility.SetDirty(tile); GUIUtility.ExitGUI(); } - break; + break; case EventType.Repaint: // Handled in Render() break; } if (Event.current.type == EventType.DragExited || - Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { + (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)) DragAndDropClear(); - } } /// - /// Draws an Inspector for the AnimatedTile. + /// Draws an Inspector for the AnimatedTile. /// public override void OnInspectorGUI() { serializedObject.Update(); - + Undo.RecordObject(tile, k_UndoName); - + EditorGUI.BeginChangeCheck(); - int count = EditorGUILayout.DelayedIntField("Number of Animated Sprites", tile.m_AnimatedSprites != null ? tile.m_AnimatedSprites.Length : 0); + var count = EditorGUILayout.DelayedIntField("Number of Animated Sprites", + tile.m_AnimatedSprites != null ? tile.m_AnimatedSprites.Length : 0); if (count < 0) count = 0; @@ -243,13 +216,14 @@ public override void OnInspectorGUI() if (count == 0) { - Rect rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 5); + var rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 5); HandleDragAndDrop(rect); - EditorGUI.DrawRect(rect, dragAndDropActive && rect.Contains(Event.current.mousePosition) ? Color.white : Color.black); + EditorGUI.DrawRect(rect, + dragAndDropActive && rect.Contains(Event.current.mousePosition) ? Color.white : Color.black); var innerRect = new Rect(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2); EditorGUI.DrawRect(innerRect, EditorGUIUtility.isProSkin - ? (Color) new Color32 (56, 56, 56, 255) - : (Color) new Color32 (194, 194, 194, 255)); + ? new Color32(56, 56, 56, 255) + : (Color)new Color32(194, 194, 194, 255)); DisplayClipboardText(Styles.emptyAnimatedTileInfo, rect); GUILayout.Space(rect.height); EditorGUILayout.Space(); @@ -265,8 +239,8 @@ public override void OnInspectorGUI() using (new EditorGUI.DisabledScope(tile.m_AnimatedSprites == null || tile.m_AnimatedSprites.Length == 0)) { - float minSpeed = EditorGUILayout.FloatField(Styles.minimumSpeedLabel, tile.m_MinSpeed); - float maxSpeed = EditorGUILayout.FloatField(Styles.maximumSpeedLabel, tile.m_MaxSpeed); + var minSpeed = EditorGUILayout.FloatField(Styles.minimumSpeedLabel, tile.m_MinSpeed); + var maxSpeed = EditorGUILayout.FloatField(Styles.maximumSpeedLabel, tile.m_MaxSpeed); if (minSpeed < 0.0f) minSpeed = 0.0f; @@ -279,17 +253,22 @@ public override void OnInspectorGUI() tile.m_MinSpeed = minSpeed; tile.m_MaxSpeed = maxSpeed; - using (new EditorGUI.DisabledScope(tile.m_AnimatedSprites == null - || (0 < tile.m_AnimationStartFrame - && tile.m_AnimationStartFrame <= tile.m_AnimatedSprites.Length))) + using (new EditorGUI.DisabledScope(tile.m_AnimatedSprites == null + || (0 < tile.m_AnimationStartFrame + && tile.m_AnimationStartFrame <= tile.m_AnimatedSprites.Length))) { - tile.m_AnimationStartTime = EditorGUILayout.FloatField(Styles.startTimeLabel, tile.m_AnimationStartTime); + tile.m_AnimationStartTime = + EditorGUILayout.FloatField(Styles.startTimeLabel, tile.m_AnimationStartTime); } - tile.m_AnimationStartFrame = EditorGUILayout.IntField(Styles.startFrameLabel, tile.m_AnimationStartFrame); - tile.m_TileColliderType = (Tile.ColliderType) EditorGUILayout.EnumPopup(Styles.colliderTypeLabel, tile.m_TileColliderType); -#if UNITY_2022_2_OR_NEWER - tile.m_TileAnimationFlags = (TileAnimationFlags) EditorGUILayout.EnumFlagsField(Styles.flagsLabel, tile.m_TileAnimationFlags); -#endif + + tile.m_AnimationStartFrame = + EditorGUILayout.IntField(Styles.startFrameLabel, tile.m_AnimationStartFrame); + tile.m_TileColliderType = + (Tile.ColliderType)EditorGUILayout.EnumPopup(Styles.colliderTypeLabel, tile.m_TileColliderType); +#if UNITY_2022_2_OR_NEWER + tile.m_TileAnimationFlags = + (TileAnimationFlags)EditorGUILayout.EnumFlagsField(Styles.flagsLabel, tile.m_TileAnimationFlags); +#endif } if (EditorGUI.EndChangeCheck()) @@ -298,11 +277,40 @@ public override void OnInspectorGUI() EditorUtility.SetDirty(tile); } } - + private void ResizeAnimatedSpriteList(int count) { m_AnimatedSprites.arraySize = count; serializedObject.ApplyModifiedProperties(); } + + private static class Styles + { + public static readonly GUIContent orderAnimatedTileSpritesInfo = + EditorGUIUtility.TrTextContent("Place sprites shown based on the order of animation."); + + public static readonly GUIContent emptyAnimatedTileInfo = + EditorGUIUtility.TrTextContent( + "Drag Sprite or Sprite Texture assets \n" + + " to start creating an Animated Tile."); + + public static readonly GUIContent minimumSpeedLabel = EditorGUIUtility.TrTextContent("Minimum Speed", + "The minimum possible speed at which the Animation of the Tile will be played. A speed value will be randomly chosen between the minimum and maximum speed."); + + public static readonly GUIContent maximumSpeedLabel = EditorGUIUtility.TrTextContent("Maximum Speed", + "The maximum possible speed at which the Animation of the Tile will be played. A speed value will be randomly chosen between the minimum and maximum speed."); + + public static readonly GUIContent startTimeLabel = EditorGUIUtility.TrTextContent("Start Time", + "The starting time of this Animated Tile. This allows you to start the Animation from a particular time."); + + public static readonly GUIContent startFrameLabel = EditorGUIUtility.TrTextContent("Start Frame", + "The starting frame of this Animated Tile. This allows you to start the Animation from a particular Sprite in the list of Animated Sprites."); + + public static readonly GUIContent colliderTypeLabel = + EditorGUIUtility.TrTextContent("Collider Type", "The Collider Shape generated by the Tile."); + + public static readonly GUIContent flagsLabel = + EditorGUIUtility.TrTextContent("Flags", "Flags for controlling the Tile Animation."); + } } } \ No newline at end of file diff --git a/Editor/Tiles/HexagonalRuleTile/HexagonalRuleTileEditor.cs b/Editor/Tiles/HexagonalRuleTile/HexagonalRuleTileEditor.cs index 9a5eea9..0b08bcd 100644 --- a/Editor/Tiles/HexagonalRuleTile/HexagonalRuleTileEditor.cs +++ b/Editor/Tiles/HexagonalRuleTile/HexagonalRuleTileEditor.cs @@ -4,19 +4,19 @@ namespace UnityEditor { /// - /// The Editor for a HexagonalRuleTile. + /// The Editor for a HexagonalRuleTile. /// [CustomEditor(typeof(HexagonalRuleTile), true)] [CanEditMultipleObjects] public class HexagonalRuleTileEditor : RuleTileEditor { /// - /// The HexagonalRuleTile being edited. + /// The HexagonalRuleTile being edited. /// public HexagonalRuleTile hexTile => target as HexagonalRuleTile; /// - /// Gets the index for a Rule with the HexagonalRuleTile to display an arrow. + /// Gets the index for a Rule with the HexagonalRuleTile to display an arrow. /// /// The adjacent position of the arrow. /// Returns the index for a Rule with the HexagonalRuleTile to display an arrow. @@ -32,33 +32,30 @@ public override int GetArrowIndex(Vector3Int position) { if (position.y > 0) return hexTile.m_FlatTop ? 5 : 1; - else - return hexTile.m_FlatTop ? 3 : 7; + return hexTile.m_FlatTop ? 3 : 7; } - else if (position.y == 0) + + if (position.y == 0) { if (position.x > 0) return hexTile.m_FlatTop ? 1 : 5; - else - return hexTile.m_FlatTop ? 7 : 3; - } - else - { - if (position.x < 0 && position.y > 0) - return hexTile.m_FlatTop ? 8 : 0; - else if (position.x > 0 && position.y > 0) - return hexTile.m_FlatTop ? 2 : 2; - else if (position.x < 0 && position.y < 0) - return hexTile.m_FlatTop ? 6 : 6; - else if (position.x > 0 && position.y < 0) - return hexTile.m_FlatTop ? 0 : 8; + return hexTile.m_FlatTop ? 7 : 3; } + if (position.x < 0 && position.y > 0) + return hexTile.m_FlatTop ? 8 : 0; + if (position.x > 0 && position.y > 0) + return hexTile.m_FlatTop ? 2 : 2; + if (position.x < 0 && position.y < 0) + return hexTile.m_FlatTop ? 6 : 6; + if (position.x > 0 && position.y < 0) + return hexTile.m_FlatTop ? 0 : 8; + return -1; } /// - /// Get the GUI bounds for a Rule. + /// Get the GUI bounds for a Rule. /// /// Cell bounds of the Rule. /// Rule to get GUI bounds for. @@ -66,29 +63,28 @@ public override int GetArrowIndex(Vector3Int position) public override BoundsInt GetRuleGUIBounds(BoundsInt bounds, RuleTile.TilingRule rule) { foreach (var n in rule.GetNeighbors()) - { if (n.Key.x == bounds.xMax - 1 && n.Key.y % 2 != 0) { bounds.xMax++; break; } - } + return base.GetRuleGUIBounds(bounds, rule); } /// - /// Gets the GUI matrix size for a Rule of a HexagonalRuleTile + /// Gets the GUI matrix size for a Rule of a HexagonalRuleTile /// /// Cell bounds of the Rule. /// Returns the GUI matrix size for a Rule of a HexagonalRuleTile. public override Vector2 GetMatrixSize(BoundsInt bounds) { - Vector2 size = base.GetMatrixSize(bounds); + var size = base.GetMatrixSize(bounds); return hexTile.m_FlatTop ? new Vector2(size.y, size.x) : size; } /// - /// Draws a Rule Matrix for the given Rule for a HexagonalRuleTile. + /// Draws a Rule Matrix for the given Rule for a HexagonalRuleTile. /// /// Tile to draw rule for. /// GUI Rect to draw rule at. @@ -96,18 +92,17 @@ public override Vector2 GetMatrixSize(BoundsInt bounds) /// Rule to draw Rule Matrix for. public override void RuleMatrixOnGUI(RuleTile tile, Rect rect, BoundsInt bounds, RuleTile.TilingRule tilingRule) { - bool flatTop = hexTile.m_FlatTop; + var flatTop = hexTile.m_FlatTop; Handles.color = EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.2f) : new Color(0f, 0f, 0f, 0.2f); - float w = rect.width / (flatTop ? bounds.size.y : bounds.size.x); - float h = rect.height / (flatTop ? bounds.size.x : bounds.size.y); + var w = rect.width / (flatTop ? bounds.size.y : bounds.size.x); + var h = rect.height / (flatTop ? bounds.size.x : bounds.size.y); // Grid if (flatTop) - { - for (int y = 0; y <= bounds.size.y; y++) + for (var y = 0; y <= bounds.size.y; y++) { - float left = rect.xMin + y * w; + var left = rect.xMin + y * w; float offset = 0; if (y == 0 && bounds.yMax % 2 == 0) @@ -119,20 +114,18 @@ public override void RuleMatrixOnGUI(RuleTile tile, Rect rect, BoundsInt bounds, if (y < bounds.size.y) { - bool noOffset = (y + bounds.yMax) % 2 != 0; - for (int x = 0; x < (noOffset ? (bounds.size.x + 1) : bounds.size.x); x++) + var noOffset = (y + bounds.yMax) % 2 != 0; + for (var x = 0; x < (noOffset ? bounds.size.x + 1 : bounds.size.x); x++) { - float top = rect.yMin + x * h + (noOffset ? 0 : h / 2); + var top = rect.yMin + x * h + (noOffset ? 0 : h / 2); Handles.DrawLine(new Vector3(left, top), new Vector3(left + w, top)); } } } - } else - { - for (int y = 0; y <= bounds.size.y; y++) + for (var y = 0; y <= bounds.size.y; y++) { - float top = rect.yMin + y * h; + var top = rect.yMin + y * h; float offset = 0; if (y == 0 && bounds.yMax % 2 == 0) @@ -144,28 +137,28 @@ public override void RuleMatrixOnGUI(RuleTile tile, Rect rect, BoundsInt bounds, if (y < bounds.size.y) { - bool noOffset = (y + bounds.yMax) % 2 != 0; - for (int x = 0; x < (noOffset ? (bounds.size.x + 1) : bounds.size.x); x++) + var noOffset = (y + bounds.yMax) % 2 != 0; + for (var x = 0; x < (noOffset ? bounds.size.x + 1 : bounds.size.x); x++) { - float left = rect.xMin + x * w + (noOffset ? 0 : w / 2); + var left = rect.xMin + x * w + (noOffset ? 0 : w / 2); Handles.DrawLine(new Vector3(left, top), new Vector3(left, top + h)); } } } - } var neighbors = tilingRule.GetNeighbors(); // Icons Handles.color = Color.white; - for (int y = bounds.yMin; y < bounds.yMax; y++) + for (var y = bounds.yMin; y < bounds.yMax; y++) { - int xMax = y % 2 == 0 ? bounds.xMax : (bounds.xMax - 1); - for (int x = bounds.xMin; x < xMax; x++) + var xMax = y % 2 == 0 ? bounds.xMax : bounds.xMax - 1; + for (var x = bounds.xMin; x < xMax; x++) { - Vector3Int pos = new Vector3Int(x, y, 0); - Vector2 offset = new Vector2(x - bounds.xMin, -y + bounds.yMax - 1); - Rect r = flatTop ? new Rect(rect.xMax - offset.y * w - w, rect.yMax - offset.x * h - h, w - 1, h - 1) + var pos = new Vector3Int(x, y, 0); + var offset = new Vector2(x - bounds.xMin, -y + bounds.yMax - 1); + var r = flatTop + ? new Rect(rect.xMax - offset.y * w - w, rect.yMax - offset.x * h - h, w - 1, h - 1) : new Rect(rect.xMin + offset.x * w, rect.yMin + offset.y * h, w - 1, h - 1); if (y % 2 != 0) @@ -182,7 +175,7 @@ public override void RuleMatrixOnGUI(RuleTile tile, Rect rect, BoundsInt bounds, } /// - /// Creates a Preview for the HexagonalRuleTile. + /// Creates a Preview for the HexagonalRuleTile. /// protected override void CreatePreview() { @@ -198,15 +191,15 @@ protected override void CreatePreview() tilemap.ClearAllTiles(); } - for (int x = -1; x <= 0; ++x) - for (int y = -1; y <= 1; ++y) - m_PreviewTilemaps[0].SetTile(new Vector3Int(x, y, 0), tile); + for (var x = -1; x <= 0; ++x) + for (var y = -1; y <= 1; ++y) + m_PreviewTilemaps[0].SetTile(new Vector3Int(x, y, 0), tile); m_PreviewTilemaps[1].SetTile(new Vector3Int(1, -1, 0), tile); m_PreviewTilemaps[1].SetTile(new Vector3Int(2, 0, 0), tile); m_PreviewTilemaps[1].SetTile(new Vector3Int(2, 1, 0), tile); - for (int x = -1; x <= 1; x++) + for (var x = -1; x <= 1; x++) m_PreviewTilemaps[2].SetTile(new Vector3Int(x, -2, 0), tile); m_PreviewTilemaps[3].SetTile(new Vector3Int(1, 1, 0), tile); @@ -220,4 +213,4 @@ protected override void CreatePreview() m_PreviewTilemapRenderers[3].sortingOrder = 0; } } -} +} \ No newline at end of file diff --git a/Editor/Tiles/IsometricRuleTile/IsometricRuleTileEditor.cs b/Editor/Tiles/IsometricRuleTile/IsometricRuleTileEditor.cs index ad6cf10..75b3507 100644 --- a/Editor/Tiles/IsometricRuleTile/IsometricRuleTileEditor.cs +++ b/Editor/Tiles/IsometricRuleTile/IsometricRuleTileEditor.cs @@ -1,24 +1,24 @@ -using UnityEngine; +using UnityEngine; using UnityEngine.Tilemaps; namespace UnityEditor { /// - /// The Editor for an IsometricRuleTile. + /// The Editor for an IsometricRuleTile. /// [CustomEditor(typeof(IsometricRuleTile), true)] [CanEditMultipleObjects] public class IsometricRuleTileEditor : RuleTileEditor { /// - /// Gets the index for a Rule with the IsometricRuleTileEditor to display an arrow. + /// Gets the index for a Rule with the IsometricRuleTileEditor to display an arrow. /// /// The adjacent position of the arrow. /// Returns the index for a Rule with the IsometricRuleTileEditor to display an arrow private static readonly int[] s_Arrows = { 3, 0, 1, 6, -1, 2, 7, 8, 5 }; /// - /// Gets the index for a Rule with the HexagonalRuleTile to display an arrow. + /// Gets the index for a Rule with the HexagonalRuleTile to display an arrow. /// /// The adjacent position of the arrow. /// Returns the index for a Rule with the HexagonalRuleTile to display an arrow. @@ -28,19 +28,19 @@ public override int GetArrowIndex(Vector3Int position) } /// - /// Gets the GUI matrix size for a Rule of a IsometricRuleTile + /// Gets the GUI matrix size for a Rule of a IsometricRuleTile /// /// Cell bounds of the Rule. /// Returns the GUI matrix size for a Rule of a IsometricRuleTile. public override Vector2 GetMatrixSize(BoundsInt bounds) { - float p = Mathf.Pow(2, 0.5f); - float w = (bounds.size.x / p + bounds.size.y / p) * k_SingleLineHeight; + var p = Mathf.Pow(2, 0.5f); + var w = (bounds.size.x / p + bounds.size.y / p) * k_SingleLineHeight; return new Vector2(w, w); } /// - /// Draws a Rule Matrix for the given Rule for a IsometricRuleTile. + /// Draws a Rule Matrix for the given Rule for a IsometricRuleTile. /// /// Tile to draw rule for. /// GUI Rect to draw rule at. @@ -49,57 +49,57 @@ public override Vector2 GetMatrixSize(BoundsInt bounds) public override void RuleMatrixOnGUI(RuleTile tile, Rect rect, BoundsInt bounds, RuleTile.TilingRule tilingRule) { Handles.color = EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.2f) : new Color(0f, 0f, 0f, 0.2f); - float w = rect.width / bounds.size.x; - float h = rect.height / bounds.size.y; + var w = rect.width / bounds.size.x; + var h = rect.height / bounds.size.y; // Grid - float d = rect.width / (bounds.size.x + bounds.size.y); - for (int y = 0; y <= bounds.size.y; y++) + var d = rect.width / (bounds.size.x + bounds.size.y); + for (var y = 0; y <= bounds.size.y; y++) { - float left = rect.xMin + d * y; - float top = rect.yMin + d * y; - float right = rect.xMax - d * (bounds.size.y - y); - float bottom = rect.yMax - d * (bounds.size.y - y); + var left = rect.xMin + d * y; + var top = rect.yMin + d * y; + var right = rect.xMax - d * (bounds.size.y - y); + var bottom = rect.yMax - d * (bounds.size.y - y); Handles.DrawLine(new Vector3(left, bottom), new Vector3(right, top)); } - for (int x = 0; x <= bounds.size.x; x++) + + for (var x = 0; x <= bounds.size.x; x++) { - float left = rect.xMin + d * x; - float top = rect.yMax - d * x; - float right = rect.xMax - d * (bounds.size.x - x); - float bottom = rect.yMin + d * (bounds.size.x - x); + var left = rect.xMin + d * x; + var top = rect.yMax - d * x; + var right = rect.xMax - d * (bounds.size.x - x); + var bottom = rect.yMin + d * (bounds.size.x - x); Handles.DrawLine(new Vector3(left, bottom), new Vector3(right, top)); } + Handles.color = Color.white; var neighbors = tilingRule.GetNeighbors(); // Icons - float iconSize = (rect.width - d) / (bounds.size.x + bounds.size.y - 1); - float iconScale = Mathf.Pow(2, 0.5f); + var iconSize = (rect.width - d) / (bounds.size.x + bounds.size.y - 1); + var iconScale = Mathf.Pow(2, 0.5f); - for (int y = bounds.yMin; y < bounds.yMax; y++) + for (var y = bounds.yMin; y < bounds.yMax; y++) + for (var x = bounds.xMin; x < bounds.xMax; x++) { - for (int x = bounds.xMin; x < bounds.xMax; x++) - { - Vector3Int pos = new Vector3Int(x, y, 0); - Vector3Int offset = new Vector3Int(pos.x - bounds.xMin, pos.y - bounds.yMin, 0); - Rect r = new Rect( - rect.xMin + rect.size.x - iconSize * (offset.y - offset.x + 0.5f + bounds.size.x), - rect.yMin + rect.size.y - iconSize * (offset.y + offset.x + 1.5f), - iconSize, iconSize - ); - Vector2 center = r.center; - r.size *= iconScale; - r.center = center; - - RuleMatrixIconOnGUI(tilingRule, neighbors, pos, r); - } + var pos = new Vector3Int(x, y, 0); + var offset = new Vector3Int(pos.x - bounds.xMin, pos.y - bounds.yMin, 0); + var r = new Rect( + rect.xMin + rect.size.x - iconSize * (offset.y - offset.x + 0.5f + bounds.size.x), + rect.yMin + rect.size.y - iconSize * (offset.y + offset.x + 1.5f), + iconSize, iconSize + ); + var center = r.center; + r.size *= iconScale; + r.center = center; + + RuleMatrixIconOnGUI(tilingRule, neighbors, pos, r); } } /// - /// Determines the current mouse position is within the given Rect. + /// Determines the current mouse position is within the given Rect. /// /// Rect to test mouse position for. /// True if the current mouse position is within the given Rect. False otherwise. @@ -111,11 +111,11 @@ public override bool ContainsMousePosition(Rect rect) var mouseFromCenter = Event.current.mousePosition - center; var xAbs = Mathf.Abs(Vector2.Dot(mouseFromCenter, Vector2.right)); var yAbs = Mathf.Abs(Vector2.Dot(mouseFromCenter, Vector2.up)); - return (xAbs / halfWidth + yAbs / halfHeight) <= 1; + return xAbs / halfWidth + yAbs / halfHeight <= 1; } /// - /// Updates preview settings for the IsometricRuleTile. + /// Updates preview settings for the IsometricRuleTile. /// public override void OnPreviewSettings() { @@ -123,13 +123,13 @@ public override void OnPreviewSettings() if (m_PreviewGrid) { - float height = EditorGUILayout.FloatField("Cell Height", m_PreviewGrid.cellSize.y); + var height = EditorGUILayout.FloatField("Cell Height", m_PreviewGrid.cellSize.y); m_PreviewGrid.cellSize = new Vector3(1f, Mathf.Max(height, 0), 1f); } } /// - /// Creates a Preview for the IsometricRuleTile. + /// Creates a Preview for the IsometricRuleTile. /// protected override void CreatePreview() { @@ -147,4 +147,4 @@ protected override void CreatePreview() m_PreviewTilemapRenderers[3].sortingOrder = 0; } } -} +} \ No newline at end of file diff --git a/Editor/Tiles/RuleOverrideTile/AdvancedRuleOverrideTileEditor.cs b/Editor/Tiles/RuleOverrideTile/AdvancedRuleOverrideTileEditor.cs index bf26fc5..a362ad2 100644 --- a/Editor/Tiles/RuleOverrideTile/AdvancedRuleOverrideTileEditor.cs +++ b/Editor/Tiles/RuleOverrideTile/AdvancedRuleOverrideTileEditor.cs @@ -1,47 +1,39 @@ -using UnityEngine; -using UnityEngine.Tilemaps; -using UnityEditorInternal; using System.Collections.Generic; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Tilemaps; namespace UnityEditor { /// - /// The Editor for an AdvancedRuleOverrideTileEditor. + /// The Editor for an AdvancedRuleOverrideTileEditor. /// [CustomEditor(typeof(AdvancedRuleOverrideTile))] public class AdvancedRuleOverrideTileEditor : RuleOverrideTileEditor { - private static class Styles - { - public static readonly GUIContent defaultSprite = EditorGUIUtility.TrTextContent("Default Sprite" - , "Overrides the default Sprite for the original Rule Tile."); - public static readonly GUIContent defaultGameObject = EditorGUIUtility.TrTextContent("Default GameObject" - , "Overrides the default GameObject for the original Rule Tile."); - public static readonly GUIContent defaultCollider = EditorGUIUtility.TrTextContent("Default Collider" - , "Overrides the default Collider for the original Rule Tile."); - } + private int m_MissingOriginalRuleIndex; + private ReorderableList m_RuleList; + + private readonly List> m_Rules = new(); + private readonly HashSet m_UniqueIds = new(); /// - /// The AdvancedRuleOverrideTile being edited. + /// The AdvancedRuleOverrideTile being edited. /// public new AdvancedRuleOverrideTile overrideTile => target as AdvancedRuleOverrideTile; - List> m_Rules = new List>(); - private ReorderableList m_RuleList; - private int m_MissingOriginalRuleIndex; - private HashSet m_UniqueIds = new HashSet(); - - static float k_DefaultElementHeight { get { return RuleTileEditor.k_DefaultElementHeight; } } - static float k_SingleLineHeight { get { return RuleTileEditor.k_SingleLineHeight; } } + private static float k_DefaultElementHeight => RuleTileEditor.k_DefaultElementHeight; + private static float k_SingleLineHeight => RuleTileEditor.k_SingleLineHeight; /// - /// OnEnable for the AdvancedRuleOverrideTileEditor + /// OnEnable for the AdvancedRuleOverrideTileEditor /// public override void OnEnable() { if (m_RuleList == null) { - m_RuleList = new ReorderableList(m_Rules, typeof(KeyValuePair), false, true, false, false); + m_RuleList = new ReorderableList(m_Rules, + typeof(KeyValuePair), false, true, false, false); m_RuleList.drawHeaderCallback = DrawRulesHeader; m_RuleList.drawElementCallback = DrawRuleElement; m_RuleList.elementHeightCallback = GetRuleElementHeight; @@ -49,7 +41,7 @@ public override void OnEnable() } /// - /// Draws the Inspector GUI for the AdvancedRuleOverrideTileEditor + /// Draws the Inspector GUI for the AdvancedRuleOverrideTileEditor /// public override void OnInspectorGUI() { @@ -58,9 +50,14 @@ public override void OnInspectorGUI() DrawTileField(); EditorGUI.BeginChangeCheck(); - overrideTile.m_DefaultSprite = EditorGUILayout.ObjectField(Styles.defaultSprite, overrideTile.m_DefaultSprite, typeof(Sprite), false) as Sprite; - overrideTile.m_DefaultGameObject = EditorGUILayout.ObjectField(Styles.defaultGameObject, overrideTile.m_DefaultGameObject, typeof(GameObject), false) as GameObject; - overrideTile.m_DefaultColliderType = (Tile.ColliderType)EditorGUILayout.EnumPopup(Styles.defaultCollider, overrideTile.m_DefaultColliderType); + overrideTile.m_DefaultSprite = + EditorGUILayout.ObjectField(Styles.defaultSprite, overrideTile.m_DefaultSprite, typeof(Sprite), + false) as Sprite; + overrideTile.m_DefaultGameObject = EditorGUILayout.ObjectField(Styles.defaultGameObject, + overrideTile.m_DefaultGameObject, typeof(GameObject), false) as GameObject; + overrideTile.m_DefaultColliderType = + (Tile.ColliderType)EditorGUILayout.EnumPopup(Styles.defaultCollider, + overrideTile.m_DefaultColliderType); if (EditorGUI.EndChangeCheck()) SaveTile(); @@ -88,15 +85,17 @@ private void ValidateRuleTile(RuleTile ruleTile) { rule.m_Id = startId++; } while (m_UniqueIds.Contains(rule.m_Id)); + EditorUtility.SetDirty(ruleTile); } + m_UniqueIds.Add(rule.m_Id); startId++; } } - + /// - /// Draws the Header for the Rule list + /// Draws the Header for the Rule list /// /// Rect to draw the header in public void DrawRulesHeader(Rect rect) @@ -105,7 +104,7 @@ public void DrawRulesHeader(Rect rect) } /// - /// Draws the Rule element for the Rule list + /// Draws the Rule element for the Rule list /// /// Rect to draw the Rule Element in /// Index of the Rule Element to draw @@ -113,12 +112,12 @@ public void DrawRulesHeader(Rect rect) /// Whether the Rule Element is focused public void DrawRuleElement(Rect rect, int index, bool active, bool focused) { - RuleTile.TilingRule originalRule = m_Rules[index].Key; + var originalRule = m_Rules[index].Key; if (originalRule == null) return; - - RuleTile.TilingRuleOutput overrideRule = m_Rules[index].Value; - bool isMissing = index >= m_MissingOriginalRuleIndex; + + var overrideRule = m_Rules[index].Value; + var isMissing = index >= m_MissingOriginalRuleIndex; DrawToggleInternal(new Rect(rect.xMin, rect.yMin, 16, rect.height)); DrawRuleInternal(new Rect(rect.xMin + 16, rect.yMin, rect.width - 16, rect.height)); @@ -127,7 +126,8 @@ void DrawToggleInternal(Rect r) { EditorGUI.BeginChangeCheck(); - bool enabled = EditorGUI.Toggle(new Rect(r.xMin, r.yMin, r.width, k_SingleLineHeight), overrideRule != null); + var enabled = EditorGUI.Toggle(new Rect(r.xMin, r.yMin, r.width, k_SingleLineHeight), + overrideRule != null); if (EditorGUI.EndChangeCheck()) { @@ -139,6 +139,7 @@ void DrawToggleInternal(Rect r) SaveTile(); } } + void DrawRuleInternal(Rect r) { EditorGUI.BeginChangeCheck(); @@ -151,51 +152,57 @@ void DrawRuleInternal(Rect r) } /// - /// Draw a Rule Override for the AdvancedRuleOverrideTileEditor + /// Draw a Rule Override for the AdvancedRuleOverrideTileEditor /// /// Rect to draw the Rule in /// The Rule Override to draw /// Whether the original Rule is being overridden /// Original Rule to override /// Whether the original Rule is missing - public void DrawRule(Rect rect, RuleTile.TilingRuleOutput rule, bool isOverride, RuleTile.TilingRule originalRule, bool isMissing) + public void DrawRule(Rect rect, RuleTile.TilingRuleOutput rule, bool isOverride, + RuleTile.TilingRule originalRule, bool isMissing) { if (isMissing) { - EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original Tiling Rule missing", MessageType.Warning); + EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original Tiling Rule missing", + MessageType.Warning); rect.yMin += 16; } using (new EditorGUI.DisabledScope(!isOverride)) { - float yPos = rect.yMin + 2f; - float height = rect.height - k_PaddingBetweenRules; - float matrixWidth = k_DefaultElementHeight; - - BoundsInt ruleBounds = originalRule.GetBounds(); - BoundsInt ruleGuiBounds = ruleTileEditor.GetRuleGUIBounds(ruleBounds, originalRule); - Vector2 matrixSize = ruleTileEditor.GetMatrixSize(ruleGuiBounds); - Vector2 matrixSizeRate = matrixSize / Mathf.Max(matrixSize.x, matrixSize.y); - Vector2 matrixRectSize = new Vector2(matrixWidth * matrixSizeRate.x, k_DefaultElementHeight * matrixSizeRate.y); - Vector2 matrixRectPosition = new Vector2(rect.xMax - matrixWidth * 2f - 10f, yPos); + var yPos = rect.yMin + 2f; + var height = rect.height - k_PaddingBetweenRules; + var matrixWidth = k_DefaultElementHeight; + + var ruleBounds = originalRule.GetBounds(); + var ruleGuiBounds = ruleTileEditor.GetRuleGUIBounds(ruleBounds, originalRule); + var matrixSize = ruleTileEditor.GetMatrixSize(ruleGuiBounds); + var matrixSizeRate = matrixSize / Mathf.Max(matrixSize.x, matrixSize.y); + var matrixRectSize = new Vector2(matrixWidth * matrixSizeRate.x, + k_DefaultElementHeight * matrixSizeRate.y); + var matrixRectPosition = new Vector2(rect.xMax - matrixWidth * 2f - 10f, yPos); matrixRectPosition.x += (matrixWidth - matrixRectSize.x) * 0.5f; matrixRectPosition.y += (k_DefaultElementHeight - matrixRectSize.y) * 0.5f; - Rect inspectorRect = new Rect(rect.xMin, yPos, rect.width - matrixWidth * 2f - 20f, height); - Rect matrixRect = new Rect(matrixRectPosition, matrixRectSize); - Rect spriteRect = new Rect(rect.xMax - matrixWidth - 5f, yPos, matrixWidth, k_DefaultElementHeight); + var inspectorRect = new Rect(rect.xMin, yPos, rect.width - matrixWidth * 2f - 20f, height); + var matrixRect = new Rect(matrixRectPosition, matrixRectSize); + var spriteRect = new Rect(rect.xMax - matrixWidth - 5f, yPos, matrixWidth, k_DefaultElementHeight); ruleTileEditor.RuleInspectorOnGUI(inspectorRect, rule); ruleTileEditor.SpriteOnGUI(spriteRect, rule); if (!isMissing) using (new EditorGUI.DisabledScope(true)) - ruleTileEditor.RuleMatrixOnGUI(overrideTile.m_InstanceTile, matrixRect, ruleGuiBounds, originalRule); + { + ruleTileEditor.RuleMatrixOnGUI(overrideTile.m_InstanceTile, matrixRect, ruleGuiBounds, + originalRule); + } } } /// - /// Returns the height for an indexed Rule Element + /// Returns the height for an indexed Rule Element /// /// Index of the Rule Element /// Height of the indexed Rule Element @@ -203,13 +210,27 @@ public float GetRuleElementHeight(int index) { var originalRule = m_Rules[index].Key; var overrideRule = m_Rules[index].Value; - float height = overrideRule != null ? ruleTileEditor.GetElementHeight(overrideRule) : ruleTileEditor.GetElementHeight(originalRule); + var height = overrideRule != null + ? ruleTileEditor.GetElementHeight(overrideRule) + : ruleTileEditor.GetElementHeight(originalRule); - bool isMissing = index >= m_MissingOriginalRuleIndex; + var isMissing = index >= m_MissingOriginalRuleIndex; if (isMissing) height += 16; return height; } + + private static class Styles + { + public static readonly GUIContent defaultSprite = EditorGUIUtility.TrTextContent("Default Sprite" + , "Overrides the default Sprite for the original Rule Tile."); + + public static readonly GUIContent defaultGameObject = EditorGUIUtility.TrTextContent("Default GameObject" + , "Overrides the default GameObject for the original Rule Tile."); + + public static readonly GUIContent defaultCollider = EditorGUIUtility.TrTextContent("Default Collider" + , "Overrides the default Collider for the original Rule Tile."); + } } -} +} \ No newline at end of file diff --git a/Editor/Tiles/RuleOverrideTile/PopulateRuleOverrideTileWizard.cs b/Editor/Tiles/RuleOverrideTile/PopulateRuleOverrideTileWizard.cs index 1b62c5e..e11c6be 100644 --- a/Editor/Tiles/RuleOverrideTile/PopulateRuleOverrideTileWizard.cs +++ b/Editor/Tiles/RuleOverrideTile/PopulateRuleOverrideTileWizard.cs @@ -1,109 +1,118 @@ -using UnityEngine; -using UnityEngine.Tilemaps; +using System; using System.Linq; using System.Text.RegularExpressions; +using UnityEngine; using UnityEngine.Scripting.APIUpdating; +using UnityEngine.Tilemaps; namespace UnityEditor.Tilemaps { /// - /// Wizard for populating RuleOverrideTile from a SpriteSheet + /// Wizard for populating RuleOverrideTile from a SpriteSheet /// [MovedFrom(true, "UnityEditor")] - public class PopulateRuleOverideTileWizard : ScriptableWizard + public class PopulateRuleOverideTileWizard : ScriptableWizard { + /// + /// The Texture2D containing the Sprites to override with + /// + public Texture2D m_spriteSet; + + private RuleOverrideTile m_tileset; + + private void OnWizardCreate() + { + try + { + Populate(); + } + catch (Exception ex) + { + EditorUtility.DisplayDialog("Auto-populate failed!", ex.Message, "Ok"); + CloneWizard(this); + } + } + + private void OnWizardUpdate() + { + isValid = m_tileset != null && m_spriteSet != null; + } + [MenuItem("CONTEXT/RuleOverrideTile/Populate From Sprite Sheet")] - static void MenuOption(MenuCommand menuCommand) + private static void MenuOption(MenuCommand menuCommand) { - PopulateRuleOverideTileWizard.CreateWizard(menuCommand.context as RuleOverrideTile); + CreateWizard(menuCommand.context as RuleOverrideTile); } + [MenuItem("CONTEXT/RuleOverrideTile/Populate From Sprite Sheet", true)] - static bool MenuOptionValidation(MenuCommand menuCommand) + private static bool MenuOptionValidation(MenuCommand menuCommand) { - RuleOverrideTile tile = menuCommand.context as RuleOverrideTile; + var tile = menuCommand.context as RuleOverrideTile; return tile.m_Tile; } /// - /// The Texture2D containing the Sprites to override with - /// - public Texture2D m_spriteSet; - - private RuleOverrideTile m_tileset; - - /// - /// Creates a wizard for the target RuleOverrideTIle + /// Creates a wizard for the target RuleOverrideTIle /// /// The RuleOverrideTile to be edited by the wizard - public static void CreateWizard(RuleOverrideTile target) { - PopulateRuleOverideTileWizard wizard = DisplayWizard("Populate Override", "Populate"); + public static void CreateWizard(RuleOverrideTile target) + { + var wizard = DisplayWizard("Populate Override", "Populate"); wizard.m_tileset = target; } /// - /// Creates a new PopulateRuleOverideTileWizard and copies the settings from an existing PopulateRuleOverideTileWizard + /// Creates a new PopulateRuleOverideTileWizard and copies the settings from an existing PopulateRuleOverideTileWizard /// /// The wizard to copy settings from - public static void CloneWizard(PopulateRuleOverideTileWizard oldWizard) { - PopulateRuleOverideTileWizard wizard = DisplayWizard("Populate Override", "Populate"); + public static void CloneWizard(PopulateRuleOverideTileWizard oldWizard) + { + var wizard = DisplayWizard("Populate Override", "Populate"); wizard.m_tileset = oldWizard.m_tileset; wizard.m_spriteSet = oldWizard.m_spriteSet; } - private void OnWizardUpdate() { - isValid = m_tileset != null && m_spriteSet != null; - } - - private void OnWizardCreate() { - try { - Populate(); - } - catch(System.Exception ex) { - EditorUtility.DisplayDialog("Auto-populate failed!", ex.Message, "Ok"); - CloneWizard(this); - } - } - /// - /// Attempts to populate the selected override tile using the chosen sprite. - /// The assumption here is that the sprite set selected by the user has the same - /// naming scheme as the original sprite. That is to say, they should both have the same number - /// of sprites, each sprite ends in an underscore followed by a number, and that they are - /// intended to be equivalent in function. + /// Attempts to populate the selected override tile using the chosen sprite. + /// The assumption here is that the sprite set selected by the user has the same + /// naming scheme as the original sprite. That is to say, they should both have the same number + /// of sprites, each sprite ends in an underscore followed by a number, and that they are + /// intended to be equivalent in function. /// - private void Populate() { - string spriteSheet = AssetDatabase.GetAssetPath(m_spriteSet); - Sprite[] overrideSprites = AssetDatabase.LoadAllAssetsAtPath(spriteSheet).OfType().ToArray(); + private void Populate() + { + var spriteSheet = AssetDatabase.GetAssetPath(m_spriteSet); + var overrideSprites = AssetDatabase.LoadAllAssetsAtPath(spriteSheet).OfType().ToArray(); - bool finished = false; + var finished = false; - try { + try + { Undo.RecordObject(m_tileset, "Auto-populate " + m_tileset.name); - foreach(RuleTile.TilingRule rule in m_tileset.m_Tile.m_TilingRules) { - foreach(Sprite originalSprite in rule.m_Sprites) { - string spriteName = originalSprite.name; - string spriteNumber = Regex.Match(spriteName, @"_\d+$").Value; + foreach (var rule in m_tileset.m_Tile.m_TilingRules) + foreach (var originalSprite in rule.m_Sprites) + { + var spriteName = originalSprite.name; + var spriteNumber = Regex.Match(spriteName, @"_\d+$").Value; - Sprite matchingOverrideSprite = overrideSprites.First(sprite => sprite.name.EndsWith(spriteNumber)); + var matchingOverrideSprite = overrideSprites.First(sprite => sprite.name.EndsWith(spriteNumber)); - m_tileset[originalSprite] = matchingOverrideSprite; - } + m_tileset[originalSprite] = matchingOverrideSprite; } finished = true; } - catch(System.InvalidOperationException ex) { - throw (new System.ArgumentOutOfRangeException("Sprite sheet mismatch", ex)); + catch (InvalidOperationException ex) + { + throw new ArgumentOutOfRangeException("Sprite sheet mismatch", ex); } - finally { + finally + { // We handle the undo like this in case we end up catching more exceptions. // We want this to ALWAYS happen unless we complete the population. - if(!finished) { - Undo.PerformUndo(); - } + if (!finished) Undo.PerformUndo(); } } - } -} +} \ No newline at end of file diff --git a/Editor/Tiles/RuleOverrideTile/RuleOverrideTileEditor.cs b/Editor/Tiles/RuleOverrideTile/RuleOverrideTileEditor.cs index 08a0ac2..9f7c324 100644 --- a/Editor/Tiles/RuleOverrideTile/RuleOverrideTileEditor.cs +++ b/Editor/Tiles/RuleOverrideTile/RuleOverrideTileEditor.cs @@ -1,28 +1,57 @@ -using UnityEngine; -using UnityEngine.Tilemaps; -using UnityEditorInternal; using System.Collections.Generic; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Tilemaps; namespace UnityEditor { /// - /// The Editor for a RuleOverrideTileEditor. + /// The Editor for a RuleOverrideTileEditor. /// [CustomEditor(typeof(RuleOverrideTile))] public class RuleOverrideTileEditor : Editor { - private static class Styles - { - public static readonly GUIContent overrideTile = EditorGUIUtility.TrTextContent("Tile" - , "The Rule Tile to override."); - } + /// + /// Height for a Sprite Element + /// + public static float k_SpriteElementHeight = 48; + + /// + /// Height for a GameObject Element + /// + public static float k_GameObjectElementHeight = 16; + + /// + /// Padding between Rule Elements + /// + public static float k_PaddingBetweenRules = 4; + + private ReorderableList m_GameObjectList; /// - /// The RuleOverrideTile being edited + /// List of GameObjects and overriding GameObjects + /// + public List> m_GameObjects = new(); + + private int m_MissingOriginalGameObjectIndex; + private int m_MissingOriginalSpriteIndex; + + private RuleTileEditor m_RuleTileEditor; + private RuleTile m_RuleTileEditorTarget; + private ReorderableList m_SpriteList; + + /// + /// List of Sprites and overriding Sprites + /// + public List> m_Sprites = new(); + + /// + /// The RuleOverrideTile being edited /// public RuleOverrideTile overrideTile => target as RuleOverrideTile; + /// - /// The RuleTileEditor for the overridden instance of the RuleTile + /// The RuleTileEditor for the overridden instance of the RuleTile /// public RuleTileEditor ruleTileEditor { @@ -31,57 +60,32 @@ public RuleTileEditor ruleTileEditor if (m_RuleTileEditorTarget != overrideTile.m_Tile) { DestroyImmediate(m_RuleTileEditor); - m_RuleTileEditor = Editor.CreateEditor(overrideTile.m_InstanceTile) as RuleTileEditor; + m_RuleTileEditor = CreateEditor(overrideTile.m_InstanceTile) as RuleTileEditor; m_RuleTileEditorTarget = overrideTile.m_Tile; } + return m_RuleTileEditor; } } - RuleTileEditor m_RuleTileEditor; - RuleTile m_RuleTileEditorTarget; - - /// - /// List of Sprites and overriding Sprites - /// - public List> m_Sprites = new List>(); - /// - /// List of GameObjects and overriding GameObjects - /// - public List> m_GameObjects = new List>(); - private ReorderableList m_SpriteList; - private ReorderableList m_GameObjectList; - private int m_MissingOriginalSpriteIndex; - private int m_MissingOriginalGameObjectIndex; - - /// - /// Height for a Sprite Element - /// - public static float k_SpriteElementHeight = 48; /// - /// Height for a GameObject Element - /// - public static float k_GameObjectElementHeight = 16; - /// - /// Padding between Rule Elements - /// - public static float k_PaddingBetweenRules = 4; - - /// - /// OnEnable for the RuleOverrideTileEditor + /// OnEnable for the RuleOverrideTileEditor /// public virtual void OnEnable() { if (m_SpriteList == null) { - m_SpriteList = new ReorderableList(m_Sprites, typeof(KeyValuePair), false, true, false, false); + m_SpriteList = new ReorderableList(m_Sprites, typeof(KeyValuePair), false, true, false, + false); m_SpriteList.drawHeaderCallback = DrawSpriteListHeader; m_SpriteList.drawElementCallback = DrawSpriteElement; m_SpriteList.elementHeightCallback = GetSpriteElementHeight; } + if (m_GameObjectList == null) { - m_GameObjectList = new ReorderableList(m_GameObjects, typeof(KeyValuePair), false, true, false, false); + m_GameObjectList = new ReorderableList(m_GameObjects, typeof(KeyValuePair), false, true, + false, false); m_GameObjectList.drawHeaderCallback = DrawGameObjectListHeader; m_GameObjectList.drawElementCallback = DrawGameObjectElement; m_GameObjectList.elementHeightCallback = GetGameObjectElementHeight; @@ -89,7 +93,7 @@ public virtual void OnEnable() } /// - /// OnDisable for the RuleOverrideTileEditor + /// OnDisable for the RuleOverrideTileEditor /// public virtual void OnDisable() { @@ -98,7 +102,7 @@ public virtual void OnDisable() } /// - /// Draws the Inspector GUI for the RuleOverrideTileEditor + /// Draws the Inspector GUI for the RuleOverrideTileEditor /// public override void OnInspectorGUI() { @@ -128,12 +132,12 @@ public override void OnInspectorGUI() } /// - /// Draws the header for the Sprite list + /// Draws the header for the Sprite list /// /// GUI Rect to draw the header at public void DrawSpriteListHeader(Rect rect) { - float xMax = rect.xMax; + var xMax = rect.xMax; rect.xMax = rect.xMax / 2.0f; GUI.Label(rect, "Original Sprite", EditorStyles.label); rect.xMin = rect.xMax; @@ -142,12 +146,12 @@ public void DrawSpriteListHeader(Rect rect) } /// - /// Draws the header for the GameObject list + /// Draws the header for the GameObject list /// /// GUI Rect to draw the header at public void DrawGameObjectListHeader(Rect rect) { - float xMax = rect.xMax; + var xMax = rect.xMax; rect.xMax = rect.xMax / 2.0f; GUI.Label(rect, "Original GameObject", EditorStyles.label); rect.xMin = rect.xMax; @@ -156,15 +160,15 @@ public void DrawGameObjectListHeader(Rect rect) } /// - /// Gets the GUI element height for a Sprite element with the given index + /// Gets the GUI element height for a Sprite element with the given index /// /// Index of the Sprite element /// GUI element height for the Sprite element public float GetSpriteElementHeight(int index) { - float height = k_SpriteElementHeight + k_PaddingBetweenRules; + var height = k_SpriteElementHeight + k_PaddingBetweenRules; - bool isMissing = index >= m_MissingOriginalSpriteIndex; + var isMissing = index >= m_MissingOriginalSpriteIndex; if (isMissing) height += 16; @@ -172,15 +176,15 @@ public float GetSpriteElementHeight(int index) } /// - /// Gets the GUI element height for a GameObject element with the given index + /// Gets the GUI element height for a GameObject element with the given index /// /// Index of the GameObject element /// GUI element height for the GameObject element public float GetGameObjectElementHeight(int index) { - float height = k_GameObjectElementHeight + k_PaddingBetweenRules; + var height = k_GameObjectElementHeight + k_PaddingBetweenRules; - bool isMissing = index >= m_MissingOriginalGameObjectIndex; + var isMissing = index >= m_MissingOriginalGameObjectIndex; if (isMissing) height += 16; @@ -188,7 +192,7 @@ public float GetGameObjectElementHeight(int index) } /// - /// Draws the Sprite element for the RuleOverride list + /// Draws the Sprite element for the RuleOverride list /// /// Rect to draw the Sprite Element in /// Index of the Sprite Element to draw @@ -196,33 +200,39 @@ public float GetGameObjectElementHeight(int index) /// Whether the Sprite Element is focused public void DrawSpriteElement(Rect rect, int index, bool active, bool focused) { - bool isMissing = index >= m_MissingOriginalSpriteIndex; + var isMissing = index >= m_MissingOriginalSpriteIndex; if (isMissing) { - EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original Sprite missing", MessageType.Warning); + EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original Sprite missing", + MessageType.Warning); rect.yMin += 16; } - Sprite originalSprite = m_Sprites[index].Key; - Sprite overrideSprite = m_Sprites[index].Value; + var originalSprite = m_Sprites[index].Key; + var overrideSprite = m_Sprites[index].Value; rect.y += 2; rect.height -= k_PaddingBetweenRules; rect.xMax = rect.xMax / 2.0f; using (new EditorGUI.DisabledScope(true)) - EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.height, rect.height), originalSprite, typeof(Sprite), false); + { + EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.height, rect.height), originalSprite, + typeof(Sprite), false); + } + rect.xMin = rect.xMax; rect.xMax *= 2.0f; EditorGUI.BeginChangeCheck(); - overrideSprite = EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.height, rect.height), overrideSprite, typeof(Sprite), false) as Sprite; + overrideSprite = EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.height, rect.height), + overrideSprite, typeof(Sprite), false) as Sprite; if (EditorGUI.EndChangeCheck()) m_Sprites[index] = new KeyValuePair(originalSprite, overrideSprite); } /// - /// Draws the GameObject element for the RuleOverride list + /// Draws the GameObject element for the RuleOverride list /// /// Rect to draw the GameObject Element in /// Index of the GameObject Element to draw @@ -230,38 +240,46 @@ public void DrawSpriteElement(Rect rect, int index, bool active, bool focused) /// Whether the GameObject Element is focused public void DrawGameObjectElement(Rect rect, int index, bool active, bool focused) { - bool isMissing = index >= m_MissingOriginalGameObjectIndex; + var isMissing = index >= m_MissingOriginalGameObjectIndex; if (isMissing) { - EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original GameObject missing", MessageType.Warning); + EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original GameObject missing", + MessageType.Warning); rect.yMin += 16; } - GameObject originalGameObject = m_GameObjects[index].Key; - GameObject overrideGameObject = m_GameObjects[index].Value; + var originalGameObject = m_GameObjects[index].Key; + var overrideGameObject = m_GameObjects[index].Value; rect.y += 2; rect.height -= k_PaddingBetweenRules; rect.xMax = rect.xMax / 2.0f; using (new EditorGUI.DisabledScope(true)) - EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.width, rect.height), originalGameObject, typeof(GameObject), false); + { + EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.width, rect.height), originalGameObject, + typeof(GameObject), false); + } + rect.xMin = rect.xMax; rect.xMax *= 2.0f; EditorGUI.BeginChangeCheck(); - overrideGameObject = EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.width, rect.height), overrideGameObject, typeof(GameObject), false) as GameObject; + overrideGameObject = EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.width, rect.height), + overrideGameObject, typeof(GameObject), false) as GameObject; if (EditorGUI.EndChangeCheck()) m_GameObjects[index] = new KeyValuePair(originalGameObject, overrideGameObject); } /// - /// Draws a field for the RuleTile be overridden + /// Draws a field for the RuleTile be overridden /// public void DrawTileField() { EditorGUI.BeginChangeCheck(); - RuleTile tile = EditorGUILayout.ObjectField(Styles.overrideTile, overrideTile.m_Tile, typeof(RuleTile), false) as RuleTile; + var tile = + EditorGUILayout.ObjectField(Styles.overrideTile, overrideTile.m_Tile, typeof(RuleTile), false) as + RuleTile; if (EditorGUI.EndChangeCheck()) { if (!LoopCheck(tile)) @@ -280,7 +298,7 @@ bool LoopCheck(RuleTile checkTile) if (!overrideTile.m_InstanceTile) return false; - HashSet renferenceTils = new HashSet(); + var renferenceTils = new HashSet(); Add(overrideTile.m_InstanceTile); return renferenceTils.Contains(checkTile); @@ -301,7 +319,7 @@ void Add(RuleTile ruleTile) } /// - /// Draw editor fields for custom properties for the RuleOverrideTile + /// Draw editor fields for custom properties for the RuleOverrideTile /// public void DrawCustomFields() { @@ -315,33 +333,30 @@ public void DrawCustomFields() private void SaveInstanceTileAsset() { - bool assetChanged = false; + var assetChanged = false; if (overrideTile.m_InstanceTile) - { if (!overrideTile.m_Tile || overrideTile.m_InstanceTile.GetType() != overrideTile.m_Tile.GetType()) { DestroyImmediate(overrideTile.m_InstanceTile, true); overrideTile.m_InstanceTile = null; assetChanged = true; } - } + if (!overrideTile.m_InstanceTile) - { if (overrideTile.m_Tile) { var t = overrideTile.m_Tile.GetType(); - RuleTile instanceTile = ScriptableObject.CreateInstance(t) as RuleTile; + var instanceTile = CreateInstance(t) as RuleTile; instanceTile.hideFlags = HideFlags.NotEditable; AssetDatabase.AddObjectToAsset(instanceTile, overrideTile); overrideTile.m_InstanceTile = instanceTile; assetChanged = true; } - } if (overrideTile.m_InstanceTile) { - string instanceTileName = overrideTile.m_Tile.name + " (Override)"; + var instanceTileName = overrideTile.m_Tile.name + " (Override)"; if (overrideTile.m_InstanceTile.name != instanceTileName) { overrideTile.m_InstanceTile.name = instanceTileName; @@ -352,12 +367,12 @@ private void SaveInstanceTileAsset() if (assetChanged) { EditorUtility.SetDirty(overrideTile.m_InstanceTile); - AssetDatabase.SaveAssetIfDirty(overrideTile.m_InstanceTile); + AssetDatabase.SaveAssetIfDirty(overrideTile.m_InstanceTile); } } /// - /// Saves any changes to the RuleOverrideTile + /// Saves any changes to the RuleOverrideTile /// public void SaveTile() { @@ -365,7 +380,7 @@ public void SaveTile() SceneView.RepaintAll(); SaveInstanceTileAsset(); - + if (overrideTile.m_InstanceTile) { overrideTile.Override(); @@ -373,14 +388,12 @@ public void SaveTile() } if (ruleTileEditor && ruleTileEditor.m_PreviewTilemaps != null) - { foreach (var tilemap in ruleTileEditor.m_PreviewTilemaps) tilemap.RefreshAllTiles(); - } } /// - /// Renders a static preview Texture2D for a RuleOverrideTile asset + /// Renders a static preview Texture2D for a RuleOverrideTile asset /// /// Asset path of the RuleOverrideTile /// Arrays of assets from the given Asset path @@ -396,7 +409,7 @@ public override Texture2D RenderStaticPreview(string assetPath, Object[] subAsse } /// - /// Whether the RuleOverrideTile has a preview GUI + /// Whether the RuleOverrideTile has a preview GUI /// /// True if RuleOverrideTile has a preview GUI. False if not. public override bool HasPreviewGUI() @@ -408,7 +421,7 @@ public override bool HasPreviewGUI() } /// - /// Updates preview settings for the RuleOverrideTile. + /// Updates preview settings for the RuleOverrideTile. /// public override void OnPreviewSettings() { @@ -417,7 +430,7 @@ public override void OnPreviewSettings() } /// - /// Draws the preview GUI for the RuleTile + /// Draws the preview GUI for the RuleTile /// /// Rect to draw the preview GUI /// The GUIStyle of the background for the preview @@ -426,5 +439,11 @@ public override void OnPreviewGUI(Rect rect, GUIStyle background) if (ruleTileEditor) ruleTileEditor.OnPreviewGUI(rect, background); } + + private static class Styles + { + public static readonly GUIContent overrideTile = EditorGUIUtility.TrTextContent("Tile" + , "The Rule Tile to override."); + } } -} +} \ No newline at end of file diff --git a/Editor/Tiles/RuleTile/RuleTileEditor.cs b/Editor/Tiles/RuleTile/RuleTileEditor.cs index fff1e31..3e536b7 100644 --- a/Editor/Tiles/RuleTile/RuleTileEditor.cs +++ b/Editor/Tiles/RuleTile/RuleTileEditor.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Linq; +using System.Reflection; using UnityEditorInternal; using UnityEngine; using UnityEngine.Tilemaps; @@ -10,34 +10,124 @@ namespace UnityEditor { /// - /// The Editor for a RuleTile. + /// The Editor for a RuleTile. /// [CustomEditor(typeof(RuleTile), true)] [CanEditMultipleObjects] public class RuleTileEditor : Editor { - private const string s_XIconString = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABoSURBVDhPnY3BDcAgDAOZhS14dP1O0x2C/LBEgiNSHvfwyZabmV0jZRUpq2zi6f0DJwdcQOEdwwDLypF0zHLMa9+NQRxkQ+ACOT2STVw/q8eY1346ZlE54sYAhVhSDrjwFymrSFnD2gTZpls2OvFUHAAAAABJRU5ErkJggg=="; - private const string s_Arrow0 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACYSURBVDhPzZExDoQwDATzE4oU4QXXcgUFj+YxtETwgpMwXuFcwMFSRMVKKwzZcWzhiMg91jtg34XIntkre5EaT7yjjhI9pOD5Mw5k2X/DdUwFr3cQ7Pu23E/BiwXyWSOxrNqx+ewnsayam5OLBtbOGPUM/r93YZL4/dhpR/amwByGFBz170gNChA6w5bQQMqramBTgJ+Z3A58WuWejPCaHQAAAABJRU5ErkJggg=="; - private const string s_Arrow1 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABqSURBVDhPxYzBDYAgEATpxYcd+PVr0fZ2siZrjmMhFz6STIiDs8XMlpEyi5RkO/d66TcgJUB43JfNBqRkSEYDnYjhbKD5GIUkDqRDwoH3+NgTAw+bL/aoOP4DOgH+iwECEt+IlFmkzGHlAYKAWF9R8zUnAAAAAElFTkSuQmCC"; - private const string s_Arrow2 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAAC0SURBVDhPjVE5EsIwDMxPKFKYF9CagoJH8xhaMskLmEGsjOSRkBzYmU2s9a58TUQUmCH1BWEHweuKP+D8tphrWcAHuIGrjPnPNY8X2+DzEWE+FzrdrkNyg2YGNNfRGlyOaZDJOxBrDhgOowaYW8UW0Vau5ZkFmXbbDr+CzOHKmLinAXMEePyZ9dZkZR+s5QX2O8DY3zZ/sgYcdDqeEVp8516o0QQV1qeMwg6C91toYoLoo+kNt/tpKQEVvFQAAAAASUVORK5CYII="; - private const string s_Arrow3 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAAB2SURBVDhPzY1LCoAwEEPnLi48gW5d6p31bH5SMhp0Cq0g+CCLxrzRPqMZ2pRqKG4IqzJc7JepTlbRZXYpWTg4RZE1XAso8VHFKNhQuTjKtZvHUNCEMogO4K3BhvMn9wP4EzoPZ3n0AGTW5fiBVzLAAYTP32C2Ay3agtu9V/9PAAAAAElFTkSuQmCC"; - private const string s_Arrow5 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABqSURBVDhPnY3BCYBADASvFx924NevRdvbyoLBmNuDJQMDGjNxAFhK1DyUQ9fvobCdO+j7+sOKj/uSB+xYHZAxl7IR1wNTXJeVcaAVU+614uWfCT9mVUhknMlxDokd15BYsQrJFHeUQ0+MB5ErsPi/6hO1AAAAAElFTkSuQmCC"; - private const string s_Arrow6 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACaSURBVDhPxZExEkAwEEVzE4UiTqClUDi0w2hlOIEZsV82xCZmQuPPfFn8t1mirLWf7S5flQOXjd64vCuEKWTKVt+6AayH3tIa7yLg6Qh2FcKFB72jBgJeziA1CMHzeaNHjkfwnAK86f3KUafU2ClHIJSzs/8HHLv09M3SaMCxS7ljw/IYJWzQABOQZ66x4h614ahTCL/WT7BSO51b5Z5hSx88AAAAAElFTkSuQmCC"; - private const string s_Arrow7 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABQSURBVDhPYxh8QNle/T8U/4MKEQdAmsz2eICx6W530gygr2aQBmSMphkZYxqErAEXxusKfAYQ7XyyNMIAsgEkaYQBkAFkaYQBsjXSGDAwAAD193z4luKPrAAAAABJRU5ErkJggg=="; - private const string s_Arrow8 = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACYSURBVDhPxZE9DoAwCIW9iUOHegJXHRw8tIdx1egJTMSHAeMPaHSR5KVQ+KCkCRF91mdz4VDEWVzXTBgg5U1N5wahjHzXS3iFFVRxAygNVaZxJ6VHGIl2D6oUXP0ijlJuTp724FnID1Lq7uw2QM5+thoKth0N+GGyA7IA3+yM77Ag1e2zkey5gCdAg/h8csy+/89v7E+YkgUntOWeVt2SfAAAAABJRU5ErkJggg=="; - private const string s_MirrorX = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAG1JREFUOE+lj9ENwCAIRB2IFdyRfRiuDSaXAF4MrR9P5eRhHGb2Gxp2oaEjIovTXSrAnPNx6hlgyCZ7o6omOdYOldGIZhAziEmOTSfigLV0RYAB9y9f/7kO8L3WUaQyhCgz0dmCL9CwCw172HgBeyG6oloC8fAAAAAASUVORK5CYII="; - private const string s_MirrorY = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAG9JREFUOE+djckNACEMAykoLdAjHbPyw1IOJ0L7mAejjFlm9hspyd77Kk+kBAjPOXcakJIh6QaKyOE0EB5dSPJAiUmOiL8PMVGxugsP/0OOib8vsY8yYwy6gRyC8CB5QIWgCMKBLgRSkikEUr5h6wOPWfMoCYILdgAAAABJRU5ErkJggg=="; - private const string s_MirrorXY = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAAHkSURBVDhPrVJLSwJRFJ4cdXwjPlrVJly1kB62cpEguElXKgYKIpaC+EIEEfGxLqI/UES1KaJlEdGmRY9ltCsIWrUJatGm0eZO3xkHIsJdH3zce+ec75z5zr3cf2MMmLdYLA/BYFA2mUyPOPvwnR+GR4PXaDQLLpfrKpVKSb1eT6bV6XTeocAS4sIw7S804BzEZ4IgsGq1ykhcr9dlj8czwPdbxJdBMyX/As/zLiz74Ar2J9lsVulcKpUYut5DnEbsHFwEx8AhtFqtGViD6BOc1ul0B5lMRhGXy2Wm1+ufkBOE/2fsL1FsQpXCiCAcQiAlk0kJRZjf7+9TRxI3Gg0WCoW+IpGISHHERBS5UKUch8n2K5WK3O125VqtpqydTkdZie12W261WjIVo73b7RZVKccZDIZ1q9XaT6fTLB6PD9BFKhQKjITFYpGFw+FBNBpVOgcCARH516pUGZYZXk5R4B3efLBxDM9f1CkWi/WR3ICtGVh6Rd4NPE+p0iEgmkSRLRoMEjYhHpA4kUiIOO8iZRU8AmnadK2/QOOfhnjPZrO95fN5Zdq5XE5yOBwvuKoNxGfBkQ8FzXkPprnj9Xrfm82mDI8fsLON3x5H/Od+RwHdLfDds9vtn0aj8QoF6QH9JzjuG3acpxmu1RgPAAAAAElFTkSuQmCC"; - private const string s_Rotated = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAHdJREFUOE+djssNwCAMQxmIFdgx+2S4Vj4YxWlQgcOT8nuG5u5C732Sd3lfLlmPMR4QhXgrTQaimUlA3EtD+CJlBuQ7aUAUMjEAv9gWCQNEPhHJUkYfZ1kEpcxDzioRzGIlr0Qwi0r+Q5rTgM+AAVcygHgt7+HtBZs/2QVWP8ahAAAAAElFTkSuQmCC"; - private const string s_RotatedMirror = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAApklEQVQoFY2SMRaAIAxDwefknVg8uIt3ckVSKdYSnjBAi/lprcaUUphZ+3WGY3u1yJcJMBdNtqAyM3BAFRgohBNmUzDEzIDCVQgGK2rL1gAxhatY3vXh+U7hIs2uOqUZ7EGfN6O1RU/wEf5VX4zgAzpTSessIhL5VDrJkrepitJtFtRHvm0YtA6MMfRSUUGcbGC+A0AdOIJx7w1w1y1WWX/FYUV1uQFvVjvOTYh+rAAAAABJRU5ErkJggg=="; - private const string s_Fixed = "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAA50lEQVQ4T51Ruw6CQBCkwBYKWkIgQAs9gfgCvgb4BML/qWBM9Bdo9QPIuVOQ3JIzosVkc7Mzty9NCPE3lORaKMm1YA/LsnTXdbdhGJ6iKHoVRTEi+r4/OI6zN01Tl/XM7HneLsuyW13XU9u2ous6gYh3kiR327YPsp6ZgyDom6aZYFqiqqqJ8mdZz8xoca64BHjkZT0zY0aVcQbysp6Z4zj+Vvkp65mZttxjOSozdkEzD7KemekcxzRNHxDOHSDiQ/DIy3pmpjtuSJBThStGKMtyRKSOLnSm3DCMz3f+FUpyLZTkOgjtDSWORSDbpbmNAAAAAElFTkSuQmCC"; + private const string s_XIconString = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABoSURBVDhPnY3BDcAgDAOZhS14dP1O0x2C/LBEgiNSHvfwyZabmV0jZRUpq2zi6f0DJwdcQOEdwwDLypF0zHLMa9+NQRxkQ+ACOT2STVw/q8eY1346ZlE54sYAhVhSDrjwFymrSFnD2gTZpls2OvFUHAAAAABJRU5ErkJggg=="; + + private const string s_Arrow0 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACYSURBVDhPzZExDoQwDATzE4oU4QXXcgUFj+YxtETwgpMwXuFcwMFSRMVKKwzZcWzhiMg91jtg34XIntkre5EaT7yjjhI9pOD5Mw5k2X/DdUwFr3cQ7Pu23E/BiwXyWSOxrNqx+ewnsayam5OLBtbOGPUM/r93YZL4/dhpR/amwByGFBz170gNChA6w5bQQMqramBTgJ+Z3A58WuWejPCaHQAAAABJRU5ErkJggg=="; + + private const string s_Arrow1 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABqSURBVDhPxYzBDYAgEATpxYcd+PVr0fZ2siZrjmMhFz6STIiDs8XMlpEyi5RkO/d66TcgJUB43JfNBqRkSEYDnYjhbKD5GIUkDqRDwoH3+NgTAw+bL/aoOP4DOgH+iwECEt+IlFmkzGHlAYKAWF9R8zUnAAAAAElFTkSuQmCC"; + + private const string s_Arrow2 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAAC0SURBVDhPjVE5EsIwDMxPKFKYF9CagoJH8xhaMskLmEGsjOSRkBzYmU2s9a58TUQUmCH1BWEHweuKP+D8tphrWcAHuIGrjPnPNY8X2+DzEWE+FzrdrkNyg2YGNNfRGlyOaZDJOxBrDhgOowaYW8UW0Vau5ZkFmXbbDr+CzOHKmLinAXMEePyZ9dZkZR+s5QX2O8DY3zZ/sgYcdDqeEVp8516o0QQV1qeMwg6C91toYoLoo+kNt/tpKQEVvFQAAAAASUVORK5CYII="; + + private const string s_Arrow3 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAAB2SURBVDhPzY1LCoAwEEPnLi48gW5d6p31bH5SMhp0Cq0g+CCLxrzRPqMZ2pRqKG4IqzJc7JepTlbRZXYpWTg4RZE1XAso8VHFKNhQuTjKtZvHUNCEMogO4K3BhvMn9wP4EzoPZ3n0AGTW5fiBVzLAAYTP32C2Ay3agtu9V/9PAAAAAElFTkSuQmCC"; + + private const string s_Arrow5 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABqSURBVDhPnY3BCYBADASvFx924NevRdvbyoLBmNuDJQMDGjNxAFhK1DyUQ9fvobCdO+j7+sOKj/uSB+xYHZAxl7IR1wNTXJeVcaAVU+614uWfCT9mVUhknMlxDokd15BYsQrJFHeUQ0+MB5ErsPi/6hO1AAAAAElFTkSuQmCC"; + + private const string s_Arrow6 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACaSURBVDhPxZExEkAwEEVzE4UiTqClUDi0w2hlOIEZsV82xCZmQuPPfFn8t1mirLWf7S5flQOXjd64vCuEKWTKVt+6AayH3tIa7yLg6Qh2FcKFB72jBgJeziA1CMHzeaNHjkfwnAK86f3KUafU2ClHIJSzs/8HHLv09M3SaMCxS7ljw/IYJWzQABOQZ66x4h614ahTCL/WT7BSO51b5Z5hSx88AAAAAElFTkSuQmCC"; + + private const string s_Arrow7 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAABQSURBVDhPYxh8QNle/T8U/4MKEQdAmsz2eICx6W530gygr2aQBmSMphkZYxqErAEXxusKfAYQ7XyyNMIAsgEkaYQBkAFkaYQBsjXSGDAwAAD193z4luKPrAAAAABJRU5ErkJggg=="; + + private const string s_Arrow8 = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAACYSURBVDhPxZE9DoAwCIW9iUOHegJXHRw8tIdx1egJTMSHAeMPaHSR5KVQ+KCkCRF91mdz4VDEWVzXTBgg5U1N5wahjHzXS3iFFVRxAygNVaZxJ6VHGIl2D6oUXP0ijlJuTp724FnID1Lq7uw2QM5+thoKth0N+GGyA7IA3+yM77Ag1e2zkey5gCdAg/h8csy+/89v7E+YkgUntOWeVt2SfAAAAABJRU5ErkJggg=="; + + private const string s_MirrorX = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAG1JREFUOE+lj9ENwCAIRB2IFdyRfRiuDSaXAF4MrR9P5eRhHGb2Gxp2oaEjIovTXSrAnPNx6hlgyCZ7o6omOdYOldGIZhAziEmOTSfigLV0RYAB9y9f/7kO8L3WUaQyhCgz0dmCL9CwCw172HgBeyG6oloC8fAAAAAASUVORK5CYII="; + + private const string s_MirrorY = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAG9JREFUOE+djckNACEMAykoLdAjHbPyw1IOJ0L7mAejjFlm9hspyd77Kk+kBAjPOXcakJIh6QaKyOE0EB5dSPJAiUmOiL8PMVGxugsP/0OOib8vsY8yYwy6gRyC8CB5QIWgCMKBLgRSkikEUr5h6wOPWfMoCYILdgAAAABJRU5ErkJggg=="; + + private const string s_MirrorXY = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAAHkSURBVDhPrVJLSwJRFJ4cdXwjPlrVJly1kB62cpEguElXKgYKIpaC+EIEEfGxLqI/UES1KaJlEdGmRY9ltCsIWrUJatGm0eZO3xkHIsJdH3zce+ec75z5zr3cf2MMmLdYLA/BYFA2mUyPOPvwnR+GR4PXaDQLLpfrKpVKSb1eT6bV6XTeocAS4sIw7S804BzEZ4IgsGq1ykhcr9dlj8czwPdbxJdBMyX/As/zLiz74Ar2J9lsVulcKpUYut5DnEbsHFwEx8AhtFqtGViD6BOc1ul0B5lMRhGXy2Wm1+ufkBOE/2fsL1FsQpXCiCAcQiAlk0kJRZjf7+9TRxI3Gg0WCoW+IpGISHHERBS5UKUch8n2K5WK3O125VqtpqydTkdZie12W261WjIVo73b7RZVKccZDIZ1q9XaT6fTLB6PD9BFKhQKjITFYpGFw+FBNBpVOgcCARH516pUGZYZXk5R4B3efLBxDM9f1CkWi/WR3ICtGVh6Rd4NPE+p0iEgmkSRLRoMEjYhHpA4kUiIOO8iZRU8AmnadK2/QOOfhnjPZrO95fN5Zdq5XE5yOBwvuKoNxGfBkQ8FzXkPprnj9Xrfm82mDI8fsLON3x5H/Od+RwHdLfDds9vtn0aj8QoF6QH9JzjuG3acpxmu1RgPAAAAAElFTkSuQmCC"; + + private const string s_Rotated = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAHdJREFUOE+djssNwCAMQxmIFdgx+2S4Vj4YxWlQgcOT8nuG5u5C732Sd3lfLlmPMR4QhXgrTQaimUlA3EtD+CJlBuQ7aUAUMjEAv9gWCQNEPhHJUkYfZ1kEpcxDzioRzGIlr0Qwi0r+Q5rTgM+AAVcygHgt7+HtBZs/2QVWP8ahAAAAAElFTkSuQmCC"; + + private const string s_RotatedMirror = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAApklEQVQoFY2SMRaAIAxDwefknVg8uIt3ckVSKdYSnjBAi/lprcaUUphZ+3WGY3u1yJcJMBdNtqAyM3BAFRgohBNmUzDEzIDCVQgGK2rL1gAxhatY3vXh+U7hIs2uOqUZ7EGfN6O1RU/wEf5VX4zgAzpTSessIhL5VDrJkrepitJtFtRHvm0YtA6MMfRSUUGcbGC+A0AdOIJx7w1w1y1WWX/FYUV1uQFvVjvOTYh+rAAAAABJRU5ErkJggg=="; + + private const string s_Fixed = + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAA50lEQVQ4T51Ruw6CQBCkwBYKWkIgQAs9gfgCvgb4BML/qWBM9Bdo9QPIuVOQ3JIzosVkc7Mzty9NCPE3lORaKMm1YA/LsnTXdbdhGJ6iKHoVRTEi+r4/OI6zN01Tl/XM7HneLsuyW13XU9u2ous6gYh3kiR327YPsp6ZgyDom6aZYFqiqqqJ8mdZz8xoca64BHjkZT0zY0aVcQbysp6Z4zj+Vvkp65mZttxjOSozdkEzD7KemekcxzRNHxDOHSDiQ/DIy3pmpjtuSJBThStGKMtyRKSOLnSm3DCMz3f+FUpyLZTkOgjtDSWORSDbpbmNAAAAAElFTkSuQmCC"; + + /// + /// Default height for a Rule Element + /// + public const float k_DefaultElementHeight = 48f; + + /// + /// Padding between Rule Elements + /// + public const float k_PaddingBetweenRules = 8f; + + /// + /// Single line height + /// + public const float k_SingleLineHeight = 18f; + + /// + /// Width for labels + /// + public const float k_LabelWidth = 80f; private static readonly string k_UndoName = L10n.Tr("Change RuleTile"); - + private static Texture2D[] s_Arrows; + private static Texture2D[] s_AutoTransforms; + /// - /// Array of arrow textures used for marking positions for Rule matches + /// Whether the RuleTile can extend its neighbors beyond directly adjacent ones + /// + public bool extendNeighbor; + + /// + /// Grid for rendering previews + /// + public Grid m_PreviewGrid; + + /// + /// List of Tilemaps for rendering previews + /// + public List m_PreviewTilemaps; + + /// + /// List of TilemapRenderers for rendering previews + /// + public List m_PreviewTilemapRenderers; + + /// + /// List of Sprites for Drag and Drop + /// + private List dragAndDropSprites; + + private MethodInfo m_ClearCacheMethod; + + /// + /// Preview Utility for rendering previews + /// + public PreviewRenderUtility m_PreviewUtility; + + /// + /// Reorderable list for Rules + /// + private ReorderableList m_ReorderableList; + + private SerializedProperty m_TilingRules; + + /// + /// Array of arrow textures used for marking positions for Rule matches /// public static Texture2D[] arrows { @@ -56,13 +146,13 @@ public static Texture2D[] arrows s_Arrows[8] = Base64ToTexture(s_Arrow8); s_Arrows[9] = Base64ToTexture(s_XIconString); } + return s_Arrows; } } - private static Texture2D[] s_AutoTransforms; /// - /// Arrays of textures used for marking transform Rule matches + /// Arrays of textures used for marking transform Rule matches /// public static Texture2D[] autoTransforms { @@ -78,139 +168,27 @@ public static Texture2D[] autoTransforms s_AutoTransforms[4] = Base64ToTexture(s_MirrorXY); s_AutoTransforms[5] = Base64ToTexture(s_RotatedMirror); } + return s_AutoTransforms; } } - private static class Styles - { - public static readonly GUIContent defaultSprite = EditorGUIUtility.TrTextContent("Default Sprite" - , "The default Sprite set when creating a new Rule."); - public static readonly GUIContent defaultGameObject = EditorGUIUtility.TrTextContent("Default GameObject" - , "The default GameObject set when creating a new Rule."); - public static readonly GUIContent defaultCollider = EditorGUIUtility.TrTextContent("Default Collider" - , "The default Collider Type set when creating a new Rule."); - - public static readonly GUIContent emptyRuleTileInfo = - EditorGUIUtility.TrTextContent( - "Drag Sprite or Sprite Texture assets \n" + - " to start creating a Rule Tile."); - - public static readonly GUIContent extendNeighbor = EditorGUIUtility.TrTextContent("Extend Neighbor" - , "Enabling this allows you to increase the range of neighbors beyond the 3x3 box."); - - public static readonly GUIContent numberOfTilingRules = EditorGUIUtility.TrTextContent( - "Number of Tiling Rules" - , "Change this to adjust of the number of tiling rules."); - - public static readonly GUIContent tilingRules = EditorGUIUtility.TrTextContent("Tiling Rules"); - public static readonly GUIContent tilingRulesGameObject = EditorGUIUtility.TrTextContent("GameObject" - , "The GameObject for the Tile which fits this Rule."); - public static readonly GUIContent tilingRulesCollider = EditorGUIUtility.TrTextContent("Collider" - , "The Collider Type for the Tile which fits this Rule"); - public static readonly GUIContent tilingRulesOutput = EditorGUIUtility.TrTextContent("Output" - , "The Output for the Tile which fits this Rule. Each Output type has its own properties."); - - public static readonly GUIContent tilingRulesNoise = EditorGUIUtility.TrTextContent("Noise" - , "The Perlin noise factor when placing the Tile."); - public static readonly GUIContent tilingRulesShuffle = EditorGUIUtility.TrTextContent("Shuffle" - , "The randomized transform given to the Tile when placing it."); - public static readonly GUIContent tilingRulesRandomSize = EditorGUIUtility.TrTextContent("Size" - , "The number of Sprites to randomize from."); - - public static readonly GUIContent tilingRulesMinSpeed = EditorGUIUtility.TrTextContent("Min Speed" - , "The minimum speed at which the animation is played."); - public static readonly GUIContent tilingRulesMaxSpeed = EditorGUIUtility.TrTextContent("Max Speed" - , "The maximum speed at which the animation is played."); - public static readonly GUIContent tilingRulesAnimationSize = EditorGUIUtility.TrTextContent("Size" - , "The number of Sprites in the animation."); - - public static readonly GUIStyle extendNeighborsLightStyle = new GUIStyle() - { - alignment = TextAnchor.MiddleLeft, - fontStyle = FontStyle.Bold, - fontSize = 10, - normal = new GUIStyleState() - { - textColor = Color.black - } - }; - - public static readonly GUIStyle extendNeighborsDarkStyle = new GUIStyle() - { - alignment = TextAnchor.MiddleLeft, - fontStyle = FontStyle.Bold, - fontSize = 10, - normal = new GUIStyleState() - { - textColor = Color.white - } - }; - } - /// - /// The RuleTile being edited + /// The RuleTile being edited /// public RuleTile tile => target as RuleTile; - - /// - /// List of Sprites for Drag and Drop - /// - private List dragAndDropSprites; - - /// - /// Reorderable list for Rules - /// - private ReorderableList m_ReorderableList; - /// - /// Whether the RuleTile can extend its neighbors beyond directly adjacent ones - /// - public bool extendNeighbor; - - /// - /// Preview Utility for rendering previews - /// - public PreviewRenderUtility m_PreviewUtility; - /// - /// Grid for rendering previews - /// - public Grid m_PreviewGrid; - /// - /// List of Tilemaps for rendering previews - /// - public List m_PreviewTilemaps; - /// - /// List of TilemapRenderers for rendering previews - /// - public List m_PreviewTilemapRenderers; - - /// - /// Default height for a Rule Element - /// - public const float k_DefaultElementHeight = 48f; - /// - /// Padding between Rule Elements - /// - public const float k_PaddingBetweenRules = 8f; - /// - /// Single line height - /// - public const float k_SingleLineHeight = 18f; - /// - /// Width for labels - /// - public const float k_LabelWidth = 80f; - private SerializedProperty m_TilingRules; + private bool dragAndDropActive => + dragAndDropSprites != null + && dragAndDropSprites.Count > 0; - private MethodInfo m_ClearCacheMethod; - /// - /// OnEnable for the RuleTileEditor + /// OnEnable for the RuleTileEditor /// public virtual void OnEnable() { - m_ReorderableList = new ReorderableList(tile != null ? tile.m_TilingRules : null, typeof(RuleTile.TilingRule), true, true, true, true); + m_ReorderableList = new ReorderableList(tile != null ? tile.m_TilingRules : null, + typeof(RuleTile.TilingRule), true, true, true, true); m_ReorderableList.drawHeaderCallback = OnDrawHeader; m_ReorderableList.drawElementCallback = OnDrawElement; m_ReorderableList.elementHeightCallback = GetElementHeight; @@ -223,16 +201,18 @@ public virtual void OnEnable() { // ClearCache was changed to InvalidateCache in newer versions of Unity. // To maintain backwards compatibility, we will attempt to retrieve each method in order - m_ClearCacheMethod = rolType.GetMethod("InvalidateCache", BindingFlags.Instance | BindingFlags.NonPublic); + m_ClearCacheMethod = + rolType.GetMethod("InvalidateCache", BindingFlags.Instance | BindingFlags.NonPublic); if (m_ClearCacheMethod == null) - m_ClearCacheMethod = rolType.GetMethod("ClearCache", BindingFlags.Instance | BindingFlags.NonPublic); + m_ClearCacheMethod = + rolType.GetMethod("ClearCache", BindingFlags.Instance | BindingFlags.NonPublic); } - + m_TilingRules = serializedObject.FindProperty("m_TilingRules"); } /// - /// OnDisable for the RuleTileEditor + /// OnDisable for the RuleTileEditor /// public virtual void OnDisable() { @@ -243,10 +223,7 @@ private void UpdateTilingRuleIds() { var existingIdSet = new HashSet(); var usedIdSet = new HashSet(); - foreach (var rule in tile.m_TilingRules) - { - existingIdSet.Add(rule.m_Id); - } + foreach (var rule in tile.m_TilingRules) existingIdSet.Add(rule.m_Id); foreach (var rule in tile.m_TilingRules) { if (usedIdSet.Contains(rule.m_Id)) @@ -255,12 +232,13 @@ private void UpdateTilingRuleIds() rule.m_Id++; existingIdSet.Add(rule.m_Id); } + usedIdSet.Add(rule.m_Id); } } /// - /// Get the GUI bounds for a Rule. + /// Get the GUI bounds for a Rule. /// /// Cell bounds of the Rule. /// Rule to get GUI bounds for. @@ -274,6 +252,7 @@ public virtual BoundsInt GetRuleGUIBounds(BoundsInt bounds, RuleTile.TilingRule bounds.xMax++; bounds.yMax++; } + bounds.xMin = Mathf.Min(bounds.xMin, -1); bounds.yMin = Mathf.Min(bounds.yMin, -1); bounds.xMax = Mathf.Max(bounds.xMax, 2); @@ -282,7 +261,7 @@ public virtual BoundsInt GetRuleGUIBounds(BoundsInt bounds, RuleTile.TilingRule } /// - /// Callback when the Rule list is updated + /// Callback when the Rule list is updated /// /// Reorderable list for Rules public void ListUpdated(ReorderableList list) @@ -292,39 +271,40 @@ public void ListUpdated(ReorderableList list) private float GetElementHeight(int index) { - RuleTile.TilingRule rule = tile.m_TilingRules[index]; + var rule = tile.m_TilingRules[index]; return GetElementHeight(rule); } /// - /// Gets the GUI element height for a TilingRule + /// Gets the GUI element height for a TilingRule /// /// Rule to get height for /// GUI element height for a TilingRule public float GetElementHeight(RuleTile.TilingRule rule) { - BoundsInt bounds = GetRuleGUIBounds(rule.GetBounds(), rule); + var bounds = GetRuleGUIBounds(rule.GetBounds(), rule); - float inspectorHeight = GetElementHeight(rule as RuleTile.TilingRuleOutput); - float matrixHeight = GetMatrixSize(bounds).y + 10f; + var inspectorHeight = GetElementHeight(rule as RuleTile.TilingRuleOutput); + var matrixHeight = GetMatrixSize(bounds).y + 10f; return Mathf.Max(inspectorHeight, matrixHeight); } /// - /// Gets the GUI element height for a TilingRuleOutput + /// Gets the GUI element height for a TilingRuleOutput /// /// Rule to get height for /// GUI element height for a TilingRuleOutput public float GetElementHeight(RuleTile.TilingRuleOutput rule) { - float inspectorHeight = k_DefaultElementHeight + k_PaddingBetweenRules; + var inspectorHeight = k_DefaultElementHeight + k_PaddingBetweenRules; switch (rule.m_Output) { case RuleTile.TilingRuleOutput.OutputSprite.Random: case RuleTile.TilingRuleOutput.OutputSprite.Animation: - inspectorHeight = k_DefaultElementHeight + k_SingleLineHeight * (rule.m_Sprites.Length + 3) + k_PaddingBetweenRules; + inspectorHeight = k_DefaultElementHeight + k_SingleLineHeight * (rule.m_Sprites.Length + 3) + + k_PaddingBetweenRules; break; } @@ -332,7 +312,7 @@ public float GetElementHeight(RuleTile.TilingRuleOutput rule) } /// - /// Gets the GUI matrix size for a Rule of a RuleTile + /// Gets the GUI matrix size for a Rule of a RuleTile /// /// Cell bounds of the Rule. /// Returns the GUI matrix size for a Rule of a RuleTile. @@ -342,7 +322,7 @@ public virtual Vector2 GetMatrixSize(BoundsInt bounds) } /// - /// Draws the Rule element for the Rule list + /// Draws the Rule element for the Rule list /// /// Rect to draw the Rule Element in /// Index of the Rule Element to draw @@ -350,16 +330,18 @@ public virtual Vector2 GetMatrixSize(BoundsInt bounds) /// Whether the Rule Element is focused protected virtual void OnDrawElement(Rect rect, int index, bool isactive, bool isfocused) { - RuleTile.TilingRule rule = tile.m_TilingRules[index]; - BoundsInt bounds = GetRuleGUIBounds(rule.GetBounds(), rule); + var rule = tile.m_TilingRules[index]; + var bounds = GetRuleGUIBounds(rule.GetBounds(), rule); - float yPos = rect.yMin + 2f; - float height = rect.height - k_PaddingBetweenRules; - Vector2 matrixSize = GetMatrixSize(bounds); + var yPos = rect.yMin + 2f; + var height = rect.height - k_PaddingBetweenRules; + var matrixSize = GetMatrixSize(bounds); - Rect spriteRect = new Rect(rect.xMax - k_DefaultElementHeight - 5f, yPos, k_DefaultElementHeight, k_DefaultElementHeight); - Rect matrixRect = new Rect(rect.xMax - matrixSize.x - spriteRect.width - 10f, yPos, matrixSize.x, matrixSize.y); - Rect inspectorRect = new Rect(rect.xMin, yPos, rect.width - matrixSize.x - spriteRect.width - 20f, height); + var spriteRect = new Rect(rect.xMax - k_DefaultElementHeight - 5f, yPos, k_DefaultElementHeight, + k_DefaultElementHeight); + var matrixRect = new Rect(rect.xMax - matrixSize.x - spriteRect.width - 10f, yPos, matrixSize.x, + matrixSize.y); + var inspectorRect = new Rect(rect.xMin, yPos, rect.width - matrixSize.x - spriteRect.width - 20f, height); RuleInspectorOnGUI(inspectorRect, rule); RuleMatrixOnGUI(tile, matrixRect, bounds, rule); @@ -369,7 +351,7 @@ protected virtual void OnDrawElement(Rect rect, int index, bool isactive, bool i private void OnAddElement(object obj) { var list = obj as ReorderableList; - RuleTile.TilingRule rule = new RuleTile.TilingRule(); + var rule = new RuleTile.TilingRule(); rule.m_Output = RuleTile.TilingRuleOutput.OutputSprite.Single; rule.m_Sprites[0] = tile.m_DefaultSprite; rule.m_GameObject = tile.m_DefaultGameObject; @@ -377,9 +359,11 @@ private void OnAddElement(object obj) var count = m_TilingRules.arraySize; ResizeRuleTileList(count + 1); - - if (list.index == -1 || list.index >= list.count) + + if (list.index == -1 || list.index >= list.count) + { tile.m_TilingRules[count] = rule; + } else { tile.m_TilingRules.Insert(list.index + 1, rule); @@ -387,6 +371,7 @@ private void OnAddElement(object obj) if (list.IsSelected(list.index)) list.index += 1; } + UpdateTilingRuleIds(); } @@ -398,10 +383,10 @@ private void OnDuplicateElement(object obj) var copyRule = tile.m_TilingRules[list.index]; var rule = copyRule.Clone(); - + var count = m_TilingRules.arraySize; ResizeRuleTileList(count + 1); - + tile.m_TilingRules.Insert(list.index + 1, rule); tile.m_TilingRules.RemoveAt(count + 1); if (list.IsSelected(list.index)) @@ -413,7 +398,7 @@ private void OnAddDropdownElement(Rect rect, ReorderableList list) { if (0 <= list.index && list.index < tile.m_TilingRules.Count && list.IsSelected(list.index)) { - GenericMenu menu = new GenericMenu(); + var menu = new GenericMenu(); menu.AddItem(EditorGUIUtility.TrTextContent("Add"), false, OnAddElement, list); menu.AddItem(EditorGUIUtility.TrTextContent("Duplicate"), false, OnDuplicateElement, list); menu.DropDown(rect); @@ -423,9 +408,9 @@ private void OnAddDropdownElement(Rect rect, ReorderableList list) OnAddElement(list); } } - + /// - /// Saves any changes to the RuleTile + /// Saves any changes to the RuleTile /// public void SaveTile() { @@ -437,14 +422,13 @@ public void SaveTile() } /// - /// Updates all RuleOverrideTiles which override the given RUleTile + /// Updates all RuleOverrideTiles which override the given RUleTile /// /// RuleTile which has been updated public static void UpdateAffectedOverrideTiles(RuleTile target) { - List overrideTiles = FindAffectedOverrideTiles(target); + var overrideTiles = FindAffectedOverrideTiles(target); if (overrideTiles != null) - { foreach (var overrideTile in overrideTiles) { Undo.RegisterCompleteObjectUndo(overrideTile, k_UndoName); @@ -453,34 +437,30 @@ public static void UpdateAffectedOverrideTiles(RuleTile target) UpdateAffectedOverrideTiles(overrideTile.m_InstanceTile); EditorUtility.SetDirty(overrideTile); } - } } /// - /// Gets all RuleOverrideTiles which override the given RuleTile + /// Gets all RuleOverrideTiles which override the given RuleTile /// /// RuleTile which has been updated /// A list of RuleOverrideTiles which override the given RuleTile public static List FindAffectedOverrideTiles(RuleTile target) { - List overrideTiles = new List(); + var overrideTiles = new List(); - string[] overrideTileGuids = AssetDatabase.FindAssets("t:" + typeof(RuleOverrideTile).Name); - foreach (string overrideTileGuid in overrideTileGuids) + var overrideTileGuids = AssetDatabase.FindAssets("t:" + typeof(RuleOverrideTile).Name); + foreach (var overrideTileGuid in overrideTileGuids) { - string overrideTilePath = AssetDatabase.GUIDToAssetPath(overrideTileGuid); - RuleOverrideTile overrideTile = AssetDatabase.LoadAssetAtPath(overrideTilePath); - if (overrideTile.m_Tile == target) - { - overrideTiles.Add(overrideTile); - } + var overrideTilePath = AssetDatabase.GUIDToAssetPath(overrideTileGuid); + var overrideTile = AssetDatabase.LoadAssetAtPath(overrideTilePath); + if (overrideTile.m_Tile == target) overrideTiles.Add(overrideTile); } return overrideTiles; } /// - /// Draws the header for the Rule list + /// Draws the header for the Rule list /// /// GUI Rect to draw the header at public void OnDrawHeader(Rect rect) @@ -498,14 +478,12 @@ public void OnDrawHeader(Rect rect) extendNeighbor = EditorGUI.Toggle(toggleRect, extendNeighbor); EditorGUI.LabelField(toggleLabelRect, Styles.extendNeighbor, style); if (EditorGUI.EndChangeCheck()) - { if (m_ClearCacheMethod != null) - m_ClearCacheMethod.Invoke(m_ReorderableList, null); - } + m_ClearCacheMethod.Invoke(m_ReorderableList, null); } /// - /// Draws the Inspector GUI for the RuleTileEditor + /// Draws the Inspector GUI for the RuleTileEditor /// public override void OnInspectorGUI() { @@ -514,16 +492,21 @@ public override void OnInspectorGUI() EditorGUI.BeginChangeCheck(); - tile.m_DefaultSprite = EditorGUILayout.ObjectField(Styles.defaultSprite, tile.m_DefaultSprite, typeof(Sprite), false) as Sprite; - tile.m_DefaultGameObject = EditorGUILayout.ObjectField(Styles.defaultGameObject, tile.m_DefaultGameObject, typeof(GameObject), false) as GameObject; - tile.m_DefaultColliderType = (Tile.ColliderType)EditorGUILayout.EnumPopup(Styles.defaultCollider, tile.m_DefaultColliderType); + tile.m_DefaultSprite = + EditorGUILayout.ObjectField(Styles.defaultSprite, tile.m_DefaultSprite, typeof(Sprite), + false) as Sprite; + tile.m_DefaultGameObject = + EditorGUILayout.ObjectField(Styles.defaultGameObject, tile.m_DefaultGameObject, typeof(GameObject), + false) as GameObject; + tile.m_DefaultColliderType = + (Tile.ColliderType)EditorGUILayout.EnumPopup(Styles.defaultCollider, tile.m_DefaultColliderType); DrawCustomFields(false); EditorGUILayout.Space(); - + EditorGUI.BeginChangeCheck(); - int count = EditorGUILayout.DelayedIntField(Styles.numberOfTilingRules, tile.m_TilingRules?.Count ?? 0); + var count = EditorGUILayout.DelayedIntField(Styles.numberOfTilingRules, tile.m_TilingRules?.Count ?? 0); if (count < 0) count = 0; if (EditorGUI.EndChangeCheck()) @@ -531,13 +514,14 @@ public override void OnInspectorGUI() if (count == 0) { - Rect rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 5); + var rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 5); HandleDragAndDrop(rect); - EditorGUI.DrawRect(rect, dragAndDropActive && rect.Contains(Event.current.mousePosition) ? Color.white : Color.black); + EditorGUI.DrawRect(rect, + dragAndDropActive && rect.Contains(Event.current.mousePosition) ? Color.white : Color.black); var innerRect = new Rect(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2); EditorGUI.DrawRect(innerRect, EditorGUIUtility.isProSkin - ? (Color) new Color32 (56, 56, 56, 255) - : (Color) new Color32 (194, 194, 194, 255)); + ? new Color32(56, 56, 56, 255) + : (Color)new Color32(194, 194, 194, 255)); DisplayClipboardText(Styles.emptyRuleTileInfo, rect); GUILayout.Space(rect.height); EditorGUILayout.Space(); @@ -561,15 +545,13 @@ private void ResizeRuleTileList(int count) m_TilingRules.arraySize = count; serializedObject.ApplyModifiedProperties(); if (isEmpty) - { - for (int i = 0; i < count; ++i) + for (var i = 0; i < count; ++i) tile.m_TilingRules[i] = new RuleTile.TilingRule(); - } UpdateTilingRuleIds(); } /// - /// Draw editor fields for custom properties for the RuleTile + /// Draw editor fields for custom properties for the RuleTile /// /// Whether override fields are drawn public void DrawCustomFields(bool isOverrideInstance) @@ -591,11 +573,10 @@ public void DrawCustomFields(bool isOverrideInstance) DestroyPreview(); CreatePreview(); } - } /// - /// Gets the index for a Rule with the RuleTile to display an arrow. + /// Gets the index for a Rule with the RuleTile to display an arrow. /// /// The relative position of the arrow from the center. /// Returns the index for a Rule with the RuleTile to display an arrow. @@ -605,32 +586,31 @@ public virtual int GetArrowIndex(Vector3Int position) { if (position.x < 0 && position.y > 0) return 0; - else if (position.x > 0 && position.y > 0) + if (position.x > 0 && position.y > 0) return 2; - else if (position.x < 0 && position.y < 0) + if (position.x < 0 && position.y < 0) return 6; - else if (position.x > 0 && position.y < 0) + if (position.x > 0 && position.y < 0) return 8; } else if (Mathf.Abs(position.x) > Mathf.Abs(position.y)) { if (position.x > 0) return 5; - else - return 3; + return 3; } else { if (position.y > 0) return 1; - else - return 7; + return 7; } + return -1; } /// - /// Draws a neighbor matching rule + /// Draws a neighbor matching rule /// /// Rect to draw on /// The relative position of the arrow from the center @@ -655,25 +635,25 @@ public virtual void RuleOnGUI(Rect rect, Vector3Int position, int neighbor) } /// - /// Draws a tooltip for the neighbor matching rule + /// Draws a tooltip for the neighbor matching rule /// /// Rect to draw on /// The index to the neighbor matching criteria public void RuleTooltipOnGUI(Rect rect, int neighbor) { - var allConsts = tile.m_NeighborType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + var allConsts = + tile.m_NeighborType.GetFields(BindingFlags.Public | BindingFlags.Static | + BindingFlags.FlattenHierarchy); foreach (var c in allConsts) - { if ((int)c.GetValue(null) == neighbor) { GUI.Label(rect, new GUIContent("", c.Name)); break; } - } } /// - /// Draws a transform matching rule + /// Draws a transform matching rule /// /// Rect to draw on /// The transform matching criteria @@ -700,28 +680,32 @@ public virtual void RuleTransformOnGUI(Rect rect, RuleTile.TilingRuleOutput.Tran GUI.DrawTexture(rect, autoTransforms[5]); break; } + GUI.Label(rect, new GUIContent("", ruleTransform.ToString())); } /// - /// Handles a neighbor matching Rule update from user mouse input + /// Handles a neighbor matching Rule update from user mouse input /// /// Rect containing neighbor matching Rule GUI /// Tiling Rule to update neighbor matching rule /// A dictionary of neighbors /// The relative position of the neighbor matching Rule - public void RuleNeighborUpdate(Rect rect, RuleTile.TilingRule tilingRule, Dictionary neighbors, Vector3Int position) + public void RuleNeighborUpdate(Rect rect, RuleTile.TilingRule tilingRule, Dictionary neighbors, + Vector3Int position) { if (Event.current.type == EventType.MouseDown && ContainsMousePosition(rect)) { - var allConsts = tile.m_NeighborType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + var allConsts = + tile.m_NeighborType.GetFields(BindingFlags.Public | BindingFlags.Static | + BindingFlags.FlattenHierarchy); var neighborConsts = allConsts.Select(c => (int)c.GetValue(null)).ToList(); neighborConsts.Sort(); if (neighbors.ContainsKey(position)) { - int oldIndex = neighborConsts.IndexOf(neighbors[position]); - int newIndex = oldIndex + GetMouseChange(); + var oldIndex = neighborConsts.IndexOf(neighbors[position]); + var newIndex = oldIndex + GetMouseChange(); if (newIndex >= 0 && newIndex < neighborConsts.Count) { newIndex = (int)Mathf.Repeat(newIndex, neighborConsts.Count); @@ -734,8 +718,9 @@ public void RuleNeighborUpdate(Rect rect, RuleTile.TilingRule tilingRule, Dictio } else { - neighbors.Add(position, neighborConsts[GetMouseChange() == 1 ? 0 : (neighborConsts.Count - 1)]); + neighbors.Add(position, neighborConsts[GetMouseChange() == 1 ? 0 : neighborConsts.Count - 1]); } + tilingRule.ApplyNeighbors(neighbors); GUI.changed = true; @@ -744,7 +729,7 @@ public void RuleNeighborUpdate(Rect rect, RuleTile.TilingRule tilingRule, Dictio } /// - /// Handles a transform matching Rule update from user mouse input + /// Handles a transform matching Rule update from user mouse input /// /// Rect containing transform matching Rule GUI /// Tiling Rule to update transform matching rule @@ -752,14 +737,16 @@ public void RuleTransformUpdate(Rect rect, RuleTile.TilingRule tilingRule) { if (Event.current.type == EventType.MouseDown && ContainsMousePosition(rect)) { - tilingRule.m_RuleTransform = (RuleTile.TilingRuleOutput.Transform)(int)Mathf.Repeat((int)tilingRule.m_RuleTransform + GetMouseChange(), Enum.GetValues(typeof(RuleTile.TilingRule.Transform)).Length); + tilingRule.m_RuleTransform = (RuleTile.TilingRuleOutput.Transform)(int)Mathf.Repeat( + (int)tilingRule.m_RuleTransform + GetMouseChange(), + Enum.GetValues(typeof(RuleTile.TilingRuleOutput.Transform)).Length); GUI.changed = true; Event.current.Use(); } } /// - /// Determines the current mouse position is within the given Rect. + /// Determines the current mouse position is within the given Rect. /// /// Rect to test mouse position for. /// True if the current mouse position is within the given Rect. False otherwise. @@ -769,7 +756,7 @@ public virtual bool ContainsMousePosition(Rect rect) } /// - /// Gets the offset change for a mouse click input + /// Gets the offset change for a mouse click input /// /// The offset change for a mouse click input public static int GetMouseChange() @@ -778,7 +765,7 @@ public static int GetMouseChange() } /// - /// Draws a Rule Matrix for the given Rule for a RuleTile. + /// Draws a Rule Matrix for the given Rule for a RuleTile. /// /// Tile to draw rule for. /// GUI Rect to draw rule at. @@ -787,42 +774,44 @@ public static int GetMouseChange() public virtual void RuleMatrixOnGUI(RuleTile tile, Rect rect, BoundsInt bounds, RuleTile.TilingRule tilingRule) { Handles.color = EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.2f) : new Color(0f, 0f, 0f, 0.2f); - float w = rect.width / bounds.size.x; - float h = rect.height / bounds.size.y; + var w = rect.width / bounds.size.x; + var h = rect.height / bounds.size.y; - for (int y = 0; y <= bounds.size.y; y++) + for (var y = 0; y <= bounds.size.y; y++) { - float top = rect.yMin + y * h; + var top = rect.yMin + y * h; Handles.DrawLine(new Vector3(rect.xMin, top), new Vector3(rect.xMax, top)); } - for (int x = 0; x <= bounds.size.x; x++) + + for (var x = 0; x <= bounds.size.x; x++) { - float left = rect.xMin + x * w; + var left = rect.xMin + x * w; Handles.DrawLine(new Vector3(left, rect.yMin), new Vector3(left, rect.yMax)); } + Handles.color = Color.white; var neighbors = tilingRule.GetNeighbors(); - for (int y = bounds.yMin; y < bounds.yMax; y++) + for (var y = bounds.yMin; y < bounds.yMax; y++) + for (var x = bounds.xMin; x < bounds.xMax; x++) { - for (int x = bounds.xMin; x < bounds.xMax; x++) - { - Vector3Int pos = new Vector3Int(x, y, 0); - Rect r = new Rect(rect.xMin + (x - bounds.xMin) * w, rect.yMin + (-y + bounds.yMax - 1) * h, w - 1, h - 1); - RuleMatrixIconOnGUI(tilingRule, neighbors, pos, r); - } + var pos = new Vector3Int(x, y, 0); + var r = new Rect(rect.xMin + (x - bounds.xMin) * w, rect.yMin + (-y + bounds.yMax - 1) * h, w - 1, + h - 1); + RuleMatrixIconOnGUI(tilingRule, neighbors, pos, r); } } /// - /// Draws a Rule Matrix Icon for the given matching Rule for a RuleTile with the given position + /// Draws a Rule Matrix Icon for the given matching Rule for a RuleTile with the given position /// /// Tile to draw rule for. /// A dictionary of neighbors /// The relative position of the neighbor matching Rule /// GUI Rect to draw icon at - public void RuleMatrixIconOnGUI(RuleTile.TilingRule tilingRule, Dictionary neighbors, Vector3Int position, Rect rect) + public void RuleMatrixIconOnGUI(RuleTile.TilingRule tilingRule, Dictionary neighbors, + Vector3Int position, Rect rect) { using (var check = new EditorGUI.ChangeCheckScope()) { @@ -833,6 +822,7 @@ public void RuleMatrixIconOnGUI(RuleTile.TilingRule tilingRule, Dictionary - /// Draws a Sprite field for the Rule + /// Draws a Sprite field for the Rule /// /// Rect to draw Sprite Inspector in /// Rule to draw Sprite Inspector for public virtual void SpriteOnGUI(Rect rect, RuleTile.TilingRuleOutput tilingRule) { - tilingRule.m_Sprites[0] = EditorGUI.ObjectField(rect, tilingRule.m_Sprites[0], typeof(Sprite), false) as Sprite; + tilingRule.m_Sprites[0] = + EditorGUI.ObjectField(rect, tilingRule.m_Sprites[0], typeof(Sprite), false) as Sprite; } /// - /// Draws an Inspector for the Rule + /// Draws an Inspector for the Rule /// /// Rect to draw Inspector in /// Rule to draw Inspector for public void RuleInspectorOnGUI(Rect rect, RuleTile.TilingRuleOutput tilingRule) { - float y = rect.yMin; + var y = rect.yMin; GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesGameObject); - tilingRule.m_GameObject = (GameObject)EditorGUI.ObjectField(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), "", tilingRule.m_GameObject, typeof(GameObject), false); + tilingRule.m_GameObject = (GameObject)EditorGUI.ObjectField( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), "", + tilingRule.m_GameObject, typeof(GameObject), false); y += k_SingleLineHeight; GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesCollider); - tilingRule.m_ColliderType = (Tile.ColliderType)EditorGUI.EnumPopup(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_ColliderType); + tilingRule.m_ColliderType = (Tile.ColliderType)EditorGUI.EnumPopup( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_ColliderType); y += k_SingleLineHeight; GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesOutput); - tilingRule.m_Output = (RuleTile.TilingRuleOutput.OutputSprite)EditorGUI.EnumPopup(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_Output); + tilingRule.m_Output = (RuleTile.TilingRuleOutput.OutputSprite)EditorGUI.EnumPopup( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_Output); y += k_SingleLineHeight; if (tilingRule.m_Output == RuleTile.TilingRuleOutput.OutputSprite.Animation) { GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesMinSpeed); - tilingRule.m_MinAnimationSpeed = EditorGUI.FloatField(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_MinAnimationSpeed); + tilingRule.m_MinAnimationSpeed = EditorGUI.FloatField( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_MinAnimationSpeed); y += k_SingleLineHeight; GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesMaxSpeed); - tilingRule.m_MaxAnimationSpeed = EditorGUI.FloatField(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_MaxAnimationSpeed); + tilingRule.m_MaxAnimationSpeed = EditorGUI.FloatField( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_MaxAnimationSpeed); y += k_SingleLineHeight; } + if (tilingRule.m_Output == RuleTile.TilingRuleOutput.OutputSprite.Random) { GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesNoise); - tilingRule.m_PerlinScale = EditorGUI.Slider(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_PerlinScale, 0.001f, 0.999f); + tilingRule.m_PerlinScale = + EditorGUI.Slider( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_PerlinScale, 0.001f, 0.999f); y += k_SingleLineHeight; GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight), Styles.tilingRulesShuffle); - tilingRule.m_RandomTransform = (RuleTile.TilingRuleOutput.Transform)EditorGUI.EnumPopup(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_RandomTransform); + tilingRule.m_RandomTransform = (RuleTile.TilingRuleOutput.Transform)EditorGUI.EnumPopup( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_RandomTransform); y += k_SingleLineHeight; } @@ -900,14 +905,19 @@ public void RuleInspectorOnGUI(Rect rect, RuleTile.TilingRuleOutput tilingRule) GUI.Label(new Rect(rect.xMin, y, k_LabelWidth, k_SingleLineHeight) , tilingRule.m_Output == RuleTile.TilingRuleOutput.OutputSprite.Animation ? Styles.tilingRulesAnimationSize : Styles.tilingRulesRandomSize); EditorGUI.BeginChangeCheck(); - int newLength = EditorGUI.DelayedIntField(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_Sprites.Length); + var newLength = EditorGUI.DelayedIntField( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_Sprites.Length); if (EditorGUI.EndChangeCheck()) Array.Resize(ref tilingRule.m_Sprites, Math.Max(newLength, 1)); y += k_SingleLineHeight; - for (int i = 0; i < tilingRule.m_Sprites.Length; i++) + for (var i = 0; i < tilingRule.m_Sprites.Length; i++) { - tilingRule.m_Sprites[i] = EditorGUI.ObjectField(new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), tilingRule.m_Sprites[i], typeof(Sprite), false) as Sprite; + tilingRule.m_Sprites[i] = + EditorGUI.ObjectField( + new Rect(rect.xMin + k_LabelWidth, y, rect.width - k_LabelWidth, k_SingleLineHeight), + tilingRule.m_Sprites[i], typeof(Sprite), false) as Sprite; y += k_SingleLineHeight; } } @@ -915,10 +925,10 @@ public void RuleInspectorOnGUI(Rect rect, RuleTile.TilingRuleOutput tilingRule) private void DisplayClipboardText(GUIContent clipboardText, Rect position) { - Color old = GUI.color; + var old = GUI.color; GUI.color = Color.gray; var infoSize = GUI.skin.label.CalcSize(clipboardText); - Rect rect = new Rect(position.center.x - infoSize.x * .5f + var rect = new Rect(position.center.x - infoSize.x * .5f , position.center.y - infoSize.y * .5f , infoSize.x , infoSize.y); @@ -926,53 +936,36 @@ private void DisplayClipboardText(GUIContent clipboardText, Rect position) GUI.color = old; } - private bool dragAndDropActive - { - get - { - return dragAndDropSprites != null - && dragAndDropSprites.Count > 0; - } - } - private static List GetSpritesFromTexture(Texture2D texture) { - string path = AssetDatabase.GetAssetPath(texture); - Object[] assets = AssetDatabase.LoadAllAssetsAtPath(path); - List sprites = new List(); + var path = AssetDatabase.GetAssetPath(texture); + var assets = AssetDatabase.LoadAllAssetsAtPath(path); + var sprites = new List(); - foreach (Object asset in assets) - { + foreach (var asset in assets) if (asset is Sprite) - { sprites.Add(asset as Sprite); - } - } return sprites; } - + private static List GetValidSingleSprites(Object[] objects) { - List result = new List(); - foreach (Object obj in objects) - { + var result = new List(); + foreach (var obj in objects) if (obj is Sprite sprite) { result.Add(sprite); } else if (obj is Texture2D texture2D) { - List sprites = GetSpritesFromTexture(texture2D); - if (sprites.Count > 0) - { - result.AddRange(sprites); - } + var sprites = GetSpritesFromTexture(texture2D); + if (sprites.Count > 0) result.AddRange(sprites); } - } + return result; } - + private void HandleDragAndDrop(Rect guiRect) { if (DragAndDrop.objectReferences.Length == 0 || !guiRect.Contains(Event.current.mousePosition)) @@ -998,10 +991,8 @@ private void HandleDragAndDrop(Rect guiRect) Undo.RegisterCompleteObjectUndo(tile, "Drag and Drop to Rule Tile"); ResizeRuleTileList(dragAndDropSprites.Count); - for (int i = 0; i < dragAndDropSprites.Count; ++i) - { + for (var i = 0; i < dragAndDropSprites.Count; ++i) tile.m_TilingRules[i].m_Sprites[0] = dragAndDropSprites[i]; - } DragAndDropClear(); GUI.changed = true; EditorUtility.SetDirty(tile); @@ -1014,21 +1005,19 @@ private void HandleDragAndDrop(Rect guiRect) } if (Event.current.type == EventType.DragExited || - Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { + (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)) DragAndDropClear(); - } } - + private void DragAndDropClear() { dragAndDropSprites = null; DragAndDrop.visualMode = DragAndDropVisualMode.None; Event.current.Use(); } - + /// - /// Whether the RuleTile has a preview GUI + /// Whether the RuleTile has a preview GUI /// /// True public override bool HasPreviewGUI() @@ -1037,7 +1026,7 @@ public override bool HasPreviewGUI() } /// - /// Draws the preview GUI for the RuleTile + /// Draws the preview GUI for the RuleTile /// /// Rect to draw the preview GUI /// The GUIStyle of the background for the preview @@ -1058,7 +1047,7 @@ public override void OnPreviewGUI(Rect rect, GUIStyle background) } /// - /// Creates a Preview for the RuleTile. + /// Creates a Preview for the RuleTile. /// protected virtual void CreatePreview() { @@ -1074,7 +1063,7 @@ protected virtual void CreatePreview() m_PreviewTilemaps = new List(); m_PreviewTilemapRenderers = new List(); - for (int i = 0; i < 4; i++) + for (var i = 0; i < 4; i++) { var previewTilemapGo = new GameObject(); m_PreviewTilemaps.Add(previewTilemapGo.AddComponent()); @@ -1083,21 +1072,21 @@ protected virtual void CreatePreview() previewTilemapGo.transform.SetParent(previewInstance.transform, false); } - for (int x = -2; x <= 0; x++) - for (int y = -1; y <= 1; y++) - m_PreviewTilemaps[0].SetTile(new Vector3Int(x, y, 0), tile); + for (var x = -2; x <= 0; x++) + for (var y = -1; y <= 1; y++) + m_PreviewTilemaps[0].SetTile(new Vector3Int(x, y, 0), tile); - for (int y = -1; y <= 1; y++) + for (var y = -1; y <= 1; y++) m_PreviewTilemaps[1].SetTile(new Vector3Int(1, y, 0), tile); - for (int x = -2; x <= 0; x++) + for (var x = -2; x <= 0; x++) m_PreviewTilemaps[2].SetTile(new Vector3Int(x, -2, 0), tile); m_PreviewTilemaps[3].SetTile(new Vector3Int(1, -2, 0), tile); } /// - /// Handles cleanup for the Preview GUI + /// Handles cleanup for the Preview GUI /// protected virtual void DestroyPreview() { @@ -1112,7 +1101,7 @@ protected virtual void DestroyPreview() } /// - /// Renders a static preview Texture2D for a RuleTile asset + /// Renders a static preview Texture2D for a RuleTile asset /// /// Asset path of the RuleTile /// Arrays of assets from the given Asset path @@ -1123,18 +1112,21 @@ public override Texture2D RenderStaticPreview(string assetPath, Object[] subAsse { if (tile.m_DefaultSprite != null) { - Type t = GetType("UnityEditor.SpriteUtility"); + var t = GetType("UnityEditor.SpriteUtility"); if (t != null) { - MethodInfo method = t.GetMethod("RenderStaticPreview", new[] { typeof(Sprite), typeof(Color), typeof(int), typeof(int) }); + var method = t.GetMethod("RenderStaticPreview", + new[] { typeof(Sprite), typeof(Color), typeof(int), typeof(int) }); if (method != null) { - object ret = method.Invoke("RenderStaticPreview", new object[] { tile.m_DefaultSprite, Color.white, width, height }); + var ret = method.Invoke("RenderStaticPreview", + new object[] { tile.m_DefaultSprite, Color.white, width, height }); if (ret is Texture2D) return ret as Texture2D; } } } + return base.RenderStaticPreview(assetPath, subAssets, width, height); } @@ -1156,65 +1148,54 @@ private static Type GetType(string typeName) return type; } } + return null; } /// - /// Converts a Base64 string to a Texture2D + /// Converts a Base64 string to a Texture2D /// /// Base64 string containing image data /// Texture2D containing an image from the given Base64 string public static Texture2D Base64ToTexture(string base64) { - Texture2D t = new Texture2D(1, 1); + var t = new Texture2D(1, 1); t.hideFlags = HideFlags.HideAndDontSave; t.LoadImage(Convert.FromBase64String(base64)); return t; } /// - /// Wrapper for serializing a list of Rules - /// - [Serializable] - class RuleTileRuleWrapper - { - /// - /// List of Rules to serialize - /// - [SerializeField] - public List rules = new List(); - } - - /// - /// Copies all Rules from a RuleTile to the clipboard + /// Copies all Rules from a RuleTile to the clipboard /// /// MenuCommand storing the RuleTile to copy from [MenuItem("CONTEXT/RuleTile/Copy All Rules")] public static void CopyAllRules(MenuCommand item) { - RuleTile tile = item.context as RuleTile; + var tile = item.context as RuleTile; if (tile == null) return; - RuleTileRuleWrapper rulesWrapper = new RuleTileRuleWrapper(); + var rulesWrapper = new RuleTileRuleWrapper(); rulesWrapper.rules = tile.m_TilingRules; var rulesJson = EditorJsonUtility.ToJson(rulesWrapper); EditorGUIUtility.systemCopyBuffer = rulesJson; } + /// - /// Pastes all Rules from the clipboard to a RuleTile + /// Pastes all Rules from the clipboard to a RuleTile /// /// MenuCommand storing the RuleTile to paste to [MenuItem("CONTEXT/RuleTile/Paste Rules")] public static void PasteRules(MenuCommand item) { - RuleTile tile = item.context as RuleTile; + var tile = item.context as RuleTile; if (tile == null) return; try { - RuleTileRuleWrapper rulesWrapper = new RuleTileRuleWrapper(); + var rulesWrapper = new RuleTileRuleWrapper(); EditorJsonUtility.FromJsonOverwrite(EditorGUIUtility.systemCopyBuffer, rulesWrapper); tile.m_TilingRules.AddRange(rulesWrapper.rules); } @@ -1223,5 +1204,92 @@ public static void PasteRules(MenuCommand item) Debug.LogError("Unable to paste rules from system copy buffer"); } } + + private static class Styles + { + public static readonly GUIContent defaultSprite = EditorGUIUtility.TrTextContent("Default Sprite" + , "The default Sprite set when creating a new Rule."); + + public static readonly GUIContent defaultGameObject = EditorGUIUtility.TrTextContent("Default GameObject" + , "The default GameObject set when creating a new Rule."); + + public static readonly GUIContent defaultCollider = EditorGUIUtility.TrTextContent("Default Collider" + , "The default Collider Type set when creating a new Rule."); + + public static readonly GUIContent emptyRuleTileInfo = + EditorGUIUtility.TrTextContent( + "Drag Sprite or Sprite Texture assets \n" + + " to start creating a Rule Tile."); + + public static readonly GUIContent extendNeighbor = EditorGUIUtility.TrTextContent("Extend Neighbor" + , "Enabling this allows you to increase the range of neighbors beyond the 3x3 box."); + + public static readonly GUIContent numberOfTilingRules = EditorGUIUtility.TrTextContent( + "Number of Tiling Rules" + , "Change this to adjust of the number of tiling rules."); + + public static readonly GUIContent tilingRules = EditorGUIUtility.TrTextContent("Tiling Rules"); + + public static readonly GUIContent tilingRulesGameObject = EditorGUIUtility.TrTextContent("GameObject" + , "The GameObject for the Tile which fits this Rule."); + + public static readonly GUIContent tilingRulesCollider = EditorGUIUtility.TrTextContent("Collider" + , "The Collider Type for the Tile which fits this Rule"); + + public static readonly GUIContent tilingRulesOutput = EditorGUIUtility.TrTextContent("Output" + , "The Output for the Tile which fits this Rule. Each Output type has its own properties."); + + public static readonly GUIContent tilingRulesNoise = EditorGUIUtility.TrTextContent("Noise" + , "The Perlin noise factor when placing the Tile."); + + public static readonly GUIContent tilingRulesShuffle = EditorGUIUtility.TrTextContent("Shuffle" + , "The randomized transform given to the Tile when placing it."); + + public static readonly GUIContent tilingRulesRandomSize = EditorGUIUtility.TrTextContent("Size" + , "The number of Sprites to randomize from."); + + public static readonly GUIContent tilingRulesMinSpeed = EditorGUIUtility.TrTextContent("Min Speed" + , "The minimum speed at which the animation is played."); + + public static readonly GUIContent tilingRulesMaxSpeed = EditorGUIUtility.TrTextContent("Max Speed" + , "The maximum speed at which the animation is played."); + + public static readonly GUIContent tilingRulesAnimationSize = EditorGUIUtility.TrTextContent("Size" + , "The number of Sprites in the animation."); + + public static readonly GUIStyle extendNeighborsLightStyle = new() + { + alignment = TextAnchor.MiddleLeft, + fontStyle = FontStyle.Bold, + fontSize = 10, + normal = new GUIStyleState + { + textColor = Color.black + } + }; + + public static readonly GUIStyle extendNeighborsDarkStyle = new() + { + alignment = TextAnchor.MiddleLeft, + fontStyle = FontStyle.Bold, + fontSize = 10, + normal = new GUIStyleState + { + textColor = Color.white + } + }; + } + + /// + /// Wrapper for serializing a list of Rules + /// + [Serializable] + private class RuleTileRuleWrapper + { + /// + /// List of Rules to serialize + /// + [SerializeField] public List rules = new(); + } } -} +} \ No newline at end of file diff --git a/Editor/Unity.2D.Tilemap.Extras.Editor.asmdef b/Editor/Unity.2D.Tilemap.Extras.Editor.asmdef index 9819767..7b09399 100644 --- a/Editor/Unity.2D.Tilemap.Extras.Editor.asmdef +++ b/Editor/Unity.2D.Tilemap.Extras.Editor.asmdef @@ -1,18 +1,18 @@ { - "name": "Unity.2D.Tilemap.Extras.Editor", - "references": [ - "GUID:613783dc1674e844b87788ea74ede0f6", - "GUID:3a9781db4804a9945b9883f3a7c46d45" - ], - "optionalUnityReferences": [], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [] + "name": "Unity.2D.Tilemap.Extras.Editor", + "references": [ + "GUID:613783dc1674e844b87788ea74ede0f6", + "GUID:3a9781db4804a9945b9883f3a7c46d45" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [] } \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index 37fcb9b..d50acc5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,5 +1,8 @@ 2D Tilemap Extras copyright © 2020 Unity Technologies ApS -Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). +Licensed under the Unity Companion License for Unity-dependent +projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). -Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. +Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS +WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and +conditions. diff --git a/README.md b/README.md index e61f10e..07f821c 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,37 @@ # 2d-extras -2d-extras is a repository containing helpful reusable scripts which you can use to make your games, with a slant towards 2D. Feel free to customise the behavior of the scripts to create new tools for your use case! +2d-extras is a repository containing helpful reusable scripts which you can use to make your games, with a slant towards +2D. Feel free to customise the behavior of the scripts to create new tools for your use case! -Implemented examples using these scripts can be found in the sister repository [2d-techdemos](https://github.com/Unity-Technologies/2d-techdemos "2d-techdemos: Examples for 2d features"). +Implemented examples using these scripts can be found in the sister +repository [2d-techdemos](https://github.com/Unity-Technologies/2d-techdemos "2d-techdemos: Examples for 2d features"). All items in the repository are grouped by use for a feature and are listed below. ## How to use this -You can use this in two different ways: downloading this repository or adding it to your project's Package Manager manifest. +You can use this in two different ways: downloading this repository or adding it to your project's Package Manager +manifest. -Alternatively, you can pick and choose the scripts that you want by placing only these scripts in your project's `Assets` folder. +Alternatively, you can pick and choose the scripts that you want by placing only these scripts in your +project's `Assets` folder. ### Download #### Setup + Download or clone this repository into your project in the folder `Packages/com.unity.2d.tilemap.extras`. ### Package Manager Manifest #### Requirements + [Git](https://git-scm.com/) must be installed and added to your path. #### Setup -The following line needs to be added to your `Packages/manifest.json` file in your Unity Project under the `dependencies` section: + +The following line needs to be added to your `Packages/manifest.json` file in your Unity Project under +the `dependencies` section: ```json "com.unity.2d.tilemap.extras": "https://github.com/Unity-Technologies/2d-extras.git#master" @@ -31,7 +39,7 @@ The following line needs to be added to your `Packages/manifest.json` file in yo ### Tilemap -For use with Unity `2023.1.0f1` onwards. +For use with Unity `2023.1.0f1` onwards. Please use the `package_2022.1` branch for Unity 2022.1.* versions. @@ -43,44 +51,67 @@ Please use the `2020.3` branch for Unity 2020.1-2020.3 versions. Please use the `1.5.0-preview` tag for Unity 2019.2-2019.4 versions. -Please use the `2019.1` tag for Unity 2019.1 versions. +Please use the `2019.1` tag for Unity 2019.1 versions. -Please use the `2018.3` branch or the `2018.3` tag for Unity 2018.3-2018.4 versions. +Please use the `2018.3` branch or the `2018.3` tag for Unity 2018.3-2018.4 versions. -Please use the `2018.2` branch or the `2018.2` tag for Unity 2018.2 versions. +Please use the `2018.2` branch or the `2018.2` tag for Unity 2018.2 versions. Please use the `2017` branch or the `2017` tag for earlier versions of Unity (from 2017.2 and up). ##### Brushes -- **Coordinate**: This Brush displays the cell coordinates it is targeting in the SceneView. Use this as an example to create brushes which have extra visualization features when painting onto a Tilemap. -- **Line**: This Brush helps draw lines of Tiles onto a Tilemap. The first click of the mouse sets the starting point of the line and the second click sets the ending point of the line and draws the lines of Tiles. Use this as an example to modify brush painting behaviour to making painting quicker with less actions. -- **Random**: This Brush helps to place random Tiles onto a Tilemap. Use this as an example to create brushes which store specific data per brush and to make brushes which randomize behaviour. -- **Prefab**: This Brush instances and places the containing Prefab onto the targeted location and parents the instanced object to the paint target. Use this as an example to quickly place an assorted type of GameObjects onto structured locations. -- **PrefabRandom**: This Brush instances and places a randomly selected Prefabs onto the targeted location and parents the instanced object to the paint target. Use this as an example to quickly place an assorted type of GameObjects onto structured locations. -- **GameObject**: This Brush instances, places and manipulates GameObjects onto the scene. Use this as an example to create brushes which targets objects other than tiles for manipulation. +- **Coordinate**: This Brush displays the cell coordinates it is targeting in the SceneView. Use this as an example to + create brushes which have extra visualization features when painting onto a Tilemap. +- **Line**: This Brush helps draw lines of Tiles onto a Tilemap. The first click of the mouse sets the starting point of + the line and the second click sets the ending point of the line and draws the lines of Tiles. Use this as an example + to modify brush painting behaviour to making painting quicker with less actions. +- **Random**: This Brush helps to place random Tiles onto a Tilemap. Use this as an example to create brushes which + store specific data per brush and to make brushes which randomize behaviour. +- **Prefab**: This Brush instances and places the containing Prefab onto the targeted location and parents the instanced + object to the paint target. Use this as an example to quickly place an assorted type of GameObjects onto structured + locations. +- **PrefabRandom**: This Brush instances and places a randomly selected Prefabs onto the targeted location and parents + the instanced object to the paint target. Use this as an example to quickly place an assorted type of GameObjects onto + structured locations. +- **GameObject**: This Brush instances, places and manipulates GameObjects onto the scene. Use this as an example to + create brushes which targets objects other than tiles for manipulation. - **TintBrush**: Brush to edit Tilemap per-cell tint colors. -- **TintBrushSmooth**: Advanced tint brush for interpolated tint color per-cell. Requires the use of custom shader (see TintedTilemap.shader) and helper component TileTextureGenerator. -- **Group**: This Brush helps to pick Tiles which are grouped together by position. Gaps can be set to identify if Tiles belong to a Group. Limits can be set to ensure that an over-sized Group will not be picked. Use this as an example to create brushes that have the ability to choose and pick whichever Tiles it is interested in. +- **TintBrushSmooth**: Advanced tint brush for interpolated tint color per-cell. Requires the use of custom shader (see + TintedTilemap.shader) and helper component TileTextureGenerator. +- **Group**: This Brush helps to pick Tiles which are grouped together by position. Gaps can be set to identify if Tiles + belong to a Group. Limits can be set to ensure that an over-sized Group will not be picked. Use this as an example to + create brushes that have the ability to choose and pick whichever Tiles it is interested in. ##### Tiles - **Animated**: Animated Tiles are tiles which run through and display a list of sprites in sequence. -- **Pipeline**: Pipeline Tiles are tiles which take into consideration its orthogonal neighboring tiles and displays a sprite depending on whether the neighboring tile is the same tile. -- **Random**: Random Tiles are tiles which pseudo-randomly pick a sprite from a given list of sprites and a target location, and displays that sprite. -- **Terrain**: Terrain Tiles, similar to Pipeline Tiles, are tiles which take into consideration its orthogonal and diagonal neighboring tiles and displays a sprite depending on whether the neighboring tile is the same tile. +- **Pipeline**: Pipeline Tiles are tiles which take into consideration its orthogonal neighboring tiles and displays a + sprite depending on whether the neighboring tile is the same tile. +- **Random**: Random Tiles are tiles which pseudo-randomly pick a sprite from a given list of sprites and a target + location, and displays that sprite. +- **Terrain**: Terrain Tiles, similar to Pipeline Tiles, are tiles which take into consideration its orthogonal and + diagonal neighboring tiles and displays a sprite depending on whether the neighboring tile is the same tile. - **RuleTile**: Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. -- **Hexagonal Rule Tile**: A Rule Tile for use with Hexagonal Grids. Enable Flat Top for Flat Top Hexagonal Grids and disable for Pointed Top Hexagonal Grids. +- **Hexagonal Rule Tile**: A Rule Tile for use with Hexagonal Grids. Enable Flat Top for Flat Top Hexagonal Grids and + disable for Pointed Top Hexagonal Grids. - **Isometric Rule Tile**: A Rule Tile for use with Isometric Grids. -- **RuleOverrideTile**: Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to provide specialised behaviour while keeping most of the Rules originally set in the Rule Tile. -- **Weighted Random**: Weighted Random Tiles are tiles which randomly pick a sprite from a given list of sprites and a target location, and displays that sprite. The sprites can be weighted with a value to change its probability of appearing. +- **RuleOverrideTile**: Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to + provide specialised behaviour while keeping most of the Rules originally set in the Rule Tile. +- **Weighted Random**: Weighted Random Tiles are tiles which randomly pick a sprite from a given list of sprites and a + target location, and displays that sprite. The sprites can be weighted with a value to change its probability of + appearing. ##### Other - **GridInformation**: A simple MonoBehaviour that stores and provides information based on Grid positions and keywords. -- **Custom Rules for RuleTile**: This helps to create new custom Rules for the Rule Tile. Check the [Wiki](https://github.com/Unity-Technologies/2d-extras/wiki) or this great [video](https://youtu.be/FwOxLkJTXag) for more information on how to use this! +- **Custom Rules for RuleTile**: This helps to create new custom Rules for the Rule Tile. Check + the [Wiki](https://github.com/Unity-Technologies/2d-extras/wiki) or this great [video](https://youtu.be/FwOxLkJTXag) + for more information on how to use this! [![How to make Custom Rule Tiles in Unity Video](http://img.youtube.com/vi/FwOxLkJTXag/0.jpg)](http://www.youtube.com/watch?v=FwOxLkJTXag "How to make Custom Rule Tiles in Unity") ### Contribution Notice -From 7 January 2019 until 12 February 2020, all contributions are licensed under the Unity Companion License for Unity-dependent projects (see https://unity3d.com/legal/licenses/unity_companion_license). + +From 7 January 2019 until 12 February 2020, all contributions are licensed under the Unity Companion License for +Unity-dependent projects (see https://unity3d.com/legal/licenses/unity_companion_license). diff --git a/Runtime/GridInformation/GridInformation.cs b/Runtime/GridInformation/GridInformation.cs index d6f6373..23f86e1 100644 --- a/Runtime/GridInformation/GridInformation.cs +++ b/Runtime/GridInformation/GridInformation.cs @@ -19,97 +19,50 @@ internal enum GridInformationType /// A simple MonoBehaviour that stores and provides information based on Grid positions and keywords. /// [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GridInformation.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GridInformation.html")] [AddComponentMenu("Tilemap/Grid Information")] public class GridInformation : MonoBehaviour, ISerializationCallbackReceiver { - [Serializable] - internal struct GridInformationValue - { - public GridInformationType type; - public object data; - } - - [Serializable] - internal struct GridInformationKey : IEquatable - { - public Vector3Int position; - public String name; - - public bool Equals(GridInformationKey key) - { - return position == key.position && name == key.name; - } - - public override int GetHashCode() - { - return HashCode.Combine(position.GetHashCode(), name.GetHashCode()); - } - } + [SerializeField] [HideInInspector] private List m_PositionIntKeys = new(); - private Dictionary m_PositionProperties = new Dictionary(); - internal Dictionary PositionProperties - { - get { return m_PositionProperties; } - } + [SerializeField] [HideInInspector] private List m_PositionIntValues = new(); - [SerializeField] - [HideInInspector] - private List m_PositionIntKeys = new List(); + [SerializeField] [HideInInspector] private List m_PositionStringKeys = new(); - [SerializeField] - [HideInInspector] - private List m_PositionIntValues = new List(); + [SerializeField] [HideInInspector] private List m_PositionStringValues = new(); - [SerializeField] - [HideInInspector] - private List m_PositionStringKeys = new List(); + [SerializeField] [HideInInspector] private List m_PositionFloatKeys = new(); - [SerializeField] - [HideInInspector] - private List m_PositionStringValues = new List(); + [SerializeField] [HideInInspector] private List m_PositionFloatValues = new(); - [SerializeField] - [HideInInspector] - private List m_PositionFloatKeys = new List(); + [SerializeField] [HideInInspector] private List m_PositionDoubleKeys = new(); - [SerializeField] - [HideInInspector] - private List m_PositionFloatValues = new List(); + [SerializeField] [HideInInspector] private List m_PositionDoubleValues = new(); - [SerializeField] - [HideInInspector] - private List m_PositionDoubleKeys = new List(); + [SerializeField] [HideInInspector] private List m_PositionObjectKeys = new(); - [SerializeField] - [HideInInspector] - private List m_PositionDoubleValues = new List(); + [SerializeField] [HideInInspector] private List m_PositionObjectValues = new(); - [SerializeField] - [HideInInspector] - private List m_PositionObjectKeys = new List(); + [SerializeField] [HideInInspector] private List m_PositionColorKeys = new(); - [SerializeField] - [HideInInspector] - private List m_PositionObjectValues = new List(); + [SerializeField] [HideInInspector] private List m_PositionColorValues = new(); - [SerializeField] - [HideInInspector] - private List m_PositionColorKeys = new List(); + internal Dictionary PositionProperties { get; } = new(); - [SerializeField] - [HideInInspector] - private List m_PositionColorValues = new List(); + /// + /// Clears all information stored + /// + public virtual void Reset() + { + PositionProperties.Clear(); + } /// /// Callback before serializing this GridInformation /// void ISerializationCallbackReceiver.OnBeforeSerialize() { - Grid grid = GetComponentInParent(); - if (grid == null) - return; - m_PositionIntKeys.Clear(); m_PositionIntValues.Clear(); m_PositionStringKeys.Clear(); @@ -123,8 +76,7 @@ void ISerializationCallbackReceiver.OnBeforeSerialize() m_PositionColorKeys.Clear(); m_PositionColorValues.Clear(); - foreach (var kvp in m_PositionProperties) - { + foreach (var kvp in PositionProperties) switch (kvp.Value.type) { case GridInformationType.Integer: @@ -133,7 +85,7 @@ void ISerializationCallbackReceiver.OnBeforeSerialize() break; case GridInformationType.String: m_PositionStringKeys.Add(kvp.Key); - m_PositionStringValues.Add(kvp.Value.data as String); + m_PositionStringValues.Add(kvp.Value.data as string); break; case GridInformationType.Float: m_PositionFloatKeys.Add(kvp.Key); @@ -152,7 +104,6 @@ void ISerializationCallbackReceiver.OnBeforeSerialize() m_PositionObjectValues.Add(kvp.Value.data as Object); break; } - } } /// @@ -160,48 +111,53 @@ void ISerializationCallbackReceiver.OnBeforeSerialize() /// void ISerializationCallbackReceiver.OnAfterDeserialize() { - m_PositionProperties.Clear(); - for (int i = 0; i != Math.Min(m_PositionIntKeys.Count, m_PositionIntValues.Count); i++) + PositionProperties.Clear(); + for (var i = 0; i != Math.Min(m_PositionIntKeys.Count, m_PositionIntValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Integer; positionValue.data = m_PositionIntValues[i]; - m_PositionProperties.Add(m_PositionIntKeys[i], positionValue); + PositionProperties.Add(m_PositionIntKeys[i], positionValue); } - for (int i = 0; i != Math.Min(m_PositionStringKeys.Count, m_PositionStringValues.Count); i++) + + for (var i = 0; i != Math.Min(m_PositionStringKeys.Count, m_PositionStringValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.String; positionValue.data = m_PositionStringValues[i]; - m_PositionProperties.Add(m_PositionStringKeys[i], positionValue); + PositionProperties.Add(m_PositionStringKeys[i], positionValue); } - for (int i = 0; i != Math.Min(m_PositionFloatKeys.Count, m_PositionFloatValues.Count); i++) + + for (var i = 0; i != Math.Min(m_PositionFloatKeys.Count, m_PositionFloatValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Float; positionValue.data = m_PositionFloatValues[i]; - m_PositionProperties.Add(m_PositionFloatKeys[i], positionValue); + PositionProperties.Add(m_PositionFloatKeys[i], positionValue); } - for (int i = 0; i != Math.Min(m_PositionDoubleKeys.Count, m_PositionDoubleValues.Count); i++) + + for (var i = 0; i != Math.Min(m_PositionDoubleKeys.Count, m_PositionDoubleValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Double; positionValue.data = m_PositionDoubleValues[i]; - m_PositionProperties.Add(m_PositionDoubleKeys[i], positionValue); + PositionProperties.Add(m_PositionDoubleKeys[i], positionValue); } - for (int i = 0; i != Math.Min(m_PositionObjectKeys.Count, m_PositionObjectValues.Count); i++) + + for (var i = 0; i != Math.Min(m_PositionObjectKeys.Count, m_PositionObjectValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.UnityObject; positionValue.data = m_PositionObjectValues[i]; - m_PositionProperties.Add(m_PositionObjectKeys[i], positionValue); + PositionProperties.Add(m_PositionObjectKeys[i], positionValue); } - for (int i = 0; i != Math.Min(m_PositionColorKeys.Count, m_PositionColorValues.Count); i++) + + for (var i = 0; i != Math.Min(m_PositionColorKeys.Count, m_PositionColorValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Color; positionValue.data = m_PositionColorValues[i]; - m_PositionProperties.Add(m_PositionColorKeys[i], positionValue); + PositionProperties.Add(m_PositionColorKeys[i], positionValue); } } @@ -214,7 +170,7 @@ void ISerializationCallbackReceiver.OnAfterDeserialize() /// Type of the information to set /// Whether the information was set /// This is not implemented as only concrete Types are supported - public bool SetPositionProperty(Vector3Int position, String name, T positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, T positionProperty) { throw new NotImplementedException("Storing this type is not accepted in GridInformation"); } @@ -226,7 +182,7 @@ public bool SetPositionProperty(Vector3Int position, String name, T positionP /// Property name to store information for /// The information to be stored at the position /// Whether the information was set - public bool SetPositionProperty(Vector3Int position, String name, int positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, int positionProperty) { return SetPositionProperty(position, name, GridInformationType.Integer, positionProperty); } @@ -238,7 +194,7 @@ public bool SetPositionProperty(Vector3Int position, String name, int positionPr /// Property name to store information for /// The information to be stored at the position /// Whether the information was set - public bool SetPositionProperty(Vector3Int position, String name, string positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, string positionProperty) { return SetPositionProperty(position, name, GridInformationType.String, positionProperty); } @@ -250,7 +206,7 @@ public bool SetPositionProperty(Vector3Int position, String name, string positio /// Property name to store information for /// The information to be stored at the position /// Whether the information was set - public bool SetPositionProperty(Vector3Int position, String name, float positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, float positionProperty) { return SetPositionProperty(position, name, GridInformationType.Float, positionProperty); } @@ -262,7 +218,7 @@ public bool SetPositionProperty(Vector3Int position, String name, float position /// Property name to store information for /// The information to be stored at the position /// Whether the information was set - public bool SetPositionProperty(Vector3Int position, String name, double positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, double positionProperty) { return SetPositionProperty(position, name, GridInformationType.Double, positionProperty); } @@ -274,7 +230,7 @@ public bool SetPositionProperty(Vector3Int position, String name, double positio /// Property name to store information for /// The information to be stored at the position /// Whether the information was set - public bool SetPositionProperty(Vector3Int position, String name, UnityEngine.Object positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, Object positionProperty) { return SetPositionProperty(position, name, GridInformationType.UnityObject, positionProperty); } @@ -286,14 +242,15 @@ public bool SetPositionProperty(Vector3Int position, String name, UnityEngine.Ob /// Property name to store information for /// The information to be stored at the position /// Whether the information was set - public bool SetPositionProperty(Vector3Int position, String name, Color positionProperty) + public bool SetPositionProperty(Vector3Int position, string name, Color positionProperty) { return SetPositionProperty(position, name, GridInformationType.Color, positionProperty); } - private bool SetPositionProperty(Vector3Int position, String name, GridInformationType dataType, System.Object positionProperty) + private bool SetPositionProperty(Vector3Int position, string name, GridInformationType dataType, + object positionProperty) { - Grid grid = GetComponentInParent(); + var grid = GetComponentInParent(); if (grid != null && positionProperty != null) { GridInformationKey positionKey; @@ -304,9 +261,10 @@ private bool SetPositionProperty(Vector3Int position, String name, GridInformati positionValue.type = dataType; positionValue.data = positionProperty; - m_PositionProperties[positionKey] = positionValue; + PositionProperties[positionKey] = positionValue; return true; } + return false; } @@ -319,19 +277,20 @@ private bool SetPositionProperty(Vector3Int position, String name, GridInformati /// Type of the information to retrieve /// The information stored at the position /// Thrown when information to be retrieved is not the given Type - public T GetPositionProperty(Vector3Int position, String name, T defaultValue) where T : UnityEngine.Object + public T GetPositionProperty(Vector3Int position, string name, T defaultValue) where T : Object { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; - if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) + if (PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.UnityObject) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return positionValue.data as T; } + return defaultValue; } @@ -343,19 +302,20 @@ public T GetPositionProperty(Vector3Int position, String name, T defaultValue /// Default int if property does not exist at the given position /// The int stored at the position /// Thrown when information to be retrieved is not a int - public int GetPositionProperty(Vector3Int position, String name, int defaultValue) + public int GetPositionProperty(Vector3Int position, string name, int defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; - if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) + if (PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Integer) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (int)positionValue.data; } + return defaultValue; } @@ -367,19 +327,20 @@ public int GetPositionProperty(Vector3Int position, String name, int defaultValu /// Default string if property does not exist at the given position /// The string stored at the position /// Thrown when information to be retrieved is not a string - public string GetPositionProperty(Vector3Int position, String name, string defaultValue) + public string GetPositionProperty(Vector3Int position, string name, string defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; - if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) + if (PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.String) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (string)positionValue.data; } + return defaultValue; } @@ -391,19 +352,20 @@ public string GetPositionProperty(Vector3Int position, String name, string defau /// Default float if property does not exist at the given position /// The float stored at the position /// Thrown when information to be retrieved is not a float - public float GetPositionProperty(Vector3Int position, String name, float defaultValue) + public float GetPositionProperty(Vector3Int position, string name, float defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; - if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) + if (PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Float) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (float)positionValue.data; } + return defaultValue; } @@ -415,19 +377,20 @@ public float GetPositionProperty(Vector3Int position, String name, float default /// Default double if property does not exist at the given position /// The double stored at the position /// Thrown when information to be retrieved is not a double - public double GetPositionProperty(Vector3Int position, String name, double defaultValue) + public double GetPositionProperty(Vector3Int position, string name, double defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; - if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) + if (PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Double) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (double)positionValue.data; } + return defaultValue; } @@ -439,19 +402,20 @@ public double GetPositionProperty(Vector3Int position, String name, double defau /// Default color if property does not exist at the given position /// The color stored at the position /// Thrown when information to be retrieved is not a Color - public Color GetPositionProperty(Vector3Int position, String name, Color defaultValue) + public Color GetPositionProperty(Vector3Int position, string name, Color defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; - if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) + if (PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Color) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (Color)positionValue.data; } + return defaultValue; } @@ -461,20 +425,12 @@ public Color GetPositionProperty(Vector3Int position, String name, Color default /// Position to erase /// Property name to erase /// Whether the information was erased - public bool ErasePositionProperty(Vector3Int position, String name) + public bool ErasePositionProperty(Vector3Int position, string name) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; - return m_PositionProperties.Remove(positionKey); - } - - /// - /// Clears all information stored - /// - public virtual void Reset() - { - m_PositionProperties.Clear(); + return PositionProperties.Remove(positionKey); } /// @@ -484,7 +440,32 @@ public virtual void Reset() /// An array of all positions with the property name public Vector3Int[] GetAllPositions(string propertyName) { - return m_PositionProperties.Keys.ToList().FindAll(x => x.name == propertyName).Select(x => x.position).ToArray(); + return PositionProperties.Keys.ToList().FindAll(x => x.name == propertyName).Select(x => x.position) + .ToArray(); + } + + [Serializable] + internal struct GridInformationValue + { + public GridInformationType type; + public object data; + } + + [Serializable] + internal struct GridInformationKey : IEquatable + { + public Vector3Int position; + public string name; + + public bool Equals(GridInformationKey key) + { + return position == key.position && name == key.name; + } + + public override int GetHashCode() + { + return HashCode.Combine(position.GetHashCode(), name.GetHashCode()); + } } } } diff --git a/Runtime/Tiles/AnimatedTile/AnimatedTile.cs b/Runtime/Tiles/AnimatedTile/AnimatedTile.cs index 0710c2b..5a0024a 100644 --- a/Runtime/Tiles/AnimatedTile/AnimatedTile.cs +++ b/Runtime/Tiles/AnimatedTile/AnimatedTile.cs @@ -1,52 +1,59 @@ -using System; +using System; namespace UnityEngine.Tilemaps { /// - /// Animated Tiles are tiles which run through and display a list of sprites in sequence. + /// Animated Tiles are tiles which run through and display a list of sprites in sequence. /// [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/AnimatedTile.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/AnimatedTile.html")] public class AnimatedTile : TileBase { /// - /// The List of Sprites set for the Animated Tile. - /// This will be played in sequence. + /// The List of Sprites set for the Animated Tile. + /// This will be played in sequence. /// public Sprite[] m_AnimatedSprites; + /// - /// The minimum possible speed at which the Animation of the Tile will be played. - /// A speed value will be randomly chosen between the minimum and maximum speed. + /// The minimum possible speed at which the Animation of the Tile will be played. + /// A speed value will be randomly chosen between the minimum and maximum speed. /// public float m_MinSpeed = 1f; + /// - /// The maximum possible speed at which the Animation of the Tile will be played. - /// A speed value will be randomly chosen between the minimum and maximum speed. + /// The maximum possible speed at which the Animation of the Tile will be played. + /// A speed value will be randomly chosen between the minimum and maximum speed. /// public float m_MaxSpeed = 1f; + /// - /// The starting time of this Animated Tile. - /// This allows you to start the Animation from time in the list of Animated Sprites depending on the - /// Tilemap's Animation Frame Rate. + /// The starting time of this Animated Tile. + /// This allows you to start the Animation from time in the list of Animated Sprites depending on the + /// Tilemap's Animation Frame Rate. /// public float m_AnimationStartTime; + /// - /// The starting frame of this Animated Tile. - /// This allows you to start the Animation from a particular Sprite in the list of Animated Sprites. - /// If this is set, this overrides m_AnimationStartTime. + /// The starting frame of this Animated Tile. + /// This allows you to start the Animation from a particular Sprite in the list of Animated Sprites. + /// If this is set, this overrides m_AnimationStartTime. /// - public int m_AnimationStartFrame = 0; + public int m_AnimationStartFrame; + /// - /// The Collider Shape generated by the Tile. + /// The Collider Shape generated by the Tile. /// public Tile.ColliderType m_TileColliderType; + /// - /// Flags for controlling the Tile Animation. + /// Flags for controlling the Tile Animation. /// public TileAnimationFlags m_TileAnimationFlags; - + /// - /// Retrieves any tile rendering data from the scripted tile. + /// Retrieves any tile rendering data from the scripted tile. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -63,13 +70,14 @@ public override void GetTileData(Vector3Int position, ITilemap tilemap, ref Tile } /// - /// Retrieves any tile animation data from the scripted tile. + /// Retrieves any tile animation data from the scripted tile. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. /// Data to run an animation on the tile. /// Whether the call was successful. - public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, ref TileAnimationData tileAnimationData) + public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, + ref TileAnimationData tileAnimationData) { if (m_AnimatedSprites.Length > 0) { @@ -81,11 +89,14 @@ public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, { var tilemapComponent = tilemap.GetComponent(); if (tilemapComponent != null && tilemapComponent.animationFrameRate > 0) - tileAnimationData.animationStartTime = (m_AnimationStartFrame - 1) / tilemapComponent.animationFrameRate; + tileAnimationData.animationStartTime = + (m_AnimationStartFrame - 1) / tilemapComponent.animationFrameRate; } + return true; } + return false; } } -} +} \ No newline at end of file diff --git a/Runtime/Tiles/HexagonalRuleTile/HexagonalRuleTile.cs b/Runtime/Tiles/HexagonalRuleTile/HexagonalRuleTile.cs index 52726e4..6465213 100644 --- a/Runtime/Tiles/HexagonalRuleTile/HexagonalRuleTile.cs +++ b/Runtime/Tiles/HexagonalRuleTile/HexagonalRuleTile.cs @@ -3,80 +3,88 @@ namespace UnityEngine { /// - /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. - /// This is templated to accept a Neighbor Rule Class for Custom Rules. - /// Use this for Hexagonal Grids. + /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. + /// This is templated to accept a Neighbor Rule Class for Custom Rules. + /// Use this for Hexagonal Grids. /// /// Neighbor Rule Class for Custom Rules public class HexagonalRuleTile : HexagonalRuleTile { /// - /// Returns the Neighbor Rule Class type for this Rule Tile. + /// Returns the Neighbor Rule Class type for this Rule Tile. /// public sealed override Type m_NeighborType => typeof(T); } /// - /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. - /// Use this for Hexagonal Grids. + /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. + /// Use this for Hexagonal Grids. /// [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleTile.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleTile.html")] public class HexagonalRuleTile : RuleTile { - /// - /// Angle in which the HexagonalRuleTile is rotated by for matching in Degrees. - /// - public override int m_RotationAngle => 60; - - private static float[] m_CosAngleArr1 = { + private static float[] m_CosAngleArr1 = + { Mathf.Cos(0 * Mathf.Deg2Rad), Mathf.Cos(-60 * Mathf.Deg2Rad), Mathf.Cos(-120 * Mathf.Deg2Rad), Mathf.Cos(-180 * Mathf.Deg2Rad), Mathf.Cos(-240 * Mathf.Deg2Rad), - Mathf.Cos(-300 * Mathf.Deg2Rad), + Mathf.Cos(-300 * Mathf.Deg2Rad) }; - private static float[] m_SinAngleArr1 = { + + private static float[] m_SinAngleArr1 = + { Mathf.Sin(0 * Mathf.Deg2Rad), Mathf.Sin(-60 * Mathf.Deg2Rad), Mathf.Sin(-120 * Mathf.Deg2Rad), Mathf.Sin(-180 * Mathf.Deg2Rad), Mathf.Sin(-240 * Mathf.Deg2Rad), - Mathf.Sin(-300 * Mathf.Deg2Rad), + Mathf.Sin(-300 * Mathf.Deg2Rad) }; - private static float[] m_CosAngleArr2 = { + + private static float[] m_CosAngleArr2 = + { Mathf.Cos(0 * Mathf.Deg2Rad), Mathf.Cos(60 * Mathf.Deg2Rad), Mathf.Cos(120 * Mathf.Deg2Rad), Mathf.Cos(180 * Mathf.Deg2Rad), Mathf.Cos(240 * Mathf.Deg2Rad), - Mathf.Cos(300 * Mathf.Deg2Rad), + Mathf.Cos(300 * Mathf.Deg2Rad) }; - private static float[] m_SinAngleArr2 = { + + private static float[] m_SinAngleArr2 = + { Mathf.Sin(0 * Mathf.Deg2Rad), Mathf.Sin(60 * Mathf.Deg2Rad), Mathf.Sin(120 * Mathf.Deg2Rad), Mathf.Sin(180 * Mathf.Deg2Rad), Mathf.Sin(240 * Mathf.Deg2Rad), - Mathf.Sin(300 * Mathf.Deg2Rad), + Mathf.Sin(300 * Mathf.Deg2Rad) }; + private static float m_TilemapToWorldYScale = Mathf.Pow(1 - Mathf.Pow(0.5f, 2f), 0.5f); + /// - /// Whether this is a flat top Hexagonal Tile + /// Whether this is a flat top Hexagonal Tile /// [DontOverride] public bool m_FlatTop; - static float m_TilemapToWorldYScale = Mathf.Pow(1 - Mathf.Pow(0.5f, 2f), 0.5f); + /// + /// Angle in which the HexagonalRuleTile is rotated by for matching in Degrees. + /// + public override int m_RotationAngle => 60; /// - /// Converts a Tilemap Position to World Position. + /// Converts a Tilemap Position to World Position. /// /// Tilemap Position to convert. /// World Position. public static Vector3 TilemapPositionToWorldPosition(Vector3Int tilemapPosition) { - Vector3 worldPosition = new Vector3(tilemapPosition.x, tilemapPosition.y); + var worldPosition = new Vector3(tilemapPosition.x, tilemapPosition.y); if (tilemapPosition.y % 2 != 0) worldPosition.x += 0.5f; worldPosition.y *= m_TilemapToWorldYScale; @@ -84,14 +92,14 @@ public static Vector3 TilemapPositionToWorldPosition(Vector3Int tilemapPosition) } /// - /// Converts a World Position to Tilemap Position. + /// Converts a World Position to Tilemap Position. /// /// World Position to convert. /// Tilemap Position. public static Vector3Int WorldPositionToTilemapPosition(Vector3 worldPosition) { worldPosition.y /= m_TilemapToWorldYScale; - Vector3Int tilemapPosition = new Vector3Int(); + var tilemapPosition = new Vector3Int(); tilemapPosition.y = Mathf.RoundToInt(worldPosition.y); if (tilemapPosition.y % 2 != 0) tilemapPosition.x = Mathf.RoundToInt(worldPosition.x - 0.5f); @@ -101,14 +109,14 @@ public static Vector3Int WorldPositionToTilemapPosition(Vector3 worldPosition) } /// - /// Get the offset for the given position with the given offset. + /// Get the offset for the given position with the given offset. /// /// Position to offset. /// Offset for the position. /// The offset position. public override Vector3Int GetOffsetPosition(Vector3Int position, Vector3Int offset) { - Vector3Int offsetPosition = position + offset; + var offsetPosition = position + offset; if (offset.y % 2 != 0 && position.y % 2 != 0) offsetPosition.x += 1; @@ -117,7 +125,7 @@ public override Vector3Int GetOffsetPosition(Vector3Int position, Vector3Int off } /// - /// Get the reversed offset for the given position with the given offset. + /// Get the reversed offset for the given position with the given offset. /// /// Position to offset. /// Offset for the position. @@ -128,7 +136,7 @@ public override Vector3Int GetOffsetPositionReverse(Vector3Int position, Vector3 } /// - /// Gets a rotated position given its original position and the rotation in degrees. + /// Gets a rotated position given its original position and the rotation in degrees. /// /// Original position of Tile. /// Rotation in degrees. @@ -137,31 +145,28 @@ public override Vector3Int GetRotatedPosition(Vector3Int position, int rotation) { if (rotation != 0) { - Vector3 worldPosition = TilemapPositionToWorldPosition(position); + var worldPosition = TilemapPositionToWorldPosition(position); - int index = rotation / 60; + var index = rotation / 60; if (m_FlatTop) - { worldPosition = new Vector3( worldPosition.x * m_CosAngleArr2[index] - worldPosition.y * m_SinAngleArr2[index], worldPosition.x * m_SinAngleArr2[index] + worldPosition.y * m_CosAngleArr2[index] ); - } else - { worldPosition = new Vector3( worldPosition.x * m_CosAngleArr1[index] - worldPosition.y * m_SinAngleArr1[index], worldPosition.x * m_SinAngleArr1[index] + worldPosition.y * m_CosAngleArr1[index] ); - } position = WorldPositionToTilemapPosition(worldPosition); } + return position; } /// - /// Gets a mirrored position given its original position and the mirroring axii. + /// Gets a mirrored position given its original position and the mirroring axii. /// /// Original position of Tile. /// Mirror in the X Axis. @@ -171,7 +176,7 @@ public override Vector3Int GetMirroredPosition(Vector3Int position, bool mirrorX { if (mirrorX || mirrorY) { - Vector3 worldPosition = TilemapPositionToWorldPosition(position); + var worldPosition = TilemapPositionToWorldPosition(position); if (m_FlatTop) { @@ -190,7 +195,8 @@ public override Vector3Int GetMirroredPosition(Vector3Int position, bool mirrorX position = WorldPositionToTilemapPosition(worldPosition); } + return position; } } -} +} \ No newline at end of file diff --git a/Runtime/Tiles/IsometricRuleTile/IsometricRuleTile.cs b/Runtime/Tiles/IsometricRuleTile/IsometricRuleTile.cs index 08c4041..eb65c1d 100644 --- a/Runtime/Tiles/IsometricRuleTile/IsometricRuleTile.cs +++ b/Runtime/Tiles/IsometricRuleTile/IsometricRuleTile.cs @@ -1,29 +1,30 @@ -using System; +using System; namespace UnityEngine { /// - /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. - /// This is templated to accept a Neighbor Rule Class for Custom Rules. - /// Use this for Isometric Grids. + /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. + /// This is templated to accept a Neighbor Rule Class for Custom Rules. + /// Use this for Isometric Grids. /// /// Neighbor Rule Class for Custom Rules public class IsometricRuleTile : IsometricRuleTile { /// - /// Returns the Neighbor Rule Class type for this Rule Tile. + /// Returns the Neighbor Rule Class type for this Rule Tile. /// public sealed override Type m_NeighborType => typeof(T); } /// - /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. - /// Use this for Isometric Grids. + /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. + /// Use this for Isometric Grids. /// [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleTile.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleTile.html")] public class IsometricRuleTile : RuleTile { // This has no differences with the RuleTile } -} +} \ No newline at end of file diff --git a/Runtime/Tiles/RuleOverrideTile/AdvancedRuleOverrideTile.cs b/Runtime/Tiles/RuleOverrideTile/AdvancedRuleOverrideTile.cs index b1bbaf7..eaf4fa6 100644 --- a/Runtime/Tiles/RuleOverrideTile/AdvancedRuleOverrideTile.cs +++ b/Runtime/Tiles/RuleOverrideTile/AdvancedRuleOverrideTile.cs @@ -1,20 +1,41 @@ -using System; +using System; using System.Collections.Generic; using UnityEngine.Scripting.APIUpdating; namespace UnityEngine.Tilemaps { /// - /// Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to provide specialised behaviour while keeping most of the Rules originally set in the Rule Tile. + /// Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to provide specialised + /// behaviour while keeping most of the Rules originally set in the Rule Tile. /// [MovedFrom(true, "UnityEngine")] [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleOverrideTile.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleOverrideTile.html")] public class AdvancedRuleOverrideTile : RuleOverrideTile { + /// + /// The Default Sprite set when creating a new Rule override. + /// + public Sprite m_DefaultSprite; + + /// + /// The Default GameObject set when creating a new Rule override. + /// + public GameObject m_DefaultGameObject; + + /// + /// The Default Collider Type set when creating a new Rule override. + /// + public Tile.ColliderType m_DefaultColliderType = Tile.ColliderType.Sprite; + + /// + /// A list of TilingRule Overrides + /// + public List m_OverrideTilingRules = new(); /// - /// Gets the overriding TilingRuleOutput of a given TilingRule. + /// Gets the overriding TilingRuleOutput of a given TilingRule. /// /// The original TilingRule that is overridden public RuleTile.TilingRuleOutput this[RuleTile.TilingRule originalRule] @@ -29,14 +50,13 @@ public RuleTile.TilingRuleOutput this[RuleTile.TilingRule originalRule] } set { - for (int i = m_OverrideTilingRules.Count - 1; i >= 0; i--) - { + for (var i = m_OverrideTilingRules.Count - 1; i >= 0; i--) if (m_OverrideTilingRules[i].m_Id == originalRule.m_Id) { m_OverrideTilingRules.RemoveAt(i); break; } - } + if (value != null) { var json = JsonUtility.ToJson(value); @@ -47,73 +67,54 @@ public RuleTile.TilingRuleOutput this[RuleTile.TilingRule originalRule] } /// - /// The Default Sprite set when creating a new Rule override. - /// - public Sprite m_DefaultSprite; - /// - /// The Default GameObject set when creating a new Rule override. - /// - public GameObject m_DefaultGameObject; - /// - /// The Default Collider Type set when creating a new Rule override. - /// - public Tile.ColliderType m_DefaultColliderType = Tile.ColliderType.Sprite; - - /// - /// A list of TilingRule Overrides - /// - public List m_OverrideTilingRules = new List(); - - /// - /// Applies overrides to this + /// Applies overrides to this /// /// A list of overrides to apply /// The input overrides list is not valid public void ApplyOverrides(IList> overrides) { if (overrides == null) - throw new System.ArgumentNullException("overrides"); + throw new ArgumentNullException("overrides"); - for (int i = 0; i < overrides.Count; i++) + for (var i = 0; i < overrides.Count; i++) this[overrides[i].Key] = overrides[i].Value; } /// - /// Gets overrides for this + /// Gets overrides for this /// /// A list of overrides to fill /// Returns the number of valid overrides for Rules /// The input overrides list is not valid - public void GetOverrides(List> overrides, ref int validCount) + public void GetOverrides(List> overrides, + ref int validCount) { if (overrides == null) - throw new System.ArgumentNullException("overrides"); + throw new ArgumentNullException("overrides"); overrides.Clear(); if (m_Tile) - { foreach (var originalRule in m_Tile.m_TilingRules) { - RuleTile.TilingRuleOutput overrideRule = this[originalRule]; - overrides.Add(new KeyValuePair(originalRule, overrideRule)); + var overrideRule = this[originalRule]; + overrides.Add( + new KeyValuePair(originalRule, overrideRule)); } - } validCount = overrides.Count; foreach (var overrideRule in m_OverrideTilingRules) - { if (!overrides.Exists(o => o.Key.m_Id == overrideRule.m_Id)) { - var originalRule = new RuleTile.TilingRule() { m_Id = overrideRule.m_Id }; - overrides.Add(new KeyValuePair(originalRule, overrideRule)); + var originalRule = new RuleTile.TilingRule { m_Id = overrideRule.m_Id }; + overrides.Add( + new KeyValuePair(originalRule, overrideRule)); } - } } /// - /// Updates the Rules with the Overrides set for this AdvancedRuleOverrideTile + /// Updates the Rules with the Overrides set for this AdvancedRuleOverrideTile /// public override void Override() { @@ -131,11 +132,8 @@ public override void Override() foreach (var rule in tile.m_TilingRules) { var overrideRule = this[rule]; - if (overrideRule != null) - { - JsonUtility.FromJsonOverwrite(JsonUtility.ToJson(overrideRule), rule); - } + if (overrideRule != null) JsonUtility.FromJsonOverwrite(JsonUtility.ToJson(overrideRule), rule); } } } -} +} \ No newline at end of file diff --git a/Runtime/Tiles/RuleOverrideTile/RuleOverrideTile.cs b/Runtime/Tiles/RuleOverrideTile/RuleOverrideTile.cs index 6bbca64..b6178c7 100644 --- a/Runtime/Tiles/RuleOverrideTile/RuleOverrideTile.cs +++ b/Runtime/Tiles/RuleOverrideTile/RuleOverrideTile.cs @@ -1,8 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using UnityEngine.Scripting.APIUpdating; - #if UNITY_EDITOR using UnityEditor; #endif @@ -10,61 +9,47 @@ namespace UnityEngine.Tilemaps { /// - /// Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to provide specialised behaviour while keeping most of the Rules originally set in the Rule Tile. + /// Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to provide specialised + /// behaviour while keeping most of the Rules originally set in the Rule Tile. /// [MovedFrom(true, "UnityEngine")] [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleOverrideTile.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleOverrideTile.html")] public class RuleOverrideTile : TileBase { + /// + /// The RuleTile to override + /// + public RuleTile m_Tile; /// - /// A data structure storing the Sprite overriding the original RuleTile Sprite + /// A list of Sprite Overrides /// - [Serializable] - public class TileSpritePair - { - /// - /// Original Sprite from the original RuleTile. - /// - public Sprite m_OriginalSprite; - /// - /// Overriding Sprite for the Original Sprite. - /// - public Sprite m_OverrideSprite; - } + public List m_Sprites = new(); /// - /// A data structure storing the GameObject overriding the original RuleTile GameObject + /// A list of GameObject Overrides /// - [Serializable] - public class TileGameObjectPair - { - /// - /// Original GameObject from the original RuleTile. - /// - public GameObject m_OriginalGameObject; - /// - /// Overriding GameObject for the Original Sprite. - /// - public GameObject m_OverrideGameObject; - } + public List m_GameObjects = new(); + + /// + /// Returns the Rule Tile for retrieving TileData + /// + [HideInInspector] public RuleTile m_InstanceTile; /// - /// Gets the overriding Sprite of a given Sprite. + /// Gets the overriding Sprite of a given Sprite. /// /// The original Sprite that is overridden public Sprite this[Sprite originalSprite] { get { - foreach (TileSpritePair spritePair in m_Sprites) - { + foreach (var spritePair in m_Sprites) if (spritePair.m_OriginalSprite == originalSprite) - { return spritePair.m_OverrideSprite; - } - } + return null; } set @@ -75,100 +60,90 @@ public Sprite this[Sprite originalSprite] } else { - foreach (TileSpritePair spritePair in m_Sprites) - { + foreach (var spritePair in m_Sprites) if (spritePair.m_OriginalSprite == originalSprite) { spritePair.m_OverrideSprite = value; return; } - } - m_Sprites.Add(new TileSpritePair() + + m_Sprites.Add(new TileSpritePair { m_OriginalSprite = originalSprite, - m_OverrideSprite = value, + m_OverrideSprite = value }); } } } /// - /// Gets the overriding GameObject of a given GameObject. + /// Gets the overriding GameObject of a given GameObject. /// /// The original GameObject that is overridden public GameObject this[GameObject originalGameObject] { get { - foreach (TileGameObjectPair gameObjectPair in m_GameObjects) - { + foreach (var gameObjectPair in m_GameObjects) if (gameObjectPair.m_OriginalGameObject == originalGameObject) - { return gameObjectPair.m_OverrideGameObject; - } - } + return null; } set { if (value == null) { - m_GameObjects = m_GameObjects.Where(gameObjectPair => gameObjectPair.m_OriginalGameObject != originalGameObject).ToList(); + m_GameObjects = m_GameObjects + .Where(gameObjectPair => gameObjectPair.m_OriginalGameObject != originalGameObject).ToList(); } else { - foreach (TileGameObjectPair gameObjectPair in m_GameObjects) - { + foreach (var gameObjectPair in m_GameObjects) if (gameObjectPair.m_OriginalGameObject == originalGameObject) { gameObjectPair.m_OverrideGameObject = value; return; } - } - m_GameObjects.Add(new TileGameObjectPair() + + m_GameObjects.Add(new TileGameObjectPair { m_OriginalGameObject = originalGameObject, - m_OverrideGameObject = value, + m_OverrideGameObject = value }); } } } /// - /// The RuleTile to override - /// - public RuleTile m_Tile; - /// - /// A list of Sprite Overrides + /// Callback when the tile is enabled /// - public List m_Sprites = new List(); - /// - /// A list of GameObject Overrides - /// - public List m_GameObjects = new List(); + public void OnEnable() + { + if (m_Tile == null) + return; - /// - /// Returns the Rule Tile for retrieving TileData - /// - [HideInInspector] public RuleTile m_InstanceTile; + if (m_InstanceTile == null) + Override(); + } private void CreateInstanceTile() { var t = m_Tile.GetType(); - RuleTile instanceTile = CreateInstance(t) as RuleTile; + var instanceTile = CreateInstance(t) as RuleTile; instanceTile.hideFlags = HideFlags.NotEditable; instanceTile.name = m_Tile.name + " (Override)"; m_InstanceTile = instanceTile; #if UNITY_EDITOR - if(AssetDatabase.Contains(this)) + if (AssetDatabase.Contains(this)) AssetDatabase.AddObjectToAsset(instanceTile, this); EditorUtility.SetDirty(this); -#endif +#endif } - + /// - /// Applies overrides to this + /// Applies overrides to this /// /// A list of overrides to apply /// The input overrides list is not valid @@ -177,12 +152,12 @@ public void ApplyOverrides(IList> overrides) if (overrides == null) throw new ArgumentNullException("overrides"); - for (int i = 0; i < overrides.Count; i++) + for (var i = 0; i < overrides.Count; i++) this[overrides[i].Key] = overrides[i].Value; } /// - /// Applies overrides to this + /// Applies overrides to this /// /// A list of overrides to apply /// The input overrides list is not valid @@ -191,12 +166,12 @@ public void ApplyOverrides(IList> overrides if (overrides == null) throw new ArgumentNullException("overrides"); - for (int i = 0; i < overrides.Count; i++) + for (var i = 0; i < overrides.Count; i++) this[overrides[i].Key] = overrides[i].Value; } /// - /// Gets overrides for this + /// Gets overrides for this /// /// A list of overrides to fill /// Returns the number of valid overrides for Sprites @@ -208,17 +183,17 @@ public void GetOverrides(List> overrides, ref int v overrides.Clear(); - List originalSprites = new List(); + var originalSprites = new List(); if (m_Tile) { if (m_Tile.m_DefaultSprite) originalSprites.Add(m_Tile.m_DefaultSprite); - foreach (RuleTile.TilingRule rule in m_Tile.m_TilingRules) - foreach (Sprite sprite in rule.m_Sprites) - if (sprite && !originalSprites.Contains(sprite)) - originalSprites.Add(sprite); + foreach (var rule in m_Tile.m_TilingRules) + foreach (var sprite in rule.m_Sprites) + if (sprite && !originalSprites.Contains(sprite)) + originalSprites.Add(sprite); } validCount = originalSprites.Count; @@ -227,12 +202,12 @@ public void GetOverrides(List> overrides, ref int v if (!originalSprites.Contains(pair.m_OriginalSprite)) originalSprites.Add(pair.m_OriginalSprite); - foreach (Sprite sprite in originalSprites) + foreach (var sprite in originalSprites) overrides.Add(new KeyValuePair(sprite, this[sprite])); } /// - /// Gets overrides for this + /// Gets overrides for this /// /// A list of overrides to fill /// Returns the number of valid overrides for GameObjects @@ -244,14 +219,14 @@ public void GetOverrides(List> overrides, r overrides.Clear(); - List originalGameObjects = new List(); + var originalGameObjects = new List(); if (m_Tile) { if (m_Tile.m_DefaultGameObject) originalGameObjects.Add(m_Tile.m_DefaultGameObject); - foreach (RuleTile.TilingRule rule in m_Tile.m_TilingRules) + foreach (var rule in m_Tile.m_TilingRules) if (rule.m_GameObject && !originalGameObjects.Contains(rule.m_GameObject)) originalGameObjects.Add(rule.m_GameObject); } @@ -262,12 +237,12 @@ public void GetOverrides(List> overrides, r if (!originalGameObjects.Contains(pair.m_OriginalGameObject)) originalGameObjects.Add(pair.m_OriginalGameObject); - foreach (GameObject gameObject in originalGameObjects) + foreach (var gameObject in originalGameObjects) overrides.Add(new KeyValuePair(gameObject, this[gameObject])); } /// - /// Updates the Rules with the Overrides set for this RuleOverrideTile + /// Updates the Rules with the Overrides set for this RuleOverrideTile /// public virtual void Override() { @@ -276,7 +251,7 @@ public virtual void Override() if (!m_InstanceTile) CreateInstanceTile(); - + PrepareOverride(); var tile = m_InstanceTile; @@ -286,9 +261,9 @@ public virtual void Override() foreach (var rule in tile.m_TilingRules) { - for (int i = 0; i < rule.m_Sprites.Length; i++) + for (var i = 0; i < rule.m_Sprites.Length; i++) { - Sprite sprite = rule.m_Sprites[i]; + var sprite = rule.m_Sprites[i]; rule.m_Sprites[i] = this[sprite] ?? sprite; } @@ -297,13 +272,13 @@ public virtual void Override() } /// - /// Prepares the Overrides set for this RuleOverrideTile + /// Prepares the Overrides set for this RuleOverrideTile /// public void PrepareOverride() { // Create clone of instanceTile to keep data from collections being overridden by JsonUtility var tempTile = Instantiate(m_InstanceTile); - + var customData = m_InstanceTile.GetCustomFields(true) .ToDictionary(field => field, field => field.GetValue(tempTile)); @@ -314,13 +289,14 @@ public void PrepareOverride() } /// - /// Retrieves any tile animation data from the scripted tile. + /// Retrieves any tile animation data from the scripted tile. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. /// Data to run an animation on the tile. /// Whether the call was successful. - public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, ref TileAnimationData tileAnimationData) + public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, + ref TileAnimationData tileAnimationData) { if (!m_InstanceTile) return false; @@ -328,7 +304,7 @@ public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, } /// - /// Retrieves any tile rendering data from the scripted tile. + /// Retrieves any tile rendering data from the scripted tile. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -341,7 +317,7 @@ public override void GetTileData(Vector3Int position, ITilemap tilemap, ref Tile } /// - /// This method is called when the tile is refreshed. + /// This method is called when the tile is refreshed. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -353,7 +329,7 @@ public override void RefreshTile(Vector3Int position, ITilemap tilemap) } /// - /// StartUp is called on the first frame of the running Scene. + /// StartUp is called on the first frame of the running Scene. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -367,15 +343,37 @@ public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject g } /// - /// Callback when the tile is enabled + /// A data structure storing the Sprite overriding the original RuleTile Sprite /// - public void OnEnable() + [Serializable] + public class TileSpritePair { - if (m_Tile == null) - return; + /// + /// Original Sprite from the original RuleTile. + /// + public Sprite m_OriginalSprite; - if (m_InstanceTile == null) - Override(); + /// + /// Overriding Sprite for the Original Sprite. + /// + public Sprite m_OverrideSprite; + } + + /// + /// A data structure storing the GameObject overriding the original RuleTile GameObject + /// + [Serializable] + public class TileGameObjectPair + { + /// + /// Original GameObject from the original RuleTile. + /// + public GameObject m_OriginalGameObject; + + /// + /// Overriding GameObject for the Original Sprite. + /// + public GameObject m_OverrideGameObject; } } -} +} \ No newline at end of file diff --git a/Runtime/Tiles/RuleTile/RuleTile.cs b/Runtime/Tiles/RuleTile/RuleTile.cs index cec1017..0120173 100644 --- a/Runtime/Tiles/RuleTile/RuleTile.cs +++ b/Runtime/Tiles/RuleTile/RuleTile.cs @@ -1,282 +1,77 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Collections.Generic; -using UnityEngine.Tilemaps; using UnityEngine.Serialization; +using UnityEngine.Tilemaps; namespace UnityEngine { /// - /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. - /// This is templated to accept a Neighbor Rule Class for Custom Rules. + /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. + /// This is templated to accept a Neighbor Rule Class for Custom Rules. /// /// Neighbor Rule Class for Custom Rules public class RuleTile : RuleTile { /// - /// Returns the Neighbor Rule Class type for this Rule Tile. + /// Returns the Neighbor Rule Class type for this Rule Tile. /// public sealed override Type m_NeighborType => typeof(T); } /// - /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. + /// Generic visual tile for creating different tilesets like terrain, pipeline, random or animated tiles. /// [Serializable] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleTile.html")] + [HelpURL( + "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleTile.html")] public class RuleTile : TileBase { - /// - /// Returns the default Neighbor Rule Class type. - /// - public virtual Type m_NeighborType => typeof(TilingRuleOutput.Neighbor); + private static Dictionary, HashSet>> + m_CacheTilemapsNeighborPositions = new(); + + private static TileBase[] m_AllocatedUsedTileArr = Array.Empty(); /// - /// The Default Sprite set when creating a new Rule. + /// The Default Sprite set when creating a new Rule. /// public Sprite m_DefaultSprite; - /// - /// The Default GameObject set when creating a new Rule. - /// - public GameObject m_DefaultGameObject; - /// - /// The Default Collider Type set when creating a new Rule. - /// - public Tile.ColliderType m_DefaultColliderType = Tile.ColliderType.Sprite; /// - /// Angle in which the RuleTile is rotated by for matching in Degrees. + /// The Default GameObject set when creating a new Rule. /// - public virtual int m_RotationAngle => 90; + public GameObject m_DefaultGameObject; /// - /// Number of rotations the RuleTile can be rotated by for matching. + /// The Default Collider Type set when creating a new Rule. /// - public int m_RotationCount => 360 / m_RotationAngle; + public Tile.ColliderType m_DefaultColliderType = Tile.ColliderType.Sprite; /// - /// The data structure holding the Rule information for matching Rule Tiles with - /// its neighbors. + /// A list of Tiling Rules for the Rule Tile. /// - [Serializable] - public class TilingRuleOutput - { - /// - /// Id for this Rule. - /// - public int m_Id; - /// - /// The output Sprites for this Rule. - /// - public Sprite[] m_Sprites = new Sprite[1]; - /// - /// The output GameObject for this Rule. - /// - public GameObject m_GameObject; - /// - /// The output minimum Animation Speed for this Rule. - /// - [FormerlySerializedAs("m_AnimationSpeed")] - public float m_MinAnimationSpeed = 1f; - /// - /// The output maximum Animation Speed for this Rule. - /// - [FormerlySerializedAs("m_AnimationSpeed")] - public float m_MaxAnimationSpeed = 1f; - /// - /// The perlin scale factor for this Rule. - /// - public float m_PerlinScale = 0.5f; - /// - /// The output type for this Rule. - /// - public OutputSprite m_Output = OutputSprite.Single; - /// - /// The output Collider Type for this Rule. - /// - public Tile.ColliderType m_ColliderType = Tile.ColliderType.Sprite; - /// - /// The randomized transform output for this Rule. - /// - public Transform m_RandomTransform; - - /// - /// The enumeration for matching Neighbors when matching Rule Tiles - /// - public class Neighbor - { - /// - /// The Rule Tile will check if the contents of the cell in that direction is an instance of this Rule Tile. - /// If not, the rule will fail. - /// - public const int This = 1; - /// - /// The Rule Tile will check if the contents of the cell in that direction is not an instance of this Rule Tile. - /// If it is, the rule will fail. - /// - public const int NotThis = 2; - } - - /// - /// The enumeration for the transform rule used when matching Rule Tiles. - /// - public enum Transform - { - /// - /// The Rule Tile will match Tiles exactly as laid out in its neighbors. - /// - Fixed, - /// - /// The Rule Tile will rotate and match its neighbors. - /// - Rotated, - /// - /// The Rule Tile will mirror in the X axis and match its neighbors. - /// - MirrorX, - /// - /// The Rule Tile will mirror in the Y axis and match its neighbors. - /// - MirrorY, - /// - /// The Rule Tile will mirror in the X or Y axis and match its neighbors. - /// - MirrorXY, - /// - /// The Rule Tile will rotate and mirror in the X and match its neighbors. - /// - RotatedMirror - } + [HideInInspector] public List m_TilingRules = new(); - /// - /// The Output for the Tile which fits this Rule. - /// - public enum OutputSprite - { - /// - /// A Single Sprite will be output. - /// - Single, - /// - /// A Random Sprite will be output. - /// - Random, - /// - /// A Sprite Animation will be output. - /// - Animation - } - } + private HashSet m_NeighborPositions = new(); /// - /// The data structure holding the Rule information for matching Rule Tiles with - /// its neighbors. + /// Returns the default Neighbor Rule Class type. /// - [Serializable] - public class TilingRule : TilingRuleOutput - { - /// - /// The matching Rule conditions for each of its neighboring Tiles. - /// - public List m_Neighbors = new List(); - /// - /// * Preset this list to RuleTile backward compatible, but not support for HexagonalRuleTile backward compatible. - /// - public List m_NeighborPositions = new List() - { - new Vector3Int(-1, 1, 0), - new Vector3Int(0, 1, 0), - new Vector3Int(1, 1, 0), - new Vector3Int(-1, 0, 0), - new Vector3Int(1, 0, 0), - new Vector3Int(-1, -1, 0), - new Vector3Int(0, -1, 0), - new Vector3Int(1, -1, 0), - }; - /// - /// The transform matching Rule for this Rule. - /// - public Transform m_RuleTransform; - - /// - /// This clones a copy of the TilingRule. - /// - /// A copy of the TilingRule. - public TilingRule Clone() - { - TilingRule rule = new TilingRule - { - m_Neighbors = new List(m_Neighbors), - m_NeighborPositions = new List(m_NeighborPositions), - m_RuleTransform = m_RuleTransform, - m_Sprites = new Sprite[m_Sprites.Length], - m_GameObject = m_GameObject, - m_MinAnimationSpeed = m_MinAnimationSpeed, - m_MaxAnimationSpeed = m_MaxAnimationSpeed, - m_PerlinScale = m_PerlinScale, - m_Output = m_Output, - m_ColliderType = m_ColliderType, - m_RandomTransform = m_RandomTransform, - }; - Array.Copy(m_Sprites, rule.m_Sprites, m_Sprites.Length); - return rule; - } - - /// - /// Returns all neighbors of this Tile as a dictionary - /// - /// A dictionary of neighbors for this Tile - public Dictionary GetNeighbors() - { - Dictionary dict = new Dictionary(); - - for (int i = 0; i < m_Neighbors.Count && i < m_NeighborPositions.Count; i++) - dict.Add(m_NeighborPositions[i], m_Neighbors[i]); - - return dict; - } - - /// - /// Applies the values from the given dictionary as this Tile's neighbors - /// - /// Dictionary to apply values from - public void ApplyNeighbors(Dictionary dict) - { - m_NeighborPositions = dict.Keys.ToList(); - m_Neighbors = dict.Values.ToList(); - } - - /// - /// Gets the cell bounds of the TilingRule. - /// - /// Returns the cell bounds of the TilingRule. - public BoundsInt GetBounds() - { - BoundsInt bounds = new BoundsInt(Vector3Int.zero, Vector3Int.one); - foreach (var neighbor in GetNeighbors()) - { - bounds.xMin = Mathf.Min(bounds.xMin, neighbor.Key.x); - bounds.yMin = Mathf.Min(bounds.yMin, neighbor.Key.y); - bounds.xMax = Mathf.Max(bounds.xMax, neighbor.Key.x + 1); - bounds.yMax = Mathf.Max(bounds.yMax, neighbor.Key.y + 1); - } - return bounds; - } - } + public virtual Type m_NeighborType => typeof(TilingRuleOutput.Neighbor); /// - /// Attribute which marks a property which cannot be overridden by a RuleOverrideTile + /// Angle in which the RuleTile is rotated by for matching in Degrees. /// - public class DontOverride : Attribute { } + public virtual int m_RotationAngle => 90; /// - /// A list of Tiling Rules for the Rule Tile. + /// Number of rotations the RuleTile can be rotated by for matching. /// - [HideInInspector] public List m_TilingRules = new List(); + public int m_RotationCount => 360 / m_RotationAngle; /// - /// Returns a set of neighboring positions for this RuleTile + /// Returns a set of neighboring positions for this RuleTile /// public HashSet neighborPositions { @@ -289,65 +84,59 @@ public HashSet neighborPositions } } - private HashSet m_NeighborPositions = new HashSet(); - /// - /// Updates the neighboring positions of this RuleTile + /// Updates the neighboring positions of this RuleTile /// public void UpdateNeighborPositions() { m_CacheTilemapsNeighborPositions.Clear(); - HashSet positions = m_NeighborPositions; + var positions = m_NeighborPositions; positions.Clear(); - foreach (TilingRule rule in m_TilingRules) + foreach (var rule in m_TilingRules) + foreach (var neighbor in rule.GetNeighbors()) { - foreach (var neighbor in rule.GetNeighbors()) - { - Vector3Int position = neighbor.Key; - positions.Add(position); + var position = neighbor.Key; + positions.Add(position); - // Check rule against rotations of 0, 90, 180, 270 - if (rule.m_RuleTransform == TilingRuleOutput.Transform.Rotated) - { - for (int angle = m_RotationAngle; angle < 360; angle += m_RotationAngle) - { - positions.Add(GetRotatedPosition(position, angle)); - } - } - // Check rule against x-axis, y-axis mirror - else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorXY) - { - positions.Add(GetMirroredPosition(position, true, true)); - positions.Add(GetMirroredPosition(position, true, false)); - positions.Add(GetMirroredPosition(position, false, true)); - } - // Check rule against x-axis mirror - else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorX) - { - positions.Add(GetMirroredPosition(position, true, false)); - } - // Check rule against y-axis mirror - else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorY) - { - positions.Add(GetMirroredPosition(position, false, true)); - } - else if (rule.m_RuleTransform == TilingRuleOutput.Transform.RotatedMirror) + // Check rule against rotations of 0, 90, 180, 270 + if (rule.m_RuleTransform == TilingRuleOutput.Transform.Rotated) + { + for (var angle = m_RotationAngle; angle < 360; angle += m_RotationAngle) + positions.Add(GetRotatedPosition(position, angle)); + } + // Check rule against x-axis, y-axis mirror + else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorXY) + { + positions.Add(GetMirroredPosition(position, true, true)); + positions.Add(GetMirroredPosition(position, true, false)); + positions.Add(GetMirroredPosition(position, false, true)); + } + // Check rule against x-axis mirror + else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorX) + { + positions.Add(GetMirroredPosition(position, true, false)); + } + // Check rule against y-axis mirror + else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorY) + { + positions.Add(GetMirroredPosition(position, false, true)); + } + else if (rule.m_RuleTransform == TilingRuleOutput.Transform.RotatedMirror) + { + var mirroredPosition = GetMirroredPosition(position, true, false); + for (var angle = m_RotationAngle; angle < 360; angle += m_RotationAngle) { - var mirroredPosition = GetMirroredPosition(position, true, false); - for (int angle = m_RotationAngle; angle < 360; angle += m_RotationAngle) - { - positions.Add(GetRotatedPosition(position, angle)); - positions.Add(GetRotatedPosition(mirroredPosition, angle)); - } + positions.Add(GetRotatedPosition(position, angle)); + positions.Add(GetRotatedPosition(mirroredPosition, angle)); } } } } /// - /// StartUp is called on the first frame of the running Scene. + /// StartUp is called on the first frame of the running Scene. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -357,40 +146,45 @@ public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject i { if (instantiatedGameObject != null) { - Tilemap tmpMap = tilemap.GetComponent(); - Matrix4x4 orientMatrix = tmpMap.orientationMatrix; + var tmpMap = tilemap.GetComponent(); + var orientMatrix = tmpMap.orientationMatrix; var iden = Matrix4x4.identity; - Vector3 gameObjectTranslation = new Vector3(); - Quaternion gameObjectRotation = new Quaternion(); - Vector3 gameObjectScale = new Vector3(); + var gameObjectTranslation = new Vector3(); + var gameObjectRotation = new Quaternion(); + var gameObjectScale = new Vector3(); - bool ruleMatched = false; - Matrix4x4 transform = iden; - foreach (TilingRule rule in m_TilingRules) - { + var ruleMatched = false; + var transform = iden; + foreach (var rule in m_TilingRules) if (RuleMatches(rule, position, tilemap, ref transform)) { transform = orientMatrix * transform; // Converts the tile's translation, rotation, & scale matrix to values to be used by the instantiated GameObject gameObjectTranslation = new Vector3(transform.m03, transform.m13, transform.m23); - gameObjectRotation = Quaternion.LookRotation(new Vector3(transform.m02, transform.m12, transform.m22), new Vector3(transform.m01, transform.m11, transform.m21)); + gameObjectRotation = Quaternion.LookRotation( + new Vector3(transform.m02, transform.m12, transform.m22), + new Vector3(transform.m01, transform.m11, transform.m21)); gameObjectScale = transform.lossyScale; ruleMatched = true; break; } - } + if (!ruleMatched) { // Fallback to just using the orientMatrix for the translation, rotation, & scale values. gameObjectTranslation = new Vector3(orientMatrix.m03, orientMatrix.m13, orientMatrix.m23); - gameObjectRotation = Quaternion.LookRotation(new Vector3(orientMatrix.m02, orientMatrix.m12, orientMatrix.m22), new Vector3(orientMatrix.m01, orientMatrix.m11, orientMatrix.m21)); + gameObjectRotation = Quaternion.LookRotation( + new Vector3(orientMatrix.m02, orientMatrix.m12, orientMatrix.m22), + new Vector3(orientMatrix.m01, orientMatrix.m11, orientMatrix.m21)); gameObjectScale = orientMatrix.lossyScale; } - instantiatedGameObject.transform.localPosition = gameObjectTranslation + tmpMap.CellToLocalInterpolated(position + tmpMap.tileAnchor); + instantiatedGameObject.transform.localPosition = gameObjectTranslation + + tmpMap.CellToLocalInterpolated(position + + tmpMap.tileAnchor); instantiatedGameObject.transform.localRotation = gameObjectRotation; instantiatedGameObject.transform.localScale = gameObjectScale; } @@ -399,7 +193,7 @@ public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject i } /// - /// Retrieves any tile rendering data from the scripted tile. + /// Retrieves any tile rendering data from the scripted tile. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -414,9 +208,8 @@ public override void GetTileData(Vector3Int position, ITilemap tilemap, ref Tile tileData.flags = TileFlags.LockTransform; tileData.transform = iden; - Matrix4x4 transform = iden; - foreach (TilingRule rule in m_TilingRules) - { + var transform = iden; + foreach (var rule in m_TilingRules) if (RuleMatches(rule, position, tilemap, ref transform)) { switch (rule.m_Output) @@ -426,22 +219,25 @@ public override void GetTileData(Vector3Int position, ITilemap tilemap, ref Tile tileData.sprite = rule.m_Sprites[0]; break; case TilingRuleOutput.OutputSprite.Random: - int index = Mathf.Clamp(Mathf.FloorToInt(GetPerlinValue(position, rule.m_PerlinScale, 100000f) * rule.m_Sprites.Length), 0, rule.m_Sprites.Length - 1); + var index = Mathf.Clamp( + Mathf.FloorToInt(GetPerlinValue(position, rule.m_PerlinScale, 100000f) * + rule.m_Sprites.Length), 0, rule.m_Sprites.Length - 1); tileData.sprite = rule.m_Sprites[index]; if (rule.m_RandomTransform != TilingRuleOutput.Transform.Fixed) - transform = ApplyRandomTransform(rule.m_RandomTransform, transform, rule.m_PerlinScale, position); + transform = ApplyRandomTransform(rule.m_RandomTransform, transform, rule.m_PerlinScale, + position); break; } + tileData.transform = transform; tileData.gameObject = rule.m_GameObject; tileData.colliderType = rule.m_ColliderType; break; } - } } /// - /// Returns a Perlin Noise value based on the given inputs. + /// Returns a Perlin Noise value based on the given inputs. /// /// Position of the Tile on the Tilemap. /// The Perlin Scale factor of the Tile. @@ -452,16 +248,14 @@ public static float GetPerlinValue(Vector3Int position, float scale, float offse return Mathf.PerlinNoise((position.x + offset) * scale, (position.y + offset) * scale); } - static Dictionary, HashSet>> m_CacheTilemapsNeighborPositions = new Dictionary, HashSet>>(); - static TileBase[] m_AllocatedUsedTileArr = Array.Empty(); - - static bool IsTilemapUsedTilesChange(Tilemap tilemap, out KeyValuePair, HashSet> hashSet) + private static bool IsTilemapUsedTilesChange(Tilemap tilemap, + out KeyValuePair, HashSet> hashSet) { if (!m_CacheTilemapsNeighborPositions.TryGetValue(tilemap, out hashSet)) return true; var oldUsedTiles = hashSet.Key; - int newUsedTilesCount = tilemap.GetUsedTilesCount(); + var newUsedTilesCount = tilemap.GetUsedTilesCount(); if (newUsedTilesCount != oldUsedTiles.Count) return true; @@ -469,9 +263,9 @@ static bool IsTilemapUsedTilesChange(Tilemap tilemap, out KeyValuePair, HashSet> CachingTilemapNeighborPositions(Tilemap tilemap) + private static KeyValuePair, HashSet> CachingTilemapNeighborPositions( + Tilemap tilemap) { - int usedTileCount = tilemap.GetUsedTilesCount(); - HashSet usedTiles = new HashSet(); - HashSet neighborPositions = new HashSet(); + var usedTileCount = tilemap.GetUsedTilesCount(); + var usedTiles = new HashSet(); + var neighborPositions = new HashSet(); if (m_AllocatedUsedTileArr.Length < usedTileCount) Array.Resize(ref m_AllocatedUsedTileArr, usedTileCount); tilemap.GetUsedTilesNonAlloc(m_AllocatedUsedTileArr); - for (int i = 0; i < usedTileCount; i++) + for (var i = 0; i < usedTileCount; i++) { - TileBase tile = m_AllocatedUsedTileArr[i]; + var tile = m_AllocatedUsedTileArr[i]; usedTiles.Add(tile); RuleTile ruleTile = null; @@ -502,7 +297,7 @@ static KeyValuePair, HashSet> CachingTilemapNeighb ruleTile = ot.m_Tile; if (ruleTile) - foreach (Vector3Int neighborPosition in ruleTile.neighborPositions) + foreach (var neighborPosition in ruleTile.neighborPositions) neighborPositions.Add(neighborPosition); } @@ -511,19 +306,16 @@ static KeyValuePair, HashSet> CachingTilemapNeighb return value; } - static bool NeedRelease() + private static bool NeedRelease() { foreach (var keypair in m_CacheTilemapsNeighborPositions) - { if (keypair.Key == null) - { return true; - } - } + return false; } - - static void ReleaseDestroyedTilemapCacheData() + + private static void ReleaseDestroyedTilemapCacheData() { if (!NeedRelease()) return; @@ -531,44 +323,42 @@ static void ReleaseDestroyedTilemapCacheData() var hasCleared = false; var keys = m_CacheTilemapsNeighborPositions.Keys.ToArray(); foreach (var key in keys) - { if (key == null && m_CacheTilemapsNeighborPositions.Remove(key)) hasCleared = true; - } + if (hasCleared) - { // TrimExcess - m_CacheTilemapsNeighborPositions = new Dictionary, HashSet>>(m_CacheTilemapsNeighborPositions); - } + m_CacheTilemapsNeighborPositions = + new Dictionary, HashSet>>( + m_CacheTilemapsNeighborPositions); } /// - /// Retrieves any tile animation data from the scripted tile. + /// Retrieves any tile animation data from the scripted tile. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. /// Data to run an animation on the tile. /// Whether the call was successful. - public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, ref TileAnimationData tileAnimationData) + public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, + ref TileAnimationData tileAnimationData) { - Matrix4x4 transform = Matrix4x4.identity; - foreach (TilingRule rule in m_TilingRules) - { + var transform = Matrix4x4.identity; + foreach (var rule in m_TilingRules) if (rule.m_Output == TilingRuleOutput.OutputSprite.Animation) - { if (RuleMatches(rule, position, tilemap, ref transform)) { tileAnimationData.animatedSprites = rule.m_Sprites; - tileAnimationData.animationSpeed = Random.Range( rule.m_MinAnimationSpeed, rule.m_MaxAnimationSpeed); + tileAnimationData.animationSpeed = + Random.Range(rule.m_MinAnimationSpeed, rule.m_MaxAnimationSpeed); return true; } - } - } + return false; } /// - /// This method is called when the tile is refreshed. + /// This method is called when the tile is refreshed. /// /// Position of the Tile on the Tilemap. /// The Tilemap the tile is present on. @@ -576,7 +366,7 @@ public override void RefreshTile(Vector3Int position, ITilemap tilemap) { base.RefreshTile(position, tilemap); - Tilemap baseTilemap = tilemap.GetComponent(); + var baseTilemap = tilemap.GetComponent(); ReleaseDestroyedTilemapCacheData(); // Prevent memory leak @@ -584,10 +374,10 @@ public override void RefreshTile(Vector3Int position, ITilemap tilemap) neighborPositionsSet = CachingTilemapNeighborPositions(baseTilemap); var neighborPositionsRuleTile = neighborPositionsSet.Value; - foreach (Vector3Int offset in neighborPositionsRuleTile) + foreach (var offset in neighborPositionsRuleTile) { - Vector3Int offsetPosition = GetOffsetPositionReverse(position, offset); - TileBase tile = tilemap.GetTile(offsetPosition); + var offsetPosition = GetOffsetPositionReverse(position, offset); + var tile = tilemap.GetTile(offsetPosition); RuleTile ruleTile = null; if (tile is RuleTile rt) @@ -602,7 +392,7 @@ public override void RefreshTile(Vector3Int position, ITilemap tilemap) } /// - /// Does a Rule Match given a Tiling Rule and neighboring Tiles. + /// Does a Rule Match given a Tiling Rule and neighboring Tiles. /// /// The Tiling Rule to match with. /// Position of the Tile on the Tilemap. @@ -620,14 +410,12 @@ public virtual bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap t // Check rule against rotations of 0, 90, 180, 270 if (rule.m_RuleTransform == TilingRuleOutput.Transform.Rotated) { - for (int angle = m_RotationAngle; angle < 360; angle += m_RotationAngle) - { + for (var angle = m_RotationAngle; angle < 360; angle += m_RotationAngle) if (RuleMatches(rule, position, tilemap, angle)) { transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), Vector3.one); return true; } - } } // Check rule against x-axis, y-axis mirror else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorXY) @@ -637,11 +425,13 @@ public virtual bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap t transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1f, -1f, 1f)); return true; } + if (RuleMatches(rule, position, tilemap, true, false)) { transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1f, 1f, 1f)); return true; } + if (RuleMatches(rule, position, tilemap, false, true)) { transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, -1f, 1f)); @@ -669,64 +459,76 @@ public virtual bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap t // Check rule against x-axis mirror with rotations of 0, 90, 180, 270 else if (rule.m_RuleTransform == TilingRuleOutput.Transform.RotatedMirror) { - for (int angle = 0; angle < 360; angle += m_RotationAngle) + for (var angle = 0; angle < 360; angle += m_RotationAngle) { if (angle != 0 && RuleMatches(rule, position, tilemap, angle)) { transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), Vector3.one); return true; } + if (RuleMatches(rule, position, tilemap, angle, true)) { - transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), new Vector3(-1f, 1f, 1f)); + transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), + new Vector3(-1f, 1f, 1f)); return true; } } } + return false; } /// - /// Returns a random transform matrix given the random transform rule. + /// Returns a random transform matrix given the random transform rule. /// /// Random transform rule. /// The original transform matrix. /// The Perlin Scale factor of the Tile. /// Position of the Tile on the Tilemap. /// A random transform matrix. - public virtual Matrix4x4 ApplyRandomTransform(TilingRuleOutput.Transform type, Matrix4x4 original, float perlinScale, Vector3Int position) + public virtual Matrix4x4 ApplyRandomTransform(TilingRuleOutput.Transform type, Matrix4x4 original, + float perlinScale, Vector3Int position) { - float perlin = GetPerlinValue(position, perlinScale, 200000f); + var perlin = GetPerlinValue(position, perlinScale, 200000f); switch (type) { case TilingRuleOutput.Transform.MirrorXY: - return original * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(Math.Abs(perlin - 0.5) > 0.25 ? 1f : -1f, perlin < 0.5 ? 1f : -1f, 1f)); + return original * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, + new Vector3(Math.Abs(perlin - 0.5) > 0.25 ? 1f : -1f, perlin < 0.5 ? 1f : -1f, 1f)); case TilingRuleOutput.Transform.MirrorX: - return original * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(perlin < 0.5 ? 1f : -1f, 1f, 1f)); + return original * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, + new Vector3(perlin < 0.5 ? 1f : -1f, 1f, 1f)); case TilingRuleOutput.Transform.MirrorY: - return original * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, perlin < 0.5 ? 1f : -1f, 1f)); + return original * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, + new Vector3(1f, perlin < 0.5 ? 1f : -1f, 1f)); case TilingRuleOutput.Transform.Rotated: { - var angle = Mathf.Clamp(Mathf.FloorToInt(perlin * m_RotationCount), 0, m_RotationCount - 1) * m_RotationAngle; + var angle = Mathf.Clamp(Mathf.FloorToInt(perlin * m_RotationCount), 0, m_RotationCount - 1) * + m_RotationAngle; return Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), Vector3.one); } case TilingRuleOutput.Transform.RotatedMirror: { - var angle = Mathf.Clamp(Mathf.FloorToInt(perlin * m_RotationCount), 0, m_RotationCount - 1) * m_RotationAngle; - return Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), new Vector3(perlin < 0.5 ? 1f : -1f, 1f, 1f)); + var angle = Mathf.Clamp(Mathf.FloorToInt(perlin * m_RotationCount), 0, m_RotationCount - 1) * + m_RotationAngle; + return Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), + new Vector3(perlin < 0.5 ? 1f : -1f, 1f, 1f)); } } + return original; } /// - /// Returns custom fields for this RuleTile + /// Returns custom fields for this RuleTile /// /// Whether override fields are returned /// Custom fields for this RuleTile public FieldInfo[] GetCustomFields(bool isOverrideInstance) { - return this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + return GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | + BindingFlags.NonPublic) .Where(field => typeof(RuleTile).GetField(field.Name) == null) .Where(field => field.IsPublic || field.IsDefined(typeof(SerializeField))) .Where(field => !field.IsDefined(typeof(HideInInspector))) @@ -735,7 +537,7 @@ public FieldInfo[] GetCustomFields(bool isOverrideInstance) } /// - /// Checks if there is a match given the neighbor matching rule and a Tile. + /// Checks if there is a match given the neighbor matching rule and a Tile. /// /// Neighbor matching rule. /// Tile to match. @@ -750,21 +552,23 @@ public virtual bool RuleMatch(int neighbor, TileBase other) case TilingRuleOutput.Neighbor.This: return other == this; case TilingRuleOutput.Neighbor.NotThis: return other != this; } + return true; } /// - /// Checks if there is a match given the neighbor matching rule and a Tile with a rotation angle. + /// Checks if there is a match given the neighbor matching rule and a Tile with a rotation angle. /// /// Neighbor matching rule. /// Position of the Tile on the Tilemap. /// Tilemap to match. /// Rotation angle for matching. + /// Mirror X Axis for matching. /// True if there is a match, False if not. public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, int angle, bool mirrorX = false) { var minCount = Math.Min(rule.m_Neighbors.Count, rule.m_NeighborPositions.Count); - for (int i = 0; i < minCount ; i++) + for (var i = 0; i < minCount; i++) { var neighbor = rule.m_Neighbors[i]; var neighborPosition = rule.m_NeighborPositions[i]; @@ -772,16 +576,14 @@ public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, neighborPosition = GetMirroredPosition(neighborPosition, true, false); var positionOffset = GetRotatedPosition(neighborPosition, angle); var other = tilemap.GetTile(GetOffsetPosition(position, positionOffset)); - if (!RuleMatch(neighbor, other)) - { - return false; - } + if (!RuleMatch(neighbor, other)) return false; } + return true; } /// - /// Checks if there is a match given the neighbor matching rule and a Tile with mirrored axii. + /// Checks if there is a match given the neighbor matching rule and a Tile with mirrored axii. /// /// Neighbor matching rule. /// Position of the Tile on the Tilemap. @@ -792,21 +594,19 @@ public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, public bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, bool mirrorX, bool mirrorY) { var minCount = Math.Min(rule.m_Neighbors.Count, rule.m_NeighborPositions.Count); - for (int i = 0; i < minCount; i++) + for (var i = 0; i < minCount; i++) { - int neighbor = rule.m_Neighbors[i]; - Vector3Int positionOffset = GetMirroredPosition(rule.m_NeighborPositions[i], mirrorX, mirrorY); - TileBase other = tilemap.GetTile(GetOffsetPosition(position, positionOffset)); - if (!RuleMatch(neighbor, other)) - { - return false; - } + var neighbor = rule.m_Neighbors[i]; + var positionOffset = GetMirroredPosition(rule.m_NeighborPositions[i], mirrorX, mirrorY); + var other = tilemap.GetTile(GetOffsetPosition(position, positionOffset)); + if (!RuleMatch(neighbor, other)) return false; } + return true; } /// - /// Gets a rotated position given its original position and the rotation in degrees. + /// Gets a rotated position given its original position and the rotation in degrees. /// /// Original position of Tile. /// Rotation in degrees. @@ -824,11 +624,12 @@ public virtual Vector3Int GetRotatedPosition(Vector3Int position, int rotation) case 270: return new Vector3Int(-position.y, position.x, 0); } + return position; } /// - /// Gets a mirrored position given its original position and the mirroring axii. + /// Gets a mirrored position given its original position and the mirroring axii. /// /// Original position of Tile. /// Mirror in the X Axis. @@ -844,7 +645,7 @@ public virtual Vector3Int GetMirroredPosition(Vector3Int position, bool mirrorX, } /// - /// Get the offset for the given position with the given offset. + /// Get the offset for the given position with the given offset. /// /// Position to offset. /// Offset for the position. @@ -855,7 +656,7 @@ public virtual Vector3Int GetOffsetPosition(Vector3Int position, Vector3Int offs } /// - /// Get the reversed offset for the given position with the given offset. + /// Get the reversed offset for the given position with the given offset. /// /// Position to offset. /// Offset for the position. @@ -864,5 +665,241 @@ public virtual Vector3Int GetOffsetPositionReverse(Vector3Int position, Vector3I { return position - offset; } + + /// + /// The data structure holding the Rule information for matching Rule Tiles with + /// its neighbors. + /// + [Serializable] + public class TilingRuleOutput + { + /// + /// The Output for the Tile which fits this Rule. + /// + public enum OutputSprite + { + /// + /// A Single Sprite will be output. + /// + Single, + + /// + /// A Random Sprite will be output. + /// + Random, + + /// + /// A Sprite Animation will be output. + /// + Animation + } + + /// + /// The enumeration for the transform rule used when matching Rule Tiles. + /// + public enum Transform + { + /// + /// The Rule Tile will match Tiles exactly as laid out in its neighbors. + /// + Fixed, + + /// + /// The Rule Tile will rotate and match its neighbors. + /// + Rotated, + + /// + /// The Rule Tile will mirror in the X axis and match its neighbors. + /// + MirrorX, + + /// + /// The Rule Tile will mirror in the Y axis and match its neighbors. + /// + MirrorY, + + /// + /// The Rule Tile will mirror in the X or Y axis and match its neighbors. + /// + MirrorXY, + + /// + /// The Rule Tile will rotate and mirror in the X and match its neighbors. + /// + RotatedMirror + } + + /// + /// Id for this Rule. + /// + public int m_Id; + + /// + /// The output Sprites for this Rule. + /// + public Sprite[] m_Sprites = new Sprite[1]; + + /// + /// The output GameObject for this Rule. + /// + public GameObject m_GameObject; + + /// + /// The output minimum Animation Speed for this Rule. + /// + [FormerlySerializedAs("m_AnimationSpeed")] + public float m_MinAnimationSpeed = 1f; + + /// + /// The output maximum Animation Speed for this Rule. + /// + [FormerlySerializedAs("m_AnimationSpeed")] + public float m_MaxAnimationSpeed = 1f; + + /// + /// The perlin scale factor for this Rule. + /// + public float m_PerlinScale = 0.5f; + + /// + /// The output type for this Rule. + /// + public OutputSprite m_Output = OutputSprite.Single; + + /// + /// The output Collider Type for this Rule. + /// + public Tile.ColliderType m_ColliderType = Tile.ColliderType.Sprite; + + /// + /// The randomized transform output for this Rule. + /// + public Transform m_RandomTransform; + + /// + /// The enumeration for matching Neighbors when matching Rule Tiles + /// + public class Neighbor + { + /// + /// The Rule Tile will check if the contents of the cell in that direction is an instance of this Rule Tile. + /// If not, the rule will fail. + /// + public const int This = 1; + + /// + /// The Rule Tile will check if the contents of the cell in that direction is not an instance of this Rule Tile. + /// If it is, the rule will fail. + /// + public const int NotThis = 2; + } + } + + /// + /// The data structure holding the Rule information for matching Rule Tiles with + /// its neighbors. + /// + [Serializable] + public class TilingRule : TilingRuleOutput + { + /// + /// The matching Rule conditions for each of its neighboring Tiles. + /// + public List m_Neighbors = new(); + + /// + /// * Preset this list to RuleTile backward compatible, but not support for HexagonalRuleTile backward compatible. + /// + public List m_NeighborPositions = new() + { + new(-1, 1, 0), + new(0, 1, 0), + new(1, 1, 0), + new(-1, 0, 0), + new(1, 0, 0), + new(-1, -1, 0), + new(0, -1, 0), + new(1, -1, 0) + }; + + /// + /// The transform matching Rule for this Rule. + /// + public Transform m_RuleTransform; + + /// + /// This clones a copy of the TilingRule. + /// + /// A copy of the TilingRule. + public TilingRule Clone() + { + var rule = new TilingRule + { + m_Neighbors = new List(m_Neighbors), + m_NeighborPositions = new List(m_NeighborPositions), + m_RuleTransform = m_RuleTransform, + m_Sprites = new Sprite[m_Sprites.Length], + m_GameObject = m_GameObject, + m_MinAnimationSpeed = m_MinAnimationSpeed, + m_MaxAnimationSpeed = m_MaxAnimationSpeed, + m_PerlinScale = m_PerlinScale, + m_Output = m_Output, + m_ColliderType = m_ColliderType, + m_RandomTransform = m_RandomTransform + }; + Array.Copy(m_Sprites, rule.m_Sprites, m_Sprites.Length); + return rule; + } + + /// + /// Returns all neighbors of this Tile as a dictionary + /// + /// A dictionary of neighbors for this Tile + public Dictionary GetNeighbors() + { + var dict = new Dictionary(); + + for (var i = 0; i < m_Neighbors.Count && i < m_NeighborPositions.Count; i++) + dict.Add(m_NeighborPositions[i], m_Neighbors[i]); + + return dict; + } + + /// + /// Applies the values from the given dictionary as this Tile's neighbors + /// + /// Dictionary to apply values from + public void ApplyNeighbors(Dictionary dict) + { + m_NeighborPositions = dict.Keys.ToList(); + m_Neighbors = dict.Values.ToList(); + } + + /// + /// Gets the cell bounds of the TilingRule. + /// + /// Returns the cell bounds of the TilingRule. + public BoundsInt GetBounds() + { + var bounds = new BoundsInt(Vector3Int.zero, Vector3Int.one); + foreach (var neighbor in GetNeighbors()) + { + bounds.xMin = Mathf.Min(bounds.xMin, neighbor.Key.x); + bounds.yMin = Mathf.Min(bounds.yMin, neighbor.Key.y); + bounds.xMax = Mathf.Max(bounds.xMax, neighbor.Key.x + 1); + bounds.yMax = Mathf.Max(bounds.yMax, neighbor.Key.y + 1); + } + + return bounds; + } + } + + /// + /// Attribute which marks a property which cannot be overridden by a RuleOverrideTile + /// + public class DontOverride : Attribute + { + } } -} +} \ No newline at end of file diff --git a/Runtime/Unity.2D.Tilemap.Extras.asmdef b/Runtime/Unity.2D.Tilemap.Extras.asmdef index 3eff8e1..e6def18 100644 --- a/Runtime/Unity.2D.Tilemap.Extras.asmdef +++ b/Runtime/Unity.2D.Tilemap.Extras.asmdef @@ -1,3 +1,3 @@ -{ - "name": "Unity.2D.Tilemap.Extras" +{ + "name": "Unity.2D.Tilemap.Extras" } diff --git a/Samples~/DungeonRuleTile/.sample.json b/Samples~/DungeonRuleTile/.sample.json deleted file mode 100644 index 12da297..0000000 --- a/Samples~/DungeonRuleTile/.sample.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "displayName": "Dungeon Rule Tile", - "interactiveImport": "false", - "description": "An example implementation of a Rule Tile with rules matching eight-way orthogonal and diagonal neighbors.", -} \ No newline at end of file diff --git a/Samples~/PipeRuleTile/.sample.json b/Samples~/PipeRuleTile/.sample.json deleted file mode 100644 index 1a56016..0000000 --- a/Samples~/PipeRuleTile/.sample.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "displayName": "Pipe Rule Tile", - "interactiveImport": "false", - "description": "An example implementation of a Rule Tile with rules matching four-way orthogonal neighbors.", -} \ No newline at end of file diff --git a/Samples~/WaterfallAnimatedTile/.sample.json b/Samples~/WaterfallAnimatedTile/.sample.json deleted file mode 100644 index 9c09d60..0000000 --- a/Samples~/WaterfallAnimatedTile/.sample.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "displayName": "Waterfall Animated Tile", - "interactiveImport": "false", - "description": "An example implementation of an Animated Tile.", -} \ No newline at end of file diff --git a/Tests.meta b/Tests.meta deleted file mode 100644 index 3517195..0000000 --- a/Tests.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7e501fe6c6911484c907a1a3b00692dd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor.meta b/Tests/Editor.meta deleted file mode 100644 index cd7fe02..0000000 --- a/Tests/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b679ec8b3957ea64ebd2626843d0a81e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/PlaceholderTests.cs b/Tests/Editor/PlaceholderTests.cs deleted file mode 100644 index 8762ea2..0000000 --- a/Tests/Editor/PlaceholderTests.cs +++ /dev/null @@ -1,10 +0,0 @@ -using NUnit.Framework; - -internal class U2DExtrasPlaceholder -{ - [Test] - public void PlaceHolderTest() - { - Assert.Pass("2D Extras tests are in a separate package."); - } -} diff --git a/Tests/Editor/PlaceholderTests.cs.meta b/Tests/Editor/PlaceholderTests.cs.meta deleted file mode 100644 index adddad8..0000000 --- a/Tests/Editor/PlaceholderTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1570cfa747cfb0647a5afa98d8babd66 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Tests/Editor/Unity.2D.Tilemap.Extras.EditorTests.asmdef b/Tests/Editor/Unity.2D.Tilemap.Extras.EditorTests.asmdef deleted file mode 100644 index 2e5ebd7..0000000 --- a/Tests/Editor/Unity.2D.Tilemap.Extras.EditorTests.asmdef +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "Unity.2D.Tilemap.Extras.Placeholder.EditorTests", - "references": [ - "UnityEngine.TestRunner", - "UnityEditor.TestRunner" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": true, - "precompiledReferences": [ - "nunit.framework.dll" - ], - "autoReferenced": false, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Tests/Editor/Unity.2D.Tilemap.Extras.EditorTests.asmdef.meta b/Tests/Editor/Unity.2D.Tilemap.Extras.EditorTests.asmdef.meta deleted file mode 100644 index c574c3a..0000000 --- a/Tests/Editor/Unity.2D.Tilemap.Extras.EditorTests.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6e1c163768a31b44ba01cc5392db861e -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Third Party Notices.md b/Third Party Notices.md index 482548d..b101ffe 100644 --- a/Third Party Notices.md +++ b/Third Party Notices.md @@ -8,11 +8,18 @@ Copyright (c) 2020 Eric Woroshow http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ericw.ca / Content © 2009-2020 Eric Woroshow. All rights reserved. Code under MIT license unless otherwise noted. @@ -25,14 +32,21 @@ Copyright © 2017 CraigGraff (https://github.com/CraigGraff) https://github.com/Unity-Technologies/2d-extras/pull/6 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Animation Tile +Component Name: Animation Tile License Type: MIT @@ -40,14 +54,21 @@ Copyright © 2017 MahdiMahzouni (https://github.com/MahdiMahzouni) https://github.com/Unity-Technologies/2d-extras/pull/12 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Coordinate Brush +Component Name: Coordinate Brush License Type: MIT @@ -55,14 +76,21 @@ Copyright © 2018 nicovain (https://github.com/nicovain) https://github.com/Unity-Technologies/2d-extras/pull/20 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Weighted Random Tile +Component Name: Weighted Random Tile License Type: MIT @@ -70,14 +98,21 @@ Copyright © 2018 nicovain (https://github.com/nicovain) https://github.com/Unity-Technologies/2d-extras/pull/20 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Rule Tile Editor +Component Name: Rule Tile Editor License Type: MIT @@ -85,14 +120,21 @@ Copyright © 2018 DreadBoy (https://github.com/DreadBoy) https://github.com/Unity-Technologies/2d-extras/pull/22 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Weighted Random Tile +Component Name: Weighted Random Tile License Type: MIT @@ -100,14 +142,21 @@ Copyright © 2018 distantcam (https://github.com/distantcam) https://github.com/Unity-Technologies/2d-extras/pull/26 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Rule Override Tile +Component Name: Rule Override Tile License Type: MIT @@ -115,11 +164,18 @@ Copyright © 2018 johnsoncodehk (https://github.com/johnsoncodehk) https://github.com/Unity-Technologies/2d-extras/pull/29 and https://github.com/Unity-Technologies/2d-extras/pull/36 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- Component Name: Rule Override Tile Editor @@ -130,11 +186,18 @@ Copyright © 2018 johnsoncodehk (https://github.com/johnsoncodehk) https://github.com/Unity-Technologies/2d-extras/pull/29 and https://github.com/Unity-Technologies/2d-extras/pull/36 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- Component Name: Rule Tile @@ -145,14 +208,21 @@ Copyright © 2018 johnsoncodehk (https://github.com/johnsoncodehk) https://github.com/Unity-Technologies/2d-extras/pull/36 and https://github.com/Unity-Technologies/2d-extras/pull/38 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Rule Tile Editor +Component Name: Rule Tile Editor License Type: MIT @@ -160,14 +230,21 @@ Copyright © 2018 johnsoncodehk (https://github.com/johnsoncodehk) https://github.com/Unity-Technologies/2d-extras/pull/36 and https://github.com/Unity-Technologies/2d-extras/pull/38 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Custom Rule Tile +Component Name: Custom Rule Tile License Type: MIT @@ -175,14 +252,21 @@ Copyright © 2018 johnsoncodehk (https://github.com/johnsoncodehk) https://github.com/Unity-Technologies/2d-extras/pull/38 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Create Asset Menus +Component Name: Create Asset Menus License Type: MIT @@ -190,11 +274,18 @@ Copyright © 2018 janissimsons (https://github.com/janissimsons) https://github.com/Unity-Technologies/2d-extras/pull/49 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- Component Name: Rule Tile @@ -203,16 +294,23 @@ License Type: MIT Copyright © 2018 DoctorShinobi (https://github.com/DoctorShinobi) - https://github.com/Unity-Technologies/2d-extras/pull/51 - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +https://github.com/Unity-Technologies/2d-extras/pull/51 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- -Component Name: Rule Tile Editor +Component Name: Rule Tile Editor License Type: MIT @@ -220,10 +318,17 @@ Copyright © 2018 DoctorShinobi (https://github.com/DoctorShinobi) https://github.com/Unity-Technologies/2d-extras/pull/51 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE. ----------------- \ No newline at end of file diff --git a/package.json b/package.json index 097f49c..9c10aa5 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "com.unity.2d.tilemap.extras", "displayName": "2D Tilemap Extras", - "version": "4.0.2", - "unity": "2023.1", + "version": "4.1.0", + "unity": "6000.0", "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": [ "2d" @@ -11,11 +11,10 @@ "dependencies": { "com.unity.modules.tilemap": "1.0.0", "com.unity.2d.tilemap": "1.0.0", - "com.unity.ugui": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0" }, "relatedPackages": { - "com.unity.2d.tilemap.extras.tests": "4.0.2" + "com.unity.2d.tilemap.extras.tests": "4.1.0" }, "samples": [ { @@ -35,15 +34,15 @@ } ], "_upm": { - "changelog": "### Fixed\n- [GameObjectBrush] Use cell offset to determine location of GameObject when painting and erasing" + "changelog": "### Fixed\n\n- [GameObjectBrush] Allow expansion of SceneRoot Grid foldout when clicking on label\n- [GridInformation] Fix exception when serializing GridInformation component if component is part of a Prefab\n- Remove dependency on com.unity.ugui" }, "upmCi": { - "footprint": "1dc77b3f9a7dc9ec88a1b175812698bd0c8714ff" + "footprint": "fbdcb391a5add50bd256ca0f119a2fddebba5602" }, - "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@4.0/manual/index.html", + "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@4.1/manual/index.html", "repository": { "url": "https://github.com/Unity-Technologies/2d-extras.git", "type": "git", - "revision": "21a24803135ec4fbe47be9ccd27fb06e47d06d88" + "revision": "8d9a9d9b09b21c40c727e0dfb6188875f796d9f5" } }