Beispiel #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));
        }
    }
Beispiel #2
0
        public void DoPaintDragged(TileMap tileMap, Vector2 local_pos, EventModifiers modifiers = default(EventModifiers))
        {
            //Debug.Log("DoPaintDragged (" + TilemapUtils.GetGridX(tilemap, localPos) + "," + TilemapUtils.GetGridY(tilemap, localPos) + ")");
            if (paint_mode == TileSetBrushPaintMode.Pencil)
            {
                Paint(tileMap, local_pos);
            }
            else
            {
                if (is_dragging)
                {
                    this.tileMap.ClearMap();
                    Vector2 brushLocPos = tileMap.transform.InverseTransformPoint(transform.position);
                    Vector2 startPos    = TileSetBrushUtil.GetSnappedPosition(pressed_position, this.tileMap.cell_size) + this.tileMap.cell_size / 2f -
                                          brushLocPos;
                    Vector2 endPos = TileSetBrushUtil.GetSnappedPosition(local_pos, this.tileMap.cell_size) + this.tileMap.cell_size / 2f -
                                     brushLocPos;
                    bool isCtrl  = (modifiers & EventModifiers.Control) != 0;
                    bool isShift = (modifiers & EventModifiers.Shift) != 0;
                    switch (paint_mode)
                    {
                    case TileSetBrushPaintMode.Line:
                        if (isCtrl)
                        {
                            TileMapDrawingUtil.DrawLineMirrored(this.tileMap, startPos, endPos, brushPattern);
                        }
                        else
                        {
                            TileMapDrawingUtil.DrawLine(this.tileMap, startPos, endPos, brushPattern);
                        }
                        break;

                    case TileSetBrushPaintMode.Rect:
                    case TileSetBrushPaintMode.FilledRect:
                    case TileSetBrushPaintMode.Ellipse:
                    case TileSetBrushPaintMode.FilledEllipse:
                        if (isShift)
                        {
                            Vector2 vTemp = endPos - startPos;
                            float   absX  = Mathf.Abs(vTemp.x);
                            float   absY  = Mathf.Abs(vTemp.y);
                            vTemp.x = (absX > absY) ? vTemp.x : Mathf.Sign(vTemp.x) * absY;
                            vTemp.y = Mathf.Sign(vTemp.y) * Mathf.Abs(vTemp.x);
                            endPos  = startPos + vTemp;
                        }

                        if (isCtrl)
                        {
                            startPos = 2f * startPos - endPos;
                        }
                        if (paint_mode == TileSetBrushPaintMode.Rect || paint_mode == TileSetBrushPaintMode.FilledRect)
                        {
                            TileMapDrawingUtil.DrawRect(this.tileMap, startPos, endPos, brushPattern,
                                                        paint_mode == TileSetBrushPaintMode.FilledRect, (modifiers & EventModifiers.Alt) != 0);
                        }
                        else if (paint_mode == TileSetBrushPaintMode.Ellipse || paint_mode == TileSetBrushPaintMode.FilledEllipse)
                        {
                            TileMapDrawingUtil.DrawEllipse(this.tileMap, startPos, endPos, brushPattern,
                                                           paint_mode == TileSetBrushPaintMode.FilledEllipse);
                        }
                        break;
                    }

                    this.tileMap.UpdateMeshImmediate();
                }
            }
        }
