├── .gitignore ├── Assets ├── GameMap.meta └── GameMap │ ├── CoreScripts.meta │ ├── CoreScripts │ ├── Editor.meta │ ├── Editor │ │ ├── GameMapAutoTileEd.cs │ │ ├── GameMapAutoTileEd.cs.meta │ │ ├── GameMapEdPopup.cs │ │ ├── GameMapEdPopup.cs.meta │ │ ├── GameMapEditor.cs │ │ ├── GameMapEditor.cs.meta │ │ ├── GameMapTextEd.cs │ │ ├── GameMapTextEd.cs.meta │ │ ├── GameMapTilesAssetInspector.cs │ │ ├── GameMapTilesAssetInspector.cs.meta │ │ ├── GameMapsAssetInspector.cs │ │ └── GameMapsAssetInspector.cs.meta │ ├── GameMap.cs │ ├── GameMap.cs.meta │ ├── GameMapIdxIdPair.cs │ ├── GameMapIdxIdPair.cs.meta │ ├── GameMapLayer.cs │ ├── GameMapLayer.cs.meta │ ├── GameMapTile.cs │ ├── GameMapTile.cs.meta │ ├── GameMapTilePreviewAttribute.cs │ ├── GameMapTilePreviewAttribute.cs.meta │ ├── GameMapTilesAsset.cs │ ├── GameMapTilesAsset.cs.meta │ ├── GameMapsAsset.cs │ └── GameMapsAsset.cs.meta │ ├── Sample.meta │ ├── Sample │ ├── MapData.meta │ ├── MapData │ │ ├── maps.asset │ │ ├── maps.asset.meta │ │ ├── tiles.asset │ │ └── tiles.asset.meta │ ├── Prefabs.meta │ ├── Prefabs │ │ ├── FloorTile.prefab │ │ ├── FloorTile.prefab.meta │ │ ├── NPC1.prefab │ │ ├── NPC1.prefab.meta │ │ ├── NPC2.prefab │ │ ├── NPC2.prefab.meta │ │ ├── Player.prefab │ │ ├── Player.prefab.meta │ │ ├── Trap.prefab │ │ └── Trap.prefab.meta │ ├── Scripts.meta │ ├── Scripts │ │ ├── Main.cs │ │ └── Main.cs.meta │ ├── Sprites.meta │ ├── Sprites │ │ ├── character.png │ │ ├── character.png.meta │ │ ├── tiles.png │ │ ├── tiles.png.meta │ │ ├── trap.png │ │ └── trap.png.meta │ ├── sample-scene.unity │ └── sample-scene.unity.meta │ ├── readme-gamemap.txt │ └── readme-gamemap.txt.meta ├── README.md └── UNLICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | /ProjectSettings/ 8 | /_build/ 9 | /_work/ 10 | 11 | # Visual Studio 2015 cache directory 12 | /.vs/ 13 | 14 | # Autogenerated VS/MD/Consulo solution and project files 15 | ExportedObj/ 16 | .consulo/ 17 | *.csproj 18 | *.unityproj 19 | *.sln 20 | *.suo 21 | *.tmp 22 | *.user 23 | *.userprefs 24 | *.pidb 25 | *.booproj 26 | *.svd 27 | *.pdb 28 | 29 | # Unity3D generated meta files 30 | *.pidb.meta 31 | 32 | # Unity3D Generated File On Crash Reports 33 | sysinfo.txt 34 | 35 | # Builds 36 | *.apk 37 | *.unitypackage 38 | -------------------------------------------------------------------------------- /Assets/GameMap.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26b0d805c1521904bb7bdb6e322b4cbc 3 | folderAsset: yes 4 | timeCreated: 1499065755 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7437c853c71eb5c4d80ecec9f2bea192 3 | folderAsset: yes 4 | timeCreated: 1499065777 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2652cec61d711624394f35daaf9e998f 3 | folderAsset: yes 4 | timeCreated: 1496060542 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapAutoTileEd.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections.Generic; 4 | 5 | public class GameMapAutoTileEd : EditorWindow 6 | { 7 | private GameMapTilesAsset asset; 8 | private GameMapTilesAsset.AutoTile autoTile; 9 | private System.Action onChange; 10 | private bool is16Tile; 11 | 12 | private static readonly GUIContent GC_Close = new GUIContent("Close"); 13 | private static readonly GUIContent GC_Info = new GUIContent("Add sprites in spaces below"); 14 | 15 | public class StyleDefs 16 | { 17 | public GUIStyle WhiteBackground; 18 | 19 | public StyleDefs() 20 | { 21 | WhiteBackground = new GUIStyle() { normal = { background = EditorGUIUtility.whiteTexture } }; 22 | } 23 | } 24 | 25 | private static StyleDefs _styles; 26 | private static StyleDefs Styles { get { return _styles ?? (_styles = new StyleDefs()); } } 27 | 28 | int[,] map46 = 29 | { // T R B L 30 | { 1,0,1,0,1,0,1,0 }, // 0* 31 | { 0,0,1,0,1,0,1,0 }, // 1* 32 | { 1,0,0,0,1,0,1,0 }, // 4 33 | { 1,0,1,0,0,0,1,0 }, // 16 34 | { 1,0,1,0,1,0,0,0 }, // 64 35 | { 0,1,0,0,1,0,1,0 }, // 5* 36 | { 1,0,0,1,0,0,1,0 }, // 20 37 | { 1,0,1,0,0,1,0,0 }, // 80 38 | { 0,0,1,0,1,0,0,1 }, // 65 39 | { 0,0,0,0,1,0,1,0 }, // 7* 40 | { 1,0,0,0,0,0,1,0 }, // 28 41 | { 1,0,1,0,0,0,0,0 }, // 112 42 | { 0,0,1,0,1,0,0,0 }, // 193 43 | { 0,0,1,0,0,0,1,0 }, // 17* 44 | { 1,0,0,0,1,0,0,0 }, // 68 45 | { 0,1,0,1,0,0,1,0 }, // 21* 46 | { 1,0,0,1,0,1,0,0 }, // 84 47 | { 0,0,1,0,0,1,0,1 }, // 81 48 | { 0,1,0,0,1,0,0,1 }, // 69 49 | { 0,0,0,1,0,0,1,0 }, // 23* 50 | { 1,0,0,0,0,1,0,0 }, // 92 51 | { 0,0,1,0,0,0,0,1 }, // 113 52 | { 0,1,0,0,1,0,0,0 }, // 197 53 | { 0,1,0,0,0,0,1,0 }, // 29* 54 | { 1,0,0,1,0,0,0,0 }, // 116 55 | { 0,0,1,0,0,1,0,0 }, // 209 56 | { 0,0,0,0,1,0,0,1 }, // 71 57 | { 0,0,0,0,0,0,1,0 }, // 31* 58 | { 1,0,0,0,0,0,0,0 }, // 124 59 | { 0,0,1,0,0,0,0,0 }, // 214 60 | { 0,0,0,0,1,0,0,0 }, // 199 61 | { 0,1,0,1,0,1,0,1 }, // 85* 62 | { 0,0,0,1,0,1,0,1 }, // 87* 63 | { 0,1,0,0,0,1,0,1 }, // 93 64 | { 0,1,0,1,0,0,0,1 }, // 117 65 | { 0,1,0,1,0,1,0,0 }, // 213 66 | { 0,0,0,0,0,1,0,1 }, // 95* 67 | { 0,1,0,0,0,0,0,1 }, // 125 68 | { 0,1,0,1,0,0,0,0 }, // 245 69 | { 0,0,0,1,0,1,0,0 }, // 215 70 | { 0,0,0,1,0,0,0,1 }, // 119* 71 | { 0,1,0,0,0,1,0,0 }, // 221 72 | { 0,0,0,0,0,0,0,1 }, // 127* 73 | { 0,1,0,0,0,0,0,0 }, // 253 74 | { 0,0,0,1,0,0,0,0 }, // 247 75 | { 0,0,0,0,0,1,0,0 }, // 223 76 | { 0,0,0,0,0,0,0,0 }, // 255* 77 | }; 78 | 79 | // ---------------------------------------------------------------------------------------------------------------- 80 | 81 | public static void Show_GameMapAutoTileEd(GameMapTilesAsset asset, GameMapTilesAsset.AutoTile autoTile, System.Action onChange) 82 | { 83 | GameMapAutoTileEd win = GetWindow(true, "AutoTile Ed", true); 84 | win.asset = asset; 85 | win.autoTile = autoTile; 86 | win.is16Tile = autoTile.tiles.Length == 16; 87 | win.onChange = onChange; 88 | win.minSize = win.maxSize = new Vector2(win.is16Tile ? 175f : 495f, 220f); 89 | win.ShowUtility(); 90 | } 91 | 92 | private void OnFocus() 93 | { 94 | wantsMouseMove = true; 95 | } 96 | 97 | private void OnLostFocus() 98 | { 99 | wantsMouseMove = false; 100 | } 101 | 102 | private void OnGUI() 103 | { 104 | if (asset == null || autoTile == null) 105 | { 106 | Close(); 107 | GUIUtility.ExitGUI(); 108 | return; 109 | } 110 | 111 | if (GUILayout.Button(GC_Close)) 112 | { 113 | Close(); 114 | } 115 | 116 | GUILayout.Label(GC_Info); 117 | EditorGUILayout.Space(); 118 | Rect rect = GUILayoutUtility.GetRect(1f, 1f, 1f, 1f); 119 | Rect r = new Rect(rect.x + 10, rect.y + 10, 35, 35); 120 | 121 | if (Event.current.type == EventType.Repaint) 122 | { 123 | GUI.color = Color.white; 124 | Styles.WhiteBackground.Draw(new Rect(rect.x, rect.y, position.width, position.height), false, false, false, false); 125 | } 126 | 127 | for (int i = 0; i < autoTile.tiles.Length; i++) 128 | { 129 | EditorGUI.BeginChangeCheck(); 130 | autoTile.tiles[i].sprite = (Sprite)EditorGUI.ObjectField(r, autoTile.tiles[i].sprite, typeof(Sprite), false); 131 | if (EditorGUI.EndChangeCheck() && onChange != null) onChange(i); 132 | 133 | if (Event.current.type == EventType.Repaint) 134 | { 135 | if (autoTile.tiles[i].sprite != null) 136 | { 137 | GUI.color = Color.black; 138 | Styles.WhiteBackground.Draw(r, false, false, false, false); 139 | GUI.color = Color.white; 140 | Sprite sp = autoTile.tiles[i].sprite; 141 | 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); 142 | GUI.DrawTextureWithTexCoords(r, sp.texture, r2); 143 | } 144 | 145 | if (autoTile.tiles[i].sprite == null || r.Contains(Event.current.mousePosition)) 146 | { 147 | if (is16Tile) Draw16TileSample(r, i); 148 | else Draw46TileSample(r, i); 149 | } 150 | } 151 | 152 | r.x += 40; 153 | if ((is16Tile && r.x > 150) || r.x > 480) { r.x = rect.x + 10; r.y += 40; } 154 | } 155 | 156 | if (Event.current.type == EventType.MouseMove) 157 | { 158 | Repaint(); 159 | } 160 | 161 | if (GUI.changed) 162 | { 163 | EditorUtility.SetDirty(asset); 164 | GUI.changed = false; 165 | Repaint(); 166 | } 167 | } 168 | 169 | // I did not want to make project messy with sample textures so will just manually draw them with these functions 170 | 171 | private void Draw16TileSample(Rect r, int idx) 172 | { 173 | switch (idx) 174 | { 175 | case 0: DrawSample(r, true, true, true, true); break; 176 | case 1: DrawSample(r, false, true, true, true); break; 177 | case 2: DrawSample(r, true, true, false, true); break; 178 | case 3: DrawSample(r, false, true, false, true); break; 179 | case 4: DrawSample(r, true, true, true, false); break; 180 | case 5: DrawSample(r, false, true, true, false); break; 181 | case 6: DrawSample(r, true, true, false, false); break; 182 | case 7: DrawSample(r, false, true, false, false); break; 183 | case 8: DrawSample(r, true, false, true, true); break; 184 | case 9: DrawSample(r, false, false, true, true); break; 185 | case 10: DrawSample(r, true, false, false, true); break; 186 | case 11: DrawSample(r, false, false, false, true); break; 187 | case 12: DrawSample(r, true, false, true, false); break; 188 | case 13: DrawSample(r, false, false, true, false); break; 189 | case 14: DrawSample(r, true, false, false, false); break; 190 | case 15: DrawSample(r, false, false, false, false); break; 191 | } 192 | } 193 | 194 | private void Draw46TileSample(Rect r, int idx) 195 | { 196 | 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]); 197 | } 198 | 199 | private void DrawSample(Rect rect, int t, int tr, int r, int br, int b, int bl, int l, int tl) 200 | { 201 | GUI.color = Color.black; 202 | Styles.WhiteBackground.Draw(rect, false, false, false, false); 203 | GUI.color = Color.green; 204 | if (t == 1) DrawTopLine(rect); 205 | if (b == 1) DrawBottomLine(rect); 206 | if (l == 1) DrawLeftLine(rect); 207 | if (r == 1) DrawRightLine(rect); 208 | if (tl == 1) DrawTopLeftCorner(rect); 209 | if (tr == 1) DrawTopRightCorner(rect); 210 | if (bl == 1) DrawBottomLeftCorner(rect); 211 | if (br == 1) DrawBottomRightCorner(rect); 212 | GUI.color = Color.white; 213 | } 214 | 215 | private void DrawSample(Rect rect, bool t, bool b, bool l, bool r) 216 | { 217 | GUI.color = Color.black; 218 | Styles.WhiteBackground.Draw(rect, false, false, false, false); 219 | GUI.color = Color.green; 220 | if (t) DrawTopLine(rect); 221 | if (b) DrawBottomLine(rect); 222 | if (l) DrawLeftLine(rect); 223 | if (r) DrawRightLine(rect); 224 | GUI.color = Color.white; 225 | } 226 | 227 | private void DrawTopLine(Rect r) 228 | { 229 | r.y += 2f; r.height = 2f; 230 | r.x += 2f; r.width -= 4f; 231 | Styles.WhiteBackground.Draw(r, false, false, false, false); 232 | } 233 | 234 | private void DrawBottomLine(Rect r) 235 | { 236 | r.y = r.yMax - 4f; r.height = 2f; 237 | r.x += 2f; r.width -= 4f; 238 | Styles.WhiteBackground.Draw(r, false, false, false, false); 239 | } 240 | 241 | private void DrawLeftLine(Rect r) 242 | { 243 | r.y += 2f; r.height -= 4f; 244 | r.x += 2f; r.width = 2f; 245 | Styles.WhiteBackground.Draw(r, false, false, false, false); 246 | } 247 | 248 | private void DrawRightLine(Rect r) 249 | { 250 | r.y += 2f; r.height -= 4f; 251 | r.x = r.xMax - 4f; r.width = 2f; 252 | Styles.WhiteBackground.Draw(r, false, false, false, false); 253 | } 254 | 255 | private void DrawTopLeftCorner(Rect r) 256 | { 257 | DrawTopLine(new Rect(r.x, r.y + 5f, 10f, r.height)); 258 | DrawLeftLine(new Rect(r.x + 5f, r.y, r.width, 10f)); 259 | } 260 | 261 | private void DrawTopRightCorner(Rect r) 262 | { 263 | DrawTopLine(new Rect(r.xMax - 10f, r.y + 5f, 10f, r.height)); 264 | DrawRightLine(new Rect(r.x - 5f, r.y, r.width, 10f)); 265 | } 266 | 267 | private void DrawBottomRightCorner(Rect r) 268 | { 269 | DrawBottomLine(new Rect(r.xMax - 10f, r.y - 5f, 10f, r.height)); 270 | DrawRightLine(new Rect(r.x - 5, r.yMax - 10f, r.width, 10f)); 271 | } 272 | 273 | private void DrawBottomLeftCorner(Rect r) 274 | { 275 | DrawBottomLine(new Rect(r.x, r.y - 5f, 10f, r.height)); 276 | DrawLeftLine(new Rect(r.x + 5f, r.yMax - 10f, r.width, 10f)); 277 | } 278 | 279 | // ---------------------------------------------------------------------------------------------------------------- 280 | } 281 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapAutoTileEd.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a934a2fd7518625459c3c699e7edb283 3 | timeCreated: 1498646321 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapEdPopup.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using UnityEditorInternal; 4 | 5 | 6 | public class GameMapEdPopup : PopupWindowContent 7 | { 8 | public GameMapsAsset Asset { get; set; } 9 | public System.Action OnMapSelected { get; set; } 10 | 11 | private ReorderableList list; 12 | private Rect contentRect; 13 | private Vector2 scroll = Vector2.zero; 14 | 15 | private static readonly Vector2 popupSz = new Vector2(200f, 200f); 16 | private static readonly GUIContent GC_Head = new GUIContent("Maps"); 17 | private static readonly GUIContent GC_Add = new GUIContent("+"); 18 | private static readonly GUIContent GC_Rem = new GUIContent("-"); 19 | 20 | public override void OnOpen() 21 | { 22 | list = new ReorderableList(Asset.maps, typeof(GameMap), true, false, false, false) 23 | { 24 | elementHeight = EditorGUIUtility.singleLineHeight, 25 | headerHeight = 0, 26 | drawElementCallback = DrawElement, 27 | onSelectCallback = SelectMap 28 | }; 29 | 30 | contentRect = new Rect(0f, 18f, popupSz.x - 20f, Mathf.Max(popupSz.y - 18, EditorGUIUtility.singleLineHeight * Asset.maps.Count + 5)); 31 | } 32 | 33 | public override void OnClose() 34 | { 35 | list = null; 36 | Asset = null; 37 | OnMapSelected = null; 38 | } 39 | 40 | public override Vector2 GetWindowSize() 41 | { 42 | return popupSz; 43 | } 44 | 45 | public override void OnGUI(Rect r) 46 | { 47 | DrawHeader(new Rect(0, 0, r.width, 18)); 48 | r.y += 18; r.height -= 18; 49 | scroll = GUI.BeginScrollView(r, scroll, contentRect, false, true); 50 | list.DoList(r); 51 | GUI.EndScrollView(); 52 | 53 | } 54 | 55 | private void DrawHeader(Rect r) 56 | { 57 | if (ReorderableList.defaultBehaviours != null) 58 | { 59 | ReorderableList.defaultBehaviours.DrawHeaderBackground(r); 60 | } 61 | 62 | GUI.Label(r, GC_Head, EditorStyles.boldLabel); 63 | r.x = r.xMax - 25; r.width = 25; 64 | GUI.enabled = list.index >= 0; 65 | if (GUI.Button(r, GC_Rem, EditorStyles.miniButtonRight)) 66 | { 67 | if (list.index >= 0 && list.index < Asset.maps.Count) 68 | { 69 | Undo.RecordObject(Asset, "Remove Game Map"); 70 | Asset.RemoveMapAtIndex(list.index); 71 | contentRect = new Rect(0f, 18f, popupSz.x - 20f, Mathf.Max(popupSz.y - 18, EditorGUIUtility.singleLineHeight * Asset.maps.Count + 5)); 72 | OnMapSelected(-1); 73 | } 74 | } 75 | 76 | GUI.enabled = true; 77 | r.x -= 25; 78 | if (GUI.Button(r, GC_Add, EditorStyles.miniButtonLeft)) 79 | { 80 | Undo.RecordObject(Asset, "Add Game Map"); 81 | Asset.AddMap(); 82 | contentRect = new Rect(0f, 18f, popupSz.x - 20f, Mathf.Max(popupSz.y - 18, EditorGUIUtility.singleLineHeight * Asset.maps.Count + 5)); 83 | OnMapSelected(Asset.maps.Count - 1); 84 | } 85 | } 86 | 87 | private void DrawElement(Rect r, int index, bool isActive, bool isFocused) 88 | { 89 | GUI.Label(r, Asset.maps[index].ToString()); 90 | } 91 | 92 | private void SelectMap(ReorderableList list) 93 | { 94 | OnMapSelected(list.index); 95 | } 96 | 97 | // ---------------------------------------------------------------------------------------------------------------- 98 | } 99 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapEdPopup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5048a07a1aac52c4b9b111773e1612a5 3 | timeCreated: 1496403576 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEditor; 6 | 7 | public class GameMapEditor : EditorWindow 8 | { 9 | // ---------------------------------------------------------------------------------------------------------------- 10 | #region vars 11 | 12 | private static Color backColor = new Color(0f, 0f, 0f, 1f); 13 | private static Color gridColor = new Color(1f, 1f, 1f, 0.3f); 14 | private static bool outsideMapIsSolid = true; // if true then the areas outside map counts as solid of an auto-tile when doing auto-tile calculations 15 | private static float refTileSz = 0f; 16 | private static float panelWidth = 250f; 17 | private static bool showEditorSettings = true; 18 | private static bool showAssetProperties = true; 19 | private static bool showMapProperties = true; 20 | private static bool showTileProperties = true; 21 | private static bool showLayers = true; 22 | private static GameMapEdPopup mapsPopup = new GameMapEdPopup(); 23 | private static Vector2[] scroll = { Vector2.zero, Vector2.zero }; 24 | 25 | private bool dragSplitter = false; 26 | private bool doRepaint = false; 27 | 28 | private GameMapsAsset asset = null; 29 | private GameMapsAsset _setAsset = null; 30 | private int mapSize_w = 0; 31 | private int mapSize_h = 0; 32 | private int mapIdx = -1; 33 | private int tileIdx = -1; 34 | private bool autoTileSelected = false; 35 | private float tileDrawSz = 32f; 36 | private int dragDropTarget = -1; 37 | private int currLayer = -1; 38 | private bool[] layerHidden = new bool[0]; 39 | 40 | [NonSerialized] private float tileListH = 1f; 41 | [NonSerialized] private bool marking = false; 42 | [NonSerialized] private bool pasting = false; 43 | [NonSerialized] private bool clearMarked = false; 44 | 45 | [NonSerialized] private SerializedObject assetObj; 46 | [NonSerialized] private Editor assetEd = null; 47 | [NonSerialized] private Editor tilesEd = null; 48 | [NonSerialized] private Dictionary tileCache = new Dictionary(); 49 | [NonSerialized] private GUIContent TileContent = new GUIContent(); 50 | [NonSerialized] private List markedTiles = new List(); 51 | [NonSerialized] private List copyBuffer = new List(); 52 | 53 | [NonSerialized] private FieldInfo colField = null; 54 | [NonSerialized] private FieldInfo sprField = null; 55 | [NonSerialized] private FieldInfo intField = null; 56 | [NonSerialized] private FieldInfo strField = null; 57 | [NonSerialized] private FieldInfo flpField = null; 58 | 59 | private static int EditorCanvasHash = "GameMapEditorCanvasHash".GetHashCode(); 60 | 61 | #endregion 62 | // ---------------------------------------------------------------------------------------------------------------- 63 | #region defs 64 | 65 | private class TileDef 66 | { 67 | public string text; 68 | public Sprite sprite; 69 | public Rect rect; 70 | public Color color = Color.white; 71 | public bool flipped; 72 | public bool isAuto; 73 | 74 | // these are used by copy/paste system 75 | public int id; 76 | public int x, y; 77 | 78 | public TileDef Copy() 79 | { 80 | return new TileDef() 81 | { 82 | text = text, 83 | sprite = sprite, 84 | rect = rect, 85 | color = color, 86 | flipped = flipped, 87 | isAuto = isAuto, 88 | id = id, 89 | x = x, 90 | y = y 91 | }; 92 | } 93 | } 94 | 95 | private class StyleDefs 96 | { 97 | public GUIStyle Panel; 98 | public GUIStyle Tile; 99 | public GUIStyle SolidWhite; 100 | 101 | public StyleDefs() 102 | { 103 | GUISkin skin = GUI.skin; 104 | Panel = new GUIStyle(skin.FindStyle("PreferencesSectionBox")) { padding = new RectOffset(0, 0, 0, 3), margin = new RectOffset(0, 0, 0, 0), stretchHeight = true, stretchWidth = false }; 105 | Tile = new GUIStyle() { alignment = TextAnchor.MiddleCenter, fontSize = 12, fontStyle = FontStyle.Bold, normal = { textColor = Color.black, background = null } }; 106 | SolidWhite = new GUIStyle() { normal = { background = EditorGUIUtility.whiteTexture } }; 107 | } 108 | } 109 | 110 | private StyleDefs _styles = null; 111 | private StyleDefs Styles { get { return _styles ?? (_styles = new StyleDefs()); } } 112 | 113 | private static readonly GUIContent GC_MapSelect = new GUIContent("-select-"); 114 | private static readonly GUIContent GC_EditorHead = new GUIContent("Editor"); 115 | private static readonly GUIContent GC_AssetHead = new GUIContent("Asset"); 116 | private static readonly GUIContent GC_MapHead = new GUIContent("Map"); 117 | private static readonly GUIContent GC_LayersHead = new GUIContent("Layers"); 118 | private static readonly GUIContent GC_TilesHead = new GUIContent("Tiles"); 119 | private static readonly GUIContent GC_new = new GUIContent("new"); 120 | private static readonly GUIContent GC_rename = new GUIContent("ren", "Rename"); 121 | private static readonly GUIContent GC_apply = new GUIContent("apply"); 122 | private static readonly GUIContent GC_clear = new GUIContent("x", "Clear tile selection. Draw empty tiles."); 123 | private static readonly GUIContent GC_add = new GUIContent("+", "Add"); 124 | private static readonly GUIContent GC_rem = new GUIContent("-", "Remove selected"); 125 | private static readonly GUIContent GC_movL = new GUIContent("<", "Move selected"); 126 | private static readonly GUIContent GC_movR = new GUIContent(">", "Move selected"); 127 | private static readonly GUIContent GC_BackCol = new GUIContent("BackColor"); 128 | private static readonly GUIContent GC_GridCol = new GUIContent("GridColor"); 129 | private static readonly GUIContent GC_Solid = new GUIContent("Outside is Solid"); 130 | private static readonly GUIContent GC_AutoSz = new GUIContent("Auto-tile Size"); 131 | private static readonly GUIContent GC_EditAuto = new GUIContent("Setup Auto-tile"); 132 | private static readonly GUIContent GC_Viz = new GUIContent("*", "Toggle layer visblity in editor"); 133 | 134 | private GenericMenu addTileMenu = null; 135 | 136 | private static readonly Dictionary map64 = new Dictionary() 137 | { 138 | { 0, 0 }, 139 | { 1, 1 }, { 4, 2 }, { 16, 3 }, { 64, 4 }, 140 | { 5, 5 }, { 20, 6 }, { 80, 7 }, {65, 8 }, 141 | { 7, 9 }, { 28, 10 }, { 112, 11 }, { 193, 12 }, 142 | { 17, 13 }, { 68, 14 }, 143 | { 21, 15 }, { 84, 16 }, { 81, 17 }, { 69, 18 }, 144 | { 23, 19 }, { 92, 20 }, { 113, 21 }, { 197, 22 }, 145 | { 29, 23 }, { 116, 24 }, { 209, 25 }, { 71, 26 }, 146 | { 31, 27 }, { 124, 28 }, { 241, 29 }, { 199, 30 }, 147 | { 85, 31 }, 148 | { 87, 32 }, { 93, 33 }, { 117, 34 }, { 213, 35 }, 149 | { 95, 36 }, { 125, 37 }, { 245, 38 }, { 215, 39 }, 150 | { 119, 40 }, { 221, 41 }, 151 | { 127, 42 }, { 253, 43 }, { 247, 44 }, { 223, 45 }, 152 | { 255, 46 } 153 | }; 154 | 155 | #endregion 156 | // ---------------------------------------------------------------------------------------------------------------- 157 | #region system 158 | 159 | [MenuItem("Window/GameMap Editor")] 160 | public static void Open_GameMapEditor() 161 | { 162 | GetWindow("GameMap", true); 163 | } 164 | 165 | public static void Open_GameMapEditor(GameMapsAsset openAsset) 166 | { 167 | GameMapEditor win = GetWindow("GameMap", true); 168 | win._setAsset = openAsset; 169 | } 170 | 171 | private void OnEnable() 172 | { 173 | backColor = EditorPrefs_GetColor("plyGameMapEd.backColor", backColor); 174 | gridColor = EditorPrefs_GetColor("plyGameMapEd.gridColor", gridColor); 175 | outsideMapIsSolid = EditorPrefs.GetBool("plyGameMapEd.outsideMapIsSolid", outsideMapIsSolid); 176 | refTileSz = EditorPrefs.GetFloat("plyGameMapEd.refTileSz", refTileSz); 177 | panelWidth = EditorPrefs.GetFloat("plyGameMapEd.panelWidth", panelWidth); 178 | showEditorSettings = EditorPrefs.GetBool("plyGameMapEd.showEditorSettings", showEditorSettings); 179 | showAssetProperties = EditorPrefs.GetBool("plyGameMapEd.showAssetProps", showAssetProperties); 180 | showMapProperties = EditorPrefs.GetBool("plyGameMapEd.showMapProps", showMapProperties); 181 | showTileProperties = EditorPrefs.GetBool("plyGameMapEd.showTileProps", showTileProperties); 182 | showLayers = EditorPrefs.GetBool("plyGameMapEd.showLayers", showLayers); 183 | 184 | // auto load 1st found asset 185 | if (_setAsset == null) 186 | { 187 | GameMapsAsset[] assets = Resources.FindObjectsOfTypeAll(); 188 | if (assets.Length > 0) _setAsset = assets[0]; 189 | } 190 | 191 | Undo.undoRedoPerformed -= OnUnRedo; 192 | Undo.undoRedoPerformed += OnUnRedo; 193 | } 194 | 195 | private void OnDisable() 196 | { 197 | Undo.undoRedoPerformed -= OnUnRedo; 198 | } 199 | 200 | private void OnFocus() 201 | { 202 | wantsMouseMove = true; 203 | dragSplitter = false; 204 | marking = false; 205 | pasting = false; 206 | clearMarked = false; 207 | } 208 | 209 | private void OnLostFocus() 210 | { 211 | wantsMouseMove = false; 212 | marking = false; 213 | pasting = false; 214 | clearMarked = false; 215 | } 216 | 217 | private void OnGUI() 218 | { 219 | if (asset == null && assetObj != null) 220 | { // catch case where asset was manually deleted while active in editor 221 | assetEd = null; 222 | tilesEd = null; 223 | assetObj = null; 224 | tileCache.Clear(); 225 | GUIUtility.ExitGUI(); 226 | return; 227 | } 228 | 229 | Event ev = Event.current; 230 | EditorGUILayout.BeginHorizontal(); 231 | { 232 | DrawSideBar(ev); 233 | DrawCanvas(ev); 234 | } 235 | EditorGUILayout.EndHorizontal(); 236 | 237 | if (doRepaint) 238 | { 239 | doRepaint = false; 240 | Repaint(); 241 | } 242 | } 243 | 244 | private void OnUnRedo() 245 | { 246 | UpdateTileDefCache(); 247 | Repaint(); 248 | } 249 | 250 | #endregion 251 | // ---------------------------------------------------------------------------------------------------------------- 252 | #region side panel 253 | 254 | private void DrawSideBar(Event ev) 255 | { 256 | Rect r = EditorGUILayout.BeginVertical(Styles.Panel, GUILayout.Width(panelWidth)); 257 | scroll[0] = EditorGUILayout.BeginScrollView(scroll[0], GUIStyle.none, GUI.skin.verticalScrollbar); 258 | { 259 | EditorGUIUtility.labelWidth = 100; 260 | 261 | if (assetObj != null) assetObj.Update(); 262 | DrawEditorSettings(); 263 | DrawMapAssetProperties(); 264 | DrawMapProperties(); 265 | DrawLayers(); 266 | if (assetObj != null) assetObj.ApplyModifiedProperties(); 267 | 268 | DrawTileProperties(ev); 269 | GUILayout.FlexibleSpace(); 270 | } 271 | EditorGUILayout.EndScrollView(); 272 | EditorGUILayout.EndVertical(); 273 | 274 | // splitter 275 | r.x = r.xMax; r.width = 5; 276 | 277 | if (ev.type == EventType.Repaint) 278 | { 279 | GUI.skin.box.Draw(r, false, false, false, false); 280 | } 281 | 282 | EditorGUIUtility.AddCursorRect(r, MouseCursor.ResizeHorizontal); 283 | if (ev.type == EventType.MouseDown && ev.button == 0 && r.Contains(ev.mousePosition)) 284 | { 285 | ev.Use(); 286 | dragSplitter = true; 287 | } 288 | 289 | if (dragSplitter && ev.button == 0) 290 | { 291 | if (ev.type == EventType.MouseUp) 292 | { 293 | ev.Use(); 294 | dragSplitter = false; 295 | doRepaint = true; 296 | EditorPrefs.SetFloat("plyGameMapEd.panelWidth", panelWidth); 297 | } 298 | 299 | if (ev.type == EventType.MouseDrag) 300 | { 301 | ev.Use(); 302 | doRepaint = true; 303 | panelWidth += ev.delta.x; 304 | float f = position.width / 2f; 305 | panelWidth = Mathf.Clamp(panelWidth, 150, f < 150 ? 150 : f); 306 | EditorPrefs.SetFloat("plyGameMapEd.panelWidth", panelWidth); 307 | } 308 | } 309 | 310 | if (ev.type == EventType.Repaint) 311 | { 312 | if (asset != _setAsset) 313 | { 314 | asset = _setAsset; 315 | assetObj = null; 316 | mapIdx = -1; 317 | doRepaint = true; 318 | } 319 | 320 | if (asset != null) 321 | { 322 | if (assetEd == null || assetEd.target != asset) 323 | { 324 | if (assetEd != null) DestroyImmediate(assetEd); 325 | assetEd = Editor.CreateEditor(asset); 326 | doRepaint = true; 327 | } 328 | 329 | if (asset.tileAsset != null) 330 | { 331 | if (tilesEd == null || tilesEd.target != asset.tileAsset) 332 | { 333 | if (tilesEd != null) DestroyImmediate(tilesEd); 334 | tilesEd = Editor.CreateEditor(asset.tileAsset); 335 | CollectTilePreviewFields(); 336 | UpdateTileDefCache(); 337 | doRepaint = true; 338 | } 339 | } 340 | else if (tilesEd != null) 341 | { 342 | DestroyImmediate(tilesEd); 343 | tilesEd = null; 344 | tileCache.Clear(); 345 | doRepaint = true; 346 | } 347 | } 348 | else 349 | { 350 | if (assetEd != null) 351 | { 352 | DestroyImmediate(assetEd); 353 | assetEd = null; 354 | assetObj = null; 355 | doRepaint = true; 356 | } 357 | 358 | if (tilesEd != null) 359 | { 360 | DestroyImmediate(tilesEd); 361 | tilesEd = null; 362 | tileCache.Clear(); 363 | doRepaint = true; 364 | } 365 | } 366 | 367 | if (assetEd != null && assetObj == null) 368 | { 369 | assetObj = assetEd.serializedObject; 370 | doRepaint = true; 371 | } 372 | 373 | if (asset != null && asset.maps.Count > 0 && mapIdx < 0) 374 | { // auto select 1st map 375 | OnMapSelected(0); 376 | } 377 | } 378 | 379 | } 380 | 381 | private void CollectTilePreviewFields() 382 | { 383 | colField = null; 384 | sprField = null; 385 | intField = null; 386 | strField = null; 387 | flpField = null; 388 | 389 | System.Type t = asset.tileAsset.tiles.GetType().GetGenericArguments()[0]; 390 | System.Type attribT = typeof(GameMapTilePreviewAttribute); 391 | FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 392 | foreach (FieldInfo f in fields) 393 | { 394 | object[] attribs = f.GetCustomAttributes(attribT, false); 395 | if (attribs.Length > 0) 396 | { 397 | if (colField == null && f.FieldType == typeof(Color)) { colField = f; continue; } 398 | if (sprField == null && f.FieldType == typeof(Sprite)) { sprField = f; continue; } 399 | if (intField == null && f.FieldType == typeof(int)) { intField = f; continue; } 400 | if (strField == null && f.FieldType == typeof(string)) { strField = f; continue; } 401 | if (flpField == null && f.FieldType == typeof(bool)) { flpField = f; continue; } 402 | } 403 | } 404 | } 405 | 406 | private void UpdateTileDefCache() 407 | { 408 | if (asset == null || asset.tileAsset == null) return; 409 | 410 | tileCache.Clear(); 411 | 412 | foreach (GameMapTilesAsset.AutoTile at in asset.tileAsset.autoTiles) 413 | { 414 | foreach (GameMapTile tile in at.tiles) 415 | { 416 | TileDef def = new TileDef() { id = tile.id }; 417 | UpdateCachedValues(def, tile, true); 418 | tileCache.Add(tile.id, def); 419 | } 420 | } 421 | 422 | foreach (GameMapTile tile in asset.tileAsset.tiles) 423 | { 424 | TileDef def = new TileDef() { id = tile.id }; 425 | UpdateCachedValues(def, tile, false); 426 | tileCache.Add(tile.id, def); 427 | } 428 | } 429 | 430 | private void UpdateCachedValues(TileDef def, GameMapTile tile, bool isAuto) 431 | { 432 | def.color = Color.white; 433 | def.sprite = null; 434 | def.text = null; 435 | def.flipped = false; 436 | def.isAuto = isAuto; 437 | 438 | if (colField != null) 439 | { 440 | def.color = (Color)colField.GetValue(tile); 441 | } 442 | 443 | if (sprField != null) 444 | { 445 | Sprite sp = (Sprite)sprField.GetValue(tile); 446 | if (sp != null) 447 | { 448 | def.sprite = sp; 449 | 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); 450 | } 451 | } 452 | 453 | if (strField != null) 454 | { 455 | string s = (string)strField.GetValue(tile); 456 | if (!string.IsNullOrEmpty(s)) def.text = s; 457 | } 458 | 459 | if (intField != null && def.text == null) 460 | { 461 | int a = (int)intField.GetValue(tile); 462 | if (a >= 0) def.text = a.ToString(); 463 | } 464 | 465 | if (flpField != null) 466 | { 467 | def.flipped = (bool)flpField.GetValue(tile); 468 | } 469 | } 470 | 471 | private void DrawEditorSettings() 472 | { 473 | EditorGUILayout.Space(); 474 | EditorGUI.BeginChangeCheck(); 475 | showEditorSettings = EditorGUILayout.Foldout(showEditorSettings, GC_EditorHead, true); 476 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showEditorSettings", showEditorSettings); 477 | if (showEditorSettings) 478 | { 479 | EditorGUI.BeginChangeCheck(); 480 | backColor = EditorGUILayout.ColorField(GC_BackCol, backColor); 481 | if (EditorGUI.EndChangeCheck()) EditorPrefs_SetColor("plyGameMapEd.backColor", backColor); 482 | 483 | EditorGUI.BeginChangeCheck(); 484 | gridColor = EditorGUILayout.ColorField(GC_GridCol, gridColor); 485 | if (EditorGUI.EndChangeCheck()) EditorPrefs_SetColor("plyGameMapEd.gridColor", gridColor); 486 | 487 | EditorGUI.BeginChangeCheck(); 488 | outsideMapIsSolid = EditorGUILayout.Toggle(GC_Solid, outsideMapIsSolid); 489 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.outsideMapIsSolid", outsideMapIsSolid); 490 | 491 | EditorGUI.BeginChangeCheck(); 492 | refTileSz = EditorGUILayout.FloatField(GC_AutoSz, refTileSz); 493 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetFloat("plyGameMapEd.refTileSz", refTileSz); 494 | 495 | EditorGUILayout.Space(); 496 | } 497 | } 498 | 499 | private void DrawMapAssetProperties() 500 | { 501 | GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f)); 502 | EditorGUI.BeginChangeCheck(); 503 | showAssetProperties = EditorGUILayout.Foldout(showAssetProperties, GC_AssetHead, true); 504 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showAssetProps", showAssetProperties); 505 | if (showAssetProperties) 506 | { 507 | EditorGUILayout.BeginHorizontal(); 508 | { 509 | EditorGUI.BeginChangeCheck(); 510 | _setAsset = (GameMapsAsset)EditorGUILayout.ObjectField(_setAsset, typeof(GameMapsAsset), false, GUILayout.ExpandWidth(true)); 511 | if (EditorGUI.EndChangeCheck()) doRepaint = true; 512 | if (GUILayout.Button(GC_new, EditorStyles.miniButtonRight, GUILayout.Width(50))) 513 | { 514 | string fn = EditorUtility.SaveFilePanel("Maps Asset", Application.dataPath, "maps", "asset"); 515 | if (!string.IsNullOrEmpty(fn)) 516 | { 517 | GameMapsAsset a = LoadOrCreateAsset(fn); 518 | if (a == null) EditorUtility.DisplayDialog("Error", "Could not create map asset", "OK"); 519 | else _setAsset = a as GameMapsAsset; 520 | doRepaint = true; 521 | } 522 | } 523 | } 524 | EditorGUILayout.EndHorizontal(); 525 | 526 | if (assetObj != null) 527 | { 528 | EditorGUILayout.BeginHorizontal(); 529 | { 530 | EditorGUI.BeginChangeCheck(); 531 | //EditorGUILayout.PropertyField(assetObj.FindProperty("tileAsset"), GUIContent.none); 532 | GameMapTilesAsset tileAsset = (GameMapTilesAsset)EditorGUILayout.ObjectField(asset.tileAsset, typeof(GameMapTilesAsset), false, GUILayout.ExpandWidth(true)); 533 | if (EditorGUI.EndChangeCheck()) 534 | { 535 | Undo.RecordObject(asset, "Set tiles asset"); 536 | asset.tileAsset = tileAsset; 537 | doRepaint = true; 538 | } 539 | if (GUILayout.Button(GC_new, EditorStyles.miniButtonRight, GUILayout.Width(50))) 540 | { 541 | string fn = EditorUtility.SaveFilePanel("Tile Asset", Application.dataPath, "tiles", "asset"); 542 | if (!string.IsNullOrEmpty(fn)) 543 | { 544 | tileAsset = LoadOrCreateAsset(fn); 545 | if (tileAsset == null) EditorUtility.DisplayDialog("Error", "Could not create tiles asset", "OK"); 546 | else 547 | { 548 | Undo.RecordObject(asset, "Set tiles asset"); 549 | asset.tileAsset = tileAsset; 550 | } 551 | doRepaint = true; 552 | } 553 | } 554 | } 555 | EditorGUILayout.EndHorizontal(); 556 | EditorGUILayout.Space(); 557 | 558 | SerializedProperty iterator = assetObj.GetIterator(); 559 | iterator.NextVisible(true); // skip the "m_Script" property 560 | bool enterChildren = true; 561 | bool hadElems = false; 562 | while (iterator.NextVisible(enterChildren)) 563 | { 564 | enterChildren = false; 565 | if (iterator.name == "maps") continue; 566 | if (iterator.name == "tileAsset") continue; 567 | if (iterator.name == "nextMapId") continue; 568 | EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]); 569 | hadElems = true; 570 | } 571 | 572 | if (hadElems) EditorGUILayout.Space(); 573 | } 574 | } 575 | } 576 | 577 | private void DrawMapProperties() 578 | { 579 | if (assetObj == null) return; 580 | GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f)); 581 | Rect r = EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true)); 582 | { 583 | // map selection button 584 | r.height = EditorGUIUtility.singleLineHeight; 585 | r.x = r.xMax - 103f; r.width = 100f; r.height = 15f; 586 | if (GUI.Button(r, GC_MapSelect)) 587 | { 588 | mapsPopup.Asset = asset; 589 | mapsPopup.OnMapSelected = OnMapSelected; 590 | PopupWindow.Show(r, mapsPopup); 591 | } 592 | 593 | // the active map's properties 594 | EditorGUI.BeginChangeCheck(); 595 | showMapProperties = EditorGUILayout.Foldout(showMapProperties, GC_MapHead, true); 596 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showMapProps", showMapProperties); 597 | 598 | if (showMapProperties) 599 | { 600 | EditorGUILayout.Space(); 601 | 602 | if (mapIdx >= 0 && mapIdx < asset.maps.Count) 603 | { 604 | EditorGUILayout.BeginHorizontal(); 605 | { 606 | EditorGUILayout.PrefixLabel("Ident"); 607 | GUILayout.Label(asset.maps[mapIdx].id.ToString() + " => " + asset.maps[mapIdx].ident); 608 | if (GUILayout.Button(GC_rename, EditorStyles.miniButtonRight)) GameMapTextEd.ShowEd("Rename map", "Enter a unique name", asset.maps[mapIdx].ident, OnRenameMap); 609 | GUILayout.FlexibleSpace(); 610 | } 611 | EditorGUILayout.EndHorizontal(); 612 | 613 | EditorGUILayout.BeginHorizontal(); 614 | { 615 | EditorGUILayout.PrefixLabel("Size"); 616 | mapSize_w = EditorGUILayout.IntField(mapSize_w, GUILayout.Width(35)); 617 | GUILayout.Label("x"); 618 | mapSize_h = EditorGUILayout.IntField(mapSize_h, GUILayout.Width(35)); 619 | if (GUILayout.Button(GC_apply, EditorStyles.miniButtonRight)) 620 | { 621 | Undo.RecordObject(asset, "Resize map"); 622 | asset.maps[mapIdx].Resize(mapSize_w, mapSize_h); 623 | mapSize_w = asset.maps[mapIdx].width; 624 | mapSize_h = asset.maps[mapIdx].height; 625 | } 626 | GUILayout.FlexibleSpace(); 627 | } 628 | EditorGUILayout.EndHorizontal(); 629 | 630 | SerializedProperty maps = assetObj.FindProperty("maps"); 631 | SerializedProperty iterator = maps.GetArrayElementAtIndex(mapIdx); 632 | SerializedProperty endprop = iterator.GetEndProperty(); 633 | bool enterChildren = true; 634 | while (iterator.NextVisible(enterChildren)) 635 | { 636 | enterChildren = false; 637 | if (SerializedProperty.EqualContents(iterator, endprop)) break; 638 | if (iterator.name == "id") continue; 639 | if (iterator.name == "ident") continue; 640 | if (iterator.name == "width") continue; 641 | if (iterator.name == "height") continue; 642 | if (iterator.name == "grid") continue; 643 | if (iterator.name == "layers") continue; 644 | EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]); 645 | } 646 | 647 | EditorGUILayout.Space(); 648 | } 649 | } 650 | } 651 | EditorGUILayout.EndVertical(); 652 | } 653 | 654 | private void OnMapSelected(int idx) 655 | { 656 | if (mapIdx == idx) return; 657 | 658 | mapIdx = idx; 659 | if (mapIdx >= asset.maps.Count) mapIdx = -1; 660 | 661 | if (mapIdx >= 0) 662 | { 663 | mapSize_w = asset.maps[mapIdx].width; 664 | mapSize_h = asset.maps[mapIdx].height; 665 | } 666 | 667 | pasting = false; 668 | marking = false; 669 | clearMarked = false; 670 | markedTiles.Clear(); 671 | 672 | Repaint(); 673 | } 674 | 675 | private void OnRenameMap(GameMapTextEd wiz) 676 | { 677 | string s = wiz.text; 678 | wiz.Close(); 679 | 680 | if (!string.IsNullOrEmpty(s) && s != asset.maps[mapIdx].ident) 681 | { 682 | if (StringIsUnique(asset.maps, s)) 683 | { 684 | Undo.RecordObject(asset, "Rename map"); 685 | asset.maps[mapIdx].ident = s; 686 | } 687 | else 688 | { 689 | EditorUtility.DisplayDialog("Error", "The map name must be unique.", "OK"); 690 | } 691 | } 692 | 693 | Repaint(); 694 | } 695 | 696 | private void DrawLayers() 697 | { 698 | if (asset == null) return; 699 | GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f)); 700 | Rect r = EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true)); 701 | { 702 | if (showLayers) 703 | { 704 | // buttons 705 | r.height = EditorGUIUtility.singleLineHeight; 706 | r.x = r.xMax - 28f; r.width = 25f; r.height = 15f; 707 | 708 | GUI.enabled = currLayer >= 0; 709 | if (GUI.Button(r, GC_rem, EditorStyles.miniButtonRight)) 710 | { 711 | Undo.RecordObject(asset, "Remove Layer"); 712 | ArrayUtility.RemoveAt(ref asset.maps[mapIdx].layers, currLayer); 713 | EditorUtility.SetDirty(asset); 714 | currLayer--; 715 | doRepaint = true; 716 | } 717 | r.x -= 25f; 718 | GUI.enabled = true; 719 | if (GUI.Button(r, GC_add, EditorStyles.miniButtonLeft)) 720 | { 721 | Undo.RecordObject(asset, "Add Layer"); 722 | ArrayUtility.Add(ref asset.maps[mapIdx].layers, new GameMapLayer()); 723 | asset.maps[mapIdx].InitLayer(asset.maps[mapIdx].layers.Length); // not -1 since special handling of grid[] vs layers[].grid 724 | EditorUtility.SetDirty(asset); 725 | doRepaint = true; 726 | } 727 | } 728 | 729 | EditorGUI.BeginChangeCheck(); 730 | showLayers = EditorGUILayout.Foldout(showLayers, GC_LayersHead, true); 731 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showLayers", showLayers); 732 | if (showLayers) 733 | { 734 | if (layerHidden.Length != asset.maps[mapIdx].layers.Length + 1) 735 | { 736 | layerHidden = new bool[asset.maps[mapIdx].layers.Length + 1]; 737 | } 738 | 739 | EditorGUILayout.Space(); 740 | for (int i = -1; i < asset.maps[mapIdx].layers.Length; i++) 741 | { 742 | DrawLayerEntry(i); 743 | } 744 | EditorGUILayout.Space(); 745 | } 746 | } 747 | EditorGUILayout.EndVertical(); 748 | } 749 | 750 | private void DrawLayerEntry(int idx) 751 | { 752 | EditorGUILayout.BeginHorizontal(); 753 | { 754 | layerHidden[idx + 1] = !GUILayout.Toggle(!layerHidden[idx + 1], GC_Viz, EditorStyles.miniButton, GUILayout.Width(25)); 755 | if (GUILayout.Toggle((idx == currLayer), "Layer " + (idx + 1), EditorStyles.miniButton)) currLayer = idx; 756 | } 757 | EditorGUILayout.EndHorizontal(); 758 | } 759 | 760 | private void DrawTileProperties(Event ev) 761 | { 762 | if (asset == null || asset.tileAsset == null || tilesEd == null) return; 763 | 764 | GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f)); 765 | Rect r = EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true)); 766 | { 767 | if (showTileProperties) 768 | { 769 | // tile manipulation buttons 770 | r.height = EditorGUIUtility.singleLineHeight; 771 | r.x = r.xMax - 28f; r.width = 25f; r.height = 15f; 772 | 773 | GUI.enabled = tileIdx >= 0; 774 | if (GUI.Button(r, GC_rem, EditorStyles.miniButtonRight)) 775 | { 776 | if (autoTileSelected) 777 | { 778 | if (tileCache.ContainsKey(asset.tileAsset.autoTiles[tileIdx].tiles[0].id)) tileCache.Remove(asset.tileAsset.autoTiles[tileIdx].tiles[0].id); 779 | Undo.RecordObject(asset.tileAsset, "Remove Auto-Tile Definition"); 780 | asset.tileAsset.RemoveAutoTileAtIndex(tileIdx); 781 | EditorUtility.SetDirty(asset.tileAsset); 782 | tileIdx--; if (tileIdx < 0 && asset.tileAsset.autoTiles.Count > 0) tileIdx = 0; 783 | if (tileIdx < 0 && asset.tileAsset.tiles.Count > 0) { tileIdx = 0; autoTileSelected = false; } 784 | } 785 | else 786 | { 787 | if (tileCache.ContainsKey(asset.tileAsset.tiles[tileIdx].id)) tileCache.Remove(asset.tileAsset.tiles[tileIdx].id); 788 | Undo.RecordObject(asset.tileAsset, "Remove Tile Definition"); 789 | asset.tileAsset.RemoveTileAtIndex(tileIdx); 790 | EditorUtility.SetDirty(asset.tileAsset); 791 | tileIdx--; if (tileIdx < 0 && asset.tileAsset.tiles.Count > 0) tileIdx = 0; 792 | if (tileIdx < 0 && asset.tileAsset.autoTiles.Count > 0) { tileIdx = 0; autoTileSelected = true; } 793 | } 794 | doRepaint = true; 795 | } 796 | r.x -= 25f; 797 | GUI.enabled = true; 798 | if (GUI.Button(r, GC_add, EditorStyles.miniButtonLeft)) 799 | { 800 | if (addTileMenu == null) 801 | { 802 | addTileMenu = new GenericMenu(); 803 | addTileMenu.AddItem(new GUIContent("Tile"), false, OnAddTile, 0); 804 | addTileMenu.AddItem(new GUIContent("Auto-16Tile"), false, OnAddTile, 1); 805 | addTileMenu.AddItem(new GUIContent("Auto-46Tile"), false, OnAddTile, 2); 806 | } 807 | 808 | addTileMenu.ShowAsContext(); 809 | } 810 | 811 | r.x -= 28f; 812 | GUI.enabled = !autoTileSelected && tileIdx < asset.tileAsset.tiles.Count - 1; 813 | if (GUI.Button(r, GC_movR, EditorStyles.miniButtonRight)) 814 | { 815 | Undo.RecordObject(asset.tileAsset, "Move Tile Definition"); 816 | GameMapTile t = asset.tileAsset.tiles[tileIdx]; 817 | asset.tileAsset.tiles.RemoveAt(tileIdx); 818 | asset.tileAsset.tiles.Insert(++tileIdx, t); 819 | EditorUtility.SetDirty(asset.tileAsset); 820 | doRepaint = true; 821 | } 822 | r.x -= 25f; 823 | GUI.enabled = !autoTileSelected && tileIdx > 0; 824 | if (GUI.Button(r, GC_movL, EditorStyles.miniButtonLeft)) 825 | { 826 | Undo.RecordObject(asset.tileAsset, "Move Tile Definition"); 827 | GameMapTile t = asset.tileAsset.tiles[tileIdx]; 828 | asset.tileAsset.tiles.RemoveAt(tileIdx); 829 | asset.tileAsset.tiles.Insert(--tileIdx, t); 830 | EditorUtility.SetDirty(asset.tileAsset); 831 | doRepaint = true; 832 | } 833 | GUI.enabled = true; 834 | 835 | r.x -= 28f; 836 | if (GUI.Button(r, GC_clear, EditorStyles.miniButton)) 837 | { 838 | pasting = false; 839 | marking = false; 840 | clearMarked = false; 841 | markedTiles.Clear(); 842 | tileIdx = -1; 843 | autoTileSelected = false; 844 | doRepaint = true; 845 | } 846 | } 847 | 848 | EditorGUI.BeginChangeCheck(); 849 | showTileProperties = EditorGUILayout.Foldout(showTileProperties, GC_TilesHead, true); 850 | if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool("plyGameMapEd.showTileProps", showTileProperties); 851 | 852 | if (showTileProperties && tileIdx >= 0 && ((!autoTileSelected && tileIdx < asset.tileAsset.tiles.Count) || (autoTileSelected && tileIdx < asset.tileAsset.autoTiles.Count))) 853 | { 854 | SerializedObject obj = tilesEd.serializedObject; 855 | obj.Update(); 856 | 857 | SerializedProperty tileProp = null; 858 | SerializedProperty endprop = null; 859 | 860 | if (autoTileSelected) 861 | { 862 | SerializedProperty tilesProp = obj.FindProperty("autoTiles"); 863 | tileProp = tilesProp.GetArrayElementAtIndex(tileIdx); 864 | tilesProp = tileProp.FindPropertyRelative("tiles"); 865 | tileProp = tilesProp.GetArrayElementAtIndex(0); 866 | endprop = tileProp.GetEndProperty(); 867 | 868 | if (GUILayout.Button(GC_EditAuto, EditorStyles.miniButton, GUILayout.Width(EditorGUIUtility.labelWidth))) 869 | { 870 | GameMapAutoTileEd.Show_GameMapAutoTileEd(asset.tileAsset, asset.tileAsset.autoTiles[tileIdx], OnAutoTileChange); 871 | } 872 | } 873 | else 874 | { 875 | SerializedProperty tilesProp = obj.FindProperty("tiles"); 876 | tileProp = tilesProp.GetArrayElementAtIndex(tileIdx); 877 | endprop = tileProp.GetEndProperty(); 878 | EditorGUILayout.Space(); 879 | } 880 | 881 | bool enterChildren = true; 882 | bool didChange = false; 883 | while (tileProp.NextVisible(enterChildren)) 884 | { 885 | enterChildren = false; 886 | if (SerializedProperty.EqualContents(tileProp, endprop)) break; 887 | if (tileProp.name == "id") continue; 888 | if (tileProp.name == "_aid") continue; 889 | EditorGUI.BeginChangeCheck(); 890 | EditorGUILayout.PropertyField(tileProp, true, new GUILayoutOption[0]); 891 | if (EditorGUI.EndChangeCheck()) didChange = true; 892 | } 893 | 894 | obj.ApplyModifiedProperties(); 895 | EditorGUILayout.Space(); 896 | if (didChange) 897 | { 898 | TileDef def = null; 899 | GameMapTile t = autoTileSelected ? asset.tileAsset.autoTiles[tileIdx].tiles[0] : asset.tileAsset.tiles[tileIdx]; 900 | if (tileCache.TryGetValue(t.id, out def)) 901 | { 902 | UpdateCachedValues(def, t, def.isAuto); 903 | } 904 | } 905 | } 906 | } 907 | EditorGUILayout.EndVertical(); 908 | 909 | // draw the tile list 910 | DrawTileList(ev); 911 | } 912 | 913 | private void OnAutoTileChange(int idx) 914 | { 915 | if (autoTileSelected && tileIdx >= 0 && tileIdx < asset.tileAsset.autoTiles.Count) 916 | { 917 | TileDef def = null; 918 | GameMapTile t = asset.tileAsset.autoTiles[tileIdx].tiles[idx]; 919 | if (tileCache.TryGetValue(t.id, out def)) UpdateCachedValues(def, t, def.isAuto); 920 | Repaint(); 921 | } 922 | } 923 | 924 | private void OnAddTile(object arg) 925 | { 926 | int opt = (int)arg; 927 | 928 | if (opt == 0) 929 | { 930 | Undo.RecordObject(asset.tileAsset, "Add Tile Definition"); 931 | asset.tileAsset.AddTile(); 932 | EditorUtility.SetDirty(asset.tileAsset); 933 | tileIdx = asset.tileAsset.tiles.Count - 1; 934 | autoTileSelected = false; 935 | 936 | TileDef def = new TileDef() { id = asset.tileAsset.tiles[tileIdx].id }; 937 | UpdateCachedValues(def, asset.tileAsset.tiles[tileIdx], false); 938 | tileCache.Add(def.id, def); 939 | } 940 | 941 | else if (opt == 1 || opt == 2) 942 | { 943 | Undo.RecordObject(asset.tileAsset, "Add Auto-Tile Definition"); 944 | asset.tileAsset.AddAutoTile(opt == 2); 945 | EditorUtility.SetDirty(asset.tileAsset); 946 | tileIdx = asset.tileAsset.autoTiles.Count - 1; 947 | autoTileSelected = true; 948 | 949 | TileDef def = new TileDef() { id = asset.tileAsset.autoTiles[tileIdx].tiles[0].id }; 950 | UpdateCachedValues(def, asset.tileAsset.autoTiles[tileIdx].tiles[0], true); 951 | tileCache.Add(def.id, def); 952 | } 953 | 954 | doRepaint = true; 955 | } 956 | 957 | private void DrawTileList(Event ev) 958 | { 959 | GUILayout.Box(GUIContent.none, GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.Height(3f)); 960 | 961 | Rect rr = GUILayoutUtility.GetLastRect(); 962 | if (ev.type == EventType.Repaint) 963 | { 964 | tileListH = Mathf.Ceil(asset.tileAsset.tiles.Count / ((rr.width - 10f) / (tileDrawSz + 5f))); 965 | tileListH += 1f; 966 | tileListH = tileListH * (tileDrawSz + 5f); 967 | } 968 | 969 | rr = GUILayoutUtility.GetRect(1f, tileListH, GUILayout.ExpandWidth(true)); 970 | Rect r = new Rect(5f, rr.y, tileDrawSz, tileDrawSz); 971 | 972 | GUI.color = Color.white; 973 | GUI.contentColor = Color.white; 974 | GUI.backgroundColor = Color.white; 975 | 976 | // *** auto-tiles 977 | for (int i = 0; i < asset.tileAsset.autoTiles.Count; i++) 978 | { 979 | GameMapTile tile = asset.tileAsset.autoTiles[i].tiles[0]; 980 | TileDef def = null; 981 | if (!tileCache.TryGetValue(tile.id, out def)) 982 | { 983 | Debug.LogError("This should not happen."); 984 | continue; 985 | } 986 | 987 | if (autoTileSelected && i == tileIdx && ev.type == EventType.Repaint) 988 | { 989 | GUI.skin.box.Draw(new Rect(r.x - 2, r.y - 2, r.width + 4, r.height + 4), false, false, false, false); 990 | } 991 | 992 | GUI.color = def.color; 993 | 994 | if (def.sprite != null) 995 | { 996 | Rect r2 = r; 997 | if (def.flipped) { r2.x += r.width; r2.width = -r.width; } 998 | GUI.DrawTextureWithTexCoords(r2, def.sprite.texture, def.rect, true); 999 | Styles.Tile.normal.background = null; 1000 | } 1001 | else 1002 | { 1003 | Styles.Tile.normal.background = EditorGUIUtility.whiteTexture; 1004 | } 1005 | 1006 | TileContent.text = def.text; 1007 | if (GUI.Button(r, TileContent, Styles.Tile)) 1008 | { 1009 | tileIdx = i; 1010 | autoTileSelected = true; 1011 | doRepaint = true; 1012 | } 1013 | 1014 | GUI.color = Color.white; 1015 | 1016 | r.x += tileDrawSz + 5f; 1017 | if (r.x > rr.xMax - (tileDrawSz + 5f)) { r.x = 5f; r.y += tileDrawSz + 5f; } 1018 | } 1019 | 1020 | // *** normal tiles 1021 | for (int i = 0; i < asset.tileAsset.tiles.Count; i++) 1022 | { 1023 | GameMapTile tile = asset.tileAsset.tiles[i]; 1024 | TileDef def = null; 1025 | if (!tileCache.TryGetValue(tile.id, out def)) 1026 | { 1027 | Debug.LogError("This should not happen."); 1028 | continue; 1029 | } 1030 | 1031 | if (!autoTileSelected && i == tileIdx && ev.type == EventType.Repaint) 1032 | { 1033 | GUI.skin.box.Draw(new Rect(r.x - 2, r.y - 2, r.width + 4, r.height + 4), false, false, false, false); 1034 | } 1035 | 1036 | GUI.color = def.color; 1037 | 1038 | if (def.sprite != null) 1039 | { 1040 | Rect r2 = r; 1041 | if (def.flipped) { r2.x += r.width; r2.width = -r.width; } 1042 | GUI.DrawTextureWithTexCoords(r2, def.sprite.texture, def.rect, true); 1043 | Styles.Tile.normal.background = null; 1044 | } 1045 | else 1046 | { 1047 | Styles.Tile.normal.background = EditorGUIUtility.whiteTexture; 1048 | } 1049 | 1050 | TileContent.text = def.text; 1051 | if (GUI.Button(r, TileContent, Styles.Tile)) 1052 | { 1053 | tileIdx = i; 1054 | autoTileSelected = false; 1055 | doRepaint = true; 1056 | } 1057 | 1058 | GUI.color = Color.white; 1059 | 1060 | // handle drag&drop of sprite onto tile list 1061 | if (sprField != null) 1062 | { 1063 | if (ev.type == EventType.DragUpdated && r.Contains(ev.mousePosition)) 1064 | { 1065 | dragDropTarget = i; 1066 | DragAndDrop.visualMode = DragAndDropVisualMode.Generic; 1067 | ev.Use(); 1068 | } 1069 | 1070 | if (ev.type == EventType.DragExited) 1071 | { 1072 | dragDropTarget = -1; 1073 | } 1074 | 1075 | if (ev.type == EventType.DragPerform && dragDropTarget == i) 1076 | { 1077 | DragAndDrop.AcceptDrag(); 1078 | ev.Use(); 1079 | if (DragAndDrop.objectReferences.Length > 0) 1080 | { 1081 | Sprite sp = DragAndDrop.objectReferences[0] as Sprite; 1082 | if (sp == null) 1083 | { 1084 | Texture2D t = DragAndDrop.objectReferences[0] as Texture2D; 1085 | if (t != null) 1086 | { 1087 | UnityEngine.Object[] objs = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(t)); 1088 | if (objs.Length > 1) sp = objs[1] as Sprite; // [0] is texture/parent so [1] is the 1st sprite in it 1089 | } 1090 | } 1091 | if (sp != null) 1092 | { 1093 | //sprField.SetValue(asset.tileAsset.tiles[i], sp); 1094 | //EditorUtility.SetDirty(asset.tileAsset); 1095 | 1096 | SerializedObject obj = tilesEd.serializedObject; 1097 | obj.Update(); 1098 | SerializedProperty tilesProp = obj.FindProperty("tiles"); 1099 | SerializedProperty tileP = tilesProp.GetArrayElementAtIndex(i); 1100 | SerializedProperty spriteP = tileP.FindPropertyRelative(sprField.Name); 1101 | spriteP.objectReferenceValue = sp; 1102 | obj.ApplyModifiedProperties(); 1103 | 1104 | UpdateCachedValues(def, asset.tileAsset.tiles[i], def.isAuto); 1105 | doRepaint = true; 1106 | } 1107 | } 1108 | dragDropTarget = -1; 1109 | } 1110 | } 1111 | 1112 | // ... 1113 | r.x += tileDrawSz + 5f; 1114 | if (r.x > rr.xMax - (tileDrawSz + 5f)) { r.x = 5f; r.y += tileDrawSz + 5f; } 1115 | } 1116 | } 1117 | 1118 | #endregion 1119 | // ---------------------------------------------------------------------------------------------------------------- 1120 | #region canvas 1121 | 1122 | private void DrawCanvas(Event ev) 1123 | { 1124 | bool changed = GUI.changed; 1125 | GUI.changed = false; 1126 | 1127 | GUILayout.Space(7); 1128 | scroll[1] = EditorGUILayout.BeginScrollView(scroll[1]); 1129 | { 1130 | if (asset == null || asset.tileAsset == null || mapIdx < 0) 1131 | { 1132 | GUILayout.FlexibleSpace(); 1133 | EditorGUILayout.EndScrollView(); 1134 | return; 1135 | } 1136 | 1137 | GameMap map = asset.maps[mapIdx]; 1138 | float w = map.width * tileDrawSz; 1139 | float h = map.height * tileDrawSz; 1140 | Rect mainRect = GUILayoutUtility.GetRect(w + 20f, h + 20f, GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(false)); 1141 | mainRect.y += 3f; mainRect.width = w; mainRect.height = h; 1142 | 1143 | int controlID = GUIUtility.GetControlID(EditorCanvasHash, FocusType.Keyboard); 1144 | if (ev.GetTypeForControl(controlID) == EventType.Repaint) 1145 | { 1146 | // black background 1147 | GUI.backgroundColor = backColor; 1148 | Styles.SolidWhite.Draw(mainRect, false, false, false, false); 1149 | GUI.backgroundColor = Color.white; 1150 | 1151 | if (layerHidden.Length != asset.maps[mapIdx].layers.Length + 1) 1152 | { 1153 | layerHidden = new bool[asset.maps[mapIdx].layers.Length + 1]; 1154 | } 1155 | 1156 | // draw placed tiles 1157 | Rect r = new Rect(mainRect.x, mainRect.yMax - tileDrawSz, tileDrawSz, tileDrawSz); 1158 | for (int i = map.layers.Length - 1; i >= 0; i--) 1159 | { 1160 | if (!layerHidden[i + 1]) DrawGridTiles(mainRect, r, map.layers[i].grid); 1161 | } 1162 | 1163 | if (!layerHidden[0]) DrawGridTiles(mainRect, r, map.grid); 1164 | 1165 | // draw marked tiles overlay 1166 | if (markedTiles.Count > 0) 1167 | { 1168 | GUI.backgroundColor = new Color(0f, 1f, 0f, 0.5f); 1169 | foreach (int idx in markedTiles) 1170 | { 1171 | int x, y; 1172 | map.IdxToPosition(idx, out x, out y); 1173 | r.x = mainRect.x + (x * tileDrawSz); 1174 | r.y = mainRect.yMax - ((y+1) * tileDrawSz); 1175 | Styles.SolidWhite.Draw(r, false, false, false, false); 1176 | } 1177 | GUI.backgroundColor = Color.white; 1178 | } 1179 | 1180 | // grid over everything 1181 | DrawGrid(mainRect, map.width, map.height); 1182 | 1183 | // draw tiles to be pasted 1184 | if (pasting) 1185 | { 1186 | float offsX = mainRect.x + Mathf.Floor(ev.mousePosition.x / tileDrawSz) * tileDrawSz; 1187 | float offsY = mainRect.y + Mathf.Floor(ev.mousePosition.y / tileDrawSz) * tileDrawSz; 1188 | foreach (TileDef tile in copyBuffer) 1189 | { 1190 | r.x = offsX + (tile.x * tileDrawSz); 1191 | r.y = offsY - (tile.y * tileDrawSz); 1192 | if (r.x < mainRect.x || r.y < mainRect.y || r.x >= mainRect.xMax || r.y >= mainRect.yMax) continue; 1193 | if (tile.id >= 0) DrawTile(r, tile); 1194 | GUI.backgroundColor = new Color(0f, 1f, 0f, 0.5f); 1195 | Styles.SolidWhite.Draw(r, false, false, false, false); 1196 | } 1197 | 1198 | GUI.backgroundColor = Color.white; 1199 | } 1200 | } 1201 | 1202 | HandleCanvasEvents(mainRect, map, ev, controlID); 1203 | } 1204 | EditorGUILayout.EndScrollView(); 1205 | 1206 | if (GUI.changed) 1207 | { 1208 | EditorUtility.SetDirty(asset); 1209 | GUI.changed = changed; 1210 | } 1211 | } 1212 | 1213 | private void DrawGridTiles(Rect mainRect, Rect r, int[] g) 1214 | { 1215 | for (int i = 0; i < g.Length; i++) 1216 | { 1217 | TileDef def = null; 1218 | if (tileCache.TryGetValue(g[i], out def)) DrawTile(r, def); 1219 | 1220 | r.x += tileDrawSz; 1221 | if (r.x >= mainRect.xMax) { r.x = mainRect.x; r.y -= tileDrawSz; } 1222 | } 1223 | } 1224 | 1225 | private void HandleCanvasEvents(Rect mainRect, GameMap map, Event ev, int controlID) 1226 | { 1227 | switch (ev.GetTypeForControl(controlID)) 1228 | { 1229 | case EventType.MouseDown: 1230 | { 1231 | if (mainRect.Contains(ev.mousePosition)) 1232 | { 1233 | if (GUIUtility.hotControl == 0) 1234 | { 1235 | GUIUtility.hotControl = controlID; 1236 | GUIUtility.keyboardControl = controlID; 1237 | 1238 | if (pasting) 1239 | { 1240 | if (ev.button == 0) 1241 | { 1242 | DoPasteTiles(mainRect, ev); 1243 | } 1244 | else if (ev.button == 1) 1245 | { 1246 | pasting = false; 1247 | doRepaint = true; 1248 | } 1249 | } 1250 | else if (ev.button <= 1) 1251 | { 1252 | GridClick(mainRect, map, ev); 1253 | doRepaint = true; 1254 | } 1255 | 1256 | ev.Use(); 1257 | } 1258 | } 1259 | else 1260 | { 1261 | if (GUIUtility.keyboardControl == controlID) 1262 | { 1263 | GUIUtility.keyboardControl = 0; 1264 | } 1265 | } 1266 | } break; 1267 | 1268 | case EventType.MouseUp: 1269 | { 1270 | if (GUIUtility.hotControl == controlID) 1271 | { 1272 | GUIUtility.hotControl = 0; 1273 | doRepaint = true; 1274 | ev.Use(); 1275 | } 1276 | } break; 1277 | 1278 | case EventType.MouseMove: 1279 | { 1280 | if (pasting) doRepaint = true; 1281 | } break; 1282 | 1283 | case EventType.MouseDrag: 1284 | { 1285 | if (!pasting && GUIUtility.hotControl == controlID) 1286 | { 1287 | if (ev.button == 2) 1288 | { 1289 | scroll[1] = scroll[1] - ev.delta; 1290 | } 1291 | else 1292 | { 1293 | GridClick(mainRect, map, ev); 1294 | } 1295 | 1296 | doRepaint = true; 1297 | ev.Use(); 1298 | } 1299 | } break; 1300 | 1301 | case EventType.KeyDown: 1302 | { 1303 | if (GUIUtility.keyboardControl == controlID) 1304 | { 1305 | if (ev.keyCode == KeyCode.Escape) 1306 | { 1307 | if (pasting) 1308 | { 1309 | pasting = false; 1310 | doRepaint = true; 1311 | ev.Use(); 1312 | } 1313 | else if (marking) 1314 | { 1315 | marking = false; 1316 | clearMarked = false; 1317 | markedTiles.Clear(); 1318 | doRepaint = true; 1319 | ev.Use(); 1320 | } 1321 | } 1322 | else if (ev.keyCode == KeyCode.Delete && markedTiles.Count > 0) 1323 | { 1324 | DeleteMarkedTiles(); 1325 | ev.Use(); 1326 | } 1327 | } 1328 | } break; 1329 | 1330 | case EventType.ValidateCommand: 1331 | { 1332 | switch (ev.commandName) 1333 | { 1334 | case "Duplicate": case "Cut": case "Copy": case "Paste": case "Delete": ev.Use(); break; 1335 | } 1336 | } break; 1337 | 1338 | case EventType.ExecuteCommand: 1339 | { 1340 | switch (ev.commandName) 1341 | { 1342 | case "Duplicate": { if (markedTiles.Count > 0) { CopyMarkedTiles(true); EnterPasteMode(); ev.Use(); } } break; 1343 | case "Cut": { if (markedTiles.Count > 0) { CopyMarkedTiles(false); DeleteMarkedTiles(); ev.Use(); } } break; 1344 | case "Copy": { if (markedTiles.Count > 0) { CopyMarkedTiles(true); ev.Use(); } } break; 1345 | case "Paste": if (copyBuffer.Count > 0) { { EnterPasteMode(); ev.Use(); } } break; 1346 | case "Delete": { if (markedTiles.Count > 0) { DeleteMarkedTiles(); ev.Use(); } } break; 1347 | } 1348 | } break; 1349 | } 1350 | } 1351 | 1352 | private void DrawTile(Rect r, TileDef def) 1353 | { 1354 | GUI.color = def.color; 1355 | 1356 | if (def.sprite != null) 1357 | { 1358 | Rect rr = r; 1359 | 1360 | if (def.isAuto && refTileSz > 0.0f) 1361 | { 1362 | rr.width *= def.sprite.rect.width / refTileSz; 1363 | rr.height *= def.sprite.rect.height / refTileSz; 1364 | } 1365 | 1366 | if (def.flipped) { rr.x += rr.width; rr.width = -rr.width; } 1367 | 1368 | GUI.DrawTextureWithTexCoords(rr, def.sprite.texture, def.rect, true); 1369 | Styles.Tile.normal.background = null; 1370 | } 1371 | else 1372 | { 1373 | Styles.Tile.normal.background = EditorGUIUtility.whiteTexture; 1374 | } 1375 | 1376 | TileContent.text = def.text; 1377 | Styles.Tile.Draw(r, TileContent, false, false, false, false); 1378 | 1379 | GUI.color = Color.white; 1380 | } 1381 | 1382 | private void GridClick(Rect mainRect, GameMap map, Event ev) 1383 | { 1384 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1385 | int idx = MousePosToGridIdx(map, ev); 1386 | 1387 | if (ev.modifiers == EventModifiers.Shift && ev.button == 0) 1388 | { // mark tiles in grid 1389 | if (idx >= 0 && idx < grid.Length) 1390 | { 1391 | if (clearMarked) 1392 | { 1393 | if (markedTiles.Contains(idx)) markedTiles.Remove(idx); 1394 | else if (ev.type == EventType.MouseDown) 1395 | { 1396 | clearMarked = false; 1397 | markedTiles.Add(idx); 1398 | } 1399 | } 1400 | else 1401 | { 1402 | if (!markedTiles.Contains(idx)) markedTiles.Add(idx); 1403 | else if (ev.type == EventType.MouseDown) 1404 | { 1405 | clearMarked = true; 1406 | markedTiles.Remove(idx); 1407 | } 1408 | 1409 | } 1410 | 1411 | marking = true; 1412 | doRepaint = true; 1413 | } 1414 | } 1415 | 1416 | else if (idx >= 0 && idx < grid.Length) 1417 | { // place or delete tiles in grid 1418 | if (autoTileSelected && ev.button == 0 && tileIdx >= 0 && tileIdx < asset.tileAsset.autoTiles.Count) 1419 | { 1420 | PaintAutoTile(map, idx); 1421 | } 1422 | 1423 | else 1424 | { 1425 | int id = -1; 1426 | if (ev.button == 0 && !autoTileSelected) id = (tileIdx >= 0 && tileIdx < asset.tileAsset.tiles.Count ? asset.tileAsset.tiles[tileIdx].id : -1); 1427 | if (grid[idx] != id) 1428 | { 1429 | Undo.RecordObject(asset, id == -1 ? "Clear Tile" : "Place Tile"); 1430 | grid[idx] = id; 1431 | doRepaint = true; 1432 | GUI.changed = true; 1433 | } 1434 | } 1435 | } 1436 | } 1437 | 1438 | private void PaintAutoTile(GameMap map, int idx) 1439 | { 1440 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1441 | int refAutoId = asset.tileAsset.autoTiles[tileIdx].id; 1442 | bool is16Tile = (asset.tileAsset.autoTiles[tileIdx].tiles.Length == 16); 1443 | 1444 | int mainX, mainY; 1445 | map.IdxToPosition(idx, out mainX, out mainY); 1446 | int id = (is16Tile ? CalcAuto16TileId(map, refAutoId, mainX, mainY) : CalcAuto46TileId(map, refAutoId, mainX, mainY)); 1447 | 1448 | if (grid[idx] != id) 1449 | { 1450 | doRepaint = true; 1451 | GUI.changed = true; 1452 | Undo.RecordObject(asset, "Place Auto-Tile"); 1453 | grid[idx] = id; 1454 | 1455 | // update the neighbouring tiles 1456 | for (int ox = -1; ox <= 1; ox++) 1457 | { 1458 | for (int oy = -1; oy <= 1; oy++) 1459 | { 1460 | if (ox == 0 && oy == 0) continue; 1461 | 1462 | int x = mainX + ox; 1463 | int y = mainY + oy; 1464 | if (x < 0 || y < 0 || x >= map.width || y >= map.height) continue; 1465 | 1466 | idx = map.PositionToIdx(x, y); 1467 | if (grid[idx] < 0) continue; 1468 | 1469 | GameMapTile t = asset.tileAsset.GetTile(grid[idx]); 1470 | if (t == null || t._aid != refAutoId) continue; 1471 | 1472 | grid[idx] = (is16Tile ? CalcAuto16TileId(map, refAutoId, x, y) : CalcAuto46TileId(map, refAutoId, x, y)); 1473 | } 1474 | } 1475 | } 1476 | } 1477 | 1478 | private int CalcAuto16TileId(GameMap map, int refAutoId, int x, int y) 1479 | { 1480 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1481 | int invalid = outsideMapIsSolid ? -2 : -1; 1482 | int[] neighbour_ids = 1483 | { 1484 | (y < map.height - 1 ? grid[map.PositionToIdx(x, y + 1)] : invalid ), 1485 | (x > 0 ? grid[map.PositionToIdx(x - 1, y)] : invalid ), 1486 | (x < map.width - 1 ? grid[map.PositionToIdx(x + 1, y)] : invalid ), 1487 | (y > 0 ? grid[map.PositionToIdx(x, y - 1)] : invalid ) 1488 | }; 1489 | 1490 | for (int i = 0; i < neighbour_ids.Length; i++) 1491 | { 1492 | if (neighbour_ids[i] == -2) 1493 | { 1494 | neighbour_ids[i] = 1; 1495 | continue; 1496 | } 1497 | 1498 | GameMapTile t = asset.tileAsset.GetTile(neighbour_ids[i]); 1499 | neighbour_ids[i] = (t == null || t._aid != refAutoId ? 0 : 1); 1500 | } 1501 | 1502 | int at_idx = (neighbour_ids[0] * 1 + neighbour_ids[1] * 2 + neighbour_ids[2] * 4 + neighbour_ids[3] * 8); 1503 | return asset.tileAsset.autoTiles[tileIdx].tiles[at_idx].id; 1504 | } 1505 | 1506 | private int CalcAuto46TileId(GameMap map, int refAutoId, int x, int y) 1507 | { 1508 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1509 | int invalid = outsideMapIsSolid ? -2 : -1; 1510 | int[] neighbour_ids = 1511 | { 1512 | (y < map.height - 1 ? grid[map.PositionToIdx(x, y + 1)] : invalid ), // 1: top 1513 | (x < map.width - 1 && y < map.height - 1 ? grid[map.PositionToIdx(x + 1, y + 1)] : invalid ), // 2: top-right 1514 | (x < map.width - 1 ? grid[map.PositionToIdx(x + 1, y)] : invalid ), // 4: right 1515 | (x < map.width - 1 && y > 0? grid[map.PositionToIdx(x + 1, y - 1)] : invalid ), // 8: bottom-right 1516 | (y > 0 ? grid[map.PositionToIdx(x, y - 1)] : invalid ), // 16: bottom 1517 | (x > 0 && y > 0 ? grid[map.PositionToIdx(x - 1, y - 1)] : invalid ), // 32: bottom-left 1518 | (x > 0 ? grid[map.PositionToIdx(x - 1, y)] : invalid ), // 64: left 1519 | (x > 0 && y < map.height - 1 ? grid[map.PositionToIdx(x - 1, y + 1)] : invalid ), // 128: top-left 1520 | }; 1521 | 1522 | for (int i = 0; i < neighbour_ids.Length; i++) 1523 | { 1524 | if (neighbour_ids[i] == -2) 1525 | { 1526 | neighbour_ids[i] = 1; 1527 | continue; 1528 | } 1529 | 1530 | GameMapTile t = asset.tileAsset.GetTile(neighbour_ids[i]); 1531 | neighbour_ids[i] = (t == null || t._aid != refAutoId ? 0 : 1); 1532 | } 1533 | 1534 | int idx = ( 1535 | neighbour_ids[0] * 1 + 1536 | neighbour_ids[1] * 2 * (neighbour_ids[0] * neighbour_ids[2]) + // corners are only valid if the sides are solid too 1537 | neighbour_ids[2] * 4 + 1538 | neighbour_ids[3] * 8 * (neighbour_ids[2] * neighbour_ids[4]) + // corners are only valid if the sides are solid too 1539 | neighbour_ids[4] * 16 + 1540 | neighbour_ids[5] * 32 * (neighbour_ids[4] * neighbour_ids[6]) + // corners are only valid if the sides are solid too 1541 | neighbour_ids[6] * 64 + 1542 | neighbour_ids[7] * 128 * (neighbour_ids[6] * neighbour_ids[0]) // corners are only valid if the sides are solid too 1543 | ); 1544 | 1545 | int mapped_idx; 1546 | if (map64.TryGetValue(idx, out mapped_idx)) 1547 | { 1548 | return asset.tileAsset.autoTiles[tileIdx].tiles[mapped_idx].id; 1549 | } 1550 | else 1551 | { 1552 | Debug.LogError("Missing mapping: " + idx); 1553 | } 1554 | 1555 | return -1; 1556 | } 1557 | 1558 | private void DrawGrid(Rect r, int w, int h) 1559 | { 1560 | GUI.backgroundColor = gridColor; 1561 | 1562 | Rect rr = r; 1563 | rr.width = 1f; 1564 | for (int i = 0; i <= w; i++) 1565 | { 1566 | rr.x = r.x + (i * tileDrawSz); 1567 | Styles.SolidWhite.Draw(rr, false, false, false, false); 1568 | } 1569 | 1570 | rr = r; 1571 | rr.height = 1f; 1572 | for (int i = 0; i <= h; i++) 1573 | { 1574 | rr.y = r.y + (i * tileDrawSz); 1575 | Styles.SolidWhite.Draw(rr, false, false, false, false); 1576 | } 1577 | 1578 | GUI.backgroundColor = Color.white; 1579 | } 1580 | 1581 | private int MousePosToGridIdx(GameMap map, Event ev) 1582 | { 1583 | int x = Mathf.FloorToInt(ev.mousePosition.x / tileDrawSz); 1584 | int y = Mathf.FloorToInt(ev.mousePosition.y / tileDrawSz); 1585 | y = map.height - (y + 1); // map's Y starts from bottom-up 1586 | if (x < 0 || y < 0 || x >= map.width || y >= map.height) return -1; 1587 | return map.PositionToIdx(x, y); 1588 | } 1589 | 1590 | private void CopyMarkedTiles(bool clearMarked) 1591 | { 1592 | copyBuffer.Clear(); 1593 | 1594 | GameMap map = asset.maps[mapIdx]; 1595 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1596 | 1597 | int x=0, y=0, offsX=0, offsY=0; 1598 | markedTiles.Sort((a, b) => a.CompareTo(b)); 1599 | map.IdxToPosition(markedTiles[markedTiles.Count / 2], out offsX, out offsY); 1600 | 1601 | foreach (int idx in markedTiles) 1602 | { 1603 | map.IdxToPosition(idx, out x, out y); 1604 | TileDef t = (grid[idx] >= 0 ? tileCache[grid[idx]].Copy() : new TileDef() { id = -1 }); 1605 | t.x = x - offsX; 1606 | t.y = y - offsY; 1607 | copyBuffer.Add(t); 1608 | } 1609 | 1610 | if (clearMarked) markedTiles.Clear(); 1611 | doRepaint = true; 1612 | } 1613 | 1614 | private void DeleteMarkedTiles() 1615 | { 1616 | Undo.RecordObject(asset, "Remove Tiles"); 1617 | 1618 | GameMap map = asset.maps[mapIdx]; 1619 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1620 | foreach (int idx in markedTiles) 1621 | { 1622 | grid[idx] = -1; 1623 | } 1624 | 1625 | markedTiles.Clear(); 1626 | GUI.changed = true; 1627 | doRepaint = true; 1628 | } 1629 | 1630 | private void EnterPasteMode() 1631 | { 1632 | pasting = true; 1633 | markedTiles.Clear(); 1634 | doRepaint = true; 1635 | } 1636 | 1637 | private void DoPasteTiles(Rect mainRect, Event ev) 1638 | { 1639 | Undo.RecordObject(asset, "Paste Tiles"); 1640 | 1641 | GameMap map = asset.maps[mapIdx]; 1642 | int[] grid = (currLayer < 0 ? map.grid : map.layers[currLayer].grid); 1643 | int xOffs = Mathf.FloorToInt(ev.mousePosition.x / tileDrawSz); 1644 | int yOffs = Mathf.FloorToInt(ev.mousePosition.y / tileDrawSz); 1645 | yOffs = map.height - (yOffs + 1); // map's Y starts from bottom-up 1646 | foreach (TileDef tile in copyBuffer) 1647 | { 1648 | int x = xOffs + tile.x; 1649 | int y = yOffs + tile.y; 1650 | if (x < 0 || x >= map.width || y < 0 || y >= map.height) continue; 1651 | 1652 | grid[map.PositionToIdx(x, y)] = tile.id; 1653 | } 1654 | 1655 | GUI.changed = true; 1656 | doRepaint = true; 1657 | } 1658 | 1659 | #endregion 1660 | // ---------------------------------------------------------------------------------------------------------------- 1661 | #region helpers 1662 | 1663 | private T LoadOrCreateAsset(string fn, bool createIfNotExist = true) 1664 | where T : ScriptableObject 1665 | { 1666 | if (!fn.StartsWith(Application.dataPath)) return null; 1667 | try 1668 | { 1669 | fn = "Assets" + fn.Replace(Application.dataPath, ""); 1670 | ScriptableObject asset = AssetDatabase.LoadAssetAtPath(fn, typeof(T)) as ScriptableObject; 1671 | if (asset == null && createIfNotExist) 1672 | { 1673 | asset = CreateInstance(typeof(T)); 1674 | AssetDatabase.CreateAsset(asset, fn); 1675 | AssetDatabase.SaveAssets(); 1676 | } 1677 | return (T)asset; 1678 | } 1679 | catch 1680 | { 1681 | return null; 1682 | } 1683 | } 1684 | 1685 | private ScriptableObject LoadOrCreateAsset(string fn, Type t, bool createIfNotExist = true) 1686 | { 1687 | if (!fn.StartsWith(Application.dataPath)) return null; 1688 | try 1689 | { 1690 | fn = "Assets" + fn.Replace(Application.dataPath, ""); 1691 | ScriptableObject asset = AssetDatabase.LoadAssetAtPath(fn, t) as ScriptableObject; 1692 | if (asset == null && createIfNotExist) 1693 | { 1694 | asset = CreateInstance(t); 1695 | AssetDatabase.CreateAsset(asset, fn); 1696 | AssetDatabase.SaveAssets(); 1697 | } 1698 | return asset; 1699 | } 1700 | catch 1701 | { 1702 | return null; 1703 | } 1704 | } 1705 | 1706 | private bool StringIsUnique(List existingStrings, string str) 1707 | { 1708 | if (string.IsNullOrEmpty(str) || existingStrings == null) return false; 1709 | for (int i = 0; i < existingStrings.Count; i++) 1710 | { 1711 | if (existingStrings[i] == null) continue; 1712 | if (str.Equals(existingStrings[i].ToString())) return false; 1713 | } 1714 | return true; 1715 | } 1716 | 1717 | private static void EditorPrefs_SetColor(string key, Color val) 1718 | { 1719 | EditorPrefs.SetString(key, string.Format("{0},{1},{2},{3}", val.r, val.g, val.b, val.a)); 1720 | } 1721 | 1722 | private static Color EditorPrefs_GetColor(string key, Color defaultValue) 1723 | { 1724 | Color res = defaultValue; 1725 | string val = EditorPrefs.GetString(key, null); 1726 | if (!string.IsNullOrEmpty(val)) 1727 | { 1728 | string[] vals = val.Split(','); 1729 | if (vals.Length == 4) 1730 | { 1731 | float.TryParse(vals[0], out res.r); 1732 | float.TryParse(vals[1], out res.g); 1733 | float.TryParse(vals[2], out res.b); 1734 | float.TryParse(vals[3], out res.a); 1735 | } 1736 | } 1737 | return res; 1738 | } 1739 | 1740 | #endregion 1741 | // ---------------------------------------------------------------------------------------------------------------- 1742 | } 1743 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad9b63da28b88d84c8206d6dfe19b57e 3 | timeCreated: 1496306198 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapTextEd.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | 5 | public class GameMapTextEd : EditorWindow 6 | { 7 | public string text { get; private set; } 8 | 9 | private string label; 10 | private System.Action callback; 11 | private bool accepted = false; 12 | private bool lostFocus = false; 13 | 14 | private static GUIStyle BottomBarStyle = null; 15 | 16 | public static void ShowEd(string title, string label, string currText, System.Action callback) 17 | { 18 | GameMapTextEd wiz = GetWindow(true, title, true); 19 | wiz.label = label; 20 | wiz.text = currText; 21 | wiz.callback = callback; 22 | wiz.minSize = wiz.maxSize = new Vector2(250, 100); 23 | wiz.ShowUtility(); 24 | } 25 | 26 | void OnFocus() { lostFocus = false; } 27 | void OnLostFocus() { lostFocus = true; } 28 | 29 | void Update() 30 | { 31 | if (lostFocus) Close(); 32 | if (accepted && callback != null) callback(this); 33 | } 34 | 35 | void OnGUI() 36 | { 37 | if (BottomBarStyle == null) 38 | { 39 | BottomBarStyle = new GUIStyle(GUI.skin.FindStyle("ProjectBrowserBottomBarBg")) { padding = new RectOffset(3, 3, 8, 8), stretchHeight = false, stretchWidth = true, fixedHeight = 0, fixedWidth = 0 }; 40 | } 41 | 42 | EditorGUILayout.Space(); 43 | GUILayout.Label(label); 44 | text = EditorGUILayout.TextField(text); 45 | GUILayout.FlexibleSpace(); 46 | EditorGUILayout.BeginHorizontal(BottomBarStyle); 47 | { 48 | GUILayout.FlexibleSpace(); 49 | if (GUILayout.Button("Accept", GUILayout.Width(80))) accepted = true; 50 | GUILayout.Space(5); 51 | if (GUILayout.Button("Cancel", GUILayout.Width(80))) Close(); 52 | GUILayout.FlexibleSpace(); 53 | } 54 | EditorGUILayout.EndHorizontal(); 55 | } 56 | 57 | // ---------------------------------------------------------------------------------------------------------------- 58 | } 59 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapTextEd.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b65e1a2eb5ee0364f81a821cae653ed7 3 | timeCreated: 1496412507 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapTilesAssetInspector.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | 5 | [CustomEditor(typeof(GameMapTilesAsset))] 6 | public class GameMapTilesAssetInspector : Editor 7 | { 8 | 9 | public override void OnInspectorGUI() 10 | { 11 | if (GUILayout.Button("Open Maps Editor")) 12 | { 13 | GameMapEditor.Open_GameMapEditor(); 14 | } 15 | } 16 | 17 | // ---------------------------------------------------------------------------------------------------------------- 18 | } 19 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapTilesAssetInspector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 08b5fb98f338cb54daf5dad00ee28a63 3 | timeCreated: 1496485405 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapsAssetInspector.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | 5 | [CustomEditor(typeof(GameMapsAsset))] 6 | public class GameMapsAssetInspector : Editor 7 | { 8 | 9 | public override void OnInspectorGUI() 10 | { 11 | if (GUILayout.Button("Open Maps Editor")) 12 | { 13 | GameMapEditor.Open_GameMapEditor((GameMapsAsset)target); 14 | } 15 | } 16 | 17 | // ---------------------------------------------------------------------------------------------------------------- 18 | } 19 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/Editor/GameMapsAssetInspector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 459e1a96bcb0006489834fb3d5a99aeb 3 | timeCreated: 1496483763 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | 5 | /// 6 | /// A map/grid of tiles. The GameMapsAsset contains a list of these maps. 7 | /// The map's 0x0 point is considered to be at the bottom-left and WxH at top-right 8 | /// 9 | [System.Serializable] 10 | public class GameMap 11 | { 12 | /// a unique identifier for the map 13 | public int id; 14 | 15 | /// a unique name by which map can be identified 16 | public string ident; 17 | 18 | /// width of the map (determines how big grid is) 19 | public int width; 20 | 21 | /// height of map (determines how big grid is) 22 | public int height; 23 | 24 | /// The grid/map. -1 is an empty tile, else a value related to GameMapTile.id will be present 25 | /// This is also known as layer-0 or the default layer when there are movethan one layer in the map. 26 | /// 27 | public int[] grid = new int[0]; 28 | 29 | /// The GameMap can have additional layers. In that case the grid[] field above will be the default, or layer-0. 30 | public GameMapLayer[] layers = new GameMapLayer[0]; 31 | 32 | // *** extra properties related to this map 33 | // add any addition serializable types here and they will appear 34 | // for editing in map properties section of the map editor 35 | 36 | //public Color backgroundColor = Color.black; 37 | 38 | // ---------------------------------------------------------------------------------------------------------------- 39 | 40 | /// 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. 41 | public int PositionToIdx(int x, int y) 42 | { 43 | return (y * width + x); 44 | } 45 | 46 | /// Get an x and y position, given specific index into grid[]. No error checking, idx out of bounds, to improve performance. 47 | public void IdxToPosition(int idx, out int x, out int y) 48 | { 49 | y = idx / width; 50 | x = idx - (y * width); 51 | } 52 | 53 | /// This returns layers.Length + 1 since grid[] is layer-0. 54 | public int LayerCount { get { return layers.Length + 1; } } 55 | 56 | /// 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 57 | public int[] GetlayerData(int layerIdx) 58 | { 59 | return (layerIdx == 0 ? grid : layers[layerIdx - 1].grid); 60 | } 61 | 62 | /// Return an array of GameMapIdxIdPair with the ID and Index of tiles neighbouring the one at x,y. 63 | /// Array is always length 4 else 8 if includeDiagonal=true. 64 | /// idx or id = -1 represents no tile or areas outside of map grid. 65 | /// Result starts at tile above (north) and go around clockwise. 66 | public GameMapIdxIdPair[] GetNeighbours(int x, int y, bool includeDiagonal = false, int layerIdx = 0) 67 | { 68 | int[] g = (layerIdx == 0 ? grid : layers[layerIdx - 1].grid); 69 | if (includeDiagonal) 70 | { 71 | return new GameMapIdxIdPair[] 72 | { 73 | (y < height - 1 ? new GameMapIdxIdPair(g[((y + 1) * width + (x + 0))], ((y + 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)), 74 | (x < width - 1 && y < height - 1 ? new GameMapIdxIdPair(g[((y + 1) * width + (x + 1))], ((y + 1) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)), 75 | (x < width - 1 ? new GameMapIdxIdPair(g[((y + 0) * width + (x + 1))], ((y + 0) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)), 76 | (x < width - 1 && y > 0 ? new GameMapIdxIdPair(g[((y - 1) * width + (x + 1))], ((y - 1) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)), 77 | (y > 0 ? new GameMapIdxIdPair(g[((y - 1) * width + (x + 0))], ((y - 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)), 78 | (x > 0 && y > 0 ? new GameMapIdxIdPair(g[((y - 1) * width + (x - 1))], ((y - 1) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1)), 79 | (x > 0 ? new GameMapIdxIdPair(g[((y + 0) * width + (x - 1))], ((y + 0) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1)), 80 | (x > 0 && y < height - 1 ? new GameMapIdxIdPair(g[((y + 1) * width + (x - 1))], ((y + 1) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1)) 81 | }; 82 | } 83 | else 84 | { 85 | return new GameMapIdxIdPair[] 86 | { 87 | (y < height - 1 ? new GameMapIdxIdPair(g[((y + 1) * width + (x + 0))], ((y + 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)), 88 | (x < width - 1 ? new GameMapIdxIdPair(g[((y + 0) * width + (x + 1))], ((y + 0) * width + (x + 1))) : new GameMapIdxIdPair(-1, -1)), 89 | (y > 0 ? new GameMapIdxIdPair(g[((y - 1) * width + (x + 0))], ((y - 1) * width + (x + 0))) : new GameMapIdxIdPair(-1, -1)), 90 | (x > 0 ? new GameMapIdxIdPair(g[((y + 0) * width + (x - 1))], ((y + 0) * width + (x - 1))) : new GameMapIdxIdPair(-1, -1)) 91 | }; 92 | } 93 | } 94 | 95 | // ---------------------------------------------------------------------------------------------------------------- 96 | 97 | /// This will destroy the exiting map. Use Resize if you want to keep existing tile data. Mainly used by editor. 98 | public void SetSize(int w, int h) 99 | { 100 | if (w < 1) w = 1; 101 | if (h < 1) h = 1; 102 | 103 | width = w; 104 | height = h; 105 | grid = new int[width * height]; 106 | foreach(GameMapLayer l in layers) l.grid = new int[width * height]; 107 | ClearMap(); 108 | } 109 | 110 | /// Resizes map, keeping existing tile data. Use SetSize() to create a clean resized map. Mainly used by editor. 111 | public void Resize(int w, int h) 112 | { 113 | if (w < 1) w = 1; 114 | if (h < 1) h = 1; 115 | 116 | int[] old = grid; 117 | grid = new int[w * h]; 118 | ClearLayer(0); 119 | 120 | for (int y = 0; y < h; y++) 121 | { 122 | if (y >= height) break; 123 | for (int x = 0; x < w; x++) 124 | { 125 | if (x >= width) break; 126 | grid[(y * w + x)] = old[(y * width + x)]; 127 | } 128 | } 129 | 130 | for (int i =0; i < layers.Length; i++) 131 | { 132 | old = layers[i].grid; 133 | layers[i].grid = new int[w * h]; 134 | ClearLayer(i+1); 135 | 136 | for (int y = 0; y < h; y++) 137 | { 138 | if (y >= height) break; 139 | for (int x = 0; x < w; x++) 140 | { 141 | if (x >= width) break; 142 | layers[i].grid[(y * w + x)] = old[(y * width + x)]; 143 | } 144 | } 145 | } 146 | 147 | width = w; 148 | height = h; 149 | } 150 | 151 | /// Fill grid with empty tiles (-1). Mainly used by editor. 152 | public void ClearMap() 153 | { 154 | for (int i = 0; i < grid.Length; i++) 155 | { 156 | grid[i] = -1; 157 | } 158 | 159 | foreach (GameMapLayer l in layers) 160 | { 161 | for (int i = 0; i < l.grid.Length; i++) 162 | { 163 | l.grid[i] = -1; 164 | } 165 | } 166 | } 167 | 168 | /// This set the size of the layer. This will destroy any exsiting tile placements in the layer. 169 | /// idx=0 refers to the grid[] while anything higher will be layers[idx-1].grid 170 | public void InitLayer(int idx) 171 | { 172 | if (idx == 0) 173 | { 174 | grid = new int[width * height]; 175 | ClearLayer(0); 176 | } 177 | else 178 | { 179 | layers[idx-1].grid = new int[width * height]; 180 | ClearLayer(idx); 181 | } 182 | } 183 | 184 | /// idx=0 refers to the grid[] while anything higher will be layers[idx-1].grid 185 | public void ClearLayer(int idx) 186 | { 187 | if (idx == 0) 188 | { 189 | for (int i = 0; i < grid.Length; i++) 190 | { 191 | grid[i] = -1; 192 | } 193 | } 194 | else 195 | { 196 | idx--; 197 | for (int i = 0; i < layers[idx].grid.Length; i++) 198 | { 199 | layers[idx].grid[i] = -1; 200 | } 201 | } 202 | } 203 | 204 | public override string ToString() 205 | { 206 | return ident; 207 | } 208 | 209 | // ---------------------------------------------------------------------------------------------------------------- 210 | } 211 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMap.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8a0d0a4bd6f2604ea512be8d7332013 3 | timeCreated: 1496307023 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapIdxIdPair.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | 5 | public class GameMapIdxIdPair 6 | { 7 | public int id; 8 | public int idx; 9 | 10 | public GameMapIdxIdPair(int id, int idx) 11 | { 12 | this.id = id; 13 | this.idx = idx; 14 | } 15 | 16 | // ---------------------------------------------------------------------------------------------------------------- 17 | } 18 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapIdxIdPair.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c3aba858c13b65744be59a12864a164a 3 | timeCreated: 1500544708 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | 5 | /// 6 | /// A layer consists of a series of values in a grid. 7 | /// Each GameMap can have one or more layers. 8 | /// 9 | [System.Serializable] 10 | public class GameMapLayer 11 | { 12 | /// The layer's grid of tile values. -1 is an empty tile, else a value related to GameMapTile.id will be present 13 | public int[] grid = new int[0]; 14 | 15 | 16 | // ---------------------------------------------------------------------------------------------------------------- 17 | } 18 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapLayer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 71a54717ca2c543478cacfc8b323e6fb 3 | timeCreated: 1500629685 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapTile.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | 4 | /// A tile definition. The map/grid consist of an array of these tiles. 5 | [System.Serializable] 6 | public class GameMapTile 7 | { 8 | // the tile needs a way to be identifiable in the editor. this can be done with either a sprite, colour, or value. 9 | // simply add the [GameMapTilePreview] attribute above any Sprite, Color, String, or Int properties below. 10 | // for String an empty value will be ignored. For Int negative numbers will be ignored. 11 | 12 | /// Unique identifier for tile. This is the value stored in GameMap.grid[] (-1 is used for empty tiles in the grid) 13 | public int id; 14 | 15 | /// Sprite representing the tile. 16 | [GameMapTilePreview] public Sprite sprite; // You may choose not to use this but do not remove it since it is required by auto-tiles system. 17 | 18 | public int _aid = -1; // helper for auto-tiles; do not remove. 19 | 20 | // *** extra properties related to this tile definition 21 | // add any addition serializable types here and they will appear 22 | // for editing in asset properties section of the map editor 23 | 24 | // Note: 25 | // Any of the fields following may be removed if you do not need/use them. They are here as an example. 26 | // (of course the demo script makes use of them so update it too) 27 | // Remember to add/remove fields to CopyTo() function too 28 | 29 | public enum Type { Start=0, End=1, Key=2, Coin=3, Block=4, Floor=20, Platform=21, NPC=30, Trap=40, Text=50 } 30 | public Type type = Type.Floor; // the runtime might use something like this to identify what the placed tile means 31 | 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. 32 | 33 | [GameMapTilePreview] public Color color = Color.white; 34 | [GameMapTilePreview] public string strVal = ""; 35 | 36 | // ---------------------------------------------------------------------------------------------------------------- 37 | 38 | /// Copies this tile's data into target. 39 | public void CopyTo(GameMapTile t) 40 | { 41 | t.id = id; 42 | t.sprite = sprite; 43 | t.type = type; 44 | t.opt1 = opt1; 45 | t.color = color; 46 | t.strVal = strVal; 47 | } 48 | 49 | // ---------------------------------------------------------------------------------------------------------------- 50 | } 51 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapTile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c7f6e977fc562464bbd1cdbb3b5c3f6e 3 | timeCreated: 1496307023 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapTilePreviewAttribute.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | [System.AttributeUsage(System.AttributeTargets.Field)] 4 | public class GameMapTilePreviewAttribute : System.Attribute 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapTilePreviewAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b8f64edff4c4be4e823b69490d5c0b4 3 | timeCreated: 1496496120 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapTilesAsset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | 5 | /// Container for all defined tiles. 6 | [System.Serializable] 7 | public class GameMapTilesAsset : ScriptableObject 8 | { 9 | [SerializeField] public List tiles = new List(); 10 | [SerializeField] public List autoTiles = new List(); 11 | [SerializeField] private int nextTileId = 1; 12 | [SerializeField] private int nextAutoTileId = 1; 13 | 14 | [System.Serializable] 15 | public class AutoTile 16 | { 17 | public int id; 18 | public GameMapTile[] tiles; // 16 or 47 depending on system using including corners or not 19 | } 20 | 21 | private Dictionary _cache = null; // 22 | 23 | // ---------------------------------------------------------------------------------------------------------------- 24 | 25 | /// Get the Tile by its unique ID. Remember that the ID is the value stored in 26 | /// GameMap.grid, not the tile's index in the GameMapTilesAsset.tiles list. 27 | public GameMapTile GetTile(int id) 28 | { 29 | if (id < 0) return null; 30 | 31 | if (_cache == null) 32 | { 33 | _cache = new Dictionary(); 34 | foreach (GameMapTile t in tiles) 35 | { 36 | _cache.Add(t.id, t); 37 | } 38 | 39 | foreach (AutoTile at in autoTiles) 40 | { 41 | _cache.Add(at.tiles[0].id, at.tiles[0]); 42 | 43 | // copy the mainTile info into all auto-tile pieces, except for the sprite 44 | // note; skip [0] on purpose since it is the main tile 45 | for (int i = 1; i < at.tiles.Length; i++) 46 | { 47 | Sprite _sp = at.tiles[i].sprite; 48 | int _id = at.tiles[i].id; 49 | at.tiles[0].CopyTo(at.tiles[i]); 50 | at.tiles[i].id = _id; 51 | at.tiles[i].sprite = _sp; 52 | _cache.Add(at.tiles[i].id, at.tiles[i]); 53 | } 54 | } 55 | } 56 | 57 | GameMapTile tile = null; 58 | if (_cache.TryGetValue(id, out tile)) return tile; 59 | return null; 60 | } 61 | 62 | // ---------------------------------------------------------------------------------------------------------------- 63 | 64 | /// Add tile definition. Mainly for editor use. 65 | public void AddTile() 66 | { 67 | GameMapTile t = new GameMapTile() { id = nextTileId++ }; 68 | 69 | tiles.Add(t); 70 | _cache = null; 71 | } 72 | 73 | /// Add auto-tile definition. Mainly for editor use. 74 | public void AddAutoTile(bool withCorners) 75 | { 76 | AutoTile at = new AutoTile() { id = nextAutoTileId++, tiles = new GameMapTile[withCorners ? 47 : 16] }; 77 | for (int i = 0; i < at.tiles.Length; i++) 78 | { 79 | at.tiles[i] = new GameMapTile() { id = nextTileId++, _aid = at.id }; 80 | } 81 | 82 | autoTiles.Add(at); 83 | _cache = null; 84 | } 85 | 86 | /// Remove tile definition. Mainly for editor use. 87 | public void RemoveTileAtIndex(int idx) 88 | { 89 | tiles.RemoveAt(idx); 90 | if (tiles.Count == 0 && autoTiles.Count == 0) nextTileId = 1; 91 | _cache = null; 92 | } 93 | 94 | /// Remove auto-tile definition. Mainly for editor use. 95 | public void RemoveAutoTileAtIndex(int idx) 96 | { 97 | autoTiles.RemoveAt(idx); 98 | if (tiles.Count == 0 && autoTiles.Count == 0) nextTileId = 1; 99 | if (autoTiles.Count == 0) nextAutoTileId = 1; 100 | _cache = null; 101 | } 102 | 103 | // ---------------------------------------------------------------------------------------------------------------- 104 | } 105 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapTilesAsset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cfd959e78eebfa6429e3b74d870c5669 3 | timeCreated: 1496485405 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapsAsset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | 5 | /// Container for all defined maps. It also holds a reference the defined tiles. 6 | [System.Serializable] 7 | public class GameMapsAsset : ScriptableObject 8 | { 9 | /// All maps created via MapEditor 10 | [SerializeField] public List maps = new List(); 11 | 12 | /// The tiles asset associated with the maps 13 | [SerializeField] public GameMapTilesAsset tileAsset; 14 | 15 | [SerializeField] private int nextMapId = 1; 16 | 17 | // *** extra properties related to this maps asset 18 | // add any addition serializable types here and they will appear 19 | // for editing in asset properties section of the map editor 20 | 21 | // public string someProperty; // example 22 | 23 | // ---------------------------------------------------------------------------------------------------------------- 24 | 25 | /// Add a new map. Mainly for use by the map editor. 26 | public void AddMap() 27 | { 28 | GameMap m = new GameMap() { id = nextMapId, ident = "Map " + nextMapId }; 29 | m.SetSize(10, 10); 30 | nextMapId++; 31 | maps.Add(m); 32 | } 33 | 34 | /// Remove a map. Mainly for use by the map editor. 35 | public void RemoveMapAtIndex(int idx) 36 | { 37 | maps.RemoveAt(idx); 38 | if (maps.Count == 0) nextMapId = 1; 39 | } 40 | 41 | // ---------------------------------------------------------------------------------------------------------------- 42 | } 43 | -------------------------------------------------------------------------------- /Assets/GameMap/CoreScripts/GameMapsAsset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4ee8a7d85ab66c3438f03e2771801706 3 | timeCreated: 1496307023 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d39e930333cb9f4bba94368590bfe9c 3 | folderAsset: yes 4 | timeCreated: 1499065790 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/MapData.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5f6c9e95cf0c5342aa706af5b956a80 3 | folderAsset: yes 4 | timeCreated: 1496994723 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/MapData/maps.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/MapData/maps.asset -------------------------------------------------------------------------------- /Assets/GameMap/Sample/MapData/maps.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bbf7388a54f14f842b7aecb67d709046 3 | timeCreated: 1496678615 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 11400000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/MapData/tiles.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/MapData/tiles.asset -------------------------------------------------------------------------------- /Assets/GameMap/Sample/MapData/tiles.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2a61f0e3528b4c148a389cf6ed4f179e 3 | timeCreated: 1496678623 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 11400000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c6356d405ac9d154f98519c4c81dc309 3 | folderAsset: yes 4 | timeCreated: 1499066053 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/FloorTile.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Prefabs/FloorTile.prefab -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/FloorTile.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c242da35d5b354343bf7c851e86985f9 3 | timeCreated: 1497255712 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/NPC1.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Prefabs/NPC1.prefab -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/NPC1.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd67b3c9abcfbfb419bfe5f0c7fe4777 3 | timeCreated: 1499066719 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/NPC2.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Prefabs/NPC2.prefab -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/NPC2.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 606d546f72896eb4eb1f4577b3b4738b 3 | timeCreated: 1499066738 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/Player.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Prefabs/Player.prefab -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/Player.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 97291c76034a8e34b8a667b05b74c993 3 | timeCreated: 1499066694 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/Trap.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Prefabs/Trap.prefab -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Prefabs/Trap.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c85322fd118b50e429fd10d18407311b 3 | timeCreated: 1497702780 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 100100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b15b9f737b91eb24096d9e5b436718a9 3 | folderAsset: yes 4 | timeCreated: 1499066870 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Scripts/Main.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | 6 | public class Main : MonoBehaviour 7 | { 8 | // ---------------------------------------------------------------------------------------------------------------- 9 | #region properties 10 | 11 | [SerializeField] public float tileSize = 32f; 12 | [SerializeField] public float ppu = 100f; 13 | 14 | [Space] 15 | [SerializeField] public GameMapsAsset mapsAsset; 16 | [SerializeField] public GameObject playerFab; 17 | [SerializeField] public GameObject floorFab; 18 | [SerializeField] public GameObject[] npcFabs; 19 | [SerializeField] public GameObject[] trapFabs; 20 | 21 | #endregion 22 | // ---------------------------------------------------------------------------------------------------------------- 23 | #region system 24 | 25 | private void Start() 26 | { 27 | LoadMap(0); 28 | } 29 | 30 | // an example of how map data could be loaded 31 | private void LoadMap(int mapIdx) 32 | { 33 | GameMap map = mapsAsset.maps[mapIdx]; 34 | 35 | float sz = tileSize / ppu; 36 | float offsX = -((map.width / 2f * sz) - (sz / 2f)); 37 | float offsY = -((map.height / 2f * sz) - (sz / 2f)); 38 | 39 | // create containers for the various map objects 40 | Transform floorContainer = new GameObject("Tiles").transform; 41 | Transform npcContainer = new GameObject("NPCs").transform; 42 | Transform trapContainer = new GameObject("Traps").transform; 43 | 44 | // place tiles and objects. GameMap supports laters but if you choose not to use them then you only need to read from map.grid[] 45 | // if you do use layers then you should also read data from map.layers[].grid[] while also still using map.grid[] as layer-0 46 | // to make it easier to read from these two sources of data you can simply use map.LayerCount and map.GetLayerData 47 | 48 | for (int i = 0; i < map.LayerCount; i++) 49 | { 50 | int[] grid = map.GetlayerData(i); 51 | int idx = 0; 52 | for (int y = 0; y < map.height; y++) 53 | { 54 | for (int x = 0; x < map.width; x++) 55 | { 56 | GameMapTile t = mapsAsset.tileAsset.GetTile(grid[idx++]); 57 | if (t == null) continue; 58 | 59 | if (t.type == GameMapTile.Type.Floor) 60 | { // place a floor tile 61 | if (t.sprite == null) continue; 62 | SpriteRenderer ren = Instantiate(floorFab).GetComponent(); 63 | ren.sprite = t.sprite; 64 | ren.transform.SetParent(floorContainer, false); 65 | ren.transform.localScale = new Vector3(tileSize / ren.sprite.rect.width, tileSize / ren.sprite.rect.height, 1f); 66 | ren.transform.localPosition = new Vector3(x * sz + offsX, y * sz + offsY, 0f); 67 | ren.GetComponent().size = new Vector2(ren.sprite.rect.width / ren.sprite.pixelsPerUnit, ren.sprite.rect.height / ren.sprite.pixelsPerUnit); 68 | } 69 | 70 | else if (t.type == GameMapTile.Type.NPC) 71 | { // place an NPC 72 | SpriteRenderer ren = Instantiate(npcFabs[t.opt1]).GetComponent(); 73 | ren.transform.SetParent(npcContainer, false); 74 | ren.transform.localScale = new Vector3(tileSize / ren.sprite.rect.width, tileSize / ren.sprite.rect.height, 1f); 75 | ren.transform.localPosition = new Vector3(x * sz + offsX, y * sz + offsY, 0f); 76 | } 77 | 78 | else if (t.type == GameMapTile.Type.Trap) 79 | { // place a Trap 80 | SpriteRenderer ren = Instantiate(trapFabs[t.opt1]).GetComponent(); 81 | ren.transform.SetParent(trapContainer, false); 82 | ren.transform.localScale = new Vector3(tileSize / ren.sprite.rect.width, tileSize / ren.sprite.rect.height, 1f); 83 | ren.transform.localPosition = new Vector3(x * sz + offsX, y * sz + offsY, 0f); 84 | } 85 | 86 | else if (t.type == GameMapTile.Type.Start) 87 | { // place player object 88 | SpriteRenderer ren = Instantiate(playerFab).GetComponent(); 89 | ren.transform.localScale = new Vector3(tileSize / ren.sprite.rect.width, tileSize / ren.sprite.rect.height, 1f); 90 | ren.transform.localPosition = new Vector3(x * sz + offsX, y * sz + offsY, 0f); 91 | } 92 | 93 | } 94 | } 95 | } 96 | } 97 | 98 | #endregion 99 | // ---------------------------------------------------------------------------------------------------------------- 100 | } 101 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Scripts/Main.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bde5bd8db153fb4429aabdfecbf3e3c3 3 | timeCreated: 1496062021 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 83c2880efb5a55c4d912e0262d70573c 3 | folderAsset: yes 4 | timeCreated: 1499066043 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites/character.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Sprites/character.png -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites/character.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65b0651ef19a49c4e9c6c4ff297c3d52 3 | timeCreated: 1499065980 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: 0 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 0 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: Android 70 | maxTextureSize: 2048 71 | textureFormat: -1 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 0 77 | - buildTarget: WebGL 78 | maxTextureSize: 2048 79 | textureFormat: -1 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 0 85 | spriteSheet: 86 | serializedVersion: 2 87 | sprites: [] 88 | outline: [] 89 | spritePackingTag: 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Sprites/tiles.png -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites/tiles.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 40d48dc34acd41044a366ee03841e848 3 | timeCreated: 1498726932 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: 7 | 21300000: tiles_0 8 | 21300002: tiles_1 9 | 21300004: tiles_3 10 | 21300006: tiles_5 11 | 21300008: tiles_8 12 | 21300010: tiles_9 13 | 21300012: tiles_16 14 | 21300014: tiles_17 15 | 21300016: tiles_19 16 | 21300018: tiles_21 17 | 21300020: tiles_36 18 | 21300022: tiles_37 19 | 21300024: tiles_38 20 | 21300026: tiles_39 21 | 21300028: tiles_40 22 | 21300030: tiles_41 23 | 21300032: tiles_42 24 | 21300034: tiles_43 25 | 21300036: tiles_44 26 | 21300038: tiles_45 27 | 21300040: tiles_46 28 | 21300042: tiles_47 29 | 21300044: tiles_48 30 | 21300046: tiles_49 31 | 21300048: tiles_50 32 | 21300050: tiles_51 33 | 21300052: tiles_52 34 | 21300054: tiles_53 35 | 21300056: tiles_54 36 | 21300058: tiles_55 37 | 21300060: tiles_56 38 | 21300062: tiles_57 39 | 21300064: tiles_58 40 | 21300066: tiles_59 41 | 21300068: tiles_60 42 | 21300070: tiles_61 43 | 21300072: tiles_62 44 | 21300074: tiles_63 45 | 21300076: tiles_2 46 | 21300078: tiles_4 47 | 21300080: tiles_6 48 | 21300082: tiles_7 49 | 21300084: tiles_10 50 | 21300086: tiles_11 51 | 21300088: tiles_12 52 | 21300090: tiles_13 53 | 21300092: tiles_14 54 | 21300094: tiles_15 55 | serializedVersion: 4 56 | mipmaps: 57 | mipMapMode: 0 58 | enableMipMap: 0 59 | sRGBTexture: 1 60 | linearTexture: 0 61 | fadeOut: 0 62 | borderMipMap: 0 63 | mipMapFadeDistanceStart: 1 64 | mipMapFadeDistanceEnd: 3 65 | bumpmap: 66 | convertToNormalMap: 0 67 | externalNormalMap: 0 68 | heightScale: 0.25 69 | normalMapFilter: 0 70 | isReadable: 0 71 | grayScaleToAlpha: 0 72 | generateCubemap: 6 73 | cubemapConvolution: 0 74 | seamlessCubemap: 0 75 | textureFormat: 1 76 | maxTextureSize: 2048 77 | textureSettings: 78 | filterMode: 0 79 | aniso: -1 80 | mipBias: -1 81 | wrapMode: 1 82 | nPOTScale: 0 83 | lightmap: 0 84 | compressionQuality: 50 85 | spriteMode: 2 86 | spriteExtrude: 1 87 | spriteMeshType: 0 88 | alignment: 0 89 | spritePivot: {x: 0.5, y: 0.5} 90 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 91 | spritePixelsToUnits: 100 92 | alphaUsage: 1 93 | alphaIsTransparency: 1 94 | spriteTessellationDetail: -1 95 | textureType: 8 96 | textureShape: 1 97 | maxTextureSizeSet: 0 98 | compressionQualitySet: 0 99 | textureFormatSet: 0 100 | platformSettings: 101 | - buildTarget: DefaultTexturePlatform 102 | maxTextureSize: 2048 103 | textureFormat: -1 104 | textureCompression: 2 105 | compressionQuality: 50 106 | crunchedCompression: 0 107 | allowsAlphaSplitting: 0 108 | overridden: 0 109 | - buildTarget: Standalone 110 | maxTextureSize: 2048 111 | textureFormat: -1 112 | textureCompression: 2 113 | compressionQuality: 50 114 | crunchedCompression: 0 115 | allowsAlphaSplitting: 0 116 | overridden: 0 117 | - buildTarget: Android 118 | maxTextureSize: 2048 119 | textureFormat: -1 120 | textureCompression: 2 121 | compressionQuality: 50 122 | crunchedCompression: 0 123 | allowsAlphaSplitting: 0 124 | overridden: 0 125 | - buildTarget: WebGL 126 | maxTextureSize: 2048 127 | textureFormat: -1 128 | textureCompression: 2 129 | compressionQuality: 50 130 | crunchedCompression: 0 131 | allowsAlphaSplitting: 0 132 | overridden: 0 133 | spriteSheet: 134 | serializedVersion: 2 135 | sprites: 136 | - serializedVersion: 2 137 | name: tiles_0 138 | rect: 139 | serializedVersion: 2 140 | x: 16 141 | y: 96 142 | width: 16 143 | height: 16 144 | alignment: 0 145 | pivot: {x: 0, y: 0} 146 | border: {x: 0, y: 0, z: 0, w: 0} 147 | outline: [] 148 | tessellationDetail: 0 149 | - serializedVersion: 2 150 | name: tiles_1 151 | rect: 152 | serializedVersion: 2 153 | x: 32 154 | y: 96 155 | width: 16 156 | height: 16 157 | alignment: 0 158 | pivot: {x: 0, y: 0} 159 | border: {x: 0, y: 0, z: 0, w: 0} 160 | outline: [] 161 | tessellationDetail: 0 162 | - serializedVersion: 2 163 | name: tiles_2 164 | rect: 165 | serializedVersion: 2 166 | x: 48 167 | y: 96 168 | width: 16 169 | height: 16 170 | alignment: 0 171 | pivot: {x: 0, y: 0} 172 | border: {x: 0, y: 0, z: 0, w: 0} 173 | outline: [] 174 | tessellationDetail: 0 175 | - serializedVersion: 2 176 | name: tiles_3 177 | rect: 178 | serializedVersion: 2 179 | x: 80 180 | y: 96 181 | width: 16 182 | height: 16 183 | alignment: 0 184 | pivot: {x: 0, y: 0} 185 | border: {x: 0, y: 0, z: 0, w: 0} 186 | outline: [] 187 | tessellationDetail: 0 188 | - serializedVersion: 2 189 | name: tiles_4 190 | rect: 191 | serializedVersion: 2 192 | x: 16 193 | y: 80 194 | width: 16 195 | height: 16 196 | alignment: 0 197 | pivot: {x: 0, y: 0} 198 | border: {x: 0, y: 0, z: 0, w: 0} 199 | outline: [] 200 | tessellationDetail: 0 201 | - serializedVersion: 2 202 | name: tiles_5 203 | rect: 204 | serializedVersion: 2 205 | x: 32 206 | y: 80 207 | width: 16 208 | height: 16 209 | alignment: 0 210 | pivot: {x: 0, y: 0} 211 | border: {x: 0, y: 0, z: 0, w: 0} 212 | outline: [] 213 | tessellationDetail: 0 214 | - serializedVersion: 2 215 | name: tiles_6 216 | rect: 217 | serializedVersion: 2 218 | x: 48 219 | y: 80 220 | width: 16 221 | height: 16 222 | alignment: 0 223 | pivot: {x: 0, y: 0} 224 | border: {x: 0, y: 0, z: 0, w: 0} 225 | outline: [] 226 | tessellationDetail: 0 227 | - serializedVersion: 2 228 | name: tiles_7 229 | rect: 230 | serializedVersion: 2 231 | x: 80 232 | y: 80 233 | width: 16 234 | height: 16 235 | alignment: 0 236 | pivot: {x: 0, y: 0} 237 | border: {x: 0, y: 0, z: 0, w: 0} 238 | outline: [] 239 | tessellationDetail: 0 240 | - serializedVersion: 2 241 | name: tiles_8 242 | rect: 243 | serializedVersion: 2 244 | x: 16 245 | y: 64 246 | width: 16 247 | height: 16 248 | alignment: 0 249 | pivot: {x: 0, y: 0} 250 | border: {x: 0, y: 0, z: 0, w: 0} 251 | outline: [] 252 | tessellationDetail: 0 253 | - serializedVersion: 2 254 | name: tiles_9 255 | rect: 256 | serializedVersion: 2 257 | x: 32 258 | y: 64 259 | width: 16 260 | height: 16 261 | alignment: 0 262 | pivot: {x: 0, y: 0} 263 | border: {x: 0, y: 0, z: 0, w: 0} 264 | outline: [] 265 | tessellationDetail: 0 266 | - serializedVersion: 2 267 | name: tiles_10 268 | rect: 269 | serializedVersion: 2 270 | x: 48 271 | y: 64 272 | width: 16 273 | height: 16 274 | alignment: 0 275 | pivot: {x: 0, y: 0} 276 | border: {x: 0, y: 0, z: 0, w: 0} 277 | outline: [] 278 | tessellationDetail: 0 279 | - serializedVersion: 2 280 | name: tiles_11 281 | rect: 282 | serializedVersion: 2 283 | x: 80 284 | y: 64 285 | width: 16 286 | height: 16 287 | alignment: 0 288 | pivot: {x: 0, y: 0} 289 | border: {x: 0, y: 0, z: 0, w: 0} 290 | outline: [] 291 | tessellationDetail: 0 292 | - serializedVersion: 2 293 | name: tiles_12 294 | rect: 295 | serializedVersion: 2 296 | x: 16 297 | y: 32 298 | width: 16 299 | height: 16 300 | alignment: 0 301 | pivot: {x: 0, y: 0} 302 | border: {x: 0, y: 0, z: 0, w: 0} 303 | outline: [] 304 | tessellationDetail: 0 305 | - serializedVersion: 2 306 | name: tiles_13 307 | rect: 308 | serializedVersion: 2 309 | x: 32 310 | y: 32 311 | width: 16 312 | height: 16 313 | alignment: 0 314 | pivot: {x: 0, y: 0} 315 | border: {x: 0, y: 0, z: 0, w: 0} 316 | outline: [] 317 | tessellationDetail: 0 318 | - serializedVersion: 2 319 | name: tiles_14 320 | rect: 321 | serializedVersion: 2 322 | x: 48 323 | y: 32 324 | width: 16 325 | height: 16 326 | alignment: 0 327 | pivot: {x: 0, y: 0} 328 | border: {x: 0, y: 0, z: 0, w: 0} 329 | outline: [] 330 | tessellationDetail: 0 331 | - serializedVersion: 2 332 | name: tiles_15 333 | rect: 334 | serializedVersion: 2 335 | x: 80 336 | y: 32 337 | width: 16 338 | height: 16 339 | alignment: 0 340 | pivot: {x: 0, y: 0} 341 | border: {x: 0, y: 0, z: 0, w: 0} 342 | outline: [] 343 | tessellationDetail: 0 344 | outline: [] 345 | spritePackingTag: 346 | userData: 347 | assetBundleName: 348 | assetBundleVariant: 349 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites/trap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/Sprites/trap.png -------------------------------------------------------------------------------- /Assets/GameMap/Sample/Sprites/trap.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1776fa26195f4d14a8d19c15614b3dd1 3 | timeCreated: 1497703226 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: 0 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: Android 70 | maxTextureSize: 2048 71 | textureFormat: -1 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 0 77 | - buildTarget: WebGL 78 | maxTextureSize: 2048 79 | textureFormat: -1 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 0 85 | spriteSheet: 86 | serializedVersion: 2 87 | sprites: [] 88 | outline: [] 89 | spritePackingTag: 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Assets/GameMap/Sample/sample-scene.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plyoung/GameMap2D/ed90ef36a31c13ee65f20da5f092d8d4c2349fc0/Assets/GameMap/Sample/sample-scene.unity -------------------------------------------------------------------------------- /Assets/GameMap/Sample/sample-scene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cf5bd62273c2d724ea3c6000a32133cc 3 | timeCreated: 1496061014 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/GameMap/readme-gamemap.txt: -------------------------------------------------------------------------------- 1 | GameMap and Editor 2 | by Leslie Young 3 | http://forum.plyoung.com/ 4 | 5 | 6 | Introduction 7 | ------------ 8 | 9 | GameMap is a simple 2D grid based solution for keeping track of map data. It also includes an editor where you can quickly define new maps and tiles. The editor includes a map editor to easily "paint" tiles on the map. 10 | 11 | A core feature of this kit is the ability to add fields to the asset, map and tile classes and be able to edit those fields in the map editor without having to make changes to the editor code; much like you would expect from scripts (components) shown in the Inspector. 12 | 13 | This tool is useful for when you do not want to draw maps/levels (grid of tile sprites) directly in scenes, for example via Unity's new tile editor, and will rather place the sprites at runtime from map data or do something else with the map data at runtime. 14 | 15 | What you do with the "map data" is up to you. This kit does not try to dictate how the grid of tiles are rendered or placed at runtime. It simply provides the editor to edit this data and make it available at runtime. As such this is a tool geared towards programmers or a team which has a programmer who will know what to do with the runtime data. Example of runtime use is included. 16 | 17 | The editor also includes a simple Auto-tiles system. These are tiles which automatically changes depending on which other tiles are around them when you place a new tile. It does not support transition to other tile-sets though and corner tiles are not supported either. 18 | 19 | 20 | Editor 21 | ------ 22 | 23 | The editor can be opened from menu: Window > GameMap Editor. 24 | 25 | 26 | * Editor 27 | 28 | Here you can make changes to editor settings. 29 | 30 | Outside is Solid: This toggle allows you to set how auto-tiles should treat the "outside" if the map when calculating what tiles to place. 31 | 32 | Auto-tile Size: Helps the editor determine how to render auto-tiles which are not using "full rect" sprites. You basically have to specify what size the tiles are, like 16, 32, etc. or leave it at 0 to not use this value. 33 | 34 | 35 | * Assets 36 | 37 | First you need to select or create a new Maps asset. This is the asset which will include all the maps and a reference to the tiles asset used by these maps. Then select or create a tiles asset to associate with the maps asset. 38 | 39 | Now you should see options to define maps and tiles. 40 | 41 | 42 | * Maps 43 | 44 | Click on "select" button in the Maps area to create or select a map. 45 | 46 | You will see an "ident" field, the "ren" button next to it allows you to change it. This name (or its ID) can be used to find the map at runtime. Each map is given a unique Integer ID which can't be changed. 47 | 48 | The Size fields allows you to change the width and height of the map. Press "apply" to apply the new size. A map's 0x0 location is at the bottom-left with (width-1) x (height-1) position at the top-right. 49 | 50 | 51 | * Layers 52 | 53 | The layers of tiles in the selected map. In the editor grid the later layers apears behind tiles of layers above. 54 | 55 | By default there is only one layer and this data is saved in GameMap.grid. This is known as the default layer or layer-0. The data for any addition layers you add are stored in GameMap.layers. 56 | 57 | 58 | * Tiles 59 | 60 | The tiles section allows you to define and select tiles to paint onto maps. 61 | 62 | Each tile is given a unique Integer ID. This ID is added to the GameMap.grid when you paint tiles. -1 is used for "empty tiles" in the grid. 63 | 64 | The Buttons in this area are as follow: 65 | 66 | - [x]: clear selected tiles. Left click in map editor canvas will remove tiles. 67 | - [<]: move selected tile left in the list of tiles. 68 | - [<]: move selected tile right in the list of tiles. 69 | - [+]: add a new tile. 70 | - [-]: remove selected tile. 71 | 72 | The properties you see for editing will depend on what fields were added to the GameMapTile class. 73 | 74 | To help visualise what a tile represents you can use a Sprite, Colour, Integer values, and String values. To tell the editor that a field should be used for this you simply add the [GameMapTilePreview] attribute to the field(s). Have a look at the source file of the GameMapTile class to learn more. By default a Color, Sprite, intVal, and strVal fields are included. 75 | 76 | 77 | * Canvas 78 | 79 | The editor canvas (a grid with black background) is where you can draw tiles onto the map. Click on a tile in the list of defined tiles to make it active, then click on the canvas to place the tile. You can also click-and-drag the mouse to place a series of tiles. 80 | 81 | - Left-Click/Drag: Place tiles (or remove if no tile is selected). 82 | - Right-Click/Drag: Remove tiles. 83 | - Shift+Left-Click/Drag: Mark tiles in canvas. 84 | - Del/Delete command: Delete marked tiles. 85 | - Ctrl+C/Copy command: Copy marked tiles. 86 | - Ctrl+V/Paste command: Make copied tiles available for pasting (move mouse and click in canvas to place the tiles). 87 | - Esc/[x]: Cancel marking tiles. 88 | 89 | 90 | Runtime 91 | ------- 92 | 93 | Please have a look at the source code to learn more about what the runtime classes present. 94 | 95 | **GameMapTilesAsset** has a list of defined tiles and is normally associated with a GameMapsAsset. 96 | 97 | **GameMapsAsset** holds a list of all defined maps. It also has a reference to the tiles asset used by the maps. 98 | 99 | **GameMap** represent one map. Its main property is the "grid" which is an array of Integer values. -1 is an "empty tile" while positive values relates to the GameMapTile.id (note, not the Index of a tile in GameMapTilesAsset). There are function to get direct references to the tile definition so that you do not have to look it up from the ID from the grid[]. You may also add additional properties to this class and edit the values in the map editor (only serializable fields will be presented in the editor). 100 | 101 | **GameMapTile** is a tile definition. This is where you will place any properties about a tile needed by your game at runtime. These properties (any serializable fields) will be presented for editing in the Map editor. 102 | 103 | -------------------------------------------------------------------------------- /Assets/GameMap/readme-gamemap.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5534986f89a79e74aa63b5e97396e27b 3 | timeCreated: 1496646088 4 | licenseType: Free 5 | TextScriptImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GameMap2D 2 | 3 | GameMap is a simple 2D grid based solution for creating and keeping track of game map/ level data. It includes an editor where you can quickly define new maps and tiles. The editor has a map editor to easily "paint" tiles on the map. 4 | GameMap is a simple 2D grid based solution for creating and keeping track of game map/ level data in Unity. It includes an editor where you can quickly define new maps and tiles. The editor has a map editor to easily "paint" tiles on the map. 5 | 6 | It was used in the development [of this game](https://plyoung.itch.io/peter-block). 7 | 8 | A core feature of this kit is the ability to add fields to the asset, map and tile classes and be able to edit those fields in the map editor without having to make changes to the editor code; much like you would expect from scripts (components) shown in the Inspector. 9 | 10 | This tool is useful for when you do not want to draw maps/levels (grid of tile sprites) directly in scenes, for example via Unity's new tile editor, and will rather place the sprites at runtime from map data or do something else with the map data at runtime. 11 | 12 | What you do with the "map data" is up to you. This kit does not try to dictate how the grid of tiles are rendered or placed at runtime. It simply provides the editor to edit this data and make it available at runtime. As such this is a tool geared towards programmers or a team which has a programmer who will know what to do with the runtime data. Example of runtime use is included. 13 | 14 | The editor also includes a simple Auto-tiles system. These are tiles which automatically changes depending on which other tiles are placed around them. It does not support transition to other tile-sets though. It supports both 16-tile and 47-tile systems. 15 | 16 | ![](https://user-images.githubusercontent.com/837362/29742219-52a1e686-8a7b-11e7-9659-a32e8d8bd323.png) 17 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | --------------------------------------------------------------------------------