コード例 #1
0
    public static void UnloadUnusedAssets()
    {
        EditorUtility.UnloadUnusedAssets();
        System.GC.Collect();

        index = null;
    }
コード例 #2
0
 public static tk2dIndex GetExistingIndex()
 {
     if (index == null)
     {
         index = AssetDatabase.LoadAssetAtPath(indexPath, typeof(tk2dIndex)) as tk2dIndex;
     }
     return(index);
 }
コード例 #3
0
    public static void UnloadUnusedAssets()
    {
        Object[] previousSelectedObjects = Selection.objects;
        Selection.objects = new Object[0];

        System.GC.Collect();
        EditorUtility.UnloadUnusedAssets();

        index = null;

        Selection.objects = previousSelectedObjects;
    }
コード例 #4
0
    public static tk2dIndex GetOrCreateIndex()
    {
        tk2dIndex thisIndex = GetExistingIndex();

        if (thisIndex == null || thisIndex.version != tk2dIndex.CURRENT_VERSION)
        {
            CreateIndex();
            thisIndex = GetExistingIndex();
        }

        return(thisIndex);
    }
コード例 #5
0
    public static tk2dIndex GetOrCreateIndex()
    {
        tk2dIndex thisIndex = GetExistingIndex();

        if (thisIndex == null)
        {
            CreateIndex();
            thisIndex = GetExistingIndex();
        }

        return(thisIndex);
    }
コード例 #6
0
 public static tk2dIndex GetExistingIndex()
 {
     if (index == null)
     {
         GameObject go = AssetDatabase.LoadAssetAtPath(indexPath, typeof(GameObject)) as GameObject;
         if (go)
         {
             index = go.GetComponent <tk2dIndex>();
         }
     }
     return(index);
 }
コード例 #7
0
    public static void UnloadUnusedAssets()
    {
        Object previousSelectedObject = Selection.activeObject;

        Selection.activeObject = null;

        EditorUtility.UnloadUnusedAssetsIgnoreManagedReferences();
        System.GC.Collect();

        index = null;

        Selection.activeObject = previousSelectedObject;
    }
コード例 #8
0
    // Rebuild a sprite collection when out of date
    // Identifies changed textures by comparing GUID
    public static void RebuildOutOfDate(string[] changedPaths)
    {
        // This should only take existing indices, as we don't want to slow anything down here
        tk2dIndex index = tk2dEditorUtility.GetExistingIndex();

        if (index == null)
        {
            return;
        }

        tk2dSpriteCollectionData[] scg = tk2dEditorUtility.GetExistingIndex().GetSpriteCollectionData();
        if (scg == null)
        {
            return;
        }

        foreach (tk2dSpriteCollectionData thisScg in scg)
        {
            bool needRebuild = false;
            foreach (var def in thisScg.spriteDefinitions)
            {
                foreach (string changedPath in changedPaths)
                {
                    if (def.sourceTextureGUID == AssetDatabase.AssetPathToGUID(changedPath))
                    {
                        needRebuild = true;
                        break;
                    }
                }

                if (needRebuild)
                {
                    break;
                }
            }

            if (needRebuild)
            {
                tk2dSpriteCollection spriteCollectionSource = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(thisScg.spriteCollectionGUID), typeof(tk2dSpriteCollection)) as tk2dSpriteCollection;
                if (spriteCollectionSource != null)
                {
                    Rebuild(spriteCollectionSource);
                }

                tk2dEditorUtility.UnloadUnusedAssets();
            }
        }
    }
コード例 #9
0
    public static void UnloadUnusedAssets()
    {
        Object[] previousSelectedObjects = Selection.objects;
        Selection.objects = new Object[0];

        System.GC.Collect();
#if (UNITY_3_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_4_8 || UNITY_4_9)
        EditorUtility.UnloadUnusedAssets();
#else
        EditorUtility.UnloadUnusedAssetsImmediate();
#endif

        index = null;

        Selection.objects = previousSelectedObjects;
    }
コード例 #10
0
    public static void UnloadUnusedAssets()
    {
        Object[] previousSelectedObjects = Selection.objects;
        Selection.objects = new Object[0];

        System.GC.Collect();
        #if UNITY_5_6_OR_NEWER
        EditorUtility.UnloadUnusedAssetsImmediate();
        #else
        EditorUtility.UnloadUnusedAssets();
        #endif

        index = null;

        Selection.objects = previousSelectedObjects;
    }
