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>
<artifactId>mapping</artifactId>
<version>1.1.1</version>
<version>1.2</version>
<repositories>
<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;
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;
}
+88 -25
View File
@@ -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;
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 (sx < 0 || sy < 0)
return;
if (shiftDown) {
for (int dx = -1; dx < 2; dx++)
for (int dy = -1; dy < 2; dy++)
changeNode(amount, controlDown, sx + dx, sy + dy);
editMap(amount, controlDown, sx + dx, sy + dy, this.tool == Tool.NODE_EXTRUDER);
} else
changeNode(amount, controlDown, sx, sy);
}
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<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() {
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;
}
}
@@ -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 = "" +
"<html>" +
@@ -19,11 +19,14 @@ class MainWindow extends JFrame {
"[SHIFT+Mouse wheel] - Set surrounding heights<br>" +
"[BACKSPACE] - Erase everything<br>" +
"[ARROWS] - Move view<br>" +
"[PAGE UP/DOWN] - Change size<br/>" +
"[PAGE UP/DOWN] - Change size<br>" +
"[CTRL+S] - Save current work<br>" +
"[SPACE] - Change tool<br>" +
"[DELETE] - Reset node/face<br>" +
"[0] - Show/hide this info<br>" +
"[1] - Show grid<br>" +
"[2] - Add random<br>";
"[1] - Show/hide grid<br>" +
"[2] - Show/hide special faces<br>" +
"[3] - Add random<br>";
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));
+55 -12
View File
@@ -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;
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];
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++)
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;
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();
}
}
+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.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;
}
}
@@ -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);
}
}