Merge pull request #1983 from SiboVG/issue-1980

[#1980] Render booster markers even if no children
This commit is contained in:
Sibo Van Gool 2023-01-20 00:56:32 +01:00 committed by GitHub
commit 0258226aa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 110 deletions

View File

@ -67,6 +67,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
private Map<Integer, Boolean> preloadStageActiveness = null;
final private Collection<MotorConfiguration> activeMotors = new ConcurrentLinkedQueue<MotorConfiguration>();
final private InstanceMap activeInstances = new InstanceMap();
final private InstanceMap extraRenderInstances = new InstanceMap(); // Extra instances to be rendered, besides the active instances
private int boundsModID = -1;
private BoundingBox cachedBoundsAerodynamic = new BoundingBox(); // Bounding box of all aerodynamic components
@ -288,7 +289,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
}
AxialStage stage = rocket.getStage(stageNumber);
return stage != null && stage.getChildCount() > 0 &&
return stage != null && stage.getChildCount() > 0 && // Stages with no children are marked as inactive
stages.get(stageNumber) != null && stages.get(stageNumber).active;
}
@ -398,6 +399,15 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
public InstanceMap getActiveInstances() {
return activeInstances;
}
/**
* Returns the InstanceMap of instances that need to be rendered, but are not present in {@link #getActiveInstances()}.
* This is the case for example for a booster that has no children. It is marked as an inactive stage, but it still needs to be rendered.
* @return the InstanceMap of instances that need to be rendered, but are not present in {@link #getActiveInstances()}.
*/
public InstanceMap getExtraRenderInstances() {
return extraRenderInstances;
}
/*
* Generates a read-only, instance-aware collection of the components for this rocket & configuration
@ -406,7 +416,8 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
*/
private void updateActiveInstances() {
activeInstances.clear();
getActiveContextListAt( this.rocket, activeInstances, Transformation.IDENTITY);
extraRenderInstances.clear();
getActiveContextListAt(this.rocket, activeInstances, Transformation.IDENTITY);
}
private InstanceMap getActiveContextListAt(final RocketComponent component, final InstanceMap results, final Transformation parentTransform ){
@ -427,7 +438,11 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
// constructs entry in-place if this component is active
if (this.isComponentActive(component)) {
results.emplace(component, this.isComponentActive(component), currentInstanceNumber, currentTransform);
results.emplace(component, currentInstanceNumber, currentTransform);
} else if (component instanceof ParallelStage && stages.get(component.getStageNumber()).active) {
// Boosters with no children are marked as inactive, but still need to be rendered.
// See GitHub issue #1980 for more information.
extraRenderInstances.emplace(component, currentInstanceNumber, currentTransform);
}
for(RocketComponent child : component.getChildren()) {

View File

@ -27,15 +27,13 @@ public class InstanceMap extends ConcurrentHashMap<RocketComponent, ArrayList<In
}
}
public void emplace(final RocketComponent component, boolean active, int number, final Transformation xform) {
final RocketComponent key = component;
if(!containsKey(component)) {
put(key, new ArrayList<InstanceContext>());
public void emplace(final RocketComponent component, int number, final Transformation transform) {
if (!containsKey(component)) {
put(component, new ArrayList<>());
}
final InstanceContext context = new InstanceContext(component, number, xform);
get(key).add(context);
final InstanceContext context = new InstanceContext(component, number, transform);
get(component).add(context);
}
public List<InstanceContext> getInstanceContexts(final RocketComponent key) {

View File

@ -0,0 +1,66 @@
package net.sf.openrocket.gui.rocketfigure;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.PodSet;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Transformation;
import java.awt.Shape;
public class ComponentAssemblyShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) {
// Ignore normal stages
if (component instanceof AxialStage && !(component instanceof ParallelStage)) {
return null;
}
double radius = getDisplayRadius(component);
Shape[] s = EmptyShapes.getShapesSideWithSelectionSquare(transformation, radius);
RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component);
// Set the color of the shapes
Color color = getColor(component);
for (int i = 0; i < shapes.length - 1; i++) {
shapes[i].setColor(color);
}
return shapes;
}
public static RocketComponentShape[] getShapesBack(final RocketComponent component, final Transformation transformation) {
// Ignore normal stages
if (component instanceof AxialStage && !(component instanceof ParallelStage)) {
return null;
}
double radius = getDisplayRadius(component);
Shape[] s = EmptyShapes.getShapesBackWithSelectionSquare(transformation, radius);
RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component);
// Set the color of the shapes
Color color = getColor(component);
for (int i = 0; i < shapes.length - 1; i++) {
shapes[i].setColor(color);
}
return shapes;
}
private static double getDisplayRadius(RocketComponent component) {
return component.getRocket().getBoundingRadius() * 0.03;
}
private static Color getColor(RocketComponent component) {
if (component instanceof PodSet) {
return new Color(160,160,215);
} else if (component instanceof ParallelStage) {
return new Color(198,163,184);
} else {
return new Color(160, 160, 160);
}
}
}