コード例 #11
0
    static void CreateIndex()
    {
        tk2dIndex newIndex = ScriptableObject.CreateInstance <tk2dIndex>();

        newIndex.version   = tk2dIndex.CURRENT_VERSION;
        newIndex.hideFlags = HideFlags.DontSave;         // get this to not be destroyed in Unity 4.1

        List <string> rebuildSpriteCollectionPaths = new List <string>();

        // check all prefabs to see if we can find any objects we are interested in
        List <string>  allPrefabPaths = new List <string>();
        Stack <string> paths          = new Stack <string>();

        paths.Push(Application.dataPath);
        while (paths.Count != 0)
        {
            string   path  = paths.Pop();
            string[] files = Directory.GetFiles(path, "*.prefab");
            foreach (var file in files)
            {
                allPrefabPaths.Add(file.Substring(Application.dataPath.Length - 6));
            }

            foreach (string subdirs in Directory.GetDirectories(path))
            {
                paths.Push(subdirs);
            }
        }

        // Check all prefabs
        int currPrefabCount = 1;

        foreach (string prefabPath in allPrefabPaths)
        {
            EditorUtility.DisplayProgressBar("Rebuilding Index", "Scanning project folder...", (float)currPrefabCount / (float)(allPrefabPaths.Count));

            GameObject iterGo = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject;
            if (!iterGo)
            {
                continue;
            }

            tk2dSpriteCollection     spriteCollection     = iterGo.GetComponent <tk2dSpriteCollection>();
            tk2dSpriteCollectionData spriteCollectionData = iterGo.GetComponent <tk2dSpriteCollectionData>();
            tk2dFont            font = iterGo.GetComponent <tk2dFont>();
            tk2dSpriteAnimation anim = iterGo.GetComponent <tk2dSpriteAnimation>();

            if (spriteCollection)
            {
                tk2dSpriteCollectionData thisSpriteCollectionData = spriteCollection.spriteCollection;
                if (thisSpriteCollectionData)
                {
                    if (thisSpriteCollectionData.version < 1)
                    {
                        rebuildSpriteCollectionPaths.Add(AssetDatabase.GetAssetPath(spriteCollection));
                    }
                    newIndex.AddSpriteCollectionData(thisSpriteCollectionData);
                }
            }
            else if (spriteCollectionData)
            {
                string guid    = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(spriteCollectionData));
                bool   present = false;
                foreach (var v in newIndex.GetSpriteCollectionIndex())
                {
                    if (v.spriteCollectionDataGUID == guid)
                    {
                        present = true;
                        break;
                    }
                }
                if (!present && guid != "")
                {
                    newIndex.AddSpriteCollectionData(spriteCollectionData);
                }
            }
            else if (font)
            {
                newIndex.AddOrUpdateFont(font);                 // unfortunate but necessary
            }
            else if (anim)
            {
                newIndex.AddSpriteAnimation(anim);
            }
            else
            {
                iterGo = null;
                System.GC.Collect();
            }

            tk2dEditorUtility.UnloadUnusedAssets();
            ++currPrefabCount;
        }
        EditorUtility.ClearProgressBar();

        // Create index
        newIndex.hideFlags = 0;         // to save it
        AssetDatabase.CreateAsset(newIndex, indexPath);
        AssetDatabase.SaveAssets();

        // unload all unused assets
        tk2dEditorUtility.UnloadUnusedAssets();

        // Rebuild invalid sprite collections
        if (rebuildSpriteCollectionPaths.Count > 0)
        {
            EditorUtility.DisplayDialog("Upgrade required",
                                        "Please wait while your sprite collection is upgraded.",
                                        "Ok");

            int count = 1;
            foreach (var scPath in rebuildSpriteCollectionPaths)
            {
                tk2dSpriteCollection sc = AssetDatabase.LoadAssetAtPath(scPath, typeof(tk2dSpriteCollection)) as tk2dSpriteCollection;
                EditorUtility.DisplayProgressBar("Rebuilding Sprite Collections", "Rebuilding Sprite Collection: " + sc.name, (float)count / (float)(rebuildSpriteCollectionPaths.Count));

                tk2dSpriteCollectionBuilder.Rebuild(sc);
                sc = null;

                tk2dEditorUtility.UnloadUnusedAssets();

                ++count;
            }

            EditorUtility.ClearProgressBar();
        }

        index = newIndex;
        tk2dSpriteGuiUtility.ResetCache();
    }
    void DrawSettingsPanel()
    {
        // Tilemap data
        tk2dTileMapData newData = (tk2dTileMapData)EditorGUILayout.ObjectField("Tile Map Data", tileMap.data, typeof(tk2dTileMapData), false);

        if (newData != tileMap.data)
        {
            tileMap.data = newData;
            LoadTileMapData();
        }
        if (tileMap.data == null)
        {
            if (tk2dGuiUtility.InfoBoxWithButtons(
                    "TileMap needs an data object to proceed. " +
                    "Please create one or drag an existing data object into the inspector slot.\n",
                    tk2dGuiUtility.WarningLevel.Info,
                    "Create") != -1)
            {
                string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Data", "tileMapData", "asset", "");
                if (assetPath.Length > 0)
                {
                    tk2dTileMapData tileMapData = ScriptableObject.CreateInstance <tk2dTileMapData>();
                    AssetDatabase.CreateAsset(tileMapData, assetPath);
                    tileMap.data = tileMapData;
                    EditorUtility.SetDirty(tileMap);

                    Init(tileMapData);
                    LoadTileMapData();
                }
            }
        }

        // Editor data
        tk2dTileMapEditorData newEditorData = (tk2dTileMapEditorData)EditorGUILayout.ObjectField("Editor Data", editorData, typeof(tk2dTileMapEditorData), false);

        if (newEditorData != editorData)
        {
            string assetPath = AssetDatabase.GetAssetPath(newEditorData);
            if (assetPath.Length > 0)
            {
                tileMap.editorDataGUID = AssetDatabase.AssetPathToGUID(assetPath);
                EditorUtility.SetDirty(tileMap);
                LoadTileMapData();
            }
        }
        if (editorData == null)
        {
            if (tk2dGuiUtility.InfoBoxWithButtons(
                    "TileMap needs an editor data object to proceed. " +
                    "Please create one or drag an existing data object into the inspector slot.\n",
                    tk2dGuiUtility.WarningLevel.Info,
                    "Create") != -1)
            {
                string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Editor Data", "tileMapEditorData", "asset", "");
                if (assetPath.Length > 0)
                {
                    tk2dTileMapEditorData tileMapEditorData = ScriptableObject.CreateInstance <tk2dTileMapEditorData>();
                    AssetDatabase.CreateAsset(tileMapEditorData, assetPath);
                    tileMap.editorDataGUID = AssetDatabase.AssetPathToGUID(assetPath);
                    EditorUtility.SetDirty(tileMap);
                    LoadTileMapData();
                }
            }
        }

        // Sprite collection
        Object selectedSpriteCollectionObject = EditorGUILayout.ObjectField("Sprite Collection", tileMap.spriteCollection, typeof(Object), false) as Object;

        if (selectedSpriteCollectionObject != tileMap.spriteCollection)
        {
            string    assetPath = AssetDatabase.GetAssetPath(selectedSpriteCollectionObject);
            string    guid      = AssetDatabase.AssetPathToGUID(assetPath);
            tk2dIndex index     = tk2dEditorUtility.GetOrCreateIndex();

            foreach (var scIndex in index.GetSpriteCollectionIndex())
            {
                if (scIndex.spriteCollectionGUID == guid ||
                    scIndex.spriteCollectionDataGUID == guid)
                {
                    string realDataPath           = AssetDatabase.GUIDToAssetPath(scIndex.spriteCollectionDataGUID);
                    tk2dSpriteCollectionData data = AssetDatabase.LoadAssetAtPath(realDataPath, typeof(tk2dSpriteCollectionData)) as tk2dSpriteCollectionData;

                    if (data.allowMultipleAtlases)
                    {
                        Debug.Log("Atlas spanning not allowed");
                    }
                    else
                    {
                        tileMap.spriteCollection = data;
                        data.InitMaterialIds();
                        LoadTileMapData();

                        EditorUtility.SetDirty(tileMap);

                        if (Ready)
                        {
                            Init(tileMap.data);
                            tileMap.BeginEditMode();
                        }
                        break;
                    }
                }
            }
        }

        // If not set up, don't bother drawing anything else
        if (!Ready)
        {
            return;
        }

        tileMap.renderData = EditorGUILayout.ObjectField("Render Data", tileMap.renderData, typeof(GameObject), false) as GameObject;
        GUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel(" ");
        if (GUILayout.Button("Make Unique"))
        {
            tk2dRuntime.TileMap.BuilderUtil.CleanRenderData(tileMap);
            tileMap.renderData = null;
        }
        GUILayout.EndHorizontal();

        // tile map size
        editorData.showDimensions = EditorGUILayout.Foldout(editorData.showDimensions, "Dimensions");
        if (editorData.showDimensions)
        {
            EditorGUI.indentLevel++;

            width          = Mathf.Clamp(EditorGUILayout.IntField("Width", width), 1, 512);
            height         = Mathf.Clamp(EditorGUILayout.IntField("Height", height), 1, 512);
            partitionSizeX = Mathf.Clamp(EditorGUILayout.IntField("PartitionSizeX", partitionSizeX), 4, 32);
            partitionSizeY = Mathf.Clamp(EditorGUILayout.IntField("PartitionSizeY", partitionSizeY), 4, 32);

            // Create a default tilemap with given dimensions
            if (!tileMap.AreSpritesInitialized())
            {
                tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);
                tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, tileMap.partitionSizeX, tileMap.partitionSizeY);
            }

            if (width != tileMap.width || height != tileMap.height || partitionSizeX != tileMap.partitionSizeX || partitionSizeY != tileMap.partitionSizeY)
            {
                if ((width < tileMap.width || height < tileMap.height))
                {
                    tk2dGuiUtility.InfoBox("The new size of the tile map is smaller than the current size." +
                                           "Some clipping will occur.", tk2dGuiUtility.WarningLevel.Warning);
                }

                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Apply", EditorStyles.miniButton))
                {
                    tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, partitionSizeX, partitionSizeY);
                }
                GUILayout.EndHorizontal();
            }

            EditorGUI.indentLevel--;
        }

        editorData.showLayers = EditorGUILayout.Foldout(editorData.showLayers, "Layers");
        if (editorData.showLayers)
        {
            EditorGUI.indentLevel++;

            DrawLayersPanel(true);

            EditorGUI.indentLevel--;
        }

        // tilemap info
        editorData.showInfo = EditorGUILayout.Foldout(editorData.showInfo, "Info");
        if (editorData.showInfo)
        {
            EditorGUI.indentLevel++;

            int numActiveChunks = 0;
            if (tileMap.Layers != null)
            {
                foreach (var layer in tileMap.Layers)
                {
                    numActiveChunks += layer.NumActiveChunks;
                }
            }
            EditorGUILayout.LabelField("Active chunks", numActiveChunks.ToString());
            int partitionMemSize = partitionSizeX * partitionSizeY * 4;
            EditorGUILayout.LabelField("Memory", ((numActiveChunks * partitionMemSize) / 1024).ToString() + "kB");

            int numActiveColorChunks = 0;
            if (tileMap.ColorChannel != null)
            {
                numActiveColorChunks += tileMap.ColorChannel.NumActiveChunks;
            }
            EditorGUILayout.LabelField("Active color chunks", numActiveColorChunks.ToString());
            int colorMemSize = (partitionSizeX + 1) * (partitionSizeY + 1) * 4;
            EditorGUILayout.LabelField("Memory", ((numActiveColorChunks * colorMemSize) / 1024).ToString() + "kB");

            EditorGUI.indentLevel--;
        }

        // tile properties
        editorData.showTileProperties = EditorGUILayout.Foldout(editorData.showTileProperties, "Tile Properties");
        if (editorData.showTileProperties)
        {
            EditorGUI.indentLevel++;

            // sort method
            tk2dGuiUtility.BeginChangeCheck();
            tileMap.data.sortMethod = (tk2dTileMapData.SortMethod)EditorGUILayout.EnumPopup("Sort Method", tileMap.data.sortMethod);
            if (tk2dGuiUtility.EndChangeCheck())
            {
                tileMap.BeginEditMode();
            }


            // reset sizes
            GUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Reset sizes");
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Reset", EditorStyles.miniButtonRight))
            {
                Init(tileMap.data);
                Build(true);
            }
            GUILayout.EndHorizontal();

            // convert these to pixel units
            Vector3 texelSize        = SpriteCollection.spriteDefinitions[0].texelSize;
            Vector3 tileOriginPixels = new Vector3(tileMap.data.tileOrigin.x / texelSize.x, tileMap.data.tileOrigin.y / texelSize.y, tileMap.data.tileOrigin.z);
            Vector3 tileSizePixels   = new Vector3(tileMap.data.tileSize.x / texelSize.x, tileMap.data.tileSize.y / texelSize.y, tileMap.data.tileSize.z);

            Vector3 newTileOriginPixels = EditorGUILayout.Vector3Field("Cursor Origin", tileOriginPixels);
            Vector3 newTileSizePixels   = EditorGUILayout.Vector3Field("Tile Size", tileSizePixels);

            if (newTileOriginPixels != tileOriginPixels ||
                newTileSizePixels != tileSizePixels)
            {
                tileMap.data.tileOrigin = new Vector3(newTileOriginPixels.x * texelSize.x, newTileOriginPixels.y * texelSize.y, newTileOriginPixels.z);
                tileMap.data.tileSize   = new Vector3(newTileSizePixels.x * texelSize.x, newTileSizePixels.y * texelSize.y, newTileSizePixels.z);
                Build(true);
            }
            EditorGUI.indentLevel--;
        }

        editorData.showPaletteProperties = EditorGUILayout.Foldout(editorData.showPaletteProperties, "Palette Properties");
        if (editorData.showPaletteProperties)
        {
            EditorGUI.indentLevel++;
            int newTilesPerRow = Mathf.Clamp(EditorGUILayout.IntField("Tiles Per Row", editorData.paletteTilesPerRow),
                                             1, SpriteCollection.Count);
            if (newTilesPerRow != editorData.paletteTilesPerRow)
            {
                guiBrushBuilder.Reset();

                editorData.paletteTilesPerRow = newTilesPerRow;
                editorData.CreateDefaultPalette(tileMap.spriteCollection, editorData.paletteBrush, editorData.paletteTilesPerRow);
            }

            GUILayout.BeginHorizontal();
            editorData.brushDisplayScale = EditorGUILayout.FloatField("Display Scale", editorData.brushDisplayScale);
            editorData.brushDisplayScale = Mathf.Clamp(editorData.brushDisplayScale, 1.0f / 16.0f, 4.0f);
            if (GUILayout.Button("Reset", EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))
            {
                editorData.brushDisplayScale = 1.0f;
                Repaint();
            }
            GUILayout.EndHorizontal();

            EditorGUILayout.PrefixLabel("Preview");
            brushRenderer.DrawBrush(tileMap, editorData.paletteBrush, editorData.brushDisplayScale, true, editorData.paletteTilesPerRow);
            EditorGUI.indentLevel--;
        }

