/// <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); }
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; }
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); }
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(); }
/// <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)); }
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); } }
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; }
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)); } }
public AutoTileInputNode(TilesetAutoTileInput autoTile) : base() { this.autoTile = autoTile; this.Image = Properties.TilemapsResCache.IconTilesetAutoTileLayer; }
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); } }
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); } } }
protected override void OnTilesetSelectionChanged(TilesetSelectionChangedEventArgs args) { this.currentAutoTile = null; this.UpdateTreeModel(); }