Пример #1
0
        public void DoInspectorGUI()
        {
            serializedObject.Update();
            TileSetBrush tileSetBrush = (TileSetBrush)target;

            if (tileSetBrush.tileSet == null)
            {
                EditorGUILayout.HelpBox("先选择一个tileset", MessageType.Info);
                EditorGUILayout.PropertyField(tileSet);
                serializedObject.ApplyModifiedProperties();
                return;
            }

            EditorGUILayout.PropertyField(tileSet);
            EditorGUILayout.PropertyField(is_show_in_palette);
            group.intValue          = TileSetEditor.DoTileSetBrushGroupFieldLayout(tileSetBrush.tileSet, "Group", group.intValue);
            auto_tile_mode.intValue = Convert.ToInt32(EditorGUILayout.EnumMaskField(new GUIContent("AutoTile Mode"), tileSetBrush.auto_tile_mode));
            string auto_tile_mode_tip =
                "auto_tile_mode:\n" +
                "Self: autotile only with tileSetBrushes of same type\n" +
                "Other: autotile with any other not empty tile\n" +
                "Group: autotile with tileSetBrushes of a group that autotile the brush group";

            EditorGUILayout.HelpBox(auto_tile_mode_tip, MessageType.Info);
            if (GUI.changed)
            {
                serializedObject.ApplyModifiedProperties();
                EditorUtility.SetDirty(target);
            }
        }
Пример #2
0
        public void FlipH(bool changeFlags)
        {
            List <uint> flippedList = new List <uint>(GridWidth * GridHeight);

            for (int gx = min_grid_x; gx <= max_grid_x; ++gx)
            {
                for (int gy = min_grid_y; gy <= max_grid_y; ++gy)
                {
                    int flippedGx = GridWidth - 1 - gx;
                    flippedList.Add(GetTileData(flippedGx, gy));
                }
            }

            int idx = 0;

            for (int gx = min_grid_x; gx <= max_grid_x; ++gx)
            {
                for (int gy = min_grid_y; gy <= max_grid_y; ++gy, ++idx)
                {
                    uint flippedTileData = flippedList[idx];
                    if (
                        changeFlags &&
                        (flippedTileData != TileSetConst.TileData_Empty) &&
                        (flippedTileData & TileSetConst.TileDataMask_TileSetBrushId) == 0 // don't activate flip flags on brushes
                        )
                    {
                        flippedTileData = TileSetBrush.ApplyAndMergeTileFlags(flippedTileData, TileSetConst.TileFlag_FlipH);
                    }
                    SetTileData(gx, gy, flippedTileData);
                }
            }
        }
Пример #3
0
 public bool IsTileSetBrushVisibleByTypeMask(TileSetBrush tileSetBrush)
 {
     if (tileSetBrush)
     {
         string[] tileSetBrushTypes = GetTileSetBrushTypeArray();
         if (tileSetBrushTypes != null && tileSetBrushTypes.Length > 0)
         {
             int idx = Array.IndexOf(tileSetBrushTypes, tileSetBrush.GetType().Name);
             return(((1 << idx) & tileSetBrush_type_mask) != 0);
         }
     }
     return(false);
 }
Пример #4
0
        public TileSetBrush FindTileSetBrush(int brushId)
        {
            if (brushId <= 0)
            {
                return(null);
            }

            TileSetBrush tileSetBrush = null;

            if (!tileSetBrush_cache_dcit.TryGetValue(brushId, out tileSetBrush))
            {
                tileSetBrush = FindBrushContainerByBrushId(brushId).tileSetBrush;
                tileSetBrush_cache_dcit[brushId] = tileSetBrush;
                //Debug.Log(" Cache miss! " + tileBrush.name);
            }
            return(tileSetBrush);
        }
