diff --git a/assets/icons/dark/toolBrush.png b/assets/icons/dark/toolBrush.png
deleted file mode 100644
index 402389a..0000000
Binary files a/assets/icons/dark/toolBrush.png and /dev/null differ
diff --git a/assets/icons/dark/toolDropper.png b/assets/icons/dark/toolDropper.png
new file mode 100644
index 0000000..137d68a
Binary files /dev/null and b/assets/icons/dark/toolDropper.png differ
diff --git a/assets/icons/dark/toolEllipse.png b/assets/icons/dark/toolEllipse.png
new file mode 100644
index 0000000..5880fa8
Binary files /dev/null and b/assets/icons/dark/toolEllipse.png differ
diff --git a/assets/icons/dark/toolEraser.png b/assets/icons/dark/toolEraser.png
index 2bbaf55..bb0cb85 100644
Binary files a/assets/icons/dark/toolEraser.png and b/assets/icons/dark/toolEraser.png differ
diff --git a/assets/icons/dark/toolRect.png b/assets/icons/dark/toolRect.png
new file mode 100644
index 0000000..4ceaeba
Binary files /dev/null and b/assets/icons/dark/toolRect.png differ
diff --git a/assets/icons/light/toolBrush.png b/assets/icons/light/toolBrush.png
deleted file mode 100644
index 2d5dd4e..0000000
Binary files a/assets/icons/light/toolBrush.png and /dev/null differ
diff --git a/assets/main/toolbar.xml b/assets/main/toolbar.xml
index 9f501e1..f565a37 100644
--- a/assets/main/toolbar.xml
+++ b/assets/main/toolbar.xml
@@ -6,10 +6,12 @@
-
-
-
-
+
+
+
+
+
+
diff --git a/src/components/Toolbar.hx b/src/components/Toolbar.hx
index a77eb63..4f91ab6 100644
--- a/src/components/Toolbar.hx
+++ b/src/components/Toolbar.hx
@@ -1,6 +1,31 @@
-package components;
-
-import haxe.ui.containers.VBox;
-
-@:build(haxe.ui.ComponentBuilder.build('../../assets/main/toolbar.xml'))
-class Toolbar extends VBox {}
\ No newline at end of file
+package components;
+
+import haxe.ui.events.UIEvent;
+import haxe.ui.events.MouseEvent;
+import haxe.ui.containers.VBox;
+
+using StringTools;
+
+@:build(haxe.ui.ComponentBuilder.build('../../assets/main/toolbar.xml'))
+class Toolbar extends VBox {
+ public function new() {
+ super();
+
+ toolPencil.registerEvent(MouseEvent.CLICK, onToolSelected);
+ toolFill.registerEvent(MouseEvent.CLICK, onToolSelected);
+ toolEraser.registerEvent(MouseEvent.CLICK, onToolSelected);
+ toolRect.registerEvent(MouseEvent.CLICK, onToolSelected);
+ toolEllipse.registerEvent(MouseEvent.CLICK, onToolSelected);
+ toolDropper.registerEvent(MouseEvent.CLICK, onToolSelected);
+ }
+
+ public function onToolSelected(event: MouseEvent) {
+ var tool = event.target.id;
+ if (tool.contains('tool')) {
+ var toolName = tool.replace('tool', '').toLowerCase();
+ var toolEvent = new UIEvent(MapEvent.TOOL_SELECT, false, toolName);
+ trace(toolEvent.data);
+ dispatch(toolEvent);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/tilemap/Tilemap.hx b/src/components/tilemap/Tilemap.hx
index af10791..fd5a406 100644
--- a/src/components/tilemap/Tilemap.hx
+++ b/src/components/tilemap/Tilemap.hx
@@ -25,7 +25,9 @@ class Tilemap extends ScrollView {
public var overlay: GridQuad;
public var activeLayer(default, set): TilemapLayerData;
public var selectedTilesetCells(default, set): Array;
-
+ public var activeTool: MapEditorTool;
+
+ var isShapeFillActive: Bool = false;
var selectedTilesetTiles: Array;
var tilesetRect: Rect;
var viewport: Visual;
@@ -89,6 +91,7 @@ class Tilemap extends ScrollView {
overlay.depth = 90;
overlay.grid.onGridClick(null, handleGridClick);
overlay.grid.onOnGridSelection(null, handleGridPointerMove);
+ overlay.onPointerUp(null, handlePointerUp);
viewport.add(overlay);
}
@@ -155,7 +158,7 @@ class Tilemap extends ScrollView {
}
public function onPointerMove(info: TouchInfo) {
- if (tileCursor == null) {
+ if (tileCursor == null || !tileCursor.visible) {
return;
};
var localCoords = new Point();
@@ -218,6 +221,59 @@ class Tilemap extends ScrollView {
updateLayerTiles(tiles);
}
+ function floodFillDraw(x: Float, y: Float, initialCell: Cell, replacementTile: TilemapTile) {
+ var stack: Array = [];
+
+ if (!withinTilemapBounds(x, y)) {
+ return;
+ }
+
+ var activeLayerTiles = getActiveLayerTiles();
+ var initialTile = activeLayerTiles[initialCell.frame];
+
+ if (initialTile == replacementTile) {
+ return;
+ }
+
+ stack.push(new Point(x, y));
+
+ while (stack.length > 0) {
+ var currentPoint = stack.pop();
+ x = currentPoint.x;
+ y = currentPoint.y;
+ var currentCellIndex = overlay.grid.getCellFrame(x, y);
+ var currentTile = activeLayerTiles[currentCellIndex];
+
+ if (currentTile != initialTile) continue;
+
+ activeLayerTiles[currentCellIndex] = replacementTile;
+
+ stack.push({ x: x + tileSize.width, y: y });
+ stack.push({ x: x - tileSize.width, y: y });
+ stack.push({ x: x, y: y + tileSize.height });
+ stack.push({ x: x, y: y - tileSize.height });
+ }
+ updateLayerTiles(activeLayerTiles);
+ }
+
+ function drawRectShapeFill(rect: Rect) {
+ var activeLayerTiles = getActiveLayerTiles();
+ var cols = Std.int(rect.width / tileSize.width) + 1;
+ var rows = Std.int(rect.height / tileSize.height) + 1;
+
+ for (i in 0...rows) {
+ for (j in 0...cols) {
+ var tileX: Float = rect.x + j * tileSize.width;
+ var tileY: Float = rect.y + i * tileSize.height;
+ var currentCellIndex = overlay.grid.getCellFrame(tileX, tileY);
+ var tilemapTile = selectedTilesetTiles[currentCellIndex];
+
+ activeLayerTiles[currentCellIndex] = tilemapTile;
+ updateLayerTiles(activeLayerTiles);
+ }
+ }
+ }
+
function withinTilemapBounds(x: Float, y: Float) {
return x >= 0 && x < tilemap.width && y >= 0 && y < tilemap.height;
}
@@ -228,16 +284,35 @@ class Tilemap extends ScrollView {
new Rect(x, y, tilesetRect.width, tilesetRect.height)
);
- if (buttonId == 0) {
- drawTile(cellsToEdit);
+ if (buttonId == 0) {
+ switch (activeTool) {
+ case MapEditorTool.Pencil:
+ drawTile(cellsToEdit);
+ case MapEditorTool.Eraser:
+ eraseTile(cellsToEdit);
+ case MapEditorTool.Fill:
+ var replacementTile = selectedTilesetTiles[0];
+ floodFillDraw(x, y, selectedTilesetCells[0], replacementTile);
+ case MapEditorTool.Rect:
+ isShapeFillActive = true;
+ overlay.grid.enableSelection = true;
+ tileCursor.visible = false;
+ case MapEditorTool.Elipse:
+ case MapEditorTool.Clone:
+ }
} else if (buttonId == 2) {
eraseTile(cellsToEdit);
}
}
- function handleGridPointerMove(cells: Array, _) {
- if (activeLayer != null && tilesetRect != null) {
- handleTilemapAction(cells[0].position.x, cells[0].position.y);
+ function handleGridPointerMove(cells: Array, __) {
+ // if (activeLayer != null && selectionRect != null) {
+ // handleTilemapAction(tiles[0].position.x, tiles[0].position.y);
+ // }
+ if (isShapeFillActive) {
+ var rect = overlay.grid.createRectFromCells(cells, tileSize);
+
+ drawRectShapeFill(rect);
}
}
@@ -250,6 +325,10 @@ class Tilemap extends ScrollView {
}
function handlePointerUp(info: TouchInfo) {
+ if (isShapeFillActive) {
+ isShapeFillActive = false;
+ tileCursor.visible = true;
+ }
if (info.buttonId == buttonId) {
buttonId = -1;
}
diff --git a/src/constants/MapEditorTool.hx b/src/constants/MapEditorTool.hx
new file mode 100644
index 0000000..189bff8
--- /dev/null
+++ b/src/constants/MapEditorTool.hx
@@ -0,0 +1,22 @@
+package constants;
+
+enum abstract MapEditorTool(String) from String to String {
+ var Pencil = 'pencil';
+ var Fill = 'fill';
+ var Rect = 'rect';
+ var Elipse = 'elipse';
+ var Eraser = 'eraser';
+ var Clone = 'clone';
+
+ static public function fromName(name: String): MapEditorTool {
+ switch (name) {
+ case 'pencil': return MapEditorTool.Pencil;
+ case Fill: return MapEditorTool.Fill;
+ case Rect: return MapEditorTool.Rect;
+ case Elipse: return MapEditorTool.Elipse;
+ case Eraser: return MapEditorTool.Eraser;
+ case Clone: return MapEditorTool.Clone;
+ case _: return MapEditorTool.Pencil;
+ }
+ }
+}
diff --git a/src/constants/MapEvent.hx b/src/constants/MapEvent.hx
index dc3173c..7d3e157 100644
--- a/src/constants/MapEvent.hx
+++ b/src/constants/MapEvent.hx
@@ -24,4 +24,7 @@ class MapEvent extends UIEvent {
/* Dispatched when the tilemap is zoomed' */
public static final MAP_ZOOM: EventType = EventType.name('mapZoom');
+
+ /* Dispatched when a tool is selected */
+ public static final TOOL_SELECT: EventType = EventType.name('toolChange');
}
\ No newline at end of file
diff --git a/src/locale/en_US/toolbar.properties b/src/locale/en_US/toolbar.properties
new file mode 100644
index 0000000..c39b439
--- /dev/null
+++ b/src/locale/en_US/toolbar.properties
@@ -0,0 +1,7 @@
+# Drawing Tools
+toolbar.toolPencil=Pencil
+toolbar.toolRect=Rect
+toolbar.toolFill=Fill
+toolbar.toolEllipse=Ellipse
+toolbar.toolDropper=Eye Dropper
+toolbar.toolEraser=Eraser
\ No newline at end of file
diff --git a/src/module.xml b/src/module.xml
index 6a9013b..2f8d019 100644
--- a/src/module.xml
+++ b/src/module.xml
@@ -14,6 +14,7 @@
+
diff --git a/src/styles/light/toolbar.css b/src/styles/light/toolbar.css
index 99ad29f..6e2cace 100644
--- a/src/styles/light/toolbar.css
+++ b/src/styles/light/toolbar.css
@@ -22,12 +22,18 @@
.toolbar #toolPencil {
icon: icon('toolPencil');
}
-.toolbar #toolBrush {
- icon: icon('toolBrush');
+.toolbar #toolRect {
+ icon: icon('toolRect');
+}
+.toolbar #toolEllipse {
+ icon: icon('toolEllipse');
}
.toolbar #toolFill {
icon: icon('toolFill');
}
+.toolbar #toolDropper {
+ icon: icon('toolDropper');
+}
.toolbar #toolEraser {
icon: icon('toolEraser');
}
diff --git a/src/views/MapEditor.hx b/src/views/MapEditor.hx
index acaab51..77e437a 100644
--- a/src/views/MapEditor.hx
+++ b/src/views/MapEditor.hx
@@ -26,6 +26,7 @@ class MapEditor extends VBox {
layerPanel.registerEvent(MapEvent.LAYER_RENAME, onLayerRename);
mapListPanel.registerEvent(MapEvent.MAP_SELECT, onActiveMapChanged);
tilePicker.registerEvent(MapEvent.TILESET_TILE_SELECTION, onTileSelection);
+ toolbar.registerEvent(MapEvent.TOOL_SELECT, onToolSelect);
}
public function menu(): Array {
@@ -143,6 +144,10 @@ class MapEditor extends VBox {
layerPanel.activeLayer.name = event.data;
}
+ function onToolSelect(event: UIEvent) {
+ tilemapView.activeTool = MapEditorTool.fromName(event.data);
+ }
+
public function update(dt: Float) {}
function emptyTilemapData(name: String) {
| | |