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
|
@Override
|
||||||
public ToolResult apply()
|
protected void applyArea(ToolEffectIfc eff)
|
||||||
{
|
{
|
||||||
Rectangle b = getBounds();
|
Rectangle b = getBounds();
|
||||||
ToolEffect eff = new ToolEffect(city, b.x, b.y);
|
|
||||||
|
|
||||||
// scan selection area for rubble, forest, etc...
|
// scan selection area for rubble, forest, etc...
|
||||||
for (int y = 0; y < b.height; y++) {
|
for (int y = 0; y < b.height; y++) {
|
||||||
|
@ -23,7 +22,7 @@ class Bulldozer extends ToolStroke
|
||||||
int tile = eff.getTile(x, y);
|
int tile = eff.getTile(x, y);
|
||||||
if (isDozeable(tile) && !isZoneCenter(tile)) {
|
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++) {
|
for (int x = 0; x < b.width; x++) {
|
||||||
|
|
||||||
if (isZoneCenter(eff.getTile(x,y))) {
|
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)
|
void dozeZone(ToolEffectIfc eff)
|
||||||
|
|
|
@ -11,11 +11,8 @@ class RoadLikeTool extends ToolStroke
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ToolResult apply()
|
protected void applyArea(ToolEffectIfc eff)
|
||||||
{
|
{
|
||||||
Rectangle b = getBounds();
|
|
||||||
ToolEffect eff = new ToolEffect(city, b.x, b.y);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!applyForward(eff)) {
|
if (!applyForward(eff)) {
|
||||||
break;
|
break;
|
||||||
|
@ -24,8 +21,6 @@ class RoadLikeTool extends ToolStroke
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return eff.apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean applyBackward(ToolEffectIfc eff)
|
boolean applyBackward(ToolEffectIfc eff)
|
||||||
|
@ -35,7 +30,7 @@ class RoadLikeTool extends ToolStroke
|
||||||
Rectangle b = getBounds();
|
Rectangle b = getBounds();
|
||||||
for (int i = b.height - 1; i >= 0; i--) {
|
for (int i = b.height - 1; i >= 0; i--) {
|
||||||
for (int j = b.width - 1; j >= 0; j--) {
|
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);
|
anyChange = anyChange || applySingle(tte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +44,7 @@ class RoadLikeTool extends ToolStroke
|
||||||
Rectangle b = getBounds();
|
Rectangle b = getBounds();
|
||||||
for (int i = 0; i < b.height; i++) {
|
for (int i = 0; i < b.height; i++) {
|
||||||
for (int j = 0; j < b.width; j++) {
|
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);
|
anyChange = anyChange || applySingle(tte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,11 @@ class ToolEffect implements ToolEffectIfc
|
||||||
final int originX;
|
final int originX;
|
||||||
final int originY;
|
final int originY;
|
||||||
|
|
||||||
|
ToolEffect(Micropolis city)
|
||||||
|
{
|
||||||
|
this(city, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
ToolEffect(Micropolis city, int xpos, int ypos)
|
ToolEffect(Micropolis city, int xpos, int ypos)
|
||||||
{
|
{
|
||||||
this.city = city;
|
this.city = city;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package micropolisj.engine;
|
package micropolisj.engine;
|
||||||
|
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import static micropolisj.engine.TileConstants.*;
|
import static micropolisj.engine.TileConstants.*;
|
||||||
|
|
||||||
|
@ -28,8 +29,7 @@ public class ToolPreview implements ToolEffectIfc
|
||||||
|
|
||||||
ToolPreview()
|
ToolPreview()
|
||||||
{
|
{
|
||||||
this.tiles = new short[1][1];
|
this.tiles = new short[0][0];
|
||||||
this.tiles[0][0] = CLEAR;
|
|
||||||
this.sounds = new ArrayList<SoundInfo>();
|
this.sounds = new ArrayList<SoundInfo>();
|
||||||
this.toolResult = ToolResult.NONE;
|
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()
|
int getWidth()
|
||||||
{
|
{
|
||||||
return tiles[0].length;
|
return tiles.length != 0 ? tiles[0].length : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getHeight()
|
int getHeight()
|
||||||
|
@ -58,13 +68,22 @@ public class ToolPreview implements ToolEffectIfc
|
||||||
boolean inRange(int dx, int dy)
|
boolean inRange(int dx, int dy)
|
||||||
{
|
{
|
||||||
return offsetY+dy >= 0 &&
|
return offsetY+dy >= 0 &&
|
||||||
offsetY+dy < tiles.length &&
|
offsetY+dy < getHeight() &&
|
||||||
offsetX+dx >= 0 &&
|
offsetX+dx >= 0 &&
|
||||||
offsetX+dx < tiles[0].length;
|
offsetX+dx < getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
void expandTo(int dx, int dy)
|
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++) {
|
for (int i = 0; i < tiles.length; i++) {
|
||||||
short[] A = tiles[i];
|
short[] A = tiles[i];
|
||||||
if (offsetX+dx >= A.length) {
|
if (offsetX+dx >= A.length) {
|
||||||
|
@ -89,9 +108,10 @@ public class ToolPreview implements ToolEffectIfc
|
||||||
offsetX += addl;
|
offsetX += addl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int width = tiles[0].length;
|
||||||
if (offsetY+dy >= tiles.length) {
|
if (offsetY+dy >= tiles.length) {
|
||||||
int newLen = offsetY+dy+1;
|
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);
|
System.arraycopy(tiles, 0, newTiles, 0, tiles.length);
|
||||||
for (int i = tiles.length; i < newLen; i++) {
|
for (int i = tiles.length; i < newLen; i++) {
|
||||||
Arrays.fill(newTiles[i], CLEAR);
|
Arrays.fill(newTiles[i], CLEAR);
|
||||||
|
@ -101,7 +121,7 @@ public class ToolPreview implements ToolEffectIfc
|
||||||
else if (offsetY+dy < 0) {
|
else if (offsetY+dy < 0) {
|
||||||
int addl = -(offsetY+dy);
|
int addl = -(offsetY+dy);
|
||||||
int newLen = tiles.length + addl;
|
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);
|
System.arraycopy(tiles, 0, newTiles, addl, tiles.length);
|
||||||
for (int i = 0; i < addl; i++) {
|
for (int i = 0; i < addl; i++) {
|
||||||
Arrays.fill(newTiles[i], CLEAR);
|
Arrays.fill(newTiles[i], CLEAR);
|
||||||
|
|
|
@ -30,18 +30,29 @@ public class ToolStroke
|
||||||
this.ydest = ypos;
|
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();
|
Rectangle r = getBounds();
|
||||||
ToolEffect eff = new ToolEffect(city, r.x, r.y);
|
|
||||||
|
|
||||||
for (int i = 0; i < r.height; i += tool.getHeight()) {
|
for (int i = 0; i < r.height; i += tool.getHeight()) {
|
||||||
for (int j = 0; j < r.width; j += tool.getWidth()) {
|
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)
|
boolean apply1(ToolEffectIfc eff)
|
||||||
|
|
|
@ -934,6 +934,7 @@ public class MainWindow extends JFrame
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.toolStroke = currentTool.beginStroke(engine, x, y);
|
this.toolStroke = currentTool.beginStroke(engine, x, y);
|
||||||
|
previewTool();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastX = x;
|
this.lastX = x;
|
||||||
|
@ -943,6 +944,8 @@ public class MainWindow extends JFrame
|
||||||
private void onToolUp(MouseEvent ev)
|
private void onToolUp(MouseEvent ev)
|
||||||
{
|
{
|
||||||
if (toolStroke != null) {
|
if (toolStroke != null) {
|
||||||
|
drawingArea.setToolPreview(null);
|
||||||
|
|
||||||
CityLocation loc = toolStroke.getLocation();
|
CityLocation loc = toolStroke.getLocation();
|
||||||
ToolResult tr = toolStroke.apply();
|
ToolResult tr = toolStroke.apply();
|
||||||
showToolResult(loc, tr);
|
showToolResult(loc, tr);
|
||||||
|
@ -952,6 +955,20 @@ public class MainWindow extends JFrame
|
||||||
onToolHover(ev);
|
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)
|
private void onToolDrag(MouseEvent ev)
|
||||||
{
|
{
|
||||||
if (currentTool == null)
|
if (currentTool == null)
|
||||||
|
@ -966,10 +983,7 @@ public class MainWindow extends JFrame
|
||||||
|
|
||||||
if (toolStroke != null) {
|
if (toolStroke != null) {
|
||||||
toolStroke.dragTo(x, y);
|
toolStroke.dragTo(x, y);
|
||||||
drawingArea.setToolCursor(
|
previewTool();
|
||||||
toolStroke.getBounds(),
|
|
||||||
currentTool
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (currentTool == MicropolisTool.QUERY) {
|
else if (currentTool == MicropolisTool.QUERY) {
|
||||||
doQueryTool(x, y);
|
doQueryTool(x, y);
|
||||||
|
|
|
@ -163,16 +163,23 @@ public class MicropolisDrawingArea extends JComponent
|
||||||
for (int x = minX; x < maxX; x++)
|
for (int x = minX; x < maxX; x++)
|
||||||
{
|
{
|
||||||
int cell = m.getTile(x,y);
|
int cell = m.getTile(x,y);
|
||||||
int tile = (cell & LOMASK) % tileImages.length;
|
|
||||||
if (blinkUnpoweredZones &&
|
if (blinkUnpoweredZones &&
|
||||||
(cell & ZONEBIT) != 0 &&
|
(cell & ZONEBIT) != 0 &&
|
||||||
(cell & PWRBIT) == 0)
|
(cell & PWRBIT) == 0)
|
||||||
{
|
{
|
||||||
unpoweredZones.add(new Point(x,y));
|
unpoweredZones.add(new Point(x,y));
|
||||||
if (blink)
|
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],
|
gr.drawImage(tileImages[tile],
|
||||||
x*TILE_WIDTH + (shakeStep != 0 ? getShakeModifier(y) : 0),
|
x*TILE_WIDTH + (shakeStep != 0 ? getShakeModifier(y) : 0),
|
||||||
y*TILE_HEIGHT,
|
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
|
//implements Scrollable
|
||||||
public Dimension getPreferredScrollableViewportSize()
|
public Dimension getPreferredScrollableViewportSize()
|
||||||
{
|
{
|
||||||
|
|
Reference in a new issue