Browse Source

导入可视化编辑器

wgl 7 months ago
parent
commit
7fe2106fd5
100 changed files with 3385 additions and 0 deletions
  1. 8 0
      ActionTowerDefense/Assets/GameLevelEditor.meta
  2. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY.meta
  3. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/Documentation.pdf
  4. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/Documentation.pdf.meta
  5. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI.meta
  6. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs.meta
  7. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components.meta
  8. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/Rule.prefab
  9. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/Rule.prefab.meta
  10. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneContentItem.prefab
  11. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneContentItem.prefab.meta
  12. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneItemLabel.prefab
  13. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneItemLabel.prefab.meta
  14. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineHeaderItem.prefab
  15. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineHeaderItem.prefab.meta
  16. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineSwimlane.prefab
  17. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineSwimlane.prefab.meta
  18. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Timeline.prefab
  19. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Timeline.prefab.meta
  20. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scenes.meta
  21. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scenes/TimelineUI.unity
  22. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scenes/TimelineUI.unity.meta
  23. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts.meta
  24. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ButtonTest.cs
  25. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ButtonTest.cs.meta
  26. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollRectContentResizer.cs
  27. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollRectContentResizer.cs.meta
  28. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollViewExtension.cs
  29. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollViewExtension.cs.meta
  30. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/SwimlaneItemLabel.cs
  31. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/SwimlaneItemLabel.cs.meta
  32. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineContentItem.cs
  33. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineContentItem.cs.meta
  34. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineController.cs
  35. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineController.cs.meta
  36. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineHeaderItem.cs
  37. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineHeaderItem.cs.meta
  38. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlane.cs
  39. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlane.cs.meta
  40. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlaneController.cs
  41. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlaneController.cs.meta
  42. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/UnityDateTime.cs
  43. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/UnityDateTime.cs.meta
  44. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/WarningPopup.cs
  45. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/WarningPopup.cs.meta
  46. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75.meta
  47. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/LICENSE
  48. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/LICENSE.meta
  49. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources.meta
  50. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplate.uxml
  51. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplate.uxml.meta
  52. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplateStyle.uss
  53. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplateStyle.uss.meta
  54. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplate.uxml
  55. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplate.uxml.meta
  56. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplateStyle.uss
  57. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplateStyle.uss.meta
  58. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/UiCalendarWindow.cs
  59. 0 0
      ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/UiCalendarWindow.cs.meta
  60. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap.meta
  61. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts.meta
  62. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor.meta
  63. 280 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapAutoTileEd.cs
  64. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapAutoTileEd.cs.meta
  65. 98 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEdPopup.cs
  66. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEdPopup.cs.meta
  67. 1742 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEditor.cs
  68. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEditor.cs.meta
  69. 58 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTextEd.cs
  70. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTextEd.cs.meta
  71. 18 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTilesAssetInspector.cs
  72. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTilesAssetInspector.cs.meta
  73. 18 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapsAssetInspector.cs
  74. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapsAssetInspector.cs.meta
  75. 210 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMap.cs
  76. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMap.cs.meta
  77. 17 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapIdxIdPair.cs
  78. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapIdxIdPair.cs.meta
  79. 17 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapLayer.cs
  80. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapLayer.cs.meta
  81. 50 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTile.cs
  82. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTile.cs.meta
  83. 6 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilePreviewAttribute.cs
  84. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilePreviewAttribute.cs.meta
  85. 104 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilesAsset.cs
  86. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilesAsset.cs.meta
  87. 42 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapsAsset.cs
  88. 12 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapsAsset.cs.meta
  89. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample.meta
  90. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData.meta
  91. 19 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/maps.asset
  92. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/maps.asset.meta
  93. 167 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/tiles.asset
  94. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/tiles.asset.meta
  95. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs.meta
  96. 113 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/FloorTile.prefab
  97. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/FloorTile.prefab.meta
  98. 86 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/NPC1.prefab
  99. 9 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/NPC1.prefab.meta
  100. 86 0
      ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/NPC2.prefab

+ 8 - 0
ActionTowerDefense/Assets/GameLevelEditor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: efbb55f6be2713545a41174756a3f2f8
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/Documentation.pdf → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/Documentation.pdf


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/Documentation.pdf.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/Documentation.pdf.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/Rule.prefab → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/Rule.prefab


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/Rule.prefab.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/Rule.prefab.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneContentItem.prefab → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneContentItem.prefab


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneContentItem.prefab.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneContentItem.prefab.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneItemLabel.prefab → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneItemLabel.prefab


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneItemLabel.prefab.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/SwimlaneItemLabel.prefab.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/TimelineHeaderItem.prefab → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineHeaderItem.prefab


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/TimelineHeaderItem.prefab.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineHeaderItem.prefab.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/TimelineSwimlane.prefab → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineSwimlane.prefab


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Components/TimelineSwimlane.prefab.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Components/TimelineSwimlane.prefab.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Timeline.prefab → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Timeline.prefab


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Prefabs/Timeline.prefab.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Prefabs/Timeline.prefab.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scenes.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scenes.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scenes/TimelineUI.unity → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scenes/TimelineUI.unity


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scenes/TimelineUI.unity.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scenes/TimelineUI.unity.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/ButtonTest.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ButtonTest.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/ButtonTest.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ButtonTest.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/ScrollRectContentResizer.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollRectContentResizer.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/ScrollRectContentResizer.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollRectContentResizer.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/ScrollViewExtension.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollViewExtension.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/ScrollViewExtension.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/ScrollViewExtension.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/SwimlaneItemLabel.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/SwimlaneItemLabel.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/SwimlaneItemLabel.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/SwimlaneItemLabel.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineContentItem.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineContentItem.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineContentItem.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineContentItem.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineController.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineController.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineController.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineController.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineHeaderItem.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineHeaderItem.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineHeaderItem.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineHeaderItem.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineSwimlane.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlane.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineSwimlane.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlane.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineSwimlaneController.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlaneController.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/TimelineSwimlaneController.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/TimelineSwimlaneController.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/UnityDateTime.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/UnityDateTime.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/UnityDateTime.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/UnityDateTime.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/WarningPopup.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/WarningPopup.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/Scripts/WarningPopup.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/Scripts/WarningPopup.cs.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/LICENSE → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/LICENSE


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/LICENSE.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/LICENSE.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplate.uxml → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplate.uxml


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplate.uxml.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplate.uxml.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplateStyle.uss → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplateStyle.uss


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplateStyle.uss.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/CalendarTemplateStyle.uss.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplate.uxml → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplate.uxml


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplate.uxml.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplate.uxml.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplateStyle.uss → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplateStyle.uss


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplateStyle.uss.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/Resources/DayContainerTemplateStyle.uss.meta


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/UiCalendarWindow.cs → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/UiCalendarWindow.cs


+ 0 - 0
ActionTowerDefense/Assets/GAAWCITY/TimelineUI/meaf75/UiCalendarWindow.cs.meta → ActionTowerDefense/Assets/GameLevelEditor/GAAWCITY/TimelineUI/meaf75/UiCalendarWindow.cs.meta


+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 26b0d805c1521904bb7bdb6e322b4cbc
+folderAsset: yes
+timeCreated: 1499065755
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 7437c853c71eb5c4d80ecec9f2bea192
+folderAsset: yes
+timeCreated: 1499065777
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 2652cec61d711624394f35daaf9e998f
+folderAsset: yes
+timeCreated: 1496060542
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 280 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapAutoTileEd.cs

