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:
parent
d0a6bb2303
commit
52794b9c25
7 changed files with 108 additions and 32 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
Reference in a new issue