Exemplo n.º 1
0
        /// <inheritdoc />
        public override void AddLayer()
        {
            base.AddLayer();
            Tileset tileset = this.SelectedTileset.Res;

            if (tileset == null)
            {
                return;
            }

            // Decide upon an id for our new layer
            string autoTileId   = TilesetAutoTileInput.DefaultId + (tileset.AutoTileConfig.Count).ToString();
            string autoTileName = TilesetAutoTileInput.DefaultName;

            // Create a new AutoTile using an UndoRedo action
            TilesetAutoTileInput newAutoTile = new TilesetAutoTileInput
            {
                Id   = autoTileId,
                Name = autoTileName
            };

            UndoRedoManager.Do(new AddTilesetConfigLayerAction <TilesetAutoTileInput>(
                                   tileset,
                                   TilemapsReflectionInfo.Property_Tileset_AutoTileConfig,
                                   newAutoTile));

            // Select the newly created AutoTile
            AutoTileInputNode modelNode = this.treeModel
                                          .Nodes
                                          .OfType <AutoTileInputNode>()
                                          .FirstOrDefault(n => n.AutoTileInput == newAutoTile);

            this.SelectLayer(modelNode);
        }
Exemplo n.º 2
0
        public EditTilesetAutoTileItemAction(Tileset tileset, TilesetAutoTileInput autoTile, RawList <TilesetAutoTileItem> tileInput, RawList <bool> tileInputMask)
        {
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }
            if (autoTile == null)
            {
                throw new ArgumentNullException("autoTile");
            }
            if (tileInput == null)
            {
                throw new ArgumentNullException("tileInput");
            }
            if (tileInputMask == null)
            {
                throw new ArgumentNullException("tileInputMask");
            }
            if (tileInputMask.Count != tileInput.Count)
            {
                throw new ArgumentException("Input Mask needs to be the same size as input.", "tileInputMask");
            }

            this.autoTile      = autoTile;
            this.tileset       = tileset;
            this.tileInput     = tileInput;
            this.tileInputMask = tileInputMask;
        }
Exemplo n.º 3
0
        private void TilesetView_MouseDown(object sender, MouseEventArgs e)
        {
            Tileset tileset = this.SelectedTileset.Res;

            if (tileset == null)
            {
                return;
            }

            TilesetAutoTileInput autoTile = this.currentAutoTile;

            if (autoTile == null)
            {
                return;
            }

            int tileIndex = this.TilesetView.HoveredTileIndex;

            if (tileIndex < 0 || tileIndex > tileset.TileCount)
            {
                return;
            }

            // Update modifier key based drawing state
            this.UpdateExternalDrawMode();

            // Draw operation on left click
            if (e.Button == MouseButtons.Left)
            {
                this.isUserDrawing = true;
                this.userDrawMode  = AutoTileDrawMode.Add;
            }
            // Clear operation on right click
            else if (e.Button == MouseButtons.Right)
            {
                this.isUserDrawing = true;
                this.userDrawMode  = AutoTileDrawMode.Remove;
            }

            // Perform the drawing operation
            this.PerformUserDrawAction();
            this.TilesetView.InvalidateTile(tileIndex, 0);
        }
Exemplo n.º 4
0
        protected override void OnLayerSelectionChanged(LayerSelectionChangedEventArgs args)
        {
            base.OnLayerSelectionChanged(args);
            Tileset           tileset      = this.SelectedTileset.Res;
            AutoTileInputNode selectedNode = args.SelectedNodeTag as AutoTileInputNode;

            // Update global editor selection, so an Object Inspector can pick up the AutoTile for editing
            if (selectedNode != null)
            {
                this.currentAutoTile = selectedNode.AutoTileInput;
                DualityEditorApp.Select(this, new ObjectSelection(new object[] { selectedNode.AutoTileInput }));
            }
            else
            {
                this.currentAutoTile = null;
                DualityEditorApp.Deselect(this, obj => obj is TilesetAutoTileInput);
            }

            this.TilesetView.Invalidate();
        }
