diff --git a/chunky/src/java/se/llbit/chunky/ui/ChunkMap.java b/chunky/src/java/se/llbit/chunky/ui/ChunkMap.java
index 8ef9b3dd5c..53576579fa 100644
--- a/chunky/src/java/se/llbit/chunky/ui/ChunkMap.java
+++ b/chunky/src/java/se/llbit/chunky/ui/ChunkMap.java
@@ -172,11 +172,7 @@ public ChunkMap(WorldMapLoader loader, ChunkyFxController controller,
selectVisible.setGraphic(new ImageView(Icon.eye.fxImage()));
selectVisible.setOnAction(event -> {
- ChunkView chunkView = new ChunkView(view); // Make thread-local copy.
- if (controller.getChunky().sceneInitialized()) {
- controller.getChunky().getRenderController().getSceneProvider().withSceneProtected(
- scene -> selectVisibleChunks(chunkView, scene));
- }
+ selectCameraVisibleChunks();
});
MenuItem exportZip = new MenuItem("Export selected chunks…");
@@ -214,6 +210,8 @@ public ChunkMap(WorldMapLoader loader, ChunkyFxController controller,
loadSelection.setDisable(noChunksSelected);
exportZip.setDisable(noChunksSelected);
deleteChunks.setDisable(noChunksSelected);
+
+ controller.disableMapMenuItems(noChunksSelected);
});
}
@@ -425,6 +423,14 @@ public int getHeight() {
return mapView.getMapView().height;
}
+ public void selectCameraVisibleChunks() {
+ ChunkView chunkView = new ChunkView(view); // Make thread-local copy.
+ if (controller.getChunky().sceneInitialized()) {
+ controller.getChunky().getRenderController().getSceneProvider().withSceneProtected(
+ scene -> selectVisibleChunks(chunkView, scene));
+ }
+ }
+
public void onKeyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case CONTROL:
diff --git a/chunky/src/java/se/llbit/chunky/ui/RenderCanvasFx.java b/chunky/src/java/se/llbit/chunky/ui/RenderCanvasFx.java
index f56985f843..3974faf8d8 100644
--- a/chunky/src/java/se/llbit/chunky/ui/RenderCanvasFx.java
+++ b/chunky/src/java/se/llbit/chunky/ui/RenderCanvasFx.java
@@ -72,7 +72,7 @@ public class RenderCanvasFx extends ScrollPane implements Repaintable, SceneStat
private final AtomicBoolean painting = new AtomicBoolean(false);
private final Canvas canvas;
- private final Group guideGroup;
+ private final Group guideGroup = new Group();
private final StackPane canvasPane;
private final Label noChunksLabel;
private final RenderManager renderManager;
@@ -81,6 +81,22 @@ public class RenderCanvasFx extends ScrollPane implements Repaintable, SceneStat
private Vector2 target = new Vector2(0, 0);
private Tooltip tooltip = new Tooltip();
+ private CheckMenuItem showGuides = new CheckMenuItem("Show guides");
+ private Line hGuide1 = new Line();
+ private Line hGuide2 = new Line();
+ private Line vGuide1 = new Line();
+ private Line vGuide2 = new Line();
+
+ private RadioMenuItem percent25 = new RadioMenuItem(String.format("%d%%", 25));
+ private RadioMenuItem percent50 = new RadioMenuItem(String.format("%d%%", 50));
+ private RadioMenuItem percent75 = new RadioMenuItem(String.format("%d%%", 75));
+ private RadioMenuItem percent100 = new RadioMenuItem(String.format("%d%%", 100));
+ private RadioMenuItem percent150 = new RadioMenuItem(String.format("%d%%", 150));
+ private RadioMenuItem percent200 = new RadioMenuItem(String.format("%d%%", 200));
+ private RadioMenuItem percent300 = new RadioMenuItem(String.format("%d%%", 300));
+ private RadioMenuItem percent400 = new RadioMenuItem(String.format("%d%%", 400));
+ private RadioMenuItem fit = new RadioMenuItem("Fit to screen");
+
private boolean fitToScreen = PersistentSettings.getCanvasFitToScreen();
private RenderStatusListener renderListener;
@@ -110,11 +126,6 @@ public RenderCanvasFx(ChunkyFxController chunkyFxController,
noChunksLabel.setTextAlignment(TextAlignment.CENTER);
canvasPane.getChildren().add(noChunksLabel);
- guideGroup = new Group();
- Line hGuide1 = new Line();
- Line hGuide2 = new Line();
- Line vGuide1 = new Line();
- Line vGuide2 = new Line();
guideGroup.getChildren().addAll(hGuide1, hGuide2, vGuide1, vGuide2);
canvasPane.getChildren().add(guideGroup);
@@ -183,44 +194,84 @@ public RenderCanvasFx(ChunkyFxController chunkyFxController,
});
contextMenu.getItems().add(setTarget);
- CheckMenuItem showGuides = new CheckMenuItem("Show guides");
showGuides.setSelected(false);
showGuides.selectedProperty().addListener((observable, oldValue, newValue) -> {
- hGuide1.setVisible(newValue);
- hGuide2.setVisible(newValue);
- vGuide1.setVisible(newValue);
- vGuide2.setVisible(newValue);
+ changeShowGuides(newValue);
+ chunkyFxController.syncShowGuides(newValue);
});
contextMenu.getItems().add(showGuides);
Menu canvasScale = new Menu("Canvas scale");
ToggleGroup scaleGroup = new ToggleGroup();
- for (int percent : new int[] { 25, 50, 75, 100, 150, 200, 300, 400 }) {
- RadioMenuItem item = new RadioMenuItem(String.format("%d%%", percent));
- item.setToggleGroup(scaleGroup);
- item.setSelected(PersistentSettings.getCanvasScale() == percent && !fitToScreen);
- item.setOnAction(e -> {
- updateCanvasScale(percent / 100.0);
- PersistentSettings.setCanvasScale(percent);
- if (fitToScreen) {
- fitToScreen = false;
- PersistentSettings.setCanvasFitToScreen(false);
- }
- });
- canvasScale.getItems().add(item);
- }
- contextMenu.getItems().add(canvasScale);
+ percent25.setToggleGroup(scaleGroup);
+ percent50.setToggleGroup(scaleGroup);
+ percent75.setToggleGroup(scaleGroup);
+ percent100.setToggleGroup(scaleGroup);
+ percent150.setToggleGroup(scaleGroup);
+ percent200.setToggleGroup(scaleGroup);
+ percent300.setToggleGroup(scaleGroup);
+ percent400.setToggleGroup(scaleGroup);
+ fit.setToggleGroup(scaleGroup);
- RadioMenuItem fit = new RadioMenuItem("Fit to Screen");
+ percent25.setSelected(PersistentSettings.getCanvasScale() == 25 && !fitToScreen);
+ percent50.setSelected(PersistentSettings.getCanvasScale() == 50 && !fitToScreen);
+ percent75.setSelected(PersistentSettings.getCanvasScale() == 75 && !fitToScreen);
+ percent100.setSelected(PersistentSettings.getCanvasScale() == 100 && !fitToScreen);
+ percent150.setSelected(PersistentSettings.getCanvasScale() == 150 && !fitToScreen);
+ percent200.setSelected(PersistentSettings.getCanvasScale() == 200 && !fitToScreen);
+ percent300.setSelected(PersistentSettings.getCanvasScale() == 300 && !fitToScreen);
+ percent400.setSelected(PersistentSettings.getCanvasScale() == 400 && !fitToScreen);
fit.setSelected(fitToScreen);
- fit.setToggleGroup(scaleGroup);
+
+ percent25.setOnAction(e -> {
+ changeCanvasScale(25);
+ chunkyFxController.syncCanvasScale(25);
+ });
+ percent50.setOnAction(e -> {
+ changeCanvasScale(50);
+ chunkyFxController.syncCanvasScale(50);
+ });
+ percent75.setOnAction(e -> {
+ changeCanvasScale(75);
+ chunkyFxController.syncCanvasScale(75);
+ });
+ percent100.setOnAction(e -> {
+ changeCanvasScale(100);
+ chunkyFxController.syncCanvasScale(100);
+ });
+ percent150.setOnAction(e -> {
+ changeCanvasScale(150);
+ chunkyFxController.syncCanvasScale(150);
+ });
+ percent200.setOnAction(e -> {
+ changeCanvasScale(200);
+ chunkyFxController.syncCanvasScale(200);
+ });
+ percent300.setOnAction(e -> {
+ changeCanvasScale(300);
+ chunkyFxController.syncCanvasScale(300);
+ });
+ percent400.setOnAction(e -> {
+ changeCanvasScale(400);
+ chunkyFxController.syncCanvasScale(400);
+ });
fit.setOnAction(e -> {
- fitToScreen = true;
- PersistentSettings.setCanvasFitToScreen(true);
- updateCanvasFit();
+ changeFitToScreen();
+ chunkyFxController.syncFitToScreen();
});
+
+ canvasScale.getItems().add(percent25);
+ canvasScale.getItems().add(percent50);
+ canvasScale.getItems().add(percent75);
+ canvasScale.getItems().add(percent100);
+ canvasScale.getItems().add(percent150);
+ canvasScale.getItems().add(percent200);
+ canvasScale.getItems().add(percent300);
+ canvasScale.getItems().add(percent400);
canvasScale.getItems().add(fit);
+ contextMenu.getItems().add(canvasScale);
+
if (fitToScreen) {
updateCanvasFit();
} else {
@@ -341,6 +392,56 @@ public RenderCanvasFx(ChunkyFxController chunkyFxController,
});
}
+ public void changeShowGuides(boolean value) {
+ hGuide1.setVisible(value);
+ hGuide2.setVisible(value);
+ vGuide1.setVisible(value);
+ vGuide2.setVisible(value);
+ }
+
+ public void syncShowGuides(boolean value) {
+ showGuides.setSelected(value);
+ }
+
+ public void changeCanvasScale(int percent) {
+ updateCanvasScale(percent / 100.0);
+ PersistentSettings.setCanvasScale(percent);
+ if (fitToScreen) {
+ fitToScreen = false;
+ PersistentSettings.setCanvasFitToScreen(false);
+ }
+ }
+
+ public void syncCanvasScale(int percent) {
+ if (percent == 25) {
+ percent25.setSelected(true);
+ } else if (percent == 50) {
+ percent50.setSelected(true);
+ } else if (percent == 75) {
+ percent75.setSelected(true);
+ } else if (percent == 100) {
+ percent100.setSelected(true);
+ } else if (percent == 150) {
+ percent150.setSelected(true);
+ } else if (percent == 200) {
+ percent200.setSelected(true);
+ } else if (percent == 300) {
+ percent300.setSelected(true);
+ } else if (percent == 400) {
+ percent400.setSelected(true);
+ }
+ }
+
+ public void changeFitToScreen() {
+ fitToScreen = true;
+ PersistentSettings.setCanvasFitToScreen(true);
+ updateCanvasFit();
+ }
+
+ public void syncFitToScreen() {
+ fit.setSelected(true);
+ }
+
private void updateCanvasPane() {
Bounds bounds = getViewportBounds();
canvasPane.setMinWidth(Math.max(canvas.getWidth() * canvas.getScaleX(), bounds.getWidth()));
diff --git a/chunky/src/java/se/llbit/chunky/ui/controller/ChunkyFxController.java b/chunky/src/java/se/llbit/chunky/ui/controller/ChunkyFxController.java
index 65f248c607..1268d06518 100644
--- a/chunky/src/java/se/llbit/chunky/ui/controller/ChunkyFxController.java
+++ b/chunky/src/java/se/llbit/chunky/ui/controller/ChunkyFxController.java
@@ -133,6 +133,29 @@ public class ChunkyFxController
@FXML private MenuItem saveSceneCopy;
@FXML private MenuItem loadScene;
@FXML private MenuItem loadSceneFile;
+
+ @FXML private MenuItem newScene;
+ @FXML private MenuItem loadSelection;
+ @FXML private MenuItem clearSelection;
+ @FXML private MenuItem selectVisible;
+ @FXML private MenuItem exportZip;
+ @FXML private MenuItem exportPng;
+ @FXML private MenuItem deleteChunks;
+
+ @FXML private CheckMenuItem showGuides;
+ @FXML private Menu canvasScale;
+ @FXML private RadioMenuItem percent25;
+ @FXML private RadioMenuItem percent50;
+ @FXML private RadioMenuItem percent75;
+ @FXML private RadioMenuItem percent100;
+ @FXML private RadioMenuItem percent150;
+ @FXML private RadioMenuItem percent200;
+ @FXML private RadioMenuItem percent300;
+ @FXML private RadioMenuItem percent400;
+ @FXML private RadioMenuItem fit;
+ @FXML private MenuItem saveCurrentFrame;
+ @FXML private MenuItem copyFrame;
+
@FXML private MenuItem creditsMenuItem;
@FXML private ProgressBar progressBar;
@@ -147,6 +170,8 @@ public class ChunkyFxController
@FXML private ToggleButton pause;
@FXML private ToggleButton reset;
+ private boolean fitToScreen = PersistentSettings.getCanvasFitToScreen();
+
RenderControlsFxController sceneControls;
private File saveFrameDirectory = new File(System.getProperty("user.dir"));
@@ -459,6 +484,98 @@ public File getSceneFile(String fileName) {
}
});
+ newScene.setGraphic(new ImageView(Icon.sky.fxImage()));
+ newScene.setOnAction(event -> {
+ SceneManager sceneManager = getRenderController().getSceneManager();
+ sceneManager
+ .loadFreshChunks(mapLoader.getWorld(), getChunkSelection().getSelection());
+ });
+ newScene.setDisable(chunkSelection.isEmpty());
+
+ loadSelection.setOnAction(event -> {
+ SceneManager sceneManager = getRenderController().getSceneManager();
+ sceneManager
+ .loadChunks(mapLoader.getWorld(), getChunkSelection().getSelection());
+ });
+ loadSelection.setDisable(chunkSelection.isEmpty());
+
+ clearSelection.setGraphic(new ImageView(Icon.clear.fxImage()));
+ clearSelection.setOnAction(event -> chunkSelection.clearSelection());
+ clearSelection.setDisable(chunkSelection.isEmpty());
+
+ selectVisible.setGraphic(new ImageView(Icon.eye.fxImage()));
+ selectVisible.setOnAction(event -> map.selectCameraVisibleChunks());
+
+ exportZip.setOnAction(e -> exportZip());
+ exportZip.setDisable(chunkSelection.size() == 0);
+
+ exportPng.setOnAction(e -> exportMapView());
+
+ ImageView deleteChunksIcon = new ImageView(Icon.tntSide.fxImage());
+ deleteChunksIcon.setFitHeight(16);
+ deleteChunksIcon.setPreserveRatio(true);
+ deleteChunks.setGraphic(deleteChunksIcon);
+ deleteChunks.setOnAction(e -> promptDeleteSelectedChunks());
+ deleteChunks.setDisable(chunkSelection.size() == 0);
+
+ showGuides.setSelected(false);
+ showGuides.selectedProperty().addListener((observable, oldValue, newValue) -> {
+ canvas.changeShowGuides(newValue);
+ canvas.syncShowGuides(newValue);
+ });
+
+ percent25.setSelected(PersistentSettings.getCanvasScale() == 25 && !fitToScreen);
+ percent50.setSelected(PersistentSettings.getCanvasScale() == 50 && !fitToScreen);
+ percent75.setSelected(PersistentSettings.getCanvasScale() == 75 && !fitToScreen);
+ percent100.setSelected(PersistentSettings.getCanvasScale() == 100 && !fitToScreen);
+ percent150.setSelected(PersistentSettings.getCanvasScale() == 150 && !fitToScreen);
+ percent200.setSelected(PersistentSettings.getCanvasScale() == 200 && !fitToScreen);
+ percent300.setSelected(PersistentSettings.getCanvasScale() == 300 && !fitToScreen);
+ percent400.setSelected(PersistentSettings.getCanvasScale() == 400 && !fitToScreen);
+ fit.setSelected(fitToScreen);
+
+ percent25.setOnAction(e -> {
+ canvas.changeCanvasScale(25);
+ canvas.syncCanvasScale(25);
+ });
+ percent50.setOnAction(e -> {
+ canvas.changeCanvasScale(50);
+ canvas.syncCanvasScale(50);
+ });
+ percent75.setOnAction(e -> {
+ canvas.changeCanvasScale(75);
+ canvas.syncCanvasScale(75);
+ });
+ percent100.setOnAction(e -> {
+ canvas.changeCanvasScale(100);
+ canvas.syncCanvasScale(100);
+ });
+ percent150.setOnAction(e -> {
+ canvas.changeCanvasScale(150);
+ canvas.syncCanvasScale(150);
+ });
+ percent200.setOnAction(e -> {
+ canvas.changeCanvasScale(200);
+
+ canvas.syncCanvasScale(200);
+ });
+ percent300.setOnAction(e -> {
+ canvas.changeCanvasScale(300);
+ canvas.syncCanvasScale(300);
+ });
+ percent400.setOnAction(e -> {
+ canvas.changeCanvasScale(400);
+ canvas.syncCanvasScale(400);
+ });
+ fit.setOnAction(e -> {
+ canvas.changeFitToScreen();
+ canvas.syncFitToScreen();
+ });
+
+ saveCurrentFrame.setOnAction(e -> saveCurrentFrame());
+
+ copyFrame.setOnAction(e -> copyCurrentFrame());
+
Log.setReceiver(new UILogReceiver(), Level.ERROR, Level.WARNING);
mapLoader = new WorldMapLoader(this, mapView);
@@ -719,6 +836,42 @@ public File getSceneFile(String fileName) {
PersistentSettings.setSppTargetDefault(scene.getTargetSpp()));
}
+ public void disableMapMenuItems(boolean value) {
+ newScene.setDisable(value);
+ loadSelection.setDisable(value);
+ clearSelection.setDisable(value);
+ exportZip.setDisable(value);
+ deleteChunks.setDisable(value);
+ }
+
+ public void syncShowGuides(boolean value) {
+ showGuides.setSelected(value);
+ }
+
+ public void syncCanvasScale(int percent) {
+ if (percent == 25) {
+ percent25.setSelected(true);
+ } else if (percent == 50) {
+ percent50.setSelected(true);
+ } else if (percent == 75) {
+ percent75.setSelected(true);
+ } else if (percent == 100) {
+ percent100.setSelected(true);
+ } else if (percent == 150) {
+ percent150.setSelected(true);
+ } else if (percent == 200) {
+ percent200.setSelected(true);
+ } else if (percent == 300) {
+ percent300.setSelected(true);
+ } else if (percent == 400) {
+ percent400.setSelected(true);
+ }
+ }
+
+ public void syncFitToScreen() {
+ fit.setSelected(true);
+ }
+
public void openSceneChooser() {
try {
if (this.sceneChooser == null) {
diff --git a/chunky/src/res/se/llbit/chunky/ui/Chunky.fxml b/chunky/src/res/se/llbit/chunky/ui/Chunky.fxml
index 5b1f555ced..befcacb330 100644
--- a/chunky/src/res/se/llbit/chunky/ui/Chunky.fxml
+++ b/chunky/src/res/se/llbit/chunky/ui/Chunky.fxml
@@ -21,8 +21,40 @@