diff --git a/core/src/net/sf/openrocket/document/Simulation.java b/core/src/net/sf/openrocket/document/Simulation.java index 594734e2b..da5c74976 100644 --- a/core/src/net/sf/openrocket/document/Simulation.java +++ b/core/src/net/sf/openrocket/document/Simulation.java @@ -2,6 +2,7 @@ package net.sf.openrocket.document; import java.util.EventListener; import java.util.EventObject; +import java.util.Iterator; import java.util.List; import net.sf.openrocket.aerodynamics.AerodynamicCalculator; @@ -10,8 +11,14 @@ import net.sf.openrocket.aerodynamics.WarningSet; import net.sf.openrocket.formatting.RocketDescriptor; import net.sf.openrocket.masscalc.BasicMassCalculator; import net.sf.openrocket.masscalc.MassCalculator; +import net.sf.openrocket.motor.Motor; +import net.sf.openrocket.motor.MotorInstanceConfiguration; import net.sf.openrocket.rocketcomponent.Configuration; +import net.sf.openrocket.rocketcomponent.IgnitionConfiguration; +import net.sf.openrocket.rocketcomponent.MotorConfiguration; +import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.simulation.BasicEventSimulationEngine; import net.sf.openrocket.simulation.DefaultSimulationOptionFactory; import net.sf.openrocket.simulation.FlightData; @@ -58,7 +65,10 @@ public class Simulation implements ChangeSource, Cloneable { EXTERNAL, /** Not yet simulated */ - NOT_SIMULATED + NOT_SIMULATED, + + /** Can't be simulated, NO_MOTORS **/ + CANT_RUN } private RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); @@ -250,13 +260,35 @@ public class Simulation implements ChangeSource, Cloneable { */ public Status getStatus() { mutex.verify(); - if (status == Status.UPTODATE || status == Status.LOADED) { - if (rocket.getFunctionalModID() != simulatedRocketID || - !options.equals(simulatedConditions)) - return Status.OUTDATED; + if (rocket.getFunctionalModID() != simulatedRocketID || !options.equals(simulatedConditions)) { + status = Status.OUTDATED; + } } + + //Make sure this simulation has motors. + Configuration c = new Configuration(this.getRocket()); + MotorInstanceConfiguration motors = new MotorInstanceConfiguration(); + c.setFlightConfigurationID(options.getMotorConfigurationID()); + final String flightConfigId = c.getFlightConfigurationID(); + + Iterator iterator = c.motorIterator(); + boolean no_motors = true; + + while (iterator.hasNext()) { + MotorMount mount = iterator.next(); + RocketComponent component = (RocketComponent) mount; + MotorConfiguration motorConfig = mount.getMotorConfiguration().get(flightConfigId); + IgnitionConfiguration ignitionConfig = mount.getIgnitionConfiguration().get(flightConfigId); + Motor motor = motorConfig.getMotor(); + if (motor != null) + no_motors = false; + } + + if (no_motors) + status = Status.CANT_RUN; + return status; } diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java index 23f8cf58c..b7d8889a0 100644 --- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java +++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java @@ -43,8 +43,8 @@ public class BasicEventSimulationEngine implements SimulationEngine { private SimulationStepper landingStepper = new BasicLandingStepper(); private SimulationStepper tumbleStepper = new BasicTumbleStepper(); - // Constant holding 20 degress in radians. This is the AOA condition - // necessary to transistion to tumbling. + // Constant holding 20 degrees in radians. This is the AOA condition + // necessary to transition to tumbling. private final static double AOA_TUMBLE_CONDITION = Math.PI / 9.0; // The thrust must be below this value for the transition to tumbling. diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java index 945dec440..70e8c01f5 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java @@ -334,7 +334,7 @@ public class PreferencesDialog extends JDialog { }); panel.add(automaticallyRunSimsBox, "wrap, growx, sg combos "); - //// Automatically run all simulation out-dated by design changes. + //// Update flight estimates in the design window final JCheckBox updateEstimates = new JCheckBox(trans.get("pref.dlg.checkbox.Updateestimates")); updateEstimates.setSelected(preferences.computeFlightInBackground()); diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index fd8c11272..10fb9e71f 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -54,6 +54,7 @@ import javax.swing.border.BevelBorder; import javax.swing.border.TitledBorder; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; +import javax.swing.event.ChangeEvent; import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; @@ -153,7 +154,7 @@ public class BasicFrame extends JFrame { /** Actions available for rocket modifications */ private final RocketActions actions; - + private SimulationPanel simulationPanel; /** @@ -174,7 +175,7 @@ public class BasicFrame extends JFrame { componentSelectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); // Obtain the simulation selection model that will be used - SimulationPanel simulationPanel = new SimulationPanel(document); + simulationPanel = new SimulationPanel(document); simulationSelectionModel = simulationPanel.getSimulationListSelectionModel(); // Combine into a DocumentSelectionModel @@ -203,6 +204,11 @@ public class BasicFrame extends JFrame { //// Flight simulations tabbedPane.addTab(trans.get("BasicFrame.tab.Flightsim"), null, simulationPanel); + // Add change listener to catch when the tabs are changed. This is to run simulations + // automagically when the simulation tab is selected. + tabbedPane.addChangeListener(new BasicFrame_changeAdapter(this)); + + vertical.setTopComponent(tabbedPane); @@ -1553,4 +1559,24 @@ public class BasicFrame extends JFrame { return null; } } + + public void stateChanged(ChangeEvent e) { + JTabbedPane tabSource = (JTabbedPane) e.getSource(); + String tab = tabSource.getTitleAt(tabSource.getSelectedIndex()); + if (tab.equals(trans.get("BasicFrame.tab.Flightsim"))) { + simulationPanel.activating(); + } + } } + + +class BasicFrame_changeAdapter implements javax.swing.event.ChangeListener { + BasicFrame adaptee; + + BasicFrame_changeAdapter(BasicFrame adaptee) { + this.adaptee = adaptee; + } + public void stateChanged(ChangeEvent e) { + adaptee.stateChanged(e); + } +} \ No newline at end of file diff --git a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java index c25d19eb1..a81436995 100644 --- a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java @@ -44,6 +44,7 @@ import net.sf.openrocket.gui.simulation.SimulationEditDialog; import net.sf.openrocket.gui.simulation.SimulationRunDialog; import net.sf.openrocket.gui.simulation.SimulationWarningDialog; import net.sf.openrocket.gui.util.Icons; +import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.ComponentChangeListener; @@ -586,6 +587,44 @@ public class SimulationPanel extends JPanel { } + /// when the simulation tab is selected this run outdated simulated if appropriate. + public void activating(){ + if( ((Preferences) Application.getPreferences()).getAutoRunSimulations()){ + int nSims = simulationTable.getRowCount(); + int outdated = 0; + if (nSims == 0) { + return; + } + + for (int i = 0; i < nSims; i++) { + Simulation.Status s = document.getSimulation(simulationTable.convertRowIndexToModel(i)).getStatus(); + if((s==Simulation.Status.NOT_SIMULATED) || + (s==Simulation.Status.OUTDATED)){ + outdated++; + } + } + if(outdated>0){ + Simulation[] sims = new Simulation[outdated]; + + int index=0; + for (int i = 0; i < nSims; i++) { + int t = simulationTable.convertRowIndexToModel(i); + Simulation s = document.getSimulation(t); + if((s.getStatus()==Status.NOT_SIMULATED)||(s.getStatus()==Status.OUTDATED)){ + sims[index] = s; + index++; + } + } + + long t = System.currentTimeMillis(); + new SimulationRunDialog(SwingUtilities.getWindowAncestor( + SimulationPanel.this), document, sims).setVisible(true); + log.info("Running simulations took " + (System.currentTimeMillis() - t) + " ms"); + fireMaintainSelection(); + } + } + } + public ListSelectionModel getSimulationListSelectionModel() { return simulationTable.getSelectionModel(); } diff --git a/swing/src/net/sf/openrocket/gui/util/Icons.java b/swing/src/net/sf/openrocket/gui/util/Icons.java index 0246cb2eb..ff67daefa 100644 --- a/swing/src/net/sf/openrocket/gui/util/Icons.java +++ b/swing/src/net/sf/openrocket/gui/util/Icons.java @@ -31,6 +31,7 @@ public class Icons { static { HashMap map = new HashMap(); map.put(Simulation.Status.NOT_SIMULATED, loadImageIcon("pix/spheres/gray-16x16.png", "Not simulated")); + map.put(Simulation.Status.CANT_RUN, loadImageIcon("pix/spheres/yellow-16x16.png", "Can't run, no motors assigned.")); map.put(Simulation.Status.UPTODATE, loadImageIcon("pix/spheres/green-16x16.png", "Up to date")); map.put(Simulation.Status.LOADED, loadImageIcon("pix/spheres/yellow-16x16.png", "Loaded from file")); map.put(Simulation.Status.OUTDATED, loadImageIcon("pix/spheres/red-16x16.png", "Out-of-date"));