Merge pull request #1798 from SiboVG/issue-1791
[#1791 & ##1631] Return component mass as section mass if subcomponents mass is overridden & add subcomponent overridden icons
This commit is contained in:
commit
347df84d61
@ -930,6 +930,12 @@ RocketCompCfg.checkbox.OverrideSubcomponents = Override for all subcomponents
|
||||
RocketCompCfg.checkbox.OverrideSubcomponents.Mass.ttip = <html>Overrides the aggregate mass of this component<br>and its subcomponents with the mass of this component.</html>
|
||||
RocketCompCfg.checkbox.OverrideSubcomponents.CG.ttip = <html>Overrides the center of gravity (CG) of this component<br>and its subcomponents with the CG of this component.</html>
|
||||
RocketCompCfg.checkbox.OverrideSubcomponents.CD.ttip = <html>Overrides the coefficient of drag (C<sub>D</sub>) of this component<br>and its subcomponents with the C<sub>D</sub> of this component.</html>
|
||||
RocketCompCfg.lbl.MassOverriddenBy = Mass overridden by %s
|
||||
RocketCompCfg.lbl.CGOverriddenBy = CG overridden by %s
|
||||
RocketCompCfg.lbl.CDOverriddenBy = <html>C<sub>D</sub> overridden by %s
|
||||
RocketCompCfg.lbl.MassOverriddenBy.ttip = The mass of this component is determined by the mass override value of %s
|
||||
RocketCompCfg.lbl.CGOverriddenBy.ttip = The CG of this component is determined by the CG override value of %s
|
||||
RocketCompCfg.lbl.CDOverriddenBy.ttip = <html>The C<sub>D</sub> of this component is determined by the C<sub>D</sub> override value of %s</html>
|
||||
RocketCompCfg.lbl.longB1 = <html>The overridden mass and center of gravity does not include motors.<br>
|
||||
RocketCompCfg.lbl.longB2 = The center of gravity is measured from the front end of the
|
||||
RocketCompCfg.lbl.Commentsonthe = Comments on the
|
||||
@ -1354,10 +1360,13 @@ PlotDialog.CheckBox.Showdatapoints = Show data points
|
||||
PlotDialog.lbl.Chart = left click drag to zoom area. mouse wheel to zoom. ctrl-mouse wheel to zoom x axis only. ctrl-left click drag to pan. right click drag to zoom dynamically.
|
||||
PlotDialog.btn.exportImage = Export Image
|
||||
|
||||
ComponentTree.ttip.massoverride = mass override
|
||||
ComponentTree.ttip.cgoverride = cg override
|
||||
ComponentTree.ttip.massoverride = mass overriden
|
||||
ComponentTree.ttip.cgoverride = CG overriden
|
||||
ComponentTree.ttip.cdoverride = <html>C<sub>D</sub> overriden</html>
|
||||
! "main" prefix is used for the main application dialog
|
||||
|
||||
ComponentTreeRenderer.total = total
|
||||
|
||||
# FIXME: Rename the description keys
|
||||
|
||||
main.menu.file = File
|
||||
|
@ -1024,6 +1024,7 @@ PlotDialog.Chart.Simulatedflight = Simulierter Flug
|
||||
PlotDialog.CheckBox.Showdatapoints = Datenpunkte anzeigen
|
||||
PlotDialog.lbl.Chart = Klicken+ziehen: runter+rechts um hinein zu zoomen, hoch+links um heraus zu zoomen
|
||||
|
||||
ComponentTreeRenderer.total = gesamt
|
||||
|
||||
! "main" prefix is used for the main application dialog
|
||||
|
||||
|
@ -732,6 +732,8 @@ PlotDialog.CheckBox.Showdatapoints = Mostrar los datos de los puntos
|
||||
PlotDialog.lbl.Chart = Arastrar con bot\u00f3n-izq rat\u00f3n para zoom del \u00e1rea. Rueda rat\u00f3n para zoom. Ctrl+rueda rat\u00f3n para zoom eje x. Ctrl+arrastrar con bot\u00f3n-izq rat\u00f3n para desplazar. Arrastrar con bot\u00f3n-der para zoom din\u00e1mico
|
||||
PlotDialog.title.Flightdataplot = Representaci\u00f3n de los datos de vuelo
|
||||
|
||||
ComponentTreeRenderer.total = total
|
||||
|
||||
PreferencesDialog.languages.default = Idioma por defecto
|
||||
PreferencesDialog.lbl.language = Idioma de la interfaz:
|
||||
PreferencesDialog.lbl.languageEffect = El idioma cambiar\u00e1 la pr\u00f3xima vez que abra OpenRocket.
|
||||
|
@ -724,6 +724,8 @@ PlotDialog.lbl.Chart = Cliquer+d\u00E9placer en bas +droite pour a
|
||||
! PlotDialog
|
||||
PlotDialog.title.Flightdataplot = Trac\u00E9 du vol
|
||||
|
||||
ComponentTreeRenderer.total = total
|
||||
|
||||
PreferencesDialog.languages.default = Valeur syst\u00E8me par d\u00E9faut
|
||||
PreferencesDialog.lbl.language = Langue du programme:
|
||||
PreferencesDialog.lbl.languageEffect = La langue sera chang\u00E9e apr\u00E8s avoir red\u00E9marr\u00E9 OpenRocket.
|
||||
|
@ -1025,6 +1025,7 @@ PlotDialog.Chart.Simulatedflight = Volo simulato
|
||||
PlotDialog.CheckBox.Showdatapoints = Mostra i punti
|
||||
PlotDialog.lbl.Chart = Clicca e trascina giu'-dx per ingrandire, su-sx per rimpicciolire
|
||||
|
||||
ComponentTreeRenderer.total = totali
|
||||
|
||||
! "main" prefix is used for the main application dialog
|
||||
|
||||
|
@ -1224,10 +1224,12 @@ TCMotorSelPan.btn.close = Sluit
|
||||
PlotDialog.CheckBox.Showdatapoints = Toon datapunten
|
||||
PlotDialog.lbl.Chart = Linksklik+sleep om in te zoomen op omgeving. Muiswiel om te zoomen. Ctrl-muiswiel om enkel x-as te zoomen. Ctrl-linksklik om te bewegen. Rechtsklik+sleep om dynamisch te zoomen.
|
||||
|
||||
ComponentTree.ttip.massoverride = Massa overschrijven
|
||||
ComponentTree.ttip.massoverride = Massa overschreven
|
||||
ComponentTree.ttip.cgoverride = ZP overschrijven
|
||||
! "main" prefix is used for the main application dialog
|
||||
|
||||
ComponentTreeRenderer.total = totaal
|
||||
|
||||
# FIXME: Rename the description keys
|
||||
|
||||
main.menu.file = Bestand
|
||||
|
BIN
core/resources/pix/icons/cd-override-subcomponent.png
Normal file
BIN
core/resources/pix/icons/cd-override-subcomponent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
core/resources/pix/icons/cg-override-subcomponent.png
Normal file
BIN
core/resources/pix/icons/cg-override-subcomponent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
core/resources/pix/icons/mass-override-subcomponent.png
Executable file
BIN
core/resources/pix/icons/mass-override-subcomponent.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
@ -14,8 +14,9 @@ public class ComponentChangeEvent extends EventObject {
|
||||
UNDO( 16, "UNDO"),
|
||||
MOTOR( 32, "Motor"),
|
||||
EVENT( 64, "Event"),
|
||||
TEXTURE ( 128, "Texture")
|
||||
, GRAPHIC( 256, "Configuration")
|
||||
TEXTURE ( 128, "Texture"),
|
||||
GRAPHIC( 256, "Configuration"),
|
||||
TREE_CHILDREN( 512, "TREE_CHILDREN"),
|
||||
;
|
||||
|
||||
protected int value;
|
||||
@ -45,6 +46,8 @@ public class ComponentChangeEvent extends EventObject {
|
||||
|
||||
/** A change that affects the rocket tree structure */
|
||||
public static final int TREE_CHANGE = TYPE.TREE.value;
|
||||
/** A change that affects the children's tree structure */
|
||||
public static final int TREE_CHANGE_CHILDREN = TYPE.TREE_CHILDREN.value;
|
||||
/** A change caused by undo/redo. */
|
||||
public static final int UNDO_CHANGE = TYPE.UNDO.value;
|
||||
/** A change in the motor configurations or names */
|
||||
@ -124,6 +127,9 @@ public class ComponentChangeEvent extends EventObject {
|
||||
public boolean isTreeChange() {
|
||||
return TYPE.TREE.matches(this.type);
|
||||
}
|
||||
public boolean isTreeChildrenChange() {
|
||||
return TYPE.TREE_CHILDREN.matches(this.type);
|
||||
}
|
||||
|
||||
public boolean isUndoChange() {
|
||||
return TYPE.UNDO.matches(this.type);
|
||||
@ -150,6 +156,8 @@ public class ComponentChangeEvent extends EventObject {
|
||||
s += ",aero";
|
||||
if (isTreeChange())
|
||||
s += ",tree";
|
||||
if (isTreeChildrenChange())
|
||||
s += ",treechild";
|
||||
if (isUndoChange())
|
||||
s += ",undo";
|
||||
if (isMotorChange())
|
||||
|
@ -96,18 +96,23 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
private LineStyle lineStyle = null;
|
||||
|
||||
|
||||
// Override mass/CG/CD
|
||||
// Override mass
|
||||
protected double overrideMass = 0;
|
||||
protected boolean massOverridden = false;
|
||||
private boolean overrideSubcomponentsMass = false;
|
||||
|
||||
private RocketComponent massOverriddenBy = null; // The (super-)parent component that overrides the mass of this component
|
||||
|
||||
// Override CG
|
||||
private double overrideCGX = 0;
|
||||
private boolean cgOverridden = false;
|
||||
private boolean overrideSubcomponentsCG = false;
|
||||
|
||||
private RocketComponent CGOverriddenBy = null; // The (super-)parent component that overrides the CG of this component
|
||||
|
||||
// Override CD
|
||||
private double overrideCD = 0;
|
||||
private boolean cdOverridden = false;
|
||||
private boolean overrideSubcomponentsCD = false;
|
||||
private RocketComponent CDOverriddenBy = null; // The (super-)parent component that overrides the CD of this component
|
||||
|
||||
private boolean cdOverriddenByAncestor = false;
|
||||
|
||||
@ -606,6 +611,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
}
|
||||
checkState();
|
||||
massOverridden = o;
|
||||
updateChildrenMassOverriddenBy();
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
@ -680,6 +686,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
}
|
||||
checkState();
|
||||
cgOverridden = o;
|
||||
updateChildrenCGOverriddenBy();
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
@ -746,6 +753,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
}
|
||||
checkState();
|
||||
cdOverridden = o;
|
||||
updateChildrenCDOverriddenBy();
|
||||
|
||||
// if overrideSubcompoents is set, we need to descend the component
|
||||
// tree. If we are overriding our own CD, we need to override all
|
||||
@ -784,7 +792,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
return overrideSubcomponentsMass;
|
||||
}
|
||||
|
||||
// TODO: delete no compatibility is needed anymore with OR 15.03
|
||||
// TODO: delete when compatibility with OR 15.03 is not needed anymore
|
||||
public void setSubcomponentsOverridden(boolean override) {
|
||||
setSubcomponentsOverriddenMass(override);
|
||||
setSubcomponentsOverriddenCG(override);
|
||||
@ -809,7 +817,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
checkState();
|
||||
overrideSubcomponentsMass = override;
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
updateChildrenMassOverriddenBy();
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE | ComponentChangeEvent.TREE_CHANGE_CHILDREN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -845,7 +855,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
checkState();
|
||||
overrideSubcomponentsCG = override;
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
updateChildrenCGOverriddenBy();
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE | ComponentChangeEvent.TREE_CHANGE_CHILDREN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -881,9 +893,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
checkState();
|
||||
overrideSubcomponentsCD = override;
|
||||
|
||||
updateChildrenCDOverriddenBy();
|
||||
|
||||
overrideSubcomponentsCD(override);
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE | ComponentChangeEvent.TREE_CHANGE_CHILDREN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -931,8 +945,62 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
mutex.verify();
|
||||
return isCGOverridden() || isMassOverridden() || isCDOverridden();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Returns which (super-)parent overrides the mass of this component, or null if no parent does so.
|
||||
*/
|
||||
public RocketComponent getMassOverriddenBy() {
|
||||
return massOverriddenBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which (super-)parent overrides the CG of this component, or null if no parent does so.
|
||||
*/
|
||||
public RocketComponent getCGOverriddenBy() {
|
||||
return CGOverriddenBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which (super-)parent overrides the CD of this component, or null if no parent does so.
|
||||
*/
|
||||
public RocketComponent getCDOverriddenBy() {
|
||||
return CDOverriddenBy;
|
||||
}
|
||||
|
||||
private void updateChildrenMassOverriddenBy() {
|
||||
RocketComponent overriddenBy = massOverridden && overrideSubcomponentsMass ? this : null;
|
||||
for (RocketComponent c : getAllChildren()) {
|
||||
c.massOverriddenBy = overriddenBy;
|
||||
// We need to update overriddenBy in case one of the children components has its subcomponents overridden
|
||||
if (overriddenBy == null) {
|
||||
overriddenBy = c.massOverridden && c.overrideSubcomponentsMass ? c : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChildrenCGOverriddenBy() {
|
||||
RocketComponent overriddenBy = cgOverridden && overrideSubcomponentsCG ? this : null;
|
||||
for (RocketComponent c : getAllChildren()) {
|
||||
c.CGOverriddenBy = overriddenBy;
|
||||
// We need to update overriddenBy in case one of the children components has its subcomponents overridden
|
||||
if (overriddenBy == null) {
|
||||
overriddenBy = c.cgOverridden && c.overrideSubcomponentsCG ? c : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChildrenCDOverriddenBy() {
|
||||
RocketComponent overriddenBy = cdOverridden && overrideSubcomponentsCD ? this : null;
|
||||
for (RocketComponent c : getAllChildren()) {
|
||||
c.CDOverriddenBy = overriddenBy;
|
||||
// We need to update overriddenBy in case one of the children components has its subcomponents overridden
|
||||
if (overriddenBy == null) {
|
||||
overriddenBy = c.cdOverridden && c.overrideSubcomponentsCD ? c : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* placeholder. This allows code to generally test if this component represents multiple instances with just one function call.
|
||||
*
|
||||
* @return number of instances
|
||||
@ -1534,6 +1602,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
*/
|
||||
public final double getSectionMass() {
|
||||
Double massSubtotal = getMass();
|
||||
if (massOverridden && overrideSubcomponentsMass) {
|
||||
return massSubtotal;
|
||||
}
|
||||
mutex.verify();
|
||||
for (RocketComponent rc : children) {
|
||||
massSubtotal += rc.getSectionMass();
|
||||
@ -1639,6 +1710,36 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
|
||||
children.add(index, component);
|
||||
component.parent = this;
|
||||
if (this.massOverridden && this.overrideSubcomponentsMass) {
|
||||
component.massOverriddenBy = this;
|
||||
} else {
|
||||
component.massOverriddenBy = this.massOverriddenBy;
|
||||
}
|
||||
if (this.cgOverridden && this.overrideSubcomponentsCG) {
|
||||
component.CGOverriddenBy = this;
|
||||
} else {
|
||||
component.CGOverriddenBy = this.CGOverriddenBy;
|
||||
}
|
||||
if (this.cdOverridden && this.overrideSubcomponentsCD) {
|
||||
component.CDOverriddenBy = this;
|
||||
} else {
|
||||
component.CDOverriddenBy = this.CDOverriddenBy;
|
||||
}
|
||||
for (Iterator<RocketComponent> it = component.iterator(false); it.hasNext(); ) {
|
||||
RocketComponent child = it.next();
|
||||
// You only want to change the overriddenBy if the overriddenBy of component changed (i.e. is not null),
|
||||
// otherwise you could lose overriddenBy information of the sub-children that have one of this component's
|
||||
// children as its overrideBy component.
|
||||
if (component.massOverriddenBy != null) {
|
||||
child.massOverriddenBy = component.massOverriddenBy;
|
||||
}
|
||||
if (component.CGOverriddenBy != null) {
|
||||
child.CGOverriddenBy = component.CGOverriddenBy;
|
||||
}
|
||||
if (component.CDOverriddenBy != null) {
|
||||
child.CDOverriddenBy = component.CDOverriddenBy;
|
||||
}
|
||||
}
|
||||
|
||||
if (component instanceof AxialStage) {
|
||||
AxialStage nStage = (AxialStage) component;
|
||||
@ -1660,7 +1761,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
*/
|
||||
public final void removeChild(int n) {
|
||||
checkState();
|
||||
RocketComponent component = this.getChild(n);
|
||||
RocketComponent component = this.getChild(n);
|
||||
this.removeChild(component);
|
||||
}
|
||||
|
||||
@ -1679,6 +1780,20 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
||||
|
||||
if (children.remove(component)) {
|
||||
component.parent = null;
|
||||
for (RocketComponent c : component) {
|
||||
// You only want to set the override components to null if the child's override component is either
|
||||
// this component, or a (super-)parent of this component. Otherwise, you could lose the overrideBy
|
||||
// information of sub-children that have one of this component's children as its overrideBy component.
|
||||
if (c.massOverriddenBy == this || c.massOverriddenBy == this.massOverriddenBy) {
|
||||
c.massOverriddenBy = null;
|
||||
}
|
||||
if (c.CGOverriddenBy == this || c.CGOverriddenBy == this.CGOverriddenBy) {
|
||||
c.CGOverriddenBy = null;
|
||||
}
|
||||
if (c.CDOverriddenBy == this || c.CDOverriddenBy == this.CDOverriddenBy) {
|
||||
c.CDOverriddenBy = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (component instanceof AxialStage) {
|
||||
AxialStage stage = (AxialStage) component;
|
||||
|
@ -4,6 +4,7 @@ public class Color {
|
||||
|
||||
public static Color BLACK = new Color(255,255,255);
|
||||
public static Color INVISIBLE = new Color(1, 1, 1, 0);
|
||||
public static Color DARK_RED = new Color(200, 0, 0);
|
||||
|
||||
private int red;
|
||||
private int green;
|
||||
@ -60,5 +61,9 @@ public class Color {
|
||||
public String toString() {
|
||||
return "Color [r=" + red + ", g=" + green + ", b=" + blue + ", a=" + alpha + "]";
|
||||
}
|
||||
|
||||
public java.awt.Color toAWTColor() {
|
||||
return new java.awt.Color(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,10 +4,12 @@ import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocumentFactory;
|
||||
import net.sf.openrocket.rocketcomponent.*;
|
||||
import net.sf.openrocket.rocketcomponent.position.AngleMethod;
|
||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
@ -377,10 +379,12 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
assertEquals(0.0, sustainerBody.getPosition().x, EPSILON);
|
||||
assertEquals(0.1, sustainerBody.getLength(), EPSILON);
|
||||
assertEquals(expSingleBodyMass, sustainerBody.getMass(), EPSILON);
|
||||
assertEquals(expSingleBodyMass, sustainerBody.getSectionMass(), EPSILON);
|
||||
|
||||
assertEquals(0.10, boosterBody.getComponentLocations()[0].x, EPSILON);
|
||||
assertEquals(0.10, boosterBody.getLength(), EPSILON);
|
||||
assertEquals(expSingleBodyMass, boosterBody.getMass(), EPSILON);
|
||||
assertEquals(expSingleBodyMass, boosterBody.getSectionMass(), EPSILON);
|
||||
}
|
||||
|
||||
{ // [1] test Rocket CM, before:
|
||||
@ -397,13 +401,16 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
|
||||
boosterBody.setSubcomponentsOverriddenMass(false);
|
||||
boosterBody.setMassOverridden(true);
|
||||
boosterBody.setOverrideMass(0.001);
|
||||
double newMass = 0.001;
|
||||
boosterBody.setOverrideMass(newMass);
|
||||
|
||||
{ // [1] test Rocket CM, after:
|
||||
final RigidBody actualStructure = MassCalculator.calculateStructure(config);
|
||||
|
||||
final double actualRocketDryMass = actualStructure.cm.weight;
|
||||
assertEquals(expSingleBodyMass+0.001, actualRocketDryMass, EPSILON);
|
||||
assertEquals(expSingleBodyMass+newMass, actualRocketDryMass, EPSILON);
|
||||
assertEquals(newMass, boosterBody.getMass(), EPSILON);
|
||||
assertEquals(newMass, boosterBody.getSectionMass(), EPSILON);
|
||||
|
||||
final Coordinate actualRocketDryCM = actualStructure.cm;
|
||||
assertEquals(0.06976699, actualRocketDryCM.x, EPSILON);
|
||||
@ -411,13 +418,15 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
|
||||
boosterBody.setSubcomponentsOverriddenMass(true); // change. Also, this body lacks subcomponents.
|
||||
boosterBody.setMassOverridden(true); // repeat
|
||||
boosterBody.setOverrideMass(0.001); // repeat
|
||||
boosterBody.setOverrideMass(newMass); // repeat
|
||||
|
||||
{ // [1] test Rocket CM, after:
|
||||
final RigidBody actualStructure = MassCalculator.calculateStructure(config);
|
||||
|
||||
final double actualRocketDryMass = actualStructure.cm.weight;
|
||||
assertEquals(expSingleBodyMass+0.001, actualRocketDryMass, EPSILON);
|
||||
assertEquals(expSingleBodyMass+newMass, actualRocketDryMass, EPSILON);
|
||||
assertEquals(newMass, boosterBody.getMass(), EPSILON);
|
||||
assertEquals(newMass, boosterBody.getSectionMass(), EPSILON);
|
||||
|
||||
final Coordinate actualRocketDryCM = actualStructure.cm;
|
||||
assertEquals(0.06976699, actualRocketDryCM.x, EPSILON);
|
||||
@ -1232,5 +1241,31 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
assertEquals("Empty Stages Rocket Rotational MOI calculated incorrectly: ", overrideMOIrotRef, overrideMOIrot, EPSILON);
|
||||
assertEquals("Empty Stages Rocket Longitudinal MOI calculated incorrectly: ", overrideMOIlongRef, overrideMOIlong, EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureMass() {
|
||||
Rocket rocket = OpenRocketDocumentFactory.createNewRocket().getRocket();
|
||||
AxialStage stage = rocket.getStage(0);
|
||||
stage.addChild(new NoseCone());
|
||||
BodyTube bodyTube = new BodyTube();
|
||||
stage.addChild(bodyTube);
|
||||
MassComponent massComponent = new MassComponent();
|
||||
massComponent.setComponentMass(0.01);
|
||||
bodyTube.addChild(massComponent);
|
||||
|
||||
assertEquals(0.041016634, bodyTube.getMass(), EPSILON);
|
||||
assertEquals(0.051016634, bodyTube.getSectionMass(), EPSILON);
|
||||
|
||||
bodyTube.setMassOverridden(true);
|
||||
bodyTube.setOverrideMass(0.02);
|
||||
|
||||
assertEquals(0.02, bodyTube.getMass(), EPSILON);
|
||||
assertEquals(0.03, bodyTube.getSectionMass(), EPSILON);
|
||||
|
||||
bodyTube.setSubcomponentsOverriddenMass(true);
|
||||
|
||||
assertEquals(0.02, bodyTube.getMass(), EPSILON);
|
||||
assertEquals(0.02, bodyTube.getSectionMass(), EPSILON);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,32 +1,21 @@
|
||||
package net.sf.openrocket.rocketcomponent;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.AerodynamicForces;
|
||||
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
|
||||
import net.sf.openrocket.aerodynamics.FlightConditions;
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
import net.sf.openrocket.util.TestRockets;
|
||||
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class OverrideTest extends BaseTestCase {
|
||||
|
||||
@ -109,4 +98,345 @@ public class OverrideTest extends BaseTestCase {
|
||||
Map<RocketComponent, AerodynamicForces> forceMap = calc.getForceAnalysis(configuration, conditions, warnings);
|
||||
assertEquals(sustainer.getOverrideCD() + bodytube.getOverrideCD() + forceMap.get(nosecone).getCD(), forceMap.get(rocket).getCD(), MathUtil.EPSILON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether children components of a parent that has subcomponents overridden for mass, CG, or CD have the correct
|
||||
* overriddenBy object.
|
||||
*/
|
||||
@Test
|
||||
public void testOverriddenBy() {
|
||||
// Create test rocket
|
||||
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||
|
||||
// Obtain the necessary components
|
||||
AxialStage sustainer = rocket.getStage(0);
|
||||
NoseCone noseCone = (NoseCone) sustainer.getChild(0);
|
||||
BodyTube bodyTube = (BodyTube) sustainer.getChild(1);
|
||||
FinSet finSet = (FinSet) bodyTube.getChild(0);
|
||||
LaunchLug launchLug = (LaunchLug) bodyTube.getChild(1);
|
||||
InnerTube innerTube = (InnerTube) bodyTube.getChild(2);
|
||||
EngineBlock engineBlock = (EngineBlock) innerTube.getChild(0);
|
||||
Parachute parachute = (Parachute) bodyTube.getChild(3);
|
||||
CenteringRing bulkhead = (CenteringRing) bodyTube.getChild(4);
|
||||
|
||||
// Check initial override by components
|
||||
assertNull(rocket.getMassOverriddenBy());
|
||||
assertNull(rocket.getCGOverriddenBy());
|
||||
assertNull(rocket.getCDOverriddenBy());
|
||||
assertNull(sustainer.getMassOverriddenBy());
|
||||
assertNull(sustainer.getCGOverriddenBy());
|
||||
assertNull(sustainer.getCDOverriddenBy());
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertNull(finSet.getCGOverriddenBy());
|
||||
assertNull(finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertNull(launchLug.getCGOverriddenBy());
|
||||
assertNull(launchLug.getCDOverriddenBy());
|
||||
assertNull(innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertNull(engineBlock.getMassOverriddenBy());
|
||||
assertNull(engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertNull(parachute.getCGOverriddenBy());
|
||||
assertNull(parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertNull(bulkhead.getCGOverriddenBy());
|
||||
assertNull(bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Override body tube mass, CG, and CD without for subcomponents
|
||||
bodyTube.setMassOverridden(true);
|
||||
bodyTube.setCGOverridden(true);
|
||||
bodyTube.setCDOverridden(true);
|
||||
|
||||
assertNull(sustainer.getMassOverriddenBy());
|
||||
assertNull(sustainer.getCGOverriddenBy());
|
||||
assertNull(sustainer.getCDOverriddenBy());
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertNull(finSet.getCGOverriddenBy());
|
||||
assertNull(finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertNull(launchLug.getCGOverriddenBy());
|
||||
assertNull(launchLug.getCDOverriddenBy());
|
||||
assertNull(innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertNull(engineBlock.getMassOverriddenBy());
|
||||
assertNull(engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertNull(parachute.getCGOverriddenBy());
|
||||
assertNull(parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertNull(bulkhead.getCGOverriddenBy());
|
||||
assertNull(bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Override body tube mass for subcomponents
|
||||
bodyTube.setSubcomponentsOverriddenMass(true);
|
||||
|
||||
assertNull(sustainer.getMassOverriddenBy());
|
||||
assertNull(sustainer.getCGOverriddenBy());
|
||||
assertNull(sustainer.getCDOverriddenBy());
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getMassOverriddenBy());
|
||||
assertNull(finSet.getCGOverriddenBy());
|
||||
assertNull(finSet.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getMassOverriddenBy());
|
||||
assertNull(launchLug.getCGOverriddenBy());
|
||||
assertNull(launchLug.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getMassOverriddenBy());
|
||||
assertNull(engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getMassOverriddenBy());
|
||||
assertNull(parachute.getCGOverriddenBy());
|
||||
assertNull(parachute.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getMassOverriddenBy());
|
||||
assertNull(bulkhead.getCGOverriddenBy());
|
||||
assertNull(bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Undo override body tube mass for subcomponents, do override of CG and CD for subcomponents
|
||||
bodyTube.setSubcomponentsOverriddenMass(false);
|
||||
bodyTube.setSubcomponentsOverriddenCG(true);
|
||||
bodyTube.setSubcomponentsOverriddenCD(true);
|
||||
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCDOverriddenBy());
|
||||
assertNull(innerTube.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getCDOverriddenBy());
|
||||
assertNull(engineBlock.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Move the inner tube from the body tube to the nose cone
|
||||
bodyTube.removeChild(innerTube);
|
||||
noseCone.addChild(innerTube);
|
||||
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertNull(engineBlock.getMassOverriddenBy());
|
||||
assertNull(engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Override mass of nose cone
|
||||
noseCone.setMassOverridden(true);
|
||||
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertNull(engineBlock.getMassOverriddenBy());
|
||||
assertNull(engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Override nose cone mass for all subcomponents
|
||||
noseCone.setSubcomponentsOverriddenMass(true);
|
||||
|
||||
assertNull(sustainer.getMassOverriddenBy());
|
||||
assertNull(sustainer.getCGOverriddenBy());
|
||||
assertNull(sustainer.getCDOverriddenBy());
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertEquals(noseCone, innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertEquals(noseCone, engineBlock.getMassOverriddenBy());
|
||||
assertNull(engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Override inner tube CG for all subcomponents
|
||||
innerTube.setCGOverridden(true);
|
||||
innerTube.setSubcomponentsOverriddenCG(true);
|
||||
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertEquals(noseCone, innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertEquals(noseCone, engineBlock.getMassOverriddenBy());
|
||||
assertEquals(innerTube, engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertNull(finSet.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCDOverriddenBy());
|
||||
assertNull(launchLug.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCDOverriddenBy());
|
||||
assertNull(parachute.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCDOverriddenBy());
|
||||
assertNull(bulkhead.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCGOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCDOverriddenBy());
|
||||
|
||||
// Set body tube mass override, reset CG & CD, and move inner tube back to body tube
|
||||
bodyTube.setMassOverridden(true);
|
||||
bodyTube.setSubcomponentsOverriddenMass(true);
|
||||
bodyTube.setCGOverridden(false);
|
||||
bodyTube.setCDOverridden(false);
|
||||
noseCone.removeChild(innerTube);
|
||||
bodyTube.addChild(innerTube);
|
||||
|
||||
assertNull(noseCone.getMassOverriddenBy());
|
||||
assertNull(noseCone.getCGOverriddenBy());
|
||||
assertNull(noseCone.getCDOverriddenBy());
|
||||
assertNull(bodyTube.getMassOverriddenBy());
|
||||
assertNull(bodyTube.getCGOverriddenBy());
|
||||
assertNull(bodyTube.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getMassOverriddenBy());
|
||||
assertNull(finSet.getCGOverriddenBy());
|
||||
assertNull(finSet.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getMassOverriddenBy());
|
||||
assertNull(launchLug.getCGOverriddenBy());
|
||||
assertNull(launchLug.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getMassOverriddenBy());
|
||||
assertNull(parachute.getCGOverriddenBy());
|
||||
assertNull(parachute.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getMassOverriddenBy());
|
||||
assertNull(bulkhead.getCGOverriddenBy());
|
||||
assertNull(bulkhead.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getMassOverriddenBy());
|
||||
assertEquals(innerTube, engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
|
||||
// Toggle the body tube CG override for all subcomponents
|
||||
bodyTube.setCGOverridden(true);
|
||||
bodyTube.setSubcomponentsOverriddenCG(true);
|
||||
|
||||
assertEquals(bodyTube, finSet.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, finSet.getCGOverriddenBy());
|
||||
assertNull(finSet.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getCGOverriddenBy());
|
||||
assertNull(launchLug.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getCGOverriddenBy());
|
||||
assertNull(parachute.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getCGOverriddenBy());
|
||||
assertNull(bulkhead.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getMassOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
|
||||
// Toggle back
|
||||
bodyTube.setSubcomponentsOverriddenCG(false);
|
||||
assertEquals(bodyTube, finSet.getMassOverriddenBy());
|
||||
assertNull(finSet.getCGOverriddenBy());
|
||||
assertNull(finSet.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, launchLug.getMassOverriddenBy());
|
||||
assertNull(launchLug.getCGOverriddenBy());
|
||||
assertNull(launchLug.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, parachute.getMassOverriddenBy());
|
||||
assertNull(parachute.getCGOverriddenBy());
|
||||
assertNull(parachute.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, bulkhead.getMassOverriddenBy());
|
||||
assertNull(bulkhead.getCGOverriddenBy());
|
||||
assertNull(bulkhead.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, innerTube.getMassOverriddenBy());
|
||||
assertNull(innerTube.getCGOverriddenBy());
|
||||
assertNull(innerTube.getCDOverriddenBy());
|
||||
assertEquals(bodyTube, engineBlock.getMassOverriddenBy());
|
||||
assertEquals(innerTube, engineBlock.getCGOverriddenBy());
|
||||
assertNull(engineBlock.getCDOverriddenBy());
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +201,15 @@ public class BooleanModel extends AbstractAction implements StateChangeListener,
|
||||
componentEnableState.add(enableState);
|
||||
updateEnableStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a component from the list of enable components controlled by this model.
|
||||
* @param component component to remove from the list
|
||||
*/
|
||||
public void removeEnableComponent(Component component) {
|
||||
checkState(true);
|
||||
components.remove(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a component which will be enabled when this boolean is <code>true</code>.
|
||||
|
@ -235,11 +235,9 @@ public class RocketComponentConfig extends JPanel {
|
||||
overridetext = trans.get("RocketCompCfg.lbl.overriddento") + " " + UnitGroup.UNITS_MASS.getDefaultUnit().
|
||||
toStringUnit(component.getOverrideMass()) + ")";
|
||||
}
|
||||
|
||||
for (RocketComponent c = component.getParent(); c != null; c = c.getParent()) {
|
||||
if (c.isMassOverridden() && c.isSubcomponentsOverriddenMass()) {
|
||||
overridetext = trans.get("RocketCompCfg.lbl.overriddenby") + " " + c.getName() + ")";
|
||||
}
|
||||
|
||||
if (component.getMassOverriddenBy() != null) {
|
||||
overridetext = trans.get("RocketCompCfg.lbl.overriddenby") + " " + component.getMassOverriddenBy().getName() + ")";
|
||||
}
|
||||
|
||||
if (overridetext != null) {
|
||||
@ -355,6 +353,7 @@ public class RocketComponentConfig extends JPanel {
|
||||
//// Override the mass, center of gravity, or drag coeficient of the component
|
||||
|
||||
JCheckBox check;
|
||||
JCheckBox checkSub;
|
||||
BooleanModel bm;
|
||||
UnitSelector us;
|
||||
BasicSlider bs;
|
||||
@ -371,15 +370,26 @@ public class RocketComponentConfig extends JPanel {
|
||||
|
||||
////// Override subcomponents
|
||||
BooleanModel bmSubcomp = new BooleanModel(component, "SubcomponentsOverriddenMass");
|
||||
check = new JCheckBox(bmSubcomp);
|
||||
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
|
||||
Font smallFont = check.getFont();
|
||||
checkSub = new JCheckBox(bmSubcomp);
|
||||
checkSub.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
|
||||
Font smallFont = checkSub.getFont();
|
||||
smallFont = smallFont.deriveFont(smallFont.getSize2D() - 1);
|
||||
check.setFont(smallFont);
|
||||
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.Mass.ttip"));
|
||||
bm.addEnableComponent(check, true);
|
||||
checkboxes.add(check, "gapleft 25lp, wrap");
|
||||
order.add(check);
|
||||
checkSub.setFont(smallFont);
|
||||
checkSub.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.Mass.ttip"));
|
||||
bm.addEnableComponent(checkSub, true);
|
||||
checkboxes.add(checkSub, "gapleft 25lp, wrap");
|
||||
order.add(checkSub);
|
||||
|
||||
////// Mass overridden by
|
||||
if (component.getMassOverriddenBy() != null) {
|
||||
StyledLabel labelMassOverriddenBy = new StyledLabel(
|
||||
String.format(trans.get("RocketCompCfg.lbl.MassOverriddenBy"), component.getMassOverriddenBy().getName()),
|
||||
0, StyledLabel.Style.BOLD);
|
||||
labelMassOverriddenBy.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
labelMassOverriddenBy.setToolTipText(
|
||||
String.format(trans.get("RocketCompCfg.lbl.MassOverriddenBy.ttip"), component.getMassOverriddenBy().getName()));
|
||||
checkboxes.add(labelMassOverriddenBy, "gapleft 25lp, wrap");
|
||||
}
|
||||
|
||||
panel.add(checkboxes, "growx 1, gapright 20lp");
|
||||
|
||||
@ -399,6 +409,18 @@ public class RocketComponentConfig extends JPanel {
|
||||
bm.addEnableComponent(bs);
|
||||
panel.add(bs, "growx 5, w 100lp, wrap");
|
||||
|
||||
if (component.getMassOverriddenBy() != null) {
|
||||
check.setEnabled(false);
|
||||
bm.removeEnableComponent(checkSub);
|
||||
bm.removeEnableComponent(spin);
|
||||
bm.removeEnableComponent(us);
|
||||
bm.removeEnableComponent(bs);
|
||||
checkSub.setEnabled(false);
|
||||
spin.setEnabled(false);
|
||||
us.setEnabled(false);
|
||||
bs.setEnabled(false);
|
||||
}
|
||||
|
||||
// END OVERRIDE MASS ----------------------------------
|
||||
|
||||
// OVERRIDE CG ----------------------------------
|
||||
@ -413,13 +435,24 @@ public class RocketComponentConfig extends JPanel {
|
||||
|
||||
////// Override subcomponents
|
||||
bmSubcomp = new BooleanModel(component, "SubcomponentsOverriddenCG");
|
||||
check = new JCheckBox(bmSubcomp);
|
||||
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
|
||||
check.setFont(smallFont);
|
||||
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.CG.ttip"));
|
||||
bm.addEnableComponent(check, true);
|
||||
checkboxes.add(check, "gapleft 25lp, wrap");
|
||||
order.add(check);
|
||||
checkSub = new JCheckBox(bmSubcomp);
|
||||
checkSub.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
|
||||
checkSub.setFont(smallFont);
|
||||
checkSub.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.CG.ttip"));
|
||||
bm.addEnableComponent(checkSub, true);
|
||||
checkboxes.add(checkSub, "gapleft 25lp, wrap");
|
||||
order.add(checkSub);
|
||||
|
||||
////// CG overridden by
|
||||
if (component.getCGOverriddenBy() != null) {
|
||||
StyledLabel labelCGOverriddenBy = new StyledLabel(
|
||||
String.format(trans.get("RocketCompCfg.lbl.CGOverriddenBy"), component.getCGOverriddenBy().getName()),
|
||||
0, StyledLabel.Style.BOLD);
|
||||
labelCGOverriddenBy.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
labelCGOverriddenBy.setToolTipText(
|
||||
String.format(trans.get("RocketCompCfg.lbl.CGOverriddenBy.ttip"), component.getCGOverriddenBy().getName()));
|
||||
checkboxes.add(labelCGOverriddenBy, "gapleft 25lp, wrap");
|
||||
}
|
||||
|
||||
panel.add(checkboxes, "growx 1, gapright 20lp");
|
||||
|
||||
@ -469,6 +502,18 @@ public class RocketComponentConfig extends JPanel {
|
||||
bm.addEnableComponent(bs);
|
||||
panel.add(bs, "growx 5, w 100lp, wrap");
|
||||
|
||||
if (component.getCGOverriddenBy() != null) {
|
||||
check.setEnabled(false);
|
||||
bm.removeEnableComponent(checkSub);
|
||||
bm.removeEnableComponent(spin);
|
||||
bm.removeEnableComponent(us);
|
||||
bm.removeEnableComponent(bs);
|
||||
checkSub.setEnabled(false);
|
||||
spin.setEnabled(false);
|
||||
us.setEnabled(false);
|
||||
bs.setEnabled(false);
|
||||
}
|
||||
|
||||
// END OVERRIDE CG ---------------------------------------------------
|
||||
|
||||
|
||||
@ -484,13 +529,24 @@ public class RocketComponentConfig extends JPanel {
|
||||
|
||||
////// Override subcomponents
|
||||
bmSubcomp = new BooleanModel(component, "SubcomponentsOverriddenCD");
|
||||
check = new JCheckBox(bmSubcomp);
|
||||
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
|
||||
check.setFont(smallFont);
|
||||
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.CD.ttip"));
|
||||
bm.addEnableComponent(check, true);
|
||||
checkboxes.add(check, "gapleft 25lp, wrap");
|
||||
order.add(check);
|
||||
checkSub = new JCheckBox(bmSubcomp);
|
||||
checkSub.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
|
||||
checkSub.setFont(smallFont);
|
||||
checkSub.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.CD.ttip"));
|
||||
bm.addEnableComponent(checkSub, true);
|
||||
checkboxes.add(checkSub, "gapleft 25lp, wrap");
|
||||
order.add(checkSub);
|
||||
|
||||
////// CD overridden by
|
||||
if (component.getCDOverriddenBy() != null) {
|
||||
StyledLabel labelCDOverriddenBy = new StyledLabel(
|
||||
String.format(trans.get("RocketCompCfg.lbl.CDOverriddenBy"), component.getCDOverriddenBy().getName()),
|
||||
0, StyledLabel.Style.BOLD);
|
||||
labelCDOverriddenBy.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
labelCDOverriddenBy.setToolTipText(
|
||||
String.format(trans.get("RocketCompCfg.lbl.CDOverriddenBy"), component.getCDOverriddenBy().getName()));
|
||||
checkboxes.add(labelCDOverriddenBy, "gapleft 25lp, wrap");
|
||||
}
|
||||
|
||||
panel.add(checkboxes, "growx 1, gapright 20lp");
|
||||
|
||||
@ -507,6 +563,16 @@ public class RocketComponentConfig extends JPanel {
|
||||
bm.addEnableComponent(bs);
|
||||
panel.add(bs, "top, skip, growx 5, w 100lp, wrap");
|
||||
|
||||
if (component.getCDOverriddenBy() != null) {
|
||||
check.setEnabled(false);
|
||||
bm.removeEnableComponent(checkSub);
|
||||
bm.removeEnableComponent(spin);
|
||||
bm.removeEnableComponent(bs);
|
||||
checkSub.setEnabled(false);
|
||||
spin.setEnabled(false);
|
||||
bs.setEnabled(false);
|
||||
}
|
||||
|
||||
// END OVERRIDE CD --------------------------------------------------
|
||||
|
||||
// OVERRIDE MASS, CG DOESN'T INCLUDE MOTORS --------------------------------------------------
|
||||
|
@ -38,7 +38,7 @@ public class LaunchPreferencesPanel extends PreferencesPanel {
|
||||
StyledLabel warning = new StyledLabel(String.format(
|
||||
"<html>%s</html>", trans.get("pref.dlg.lbl.launchWarning")),
|
||||
0.5f, StyledLabel.Style.BOLD);
|
||||
warning.setFontColor(Color.RED);
|
||||
warning.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
warning.setToolTipText(trans.get("pref.dlg.lbl.launchWarning.ttip"));
|
||||
add(warning, "spanx, growx 0, gapbottom para, wrap");
|
||||
|
||||
|
@ -15,6 +15,7 @@ import net.sf.openrocket.gui.SpinnerEditor;
|
||||
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
||||
import net.sf.openrocket.gui.adaptors.EnumModel;
|
||||
import net.sf.openrocket.gui.components.BasicSlider;
|
||||
import net.sf.openrocket.gui.components.StyledLabel;
|
||||
import net.sf.openrocket.gui.components.UnitSelector;
|
||||
import net.sf.openrocket.simulation.RK4SimulationStepper;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
@ -79,6 +80,14 @@ public class SimulationPreferencesPanel extends PreferencesPanel {
|
||||
// layout
|
||||
subsub = new JPanel(new MigLayout("insets 0, fill", "[grow][min!][min!][]"));
|
||||
|
||||
// // Warning
|
||||
StyledLabel warning = new StyledLabel(String.format(
|
||||
"<html>%s</html>", trans.get("pref.dlg.lbl.launchWarning")),
|
||||
0, StyledLabel.Style.BOLD);
|
||||
warning.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
warning.setToolTipText(trans.get("pref.dlg.lbl.launchWarning.ttip"));
|
||||
subsub.add(warning, "spanx, wrap para");
|
||||
|
||||
// // Calculation method:
|
||||
tip = trans.get("simedtdlg.lbl.ttip.Calcmethod");
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Calcmethod"));
|
||||
|
@ -90,9 +90,9 @@ public class ComponentTreeModel implements TreeModel, ComponentChangeListener {
|
||||
|
||||
private void fireTreeNodeChanged(RocketComponent node) {
|
||||
TreeModelEvent e = new TreeModelEvent(this, makeTreePath(node), null, null);
|
||||
Object[] l = listeners.toArray();
|
||||
for (int i = 0; i < l.length; i++)
|
||||
((TreeModelListener) l[i]).treeNodesChanged(e);
|
||||
for (TreeModelListener listener : listeners) {
|
||||
listener.treeNodesChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -147,7 +147,12 @@ public class ComponentTreeModel implements TreeModel, ComponentChangeListener {
|
||||
// TODO: LOW: Could this be performed better?
|
||||
expandAll();
|
||||
}
|
||||
} else {
|
||||
} else if (e.isTreeChildrenChange()) {
|
||||
for (RocketComponent c : e.getSource().getAllChildren()) {
|
||||
fireTreeNodeChanged(c);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fireTreeNodeChanged(e.getSource());
|
||||
}
|
||||
}
|
||||
|
@ -49,23 +49,31 @@ public class ComponentTreeRenderer extends DefaultTreeCellRenderer {
|
||||
} else {
|
||||
setIcon(ComponentIcons.getSmallIcon(value.getClass()));
|
||||
}
|
||||
if (c.isMassOverridden() || c.isCGOverridden() || c.isCDOverridden()) {
|
||||
if (c.isMassOverridden() || c.getMassOverriddenBy() != null ||
|
||||
c.isCGOverridden() || c.getCGOverriddenBy() != null ||
|
||||
c.isCDOverridden() || c.getCDOverriddenBy() != null) {
|
||||
JPanel p = new JPanel();
|
||||
p.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
|
||||
p.setBackground(UIManager.getColor("Tree.textBackground"));
|
||||
p.setForeground(UIManager.getColor("Tree.textForeground"));
|
||||
p.add(comp/* , BorderLayout.WEST */);
|
||||
if (c.isMassOverridden()) {
|
||||
if (c.getMassOverriddenBy() != null) {
|
||||
p.add(new JLabel(Icons.MASS_OVERRIDE_SUBCOMPONENT));
|
||||
} else if (c.isMassOverridden()) {
|
||||
p.add(new JLabel(Icons.MASS_OVERRIDE));
|
||||
}
|
||||
if (c.isCGOverridden()) {
|
||||
if (c.getCGOverriddenBy() != null) {
|
||||
p.add(new JLabel(Icons.CG_OVERRIDE_SUBCOMPONENT));
|
||||
} else if (c.isCGOverridden()) {
|
||||
p.add(new JLabel(Icons.CG_OVERRIDE));
|
||||
}
|
||||
if (c.isCDOverridden()) {
|
||||
if (c.getCDOverriddenBy() != null) {
|
||||
p.add(new JLabel(Icons.CD_OVERRIDE_SUBCOMPONENT));
|
||||
} else if (c.isCDOverridden()) {
|
||||
p.add(new JLabel(Icons.CD_OVERRIDE));
|
||||
}
|
||||
|
||||
|
||||
// Make sure the tooltip also works on the override icons
|
||||
if (components != null && components.size() > 1 && components.contains(c)) {
|
||||
p.setToolTipText(getToolTipMultipleComponents(components));
|
||||
} else {
|
||||
@ -88,32 +96,60 @@ public class ComponentTreeRenderer extends DefaultTreeCellRenderer {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<html>");
|
||||
|
||||
// Component name title
|
||||
sb.append("<b>").append(c.getName()).append("</b>");
|
||||
if (c.isMassive() || c.isMassOverridden()) {
|
||||
|
||||
// Only add mass information if mass is not overridden by a parent component
|
||||
RocketComponent overriddenBy = c.getMassOverriddenBy();
|
||||
if (overriddenBy == null) {
|
||||
if (c.isMassive() || c.isMassOverridden()) {
|
||||
sb.append(" (").append(
|
||||
UnitGroup.UNITS_MASS.toStringUnit(c.getMass()));
|
||||
if (c.getChildCount() > 0) {
|
||||
sb.append(" of ")
|
||||
.append(UnitGroup.UNITS_MASS.toStringUnit(c
|
||||
.getSectionMass())).append(" ").append(trans.get("ComponentTreeRenderer.total"));
|
||||
}
|
||||
sb.append(")");
|
||||
} else {
|
||||
if ((c.getChildCount() > 0) && (c.getSectionMass() > 0)) {
|
||||
sb.append(" (")
|
||||
.append(UnitGroup.UNITS_MASS.toStringUnit(c
|
||||
.getSectionMass())).append(" ").append(trans.get("ComponentTreeRenderer.total")).append(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add component override information in title
|
||||
if (c.isMassOverridden() && c.getMassOverriddenBy() == null) {
|
||||
sb.append(", ").append(trans.get("ComponentTree.ttip.massoverride"));
|
||||
}
|
||||
if (c.isCGOverridden() && c.getCGOverriddenBy() == null) {
|
||||
sb.append(", ").append(trans.get("ComponentTree.ttip.cgoverride"));
|
||||
}
|
||||
if (c.isCDOverridden() && c.getCDOverriddenBy() == null) {
|
||||
sb.append(", ").append(trans.get("ComponentTree.ttip.cdoverride"));
|
||||
}
|
||||
|
||||
// Add parent component override information on new lines
|
||||
if (overriddenBy != null) {
|
||||
sb.append("<br>").append(String.format(trans.get("RocketCompCfg.lbl.MassOverriddenBy"), overriddenBy.getName()));
|
||||
sb.append(" (").append(
|
||||
UnitGroup.UNITS_MASS.toStringUnit(c.getMass()));
|
||||
if (c.getChildCount() > 0) {
|
||||
sb.append(" of ")
|
||||
.append(UnitGroup.UNITS_MASS.toStringUnit(c
|
||||
.getSectionMass())).append(" total");
|
||||
}
|
||||
sb.append(")");
|
||||
} else {
|
||||
if ((c.getChildCount() > 0) && (c.getSectionMass() > 0)) {
|
||||
sb.append(" (")
|
||||
.append(UnitGroup.UNITS_MASS.toStringUnit(c
|
||||
.getSectionMass())).append(" total)");
|
||||
}
|
||||
}
|
||||
|
||||
if (c.isMassOverridden()) {
|
||||
sb.append(" ").append(trans.get("ComponentTree.ttip.massoverride"));
|
||||
}
|
||||
|
||||
if (c.isCGOverridden()) {
|
||||
sb.append(" ").append(trans.get("ComponentTree.ttip.cgoverride"));
|
||||
UnitGroup.UNITS_MASS.toStringUnit(overriddenBy.getMass())).append(")");
|
||||
}
|
||||
overriddenBy = c.getCGOverriddenBy();
|
||||
if (overriddenBy != null) {
|
||||
sb.append("<br>").append(String.format(trans.get("RocketCompCfg.lbl.CGOverriddenBy"), overriddenBy.getName()));
|
||||
sb.append(" (").append(
|
||||
UnitGroup.UNITS_LENGTH.toStringUnit(overriddenBy.getOverrideCGX())).append(")");
|
||||
}
|
||||
overriddenBy = c.getCDOverriddenBy();
|
||||
if (overriddenBy != null) {
|
||||
sb.append("<br>").append(String.format(trans.get("RocketCompCfg.lbl.CDOverriddenBy"), overriddenBy.getName()));
|
||||
sb.append(" (").append(overriddenBy.getOverrideCD()).append(")");
|
||||
}
|
||||
|
||||
// Add component comment on new line
|
||||
String comment = c.getComment().trim();
|
||||
if (comment.length() > 0) {
|
||||
comment = TextUtil.escapeXML(comment);
|
||||
@ -132,11 +168,24 @@ public class ComponentTreeRenderer extends DefaultTreeCellRenderer {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<html>");
|
||||
|
||||
// Components title
|
||||
sb.append("<b>Components</b>");
|
||||
|
||||
// Calculate the total mass of the selected components
|
||||
double totalMass = 0;
|
||||
double totalSectionMass = 0;
|
||||
boolean containsSectionMass = false;
|
||||
List<RocketComponent> overriddenByComponents = new java.util.ArrayList<>(); // Components that override the mass of the selected components
|
||||
for (RocketComponent c : components) {
|
||||
RocketComponent overriddenBy = c.getMassOverriddenBy();
|
||||
if (overriddenBy != null) {
|
||||
if (!components.contains(overriddenBy) && !overriddenByComponents.contains(overriddenBy)) {
|
||||
totalMass += overriddenBy.getMass();
|
||||
overriddenByComponents.add(overriddenBy);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c.isMassive() || c.isMassOverridden()) {
|
||||
totalMass += c.getMass();
|
||||
// Don't add this component's mass to the section mass if its parent is in the list, otherwise you add up duplicate mass
|
||||
@ -155,9 +204,11 @@ public class ComponentTreeRenderer extends DefaultTreeCellRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
// Add total mass of the selected components in the title
|
||||
sb.append(" (").append(UnitGroup.UNITS_MASS.toStringUnit(totalMass));
|
||||
if (containsSectionMass) {
|
||||
sb.append(" of ").append(UnitGroup.UNITS_MASS.toStringUnit(totalSectionMass)).append(" total)");
|
||||
sb.append(" of ").append(UnitGroup.UNITS_MASS.toStringUnit(totalSectionMass))
|
||||
.append(" ").append(trans.get("ComponentTreeRenderer.total")).append(")");
|
||||
} else {
|
||||
sb.append(")");
|
||||
}
|
||||
|
@ -94,8 +94,11 @@ public class Icons {
|
||||
public static final Icon FAVORITE = loadImageIcon("pix/icons/star_gold.png", "Favorite");
|
||||
|
||||
public static final Icon CG_OVERRIDE = loadImageIcon("pix/icons/cg-override.png", "CG Override");
|
||||
public static final Icon CG_OVERRIDE_SUBCOMPONENT = loadImageIcon("pix/icons/cg-override-subcomponent.png", "CG Override Subcomponent");
|
||||
public static final Icon CD_OVERRIDE = loadImageIcon("pix/icons/cd-override.png", "CD Override");
|
||||
public static final Icon CD_OVERRIDE_SUBCOMPONENT = loadImageIcon("pix/icons/cd-override-subcomponent.png", "CD Override Subcomponent");
|
||||
public static final Icon MASS_OVERRIDE = loadImageIcon("pix/icons/mass-override.png", "Mass Override");
|
||||
public static final Icon MASS_OVERRIDE_SUBCOMPONENT = loadImageIcon("pix/icons/mass-override-subcomponent.png", "Mass Override Subcomponent");
|
||||
|
||||
// MANUFACTURERS ICONS
|
||||
public static final Icon RASAERO_ICON = loadImageIcon("pix/icons/RASAero_16.png", "RASAero Icon");
|
||||
|
Loading…
x
Reference in New Issue
Block a user