Пример #5
0
        public string[] UpdateTileSetBrushTypeArray()
        {
            List <string> out_list = new List <string>();

            for (int i = 0; i < tileSetBrush_list.Count; ++i)
            {
                TileSetBrush tileSetBrush = tileSetBrush_list[i].tileSetBrush;
                if (tileSetBrush)
                {
                    string type = tileSetBrush.GetType().Name;
                    if (!out_list.Contains(type))
                    {
                        out_list.Add(type);
                    }
                }
            }
            tileSetBrush_type_mask_options = out_list.ToArray();
            return(tileSetBrush_type_mask_options);
        }
        private void DisplayTileSetBrushReorderableList()
        {
            Event e = Event.current;

            if (sharedTileSetData.tileSetBrush_reorderableList == null ||
                sharedTileSetData.tileSetBrush_reorderableList.list != tileSet.tileSetBrush_list)
            {
                if (e.type != EventType.Layout)
                {
                    sharedTileSetData.tileSetBrush_reorderableList = CreateTileSetBrushReorderableList(tileSet);
                    sharedTileSetData.tileSetBrush_reorderableList.onSelectCallback += (ReorderableList reorderableList) =>
                    {
                        var tileSetBrush_list = tileSet.tileSetBrush_list[reorderableList.index];
                        tileSet.selected_tileSetBrushId = tileSetBrush_list.id;
                        RemoveTileSelection();
                        if (mouseDoubleClick.IsDoubleClick)
                        {
                            EditorGUIUtility.PingObject(tileSetBrush_list.tileSetBrush);
                            selected_tileSetBrush_in_inspector = tileSetBrush_list.tileSetBrush;
                        }
                    };
                }
            }
            else
            {
                using (new GUILayoutBeginVerticalScope(GUIStyleConst.Box_Style))
                {
                    sharedTileSetData.tileSetBrush_reorderableList.index =
                        tileSet.tileSetBrush_list.FindIndex(x => x.id == tileSet.selected_tileSetBrushId);
                    sharedTileSetData.tileSetBrush_reorderableList.index = Mathf.Clamp(
                        sharedTileSetData.tileSetBrush_reorderableList.index, -1, tileSet.tileSetBrush_list.Count - 1);
                    sharedTileSetData.tileSetBrush_reorderableList.elementHeight = tileSet.visual_tile_size.y + 10f;
                    sharedTileSetData.tileSetBrush_reorderableList.DoLayoutList();
                    Rect list_rect = GUILayoutUtility.GetLastRect();
                    if (e.isMouse && !list_rect.Contains(e.mousePosition))
                    {
                        sharedTileSetData.tileSetBrush_reorderableList.ReleaseKeyboardFocus();
                    }
                }
            }
        }
Пример #7
0
        public void Rot90(bool changeFlags)
        {
            List <uint> flippedList = new List <uint>(GridWidth * GridHeight);

            for (int gy = min_grid_y; gy <= max_grid_y; ++gy)
            {
                for (int gx = min_grid_x; gx <= max_grid_x; ++gx)
                {
                    flippedList.Add(GetTileData(gx, gy));
                }
            }

            int minGridX = min_grid_x;
            int minGridY = min_grid_y;
            int maxGridX = max_grid_x;
            int maxGridY = max_grid_x;

            ClearMap();

            int idx = 0;

            for (int gx = minGridX; gx <= maxGridX; ++gx)
            {
                for (int gy = maxGridY; gy >= minGridY; --gy, ++idx)
                {
                    uint flippedTileData = flippedList[idx];
                    if (
                        changeFlags &&
                        (flippedTileData != TileSetConst.TileData_Empty) &&
                        (flippedTileData & TileSetConst.TileDataMask_TileSetBrushId) == 0 // don't activate flip flags on brushes
                        )
                    {
                        flippedTileData = TileSetBrush.ApplyAndMergeTileFlags(flippedTileData, TileSetConst.TileFlag_Rot90);
                    }
                    SetTileData(gx, gy, flippedTileData);
                }
            }
        }