View File

@ -1,48 +0,0 @@
package net.sf.openrocket.gui.rocketfigure;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Transformation;
import java.awt.Shape;
public class ParallelStageShapes extends RocketComponentShape {
public static final Color boosterColor = new Color(198,163,184);
public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) {
ParallelStage booster = (ParallelStage)component;
double radius = getDisplayRadius(booster);
Shape[] s = EmptyShapes.getShapesSideWithSelectionSquare(transformation, radius);
RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component);
// Set the color of the shapes
for (int i = 0; i < shapes.length - 1; i++) {
shapes[i].setColor(boosterColor);
}
shapes[shapes.length - 1].setColor(Color.INVISIBLE);
return shapes;
}
public static RocketComponentShape[] getShapesBack(final RocketComponent component, final Transformation transformation) {
ParallelStage booster = (ParallelStage)component;
double radius = getDisplayRadius(booster);
Shape[] s = EmptyShapes.getShapesBackWithSelectionSquare(transformation, radius);
RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component);
// Set the color of the shapes
for (int i = 0; i < shapes.length - 1; i++) {
shapes[i].setColor(boosterColor);
}
shapes[shapes.length - 1].setColor(Color.INVISIBLE);
return shapes;
}
private static double getDisplayRadius(ParallelStage booster) {
return booster.getRocket().getBoundingRadius() * 0.03;
}
}

View File

@ -1,48 +0,0 @@
package net.sf.openrocket.gui.rocketfigure;
import net.sf.openrocket.rocketcomponent.PodSet;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Transformation;
import java.awt.Shape;
public class PodSetShapes extends RocketComponentShape {
public static final Color podsetColor = new Color(160,160,215);
public static RocketComponentShape[] getShapesSide(final RocketComponent component, final Transformation transformation) {
PodSet podset = (PodSet)component;
double radius = getDisplayRadius(podset);
Shape[] s = EmptyShapes.getShapesSideWithSelectionSquare(transformation, radius);
RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component);
// Set the color of the shapes
for (int i = 0; i < shapes.length - 1; i++) {
shapes[i].setColor(podsetColor);
}
shapes[shapes.length - 1].setColor(Color.INVISIBLE);
return shapes;
}
public static RocketComponentShape[] getShapesBack(final RocketComponent component, final Transformation transformation) {
PodSet podset = (PodSet)component;
double radius = getDisplayRadius(podset);
Shape[] s = EmptyShapes.getShapesBackWithSelectionSquare(transformation, radius);
RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component);
// Set the color of the shapes
for (int i = 0; i < shapes.length - 1; i++) {
shapes[i].setColor(podsetColor);
}
shapes[shapes.length - 1].setColor(Color.INVISIBLE);
return shapes;
}
private static double getDisplayRadius(PodSet podset) {
return podset.getRocket().getBoundingRadius() * 0.03;
}
}

View File

@ -384,11 +384,16 @@ public class RocketFigure extends AbstractScaleFigure {
// allShapes is an output buffer -- it stores all the generated shapes
allShapes.clear();
for (Entry<RocketComponent, ArrayList<InstanceContext>> entry : config.getActiveInstances().entrySet()) {
addShapesFromInstanceEntries(allShapes, config.getActiveInstances().entrySet());
addShapesFromInstanceEntries(allShapes, config.getExtraRenderInstances().entrySet());
}
private void addShapesFromInstanceEntries(PriorityQueue<RocketComponentShape> allShapes, Set<Entry<RocketComponent, ArrayList<InstanceContext>>> entries) {
for (Entry<RocketComponent, ArrayList<InstanceContext>> entry : entries) {
final RocketComponent comp = entry.getKey();
// Only draw podsets when they are selected
if ((comp instanceof PodSet || comp instanceof ParallelStage) && preferences.isShowMarkers()) {
// Only draw pod sets and boosters when they are selected
if (preferences.isShowMarkers() && (comp instanceof PodSet || comp instanceof ParallelStage)) {
boolean selected = false;
// Check if component is in the selection
@ -409,7 +414,7 @@ public class RocketFigure extends AbstractScaleFigure {
}
}
}
/**
* Gets the shapes required to draw the component.
*