Fix saving inner appearance

This commit is contained in:
Sibo Van Gool 2021-06-30 00:11:21 +02:00
parent 5fa3b2cd3a
commit 46d9841947
8 changed files with 166 additions and 59 deletions

View File

@ -9,6 +9,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import net.sf.openrocket.rocketcomponent.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -19,12 +20,6 @@ import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.document.events.DocumentChangeListener;
import net.sf.openrocket.document.events.SimulationChangeEvent;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.customexpression.CustomExpression;
import net.sf.openrocket.simulation.extension.SimulationExtension;
@ -259,7 +254,10 @@ public class OpenRocketDocument implements ComponentChangeListener {
Iterator<RocketComponent> it = rocket.iterator();
while (it.hasNext()) {
if(hasDecal(it.next(),img))
RocketComponent c = it.next();
if(hasDecal(c ,img))
count++;
else if (hasDecalInside(c, img))
count++;
}
return count;
@ -285,6 +283,29 @@ public class OpenRocketDocument implements ComponentChangeListener {
return false;
}
//TODO: LOW: move this method to rocketComponent, Appearance and decal
//I see 3 layers of object accessed, seems unsafe
/**
* checks if a rocket component has the given inside decalImage
* @param comp the RocketComponent to be searched
* @param img the DecalImage to be checked
* @return if the comp has img
*/
private boolean hasDecalInside(RocketComponent comp, DecalImage img) {
if (comp instanceof InsideColorComponent) {
Appearance a = ((InsideColorComponent)comp).getInsideAppearance();
if (a == null)
return false;
Decal d = a.getTexture();
if (d == null)
return false;
if (img.equals(d.getImage()))
return true;
return false;
}
return false;
}
/**
* gets a unique identification for the given decal
* @param img the decal to be made unique

View File

@ -20,6 +20,7 @@ import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.document.StorageOptions.FileType;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.file.rocksim.export.RocksimSaver;
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.MathUtil;
@ -84,7 +85,7 @@ public class GeneralRocketSaver {
*
* @param dest the destination stream.
* @param doc the document to save.
* @param options the storage options.
* @param opts the storage options.
* @param progress a SavingProgress object used to provide progress information
* @throws IOException in case of an I/O error.
*/
@ -159,18 +160,23 @@ public class GeneralRocketSaver {
// Look for all decals used in the rocket.
for (RocketComponent c : document.getRocket()) {
if (c.getAppearance() == null) {
continue;
}
Appearance ap = c.getAppearance();
if (ap.getTexture() == null) {
continue;
}
Appearance ap_in = null;
if (c instanceof InsideColorComponent)
ap_in = ((InsideColorComponent)c).getInsideAppearance();
if ((ap == null) && (ap_in == null)) continue;
if (ap != null) {
Decal decal = ap.getTexture();
if (decal != null)
usedDecals.add(decal.getImage());
}
if (ap_in != null) {
Decal decal = ap_in.getTexture();
if (decal != null)
usedDecals.add(decal.getImage());
}
}
saveAllPartsZipFile(output, document, options, usedDecals);
}

View File

@ -16,11 +16,11 @@ import net.sf.openrocket.util.Color;
import org.xml.sax.SAXException;
class AppearanceHandler extends AbstractElementHandler {
private final DocumentLoadingContext context;
private final RocketComponent component;
protected final DocumentLoadingContext context;
protected final RocketComponent component;
private final AppearanceBuilder builder = new AppearanceBuilder();
private boolean isInDecal = false;
protected final AppearanceBuilder builder = new AppearanceBuilder();
protected boolean isInDecal = false;
public AppearanceHandler(RocketComponent component, DocumentLoadingContext context) {
this.context = context;
@ -99,8 +99,12 @@ class AppearanceHandler extends AbstractElementHandler {
isInDecal = false;
return;
}
component.setAppearance(builder.getAppearance());
setAppearance();
super.endHandler(element, attributes, content, warnings);
}
protected void setAppearance() {
component.setAppearance(builder.getAppearance());
}
}

View File

@ -40,6 +40,9 @@ class ComponentParameterHandler extends AbstractElementHandler {
if ( element.equals("appearance")) {
return new AppearanceHandler(component,context);
}
if (element.equals("inside-appearance")) {
return new InsideAppearanceHandler(component, context);
}
if (element.equals("motormount")) {
if (!(component instanceof MotorMount)) {
warnings.add(Warning.fromString("Illegal component defined as motor mount."));
@ -92,8 +95,8 @@ class ComponentParameterHandler extends AbstractElementHandler {
if (element.equals("subcomponents") || element.equals("motormount") ||
element.equals("finpoints") || element.equals("motorconfiguration") ||
element.equals("appearance") || element.equals("deploymentconfiguration") ||
element.equals("separationconfiguration")) {
element.equals("appearance") || element.equals("inside-appearance") ||
element.equals("deploymentconfiguration") || element.equals("separationconfiguration")) {
return;
}

View File

@ -0,0 +1,45 @@
package net.sf.openrocket.file.openrocket.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import org.xml.sax.SAXException;
import java.util.HashMap;
public class InsideAppearanceHandler extends AppearanceHandler {
public InsideAppearanceHandler(RocketComponent component, DocumentLoadingContext context) {
super(component, context);
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
if ("edgesSameAsInside".equals(element)) {
boolean edgesSameAsInside = Boolean.parseBoolean(content);
if (component instanceof InsideColorComponent)
((InsideColorComponent)component).setEdgesSameAsInside(edgesSameAsInside);
return;
}
if ("insideSameAsOutside".equals(element)) {
boolean insideSameAsOutside = Boolean.parseBoolean(content);
if (component instanceof InsideColorComponent)
((InsideColorComponent)component).setInsideSameAsOutside(insideSameAsOutside);
return;
}
super.closeElement(element, attributes, content, warnings);
}
@Override
protected void setAppearance() {
if ((component instanceof InsideColorComponent))
((InsideColorComponent)component).setInsideAppearance(builder.getAppearance());
}
}

View File

@ -15,14 +15,7 @@ import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.rocketcomponent.Clusterable;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.Instanceable;
import net.sf.openrocket.rocketcomponent.LineInstanceable;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.*;
import net.sf.openrocket.rocketcomponent.position.AnglePositionable;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.rocketcomponent.position.RadiusPositionable;
@ -50,29 +43,26 @@ public class RocketComponentSaver {
"\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() + "\"/>");
}
// Save outside appearance
Appearance ap = c.getAppearance();
if (ap != null) {
elements.add("<appearance>");
Color paint = ap.getPaint();
emitColor("paint", elements, paint);
elements.add("<shine>" + ap.getShine() + "</shine>");
Decal decal = ap.getTexture();
if (decal != null) {
String name = decal.getImage().getName();
double rotation = decal.getRotation();
EdgeMode edgeMode = decal.getEdgeMode();
elements.add("<decal name=\"" + TextUtil.escapeXML(name) + "\" rotation=\"" + rotation + "\" edgemode=\"" + edgeMode.name() + "\">");
Coordinate center = decal.getCenter();
elements.add("<center x=\"" + center.x + "\" y=\"" + center.y + "\"/>");
Coordinate offset = decal.getOffset();
elements.add("<offset x=\"" + offset.x + "\" y=\"" + offset.y + "\"/>");
Coordinate scale = decal.getScale();
elements.add("<scale x=\"" + scale.x + "\" y=\"" + scale.y + "\"/>");
elements.add("</decal>");
}
buildAppearanceElements(elements, ap);
elements.add("</appearance>");
}
// Save inside appearance
if (c instanceof InsideColorComponent) {
Appearance ap_in = ((InsideColorComponent)c).getInsideAppearance();
if (ap_in != null) {
elements.add("<inside-appearance>");
elements.add("<edgesSameAsInside>" + ((InsideColorComponent) c).isEdgesSameAsInside() + "</edgesSameAsInside>");
elements.add("<insideSameAsOutside>" + ((InsideColorComponent) c).isInsideSameAsOutside() + "</insideSameAsOutside>");
buildAppearanceElements(elements, ap_in);
elements.add("</inside-appearance>");
}
}
// Save color and line style if significant
if (!(c instanceof Rocket || c instanceof ComponentAssembly)) {
Color color = c.getColor();
@ -148,8 +138,25 @@ public class RocketComponentSaver {
}
private void buildAppearanceElements(List<String> elements, Appearance a) {
Color paint = a.getPaint();
emitColor("paint", elements, paint);
elements.add("<shine>" + a.getShine() + "</shine>");
Decal decal = a.getTexture();
if (decal != null) {
String name = decal.getImage().getName();
double rotation = decal.getRotation();
EdgeMode edgeMode = decal.getEdgeMode();
elements.add("<decal name=\"" + TextUtil.escapeXML(name) + "\" rotation=\"" + rotation + "\" edgemode=\"" + edgeMode.name() + "\">");
Coordinate center = decal.getCenter();
elements.add("<center x=\"" + center.x + "\" y=\"" + center.y + "\"/>");
Coordinate offset = decal.getOffset();
elements.add("<offset x=\"" + offset.x + "\" y=\"" + offset.y + "\"/>");
Coordinate scale = decal.getScale();
elements.add("<scale x=\"" + scale.x + "\" y=\"" + scale.y + "\"/>");
elements.add("</decal>");
}
}
protected final String materialParam(Material mat) {
return materialParam("material", mat);

View File

@ -442,7 +442,7 @@ public class AppearancePanel extends JPanel {
DecalImage newImage = editDecalHelper.editDecal(
SwingUtilities
.getWindowAncestor(panel),
document, c, builder.getImage());
document, c, builder.getImage(), insideBuilder);
builder.setImage(newImage);
} catch (EditDecalHelperException ex) {
JOptionPane.showMessageDialog(panel,

View File

@ -16,6 +16,7 @@ import net.sf.openrocket.gui.watcher.FileWatcher;
import net.sf.openrocket.gui.watcher.WatchEvent;
import net.sf.openrocket.gui.watcher.WatchService;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import com.google.inject.Inject;
@ -67,10 +68,12 @@ public class EditDecalHelper {
* @param doc
* @param component
* @param decal
* @param insideApp flag to check whether it is the inside appearance that is edited
* @return
* @throws EditDecalHelperException
*/
public DecalImage editDecal(Window parent, OpenRocketDocument doc, RocketComponent component, DecalImage decal) throws EditDecalHelperException {
public DecalImage editDecal(Window parent, OpenRocketDocument doc, RocketComponent component, DecalImage decal,
boolean insideApp) throws EditDecalHelperException {
boolean sysPrefSet = prefs.isDecalEditorPreferenceSet();
int usageCount = doc.countDecalUsage(decal);
@ -111,7 +114,10 @@ public class EditDecalHelper {
}
if (dialog.isEditOne()) {
if (insideApp)
decal = makeDecalUnique(doc, component, decal);
else
decal = makeDecalUniqueInside(doc, component, decal);
}
launchEditor(useSystemEditor, commandLine, decal);
@ -132,6 +138,21 @@ public class EditDecalHelper {
return newImage;
}
private static DecalImage makeDecalUniqueInside(OpenRocketDocument doc, RocketComponent component, DecalImage decal) {
DecalImage newImage = doc.makeUniqueDecal(decal);
if (component instanceof InsideColorComponent) {
InsideColorComponent c = ((InsideColorComponent)component);
AppearanceBuilder appearanceBuilder = new AppearanceBuilder(c.getInsideAppearance());
appearanceBuilder.setImage(newImage);
c.setInsideAppearance(appearanceBuilder.getAppearance());
}
return newImage;
}
private void launchEditor(boolean useSystemEditor, String commandTemplate, final DecalImage decal) throws EditDecalHelperException {
String decalId = decal.getName();