Exemplo n.º 5
0
        /// <inheritdoc />
        public override void RemoveLayer()
        {
            base.RemoveLayer();

            Tileset tileset = this.SelectedTileset.Res;
            TilesetAutoTileInput autoTile = this.currentAutoTile;

            if (tileset == null)
            {
                return;
            }
            if (autoTile == null)
            {
                return;
            }

            UndoRedoManager.Do(new RemoveTilesetConfigLayerAction <TilesetAutoTileInput>(
                                   tileset,
                                   TilemapsReflectionInfo.Property_Tileset_AutoTileConfig,
                                   autoTile));
        }
Exemplo n.º 6
0
        private void UpdateExternalDrawMode()
        {
            TilesetAutoTileInput autoTile = this.currentAutoTile;

            if (autoTile == null)
            {
                return;
            }

            bool lastExternalDraw    = this.isExternalDraw;
            int  hoveredTile         = this.TilesetView.HoveredTileIndex;
            TilesetAutoTileItem item = (hoveredTile >= 0 && hoveredTile < autoTile.TileInput.Count) ?
                                       autoTile.TileInput[hoveredTile] :
                                       default(TilesetAutoTileItem);

            this.isExternalDraw = Control.ModifierKeys.HasFlag(Keys.Shift) || item.ConnectsToAutoTile;

            if (lastExternalDraw != this.isExternalDraw)
            {
                this.TilesetView.InvalidateTile(this.TilesetView.HoveredTileIndex, 0);
            }
        }
Exemplo n.º 7
0
        public EditTilesetAutoTileItemAction(Tileset tileset, TilesetAutoTileInput autoTile, int tileIndex, TilesetAutoTileItem tileInput)
        {
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }
            if (autoTile == null)
            {
                throw new ArgumentNullException("autoTile");
            }

            this.tileset  = tileset;
            this.autoTile = autoTile;

            this.tileInput                 = new RawList <TilesetAutoTileItem>(tileIndex + 1);
            this.tileInput.Count           = tileIndex + 1;
            this.tileInput.Data[tileIndex] = tileInput;

            this.tileInputMask                 = new RawList <bool>(tileIndex + 1);
            this.tileInputMask.Count           = tileIndex + 1;
            this.tileInputMask.Data[tileIndex] = true;
        }
Exemplo n.º 8
0
        private void PerformUserDrawAction()
        {
            Tileset tileset = this.SelectedTileset.Res;

            if (tileset == null)
            {
                return;
            }

            TilesetAutoTileInput autoTile = this.currentAutoTile;

            if (autoTile == null)
            {
                return;
            }

            int tileIndex = this.TilesetView.HoveredTileIndex;

            if (tileIndex < 0 || tileIndex > tileset.TileCount)
            {
                return;
            }

            // Determine data before the operation, and set up data for afterwards
            bool lastIsBaseTile           = autoTile.BaseTileIndex == tileIndex;
            bool newIsBaseTile            = lastIsBaseTile;
            TilesetAutoTileItem lastInput = (autoTile.TileInput.Count > tileIndex) ?
                                            autoTile.TileInput[tileIndex] :
                                            default(TilesetAutoTileItem);
            TilesetAutoTileItem newInput = lastInput;

            // Determine how data is modified due to our user operation
            if (this.userDrawMode == AutoTileDrawMode.Add)
            {
                if (this.isExternalDraw)
                {
                    newInput.Neighbours         = TileConnection.None;
                    newInput.ConnectsToAutoTile = true;
                    newInput.IsAutoTile         = false;
                    newIsBaseTile = false;
                }
                else if (this.isBaseTileDraw)
                {
                    newInput.Neighbours         = TileConnection.All;
                    newInput.IsAutoTile         = true;
                    newInput.ConnectsToAutoTile = false;
                    newIsBaseTile = true;
                }
                else
                {
                    newInput.Neighbours        |= this.hoveredArea;
                    newInput.IsAutoTile         = true;
                    newInput.ConnectsToAutoTile = false;
                }
            }
            else if (this.userDrawMode == AutoTileDrawMode.Remove)
            {
                if (this.isExternalDraw || this.isBaseTileDraw || this.hoveredArea == TileConnection.None)
                {
                    newInput.Neighbours         = TileConnection.None;
                    newInput.ConnectsToAutoTile = false;
                    newInput.IsAutoTile         = false;
                    newIsBaseTile = false;
                }
                else
                {
                    newInput.Neighbours &= ~this.hoveredArea;
                    newInput.IsAutoTile  = (newInput.Neighbours != TileConnection.None);
                }
            }

            // Apply the new, modified data to the actual data using an UndoRedo operation
            if (newIsBaseTile != lastIsBaseTile)
            {
                UndoRedoManager.Do(new EditPropertyAction(
                                       null,
                                       TilemapsReflectionInfo.Property_TilesetAutoTileInput_BaseTile,
                                       new object[] { autoTile },
                                       new object[] { newIsBaseTile?tileIndex: -1 }));
            }
            if (!object.Equals(lastInput, newInput))
            {
                UndoRedoManager.Do(new EditTilesetAutoTileItemAction(
                                       tileset,
                                       autoTile,
                                       tileIndex,
                                       newInput));
            }
        }
