public override void UpdatePreview() { ITilemapToolEnvironment env = this.Environment; IReadOnlyGrid <bool> sourceShape = env.TileDrawSource.SourceShape; env.ActiveAreaOutlines.Clear(); env.ActiveOrigin = new Point2( env.HoveredTile.X - sourceShape.Width / 2, env.HoveredTile.Y - sourceShape.Height / 2); if (sourceShape.Width > 0 && sourceShape.Height > 0) { env.ActiveArea.ResizeClear(sourceShape.Width, sourceShape.Height); for (int y = 0; y < sourceShape.Height; y++) { for (int x = 0; x < sourceShape.Width; x++) { env.ActiveArea[x, y] = sourceShape[x, y]; } } } else { env.ActiveArea.ResizeClear(1, 1); env.ActiveArea[0, 0] = true; } env.SubmitActiveAreaChanges(true); }
public override void UpdatePreview() { ITilemapToolEnvironment env = this.Environment; env.ActiveAreaOutlines.Clear(); env.ActiveOrigin = env.HoveredTile; env.ActiveArea.ResizeClear(0, 0); env.SubmitActiveAreaChanges(true); }
public override void UpdateActiveArea() { base.UpdateActiveArea(); ITilemapToolEnvironment env = this.Environment; Point2 activeOrigin = env.ActiveOrigin; this.floodFill.GetFillArea(env.ActiveTilemap, activeOrigin, false, env.ActiveArea, ref activeOrigin); env.ActiveOrigin = activeOrigin; env.ActiveAreaOutlines.Clear(); env.SubmitActiveAreaChanges(true); }
public override void UpdatePreview() { ITilemapToolEnvironment env = this.Environment; // Don't update flood fill when hovering a tile that's out of range of the tilemap if (env.HoveredTile.X < 0 || env.HoveredTile.Y < 0 || env.HoveredTile.X >= env.ActiveTilemap.Size.X || env.HoveredTile.Y >= env.ActiveTilemap.Size.Y) { return; } // Don't update flood fill when still hovering the same tile if (env.ActiveOrigin == env.HoveredTile) { return; } // Don't update flood fill when still inside the previous flood fill area Point2 activeLocalHover = new Point2( env.HoveredTile.X - env.ActiveOrigin.X, env.HoveredTile.Y - env.ActiveOrigin.Y); bool hoverInsideActiveRect = ( activeLocalHover.X >= 0 && activeLocalHover.Y >= 0 && activeLocalHover.X < env.ActiveArea.Width && activeLocalHover.Y < env.ActiveArea.Height); bool hoverInsideActiveArea = (hoverInsideActiveRect && env.ActiveArea[activeLocalHover.X, activeLocalHover.Y]); if (hoverInsideActiveArea) { return; } // Run the flood fill algorithm Point2 activeOrigin = env.ActiveOrigin; bool previewValid = this.floodFill.GetFillArea(env.ActiveTilemap, env.HoveredTile, true, env.ActiveArea, ref activeOrigin); env.ActiveOrigin = activeOrigin; if (!previewValid) { env.ActiveOrigin = env.HoveredTile; env.ActiveArea.ResizeClear(1, 1); env.ActiveArea[0, 0] = true; } env.ActiveAreaOutlines.Clear(); env.SubmitActiveAreaChanges(previewValid); }
public override void UpdatePreview() { ITilemapToolEnvironment env = this.Environment; Point2 topLeft = new Point2( Math.Min(env.ActionBeginTile.X, env.HoveredTile.X), Math.Min(env.ActionBeginTile.Y, env.HoveredTile.Y)); Point2 size = new Point2( 1 + Math.Abs(env.ActionBeginTile.X - env.HoveredTile.X), 1 + Math.Abs(env.ActionBeginTile.Y - env.HoveredTile.Y)); // Don't update the rect when still using the same boundary size bool hoverInsideActiveArea = (env.ActiveOrigin == topLeft && env.ActiveArea.Width == size.X && env.ActiveArea.Height == size.Y); if (hoverInsideActiveArea) { return; } Vector2 radius = (Vector2)size * 0.5f; Vector2 offset = new Vector2(0.5f, 0.5f) - radius; // Adjust to receive nicer low-res shapes radius.X -= 0.1f; radius.Y -= 0.1f; env.ActiveOrigin = topLeft; env.ActiveArea.ResizeClear(size.X, size.Y); for (int y = 0; y < size.Y; y++) { for (int x = 0; x < size.X; x++) { Vector2 relative = new Vector2(x, y) + offset; env.ActiveArea[x, y] = ((relative.X * relative.X) / (radius.X * radius.X)) + ((relative.Y * relative.Y) / (radius.Y * radius.Y)) <= 1.0f; } } env.ActiveAreaOutlines.Clear(); env.SubmitActiveAreaChanges(true); }
public override void UpdatePreview() { ITilemapToolEnvironment env = this.Environment; Point2 topLeft = new Point2( Math.Min(env.ActionBeginTile.X, env.HoveredTile.X), Math.Min(env.ActionBeginTile.Y, env.HoveredTile.Y)); Point2 size = new Point2( 1 + Math.Abs(env.ActionBeginTile.X - env.HoveredTile.X), 1 + Math.Abs(env.ActionBeginTile.Y - env.HoveredTile.Y)); // Don't update the rect when still using the same boundary size bool hoverInsideActiveArea = (env.ActiveOrigin == topLeft && env.ActiveArea.Width == size.X && env.ActiveArea.Height == size.Y); if (hoverInsideActiveArea) { return; } env.ActiveOrigin = topLeft; env.ActiveArea.ResizeClear(size.X, size.Y); env.ActiveArea.Fill(true, 0, 0, size.X, size.Y); // Manually define outlines in the trivial rect case Tileset tileset = env.ActiveTilemap != null ? env.ActiveTilemap.Tileset.Res : null; Vector2 tileSize = tileset != null ? tileset.TileSize : Tileset.DefaultTileSize; env.ActiveAreaOutlines.Clear(); env.ActiveAreaOutlines.Add(new Vector2[] { new Vector2(0, 0), new Vector2(tileSize.X * size.X, 0), new Vector2(tileSize.X * size.X, tileSize.Y * size.Y), new Vector2(0, tileSize.Y * size.Y), new Vector2(0, 0) // Close the loop }); env.SubmitActiveAreaChanges(true); }
public override void UpdateAction() { base.UpdateAction(); ITilemapToolEnvironment env = this.Environment; Grid <bool> drawArea; Point2 drawPos; // Since the cursor might move faster than one tile per update, we'll need // to expand the previewed actived area along its line of movement. if (Math.Abs(this.lastHoveredTile.X - env.HoveredTile.X) > 1 || Math.Abs(this.lastHoveredTile.Y - env.HoveredTile.Y) > 1) { Grid <bool> activeBrush = env.ActiveArea; Point2 brushOffset = new Point2( env.ActiveOrigin.X - env.HoveredTile.X, env.ActiveOrigin.Y - env.HoveredTile.Y); // We'll be using a temporary draw buffer to accumulate a mask for our line-filled // drawing operation. this.drawAreaBuffer.ResizeClear( activeBrush.Width + MathF.Abs(env.HoveredTile.X - this.lastHoveredTile.X), activeBrush.Height + MathF.Abs(env.HoveredTile.Y - this.lastHoveredTile.Y)); drawArea = this.drawAreaBuffer; drawPos = new Point2( Math.Min(this.lastHoveredTile.X, env.HoveredTile.X) + brushOffset.X, Math.Min(this.lastHoveredTile.Y, env.HoveredTile.Y) + brushOffset.Y); // Determine the vector of movement Vector2 tileMoveDelta = (Vector2)env.HoveredTile - (Vector2)lastHoveredTile; Vector2 tileMoveDir = tileMoveDelta.Normalized; Vector2 tileMoveNormal = tileMoveDir.PerpendicularRight; // Project the shape onto the perpendicular axis to that vector, so // we can determine brush line width. float minPosInMoveShape = 0.0f; float maxPosInMoveShape = 0.0f; for (int y = 0; y < activeBrush.Height; y++) { for (int x = 0; x < activeBrush.Width; x++) { if (activeBrush[x, y]) { Vector2 relativePos = new Vector2(x, y) + brushOffset; float projectedPos = Vector2.Dot(tileMoveNormal, relativePos); minPosInMoveShape = MathF.Min(minPosInMoveShape, projectedPos - 0.5f); maxPosInMoveShape = MathF.Max(maxPosInMoveShape, projectedPos + 0.5f); } } } // Fill all the tiles that are within the "movement line" for (int y = 0; y < this.drawAreaBuffer.Height; y++) { for (int x = 0; x < this.drawAreaBuffer.Width; x++) { Vector2 relativePos = new Vector2(x, y) + drawPos - this.lastHoveredTile; float projectedWidthPos = Vector2.Dot(tileMoveNormal, relativePos); if (projectedWidthPos < minPosInMoveShape) { continue; } if (projectedWidthPos > maxPosInMoveShape) { continue; } float projectedLengthPos = Vector2.Dot(tileMoveDir, relativePos); if (projectedLengthPos < 0.0f) { continue; } if (projectedLengthPos > tileMoveDelta.Length) { continue; } this.drawAreaBuffer[x, y] = true; } } // Insert the brush at the start of the line, i.e. the last position activeBrush.CopyTo( this.drawAreaBuffer, this.lastHoveredTile.X - drawPos.X + brushOffset.X, this.lastHoveredTile.Y - drawPos.Y + brushOffset.Y); // Insert the brush at the end of the line, i.e. the current position activeBrush.CopyTo( this.drawAreaBuffer, env.ActiveOrigin.X - drawPos.X, env.ActiveOrigin.Y - drawPos.Y); } // Otherwise, we can just draw exactly our movement brush else { drawArea = env.ActiveArea; drawPos = env.ActiveOrigin; } // Perform a tile editing operation using the drawin area and position we calculated env.PerformEditTiles( EditTilemapActionType.DrawTile, env.ActiveTilemap, drawPos, drawArea, env.TileDrawSource, new Point2( drawPos.X - env.ActionBeginTile.X, drawPos.Y - env.ActionBeginTile.Y)); this.lastHoveredTile = env.HoveredTile; }