//		editorData.showAdvancedProperties = EditorGUILayout.Foldout(editorData.showAdvancedProperties, "Advanced");
//		if (editorData.showAdvancedProperties)
//		{
//		}
    }
コード例 #13
0
    void DrawSettingsPanel()
    {
        // Tilemap data
        tk2dTileMapData newData = (tk2dTileMapData)EditorGUILayout.ObjectField("Tile Map Data", tileMap.data, typeof(tk2dTileMapData), false);

        if (newData != tileMap.data)
        {
            tileMap.data = newData;
            LoadTileMapData();
        }
        if (tileMap.data == null)
        {
            if (tk2dGuiUtility.InfoBoxWithButtons(
                    "TileMap needs an data object to proceed. " +
                    "Please create one or drag an existing data object into the inspector slot.\n",
                    tk2dGuiUtility.WarningLevel.Info,
                    "Create") != -1)
            {
                string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Data", "tileMapData", "asset", "");
                if (assetPath.Length > 0)
                {
                    tk2dTileMapData tileMapData = ScriptableObject.CreateInstance <tk2dTileMapData>();
                    AssetDatabase.CreateAsset(tileMapData, assetPath);
                    tileMap.data = tileMapData;
                    EditorUtility.SetDirty(tileMap);

                    Init(tileMapData);
                    LoadTileMapData();
                }
            }
        }

        // Editor data
        tk2dTileMapEditorData newEditorData = (tk2dTileMapEditorData)EditorGUILayout.ObjectField("Editor Data", editorData, typeof(tk2dTileMapEditorData), false);

        if (newEditorData != editorData)
        {
            string assetPath = AssetDatabase.GetAssetPath(newEditorData);
            if (assetPath.Length > 0)
            {
                tileMap.editorDataGUID = AssetDatabase.AssetPathToGUID(assetPath);
                EditorUtility.SetDirty(tileMap);
                LoadTileMapData();
            }
        }
        if (editorData == null)
        {
            if (tk2dGuiUtility.InfoBoxWithButtons(
                    "TileMap needs an editor data object to proceed. " +
                    "Please create one or drag an existing data object into the inspector slot.\n",
                    tk2dGuiUtility.WarningLevel.Info,
                    "Create") != -1)
            {
                string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Editor Data", "tileMapEditorData", "asset", "");
                if (assetPath.Length > 0)
                {
                    tk2dTileMapEditorData tileMapEditorData = ScriptableObject.CreateInstance <tk2dTileMapEditorData>();
                    AssetDatabase.CreateAsset(tileMapEditorData, assetPath);
                    tileMap.editorDataGUID = AssetDatabase.AssetPathToGUID(assetPath);
                    EditorUtility.SetDirty(tileMap);
                    LoadTileMapData();
                }
            }
        }

        // Sprite collection
        GUILayout.BeginHorizontal();
        Object selectedSpriteCollectionObject = EditorGUILayout.ObjectField("Sprite Collection", tileMap.Editor__SpriteCollection, typeof(Object), false) as Object;

        if (tileMap.Editor__SpriteCollection != null && GUILayout.Button(">", EditorStyles.miniButton, GUILayout.Width(19)))
        {
            tk2dSpriteCollectionEditorPopup v = EditorWindow.GetWindow(typeof(tk2dSpriteCollectionEditorPopup), false, "Sprite Collection Editor") as tk2dSpriteCollectionEditorPopup;
            string assetPath        = AssetDatabase.GUIDToAssetPath(tileMap.Editor__SpriteCollection.spriteCollectionGUID);
            var    spriteCollection = AssetDatabase.LoadAssetAtPath(assetPath, typeof(tk2dSpriteCollection)) as tk2dSpriteCollection;
            v.SetGeneratorAndSelectedSprite(spriteCollection, 0);
        }
        GUILayout.EndHorizontal();
        if (selectedSpriteCollectionObject != tileMap.Editor__SpriteCollection)
        {
            string    assetPath = AssetDatabase.GetAssetPath(selectedSpriteCollectionObject);
            string    guid      = AssetDatabase.AssetPathToGUID(assetPath);
            tk2dIndex index     = tk2dEditorUtility.GetOrCreateIndex();

            foreach (var scIndex in index.GetSpriteCollectionIndex())
            {
                if (scIndex.spriteCollectionGUID == guid ||
                    scIndex.spriteCollectionDataGUID == guid)
                {
                    string realDataPath           = AssetDatabase.GUIDToAssetPath(scIndex.spriteCollectionDataGUID);
                    tk2dSpriteCollectionData data = AssetDatabase.LoadAssetAtPath(realDataPath, typeof(tk2dSpriteCollectionData)) as tk2dSpriteCollectionData;

                    if (data.allowMultipleAtlases)
                    {
                        Debug.Log("Atlas spanning not allowed");
                    }
                    else
                    {
                        tileMap.Editor__SpriteCollection = data;
                        data.InitMaterialIds();
                        LoadTileMapData();

                        EditorUtility.SetDirty(tileMap);

                        if (Ready)
                        {
                            Init(tileMap.data);
                            tileMap.BeginEditMode();
                        }
                        break;
                    }
                }
            }
        }

        // If not set up, don't bother drawing anything else
        if (!Ready)
        {
            return;
        }

        // this is intentionally read only
        EditorGUILayout.ObjectField("Render Data", tileMap.renderData, typeof(GameObject), false);
        GUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel(" ");
        if (GUILayout.Button("Make Unique"))
        {
            tk2dRuntime.TileMap.BuilderUtil.CleanRenderData(tileMap);
            tileMap.renderData = null;
        }
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel(" ");
        if (!tileMap.serializeRenderData && GUILayout.Button("Make Serializable"))
        {
            if (tileMap.serializeRenderData == true)
            {
                tk2dRuntime.TileMap.BuilderUtil.CleanRenderData(tileMap);                 // clear everything (i.e. all serialized meshes will be back in "serializedMeshes")
                tileMap.serializeRenderData = false;
            }

            string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Render Data", "Tilemap Render Data 1", "asset",
                                                                    "Select an asset file to save the render data to.\n" +
                                                                    "It is best to save this in an empty directory, as the tilemap may contain more than one mesh");
            if (assetPath.Length > 0)
            {
                tileMap.serializeRenderData = true;
                tileMap.serializedMeshPath  = assetPath;
                if (tileMap.renderData)
                {
                    List <Mesh>    existingMeshes = new List <Mesh>();
                    MeshFilter[]   meshFilters    = tileMap.renderData.GetComponentsInChildren <MeshFilter>();
                    MeshCollider[] meshColliders  = tileMap.renderData.GetComponentsInChildren <MeshCollider>();
                    foreach (var j in meshFilters)
                    {
                        existingMeshes.Add(j.sharedMesh);
                    }
                    foreach (var j in meshColliders)
                    {
                        existingMeshes.Add(j.sharedMesh);
                    }

                    existingMeshes.RemoveAll(a => a == null);
                    foreach (var j in existingMeshes)
                    {
                        j.RecalculateNormals();                         // normals are likely to be missing here
                        AssetDatabase.CreateAsset(j, AssetDatabase.GenerateUniqueAssetPath(tileMap.serializedMeshPath));
                    }
                }
            }
        }
        if (tileMap.serializeRenderData)
        {
            if (GUILayout.Toggle(true, "Serialized", "button") == false)
            {
                GameObject.DestroyImmediate(tileMap.renderData);
                tileMap.renderData          = null;
                tileMap.serializeRenderData = false;

                Build(true);
            }
        }
        GUILayout.EndHorizontal();

        // tile map size

        if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Dimensions, "Dimensions"))
        {
            EditorGUI.indentLevel++;

            width          = Mathf.Clamp(EditorGUILayout.IntField("Width", width), 1, tk2dEditor.TileMap.TileMapUtility.MaxWidth);
            height         = Mathf.Clamp(EditorGUILayout.IntField("Height", height), 1, tk2dEditor.TileMap.TileMapUtility.MaxHeight);
            partitionSizeX = Mathf.Clamp(EditorGUILayout.IntField("PartitionSizeX", partitionSizeX), 4, 32);
            partitionSizeY = Mathf.Clamp(EditorGUILayout.IntField("PartitionSizeY", partitionSizeY), 4, 32);

            // Create a default tilemap with given dimensions
            if (!tileMap.AreSpritesInitialized())
            {
                tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);
                tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, tileMap.partitionSizeX, tileMap.partitionSizeY);
            }

            if (width != tileMap.width || height != tileMap.height || partitionSizeX != tileMap.partitionSizeX || partitionSizeY != tileMap.partitionSizeY)
            {
                if ((width < tileMap.width || height < tileMap.height))
                {
                    tk2dGuiUtility.InfoBox("The new size of the tile map is smaller than the current size." +
                                           "Some clipping will occur.", tk2dGuiUtility.WarningLevel.Warning);
                }

                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Apply", EditorStyles.miniButton))
                {
                    tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, partitionSizeX, partitionSizeY);
                }
                GUILayout.EndHorizontal();
            }

            EditorGUI.indentLevel--;
        }

        if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Layers, "Layers"))
        {
            EditorGUI.indentLevel++;

            DrawLayersPanel(true);

            EditorGUI.indentLevel--;
        }

        // tilemap info
        if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Info, "Info"))
        {
            EditorGUI.indentLevel++;

            int numActiveChunks = 0;
            if (tileMap.Layers != null)
            {
                foreach (var layer in tileMap.Layers)
                {
                    numActiveChunks += layer.NumActiveChunks;
                }
            }
            EditorGUILayout.LabelField("Active chunks", numActiveChunks.ToString());
            int partitionMemSize = partitionSizeX * partitionSizeY * 4;
            EditorGUILayout.LabelField("Memory", ((numActiveChunks * partitionMemSize) / 1024).ToString() + "kB");

            int numActiveColorChunks = 0;
            if (tileMap.ColorChannel != null)
            {
                numActiveColorChunks += tileMap.ColorChannel.NumActiveChunks;
            }
            EditorGUILayout.LabelField("Active color chunks", numActiveColorChunks.ToString());
            int colorMemSize = (partitionSizeX + 1) * (partitionSizeY + 1) * 4;
            EditorGUILayout.LabelField("Memory", ((numActiveColorChunks * colorMemSize) / 1024).ToString() + "kB");

            EditorGUI.indentLevel--;
        }

        // tile properties
        if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.TileProperties, "Tile Properties"))
        {
            EditorGUI.indentLevel++;

            // sort method
            tk2dGuiUtility.BeginChangeCheck();
            tileMap.data.tileType   = (tk2dTileMapData.TileType)EditorGUILayout.EnumPopup("Tile Type", tileMap.data.tileType);
            tileMap.data.sortMethod = (tk2dTileMapData.SortMethod)EditorGUILayout.EnumPopup("Sort Method", tileMap.data.sortMethod);
            if (tk2dGuiUtility.EndChangeCheck())
            {
                tileMap.BeginEditMode();
            }


            // reset sizes
            GUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Reset sizes");
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Reset", EditorStyles.miniButtonRight))
            {
                Init(tileMap.data);
                Build(true);
            }
            GUILayout.EndHorizontal();

            // convert these to pixel units
            Vector3 texelSize        = SpriteCollection.spriteDefinitions[0].texelSize;
            Vector3 tileOriginPixels = new Vector3(tileMap.data.tileOrigin.x / texelSize.x, tileMap.data.tileOrigin.y / texelSize.y, tileMap.data.tileOrigin.z);
            Vector3 tileSizePixels   = new Vector3(tileMap.data.tileSize.x / texelSize.x, tileMap.data.tileSize.y / texelSize.y, tileMap.data.tileSize.z);

            Vector3 newTileOriginPixels = EditorGUILayout.Vector3Field("Origin", tileOriginPixels);
            Vector3 newTileSizePixels   = EditorGUILayout.Vector3Field("Size", tileSizePixels);

            if (newTileOriginPixels != tileOriginPixels ||
                newTileSizePixels != tileSizePixels)
            {
                tileMap.data.tileOrigin = new Vector3(newTileOriginPixels.x * texelSize.x, newTileOriginPixels.y * texelSize.y, newTileOriginPixels.z);
                tileMap.data.tileSize   = new Vector3(newTileSizePixels.x * texelSize.x, newTileSizePixels.y * texelSize.y, newTileSizePixels.z);
                Build(true);
            }
            EditorGUI.indentLevel--;
        }

        if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.PaletteProperties, "Palette Properties"))
        {
            EditorGUI.indentLevel++;
            int newTilesPerRow = Mathf.Clamp(EditorGUILayout.IntField("Tiles Per Row", editorData.paletteTilesPerRow),
                                             1, SpriteCollection.Count);
            if (newTilesPerRow != editorData.paletteTilesPerRow)
            {
                guiBrushBuilder.Reset();

                editorData.paletteTilesPerRow = newTilesPerRow;
                editorData.CreateDefaultPalette(tileMap.SpriteCollectionInst, editorData.paletteBrush, editorData.paletteTilesPerRow);
            }

            GUILayout.BeginHorizontal();
            editorData.brushDisplayScale = EditorGUILayout.FloatField("Display Scale", editorData.brushDisplayScale);
            editorData.brushDisplayScale = Mathf.Clamp(editorData.brushDisplayScale, 1.0f / 16.0f, 4.0f);
            if (GUILayout.Button("Reset", EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))
            {
                editorData.brushDisplayScale = 1.0f;
                Repaint();
            }
            GUILayout.EndHorizontal();

            EditorGUILayout.PrefixLabel("Preview");
            brushRenderer.DrawBrush(tileMap, editorData.paletteBrush, editorData.brushDisplayScale, true, editorData.paletteTilesPerRow);
            EditorGUI.indentLevel--;
        }

        if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Import, "Import"))
        {
            EditorGUI.indentLevel++;

            if (GUILayout.Button("Import TMX"))
            {
                if (tk2dEditor.TileMap.Importer.Import(tileMap, tk2dEditor.TileMap.Importer.Format.TMX))
                {
                    Build(true);
                    width          = tileMap.width;
                    height         = tileMap.height;
                    partitionSizeX = tileMap.partitionSizeX;
                    partitionSizeY = tileMap.partitionSizeY;
                }
            }

            EditorGUI.indentLevel--;
        }
    }
