diff --git a/core/src/net/sf/openrocket/document/OpenRocketDocument.java b/core/src/net/sf/openrocket/document/OpenRocketDocument.java index 8efe1460e..c5cdb94cc 100644 --- a/core/src/net/sf/openrocket/document/OpenRocketDocument.java +++ b/core/src/net/sf/openrocket/document/OpenRocketDocument.java @@ -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 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; @@ -284,6 +282,29 @@ public class OpenRocketDocument implements ComponentChangeListener { return true; 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 diff --git a/core/src/net/sf/openrocket/file/GeneralRocketSaver.java b/core/src/net/sf/openrocket/file/GeneralRocketSaver.java index 877435ab2..7e1a1827c 100644 --- a/core/src/net/sf/openrocket/file/GeneralRocketSaver.java +++ b/core/src/net/sf/openrocket/file/GeneralRocketSaver.java @@ -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,17 +160,22 @@ 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()); } - - Decal decal = ap.getTexture(); - - usedDecals.add(decal.getImage()); } saveAllPartsZipFile(output, document, options, usedDecals); diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/AppearanceHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/AppearanceHandler.java index b59cea9cd..4d7445d14 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/AppearanceHandler.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/AppearanceHandler.java @@ -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; - - private final AppearanceBuilder builder = new AppearanceBuilder(); - private boolean isInDecal = false; + protected final DocumentLoadingContext context; + protected final RocketComponent component; + + protected final AppearanceBuilder builder = new AppearanceBuilder(); + protected boolean isInDecal = false; public AppearanceHandler(RocketComponent component, DocumentLoadingContext context) { this.context = context; @@ -44,7 +44,7 @@ class AppearanceHandler extends AbstractElementHandler { } return PlainTextHandler.INSTANCE; } - + @Override public void closeElement(String element, HashMap attributes, String content, WarningSet warnings) throws SAXException { if ("paint".equals(element)) { @@ -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()); + } } diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java index 7bc42fe54..89bb2fd6d 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/ComponentParameterHandler.java @@ -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; } diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java new file mode 100644 index 000000000..16c3e6753 --- /dev/null +++ b/core/src/net/sf/openrocket/file/openrocket/importt/InsideAppearanceHandler.java @@ -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 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()); + } +} diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java index 293550cb6..29664b387 100644 --- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java +++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java @@ -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; @@ -49,29 +42,26 @@ public class RocketComponentSaver { "\" manufacturer=\"" + preset.getManufacturer().getSimpleName() + "\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() + "\"/>"); } - + + // Save outside appearance Appearance ap = c.getAppearance(); if (ap != null) { elements.add(""); - Color paint = ap.getPaint(); - emitColor("paint", elements, paint); - elements.add("" + ap.getShine() + ""); - Decal decal = ap.getTexture(); - if (decal != null) { - String name = decal.getImage().getName(); - double rotation = decal.getRotation(); - EdgeMode edgeMode = decal.getEdgeMode(); - elements.add(""); - Coordinate center = decal.getCenter(); - elements.add("
"); - Coordinate offset = decal.getOffset(); - elements.add(""); - Coordinate scale = decal.getScale(); - elements.add(""); - elements.add(""); - } + buildAppearanceElements(elements, ap); elements.add(""); } + + // Save inside appearance + if (c instanceof InsideColorComponent) { + Appearance ap_in = ((InsideColorComponent)c).getInsideAppearance(); + if (ap_in != null) { + elements.add(""); + elements.add("" + ((InsideColorComponent) c).isEdgesSameAsInside() + ""); + elements.add("" + ((InsideColorComponent) c).isInsideSameAsOutside() + ""); + buildAppearanceElements(elements, ap_in); + elements.add(""); + } + } // Save color and line style if significant if (!(c instanceof Rocket || c instanceof ComponentAssembly)) { @@ -147,10 +137,27 @@ public class RocketComponentSaver { } } - - - - + + private void buildAppearanceElements(List elements, Appearance a) { + Color paint = a.getPaint(); + emitColor("paint", elements, paint); + elements.add("" + a.getShine() + ""); + Decal decal = a.getTexture(); + if (decal != null) { + String name = decal.getImage().getName(); + double rotation = decal.getRotation(); + EdgeMode edgeMode = decal.getEdgeMode(); + elements.add(""); + Coordinate center = decal.getCenter(); + elements.add("
"); + Coordinate offset = decal.getOffset(); + elements.add(""); + Coordinate scale = decal.getScale(); + elements.add(""); + elements.add(""); + } + } + protected final String materialParam(Material mat) { return materialParam("material", mat); } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 22d63fe73..9fb0f9fff 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -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, diff --git a/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java b/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java index 864f3b2a1..b6ed0c1a5 100644 --- a/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java +++ b/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java @@ -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()) { - decal = makeDecalUnique(doc, component, decal); + if (insideApp) + decal = makeDecalUnique(doc, component, decal); + else + decal = makeDecalUniqueInside(doc, component, decal); } launchEditor(useSystemEditor, commandLine, decal); @@ -131,6 +137,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 {