From 354c05fa603527108c5b6b14861f2778f7debb0c Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Thu, 1 Jul 2021 20:04:46 +0200 Subject: [PATCH 01/11] [fixes #969] Added custom left and right side appearance fins --- core/resources/l10n/messages.properties | 6 ++ .../sf/openrocket/rocketcomponent/FinSet.java | 64 ++++++++++++-- .../gui/configdialog/AppearancePanel.java | 39 +++++++-- .../gui/figure3d/RealisticRenderer.java | 6 +- .../figure3d/geometry/ComponentRenderer.java | 4 +- .../gui/figure3d/geometry/FinRenderer.java | 85 ++++++++++--------- 6 files changed, 144 insertions(+), 60 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index f843f23e7..86757cfd9 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -810,9 +810,13 @@ AppearanceCfg.lbl.texture.center = Center: AppearanceCfg.lbl.texture.rotation = Rotation: AppearanceCfg.lbl.texture.repeat = Repeat: AppearanceCfg.lbl.InsideSameAsOutside = Same as outside +AppearanceCfg.lbl.LeftSideSameAsRightSide = Same as right side AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use the same appearance for the inside as for the outside +AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use the same appearance for the left side as for the right side AppearanceCfg.lbl.EdgesSameAsInside = Use inside appearance for edges +AppearanceCfg.lbl.EdgesSameAsLeftSide = Use left side appearance for edges AppearanceCfg.lbl.ttip.EdgesSameAsInside = Use the inside appearance (checked) or outside appearance (unchecked) for the edges +AppearanceCfg.lbl.ttip.EdgesSameAsLeftSide = Use the left side appearance (checked) or right side appearance (unchecked) for the edges ! Texture Wrap Modes TextureWrap.Repeat = Repeat @@ -878,6 +882,8 @@ RocketCompCfg.lbl.InstanceCount = Instance Count RocketCompCfg.lbl.InstanceSeparation = Instance Separation RocketCompCfg.tab.Outside = Outside RocketCompCfg.tab.Inside = Inside +RocketCompCfg.tab.RightSide = Right Side +RocketCompCfg.tab.LeftSide = Left Side ! BulkheadConfig BulkheadCfg.tab.Diameter = Diameter: diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java index 7c07b0c57..7c6e637a2 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java @@ -1,12 +1,13 @@ package net.sf.openrocket.rocketcomponent; import java.awt.geom.Point2D; +import java.util.*; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import net.sf.openrocket.appearance.Appearance; +import net.sf.openrocket.appearance.Decal; +import net.sf.openrocket.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,15 +19,10 @@ import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.AxialPositionable; import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.rocketcomponent.Transition.Shape; -import net.sf.openrocket.util.Coordinate; -import net.sf.openrocket.util.MathUtil; -import net.sf.openrocket.util.Transformation; - -public abstract class FinSet extends ExternalComponent implements AxialPositionable, BoxBounded, RingInstanceable { +public abstract class FinSet extends ExternalComponent implements AxialPositionable, BoxBounded, RingInstanceable, InsideColorComponent { private static final Logger log = LoggerFactory.getLogger(FinSet.class); private static final Translator trans = Application.getTranslator(); @@ -125,6 +121,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona private double singlePlanformArea = Double.NaN; private double totalVolume = Double.NaN; private Coordinate centerOfMass = Coordinate.NaN; + + // Settings for inside/edge appearance + private Appearance insideAppearance = null; + private boolean insideSameAsOutside = true; + private boolean edgesSameAsInside = true; /** * New FinSet with given number of fins and given base rotation angle. @@ -1269,4 +1270,49 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona return toReturn; } + + @Override + public Appearance getInsideAppearance() { + return this.insideAppearance; + } + + @Override + public void setInsideAppearance(Appearance appearance) { + this.insideAppearance = appearance; + if (this.insideAppearance != null) { + Decal d = this.insideAppearance.getTexture(); + if (d != null) { + d.getImage().addChangeListener(new StateChangeListener() { + + @Override + public void stateChanged(EventObject e) { + fireComponentChangeEvent(ComponentChangeEvent.TEXTURE_CHANGE); + } + + }); + } + } + // CHECK - should this be a TEXTURE_CHANGE and not NONFUNCTIONAL_CHANGE? + fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); + } + + @Override + public boolean isEdgesSameAsInside() { + return this.edgesSameAsInside; + } + + @Override + public void setEdgesSameAsInside(boolean newState) { + this.edgesSameAsInside = newState; + } + + @Override + public boolean isInsideSameAsOutside() { + return this.insideSameAsOutside; + } + + @Override + public void setInsideSameAsOutside(boolean newState) { + this.insideSameAsOutside = newState; + } } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index a0bee20fa..9149f995c 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -34,6 +34,7 @@ import net.sf.openrocket.gui.util.EditDecalHelper.EditDecalHelperException; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; +import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.InsideColorComponent; import net.sf.openrocket.rocketcomponent.InsideColorComponentHandler; import net.sf.openrocket.rocketcomponent.RocketComponent; @@ -309,17 +310,32 @@ public class AppearancePanel extends JPanel { appearanceSection(document, c, false, outsidePanel); appearanceSection(document, c, true, insidePanel); - tabbedPane.addTab(trans.get("RocketCompCfg.tab.Outside"), null, outsidePanel, + // Get translator keys + String tr_outside, tr_inside, tr_edges, tr_edges_ttip; + if (c instanceof FinSet) { + tr_outside = "RocketCompCfg.tab.RightSide"; + tr_inside = "RocketCompCfg.tab.LeftSide"; + tr_edges = "AppearanceCfg.lbl.EdgesSameAsLeftSide"; + tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsLeftSide"; + } + else { + tr_outside = "RocketCompCfg.tab.Outside"; + tr_inside = "RocketCompCfg.tab.Inside"; + tr_edges = "AppearanceCfg.lbl.EdgesSameAsInside"; + tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsInside"; + } + + tabbedPane.addTab(trans.get(tr_outside), null, outsidePanel, "Outside Tool Tip"); - tabbedPane.addTab(trans.get("RocketCompCfg.tab.Inside"), null, insidePanel, + tabbedPane.addTab(trans.get(tr_inside), null, insidePanel, "Inside Tool Tip"); add(tabbedPane, "span 4, growx, wrap"); // Checkbox to set edges the same as inside/outside BooleanModel b = new BooleanModel(handler.isEdgesSameAsInside()); JCheckBox edges = new JCheckBox(b); - edges.setText(trans.get("AppearanceCfg.lbl.EdgesSameAsInside")); - edges.setToolTipText(trans.get("AppearanceCfg.lbl.ttip.EdgesSameAsInside")); + edges.setText(trans.get(tr_edges)); + edges.setToolTipText(trans.get(tr_edges_ttip)); add(edges, "wrap"); edges.addActionListener(new ActionListener() { @@ -406,13 +422,24 @@ public class AppearancePanel extends JPanel { else panel.add(materialDefault, "wrap"); + // Get translation keys + String tr_insideOutside, tr_insideOutside_ttip; + if (c instanceof FinSet) { + tr_insideOutside = "AppearanceCfg.lbl.LeftSideSameAsRightSide"; + tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide"; + } + else { + tr_insideOutside = "AppearanceCfg.lbl.InsideSameAsOutside"; + tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.InsideSameAsOutside"; + } + // Custom inside color if (insideBuilder) { InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); BooleanModel b = new BooleanModel(handler.isInsideSameAsOutside()); JCheckBox customInside = new JCheckBox(b); - customInside.setText(trans.get("AppearanceCfg.lbl.InsideSameAsOutside")); - customInside.setToolTipText(trans.get("AppearanceCfg.lbl.ttip.InsideSameAsOutside")); + customInside.setText(trans.get(tr_insideOutside)); + customInside.setToolTipText(trans.get(tr_insideOutside_ttip)); customInside.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { diff --git a/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java index 9b155748a..62e480053 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java @@ -99,13 +99,13 @@ public class RealisticRenderer extends RocketRenderer { render(gl, geom, Surface.INSIDE, innerApp, true, alpha); if (((InsideColorComponent) c).getInsideColorComponentHandler().isEdgesSameAsInside()) - render(gl, geom, Surface.EDGES, innerApp, false, alpha); + render(gl, geom, Surface.EDGES, innerApp, true, alpha); else - render(gl, geom, Surface.EDGES, app, false, alpha); + render(gl, geom, Surface.EDGES, app, true, alpha); } else { render(gl, geom, Surface.INSIDE, app, true, alpha); - render(gl, geom, Surface.EDGES, app, false, alpha); + render(gl, geom, Surface.EDGES, app, true, alpha); } render(gl, geom, Surface.OUTSIDE, app, true, alpha); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java index e239701b6..2f364d708 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java @@ -112,9 +112,7 @@ public class ComponentRenderer { renderMassObject(gl, (MassObject) c); } else if (c instanceof FinSet) { FinSet fins = (FinSet) c; - if (which == Surface.OUTSIDE) { - fr.renderFinSet(gl, fins); - } + fr.renderFinSet(gl, fins, which); } else if (c instanceof TubeFinSet) { renderTubeFins( gl, (TubeFinSet) c, which); } else if ( c instanceof AxialStage ) { diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java index ddd3acf66..1fb457e1e 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java @@ -13,11 +13,12 @@ import net.sf.openrocket.rocketcomponent.EllipticalFinSet; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface; public class FinRenderer { private GLUtessellator tobj = GLU.gluNewTess(); - public void renderFinSet(final GL2 gl, FinSet finSet ) { + public void renderFinSet(final GL2 gl, FinSet finSet, Surface which) { BoundingBox bounds = finSet.getInstanceBoundingBox(); gl.glMatrixMode(GL.GL_TEXTURE); @@ -61,51 +62,57 @@ public class FinRenderer { GLU.gluTessCallback(tobj, GLU.GLU_TESS_END, cb); // fin side: +z - GLU.gluTessBeginPolygon(tobj, null); - GLU.gluTessBeginContour(tobj); - gl.glNormal3f(0, 0, 1); - for (int i = finPoints.length - 1; i >= 0; i--) { - Coordinate c = finPoints[i]; - double[] p = new double[] { c.x, c.y + finSet.getBodyRadius(), - c.z + finSet.getThickness() / 2.0 }; - GLU.gluTessVertex(tobj, p, 0, p); - + if (which == Surface.OUTSIDE) { + GLU.gluTessBeginPolygon(tobj, null); + GLU.gluTessBeginContour(tobj); + gl.glNormal3f(0, 0, 1); + for (int i = finPoints.length - 1; i >= 0; i--) { + Coordinate c = finPoints[i]; + double[] p = new double[]{c.x, c.y + finSet.getBodyRadius(), + c.z + finSet.getThickness() / 2.0}; + GLU.gluTessVertex(tobj, p, 0, p); + + } + GLU.gluTessEndContour(tobj); + GLU.gluTessEndPolygon(tobj); } - GLU.gluTessEndContour(tobj); - GLU.gluTessEndPolygon(tobj); // fin side: -z - GLU.gluTessBeginPolygon(tobj, null); - GLU.gluTessBeginContour(tobj); - gl.glNormal3f(0, 0, -1); - for (int i = 0; i < finPoints.length; i++) { - Coordinate c = finPoints[i]; - double[] p = new double[] { c.x, c.y + finSet.getBodyRadius(), - c.z - finSet.getThickness() / 2.0 }; - GLU.gluTessVertex(tobj, p, 0, p); - + if (which == Surface.INSIDE) { + GLU.gluTessBeginPolygon(tobj, null); + GLU.gluTessBeginContour(tobj); + gl.glNormal3f(0, 0, -1); + for (int i = 0; i < finPoints.length; i++) { + Coordinate c = finPoints[i]; + double[] p = new double[]{c.x, c.y + finSet.getBodyRadius(), + c.z - finSet.getThickness() / 2.0}; + GLU.gluTessVertex(tobj, p, 0, p); + + } + GLU.gluTessEndContour(tobj); + GLU.gluTessEndPolygon(tobj); } - GLU.gluTessEndContour(tobj); - GLU.gluTessEndPolygon(tobj); // Strip around the edge - if (!(finSet instanceof EllipticalFinSet)) - gl.glShadeModel(GLLightingFunc.GL_FLAT); - gl.glBegin(GL.GL_TRIANGLE_STRIP); - for (int i = 0; i <= finPoints.length; i++) { - Coordinate c = finPoints[i % finPoints.length]; - // if ( i > 1 ){ - Coordinate c2 = finPoints[(i - 1 + finPoints.length) - % finPoints.length]; - gl.glNormal3d(c2.y - c.y, c.x - c2.x, 0); - // } - gl.glTexCoord2d(c.x, c.y + finSet.getBodyRadius()); - gl.glVertex3d(c.x, c.y + finSet.getBodyRadius(), - c.z - finSet.getThickness() / 2.0); - gl.glVertex3d(c.x, c.y + finSet.getBodyRadius(), - c.z + finSet.getThickness() / 2.0); + if (which == Surface.EDGES) { + if (!(finSet instanceof EllipticalFinSet)) + gl.glShadeModel(GLLightingFunc.GL_FLAT); + gl.glBegin(GL.GL_TRIANGLE_STRIP); + for (int i = 0; i <= finPoints.length; i++) { + Coordinate c = finPoints[i % finPoints.length]; + // if ( i > 1 ){ + Coordinate c2 = finPoints[(i - 1 + finPoints.length) + % finPoints.length]; + gl.glNormal3d(c2.y - c.y, c.x - c2.x, 0); + // } + gl.glTexCoord2d(c.x, c.y + finSet.getBodyRadius()); + gl.glVertex3d(c.x, c.y + finSet.getBodyRadius(), + c.z - finSet.getThickness() / 2.0); + gl.glVertex3d(c.x, c.y + finSet.getBodyRadius(), + c.z + finSet.getThickness() / 2.0); + } + gl.glEnd(); } - gl.glEnd(); if (!(finSet instanceof EllipticalFinSet)) gl.glShadeModel(GLLightingFunc.GL_SMOOTH); From 34ddba4e2f68b914c5ebc5fb445cf608c5538912 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Tue, 13 Jul 2021 20:25:59 +0200 Subject: [PATCH 02/11] [fixes #969] Updated custom FinSet appearance with unstable --- .../sf/openrocket/rocketcomponent/FinSet.java | 49 ++----------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java index 7c6e637a2..b298608bc 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java @@ -122,10 +122,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona private double totalVolume = Double.NaN; private Coordinate centerOfMass = Coordinate.NaN; - // Settings for inside/edge appearance - private Appearance insideAppearance = null; - private boolean insideSameAsOutside = true; - private boolean edgesSameAsInside = true; + private final InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this); /** * New FinSet with given number of fins and given base rotation angle. @@ -1272,47 +1269,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona } @Override - public Appearance getInsideAppearance() { - return this.insideAppearance; - } - - @Override - public void setInsideAppearance(Appearance appearance) { - this.insideAppearance = appearance; - if (this.insideAppearance != null) { - Decal d = this.insideAppearance.getTexture(); - if (d != null) { - d.getImage().addChangeListener(new StateChangeListener() { - - @Override - public void stateChanged(EventObject e) { - fireComponentChangeEvent(ComponentChangeEvent.TEXTURE_CHANGE); - } - - }); - } - } - // CHECK - should this be a TEXTURE_CHANGE and not NONFUNCTIONAL_CHANGE? - fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); - } - - @Override - public boolean isEdgesSameAsInside() { - return this.edgesSameAsInside; - } - - @Override - public void setEdgesSameAsInside(boolean newState) { - this.edgesSameAsInside = newState; - } - - @Override - public boolean isInsideSameAsOutside() { - return this.insideSameAsOutside; - } - - @Override - public void setInsideSameAsOutside(boolean newState) { - this.insideSameAsOutside = newState; + public InsideColorComponentHandler getInsideColorComponentHandler() { + return this.insideColorComponentHandler; } } From d9566dd5583789928ac9c2d38dc5605950cc082e Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Sun, 25 Jul 2021 23:46:31 +0200 Subject: [PATCH 03/11] [fixes #969] Switched right/left tab + switched checkbox position + mirrored right side decal --- core/resources/l10n/messages.properties | 8 ++++---- .../gui/configdialog/AppearancePanel.java | 16 ++++++++-------- .../gui/figure3d/geometry/FinRenderer.java | 12 +++++++++--- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 86757cfd9..6faa2e52e 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -809,14 +809,14 @@ AppearanceCfg.lbl.texture.offset = Offset: AppearanceCfg.lbl.texture.center = Center: AppearanceCfg.lbl.texture.rotation = Rotation: AppearanceCfg.lbl.texture.repeat = Repeat: -AppearanceCfg.lbl.InsideSameAsOutside = Same as outside +AppearanceCfg.lbl.InsideSameAsOutside = Same as inside AppearanceCfg.lbl.LeftSideSameAsRightSide = Same as right side AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use the same appearance for the inside as for the outside -AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use the same appearance for the left side as for the right side +AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use the same appearance for the right side as for the left side AppearanceCfg.lbl.EdgesSameAsInside = Use inside appearance for edges -AppearanceCfg.lbl.EdgesSameAsLeftSide = Use left side appearance for edges +AppearanceCfg.lbl.EdgesSameAsRightSide = Use right side appearance for edges AppearanceCfg.lbl.ttip.EdgesSameAsInside = Use the inside appearance (checked) or outside appearance (unchecked) for the edges -AppearanceCfg.lbl.ttip.EdgesSameAsLeftSide = Use the left side appearance (checked) or right side appearance (unchecked) for the edges +AppearanceCfg.lbl.ttip.EdgesSameAsRightSide = Use the right side appearance (checked) or left side appearance (unchecked) for the edges ! Texture Wrap Modes TextureWrap.Repeat = Repeat diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 9149f995c..08a5b5615 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -313,10 +313,10 @@ public class AppearancePanel extends JPanel { // Get translator keys String tr_outside, tr_inside, tr_edges, tr_edges_ttip; if (c instanceof FinSet) { - tr_outside = "RocketCompCfg.tab.RightSide"; - tr_inside = "RocketCompCfg.tab.LeftSide"; - tr_edges = "AppearanceCfg.lbl.EdgesSameAsLeftSide"; - tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsLeftSide"; + tr_outside = "RocketCompCfg.tab.LeftSide"; + tr_inside = "RocketCompCfg.tab.RightSide"; + tr_edges = "AppearanceCfg.lbl.EdgesSameAsRightSide"; + tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsRightSide"; } else { tr_outside = "RocketCompCfg.tab.Outside"; @@ -418,9 +418,9 @@ public class AppearancePanel extends JPanel { }); materialDefault.setText(trans.get("AppearanceCfg.lbl.Usedefault")); if (insideBuilder) - panel.add(materialDefault); - else panel.add(materialDefault, "wrap"); + else + panel.add(materialDefault); // Get translation keys String tr_insideOutside, tr_insideOutside_ttip; @@ -433,8 +433,8 @@ public class AppearancePanel extends JPanel { tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.InsideSameAsOutside"; } - // Custom inside color - if (insideBuilder) { + // Custom inside color checkbox on outside tab + if (!insideBuilder) { InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); BooleanModel b = new BooleanModel(handler.isInsideSameAsOutside()); JCheckBox customInside = new JCheckBox(b); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java index 1fb457e1e..a7e526394 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java @@ -23,7 +23,13 @@ public class FinRenderer { BoundingBox bounds = finSet.getInstanceBoundingBox(); gl.glMatrixMode(GL.GL_TEXTURE); gl.glPushMatrix(); - gl.glScaled(1 / (bounds.max.x - bounds.min.x), 1 / (bounds.max.y - bounds.min.y), 0); + // Mirror the right side fin texture to avoid e.g. mirrored decal text + if (which == Surface.INSIDE) { + gl.glScaled(-1 / (bounds.max.x - bounds.min.x), 1 / (bounds.max.y - bounds.min.y), 0); + } + else { + gl.glScaled(1 / (bounds.max.x - bounds.min.x), 1 / (bounds.max.y - bounds.min.y), 0); + } gl.glTranslated(-bounds.min.x, -bounds.min.y - finSet.getBodyRadius(), 0); gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); @@ -62,7 +68,7 @@ public class FinRenderer { GLU.gluTessCallback(tobj, GLU.GLU_TESS_END, cb); // fin side: +z - if (which == Surface.OUTSIDE) { + if (which == Surface.INSIDE) { // Right side GLU.gluTessBeginPolygon(tobj, null); GLU.gluTessBeginContour(tobj); gl.glNormal3f(0, 0, 1); @@ -78,7 +84,7 @@ public class FinRenderer { } // fin side: -z - if (which == Surface.INSIDE) { + if (which == Surface.OUTSIDE) { // Left side GLU.gluTessBeginPolygon(tobj, null); GLU.gluTessBeginContour(tobj); gl.glNormal3f(0, 0, -1); From 3a5983e0fc52a63bc6c1c20c5477c4c58b239075 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Mon, 26 Jul 2021 03:38:39 +0200 Subject: [PATCH 04/11] [fixes #969] Change linguistics + uncheck edges --- core/resources/l10n/messages.properties | 4 ++-- core/src/net/sf/openrocket/rocketcomponent/FinSet.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 6faa2e52e..d23d9c33b 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -809,8 +809,8 @@ AppearanceCfg.lbl.texture.offset = Offset: AppearanceCfg.lbl.texture.center = Center: AppearanceCfg.lbl.texture.rotation = Rotation: AppearanceCfg.lbl.texture.repeat = Repeat: -AppearanceCfg.lbl.InsideSameAsOutside = Same as inside -AppearanceCfg.lbl.LeftSideSameAsRightSide = Same as right side +AppearanceCfg.lbl.InsideSameAsOutside = Use for inside +AppearanceCfg.lbl.LeftSideSameAsRightSide = Use for right side AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use the same appearance for the inside as for the outside AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use the same appearance for the right side as for the left side AppearanceCfg.lbl.EdgesSameAsInside = Use inside appearance for edges diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java index b298608bc..873bc9f18 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java @@ -134,6 +134,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona this.filletMaterial = Application.getPreferences().getDefaultComponentMaterial(this.getClass(), Material.Type.BULK); super.displayOrder_side = 4; // Order for displaying the component in the 2D side view super.displayOrder_back = 4; // Order for displaying the component in the 2D back view + insideColorComponentHandler.setEdgesSameAsInside(false); } @Override From 145a27d0f5ddf1cb05aa6e230f7ad7365ce3a476 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Mon, 26 Jul 2021 20:59:40 +0200 Subject: [PATCH 05/11] [fixes #969] Use disabled inside/right tab --- .../gui/configdialog/AppearancePanel.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 08a5b5615..9af1d5c38 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -6,7 +6,20 @@ import java.awt.event.ActionListener; import java.lang.reflect.Method; import java.util.EventObject; -import javax.swing.*; +import javax.swing.JPanel; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JComboBox; +import javax.swing.JSeparator; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.JOptionPane; +import javax.swing.JSpinner; +import javax.swing.JSlider; +import javax.swing.JTabbedPane; import javax.swing.colorchooser.ColorSelectionModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -67,6 +80,8 @@ public class AppearancePanel extends JPanel { // faster. private Appearance defaultAppearance = null; + private JTabbedPane outsideInsidePane = null; + /** * A non-unit that adjusts by a small amount, suitable for values that are * on the 0-1 scale @@ -303,7 +318,7 @@ public class AppearancePanel extends JPanel { if (c instanceof InsideColorComponent) { InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); - JTabbedPane tabbedPane = new JTabbedPane(); + outsideInsidePane = new JTabbedPane(); JPanel outsidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); JPanel insidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); @@ -325,11 +340,12 @@ public class AppearancePanel extends JPanel { tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsInside"; } - tabbedPane.addTab(trans.get(tr_outside), null, outsidePanel, + outsideInsidePane.addTab(trans.get(tr_outside), null, outsidePanel, "Outside Tool Tip"); - tabbedPane.addTab(trans.get(tr_inside), null, insidePanel, + outsideInsidePane.addTab(trans.get(tr_inside), null, insidePanel, "Inside Tool Tip"); - add(tabbedPane, "span 4, growx, wrap"); + outsideInsidePane.setEnabledAt(1, false); + add(outsideInsidePane, "span 4, growx, wrap"); // Checkbox to set edges the same as inside/outside BooleanModel b = new BooleanModel(handler.isEdgesSameAsInside()); @@ -445,6 +461,8 @@ public class AppearancePanel extends JPanel { public void actionPerformed(ActionEvent e) { handler.setInsideSameAsOutside(customInside.isSelected()); c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); + if (outsideInsidePane != null) + outsideInsidePane.setEnabledAt(1, !customInside.isSelected()); } }); panel.add(customInside, "wrap"); From e84f8fd429623efed9b0f19bc4c47ee760fa511a Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Mon, 26 Jul 2021 21:07:57 +0200 Subject: [PATCH 06/11] [fixes #969] Use hidden edges checkbox --- .../gui/configdialog/AppearancePanel.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 9af1d5c38..6ad2525f6 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -81,6 +81,7 @@ public class AppearancePanel extends JPanel { private Appearance defaultAppearance = null; private JTabbedPane outsideInsidePane = null; + private JCheckBox edgesCheckbox = null; /** * A non-unit that adjusts by a small amount, suitable for values that are @@ -349,15 +350,16 @@ public class AppearancePanel extends JPanel { // Checkbox to set edges the same as inside/outside BooleanModel b = new BooleanModel(handler.isEdgesSameAsInside()); - JCheckBox edges = new JCheckBox(b); - edges.setText(trans.get(tr_edges)); - edges.setToolTipText(trans.get(tr_edges_ttip)); - add(edges, "wrap"); + edgesCheckbox = new JCheckBox(b); + edgesCheckbox.setText(trans.get(tr_edges)); + edgesCheckbox.setToolTipText(trans.get(tr_edges_ttip)); + edgesCheckbox.setVisible(false); + add(edgesCheckbox, "wrap"); - edges.addActionListener(new ActionListener() { + edgesCheckbox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - handler.setEdgesSameAsInside(edges.isSelected()); + handler.setEdgesSameAsInside(edgesCheckbox.isSelected()); c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } }); @@ -463,6 +465,8 @@ public class AppearancePanel extends JPanel { c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); if (outsideInsidePane != null) outsideInsidePane.setEnabledAt(1, !customInside.isSelected()); + if (edgesCheckbox != null) + edgesCheckbox.setVisible(!customInside.isSelected()); } }); panel.add(customInside, "wrap"); From 1f7e1fd75c1fc2c5b9cd4ca2e4c0649fce87790d Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Wed, 28 Jul 2021 01:19:40 +0200 Subject: [PATCH 07/11] [fixes #969] Minor bug fixes --- .../gui/configdialog/AppearancePanel.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 6ad2525f6..cc31f1bd0 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -83,6 +83,8 @@ public class AppearancePanel extends JPanel { private JTabbedPane outsideInsidePane = null; private JCheckBox edgesCheckbox = null; + private JCheckBox customInside = null; + /** * A non-unit that adjusts by a small amount, suitable for values that are * on the 0-1 scale @@ -345,15 +347,14 @@ public class AppearancePanel extends JPanel { "Outside Tool Tip"); outsideInsidePane.addTab(trans.get(tr_inside), null, insidePanel, "Inside Tool Tip"); - outsideInsidePane.setEnabledAt(1, false); add(outsideInsidePane, "span 4, growx, wrap"); // Checkbox to set edges the same as inside/outside - BooleanModel b = new BooleanModel(handler.isEdgesSameAsInside()); + BooleanModel b = new BooleanModel(!handler.isEdgesSameAsInside()); edgesCheckbox = new JCheckBox(b); edgesCheckbox.setText(trans.get(tr_edges)); edgesCheckbox.setToolTipText(trans.get(tr_edges_ttip)); - edgesCheckbox.setVisible(false); + edgesCheckbox.doClick(); add(edgesCheckbox, "wrap"); edgesCheckbox.addActionListener(new ActionListener() { @@ -363,6 +364,9 @@ public class AppearancePanel extends JPanel { c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } }); + + customInside.getActionListeners()[0].actionPerformed(null); + //edgesCheckbox.getActionListeners()[0].actionPerformed(null); } else appearanceSection(document, c, false, this); @@ -452,10 +456,10 @@ public class AppearancePanel extends JPanel { } // Custom inside color checkbox on outside tab - if (!insideBuilder) { + if (!insideBuilder && (c instanceof InsideColorComponent)) { InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); BooleanModel b = new BooleanModel(handler.isInsideSameAsOutside()); - JCheckBox customInside = new JCheckBox(b); + this.customInside = new JCheckBox(b); customInside.setText(trans.get(tr_insideOutside)); customInside.setToolTipText(trans.get(tr_insideOutside_ttip)); customInside.addActionListener(new ActionListener() { @@ -463,10 +467,12 @@ public class AppearancePanel extends JPanel { public void actionPerformed(ActionEvent e) { handler.setInsideSameAsOutside(customInside.isSelected()); c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); - if (outsideInsidePane != null) + if (outsideInsidePane != null) { outsideInsidePane.setEnabledAt(1, !customInside.isSelected()); - if (edgesCheckbox != null) + } + if (edgesCheckbox != null) { edgesCheckbox.setVisible(!customInside.isSelected()); + } } }); panel.add(customInside, "wrap"); From e18bc1ad9506dcccaafaf8e8facf974dfa964db2 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Wed, 4 Aug 2021 00:18:28 +0200 Subject: [PATCH 08/11] [fixes #969] Hide tabbed view --- core/resources/l10n/messages.properties | 8 +- .../gui/configdialog/AppearancePanel.java | 98 +++++++++---------- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index d23d9c33b..1c1aa78e4 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -809,10 +809,10 @@ AppearanceCfg.lbl.texture.offset = Offset: AppearanceCfg.lbl.texture.center = Center: AppearanceCfg.lbl.texture.rotation = Rotation: AppearanceCfg.lbl.texture.repeat = Repeat: -AppearanceCfg.lbl.InsideSameAsOutside = Use for inside -AppearanceCfg.lbl.LeftSideSameAsRightSide = Use for right side -AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use the same appearance for the inside as for the outside -AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use the same appearance for the right side as for the left side +AppearanceCfg.lbl.InsideSameAsOutside = Use separate appearance for outside and inside +AppearanceCfg.lbl.LeftSideSameAsRightSide = Use separate appearance for left and right side(s) +AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use a separate appearance for outside and inside +AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use a separate appearance for left and right side(s) AppearanceCfg.lbl.EdgesSameAsInside = Use inside appearance for edges AppearanceCfg.lbl.EdgesSameAsRightSide = Use right side appearance for edges AppearanceCfg.lbl.ttip.EdgesSameAsInside = Use the inside appearance (checked) or outside appearance (unchecked) for the edges diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index cc31f1bd0..6a68f4286 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -321,33 +321,31 @@ public class AppearancePanel extends JPanel { if (c instanceof InsideColorComponent) { InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); - outsideInsidePane = new JTabbedPane(); - JPanel outsidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); - JPanel insidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); - - appearanceSection(document, c, false, outsidePanel); - appearanceSection(document, c, true, insidePanel); - // Get translator keys - String tr_outside, tr_inside, tr_edges, tr_edges_ttip; + String tr_outside, tr_inside, tr_edges, tr_edges_ttip, tr_insideOutside, tr_insideOutside_ttip; if (c instanceof FinSet) { tr_outside = "RocketCompCfg.tab.LeftSide"; tr_inside = "RocketCompCfg.tab.RightSide"; tr_edges = "AppearanceCfg.lbl.EdgesSameAsRightSide"; tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsRightSide"; + tr_insideOutside = "AppearanceCfg.lbl.LeftSideSameAsRightSide"; + tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide"; } else { tr_outside = "RocketCompCfg.tab.Outside"; tr_inside = "RocketCompCfg.tab.Inside"; tr_edges = "AppearanceCfg.lbl.EdgesSameAsInside"; tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsInside"; + tr_insideOutside = "AppearanceCfg.lbl.InsideSameAsOutside"; + tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.InsideSameAsOutside"; } - outsideInsidePane.addTab(trans.get(tr_outside), null, outsidePanel, - "Outside Tool Tip"); - outsideInsidePane.addTab(trans.get(tr_inside), null, insidePanel, - "Inside Tool Tip"); - add(outsideInsidePane, "span 4, growx, wrap"); + // Checkbox for using separate outside/inside appearance + BooleanModel b_customInside = new BooleanModel(handler.isInsideSameAsOutside()); + this.customInside = new JCheckBox(b_customInside); + customInside.setText(trans.get(tr_insideOutside)); + customInside.setToolTipText(trans.get(tr_insideOutside_ttip)); + add(customInside, "wrap"); // Checkbox to set edges the same as inside/outside BooleanModel b = new BooleanModel(!handler.isEdgesSameAsInside()); @@ -357,6 +355,19 @@ public class AppearancePanel extends JPanel { edgesCheckbox.doClick(); add(edgesCheckbox, "wrap"); + outsideInsidePane = new JTabbedPane(); + JPanel outsidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); + JPanel insidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); + + appearanceSection(document, c, false, outsidePanel); + appearanceSection(document, c, true, insidePanel); + + outsideInsidePane.addTab(trans.get(tr_outside), null, outsidePanel, + "Outside Tool Tip"); + outsideInsidePane.addTab(trans.get(tr_inside), null, insidePanel, + "Inside Tool Tip"); + add(outsideInsidePane, "span 4, growx, wrap"); + edgesCheckbox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -365,8 +376,28 @@ public class AppearancePanel extends JPanel { } }); + // Show the outside/inside tabbed display when customInside is selected + customInside.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + handler.setInsideSameAsOutside(!customInside.isSelected()); + c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); + if (customInside.isSelected()) { + remove(outsidePanel); + outsideInsidePane.insertTab(trans.get(tr_outside), null, outsidePanel, + "Outside Tool Tip", 0); + outsideInsidePane.setSelectedIndex(0); + add(outsideInsidePane, "span 4, growx, wrap"); + } + else { + remove(outsideInsidePane); + add(outsidePanel, "span 4, growx, wrap"); + } + updateUI(); + } + }); + customInside.getActionListeners()[0].actionPerformed(null); - //edgesCheckbox.getActionListeners()[0].actionPerformed(null); } else appearanceSection(document, c, false, this); @@ -439,44 +470,7 @@ public class AppearancePanel extends JPanel { } }); materialDefault.setText(trans.get("AppearanceCfg.lbl.Usedefault")); - if (insideBuilder) - panel.add(materialDefault, "wrap"); - else - panel.add(materialDefault); - - // Get translation keys - String tr_insideOutside, tr_insideOutside_ttip; - if (c instanceof FinSet) { - tr_insideOutside = "AppearanceCfg.lbl.LeftSideSameAsRightSide"; - tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide"; - } - else { - tr_insideOutside = "AppearanceCfg.lbl.InsideSameAsOutside"; - tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.InsideSameAsOutside"; - } - - // Custom inside color checkbox on outside tab - if (!insideBuilder && (c instanceof InsideColorComponent)) { - InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); - BooleanModel b = new BooleanModel(handler.isInsideSameAsOutside()); - this.customInside = new JCheckBox(b); - customInside.setText(trans.get(tr_insideOutside)); - customInside.setToolTipText(trans.get(tr_insideOutside_ttip)); - customInside.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - handler.setInsideSameAsOutside(customInside.isSelected()); - c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); - if (outsideInsidePane != null) { - outsideInsidePane.setEnabledAt(1, !customInside.isSelected()); - } - if (edgesCheckbox != null) { - edgesCheckbox.setVisible(!customInside.isSelected()); - } - } - }); - panel.add(customInside, "wrap"); - } + panel.add(materialDefault, "wrap"); // Texture File panel.add(new JLabel(trans.get("AppearanceCfg.lbl.Texture"))); From 6b67aac739a33005d8049a854feedcd0d76ad0f8 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Wed, 4 Aug 2021 21:14:35 +0200 Subject: [PATCH 09/11] [fixes #969] Use comboBox for edges --- core/resources/l10n/messages.properties | 14 ++-- .../importt/InsideAppearanceHandler.java | 2 +- .../savers/RocketComponentSaver.java | 2 +- .../InsideColorComponentHandler.java | 21 +++--- .../gui/configdialog/AppearancePanel.java | 70 ++++++++++++------- .../gui/figure3d/RealisticRenderer.java | 10 ++- 6 files changed, 68 insertions(+), 51 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 1c1aa78e4..2e2e983e8 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -809,14 +809,12 @@ AppearanceCfg.lbl.texture.offset = Offset: AppearanceCfg.lbl.texture.center = Center: AppearanceCfg.lbl.texture.rotation = Rotation: AppearanceCfg.lbl.texture.repeat = Repeat: -AppearanceCfg.lbl.InsideSameAsOutside = Use separate appearance for outside and inside -AppearanceCfg.lbl.LeftSideSameAsRightSide = Use separate appearance for left and right side(s) -AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use a separate appearance for outside and inside -AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide = Use a separate appearance for left and right side(s) -AppearanceCfg.lbl.EdgesSameAsInside = Use inside appearance for edges -AppearanceCfg.lbl.EdgesSameAsRightSide = Use right side appearance for edges -AppearanceCfg.lbl.ttip.EdgesSameAsInside = Use the inside appearance (checked) or outside appearance (unchecked) for the edges -AppearanceCfg.lbl.ttip.EdgesSameAsRightSide = Use the right side appearance (checked) or left side appearance (unchecked) for the edges +AppearanceCfg.lbl.separateInsideOutside = Use separate appearance for outside and inside +AppearanceCfg.lbl.separateLeftSideRightSide = Use separate appearance for left and right side(s) +AppearanceCfg.lbl.ttip.separateInsideOutside = Use a separate appearance for outside and inside +AppearanceCfg.lbl.ttip.separateLeftSideRightSide = Use a separate appearance for left and right side(s) +AppearanceCfg.lbl.AppearanceEdges = Appearance for edges: +AppearanceCfg.lbl.ttip.AppearanceEdges = Select the appearance that should be used for the edges ! Texture Wrap Modes TextureWrap.Repeat = Repeat diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java index 37ec07d23..3bbaee47e 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java @@ -30,7 +30,7 @@ public class InsideAppearanceHandler extends AppearanceHandler { if ("insideSameAsOutside".equals(element)) { boolean insideSameAsOutside = Boolean.parseBoolean(content); if (component instanceof InsideColorComponent) - ((InsideColorComponent)component).getInsideColorComponentHandler().setInsideSameAsOutside(insideSameAsOutside); + ((InsideColorComponent)component).getInsideColorComponentHandler().setSeparateInsideOutside(insideSameAsOutside); return; } diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java index 1c4acc289..449164970 100644 --- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java +++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java @@ -58,7 +58,7 @@ public class RocketComponentSaver { if (ap_in != null) { elements.add(""); elements.add("" + handler.isEdgesSameAsInside() + ""); - elements.add("" + handler.isInsideSameAsOutside() + ""); + elements.add("" + handler.isSeparateInsideOutside() + ""); buildAppearanceElements(elements, ap_in); elements.add(""); } diff --git a/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java b/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java index 44f966418..aa05b8643 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java +++ b/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java @@ -14,7 +14,7 @@ import java.util.EventObject; public class InsideColorComponentHandler { private final RocketComponent component; private Appearance insideAppearance = null; - private boolean insideSameAsOutside = true; + private boolean separateInsideOutside = false; // Flag for separate inside and outside appearance private boolean edgesSameAsInside = true; public InsideColorComponentHandler(RocketComponent component) { @@ -76,22 +76,21 @@ public class InsideColorComponentHandler { } /** - * Checks whether the component should use the same appearance for the inside as the outside (return true) or as the - * outside (return false) + * Checks whether the component should use a separate appearance for the inside and outside. * - * @return true if edges should use the same appearance as the inside, - * false if edges should use the same appearance as the outside + * @return true if a separate inside and outside appearance should be used, + * false if the inside should have the outside appearance */ - public boolean isInsideSameAsOutside() { - return this.insideSameAsOutside; + public boolean isSeparateInsideOutside() { + return this.separateInsideOutside; } /** - * Sets the new state for insideSameAsOutside to newState + * Sets the new state for separateInsideOutside to newState * - * @param newState new edgesUseInsideAppearance value + * @param newState new separateInsideOutside value */ - public void setInsideSameAsOutside(boolean newState) { - this.insideSameAsOutside = newState; + public void setSeparateInsideOutside(boolean newState) { + this.separateInsideOutside = newState; } } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 6a68f4286..97b20a6bb 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -81,7 +81,6 @@ public class AppearancePanel extends JPanel { private Appearance defaultAppearance = null; private JTabbedPane outsideInsidePane = null; - private JCheckBox edgesCheckbox = null; private JCheckBox customInside = null; @@ -322,38 +321,42 @@ public class AppearancePanel extends JPanel { InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler(); // Get translator keys - String tr_outside, tr_inside, tr_edges, tr_edges_ttip, tr_insideOutside, tr_insideOutside_ttip; + String tr_outside, tr_inside, tr_insideOutside, tr_insideOutside_ttip; if (c instanceof FinSet) { tr_outside = "RocketCompCfg.tab.LeftSide"; tr_inside = "RocketCompCfg.tab.RightSide"; - tr_edges = "AppearanceCfg.lbl.EdgesSameAsRightSide"; - tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsRightSide"; - tr_insideOutside = "AppearanceCfg.lbl.LeftSideSameAsRightSide"; - tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.LeftSideSameAsRightSide"; + tr_insideOutside = "AppearanceCfg.lbl.separateLeftSideRightSide"; + tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.separateLeftSideRightSide"; } else { tr_outside = "RocketCompCfg.tab.Outside"; tr_inside = "RocketCompCfg.tab.Inside"; - tr_edges = "AppearanceCfg.lbl.EdgesSameAsInside"; - tr_edges_ttip = "AppearanceCfg.lbl.ttip.EdgesSameAsInside"; - tr_insideOutside = "AppearanceCfg.lbl.InsideSameAsOutside"; - tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.InsideSameAsOutside"; + tr_insideOutside = "AppearanceCfg.lbl.separateInsideOutside"; + tr_insideOutside_ttip = "AppearanceCfg.lbl.ttip.separateInsideOutside"; } // Checkbox for using separate outside/inside appearance - BooleanModel b_customInside = new BooleanModel(handler.isInsideSameAsOutside()); + BooleanModel b_customInside = new BooleanModel(handler.isSeparateInsideOutside()); this.customInside = new JCheckBox(b_customInside); customInside.setText(trans.get(tr_insideOutside)); customInside.setToolTipText(trans.get(tr_insideOutside_ttip)); - add(customInside, "wrap"); + add(customInside, "span 2"); // Checkbox to set edges the same as inside/outside - BooleanModel b = new BooleanModel(!handler.isEdgesSameAsInside()); - edgesCheckbox = new JCheckBox(b); - edgesCheckbox.setText(trans.get(tr_edges)); - edgesCheckbox.setToolTipText(trans.get(tr_edges_ttip)); - edgesCheckbox.doClick(); - add(edgesCheckbox, "wrap"); + JPanel edgesPanel = new JPanel(new MigLayout()); + JLabel edgesText = new JLabel(trans.get("AppearanceCfg.lbl.AppearanceEdges")); + edgesPanel.add(edgesText); + String[] options = new String[] {trans.get(tr_outside), trans.get(tr_inside)}; + JComboBox edgesComboBox = new JComboBox(options); + if (handler.isEdgesSameAsInside()) { + edgesComboBox.setSelectedItem(trans.get(tr_inside)); + } + else { + edgesComboBox.setSelectedItem(trans.get(tr_outside)); + } + edgesPanel.add(edgesComboBox); + edgesPanel.setToolTipText(trans.get("AppearanceCfg.lbl.ttip.AppearanceEdges")); + add(edgesPanel, "span 2, wrap"); outsideInsidePane = new JTabbedPane(); JPanel outsidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]")); @@ -368,19 +371,11 @@ public class AppearancePanel extends JPanel { "Inside Tool Tip"); add(outsideInsidePane, "span 4, growx, wrap"); - edgesCheckbox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - handler.setEdgesSameAsInside(edgesCheckbox.isSelected()); - c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); - } - }); - // Show the outside/inside tabbed display when customInside is selected customInside.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - handler.setInsideSameAsOutside(!customInside.isSelected()); + handler.setSeparateInsideOutside(customInside.isSelected()); c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); if (customInside.isSelected()) { remove(outsidePanel); @@ -393,11 +388,32 @@ public class AppearancePanel extends JPanel { remove(outsideInsidePane); add(outsidePanel, "span 4, growx, wrap"); } + edgesText.setEnabled(customInside.isSelected()); + edgesComboBox.setEnabled(customInside.isSelected()); updateUI(); } }); + // Change the edge appearance upon item selection + edgesComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (edgesComboBox.getSelectedItem() == null) return; + if (edgesComboBox.getSelectedItem().equals(trans.get(tr_outside))) { + handler.setEdgesSameAsInside(false); + } + else if (edgesComboBox.getSelectedItem().equals(trans.get(tr_inside))) { + handler.setEdgesSameAsInside(true); + } + else { + return; + } + c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); + } + }); + customInside.getActionListeners()[0].actionPerformed(null); + edgesComboBox.getActionListeners()[0].actionPerformed(null); } else appearanceSection(document, c, false, this); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java index 62e480053..3fdbfedb2 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java @@ -95,13 +95,17 @@ public class RealisticRenderer extends RocketRenderer { Appearance app = getAppearance(c); if (c instanceof InsideColorComponent) { Appearance innerApp = getInsideAppearance(c); - if (((InsideColorComponent) c).getInsideColorComponentHandler().isInsideSameAsOutside()) innerApp = app; + if (!((InsideColorComponent) c).getInsideColorComponentHandler().isSeparateInsideOutside()) { + innerApp = app; + } render(gl, geom, Surface.INSIDE, innerApp, true, alpha); - if (((InsideColorComponent) c).getInsideColorComponentHandler().isEdgesSameAsInside()) + if (((InsideColorComponent) c).getInsideColorComponentHandler().isEdgesSameAsInside()) { render(gl, geom, Surface.EDGES, innerApp, true, alpha); - else + } + else { render(gl, geom, Surface.EDGES, app, true, alpha); + } } else { render(gl, geom, Surface.INSIDE, app, true, alpha); From 7b1fcf0f605b55f00b99ea395ae9389f660cc40c Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Mon, 9 Aug 2021 19:47:07 +0200 Subject: [PATCH 10/11] [fixes #969] Use edgesSameAsInside default false --- core/src/net/sf/openrocket/rocketcomponent/FinSet.java | 1 - .../rocketcomponent/InsideColorComponentHandler.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java index 873bc9f18..b298608bc 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java @@ -134,7 +134,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona this.filletMaterial = Application.getPreferences().getDefaultComponentMaterial(this.getClass(), Material.Type.BULK); super.displayOrder_side = 4; // Order for displaying the component in the 2D side view super.displayOrder_back = 4; // Order for displaying the component in the 2D back view - insideColorComponentHandler.setEdgesSameAsInside(false); } @Override diff --git a/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java b/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java index aa05b8643..fdd2a9556 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java +++ b/core/src/net/sf/openrocket/rocketcomponent/InsideColorComponentHandler.java @@ -14,8 +14,8 @@ import java.util.EventObject; public class InsideColorComponentHandler { private final RocketComponent component; private Appearance insideAppearance = null; - private boolean separateInsideOutside = false; // Flag for separate inside and outside appearance - private boolean edgesSameAsInside = true; + private boolean separateInsideOutside = false; // Flag for separate inside and outside appearance + private boolean edgesSameAsInside = false; // Flag for setting the edge appearance to the inside (true) or outside (false) appearance public InsideColorComponentHandler(RocketComponent component) { this.component = component; From 871ac30585e679c2c5c2ea137f921b81ffc0ce22 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Mon, 9 Aug 2021 21:39:43 +0200 Subject: [PATCH 11/11] [fixes #969] Only mirror right side decal in separate appearance mode --- .../net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java index a7e526394..311102ceb 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/FinRenderer.java @@ -11,6 +11,7 @@ import com.jogamp.opengl.glu.GLUtessellatorCallbackAdapter; import net.sf.openrocket.rocketcomponent.EllipticalFinSet; import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.InsideColorComponent; import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface; @@ -24,7 +25,7 @@ public class FinRenderer { gl.glMatrixMode(GL.GL_TEXTURE); gl.glPushMatrix(); // Mirror the right side fin texture to avoid e.g. mirrored decal text - if (which == Surface.INSIDE) { + if (which == Surface.INSIDE && ((InsideColorComponent) finSet).getInsideColorComponentHandler().isSeparateInsideOutside()) { gl.glScaled(-1 / (bounds.max.x - bounds.min.x), 1 / (bounds.max.y - bounds.min.y), 0); } else {