Beispiel #3
0
        //https://social.msdn.microsoft.com/Forums/en-US/9d926a16-0051-4ca3-b77c-8095fb489ae2/flood-fill-c?forum=csharplanguage
        public static void FloodFill(TileMap tilemap, int gridX, int gridY, uint[,] tileData, bool randomize = false)
        {
            float timeStamp;

            timeStamp = Time.realtimeSinceStartup;
            //float callTimeStamp = timeStamp;

            int patternW             = tileData.GetLength(0);
            int patternH             = tileData.GetLength(1);
            LinkedList <Point> check = new LinkedList <Point>();
            uint floodFrom           = tilemap.GetTileData(gridX, gridY);
            int  dataIdx0            = randomize ? Random.Range(0, patternW) : (gridX % patternW + patternW) % patternW;
            int  dataIdx1            = randomize ? Random.Range(0, patternH) : (gridY % patternH + patternH) % patternH;

            tilemap.SetTileData(gridX, gridY, tileData[dataIdx0, dataIdx1]);
            bool isBrush = TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != 0;

            //Debug.Log(" Flood Fill Starts +++++++++++++++ ");
            if (
                (patternW > 0 && patternH > 0) &&
                isBrush ?
                TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != TileSetUtil.GetTileSetBrushIdFromTileData(tileData[0, 0])
          :
                floodFrom != tileData[0, 0]
                )
            {
                check.AddLast(new Point(gridX, gridY));
                while (check.Count > 0)
                {
                    Point cur = check.First.Value;
                    check.RemoveFirst();

                    foreach (Point off in new Point[] {
                        new Point(0, -1), new Point(0, 1),
                        new Point(-1, 0), new Point(1, 0)
                    })
                    {
                        Point next         = new Point(cur.X + off.X, cur.Y + off.Y);
                        uint  nextTileData = tilemap.GetTileData(next.X, next.Y);
                        if (
                            next.X >= tilemap.min_grid_x && next.X <= tilemap.max_grid_x &&
                            next.Y >= tilemap.min_grid_y && next.Y <= tilemap.max_grid_y
                            )
                        {
                            if (
                                isBrush ?
                                TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) == TileSetUtil.GetTileSetBrushIdFromTileData(nextTileData)
                  :
                                floodFrom == nextTileData
                                )
                            {
                                check.AddLast(next);
                                dataIdx0 = randomize ? Random.Range(0, patternW) : (next.X % patternW + patternW) % patternW;
                                dataIdx1 = randomize ? Random.Range(0, patternH) : (next.Y % patternH + patternH) % patternH;
                                tilemap.SetTileData(next.X, next.Y, tileData[dataIdx0, dataIdx1]);
                            }
                        }
                    }

                    float timePast = Time.realtimeSinceStartup - timeStamp;
                    if (timePast > k_timeToAbortFloodFill)
                    {
#if UNITY_EDITOR
                        int result = UnityEditor.EditorUtility.DisplayDialogComplex("FloodFill is taking too much time", "Do you want to continue for another " + k_timeToAbortFloodFill + " seconds?", "Wait", "Cancel", "Wait and Don't ask again");
                        if (result == 0)
                        {
                            timeStamp = Time.realtimeSinceStartup;
                        }
                        else if (result == 1)
                        {
                            break;
                        }
                        else if (result == 2)
                        {
                            timeStamp = float.MaxValue;
                        }
#else
                        check.Clear();
#endif
                    }
                }
            }

            //Debug.Log("FloodFill Time " + (int)((Time.realtimeSinceStartup - callTimeStamp) * 1000) + "ms");
        }