@@ -0,0 +1,280 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+
+public class GameMapAutoTileEd : EditorWindow
+{
+	private GameMapTilesAsset asset;
+	private GameMapTilesAsset.AutoTile autoTile;
+	private System.Action<int> onChange;
+	private bool is16Tile;
+
+	private static readonly GUIContent GC_Close = new GUIContent("Close");
+	private static readonly GUIContent GC_Info = new GUIContent("Add sprites in spaces below");
+
+	public class StyleDefs
+	{
+		public GUIStyle WhiteBackground;
+
+		public StyleDefs()
+		{
+			WhiteBackground = new GUIStyle() { normal = { background = EditorGUIUtility.whiteTexture } };
+		}
+	}
+
+	private static StyleDefs _styles;
+	private static StyleDefs Styles { get { return _styles ?? (_styles = new StyleDefs()); } }
+
+	int[,] map46 =
+	{ //  T   R   B   L
+		{ 1,0,1,0,1,0,1,0 }, // 0*
+		{ 0,0,1,0,1,0,1,0 }, // 1*
+		{ 1,0,0,0,1,0,1,0 }, // 4
+		{ 1,0,1,0,0,0,1,0 }, // 16
+		{ 1,0,1,0,1,0,0,0 }, // 64
+		{ 0,1,0,0,1,0,1,0 }, // 5*
+		{ 1,0,0,1,0,0,1,0 }, // 20
+		{ 1,0,1,0,0,1,0,0 }, // 80
+		{ 0,0,1,0,1,0,0,1 }, // 65
+		{ 0,0,0,0,1,0,1,0 }, // 7*
+		{ 1,0,0,0,0,0,1,0 }, // 28
+		{ 1,0,1,0,0,0,0,0 }, // 112
+		{ 0,0,1,0,1,0,0,0 }, // 193
+		{ 0,0,1,0,0,0,1,0 }, // 17*
+		{ 1,0,0,0,1,0,0,0 }, // 68
+		{ 0,1,0,1,0,0,1,0 }, // 21*
+		{ 1,0,0,1,0,1,0,0 }, // 84
+		{ 0,0,1,0,0,1,0,1 }, // 81
+		{ 0,1,0,0,1,0,0,1 }, // 69
+		{ 0,0,0,1,0,0,1,0 }, // 23*
+		{ 1,0,0,0,0,1,0,0 }, // 92
+		{ 0,0,1,0,0,0,0,1 }, // 113
+		{ 0,1,0,0,1,0,0,0 }, // 197
+		{ 0,1,0,0,0,0,1,0 }, // 29*
+		{ 1,0,0,1,0,0,0,0 }, // 116
+		{ 0,0,1,0,0,1,0,0 }, // 209
+		{ 0,0,0,0,1,0,0,1 }, // 71
+		{ 0,0,0,0,0,0,1,0 }, // 31*
+		{ 1,0,0,0,0,0,0,0 }, // 124
+		{ 0,0,1,0,0,0,0,0 }, // 214
+		{ 0,0,0,0,1,0,0,0 }, // 199
+		{ 0,1,0,1,0,1,0,1 }, // 85*
+		{ 0,0,0,1,0,1,0,1 }, // 87*
+		{ 0,1,0,0,0,1,0,1 }, // 93
+		{ 0,1,0,1,0,0,0,1 }, // 117
+		{ 0,1,0,1,0,1,0,0 }, // 213
+		{ 0,0,0,0,0,1,0,1 }, // 95*
+		{ 0,1,0,0,0,0,0,1 }, // 125
+		{ 0,1,0,1,0,0,0,0 }, // 245
+		{ 0,0,0,1,0,1,0,0 }, // 215
+		{ 0,0,0,1,0,0,0,1 }, // 119*
+		{ 0,1,0,0,0,1,0,0 }, // 221
+		{ 0,0,0,0,0,0,0,1 }, // 127*
+		{ 0,1,0,0,0,0,0,0 }, // 253
+		{ 0,0,0,1,0,0,0,0 }, // 247
+		{ 0,0,0,0,0,1,0,0 }, // 223
+		{ 0,0,0,0,0,0,0,0 }, // 255*
+	};
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	public static void Show_GameMapAutoTileEd(GameMapTilesAsset asset, GameMapTilesAsset.AutoTile autoTile, System.Action<int> onChange)
+	{
+		GameMapAutoTileEd win = GetWindow<GameMapAutoTileEd>(true, "AutoTile Ed", true);
+		win.asset = asset;
+		win.autoTile = autoTile;
+		win.is16Tile = autoTile.tiles.Length == 16;
+		win.onChange = onChange;
+		win.minSize = win.maxSize = new Vector2(win.is16Tile ? 175f : 495f, 220f);
+		win.ShowUtility();
+	}
+
+	private void OnFocus()
+	{
+		wantsMouseMove = true;
+	}
+
+	private void OnLostFocus()
+	{
+		wantsMouseMove = false;
+	}
+
+	private void OnGUI()
+	{
+		if (asset == null || autoTile == null)
+		{
+			Close();
+			GUIUtility.ExitGUI();
+			return;
+		}
+
+		if (GUILayout.Button(GC_Close))
+		{
+			Close();
+		}
+
+		GUILayout.Label(GC_Info);
+		EditorGUILayout.Space();
+		Rect rect = GUILayoutUtility.GetRect(1f, 1f, 1f, 1f);
+		Rect r = new Rect(rect.x + 10, rect.y + 10, 35, 35);
+
+		if (Event.current.type == EventType.Repaint)
+		{
+			GUI.color = Color.white;
+			Styles.WhiteBackground.Draw(new Rect(rect.x, rect.y, position.width, position.height), false, false, false, false);
+		}
+
+		for (int i = 0; i < autoTile.tiles.Length; i++)
+		{
+			EditorGUI.BeginChangeCheck();
+			autoTile.tiles[i].sprite = (Sprite)EditorGUI.ObjectField(r, autoTile.tiles[i].sprite, typeof(Sprite), false);
+			if (EditorGUI.EndChangeCheck() && onChange != null) onChange(i);
+
+			if (Event.current.type == EventType.Repaint)
+			{
+				if (autoTile.tiles[i].sprite != null)
+				{
+					GUI.color = Color.black;
+					Styles.WhiteBackground.Draw(r, false, false, false, false);
+					GUI.color = Color.white;
+					Sprite sp = autoTile.tiles[i].sprite;
+					Rect r2= new Rect(sp.rect.x / sp.texture.width, sp.rect.y / sp.texture.height, sp.rect.width / sp.texture.width, sp.rect.height / sp.texture.height);
+					GUI.DrawTextureWithTexCoords(r, sp.texture, r2);
+				}
+
+				if (autoTile.tiles[i].sprite == null || r.Contains(Event.current.mousePosition))
+				{
+					if (is16Tile) Draw16TileSample(r, i);
+					else Draw46TileSample(r, i);
+				}
+			}
+
+			r.x += 40;
+			if ((is16Tile && r.x > 150) || r.x > 480) { r.x = rect.x + 10; r.y += 40; }
+		}
+
+		if (Event.current.type == EventType.MouseMove)
+		{
+			Repaint();
+		}
+
+		if (GUI.changed)
+		{
+			EditorUtility.SetDirty(asset);
+			GUI.changed = false;
+			Repaint();
+		}
+	}
+
+	// I did not want to make project messy with sample textures so will just manually draw them with these functions
+
+	private void Draw16TileSample(Rect r, int idx)
+	{
+		switch (idx)
+		{
+			case 0: DrawSample(r, true, true, true, true); break;
+			case 1: DrawSample(r, false, true, true, true); break;
+			case 2: DrawSample(r, true, true, false, true); break;
+			case 3: DrawSample(r, false, true, false, true); break;
+			case 4: DrawSample(r, true, true, true, false); break;
+			case 5: DrawSample(r, false, true, true, false); break;
+			case 6: DrawSample(r, true, true, false, false); break;
+			case 7: DrawSample(r, false, true, false, false); break;
+			case 8: DrawSample(r, true, false, true, true); break;
+			case 9: DrawSample(r, false, false, true, true); break;
+			case 10: DrawSample(r, true, false, false, true); break;
+			case 11: DrawSample(r, false, false, false, true); break;
+			case 12: DrawSample(r, true, false, true, false); break;
+			case 13: DrawSample(r, false, false, true, false); break;
+			case 14: DrawSample(r, true, false, false, false); break;
+			case 15: DrawSample(r, false, false, false, false); break;
+		}
+	}
+
+	private void Draw46TileSample(Rect r, int idx)
+	{
+		DrawSample(r, map46[idx, 0], map46[idx, 1], map46[idx, 2], map46[idx, 3], map46[idx, 4], map46[idx, 5], map46[idx, 6], map46[idx, 7]);
+	}
+
+	private void DrawSample(Rect rect, int t, int tr, int r, int br, int b, int bl, int l, int tl)
+	{
+		GUI.color = Color.black;
+		Styles.WhiteBackground.Draw(rect, false, false, false, false);
+		GUI.color = Color.green;
+		if (t == 1) DrawTopLine(rect);
+		if (b == 1) DrawBottomLine(rect);
+		if (l == 1) DrawLeftLine(rect);
+		if (r == 1) DrawRightLine(rect);
+		if (tl == 1) DrawTopLeftCorner(rect);
+		if (tr == 1) DrawTopRightCorner(rect);
+		if (bl == 1) DrawBottomLeftCorner(rect);
+		if (br == 1) DrawBottomRightCorner(rect);
+		GUI.color = Color.white;
+	}
+
+	private void DrawSample(Rect rect, bool t, bool b, bool l, bool r)
+	{
+		GUI.color = Color.black;
+		Styles.WhiteBackground.Draw(rect, false, false, false, false);
+		GUI.color = Color.green;
+		if (t) DrawTopLine(rect);
+		if (b) DrawBottomLine(rect);
+		if (l) DrawLeftLine(rect);
+		if (r) DrawRightLine(rect);
+		GUI.color = Color.white;
+	}
+
+	private void DrawTopLine(Rect r)
+	{
+		r.y += 2f; r.height = 2f;
+		r.x += 2f; r.width -= 4f;
+		Styles.WhiteBackground.Draw(r, false, false, false, false);
+	}
+
+	private void DrawBottomLine(Rect r)
+	{
+		r.y = r.yMax - 4f; r.height = 2f;
+		r.x += 2f; r.width -= 4f;
+		Styles.WhiteBackground.Draw(r, false, false, false, false);
+	}
+
+	private void DrawLeftLine(Rect r)
+	{
+		r.y += 2f; r.height -= 4f;
+		r.x += 2f; r.width = 2f;
+		Styles.WhiteBackground.Draw(r, false, false, false, false);
+	}
+
+	private void DrawRightLine(Rect r)
+	{
+		r.y += 2f; r.height -= 4f;
+		r.x = r.xMax - 4f; r.width = 2f;
+		Styles.WhiteBackground.Draw(r, false, false, false, false);
+	}
+
+	private void DrawTopLeftCorner(Rect r)
+	{
+		DrawTopLine(new Rect(r.x, r.y + 5f, 10f, r.height));
+		DrawLeftLine(new Rect(r.x + 5f, r.y, r.width, 10f));
+	}
+
+	private void DrawTopRightCorner(Rect r)
+	{
+		DrawTopLine(new Rect(r.xMax - 10f, r.y + 5f, 10f, r.height));
+		DrawRightLine(new Rect(r.x - 5f, r.y, r.width, 10f));
+	}
+
+	private void DrawBottomRightCorner(Rect r)
+	{
+		DrawBottomLine(new Rect(r.xMax - 10f, r.y - 5f, 10f, r.height));
+		DrawRightLine(new Rect(r.x - 5, r.yMax - 10f, r.width, 10f));
+	}
+
+	private void DrawBottomLeftCorner(Rect r)
+	{
+		DrawBottomLine(new Rect(r.x, r.y - 5f, 10f, r.height));
+		DrawLeftLine(new Rect(r.x + 5f, r.yMax - 10f, r.width, 10f));
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapAutoTileEd.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a934a2fd7518625459c3c699e7edb283
+timeCreated: 1498646321
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 98 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEdPopup.cs

@@ -0,0 +1,98 @@
+using UnityEngine;
+using UnityEditor;
+using UnityEditorInternal;
+
+
+public class GameMapEdPopup : PopupWindowContent
+{
+	public GameMapsAsset Asset { get; set; }
+	public System.Action<int> OnMapSelected { get; set; }
+
+	private ReorderableList list;
+	private Rect contentRect;
+	private Vector2 scroll = Vector2.zero;
+
+	private static readonly Vector2 popupSz = new Vector2(200f, 200f);
+	private static readonly GUIContent GC_Head = new GUIContent("Maps");
+	private static readonly GUIContent GC_Add = new GUIContent("+");
+	private static readonly GUIContent GC_Rem = new GUIContent("-");
+
+	public override void OnOpen()
+	{
+		list = new ReorderableList(Asset.maps, typeof(GameMap), true, false, false, false)
+		{
+			elementHeight = EditorGUIUtility.singleLineHeight,
+			headerHeight = 0,
+			drawElementCallback = DrawElement,
+			onSelectCallback = SelectMap
+		};
+
+		contentRect = new Rect(0f, 18f, popupSz.x - 20f, Mathf.Max(popupSz.y - 18, EditorGUIUtility.singleLineHeight * Asset.maps.Count + 5));
+	}
+
+	public override void OnClose()
+	{
+		list = null;
+		Asset = null;
+		OnMapSelected = null;
+	}
+
+	public override Vector2 GetWindowSize()
+	{
+		return popupSz;
+	}
+
+	public override void OnGUI(Rect r)
+	{
+		DrawHeader(new Rect(0, 0, r.width, 18));
+		r.y += 18; r.height -= 18;
+		scroll = GUI.BeginScrollView(r, scroll, contentRect, false, true);
+		list.DoList(r);
+		GUI.EndScrollView();
+
+	}
+
+	private void DrawHeader(Rect r)
+	{
+		if (ReorderableList.defaultBehaviours != null)
+		{
+			ReorderableList.defaultBehaviours.DrawHeaderBackground(r);
+		}
+
+		GUI.Label(r, GC_Head, EditorStyles.boldLabel);
+		r.x = r.xMax - 25; r.width = 25;
+		GUI.enabled = list.index >= 0;
+		if (GUI.Button(r, GC_Rem, EditorStyles.miniButtonRight))
+		{
+			if (list.index >= 0 && list.index < Asset.maps.Count)
+			{
+				Undo.RecordObject(Asset, "Remove Game Map");
+				Asset.RemoveMapAtIndex(list.index);
+				contentRect = new Rect(0f, 18f, popupSz.x - 20f, Mathf.Max(popupSz.y - 18, EditorGUIUtility.singleLineHeight * Asset.maps.Count + 5));
+				OnMapSelected(-1);
+			}
+		}
+
+		GUI.enabled = true;
+		r.x -= 25;
+		if (GUI.Button(r, GC_Add, EditorStyles.miniButtonLeft))
+		{
+			Undo.RecordObject(Asset, "Add Game Map");
+			Asset.AddMap();
+			contentRect = new Rect(0f, 18f, popupSz.x - 20f, Mathf.Max(popupSz.y - 18, EditorGUIUtility.singleLineHeight * Asset.maps.Count + 5));
+			OnMapSelected(Asset.maps.Count - 1);
+		}
+	}
+
+	private void DrawElement(Rect r, int index, bool isActive, bool isFocused)
+	{
+		GUI.Label(r, Asset.maps[index].ToString());
+	}
+
+	private void SelectMap(ReorderableList list)
+	{
+		OnMapSelected(list.index);
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEdPopup.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5048a07a1aac52c4b9b111773e1612a5
+timeCreated: 1496403576
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1742 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEditor.cs

@@ -0,0 +1,1742 @@
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+public class GameMapEditor : EditorWindow
+{
+	// ----------------------------------------------------------------------------------------------------------------
+	#region vars
+
+	private static Color backColor = new Color(0f, 0f, 0f, 1f);
+	private static Color gridColor = new Color(1f, 1f, 1f, 0.3f);
+	private static bool outsideMapIsSolid = true; // if true then the areas outside map counts as solid of an auto-tile when doing auto-tile calculations
+	private static float refTileSz = 0f;
+	private static float panelWidth = 250f;
+	private static bool showEditorSettings = true;
+	private static bool showAssetProperties = true;
+	private static bool showMapProperties = true;
+	private static bool showTileProperties = true;
+    private static bool showLayers = true;
+    private static GameMapEdPopup mapsPopup = new GameMapEdPopup();
+	private static Vector2[] scroll = { Vector2.zero, Vector2.zero };
+
+	private bool dragSplitter = false;
+	private bool doRepaint = false;
+
+	private GameMapsAsset asset = null;
+	private GameMapsAsset _setAsset = null;
+	private int mapSize_w = 0;
+	private int mapSize_h = 0;
+	private int mapIdx = -1;
+	private int tileIdx = -1;
+	private bool autoTileSelected = false;
+	private float tileDrawSz = 32f;
+	private int dragDropTarget = -1;
+    private int currLayer = -1;
+    private bool[] layerHidden = new bool[0];
+
+	[NonSerialized] private float tileListH = 1f;
+	[NonSerialized] private bool marking = false;
+	[NonSerialized] private bool pasting = false;
+	[NonSerialized] private bool clearMarked = false;
+
+	[NonSerialized] private SerializedObject assetObj;
+	[NonSerialized] private Editor assetEd = null;
+	[NonSerialized] private Editor tilesEd = null;
+	[NonSerialized] private Dictionary<int, TileDef> tileCache = new Dictionary<int, TileDef>();
+	[NonSerialized] private GUIContent TileContent = new GUIContent();
+	[NonSerialized] private List<int> markedTiles = new List<int>();
+	[NonSerialized] private List<TileDef> copyBuffer = new List<TileDef>();
+
+	[NonSerialized] private FieldInfo colField = null;
+	[NonSerialized] private FieldInfo sprField = null;
+	[NonSerialized] private FieldInfo intField = null;
+	[NonSerialized] private FieldInfo strField = null;
+	[NonSerialized] private FieldInfo flpField = null;
+
+	private static int EditorCanvasHash = "GameMapEditorCanvasHash".GetHashCode();
+
+	#endregion
+	// ----------------------------------------------------------------------------------------------------------------
+	#region defs
+
+	private class TileDef
+	{
+		public string text;
+		public Sprite sprite;
+		public Rect rect;
+		public Color color = Color.white;
+		public bool flipped;
+		public bool isAuto;
+
+		// these are used by copy/paste system
+		public int id;
+		public int x, y;
+
+		public TileDef Copy()
+		{
+			return new TileDef()
+			{
+				text = text,
+				sprite = sprite,
+				rect = rect,
+				color = color,
+				flipped = flipped,
+				isAuto = isAuto,
+				id = id,
+				x = x,
+				y = y
+			};
+		}
+	}
+
+	private class StyleDefs
+	{
+		public GUIStyle Panel;
+		public GUIStyle Tile;
+		public GUIStyle SolidWhite;
+
+		public StyleDefs()
+		{
+			GUISkin skin = GUI.skin;
+			Panel = new GUIStyle(skin.FindStyle("PreferencesSectionBox")) { padding = new RectOffset(0, 0, 0, 3), margin = new RectOffset(0, 0, 0, 0), stretchHeight = true, stretchWidth = false };
+			Tile = new GUIStyle() { alignment = TextAnchor.MiddleCenter, fontSize = 12, fontStyle = FontStyle.Bold, normal = { textColor = Color.black, background = null } };
+			SolidWhite = new GUIStyle() { normal = { background = EditorGUIUtility.whiteTexture } };
+		}
+	}
+
+	private StyleDefs _styles = null;
+	private StyleDefs Styles { get { return _styles ?? (_styles = new StyleDefs()); } }
+
+	private static readonly GUIContent GC_MapSelect = new GUIContent("-select-");
+	private static readonly GUIContent GC_EditorHead = new GUIContent("Editor");
+	private static readonly GUIContent GC_AssetHead = new GUIContent("Asset");
+	private static readonly GUIContent GC_MapHead = new GUIContent("Map");
+    private static readonly GUIContent GC_LayersHead = new GUIContent("Layers");
+    private static readonly GUIContent GC_TilesHead = new GUIContent("Tiles");
+	private static readonly GUIContent GC_new = new GUIContent("new");
+	private static readonly GUIContent GC_rename = new GUIContent("ren", "Rename");
+	private static readonly GUIContent GC_apply = new GUIContent("apply");
+	private static readonly GUIContent GC_clear = new GUIContent("x", "Clear tile selection. Draw empty tiles.");
+	private static readonly GUIContent GC_add = new GUIContent("+", "Add");
+	private static readonly GUIContent GC_rem = new GUIContent("-", "Remove selected");
+	private static readonly GUIContent GC_movL = new GUIContent("<", "Move selected");
+	private static readonly GUIContent GC_movR = new GUIContent(">", "Move selected");
+	private static readonly GUIContent GC_BackCol = new GUIContent("BackColor");
+	private static readonly GUIContent GC_GridCol = new GUIContent("GridColor");
+	private static readonly GUIContent GC_Solid = new GUIContent("Outside is Solid");
+	private static readonly GUIContent GC_AutoSz = new GUIContent("Auto-tile Size");
+	private static readonly GUIContent GC_EditAuto = new GUIContent("Setup Auto-tile");
+    private static readonly GUIContent GC_Viz = new GUIContent("*", "Toggle layer visblity in editor");
+
+    private GenericMenu addTileMenu = null;
+
+	private static readonly Dictionary<int, int> map64 = new Dictionary<int, int>()
+	{
+		{ 0, 0 },
+		{ 1, 1 }, { 4, 2 }, { 16, 3 }, { 64, 4 },
+		{ 5, 5 }, { 20, 6 }, { 80, 7 }, {65, 8 },
+		{ 7, 9 }, { 28, 10 }, { 112, 11 }, { 193, 12 },
+		{ 17, 13 }, { 68, 14 },
+		{ 21, 15 }, { 84, 16 }, { 81, 17 }, { 69, 18 },
+		{ 23, 19 }, { 92, 20 }, { 113, 21 }, { 197, 22 },
+		{ 29, 23 }, { 116, 24 }, { 209, 25 }, { 71, 26 },
+		{ 31, 27 }, { 124, 28 }, { 241, 29 }, { 199, 30 },
+		{ 85, 31 },
+		{ 87, 32 }, { 93, 33 }, { 117, 34 }, { 213, 35 },
+		{ 95, 36 }, { 125, 37 }, { 245, 38 }, { 215, 39 },
+		{ 119, 40 }, { 221, 41 },
+		{ 127, 42 }, { 253, 43 }, { 247, 44 }, { 223, 45 },
+		{ 255, 46 }
+	};
+
+	#endregion
+	// ----------------------------------------------------------------------------------------------------------------
+	#region system
+
+	[MenuItem("Window/GameMap Editor")]
+	public static void Open_GameMapEditor()
+	{
+		GetWindow<GameMapEditor>("GameMap", true);
+	}
+
+	public static void Open_GameMapEditor(GameMapsAsset openAsset)
+	{
+		GameMapEditor win = GetWindow<GameMapEditor>("GameMap", true);
+		win._setAsset = openAsset;
+	}
+
+	private void OnEnable()
+	{
+		backColor = EditorPrefs_GetColor("plyGameMapEd.backColor", backColor);
+		gridColor = EditorPrefs_GetColor("plyGameMapEd.gridColor", gridColor);
+		outsideMapIsSolid = EditorPrefs.GetBool("plyGameMapEd.outsideMapIsSolid", outsideMapIsSolid);
+		refTileSz = EditorPrefs.GetFloat("plyGameMapEd.refTileSz", refTileSz);
+		panelWidth = EditorPrefs.GetFloat("plyGameMapEd.panelWidth", panelWidth);
+		showEditorSettings = EditorPrefs.GetBool("plyGameMapEd.showEditorSettings", showEditorSettings);
+		showAssetProperties = EditorPrefs.GetBool("plyGameMapEd.showAssetProps", showAssetProperties);
+		showMapProperties = EditorPrefs.GetBool("plyGameMapEd.showMapProps", showMapProperties);
+		showTileProperties = EditorPrefs.GetBool("plyGameMapEd.showTileProps", showTileProperties);
+        showLayers = EditorPrefs.GetBool("plyGameMapEd.showLayers", showLayers);
+
+        // auto load 1st found asset
+        if (_setAsset == null)
+		{
+			GameMapsAsset[] assets = Resources.FindObjectsOfTypeAll<GameMapsAsset>();
+			if (assets.Length > 0) _setAsset = assets[0];
+		}
+
+		Undo.undoRedoPerformed -= OnUnRedo;
+		Undo.undoRedoPerformed += OnUnRedo;
+	}
+
+	private void OnDisable()
+	{
+		Undo.undoRedoPerformed -= OnUnRedo;
+	}
+
+	private void OnFocus()
+	{
+		wantsMouseMove = true;
+		dragSplitter = false;
+		marking = false;
+		pasting = false;
+		clearMarked = false;
+	}
+
+	private void OnLostFocus()
+	{
+		wantsMouseMove = false;
+		marking = false;
+		pasting = false;
+		clearMarked = false;
+	}
+
+	private void OnGUI()
+	{
+		if (asset == null && assetObj != null)
+		{   // catch case where asset was manually deleted while active in editor
+			assetEd = null;
+			tilesEd = null;
+			assetObj = null;
+			tileCache.Clear();
+			GUIUtility.ExitGUI();
+			return;
+		}
+
+		Event ev = Event.current;
+		EditorGUILayout.BeginHorizontal();
+		{
+			DrawSideBar(ev);
+			DrawCanvas(ev);
+		}
+		EditorGUILayout.EndHorizontal();
+
+		if (doRepaint)
+		{
+			doRepaint = false;
+			Repaint();
+		}
+	}
+
+	private void OnUnRedo()
+	{
+		UpdateTileDefCache();
+		Repaint();
+	}
+
+	#endregion
+	// ----------------------------------------------------------------------------------------------------------------
+	#region side panel
+
+	private void DrawSideBar(Event ev)
+	{
+		Rect r = EditorGUILayout.BeginVertical(Styles.Panel, GUILayout.Width(panelWidth));
+		scroll[0] = EditorGUILayout.BeginScrollView(scroll[0], GUIStyle.none, GUI.skin.verticalScrollbar);
+		{
+			EditorGUIUtility.labelWidth = 100;
+
+			if (assetObj != null) assetObj.Update();
+			DrawEditorSettings();
+			DrawMapAssetProperties();
+			DrawMapProperties();
+            DrawLayers();
+            if (assetObj != null) assetObj.ApplyModifiedProperties();
+
+			DrawTileProperties(ev);
+			GUILayout.FlexibleSpace();
+		}
+		EditorGUILayout.EndScrollView();
+		EditorGUILayout.EndVertical();
+
+		// splitter
+		r.x = r.xMax; r.width = 5;
+
+		if (ev.type == EventType.Repaint)
+		{
+			GUI.skin.box.Draw(r, false, false, false, false);
+		}
+
+		EditorGUIUtility.AddCursorRect(r, MouseCursor.ResizeHorizontal);
+		if (ev.type == EventType.MouseDown && ev.button == 0 && r.Contains(ev.mousePosition))
+		{
+			ev.Use();
+			dragSplitter = true;
+		}
+
+		if (dragSplitter && ev.button == 0)
+		{
+			if (ev.type == EventType.MouseUp)
+			{
+				ev.Use();
+				dragSplitter = false;
+				doRepaint = true;
+				EditorPrefs.SetFloat("plyGameMapEd.panelWidth", panelWidth);
+			}
+
+			if (ev.type == EventType.MouseDrag)
+			{
+				ev.Use();
+				doRepaint = true;
+				panelWidth += ev.delta.x;
+				float f = position.width / 2f;
+				panelWidth = Mathf.Clamp(panelWidth, 150, f < 150 ? 150 : f);
+				EditorPrefs.SetFloat("plyGameMapEd.panelWidth", panelWidth);
+			}
+		}
+
+		if (ev.type == EventType.Repaint)
+		{
+			if (asset != _setAsset)
+			{
+				asset = _setAsset;
+				assetObj = null;
+				mapIdx = -1;
+				doRepaint = true;
+			}
+
+			if (asset != null)
+			{
+				if (assetEd == null || assetEd.target != asset)
+				{
+					if (assetEd != null) DestroyImmediate(assetEd);
+					assetEd = Editor.CreateEditor(asset);
+					doRepaint = true;
+				}
+
+				if (asset.tileAsset != null)
+				{
+					if (tilesEd == null || tilesEd.target != asset.tileAsset)
+					{
+						if (tilesEd != null) DestroyImmediate(tilesEd);
+						tilesEd = Editor.CreateEditor(asset.tileAsset);
+						CollectTilePreviewFields();
+						UpdateTileDefCache();
+						doRepaint = true;
+					}
+				}
+				else if (tilesEd != null)
+				{
+					DestroyImmediate(tilesEd);
+					tilesEd = null;
+					tileCache.Clear();
+					doRepaint = true;
+				}
+			}
+			else
+			{
+				if (assetEd != null)
+				{
+					DestroyImmediate(assetEd);
+					assetEd = null;
+					assetObj = null;
+					doRepaint = true;
+				}
+
+				if (tilesEd != null)
+				{
+					DestroyImmediate(tilesEd);
+					tilesEd = null;
+					tileCache.Clear();
+					doRepaint = true;
+				}
+			}
+
+			if (assetEd != null && assetObj == null)
+			{
+				assetObj = assetEd.serializedObject;
+				doRepaint = true;
+			}
+
+			if (asset != null && asset.maps.Count > 0 && mapIdx < 0)
+			{   // auto select 1st map
+				OnMapSelected(0);
+			}
+		}
+
+	}
+
+	private void CollectTilePreviewFields()
+	{
+		colField = null;
+		sprField = null;
+		intField = null;
+		strField = null;
+		flpField = null;
+
+		System.Type t = asset.tileAsset.tiles.GetType().GetGenericArguments()[0];
+		System.Type attribT = typeof(GameMapTilePreviewAttribute);
+		FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+		foreach (FieldInfo f in fields)
+		{
+			object[] attribs = f.GetCustomAttributes(attribT, false);
+			if (attribs.Length > 0)
+			{
+				if (colField == null && f.FieldType == typeof(Color)) { colField = f; continue; }
+				if (sprField == null && f.FieldType == typeof(Sprite)) { sprField = f; continue; }
+				if (intField == null && f.FieldType == typeof(int)) { intField = f; continue; }
+				if (strField == null && f.FieldType == typeof(string)) { strField = f; continue; }
+				if (flpField == null && f.FieldType == typeof(bool)) { flpField = f; continue; }
+			}
+		}
+	}
+
+	private void UpdateTileDefCache()
+	{
+		if (asset == null || asset.tileAsset == null) return;
+
+		tileCache.Clear();
+
+		foreach (GameMapTilesAsset.AutoTile at in asset.tileAsset.autoTiles)
+		{
+			foreach (GameMapTile tile in at.tiles)
+			{
+				TileDef def = new TileDef() { id = tile.id };
+				UpdateCachedValues(def, tile, true);
+				tileCache.Add(tile.id, def);
+			}
+		}
+
+		foreach (GameMapTile tile in asset.tileAsset.tiles)
+		{
+			TileDef def = new TileDef() { id = tile.id };
+			UpdateCachedValues(def, tile, false);
+			tileCache.Add(tile.id, def);
+		}
+	}
+
+	private void UpdateCachedValues(TileDef def, GameMapTile tile, bool isAuto)
+	{
+		def.color = Color.white;
+		def.sprite = null;
+		def.text = null;
+		def.flipped = false;
+		def.isAuto = isAuto;
+
+		if (colField != null)
+		{
+			def.color = (Color)colField.GetValue(tile);
+		}
+
+		if (sprField != null)
+		{
+			Sprite sp = (Sprite)sprField.GetValue(tile);
+			if (sp != null)
+			{
+				def.sprite = sp;
+				def.rect = new Rect(sp.rect.x / sp.texture.width, sp.rect.y / sp.texture.height, sp.rect.width / sp.texture.width, sp.rect.height / sp.texture.height);
+			}
+		}
+
+		if (strField != null)
+		{
+			string s = (string)strField.GetValue(tile);
+			if (!string.IsNullOrEmpty(s)) def.text = s;
+		}
+
+		if (intField != null && def.text == null)
+		{
+			int a = (int)intField.GetValue(tile);
+			if (a >= 0) def.text = a.ToString();
+		}
+
+		if (flpField != null)
+		{
+			def.flipped = (bool)flpField.GetValue(tile);
+		}
+	}
+
+	private void DrawEditorSettings()
+	{
+		EditorGUILayout.Space();
+		EditorGUI.BeginChangeCheck();
+		showEditorSettings = EditorGUILayout.Foldout(showEditorSettings, GC_EditorHead, true);
+		if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showEditorSettings", showEditorSettings);
+		if (showEditorSettings)
+		{
+			EditorGUI.BeginChangeCheck();
+			backColor = EditorGUILayout.ColorField(GC_BackCol, backColor);
+			if (EditorGUI.EndChangeCheck()) EditorPrefs_SetColor("plyGameMapEd.backColor", backColor);
+
+			EditorGUI.BeginChangeCheck();
+			gridColor = EditorGUILayout.ColorField(GC_GridCol, gridColor);
+			if (EditorGUI.EndChangeCheck()) EditorPrefs_SetColor("plyGameMapEd.gridColor", gridColor);
+
+			EditorGUI.BeginChangeCheck();
+			outsideMapIsSolid = EditorGUILayout.Toggle(GC_Solid, outsideMapIsSolid);
+			if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.outsideMapIsSolid", outsideMapIsSolid);
+
+			EditorGUI.BeginChangeCheck();
+			refTileSz = EditorGUILayout.FloatField(GC_AutoSz, refTileSz);
+			if (EditorGUI.EndChangeCheck()) EditorPrefs.SetFloat("plyGameMapEd.refTileSz", refTileSz);
+
+			EditorGUILayout.Space();
+		}
+	}
+
+	private void DrawMapAssetProperties()
+	{
+		GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f));
+		EditorGUI.BeginChangeCheck();
+		showAssetProperties = EditorGUILayout.Foldout(showAssetProperties, GC_AssetHead, true);
+		if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showAssetProps", showAssetProperties);
+		if (showAssetProperties)
+		{
+			EditorGUILayout.BeginHorizontal();
+			{
+				EditorGUI.BeginChangeCheck();
+				_setAsset = (GameMapsAsset)EditorGUILayout.ObjectField(_setAsset, typeof(GameMapsAsset), false, GUILayout.ExpandWidth(true));
+				if (EditorGUI.EndChangeCheck()) doRepaint = true;
+				if (GUILayout.Button(GC_new, EditorStyles.miniButtonRight, GUILayout.Width(50)))
+				{
+					string fn = EditorUtility.SaveFilePanel("Maps Asset", Application.dataPath, "maps", "asset");
+					if (!string.IsNullOrEmpty(fn))
+					{
+						GameMapsAsset a = LoadOrCreateAsset<GameMapsAsset>(fn);
+						if (a == null) EditorUtility.DisplayDialog("Error", "Could not create map asset", "OK");
+						else _setAsset = a as GameMapsAsset;
+						doRepaint = true;
+					}
+				}
+			}
+			EditorGUILayout.EndHorizontal();
+
+			if (assetObj != null)
+			{
+				EditorGUILayout.BeginHorizontal();
+				{
+					EditorGUI.BeginChangeCheck();
+					//EditorGUILayout.PropertyField(assetObj.FindProperty("tileAsset"), GUIContent.none);
+					GameMapTilesAsset tileAsset = (GameMapTilesAsset)EditorGUILayout.ObjectField(asset.tileAsset, typeof(GameMapTilesAsset), false, GUILayout.ExpandWidth(true));
+					if (EditorGUI.EndChangeCheck())
+					{
+						Undo.RecordObject(asset, "Set tiles asset");
+						asset.tileAsset = tileAsset;
+						doRepaint = true;
+					}
+					if (GUILayout.Button(GC_new, EditorStyles.miniButtonRight, GUILayout.Width(50)))
+					{
+						string fn = EditorUtility.SaveFilePanel("Tile Asset", Application.dataPath, "tiles", "asset");
+						if (!string.IsNullOrEmpty(fn))
+						{
+							tileAsset = LoadOrCreateAsset<GameMapTilesAsset>(fn);
+							if (tileAsset == null) EditorUtility.DisplayDialog("Error", "Could not create tiles asset", "OK");
+							else
+							{
+								Undo.RecordObject(asset, "Set tiles asset");
+								asset.tileAsset = tileAsset;
+							}
+							doRepaint = true;
+						}
+					}
+				}
+				EditorGUILayout.EndHorizontal();
+				EditorGUILayout.Space();
+
+				SerializedProperty iterator = assetObj.GetIterator();
+				iterator.NextVisible(true); // skip the "m_Script" property
+				bool enterChildren = true;
+				bool hadElems = false;
+				while (iterator.NextVisible(enterChildren))
+				{
+					enterChildren = false;
+					if (iterator.name == "maps") continue;
+					if (iterator.name == "tileAsset") continue;
+					if (iterator.name == "nextMapId") continue;
+					EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
+					hadElems = true;
+				}
+
+				if (hadElems) EditorGUILayout.Space();
+			}
+		}
+	}
+
+	private void DrawMapProperties()
+	{
+		if (assetObj == null) return;
+		GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f));
+		Rect r = EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
+		{
+			// map selection button
+			r.height = EditorGUIUtility.singleLineHeight;
+			r.x = r.xMax - 103f; r.width = 100f; r.height = 15f;
+			if (GUI.Button(r, GC_MapSelect))
+			{
+				mapsPopup.Asset = asset;
+				mapsPopup.OnMapSelected = OnMapSelected;
+				PopupWindow.Show(r, mapsPopup);
+			}
+
+			// the active map's properties
+			EditorGUI.BeginChangeCheck();
+			showMapProperties = EditorGUILayout.Foldout(showMapProperties, GC_MapHead, true);
+			if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showMapProps", showMapProperties);
+
+			if (showMapProperties)
+			{
+				EditorGUILayout.Space();
+
+				if (mapIdx >= 0 && mapIdx < asset.maps.Count)
+				{
+					EditorGUILayout.BeginHorizontal();
+					{
+						EditorGUILayout.PrefixLabel("Ident");
+						GUILayout.Label(asset.maps[mapIdx].id.ToString() + " => " + asset.maps[mapIdx].ident);
+						if (GUILayout.Button(GC_rename, EditorStyles.miniButtonRight)) GameMapTextEd.ShowEd("Rename map", "Enter a unique name", asset.maps[mapIdx].ident, OnRenameMap);
+						GUILayout.FlexibleSpace();
+					}
+					EditorGUILayout.EndHorizontal();
+
+					EditorGUILayout.BeginHorizontal();
+					{
+						EditorGUILayout.PrefixLabel("Size");
+						mapSize_w = EditorGUILayout.IntField(mapSize_w, GUILayout.Width(35));
+						GUILayout.Label("x");
+						mapSize_h = EditorGUILayout.IntField(mapSize_h, GUILayout.Width(35));
+						if (GUILayout.Button(GC_apply, EditorStyles.miniButtonRight))
+						{
+							Undo.RecordObject(asset, "Resize map");
+							asset.maps[mapIdx].Resize(mapSize_w, mapSize_h);
+							mapSize_w = asset.maps[mapIdx].width;
+							mapSize_h = asset.maps[mapIdx].height;
+						}
+						GUILayout.FlexibleSpace();
+					}
+					EditorGUILayout.EndHorizontal();
+
+					SerializedProperty maps = assetObj.FindProperty("maps");
+					SerializedProperty iterator = maps.GetArrayElementAtIndex(mapIdx);
+					SerializedProperty endprop = iterator.GetEndProperty();
+					bool enterChildren = true;
+					while (iterator.NextVisible(enterChildren))
+					{
+						enterChildren = false;
+						if (SerializedProperty.EqualContents(iterator, endprop)) break;
+						if (iterator.name == "id") continue;
+						if (iterator.name == "ident") continue;
+						if (iterator.name == "width") continue;
+						if (iterator.name == "height") continue;
+						if (iterator.name == "grid") continue;
+                        if (iterator.name == "layers") continue;
+                        EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
+					}
+
+					EditorGUILayout.Space();
+				}
+			}
+		}
+		EditorGUILayout.EndVertical();
+	}
+
+	private void OnMapSelected(int idx)
+	{
+		if (mapIdx == idx) return;
+
+		mapIdx = idx;
+		if (mapIdx >= asset.maps.Count) mapIdx = -1;
+
+		if (mapIdx >= 0)
+		{
+			mapSize_w = asset.maps[mapIdx].width;
+			mapSize_h = asset.maps[mapIdx].height;
+		}
+
+		pasting = false;
+		marking = false;
+		clearMarked = false;
+		markedTiles.Clear();
+
+		Repaint();
+	}
+
+	private void OnRenameMap(GameMapTextEd wiz)
+	{
+		string s = wiz.text;
+		wiz.Close();
+
+		if (!string.IsNullOrEmpty(s) && s != asset.maps[mapIdx].ident)
+		{
+			if (StringIsUnique(asset.maps, s))
+			{
+				Undo.RecordObject(asset, "Rename map");
+				asset.maps[mapIdx].ident = s;
+			}
+			else
+			{
+				EditorUtility.DisplayDialog("Error", "The map name must be unique.", "OK");
+			}
+		}
+
+		Repaint();
+	}
+
+    private void DrawLayers()
+    {
+        if (asset == null) return;
+        GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f));
+        Rect r = EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
+        {
+            if (showLayers)
+            {
+                // buttons
+                r.height = EditorGUIUtility.singleLineHeight;
+                r.x = r.xMax - 28f; r.width = 25f; r.height = 15f;
+
+                GUI.enabled = currLayer >= 0;
+                if (GUI.Button(r, GC_rem, EditorStyles.miniButtonRight))
+                {
+                    Undo.RecordObject(asset, "Remove Layer");
+                    ArrayUtility.RemoveAt(ref asset.maps[mapIdx].layers, currLayer);
+                    EditorUtility.SetDirty(asset);
+                    currLayer--;
+                    doRepaint = true;
+                }
+                r.x -= 25f;
+                GUI.enabled = true;
+                if (GUI.Button(r, GC_add, EditorStyles.miniButtonLeft))
+                {
+                    Undo.RecordObject(asset, "Add Layer");
+                    ArrayUtility.Add(ref asset.maps[mapIdx].layers, new GameMapLayer());
+                    asset.maps[mapIdx].InitLayer(asset.maps[mapIdx].layers.Length); // not -1 since special handling of grid[] vs layers[].grid
+                    EditorUtility.SetDirty(asset);
+                    doRepaint = true;
+                }
+            }
+
+            EditorGUI.BeginChangeCheck();
+            showLayers = EditorGUILayout.Foldout(showLayers, GC_LayersHead, true);
+            if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showLayers", showLayers);
+            if (showLayers)
+            {
+                if (layerHidden.Length != asset.maps[mapIdx].layers.Length + 1)
+                {
+                    layerHidden = new bool[asset.maps[mapIdx].layers.Length + 1];
+                }
+
+                EditorGUILayout.Space();
+                for (int i = -1; i < asset.maps[mapIdx].layers.Length; i++)
+                {
+                    DrawLayerEntry(i);
+                }
+                EditorGUILayout.Space();
+            }
+        }
+        EditorGUILayout.EndVertical();
+    }
+
+    private void DrawLayerEntry(int idx)
+    {
+        EditorGUILayout.BeginHorizontal();
+        {
+            layerHidden[idx + 1] = !GUILayout.Toggle(!layerHidden[idx + 1], GC_Viz, EditorStyles.miniButton, GUILayout.Width(25));
+            if (GUILayout.Toggle((idx == currLayer), "Layer " + (idx + 1), EditorStyles.miniButton)) currLayer = idx;
+        }
+        EditorGUILayout.EndHorizontal();
+    }
+
+	private void DrawTileProperties(Event ev)
+	{
+		if (asset == null || asset.tileAsset == null || tilesEd == null) return;
+
+		GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f));
+		Rect r = EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
+		{
+            if (showTileProperties)
+            {
+                // tile manipulation buttons
+                r.height = EditorGUIUtility.singleLineHeight;
+                r.x = r.xMax - 28f; r.width = 25f; r.height = 15f;
+
+                GUI.enabled = tileIdx >= 0;
+                if (GUI.Button(r, GC_rem, EditorStyles.miniButtonRight))
+                {
+                    if (autoTileSelected)
+                    {
+                        if (tileCache.ContainsKey(asset.tileAsset.autoTiles[tileIdx].tiles[0].id)) tileCache.Remove(asset.tileAsset.autoTiles[tileIdx].tiles[0].id);
+                        Undo.RecordObject(asset.tileAsset, "Remove Auto-Tile Definition");
+                        asset.tileAsset.RemoveAutoTileAtIndex(tileIdx);
+                        EditorUtility.SetDirty(asset.tileAsset);
+                        tileIdx--; if (tileIdx < 0 && asset.tileAsset.autoTiles.Count > 0) tileIdx = 0;
+                        if (tileIdx < 0 && asset.tileAsset.tiles.Count > 0) { tileIdx = 0; autoTileSelected = false; }
+                    }
+                    else
+                    {
+                        if (tileCache.ContainsKey(asset.tileAsset.tiles[tileIdx].id)) tileCache.Remove(asset.tileAsset.tiles[tileIdx].id);
+                        Undo.RecordObject(asset.tileAsset, "Remove Tile Definition");
+                        asset.tileAsset.RemoveTileAtIndex(tileIdx);
+                        EditorUtility.SetDirty(asset.tileAsset);
+                        tileIdx--; if (tileIdx < 0 && asset.tileAsset.tiles.Count > 0) tileIdx = 0;
+                        if (tileIdx < 0 && asset.tileAsset.autoTiles.Count > 0) { tileIdx = 0; autoTileSelected = true; }
+                    }
+                    doRepaint = true;
+                }
+                r.x -= 25f;
+                GUI.enabled = true;
+                if (GUI.Button(r, GC_add, EditorStyles.miniButtonLeft))
+                {
+                    if (addTileMenu == null)
+                    {
+                        addTileMenu = new GenericMenu();
+                        addTileMenu.AddItem(new GUIContent("Tile"), false, OnAddTile, 0);
+                        addTileMenu.AddItem(new GUIContent("Auto-16Tile"), false, OnAddTile, 1);
+                        addTileMenu.AddItem(new GUIContent("Auto-46Tile"), false, OnAddTile, 2);
+                    }
+
+                    addTileMenu.ShowAsContext();
+                }
+
+                r.x -= 28f;
+                GUI.enabled = !autoTileSelected && tileIdx < asset.tileAsset.tiles.Count - 1;
+                if (GUI.Button(r, GC_movR, EditorStyles.miniButtonRight))
+                {
+                    Undo.RecordObject(asset.tileAsset, "Move Tile Definition");
+                    GameMapTile t = asset.tileAsset.tiles[tileIdx];
+                    asset.tileAsset.tiles.RemoveAt(tileIdx);
+                    asset.tileAsset.tiles.Insert(++tileIdx, t);
+                    EditorUtility.SetDirty(asset.tileAsset);
+                    doRepaint = true;
+                }
+                r.x -= 25f;
+                GUI.enabled = !autoTileSelected && tileIdx > 0;
+                if (GUI.Button(r, GC_movL, EditorStyles.miniButtonLeft))
+                {
+                    Undo.RecordObject(asset.tileAsset, "Move Tile Definition");
+                    GameMapTile t = asset.tileAsset.tiles[tileIdx];
+                    asset.tileAsset.tiles.RemoveAt(tileIdx);
+                    asset.tileAsset.tiles.Insert(--tileIdx, t);
+                    EditorUtility.SetDirty(asset.tileAsset);
+                    doRepaint = true;
+                }
+                GUI.enabled = true;
+
+                r.x -= 28f;
+                if (GUI.Button(r, GC_clear, EditorStyles.miniButton))
+                {
+                    pasting = false;
+                    marking = false;
+                    clearMarked = false;
+                    markedTiles.Clear();
+                    tileIdx = -1;
+                    autoTileSelected = false;
+                    doRepaint = true;
+                }
+            }
+
+			EditorGUI.BeginChangeCheck();
+			showTileProperties = EditorGUILayout.Foldout(showTileProperties, GC_TilesHead, true);
+			if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showTileProps", showTileProperties);
+
+			if (showTileProperties && tileIdx >= 0 && ((!autoTileSelected && tileIdx < asset.tileAsset.tiles.Count) || (autoTileSelected && tileIdx < asset.tileAsset.autoTiles.Count)))
+			{
+				SerializedObject obj = tilesEd.serializedObject;
+				obj.Update();
+
+				SerializedProperty tileProp = null;
+				SerializedProperty endprop = null;
+
+				if (autoTileSelected)
+				{
+					SerializedProperty tilesProp = obj.FindProperty("autoTiles");
+					tileProp = tilesProp.GetArrayElementAtIndex(tileIdx);
+					tilesProp = tileProp.FindPropertyRelative("tiles");
+					tileProp = tilesProp.GetArrayElementAtIndex(0);
+					endprop = tileProp.GetEndProperty();
+
+					if (GUILayout.Button(GC_EditAuto, EditorStyles.miniButton, GUILayout.Width(EditorGUIUtility.labelWidth)))
+					{
+						GameMapAutoTileEd.Show_GameMapAutoTileEd(asset.tileAsset, asset.tileAsset.autoTiles[tileIdx], OnAutoTileChange);
+					}
+				}
+				else
+				{
+					SerializedProperty tilesProp = obj.FindProperty("tiles");
+					tileProp = tilesProp.GetArrayElementAtIndex(tileIdx);
+					endprop = tileProp.GetEndProperty();
+					EditorGUILayout.Space();
+				}
+
+				bool enterChildren = true;
+				bool didChange = false;
+				while (tileProp.NextVisible(enterChildren))
+				{
+					enterChildren = false;
+					if (SerializedProperty.EqualContents(tileProp, endprop)) break;
+					if (tileProp.name == "id") continue;
+					if (tileProp.name == "_aid") continue;
+					EditorGUI.BeginChangeCheck();
+					EditorGUILayout.PropertyField(tileProp, true, new GUILayoutOption[0]);
+					if (EditorGUI.EndChangeCheck()) didChange = true;
+				}
+
+				obj.ApplyModifiedProperties();
+				EditorGUILayout.Space();
+				if (didChange)
+				{
+					TileDef def = null;
+					GameMapTile t = autoTileSelected ? asset.tileAsset.autoTiles[tileIdx].tiles[0] : asset.tileAsset.tiles[tileIdx];
+					if (tileCache.TryGetValue(t.id, out def))
+					{
+						UpdateCachedValues(def, t, def.isAuto);
+					}
+				}
+			}
+		}
+		EditorGUILayout.EndVertical();
+
+		// draw the tile list
+		DrawTileList(ev);
+	}
+
+	private void OnAutoTileChange(int idx)
+	{
+		if (autoTileSelected && tileIdx >= 0 && tileIdx < asset.tileAsset.autoTiles.Count)
+		{
+			TileDef def = null;
+			GameMapTile t = asset.tileAsset.autoTiles[tileIdx].tiles[idx];
+			if (tileCache.TryGetValue(t.id, out def)) UpdateCachedValues(def, t, def.isAuto);
+			Repaint();
+		}
+	}
+
+	private void OnAddTile(object arg)
+	{
+		int opt = (int)arg;
+
+		if (opt == 0)
+		{
+			Undo.RecordObject(asset.tileAsset, "Add Tile Definition");
+			asset.tileAsset.AddTile();
+			EditorUtility.SetDirty(asset.tileAsset);
+			tileIdx = asset.tileAsset.tiles.Count - 1;
+			autoTileSelected = false;
+
+			TileDef def = new TileDef() { id = asset.tileAsset.tiles[tileIdx].id };
+			UpdateCachedValues(def, asset.tileAsset.tiles[tileIdx], false);
+			tileCache.Add(def.id, def);
+		}
+
+		else if (opt == 1 || opt == 2)
+		{
+			Undo.RecordObject(asset.tileAsset, "Add Auto-Tile Definition");
+			asset.tileAsset.AddAutoTile(opt == 2);
+			EditorUtility.SetDirty(asset.tileAsset);
+			tileIdx = asset.tileAsset.autoTiles.Count - 1;
+			autoTileSelected = true;
+
+			TileDef def = new TileDef() { id = asset.tileAsset.autoTiles[tileIdx].tiles[0].id };
+			UpdateCachedValues(def, asset.tileAsset.autoTiles[tileIdx].tiles[0], true);
+			tileCache.Add(def.id, def);
+		}
+
+		doRepaint = true;
+	}
+
+	private void DrawTileList(Event ev)
+	{
+		GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f));
+
+		Rect rr = GUILayoutUtility.GetLastRect();
+		if (ev.type == EventType.Repaint)
+		{
+			tileListH = Mathf.Ceil(asset.tileAsset.tiles.Count / ((rr.width - 10f) / (tileDrawSz + 5f)));
+			tileListH += 1f;
+			tileListH = tileListH * (tileDrawSz + 5f);
+		}
+
+		rr = GUILayoutUtility.GetRect(1f, tileListH, GUILayout.ExpandWidth(true));
+		Rect r = new Rect(5f, rr.y, tileDrawSz, tileDrawSz);
+
+		GUI.color = Color.white;
+		GUI.contentColor = Color.white;
+		GUI.backgroundColor = Color.white;
+
+		// *** auto-tiles
+		for (int i = 0; i < asset.tileAsset.autoTiles.Count; i++)
+		{
+			GameMapTile tile = asset.tileAsset.autoTiles[i].tiles[0];
+			TileDef def = null;
+			if (!tileCache.TryGetValue(tile.id, out def))
+			{
+				Debug.LogError("This should not happen.");
+				continue;
+			}
+
+			if (autoTileSelected && i == tileIdx && ev.type == EventType.Repaint)
+			{
+				GUI.skin.box.Draw(new Rect(r.x - 2, r.y - 2, r.width + 4, r.height + 4), false, false, false, false);
+			}
+
+			GUI.color = def.color;
+
+			if (def.sprite != null)
+			{
+				Rect r2 = r;
+				if (def.flipped) { r2.x += r.width; r2.width = -r.width; }
+				GUI.DrawTextureWithTexCoords(r2, def.sprite.texture, def.rect, true);
+				Styles.Tile.normal.background = null;
+			}
+			else
+			{
+				Styles.Tile.normal.background = EditorGUIUtility.whiteTexture;
+			}
+
+			TileContent.text = def.text;
+			if (GUI.Button(r, TileContent, Styles.Tile))
+			{
+				tileIdx = i;
+				autoTileSelected = true;
+				doRepaint = true;
+			}
+
+			GUI.color = Color.white;
+
+			r.x += tileDrawSz + 5f;
+			if (r.x > rr.xMax - (tileDrawSz + 5f)) { r.x = 5f; r.y += tileDrawSz + 5f; }
+		}
+
+		// *** normal tiles
+		for (int i = 0; i < asset.tileAsset.tiles.Count; i++)
+		{
+			GameMapTile tile = asset.tileAsset.tiles[i];
+			TileDef def = null;
+			if (!tileCache.TryGetValue(tile.id, out def))
+			{
+				Debug.LogError("This should not happen.");
+				continue;
+			}
+
+			if (!autoTileSelected && i == tileIdx && ev.type == EventType.Repaint)
+			{
+				GUI.skin.box.Draw(new Rect(r.x - 2, r.y - 2, r.width + 4, r.height + 4), false, false, false, false);
+			}
+
+			GUI.color = def.color;
+
+			if (def.sprite != null)
+			{
+				Rect r2 = r;
+				if (def.flipped) { r2.x += r.width; r2.width = -r.width; }
+				GUI.DrawTextureWithTexCoords(r2, def.sprite.texture, def.rect, true);
+				Styles.Tile.normal.background = null;
+			}
+			else
+			{
+				Styles.Tile.normal.background = EditorGUIUtility.whiteTexture;
+			}
+
+			TileContent.text = def.text;
+			if (GUI.Button(r, TileContent, Styles.Tile))
+			{
+				tileIdx = i;
+				autoTileSelected = false;
+				doRepaint = true;
+			}
+
+			GUI.color = Color.white;
+
+			// handle drag&drop of sprite onto tile list
+			if (sprField != null)
+			{
+				if (ev.type == EventType.DragUpdated && r.Contains(ev.mousePosition))
+				{
+					dragDropTarget = i;
+					DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
+					ev.Use();
+				}
+
+				if (ev.type == EventType.DragExited)
+				{
+					dragDropTarget = -1;
+				}
+
+				if (ev.type == EventType.DragPerform && dragDropTarget == i)
+				{
+					DragAndDrop.AcceptDrag();
+					ev.Use();
+					if (DragAndDrop.objectReferences.Length > 0)
+					{
+						Sprite sp = DragAndDrop.objectReferences[0] as Sprite;
+						if (sp == null)
+						{
+							Texture2D t = DragAndDrop.objectReferences[0] as Texture2D;
+							if (t != null)
+							{
+								UnityEngine.Object[] objs = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(t));
+								if (objs.Length > 1) sp = objs[1] as Sprite; // [0] is texture/parent so [1] is the 1st sprite in it
+							}
+						}
+						if (sp != null)
+						{
+							//sprField.SetValue(asset.tileAsset.tiles[i], sp);
+							//EditorUtility.SetDirty(asset.tileAsset);
+
+							SerializedObject obj = tilesEd.serializedObject;
+							obj.Update();
+							SerializedProperty tilesProp = obj.FindProperty("tiles");
+							SerializedProperty tileP = tilesProp.GetArrayElementAtIndex(i);
+							SerializedProperty spriteP = tileP.FindPropertyRelative(sprField.Name);
+							spriteP.objectReferenceValue = sp;
+							obj.ApplyModifiedProperties();
+
+							UpdateCachedValues(def, asset.tileAsset.tiles[i], def.isAuto);
+							doRepaint = true;
+						}
+					}
+					dragDropTarget = -1;
+				}
+			}
+
+			// ...
+			r.x += tileDrawSz + 5f;
+			if (r.x > rr.xMax - (tileDrawSz + 5f)) { r.x = 5f; r.y += tileDrawSz + 5f; }
+		}
+	}
+
+	#endregion
+	// ----------------------------------------------------------------------------------------------------------------
+	#region canvas
+
+	private void DrawCanvas(Event ev)
+	{
+		bool changed = GUI.changed;
+		GUI.changed = false;
+
+		GUILayout.Space(7);
+		scroll[1] = EditorGUILayout.BeginScrollView(scroll[1]);
+		{
+			if (asset == null || asset.tileAsset == null || mapIdx < 0)
+			{
+				GUILayout.FlexibleSpace();
+				EditorGUILayout.EndScrollView();
+				return;
+			}
+
+			GameMap map = asset.maps[mapIdx];
+			float w = map.width * tileDrawSz;
+			float h = map.height * tileDrawSz;
+			Rect mainRect = GUILayoutUtility.GetRect(w + 20f, h + 20f, GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(false));
+			mainRect.y += 3f; mainRect.width = w; mainRect.height = h;
+
+			int controlID = GUIUtility.GetControlID(EditorCanvasHash, FocusType.Keyboard);
+			if (ev.GetTypeForControl(controlID) == EventType.Repaint)
+			{
+				// black background
+				GUI.backgroundColor = backColor;
+				Styles.SolidWhite.Draw(mainRect, false, false, false, false);
+				GUI.backgroundColor = Color.white;
+
+                if (layerHidden.Length != asset.maps[mapIdx].layers.Length + 1)
+                {
+                    layerHidden = new bool[asset.maps[mapIdx].layers.Length + 1];
+                }
+
+                // draw placed tiles
+                Rect r = new Rect(mainRect.x, mainRect.yMax - tileDrawSz, tileDrawSz, tileDrawSz);
+                for (int i = map.layers.Length - 1; i >= 0; i--)
+                {
+                    if (!layerHidden[i + 1]) DrawGridTiles(mainRect, r, map.layers[i].grid);
+                }
+
+                if (!layerHidden[0]) DrawGridTiles(mainRect, r, map.grid);
+
+				// draw marked tiles overlay
+				if (markedTiles.Count > 0)
+				{
+					GUI.backgroundColor = new Color(0f, 1f, 0f, 0.5f);
+					foreach (int idx in markedTiles)
+					{
+						int x, y;
+						map.IdxToPosition(idx, out x, out y);
+						r.x = mainRect.x + (x * tileDrawSz);
+						r.y = mainRect.yMax - ((y+1) * tileDrawSz);
+						Styles.SolidWhite.Draw(r, false, false, false, false);
+					}
+					GUI.backgroundColor = Color.white;
+				}
+
+				// grid over everything
+				DrawGrid(mainRect, map.width, map.height);
+
+				// draw tiles to be pasted
+				if (pasting)
+				{
+					float offsX = mainRect.x + Mathf.Floor(ev.mousePosition.x / tileDrawSz) * tileDrawSz;
+					float offsY = mainRect.y + Mathf.Floor(ev.mousePosition.y / tileDrawSz) * tileDrawSz;
+					foreach (TileDef tile in copyBuffer)
+					{
+						r.x = offsX + (tile.x * tileDrawSz);
+						r.y = offsY - (tile.y * tileDrawSz);
+						if (r.x < mainRect.x || r.y < mainRect.y || r.x >= mainRect.xMax || r.y >= mainRect.yMax) continue;
+						if (tile.id >= 0) DrawTile(r, tile);
+						GUI.backgroundColor = new Color(0f, 1f, 0f, 0.5f);
+						Styles.SolidWhite.Draw(r, false, false, false, false);
+					}
+
+					GUI.backgroundColor = Color.white;
+				}
+			}
+
+			HandleCanvasEvents(mainRect, map, ev, controlID);
+		}
+		EditorGUILayout.EndScrollView();
+
+		if (GUI.changed)
+		{
+			EditorUtility.SetDirty(asset);
+			GUI.changed = changed;
+		}
+	}
+
+    private void DrawGridTiles(Rect mainRect, Rect r, int[] g)
+    {
+        for (int i = 0; i < g.Length; i++)
+        {
+            TileDef def = null;
+            if (tileCache.TryGetValue(g[i], out def)) DrawTile(r, def);
+
+            r.x += tileDrawSz;
+            if (r.x >= mainRect.xMax) { r.x = mainRect.x; r.y -= tileDrawSz; }
+        }
+    }
+
+    private void HandleCanvasEvents(Rect mainRect, GameMap map, Event ev, int controlID)
+	{
+		switch (ev.GetTypeForControl(controlID))
+		{
+			case EventType.MouseDown:
+			{
+				if (mainRect.Contains(ev.mousePosition))
+				{
+					if (GUIUtility.hotControl == 0)
+					{
+						GUIUtility.hotControl = controlID;
+						GUIUtility.keyboardControl = controlID;
+
+						if (pasting)
+						{
+							if (ev.button == 0)
+							{
+								DoPasteTiles(mainRect, ev);
+							}
+							else if (ev.button == 1)
+							{
+								pasting = false;
+								doRepaint = true;
+							}
+						}
+						else if (ev.button <= 1)
+						{
+							GridClick(mainRect, map, ev);
+							doRepaint = true;
+						}
+
+						ev.Use();
+					}
+				}
+				else
+				{
+					if (GUIUtility.keyboardControl == controlID)
+					{
+						GUIUtility.keyboardControl = 0;
+					}
+				}
+			} break;
+
+			case EventType.MouseUp:
+			{
+				if (GUIUtility.hotControl == controlID)
+				{
+					GUIUtility.hotControl = 0;
+					doRepaint = true;
+					ev.Use();
+				}
+			} break;
+
+			case EventType.MouseMove:
+			{
+				if (pasting) doRepaint = true;
+			} break;
+
+			case EventType.MouseDrag:
+			{
+				if (!pasting && GUIUtility.hotControl == controlID)
+				{
+					if (ev.button == 2)
+					{
+						scroll[1] = scroll[1] - ev.delta;
+					}
+					else
+					{
+						GridClick(mainRect, map, ev);
+					}
+
+					doRepaint = true;
+					ev.Use();
+				}
+			} break;
+
+			case EventType.KeyDown:
+			{
+				if (GUIUtility.keyboardControl == controlID)
+				{
+					if (ev.keyCode == KeyCode.Escape)
+					{
+						if (pasting)
+						{
+							pasting = false;
+							doRepaint = true;
+							ev.Use();
+						}
+						else if (marking)
+						{
+							marking = false;
+							clearMarked = false;
+							markedTiles.Clear();
+							doRepaint = true;
+							ev.Use();
+						}
+					}
+					else if (ev.keyCode == KeyCode.Delete && markedTiles.Count > 0)
+					{
+						DeleteMarkedTiles();
+						ev.Use();
+					}
+				}
+			} break;
+
+			case EventType.ValidateCommand:
+			{
+				switch (ev.commandName)
+				{
+					case "Duplicate": case "Cut": case "Copy": case "Paste": case "Delete": ev.Use(); break;
+				}
+			} break;
+
+			case EventType.ExecuteCommand:
+			{
+				switch (ev.commandName)
+				{
+					case "Duplicate": { if (markedTiles.Count > 0) { CopyMarkedTiles(true); EnterPasteMode(); ev.Use(); } } break;
+					case "Cut": { if (markedTiles.Count > 0) { CopyMarkedTiles(false); DeleteMarkedTiles(); ev.Use(); } } break;
+					case "Copy": { if (markedTiles.Count > 0) { CopyMarkedTiles(true); ev.Use(); } } break;
+					case "Paste": if (copyBuffer.Count > 0) { { EnterPasteMode(); ev.Use(); } } break;
+					case "Delete": { if (markedTiles.Count > 0) { DeleteMarkedTiles(); ev.Use(); } } break;
+				}
+			} break;
+		}
+	}
+
+	private void DrawTile(Rect r, TileDef def)
+	{
+		GUI.color = def.color;
+
+		if (def.sprite != null)
+		{
+			Rect rr = r;
+
+			if (def.isAuto && refTileSz > 0.0f)
+			{
+				rr.width *= def.sprite.rect.width / refTileSz;
+				rr.height *= def.sprite.rect.height / refTileSz;
+			}
+
+			if (def.flipped) { rr.x += rr.width; rr.width = -rr.width; }
+
+			GUI.DrawTextureWithTexCoords(rr, def.sprite.texture, def.rect, true);
+			Styles.Tile.normal.background = null;
+		}
+		else
+		{
+			Styles.Tile.normal.background = EditorGUIUtility.whiteTexture;
+		}
+
+		TileContent.text = def.text;
+		Styles.Tile.Draw(r, TileContent, false, false, false, false);
+
+		GUI.color = Color.white;
+	}
+
+	private void GridClick(Rect mainRect, GameMap map, Event ev)
+	{
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+        int idx = MousePosToGridIdx(map, ev);
+
+		if (ev.modifiers == EventModifiers.Shift && ev.button == 0)
+		{   // mark tiles in grid
+			if (idx >= 0 && idx < grid.Length)
+			{
+				if (clearMarked)
+				{
+					if (markedTiles.Contains(idx)) markedTiles.Remove(idx);
+					else if (ev.type == EventType.MouseDown)
+					{
+						clearMarked = false;
+						markedTiles.Add(idx);
+					}
+				}
+				else 
+				{
+					if (!markedTiles.Contains(idx)) markedTiles.Add(idx);
+					else if (ev.type == EventType.MouseDown)
+					{
+						clearMarked = true;
+						markedTiles.Remove(idx);
+					}
+					
+				}
+
+				marking = true;
+				doRepaint = true;
+			}
+		}
+
+		else if (idx >= 0 && idx < grid.Length)
+		{   // place or delete tiles in grid
+			if (autoTileSelected && ev.button == 0 && tileIdx >= 0 && tileIdx < asset.tileAsset.autoTiles.Count)
+			{
+				PaintAutoTile(map, idx);
+			}
+
+			else
+			{
+				int id = -1;
+				if (ev.button == 0 && !autoTileSelected) id = (tileIdx >= 0 && tileIdx < asset.tileAsset.tiles.Count ? asset.tileAsset.tiles[tileIdx].id : -1);
+				if (grid[idx] != id)
+				{
+					Undo.RecordObject(asset, id == -1 ? "Clear Tile" : "Place Tile");
+					grid[idx] = id;
+					doRepaint = true;
+					GUI.changed = true;
+				}
+			}
+		}
+	}
+
+	private void PaintAutoTile(GameMap map, int idx)
+	{
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+        int refAutoId = asset.tileAsset.autoTiles[tileIdx].id;
+		bool is16Tile = (asset.tileAsset.autoTiles[tileIdx].tiles.Length == 16);
+
+		int mainX, mainY;
+		map.IdxToPosition(idx, out mainX, out mainY);
+		int id = (is16Tile ? CalcAuto16TileId(map, refAutoId, mainX, mainY) : CalcAuto46TileId(map, refAutoId, mainX, mainY));
+
+		if (grid[idx] != id)
+		{
+			doRepaint = true;
+			GUI.changed = true;
+			Undo.RecordObject(asset, "Place Auto-Tile");
+			grid[idx] = id;
+
+			// update the neighbouring tiles
+			for (int ox = -1; ox <= 1; ox++)
+			{
+				for (int oy = -1; oy <= 1; oy++)
+				{
+					if (ox == 0 && oy == 0) continue;
+
+					int x = mainX + ox;
+					int y = mainY + oy;
+					if (x < 0 || y < 0 || x >= map.width || y >= map.height) continue;
+
+					idx = map.PositionToIdx(x, y);
+					if (grid[idx] < 0) continue;
+
+					GameMapTile t = asset.tileAsset.GetTile(grid[idx]);
+					if (t == null || t._aid != refAutoId) continue;
+
+					grid[idx] = (is16Tile ? CalcAuto16TileId(map, refAutoId, x, y) : CalcAuto46TileId(map, refAutoId, x, y));
+				}
+			}
+		}
+	}
+
+	private int CalcAuto16TileId(GameMap map, int refAutoId, int x, int y)
+	{
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+        int invalid = outsideMapIsSolid ? -2 : -1;
+		int[] neighbour_ids =
+		{
+			(y < map.height - 1 ? grid[map.PositionToIdx(x, y + 1)] : invalid ),
+			(x > 0 ? grid[map.PositionToIdx(x - 1, y)] : invalid ),
+			(x < map.width - 1 ? grid[map.PositionToIdx(x + 1, y)] : invalid ),
+			(y > 0 ? grid[map.PositionToIdx(x, y - 1)] : invalid )
+		};
+
+		for (int i = 0; i < neighbour_ids.Length; i++)
+		{
+			if (neighbour_ids[i] == -2)
+			{
+				neighbour_ids[i] = 1;
+				continue;
+			}
+
+			GameMapTile t = asset.tileAsset.GetTile(neighbour_ids[i]);
+			neighbour_ids[i] = (t == null || t._aid != refAutoId ? 0 : 1);
+		}
+
+		int at_idx = (neighbour_ids[0] * 1 + neighbour_ids[1] * 2 + neighbour_ids[2] * 4 + neighbour_ids[3] * 8);
+		return asset.tileAsset.autoTiles[tileIdx].tiles[at_idx].id;
+	}
+
+	private int CalcAuto46TileId(GameMap map, int refAutoId, int x, int y)
+	{
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+        int invalid = outsideMapIsSolid ? -2 : -1;
+		int[] neighbour_ids =
+		{
+			(y < map.height - 1 ? grid[map.PositionToIdx(x, y + 1)] : invalid ),							// 1: top
+			(x < map.width - 1 && y < map.height - 1 ? grid[map.PositionToIdx(x + 1, y + 1)] : invalid ),	// 2: top-right
+			(x < map.width - 1 ? grid[map.PositionToIdx(x + 1, y)] : invalid ),								// 4: right
+			(x < map.width - 1 && y > 0? grid[map.PositionToIdx(x + 1, y - 1)] : invalid ),					// 8: bottom-right
+			(y > 0 ? grid[map.PositionToIdx(x, y - 1)] : invalid ),											// 16: bottom
+			(x > 0 && y > 0 ? grid[map.PositionToIdx(x - 1, y - 1)] : invalid ),							// 32: bottom-left
+			(x > 0 ? grid[map.PositionToIdx(x - 1, y)] : invalid ),											// 64: left
+			(x > 0 && y < map.height - 1 ? grid[map.PositionToIdx(x - 1, y + 1)] : invalid ),				// 128: top-left
+		};
+
+		for (int i = 0; i < neighbour_ids.Length; i++)
+		{
+			if (neighbour_ids[i] == -2)
+			{
+				neighbour_ids[i] = 1;
+				continue;
+			}
+
+			GameMapTile t = asset.tileAsset.GetTile(neighbour_ids[i]);
+			neighbour_ids[i] = (t == null || t._aid != refAutoId ? 0 : 1);
+		}
+
+		int idx = (
+			neighbour_ids[0] * 1 + 
+			neighbour_ids[1] * 2 * (neighbour_ids[0] * neighbour_ids[2]) +		// corners are only valid if the sides are solid too
+			neighbour_ids[2] * 4 + 
+			neighbour_ids[3] * 8 * (neighbour_ids[2] * neighbour_ids[4]) +		// corners are only valid if the sides are solid too
+			neighbour_ids[4] * 16 + 
+			neighbour_ids[5] * 32 * (neighbour_ids[4] * neighbour_ids[6]) +		// corners are only valid if the sides are solid too
+			neighbour_ids[6] * 64 +
+			neighbour_ids[7] * 128 * (neighbour_ids[6] * neighbour_ids[0])		// corners are only valid if the sides are solid too
+			);
+
+		int mapped_idx;
+		if (map64.TryGetValue(idx, out mapped_idx))
+		{
+			return asset.tileAsset.autoTiles[tileIdx].tiles[mapped_idx].id;
+		}
+		else
+		{
+			Debug.LogError("Missing mapping: " + idx);
+		}
+
+		return -1;
+	}
+
+	private void DrawGrid(Rect r, int w, int h)
+	{
+		GUI.backgroundColor = gridColor;
+
+		Rect rr = r;
+		rr.width = 1f;
+		for (int i = 0; i <= w; i++)
+		{
+			rr.x = r.x + (i * tileDrawSz);
+			Styles.SolidWhite.Draw(rr, false, false, false, false);
+		}
+
+		rr = r;
+		rr.height = 1f;
+		for (int i = 0; i <= h; i++)
+		{
+			rr.y = r.y + (i * tileDrawSz);
+			Styles.SolidWhite.Draw(rr, false, false, false, false);
+		}
+
+		GUI.backgroundColor = Color.white;
+	}
+
+	private int MousePosToGridIdx(GameMap map, Event ev)
+	{
+		int x = Mathf.FloorToInt(ev.mousePosition.x / tileDrawSz);
+		int y = Mathf.FloorToInt(ev.mousePosition.y / tileDrawSz);
+		y = map.height - (y + 1); // map's Y starts from bottom-up
+		if (x < 0 || y < 0 || x >= map.width || y >= map.height) return -1;
+		return map.PositionToIdx(x, y);
+	}
+
+	private void CopyMarkedTiles(bool clearMarked)
+	{
+		copyBuffer.Clear();
+
+		GameMap map = asset.maps[mapIdx];
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+
+        int x=0, y=0, offsX=0, offsY=0;
+		markedTiles.Sort((a, b) => a.CompareTo(b));
+		map.IdxToPosition(markedTiles[markedTiles.Count / 2], out offsX, out offsY);
+
+		foreach (int idx in markedTiles)
+		{
+			map.IdxToPosition(idx, out x, out y);
+			TileDef t = (grid[idx] >= 0 ? tileCache[grid[idx]].Copy() : new TileDef() { id = -1 });
+			t.x = x - offsX;
+			t.y = y - offsY;
+			copyBuffer.Add(t);
+		}
+
+		if (clearMarked) markedTiles.Clear();
+		doRepaint = true;
+	}
+
+	private void DeleteMarkedTiles()
+	{
+		Undo.RecordObject(asset, "Remove Tiles");
+
+        GameMap map = asset.maps[mapIdx];
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+        foreach (int idx in markedTiles)
+		{
+			grid[idx] = -1;
+		}
+
+		markedTiles.Clear();
+		GUI.changed = true;
+		doRepaint = true;
+	}
+
+	private void EnterPasteMode()
+	{
+		pasting = true;
+		markedTiles.Clear();
+		doRepaint = true;
+	}
+
+	private void DoPasteTiles(Rect mainRect, Event ev)
+	{
+		Undo.RecordObject(asset, "Paste Tiles");
+
+		GameMap map = asset.maps[mapIdx];
+        int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid);
+		int xOffs = Mathf.FloorToInt(ev.mousePosition.x / tileDrawSz);
+		int yOffs = Mathf.FloorToInt(ev.mousePosition.y / tileDrawSz);
+		yOffs = map.height - (yOffs + 1); // map's Y starts from bottom-up
+		foreach (TileDef tile in copyBuffer)
+		{
+			int x = xOffs + tile.x;
+			int y = yOffs + tile.y;
+			if (x < 0 || x >= map.width || y < 0 || y >= map.height) continue;
+
+			grid[map.PositionToIdx(x, y)] = tile.id;
+		}
+
+		GUI.changed = true;
+		doRepaint = true;
+	}
+
+	#endregion
+	// ----------------------------------------------------------------------------------------------------------------
+	#region helpers
+
+	private T LoadOrCreateAsset<T>(string fn, bool createIfNotExist = true)
+		where T : ScriptableObject
+	{
+		if (!fn.StartsWith(Application.dataPath)) return null;
+		try
+		{
+			fn = "Assets" + fn.Replace(Application.dataPath, "");
+			ScriptableObject asset = AssetDatabase.LoadAssetAtPath(fn, typeof(T)) as ScriptableObject;
+			if (asset == null && createIfNotExist)
+			{
+				asset = CreateInstance(typeof(T));
+				AssetDatabase.CreateAsset(asset, fn);
+				AssetDatabase.SaveAssets();
+			}
+			return (T)asset;
+		}
+		catch
+		{
+			return null;
+		}
+	}
+
+	private ScriptableObject LoadOrCreateAsset(string fn, Type t, bool createIfNotExist = true)
+	{
+		if (!fn.StartsWith(Application.dataPath)) return null;
+		try
+		{
+			fn = "Assets" + fn.Replace(Application.dataPath, "");
+			ScriptableObject asset = AssetDatabase.LoadAssetAtPath(fn, t) as ScriptableObject;
+			if (asset == null && createIfNotExist)
+			{
+				asset = CreateInstance(t);
+				AssetDatabase.CreateAsset(asset, fn);
+				AssetDatabase.SaveAssets();
+			}
+			return asset;
+		}
+		catch
+		{
+			return null;
+		}
+	}
+
+	private bool StringIsUnique<T>(List<T> existingStrings, string str)
+	{
+		if (string.IsNullOrEmpty(str) || existingStrings == null) return false;
+		for (int i = 0; i < existingStrings.Count; i++)
+		{
+			if (existingStrings[i] == null) continue;
+			if (str.Equals(existingStrings[i].ToString())) return false;
+		}
+		return true;
+	}
+
+	private static void EditorPrefs_SetColor(string key, Color val)
+	{
+		EditorPrefs.SetString(key, string.Format("{0},{1},{2},{3}", val.r, val.g, val.b, val.a));
+	}
+
+	private static Color EditorPrefs_GetColor(string key, Color defaultValue)
+	{
+		Color res = defaultValue;
+		string val = EditorPrefs.GetString(key, null);
+		if (!string.IsNullOrEmpty(val))
+		{
+			string[] vals = val.Split(',');
+			if (vals.Length == 4)
+			{
+				float.TryParse(vals[0], out res.r);
+				float.TryParse(vals[1], out res.g);
+				float.TryParse(vals[2], out res.b);
+				float.TryParse(vals[3], out res.a);
+			}
+		}
+		return res;
+	}
+
+	#endregion
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapEditor.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ad9b63da28b88d84c8206d6dfe19b57e
+timeCreated: 1496306198
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 58 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTextEd.cs

