Example #1
0
        private void DisplayCollider()
        {
            Event e = Event.current;

            if (tileSet.selected_tileSetBrushId != TileSetConst.TileSetBrushId_Default)
            {
                EditorGUILayout.LabelField("tileSetBrush不能被编辑", EditorStyles.boldLabel);
                return;
            }

            bool is_multi_selection = tileSet.tileSelection != null;
            bool is_save_changes    = false;
            Tile selected_tile      = is_multi_selection
      ? tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[0])]
      : tileSet.selected_tile;

            if (e.type == EventType.MouseDown)
            {
                is_dragging = true;
                if (selected_tile.tileColliderData.vertices != null)
                {
                    saved_vertexs = new Vector2[selected_tile.tileColliderData.vertices.Length];
                    selected_tile.tileColliderData.vertices.CopyTo(saved_vertexs, 0);
                }
            }
            else if (e.type == EventType.MouseUp)
            {
                is_dragging = false;
            }

            //background_color
            tileSet.background_color = EditorGUILayout.ColorField(tileSet.background_color);
            if (pre_background_color != tileSet.background_color || GUIStyleConst.Scroll_Style.normal.background == null)
            {
                pre_background_color = tileSet.background_color;
                if (GUIStyleConst.Scroll_Style.normal.background == null)
                {
                    GUIStyleConst.Scroll_Style.normal.background = new Texture2D(1, 1)
                    {
                        hideFlags = HideFlags.DontSave
                    }
                }
                ;
                GUIStyleConst.Scroll_Style.normal.background.SetPixel(0, 0, tileSet.background_color);
                GUIStyleConst.Scroll_Style.normal.background.Apply();
            }

            float aspect_ratio = tileSet.tile_pixel_size.x / tileSet.tile_pixel_size.y; //比例
            float padding      = 2;                                                     // pixel size of the border around the tile

            //画tile图
            //包围tile_rect的rect
            Rect tile_parent_rect = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));

            using (new GUIBeginGroupScope(tile_parent_rect, GUIStyleConst.Scroll_Style))
            {
                if (e.type == EventType.Repaint)
                {
                    float tile_pixel_size = tile_parent_rect.width / (tileSet.tile_pixel_size.x + 2 * padding);//2*padding是因为padding有左边和右边
                    mouse_pos = e.mousePosition;
                    tile_rect = new Rect(padding * tile_pixel_size, padding * tile_pixel_size,
                                         tile_parent_rect.width - 2 * padding * tile_pixel_size,
                                         (tile_parent_rect.width / aspect_ratio) - 2 * padding * tile_pixel_size);
                    tile_rect.height = Mathf.Min(tile_rect.height, tile_parent_rect.height - 2 * padding * tile_pixel_size);
                    tile_rect.width  = (tile_rect.height * aspect_ratio);
                }
                using (new GUIColorScope(new Color(1f, 1f, 1f, 0.1f)))
                {
                    GUI.DrawTexture(tile_rect, EditorGUIUtility.whiteTexture);
                }
                if (is_multi_selection)
                {
                    foreach (uint tileData in tileSet.tileSelection.selection_tileData_list)
                    {
                        int  tileId = TileSetUtil.GetTileIdFromTileData(tileData);
                        Tile tile   = tileSet.GetTile(tileId);
                        if (tile != null)
                        {
                            GUI.color = new Color(1f, 1f, 1f, 1f / tileSet.tileSelection.selection_tileData_list.Count);
                            GUI.DrawTextureWithTexCoords(tile_rect, tileSet.atlas_texture, tile.uv);
                        }
                    }
                    GUI.color = Color.white;
                }
                else
                {
                    GUI.DrawTextureWithTexCoords(tile_rect, tileSet.atlas_texture, selected_tile.uv);
                }

                /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                Color saved_handle_color = Handles.color;
                if (selected_tile.tileColliderData.type != TileColliderType.None)
                {
                    Vector2[] collider_vertices = selected_tile.tileColliderData.type == TileColliderType.Full ? TileConst.Full_Collider_Tile_Vertices : selected_tile.tileColliderData.vertices;
                    if (collider_vertices == null || collider_vertices.Length == 0)
                    {
                        collider_vertices = selected_tile.tileColliderData.vertices = new Vector2[TileConst.Full_Collider_Tile_Vertices.Length];
                        Array.Copy(TileConst.Full_Collider_Tile_Vertices, collider_vertices, TileConst.Full_Collider_Tile_Vertices.Length);
                        EditorUtility.SetDirty(tileSet);
                    }

                    // 将vertice的xy限制在[0,1]之间
                    for (int i = 0; i < collider_vertices.Length; ++i)
                    {
                        Vector2 collider_vertice = collider_vertices[i];
                        collider_vertice     = collider_vertice.Snap2(tileSet.tile_pixel_size).ConvertElement(v => Mathf.Clamp01(v));
                        collider_vertices[i] = collider_vertice;
                    }

                    // 画边 draw edges
                    Vector3[] poly_edges = new Vector3[collider_vertices.Length + 1];
                    for (int i = 0; i < collider_vertices.Length; ++i)
                    {
                        Vector2 collider_vertice = collider_vertices[i];
                        collider_vertice.x = tile_rect.x + tile_rect.width * collider_vertice.x;
                        collider_vertice.y = tile_rect.yMax - tile_rect.height * collider_vertice.y;

                        Vector2 collider_vertice_next = collider_vertices[(i + 1) % collider_vertices.Length];
                        collider_vertice_next.x = tile_rect.x + tile_rect.width * collider_vertice_next.x;
                        collider_vertice_next.y = tile_rect.yMax - tile_rect.height * collider_vertice_next.y;

                        poly_edges[i]     = collider_vertice;
                        poly_edges[i + 1] = collider_vertice_next;

                        //画边
                        Handles.color = Color.green;
                        Handles.DrawLine(collider_vertice, collider_vertice_next);
                        //画边上的法线 Draw normals
                        Handles.color = Color.white;
                        Vector3 normal_pos = (collider_vertice + collider_vertice_next) / 2f;
                        Handles.DrawLine(normal_pos, normal_pos + Vector3.Cross(collider_vertice_next - collider_vertice, Vector3.forward).normalized *tile_rect.yMin);

                        Handles.color = saved_handle_color;
                    }

                    float pixel_size = tile_rect.width / tileSet.tile_pixel_size.x;
                    if (selected_tile.tileColliderData.type == TileColliderType.Polygon)
                    {
                        bool is_adding_vertex_on   = !is_dragging && e.shift && active_vertex_index == -1;
                        bool is_removing_vertex_on = !is_dragging && ((Application.platform == RuntimePlatform.OSXEditor) ? e.command : e.control) && collider_vertices.Length > 3;
                        //删除顶点
                        if (is_removing_vertex_on && active_vertex_index != -1 && e.type == EventType.MouseUp)
                        {
                            selected_tile.tileColliderData.vertices = new Vector2[collider_vertices.Length - 1];
                            for (int i = 0, j = 0; i < collider_vertices.Length; ++i)
                            {
                                if (i == active_vertex_index)
                                {
                                    continue;
                                }
                                selected_tile.tileColliderData.vertices[j] = collider_vertices[i];
                                ++j;
                            }
                            collider_vertices   = selected_tile.tileColliderData.vertices;
                            active_vertex_index = -1;
                        }

                        float min_distance = float.MaxValue;
                        if (!is_dragging)
                        {
                            active_vertex_index = -1;
                        }
                        for (int i = 0; i < collider_vertices.Length; ++i)
                        {
                            Vector2 collider_vertice = collider_vertices[i];
                            collider_vertice.x = tile_rect.x + tile_rect.width * collider_vertice.x;
                            collider_vertice.y = tile_rect.yMax - tile_rect.height * collider_vertice.y;

                            if (is_dragging)
                            {
                                if (i == active_vertex_index)
                                {
                                    collider_vertice       = mouse_pos;
                                    collider_vertice      -= tile_rect.position;
                                    collider_vertice.x     = Mathf.Clamp(Mathf.Round(collider_vertice.x / pixel_size) * pixel_size, 0, tile_rect.width);
                                    collider_vertice.y     = Mathf.Clamp(Mathf.Round(collider_vertice.y / pixel_size) * pixel_size, 0, tile_rect.height);
                                    collider_vertice      += tile_rect.position;
                                    collider_vertices[i].x = Mathf.Clamp01((collider_vertice.x - tile_rect.x) / tile_rect.width);
                                    collider_vertices[i].y = Mathf.Clamp01((collider_vertice.y - tile_rect.yMax) / -tile_rect.height);
                                }
                            }
                            else
                            {
                                float distance = Vector2.Distance(mouse_pos, collider_vertice);
                                //distance < GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width是为了限定少于多少距离(该顶点与mouse_pos的距离)的时候才选中该顶点
                                if (distance <= min_distance && distance < GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width)
                                {
                                    min_distance        = distance;
                                    active_vertex_index = i;
                                }
                            }
                            //画顶点
                            if (e.type == EventType.Repaint)
                            {
                                //画左上角的坐标
                                if (i == active_vertex_index)
                                {
                                    GUIStyleConst.VertexCoord_Style.fontSize = (int)(Mathf.Min(12f, tile_rect.yMin / 2f));
                                    GUI.Label(new Rect(0, 0, tile_rect.width, tile_rect.yMin), Vector2.Scale(collider_vertices[i], tileSet.tile_pixel_size).ToString(), GUIStyleConst.VertexCoord_Style);
                                }
                                GUI.color = active_vertex_index == i ? (is_removing_vertex_on ? Color.red : Color.cyan) : new Color(0.7f, 0.7f, 0.7f, 0.8f);
                                GUIStyleConst.Collider_Vertex_Handle_Style.Draw(new Rect(collider_vertice.x - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width / 2, collider_vertice.y - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.height / 2, 1, 1), i.ToString(), false, false, false, false);
                                GUI.color = Color.white;
                            }
                        }

                        //添加顶点
                        if (is_adding_vertex_on)
                        {
                            //线段index
                            int     segment_index;
                            Vector2 new_vertex_pos = ClosestPointToPolyLine(poly_edges, out segment_index);

                            if (e.type == EventType.MouseUp)
                            {
                                selected_tile.tileColliderData.vertices = new Vector2[collider_vertices.Length + 1];
                                segment_index = (segment_index + 1) % selected_tile.tileColliderData.vertices.Length;
                                for (int i = 0, j = 0; i < selected_tile.tileColliderData.vertices.Length; ++i)
                                {
                                    if (segment_index == i)
                                    {
                                        new_vertex_pos.x = Mathf.Clamp(Mathf.Round(new_vertex_pos.x / pixel_size) * pixel_size, tile_rect.x, tile_rect.xMax);
                                        new_vertex_pos.y = Mathf.Clamp(Mathf.Round(new_vertex_pos.y / pixel_size) * pixel_size, tile_rect.y, tile_rect.yMax);
                                        selected_tile.tileColliderData.vertices[i].x = Mathf.Clamp01((new_vertex_pos.x - tile_rect.x) / tile_rect.width);
                                        selected_tile.tileColliderData.vertices[i].y = Mathf.Clamp01((new_vertex_pos.y - tile_rect.yMax) / -tile_rect.height);
                                    }
                                    else
                                    {
                                        selected_tile.tileColliderData.vertices[i] = collider_vertices[j];
                                        ++j;
                                    }
                                }
                                collider_vertices   = selected_tile.tileColliderData.vertices;
                                active_vertex_index = -1;
                            }
                            else if (e.type == EventType.Repaint)
                            {
                                //添加顶点中移动鼠标,透明动态显示当前将要新增顶点的位置
                                GUI.color = new Color(0.7f, 0.7f, 0.7f, 0.8f);
                                GUIStyleConst.Collider_Vertex_Handle_Style.Draw(new Rect(new_vertex_pos.x - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width / 2, new_vertex_pos.y - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.height / 2, 1, 1), segment_index.ToString(), false, false, false, false);
                                GUI.color = Color.white;
                            }
                        }
                    }

                    if (e.type == EventType.MouseUp)
                    {
                        is_save_changes = true;
                        //remove duplicated vertex
                        selected_tile.tileColliderData.vertices = selected_tile.tileColliderData.vertices.Distinct().ToArray();
                        if (selected_tile.tileColliderData.vertices.Length <= 2)
                        {
                            selected_tile.tileColliderData.vertices = saved_vertexs;
                        }
                        //snap vertex positions
                        selected_tile.tileColliderData.SnapVertices(tileSet);
                    }
                }
            }



            if (GUILayout.Button("反转法线"))
            {
                selected_tile.tileColliderData.vertices.Reverse();
            }

            EditorGUILayout.Space();

            string helpInfo =
                "  - 移动:点击图中的顶点并移动它的位置" + "\n" +
                "  - 添加:按住Shift并点击鼠标进行添加顶点" + "\n" +
                "  - 删除:按住Ctrl并且点击顶点进行删除顶点 (should be more than 3)";

            EditorGUILayout.HelpBox(helpInfo, MessageType.Info);

            // Collider Settings
            float saved_label_width = EditorGUIUtility.labelWidth;

            EditorGUIUtility.labelWidth = 40;
            if (is_multi_selection)
            {
                EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel);
            }
            using (new EditorGUILayoutBeginHorizontalScope(GUILayout.MinWidth(140)))
            {
                EditorGUILayout.LabelField("Collider Data", EditorStyles.boldLabel);
                if (GUILayout.Button("Copy", GUILayout.Width(50)))
                {
                    copied_colliderData = selected_tile.tileColliderData.Clone();
                }
                if (GUILayout.Button("Paste", GUILayout.Width(50)))
                {
                    selected_tile.tileColliderData = copied_colliderData.Clone();
                    is_save_changes = true;
                }
            }
            EditorGUILayout.Space();

            using (var check = new EditorGUIBeginChangeCheckScope())
            {
                EditorGUIUtility.labelWidth = 100;
                EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel);
                using (new EditorGUIIndentLevelScope(2))
                {
                    string[] tile_collider_names = Enum.GetNames(typeof(TileColliderType));
                    selected_tile.tileColliderData.type = (TileColliderType)GUILayout.Toolbar((int)selected_tile.tileColliderData.type, tile_collider_names);
                }
                EditorGUIUtility.labelWidth = saved_label_width;
                is_save_changes            |= check.IsChanged;
            }

            //Save changes
            if (is_save_changes)
            {
                if (is_multi_selection)
                {
                    for (int i = 0; i < tileSet.tileSelection.selection_tileData_list.Count; ++i)
                    {
                        tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[i])].tileColliderData = selected_tile.tileColliderData.Clone();
                    }
                }
                EditorUtility.SetDirty(tileSet);
                //Refresh selected tileMap
                TileMap selected_tileMap = Selection.activeGameObject ? Selection.activeGameObject.GetComponent <TileMap>() : null;
                if (selected_tileMap)
                {
                    selected_tileMap.Refresh(false, true);
                }
            }
        }

        //获取polyline(vertices组成的线段)线段上的离当前mouse poistion最近的点
        //Get the point on a polyline (in 3D space) which is closest to the current mouse position
        Vector3 ClosestPointToPolyLine(Vector3[] vertices, out int closest_segment_index)
        {
            float min_distance = float.MaxValue;

            closest_segment_index = 0;
            for (int i = 0; i < vertices.Length - 1; ++i)
            {
                float distance = HandleUtility.DistanceToLine(vertices[i], vertices[i + 1]);
                if (distance < min_distance)
                {
                    min_distance          = distance;
                    closest_segment_index = i;
                }
            }
            return(HandleUtility.ClosestPointToPolyLine(vertices));
        }
    }
