From 52794b9c25e8ae86e5ed490b92769bb3be317301 Mon Sep 17 00:00:00 2001 From: "jason@long.name" Date: Thu, 16 May 2013 23:45:35 +0000 Subject: [PATCH] toolstroke: show the tool's effect as a preview when mouse is down git-svn-id: https://micropolis.googlecode.com/svn/trunk/micropolis-java@645 d9718cc8-9f43-0410-858b-315f434eb58c --- src/micropolisj/engine/Bulldozer.java | 9 ++--- src/micropolisj/engine/RoadLikeTool.java | 11 ++---- src/micropolisj/engine/ToolEffect.java | 5 +++ src/micropolisj/engine/ToolPreview.java | 34 +++++++++++++---- src/micropolisj/engine/ToolStroke.java | 21 +++++++--- src/micropolisj/gui/MainWindow.java | 22 +++++++++-- .../gui/MicropolisDrawingArea.java | 38 ++++++++++++++++++- 7 files changed, 108 insertions(+), 32 deletions(-) diff --git a/src/micropolisj/engine/Bulldozer.java b/src/micropolisj/engine/Bulldozer.java index 83eb613..0648905 100644 --- a/src/micropolisj/engine/Bulldozer.java +++ b/src/micropolisj/engine/Bulldozer.java @@ -11,10 +11,9 @@ class Bulldozer extends ToolStroke } @Override - public ToolResult apply() + protected void applyArea(ToolEffectIfc eff) { Rectangle b = getBounds(); - ToolEffect eff = new ToolEffect(city, b.x, b.y); // scan selection area for rubble, forest, etc... for (int y = 0; y < b.height; y++) { @@ -23,7 +22,7 @@ class Bulldozer extends ToolStroke int tile = eff.getTile(x, y); if (isDozeable(tile) && !isZoneCenter(tile)) { - dozeField(new TranslatedToolEffect(eff, x, y)); + dozeField(new TranslatedToolEffect(eff, b.x+x, b.y+y)); } } @@ -34,12 +33,10 @@ class Bulldozer extends ToolStroke for (int x = 0; x < b.width; x++) { if (isZoneCenter(eff.getTile(x,y))) { - dozeZone(new TranslatedToolEffect(eff, x, y)); + dozeZone(new TranslatedToolEffect(eff, b.x+x, b.y+y)); } } } - - return eff.apply(); } void dozeZone(ToolEffectIfc eff) diff --git a/src/micropolisj/engine/RoadLikeTool.java b/src/micropolisj/engine/RoadLikeTool.java index a7fd27d..61f82f5 100644 --- a/src/micropolisj/engine/RoadLikeTool.java +++ b/src/micropolisj/engine/RoadLikeTool.java @@ -11,11 +11,8 @@ class RoadLikeTool extends ToolStroke } @Override - public ToolResult apply() + protected void applyArea(ToolEffectIfc eff) { - Rectangle b = getBounds(); - ToolEffect eff = new ToolEffect(city, b.x, b.y); - for (;;) { if (!applyForward(eff)) { break; @@ -24,8 +21,6 @@ class RoadLikeTool extends ToolStroke break; } } - - return eff.apply(); } boolean applyBackward(ToolEffectIfc eff) @@ -35,7 +30,7 @@ class RoadLikeTool extends ToolStroke Rectangle b = getBounds(); for (int i = b.height - 1; i >= 0; i--) { for (int j = b.width - 1; j >= 0; j--) { - TranslatedToolEffect tte = new TranslatedToolEffect(eff, j, i); + TranslatedToolEffect tte = new TranslatedToolEffect(eff, b.x+j, b.y+i); anyChange = anyChange || applySingle(tte); } } @@ -49,7 +44,7 @@ class RoadLikeTool extends ToolStroke Rectangle b = getBounds(); for (int i = 0; i < b.height; i++) { for (int j = 0; j < b.width; j++) { - TranslatedToolEffect tte = new TranslatedToolEffect(eff, j, i); + TranslatedToolEffect tte = new TranslatedToolEffect(eff, b.x+j, b.y+i); anyChange = anyChange || applySingle(tte); } } diff --git a/src/micropolisj/engine/ToolEffect.java b/src/micropolisj/engine/ToolEffect.java index 79dc2d6..738912b 100644 --- a/src/micropolisj/engine/ToolEffect.java +++ b/src/micropolisj/engine/ToolEffect.java @@ -9,6 +9,11 @@ class ToolEffect implements ToolEffectIfc final int originX; final int originY; + ToolEffect(Micropolis city) + { + this(city, 0, 0); + } + ToolEffect(Micropolis city, int xpos, int ypos) { this.city = city; diff --git a/src/micropolisj/engine/ToolPreview.java b/src/micropolisj/engine/ToolPreview.java index e44f210..208e2e0 100644 --- a/src/micropolisj/engine/ToolPreview.java +++ b/src/micropolisj/engine/ToolPreview.java @@ -1,5 +1,6 @@ package micropolisj.engine; +import java.awt.Rectangle; import java.util.*; import static micropolisj.engine.TileConstants.*; @@ -28,8 +29,7 @@ public class ToolPreview implements ToolEffectIfc ToolPreview() { - this.tiles = new short[1][1]; - this.tiles[0][0] = CLEAR; + this.tiles = new short[0][0]; this.sounds = new ArrayList(); this.toolResult = ToolResult.NONE; } @@ -45,9 +45,19 @@ public class ToolPreview implements ToolEffectIfc } } + public Rectangle getBounds() + { + return new Rectangle( + -offsetX, + -offsetY, + getWidth(), + getHeight() + ); + } + int getWidth() { - return tiles[0].length; + return tiles.length != 0 ? tiles[0].length : 0; } int getHeight() @@ -58,13 +68,22 @@ public class ToolPreview implements ToolEffectIfc boolean inRange(int dx, int dy) { return offsetY+dy >= 0 && - offsetY+dy < tiles.length && + offsetY+dy < getHeight() && offsetX+dx >= 0 && - offsetX+dx < tiles[0].length; + offsetX+dx < getWidth(); } void expandTo(int dx, int dy) { + if (tiles == null || tiles.length == 0) { + tiles = new short[1][1]; + tiles[0][0] = CLEAR; + offsetX = -dx; + offsetY = -dy; + return; + } + + // expand each existing row as needed for (int i = 0; i < tiles.length; i++) { short[] A = tiles[i]; if (offsetX+dx >= A.length) { @@ -89,9 +108,10 @@ public class ToolPreview implements ToolEffectIfc offsetX += addl; } + int width = tiles[0].length; if (offsetY+dy >= tiles.length) { int newLen = offsetY+dy+1; - short[][] newTiles = new short[newLen][tiles[0].length]; + short[][] newTiles = new short[newLen][width]; System.arraycopy(tiles, 0, newTiles, 0, tiles.length); for (int i = tiles.length; i < newLen; i++) { Arrays.fill(newTiles[i], CLEAR); @@ -101,7 +121,7 @@ public class ToolPreview implements ToolEffectIfc else if (offsetY+dy < 0) { int addl = -(offsetY+dy); int newLen = tiles.length + addl; - short[][] newTiles = new short[newLen][tiles[0].length]; + short[][] newTiles = new short[newLen][width]; System.arraycopy(tiles, 0, newTiles, addl, tiles.length); for (int i = 0; i < addl; i++) { Arrays.fill(newTiles[i], CLEAR); diff --git a/src/micropolisj/engine/ToolStroke.java b/src/micropolisj/engine/ToolStroke.java index fbd91f0..522ce0a 100644 --- a/src/micropolisj/engine/ToolStroke.java +++ b/src/micropolisj/engine/ToolStroke.java @@ -30,18 +30,29 @@ public class ToolStroke this.ydest = ypos; } - public ToolResult apply() + public final ToolPreview getPreview() + { + ToolEffect eff = new ToolEffect(city); + applyArea(eff); + return eff.preview; + } + + public final ToolResult apply() + { + ToolEffect eff = new ToolEffect(city); + applyArea(eff); + return eff.apply(); + } + + protected void applyArea(ToolEffectIfc eff) { Rectangle r = getBounds(); - ToolEffect eff = new ToolEffect(city, r.x, r.y); for (int i = 0; i < r.height; i += tool.getHeight()) { for (int j = 0; j < r.width; j += tool.getWidth()) { - apply1(new TranslatedToolEffect(eff, j, i)); + apply1(new TranslatedToolEffect(eff, r.x+j, r.y+i)); } } - - return eff.apply(); } boolean apply1(ToolEffectIfc eff) diff --git a/src/micropolisj/gui/MainWindow.java b/src/micropolisj/gui/MainWindow.java index b021906..8cf1b92 100644 --- a/src/micropolisj/gui/MainWindow.java +++ b/src/micropolisj/gui/MainWindow.java @@ -934,6 +934,7 @@ public class MainWindow extends JFrame } else { this.toolStroke = currentTool.beginStroke(engine, x, y); + previewTool(); } this.lastX = x; @@ -943,6 +944,8 @@ public class MainWindow extends JFrame private void onToolUp(MouseEvent ev) { if (toolStroke != null) { + drawingArea.setToolPreview(null); + CityLocation loc = toolStroke.getLocation(); ToolResult tr = toolStroke.apply(); showToolResult(loc, tr); @@ -952,6 +955,20 @@ public class MainWindow extends JFrame onToolHover(ev); } + void previewTool() + { + assert this.toolStroke != null; + assert this.currentTool != null; + + drawingArea.setToolCursor( + toolStroke.getBounds(), + currentTool + ); + drawingArea.setToolPreview( + toolStroke.getPreview() + ); + } + private void onToolDrag(MouseEvent ev) { if (currentTool == null) @@ -966,10 +983,7 @@ public class MainWindow extends JFrame if (toolStroke != null) { toolStroke.dragTo(x, y); - drawingArea.setToolCursor( - toolStroke.getBounds(), - currentTool - ); + previewTool(); } else if (currentTool == MicropolisTool.QUERY) { doQueryTool(x, y); diff --git a/src/micropolisj/gui/MicropolisDrawingArea.java b/src/micropolisj/gui/MicropolisDrawingArea.java index 09f7efd..715a5e1 100644 --- a/src/micropolisj/gui/MicropolisDrawingArea.java +++ b/src/micropolisj/gui/MicropolisDrawingArea.java @@ -163,16 +163,23 @@ public class MicropolisDrawingArea extends JComponent for (int x = minX; x < maxX; x++) { int cell = m.getTile(x,y); - int tile = (cell & LOMASK) % tileImages.length; if (blinkUnpoweredZones && (cell & ZONEBIT) != 0 && (cell & PWRBIT) == 0) { unpoweredZones.add(new Point(x,y)); if (blink) - tile = LIGHTNINGBOLT; + cell = LIGHTNINGBOLT; } + if (toolPreview != null) { + int c = toolPreview.getTile(x, y); + if (c != CLEAR) { + cell = c; + } + } + + int tile = (cell & LOMASK) % tileImages.length; gr.drawImage(tileImages[tile], x*TILE_WIDTH + (shakeStep != 0 ? getShakeModifier(y) : 0), y*TILE_HEIGHT, @@ -266,6 +273,33 @@ public class MicropolisDrawingArea extends JComponent } } + public void setToolPreview(ToolPreview newPreview) + { + if (toolPreview != null) { + Rectangle b = toolPreview.getBounds(); + Rectangle r = new Rectangle( + b.x*TILE_WIDTH, + b.y*TILE_HEIGHT, + b.width*TILE_WIDTH, + b.height*TILE_HEIGHT + ); + repaint(r); + } + + toolPreview = newPreview; + if (toolPreview != null) { + + Rectangle b = toolPreview.getBounds(); + Rectangle r = new Rectangle( + b.x*TILE_WIDTH, + b.y*TILE_HEIGHT, + b.width*TILE_WIDTH, + b.height*TILE_HEIGHT + ); + repaint(r); + } + } + //implements Scrollable public Dimension getPreferredScrollableViewportSize() {