Merge pull request #962 from SiboVG/issue-905
[fixes #905] Added ability to select a different color for the outside and inside of component
This commit is contained in:
commit
a9ad4208f9
@ -809,6 +809,10 @@ AppearanceCfg.lbl.texture.offset = Offset:
|
|||||||
AppearanceCfg.lbl.texture.center = Center:
|
AppearanceCfg.lbl.texture.center = Center:
|
||||||
AppearanceCfg.lbl.texture.rotation = Rotation:
|
AppearanceCfg.lbl.texture.rotation = Rotation:
|
||||||
AppearanceCfg.lbl.texture.repeat = Repeat:
|
AppearanceCfg.lbl.texture.repeat = Repeat:
|
||||||
|
AppearanceCfg.lbl.InsideSameAsOutside = Same as outside
|
||||||
|
AppearanceCfg.lbl.ttip.InsideSameAsOutside = Use the same appearance for the inside as for the outside
|
||||||
|
AppearanceCfg.lbl.EdgesSameAsInside = Use inside appearance for edges
|
||||||
|
AppearanceCfg.lbl.ttip.EdgesSameAsInside = Use the inside appearance (checked) or outside appearance (unchecked) for the edges
|
||||||
|
|
||||||
! Texture Wrap Modes
|
! Texture Wrap Modes
|
||||||
TextureWrap.Repeat = Repeat
|
TextureWrap.Repeat = Repeat
|
||||||
@ -871,6 +875,8 @@ RocketCompCfg.border.Foreshoulder = Fore shoulder
|
|||||||
!RocketCompCfg.lbl.Length = Length:
|
!RocketCompCfg.lbl.Length = Length:
|
||||||
RocketCompCfg.lbl.InstanceCount = Instance Count
|
RocketCompCfg.lbl.InstanceCount = Instance Count
|
||||||
RocketCompCfg.lbl.InstanceSeparation = Instance Separation
|
RocketCompCfg.lbl.InstanceSeparation = Instance Separation
|
||||||
|
RocketCompCfg.tab.Outside = Outside
|
||||||
|
RocketCompCfg.tab.Inside = Inside
|
||||||
|
|
||||||
! BulkheadConfig
|
! BulkheadConfig
|
||||||
BulkheadCfg.tab.Diameter = Diameter:
|
BulkheadCfg.tab.Diameter = Diameter:
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.openrocket.rocketcomponent.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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.DocumentChangeListener;
|
||||||
import net.sf.openrocket.document.events.SimulationChangeEvent;
|
import net.sf.openrocket.document.events.SimulationChangeEvent;
|
||||||
import net.sf.openrocket.logging.Markers;
|
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.FlightDataType;
|
||||||
import net.sf.openrocket.simulation.customexpression.CustomExpression;
|
import net.sf.openrocket.simulation.customexpression.CustomExpression;
|
||||||
import net.sf.openrocket.simulation.extension.SimulationExtension;
|
import net.sf.openrocket.simulation.extension.SimulationExtension;
|
||||||
@ -259,7 +254,10 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
|
|
||||||
Iterator<RocketComponent> it = rocket.iterator();
|
Iterator<RocketComponent> it = rocket.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
if(hasDecal(it.next(),img))
|
RocketComponent c = it.next();
|
||||||
|
if(hasDecal(c ,img))
|
||||||
|
count++;
|
||||||
|
else if (hasDecalInside(c, img))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@ -284,6 +282,29 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
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).getInsideColorComponentHandler().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
|
* gets a unique identification for the given decal
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import net.sf.openrocket.document.StorageOptions;
|
|||||||
import net.sf.openrocket.document.StorageOptions.FileType;
|
import net.sf.openrocket.document.StorageOptions.FileType;
|
||||||
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
|
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
|
||||||
import net.sf.openrocket.file.rocksim.export.RocksimSaver;
|
import net.sf.openrocket.file.rocksim.export.RocksimSaver;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ public class GeneralRocketSaver {
|
|||||||
*
|
*
|
||||||
* @param dest the destination stream.
|
* @param dest the destination stream.
|
||||||
* @param doc the document to save.
|
* @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
|
* @param progress a SavingProgress object used to provide progress information
|
||||||
* @throws IOException in case of an I/O error.
|
* @throws IOException in case of an I/O error.
|
||||||
*/
|
*/
|
||||||
@ -159,17 +160,22 @@ public class GeneralRocketSaver {
|
|||||||
|
|
||||||
// Look for all decals used in the rocket.
|
// Look for all decals used in the rocket.
|
||||||
for (RocketComponent c : document.getRocket()) {
|
for (RocketComponent c : document.getRocket()) {
|
||||||
if (c.getAppearance() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Appearance ap = c.getAppearance();
|
Appearance ap = c.getAppearance();
|
||||||
if (ap.getTexture() == null) {
|
Appearance ap_in = null;
|
||||||
continue;
|
if (c instanceof InsideColorComponent)
|
||||||
|
ap_in = ((InsideColorComponent)c).getInsideColorComponentHandler().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);
|
saveAllPartsZipFile(output, document, options, usedDecals);
|
||||||
|
|||||||
@ -16,11 +16,11 @@ import net.sf.openrocket.util.Color;
|
|||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
class AppearanceHandler extends AbstractElementHandler {
|
class AppearanceHandler extends AbstractElementHandler {
|
||||||
private final DocumentLoadingContext context;
|
protected final DocumentLoadingContext context;
|
||||||
private final RocketComponent component;
|
protected final RocketComponent component;
|
||||||
|
|
||||||
private final AppearanceBuilder builder = new AppearanceBuilder();
|
protected final AppearanceBuilder builder = new AppearanceBuilder();
|
||||||
private boolean isInDecal = false;
|
protected boolean isInDecal = false;
|
||||||
|
|
||||||
public AppearanceHandler(RocketComponent component, DocumentLoadingContext context) {
|
public AppearanceHandler(RocketComponent component, DocumentLoadingContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -44,7 +44,7 @@ class AppearanceHandler extends AbstractElementHandler {
|
|||||||
}
|
}
|
||||||
return PlainTextHandler.INSTANCE;
|
return PlainTextHandler.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
|
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
|
||||||
if ("paint".equals(element)) {
|
if ("paint".equals(element)) {
|
||||||
@ -99,8 +99,12 @@ class AppearanceHandler extends AbstractElementHandler {
|
|||||||
isInDecal = false;
|
isInDecal = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
component.setAppearance(builder.getAppearance());
|
setAppearance();
|
||||||
super.endHandler(element, attributes, content, warnings);
|
super.endHandler(element, attributes, content, warnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setAppearance() {
|
||||||
|
component.setAppearance(builder.getAppearance());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,9 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
|||||||
if ( element.equals("appearance")) {
|
if ( element.equals("appearance")) {
|
||||||
return new AppearanceHandler(component,context);
|
return new AppearanceHandler(component,context);
|
||||||
}
|
}
|
||||||
|
if (element.equals("inside-appearance")) {
|
||||||
|
return new InsideAppearanceHandler(component, context);
|
||||||
|
}
|
||||||
if (element.equals("motormount")) {
|
if (element.equals("motormount")) {
|
||||||
if (!(component instanceof MotorMount)) {
|
if (!(component instanceof MotorMount)) {
|
||||||
warnings.add(Warning.fromString("Illegal component defined as motor mount."));
|
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") ||
|
if (element.equals("subcomponents") || element.equals("motormount") ||
|
||||||
element.equals("finpoints") || element.equals("motorconfiguration") ||
|
element.equals("finpoints") || element.equals("motorconfiguration") ||
|
||||||
element.equals("appearance") || element.equals("deploymentconfiguration") ||
|
element.equals("appearance") || element.equals("inside-appearance") ||
|
||||||
element.equals("separationconfiguration")) {
|
element.equals("deploymentconfiguration") || element.equals("separationconfiguration")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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).getInsideColorComponentHandler().setEdgesSameAsInside(edgesSameAsInside);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ("insideSameAsOutside".equals(element)) {
|
||||||
|
boolean insideSameAsOutside = Boolean.parseBoolean(content);
|
||||||
|
if (component instanceof InsideColorComponent)
|
||||||
|
((InsideColorComponent)component).getInsideColorComponentHandler().setInsideSameAsOutside(insideSameAsOutside);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.closeElement(element, attributes, content, warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setAppearance() {
|
||||||
|
if ((component instanceof InsideColorComponent))
|
||||||
|
((InsideColorComponent)component).getInsideColorComponentHandler().setInsideAppearance(builder.getAppearance());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,14 +15,7 @@ import net.sf.openrocket.motor.Motor;
|
|||||||
import net.sf.openrocket.motor.MotorConfiguration;
|
import net.sf.openrocket.motor.MotorConfiguration;
|
||||||
import net.sf.openrocket.motor.ThrustCurveMotor;
|
import net.sf.openrocket.motor.ThrustCurveMotor;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.rocketcomponent.Clusterable;
|
import net.sf.openrocket.rocketcomponent.*;
|
||||||
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.position.AnglePositionable;
|
import net.sf.openrocket.rocketcomponent.position.AnglePositionable;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.RadiusPositionable;
|
import net.sf.openrocket.rocketcomponent.position.RadiusPositionable;
|
||||||
@ -49,29 +42,27 @@ public class RocketComponentSaver {
|
|||||||
"\" manufacturer=\"" + preset.getManufacturer().getSimpleName() +
|
"\" manufacturer=\"" + preset.getManufacturer().getSimpleName() +
|
||||||
"\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() + "\"/>");
|
"\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() + "\"/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save outside appearance
|
||||||
Appearance ap = c.getAppearance();
|
Appearance ap = c.getAppearance();
|
||||||
if (ap != null) {
|
if (ap != null) {
|
||||||
elements.add("<appearance>");
|
elements.add("<appearance>");
|
||||||
Color paint = ap.getPaint();
|
buildAppearanceElements(elements, ap);
|
||||||
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>");
|
|
||||||
}
|
|
||||||
elements.add("</appearance>");
|
elements.add("</appearance>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save inside appearance
|
||||||
|
if (c instanceof InsideColorComponent) {
|
||||||
|
InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler();
|
||||||
|
Appearance ap_in = handler.getInsideAppearance();
|
||||||
|
if (ap_in != null) {
|
||||||
|
elements.add("<inside-appearance>");
|
||||||
|
elements.add("<edgesSameAsInside>" + handler.isEdgesSameAsInside() + "</edgesSameAsInside>");
|
||||||
|
elements.add("<insideSameAsOutside>" + handler.isInsideSameAsOutside() + "</insideSameAsOutside>");
|
||||||
|
buildAppearanceElements(elements, ap_in);
|
||||||
|
elements.add("</inside-appearance>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Save color and line style if significant
|
// Save color and line style if significant
|
||||||
if (!(c instanceof Rocket || c instanceof ComponentAssembly)) {
|
if (!(c instanceof Rocket || c instanceof ComponentAssembly)) {
|
||||||
@ -147,10 +138,27 @@ 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) {
|
protected final String materialParam(Material mat) {
|
||||||
return materialParam("material", mat);
|
return materialParam("material", mat);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,17 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.EventObject;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.motor.Motor;
|
import net.sf.openrocket.motor.Motor;
|
||||||
import net.sf.openrocket.motor.MotorConfiguration;
|
import net.sf.openrocket.motor.MotorConfiguration;
|
||||||
import net.sf.openrocket.motor.MotorConfigurationSet;
|
import net.sf.openrocket.motor.MotorConfigurationSet;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
import net.sf.openrocket.util.*;
|
||||||
import net.sf.openrocket.util.BugException;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
|
||||||
import net.sf.openrocket.util.MathUtil;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +20,7 @@ import net.sf.openrocket.util.MathUtil;
|
|||||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMount, Coaxial {
|
public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMount, Coaxial, InsideColorComponent {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
private double outerRadius = 0;
|
private double outerRadius = 0;
|
||||||
@ -33,6 +31,8 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
|
|||||||
private boolean isActingMount = false;
|
private boolean isActingMount = false;
|
||||||
|
|
||||||
private MotorConfigurationSet motors;
|
private MotorConfigurationSet motors;
|
||||||
|
|
||||||
|
private final InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
|
||||||
|
|
||||||
public BodyTube() {
|
public BodyTube() {
|
||||||
this(8 * DEFAULT_RADIUS, DEFAULT_RADIUS);
|
this(8 * DEFAULT_RADIUS, DEFAULT_RADIUS);
|
||||||
@ -455,4 +455,10 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
|
|||||||
public ClusterConfiguration getClusterConfiguration() {
|
public ClusterConfiguration getClusterConfiguration() {
|
||||||
return ClusterConfiguration.SINGLE;
|
return ClusterConfiguration.SINGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsideColorComponentHandler getInsideColorComponentHandler() {
|
||||||
|
return this.insideColorComponentHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a marker interface which, if applied to a component, will mark that component as having the possibility to
|
||||||
|
* have a different inside and outside color. This will cause the appearance editor of that component to have a separate
|
||||||
|
* section for the inside and outside color and will consequently also render the inside and outside of that component
|
||||||
|
* (in a 3D figure) differently.
|
||||||
|
*
|
||||||
|
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
|
||||||
|
*/
|
||||||
|
public interface InsideColorComponent {
|
||||||
|
/**
|
||||||
|
* @return the InsideColorComponentHandler
|
||||||
|
*/
|
||||||
|
InsideColorComponentHandler getInsideColorComponentHandler();
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component handles the necessary functionalities of an InsideColorComponent.
|
||||||
|
*
|
||||||
|
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
|
||||||
|
*/
|
||||||
|
public class InsideColorComponentHandler {
|
||||||
|
private final RocketComponent component;
|
||||||
|
private Appearance insideAppearance = null;
|
||||||
|
private boolean insideSameAsOutside = true;
|
||||||
|
private boolean edgesSameAsInside = true;
|
||||||
|
|
||||||
|
public InsideColorComponentHandler(RocketComponent component) {
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the realistic inside appearance of this component.
|
||||||
|
* <code>null</code> = use the default for this material
|
||||||
|
*
|
||||||
|
* @return The component's realistic inner appearance, or <code>null</code>
|
||||||
|
*/
|
||||||
|
public Appearance getInsideAppearance() {
|
||||||
|
return this.insideAppearance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the realistic inside appearance of this component.
|
||||||
|
* Use <code>null</code> for default.
|
||||||
|
*
|
||||||
|
* @param appearance the inner appearance to be set
|
||||||
|
*/
|
||||||
|
public void setInsideAppearance(Appearance appearance) {
|
||||||
|
this.insideAppearance = appearance;
|
||||||
|
if (this.insideAppearance != null) {
|
||||||
|
Decal d = this.insideAppearance.getTexture();
|
||||||
|
if (d != null) {
|
||||||
|
d.getImage().addChangeListener(new StateChangeListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged(EventObject e) {
|
||||||
|
component.fireComponentChangeEvent(ComponentChangeEvent.TEXTURE_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
component.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the component uses for the edges the same appearance as the inside (return true) or as the
|
||||||
|
* outside (return false)
|
||||||
|
*
|
||||||
|
* @return true if edges should use the same appearance as the inside,
|
||||||
|
* false if edges should use the same appearance as the outside
|
||||||
|
*/
|
||||||
|
public boolean isEdgesSameAsInside() {
|
||||||
|
return this.edgesSameAsInside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the new state for edgesUseInsideAppearance to newState
|
||||||
|
*
|
||||||
|
* @param newState new edgesUseInsideAppearance value
|
||||||
|
*/
|
||||||
|
public void setEdgesSameAsInside(boolean newState) {
|
||||||
|
this.edgesSameAsInside = newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the component should use the same appearance for the inside as the outside (return true) or as the
|
||||||
|
* outside (return false)
|
||||||
|
*
|
||||||
|
* @return true if edges should use the same appearance as the inside,
|
||||||
|
* false if edges should use the same appearance as the outside
|
||||||
|
*/
|
||||||
|
public boolean isInsideSameAsOutside() {
|
||||||
|
return this.insideSameAsOutside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the new state for insideSameAsOutside to newState
|
||||||
|
*
|
||||||
|
* @param newState new edgesUseInsideAppearance value
|
||||||
|
*/
|
||||||
|
public void setInsideSameAsOutside(boolean newState) {
|
||||||
|
this.insideSameAsOutside = newState;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,10 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
@ -11,10 +14,10 @@ import net.sf.openrocket.startup.Application;
|
|||||||
import net.sf.openrocket.util.BoundingBox;
|
import net.sf.openrocket.util.BoundingBox;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
|
||||||
|
public class LaunchLug extends ExternalComponent implements AnglePositionable, BoxBounded, Coaxial, LineInstanceable, InsideColorComponent {
|
||||||
public class LaunchLug extends ExternalComponent implements AnglePositionable, BoxBounded, Coaxial, LineInstanceable {
|
|
||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
@ -26,6 +29,8 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, B
|
|||||||
|
|
||||||
private int instanceCount = 1;
|
private int instanceCount = 1;
|
||||||
private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0];
|
private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0];
|
||||||
|
|
||||||
|
private final InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
|
||||||
|
|
||||||
public LaunchLug() {
|
public LaunchLug() {
|
||||||
super(AxialMethod.MIDDLE);
|
super(AxialMethod.MIDDLE);
|
||||||
@ -279,4 +284,9 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, B
|
|||||||
public void setAngleMethod(AngleMethod newMethod) {
|
public void setAngleMethod(AngleMethod newMethod) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsideColorComponentHandler getInsideColorComponentHandler() {
|
||||||
|
return this.insideColorComponentHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,14 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rocket nose cones of various types. Implemented as a transition with the
|
* Rocket nose cones of various types. Implemented as a transition with the
|
||||||
@ -12,9 +17,10 @@ import net.sf.openrocket.startup.Application;
|
|||||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NoseCone extends Transition {
|
public class NoseCone extends Transition implements InsideColorComponent {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
private final InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
|
||||||
|
|
||||||
/********* Constructors **********/
|
/********* Constructors **********/
|
||||||
public NoseCone() {
|
public NoseCone() {
|
||||||
@ -135,5 +141,10 @@ public class NoseCone extends Transition {
|
|||||||
//// Nose cone
|
//// Nose cone
|
||||||
return trans.get("NoseCone.NoseCone");
|
return trans.get("NoseCone.NoseCone");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsideColorComponentHandler getInsideColorComponentHandler() {
|
||||||
|
return this.insideColorComponentHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,16 +5,20 @@ import static net.sf.openrocket.util.MathUtil.pow2;
|
|||||||
import static net.sf.openrocket.util.MathUtil.pow3;
|
import static net.sf.openrocket.util.MathUtil.pow3;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
|
||||||
public class Transition extends SymmetricComponent {
|
public class Transition extends SymmetricComponent implements InsideColorComponent {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
private static final double CLIP_PRECISION = 0.0001;
|
private static final double CLIP_PRECISION = 0.0001;
|
||||||
|
|
||||||
@ -40,6 +44,8 @@ public class Transition extends SymmetricComponent {
|
|||||||
// Used to cache the clip length
|
// Used to cache the clip length
|
||||||
private double clipLength = -1;
|
private double clipLength = -1;
|
||||||
|
|
||||||
|
private final InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
|
||||||
|
|
||||||
public Transition() {
|
public Transition() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -598,6 +604,11 @@ public class Transition extends SymmetricComponent {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsideColorComponentHandler getInsideColorComponentHandler() {
|
||||||
|
return this.insideColorComponentHandler;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enumeration listing the possible shapes of transitions.
|
* An enumeration listing the possible shapes of transitions.
|
||||||
*
|
*
|
||||||
@ -938,4 +949,5 @@ public class Transition extends SymmetricComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,11 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EventObject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
@ -12,12 +15,9 @@ import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
|||||||
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
||||||
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
import net.sf.openrocket.util.*;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
|
||||||
import net.sf.openrocket.util.MathUtil;
|
|
||||||
import net.sf.openrocket.util.Transformation;
|
|
||||||
|
|
||||||
public class TubeFinSet extends ExternalComponent implements AxialPositionable, BoxBounded, RingInstanceable {
|
public class TubeFinSet extends ExternalComponent implements AxialPositionable, BoxBounded, RingInstanceable, InsideColorComponent {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
private final static double DEFAULT_RADIUS = 0.025;
|
private final static double DEFAULT_RADIUS = 0.025;
|
||||||
@ -27,6 +27,8 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable,
|
|||||||
protected double thickness = 0.002;
|
protected double thickness = 0.002;
|
||||||
private AngleMethod angleMethod = AngleMethod.FIXED;
|
private AngleMethod angleMethod = AngleMethod.FIXED;
|
||||||
protected RadiusMethod radiusMethod = RadiusMethod.RELATIVE;
|
protected RadiusMethod radiusMethod = RadiusMethod.RELATIVE;
|
||||||
|
|
||||||
|
private final InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotation angle of the first fin. Zero corresponds to the positive y-axis.
|
* Rotation angle of the first fin. Zero corresponds to the positive y-axis.
|
||||||
@ -452,5 +454,10 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable,
|
|||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsideColorComponentHandler getInsideColorComponentHandler() {
|
||||||
|
return this.insideColorComponentHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,19 +6,7 @@ import java.awt.event.ActionListener;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.EventObject;
|
import java.util.EventObject;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.*;
|
||||||
import javax.swing.JCheckBox;
|
|
||||||
import javax.swing.JColorChooser;
|
|
||||||
import javax.swing.JComboBox;
|
|
||||||
import javax.swing.JDialog;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JSeparator;
|
|
||||||
import javax.swing.JSlider;
|
|
||||||
import javax.swing.JSpinner;
|
|
||||||
import javax.swing.SwingConstants;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.colorchooser.ColorSelectionModel;
|
import javax.swing.colorchooser.ColorSelectionModel;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
@ -45,6 +33,9 @@ import net.sf.openrocket.gui.util.EditDecalHelper;
|
|||||||
import net.sf.openrocket.gui.util.EditDecalHelper.EditDecalHelperException;
|
import net.sf.openrocket.gui.util.EditDecalHelper.EditDecalHelperException;
|
||||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InsideColorComponentHandler;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.unit.GeneralUnit;
|
import net.sf.openrocket.unit.GeneralUnit;
|
||||||
@ -58,15 +49,18 @@ public class AppearancePanel extends JPanel {
|
|||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
private EditDecalHelper editDecalHelper = Application.getInjector()
|
final private EditDecalHelper editDecalHelper = Application.getInjector()
|
||||||
.getInstance(EditDecalHelper.class);
|
.getInstance(EditDecalHelper.class);
|
||||||
|
|
||||||
private AppearanceBuilder ab;
|
// Outside and inside appearance builder
|
||||||
|
final private AppearanceBuilder ab;
|
||||||
|
private AppearanceBuilder insideAb;
|
||||||
|
|
||||||
// We hang on to the user selected appearance when switching to default
|
// We hang on to the user selected appearance when switching to default
|
||||||
// appearance.
|
// appearance.
|
||||||
// this appearance is restored if the user unchecks the "default" button.
|
// this appearance is restored if the user unchecks the "default" button.
|
||||||
private Appearance previousUserSelectedAppearance = null;
|
private Appearance previousUserSelectedAppearance = null;
|
||||||
|
private Appearance previousUserSelectedInsideAppearance = null;
|
||||||
|
|
||||||
// We cache the default appearance for this component to make switching
|
// We cache the default appearance for this component to make switching
|
||||||
// faster.
|
// faster.
|
||||||
@ -105,7 +99,7 @@ public class AppearancePanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Changes the color of the selected color to <color>
|
Changes the color of the selected component to <color>
|
||||||
@param color: color to change the component to
|
@param color: color to change the component to
|
||||||
*/
|
*/
|
||||||
private void changeComponentColor(Color color) {
|
private void changeComponentColor(Color color) {
|
||||||
@ -182,8 +176,9 @@ public class AppearancePanel extends JPanel {
|
|||||||
final RocketComponent c) {
|
final RocketComponent c) {
|
||||||
super(new MigLayout("fill", "[150][grow][150][grow]"));
|
super(new MigLayout("fill", "[150][grow][150][grow]"));
|
||||||
|
|
||||||
previousUserSelectedAppearance = c.getAppearance();
|
|
||||||
defaultAppearance = DefaultAppearance.getDefaultAppearance(c);
|
defaultAppearance = DefaultAppearance.getDefaultAppearance(c);
|
||||||
|
|
||||||
|
previousUserSelectedAppearance = c.getAppearance();
|
||||||
if (previousUserSelectedAppearance == null) {
|
if (previousUserSelectedAppearance == null) {
|
||||||
previousUserSelectedAppearance = new AppearanceBuilder()
|
previousUserSelectedAppearance = new AppearanceBuilder()
|
||||||
.getAppearance();
|
.getAppearance();
|
||||||
@ -192,6 +187,18 @@ public class AppearancePanel extends JPanel {
|
|||||||
ab = new AppearanceBuilder(previousUserSelectedAppearance);
|
ab = new AppearanceBuilder(previousUserSelectedAppearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c instanceof InsideColorComponent) {
|
||||||
|
previousUserSelectedInsideAppearance = ((InsideColorComponent) c).getInsideColorComponentHandler()
|
||||||
|
.getInsideAppearance();
|
||||||
|
if (previousUserSelectedInsideAppearance == null) {
|
||||||
|
previousUserSelectedInsideAppearance = new AppearanceBuilder()
|
||||||
|
.getAppearance();
|
||||||
|
insideAb = new AppearanceBuilder(defaultAppearance);
|
||||||
|
} else {
|
||||||
|
insideAb = new AppearanceBuilder(previousUserSelectedInsideAppearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
net.sf.openrocket.util.Color figureColor = c.getColor();
|
net.sf.openrocket.util.Color figureColor = c.getColor();
|
||||||
if (figureColor == null) {
|
if (figureColor == null) {
|
||||||
figureColor = Application.getPreferences().getDefaultColor(
|
figureColor = Application.getPreferences().getDefaultColor(
|
||||||
@ -200,19 +207,9 @@ public class AppearancePanel extends JPanel {
|
|||||||
final JButton figureColorButton = new JButton(
|
final JButton figureColorButton = new JButton(
|
||||||
new ColorIcon(figureColor));
|
new ColorIcon(figureColor));
|
||||||
|
|
||||||
final JButton colorButton = new JButton(new ColorIcon(ab.getPaint()));
|
|
||||||
|
|
||||||
final DecalModel decalModel = new DecalModel(this, document, ab);
|
|
||||||
final JComboBox<DecalImage> textureDropDown = new JComboBox<DecalImage>(decalModel);
|
|
||||||
|
|
||||||
ab.addChangeListener(new StateChangeListener() {
|
ab.addChangeListener(new StateChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(EventObject e) {
|
public void stateChanged(EventObject e) { figureColorButton.setIcon(new ColorIcon(c.getColor())); }
|
||||||
figureColorButton.setIcon(new ColorIcon(c.getColor()));
|
|
||||||
colorButton.setIcon(new ColorIcon(ab.getPaint()));
|
|
||||||
c.setAppearance(ab.getAppearance());
|
|
||||||
decalModel.refresh();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
c.addChangeListener(new StateChangeListener() {
|
c.addChangeListener(new StateChangeListener() {
|
||||||
@ -229,9 +226,7 @@ public class AppearancePanel extends JPanel {
|
|||||||
|
|
||||||
figureColorButton
|
figureColorButton
|
||||||
.addActionListener(new ColorActionListener(c, "Color"));
|
.addActionListener(new ColorActionListener(c, "Color"));
|
||||||
colorButton.addActionListener(new ColorActionListener(ab, "Paint"));
|
|
||||||
|
|
||||||
BooleanModel mDefault = new BooleanModel(c.getAppearance() == null);
|
|
||||||
BooleanModel fDefault = new BooleanModel(c.getColor() == null);
|
BooleanModel fDefault = new BooleanModel(c.getColor() == null);
|
||||||
|
|
||||||
{// Style Header Row
|
{// Style Header Row
|
||||||
@ -285,7 +280,6 @@ public class AppearancePanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{// Line Style
|
{// Line Style
|
||||||
|
|
||||||
add(new JLabel(trans.get("RocketCompCfg.lbl.Complinestyle")));
|
add(new JLabel(trans.get("RocketCompCfg.lbl.Complinestyle")));
|
||||||
|
|
||||||
LineStyle[] list = new LineStyle[LineStyle.values().length + 1];
|
LineStyle[] list = new LineStyle[LineStyle.values().length + 1];
|
||||||
@ -304,152 +298,245 @@ public class AppearancePanel extends JPanel {
|
|||||||
|
|
||||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||||
|
|
||||||
{// Texture Header Row
|
// Display a tabbed panel for choosing the outside and inside appearance, if the object is of type InsideColorComponent
|
||||||
add(new StyledLabel(trans.get("AppearanceCfg.lbl.Appearance"),
|
if (c instanceof InsideColorComponent) {
|
||||||
Style.BOLD));
|
InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler();
|
||||||
final JCheckBox materialDefault = new JCheckBox(mDefault);
|
|
||||||
materialDefault.addActionListener(new ActionListener() {
|
JTabbedPane tabbedPane = new JTabbedPane();
|
||||||
|
JPanel outsidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]"));
|
||||||
|
JPanel insidePanel = new JPanel(new MigLayout("fill", "[150][grow][150][grow]"));
|
||||||
|
|
||||||
|
appearanceSection(document, c, false, outsidePanel);
|
||||||
|
appearanceSection(document, c, true, insidePanel);
|
||||||
|
|
||||||
|
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Outside"), null, outsidePanel,
|
||||||
|
"Outside Tool Tip");
|
||||||
|
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Inside"), null, insidePanel,
|
||||||
|
"Inside Tool Tip");
|
||||||
|
add(tabbedPane, "span 4, growx, wrap");
|
||||||
|
|
||||||
|
// Checkbox to set edges the same as inside/outside
|
||||||
|
BooleanModel b = new BooleanModel(handler.isEdgesSameAsInside());
|
||||||
|
JCheckBox edges = new JCheckBox(b);
|
||||||
|
edges.setText(trans.get("AppearanceCfg.lbl.EdgesSameAsInside"));
|
||||||
|
edges.setToolTipText(trans.get("AppearanceCfg.lbl.ttip.EdgesSameAsInside"));
|
||||||
|
add(edges, "wrap");
|
||||||
|
|
||||||
|
edges.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (materialDefault.isSelected()) {
|
handler.setEdgesSameAsInside(edges.isSelected());
|
||||||
previousUserSelectedAppearance = (ab == null) ? null
|
c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||||
: ab.getAppearance();
|
|
||||||
ab.setAppearance(defaultAppearance);
|
|
||||||
c.setAppearance(null);
|
|
||||||
} else {
|
|
||||||
ab.setAppearance(previousUserSelectedAppearance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
materialDefault.setText(trans.get("AppearanceCfg.lbl.Usedefault"));
|
|
||||||
add(materialDefault, "wrap");
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
appearanceSection(document, c, false, this);
|
||||||
|
}
|
||||||
|
|
||||||
{// Texture File
|
/**
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.Texture")));
|
*
|
||||||
JPanel p = new JPanel(new MigLayout("fill, ins 0", "[grow][]"));
|
* @param document
|
||||||
mDefault.addEnableComponent(textureDropDown, false);
|
* @param c
|
||||||
p.add(textureDropDown, "grow");
|
* @param insideBuilder flag to check whether you are on the inside builder (true) or outside builder
|
||||||
add(p, "span 3, growx, wrap");
|
* @param panel
|
||||||
final JButton editBtn = new JButton(
|
*/
|
||||||
trans.get("AppearanceCfg.but.edit"));
|
private void appearanceSection(OpenRocketDocument document, RocketComponent c,
|
||||||
editBtn.setEnabled(ab.getImage() != null);
|
boolean insideBuilder, JPanel panel) {
|
||||||
// Enable the editBtn only when the appearance builder has an Image
|
AppearanceBuilder builder;
|
||||||
// assigned to it.
|
BooleanModel mDefault;
|
||||||
ab.addChangeListener(new StateChangeListener() {
|
if (!insideBuilder) {
|
||||||
@Override
|
builder = ab;
|
||||||
public void stateChanged(EventObject e) {
|
mDefault = new BooleanModel(c.getAppearance() == null);
|
||||||
editBtn.setEnabled(ab.getImage() != null);
|
}
|
||||||
|
else if (c instanceof InsideColorComponent) {
|
||||||
|
builder = insideAb;
|
||||||
|
mDefault = new BooleanModel(
|
||||||
|
((InsideColorComponent)c).getInsideColorComponentHandler().getInsideAppearance() == null);
|
||||||
|
}
|
||||||
|
else return;
|
||||||
|
|
||||||
|
DecalModel decalModel = new DecalModel(panel, document, builder);
|
||||||
|
JComboBox<DecalImage> textureDropDown = new JComboBox<DecalImage>(decalModel);
|
||||||
|
|
||||||
|
JButton colorButton = new JButton(new ColorIcon(builder.getPaint()));
|
||||||
|
|
||||||
|
builder.addChangeListener(new StateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(EventObject e) {
|
||||||
|
colorButton.setIcon(new ColorIcon(builder.getPaint()));
|
||||||
|
if (!insideBuilder)
|
||||||
|
c.setAppearance(builder.getAppearance());
|
||||||
|
else
|
||||||
|
((InsideColorComponent)c).getInsideColorComponentHandler().setInsideAppearance(builder.getAppearance());
|
||||||
|
decalModel.refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
colorButton.addActionListener(new ColorActionListener(builder, "Paint"));
|
||||||
|
|
||||||
|
// Texture Header Row
|
||||||
|
panel.add(new StyledLabel(trans.get("AppearanceCfg.lbl.Appearance"),
|
||||||
|
Style.BOLD));
|
||||||
|
JCheckBox materialDefault = new JCheckBox(mDefault);
|
||||||
|
materialDefault.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (materialDefault.isSelected()) {
|
||||||
|
if (!insideBuilder) {
|
||||||
|
previousUserSelectedAppearance = (builder == null) ? null
|
||||||
|
: builder.getAppearance();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
previousUserSelectedInsideAppearance = (builder == null) ? null
|
||||||
|
: builder.getAppearance();
|
||||||
|
}
|
||||||
|
builder.setAppearance(defaultAppearance);
|
||||||
|
} else {
|
||||||
|
if (!insideBuilder)
|
||||||
|
builder.setAppearance(previousUserSelectedAppearance);
|
||||||
|
else
|
||||||
|
builder.setAppearance(previousUserSelectedInsideAppearance);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
editBtn.addActionListener(new ActionListener() {
|
});
|
||||||
|
materialDefault.setText(trans.get("AppearanceCfg.lbl.Usedefault"));
|
||||||
|
if (insideBuilder)
|
||||||
|
panel.add(materialDefault);
|
||||||
|
else
|
||||||
|
panel.add(materialDefault, "wrap");
|
||||||
|
|
||||||
|
// Custom inside color
|
||||||
|
if (insideBuilder) {
|
||||||
|
InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler();
|
||||||
|
BooleanModel b = new BooleanModel(handler.isInsideSameAsOutside());
|
||||||
|
JCheckBox customInside = new JCheckBox(b);
|
||||||
|
customInside.setText(trans.get("AppearanceCfg.lbl.InsideSameAsOutside"));
|
||||||
|
customInside.setToolTipText(trans.get("AppearanceCfg.lbl.ttip.InsideSameAsOutside"));
|
||||||
|
customInside.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
try {
|
handler.setInsideSameAsOutside(customInside.isSelected());
|
||||||
DecalImage newImage = editDecalHelper.editDecal(
|
c.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||||
SwingUtilities
|
|
||||||
.getWindowAncestor(AppearancePanel.this),
|
|
||||||
document, c, ab.getImage());
|
|
||||||
ab.setImage(newImage);
|
|
||||||
} catch (EditDecalHelperException ex) {
|
|
||||||
JOptionPane.showMessageDialog(AppearancePanel.this,
|
|
||||||
ex.getMessage(), "", JOptionPane.ERROR_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
p.add(editBtn);
|
panel.add(customInside, "wrap");
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Color
|
// Texture File
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.color.Color")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.Texture")));
|
||||||
mDefault.addEnableComponent(colorButton, false);
|
JPanel p = new JPanel(new MigLayout("fill, ins 0", "[grow][]"));
|
||||||
add(colorButton);
|
mDefault.addEnableComponent(textureDropDown, false);
|
||||||
}
|
p.add(textureDropDown, "grow");
|
||||||
|
panel.add(p, "span 3, growx, wrap");
|
||||||
|
JButton editBtn = new JButton(
|
||||||
|
trans.get("AppearanceCfg.but.edit"));
|
||||||
|
editBtn.setEnabled(builder.getImage() != null);
|
||||||
|
// Enable the editBtn only when the appearance builder has an Image
|
||||||
|
// assigned to it.
|
||||||
|
builder.addChangeListener(new StateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(EventObject e) {
|
||||||
|
editBtn.setEnabled(builder.getImage() != null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
{ // Scale
|
editBtn.addActionListener(new ActionListener() {
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.texture.scale")));
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
try {
|
||||||
|
DecalImage newImage = editDecalHelper.editDecal(
|
||||||
|
SwingUtilities
|
||||||
|
.getWindowAncestor(panel),
|
||||||
|
document, c, builder.getImage(), insideBuilder);
|
||||||
|
builder.setImage(newImage);
|
||||||
|
} catch (EditDecalHelperException ex) {
|
||||||
|
JOptionPane.showMessageDialog(panel,
|
||||||
|
ex.getMessage(), "", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
add(new JLabel("x:"), "split 4");
|
});
|
||||||
JSpinner scaleU = new JSpinner(new DoubleModel(ab, "ScaleX",
|
p.add(editBtn);
|
||||||
TEXTURE_UNIT).getSpinnerModel());
|
|
||||||
scaleU.setEditor(new SpinnerEditor(scaleU));
|
|
||||||
mDefault.addEnableComponent(scaleU, false);
|
|
||||||
add(scaleU, "w 40");
|
|
||||||
|
|
||||||
add(new JLabel("y:"));
|
// Color
|
||||||
JSpinner scaleV = new JSpinner(new DoubleModel(ab, "ScaleY",
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.color.Color")));
|
||||||
TEXTURE_UNIT).getSpinnerModel());
|
mDefault.addEnableComponent(colorButton, false);
|
||||||
scaleV.setEditor(new SpinnerEditor(scaleV));
|
panel.add(colorButton);
|
||||||
mDefault.addEnableComponent(scaleV, false);
|
|
||||||
add(scaleV, "wrap, w 40");
|
|
||||||
}
|
|
||||||
|
|
||||||
{// Shine
|
// Scale
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.shine")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.scale")));
|
||||||
DoubleModel shineModel = new DoubleModel(ab, "Shine",
|
|
||||||
UnitGroup.UNITS_RELATIVE);
|
|
||||||
// Set the initial value to the reset state, not the shine value of the default appearance of this component
|
|
||||||
if (mDefault.getValue() && previousUserSelectedAppearance != null)
|
|
||||||
shineModel.setValue(previousUserSelectedAppearance.getShine());
|
|
||||||
JSpinner spin = new JSpinner(shineModel.getSpinnerModel());
|
|
||||||
spin.setEditor(new SpinnerEditor(spin));
|
|
||||||
JSlider slide = new JSlider(shineModel.getSliderModel(0, 1));
|
|
||||||
UnitSelector unit = new UnitSelector(shineModel);
|
|
||||||
|
|
||||||
mDefault.addEnableComponent(slide, false);
|
panel.add(new JLabel("x:"), "split 4");
|
||||||
mDefault.addEnableComponent(spin, false);
|
JSpinner scaleU = new JSpinner(new DoubleModel(builder, "ScaleX",
|
||||||
mDefault.addEnableComponent(unit, false);
|
TEXTURE_UNIT).getSpinnerModel());
|
||||||
|
scaleU.setEditor(new SpinnerEditor(scaleU));
|
||||||
|
mDefault.addEnableComponent(scaleU, false);
|
||||||
|
panel.add(scaleU, "w 40");
|
||||||
|
|
||||||
add(spin, "split 3, w 50");
|
panel.add(new JLabel("y:"));
|
||||||
add(unit);
|
JSpinner scaleV = new JSpinner(new DoubleModel(builder, "ScaleY",
|
||||||
add(slide, "w 50");
|
TEXTURE_UNIT).getSpinnerModel());
|
||||||
}
|
scaleV.setEditor(new SpinnerEditor(scaleV));
|
||||||
|
mDefault.addEnableComponent(scaleV, false);
|
||||||
|
panel.add(scaleV, "wrap, w 40");
|
||||||
|
|
||||||
{ // Offset
|
// Shine
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.texture.offset")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.shine")));
|
||||||
|
DoubleModel shineModel = new DoubleModel(builder, "Shine",
|
||||||
|
UnitGroup.UNITS_RELATIVE);
|
||||||
|
JSpinner spin = new JSpinner(shineModel.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
JSlider slide = new JSlider(shineModel.getSliderModel(0, 1));
|
||||||
|
UnitSelector unit = new UnitSelector(shineModel);
|
||||||
|
|
||||||
add(new JLabel("x:"), "split 4");
|
mDefault.addEnableComponent(slide, false);
|
||||||
JSpinner offsetU = new JSpinner(new DoubleModel(ab, "OffsetU",
|
mDefault.addEnableComponent(spin, false);
|
||||||
TEXTURE_UNIT).getSpinnerModel());
|
mDefault.addEnableComponent(unit, false);
|
||||||
offsetU.setEditor(new SpinnerEditor(offsetU));
|
|
||||||
mDefault.addEnableComponent(offsetU, false);
|
|
||||||
add(offsetU, "w 40");
|
|
||||||
|
|
||||||
add(new JLabel("y:"));
|
panel.add(spin, "split 3, w 50");
|
||||||
JSpinner offsetV = new JSpinner(new DoubleModel(ab, "OffsetV",
|
panel.add(unit);
|
||||||
TEXTURE_UNIT).getSpinnerModel());
|
panel.add(slide, "w 50");
|
||||||
offsetV.setEditor(new SpinnerEditor(offsetV));
|
|
||||||
mDefault.addEnableComponent(offsetV, false);
|
|
||||||
add(offsetV, "wrap, w 40");
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // Repeat
|
// Offset
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.texture.repeat")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.offset")));
|
||||||
EdgeMode[] list = new EdgeMode[EdgeMode.values().length];
|
|
||||||
System.arraycopy(EdgeMode.values(), 0, list, 0,
|
|
||||||
EdgeMode.values().length);
|
|
||||||
JComboBox<EdgeMode> combo = new JComboBox<EdgeMode>(new EnumModel<EdgeMode>(ab,
|
|
||||||
"EdgeMode", list));
|
|
||||||
mDefault.addEnableComponent(combo, false);
|
|
||||||
add(combo);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // Rotation
|
panel.add(new JLabel("x:"), "split 4");
|
||||||
add(new JLabel(trans.get("AppearanceCfg.lbl.texture.rotation")));
|
JSpinner offsetU = new JSpinner(new DoubleModel(builder, "OffsetU",
|
||||||
DoubleModel rotationModel = new DoubleModel(ab, "Rotation",
|
TEXTURE_UNIT).getSpinnerModel());
|
||||||
UnitGroup.UNITS_ANGLE);
|
offsetU.setEditor(new SpinnerEditor(offsetU));
|
||||||
JSpinner rotation = new JSpinner(rotationModel.getSpinnerModel());
|
mDefault.addEnableComponent(offsetU, false);
|
||||||
rotation.setEditor(new SpinnerEditor(rotation));
|
panel.add(offsetU, "w 40");
|
||||||
mDefault.addEnableComponent(rotation, false);
|
|
||||||
add(rotation, "split 3, w 50");
|
|
||||||
add(new UnitSelector(rotationModel));
|
|
||||||
BasicSlider bs = new BasicSlider(rotationModel.getSliderModel(
|
|
||||||
-Math.PI, Math.PI));
|
|
||||||
mDefault.addEnableComponent(bs, false);
|
|
||||||
add(bs, "w 50, wrap");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
panel.add(new JLabel("y:"));
|
||||||
|
JSpinner offsetV = new JSpinner(new DoubleModel(builder, "OffsetV",
|
||||||
|
TEXTURE_UNIT).getSpinnerModel());
|
||||||
|
offsetV.setEditor(new SpinnerEditor(offsetV));
|
||||||
|
mDefault.addEnableComponent(offsetV, false);
|
||||||
|
panel.add(offsetV, "wrap, w 40");
|
||||||
|
|
||||||
|
// Repeat
|
||||||
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.repeat")));
|
||||||
|
EdgeMode[] list = new EdgeMode[EdgeMode.values().length];
|
||||||
|
System.arraycopy(EdgeMode.values(), 0, list, 0,
|
||||||
|
EdgeMode.values().length);
|
||||||
|
JComboBox<EdgeMode> combo = new JComboBox<EdgeMode>(new EnumModel<EdgeMode>(builder,
|
||||||
|
"EdgeMode", list));
|
||||||
|
mDefault.addEnableComponent(combo, false);
|
||||||
|
panel.add(combo);
|
||||||
|
|
||||||
|
// Rotation
|
||||||
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.rotation")));
|
||||||
|
DoubleModel rotationModel = new DoubleModel(builder, "Rotation",
|
||||||
|
UnitGroup.UNITS_ANGLE);
|
||||||
|
JSpinner rotation = new JSpinner(rotationModel.getSpinnerModel());
|
||||||
|
rotation.setEditor(new SpinnerEditor(rotation));
|
||||||
|
mDefault.addEnableComponent(rotation, false);
|
||||||
|
panel.add(rotation, "split 3, w 50");
|
||||||
|
panel.add(new UnitSelector(rotationModel));
|
||||||
|
BasicSlider bs = new BasicSlider(rotationModel.getSliderModel(
|
||||||
|
-Math.PI, Math.PI));
|
||||||
|
mDefault.addEnableComponent(bs, false);
|
||||||
|
panel.add(bs, "w 50, wrap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import net.sf.openrocket.document.OpenRocketDocument;
|
|||||||
import net.sf.openrocket.gui.figure3d.geometry.Geometry;
|
import net.sf.openrocket.gui.figure3d.geometry.Geometry;
|
||||||
import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface;
|
import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface;
|
||||||
import net.sf.openrocket.motor.Motor;
|
import net.sf.openrocket.motor.Motor;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
|
|
||||||
@ -90,10 +91,24 @@ public class RealisticRenderer extends RocketRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderComponent(final GL2 gl, Geometry geom, final float alpha) {
|
public void renderComponent(final GL2 gl, Geometry geom, final float alpha) {
|
||||||
Appearance app = getAppearance( geom.getComponent() );
|
RocketComponent c = geom.getComponent();
|
||||||
render(gl, geom, Surface.INSIDE, app, true, alpha);
|
Appearance app = getAppearance(c);
|
||||||
|
if (c instanceof InsideColorComponent) {
|
||||||
|
Appearance innerApp = getInsideAppearance(c);
|
||||||
|
if (((InsideColorComponent) c).getInsideColorComponentHandler().isInsideSameAsOutside()) innerApp = app;
|
||||||
|
|
||||||
|
render(gl, geom, Surface.INSIDE, innerApp, true, alpha);
|
||||||
|
if (((InsideColorComponent) c).getInsideColorComponentHandler().isEdgesSameAsInside())
|
||||||
|
render(gl, geom, Surface.EDGES, innerApp, false, alpha);
|
||||||
|
else
|
||||||
|
render(gl, geom, Surface.EDGES, app, false, alpha);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
render(gl, geom, Surface.INSIDE, app, true, alpha);
|
||||||
|
render(gl, geom, Surface.EDGES, app, false, alpha);
|
||||||
|
}
|
||||||
render(gl, geom, Surface.OUTSIDE, app, true, alpha);
|
render(gl, geom, Surface.OUTSIDE, app, true, alpha);
|
||||||
render(gl, geom, Surface.EDGES, app, false, alpha);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float[] convertColor(Appearance a, float alpha) {
|
protected float[] convertColor(Appearance a, float alpha) {
|
||||||
@ -190,6 +205,19 @@ public class RealisticRenderer extends RocketRenderer {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Appearance getInsideAppearance(RocketComponent c) {
|
||||||
|
if (c instanceof InsideColorComponent) {
|
||||||
|
Appearance ret = ((InsideColorComponent)c).getInsideColorComponentHandler().getInsideAppearance();
|
||||||
|
if (ret == null) {
|
||||||
|
ret = DefaultAppearance.getDefaultAppearance(c);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return DefaultAppearance.getDefaultAppearance(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int toEdgeMode(Decal.EdgeMode m) {
|
private int toEdgeMode(Decal.EdgeMode m) {
|
||||||
switch (m) {
|
switch (m) {
|
||||||
|
|||||||
@ -16,6 +16,8 @@ import net.sf.openrocket.gui.watcher.FileWatcher;
|
|||||||
import net.sf.openrocket.gui.watcher.WatchEvent;
|
import net.sf.openrocket.gui.watcher.WatchEvent;
|
||||||
import net.sf.openrocket.gui.watcher.WatchService;
|
import net.sf.openrocket.gui.watcher.WatchService;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InsideColorComponentHandler;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@ -67,10 +69,12 @@ public class EditDecalHelper {
|
|||||||
* @param doc
|
* @param doc
|
||||||
* @param component
|
* @param component
|
||||||
* @param decal
|
* @param decal
|
||||||
|
* @param insideApp flag to check whether it is the inside appearance that is edited
|
||||||
* @return
|
* @return
|
||||||
* @throws EditDecalHelperException
|
* @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();
|
boolean sysPrefSet = prefs.isDecalEditorPreferenceSet();
|
||||||
int usageCount = doc.countDecalUsage(decal);
|
int usageCount = doc.countDecalUsage(decal);
|
||||||
@ -111,7 +115,10 @@ public class EditDecalHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dialog.isEditOne()) {
|
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);
|
launchEditor(useSystemEditor, commandLine, decal);
|
||||||
@ -131,6 +138,21 @@ public class EditDecalHelper {
|
|||||||
|
|
||||||
return newImage;
|
return newImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DecalImage makeDecalUniqueInside(OpenRocketDocument doc, RocketComponent component, DecalImage decal) {
|
||||||
|
|
||||||
|
DecalImage newImage = doc.makeUniqueDecal(decal);
|
||||||
|
|
||||||
|
if (component instanceof InsideColorComponent) {
|
||||||
|
InsideColorComponentHandler handler = ((InsideColorComponent)component).getInsideColorComponentHandler();
|
||||||
|
AppearanceBuilder appearanceBuilder = new AppearanceBuilder(handler.getInsideAppearance());
|
||||||
|
appearanceBuilder.setImage(newImage);
|
||||||
|
|
||||||
|
handler.setInsideAppearance(appearanceBuilder.getAppearance());
|
||||||
|
}
|
||||||
|
|
||||||
|
return newImage;
|
||||||
|
}
|
||||||
|
|
||||||
private void launchEditor(boolean useSystemEditor, String commandTemplate, final DecalImage decal) throws EditDecalHelperException {
|
private void launchEditor(boolean useSystemEditor, String commandTemplate, final DecalImage decal) throws EditDecalHelperException {
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user