Пример #8
0
 public void AddTileSetBrush(TileSetBrush tileSetBrush)
 {
     if (tileSetBrush.tileSet == this)
     {
         if (!tileSetBrush_list.Exists(x => x.tileSetBrush == tileSetBrush))
         {
             int id     = tileSetBrush_list.Count > 0 ? tileSetBrush_list[tileSetBrush_list.Count - 1].id : 1; //NOTE: id 0 is reserved for default brush
             int max_id = (int)TileSetConst.TileDataMask_TileSetBrushId >> 16;
             if (tileSetBrush_list.Count >= max_id)
             {
                 LogCat.error(string.Format(" Max number of brushes reached! {0}", max_id));
             }
             else
             {
                 // find a not used id
                 while (tileSetBrush_list.Exists(x => x.id == id))
                 {
                     ++id;
                     if (id > max_id)
                     {
                         id = 1;
                     }
                 }
                 tileSetBrush_list.Add(new TileSetBrushContainer()
                 {
                     id = id, tileSetBrush = tileSetBrush
                 });
                 tileSetBrush_cache_dcit.Clear();
             }
         }
     }
     else
     {
         Debug.LogWarning(string.Format("This brush {0} has a different tileset and will not be added! ", tileSetBrush.name));
     }
 }
Пример #9
0
        private bool FillMeshData()
        {
            //Debug.Log( "[" + ParentTilemap.name + "] FillData -> " + name);
            if (!tileSet || !tileSet.atlas_texture)
            {
                return(false);
            }
            current_updated_tileMapChunk = this;

            int total_tile_count = width * height;

            if (vertice_list == null)
            {
                vertice_list = new List <Vector3>(total_tile_count * 4);
            }
            else
            {
                vertice_list.Clear();
            }
            if (triangle_list == null)
            {
                triangle_list = new List <int>(total_tile_count * 6);
            }
            else
            {
                triangle_list.Clear();
            }
            if (colors32_list == null)
            {
                colors32_list = new List <Color32>(total_tile_count * 4);
            }
            else
            {
                colors32_list.Clear();
            }
            if (uv_list == null)
            {
                uv_list = new List <Vector2>(total_tile_count * 4);
            }
            else
            {
                uv_list.Clear();
            }

            Vector2[] sub_tile_offset = new Vector2[]
            {
                new Vector2(0f, 0f),
                new Vector2(cell_size.x / 2f, 0f),
                new Vector2(0f, cell_size.y / 2f),
                new Vector2(cell_size.x / 2f, cell_size.y / 2f),
            };
            Vector2 sub_tile_size = cell_size / 2f;

            animated_tile_list.Clear();
            bool is_empty = true;

            for (int tile_y = 0, tile_index = 0; tile_y < height; ++tile_y)
            {
                for (int tile_x = 0; tile_x < width; ++tile_x, ++tile_index)
                {
                    uint tileData = tileData_list[tile_index];
                    if (tileData != TileSetConst.TileData_Empty)
                    {
                        int          brushId   = (int)((tileData & TileSetConst.TileDataMask_TileSetBrushId) >> 16);
                        int          tileId    = (int)(tileData & TileSetConst.TileDataMask_TileId);
                        Tile         tile      = tileSet.GetTile(tileId);
                        TileSetBrush tileBrush = null;
                        if (brushId > 0)
                        {
                            tileBrush = tileSet.FindTileSetBrush(brushId);
                            if (tileBrush == null)
                            {
                                Debug.LogWarning(parent_tileMap.name + "\\" + name + ": BrushId " + brushId + " not found! GridPos(" + tile_x + "," + tile_y + ") tilaData 0x" + tileData.ToString("X"));
                                tileData_list[tile_index] = tileData & ~TileSetConst.TileDataMask_TileSetBrushId;//找不到对应的brush则设置该tileData的brushid为空
                            }
                            if (tileBrush != null && (is_invalidate_tileSetBrushes || (tileData & TileSetConst.TileFlag_Updated) == 0))
                            {
                                tileData = tileBrush.Refresh(parent_tileMap, offset_grid_x + tile_x, offset_grid_y + tile_y, tileData);
                                //+++NOTE: this code add support for animated brushes inside a random brush
                                // Collateral effects of supporting changing the brush id in Refresh:
                                // - When the random brush select a tile data with another brush id, this tile won't be a random tile any more
                                // - If the tilemap is refreshed several times, and at least a tile data contains another brush id, then all tiles will loose the brush id of the random brush
                                if (TileSetBrushBehaviour.instance.tileMap == parent_tileMap) // avoid changing brushId when updating the BrushTilemap
                                {
                                    tileData &= ~TileSetConst.TileDataMask_TileSetBrushId;
                                    tileData |= (uint)(brushId << 16);
                                }
                                int new_brushId = (int)((tileData & TileSetConst.TileDataMask_TileSetBrushId) >> 16);
                                if (brushId != new_brushId)
                                {
                                    brushId   = new_brushId;
                                    tileBrush = tileSet.FindTileSetBrush(brushId);
                                }
                                //---
                                tileData |= TileSetConst.TileFlag_Updated; // set updated flag
                                tileData_list[tile_index] = tileData;      // update tileData
                                tileId = (int)(tileData & TileSetConst.TileDataMask_TileId);
                                tile   = tileSet.GetTile(tileId);
                                // update created objects
                                if (tile != null && tile.tilePrefabData.prefab != null)
                                {
                                    CreateTileObject(tile_index, tile.tilePrefabData);
                                }
                                else
                                {
                                    DestroyTileObject(tile_index);
                                }
                            }
                        }

                        is_empty = false;

                        if (tileBrush != null && tileBrush.IsAnimated())
                        {
                            animated_tile_list.Add(new AnimTileData()
                            {
                                vertex_index = vertice_list.Count, tileSetBrush = tileBrush, sub_tile_index = -1
                            });
                        }

                        current_uv_vertex = vertice_list.Count;
                        Rect   tile_uv;
                        uint[] subtileData = tileBrush != null?tileBrush.GetSubTiles(parent_tileMap, offset_grid_x + tile_x, offset_grid_y + tile_y, tileData) : null;

                        if (subtileData == null)
                        {
                            if (tile != null)
                            {
                                if (tile.tilePrefabData.prefab == null || tile.tilePrefabData.is_show_tile_with_prefab || //hide the tiles with prefabs ( unless showTileWithPrefab is true )
                                    tileBrush && tileBrush.IsAnimated()) // ( skip if it's an animated brush )
                                {
                                    tile_uv = tile.uv;
                                    _AddTileToMesh(tile_uv, tile_x, tile_y, tileData, Vector2.zero, cell_size);
                                    if (tile_color_list != null && tile_color_list.Count > tile_index)
                                    {
                                        TileColor32 tileColor32 = tile_color_list[tile_index];
                                        colors32_list.Add(tileColor32.color0);
                                        colors32_list.Add(tileColor32.color1);
                                        colors32_list.Add(tileColor32.color2);
                                        colors32_list.Add(tileColor32.color3);
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (int i = 0; i < subtileData.Length; ++i)
                            {
                                uint subTileData = subtileData[i];
                                int  subTileId   = (int)(subTileData & TileSetConst.TileDataMask_TileId);
                                Tile subTile     = tileSet.GetTile(subTileId);
                                tile_uv = subTile != null ? subTile.uv : default(Rect);
                                //if (tileUV != default(Rect)) //NOTE: if this is uncommented, there won't be coherence with geometry ( 16 vertices per tiles with subtiles ). But it means also, the tile shouldn't be null.
                                {
                                    _AddTileToMesh(tile_uv, tile_x, tile_y, subTileData, sub_tile_offset[i], sub_tile_size, i);
                                    if (tile_color_list != null && tile_color_list.Count > tile_index)
                                    {
                                        TileColor32 tileColor32 = tile_color_list[tile_index];
                                        Color32     middleColor = new Color32(
                                            System.Convert.ToByte((tileColor32.color0.r + tileColor32.color1.r + tileColor32.color2.r + tileColor32.color3.r) >> 2),
                                            System.Convert.ToByte((tileColor32.color0.g + tileColor32.color1.g + tileColor32.color2.g + tileColor32.color3.g) >> 2),
                                            System.Convert.ToByte((tileColor32.color0.b + tileColor32.color1.b + tileColor32.color2.b + tileColor32.color3.b) >> 2),
                                            System.Convert.ToByte((tileColor32.color0.a + tileColor32.color1.a + tileColor32.color2.a + tileColor32.color3.a) >> 2)
                                            );
                                        switch (i)
                                        {
                                        case 0:
                                            colors32_list.Add(tileColor32.color0);
                                            colors32_list.Add(Color32.Lerp(tileColor32.color1, tileColor32.color0, .5f));
                                            colors32_list.Add(Color32.Lerp(tileColor32.color2, tileColor32.color0, .5f));
                                            colors32_list.Add(middleColor);
                                            break;

                                        case 1:
                                            colors32_list.Add(Color32.Lerp(tileColor32.color0, tileColor32.color1, .5f));
                                            colors32_list.Add(tileColor32.color1);
                                            colors32_list.Add(middleColor);
                                            colors32_list.Add(Color32.Lerp(tileColor32.color3, tileColor32.color1, .5f));
                                            break;

                                        case 2:
                                            colors32_list.Add(Color32.Lerp(tileColor32.color0, tileColor32.color2, .5f));
                                            colors32_list.Add(middleColor);
                                            colors32_list.Add(tileColor32.color2);
                                            colors32_list.Add(Color32.Lerp(tileColor32.color3, tileColor32.color2, .5f));
                                            break;

                                        case 3:
                                            colors32_list.Add(middleColor);
                                            colors32_list.Add(Color32.Lerp(tileColor32.color1, tileColor32.color3, .5f));
                                            colors32_list.Add(Color32.Lerp(tileColor32.color2, tileColor32.color3, .5f));
                                            colors32_list.Add(tileColor32.color3);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //NOTE: the destruction of tileobjects needs to be done here to avoid a Undo/Redo bug. Check inside DestroyTileObject for more information.
            for (int i = 0; i < tile_gameObject_to_be_removed_list.Count; ++i)
            {
                DestroyTileObject(tile_gameObject_to_be_removed_list[i]);
            }
            tile_gameObject_to_be_removed_list.Clear();
            current_updated_tileMapChunk = null;
            return(!is_empty);
        }
Пример #10
0
        public void SetTileData(int local_grid_x, int local_grid_y, uint tileData)
        {
            if (local_grid_x >= 0 && local_grid_x < width && local_grid_y >= 0 && local_grid_y < height)
            {
                int tile_index = local_grid_y * width + local_grid_x;

                int  tileId = (int)(tileData & TileSetConst.TileDataMask_TileId);
                Tile tile   = tileSet.GetTile(tileId);

                int  prev_tileId = (int)(tileData_list[tile_index] & TileSetConst.TileDataMask_TileId);
                Tile prev_tile   = tileSet.GetTile(prev_tileId);

                int brushId      = TileSetUtil.GetTileSetBrushIdFromTileData(tileData);
                int prev_brushId = TileSetUtil.GetTileSetBrushIdFromTileData(tileData_list[tile_index]);

                if (brushId != prev_brushId)
                {
                    if (!current_updated_tileMapChunk) // avoid this is chunks is being Updated from FillMeshData
                    {
                        // Refresh Neighbors ( and itself if needed )
                        for (int y_offset = -1; y_offset <= 1; ++y_offset)
                        {
                            for (int x_offset = -1; x_offset <= 1; ++x_offset)
                            {
                                if ((x_offset | y_offset) == 0)
                                {
                                    if (brushId > 0)
                                    {
                                        // Refresh itself
                                        tileData = (tileData & ~TileSetConst.TileFlag_Updated);
                                    }
                                }
                                else
                                {
                                    int          grid_x                = (local_grid_x + x_offset);
                                    int          grid_y                = (local_grid_y + y_offset);
                                    int          index                 = grid_y * width + grid_x;
                                    bool         is_inside_chunk       = (grid_x >= 0 && grid_x < width && grid_y >= 0 && grid_y < height);
                                    uint         neighbor_tileData     = is_inside_chunk ? tileData_list[index] : parent_tileMap.GetTileData(offset_grid_x + local_grid_x + x_offset, offset_grid_y + local_grid_y + y_offset);
                                    int          neighbor_brushId      = (int)((neighbor_tileData & TileSetConst.TileDataMask_TileSetBrushId) >> 16);
                                    TileSetBrush neighbor_tileSetBrush = parent_tileMap.tileSet.FindTileSetBrush(neighbor_brushId);
                                    //if (brush != null && brush.AutotileWith(brushId, neighborBrushId) || prevBrush != null && prevBrush.AutotileWith(prevBrushId, neighborBrushId))
                                    if (neighbor_tileSetBrush != null &&
                                        (neighbor_tileSetBrush.AutoTileWith(neighbor_brushId, brushId) || neighbor_tileSetBrush.AutoTileWith(neighbor_brushId, prev_brushId)))
                                    {
                                        neighbor_tileData = (neighbor_tileData & ~TileSetConst.TileFlag_Updated); // force a refresh
                                        if (is_inside_chunk)
                                        {
                                            tileData_list[index] = neighbor_tileData;
                                        }
                                        else
                                        {
                                            parent_tileMap.SetTileData(offset_grid_x + grid_x, offset_grid_y + grid_y, neighbor_tileData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else if (brushId > 0)
                {
                    // Refresh itself
                    tileData = (tileData & ~TileSetConst.TileFlag_Updated);
                }

                is_need_rebuild_mesh      |= (tileData_list[tile_index] != tileData) || (tileData & TileSetConst.TileDataMask_TileId) == TileSetConst.TileId_Empty;
                is_need_rebuild_colliders |= is_need_rebuild_mesh &&
                                             (
                    (prev_brushId > 0) || (brushId > 0) || // there is a brush (a brush could change the collider data later)
                    (tile != null && tile.tileColliderData.type != TileColliderType.None) || (prev_tile != null && prev_tile.tileColliderData.type != TileColliderType.None) // prev. or new tile has colliders
                                             );

                if (parent_tileMap.tileMapColliderType != TileMapColliderType.None && is_need_rebuild_colliders)
                {
                    // Refresh Neighbors tilechunk colliders, to make the collider autotiling
                    // Only if neighbor is outside this tilechunk
                    for (int y_offset = -1; y_offset <= 1; ++y_offset)
                    {
                        for (int x_offset = -1; x_offset <= 1; ++x_offset)
                        {
                            if ((x_offset | y_offset) != 0) // skip this tile position xf = yf = 0
                            {
                                int  grid_x          = (local_grid_x + x_offset);
                                int  grid_y          = (local_grid_y + y_offset);
                                bool is_inside_chunk = (grid_x >= 0 && grid_x < width && grid_y >= 0 && grid_y < height);
                                if (!is_inside_chunk)
                                {
                                    parent_tileMap.InvalidateChunkAt(offset_grid_x + grid_x, offset_grid_y + grid_y, false, true);
                                }
                            }
                        }
                    }
                }

                // Update tile data
                tileData_list[tile_index] = tileData;

                if (!TileMap.Is_Disable_Tile_Prefab_Creation)
                {
                    // Create tile Objects
                    if (tile != null && tile.tilePrefabData.prefab != null)
                    {
                        CreateTileObject(tile_index, tile.tilePrefabData);
                    }
                    else
                    {
                        DestroyTileObject(tile_index);
                    }
                }

                TileSetBrush brush = parent_tileMap.tileSet.FindTileSetBrush(brushId);
                if (brushId != prev_brushId)
                {
                    TileSetBrush prevBrush = parent_tileMap.tileSet.FindTileSetBrush(prev_brushId);
                    if (prevBrush != null)
                    {
                        prevBrush.OnErase(this, local_grid_x, local_grid_y, tileData, prev_brushId);
                    }
                }
                if (brush != null)
                {
                    tileData = brush.OnPaint(this, local_grid_x, local_grid_y, tileData);
                }
            }
        }
        public void DisplayTileSetBrush()
        {
            var  e = Event.current;
            bool is_mouse_inside_tileSetBrush_palette_scroll_area =
                e.isMouse && tileSetBrush_palette_scroll_area_rect.Contains(e.mousePosition);

            using (new EditorGUILayoutBeginHorizontalScope())
            {
                string tileSetBrushId_label = tileSet.selected_tileSetBrushId > 0
        ? string.Format("(id:{0})", tileSet.selected_tileSetBrushId)
        : "";
                EditorGUILayout.LabelField("TileSetBrush Palette" + tileSetBrushId_label, EditorStyles.boldLabel);
                is_display_tileSetBrush_reordableList =
                    GUILayoutUtil.ToggleButton("Display List", is_display_tileSetBrush_reordableList);
            }

//    tileSet.tileSetBrush_type_mask = EditorGUILayout.MaskField("TileSetBrush Mask", tileSet.tileSetBrush_type_mask,
//      tileSet.GetTileSetBrushTypeArray());

            int column_count = (int)(tile_scroll_size_rect.width / (tileSet.visual_tile_size.x + visual_tile_padding));

            if (column_count <= 0)
            {
                column_count = 1;
            }
            float tileSetBrushes_scroll_max_height = Screen.height / 4;
            //commented because m_rTileScrollSize.width.height was changed to Screen.height;  fBrushesScrollMaxHeight -= fBrushesScrollMaxHeight % 2; // sometimes because size of tile scroll affects size of brush scroll, the height is dancing between +-1, so this is always taking the pair value
            float tileSetBrush_palette_scroll_area_height = Mathf.Min(tileSetBrushes_scroll_max_height,
                                                                      4 + (tileSet.visual_tile_size.y + visual_tile_padding) * (1 + (tileSet.tileSetBrush_list.Count / column_count)));

            using (new EditorGUILayoutBeginVerticalScope(GUILayout.MinHeight(tileSetBrush_palette_scroll_area_height)))
            {
                if (is_display_tileSetBrush_reordableList)
                {
                    DisplayTileSetBrushReorderableList();
                }
                else
                {
                    bool    is_refresh_tileSetBrushList = false;
                    Vector2 tileSetBrushes_scroll_pos   = sharedTileSetData.tileSetBrushes_scroll_pos;
                    using (new EditorGUILayoutBeginScrollViewScope(ref tileSetBrushes_scroll_pos, GUIStyleConst.Scroll_Style))
                    {
                        if (is_update_scroll_pos)
                        {
                            sharedTileSetData.tileSetBrushes_scroll_pos = tileSetBrushes_scroll_pos;
                        }

                        Rect scroll_view_rect = new Rect(0, 0, tile_scroll_size_rect.width, 0);
                        column_count =
                            Mathf.Clamp((int)scroll_view_rect.width / (int)(tileSet.visual_tile_size.x + visual_tile_padding), 1,
                                        column_count);
                        if (tileSet.tileSetBrush_list != null)
                        {
                            GUILayout.Space((tileSet.visual_tile_size.y + visual_tile_padding) *
                                            (1 + (tileSet.tileSetBrush_list.Count - 1) / column_count));
                            for (int i = 0, index = 0; i < tileSet.tileSetBrush_list.Count; ++i, ++index)
                            {
                                var tileSetBrushContainer = tileSet.tileSetBrush_list[i];
                                if (tileSetBrushContainer.tileSetBrush == null || tileSetBrushContainer.tileSetBrush.tileSet != tileSet)
                                {
                                    is_refresh_tileSetBrushList = true;
                                    continue;
                                }

                                if (!tileSetBrushContainer.tileSetBrush.is_show_in_palette ||
                                    !tileSet.IsTileSetBrushVisibleByTypeMask(tileSetBrushContainer.tileSetBrush))
                                {
                                    --index;
                                    continue;
                                }

                                int  tile_x           = index % column_count;
                                int  tile_y           = index / column_count;
                                Rect visual_tile_rect = new Rect(2 + tile_x * (tileSet.visual_tile_size.x + visual_tile_padding),
                                                                 2 + tile_y * (tileSet.visual_tile_size.y + visual_tile_padding), tileSet.visual_tile_size.x,
                                                                 tileSet.visual_tile_size.y);
                                //Fix Missing Tileset reference
                                if (tileSetBrushContainer.tileSetBrush.tileSet == null)
                                {
                                    LogCat.warn(string.Format("Fixed missing tileset reference in brush {0}  Id({1})",
                                                              tileSetBrushContainer.tileSetBrush.name, tileSetBrushContainer.id));
                                    tileSetBrushContainer.tileSetBrush.tileSet = tileSet;
                                }

                                uint tileData = TileSetConst.TileData_Empty;
                                if (tileSetBrushContainer.tileSetBrush.IsAnimated())
                                {
                                    tileData = tileSetBrushContainer.tileSetBrush.GetAnimTileData();
                                }
                                else
                                {
                                    tileData = tileSetBrushContainer.tileSetBrush.PreviewTileData();
                                }
                                TileSetEditor.DoGUIDrawTileFromTileData(visual_tile_rect, tileData, tileSet,
                                                                        tileSetBrushContainer.tileSetBrush.GetAnimUV());
                                if ((is_left_mouse_released || is_right_mouse_released || mouseDoubleClick.IsDoubleClick) && //左键放开,右键放开,双击鼠标
                                    is_mouse_inside_tileSetBrush_palette_scroll_area && visual_tile_rect.Contains(Event.current.mousePosition))//点钟该区域
                                {
                                    tileSet.selected_tileSetBrushId = tileSetBrushContainer.id;
                                    RemoveTileSelection();
                                    if (mouseDoubleClick.IsDoubleClick)
                                    {
                                        EditorGUIUtility.PingObject(tileSetBrushContainer.tileSetBrush);
                                        selected_tileSetBrush_in_inspector = tileSetBrushContainer.tileSetBrush;
                                    }

                                    if (is_right_mouse_released)
                                    {
                                        TilePropertiesEditor.Show(tileSet);
                                    }
                                }
                                else if (tileSet.selected_tileSetBrushId == tileSetBrushContainer.id)
                                {
                                    Rect selection_rect = new Rect(2 + tile_x * (tileSet.visual_tile_size.x + visual_tile_padding),
                                                                   2 + tile_y * (tileSet.visual_tile_size.y + visual_tile_padding),
                                                                   (tileSet.visual_tile_size.x + visual_tile_padding),
                                                                   (tileSet.visual_tile_size.y + visual_tile_padding));
                                    DrawUtil.HandlesDrawSolidRectangleWithOutline(selection_rect, new Color(0f, 0f, 0f, 0.1f),
                                                                                  new Color(1f, 1f, 0f, 1f));
                                }
                            }


                            if (is_refresh_tileSetBrushList)
                            {
                                tileSet.RemoveInvalidTileSetBrushList();
                                tileSet.UpdateTileSetBrushTypeArray();
                            }
                        }
                    }

                    if (e.type == EventType.Repaint)
                    {
                        tileSetBrush_palette_scroll_area_rect = GUILayoutUtility.GetLastRect();
                    }
                }
            }

            if (GUILayout.Button("Import all tileSetBrush_list found in the project"))
            {
                AddAllTileSetBrushesFoundInTheProject(tileSet);
                EditorUtility.SetDirty(tileSet);
            }
        }