From 0f0ab224806ee2456fc5c8e518a53d5c876b27c3 Mon Sep 17 00:00:00 2001 From: Tobias Knerr Date: Fri, 14 Jul 2023 16:26:39 +0200 Subject: [PATCH] Add a LOD selector to the viewer's options menu --- .../viewer/control/actions/SetLodAction.java | 51 +++++++++++++++++++ .../java/org/osm2world/viewer/model/Data.java | 23 ++++++--- .../osm2world/viewer/model/RenderOptions.java | 12 +++++ .../osm2world/viewer/view/ViewerFrame.java | 12 +++++ 4 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/osm2world/viewer/control/actions/SetLodAction.java diff --git a/src/main/java/org/osm2world/viewer/control/actions/SetLodAction.java b/src/main/java/org/osm2world/viewer/control/actions/SetLodAction.java new file mode 100644 index 000000000..6a81d9023 --- /dev/null +++ b/src/main/java/org/osm2world/viewer/control/actions/SetLodAction.java @@ -0,0 +1,51 @@ +package org.osm2world.viewer.control.actions; + +import java.awt.event.ActionEvent; +import java.io.Serial; + +import javax.swing.*; + +import org.apache.commons.configuration.Configuration; +import org.osm2world.core.target.common.mesh.LevelOfDetail; +import org.osm2world.viewer.model.Data; +import org.osm2world.viewer.model.RenderOptions; +import org.osm2world.viewer.view.ViewerFrame; + +public class SetLodAction extends AbstractAction { + + @Serial + private static final long serialVersionUID = 1L; + + LevelOfDetail lod; + ViewerFrame viewerFrame; + Data data; + RenderOptions renderOptions; + + public SetLodAction(LevelOfDetail lod, ViewerFrame viewerFrame, Data data, RenderOptions renderOptions) { + + super(lod.name()); + + putValue(SELECTED_KEY, lod == renderOptions.getLod()); + + this.lod = lod; + this.viewerFrame = viewerFrame; + this.data = data; + this.renderOptions = renderOptions; + + } + + @Override + public void actionPerformed(ActionEvent e) { + + renderOptions.setLod(lod); + + Configuration config = data.getConfig(); + config.clearProperty("lod"); + config.addProperty("lod", lod.ordinal()); + data.setConfig(config); + + putValue(SELECTED_KEY, lod == renderOptions.getLod()); + + } + +} diff --git a/src/main/java/org/osm2world/viewer/model/Data.java b/src/main/java/org/osm2world/viewer/model/Data.java index 9cf18e7ae..46a83f864 100644 --- a/src/main/java/org/osm2world/viewer/model/Data.java +++ b/src/main/java/org/osm2world/viewer/model/Data.java @@ -36,6 +36,20 @@ public Configuration getConfig() { return config; } + /** updates the configuration */ + public void setConfig(Configuration config) { + + this.config = config; + + ConfigUtil.parseFonts(config); + + if (conversionResults != null) { + this.setChanged(); + this.notifyObservers(); + } + + } + /** reloads the configuration from the config file */ public void reloadConfig() throws ConfigurationException { @@ -45,14 +59,7 @@ public void reloadConfig() throws ConfigurationException { fileConfig.setListDelimiter(';'); fileConfig.load(configFile); - this.config = fileConfig; - - ConfigUtil.parseFonts(fileConfig); - - if (conversionResults != null) { - this.setChanged(); - this.notifyObservers(); - } + this.setConfig(fileConfig); } diff --git a/src/main/java/org/osm2world/viewer/model/RenderOptions.java b/src/main/java/org/osm2world/viewer/model/RenderOptions.java index a2c870ef7..39e77fc88 100644 --- a/src/main/java/org/osm2world/viewer/model/RenderOptions.java +++ b/src/main/java/org/osm2world/viewer/model/RenderOptions.java @@ -3,10 +3,13 @@ import java.util.HashSet; import java.util.Set; +import javax.annotation.Nullable; + import org.osm2world.core.map_elevation.creation.EleConstraintEnforcer; import org.osm2world.core.map_elevation.creation.NoneEleConstraintEnforcer; import org.osm2world.core.map_elevation.creation.TerrainInterpolator; import org.osm2world.core.map_elevation.creation.ZeroInterpolator; +import org.osm2world.core.target.common.mesh.LevelOfDetail; import org.osm2world.core.target.common.rendering.Camera; import org.osm2world.core.target.common.rendering.Projection; import org.osm2world.viewer.view.debug.DebugView; @@ -22,6 +25,8 @@ public class RenderOptions { private boolean wireframe = false; private boolean backfaceCulling = true; + private @Nullable LevelOfDetail lod = null; + Class interpolatorClass = ZeroInterpolator.class; Class enforcerClass = NoneEleConstraintEnforcer.class; @@ -44,6 +49,13 @@ public void setBackfaceCulling(boolean backfaceCulling) { this.backfaceCulling = backfaceCulling; } + public @Nullable LevelOfDetail getLod() { + return lod; + } + public void setLod(LevelOfDetail lod) { + this.lod = lod; + } + public Class getInterpolatorClass() { return interpolatorClass; } diff --git a/src/main/java/org/osm2world/viewer/view/ViewerFrame.java b/src/main/java/org/osm2world/viewer/view/ViewerFrame.java index 4e710219d..ef31101bf 100644 --- a/src/main/java/org/osm2world/viewer/view/ViewerFrame.java +++ b/src/main/java/org/osm2world/viewer/view/ViewerFrame.java @@ -14,6 +14,7 @@ import org.apache.commons.configuration.Configuration; import org.osm2world.core.map_elevation.creation.*; +import org.osm2world.core.target.common.mesh.LevelOfDetail; import org.osm2world.viewer.control.actions.*; import org.osm2world.viewer.control.navigation.DefaultNavigation; import org.osm2world.viewer.model.Data; @@ -172,6 +173,17 @@ private void createMenuBar() { JMenu subMenu = new JMenu("Options"); subMenu.setMnemonic(VK_O); + JMenu lodMenu = new JMenu("Level of Detail"); + subMenu.add(lodMenu); + + var lodGroup = new ButtonGroup(); + + for (LevelOfDetail lod : LevelOfDetail.values()) { + var item = new JRadioButtonMenuItem(new SetLodAction(lod, this, data, renderOptions)); + lodGroup.add(item); + lodMenu.add(item); + } + JMenu interpolatorMenu = new JMenu("TerrainInterpolator"); subMenu.add(interpolatorMenu);