From c1c1987188c1ca388e509e5cf6ebe0084561db0f Mon Sep 17 00:00:00 2001 From: Dan Royer Date: Sat, 6 Jan 2024 15:47:15 -0800 Subject: [PATCH 1/5] deprecate --- .../parameters/swing/ComponentSwingViewFactory.java | 2 +- .../robotoverlord/parameters/swing/ViewElement.java | 2 +- .../robotoverlord/parameters/swing/ViewElementBoolean.java | 2 +- .../robotoverlord/parameters/swing/ViewElementButton.java | 2 +- .../robotoverlord/parameters/swing/ViewElementColor.java | 2 +- .../robotoverlord/parameters/swing/ViewElementComboBox.java | 2 +- .../robotoverlord/parameters/swing/ViewElementDouble.java | 2 +- .../robotoverlord/parameters/swing/ViewElementFactory.java | 2 +- .../robotoverlord/parameters/swing/ViewElementFilename.java | 2 +- .../robotoverlord/parameters/swing/ViewElementInt.java | 2 +- .../robotoverlord/parameters/swing/ViewElementList.java | 2 +- .../robotoverlord/parameters/swing/ViewElementReference.java | 2 +- .../robotoverlord/parameters/swing/ViewElementSlider.java | 2 +- .../robotoverlord/parameters/swing/ViewElementSliderDouble.java | 2 +- .../robotoverlord/parameters/swing/ViewElementString.java | 2 +- .../robotoverlord/parameters/swing/ViewElementVector3d.java | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ComponentSwingViewFactory.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ComponentSwingViewFactory.java index 56dc74080..6e1be06f5 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ComponentSwingViewFactory.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ComponentSwingViewFactory.java @@ -18,7 +18,7 @@ * @author Dan Royer * @since 1.6.0 */ -public class ComponentSwingViewFactory { +@Deprecated public class ComponentSwingViewFactory { private final ViewElementFactory viewElementFactory; private final JPanel result = new JPanel(); private final GridBagConstraints gbc = new GridBagConstraints(); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElement.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElement.java index 3d716e2f8..9e42f24bd 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElement.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElement.java @@ -12,7 +12,7 @@ * @since 1.6.0 * */ -public class ViewElement extends JPanel { +@Deprecated public class ViewElement extends JPanel { public ViewElement() { super(); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementBoolean.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementBoolean.java index eaa3c25f8..047855846 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementBoolean.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementBoolean.java @@ -17,7 +17,7 @@ * @author Dan Royer * */ -public class ViewElementBoolean extends ViewElement implements PropertyChangeListener { +@Deprecated public class ViewElementBoolean extends ViewElement implements PropertyChangeListener { private final JLabel label; private final JCheckBox field = new JCheckBox(); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementButton.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementButton.java index 0e2c89e82..7143bdcbf 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementButton.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementButton.java @@ -12,7 +12,7 @@ * @since 1.6.0 * */ -public class ViewElementButton extends ViewElement { +@Deprecated public class ViewElementButton extends ViewElement { protected JButton field; // who is listening to me? diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementColor.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementColor.java index 2f6991c6f..0912bff9e 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementColor.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementColor.java @@ -14,7 +14,7 @@ * Panel to alter a color parameter (four float values). * @author Dan Royer */ -public class ViewElementColor extends ViewElement implements PropertyChangeListener { +@Deprecated public class ViewElementColor extends ViewElement implements PropertyChangeListener { private final BackgroundPaintedButton chooseButton = new BackgroundPaintedButton(""); private final ColorParameter parameter; diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementComboBox.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementComboBox.java index 462e88a5b..15ad4492e 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementComboBox.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementComboBox.java @@ -18,7 +18,7 @@ * @author Dan Royer * @since 2.5.0 */ -public class ViewElementComboBox extends ViewElement implements ActionListener, PropertyChangeListener { +@Deprecated public class ViewElementComboBox extends ViewElement implements ActionListener, PropertyChangeListener { private final JComboBox field; private final IntParameter parameter; diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementDouble.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementDouble.java index 8a36b7cdf..41f7cf34c 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementDouble.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementDouble.java @@ -21,7 +21,7 @@ * @author Dan Royer * */ -public class ViewElementDouble extends ViewElement implements DocumentListener, PropertyChangeListener { +@Deprecated public class ViewElementDouble extends ViewElement implements DocumentListener, PropertyChangeListener { private final JLabel label; private final JTextField field; private final DoubleParameter parameter; diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFactory.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFactory.java index a36a5d959..5f8d80672 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFactory.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFactory.java @@ -13,7 +13,7 @@ * @author Dan Royer * @since 2.6.3 */ -public class ViewElementFactory { +@Deprecated public class ViewElementFactory { private final EntityManager entityManager; public ViewElementFactory(EntityManager entityManager) { diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFilename.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFilename.java index aa301094c..de0ea7c10 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFilename.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementFilename.java @@ -23,7 +23,7 @@ * @author Dan Royer * */ -public class ViewElementFilename extends ViewElement implements ActionListener { +@Deprecated public class ViewElementFilename extends ViewElement implements ActionListener { private static final JFileChooser chooser = new JFileChooser(PathHelper.SCENE_PATH); private final JLabel label; private final JTextField field = new JTextField(15); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementInt.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementInt.java index 83a12dcad..06dd8f04f 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementInt.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementInt.java @@ -20,7 +20,7 @@ * @author Dan Royer * */ -public class ViewElementInt extends ViewElement implements DocumentListener, PropertyChangeListener { +@Deprecated public class ViewElementInt extends ViewElement implements DocumentListener, PropertyChangeListener { private final JTextField field; private final IntParameter parameter; private final ReentrantLock lock = new ReentrantLock(); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementList.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementList.java index 2c9fb33cd..22960c855 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementList.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementList.java @@ -15,7 +15,7 @@ * @author Dan Royer * @since 2.6.3 */ -public class ViewElementList extends ViewElement { +@Deprecated class ViewElementList extends ViewElement { private final ListParameter list; private final EntityManager entityManager; private final JPanel header = new JPanel(new BorderLayout(2,2)); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementReference.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementReference.java index 5cc33cc7e..a7958ee01 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementReference.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementReference.java @@ -19,7 +19,7 @@ * @author Dan Royer * @since 2.5.0 */ -public class ViewElementReference extends ViewElement implements ActionListener { +@Deprecated public class ViewElementReference extends ViewElement implements ActionListener { private final JTextField field = new FocusTextField(20); private final ReferenceParameter parameter; private final EntityManager entityManager; diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSlider.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSlider.java index a044a6b1a..6c1b5dcd5 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSlider.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSlider.java @@ -15,7 +15,7 @@ * Panel to alter a color parameter (four float values). * @author Dan Royer */ -public class ViewElementSlider extends ViewElement implements ChangeListener, PropertyChangeListener { +@Deprecated public class ViewElementSlider extends ViewElement implements ChangeListener, PropertyChangeListener { private final JSlider field = new JSlider(); private final JLabel value; private final IntParameter parameter; diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSliderDouble.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSliderDouble.java index 634f618eb..18657c379 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSliderDouble.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementSliderDouble.java @@ -15,7 +15,7 @@ * Panel to alter a color parameter (four float values). * @author Dan Royer */ -public class ViewElementSliderDouble extends ViewElement implements ChangeListener, PropertyChangeListener { +@Deprecated public class ViewElementSliderDouble extends ViewElement implements ChangeListener, PropertyChangeListener { private final JSlider field = new JSlider(); private final JLabel value; private final DoubleParameter parameter; diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementString.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementString.java index d9d8dfd5e..226960ff4 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementString.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementString.java @@ -17,7 +17,7 @@ * @author Dan Royer * */ -public class ViewElementString extends ViewElement implements DocumentListener, PropertyChangeListener { +@Deprecated public class ViewElementString extends ViewElement implements DocumentListener, PropertyChangeListener { private final JTextField field = new FocusTextField(20); private final StringParameter parameter; private final ReentrantLock lock = new ReentrantLock(); diff --git a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementVector3d.java b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementVector3d.java index ecb6d5ce8..80d054bc9 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementVector3d.java +++ b/src/main/java/com/marginallyclever/robotoverlord/parameters/swing/ViewElementVector3d.java @@ -22,7 +22,7 @@ * @author Dan Royer * */ -public class ViewElementVector3d extends ViewElement implements DocumentListener, PropertyChangeListener { +@Deprecated public class ViewElementVector3d extends ViewElement implements DocumentListener, PropertyChangeListener { private final JTextField [] fields = new JTextField[3]; private final Vector3DParameter parameter; private final ReentrantLock lock = new ReentrantLock(); From 3a5e294b9e2cf0b5b7e32c868e0f9b4a3b7ae651 Mon Sep 17 00:00:00 2001 From: Dan Royer Date: Sat, 6 Jan 2024 15:48:50 -0800 Subject: [PATCH 2/5] MeshFactory is not a singleton any more. --- .../com/marginallyclever/ro3/Registry.java | 3 +- .../ro3/apps/RO3FrameDropTarget.java | 5 +-- .../ro3/apps/actions/ExportScene.java | 3 +- .../ro3/apps/dialogs/MeshFactoryDialog.java | 7 ++-- .../apps/dialogs/TextureFactoryDialog.java | 3 +- .../ro3/listwithevents/ListWithEvents.java | 8 ++-- .../ro3/mesh/{load => }/MeshFactory.java | 39 +++++++++---------- .../ro3/mesh/load/MeshLoader.java | 1 + .../ro3/node/nodes/MeshInstance.java | 6 +-- .../ro3/texture/TextureFactory.java | 11 +++--- 10 files changed, 42 insertions(+), 44 deletions(-) rename src/main/java/com/marginallyclever/ro3/mesh/{load => }/MeshFactory.java (76%) diff --git a/src/main/java/com/marginallyclever/ro3/Registry.java b/src/main/java/com/marginallyclever/ro3/Registry.java index 5dd2f0b1b..8e04deb14 100644 --- a/src/main/java/com/marginallyclever/ro3/Registry.java +++ b/src/main/java/com/marginallyclever/ro3/Registry.java @@ -1,6 +1,7 @@ package com.marginallyclever.ro3; import com.marginallyclever.ro3.listwithevents.ListWithEvents; +import com.marginallyclever.ro3.mesh.MeshFactory; import com.marginallyclever.ro3.node.nodes.*; import com.marginallyclever.ro3.node.Node; import com.marginallyclever.ro3.node.nodes.marlinrobotarm.MarlinRobotArm; @@ -11,7 +12,6 @@ import java.awt.*; import java.awt.datatransfer.Clipboard; import java.util.ArrayList; -import java.util.Collection; import java.util.List; /** @@ -21,6 +21,7 @@ public class Registry { public static final EventListenerList listeners = new EventListenerList(); public static final TextureFactory textureFactory = new TextureFactory(); + public static final MeshFactory meshFactory = new MeshFactory(); public static final Factory nodeFactory = new Factory<>(Node.class); private static Node scene = new Node("Scene"); public static final ListWithEvents cameras = new ListWithEvents<>(); diff --git a/src/main/java/com/marginallyclever/ro3/apps/RO3FrameDropTarget.java b/src/main/java/com/marginallyclever/ro3/apps/RO3FrameDropTarget.java index 12fc3fd22..d965aebe6 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/RO3FrameDropTarget.java +++ b/src/main/java/com/marginallyclever/ro3/apps/RO3FrameDropTarget.java @@ -3,7 +3,6 @@ import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.apps.commands.ImportScene; import com.marginallyclever.ro3.node.nodes.MeshInstance; -import com.marginallyclever.ro3.mesh.load.MeshFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,13 +67,13 @@ public void drop(DropTargetDropEvent event) { private boolean importMesh(String absolutePath) { logger.debug("drag importMesh {}",absolutePath); - if(!MeshFactory.canLoad(absolutePath)) { + if(!Registry.meshFactory.canLoad(absolutePath)) { logger.info("can't load file."); return false; } MeshInstance meshInstance = new MeshInstance(getFilenameWithoutExtensionFromPath(absolutePath)); - meshInstance.setMesh(MeshFactory.load(absolutePath)); + meshInstance.setMesh(Registry.meshFactory.load(absolutePath)); Registry.getScene().addChild(meshInstance); logger.error("done."); return true; diff --git a/src/main/java/com/marginallyclever/ro3/apps/actions/ExportScene.java b/src/main/java/com/marginallyclever/ro3/apps/actions/ExportScene.java index d214fb2f2..9802730f6 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/actions/ExportScene.java +++ b/src/main/java/com/marginallyclever/ro3/apps/actions/ExportScene.java @@ -3,7 +3,6 @@ import com.marginallyclever.convenience.helpers.FileHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.apps.RO3Frame; -import com.marginallyclever.ro3.mesh.load.MeshFactory; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,7 +90,7 @@ public void commitExport(String absolutePath) { JSONObject json = Registry.getScene().toJSON(); List sources = Registry.textureFactory.getAllSourcesForExport(); - sources.addAll(MeshFactory.getAllSourcesForExport()); + sources.addAll(Registry.meshFactory.getAllSourcesForExport()); createZipAndAddAssets(absolutePath, json.toString(), sources); diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java index abd458a3c..c56145c84 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java @@ -1,8 +1,9 @@ package com.marginallyclever.ro3.apps.dialogs; +import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.apps.shared.PersistentJFileChooser; import com.marginallyclever.ro3.mesh.Mesh; -import com.marginallyclever.ro3.mesh.load.MeshFactory; +import com.marginallyclever.ro3.mesh.MeshFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,7 +23,7 @@ public class MeshFactoryDialog { public MeshFactoryDialog() { super(); - List filters = MeshFactory.getAllExtensions(); + List filters = Registry.meshFactory.getAllExtensions(); if (filters.isEmpty()) throw new RuntimeException("No MeshFactory filters found?!"); if (filters.size() == 1) { chooser.setFileFilter(filters.get(0)); @@ -42,7 +43,7 @@ public int run() { if(returnVal == JFileChooser.APPROVE_OPTION) { String absPath = chooser.getSelectedFile().getAbsolutePath(); try { - lastMeshLoaded = MeshFactory.load(absPath); + lastMeshLoaded = Registry.meshFactory.load(absPath); } catch(Exception e) { logger.error("Failed to load from "+absPath,e); returnVal = JFileChooser.CANCEL_OPTION; diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java index ed714b3e5..3e18844ce 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java @@ -4,7 +4,6 @@ import com.marginallyclever.ro3.apps.shared.PersistentJFileChooser; import com.marginallyclever.ro3.texture.TextureFactory; import com.marginallyclever.ro3.texture.TextureWithMetadata; -import com.marginallyclever.ro3.mesh.load.MeshFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,7 +25,7 @@ public class TextureFactoryDialog { public TextureFactoryDialog() { super(); - List filters = MeshFactory.getAllExtensions(); + List filters = Registry.meshFactory.getAllExtensions(); if (filters.isEmpty()) throw new RuntimeException("No MeshFactory filters found?!"); if (filters.size() == 1) { chooser.setFileFilter(filters.get(0)); diff --git a/src/main/java/com/marginallyclever/ro3/listwithevents/ListWithEvents.java b/src/main/java/com/marginallyclever/ro3/listwithevents/ListWithEvents.java index 36738665c..25699c394 100644 --- a/src/main/java/com/marginallyclever/ro3/listwithevents/ListWithEvents.java +++ b/src/main/java/com/marginallyclever/ro3/listwithevents/ListWithEvents.java @@ -43,14 +43,14 @@ public void removeItemRemovedListener(ItemRemovedListener listener) { } protected void fireItemAdded(T item) { - for (ItemAddedListener l : listenerList.getListeners(ItemAddedListener.class)) { - l.itemAdded(this,item); + for (ItemAddedListener listener : listenerList.getListeners(ItemAddedListener.class)) { + listener.itemAdded(this,item); } } protected void fireItemRemoved(T item) { - for (ItemRemovedListener l : listenerList.getListeners(ItemRemovedListener.class)) { - l.itemRemoved(this,item); + for (ItemRemovedListener listener : listenerList.getListeners(ItemRemovedListener.class)) { + listener.itemRemoved(this,item); } } diff --git a/src/main/java/com/marginallyclever/ro3/mesh/load/MeshFactory.java b/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java similarity index 76% rename from src/main/java/com/marginallyclever/ro3/mesh/load/MeshFactory.java rename to src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java index 60c66ee6c..b702166cd 100644 --- a/src/main/java/com/marginallyclever/ro3/mesh/load/MeshFactory.java +++ b/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java @@ -1,17 +1,16 @@ -package com.marginallyclever.ro3.mesh.load; +package com.marginallyclever.ro3.mesh; import com.marginallyclever.convenience.helpers.FileHelper; -import com.marginallyclever.ro3.mesh.Mesh; +import com.marginallyclever.ro3.listwithevents.ListWithEvents; +import com.marginallyclever.ro3.mesh.load.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.BufferedInputStream; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; /** @@ -22,23 +21,23 @@ */ public class MeshFactory { private static final Logger logger = LoggerFactory.getLogger(MeshFactory.class); - private static final MeshLoader [] loaders = { + private final MeshLoader [] loaders = { new Load3MF(), new LoadAMF(), new LoadOBJ(), new LoadPLY(), new LoadSTL(), }; - + // the pool of all mesh loaded - private static final LinkedList meshPool = new LinkedList<>(); + private final ListWithEvents meshPool = new ListWithEvents<>(); /** * Makes sure to only load one instance of each source file. Loads all the data immediately. * @param filename file from which to load. may be filename.ext or zipfile.zip:filename.ext * @return an instance of Mesh. It may contain nothing. */ - public static Mesh load(String filename) { + public Mesh load(String filename) { if(filename == null || filename.trim().isEmpty()) return null; String absolutePath = FileHelper.getAbsolutePathOrFilename(filename); @@ -51,9 +50,9 @@ public static Mesh load(String filename) { return mesh; } - private static Mesh getMeshFromPool(String filename) { + private Mesh getMeshFromPool(String filename) { // find the existing shape in the pool - for( Mesh m : meshPool ) { + for( Mesh m : meshPool.getList() ) { String sourceName = m.getSourceName(); if(sourceName==null) continue; if(filename.equals(sourceName)) { @@ -64,7 +63,7 @@ private static Mesh getMeshFromPool(String filename) { return null; } - private static void attemptLoad(String filename, Mesh mesh) { + private void attemptLoad(String filename, Mesh mesh) { for( MeshLoader loader : loaders ) { if(isValidExtension(filename,loader)) { loadMeshWithLoader(filename,mesh,loader); @@ -73,7 +72,7 @@ private static void attemptLoad(String filename, Mesh mesh) { } } - private static boolean isValidExtension(String filename, MeshLoader loader) { + private boolean isValidExtension(String filename, MeshLoader loader) { filename = filename.toLowerCase(); String [] extensions = loader.getValidExtensions(); for( String e : extensions ) { @@ -82,7 +81,7 @@ private static boolean isValidExtension(String filename, MeshLoader loader) { return false; } - private static void loadMeshWithLoader(String filename, Mesh mesh, MeshLoader loader) { + private void loadMeshWithLoader(String filename, Mesh mesh, MeshLoader loader) { logger.info("Loading "+filename+" with "+loader.getEnglishName()); mesh.setSourceName(filename); @@ -98,12 +97,12 @@ private static void loadMeshWithLoader(String filename, Mesh mesh, MeshLoader lo mesh.updateCuboid(); } - public static void reload(Mesh myMesh) { + public void reload(Mesh myMesh) { myMesh.clear(); attemptLoad(myMesh.getSourceName(),myMesh); } - public static List getAllExtensions() { + public List getAllExtensions() { ArrayList filters = new ArrayList<>(); for( MeshLoader loader : loaders ) { @@ -112,7 +111,7 @@ public static List getAllExtensions() { return filters; } - public static boolean canLoad(String absolutePath) { + public boolean canLoad(String absolutePath) { String lowerCasePath = absolutePath.toLowerCase(); for( MeshLoader loader : loaders ) { if(Arrays.stream(loader.getValidExtensions()).anyMatch(ext -> lowerCasePath.endsWith(ext.toLowerCase()))) return true; @@ -120,23 +119,23 @@ public static boolean canLoad(String absolutePath) { return false; } - public static boolean hasMaterial(String absolutePath) { + public boolean hasMaterial(String absolutePath) { for( MeshLoader loader : loaders ) { if(loader.hasMaterial(absolutePath)) return true; } return false; } - public static String getMaterialPath(String absolutePath) { + public String getMaterialPath(String absolutePath) { for( MeshLoader loader : loaders ) { if(loader.hasMaterial(absolutePath)) return loader.getMaterialPath(absolutePath); } return null; } - public static List getAllSourcesForExport() { + public List getAllSourcesForExport() { List result = new ArrayList<>(); - for( Mesh m : meshPool ) { + for( Mesh m : meshPool.getList() ) { result.add(m.getSourceName()); } return result; diff --git a/src/main/java/com/marginallyclever/ro3/mesh/load/MeshLoader.java b/src/main/java/com/marginallyclever/ro3/mesh/load/MeshLoader.java index a09123ced..3096438ea 100644 --- a/src/main/java/com/marginallyclever/ro3/mesh/load/MeshLoader.java +++ b/src/main/java/com/marginallyclever/ro3/mesh/load/MeshLoader.java @@ -1,6 +1,7 @@ package com.marginallyclever.ro3.mesh.load; import com.marginallyclever.ro3.mesh.Mesh; +import com.marginallyclever.ro3.mesh.MeshFactory; import java.io.BufferedInputStream; diff --git a/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java b/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java index 325a14e9b..46f4d2f07 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java @@ -2,10 +2,10 @@ import com.marginallyclever.convenience.Ray; import com.marginallyclever.convenience.helpers.MatrixHelper; +import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.apps.dialogs.MeshFactoryDialog; import com.marginallyclever.ro3.mesh.Mesh; import com.marginallyclever.ro3.mesh.MeshSmoother; -import com.marginallyclever.ro3.mesh.load.MeshFactory; import com.marginallyclever.ro3.raypicking.RayHit; import org.json.JSONObject; @@ -66,7 +66,7 @@ public void getComponents(List list) { addLabelAndComponent(pane,"Local origin",adjust); JButton reload = new JButton("Reload"); - reload.addActionListener(e-> MeshFactory.reload(mesh) ); + reload.addActionListener(e-> Registry.meshFactory.reload(mesh) ); addLabelAndComponent(pane,"Source",reload); } @@ -102,7 +102,7 @@ public JSONObject toJSON() { public void fromJSON(JSONObject from) { super.fromJSON(from); if(from.has("mesh")) { - mesh = MeshFactory.load(from.getString("mesh")); + mesh = Registry.meshFactory.load(from.getString("mesh")); } } diff --git a/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java b/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java index 876240272..14bdd6aed 100644 --- a/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java +++ b/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java @@ -7,7 +7,6 @@ import javax.imageio.ImageIO; import java.awt.image.BufferedImage; -import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -17,7 +16,7 @@ */ public class TextureFactory { private static final Logger logger = LoggerFactory.getLogger(TextureFactory.class); - private final List textures = new ArrayList<>(); + private final List texturePool = new ArrayList<>(); public TextureFactory() {} @@ -29,13 +28,13 @@ public TextureFactory() {} public TextureWithMetadata load(String filename) { String absolutePath = FileHelper.getAbsolutePathOrFilename(filename); - for(TextureWithMetadata t : textures) { + for(TextureWithMetadata t : texturePool) { if(t.getSource().equals(absolutePath)) { return t; } } TextureWithMetadata t = loadTexture(absolutePath); - if(t!=null) textures.add(t); + if(t!=null) texturePool.add(t); return t; } @@ -54,7 +53,7 @@ private TextureWithMetadata loadTexture(String filename) { * Does not free the underlying {@link BufferedImage} data. */ public void unloadAll() { - for(TextureWithMetadata t : textures) { + for(TextureWithMetadata t : texturePool) { t.unload(); } } @@ -64,7 +63,7 @@ public void unloadAll() { */ public List getAllSourcesForExport() { List result = new ArrayList<>(); - for(TextureWithMetadata t : textures) { + for(TextureWithMetadata t : texturePool) { if(t.isDoNotExport()) continue; result.add(t.getSource()); } From 59fb8357a75e66b228ed9bb6f3411d2d7c37f0b2 Mon Sep 17 00:00:00 2001 From: Dan Royer Date: Sat, 6 Jan 2024 16:27:20 -0800 Subject: [PATCH 3/5] Added MeshChooserDialog --- .../ro3/apps/dialogs/MeshChooserDialog.java | 154 ++++++++++++++++++ .../ro3/apps/dialogs/MeshFactoryDialog.java | 3 +- .../apps/dialogs/TextureFactoryDialog.java | 2 +- .../ro3/mesh/MeshFactory.java | 4 + .../ro3/node/nodes/MeshInstance.java | 7 +- .../ro3/texture/TextureFactory.java | 16 +- .../ro3/apps/dialogs/icons8-mesh-16.png | Bin 0 -> 388 bytes .../marginallyclever/ro3/TestAllPanels.java | 3 +- 8 files changed, 178 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java create mode 100644 src/main/resources/com/marginallyclever/ro3/apps/dialogs/icons8-mesh-16.png diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java new file mode 100644 index 000000000..9e7af27ce --- /dev/null +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java @@ -0,0 +1,154 @@ +package com.marginallyclever.ro3.apps.dialogs; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.Objects; + +import com.marginallyclever.ro3.Registry; +import com.marginallyclever.ro3.listwithevents.ItemAddedListener; +import com.marginallyclever.ro3.listwithevents.ItemRemovedListener; +import com.marginallyclever.ro3.mesh.Mesh; +import com.marginallyclever.ro3.mesh.MeshFactory; + +/** + *

The {@link MeshChooserDialog} class allows for selecting a {@link com.marginallyclever.ro3.mesh.Mesh} + * that has been previously loaded by the {@link MeshFactory}. + * This class also provides access to the {@link MeshFactoryDialog} for loading additional meshes.

+ *

TODO In the future it would be nice to count references to a Mesh and unload it when no longer needed.

+ */ +public class MeshChooserDialog extends JPanel implements ItemAddedListener, ItemRemovedListener { + private final DefaultListModel model = new DefaultListModel<>(); + private final JList meshList = new JList<>(); + private final JToolBar toolBar = new JToolBar(); + private Mesh selectedMesh; + private String viewType; + + public MeshChooserDialog() { + super(new BorderLayout()); + + setupToolbar(); + setupMeshList(); + + var clearButton = new JButton("Clear"); + clearButton.addActionListener(e -> setSelection(null)); + + add(toolBar, BorderLayout.NORTH); + add(new JScrollPane(meshList), BorderLayout.CENTER); + add(clearButton, BorderLayout.SOUTH); + } + + private void setSelection(Mesh mesh) { + selectedMesh = mesh; + if(mesh==null) { + meshList.clearSelection(); + } else { + meshList.setSelectedValue(mesh, true); + } + } + + private void setupToolbar() { + toolBar.add(new JButton(new AbstractAction() { + { + putValue(Action.NAME, "Load Mesh"); + putValue(Action.SHORT_DESCRIPTION, "Load a mesh from a file."); + putValue(Action.SMALL_ICON, new ImageIcon(Objects.requireNonNull(getClass().getResource( + "/com/marginallyclever/ro3/apps/actions/icons8-load-16.png")))); + } + + @Override + public void actionPerformed(ActionEvent e) { + MeshFactoryDialog meshFactoryDialog = new MeshFactoryDialog(); + int result = meshFactoryDialog.run(); + if (result == JFileChooser.APPROVE_OPTION) { + Mesh mesh = meshFactoryDialog.getMesh(); + setSelection(mesh); + } + } + })); + + /* + String[] viewTypes = {"List View", "Detail View", "Thumbnail View"}; + JComboBox viewTypeComboBox = new JComboBox<>(viewTypes); + viewTypeComboBox.addActionListener(e -> { + viewType = (String) viewTypeComboBox.getSelectedItem(); + updateView(); + }); + toolbar.add(viewTypeComboBox); + */ + } + + private void setupMeshList() { + meshList.setCellRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Mesh mesh = (Mesh) value; + String text = mesh.getSourceName() + " (" + mesh.getNumVertices() + " vertices)"; + return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus); + } + }); + + for (Mesh mesh : Registry.meshFactory.getMeshPool().getList()) { + model.addElement(mesh); + } + meshList.setModel(model); + meshList.addListSelectionListener(e -> selectedMesh = meshList.getSelectedValue()); + } + + @Override + public void addNotify() { + super.addNotify(); + Registry.meshFactory.getMeshPool().addItemAddedListener(this); + Registry.meshFactory.getMeshPool().addItemRemovedListener(this); + } + + @Override + public void removeNotify() { + super.removeNotify(); + Registry.meshFactory.getMeshPool().removeItemAddedListener(this); + Registry.meshFactory.getMeshPool().removeItemRemovedListener(this); + } + + private void updateView() { + // Update the list of meshes based on the selected view type + // This could involve changing the ListCellRenderer of the JList + // For example, for the "Thumbnail View", you could display a small preview of each mesh + } + + public Mesh getMesh() { + return selectedMesh; + } + + @Override + public void itemAdded(Object source, Mesh item) { + model.addElement(item); + } + + @Override + public void itemRemoved(Object source, Mesh item) { + model.removeElement(item); + } + + /** + * Run the Mesh selection as a dialog. + * @param parent the parent component for the dialog. + * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION. return type is int because this is a + * JFileChooser replacement. It is consistent with {@link MeshFactoryDialog} and {@link TextureFactoryDialog}. + */ + public int run(JComponent parent) { + int result = JOptionPane.showOptionDialog( + parent, + this, + "Select", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE, + new ImageIcon(Objects.requireNonNull(getClass().getResource( + "/com/marginallyclever/ro3/apps/dialogs/icons8-mesh-16.png"))), + null, + null); + if(result == JOptionPane.OK_OPTION) { + return JFileChooser.APPROVE_OPTION; + } + return JFileChooser.CANCEL_OPTION; + } +} diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java index c56145c84..f30a52ae1 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java @@ -35,8 +35,7 @@ public MeshFactoryDialog() { } /** - * - * @return JFileChooser.APPROVE_OPTION or return JFileChooser.CANCEL_OPTION + * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION */ public int run() { int returnVal = chooser.showDialog(SwingUtilities.getWindowAncestor(chooser), "Select"); diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java index 3e18844ce..6aaf7d1c3 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java @@ -38,7 +38,7 @@ public TextureFactoryDialog() { /** * - * @return JFileChooser.APPROVE_OPTION or return JFileChooser.CANCEL_OPTION + * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION */ public int run() { int returnVal = chooser.showDialog(SwingUtilities.getWindowAncestor(chooser), "Select"); diff --git a/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java b/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java index b702166cd..b699d3c78 100644 --- a/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java +++ b/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java @@ -140,4 +140,8 @@ public List getAllSourcesForExport() { } return result; } + + public ListWithEvents getMeshPool() { + return meshPool; + } } diff --git a/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java b/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java index 46f4d2f07..e2b64b8e5 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java @@ -3,6 +3,7 @@ import com.marginallyclever.convenience.Ray; import com.marginallyclever.convenience.helpers.MatrixHelper; import com.marginallyclever.ro3.Registry; +import com.marginallyclever.ro3.apps.dialogs.MeshChooserDialog; import com.marginallyclever.ro3.apps.dialogs.MeshFactoryDialog; import com.marginallyclever.ro3.mesh.Mesh; import com.marginallyclever.ro3.mesh.MeshSmoother; @@ -44,10 +45,10 @@ public void getComponents(List list) { JButton select = new JButton(); setMeshButtonLabel(select); select.addActionListener(e -> { - MeshFactoryDialog meshFactoryDialog = new MeshFactoryDialog(); - int result = meshFactoryDialog.run(); + var meshChooserDialog = new MeshChooserDialog(); + int result = meshChooserDialog.run(pane); if(result == JFileChooser.APPROVE_OPTION) { - mesh = meshFactoryDialog.getMesh(); + mesh = meshChooserDialog.getMesh(); setMeshButtonLabel(select); } }); diff --git a/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java b/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java index 14bdd6aed..26f4a0566 100644 --- a/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java +++ b/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java @@ -2,6 +2,7 @@ import com.jogamp.opengl.GLAutoDrawable; import com.marginallyclever.convenience.helpers.FileHelper; +import com.marginallyclever.ro3.listwithevents.ListWithEvents; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,7 +17,7 @@ */ public class TextureFactory { private static final Logger logger = LoggerFactory.getLogger(TextureFactory.class); - private final List texturePool = new ArrayList<>(); + private final ListWithEvents texturePool = new ListWithEvents<>(); public TextureFactory() {} @@ -28,7 +29,7 @@ public TextureFactory() {} public TextureWithMetadata load(String filename) { String absolutePath = FileHelper.getAbsolutePathOrFilename(filename); - for(TextureWithMetadata t : texturePool) { + for(TextureWithMetadata t : texturePool.getList()) { if(t.getSource().equals(absolutePath)) { return t; } @@ -53,7 +54,7 @@ private TextureWithMetadata loadTexture(String filename) { * Does not free the underlying {@link BufferedImage} data. */ public void unloadAll() { - for(TextureWithMetadata t : texturePool) { + for(TextureWithMetadata t : texturePool.getList()) { t.unload(); } } @@ -63,10 +64,17 @@ public void unloadAll() { */ public List getAllSourcesForExport() { List result = new ArrayList<>(); - for(TextureWithMetadata t : texturePool) { + for(TextureWithMetadata t : texturePool.getList()) { if(t.isDoNotExport()) continue; result.add(t.getSource()); } return result; } + + /** + * @return a list of all the textures loaded. + */ + public ListWithEvents getAllTextures() { + return texturePool; + } } diff --git a/src/main/resources/com/marginallyclever/ro3/apps/dialogs/icons8-mesh-16.png b/src/main/resources/com/marginallyclever/ro3/apps/dialogs/icons8-mesh-16.png new file mode 100644 index 0000000000000000000000000000000000000000..732be97101b6f95ede160fdb9a8ec128005ce3c2 GIT binary patch literal 388 zcmV-~0ek+5P)|>O?0wa_B$szsiPnNQ6ci=r1QWrz~_Rz*j{OzZ; zS~^;aNTVYOcsW_z<0rnv-!L{RAvOXmoz3GFe#FK-=HqiA7Yg}ne(7jJ-pQ|hhwEnZ zP|u*0CB&Y}cd^-zy@%}!isD~ef2Rl+NSQ_^3-K{Ij#rTvobOjf i9h Date: Sat, 6 Jan 2024 17:07:23 -0800 Subject: [PATCH 4/5] added TextureChooserDialog --- .../ro3/apps/dialogs/MeshChooserDialog.java | 42 ++--- .../ro3/apps/dialogs/MeshFactoryDialog.java | 6 +- .../apps/dialogs/TextureChooserDialog.java | 154 ++++++++++++++++++ .../apps/dialogs/TextureFactoryDialog.java | 8 +- .../ro3/mesh/MeshFactory.java | 2 +- .../ro3/node/nodes/Material.java | 36 +++- .../ro3/node/nodes/MeshInstance.java | 4 +- .../nodes/marlinrobotarm/MarlinRobotArm.java | 2 +- .../ro3/texture/TextureFactory.java | 16 +- .../ro3/apps/dialogs/icons8-texture-16.png | Bin 0 -> 292 bytes 10 files changed, 228 insertions(+), 42 deletions(-) create mode 100644 src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureChooserDialog.java create mode 100644 src/main/resources/com/marginallyclever/ro3/apps/dialogs/icons8-texture-16.png diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java index 9e7af27ce..c9902f741 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshChooserDialog.java @@ -15,13 +15,13 @@ *

The {@link MeshChooserDialog} class allows for selecting a {@link com.marginallyclever.ro3.mesh.Mesh} * that has been previously loaded by the {@link MeshFactory}. * This class also provides access to the {@link MeshFactoryDialog} for loading additional meshes.

- *

TODO In the future it would be nice to count references to a Mesh and unload it when no longer needed.

+ *

TODO In the future it would be nice to count references and unload it when no longer needed.

*/ public class MeshChooserDialog extends JPanel implements ItemAddedListener, ItemRemovedListener { private final DefaultListModel model = new DefaultListModel<>(); - private final JList meshList = new JList<>(); + private final JList list = new JList<>(); private final JToolBar toolBar = new JToolBar(); - private Mesh selectedMesh; + private Mesh selectedItem; private String viewType; public MeshChooserDialog() { @@ -31,19 +31,19 @@ public MeshChooserDialog() { setupMeshList(); var clearButton = new JButton("Clear"); - clearButton.addActionListener(e -> setSelection(null)); + clearButton.addActionListener(e -> setSelectedItem(null)); add(toolBar, BorderLayout.NORTH); - add(new JScrollPane(meshList), BorderLayout.CENTER); + add(new JScrollPane(list), BorderLayout.CENTER); add(clearButton, BorderLayout.SOUTH); } - private void setSelection(Mesh mesh) { - selectedMesh = mesh; + public void setSelectedItem(Mesh mesh) { + selectedItem = mesh; if(mesh==null) { - meshList.clearSelection(); + list.clearSelection(); } else { - meshList.setSelectedValue(mesh, true); + list.setSelectedValue(mesh, true); } } @@ -62,7 +62,7 @@ public void actionPerformed(ActionEvent e) { int result = meshFactoryDialog.run(); if (result == JFileChooser.APPROVE_OPTION) { Mesh mesh = meshFactoryDialog.getMesh(); - setSelection(mesh); + setSelectedItem(mesh); } } })); @@ -79,7 +79,7 @@ public void actionPerformed(ActionEvent e) { } private void setupMeshList() { - meshList.setCellRenderer(new DefaultListCellRenderer() { + list.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Mesh mesh = (Mesh) value; @@ -88,25 +88,25 @@ public Component getListCellRendererComponent(JList list, Object value, int i } }); - for (Mesh mesh : Registry.meshFactory.getMeshPool().getList()) { + for (Mesh mesh : Registry.meshFactory.getPool().getList()) { model.addElement(mesh); } - meshList.setModel(model); - meshList.addListSelectionListener(e -> selectedMesh = meshList.getSelectedValue()); + list.setModel(model); + list.addListSelectionListener(e -> selectedItem = list.getSelectedValue()); } @Override public void addNotify() { super.addNotify(); - Registry.meshFactory.getMeshPool().addItemAddedListener(this); - Registry.meshFactory.getMeshPool().addItemRemovedListener(this); + Registry.meshFactory.getPool().addItemAddedListener(this); + Registry.meshFactory.getPool().addItemRemovedListener(this); } @Override public void removeNotify() { super.removeNotify(); - Registry.meshFactory.getMeshPool().removeItemAddedListener(this); - Registry.meshFactory.getMeshPool().removeItemRemovedListener(this); + Registry.meshFactory.getPool().removeItemAddedListener(this); + Registry.meshFactory.getPool().removeItemRemovedListener(this); } private void updateView() { @@ -115,8 +115,8 @@ private void updateView() { // For example, for the "Thumbnail View", you could display a small preview of each mesh } - public Mesh getMesh() { - return selectedMesh; + public Mesh getSelectedItem() { + return selectedItem; } @Override @@ -130,7 +130,7 @@ public void itemRemoved(Object source, Mesh item) { } /** - * Run the Mesh selection as a dialog. + * Run the selection as a dialog. * @param parent the parent component for the dialog. * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION. return type is int because this is a * JFileChooser replacement. It is consistent with {@link MeshFactoryDialog} and {@link TextureFactoryDialog}. diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java index f30a52ae1..7f87090e0 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/MeshFactoryDialog.java @@ -17,14 +17,14 @@ */ public class MeshFactoryDialog { private static final Logger logger = LoggerFactory.getLogger(MeshFactoryDialog.class); - private static final JFileChooser chooser = new PersistentJFileChooser(); + private final PersistentJFileChooser chooser = new PersistentJFileChooser(); private Mesh lastMeshLoaded; public MeshFactoryDialog() { super(); List filters = Registry.meshFactory.getAllExtensions(); - if (filters.isEmpty()) throw new RuntimeException("No MeshFactory filters found?!"); + if (filters.isEmpty()) throw new RuntimeException("No filters found?!"); if (filters.size() == 1) { chooser.setFileFilter(filters.get(0)); } else { @@ -38,7 +38,7 @@ public MeshFactoryDialog() { * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION */ public int run() { - int returnVal = chooser.showDialog(SwingUtilities.getWindowAncestor(chooser), "Select"); + int returnVal = chooser.showOpenDialog(SwingUtilities.getWindowAncestor(chooser)); if(returnVal == JFileChooser.APPROVE_OPTION) { String absPath = chooser.getSelectedFile().getAbsolutePath(); try { diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureChooserDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureChooserDialog.java new file mode 100644 index 000000000..5c061ff88 --- /dev/null +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureChooserDialog.java @@ -0,0 +1,154 @@ +package com.marginallyclever.ro3.apps.dialogs; + +import com.marginallyclever.ro3.Registry; +import com.marginallyclever.ro3.listwithevents.ItemAddedListener; +import com.marginallyclever.ro3.listwithevents.ItemRemovedListener; +import com.marginallyclever.ro3.texture.TextureWithMetadata; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.Objects; + +/** + *

The {@link TextureChooserDialog} class allows for selecting a {@link com.marginallyclever.ro3.texture.TextureWithMetadata} + * that has been previously loaded by the {@link com.marginallyclever.ro3.texture.TextureFactory}. + * This class also provides access to the {@link TextureFactoryDialog} for loading additional meshes.

+ *

TODO In the future it would be nice to count references and unload it when no longer needed.

+ */ +public class TextureChooserDialog extends JPanel + implements ItemAddedListener, ItemRemovedListener { + private final DefaultListModel model = new DefaultListModel<>(); + private final JList list = new JList<>(); + private final JToolBar toolBar = new JToolBar(); + private TextureWithMetadata selectedItem; + private String viewType; + + public TextureChooserDialog() { + super(new BorderLayout()); + + setupToolbar(); + setupMeshList(); + + var clearButton = new JButton("Clear"); + clearButton.addActionListener(e -> setSelectedItem(null)); + + add(toolBar, BorderLayout.NORTH); + add(new JScrollPane(list), BorderLayout.CENTER); + add(clearButton, BorderLayout.SOUTH); + } + + public void setSelectedItem(TextureWithMetadata mesh) { + selectedItem = mesh; + if (mesh == null) { + list.clearSelection(); + } else { + list.setSelectedValue(mesh, true); + } + } + + private void setupToolbar() { + toolBar.add(new JButton(new AbstractAction() { + { + putValue(Action.NAME, "Load Texture"); + putValue(Action.SHORT_DESCRIPTION, "Load a texture from a file."); + putValue(Action.SMALL_ICON, new ImageIcon(Objects.requireNonNull(getClass().getResource( + "/com/marginallyclever/ro3/apps/actions/icons8-load-16.png")))); + } + + @Override + public void actionPerformed(ActionEvent e) { + var textureFactoryDialog = new TextureFactoryDialog(); + int result = textureFactoryDialog.run(); + if (result == JFileChooser.APPROVE_OPTION) { + TextureWithMetadata mesh = textureFactoryDialog.getTexture(); + setSelectedItem(mesh); + } + } + })); + + /* + String[] viewTypes = {"List View", "Detail View", "Thumbnail View"}; + JComboBox viewTypeComboBox = new JComboBox<>(viewTypes); + viewTypeComboBox.addActionListener(e -> { + viewType = (String) viewTypeComboBox.getSelectedItem(); + updateView(); + }); + toolbar.add(viewTypeComboBox); + */ + } + + private void setupMeshList() { + list.setCellRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + TextureWithMetadata item = (TextureWithMetadata) value; + String text = item.getSource() + " (" + item.getWidth()+"x"+item.getHeight()+")"; + return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus); + } + }); + + for (TextureWithMetadata mesh : Registry.textureFactory.getPool().getList()) { + model.addElement(mesh); + } + list.setModel(model); + list.addListSelectionListener(e -> selectedItem = list.getSelectedValue()); + } + + @Override + public void addNotify() { + super.addNotify(); + Registry.textureFactory.getPool().addItemAddedListener(this); + Registry.textureFactory.getPool().addItemRemovedListener(this); + } + + @Override + public void removeNotify() { + super.removeNotify(); + Registry.textureFactory.getPool().removeItemAddedListener(this); + Registry.textureFactory.getPool().removeItemRemovedListener(this); + } + + private void updateView() { + // Update the list of meshes based on the selected view type + // This could involve changing the ListCellRenderer of the JList + // For example, for the "Thumbnail View", you could display a small preview of each mesh + } + + public TextureWithMetadata getSelectedItem() { + return selectedItem; + } + + @Override + public void itemAdded(Object source, TextureWithMetadata item) { + model.addElement(item); + } + + @Override + public void itemRemoved(Object source, TextureWithMetadata item) { + model.removeElement(item); + } + + /** + * Run the selection as a dialog. + * @param parent the parent component for the dialog. + * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION. return type is int because this is a + * JFileChooser replacement. It is consistent with {@link MeshFactoryDialog} and {@link TextureFactoryDialog}. + */ + public int run(JComponent parent) { + int result = JOptionPane.showOptionDialog( + parent, + this, + "Select", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE, + new ImageIcon(Objects.requireNonNull(getClass().getResource( + "/com/marginallyclever/ro3/apps/dialogs/icons8-texture-16.png"))), + null, + null); + if(result == JOptionPane.OK_OPTION) { + return JFileChooser.APPROVE_OPTION; + } + return JFileChooser.CANCEL_OPTION; + } +} diff --git a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java index 6aaf7d1c3..7528374cb 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/dialogs/TextureFactoryDialog.java @@ -19,14 +19,14 @@ */ public class TextureFactoryDialog { private static final Logger logger = LoggerFactory.getLogger(TextureFactoryDialog.class); - private static final JFileChooser chooser = new PersistentJFileChooser(); + private final PersistentJFileChooser chooser = new PersistentJFileChooser(); private TextureWithMetadata lastTextureLoaded; public TextureFactoryDialog() { super(); - List filters = Registry.meshFactory.getAllExtensions(); - if (filters.isEmpty()) throw new RuntimeException("No MeshFactory filters found?!"); + List filters = Registry.textureFactory.getAllExtensions(); + if (filters.isEmpty()) throw new RuntimeException("No filters found?!"); if (filters.size() == 1) { chooser.setFileFilter(filters.get(0)); } else { @@ -41,7 +41,7 @@ public TextureFactoryDialog() { * @return JFileChooser.APPROVE_OPTION or JFileChooser.CANCEL_OPTION */ public int run() { - int returnVal = chooser.showDialog(SwingUtilities.getWindowAncestor(chooser), "Select"); + int returnVal = chooser.showOpenDialog(SwingUtilities.getWindowAncestor(chooser)); if(returnVal == JFileChooser.APPROVE_OPTION) { String absPath = chooser.getSelectedFile().getAbsolutePath(); lastTextureLoaded = Registry.textureFactory.load(absPath); diff --git a/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java b/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java index b699d3c78..ad40d2d9b 100644 --- a/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java +++ b/src/main/java/com/marginallyclever/ro3/mesh/MeshFactory.java @@ -141,7 +141,7 @@ public List getAllSourcesForExport() { return result; } - public ListWithEvents getMeshPool() { + public ListWithEvents getPool() { return meshPool; } } diff --git a/src/main/java/com/marginallyclever/ro3/node/nodes/Material.java b/src/main/java/com/marginallyclever/ro3/node/nodes/Material.java index cf51f9e09..5cc66262d 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodes/Material.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodes/Material.java @@ -1,8 +1,8 @@ package com.marginallyclever.ro3.node.nodes; import com.marginallyclever.ro3.Registry; +import com.marginallyclever.ro3.apps.dialogs.TextureChooserDialog; import com.marginallyclever.ro3.node.Node; -import com.marginallyclever.ro3.apps.dialogs.TextureFactoryDialog; import com.marginallyclever.ro3.texture.TextureWithMetadata; import org.json.JSONObject; @@ -58,10 +58,11 @@ public void getComponents(List list) { JButton button = new JButton(); setTextureButtonLabel(button); button.addActionListener(e -> { - TextureFactoryDialog textureFactoryDialog = new TextureFactoryDialog(); - int result = textureFactoryDialog.run(); + var textureChooserDialog = new TextureChooserDialog(); + textureChooserDialog.setSelectedItem(texture); + int result = textureChooserDialog.run(pane); if(result == JFileChooser.APPROVE_OPTION) { - texture = textureFactoryDialog.getTexture(); + texture = textureChooserDialog.getSelectedItem(); setTextureButtonLabel(button); } }); @@ -103,20 +104,37 @@ public void getComponents(List list) { }); addLabelAndComponent(pane,"Emissive",selectColorEmission,gbc); - // shininess - JSlider shininessSlider = new JSlider(0,128,getShininess()); - shininessSlider.addChangeListener(e -> setShininess(shininessSlider.getValue())); - addLabelAndComponent(pane,"Shininess",shininessSlider,gbc); - // lit JToggleButton isLitButton = new JToggleButton("Lit",isLit()); isLitButton.addActionListener(e -> setLit(isLitButton.isSelected())); addLabelAndComponent(pane,"Lit",isLitButton,gbc); + // shininess + gbc.gridx=0; + gbc.gridy++; + gbc.gridwidth=2; + pane.add(createShininessSlider(),gbc); + super.getComponents(list); } + private JComponent createShininessSlider() { + JPanel container = new JPanel(new BorderLayout()); + + JSlider slider = new JSlider(0,128,getShininess()); + slider.addChangeListener(e -> setShininess(slider.getValue())); + + // Make the slider fill the available horizontal space + slider.setMaximumSize(new Dimension(Integer.MAX_VALUE, slider.getPreferredSize().height)); + slider.setMinimumSize(new Dimension(50, slider.getPreferredSize().height)); + + container.add(new JLabel("Shininess"), BorderLayout.LINE_START); + container.add(slider, BorderLayout.CENTER); // Add slider to the center of the container + + return container; + } + public BufferedImage scaleImage(BufferedImage sourceImage,int size) { Image tmp = sourceImage.getScaledInstance(size, size, Image.SCALE_SMOOTH); BufferedImage scaledImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); diff --git a/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java b/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java index e2b64b8e5..4e3d31ec5 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodes/MeshInstance.java @@ -4,7 +4,6 @@ import com.marginallyclever.convenience.helpers.MatrixHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.apps.dialogs.MeshChooserDialog; -import com.marginallyclever.ro3.apps.dialogs.MeshFactoryDialog; import com.marginallyclever.ro3.mesh.Mesh; import com.marginallyclever.ro3.mesh.MeshSmoother; import com.marginallyclever.ro3.raypicking.RayHit; @@ -46,9 +45,10 @@ public void getComponents(List list) { setMeshButtonLabel(select); select.addActionListener(e -> { var meshChooserDialog = new MeshChooserDialog(); + meshChooserDialog.setSelectedItem(mesh); int result = meshChooserDialog.run(pane); if(result == JFileChooser.APPROVE_OPTION) { - mesh = meshChooserDialog.getMesh(); + mesh = meshChooserDialog.getSelectedItem(); setMeshButtonLabel(select); } }); diff --git a/src/main/java/com/marginallyclever/ro3/node/nodes/marlinrobotarm/MarlinRobotArm.java b/src/main/java/com/marginallyclever/ro3/node/nodes/marlinrobotarm/MarlinRobotArm.java index 27f53fae1..e54022a16 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodes/marlinrobotarm/MarlinRobotArm.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodes/marlinrobotarm/MarlinRobotArm.java @@ -187,11 +187,11 @@ private JComponent createVelocitySlider() { // Make the slider fill the available horizontal space slider.setMaximumSize(new Dimension(Integer.MAX_VALUE, slider.getPreferredSize().height)); + slider.setMinimumSize(new Dimension(50, slider.getPreferredSize().height)); container.add(new JLabel("Linear Vel"), BorderLayout.LINE_START); container.add(slider, BorderLayout.CENTER); // Add slider to the center of the container - return container; } diff --git a/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java b/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java index 26f4a0566..6ac040085 100644 --- a/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java +++ b/src/main/java/com/marginallyclever/ro3/texture/TextureFactory.java @@ -7,6 +7,8 @@ import org.slf4j.LoggerFactory; import javax.imageio.ImageIO; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; @@ -74,7 +76,19 @@ public List getAllSourcesForExport() { /** * @return a list of all the textures loaded. */ - public ListWithEvents getAllTextures() { + public ListWithEvents getPool() { return texturePool; } + + public List getAllExtensions() { + List result = new ArrayList<>(); + String[] suffixes = ImageIO.getReaderFileSuffixes(); + + for (String suffix : suffixes) { + FileFilter filter = new FileNameExtensionFilter(suffix + " files", suffix); + result.add(filter); + } + + return result; + } } diff --git a/src/main/resources/com/marginallyclever/ro3/apps/dialogs/icons8-texture-16.png b/src/main/resources/com/marginallyclever/ro3/apps/dialogs/icons8-texture-16.png new file mode 100644 index 0000000000000000000000000000000000000000..ba0766be2d16738d9afcf29b3ba94db1bf5079de GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1F_k zi(^Q|oa6)vlLdRqUwyss=hc73%Fqf!kF$HWM)N002za%m3C!D-^Y;Jha``_;4HQ^B z14}$@BOYFBK7O#`)TXWf7k4WrU4LiGl01jaW%`x>_sd_=IkM{j%g|LE*;4rv3? zlVTEVosCbPt-0xQqd}LwKlv)pp{ Date: Sat, 6 Jan 2024 17:08:28 -0800 Subject: [PATCH 5/5] 2.101.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index edd895a4c..cbf2f228f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.marginallyclever RobotOverlord - 2.100.0 + 2.101.0 Robot Overlord A friendly 3D user interface for controlling robots. https://www.marginallyclever.com/