Example #2
0
        private bool FillColliderMeshData()
        {
            //Debug.Log( "[" + ParentTilemap.name + "] FillColliderMeshData -> " + name);
            if (tileSet == null || parent_tileMap.tileMapColliderType == TileMapColliderType.None)
            {
                return(false);
            }

            System.Type collider2DType = parent_tileMap.tileMap2DColliderType == TileMap2DColliderType.EdgeCollider2D ? typeof(EdgeCollider2D) : typeof(PolygonCollider2D);
            Component[] aColliders2D   = null;
            if (parent_tileMap.tileMapColliderType == TileMapColliderType._3D)
            {
                int totalTiles = width * height;
                if (mesh_collider_vertice_list == null)
                {
                    mesh_collider_vertice_list  = new List <Vector3>(totalTiles * 4);
                    mesh_collider_triangle_list = new List <int>(totalTiles * 6);
                }
                else
                {
                    mesh_collider_vertice_list.Clear();
                    mesh_collider_triangle_list.Clear();
                }
            }
            else //if (ParentTilemap.ColliderType == eColliderType._2D)
            {
                has_2D_colliders = true;
                open_edge_list.Clear();
                aColliders2D = GetComponents(collider2DType);
            }
            float halvedCollDepth = parent_tileMap.collider_depth / 2f;
            bool  isEmpty         = true;

            for (int ty = 0, tileIdx = 0; ty < height; ++ty)
            {
                for (int tx = 0; tx < width; ++tx, ++tileIdx)
                {
                    uint tileData = tileData_list[tileIdx];
                    if (tileData != TileSetConst.TileData_Empty)
                    {
                        int  tileId = (int)(tileData & TileSetConst.TileDataMask_TileId);
                        Tile tile   = tileSet.GetTile(tileId);
                        if (tile != null)
                        {
#if ENABLE_MERGED_SUBTILE_COLLIDERS
                            TilesetBrush brush = ParentTilemap.Tileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData));
                            Vector2[]    subTileMergedColliderVertices = brush ? brush.GetMergedSubtileColliderVertices(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData) : null;
#else
                            Vector2[] subTileMergedColliderVertices = null;
#endif
                            bool hasMergedColliders = subTileMergedColliderVertices != null;

                            TileColliderData tileCollData = tile.tileColliderData;
                            if (tileCollData.type != TileColliderType.None || hasMergedColliders)
                            {
                                isEmpty = false;
                                int  neighborCollFlags           = 0; // don't remove, even using neighborTileCollData, neighborTileCollData is not filled if tile is empty
                                bool isSurroundedByFullColliders = true;
                                for (int i = 0; i < neighbor_segment_min_max.Length; ++i)
                                {
                                    neighbor_segment_min_max[i].x = float.MaxValue;
                                    neighbor_segment_min_max[i].y = float.MinValue;
                                }
                                System.Array.Clear(neighbor_tileColliderData, 0, neighbor_tileColliderData.Length);

                                if (!hasMergedColliders)
                                {
                                    if ((tileData & (TileSetConst.TileFlag_FlipH | TileSetConst.TileFlag_FlipV | TileSetConst.TileFlag_Rot90)) != 0)
                                    {
                                        tileCollData = tileCollData.Clone();
                                        tileCollData.ApplyFlippingFlags(tileData);
                                    }
                                    for (int i = 0; i < 4; ++i)
                                    {
                                        uint neighborTileData;
                                        bool isTriggerOrPolygon = parent_tileMap.is_trigger ||
                                                                  parent_tileMap.tileMapColliderType == TileMapColliderType._2D &&
                                                                  parent_tileMap.tileMap2DColliderType == TileMap2DColliderType.PolygonCollider2D;
                                        switch (i)
                                        {
                                        case 0: // Up Tile
                                            neighborTileData = (tileIdx + width) < tileData_list.Count ?
                                                               tileData_list[tileIdx + width]
                      :
                                                               isTriggerOrPolygon ? TileSetConst.TileData_Empty : parent_tileMap.GetTileData(offset_grid_x + tx, offset_grid_y + ty + 1); break;

                                        case 1:                                             // Right Tile
                                            neighborTileData = (tileIdx + 1) % width != 0 ? //(tileIdx + 1) < m_tileDataList.Count ?
                                                               tileData_list[tileIdx + 1]
                      :
                                                               isTriggerOrPolygon ? TileSetConst.TileData_Empty : parent_tileMap.GetTileData(offset_grid_x + tx + 1, offset_grid_y + ty); break;

                                        case 2: // Down Tile
                                            neighborTileData = tileIdx >= width ?
                                                               tileData_list[tileIdx - width]
                      :
                                                               isTriggerOrPolygon ? TileSetConst.TileData_Empty : parent_tileMap.GetTileData(offset_grid_x + tx, offset_grid_y + ty - 1); break;

                                        case 3:                                       // Left Tile
                                            neighborTileData = tileIdx % width != 0 ? //neighborTileId = tileIdx >= 1 ?
                                                               tileData_list[tileIdx - 1]
                      :
                                                               isTriggerOrPolygon ? TileSetConst.TileData_Empty : parent_tileMap.GetTileData(offset_grid_x + tx - 1, offset_grid_y + ty); break;

                                        default: neighborTileData = TileSetConst.TileData_Empty; break;
                                        }

                                        int neighborTileId = (int)(neighborTileData & TileSetConst.TileDataMask_TileId);
                                        if (neighborTileId != TileSetConst.TileId_Empty)
                                        {
                                            Vector2          segmentMinMax;
                                            TileColliderData neighborTileCollider;
                                            neighborTileCollider = tileSet.tile_list[neighborTileId].tileColliderData;
                                            if ((neighborTileData & (TileSetConst.TileFlag_FlipH | TileSetConst.TileFlag_FlipV | TileSetConst.TileFlag_Rot90)) != 0)
                                            {
                                                neighborTileCollider = neighborTileCollider.Clone();
                                                if ((neighborTileData & TileSetConst.TileFlag_FlipH) != 0)
                                                {
                                                    neighborTileCollider.FlipH();
                                                }
                                                if ((neighborTileData & TileSetConst.TileFlag_FlipV) != 0)
                                                {
                                                    neighborTileCollider.FlipV();
                                                }
                                                if ((neighborTileData & TileSetConst.TileFlag_Rot90) != 0)
                                                {
                                                    neighborTileCollider.Rot90();
                                                }
                                            }
                                            neighbor_tileColliderData[i] = neighborTileCollider;
                                            isSurroundedByFullColliders &= (neighborTileCollider.type == TileColliderType.Full);

                                            if (neighborTileCollider.type == TileColliderType.None)
                                            {
                                                segmentMinMax = new Vector2(float.MaxValue, float.MinValue); //NOTE: x will be min, y will be max
                                            }
                                            else if (neighborTileCollider.type == TileColliderType.Full)
                                            {
                                                segmentMinMax      = new Vector2(0f, 1f); //NOTE: x will be min, y will be max
                                                neighborCollFlags |= (1 << i);
                                            }
                                            else
                                            {
                                                segmentMinMax      = new Vector2(float.MaxValue, float.MinValue); //NOTE: x will be min, y will be max
                                                neighborCollFlags |= (1 << i);
                                                for (int j = 0; j < neighborTileCollider.vertices.Length; ++j)
                                                {
                                                    Vector2 v = neighborTileCollider.vertices[j];
                                                    {
                                                        if (i == 0 && v.y == 0 || i == 2 && v.y == 1) //Top || Bottom
                                                        {
                                                            if (v.x < segmentMinMax.x)
                                                            {
                                                                segmentMinMax.x = v.x;
                                                            }
                                                            if (v.x > segmentMinMax.y)
                                                            {
                                                                segmentMinMax.y = v.x;
                                                            }
                                                        }
                                                        else if (i == 1 && v.x == 0 || i == 3 && v.x == 1) //Right || Left
                                                        {
                                                            if (v.y < segmentMinMax.x)
                                                            {
                                                                segmentMinMax.x = v.y;
                                                            }
                                                            if (v.y > segmentMinMax.y)
                                                            {
                                                                segmentMinMax.y = v.y;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                            neighbor_segment_min_max[i] = segmentMinMax;
                                        }
                                        else
                                        {
                                            isSurroundedByFullColliders = false;
                                        }
                                    }
                                }
                                // Create Mesh Colliders
                                if (isSurroundedByFullColliders && !hasMergedColliders)
                                {
                                    //Debug.Log(" Surrounded! " + tileIdx);
                                }
                                else
                                {
                                    float     px0          = tx * cell_size.x;
                                    float     py0          = ty * cell_size.y;
                                    Vector2[] collVertices = subTileMergedColliderVertices;
                                    if (!hasMergedColliders)
                                    {
                                        collVertices = tileCollData.type == TileColliderType.Full ?TileConst.Full_Collider_Tile_Vertices : tileCollData.vertices;
                                    }

                                    for (int i = 0; i < collVertices.Length; ++i)
                                    {
                                        Vector2 s0 = collVertices[i];
                                        Vector2 s1 = collVertices[i == (collVertices.Length - 1) ? 0 : i + 1];
                                        if (hasMergedColliders)
                                        {
                                            ++i; // add ++i; in this case to go 2 by 2 because the collVertices for merged colliders will have the segments in pairs
                                        }
                                        // full collider optimization
                                        if ((tileCollData.type == TileColliderType.Full) &&
                                            (
                                                (i == 0 && neighbor_tileColliderData[3].type == TileColliderType.Full) || // left tile has collider
                                                (i == 1 && neighbor_tileColliderData[0].type == TileColliderType.Full) || // top tile has collider
                                                (i == 2 && neighbor_tileColliderData[1].type == TileColliderType.Full) || // right tile has collider
                                                (i == 3 && neighbor_tileColliderData[2].type == TileColliderType.Full)    // bottom tile has collider
                                            )
                                            )
                                        {
                                            continue;
                                        }
                                        // polygon collider optimization
                                        else // if( tileCollData.type == eTileCollider.Polygon ) Or Full colliders if neighbor is not Full as well
                                        {
                                            Vector2 n, m;
                                            if (s0.y == 1f && s1.y == 1f)           // top side
                                            {
                                                if ((neighborCollFlags & 0x1) != 0) // top tile has collider
                                                {
                                                    n = neighbor_segment_min_max[0];
                                                    if (n.x < n.y && n.x <= s0.x && n.y >= s1.x)
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.x == 1f && s1.x == 1f)      // right side
                                            {
                                                if ((neighborCollFlags & 0x2) != 0) // right tile has collider
                                                {
                                                    n = neighbor_segment_min_max[1];
                                                    if (n.x < n.y && n.x <= s1.y && n.y >= s0.y)
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.y == 0f && s1.y == 0f)      // bottom side
                                            {
                                                if ((neighborCollFlags & 0x4) != 0) // bottom tile has collider
                                                {
                                                    n = neighbor_segment_min_max[2];
                                                    if (n.x < n.y && n.x <= s1.x && n.y >= s0.x)
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.x == 0f && s1.x == 0f)      // left side
                                            {
                                                if ((neighborCollFlags & 0x8) != 0) // left tile has collider
                                                {
                                                    n = neighbor_segment_min_max[3];
                                                    if (n.x < n.y && n.x <= s0.y && n.y >= s1.y)
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.y == 1f && s1.x == 1f) // top - right diagonal
                                            {
                                                if ((neighborCollFlags & 0x1) != 0 && (neighborCollFlags & 0x2) != 0)
                                                {
                                                    n = neighbor_segment_min_max[0];
                                                    m = neighbor_segment_min_max[1];
                                                    if ((n.x < n.y && n.x <= s0.x && n.y == 1f) && (m.x < m.y && m.x <= s1.y && m.y == 1f))
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.x == 1f && s1.y == 0f) // right - bottom diagonal
                                            {
                                                if ((neighborCollFlags & 0x2) != 0 && (neighborCollFlags & 0x4) != 0)
                                                {
                                                    n = neighbor_segment_min_max[1];
                                                    m = neighbor_segment_min_max[2];
                                                    if ((n.x < n.y && n.x == 0f && n.y >= s0.y) && (m.x < m.y && m.x <= s1.x && m.y == 1f))
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.y == 0f && s1.x == 0f) // bottom - left diagonal
                                            {
                                                if ((neighborCollFlags & 0x4) != 0 && (neighborCollFlags & 0x8) != 0)
                                                {
                                                    n = neighbor_segment_min_max[2];
                                                    m = neighbor_segment_min_max[3];
                                                    if ((n.x < n.y && n.x == 0f && n.y >= s0.x) && (m.x < m.y && m.x == 0f && m.y >= s1.y))
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                            else if (s0.x == 0f && s1.y == 1f) // left - top diagonal
                                            {
                                                if ((neighborCollFlags & 0x8) != 0 && (neighborCollFlags & 0x1) != 0)
                                                {
                                                    n = neighbor_segment_min_max[3];
                                                    m = neighbor_segment_min_max[0];
                                                    if ((n.x < n.y && n.x <= s0.y && n.y == 1f) && (m.x < m.y && m.x == 0f && m.y >= s1.x))
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                        }
                                        // Update s0 and s1 to world positions
                                        s0.x = px0 + cell_size.x * s0.x; s0.y = py0 + cell_size.y * s0.y;
                                        s1.x = px0 + cell_size.x * s1.x; s1.y = py0 + cell_size.y * s1.y;
                                        if (parent_tileMap.tileMapColliderType == TileMapColliderType._3D)
                                        {
                                            int collVertexIdx = mesh_collider_vertice_list.Count;
                                            mesh_collider_vertice_list.Add(new Vector3(s0.x, s0.y, -halvedCollDepth));
                                            mesh_collider_vertice_list.Add(new Vector3(s0.x, s0.y, halvedCollDepth));
                                            mesh_collider_vertice_list.Add(new Vector3(s1.x, s1.y, halvedCollDepth));
                                            mesh_collider_vertice_list.Add(new Vector3(s1.x, s1.y, -halvedCollDepth));

                                            mesh_collider_triangle_list.Add(collVertexIdx + 0);
                                            mesh_collider_triangle_list.Add(collVertexIdx + 1);
                                            mesh_collider_triangle_list.Add(collVertexIdx + 2);
                                            mesh_collider_triangle_list.Add(collVertexIdx + 2);
                                            mesh_collider_triangle_list.Add(collVertexIdx + 3);
                                            mesh_collider_triangle_list.Add(collVertexIdx + 0);
                                        }
                                        else //if( ParentTilemap.ColliderType == eColliderType._2D )
                                        {
                                            int linkedSegments    = 0;
                                            int segmentIdxToMerge = -1;
                                            for (int edgeIdx = open_edge_list.Count - 1; edgeIdx >= 0 && linkedSegments < 2; --edgeIdx)
                                            {
                                                LinkedList <Vector2> edgeSegments = open_edge_list[edgeIdx];
                                                if (edgeSegments.First.Value == edgeSegments.Last.Value)
                                                {
                                                    continue; //skip closed edges
                                                }
                                                if (edgeSegments.Last.Value == s0)
                                                {
                                                    if (segmentIdxToMerge >= 0)
                                                    {
                                                        LinkedList <Vector2> segmentToMerge = open_edge_list[segmentIdxToMerge];
                                                        if (s0 == segmentToMerge.First.Value)
                                                        {
                                                            for (LinkedListNode <Vector2> node = segmentToMerge.First.Next; node != null; node = node.Next)
                                                            {
                                                                edgeSegments.AddLast(node.Value);
                                                            }
                                                            open_edge_list.RemoveAt(segmentIdxToMerge);
                                                        }

                                                        /* Cannot join head with head or tail with tail, it will change the segment normal
                                                         * else
                                                         *  for (LinkedListNode<Vector2> node = segmentToMerge.Last.Previous; node != null; node = node.Previous)
                                                         *      edgeSegments.AddLast(node.Value);*/
                                                    }
                                                    else
                                                    {
                                                        segmentIdxToMerge = edgeIdx;
                                                        edgeSegments.AddLast(s1);
                                                    }
                                                    ++linkedSegments;
                                                }

                                                /* Cannot join head with head or tail with tail, it will change the segment normal
                                                 * else if( edgeSegments.Last.Value == s1 )
                                                 * else if (edgeSegments.First.Value == s0)*/
                                                else if (edgeSegments.First.Value == s1)
                                                {
                                                    if (segmentIdxToMerge >= 0)
                                                    {
                                                        LinkedList <Vector2> segmentToMerge = open_edge_list[segmentIdxToMerge];
                                                        if (s1 == segmentToMerge.Last.Value)
                                                        {
                                                            for (LinkedListNode <Vector2> node = edgeSegments.First.Next; node != null; node = node.Next)
                                                            {
                                                                segmentToMerge.AddLast(node.Value);
                                                            }
                                                            open_edge_list.RemoveAt(edgeIdx);
                                                        }

                                                        /* Cannot join head with head or tail with tail, it will change the segment normal
                                                         * else
                                                         *  for (LinkedListNode<Vector2> node = edgeSegments.First.Next; node != null; node = node.Next)
                                                         *      segmentToMerge.AddFirst(node.Value);*/
                                                    }
                                                    else
                                                    {
                                                        segmentIdxToMerge = edgeIdx;
                                                        edgeSegments.AddFirst(s0);
                                                    }
                                                    ++linkedSegments;
                                                }
                                            }
                                            if (linkedSegments == 0)
                                            {
                                                LinkedList <Vector2> newEdge = new LinkedList <Vector2>();
                                                newEdge.AddFirst(s0);
                                                newEdge.AddLast(s1);
                                                open_edge_list.Add(newEdge);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (parent_tileMap.tileMapColliderType == TileMapColliderType._2D)
            {
                //+++ Process Edges
                //(NOTE: this was added to fix issues related with lighting, otherwise leave this commented)
                {
                    // Remove vertex inside a line
                    RemoveRedundantVertices(open_edge_list);

                    // Split segments (NOTE: This is not working with polygon colliders)

                    /*/ commented unless necessary for performance reasons
                     * if (ParentTilemap.Collider2DType == e2DColliderType.EdgeCollider2D)
                     * {
                     *  openEdges = SplitSegments(openEdges);
                     * }
                     * //*/
                }
                //---

                //Create Edges
                for (int i = 0; i < open_edge_list.Count; ++i)
                {
                    LinkedList <Vector2> edgeSegments = open_edge_list[i];
                    bool       reuseCollider          = i < aColliders2D.Length;
                    Collider2D collider2D             = reuseCollider ? (Collider2D)aColliders2D[i] : (Collider2D)gameObject.AddComponent(collider2DType);
                    collider2D.enabled        = true;
                    collider2D.isTrigger      = parent_tileMap.is_trigger;
                    collider2D.sharedMaterial = parent_tileMap.physicMaterial2D;
                    if (parent_tileMap.tileMap2DColliderType == TileMap2DColliderType.EdgeCollider2D)
                    {
                        ((EdgeCollider2D)collider2D).points = edgeSegments.ToArray();
                    }
                    else
                    {
                        ((PolygonCollider2D)collider2D).SetPath(0, edgeSegments.ToArray());
                    }
                }

                //Destroy unused edge colliders
                for (int i = open_edge_list.Count; i < aColliders2D.Length; ++i)
                {
                    if (!is_on_validate)
                    {
                        DestroyImmediate(aColliders2D[i]);
                    }
                    else
                    {
                        ((Collider2D)aColliders2D[i]).enabled = false;
                    }
                }
            }

            return(!isEmpty);
        }