コード例 #14
0
    static void CreateIndex()
    {
        GameObject go       = new GameObject();
        tk2dIndex  newIndex = go.AddComponent <tk2dIndex>();

        go.active = false;

        List <string> rebuildSpriteCollectionPaths = new List <string>();

        // check all prefabs to see if we can find any objects we are interested in
        List <string>  allPrefabPaths = new List <string>();
        Stack <string> paths          = new Stack <string>();

        paths.Push(Application.dataPath);
        while (paths.Count != 0)
        {
            string   path  = paths.Pop();
            string[] files = Directory.GetFiles(path, "*.prefab");
            foreach (var file in files)
            {
                allPrefabPaths.Add(file.Substring(Application.dataPath.Length - 6));
            }

            foreach (string subdirs in Directory.GetDirectories(path))
            {
                paths.Push(subdirs);
            }
        }

        // Check all prefabs
        int currPrefabCount = 1;

        foreach (string prefabPath in allPrefabPaths)
        {
            EditorUtility.DisplayProgressBar("Rebuilding Index", "Scanning project folder...", (float)currPrefabCount / (float)(allPrefabPaths.Count));

            GameObject iterGo = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject;
            if (!iterGo)
            {
                continue;
            }

            tk2dSpriteCollection spriteCollection = iterGo.GetComponent <tk2dSpriteCollection>();
            tk2dFont             font             = iterGo.GetComponent <tk2dFont>();
            tk2dSpriteAnimation  anims            = iterGo.GetComponent <tk2dSpriteAnimation>();

            if (spriteCollection)
            {
                tk2dSpriteCollectionData spriteCollectionData = spriteCollection.spriteCollection;
                if (spriteCollectionData)
                {
                    if (spriteCollectionData.version < 1)
                    {
                        rebuildSpriteCollectionPaths.Add(AssetDatabase.GetAssetPath(spriteCollection));
                    }
                    newIndex.AddSpriteCollectionData(spriteCollectionData);
                }
            }
            else if (font)
            {
                newIndex.AddFont(font);
            }
            else if (anims)
            {
                newIndex.AddSpriteAnimation(anims);
            }
            else
            {
                iterGo = null;
                System.GC.Collect();
            }

            tk2dEditorUtility.UnloadUnusedAssets();
            ++currPrefabCount;
        }
        EditorUtility.ClearProgressBar();

        // Create index
        Object p = EditorUtility.CreateEmptyPrefab(indexPath);

        EditorUtility.ReplacePrefab(go, p, ReplacePrefabOptions.ConnectToPrefab);
        GameObject.DestroyImmediate(go);

        // unload all unused assets
        tk2dEditorUtility.UnloadUnusedAssets();

        // Rebuild invalid sprite collections
        if (rebuildSpriteCollectionPaths.Count > 0)
        {
            EditorUtility.DisplayDialog("Upgrade required",
                                        "Please wait while your sprite collection is upgraded.",
                                        "Ok");

            int count = 1;
            foreach (var scPath in rebuildSpriteCollectionPaths)
            {
                tk2dSpriteCollection sc = AssetDatabase.LoadAssetAtPath(scPath, typeof(tk2dSpriteCollection)) as tk2dSpriteCollection;
                EditorUtility.DisplayProgressBar("Rebuilding Sprite Collections", "Rebuilding Sprite Collection: " + sc.name, (float)count / (float)(rebuildSpriteCollectionPaths.Count));

                tk2dSpriteCollectionBuilder.Rebuild(sc);
                sc = null;

                tk2dEditorUtility.UnloadUnusedAssets();

                ++count;
            }

            EditorUtility.ClearProgressBar();
        }
    }
