diff --git a/core/src/main/java/com/volmit/iris/core/gui/HotloadComparison.java b/core/src/main/java/com/volmit/iris/core/gui/HotloadComparison.java
deleted file mode 100644
index 9df922a78..000000000
--- a/core/src/main/java/com/volmit/iris/core/gui/HotloadComparison.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Iris is a World Generator for Minecraft Bukkit Servers
- * Copyright (c) 2022 Arcane Arts (Volmit Software)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package com.volmit.iris.core.gui;
-
-import com.volmit.iris.core.gui.components.MapStyle;
-import com.volmit.iris.core.gui.components.RenderType;
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferInt;
-import java.util.Locale;
-
-/**
- * Keeps the picture of the map from just before a hotload, and shows it next to the new one: either split by a
- * draggable divider, or with everything that stayed the same faded out.
- */
-final class HotloadComparison {
- private static final double DEFAULT_SWIPE_FRACTION = 0.5D;
- private static final int DIVIDER_GRAB_DISTANCE = 8;
- private static final int DIVIDER_HANDLE_RADIUS = 9;
- private static final int UNCHANGED_FADE_TARGET = 0x1E1F22;
- private static final double UNCHANGED_FADE = 0.78D;
- private static final Color DIVIDER = new Color(255, 255, 255, 220);
-
- private BufferedImage before;
- private Scene beforeScene;
- private Mode mode = Mode.OFF;
- private double swipeFraction = DEFAULT_SWIPE_FRACTION;
- private BufferedImage changes;
- private ChangesKey changesKey;
- private double changedShare;
-
- enum Mode {
- OFF,
- SWIPE,
- CHANGES;
-
- Mode next() {
- Mode[] modes = values();
- return modes[(ordinal() + 1) % modes.length];
- }
- }
-
- /**
- * What a map picture shows, so the before picture is only laid over a now picture of the same kind and zoom.
- */
- record Scene(RenderType type, MapStyle style, double blocksPerPixel, double centerX, double centerZ) {
- boolean looksLike(Scene other) {
- return type == other.type && style.equals(other.style);
- }
- }
-
- boolean hasBefore() {
- return before != null;
- }
-
- Mode mode() {
- return mode;
- }
-
- void setMode(Mode nextMode) {
- mode = nextMode;
- }
-
- void capture(BufferedImage layer, Scene scene) {
- BufferedImage copy = new BufferedImage(layer.getWidth(), layer.getHeight(), BufferedImage.TYPE_INT_RGB);
- copy.setAccelerationPriority(0F);
- Graphics2D graphics = copy.createGraphics();
- try {
- graphics.drawImage(layer, 0, 0, null);
- } finally {
- graphics.dispose();
- }
- before = copy;
- beforeScene = scene;
- changes = null;
- changesKey = null;
- }
-
- void forget() {
- before = null;
- beforeScene = null;
- changes = null;
- changesKey = null;
- mode = Mode.OFF;
- }
-
- boolean isShowing() {
- return mode != Mode.OFF && before != null;
- }
-
- boolean isNearDivider(int screenX, int width) {
- return isShowing() && mode == Mode.SWIPE
- && Math.abs(screenX - dividerX(width)) <= StudioTheme.scale(DIVIDER_GRAB_DISTANCE);
- }
-
- void moveDivider(int screenX, int width) {
- swipeFraction = Math.max(0D, Math.min(1D, screenX / (double) Math.max(1, width)));
- }
-
- /**
- * Draws the comparison in place of the plain map picture.
- *
- * @param nowVersion changes whenever the now picture is redrawn, so the change mask is only rebuilt when needed
- * @param nowComplete whether every tile of the now picture has been drawn; changes are only counted then
- */
- void paint(Graphics2D canvas, BufferedImage now, long nowVersion, Scene nowScene, boolean nowComplete) {
- canvas.drawImage(now, 0, 0, null);
- if (!beforeScene.looksLike(nowScene)) {
- drawCaption(canvas, now.getWidth(), "Before and after needs the view and layers the hotload had");
- return;
- }
- if (mode == Mode.SWIPE) {
- paintSwipe(canvas, now.getWidth(), now.getHeight(), nowScene);
- return;
- }
- if (beforeScene.blocksPerPixel() != nowScene.blocksPerPixel()) {
- drawCaption(canvas, now.getWidth(), "Changes needs the zoom the hotload had");
- return;
- }
- if (!nowComplete) {
- drawCaption(canvas, now.getWidth(), "Comparing once the map has finished drawing");
- return;
- }
- int offsetX = (int) Math.round(beforeScreenX(now.getWidth(), nowScene));
- int offsetZ = (int) Math.round(beforeScreenZ(now.getHeight(), nowScene));
- canvas.drawImage(changesImage(now, nowVersion, offsetX, offsetZ), 0, 0, null);
- drawCaption(canvas, now.getWidth(), changesCaption());
- }
-
- private void paintSwipe(Graphics2D canvas, int width, int height, Scene now) {
- int dividerX = dividerX(width);
- double scale = beforeScene.blocksPerPixel() / now.blocksPerPixel();
- Graphics2D beforeSide = (Graphics2D) canvas.create();
- try {
- beforeSide.clipRect(0, 0, dividerX, height);
- beforeSide.drawImage(before,
- (int) Math.round(beforeScreenX(width, now)),
- (int) Math.round(beforeScreenZ(height, now)),
- (int) Math.round(before.getWidth() * scale),
- (int) Math.round(before.getHeight() * scale),
- null);
- } finally {
- beforeSide.dispose();
- }
- canvas.setColor(DIVIDER);
- canvas.setStroke(new BasicStroke(StudioTheme.scale(2)));
- canvas.drawLine(dividerX, 0, dividerX, height);
- int radius = StudioTheme.scale(DIVIDER_HANDLE_RADIUS);
- canvas.fillOval(dividerX - radius, height / 2 - radius, radius * 2, radius * 2);
- canvas.setColor(StudioTheme.EDITOR_BACKGROUND);
- int gripHalfHeight = radius / 2;
- int gripGap = Math.max(1, radius / 4);
- canvas.drawLine(dividerX - gripGap, height / 2 - gripHalfHeight, dividerX - gripGap, height / 2 + gripHalfHeight);
- canvas.drawLine(dividerX + gripGap, height / 2 - gripHalfHeight, dividerX + gripGap, height / 2 + gripHalfHeight);
- drawSideLabel(canvas, "Before", dividerX - StudioTheme.scale(12), 1D);
- drawSideLabel(canvas, "Now", dividerX + StudioTheme.scale(12), 0D);
- }
-
- private int dividerX(int width) {
- return (int) Math.round(width * swipeFraction);
- }
-
- // Where the before picture's top left corner lands on screen now, after any panning, zooming or resizing since.
- private double beforeScreenX(int width, Scene now) {
- double beforeLeftWorld = beforeScene.centerX() - before.getWidth() * 0.5D * beforeScene.blocksPerPixel();
- return width * 0.5D + (beforeLeftWorld - now.centerX()) / now.blocksPerPixel();
- }
-
- private double beforeScreenZ(int height, Scene now) {
- double beforeTopWorld = beforeScene.centerZ() - before.getHeight() * 0.5D * beforeScene.blocksPerPixel();
- return height * 0.5D + (beforeTopWorld - now.centerZ()) / now.blocksPerPixel();
- }
-
- private BufferedImage changesImage(BufferedImage now, long nowVersion, int offsetX, int offsetZ) {
- ChangesKey key = new ChangesKey(nowVersion, offsetX, offsetZ, now.getWidth(), now.getHeight());
- if (changes != null && key.equals(changesKey)) {
- return changes;
- }
- int width = now.getWidth();
- int height = now.getHeight();
- int[] nowPixels = pixels(now);
- int[] beforePixels = pixels(before);
- BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- mask.setAccelerationPriority(0F);
- int[] maskPixels = pixels(mask);
- long compared = 0L;
- long changed = 0L;
- for (int y = 0; y < height; y++) {
- int beforeY = y - offsetZ;
- boolean rowInBefore = beforeY >= 0 && beforeY < before.getHeight();
- for (int x = 0; x < width; x++) {
- int index = y * width + x;
- int nowColor = nowPixels[index] & 0xFFFFFF;
- int beforeX = x - offsetX;
- boolean inBefore = rowInBefore && beforeX >= 0 && beforeX < before.getWidth();
- boolean differs = inBefore && (beforePixels[beforeY * before.getWidth() + beforeX] & 0xFFFFFF) != nowColor;
- if (inBefore) {
- compared++;
- }
- if (differs) {
- changed++;
- maskPixels[index] = nowColor;
- } else {
- maskPixels[index] = fade(nowColor);
- }
- }
- }
- changedShare = compared == 0L ? 0D : changed / (double) compared;
- changes = mask;
- changesKey = key;
- return mask;
- }
-
- private String changesCaption() {
- if (changedShare == 0D) {
- return "Nothing on screen changed in the hotload";
- }
- double percent = changedShare * 100D;
- String amount = percent < 0.1D ? "<0.1" : String.format(Locale.ROOT, percent < 10D ? "%.1f" : "%.0f", percent);
- return amount + "% of the map on screen changed in the hotload";
- }
-
- private static int[] pixels(BufferedImage image) {
- return ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
- }
-
- private static int fade(int color) {
- int red = (int) (((color >> 16) & 0xFF) * (1D - UNCHANGED_FADE) + ((UNCHANGED_FADE_TARGET >> 16) & 0xFF) * UNCHANGED_FADE);
- int green = (int) (((color >> 8) & 0xFF) * (1D - UNCHANGED_FADE) + ((UNCHANGED_FADE_TARGET >> 8) & 0xFF) * UNCHANGED_FADE);
- int blue = (int) ((color & 0xFF) * (1D - UNCHANGED_FADE) + (UNCHANGED_FADE_TARGET & 0xFF) * UNCHANGED_FADE);
- return (red << 16) | (green << 8) | blue;
- }
-
- private static void drawSideLabel(Graphics2D canvas, String text, int anchorX, double pushX) {
- canvas.setFont(StudioTheme.boldFont());
- int padding = StudioTheme.scale(8);
- int width = canvas.getFontMetrics().stringWidth(text) + padding * 2;
- int height = canvas.getFontMetrics().getHeight() + padding;
- int x = (int) Math.round(anchorX - width * pushX);
- int y = StudioTheme.scale(12);
- StudioOverlay.drawCard(canvas, x, y, width, height);
- canvas.setColor(StudioTheme.TEXT);
- canvas.drawString(text, x + padding, y + padding / 2 + canvas.getFontMetrics().getAscent());
- }
-
- private static void drawCaption(Graphics2D canvas, int width, String text) {
- canvas.setFont(StudioTheme.font());
- int padding = StudioTheme.scale(10);
- int captionWidth = canvas.getFontMetrics().stringWidth(text) + padding * 2;
- int height = canvas.getFontMetrics().getHeight() + padding;
- int x = (width - captionWidth) / 2;
- int y = StudioTheme.scale(12);
- StudioOverlay.drawCard(canvas, x, y, captionWidth, height);
- canvas.setColor(StudioTheme.TEXT);
- canvas.drawString(text, x + padding, y + padding / 2 + canvas.getFontMetrics().getAscent());
- }
-
- private record ChangesKey(long nowVersion, int offsetX, int offsetZ, int width, int height) {
- }
-}
diff --git a/core/src/main/java/com/volmit/iris/core/gui/MapCanvas.java b/core/src/main/java/com/volmit/iris/core/gui/MapCanvas.java
index 4b82ae514..d78dd54ab 100644
--- a/core/src/main/java/com/volmit/iris/core/gui/MapCanvas.java
+++ b/core/src/main/java/com/volmit/iris/core/gui/MapCanvas.java
@@ -33,7 +33,6 @@ import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import java.awt.Color;
-import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
@@ -87,7 +86,6 @@ final class MapCanvas extends JPanel {
private final Timer notificationTimer;
private final Timer legendTimer;
private final Map notifications = new LinkedHashMap<>();
- private final HotloadComparison comparison = new HotloadComparison();
private Engine engine;
private IrisRenderer renderer;
@@ -95,7 +93,6 @@ final class MapCanvas extends JPanel {
private VisionRenderController.Frame renderFrame;
private BufferedImage tileLayer;
private boolean tileLayerStale = true;
- private long tileLayerVersion;
private MapStyle style = MapStyle.PLAIN;
private RenderType currentType = RenderType.BIOME;
private String viewLabel = MapView.BIOMES.label();
@@ -105,7 +102,6 @@ final class MapCanvas extends JPanel {
private MapHoverProbe.Details hoverDetails;
private Point cursor;
private Point dragOrigin;
- private boolean draggingDivider;
private double centerX;
private double centerZ;
private long contentRevision = 1L;
@@ -184,14 +180,6 @@ final class MapCanvas extends JPanel {
return style;
}
- HotloadComparison.Mode comparisonMode() {
- return comparison.hasBefore() ? comparison.mode() : HotloadComparison.Mode.OFF;
- }
-
- boolean hasBeforePicture() {
- return comparison.hasBefore();
- }
-
void start() {
refreshMarkers();
requestRender();
@@ -238,27 +226,14 @@ final class MapCanvas extends JPanel {
notifyUser("No active Iris engine");
return;
}
- boolean captured = captureBeforePicture();
renderer = new IrisRenderer(engine);
overlay = new VisionOverlay(engine, openerId);
contentRevision++;
requestRender();
- notifyUser(captured && comparison.mode() == HotloadComparison.Mode.OFF
- ? "Refreshing ยท press C to compare with before"
- : "Refreshing");
+ notifyUser("Refreshing");
listener.onTogglesChanged();
}
- // Only a finished picture is worth comparing against; a half drawn one would show its gaps as changes.
- private boolean captureBeforePicture() {
- if (tileLayer == null || controller.progress(renderFrame).completion() < 1D) {
- comparison.forget();
- return false;
- }
- comparison.capture(currentTileLayer(), currentScene());
- return true;
- }
-
void toggleShading() {
applyStyle(style.withShading(!style.shading()));
notifyUser(style.shading() ? "Terrain shading on" : "Terrain shading off");
@@ -297,13 +272,11 @@ final class MapCanvas extends JPanel {
}
/**
- * Esc steps back one layer of emphasis: the highlight first, then the comparison, then the help.
+ * Esc steps back one layer of emphasis: the highlight first, then the help.
*/
void dismissEmphasis() {
if (style.highlight() != null) {
clearHighlight();
- } else if (comparisonMode() != HotloadComparison.Mode.OFF) {
- showComparison(HotloadComparison.Mode.OFF);
} else if (help) {
toggleHelp();
}
@@ -314,26 +287,6 @@ final class MapCanvas extends JPanel {
notifyUser("Highlight cleared");
}
- void cycleComparison() {
- showComparison(comparisonMode().next());
- }
-
- void showComparison(HotloadComparison.Mode mode) {
- if (!comparison.hasBefore()) {
- notifyUser("Refresh or hotload the pack first, then compare with before");
- listener.onTogglesChanged();
- return;
- }
- comparison.setMode(mode);
- notifyUser(switch (mode) {
- case OFF -> "Comparison off";
- case SWIPE -> "Drag the divider to compare before and now";
- case CHANGES -> "Showing what changed in the hotload";
- });
- repaint();
- listener.onTogglesChanged();
- }
-
private void applyStyle(MapStyle next) {
boolean heightsWereNeeded = needsHeights();
style = next;
@@ -440,9 +393,6 @@ final class MapCanvas extends JPanel {
public void mouseMoved(MouseEvent event) {
cursor = event.getPoint();
setDetailedHover(event.isShiftDown());
- setCursor(comparison.isNearDivider(event.getX(), getWidth())
- ? Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)
- : Cursor.getDefaultCursor());
showQuickHover();
hoverTimer.restart();
refreshStatus();
@@ -451,11 +401,6 @@ final class MapCanvas extends JPanel {
@Override
public void mouseDragged(MouseEvent event) {
cursor = event.getPoint();
- if (draggingDivider) {
- comparison.moveDivider(event.getX(), getWidth());
- repaint();
- return;
- }
if (dragOrigin == null) {
return;
}
@@ -480,8 +425,6 @@ final class MapCanvas extends JPanel {
cursor = event.getPoint();
if (event.isPopupTrigger()) {
showContextMenu(event);
- } else if (SwingUtilities.isLeftMouseButton(event) && comparison.isNearDivider(event.getX(), getWidth())) {
- draggingDivider = true;
} else if (SwingUtilities.isLeftMouseButton(event)) {
dragOrigin = event.getPoint();
}
@@ -490,7 +433,6 @@ final class MapCanvas extends JPanel {
@Override
public void mouseReleased(MouseEvent event) {
dragOrigin = null;
- draggingDivider = false;
if (event.isPopupTrigger()) {
showContextMenu(event);
}
@@ -628,17 +570,7 @@ final class MapCanvas extends JPanel {
// The display server gets one finished picture per paint: handing it every tile separately made the map lag.
private void renderTiles(Graphics2D canvas) {
- BufferedImage layer = currentTileLayer();
- if (!comparison.isShowing()) {
- canvas.drawImage(layer, 0, 0, null);
- return;
- }
- boolean complete = controller.progress(renderFrame).completion() >= 1D;
- comparison.paint(canvas, layer, tileLayerVersion, currentScene(), complete);
- }
-
- private HotloadComparison.Scene currentScene() {
- return new HotloadComparison.Scene(currentType, style, blocksPerPixel, centerX, centerZ);
+ canvas.drawImage(currentTileLayer(), 0, 0, null);
}
private BufferedImage currentTileLayer() {
@@ -657,7 +589,6 @@ final class MapCanvas extends JPanel {
layer.dispose();
}
tileLayerStale = false;
- tileLayerVersion++;
}
return tileLayer;
}
@@ -833,7 +764,7 @@ final class MapCanvas extends JPanel {
private void renderHover(Graphics2D canvas) {
QuickHover quick = quickHover;
- if (quick == null || draggingDivider) {
+ if (quick == null) {
return;
}
MapHoverProbe.Details details = hoverDetails;
@@ -846,7 +777,7 @@ final class MapCanvas extends JPanel {
private void renderHelp(Graphics2D canvas) {
List keys = List.of("Drag", "Wheel / + -", "\\", "Double-click", "Right-click", "Ctrl+Click", "Alt+Click",
- "Shift", "H", "Esc", "S", "B", "C", "R", "F", "G", "E", "M", "1 to 0, P", "/");
+ "Shift", "H", "Esc", "S", "B", "R", "F", "G", "E", "M", "1 to 0, P", "/");
List descriptions = List.of(
"Move the map",
"Zoom in and out",
@@ -860,7 +791,6 @@ final class MapCanvas extends JPanel {
"Clear the highlight",
"Terrain shading",
"Region borders",
- "Compare with before the last hotload",
"Redraw the map",
"Follow your player",
"Chunk and region grid",
diff --git a/core/src/main/java/com/volmit/iris/core/gui/MapWindow.java b/core/src/main/java/com/volmit/iris/core/gui/MapWindow.java
index 8bdbe61c5..77ba0c503 100644
--- a/core/src/main/java/com/volmit/iris/core/gui/MapWindow.java
+++ b/core/src/main/java/com/volmit/iris/core/gui/MapWindow.java
@@ -73,10 +73,6 @@ public final class MapWindow implements MapCanvas.Listener {
private final JToggleButton followToggle = StudioToolbar.toggle("Follow", "Keep your player in the middle (F)");
private final JToggleButton shadingToggle = StudioToolbar.toggle("Shading", "Shade hills and valleys on every view (S)");
private final JToggleButton bordersToggle = StudioToolbar.toggle("Borders", "Outline the regions on every view (B)");
- private final JToggleButton swipeToggle = StudioToolbar.toggle("Before / after",
- "Split the map between before and after the last hotload or refresh (C)");
- private final JToggleButton changesToggle = StudioToolbar.toggle("Changes",
- "Fade out everything the last hotload or refresh left the same (C twice)");
private final MapLegendPanel legendPanel;
private NoiseExplorerGUI paletteExplorer;
@@ -150,18 +146,11 @@ public final class MapWindow implements MapCanvas.Listener {
mapControls.add(toolbarSeparator());
mapControls.add(shadingToggle);
mapControls.add(bordersToggle);
- mapControls.add(toolbarSeparator());
- mapControls.add(swipeToggle);
- mapControls.add(changesToggle);
gridToggle.addActionListener(event -> canvas.toggleGrid());
entitiesToggle.addActionListener(event -> canvas.toggleEntities());
followToggle.addActionListener(event -> canvas.toggleFollow());
shadingToggle.addActionListener(event -> canvas.toggleShading());
bordersToggle.addActionListener(event -> canvas.toggleRegionBorders());
- swipeToggle.addActionListener(event -> canvas.showComparison(
- swipeToggle.isSelected() ? HotloadComparison.Mode.SWIPE : HotloadComparison.Mode.OFF));
- changesToggle.addActionListener(event -> canvas.showComparison(
- changesToggle.isSelected() ? HotloadComparison.Mode.CHANGES : HotloadComparison.Mode.OFF));
mapControls.forEach(toolbar::add);
paletteControls.add(StudioToolbar.button("Reset view", "Go back to the starting position and zoom (R)", this::resetPaletteView));
@@ -297,8 +286,6 @@ public final class MapWindow implements MapCanvas.Listener {
followToggle.setSelected(canvas.isFollowing());
shadingToggle.setSelected(canvas.style().shading());
bordersToggle.setSelected(canvas.style().regionBorders());
- swipeToggle.setSelected(canvas.comparisonMode() == HotloadComparison.Mode.SWIPE);
- changesToggle.setSelected(canvas.comparisonMode() == HotloadComparison.Mode.CHANGES);
}
@Override
@@ -340,7 +327,6 @@ public final class MapWindow implements MapCanvas.Listener {
bindMap(rootPane, KeyEvent.VK_ESCAPE, 0, "dismiss", canvas::dismissEmphasis);
bindMap(rootPane, KeyEvent.VK_S, 0, "shading", canvas::toggleShading);
bindMap(rootPane, KeyEvent.VK_B, 0, "borders", canvas::toggleRegionBorders);
- bindMap(rootPane, KeyEvent.VK_C, 0, "compare", canvas::cycleComparison);
bindMap(rootPane, KeyEvent.VK_EQUALS, 0, "zoom-in", canvas::zoomIn);
bindMap(rootPane, KeyEvent.VK_EQUALS, KeyEvent.SHIFT_DOWN_MASK, "zoom-in-plus", canvas::zoomIn);
bindMap(rootPane, KeyEvent.VK_ADD, 0, "zoom-in-keypad", canvas::zoomIn);