Exemplo n.º 9
0
 public AutoTileInputNode(TilesetAutoTileInput autoTile) : base()
 {
     this.autoTile = autoTile;
     this.Image    = Properties.TilemapsResCache.IconTilesetAutoTileLayer;
 }
Exemplo n.º 10
0
        private void TilesetView_MouseMove(object sender, MouseEventArgs e)
        {
            Size  tileSize   = this.TilesetView.DisplayedTileSize;
            Point tilePos    = this.TilesetView.GetTileIndexLocation(this.TilesetView.HoveredTileIndex);
            Point posOnTile  = new Point(e.X - tilePos.X, e.Y - tilePos.Y);
            Size  centerSize = new Size(tileSize.Width / 2, tileSize.Height / 2);

            // Determine the hovered tile hotspot for user interaction
            TileConnection lastHoveredArea = this.hoveredArea;

            if (posOnTile.X > (tileSize.Width - centerSize.Width) / 2 &&
                posOnTile.Y > (tileSize.Height - centerSize.Height) / 2 &&
                posOnTile.X < (tileSize.Width + centerSize.Width) / 2 &&
                posOnTile.Y < (tileSize.Height + centerSize.Height) / 2)
            {
                this.hoveredArea = TileConnection.None;
            }
            else
            {
                float angle     = MathF.Angle(tileSize.Width / 2, tileSize.Height / 2, posOnTile.X, posOnTile.Y);
                float threshold = MathF.DegToRad(22.5f);
                if (MathF.CircularDist(angle, MathF.DegToRad(315.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.TopLeft;
                }
                else if (MathF.CircularDist(angle, MathF.DegToRad(0.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.Top;
                }
                else if (MathF.CircularDist(angle, MathF.DegToRad(45.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.TopRight;
                }
                else if (MathF.CircularDist(angle, MathF.DegToRad(270.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.Left;
                }
                else if (MathF.CircularDist(angle, MathF.DegToRad(90.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.Right;
                }
                else if (MathF.CircularDist(angle, MathF.DegToRad(225.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.BottomLeft;
                }
                else if (MathF.CircularDist(angle, MathF.DegToRad(180.0f)) <= threshold)
                {
                    this.hoveredArea = TileConnection.Bottom;
                }
                else
                {
                    this.hoveredArea = TileConnection.BottomRight;
                }
            }

            // Update action state
            TilesetAutoTileInput autoTile = this.currentAutoTile;

            if (autoTile != null)
            {
                this.isBaseTileDraw =
                    autoTile.BaseTileIndex == -1 ||
                    autoTile.BaseTileIndex == this.TilesetView.HoveredTileIndex;
            }
            this.UpdateExternalDrawMode();

            // If the user is in the process of setting or clearing bits, perform the drawing operation
            if (this.isUserDrawing)
            {
                this.PerformUserDrawAction();
            }

            if (lastHoveredArea != this.hoveredArea)
            {
                this.TilesetView.InvalidateTile(this.TilesetView.HoveredTileIndex, 0);
            }
        }
Exemplo n.º 11
0
        private void TilesetView_PaintTiles(object sender, TilesetViewPaintTilesEventArgs e)
        {
            Color highlightColor          = Color.FromArgb(255, 255, 255);
            Color baseTileDrawColor       = Color.FromArgb(255, 192, 128);
            Color externalDrawColor       = Color.FromArgb(128, 192, 255);
            Color nonConnectedColor       = Color.FromArgb(128, 0, 0, 0);
            Brush brushNonConnected       = new SolidBrush(nonConnectedColor);
            TilesetAutoTileInput autoTile = this.currentAutoTile;

            // Early-out if there is nothing we can edit right now
            if (autoTile == null)
            {
                return;
            }

            // If we're in a special draw mode, switch highlight colors to indicate this.
            if (this.isExternalDraw)
            {
                highlightColor = externalDrawColor;
            }
            else if (this.isBaseTileDraw)
            {
                highlightColor = baseTileDrawColor;
            }

            // Set up shared working data
            TilesetAutoTileItem[]    tileInput         = autoTile.TileInput.Data;
            TilesetViewPaintTileData hoveredData       = default(TilesetViewPaintTileData);
            TilesetAutoTileItem      hoveredItem       = default(TilesetAutoTileItem);
            GraphicsPath             connectedOutlines = new GraphicsPath();
            GraphicsPath             connectedRegion   = new GraphicsPath();

            // Draw all the tiles that we're supposed to paint
            for (int i = 0; i < e.PaintedTiles.Count; i++)
            {
                TilesetViewPaintTileData paintData = e.PaintedTiles[i];

                // Prepare some data we'll need for drawing the per-tile info overlay
                bool tileHovered         = this.TilesetView.HoveredTileIndex == paintData.TileIndex;
                bool isBaseTile          = autoTile.BaseTileIndex == paintData.TileIndex;
                TilesetAutoTileItem item = (autoTile.TileInput.Count > paintData.TileIndex) ?
                                           tileInput[paintData.TileIndex] :
                                           default(TilesetAutoTileItem);

                // Remember hovered item data for later (post-overlay)
                if (tileHovered)
                {
                    hoveredData = paintData;
                    hoveredItem = item;
                }

                // Accumulate a shared region for displaying connectivity, as well as a path of all their outlines
                if (item.IsAutoTile)
                {
                    Rectangle centerRect = GetConnectivityRegionRect(TileConnection.None, paintData.ViewRect);
                    connectedRegion.AddRectangle(centerRect);
                    DrawConnectivityRegion(connectedRegion, item.Neighbours, paintData.ViewRect);
                    DrawConnectivityOutlines(connectedOutlines, item.Neighbours, paintData.ViewRect);
                }
                else if (item.ConnectsToAutoTile)
                {
                    connectedRegion.AddRectangle(paintData.ViewRect);
                }

                // Highlight base tile and external connecting tiles
                if (isBaseTile)
                {
                    DrawTileHighlight(e.Graphics, paintData.ViewRect, baseTileDrawColor);
                }
                else if (!item.IsAutoTile && item.ConnectsToAutoTile)
                {
                    DrawTileHighlight(e.Graphics, paintData.ViewRect, externalDrawColor);
                }
            }

            // Fill all non-connected regions with the overlay brush
            Region surroundingRegion = new Region();

            surroundingRegion.MakeInfinite();
            surroundingRegion.Exclude(connectedRegion);
            e.Graphics.IntersectClip(surroundingRegion);
            e.Graphics.FillRectangle(brushNonConnected, this.TilesetView.ClientRectangle);
            e.Graphics.ResetClip();

            // Draw connected region outlines
            e.Graphics.DrawPath(Pens.White, connectedOutlines);

            // Draw a tile-based hover indicator
            if (!hoveredData.ViewRect.IsEmpty && !this.isBaseTileDraw && !this.isExternalDraw)
            {
                DrawHoverIndicator(e.Graphics, hoveredData.ViewRect, 64, highlightColor);
            }

            // Draw a hover indicator for a specific hovered region
            if (!hoveredData.ViewRect.IsEmpty)
            {
                if (!this.isBaseTileDraw && !this.isExternalDraw)
                {
                    DrawHoverIndicator(e.Graphics, GetConnectivityRegionRect(this.hoveredArea, hoveredData.ViewRect), 255, highlightColor);
                }
                else
                {
                    DrawHoverIndicator(e.Graphics, hoveredData.ViewRect, 255, highlightColor);
                }
            }
        }
Exemplo n.º 12
0
 protected override void OnTilesetSelectionChanged(TilesetSelectionChangedEventArgs args)
 {
     this.currentAutoTile = null;
     this.UpdateTreeModel();
 }