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
This commit is contained in:
jason@long.name 2013-05-16 23:45:35 +00:00
parent d0a6bb2303
commit 52794b9c25
7 changed files with 108 additions and 32 deletions

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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<SoundInfo>();
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);

View file

@ -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)

View file

@ -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);

View file

@ -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()
{