re-implemented moving of tiles
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>de.srsoftware</groupId>
|
<groupId>de.srsoftware</groupId>
|
||||||
<artifactId>web4rail</artifactId>
|
<artifactId>web4rail</artifactId>
|
||||||
<version>1.2.16</version>
|
<version>1.2.17</version>
|
||||||
<name>Web4Rail</name>
|
<name>Web4Rail</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<description>Java Model Railway Control</description>
|
<description>Java Model Railway Control</description>
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ svg circle{
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Shadow,
|
.Shadow{
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
.menu .list{
|
.menu .list{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,6 +397,10 @@ public abstract class BaseClass implements Constants{
|
|||||||
protected static String t(String txt, Object...fills) {
|
protected static String t(String txt, Object...fills) {
|
||||||
return Translation.get(Application.class, txt, fills);
|
return Translation.get(Application.class, txt, fills);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BaseClass unregister() {
|
||||||
|
return registry.remove(this.id());
|
||||||
|
}
|
||||||
|
|
||||||
protected Object update(HashMap<String, String> params) {
|
protected Object update(HashMap<String, String> params) {
|
||||||
LOG.debug("update: {}",params);
|
LOG.debug("update: {}",params);
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Stack;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@@ -63,6 +62,7 @@ import de.srsoftware.web4rail.tiles.SignalS;
|
|||||||
import de.srsoftware.web4rail.tiles.SignalW;
|
import de.srsoftware.web4rail.tiles.SignalW;
|
||||||
import de.srsoftware.web4rail.tiles.StraightH;
|
import de.srsoftware.web4rail.tiles.StraightH;
|
||||||
import de.srsoftware.web4rail.tiles.StraightV;
|
import de.srsoftware.web4rail.tiles.StraightV;
|
||||||
|
import de.srsoftware.web4rail.tiles.StretchableTile;
|
||||||
import de.srsoftware.web4rail.tiles.TextDisplay;
|
import de.srsoftware.web4rail.tiles.TextDisplay;
|
||||||
import de.srsoftware.web4rail.tiles.Tile;
|
import de.srsoftware.web4rail.tiles.Tile;
|
||||||
import de.srsoftware.web4rail.tiles.Turnout.State;
|
import de.srsoftware.web4rail.tiles.Turnout.State;
|
||||||
@@ -238,9 +238,8 @@ public class Plan extends BaseClass{
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
//if (configJson != null) tile.configure(new JSONObject(configJson));
|
if (tile instanceof StretchableTile) ((StretchableTile)tile).placeShadows();
|
||||||
set(x, y, tile);
|
place(tile.position(x, y));
|
||||||
tile.parent(this);
|
|
||||||
return t("Added {}",tile.getClass().getSimpleName());
|
return t("Added {}",tile.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,13 +502,13 @@ public class Plan extends BaseClass{
|
|||||||
private String moveTile(String direction, Id tileId) throws NumberFormatException, IOException {
|
private String moveTile(String direction, Id tileId) throws NumberFormatException, IOException {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case "south":
|
case "south":
|
||||||
return moveTile(get(tileId,false),Direction.SOUTH);
|
return moveTile(get(tileId,true),Direction.SOUTH);
|
||||||
case "north":
|
case "north":
|
||||||
return moveTile(get(tileId,false),Direction.NORTH);
|
return moveTile(get(tileId,true),Direction.NORTH);
|
||||||
case "east":
|
case "east":
|
||||||
return moveTile(get(tileId,false),Direction.EAST);
|
return moveTile(get(tileId,true),Direction.EAST);
|
||||||
case "west":
|
case "west":
|
||||||
return moveTile(get(tileId,false),Direction.WEST);
|
return moveTile(get(tileId,true),Direction.WEST);
|
||||||
}
|
}
|
||||||
throw new InvalidParameterException(t("\"{}\" is not a known direction!"));
|
throw new InvalidParameterException(t("\"{}\" is not a known direction!"));
|
||||||
}
|
}
|
||||||
@@ -527,49 +526,27 @@ public class Plan extends BaseClass{
|
|||||||
LOG.debug("moveTile({},{},{})",direction,tile.x,tile.y);
|
LOG.debug("moveTile({},{},{})",direction,tile.x,tile.y);
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case EAST:
|
case EAST:
|
||||||
moved = moveTile(tile,+1,0);
|
moved = tile.move(+1,0);
|
||||||
break;
|
break;
|
||||||
case WEST:
|
case WEST:
|
||||||
moved = moveTile(tile,-1,0);
|
moved = tile.move(-1,0);
|
||||||
break;
|
break;
|
||||||
case NORTH:
|
case NORTH:
|
||||||
moved = moveTile(tile,0,-1);
|
moved = tile.move(0,-1);
|
||||||
break;
|
break;
|
||||||
case SOUTH:
|
case SOUTH:
|
||||||
moved = moveTile(tile,0,+1);
|
moved = tile.move(0,+1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t(moved ? "Tile(s) moved.":"No tile(s) moved.");
|
return t(moved ? "Tile(s) moved.":"No tile(s) moved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void drop(Tile tile) {
|
||||||
* processes move-tile instructions sent from the client (subroutine)
|
tile.unregister();
|
||||||
* @param tile
|
stream("remove "+tile.id());
|
||||||
* @param xstep
|
|
||||||
* @param ystep
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private boolean moveTile(Tile tile,int xstep,int ystep) throws IOException {
|
|
||||||
LOG.error("moveTile({} +{}/+{})",tile,xstep,ystep);
|
|
||||||
Stack<Tile> stack = new Stack<Tile>();
|
|
||||||
while (tile != null) {
|
|
||||||
LOG.debug("scheduling tile for movement: {}",tile);
|
|
||||||
stack.add(tile);
|
|
||||||
tile = get(Tile.id(tile.x+xstep, tile.y+ystep),false);
|
|
||||||
}
|
|
||||||
while (!stack.isEmpty()) {
|
|
||||||
tile = stack.pop();
|
|
||||||
if (!(tile instanceof Shadow)) {
|
|
||||||
LOG.debug("altering position of {}",tile);
|
|
||||||
tile.remove();
|
|
||||||
set(tile.x+xstep,tile.y+ystep,tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds a new tile to the plan on the client side
|
* adds a new tile to the plan on the client side
|
||||||
* @param tile
|
* @param tile
|
||||||
@@ -578,6 +555,8 @@ public class Plan extends BaseClass{
|
|||||||
*/
|
*/
|
||||||
public Tile place(Tile tile) {
|
public Tile place(Tile tile) {
|
||||||
try {
|
try {
|
||||||
|
tile.parent(this);
|
||||||
|
tile.register();
|
||||||
stream("place "+tile.tag(null));
|
stream("place "+tile.tag(null));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -659,22 +638,7 @@ public class Plan extends BaseClass{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void removeChild(BaseClass child) {
|
protected void removeChild(BaseClass child) {
|
||||||
if (child instanceof Tile) {
|
if (child instanceof Tile) drop((Tile) child);
|
||||||
Tile tile = (Tile) child;
|
|
||||||
stream("remove "+tile.id());
|
|
||||||
for (int i=1; i<tile.width(); i++) removeTile(tile.x+i, tile.y); // remove shadow tiles
|
|
||||||
for (int i=1; i<tile.height(); i++) removeTile(tile.x, tile.y+i); // remove shadow tiles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* removes a tile from the track layout (subroutine)
|
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
*/
|
|
||||||
private void removeTile(int x, int y) {
|
|
||||||
Tile tile = BaseClass.get(Tile.id(x, y));
|
|
||||||
if (isSet(tile)) tile.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -713,31 +677,6 @@ public class Plan extends BaseClass{
|
|||||||
.put(LENGTH_UNIT, lengthUnit);
|
.put(LENGTH_UNIT, lengthUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* adds a tile to the plan at a specific position
|
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
* @param tile
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void set(int x,int y,Tile tile) throws IOException {
|
|
||||||
if (isNull(tile)) return;
|
|
||||||
setIntern(x,y,tile);
|
|
||||||
for (int i=1; i<tile.width(); i++) set(x+i,y,new Shadow(tile,x+i,y));
|
|
||||||
for (int i=1; i<tile.height(); i++) set(x,y+i,new Shadow(tile,x,y+1));
|
|
||||||
place(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* adds a tile to the plan at a specific position (subroutine)
|
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
* @param tile
|
|
||||||
*/
|
|
||||||
private void setIntern(int x, int y, Tile tile) {
|
|
||||||
tile.position(x, y).register();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sensor(int addr, boolean active) {
|
public void sensor(int addr, boolean active) {
|
||||||
Contact contact = Contact.get(addr);
|
Contact contact = Contact.get(addr);
|
||||||
if (active && learningContact != null) {
|
if (active && learningContact != null) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class BlockH extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int width() {
|
public int width() {
|
||||||
return stretch;
|
return stretch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class BlockV extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int height() {
|
public int height() {
|
||||||
return stretch;
|
return stretch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ public class Shadow extends Tile{
|
|||||||
return super.connections(from);
|
return super.connections(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Shadow(Tile overlay, int x, int y) {
|
public Shadow(StretchableTile overlay, int x, int y) {
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
overlay.addShadow(this);
|
overlay.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile overlay() {
|
public Tile overlay() {
|
||||||
|
|||||||
@@ -35,6 +35,6 @@ public class StraightH extends StretchableTile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int width() {
|
public int width() {
|
||||||
return stretch;
|
return stretch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class StraightV extends StretchableTile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int height() {
|
public int height() {
|
||||||
return stretch;
|
return stretch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,17 +3,24 @@ package de.srsoftware.web4rail.tiles;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import de.srsoftware.tools.Tag;
|
import de.srsoftware.tools.Tag;
|
||||||
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
import de.srsoftware.web4rail.Window;
|
import de.srsoftware.web4rail.Window;
|
||||||
import de.srsoftware.web4rail.tags.Fieldset;
|
import de.srsoftware.web4rail.tags.Fieldset;
|
||||||
import de.srsoftware.web4rail.tags.Input;
|
import de.srsoftware.web4rail.tags.Input;
|
||||||
|
|
||||||
public abstract class StretchableTile extends Tile {
|
public abstract class StretchableTile extends Tile {
|
||||||
private static final String STRETCH_LENGTH = "stretch";
|
private static final String STRETCH_LENGTH = "stretch";
|
||||||
public int stretch = 1;
|
private int stretch = 1;
|
||||||
|
private Vector<Id> shadows = new Vector<Id>();
|
||||||
|
|
||||||
|
public void add(Shadow shadow) {
|
||||||
|
shadows.add(shadow.id());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject config() {
|
public JSONObject config() {
|
||||||
@@ -35,12 +42,57 @@ public abstract class StretchableTile extends Tile {
|
|||||||
return super.load(json);
|
return super.load(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean move(int dx, int dy) {
|
||||||
|
for (int destX=1; destX<width(); destX++) {
|
||||||
|
int destY = dy > 0 ? height() : dy;
|
||||||
|
Tile tileAtDest = plan.get(Tile.id(x+destX, y+destY), true);
|
||||||
|
if (isNull(tileAtDest) || tileAtDest == this) continue;
|
||||||
|
if (!tileAtDest.move(dx, dy)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int destY=1; destY<height(); destY++) {
|
||||||
|
int destX = dx > 0 ? width() : dx;
|
||||||
|
Tile tileAtDest = plan.get(Tile.id(x+destX, y+destY), true);
|
||||||
|
if (isNull(tileAtDest) || tileAtDest == this) continue;
|
||||||
|
if (!tileAtDest.move(dx, dy)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean moved = super.move(dx, dy);
|
||||||
|
if (moved) placeShadows();
|
||||||
|
return moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void placeShadows() {
|
||||||
|
removeShadows();
|
||||||
|
for (int dx=1; dx<width(); dx++) plan.place(new Shadow(this, x+dx, y));
|
||||||
|
for (int dy=1; dy<height(); dy++) plan.place(new Shadow(this, x, y+dy));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm) {
|
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm) {
|
||||||
formInputs.add(stretchType(),new Input(STRETCH_LENGTH, stretch).numeric().addTo(new Tag("span")).content(NBSP+t("Tile(s)")));
|
formInputs.add(stretchType(),new Input(STRETCH_LENGTH, stretch).numeric().addTo(new Tag("span")).content(NBSP+t("Tile(s)")));
|
||||||
return super.properties(preForm, formInputs, postForm);
|
return super.properties(preForm, formInputs, postForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseClass remove() {
|
||||||
|
super.remove();
|
||||||
|
removeShadows();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeShadows() {
|
||||||
|
while (!shadows.isEmpty()) {
|
||||||
|
Tile tile = BaseClass.get(shadows.remove(0));
|
||||||
|
if (tile instanceof Shadow) tile.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int stretch() {
|
||||||
|
return stretch;
|
||||||
|
}
|
||||||
|
|
||||||
private void stretch(String value) {
|
private void stretch(String value) {
|
||||||
try {
|
try {
|
||||||
stretch(Integer.parseInt(value));
|
stretch(Integer.parseInt(value));
|
||||||
@@ -49,10 +101,14 @@ public abstract class StretchableTile extends Tile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stretch(int len) {
|
public void stretch(int newStretch) {
|
||||||
this.stretch = Math.max(1, len);
|
newStretch = Math.max(1, newStretch);
|
||||||
|
if (newStretch != stretch) {
|
||||||
|
stretch = newStretch;
|
||||||
|
placeShadows();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract String stretchType();
|
protected abstract String stretchType();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -81,6 +81,6 @@ public class TextDisplay extends StretchableTile {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int width() {
|
public int width() {
|
||||||
return stretch;
|
return stretch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
|||||||
protected Direction oneWay = null;
|
protected Direction oneWay = null;
|
||||||
protected Route route = null;
|
protected Route route = null;
|
||||||
private TreeSet<Route> routes = new TreeSet<>();
|
private TreeSet<Route> routes = new TreeSet<>();
|
||||||
protected TreeSet<Shadow> shadows = new TreeSet<>();
|
|
||||||
protected Train train = null;
|
protected Train train = null;
|
||||||
public Integer x = null;
|
public Integer x = null;
|
||||||
public Integer y = null;
|
public Integer y = null;
|
||||||
@@ -65,10 +64,6 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
|||||||
this.routes.add(route);
|
this.routes.add(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addShadow(Shadow shadow) {
|
|
||||||
shadows.add(shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Vector<String> classes(){
|
protected Vector<String> classes(){
|
||||||
Vector<String> classes = new Vector<String>();
|
Vector<String> classes = new Vector<String>();
|
||||||
classes.add("tile");
|
classes.add("tile");
|
||||||
@@ -113,8 +108,9 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
|||||||
private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
|
private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
|
||||||
clazz = Tile.class.getName().replace(".Tile", "."+clazz);
|
clazz = Tile.class.getName().replace(".Tile", "."+clazz);
|
||||||
Tile tile = (Tile) Tile.class.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance();
|
Tile tile = (Tile) Tile.class.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance();
|
||||||
tile.load(json).parent(plan);
|
tile.load(json).register();
|
||||||
plan.set(tile.x, tile.y, tile);
|
if (tile instanceof StretchableTile) ((StretchableTile)tile).placeShadows();
|
||||||
|
plan.place(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFreeFor(Train newTrain) {
|
public boolean isFreeFor(Train newTrain) {
|
||||||
@@ -382,14 +378,12 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
|||||||
public BaseClass remove() {
|
public BaseClass remove() {
|
||||||
super.remove();
|
super.remove();
|
||||||
while (!routes.isEmpty()) routes.first().remove();
|
while (!routes.isEmpty()) routes.first().remove();
|
||||||
while (!shadows.isEmpty()) shadows.first().remove();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeChild(BaseClass child) {
|
public void removeChild(BaseClass child) {
|
||||||
routes.remove(child);
|
routes.remove(child);
|
||||||
if (child instanceof Shadow) shadows.remove(child);
|
|
||||||
if (child == train) train = null;
|
if (child == train) train = null;
|
||||||
if (child == route) route = null;
|
if (child == route) route = null;
|
||||||
plan.place(this);
|
plan.place(this);
|
||||||
@@ -421,4 +415,17 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
|||||||
public int width() {
|
public int width() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean move(int dx, int dy) {
|
||||||
|
int destX = x+(dx > 0 ? width() : dx);
|
||||||
|
int destY = y+(dy > 0 ? height() : dy);
|
||||||
|
if (destX < 0 || destY < 0) return false;
|
||||||
|
|
||||||
|
Tile tileAtDestination = plan.get(id(destX, destY),true);
|
||||||
|
if (isSet(tileAtDestination) && !tileAtDestination.move(dx, dy)) return false;
|
||||||
|
plan.drop(this);
|
||||||
|
position(x+dx, y+dy);
|
||||||
|
plan.place(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user