コード例 #15
0
	void DrawSettingsPanel()
	{
		// Tilemap data
		tk2dTileMapData newData = (tk2dTileMapData)EditorGUILayout.ObjectField("Tile Map Data", tileMap.data, typeof(tk2dTileMapData), false);
		if (newData != tileMap.data)
		{
			tileMap.data = newData;
			LoadTileMapData();
		}
		if (tileMap.data == null)
		{
			if (tk2dGuiUtility.InfoBoxWithButtons(
				"TileMap needs an data object to proceed. " +
				"Please create one or drag an existing data object into the inspector slot.\n",
				tk2dGuiUtility.WarningLevel.Info, 
				"Create") != -1)
			{
				string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Data", "tileMapData", "asset", "");
				if (assetPath.Length > 0)
				{
					tk2dTileMapData tileMapData = ScriptableObject.CreateInstance<tk2dTileMapData>();
					AssetDatabase.CreateAsset(tileMapData, assetPath);
					tileMap.data = tileMapData;
					EditorUtility.SetDirty(tileMap);
					
					Init(tileMapData);
					LoadTileMapData();
				}
			}
		}
		
		// Editor data
		tk2dTileMapEditorData newEditorData = (tk2dTileMapEditorData)EditorGUILayout.ObjectField("Editor Data", editorData, typeof(tk2dTileMapEditorData), false);
		if (newEditorData != editorData)
		{
			string assetPath = AssetDatabase.GetAssetPath(newEditorData);
			if (assetPath.Length > 0)
			{
				tileMap.editorDataGUID = AssetDatabase.AssetPathToGUID(assetPath);
				EditorUtility.SetDirty(tileMap);
				LoadTileMapData();
			}
		}
		if (editorData == null)
		{
			if (tk2dGuiUtility.InfoBoxWithButtons(
				"TileMap needs an editor data object to proceed. " +
				"Please create one or drag an existing data object into the inspector slot.\n",
				tk2dGuiUtility.WarningLevel.Info, 
				"Create") != -1)
			{
				string assetPath = EditorUtility.SaveFilePanelInProject("Save Tile Map Editor Data", "tileMapEditorData", "asset", "");
				if (assetPath.Length > 0)
				{
					tk2dTileMapEditorData tileMapEditorData = ScriptableObject.CreateInstance<tk2dTileMapEditorData>();
					AssetDatabase.CreateAsset(tileMapEditorData, assetPath);
					tileMap.editorDataGUID = AssetDatabase.AssetPathToGUID(assetPath);
					EditorUtility.SetDirty(tileMap);
					LoadTileMapData();
				}
			}
		}
		
		// Sprite collection
		GUILayout.BeginHorizontal();
		Object selectedSpriteCollectionObject = EditorGUILayout.ObjectField("Sprite Collection", tileMap.Editor__SpriteCollection, typeof(Object), false) as Object;
		if (tileMap.Editor__SpriteCollection != null && GUILayout.Button(">", EditorStyles.miniButton, GUILayout.Width(19)))
		{
			tk2dSpriteCollectionEditorPopup v = EditorWindow.GetWindow( typeof(tk2dSpriteCollectionEditorPopup), false, "Sprite Collection Editor" ) as tk2dSpriteCollectionEditorPopup;
			string assetPath = AssetDatabase.GUIDToAssetPath(tileMap.Editor__SpriteCollection.spriteCollectionGUID);
			var spriteCollection = AssetDatabase.LoadAssetAtPath(assetPath, typeof(tk2dSpriteCollection)) as tk2dSpriteCollection;
			v.SetGeneratorAndSelectedSprite(spriteCollection, 0);
		}
		GUILayout.EndHorizontal();
		if (selectedSpriteCollectionObject != tileMap.Editor__SpriteCollection)
		{
			string assetPath = AssetDatabase.GetAssetPath(selectedSpriteCollectionObject);
			string guid = AssetDatabase.AssetPathToGUID(assetPath);
			tk2dIndex index = tk2dEditorUtility.GetOrCreateIndex();
			
			foreach (var scIndex in index.GetSpriteCollectionIndex())
			{
				if (scIndex.spriteCollectionGUID == guid ||
					scIndex.spriteCollectionDataGUID == guid)
				{
					string realDataPath = AssetDatabase.GUIDToAssetPath(scIndex.spriteCollectionDataGUID);
					tk2dSpriteCollectionData data = AssetDatabase.LoadAssetAtPath(realDataPath, typeof(tk2dSpriteCollectionData)) as tk2dSpriteCollectionData;
					
					if (data.allowMultipleAtlases)
					{
						Debug.Log("Atlas spanning not allowed");
					}
					else
					{
						tileMap.Editor__SpriteCollection = data;
						data.InitMaterialIds();
						LoadTileMapData();
						
						EditorUtility.SetDirty(tileMap);
						
						if (Ready)
						{
							Init(tileMap.data);
							tileMap.BeginEditMode();
						}
						break;						
					}
				}
			}
		}
		
		// If not set up, don't bother drawing anything else
		if (!Ready)
			return;
		
		// this is intentionally read only
		EditorGUILayout.ObjectField("Render Data", tileMap.renderData, typeof(GameObject), false);
		GUILayout.BeginHorizontal();
		EditorGUILayout.PrefixLabel(" ");
		if (GUILayout.Button("Make Unique")) {
			tk2dEditor.TileMap.TileMapUtility.MakeUnique(tileMap);
		}
		GUILayout.EndHorizontal();
		
		// tile map size
		
		if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Dimensions, "Dimensions"))
		{
			EditorGUI.indentLevel++;
			
			width = Mathf.Clamp(EditorGUILayout.IntField("Width", width), 1, tk2dEditor.TileMap.TileMapUtility.MaxWidth);
			height = Mathf.Clamp(EditorGUILayout.IntField("Height", height), 1, tk2dEditor.TileMap.TileMapUtility.MaxHeight);
			partitionSizeX = Mathf.Clamp(EditorGUILayout.IntField("PartitionSizeX", partitionSizeX), 4, 32);
			partitionSizeY = Mathf.Clamp(EditorGUILayout.IntField("PartitionSizeY", partitionSizeY), 4, 32);
			
			// Create a default tilemap with given dimensions
			if (!tileMap.AreSpritesInitialized())
			{
				tk2dRuntime.TileMap.BuilderUtil.InitDataStore(tileMap);
				tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, tileMap.partitionSizeX, tileMap.partitionSizeY);	
			}
			
			if (width != tileMap.width || height != tileMap.height || partitionSizeX != tileMap.partitionSizeX || partitionSizeY != tileMap.partitionSizeY)
			{
				if ((width < tileMap.width || height < tileMap.height))
				{
					tk2dGuiUtility.InfoBox("The new size of the tile map is smaller than the current size." +
						"Some clipping will occur.", tk2dGuiUtility.WarningLevel.Warning);
				}
				
				GUILayout.BeginHorizontal();
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("Apply", EditorStyles.miniButton))
				{
					tk2dEditor.TileMap.TileMapUtility.ResizeTileMap(tileMap, width, height, partitionSizeX, partitionSizeY);
				}
				GUILayout.EndHorizontal();
			}

			EditorGUI.indentLevel--;
		}
		
		if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Layers, "Layers"))
		{
			EditorGUI.indentLevel++;
			
			DrawLayersPanel(true);
			
			EditorGUI.indentLevel--;
		}
		
		// tilemap info
		if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Info, "Info"))
		{
			EditorGUI.indentLevel++;
			
			int numActiveChunks = 0;
			if (tileMap.Layers != null)
			{
				foreach (var layer in tileMap.Layers)
					numActiveChunks += layer.NumActiveChunks;
			}
			EditorGUILayout.LabelField("Active chunks", numActiveChunks.ToString());
			int partitionMemSize = partitionSizeX * partitionSizeY * 4;
			EditorGUILayout.LabelField("Memory", ((numActiveChunks * partitionMemSize) / 1024).ToString() + "kB" );
			
			int numActiveColorChunks = 0;
			if (tileMap.ColorChannel != null)
				numActiveColorChunks += tileMap.ColorChannel.NumActiveChunks;
			EditorGUILayout.LabelField("Active color chunks", numActiveColorChunks.ToString());
			int colorMemSize = (partitionSizeX + 1) * (partitionSizeY + 1) * 4;
			EditorGUILayout.LabelField("Memory", ((numActiveColorChunks * colorMemSize) / 1024).ToString() + "kB" );
			
			EditorGUI.indentLevel--;
		}
		
		// tile properties
		if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.TileProperties, "Tile Properties"))
		{
			EditorGUI.indentLevel++;

			// sort method
			tk2dGuiUtility.BeginChangeCheck();
			tileMap.data.tileType = (tk2dTileMapData.TileType)EditorGUILayout.EnumPopup("Tile Type", tileMap.data.tileType);
			tileMap.data.sortMethod = (tk2dTileMapData.SortMethod)EditorGUILayout.EnumPopup("Sort Method", tileMap.data.sortMethod);
			if (tk2dGuiUtility.EndChangeCheck())
			{
				tileMap.BeginEditMode();
			}
			

			// reset sizes			
			GUILayout.BeginHorizontal();
			EditorGUILayout.PrefixLabel("Reset sizes");
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Reset", EditorStyles.miniButtonRight))
			{
				Init(tileMap.data);
				Build(true);
			}
			GUILayout.EndHorizontal();

			// convert these to pixel units
			Vector3 texelSize = SpriteCollection.spriteDefinitions[0].texelSize;
			Vector3 tileOriginPixels = new Vector3(tileMap.data.tileOrigin.x / texelSize.x, tileMap.data.tileOrigin.y / texelSize.y, tileMap.data.tileOrigin.z);
			Vector3 tileSizePixels = new Vector3(tileMap.data.tileSize.x / texelSize.x, tileMap.data.tileSize.y / texelSize.y, tileMap.data.tileSize.z);
			
			Vector3 newTileOriginPixels = EditorGUILayout.Vector3Field("Origin", tileOriginPixels);
			Vector3 newTileSizePixels = EditorGUILayout.Vector3Field("Size", tileSizePixels);
			
			if (newTileOriginPixels != tileOriginPixels ||
				newTileSizePixels != tileSizePixels)
			{
				tileMap.data.tileOrigin = new Vector3(newTileOriginPixels.x * texelSize.x, newTileOriginPixels.y * texelSize.y, newTileOriginPixels.z);
				tileMap.data.tileSize = new Vector3(newTileSizePixels.x * texelSize.x, newTileSizePixels.y * texelSize.y, newTileSizePixels.z);
				Build(true);
			}

			// preview tile origin and size setting
			Vector2 spritePixelOrigin = Vector2.zero;
			Vector2 spritePixelSize = Vector2.one;
			tk2dSpriteDefinition[] spriteDefs = tileMap.SpriteCollectionInst.spriteDefinitions;
			tk2dSpriteDefinition spriteDef = (tilePropertiesPreviewIdx < spriteDefs.Length) ? spriteDefs[tilePropertiesPreviewIdx] : null;
			if (!spriteDef.Valid) spriteDef = null;
			if (spriteDef != null) {
				spritePixelOrigin = new Vector2(spriteDef.untrimmedBoundsData[0].x / spriteDef.texelSize.x, spriteDef.untrimmedBoundsData[0].y / spriteDef.texelSize.y);
				spritePixelSize = new Vector2(spriteDef.untrimmedBoundsData[1].x / spriteDef.texelSize.x, spriteDef.untrimmedBoundsData[1].y / spriteDef.texelSize.y);
			}
			float zoomFactor = (Screen.width - 32.0f) / (spritePixelSize.x * 2.0f);
			EditorGUILayout.BeginScrollView(Vector2.zero, GUILayout.Height(spritePixelSize.y * 2.0f * zoomFactor + 32.0f));
			Rect innerRect = new Rect(0, 0, spritePixelSize.x * 2.0f * zoomFactor, spritePixelSize.y * 2.0f * zoomFactor);
			tk2dGrid.Draw(innerRect);
			if (spriteDef != null) {
				// Preview tiles
				tk2dSpriteThumbnailCache.DrawSpriteTexture(new Rect(spritePixelSize.x * 0.5f * zoomFactor, spritePixelSize.y * 0.5f * zoomFactor, spritePixelSize.x * zoomFactor, spritePixelSize.y * zoomFactor), spriteDef);
				// Preview cursor
				Vector2 cursorOffset = (spritePixelSize * 0.5f - spritePixelOrigin) * zoomFactor;
				Vector2 cursorSize = new Vector2(tileSizePixels.x * zoomFactor, tileSizePixels.y * zoomFactor);
				cursorOffset.x += tileOriginPixels.x * zoomFactor;
				cursorOffset.y += tileOriginPixels.y * zoomFactor;
				cursorOffset.x += spritePixelSize.x * 0.5f * zoomFactor;
				cursorOffset.y += spritePixelSize.y * 0.5f * zoomFactor;
				float top = spritePixelSize.y * 2.0f * zoomFactor;
				Vector3[] cursorVerts = new Vector3[] {
					new Vector3(cursorOffset.x, top - cursorOffset.y, 0),
					new Vector3(cursorOffset.x + cursorSize.x, top - cursorOffset.y, 0),
					new Vector3(cursorOffset.x + cursorSize.x, top - (cursorOffset.y + cursorSize.y), 0),
					new Vector3(cursorOffset.x, top - (cursorOffset.y + cursorSize.y), 0)
				};
				Handles.DrawSolidRectangleWithOutline(cursorVerts, new Color(1.0f, 1.0f, 1.0f, 0.2f), Color.white);
			}
			if (GUILayout.Button(new GUIContent("", "Click - preview using different tile"), "label", GUILayout.Width(innerRect.width), GUILayout.Height(innerRect.height))) {
				int n = spriteDefs.Length;
				for (int i = 0; i < n; ++i) {
					if (++tilePropertiesPreviewIdx >= n)
						tilePropertiesPreviewIdx = 0;
					if (spriteDefs[tilePropertiesPreviewIdx].Valid)
						break;
				}
			}
			EditorGUILayout.EndScrollView();

			EditorGUI.indentLevel--;
		}
		
		if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.PaletteProperties, "Palette Properties"))
		{
			EditorGUI.indentLevel++;
			int newTilesPerRow = Mathf.Clamp(EditorGUILayout.IntField("Tiles Per Row", editorData.paletteTilesPerRow),
											1, SpriteCollection.Count);
			if (newTilesPerRow != editorData.paletteTilesPerRow)
			{
				guiBrushBuilder.Reset();
				
				editorData.paletteTilesPerRow = newTilesPerRow;
				editorData.CreateDefaultPalette(tileMap.SpriteCollectionInst, editorData.paletteBrush, editorData.paletteTilesPerRow);
			}
			
			GUILayout.BeginHorizontal();
			editorData.brushDisplayScale = EditorGUILayout.FloatField("Display Scale", editorData.brushDisplayScale);
			editorData.brushDisplayScale = Mathf.Clamp(editorData.brushDisplayScale, 1.0f / 16.0f, 4.0f);
			if (GUILayout.Button("Reset", EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))
			{
				editorData.brushDisplayScale = 1.0f;
				Repaint();
			}
			GUILayout.EndHorizontal();
			
			EditorGUILayout.PrefixLabel("Preview");
			Rect innerRect = brushRenderer.GetBrushViewRect(editorData.paletteBrush, editorData.paletteTilesPerRow);
			paletteSettingsScrollPos = EditorGUILayout.BeginScrollView(paletteSettingsScrollPos, GUILayout.MinHeight(innerRect.height * editorData.brushDisplayScale + 32.0f));
			innerRect.width *= editorData.brushDisplayScale;
			innerRect.height *= editorData.brushDisplayScale;
			tk2dGrid.Draw(innerRect);
			brushRenderer.DrawBrush(tileMap, editorData.paletteBrush, editorData.brushDisplayScale, true, editorData.paletteTilesPerRow);
			EditorGUILayout.EndScrollView();
			EditorGUI.indentLevel--;
		}

		if (Foldout(ref editorData.setupMode, tk2dTileMapEditorData.SetupMode.Import, "Import"))
		{
			EditorGUI.indentLevel++;
			
			if (GUILayout.Button("Import TMX"))
			{
				if (tk2dEditor.TileMap.Importer.Import(tileMap, tk2dEditor.TileMap.Importer.Format.TMX)) 
				{
					Build(true);	
					width = tileMap.width;
					height = tileMap.height;
					partitionSizeX = tileMap.partitionSizeX;
					partitionSizeY = tileMap.partitionSizeY;
				}
			}
			
			EditorGUI.indentLevel--;
		}
	}