From 0ae99d65c5ae29eb88cbe03e8422db8b85ccb8ca Mon Sep 17 00:00:00 2001 From: Billy Olsen Date: Tue, 15 Jun 2021 20:43:03 -0700 Subject: [PATCH 1/7] Make spinner options in photo keyboard editable Spinner options in photo frame does not have an editor, so doesn't allow for keyboard edits. Add an EditableSpinner class which automatically sets the editor and use that instead of JSpinner. Note: this EditableSpinner can be used throughout OR, but not including everywhere as it is a large change at this point and I'd rather wait for the refactor until after release, so change is small. Fixes #873 Signed-off-by: Billy Olsen --- .../gui/components/EditableSpinner.java | 28 +++++++++++++++ .../figure3d/photo/PhotoSettingsConfig.java | 34 +++++++++---------- 2 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 swing/src/net/sf/openrocket/gui/components/EditableSpinner.java diff --git a/swing/src/net/sf/openrocket/gui/components/EditableSpinner.java b/swing/src/net/sf/openrocket/gui/components/EditableSpinner.java new file mode 100644 index 000000000..462ba97d8 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/components/EditableSpinner.java @@ -0,0 +1,28 @@ +package net.sf.openrocket.gui.components; + +import javax.swing.JSpinner; +import javax.swing.SpinnerModel; + +import net.sf.openrocket.gui.SpinnerEditor; + +/** + * A JSpinner that allows edits. + * + * @author Billy Olsen + */ +public class EditableSpinner extends JSpinner { + + private static final long serialVersionUID = 1L; + + + /** + * Creates a new EditableSpinner for the SpinnerModel + * + * @param model + */ + public EditableSpinner(SpinnerModel model) { + super(model); + this.setEditor(new SpinnerEditor(this)); + } + +} diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java index dac63d28c..672a1fc0a 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java @@ -16,7 +16,6 @@ import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSeparator; -import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.SwingConstants; @@ -25,6 +24,7 @@ import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.components.ColorIcon; +import net.sf.openrocket.gui.components.EditableSpinner; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; import net.sf.openrocket.gui.components.UnitSelector; @@ -128,22 +128,22 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.pitch"))); DoubleModel pitchModel = new DoubleModel(p, "Pitch", UnitGroup.UNITS_ANGLE); - add(new JSpinner(pitchModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(pitchModel.getSpinnerModel()), "w 40"); add(new UnitSelector(pitchModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.yaw"))); DoubleModel yawModel = new DoubleModel(p, "Yaw", UnitGroup.UNITS_ANGLE); - add(new JSpinner(yawModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(yawModel.getSpinnerModel()), "w 40"); add(new UnitSelector(yawModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.roll"))); DoubleModel rollModel = new DoubleModel(p, "Roll", UnitGroup.UNITS_ANGLE); - add(new JSpinner(rollModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(rollModel.getSpinnerModel()), "w 40"); add(new UnitSelector(rollModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.advance"))); DoubleModel advanceModel = new DoubleModel(p, "Advance", UnitGroup.UNITS_LENGTH); - add(new JSpinner(advanceModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(advanceModel.getSpinnerModel()), "w 40"); add(new UnitSelector(advanceModel), "wrap"); add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.camera"), Style.BOLD)); @@ -151,22 +151,22 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vAz"))); DoubleModel viewAzModel = new DoubleModel(p, "ViewAz", UnitGroup.UNITS_ANGLE); - add(new JSpinner(viewAzModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(viewAzModel.getSpinnerModel()), "w 40"); add(new UnitSelector(viewAzModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vAlt"))); DoubleModel viewAltModle = new DoubleModel(p, "ViewAlt", UnitGroup.UNITS_ANGLE); - add(new JSpinner(viewAltModle.getSpinnerModel()), "w 40"); + add(new EditableSpinner(viewAltModle.getSpinnerModel()), "w 40"); add(new UnitSelector(viewAltModle), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.vDist"))); DoubleModel viewDistanceModel = new DoubleModel(p, "ViewDistance", UnitGroup.UNITS_LENGTH); - add(new JSpinner(viewDistanceModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(viewDistanceModel.getSpinnerModel()), "w 40"); add(new UnitSelector(viewDistanceModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.fov"))); DoubleModel fovModel = new DoubleModel(p, "Fov", UnitGroup.UNITS_ANGLE); - add(new JSpinner(fovModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(fovModel.getSpinnerModel()), "w 40"); add(new UnitSelector(fovModel), "wrap"); } }); @@ -181,16 +181,16 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.amb"))); DoubleModel ambianceModel = new DoubleModel(p, "Ambiance", 100, UnitGroup.UNITS_NONE, 0, 100); - add(new JSpinner(ambianceModel.getSpinnerModel()), "wrap"); + add(new EditableSpinner(ambianceModel.getSpinnerModel()), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAz"))); DoubleModel lightAzModel = new DoubleModel(p, "LightAz", UnitGroup.UNITS_ANGLE); - add(new JSpinner(lightAzModel.getSpinnerModel()), "w 40"); + add(new EditableSpinner(lightAzModel.getSpinnerModel()), "w 40"); add(new UnitSelector(lightAzModel), "wrap"); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.lightAlt"))); DoubleModel lightAltModle = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE); - add(new JSpinner(lightAltModle.getSpinnerModel()), "wrap"); + add(new EditableSpinner(lightAltModle.getSpinnerModel()), "wrap"); add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.sky"), Style.BOLD)); add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx"); @@ -265,7 +265,7 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.smokeOpacity"))); DoubleModel smokeAlphaModel = new DoubleModel(p, "SmokeAlpha", 100, UnitGroup.UNITS_NONE, 0, 100); - JSpinner opacitySpinner = new JSpinner(smokeAlphaModel.getSpinnerModel()); + EditableSpinner opacitySpinner = new EditableSpinner(smokeAlphaModel.getSpinnerModel()); add(opacitySpinner, "wrap"); smokeModel.addEnableComponent(opacitySpinner); @@ -279,7 +279,7 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.flameAspect"))); DoubleModel flameAspectModel = new DoubleModel(p, "FlameAspectRatio", 100, UnitGroup.UNITS_NONE, 25, 250); - JSpinner flameAspectSpinner = new JSpinner(flameAspectModel.getSpinnerModel()); + EditableSpinner flameAspectSpinner = new EditableSpinner(flameAspectModel.getSpinnerModel()); add(flameAspectSpinner, "wrap"); fireModel.addEnableComponent(flameAspectSpinner); @@ -292,19 +292,19 @@ public class PhotoSettingsConfig extends JTabbedPane { add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparkConcentration"))); DoubleModel sparkConcentrationModel = new DoubleModel(p, "SparkConcentration", 100, UnitGroup.UNITS_NONE, 0, 100); - JSpinner sparkConcentrationSpinner = new JSpinner(sparkConcentrationModel.getSpinnerModel()); + EditableSpinner sparkConcentrationSpinner = new EditableSpinner(sparkConcentrationModel.getSpinnerModel()); add(sparkConcentrationSpinner, "wrap"); sparksModel.addEnableComponent(sparkConcentrationSpinner); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.sparkWeight"))); DoubleModel sparkWeightModel = new DoubleModel(p, "SparkWeight", 100, UnitGroup.UNITS_NONE, 0, 100); - JSpinner sparkWeightSpinner = new JSpinner(sparkWeightModel.getSpinnerModel()); + EditableSpinner sparkWeightSpinner = new EditableSpinner(sparkWeightModel.getSpinnerModel()); add(sparkWeightSpinner, "wrap"); sparksModel.addEnableComponent(sparkWeightSpinner); add(new JLabel(trans.get("PhotoSettingsConfig.lbl.exhaustScale"))); DoubleModel exhaustScaleModel = new DoubleModel(p, "ExhaustScale", 100, UnitGroup.UNITS_NONE, 0, 1000); - add(new JSpinner(exhaustScaleModel.getSpinnerModel()), "wrap"); + add(new EditableSpinner(exhaustScaleModel.getSpinnerModel()), "wrap"); add(new StyledLabel(trans.get("PhotoSettingsConfig.lbl.effects"), Style.BOLD)); add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx"); From 3e199d779fc6d3a754cd339f7a4fc0effe1fcafc Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Fri, 18 Jun 2021 20:57:56 +0200 Subject: [PATCH 2/7] Fix launch lug reference, no refactoring --- .../gui/configdialog/LaunchLugConfig.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java index 0711c72e6..7402580ea 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/LaunchLugConfig.java @@ -20,6 +20,9 @@ import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + @SuppressWarnings("serial") public class LaunchLugConfig extends RocketComponentConfig { @@ -108,28 +111,33 @@ public class LaunchLugConfig extends RocketComponentConfig { // create a new panel for the right column panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", "")); - + //// Position relative to: panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"))); EnumModel positionModel = new EnumModel(component, "AxialMethod", AxialMethod.axialOffsetMethods ); JComboBox positionCombo = new JComboBox( positionModel ); - panel.add( positionCombo, "spanx, growx, wrap"); + panel.add(positionCombo, "spanx, growx, wrap"); //// plus + final DoubleModel mAxOff = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.plus")), "right"); - - m = new DoubleModel(component, "AxialOffset", UnitGroup.UNITS_LENGTH); - spin = new JSpinner(m.getSpinnerModel()); + spin = new JSpinner(mAxOff.getSpinnerModel()); // Plus quantity input spin.setEditor(new SpinnerEditor(spin)); panel.add(spin, "growx"); - panel.add(new UnitSelector(m), "growx"); - panel.add(new BasicSlider(m.getSliderModel( + panel.add(new UnitSelector(mAxOff), "growx"); // Unity selection + panel.add(new BasicSlider(mAxOff.getSliderModel( // Plus quantity slider new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE), new DoubleModel(component.getParent(), "Length"))), "w 100lp, wrap para"); - - + + // Add an action listener to update the plus quantity, based on the selected reference point + positionCombo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mAxOff.stateChanged(e); + } + }); //// Material panel.add(materialPanel( Material.Type.BULK), "span, wrap"); From 0fb216ae5a3e08d4236c06250649773ca36bb25a Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Fri, 18 Jun 2021 21:43:59 +0200 Subject: [PATCH 3/7] =?UTF-8?q?Default=20lug=20&=20rail=20rotation=20180?= =?UTF-8?q?=C2=B0,=20no=20refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java | 2 +- core/src/net/sf/openrocket/rocketcomponent/RailButton.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java index 442deb00d..92ef86e72 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java +++ b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java @@ -21,7 +21,7 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, B private double radius; private double thickness; - private double angleOffsetRadians = 0; + private double angleOffsetRadians = Math.PI; private double radialOffset = 0; private int instanceCount = 1; diff --git a/core/src/net/sf/openrocket/rocketcomponent/RailButton.java b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java index 10241780f..5ce537034 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RailButton.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java @@ -56,7 +56,7 @@ public class RailButton extends ExternalComponent implements AnglePositionable, private double radialDistance_m=0; protected static final AngleMethod angleMethod = AngleMethod.RELATIVE; - private double angle_rad = 0; + private double angle_rad = Math.PI; private int instanceCount = 1; private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0]; From 3f84149cb85d56ef0b0a4ec82c066d38c314af7e Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Fri, 18 Jun 2021 22:35:51 +0200 Subject: [PATCH 4/7] Updated unit tests to match new lug rotation --- core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java | 2 +- core/test/net/sf/openrocket/rocketcomponent/RocketTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java b/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java index 79dd28f05..36c3d90bb 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java @@ -22,7 +22,7 @@ public class LaunchLugTest extends BaseTestCase { lug.setInstanceCount(2); double expX = 0.111 + body.getLocations()[0].x; - double expR = body.getOuterRadius()+lug.getOuterRadius(); + double expR = -(body.getOuterRadius()+lug.getOuterRadius()); Coordinate expPos = new Coordinate( expX, expR, 0, 0); Coordinate actPos[] = lug.getLocations(); assertEquals(" LaunchLug has the wrong x value: ", expPos.x, actPos[0].x, EPSILON); diff --git a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java index e75146eca..2cbe37116 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java @@ -89,7 +89,7 @@ public class RocketTest extends BaseTestCase { } LaunchLug lugs = (LaunchLug)body.getChild(1); - expLoc = new Coordinate(0.181, 0.015, 0); + expLoc = new Coordinate(0.181, -0.015, 0); assertThat(lugs.getName()+" have incorrect count: ", lugs.getInstanceCount(), equalTo(1)); actLocs = lugs.getComponentLocations(); { // singular instance: From 2e6a18930519cad5bf9e486a7503d3a551702473 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 27 Jun 2021 00:32:12 +0200 Subject: [PATCH 5/7] Add real-time color change Photo Studio (#955) Co-authored-by: Sibo Van Gool --- .../figure3d/photo/PhotoSettingsConfig.java | 56 +++++++++++++++---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java index 672a1fc0a..c8b7d1faa 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoSettingsConfig.java @@ -19,6 +19,9 @@ import javax.swing.JSeparator; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.SwingConstants; +import javax.swing.colorchooser.ColorSelectionModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.adaptors.BooleanModel; @@ -57,28 +60,61 @@ public class PhotoSettingsConfig extends JTabbedPane { this.o = o; } + /** + Changes the color of the selected component to + @param color: color to change the component to + */ + private void changeComponentColor(Color color) { + try { + final Method setMethod = o.getClass().getMethod("set" + valueName, net.sf.openrocket.util.Color.class); + if (color == null) + return; + try { + setMethod.invoke(o, ColorConversion.fromAwtColor(color)); + } catch (Throwable e1) { + Application.getExceptionHandler().handleErrorCondition(e1); + } + } catch (Throwable e1) { + Application.getExceptionHandler().handleErrorCondition(e1); + } + + } + + @Override public void actionPerformed(ActionEvent colorClickEvent) { try { final Method getMethod = o.getClass().getMethod("get" + valueName); - final Method setMethod = o.getClass().getMethod("set" + valueName, net.sf.openrocket.util.Color.class); net.sf.openrocket.util.Color c = (net.sf.openrocket.util.Color) getMethod.invoke(o); Color awtColor = ColorConversion.toAwtColor(c); colorChooser.setColor(awtColor); + + // Bind a change of color selection to a change in the components color + ColorSelectionModel model = colorChooser.getSelectionModel(); + ChangeListener changeListener = new ChangeListener() { + public void stateChanged(ChangeEvent changeEvent) { + Color selected = colorChooser.getColor(); + changeComponentColor(selected); + } + }; + model.addChangeListener(changeListener); + JDialog d = JColorChooser.createDialog(PhotoSettingsConfig.this, trans.get("PhotoSettingsConfig.colorChooser.title"), true, colorChooser, new ActionListener() { @Override public void actionPerformed(ActionEvent okEvent) { - Color selected = colorChooser.getColor(); - if (selected == null) - return; - try { - setMethod.invoke(o, ColorConversion.fromAwtColor(selected)); - } catch (Throwable e1) { - Application.getExceptionHandler().handleErrorCondition(e1); - } + changeComponentColor(colorChooser.getColor()); + // Unbind listener to avoid the current component's appearance to change with other components + model.removeChangeListener(changeListener); } - }, null); + }, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + changeComponentColor(awtColor); + // Unbind listener to avoid the current component's appearance to change with other components + model.removeChangeListener(changeListener); + } + }); d.setVisible(true); } catch (Throwable e1) { Application.getExceptionHandler().handleErrorCondition(e1); From eddaae88ff2a64fd6aefb995e0ad889dfb1c1851 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 27 Jun 2021 00:38:31 +0200 Subject: [PATCH 6/7] Fix mass components 3D view (#957) Co-authored-by: Sibo Van Gool --- .../figure3d/geometry/MassObjectRenderer.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java index 58a3c1d93..c51e5da32 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/MassObjectRenderer.java @@ -124,12 +124,20 @@ final class MassObjectRenderer { private MassObjectRenderer() { } - + + /** + * Draw the mass object as a 3D figure. + * + * @param gl OpenGL object + * @param o mass object to draw (e.g. Parachute or Mass Component) + * @param slices number of slices for the 3D object (kind of like subdivision surface) + * @param stacks number of stacks for the 3D object (kind of like subdivision surface) + */ static final void drawMassObject(final GL2 gl, final MassObject o, final int slices, final int stacks) { - - double da, r, dz; - double x, y, z; + + double da, r, dz; // Axial length per slice, radius & length per stack + double x, y, z; // X-, y- and z-position int i, j; da = 2.0f * PI / slices; @@ -156,20 +164,24 @@ final class MassObjectRenderer { x = sin((i * da)); y = cos((i * da)); } - + + // Add radial offset + double xOffset = o.getRadialPosition() * sin(o.getRadialDirection()); + double yOffset = o.getRadialPosition() * cos(o.getRadialDirection()); + if (r == 0) normal3d(gl, 0, 0, 1); else normal3d(gl, x, y, z); TXTR_COORD(gl, s, t); - glVertex3d(gl, (x * r), (y * r), z); + glVertex3d(gl, (x * r) + xOffset, (y * r) + yOffset, z); if (rNext == 0) normal3d(gl, 0, 0, -1); else normal3d(gl, x, y, z); TXTR_COORD(gl, s, t + dt); - glVertex3d(gl, (x * rNext), (y * rNext), (z + dz)); + glVertex3d(gl, (x * rNext) + xOffset, (y * rNext) + yOffset, (z + dz)); s += ds; } // for slices From c1281a695199e4847bd654d6ac2b3814986cec5c Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Thu, 24 Jun 2021 11:58:15 +0200 Subject: [PATCH 7/7] Add radial positioning shock cord --- core/resources/l10n/messages.properties | 5 ++ .../gui/configdialog/ShockCordConfig.java | 63 ++++++++++++++++--- .../gui/rocketfigure/ShockCordShapes.java | 35 +++++++---- 3 files changed, 83 insertions(+), 20 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 20cbc4bac..f84c5e7b3 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1066,6 +1066,11 @@ ShockCordCfg.lbl.Posrelativeto = Position relative to: ShockCordCfg.lbl.plus = plus ShockCordCfg.lbl.Packedlength = Packed length: ShockCordCfg.lbl.Packeddiam = Packed diameter: +ShockCordCfg.tab.Radialpos = Radial position +ShockCordCfg.tab.ttip.Radialpos = Radial position configuration +ShockCordCfg.lbl.Radialdistance = Radial distance: +ShockCordCfg.lbl.Radialdirection = Radial direction: +ShockCordCfg.but.Reset = Reset ShockCordCfg.tab.General = General ShockCordCfg.tab.ttip.General = General properties diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java index 113381cdc..0edf5e687 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/ShockCordConfig.java @@ -1,10 +1,7 @@ package net.sf.openrocket.gui.configdialog; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; +import javax.swing.*; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; @@ -15,11 +12,16 @@ import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; +import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.ShockCord; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + @SuppressWarnings("serial") public class ShockCordConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); @@ -114,11 +116,56 @@ public class ShockCordConfig extends RocketComponentConfig { //// General and General properties - tabbedPane.insertTab(trans.get("ShockCordCfg.tab.General"), null, panel, trans.get("ShockCordCfg.tab.ttip.General"), 0); - // tabbedPane.insertTab("Radial position", null, positionTab(), - // "Radial position configuration", 1); + tabbedPane.insertTab(trans.get("ShockCordCfg.tab.General"), null, panel, + trans.get("ShockCordCfg.tab.ttip.General"), 0); + //// Radial position and Radial position configuration + tabbedPane.insertTab(trans.get("ShockCordCfg.tab.Radialpos"), null, positionTab(), + trans.get("ShockCordCfg.tab.ttip.Radialpos"), 1); tabbedPane.setSelectedIndex(0); } - + // TODO: LOW: there is a lot of duplicate code here with other mass components... (e.g. in MassComponentConfig or ParachuteConfig) + protected JPanel positionTab() { + JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::]", "")); + + //// Radial position + //// Radial distance: + panel.add(new JLabel(trans.get("ShockCordCfg.lbl.Radialdistance"))); + + DoubleModel m = new DoubleModel(component, "RadialPosition", UnitGroup.UNITS_LENGTH, 0); + + JSpinner spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(0, 0.1, 1.0)), "w 100lp, wrap"); + + + //// Radial direction: + panel.add(new JLabel(trans.get("ShockCordCfg.lbl.Radialdirection"))); + + m = new DoubleModel(component, "RadialDirection", UnitGroup.UNITS_ANGLE); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + panel.add(spin, "growx"); + + panel.add(new UnitSelector(m), "growx"); + panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap"); + + + //// Reset button + JButton button = new JButton(trans.get("ShockCordCfg.but.Reset")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ((ShockCord) component).setRadialDirection(0.0); + ((ShockCord) component).setRadialPosition(0.0); + } + }); + panel.add(button, "spanx, right"); + + return panel; + } } diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java index 92962bf24..0ff5dbccf 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java @@ -1,6 +1,9 @@ package net.sf.openrocket.gui.rocketfigure; +import net.sf.openrocket.rocketcomponent.MassComponent; +import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.ShockCord; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; @@ -13,33 +16,41 @@ import java.awt.geom.RoundRectangle2D; public class ShockCordShapes extends RocketComponentShape { public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { - - - net.sf.openrocket.rocketcomponent.MassObject massObj = (net.sf.openrocket.rocketcomponent.MassObject)component; + final ShockCord massObj = (ShockCord)component; double length = massObj.getLength(); double radius = massObj.getRadius(); double arc = Math.min(length, 2*radius) * 0.7; - - Coordinate start = transformation.transform(Coordinate.ZERO); + final double radialDistance = massObj.getRadialPosition(); + final double radialAngleRadians = massObj.getRadialDirection(); + + final Coordinate localPosition = new Coordinate(0, + radialDistance * Math.cos(radialAngleRadians), + radialDistance * Math.sin(radialAngleRadians)); + final Coordinate renderPosition = transformation.transform(localPosition); Shape[] s = new Shape[1]; - s[0] = new RoundRectangle2D.Double(start.x,(start.y-radius), + s[0] = new RoundRectangle2D.Double(renderPosition.x,(renderPosition.y-radius), length,2*radius,arc,arc); - return RocketComponentShape.toArray( addSymbol(s), component); + return RocketComponentShape.toArray(addSymbol(s), component); } public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { - - net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; + final ShockCord massObj = (ShockCord)component; - double or = tube.getRadius(); + double or = massObj.getRadius(); + final double radialDistance = massObj.getRadialPosition(); + final double radialAngleRadians = massObj.getRadialDirection(); + + final Coordinate localPosition = new Coordinate(0, + radialDistance * Math.cos(radialAngleRadians), + radialDistance * Math.sin(radialAngleRadians)); + final Coordinate renderPosition = transformation.transform(localPosition); Shape[] s = new Shape[1]; - Coordinate start = transformation.transform(Coordinate.ZERO); - s[0] = new Ellipse2D.Double((start.z-or),(start.y-or),2*or,2*or); + s[0] = new Ellipse2D.Double((renderPosition.z-or),(renderPosition.y-or),2*or,2*or); // Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset)); //