diff --git a/download/mapping-1.1.1.jar b/download/mapping-1.1.1.jar
deleted file mode 100644
index 4349c05..0000000
Binary files a/download/mapping-1.1.1.jar and /dev/null differ
diff --git a/download/mapping-1.2.jar b/download/mapping-1.2.jar
new file mode 100644
index 0000000..12a8602
Binary files /dev/null and b/download/mapping-1.2.jar differ
diff --git a/pom.xml b/pom.xml
index 681e503..07a8cd6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
fr.klemek
mapping
- 1.1.1
+ 1.2
diff --git a/preview.png b/preview.png
index 67f8b4e..d1b2a8f 100644
Binary files a/preview.png and b/preview.png differ
diff --git a/src/main/java/fr/klemek/mapping/KeyEventListener.java b/src/main/java/fr/klemek/mapping/KeyEventListener.java
index 828b5c8..451bd2d 100644
--- a/src/main/java/fr/klemek/mapping/KeyEventListener.java
+++ b/src/main/java/fr/klemek/mapping/KeyEventListener.java
@@ -44,10 +44,14 @@ public class KeyEventListener implements KeyListener {
break;
case KeyEvent.VK_1:
case KeyEvent.VK_NUMPAD1:
- this.mp.setShowGrid(!this.mp.isShowGrid());
+ this.mp.changeShowGrid();
break;
case KeyEvent.VK_2:
case KeyEvent.VK_NUMPAD2:
+ this.mp.changeShowFaces();
+ break;
+ case KeyEvent.VK_3:
+ case KeyEvent.VK_NUMPAD3:
this.mp.getMap().randomize();
break;
case KeyEvent.VK_PAGE_UP:
@@ -93,6 +97,12 @@ public class KeyEventListener implements KeyListener {
case KeyEvent.VK_SHIFT:
this.mp.setShiftDown(true);
break;
+ case KeyEvent.VK_SPACE:
+ this.mp.changeTool();
+ break;
+ case KeyEvent.VK_DELETE:
+ this.mp.deleteSelected();
+ break;
default:
break;
}
diff --git a/src/main/java/fr/klemek/mapping/MainPanel.java b/src/main/java/fr/klemek/mapping/MainPanel.java
index b5fcce5..55aff2e 100644
--- a/src/main/java/fr/klemek/mapping/MainPanel.java
+++ b/src/main/java/fr/klemek/mapping/MainPanel.java
@@ -1,6 +1,8 @@
package fr.klemek.mapping;
import java.awt.*;
+import java.util.ArrayList;
+import java.util.Arrays;
import javax.swing.*;
@@ -11,6 +13,10 @@ class MainPanel extends JPanel {
private float ratio = DEFAULT_RATIO;
private transient Map map;
+ private transient ToolChangeListener toolChangeListener;
+
+ private transient Tool tool = Tool.NODE_EXTRUDER;
+
private int x0;
private int y0;
private float xstep;
@@ -22,11 +28,13 @@ class MainPanel extends JPanel {
private int[][] ys;
private boolean showGrid;
+ private boolean showFaces = true;
private boolean shiftDown;
private float angle;
- MainPanel(Map map) {
+ MainPanel(Map map, ToolChangeListener toolChangeListener) {
this.map = map;
+ this.toolChangeListener = toolChangeListener;
new MouseListener(this);
}
@@ -42,6 +50,8 @@ class MainPanel extends JPanel {
if (this.showGrid)
this.drawGrid(g2);
this.drawMap(g2);
+ if (this.showFaces)
+ this.drawFaces(g2);
}
private void computeNodes() {
@@ -95,8 +105,6 @@ class MainPanel extends JPanel {
}
private void drawMap(Graphics2D g2) {
-
-
for (int x = 0; x < this.map.size(); x++) {
for (int y = 0; y < this.map.size(); y++) {
this.drawLine(g2, x - 1, y, x, y);
@@ -122,47 +130,98 @@ class MainPanel extends JPanel {
y1 >= 0 && y1 < this.map.size() &&
x2 >= 0 && x2 < this.map.size() &&
y2 >= 0 && y2 < this.map.size()) {
- if (Utils.dist2(x1, y1, sx, sy) < (this.shiftDown ? 2 : 1) || Utils.dist2(x2, y2, sx, sy) < (this.shiftDown ? 2 : 1)) {
- g2.setColor(Color.RED);
- } else {
- g2.setColor(Color.BLACK);
- }
+ g2.setColor(isSelectedLine(x1, y1, x2, y2) ? Color.RED : Color.BLACK);
g2.drawLine(this.xs[x1][y1], this.ys[x1][y1], this.xs[x2][y2], this.ys[x2][y2]);
}
}
+ private boolean isSelectedLine(int x1, int y1, int x2, int y2) {
+ return this.tool == Tool.NODE_EXTRUDER &&
+ (Utils.dist2(x1, y1, sx, sy) < (this.shiftDown ? 2 : 1) ||
+ Utils.dist2(x2, y2, sx, sy) < (this.shiftDown ? 2 : 1));
+ }
+
+ private void drawFaces(Graphics2D g2) {
+ for (int x = 0; x < this.map.size() - 1; x++)
+ for (int y = 0; y < this.map.size() - 1; y++)
+ drawFace(g2, x, y);
+ }
+
+ private void drawFace(Graphics2D g2, int x, int y) {
+ int diffY = Math.round(this.map.get(x, y, false) * this.ystep);
+ boolean selected = this.tool == Tool.FACE_EXTRUDER && Utils.dist2(x, y, sx, sy) < (this.shiftDown ? 3 : 1);
+ if (diffY == 0 && !selected)
+ return;
+ g2.setColor(selected ? Color.RED : Color.BLUE);
+ for (int dx = 0; dx <= 1; dx++)
+ for (int dy = 0; dy <= 1; dy++)
+ g2.drawLine(this.xs[x + dx][y + dy], this.ys[x + dx][y + dy], this.xs[x + dx][y + dy], this.ys[x + dx][y + dy] - diffY);
+ Polygon face = getFace(x, y);
+ face.translate(0, -diffY);
+ g2.drawPolygon(face);
+ }
+
void computeMouseMoved(Point position) {
sx = -1;
sy = -1;
- if (MainPanel.this.xs != null) {
- for (int x = 0; x < MainPanel.this.map.size(); x++)
- for (int y = 0; y < MainPanel.this.map.size(); y++)
- if (position.distance(MainPanel.this.xs[x][y], MainPanel.this.ys[x][y]) < 6) {
- sx = x;
- sy = y;
- return;
- }
- }
+ if (this.xs == null)
+ return;
+ int mx = -1;
+ int my = -1;
+ double min = 20;
+ double d;
+ for (int x = 0; x < this.map.size(); x++)
+ for (int y = 0; y < this.map.size(); y++)
+ if (this.tool == Tool.FACE_EXTRUDER && x < this.map.size() - 1 && y < this.map.size() - 1 && this.getFace(x, y).contains(position)) {
+ this.sx = x;
+ this.sy = y;
+ return;
+ } else if (this.tool == Tool.NODE_EXTRUDER && (d = position.distance(this.xs[x][y], this.ys[x][y])) < min) {
+ mx = x;
+ my = y;
+ min = d;
+ }
+ this.sx = mx;
+ this.sy = my;
+ }
+
+ private Polygon getFace(int x, int y) {
+ return new Polygon(new int[]{this.xs[x][y], this.xs[x + 1][y], this.xs[x + 1][y + 1], this.xs[x][y + 1]},
+ new int[]{this.ys[x][y], this.ys[x + 1][y], this.ys[x + 1][y + 1], this.ys[x][y + 1]}, 4);
}
void computeMouseWheel(int amount, boolean controlDown, boolean shiftDown) {
- if (sx >= 0 && sy >= 0) {
- if (shiftDown) {
- for (int dx = -1; dx < 2; dx++)
- for (int dy = -1; dy < 2; dy++)
- changeNode(amount, controlDown, sx + dx, sy + dy);
- } else
- changeNode(amount, controlDown, sx, sy);
- }
+ if (sx < 0 || sy < 0)
+ return;
+ if (shiftDown) {
+ for (int dx = -1; dx < 2; dx++)
+ for (int dy = -1; dy < 2; dy++)
+ editMap(amount, controlDown, sx + dx, sy + dy, this.tool == Tool.NODE_EXTRUDER);
+ } else
+ editMap(amount, controlDown, sx, sy, this.tool == Tool.NODE_EXTRUDER);
}
- private void changeNode(int amount, boolean controlDown, int x, int y) {
+ private void editMap(int amount, boolean controlDown, int x, int y, boolean node) {
if (x >= 0 && x < this.map.size()
&& y >= 0 && y < this.map.size())
- this.map.set(x, y, MainPanel.this.map.get(x, y)
- + amount * (controlDown ? -1f : -.1f));
+ this.map.set(x, y, this.map.get(x, y, node)
+ + amount * (controlDown ? -1f : -.1f), node);
}
+ void changeTool() {
+ ArrayList tools = new ArrayList<>(Arrays.asList(Tool.values()));
+ this.tool = tools.get((tools.indexOf(this.tool) + 1) % tools.size());
+ if (this.tool == Tool.FACE_EXTRUDER)
+ this.showFaces = true;
+ if (toolChangeListener != null)
+ toolChangeListener.toolChange(this.tool);
+ }
+
+ void deleteSelected() {
+ if (sx < 0 || sy < 0)
+ return;
+ this.map.set(sx, sy, 0f, this.tool == Tool.NODE_EXTRUDER);
+ }
float getRatio() {
return ratio;
@@ -172,12 +231,12 @@ class MainPanel extends JPanel {
this.ratio = ratio;
}
- boolean isShowGrid() {
- return showGrid;
+ void changeShowGrid() {
+ this.showGrid = !showGrid;
}
- void setShowGrid(boolean showGrid) {
- this.showGrid = showGrid;
+ void changeShowFaces() {
+ this.showFaces = !showFaces;
}
float getAngle() {
@@ -195,4 +254,8 @@ class MainPanel extends JPanel {
void setShiftDown(boolean shiftDown) {
this.shiftDown = shiftDown;
}
+
+ Tool getTool() {
+ return tool;
+ }
}
diff --git a/src/main/java/fr/klemek/mapping/MainWindow.java b/src/main/java/fr/klemek/mapping/MainWindow.java
index b661767..3da6093 100644
--- a/src/main/java/fr/klemek/mapping/MainWindow.java
+++ b/src/main/java/fr/klemek/mapping/MainWindow.java
@@ -9,7 +9,7 @@ import javax.swing.*;
class MainWindow extends JFrame {
static final String FILE_NAME = "mapping.csv";
- private static final String VERSION = "1.1";
+ private static final String VERSION = "1.2";
private static final int DEFAULT_SIZE = 17;
private static final String INFO_TEXT = "" +
"" +
@@ -19,11 +19,14 @@ class MainWindow extends JFrame {
"[SHIFT+Mouse wheel] - Set surrounding heights
" +
"[BACKSPACE] - Erase everything
" +
"[ARROWS] - Move view
" +
- "[PAGE UP/DOWN] - Change size
" +
+ "[PAGE UP/DOWN] - Change size
" +
"[CTRL+S] - Save current work
" +
+ "[SPACE] - Change tool
" +
+ "[DELETE] - Reset node/face
" +
"[0] - Show/hide this info
" +
- "[1] - Show grid
" +
- "[2] - Add random
";
+ "[1] - Show/hide grid
" +
+ "[2] - Show/hide special faces
" +
+ "[3] - Add random
";
private transient MainPanel mp;
private transient RefreshThread refresh;
@@ -33,7 +36,7 @@ class MainWindow extends JFrame {
String saved = Utils.openFile(FILE_NAME);
if (saved != null)
m = new Map(saved);
- this.mp = new MainPanel(m);
+ this.mp = new MainPanel(m, tool -> this.setTitle("Mapping v" + VERSION + " (" + tool.name + ")"));
this.refresh = new RefreshThread(this.mp, 100);
this.initWindow();
}
@@ -41,7 +44,7 @@ class MainWindow extends JFrame {
private void initWindow() {
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setResizable(true);
- this.setTitle("Mapping v" + VERSION);
+ this.setTitle("Mapping v" + VERSION + " (" + this.mp.getTool().name + ")");
this.setSize(new Dimension(800, 600));
this.getContentPane().setLayout(new BorderLayout(0, 0));
diff --git a/src/main/java/fr/klemek/mapping/Map.java b/src/main/java/fr/klemek/mapping/Map.java
index 24481e4..d2ecd1f 100644
--- a/src/main/java/fr/klemek/mapping/Map.java
+++ b/src/main/java/fr/klemek/mapping/Map.java
@@ -5,16 +5,33 @@ import java.util.Random;
class Map {
private float[][] m;
+ private float[][] m2;
Map(String input) {
- String[] lines = input.split("\n");
+ String[] parts = input.split("\n\n");
+ String[] lines = parts[0].split("\n");
this.m = new float[lines.length][lines.length];
- for (int x = 0; x < lines.length; x++) {
+ for (int x = 0; x < this.m.length; x++) {
String[] lineSplit = lines[x].split(";");
- for (int y = 0; y < Math.min(lines.length, lineSplit.length); y++) {
+ for (int y = 0; y < Math.min(this.m.length, lineSplit.length); y++) {
try {
this.m[x][y] = Float.parseFloat(lineSplit[y]);
} catch (NumberFormatException ignored) {
+ //ignored
+ }
+ }
+ }
+ this.m2 = new float[lines.length - 1][lines.length - 1];
+ if (parts.length > 1) {
+ lines = parts[1].split("\n");
+ for (int x = 0; x < Math.min(this.m2.length, lines.length); x++) {
+ String[] lineSplit = lines[x].split(";");
+ for (int y = 0; y < Math.min(this.m2.length, lineSplit.length); y++) {
+ try {
+ this.m2[x][y] = Float.parseFloat(lineSplit[y]);
+ } catch (NumberFormatException ignored) {
+ //ignored
+ }
}
}
}
@@ -22,6 +39,7 @@ class Map {
Map(int size) {
this.m = new float[size][size];
+ this.m2 = new float[size - 1][size - 1];
}
int size() {
@@ -29,37 +47,54 @@ class Map {
}
float get(int x, int y) {
- if (x < 0 || y < 0 || x >= this.m.length || y >= this.m.length)
+ return this.get(x, y, true);
+ }
+
+ float get(int x, int y, boolean primary) {
+ if (x < 0 || y < 0 || x >= this.m.length - (primary ? 0 : 1) || y >= this.m.length - (primary ? 0 : 1))
return 0f;
- return this.m[x][y];
+ return primary ? this.m[x][y] : this.m2[x][y];
}
void set(int x, int y, float value) {
- if (x < 0 || y < 0 || x >= this.m.length || y >= this.m.length)
+ this.set(x, y, value, true);
+ }
+
+ void set(int x, int y, float value, boolean primary) {
+ if (x < 0 || y < 0 || x >= this.m.length - (primary ? 0 : 1) || y >= this.m.length - (primary ? 0 : 1))
return;
- this.m[x][y] = value;
+ if (primary)
+ this.m[x][y] = value;
+ else
+ this.m2[x][y] = value;
}
void reset() {
this.m = new float[this.m.length][this.m.length];
+ this.m2 = new float[this.m.length - 1][this.m.length - 1];
}
void changeSize(int newSize) {
- if (newSize > 1) {
- float[][] m2 = new float[newSize][newSize];
- for (int x = 0; x < newSize; x++)
- for (int y = 0; y < newSize; y++)
- if (x < this.m.length && y < this.m.length)
- m2[x][y] = this.m[x][y];
- this.m = m2;
- }
+ if (newSize < 2)
+ return;
+ float[][] tm = new float[newSize][newSize];
+ float[][] tm2 = new float[newSize - 1][newSize - 1];
+ for (int x = 0; x < newSize; x++)
+ for (int y = 0; y < newSize; y++) {
+ if (x < this.m.length && y < this.m.length)
+ tm[x][y] = this.m[x][y];
+ if (x < this.m2.length && y < this.m2.length)
+ tm2[x][y] = this.m2[x][y];
+ }
+ this.m = tm;
+ this.m2 = tm2;
}
void randomize() {
Random r = new Random();
for (int x = 0; x < this.m.length; x++)
for (int y = 0; y < this.m.length; y++)
- this.m[x][y] += r.nextFloat() - 0.5f;
+ this.m[x][y] += r.nextInt(11) * .1f - 0.5f;
}
@Override
@@ -72,6 +107,14 @@ class Map {
}
output.append('\n');
}
+ output.append('\n');
+ for (int x = 0; x < this.size() - 1; x++) {
+ for (int y = 0; y < this.size() - 1; y++) {
+ output.append(this.m2[x][y]);
+ output.append(';');
+ }
+ output.append('\n');
+ }
return output.toString();
}
}
diff --git a/src/main/java/fr/klemek/mapping/Tool.java b/src/main/java/fr/klemek/mapping/Tool.java
new file mode 100644
index 0000000..0a8b387
--- /dev/null
+++ b/src/main/java/fr/klemek/mapping/Tool.java
@@ -0,0 +1,12 @@
+package fr.klemek.mapping;
+
+public enum Tool {
+ NODE_EXTRUDER("Node mode"),
+ FACE_EXTRUDER("Face mode");
+
+ String name;
+
+ Tool(String name) {
+ this.name = name;
+ }
+}
diff --git a/src/main/java/fr/klemek/mapping/ToolChangeListener.java b/src/main/java/fr/klemek/mapping/ToolChangeListener.java
new file mode 100644
index 0000000..5ec9db4
--- /dev/null
+++ b/src/main/java/fr/klemek/mapping/ToolChangeListener.java
@@ -0,0 +1,7 @@
+package fr.klemek.mapping;
+
+interface ToolChangeListener {
+
+ void toolChange(Tool tool);
+
+}
diff --git a/src/main/java/fr/klemek/mapping/Utils.java b/src/main/java/fr/klemek/mapping/Utils.java
index 33a87ca..c54a969 100644
--- a/src/main/java/fr/klemek/mapping/Utils.java
+++ b/src/main/java/fr/klemek/mapping/Utils.java
@@ -7,6 +7,7 @@ import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.logging.Level;
final class Utils {
@@ -23,7 +24,7 @@ final class Utils {
bw.write(content);
return true;
} catch (IOException ex) {
- Logger.log(ex);
+ Logger.log(Level.WARNING, ex);
return false;
}
}
@@ -38,7 +39,7 @@ final class Utils {
}
return output.toString();
} catch (IOException ex) {
- Logger.log(ex);
+ Logger.log(Level.WARNING, ex);
return null;
}
}
diff --git a/src/test/java/fr/klemek/mapping/MapTest.java b/src/test/java/fr/klemek/mapping/MapTest.java
index 92d3937..8c74d0b 100644
--- a/src/test/java/fr/klemek/mapping/MapTest.java
+++ b/src/test/java/fr/klemek/mapping/MapTest.java
@@ -11,40 +11,48 @@ public class MapTest {
public void testToString() {
Map m = new Map(15);
m.randomize();
+ m.set(0, 0, 5f, false);
assertEquals(15, m.size());
Map m2 = new Map(m.toString());
assertEquals(m.size(), m2.size());
for (int x = 0; x < m.size(); x++)
for (int y = 0; y < m.size(); y++)
assertEquals(m.get(x, y), m2.get(x, y), 0.001f);
+ assertEquals(m.get(0, 0, false), m2.get(0, 0, false), 0.001f);
}
@Test
public void testReset() {
Map m = new Map(15);
m.randomize();
+ m.set(0, 0, 5f, false);
assertNotEquals(0, m.get(0, 0), 0.001f);
m.reset();
assertEquals(0, m.get(0, 0), 0.001f);
+ assertEquals(0, m.get(0, 0, false), 0.001f);
}
@Test
public void testChangeSize() {
Map m = new Map(15);
m.randomize();
+ m.set(0, 0, 5f, false);
float value = m.get(0, 0);
assertEquals(15, m.size());
m.changeSize(18);
assertEquals(18, m.size());
assertEquals(value, m.get(0, 0), 0.001f);
assertEquals(0, m.get(17, 17), 0.001f);
+ assertEquals(5f, m.get(0, 0, false), 0.001f);
}
@Test
public void testRandomize() {
Map m = new Map(15);
assertEquals(0, m.get(0, 0), 0.001f);
+ m.set(0, 0, 5f, false);
m.randomize();
assertNotEquals(0, m.get(0, 0), 0.001f);
+ assertEquals(5f, m.get(0, 0, false), 0.001f);
}
}
\ No newline at end of file