v1.2 : Face extruding tool + reset hotkey

This commit is contained in:
Klemek
2018-11-04 15:08:46 +01:00
parent e2a5fc101c
commit 22748f17e9
12 changed files with 205 additions and 58 deletions
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>fr.klemek</groupId> <groupId>fr.klemek</groupId>
<artifactId>mapping</artifactId> <artifactId>mapping</artifactId>
<version>1.1.1</version> <version>1.2</version>
<repositories> <repositories>
<repository> <repository>
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 94 KiB

@@ -44,10 +44,14 @@ public class KeyEventListener implements KeyListener {
break; break;
case KeyEvent.VK_1: case KeyEvent.VK_1:
case KeyEvent.VK_NUMPAD1: case KeyEvent.VK_NUMPAD1:
this.mp.setShowGrid(!this.mp.isShowGrid()); this.mp.changeShowGrid();
break; break;
case KeyEvent.VK_2: case KeyEvent.VK_2:
case KeyEvent.VK_NUMPAD2: case KeyEvent.VK_NUMPAD2:
this.mp.changeShowFaces();
break;
case KeyEvent.VK_3:
case KeyEvent.VK_NUMPAD3:
this.mp.getMap().randomize(); this.mp.getMap().randomize();
break; break;
case KeyEvent.VK_PAGE_UP: case KeyEvent.VK_PAGE_UP:
@@ -93,6 +97,12 @@ public class KeyEventListener implements KeyListener {
case KeyEvent.VK_SHIFT: case KeyEvent.VK_SHIFT:
this.mp.setShiftDown(true); this.mp.setShiftDown(true);
break; break;
case KeyEvent.VK_SPACE:
this.mp.changeTool();
break;
case KeyEvent.VK_DELETE:
this.mp.deleteSelected();
break;
default: default:
break; break;
} }
+95 -32
View File
@@ -1,6 +1,8 @@
package fr.klemek.mapping; package fr.klemek.mapping;
import java.awt.*; import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.*; import javax.swing.*;
@@ -11,6 +13,10 @@ class MainPanel extends JPanel {
private float ratio = DEFAULT_RATIO; private float ratio = DEFAULT_RATIO;
private transient Map map; private transient Map map;
private transient ToolChangeListener toolChangeListener;
private transient Tool tool = Tool.NODE_EXTRUDER;
private int x0; private int x0;
private int y0; private int y0;
private float xstep; private float xstep;
@@ -22,11 +28,13 @@ class MainPanel extends JPanel {
private int[][] ys; private int[][] ys;
private boolean showGrid; private boolean showGrid;
private boolean showFaces = true;
private boolean shiftDown; private boolean shiftDown;
private float angle; private float angle;
MainPanel(Map map) { MainPanel(Map map, ToolChangeListener toolChangeListener) {
this.map = map; this.map = map;
this.toolChangeListener = toolChangeListener;
new MouseListener(this); new MouseListener(this);
} }
@@ -42,6 +50,8 @@ class MainPanel extends JPanel {
if (this.showGrid) if (this.showGrid)
this.drawGrid(g2); this.drawGrid(g2);
this.drawMap(g2); this.drawMap(g2);
if (this.showFaces)
this.drawFaces(g2);
} }
private void computeNodes() { private void computeNodes() {
@@ -95,8 +105,6 @@ class MainPanel extends JPanel {
} }
private void drawMap(Graphics2D g2) { private void drawMap(Graphics2D g2) {
for (int x = 0; x < this.map.size(); x++) { for (int x = 0; x < this.map.size(); x++) {
for (int y = 0; y < this.map.size(); y++) { for (int y = 0; y < this.map.size(); y++) {
this.drawLine(g2, x - 1, y, x, y); this.drawLine(g2, x - 1, y, x, y);
@@ -122,47 +130,98 @@ class MainPanel extends JPanel {
y1 >= 0 && y1 < this.map.size() && y1 >= 0 && y1 < this.map.size() &&
x2 >= 0 && x2 < this.map.size() && x2 >= 0 && x2 < this.map.size() &&
y2 >= 0 && y2 < 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(isSelectedLine(x1, y1, x2, y2) ? Color.RED : Color.BLACK);
g2.setColor(Color.RED);
} else {
g2.setColor(Color.BLACK);
}
g2.drawLine(this.xs[x1][y1], this.ys[x1][y1], this.xs[x2][y2], this.ys[x2][y2]); 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) { void computeMouseMoved(Point position) {
sx = -1; sx = -1;
sy = -1; sy = -1;
if (MainPanel.this.xs != null) { if (this.xs == null)
for (int x = 0; x < MainPanel.this.map.size(); x++) return;
for (int y = 0; y < MainPanel.this.map.size(); y++) int mx = -1;
if (position.distance(MainPanel.this.xs[x][y], MainPanel.this.ys[x][y]) < 6) { int my = -1;
sx = x; double min = 20;
sy = y; double d;
return; 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) { void computeMouseWheel(int amount, boolean controlDown, boolean shiftDown) {
if (sx >= 0 && sy >= 0) { if (sx < 0 || sy < 0)
if (shiftDown) { return;
for (int dx = -1; dx < 2; dx++) if (shiftDown) {
for (int dy = -1; dy < 2; dy++) for (int dx = -1; dx < 2; dx++)
changeNode(amount, controlDown, sx + dx, sy + dy); for (int dy = -1; dy < 2; dy++)
} else editMap(amount, controlDown, sx + dx, sy + dy, this.tool == Tool.NODE_EXTRUDER);
changeNode(amount, controlDown, sx, sy); } 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() if (x >= 0 && x < this.map.size()
&& y >= 0 && y < this.map.size()) && y >= 0 && y < this.map.size())
this.map.set(x, y, MainPanel.this.map.get(x, y) this.map.set(x, y, this.map.get(x, y, node)
+ amount * (controlDown ? -1f : -.1f)); + amount * (controlDown ? -1f : -.1f), node);
} }
void changeTool() {
ArrayList<Tool> 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() { float getRatio() {
return ratio; return ratio;
@@ -172,12 +231,12 @@ class MainPanel extends JPanel {
this.ratio = ratio; this.ratio = ratio;
} }
boolean isShowGrid() { void changeShowGrid() {
return showGrid; this.showGrid = !showGrid;
} }
void setShowGrid(boolean showGrid) { void changeShowFaces() {
this.showGrid = showGrid; this.showFaces = !showFaces;
} }
float getAngle() { float getAngle() {
@@ -195,4 +254,8 @@ class MainPanel extends JPanel {
void setShiftDown(boolean shiftDown) { void setShiftDown(boolean shiftDown) {
this.shiftDown = shiftDown; this.shiftDown = shiftDown;
} }
Tool getTool() {
return tool;
}
} }
@@ -9,7 +9,7 @@ import javax.swing.*;
class MainWindow extends JFrame { class MainWindow extends JFrame {
static final String FILE_NAME = "mapping.csv"; 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 int DEFAULT_SIZE = 17;
private static final String INFO_TEXT = "" + private static final String INFO_TEXT = "" +
"<html>" + "<html>" +
@@ -19,11 +19,14 @@ class MainWindow extends JFrame {
"[SHIFT+Mouse wheel] - Set surrounding heights<br>" + "[SHIFT+Mouse wheel] - Set surrounding heights<br>" +
"[BACKSPACE] - Erase everything<br>" + "[BACKSPACE] - Erase everything<br>" +
"[ARROWS] - Move view<br>" + "[ARROWS] - Move view<br>" +
"[PAGE UP/DOWN] - Change size<br/>" + "[PAGE UP/DOWN] - Change size<br>" +
"[CTRL+S] - Save current work<br>" + "[CTRL+S] - Save current work<br>" +
"[SPACE] - Change tool<br>" +
"[DELETE] - Reset node/face<br>" +
"[0] - Show/hide this info<br>" + "[0] - Show/hide this info<br>" +
"[1] - Show grid<br>" + "[1] - Show/hide grid<br>" +
"[2] - Add random<br>"; "[2] - Show/hide special faces<br>" +
"[3] - Add random<br>";
private transient MainPanel mp; private transient MainPanel mp;
private transient RefreshThread refresh; private transient RefreshThread refresh;
@@ -33,7 +36,7 @@ class MainWindow extends JFrame {
String saved = Utils.openFile(FILE_NAME); String saved = Utils.openFile(FILE_NAME);
if (saved != null) if (saved != null)
m = new Map(saved); 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.refresh = new RefreshThread(this.mp, 100);
this.initWindow(); this.initWindow();
} }
@@ -41,7 +44,7 @@ class MainWindow extends JFrame {
private void initWindow() { private void initWindow() {
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setResizable(true); this.setResizable(true);
this.setTitle("Mapping v" + VERSION); this.setTitle("Mapping v" + VERSION + " (" + this.mp.getTool().name + ")");
this.setSize(new Dimension(800, 600)); this.setSize(new Dimension(800, 600));
this.getContentPane().setLayout(new BorderLayout(0, 0)); this.getContentPane().setLayout(new BorderLayout(0, 0));
+59 -16
View File
@@ -5,16 +5,33 @@ import java.util.Random;
class Map { class Map {
private float[][] m; private float[][] m;
private float[][] m2;
Map(String input) { 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]; 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(";"); 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 { try {
this.m[x][y] = Float.parseFloat(lineSplit[y]); this.m[x][y] = Float.parseFloat(lineSplit[y]);
} catch (NumberFormatException ignored) { } 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) { Map(int size) {
this.m = new float[size][size]; this.m = new float[size][size];
this.m2 = new float[size - 1][size - 1];
} }
int size() { int size() {
@@ -29,37 +47,54 @@ class Map {
} }
float get(int x, int y) { 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 0f;
return this.m[x][y]; return primary ? this.m[x][y] : this.m2[x][y];
} }
void set(int x, int y, float value) { 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; return;
this.m[x][y] = value; if (primary)
this.m[x][y] = value;
else
this.m2[x][y] = value;
} }
void reset() { void reset() {
this.m = new float[this.m.length][this.m.length]; 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) { void changeSize(int newSize) {
if (newSize > 1) { if (newSize < 2)
float[][] m2 = new float[newSize][newSize]; return;
for (int x = 0; x < newSize; x++) float[][] tm = new float[newSize][newSize];
for (int y = 0; y < newSize; y++) float[][] tm2 = new float[newSize - 1][newSize - 1];
if (x < this.m.length && y < this.m.length) for (int x = 0; x < newSize; x++)
m2[x][y] = this.m[x][y]; for (int y = 0; y < newSize; y++) {
this.m = m2; 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() { void randomize() {
Random r = new Random(); Random r = new Random();
for (int x = 0; x < this.m.length; x++) for (int x = 0; x < this.m.length; x++)
for (int y = 0; y < this.m.length; y++) 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 @Override
@@ -72,6 +107,14 @@ class Map {
} }
output.append('\n'); 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(); return output.toString();
} }
} }
+12
View File
@@ -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;
}
}
@@ -0,0 +1,7 @@
package fr.klemek.mapping;
interface ToolChangeListener {
void toolChange(Tool tool);
}
+3 -2
View File
@@ -7,6 +7,7 @@ import java.io.BufferedWriter;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level;
final class Utils { final class Utils {
@@ -23,7 +24,7 @@ final class Utils {
bw.write(content); bw.write(content);
return true; return true;
} catch (IOException ex) { } catch (IOException ex) {
Logger.log(ex); Logger.log(Level.WARNING, ex);
return false; return false;
} }
} }
@@ -38,7 +39,7 @@ final class Utils {
} }
return output.toString(); return output.toString();
} catch (IOException ex) { } catch (IOException ex) {
Logger.log(ex); Logger.log(Level.WARNING, ex);
return null; return null;
} }
} }
@@ -11,40 +11,48 @@ public class MapTest {
public void testToString() { public void testToString() {
Map m = new Map(15); Map m = new Map(15);
m.randomize(); m.randomize();
m.set(0, 0, 5f, false);
assertEquals(15, m.size()); assertEquals(15, m.size());
Map m2 = new Map(m.toString()); Map m2 = new Map(m.toString());
assertEquals(m.size(), m2.size()); assertEquals(m.size(), m2.size());
for (int x = 0; x < m.size(); x++) for (int x = 0; x < m.size(); x++)
for (int y = 0; y < m.size(); y++) for (int y = 0; y < m.size(); y++)
assertEquals(m.get(x, y), m2.get(x, y), 0.001f); 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 @Test
public void testReset() { public void testReset() {
Map m = new Map(15); Map m = new Map(15);
m.randomize(); m.randomize();
m.set(0, 0, 5f, false);
assertNotEquals(0, m.get(0, 0), 0.001f); assertNotEquals(0, m.get(0, 0), 0.001f);
m.reset(); m.reset();
assertEquals(0, m.get(0, 0), 0.001f); assertEquals(0, m.get(0, 0), 0.001f);
assertEquals(0, m.get(0, 0, false), 0.001f);
} }
@Test @Test
public void testChangeSize() { public void testChangeSize() {
Map m = new Map(15); Map m = new Map(15);
m.randomize(); m.randomize();
m.set(0, 0, 5f, false);
float value = m.get(0, 0); float value = m.get(0, 0);
assertEquals(15, m.size()); assertEquals(15, m.size());
m.changeSize(18); m.changeSize(18);
assertEquals(18, m.size()); assertEquals(18, m.size());
assertEquals(value, m.get(0, 0), 0.001f); assertEquals(value, m.get(0, 0), 0.001f);
assertEquals(0, m.get(17, 17), 0.001f); assertEquals(0, m.get(17, 17), 0.001f);
assertEquals(5f, m.get(0, 0, false), 0.001f);
} }
@Test @Test
public void testRandomize() { public void testRandomize() {
Map m = new Map(15); Map m = new Map(15);
assertEquals(0, m.get(0, 0), 0.001f); assertEquals(0, m.get(0, 0), 0.001f);
m.set(0, 0, 5f, false);
m.randomize(); m.randomize();
assertNotEquals(0, m.get(0, 0), 0.001f); assertNotEquals(0, m.get(0, 0), 0.001f);
assertEquals(5f, m.get(0, 0, false), 0.001f);
} }
} }