@@ -0,0 +1,58 @@
+using UnityEngine;
+using UnityEditor;
+
+
+public class GameMapTextEd : EditorWindow
+{
+	public string text { get; private set; }
+
+	private string label;
+	private System.Action<GameMapTextEd> callback;
+	private bool accepted = false;
+	private bool lostFocus = false;
+
+	private static GUIStyle BottomBarStyle = null;
+
+	public static void ShowEd(string title, string label, string currText, System.Action<GameMapTextEd> callback)
+	{
+		GameMapTextEd wiz = GetWindow<GameMapTextEd>(true, title, true);
+		wiz.label = label;
+		wiz.text = currText;
+		wiz.callback = callback;
+		wiz.minSize = wiz.maxSize = new Vector2(250, 100);
+		wiz.ShowUtility();
+	}
+
+	void OnFocus() { lostFocus = false; }
+	void OnLostFocus() { lostFocus = true; }
+
+	void Update()
+	{
+		if (lostFocus) Close();
+		if (accepted && callback != null) callback(this);
+	}
+
+	void OnGUI()
+	{
+		if (BottomBarStyle == null)
+		{
+			BottomBarStyle = new GUIStyle(GUI.skin.FindStyle("ProjectBrowserBottomBarBg")) { padding = new RectOffset(3, 3, 8, 8), stretchHeight = false, stretchWidth = true, fixedHeight = 0, fixedWidth = 0 };
+		}
+
+		EditorGUILayout.Space();
+		GUILayout.Label(label);
+		text = EditorGUILayout.TextField(text);
+		GUILayout.FlexibleSpace();
+		EditorGUILayout.BeginHorizontal(BottomBarStyle);
+		{
+			GUILayout.FlexibleSpace();
+			if (GUILayout.Button("Accept", GUILayout.Width(80))) accepted = true;
+			GUILayout.Space(5);
+			if (GUILayout.Button("Cancel", GUILayout.Width(80))) Close();
+			GUILayout.FlexibleSpace();
+		}
+		EditorGUILayout.EndHorizontal();
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTextEd.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b65e1a2eb5ee0364f81a821cae653ed7
+timeCreated: 1496412507
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 18 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTilesAssetInspector.cs

@@ -0,0 +1,18 @@
+using UnityEngine;
+using UnityEditor;
+
+
+[CustomEditor(typeof(GameMapTilesAsset))]
+public class GameMapTilesAssetInspector : Editor
+{
+
+	public override void OnInspectorGUI()
+	{
+		if (GUILayout.Button("Open Maps Editor"))
+		{
+			GameMapEditor.Open_GameMapEditor();
+		}
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapTilesAssetInspector.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 08b5fb98f338cb54daf5dad00ee28a63
+timeCreated: 1496485405
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 18 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapsAssetInspector.cs

@@ -0,0 +1,18 @@
+using UnityEngine;
+using UnityEditor;
+
+
+[CustomEditor(typeof(GameMapsAsset))]
+public class GameMapsAssetInspector : Editor
+{
+
+	public override void OnInspectorGUI()
+	{
+		if (GUILayout.Button("Open Maps Editor"))
+		{
+			GameMapEditor.Open_GameMapEditor((GameMapsAsset)target);
+		}
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/Editor/GameMapsAssetInspector.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 459e1a96bcb0006489834fb3d5a99aeb
+timeCreated: 1496483763
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 210 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMap.cs

@@ -0,0 +1,210 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+
+/// <summary>
+/// A map/grid of tiles. The GameMapsAsset contains a list of these maps. 
+/// The map's 0x0 point is considered to be at the bottom-left and WxH at top-right
+/// </summary>
+[System.Serializable]
+public class GameMap
+{
+	/// <summary> a unique identifier for the map </summary>
+	public int id;
+
+	/// <summary> a unique name by which map can be identified </summary>
+	public string ident;
+
+	/// <summary> width of the map (determines how big grid is) </summary>
+	public int width;
+
+	/// <summary> height of map (determines how big grid is) </summary>
+	public int height;
+
+	/// <summary> The grid/map. -1 is an empty tile, else a value related to GameMapTile.id will be present 
+    /// This is also known as layer-0 or the default layer when there are movethan one layer in the map.
+    /// </summary>
+	public int[] grid = new int[0];
+
+    /// <summary> The GameMap can have additional layers. In that case the grid[] field above will be the default, or layer-0. </summary>
+    public GameMapLayer[] layers = new GameMapLayer[0];
+
+	// *** extra properties related to this map
+	// add any addition serializable types here and they will appear
+	// for editing in map properties section of the map editor
+
+	//public Color backgroundColor = Color.black;
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	/// <summary> Return the grid index of a tile at position (x,y). No error checking, x or y value is out of bounds, to improve performance. </summary>
+	public int PositionToIdx(int x, int y)
+	{
+		return (y * width + x);
+	}
+
+	/// <summary> Get an x and y position, given specific index into grid[]. No error checking, idx out of bounds, to improve performance. </summary>
+	public void IdxToPosition(int idx, out int x, out int y)
+	{
+		y = idx / width;
+		x = idx - (y * width);
+	}
+
+    /// <summary> This returns layers.Length + 1 since grid[] is layer-0. </summary>
+    public int LayerCount { get { return layers.Length + 1;  } }
+
+    /// <summary> Returns data from a layer. layerIdx=0 is the same as reading GameMap.grid[] while any higher value (1+) will be data from GameMap.layers[layerIdx-1].grid </summary>
+    public int[] GetlayerData(int layerIdx)
+    {
+        return (layerIdx == 0 ? grid : layers[layerIdx - 1].grid);
+    }
+
+	/// <summary> Return an array of GameMapIdxIdPair with the ID and Index of tiles neighbouring the one at x,y.
+	/// Array is always length 4 else 8 if includeDiagonal=true.
+	/// idx or id = -1 represents no tile or areas outside of map grid.
+	/// Result starts at tile above (north) and go around clockwise. </summary>
+	public GameMapIdxIdPair[] GetNeighbours(int x, int y, bool includeDiagonal = false, int layerIdx = 0)
+	{
+        int[] g = (layerIdx == 0 ? grid : layers[layerIdx - 1].grid);
+		if (includeDiagonal)
+		{
+			return new GameMapIdxIdPair[]
+				{
+					(y < height - 1 ?                   new GameMapIdxIdPair(g[((y + 1) * width + (x + 0))], ((y + 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)),
+					(x < width - 1 && y < height - 1 ?  new GameMapIdxIdPair(g[((y + 1) * width + (x + 1))], ((y + 1) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)),
+					(x < width - 1 ?                    new GameMapIdxIdPair(g[((y + 0) * width + (x + 1))], ((y + 0) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)),
+					(x < width - 1 && y > 0 ?           new GameMapIdxIdPair(g[((y - 1) * width + (x + 1))], ((y - 1) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)),
+					(y > 0 ?                            new GameMapIdxIdPair(g[((y - 1) * width + (x + 0))], ((y - 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)),
+					(x > 0 && y > 0 ?                   new GameMapIdxIdPair(g[((y - 1) * width + (x - 1))], ((y - 1) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1)),
+					(x > 0 ?                            new GameMapIdxIdPair(g[((y + 0) * width + (x - 1))], ((y + 0) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1)),
+					(x > 0 && y < height - 1 ?          new GameMapIdxIdPair(g[((y + 1) * width + (x - 1))], ((y + 1) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1))
+				};
+		}
+		else
+		{
+			return new GameMapIdxIdPair[]
+				{
+					(y < height - 1 ?   new GameMapIdxIdPair(g[((y + 1) * width + (x + 0))], ((y + 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)),
+					(x < width - 1 ?    new GameMapIdxIdPair(g[((y + 0) * width + (x + 1))], ((y + 0) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)),
+					(y > 0 ?            new GameMapIdxIdPair(g[((y - 1) * width + (x + 0))], ((y - 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)),
+					(x > 0 ?            new GameMapIdxIdPair(g[((y + 0) * width + (x - 1))], ((y + 0) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1))
+				};
+		}
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	/// <summary> This will destroy the exiting map. Use Resize if you want to keep existing tile data. Mainly used by editor. </summary>
+	public void SetSize(int w, int h)
+	{
+		if (w < 1) w = 1;
+		if (h < 1) h = 1;
+
+		width = w;
+		height = h;
+		grid = new int[width * height];
+        foreach(GameMapLayer l in layers) l.grid = new int[width * height];
+        ClearMap();
+	}
+
+    /// <summary> Resizes map, keeping existing tile data. Use SetSize() to create a clean resized map. Mainly used by editor. </summary>
+    public void Resize(int w, int h)
+	{
+		if (w < 1) w = 1;
+		if (h < 1) h = 1;
+
+		int[] old = grid;
+		grid = new int[w * h];
+        ClearLayer(0);
+
+		for (int y = 0; y < h; y++)
+		{
+			if (y >= height) break;
+			for (int x = 0; x < w; x++)
+			{
+				if (x >= width) break;
+				grid[(y * w + x)] = old[(y * width + x)];
+			}
+		}
+
+        for (int i =0; i < layers.Length; i++)
+        {
+            old = layers[i].grid;
+            layers[i].grid = new int[w * h];
+            ClearLayer(i+1);
+
+            for (int y = 0; y < h; y++)
+            {
+                if (y >= height) break;
+                for (int x = 0; x < w; x++)
+                {
+                    if (x >= width) break;
+                    layers[i].grid[(y * w + x)] = old[(y * width + x)];
+                }
+            }
+        }
+
+        width = w;
+		height = h;
+	}
+
+	/// <summary> Fill grid with empty tiles (-1). Mainly used by editor. </summary>
+	public void ClearMap()
+	{
+        for (int i = 0; i < grid.Length; i++)
+        {
+            grid[i] = -1;
+        }
+
+        foreach (GameMapLayer l in layers)
+        {
+            for (int i = 0; i < l.grid.Length; i++)
+            {
+                l.grid[i] = -1;
+            }
+        }
+    }
+
+    /// <summary> This set the size of the layer. This will destroy any exsiting tile placements in the layer.
+    /// idx=0 refers to the grid[] while anything higher will be layers[idx-1].grid </summary>
+    public void InitLayer(int idx)
+    {
+        if (idx == 0)
+        {
+            grid = new int[width * height];
+            ClearLayer(0);
+        }
+        else
+        {
+            layers[idx-1].grid = new int[width * height];
+            ClearLayer(idx);
+        }
+    }
+
+    /// <summary> idx=0 refers to the grid[] while anything higher will be layers[idx-1].grid </summary>
+    public void ClearLayer(int idx)
+    {
+        if (idx == 0)
+        {
+            for (int i = 0; i < grid.Length; i++)
+            {
+                grid[i] = -1;
+            }
+        }
+        else
+        {
+            idx--;
+            for (int i = 0; i < layers[idx].grid.Length; i++)
+            {
+                layers[idx].grid[i] = -1;
+            }
+        }
+    }
+
+	public override string ToString()
+	{
+		return ident;
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMap.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d8a0d0a4bd6f2604ea512be8d7332013
+timeCreated: 1496307023
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 17 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapIdxIdPair.cs

@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+
+public class GameMapIdxIdPair
+{
+	public int id;
+	public int idx;
+
+	public GameMapIdxIdPair(int id, int idx)
+	{
+		this.id = id;
+		this.idx = idx;
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapIdxIdPair.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c3aba858c13b65744be59a12864a164a
+timeCreated: 1500544708
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 17 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapLayer.cs

@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+
+/// <summary>
+/// A layer consists of a series of values in a grid.
+/// Each GameMap can have one or more layers.
+/// </summary>
+[System.Serializable]
+public class GameMapLayer
+{
+	/// <summary> The layer's grid of tile values. -1 is an empty tile, else a value related to GameMapTile.id will be present </summary>
+	public int[] grid = new int[0];
+
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapLayer.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 71a54717ca2c543478cacfc8b323e6fb
+timeCreated: 1500629685
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 50 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTile.cs

@@ -0,0 +1,50 @@
+using UnityEngine;
+
+
+/// <summary> A tile definition. The map/grid consist of an array of these tiles. </summary>
+[System.Serializable]
+public class GameMapTile
+{
+	// the tile needs a way to be identifiable in the editor. this can be done with either a sprite, colour, or value.
+	// simply add the [GameMapTilePreview] attribute above any Sprite, Color, String, or Int properties below.
+	// for String an empty value will be ignored. For Int negative numbers will be ignored.
+
+	/// <summary> Unique identifier for tile. This is the value stored in GameMap.grid[] (-1 is used for empty tiles in the grid) </summary>
+	public int id;
+
+	/// <summary> Sprite representing the tile. </summary>
+	[GameMapTilePreview] public Sprite sprite; // You may choose not to use this but do not remove it since it is required by auto-tiles system.
+
+	public int _aid = -1; // helper for auto-tiles; do not remove.
+
+	// *** extra properties related to this tile definition
+	// add any addition serializable types here and they will appear
+	// for editing in asset properties section of the map editor
+
+	// Note: 
+	//	Any of the fields following may be removed if you do not need/use them. They are here as an example. 
+	//	(of course the demo script makes use of them so update it too)
+	//	Remember to add/remove fields to CopyTo() function too
+
+	public enum Type { Start=0, End=1, Key=2, Coin=3, Block=4, Floor=20, Platform=21, NPC=30, Trap=40, Text=50 }
+	public Type type = Type.Floor;	// the runtime might use something like this to identify what the placed tile means
+	public int opt1 = 0;			// this value could depend on the chosen type. For example, if NPC then this could indicate which NPC prefab to spawn from an array of NPC prefabs.
+	
+	[GameMapTilePreview] public Color color = Color.white;
+	[GameMapTilePreview] public string strVal = "";
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	/// <summary> Copies this tile's data into target. </summary>
+	public void CopyTo(GameMapTile t)
+	{
+		t.id = id;
+		t.sprite = sprite;
+		t.type = type;
+		t.opt1 = opt1;
+		t.color = color;
+		t.strVal = strVal;
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTile.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c7f6e977fc562464bbd1cdbb3b5c3f6e
+timeCreated: 1496307023
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 6 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilePreviewAttribute.cs

@@ -0,0 +1,6 @@
+
+
+[System.AttributeUsage(System.AttributeTargets.Field)]
+public class GameMapTilePreviewAttribute : System.Attribute
+{
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilePreviewAttribute.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5b8f64edff4c4be4e823b69490d5c0b4
+timeCreated: 1496496120
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 104 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilesAsset.cs

@@ -0,0 +1,104 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+
+/// <summary> Container for all defined tiles. </summary>
+[System.Serializable]
+public class GameMapTilesAsset : ScriptableObject
+{
+	[SerializeField] public List<GameMapTile> tiles = new List<GameMapTile>();
+	[SerializeField] public List<AutoTile> autoTiles = new List<AutoTile>();
+	[SerializeField] private int nextTileId = 1;
+	[SerializeField] private int nextAutoTileId = 1;
+
+	[System.Serializable]
+	public class AutoTile
+	{
+		public int id;
+		public GameMapTile[] tiles; // 16 or 47 depending on system using including corners or not
+	}
+
+	private Dictionary<int, GameMapTile> _cache = null; // <Tile ID, Tile Definition>
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	/// <summary> Get the Tile by its unique ID. Remember that the ID is the value stored in 
+	/// GameMap.grid, not the tile's index in the GameMapTilesAsset.tiles list. </summary>
+	public GameMapTile GetTile(int id)
+	{
+		if (id < 0) return null;
+
+		if (_cache == null)
+		{
+			_cache = new Dictionary<int, GameMapTile>();
+			foreach (GameMapTile t in tiles)
+			{
+				_cache.Add(t.id, t);
+			}
+
+			foreach (AutoTile at in autoTiles)
+			{
+				_cache.Add(at.tiles[0].id, at.tiles[0]);
+
+				// copy the mainTile info into all auto-tile pieces, except for the sprite
+				// note; skip [0] on purpose since it is the main tile
+				for (int i = 1; i < at.tiles.Length; i++)
+				{
+					Sprite _sp = at.tiles[i].sprite;
+					int _id = at.tiles[i].id;
+					at.tiles[0].CopyTo(at.tiles[i]);
+					at.tiles[i].id = _id;
+					at.tiles[i].sprite = _sp;
+					_cache.Add(at.tiles[i].id, at.tiles[i]);
+				}
+			}
+		}
+
+		GameMapTile tile = null;
+		if (_cache.TryGetValue(id, out tile)) return tile;
+		return null;
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	/// <summary> Add tile definition. Mainly for editor use. </summary>
+	public void AddTile()
+	{
+		GameMapTile t = new GameMapTile() { id = nextTileId++ };
+
+		tiles.Add(t);
+		_cache = null;
+	}
+
+	/// <summary> Add auto-tile definition. Mainly for editor use. </summary>
+	public void AddAutoTile(bool withCorners)
+	{
+		AutoTile at = new AutoTile() { id = nextAutoTileId++, tiles = new GameMapTile[withCorners ? 47 : 16] };
+		for (int i = 0; i < at.tiles.Length; i++)
+		{
+			at.tiles[i] = new GameMapTile() { id = nextTileId++, _aid = at.id };
+		}
+
+		autoTiles.Add(at);
+		_cache = null;
+	}
+
+	/// <summary> Remove tile definition. Mainly for editor use. </summary>
+	public void RemoveTileAtIndex(int idx)
+	{
+		tiles.RemoveAt(idx);
+		if (tiles.Count == 0 && autoTiles.Count == 0) nextTileId = 1;
+		_cache = null;
+	}
+
+	/// <summary> Remove auto-tile definition. Mainly for editor use. </summary>
+	public void RemoveAutoTileAtIndex(int idx)
+	{
+		autoTiles.RemoveAt(idx);
+		if (tiles.Count == 0 && autoTiles.Count == 0) nextTileId = 1;
+		if (autoTiles.Count == 0) nextAutoTileId = 1;
+		_cache = null;
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapTilesAsset.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: cfd959e78eebfa6429e3b74d870c5669
+timeCreated: 1496485405
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 42 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapsAsset.cs

@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+
+/// <summary> Container for all defined maps. It also holds a reference the defined tiles. </summary>
+[System.Serializable]
+public class GameMapsAsset : ScriptableObject
+{
+	/// <summary> All maps created via MapEditor </summary>	
+	[SerializeField] public List<GameMap> maps = new List<GameMap>();
+
+	/// <summary> The tiles asset associated with the maps </summary>	
+	[SerializeField] public GameMapTilesAsset tileAsset;
+
+	[SerializeField] private int nextMapId = 1;
+
+	// *** extra properties related to this maps asset
+	// add any addition serializable types here and they will appear
+	// for editing in asset properties section of the map editor
+
+	// public string someProperty; // example
+
+	// ----------------------------------------------------------------------------------------------------------------
+
+	/// <summary> Add a new map. Mainly for use by the map editor. </summary>
+	public void AddMap()
+	{
+		GameMap m = new GameMap() { id = nextMapId, ident = "Map " + nextMapId };
+		m.SetSize(10, 10);
+		nextMapId++;
+		maps.Add(m);
+	}
+
+	/// <summary> Remove a map. Mainly for use by the map editor. </summary>
+	public void RemoveMapAtIndex(int idx)
+	{
+		maps.RemoveAt(idx);
+		if (maps.Count == 0) nextMapId = 1;
+	}
+
+	// ----------------------------------------------------------------------------------------------------------------
+}

+ 12 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/CoreScripts/GameMapsAsset.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4ee8a7d85ab66c3438f03e2771801706
+timeCreated: 1496307023
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 1d39e930333cb9f4bba94368590bfe9c
+folderAsset: yes
+timeCreated: 1499065790
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: a5f6c9e95cf0c5342aa706af5b956a80
+folderAsset: yes
+timeCreated: 1496994723
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

File diff suppressed because it is too large
+ 19 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/maps.asset


+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/maps.asset.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: bbf7388a54f14f842b7aecb67d709046
+timeCreated: 1496678615
+licenseType: Free
+NativeFormatImporter:
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 167 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/tiles.asset

@@ -0,0 +1,167 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: cfd959e78eebfa6429e3b74d870c5669, type: 3}
+  m_Name: tiles
+  m_EditorClassIdentifier: 
+  tiles:
+  - id: 4
+    sprite: {fileID: 0}
+    _aid: -1
+    type: 0
+    opt1: 0
+    color: {r: 0.15862083, g: 1, b: 0, a: 1}
+    strVal: start
+  - id: 5
+    sprite: {fileID: 0}
+    _aid: -1
+    type: 1
+    opt1: 0
+    color: {r: 1, g: 0, b: 0, a: 1}
+    strVal: end
+  - id: 6
+    sprite: {fileID: 21300000, guid: 65b0651ef19a49c4e9c6c4ff297c3d52, type: 3}
+    _aid: -1
+    type: 30
+    opt1: 0
+    color: {r: 1, g: 0, b: 0, a: 1}
+    strVal: 
+  - id: 7
+    sprite: {fileID: 21300000, guid: 65b0651ef19a49c4e9c6c4ff297c3d52, type: 3}
+    _aid: -1
+    type: 30
+    opt1: 1
+    color: {r: 0.862069, g: 1, b: 0, a: 1}
+    strVal: 
+  - id: 97
+    sprite: {fileID: 21300000, guid: 1776fa26195f4d14a8d19c15614b3dd1, type: 3}
+    _aid: -1
+    type: 40
+    opt1: 0
+    color: {r: 1, g: 1, b: 1, a: 1}
+    strVal: 
+  autoTiles:
+  - id: 1
+    tiles:
+    - id: 31
+      sprite: {fileID: 21300094, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 32
+      sprite: {fileID: 21300086, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 33
+      sprite: {fileID: 21300092, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 34
+      sprite: {fileID: 21300084, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 35
+      sprite: {fileID: 21300088, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 36
+      sprite: {fileID: 21300008, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 37
+      sprite: {fileID: 21300090, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 38
+      sprite: {fileID: 21300010, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 39
+      sprite: {fileID: 21300004, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 40
+      sprite: {fileID: 21300082, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 41
+      sprite: {fileID: 21300076, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 42
+      sprite: {fileID: 21300080, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 43
+      sprite: {fileID: 21300000, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 44
+      sprite: {fileID: 21300078, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 45
+      sprite: {fileID: 21300002, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+    - id: 46
+      sprite: {fileID: 21300006, guid: 40d48dc34acd41044a366ee03841e848, type: 3}
+      _aid: 1
+      type: 20
+      opt1: 0
+      color: {r: 1, g: 1, b: 1, a: 1}
+      strVal: 
+  nextTileId: 161
+  nextAutoTileId: 7

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/MapData/tiles.asset.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 2a61f0e3528b4c148a389cf6ed4f179e
+timeCreated: 1496678623
+licenseType: Free
+NativeFormatImporter:
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: c6356d405ac9d154f98519c4c81dc309
+folderAsset: yes
+timeCreated: 1499066053
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 113 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/FloorTile.prefab

@@ -0,0 +1,113 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1785946539236164
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 4052562210846084}
+  - component: {fileID: 212750468613699280}
+  - component: {fileID: 61042912524059136}
+  m_Layer: 8
+  m_Name: FloorTile
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &4052562210846084
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1785946539236164}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!212 &212750468613699280
+SpriteRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1785946539236164}
+  m_Enabled: 1
+  m_CastShadows: 0
+  m_ReceiveShadows: 0
+  m_DynamicOccludee: 1
+  m_StaticShadowCaster: 0
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RayTracingMode: 0
+  m_RayTraceProcedural: 0
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_ReceiveGI: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 1
+  m_SelectedEditorRenderState: 0
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+  m_Sprite: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_FlipX: 0
+  m_FlipY: 0
+  m_DrawMode: 0
+  m_Size: {x: 0.64, y: 0.64}
+  m_AdaptiveModeThreshold: 0.5
+  m_SpriteTileMode: 0
+  m_WasSpriteAssigned: 0
+  m_MaskInteraction: 0
+  m_SpriteSortPoint: 0
+--- !u!61 &61042912524059136
+BoxCollider2D:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1785946539236164}
+  m_Enabled: 1
+  m_Density: 1
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_UsedByEffector: 0
+  m_UsedByComposite: 0
+  m_Offset: {x: 0, y: 0}
+  m_SpriteTilingProperty:
+    border: {x: 0, y: 0, z: 0, w: 0}
+    pivot: {x: 0, y: 0}
+    oldSize: {x: 0, y: 0}
+    newSize: {x: 0, y: 0}
+    adaptiveTilingThreshold: 0
+    drawMode: 0
+    adaptiveTiling: 0
+  m_AutoTiling: 0
+  serializedVersion: 2
+  m_Size: {x: 0.32, y: 0.32}
+  m_EdgeRadius: 0

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/FloorTile.prefab.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: c242da35d5b354343bf7c851e86985f9
+timeCreated: 1497255712
+licenseType: Free
+NativeFormatImporter:
+  mainObjectFileID: 100100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 86 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/NPC1.prefab

@@ -0,0 +1,86 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1937426593683706
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 4898395561882668}
+  - component: {fileID: 212764839259425412}
+  m_Layer: 0
+  m_Name: NPC1
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &4898395561882668
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1937426593683706}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!212 &212764839259425412
+SpriteRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1937426593683706}
+  m_Enabled: 1
+  m_CastShadows: 0
+  m_ReceiveShadows: 0
+  m_DynamicOccludee: 1
+  m_StaticShadowCaster: 0
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RayTracingMode: 0
+  m_RayTraceProcedural: 0
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_ReceiveGI: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 1
+  m_SelectedEditorRenderState: 0
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+  m_Sprite: {fileID: 21300000, guid: 65b0651ef19a49c4e9c6c4ff297c3d52, type: 3}
+  m_Color: {r: 1, g: 0, b: 0, a: 1}
+  m_FlipX: 0
+  m_FlipY: 0
+  m_DrawMode: 0
+  m_Size: {x: 0.32, y: 0.32}
+  m_AdaptiveModeThreshold: 0.5
+  m_SpriteTileMode: 0
+  m_WasSpriteAssigned: 1
+  m_MaskInteraction: 0
+  m_SpriteSortPoint: 0

+ 9 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/NPC1.prefab.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: fd67b3c9abcfbfb419bfe5f0c7fe4777
+timeCreated: 1499066719
+licenseType: Free
+NativeFormatImporter:
+  mainObjectFileID: 100100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 86 - 0
ActionTowerDefense/Assets/GameLevelEditor/GameMap/Sample/Prefabs/NPC2.prefab

@@ -0,0 +1,86 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1495283989979954
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 4352991751251628}
+  - component: {fileID: 212115148741949868}
+  m_Layer: 0
+  m_Name: NPC2
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &4352991751251628
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1495283989979954}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!212 &212115148741949868
+SpriteRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1495283989979954}
+  m_Enabled: 1
+  m_CastShadows: 0
+  m_ReceiveShadows: 0
+  m_DynamicOccludee: 1
+  m_StaticShadowCaster: 0
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RayTracingMode: 0
+  m_RayTraceProcedural: 0
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_ReceiveGI: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 1
+  m_SelectedEditorRenderState: 0
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 0
+  m_SortingLayer: 0
+  m_SortingOrder: 0
+  m_Sprite: {fileID: 21300000, guid: 65b0651ef19a49c4e9c6c4ff297c3d52, type: 3}
+  m_Color: {r: 1, g: 0.9310343, b: 0, a: 1}
+  m_FlipX: 0
+  m_FlipY: 0
+  m_DrawMode: 0
+  m_Size: {x: 0.32, y: 0.32}
+  m_AdaptiveModeThreshold: 0.5
+  m_SpriteTileMode: 0
+  m_WasSpriteAssigned: 1
+  m_MaskInteraction: 0
+  m_SpriteSortPoint: 0

Some files were not shown because too many files changed in this diff