v1.2 : Face extruding tool + reset hotkey
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>fr.klemek</groupId>
|
||||
<artifactId>mapping</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<version>1.2</version>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
|
||||
BIN
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;
|
||||
}
|
||||
|
||||
@@ -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<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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user