Beispiel #4
0
        public static void DrawRect(TileMap tilemap, int x0, int y0, int x1, int y1, uint[,] tileData, bool isFilled, bool is9Sliced = false, bool randomize = false)
        {
            int w = tileData.GetLength(0);
            int h = tileData.GetLength(1);

            if (x0 > x1)
            {
                Swap <int>(ref x0, ref x1);
            }
            if (y0 > y1)
            {
                Swap <int>(ref y0, ref y1);
            }
            TileMapDrawingUtil.Rect(x0, y0, x1, y1, isFilled,
                                    (x, y) =>
            {
                if (is9Sliced)
                {
                    if (x == x0 && y == y0)
                    {
                        tilemap.SetTileData(x, y, tileData[0, 0]);
                    }
                    else if (x == x0 && y == y1)
                    {
                        tilemap.SetTileData(x, y, tileData[0, h - 1]);
                    }
                    else if (x == x1 && y == y0)
                    {
                        tilemap.SetTileData(x, y, tileData[w - 1, 0]);
                    }
                    else if (x == x1 && y == y1)
                    {
                        tilemap.SetTileData(x, y, tileData[w - 1, h - 1]);
                    }
                    else
                    {
                        int cw = w - 2;
                        int ch = h - 2;
                        int cx = cw >= 1 ? 1 + (x % cw + cw) % cw : (x % w + w) % w;
                        int cy = ch >= 1 ? 1 + (y % ch + ch) % ch : (y % h + h) % h;
                        if (x == x0)
                        {
                            tilemap.SetTileData(x, y, tileData[0, cy]);
                        }
                        else if (x == x1)
                        {
                            tilemap.SetTileData(x, y, tileData[w - 1, cy]);
                        }
                        else if (y == y0)
                        {
                            tilemap.SetTileData(x, y, tileData[cx, 0]);
                        }
                        else if (y == y1)
                        {
                            tilemap.SetTileData(x, y, tileData[cx, h - 1]);
                        }
                        else
                        {
                            tilemap.SetTileData(x, y, tileData[cx, cy]);
                        }
                    }
                }
                else
                {
                    int dataIdx0 = randomize ? Random.Range(0, w) : (x % w + w) % w;
                    int dataIdx1 = randomize ? Random.Range(0, h) : (y % h + h) % h;
                    tilemap.SetTileData(x, y, tileData[dataIdx0, dataIdx1]);
                }
                return(true);
            }
                                    );
        }
Beispiel #5
0
        //Note: this is doing the same as FloodFill but not saving data in the tilemap, only saving the filled points and returning a list
        public static void FloodFillPreview(TileMap tilemap, int gridX, int gridY, uint tileData, List <Vector2> outFilledPoints, uint maxPoints = uint.MaxValue)
        {
            if (
                gridX >= tilemap.min_grid_x && gridX <= tilemap.max_grid_x &&
                gridY >= tilemap.min_grid_y && gridY <= tilemap.max_grid_y
                )
            {
                bool[]             filledPoints = new bool[tilemap.GridWidth * tilemap.GridHeight];
                LinkedList <Point> check        = new LinkedList <Point>();
                uint floodFrom = tilemap.GetTileData(gridX, gridY);
                outFilledPoints.Add(Vector2.Scale(new Vector2(gridX, gridY), tilemap.cell_size));
                filledPoints[(gridY - tilemap.min_grid_y) * tilemap.GridWidth + gridX - tilemap.min_grid_x] = true;
                bool isBrush = TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != 0;
                if (
                    isBrush ?
                    TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != TileSetUtil.GetTileSetBrushIdFromTileData(tileData)
            :
                    floodFrom != tileData
                    )
                {
                    check.AddLast(new Point(gridX, gridY));
                    while (check.Count > 0)
                    {
                        Point cur = check.First.Value;
                        check.RemoveFirst();

                        foreach (Point off in new Point[] {
                            new Point(0, -1), new Point(0, 1),
                            new Point(-1, 0), new Point(1, 0)
                        })
                        {
                            Point next = new Point(cur.X + off.X, cur.Y + off.Y);

                            if (
                                next.X >= tilemap.min_grid_x && next.X <= tilemap.max_grid_x &&
                                next.Y >= tilemap.min_grid_y && next.Y <= tilemap.max_grid_y
                                )
                            {
                                if (filledPoints[(next.Y - tilemap.min_grid_y) * tilemap.GridWidth + next.X - tilemap.min_grid_x])
                                {
                                    continue;                                                                                // skip already filled points
                                }
                                uint nextTileData = tilemap.GetTileData(next.X, next.Y);
                                if (
                                    isBrush ?
                                    TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) == TileSetUtil.GetTileSetBrushIdFromTileData(nextTileData)
                    :
                                    floodFrom == nextTileData
                                    )
                                {
                                    check.AddLast(next);
                                    filledPoints[(next.Y - tilemap.min_grid_y) * tilemap.GridWidth + next.X - tilemap.min_grid_x] = true;
                                    outFilledPoints.Add(Vector2.Scale(new Vector2(next.X, next.Y), tilemap.cell_size));
                                    if (outFilledPoints.Count >= maxPoints)
                                    {
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }