Sizable commit with lots of changes to support decals in openrocket files. Added support for zip container support. Changed Decal to hold a String instead of URL. Refactored GeneralRocketLoader out of the RocketLoader hierarchy so the GeneralRocketLoader knows about files and RocketLoader only knows about streams. Changed the OpenRocket file format to 1.6 and added <appearance> and it's children for ambient light and decals. Implemented a DecalRegistry which is a member of the OpenRocketDocument. This class is used to get InputStreams for decals by their names.
This commit is contained in:
parent
49c9329fde
commit
05d1b91d90
@ -0,0 +1,59 @@
|
|||||||
|
package net.sf.openrocket.startup;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import net.sf.openrocket.database.ComponentPresetDatabase;
|
||||||
|
import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
|
||||||
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
|
import net.sf.openrocket.document.StorageOptions;
|
||||||
|
import net.sf.openrocket.file.DatabaseMotorFinder;
|
||||||
|
import net.sf.openrocket.file.GeneralRocketLoader;
|
||||||
|
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
|
||||||
|
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||||
|
import net.sf.openrocket.l10n.ResourceBundleTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An application for quickly testing 3d figure witout all the OpenRocket user
|
||||||
|
* interface
|
||||||
|
*
|
||||||
|
* @author bkuker
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TextureOutputTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
|
||||||
|
Application.setMotorSetDatabase(new ThrustCurveMotorSetDatabase(false) {
|
||||||
|
{
|
||||||
|
startLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadMotors() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Application.setPreferences(new SwingPreferences());
|
||||||
|
|
||||||
|
// Must be done after localization is initialized
|
||||||
|
ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase(true) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void load() {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
Application.setComponentPresetDao(componentPresetDao);
|
||||||
|
|
||||||
|
OpenRocketDocument doc = new GeneralRocketLoader().load(
|
||||||
|
new File("3d-Test-Junk/net/sf/openrocket/startup/al1 Apocalypse_54mmtestFr.rkt.xml"),
|
||||||
|
new DatabaseMotorFinder());
|
||||||
|
|
||||||
|
StorageOptions saver = new StorageOptions();
|
||||||
|
saver.setIncludeDecals(true);
|
||||||
|
|
||||||
|
new OpenRocketSaver().save(new File("3d-Test-Junk/net/sf/openrocket/startup/Apocalypse-ork.zip"), doc, saver);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package net.sf.openrocket.startup;
|
package net.sf.openrocket.startup;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
|
import java.io.File;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
@ -10,7 +11,7 @@ import net.sf.openrocket.database.ComponentPresetDatabase;
|
|||||||
import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
|
import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.file.DatabaseMotorFinder;
|
import net.sf.openrocket.file.DatabaseMotorFinder;
|
||||||
import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
|
import net.sf.openrocket.file.GeneralRocketLoader;
|
||||||
import net.sf.openrocket.gui.main.componenttree.ComponentTree;
|
import net.sf.openrocket.gui.main.componenttree.ComponentTree;
|
||||||
import net.sf.openrocket.gui.scalefigure.RocketPanel;
|
import net.sf.openrocket.gui.scalefigure.RocketPanel;
|
||||||
import net.sf.openrocket.gui.util.GUIUtil;
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
@ -47,22 +48,14 @@ public class TextureTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void load() {
|
protected void load() {
|
||||||
ConcurrentComponentPresetDatabaseLoader presetLoader = new ConcurrentComponentPresetDatabaseLoader( this );
|
|
||||||
presetLoader.load();
|
|
||||||
try {
|
|
||||||
presetLoader.await();
|
|
||||||
} catch ( InterruptedException iex) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
componentPresetDao.load("datafiles", ".*csv");
|
|
||||||
componentPresetDao.startLoading();
|
|
||||||
Application.setComponentPresetDao(componentPresetDao);
|
Application.setComponentPresetDao(componentPresetDao);
|
||||||
|
|
||||||
OpenRocketDocument doc = new RocksimLoader().load(
|
OpenRocketDocument doc = new GeneralRocketLoader().load(
|
||||||
TextureTest.class.getResourceAsStream("al1 Apocalypse_54mmtestFr.rkt.xml"), new DatabaseMotorFinder());
|
new File("3d-Test-Junk/net/sf/openrocket/startup/al1 Apocalypse_54mmtestFr.rkt.xml"),
|
||||||
|
new DatabaseMotorFinder());
|
||||||
|
|
||||||
GUIUtil.setBestLAF();
|
GUIUtil.setBestLAF();
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@
|
|||||||
<PartDesc>Plastic nose cone</PartDesc>
|
<PartDesc>Plastic nose cone</PartDesc>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>0.</RadialAngle>
|
<RadialAngle>0.</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/Apocalypse_CONE_pointsFrfl.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
<Texture>file=(Apocalypse_CONE_pointsFrfl.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -292,7 +292,7 @@
|
|||||||
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>0.</RadialAngle>
|
<RadialAngle>0.</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/Apocalypse_logo_HAUT_fr2.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(2,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(0)
|
<Texture>file=(Apocalypse_logo_HAUT_fr2.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(2,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(0)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -460,7 +460,7 @@
|
|||||||
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>0.</RadialAngle>
|
<RadialAngle>0.</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/Apocalypse_logo_medium2.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(2,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(0))
|
<Texture>file=(Apocalypse_logo_medium2.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(2,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(0))
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -571,7 +571,7 @@
|
|||||||
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>0.</RadialAngle>
|
<RadialAngle>0.</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/Apocalypse_logo_bas_coup2.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(2,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(0)
|
<Texture>file=(Apocalypse_logo_bas_coup2.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(2,1,1)|repeat=(1)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(0)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -851,7 +851,7 @@
|
|||||||
<DensityType>0</DensityType>
|
<DensityType>0</DensityType>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>0.</RadialAngle>
|
<RadialAngle>0.</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
<Texture>file=(fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -1095,7 +1095,7 @@
|
|||||||
<DensityType>0</DensityType>
|
<DensityType>0</DensityType>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>1.5708</RadialAngle>
|
<RadialAngle>1.5708</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
<Texture>file=(fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -1339,7 +1339,7 @@
|
|||||||
<DensityType>0</DensityType>
|
<DensityType>0</DensityType>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>3.14159</RadialAngle>
|
<RadialAngle>3.14159</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
<Texture>file=(fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
@ -1583,7 +1583,7 @@
|
|||||||
<DensityType>0</DensityType>
|
<DensityType>0</DensityType>
|
||||||
<RadialLoc>0.</RadialLoc>
|
<RadialLoc>0.</RadialLoc>
|
||||||
<RadialAngle>-1.5708</RadialAngle>
|
<RadialAngle>-1.5708</RadialAngle>
|
||||||
<Texture>file=(3d-Test-Junk/net/sf/openrocket/startup/fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
<Texture>file=(fin rad-test5.jpg)|position=(0,0,0)|origin=(0.5,0.5,0.5)|scale=(1,1,1)|repeat=(0)|interpolate=(0)|flipr(0)|flips(0)|flipt=(0)|preventseam=(1)
|
||||||
</Texture>
|
</Texture>
|
||||||
<Opacity>1.</Opacity>
|
<Opacity>1.</Opacity>
|
||||||
<Specular>0.</Specular>
|
<Specular>0.</Specular>
|
||||||
|
@ -1041,6 +1041,8 @@ StorageOptChooser.lbl.seconds = seconds
|
|||||||
StorageOptChooser.rdbut.Onlyprimfig = Only primary figures
|
StorageOptChooser.rdbut.Onlyprimfig = Only primary figures
|
||||||
StorageOptChooser.lbl.longC1 = <html>Store only the values shown in the summary table.<br>
|
StorageOptChooser.lbl.longC1 = <html>Store only the values shown in the summary table.<br>
|
||||||
StorageOptChooser.lbl.longC2 = This results in the smallest files.
|
StorageOptChooser.lbl.longC2 = This results in the smallest files.
|
||||||
|
StorageOptChooser.checkbox.IncludeDecals = Include decals
|
||||||
|
StorageOptChooser.lbl.IncludeDecals = "Including decals will produce a compressed zip file"
|
||||||
StorageOptChooser.checkbox.Compfile = Compress file
|
StorageOptChooser.checkbox.Compfile = Compress file
|
||||||
StorageOptChooser.lbl.UsingComp = Using compression reduces the file size significantly.
|
StorageOptChooser.lbl.UsingComp = Using compression reduces the file size significantly.
|
||||||
StorageOptChooser.lbl.longD1 = An estimate on how large the resulting file would be with the present options.
|
StorageOptChooser.lbl.longD1 = An estimate on how large the resulting file would be with the present options.
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.sf.openrocket.appearance;
|
package net.sf.openrocket.appearance;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
||||||
import net.sf.openrocket.util.AbstractChangeSource;
|
import net.sf.openrocket.util.AbstractChangeSource;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
@ -26,7 +24,7 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
private double centerU, centerV;
|
private double centerU, centerV;
|
||||||
private double scaleU, scaleV;
|
private double scaleU, scaleV;
|
||||||
private double rotation;
|
private double rotation;
|
||||||
private URL image;
|
private String image;
|
||||||
private Decal.EdgeMode edgeMode;
|
private Decal.EdgeMode edgeMode;
|
||||||
|
|
||||||
public AppearanceBuilder() {
|
public AppearanceBuilder() {
|
||||||
@ -47,7 +45,7 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
setScale(d.getScale().x, d.getScale().y);
|
setScale(d.getScale().x, d.getScale().y);
|
||||||
setRotation(d.getRotation());
|
setRotation(d.getRotation());
|
||||||
setEdgeMode(d.getEdgeMode());
|
setEdgeMode(d.getEdgeMode());
|
||||||
setImage(d.getImageURL());
|
setImage(d.getImage());
|
||||||
}
|
}
|
||||||
// TODO Critical the rest of this!
|
// TODO Critical the rest of this!
|
||||||
}
|
}
|
||||||
@ -199,11 +197,11 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
fireChangeEvent();
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public URL getImage() {
|
public String getImage() {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImage(URL image) {
|
public void setImage(String image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
fireChangeEvent();
|
fireChangeEvent();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.sf.openrocket.appearance;
|
package net.sf.openrocket.appearance;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
@ -26,11 +24,11 @@ public class Decal {
|
|||||||
|
|
||||||
private final Coordinate offset, center, scale;
|
private final Coordinate offset, center, scale;
|
||||||
private final double rotation;
|
private final double rotation;
|
||||||
private final URL image;
|
private final String image;
|
||||||
private final EdgeMode mode;
|
private final EdgeMode mode;
|
||||||
|
|
||||||
Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation,
|
Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation,
|
||||||
final URL image, final EdgeMode mode) {
|
final String image, final EdgeMode mode) {
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.center = center;
|
this.center = center;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
@ -59,7 +57,7 @@ public class Decal {
|
|||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public URL getImageURL() {
|
public String getImage() {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
core/src/net/sf/openrocket/document/DecalRegistry.java
Normal file
54
core/src/net/sf/openrocket/document/DecalRegistry.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package net.sf.openrocket.document;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
public class DecalRegistry {
|
||||||
|
|
||||||
|
private File baseFile;
|
||||||
|
private boolean isZipFile = false;
|
||||||
|
|
||||||
|
/* FIXME - Caching ?
|
||||||
|
private Map<String,byte[]> cache = new HashMap<String,byte[]>();
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setBaseFile(File baseFile) {
|
||||||
|
this.baseFile = baseFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsZipFile( boolean isZipFile ) {
|
||||||
|
this.isZipFile = isZipFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getDecal( String name ) throws FileNotFoundException, IOException {
|
||||||
|
/* FIXME - Caching?
|
||||||
|
byte[] bytes = cache.get(name);
|
||||||
|
if ( bytes != null ) {
|
||||||
|
return new ByteArrayInputStream(bytes);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if ( isZipFile ) {
|
||||||
|
ZipInputStream zis = new ZipInputStream(new FileInputStream(baseFile));
|
||||||
|
ZipEntry entry = zis.getNextEntry();
|
||||||
|
while ( entry != null ) {
|
||||||
|
if ( entry.getName().equals(name) ) {
|
||||||
|
return zis;
|
||||||
|
}
|
||||||
|
entry = zis.getNextEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( baseFile != null ) {
|
||||||
|
File decal = new File(baseFile.getParentFile(), name);
|
||||||
|
// FIXME - update cache
|
||||||
|
return new FileInputStream(decal);
|
||||||
|
}
|
||||||
|
throw new FileNotFoundException( "Unable to locate decal for name " + name );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -59,8 +59,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
|
|
||||||
private final ArrayList<Simulation> simulations = new ArrayList<Simulation>();
|
private final ArrayList<Simulation> simulations = new ArrayList<Simulation>();
|
||||||
private ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
|
private ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The undo/redo variables and mechanism are documented in doc/undo-redo-flow.*
|
* The undo/redo variables and mechanism are documented in doc/undo-redo-flow.*
|
||||||
*/
|
*/
|
||||||
@ -85,6 +83,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
private String nextDescription = null;
|
private String nextDescription = null;
|
||||||
private String storedDescription = null;
|
private String storedDescription = null;
|
||||||
|
|
||||||
|
private DecalRegistry decalRegistry = new DecalRegistry();
|
||||||
|
|
||||||
private ArrayList<UndoRedoListener> undoRedoListeners = new ArrayList<UndoRedoListener>(2);
|
private ArrayList<UndoRedoListener> undoRedoListeners = new ArrayList<UndoRedoListener>(2);
|
||||||
|
|
||||||
@ -176,6 +175,15 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DecalRegistry getDecalRegistry() {
|
||||||
|
return decalRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setDecalRegistry(DecalRegistry decalRegistry) {
|
||||||
|
this.decalRegistry = decalRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
public File getFile() {
|
public File getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
@ -15,32 +15,6 @@ public abstract class AbstractRocketLoader implements RocketLoader {
|
|||||||
protected final WarningSet warnings = new WarningSet();
|
protected final WarningSet warnings = new WarningSet();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a rocket from the specified File object.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final OpenRocketDocument load(File source, MotorFinder motorFinder) throws RocketLoadException {
|
|
||||||
warnings.clear();
|
|
||||||
InputStream stream = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
stream = new BufferedInputStream(new FileInputStream(source));
|
|
||||||
return load(stream, motorFinder);
|
|
||||||
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new RocketLoadException("File not found: " + source);
|
|
||||||
} finally {
|
|
||||||
if (stream != null) {
|
|
||||||
try {
|
|
||||||
stream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a rocket from the specified InputStream.
|
* Loads a rocket from the specified InputStream.
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.sf.openrocket.file;
|
package net.sf.openrocket.file;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
@ -9,6 +11,7 @@ import java.util.zip.GZIPInputStream;
|
|||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
|
import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
|
||||||
import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
|
import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
|
||||||
@ -23,8 +26,10 @@ import net.sf.openrocket.util.TextUtil;
|
|||||||
*
|
*
|
||||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
public class GeneralRocketLoader extends AbstractRocketLoader {
|
public class GeneralRocketLoader {
|
||||||
|
|
||||||
|
protected final WarningSet warnings = new WarningSet();
|
||||||
|
|
||||||
private static final int READ_BYTES = 300;
|
private static final int READ_BYTES = 300;
|
||||||
|
|
||||||
private static final byte[] GZIP_SIGNATURE = { 31, -117 }; // 0x1f, 0x8b
|
private static final byte[] GZIP_SIGNATURE = { 31, -117 }; // 0x1f, 0x8b
|
||||||
@ -36,7 +41,46 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
|||||||
|
|
||||||
private final RocksimLoader rocksimLoader = new RocksimLoader();
|
private final RocksimLoader rocksimLoader = new RocksimLoader();
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Loads a rocket from the specified File object.
|
||||||
|
*/
|
||||||
|
public final OpenRocketDocument load(File source, MotorFinder motorFinder) throws RocketLoadException {
|
||||||
|
warnings.clear();
|
||||||
|
InputStream stream = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
stream = new BufferedInputStream(new FileInputStream(source));
|
||||||
|
OpenRocketDocument doc = load(stream, source, motorFinder);
|
||||||
|
return doc;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RocketLoadException("Exception loading file: " + source,e);
|
||||||
|
} finally {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final OpenRocketDocument load(InputStream source, File file, MotorFinder motorFinder) throws RocketLoadException {
|
||||||
|
try {
|
||||||
|
OpenRocketDocument doc = loadFromStream(source, motorFinder );
|
||||||
|
doc.getDecalRegistry().setBaseFile(file);
|
||||||
|
return doc;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RocketLoadException("Exception loading stream", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final WarningSet getWarnings() {
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
|
||||||
protected OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws IOException,
|
protected OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws IOException,
|
||||||
RocketLoadException {
|
RocketLoadException {
|
||||||
|
|
||||||
@ -56,12 +100,14 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
|||||||
throw new RocketLoadException("Unsupported or corrupt file.");
|
throw new RocketLoadException("Unsupported or corrupt file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Detect the appropriate loader
|
// Detect the appropriate loader
|
||||||
|
|
||||||
// Check for GZIP
|
// Check for GZIP
|
||||||
if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
|
if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
|
||||||
OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source), motorFinder);
|
OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source), motorFinder);
|
||||||
doc.getDefaultStorageOptions().setCompressionEnabled(true);
|
doc.getDefaultStorageOptions().setCompressionEnabled(true);
|
||||||
|
doc.getDecalRegistry().setIsZipFile(false);
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +123,7 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
|||||||
if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
|
if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
|
||||||
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
||||||
doc.getDefaultStorageOptions().setCompressionEnabled(true);
|
doc.getDefaultStorageOptions().setCompressionEnabled(true);
|
||||||
|
doc.getDecalRegistry().setIsZipFile(true);
|
||||||
return doc;
|
return doc;
|
||||||
} else if ( entry.getName().matches(".*\\.[rR][kK][tT]$")) {
|
} else if ( entry.getName().matches(".*\\.[rR][kK][tT]$")) {
|
||||||
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
||||||
@ -91,7 +138,9 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
|||||||
if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
|
if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
|
||||||
match++;
|
match++;
|
||||||
if (match == OPENROCKET_SIGNATURE.length) {
|
if (match == OPENROCKET_SIGNATURE.length) {
|
||||||
return loadUsing(source, openRocketLoader, motorFinder);
|
OpenRocketDocument doc = loadUsing(openRocketLoader, source, motorFinder);
|
||||||
|
doc.getDecalRegistry().setIsZipFile(false);
|
||||||
|
return doc;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match = 0;
|
match = 0;
|
||||||
@ -100,12 +149,14 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
|||||||
|
|
||||||
byte[] typeIdentifier = ArrayUtils.copyOf(buffer, ROCKSIM_SIGNATURE.length);
|
byte[] typeIdentifier = ArrayUtils.copyOf(buffer, ROCKSIM_SIGNATURE.length);
|
||||||
if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
|
if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
|
||||||
return loadUsing(source, rocksimLoader, motorFinder);
|
OpenRocketDocument doc = loadUsing(rocksimLoader, source, motorFinder);
|
||||||
|
doc.getDecalRegistry().setIsZipFile(false);
|
||||||
|
return doc;
|
||||||
}
|
}
|
||||||
throw new RocketLoadException("Unsupported or corrupt file.");
|
throw new RocketLoadException("Unsupported or corrupt file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private OpenRocketDocument loadUsing(InputStream source, RocketLoader loader, MotorFinder motorFinder)
|
private OpenRocketDocument loadUsing(RocketLoader loader, InputStream source, MotorFinder motorFinder)
|
||||||
throws RocketLoadException {
|
throws RocketLoadException {
|
||||||
warnings.clear();
|
warnings.clear();
|
||||||
OpenRocketDocument doc = loader.load(source, motorFinder);
|
OpenRocketDocument doc = loader.load(source, motorFinder);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.sf.openrocket.file;
|
package net.sf.openrocket.file;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||||
@ -8,8 +7,6 @@ import net.sf.openrocket.document.OpenRocketDocument;
|
|||||||
|
|
||||||
public interface RocketLoader {
|
public interface RocketLoader {
|
||||||
|
|
||||||
public OpenRocketDocument load(File source, MotorFinder motorFinder) throws RocketLoadException;
|
|
||||||
|
|
||||||
public OpenRocketDocument load(InputStream source, MotorFinder motorFinder) throws RocketLoadException;
|
public OpenRocketDocument load(InputStream source, MotorFinder motorFinder) throws RocketLoadException;
|
||||||
|
|
||||||
public WarningSet getWarnings();
|
public WarningSet getWarnings();
|
||||||
|
@ -36,7 +36,7 @@ public abstract class RocketSaver {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
OutputStream s = new BufferedOutputStream(new FileOutputStream(dest));
|
OutputStream s = new BufferedOutputStream(new FileOutputStream(dest));
|
||||||
try {
|
try {
|
||||||
save(s, document, options);
|
save(dest.getName(), s, document, options);
|
||||||
} finally {
|
} finally {
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
@ -50,8 +50,8 @@ public abstract class RocketSaver {
|
|||||||
* @param doc the document to save.
|
* @param doc the document to save.
|
||||||
* @throws IOException in case of an I/O error.
|
* @throws IOException in case of an I/O error.
|
||||||
*/
|
*/
|
||||||
public final void save(OutputStream dest, OpenRocketDocument doc) throws IOException {
|
public final void save(String fileName, OutputStream dest, OpenRocketDocument doc) throws IOException {
|
||||||
save(dest, doc, doc.getDefaultStorageOptions());
|
save(fileName, dest, doc, doc.getDefaultStorageOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ public abstract class RocketSaver {
|
|||||||
* @param options the storage options.
|
* @param options the storage options.
|
||||||
* @throws IOException in case of an I/O error.
|
* @throws IOException in case of an I/O error.
|
||||||
*/
|
*/
|
||||||
public abstract void save(OutputStream dest, OpenRocketDocument doc,
|
public abstract void save(String fileName, OutputStream dest, OpenRocketDocument doc,
|
||||||
StorageOptions options) throws IOException;
|
StorageOptions options) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +1,26 @@
|
|||||||
package net.sf.openrocket.file.openrocket;
|
package net.sf.openrocket.file.openrocket;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import net.sf.openrocket.aerodynamics.Warning;
|
import net.sf.openrocket.aerodynamics.Warning;
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.AppearanceBuilder;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.document.Simulation;
|
import net.sf.openrocket.document.Simulation;
|
||||||
import net.sf.openrocket.document.StorageOptions;
|
import net.sf.openrocket.document.StorageOptions;
|
||||||
@ -39,22 +48,22 @@ import net.sf.openrocket.util.TextUtil;
|
|||||||
|
|
||||||
public class OpenRocketSaver extends RocketSaver {
|
public class OpenRocketSaver extends RocketSaver {
|
||||||
private static final LogHelper log = Application.getLogger();
|
private static final LogHelper log = Application.getLogger();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divisor used in converting an integer version to the point-represented version.
|
* Divisor used in converting an integer version to the point-represented version.
|
||||||
* The integer version divided by this value is the major version and the remainder is
|
* The integer version divided by this value is the major version and the remainder is
|
||||||
* the minor version. For example 101 corresponds to file version "1.1".
|
* the minor version. For example 101 corresponds to file version "1.1".
|
||||||
*/
|
*/
|
||||||
public static final int FILE_VERSION_DIVISOR = 100;
|
public static final int FILE_VERSION_DIVISOR = 100;
|
||||||
|
|
||||||
|
|
||||||
private static final String OPENROCKET_CHARSET = "UTF-8";
|
private static final String OPENROCKET_CHARSET = "UTF-8";
|
||||||
|
|
||||||
private static final String METHOD_PACKAGE = "net.sf.openrocket.file.openrocket.savers";
|
private static final String METHOD_PACKAGE = "net.sf.openrocket.file.openrocket.savers";
|
||||||
private static final String METHOD_SUFFIX = "Saver";
|
private static final String METHOD_SUFFIX = "Saver";
|
||||||
|
|
||||||
|
|
||||||
// Estimated storage used by different portions
|
// Estimated storage used by different portions
|
||||||
// These have been hand-estimated from saved files
|
// These have been hand-estimated from saved files
|
||||||
private static final int BYTES_PER_COMPONENT_UNCOMPRESSED = 590;
|
private static final int BYTES_PER_COMPONENT_UNCOMPRESSED = 590;
|
||||||
@ -63,44 +72,163 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
private static final int BYTES_PER_SIMULATION_COMPRESSED = 100;
|
private static final int BYTES_PER_SIMULATION_COMPRESSED = 100;
|
||||||
private static final int BYTES_PER_DATAPOINT_UNCOMPRESSED = 350;
|
private static final int BYTES_PER_DATAPOINT_UNCOMPRESSED = 350;
|
||||||
private static final int BYTES_PER_DATAPOINT_COMPRESSED = 100;
|
private static final int BYTES_PER_DATAPOINT_COMPRESSED = 100;
|
||||||
|
|
||||||
|
|
||||||
private int indent;
|
private int indent;
|
||||||
private Writer dest;
|
private Writer dest;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream output, OpenRocketDocument document, StorageOptions options)
|
public void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
|
if (!options.isIncludeDecals()) {
|
||||||
|
saveInternal(output,document,options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tweak the options - no need to double compress:
|
||||||
|
options.setCompressionEnabled(false);
|
||||||
|
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(output);
|
||||||
|
zos.setLevel(9);
|
||||||
|
|
||||||
|
/* if we want a directory ...
|
||||||
|
String path = fileName;
|
||||||
|
int dotlocation = fileName.lastIndexOf('.');
|
||||||
|
if ( dotlocation > 1 ) {
|
||||||
|
path = fileName.substring(dotlocation);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// grab the set of decal images.
|
||||||
|
Map<String,InputStream> decals = new HashMap<String,InputStream>();
|
||||||
|
Map<String,String> decalNameNormalization = new HashMap<String,String>();
|
||||||
|
try {
|
||||||
|
for( RocketComponent c : document.getRocket() ) {
|
||||||
|
|
||||||
|
if ( c.getAppearance() == null ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Appearance ap = c.getAppearance();
|
||||||
|
|
||||||
|
if ( ap.getTexture() == null ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Decal decal = ap.getTexture();
|
||||||
|
|
||||||
|
String decalName = decal.getImage();
|
||||||
|
|
||||||
|
if ( decals.containsKey(decalName) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = document.getDecalRegistry().getDecal(decalName);
|
||||||
|
|
||||||
|
decals.put(decalName, is);
|
||||||
|
|
||||||
|
// Normalize the name:
|
||||||
|
File fname = new File(decalName);
|
||||||
|
String newName = "decals/" + fname.getName();
|
||||||
|
|
||||||
|
decalNameNormalization.put(decalName, newName);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
for ( InputStream is: decals.values() ) {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
catch ( Throwable t ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we have to loop through all the components and update their names.
|
||||||
|
|
||||||
|
for( RocketComponent c : document.getRocket() ) {
|
||||||
|
|
||||||
|
if ( c.getAppearance() == null ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Appearance ap = c.getAppearance();
|
||||||
|
|
||||||
|
if ( ap.getTexture() == null ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppearanceBuilder builder = new AppearanceBuilder(ap);
|
||||||
|
|
||||||
|
builder.setImage( decalNameNormalization.get(ap.getTexture().getImage()));
|
||||||
|
|
||||||
|
c.setAppearance(builder.getAppearance());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixme - should probably be the same name? Should we put everything in a directory?
|
||||||
|
ZipEntry mainFile = new ZipEntry("rocket.ork");
|
||||||
|
zos.putNextEntry(mainFile);
|
||||||
|
saveInternal(zos,document,options);
|
||||||
|
zos.closeEntry();
|
||||||
|
|
||||||
|
// Now we write out all the decal images files.
|
||||||
|
|
||||||
|
for( Map.Entry<String, InputStream> image : decals.entrySet() ) {
|
||||||
|
|
||||||
|
String newName = decalNameNormalization.get(image.getKey());
|
||||||
|
ZipEntry decal = new ZipEntry(newName);
|
||||||
|
zos.putNextEntry(decal);
|
||||||
|
|
||||||
|
InputStream is = image.getValue();
|
||||||
|
int bytesRead = 0;
|
||||||
|
byte[] buffer = new byte[2048];
|
||||||
|
while( (bytesRead = is.read(buffer)) > 0 ) {
|
||||||
|
zos.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
zos.flush();
|
||||||
|
zos.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveInternal(OutputStream output, OpenRocketDocument document, StorageOptions options)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
log.info("Saving .ork file");
|
log.info("Saving .ork file");
|
||||||
|
|
||||||
if (options.isCompressionEnabled()) {
|
if (options.isCompressionEnabled()) {
|
||||||
log.debug("Enabling compression");
|
log.debug("Enabling compression");
|
||||||
output = new GZIPOutputStream(output);
|
output = new GZIPOutputStream(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = new BufferedWriter(new OutputStreamWriter(output, OPENROCKET_CHARSET));
|
dest = new BufferedWriter(new OutputStreamWriter(output, OPENROCKET_CHARSET));
|
||||||
|
|
||||||
// Select file version number
|
// Select file version number
|
||||||
final int fileVersion = calculateNecessaryFileVersion(document, options);
|
final int fileVersion = calculateNecessaryFileVersion(document, options);
|
||||||
final String fileVersionString =
|
final String fileVersionString =
|
||||||
(fileVersion / FILE_VERSION_DIVISOR) + "." + (fileVersion % FILE_VERSION_DIVISOR);
|
(fileVersion / FILE_VERSION_DIVISOR) + "." + (fileVersion % FILE_VERSION_DIVISOR);
|
||||||
log.debug("Storing file version " + fileVersionString);
|
log.debug("Storing file version " + fileVersionString);
|
||||||
|
|
||||||
|
|
||||||
this.indent = 0;
|
this.indent = 0;
|
||||||
|
|
||||||
|
|
||||||
writeln("<?xml version='1.0' encoding='utf-8'?>");
|
writeln("<?xml version='1.0' encoding='utf-8'?>");
|
||||||
writeln("<openrocket version=\"" + fileVersionString + "\" creator=\"OpenRocket "
|
writeln("<openrocket version=\"" + fileVersionString + "\" creator=\"OpenRocket "
|
||||||
+ BuildProperties.getVersion() + "\">");
|
+ BuildProperties.getVersion() + "\">");
|
||||||
indent++;
|
indent++;
|
||||||
|
|
||||||
// Recursively save the rocket structure
|
// Recursively save the rocket structure
|
||||||
saveComponent(document.getRocket());
|
saveComponent(document.getRocket());
|
||||||
|
|
||||||
writeln("");
|
writeln("");
|
||||||
|
|
||||||
// Save custom expressions;
|
// Save custom expressions;
|
||||||
saveCustomDatatypes(document);
|
saveCustomDatatypes(document);
|
||||||
|
|
||||||
@ -168,6 +296,8 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
|
|
||||||
long size = 0;
|
long size = 0;
|
||||||
|
|
||||||
|
// FIXME - estimate decals
|
||||||
|
|
||||||
// Size per component
|
// Size per component
|
||||||
int componentCount = 0;
|
int componentCount = 0;
|
||||||
Rocket rocket = doc.getRocket();
|
Rocket rocket = doc.getRocket();
|
||||||
@ -176,20 +306,20 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
iterator.next();
|
iterator.next();
|
||||||
componentCount++;
|
componentCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.isCompressionEnabled())
|
if (options.isCompressionEnabled())
|
||||||
size += componentCount * BYTES_PER_COMPONENT_COMPRESSED;
|
size += componentCount * BYTES_PER_COMPONENT_COMPRESSED;
|
||||||
else
|
else
|
||||||
size += componentCount * BYTES_PER_COMPONENT_UNCOMPRESSED;
|
size += componentCount * BYTES_PER_COMPONENT_UNCOMPRESSED;
|
||||||
|
|
||||||
|
|
||||||
// Size per simulation
|
// Size per simulation
|
||||||
if (options.isCompressionEnabled())
|
if (options.isCompressionEnabled())
|
||||||
size += doc.getSimulationCount() * BYTES_PER_SIMULATION_COMPRESSED;
|
size += doc.getSimulationCount() * BYTES_PER_SIMULATION_COMPRESSED;
|
||||||
else
|
else
|
||||||
size += doc.getSimulationCount() * BYTES_PER_SIMULATION_UNCOMPRESSED;
|
size += doc.getSimulationCount() * BYTES_PER_SIMULATION_UNCOMPRESSED;
|
||||||
|
|
||||||
|
|
||||||
// Size per flight data point
|
// Size per flight data point
|
||||||
int pointCount = 0;
|
int pointCount = 0;
|
||||||
double timeSkip = options.getSimulationTimeSkip();
|
double timeSkip = options.getSimulationTimeSkip();
|
||||||
@ -203,16 +333,16 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.isCompressionEnabled())
|
if (options.isCompressionEnabled())
|
||||||
size += pointCount * BYTES_PER_DATAPOINT_COMPRESSED;
|
size += pointCount * BYTES_PER_DATAPOINT_COMPRESSED;
|
||||||
else
|
else
|
||||||
size += pointCount * BYTES_PER_DATAPOINT_UNCOMPRESSED;
|
size += pointCount * BYTES_PER_DATAPOINT_UNCOMPRESSED;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine which file version is required in order to store all the features of the
|
* Determine which file version is required in order to store all the features of the
|
||||||
* current design. By default the oldest version that supports all the necessary features
|
* current design. By default the oldest version that supports all the necessary features
|
||||||
@ -224,6 +354,9 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
*/
|
*/
|
||||||
private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) {
|
private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) {
|
||||||
/*
|
/*
|
||||||
|
* File version 1.6 is required for:
|
||||||
|
* - saving files using appearances and textures
|
||||||
|
*
|
||||||
* File version 1.5 is requires for:
|
* File version 1.5 is requires for:
|
||||||
* - saving designs using ComponentPrests
|
* - saving designs using ComponentPrests
|
||||||
* - recovery device deployment on lower stage separation
|
* - recovery device deployment on lower stage separation
|
||||||
@ -239,14 +372,21 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
*
|
*
|
||||||
* Otherwise use version 1.0.
|
* Otherwise use version 1.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Search the rocket for any Appearnces (version 1.6)
|
||||||
|
for (RocketComponent c : document.getRocket()) {
|
||||||
|
if (c.getAppearance() != null) {
|
||||||
|
return FILE_VERSION_DIVISOR + 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Search the rocket for any ComponentPresets (version 1.5)
|
// Search the rocket for any ComponentPresets (version 1.5)
|
||||||
for (RocketComponent c : document.getRocket()) {
|
for (RocketComponent c : document.getRocket()) {
|
||||||
if (c.getPresetComponent() != null) {
|
if (c.getPresetComponent() != null) {
|
||||||
return FILE_VERSION_DIVISOR + 5;
|
return FILE_VERSION_DIVISOR + 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for recovery device deployment type LOWER_STAGE_SEPARATION (version 1.5)
|
// Search for recovery device deployment type LOWER_STAGE_SEPARATION (version 1.5)
|
||||||
for (RocketComponent c : document.getRocket()) {
|
for (RocketComponent c : document.getRocket()) {
|
||||||
if (c instanceof RecoveryDevice) {
|
if (c instanceof RecoveryDevice) {
|
||||||
@ -260,17 +400,17 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
if (!document.getCustomExpressions().isEmpty()) {
|
if (!document.getCustomExpressions().isEmpty()) {
|
||||||
return FILE_VERSION_DIVISOR + 5;
|
return FILE_VERSION_DIVISOR + 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if design has simulations defined (version 1.4)
|
// Check if design has simulations defined (version 1.4)
|
||||||
if (document.getSimulationCount() > 0) {
|
if (document.getSimulationCount() > 0) {
|
||||||
return FILE_VERSION_DIVISOR + 4;
|
return FILE_VERSION_DIVISOR + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for motor definitions (version 1.4)
|
// Check for motor definitions (version 1.4)
|
||||||
for (RocketComponent c : document.getRocket()) {
|
for (RocketComponent c : document.getRocket()) {
|
||||||
if (!(c instanceof MotorMount))
|
if (!(c instanceof MotorMount))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MotorMount mount = (MotorMount) c;
|
MotorMount mount = (MotorMount) c;
|
||||||
for (String id : document.getRocket().getMotorConfigurationIDs()) {
|
for (String id : document.getRocket().getMotorConfigurationIDs()) {
|
||||||
if (mount.getMotor(id) != null) {
|
if (mount.getMotor(id) != null) {
|
||||||
@ -278,7 +418,7 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for fin tabs (version 1.1)
|
// Check for fin tabs (version 1.1)
|
||||||
for (RocketComponent c : document.getRocket()) {
|
for (RocketComponent c : document.getRocket()) {
|
||||||
// Check for fin tabs
|
// Check for fin tabs
|
||||||
@ -289,7 +429,7 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
return FILE_VERSION_DIVISOR + 1;
|
return FILE_VERSION_DIVISOR + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for components attached to tube coupler
|
// Check for components attached to tube coupler
|
||||||
if (c instanceof TubeCoupler) {
|
if (c instanceof TubeCoupler) {
|
||||||
if (c.getChildCount() > 0) {
|
if (c.getChildCount() > 0) {
|
||||||
@ -297,45 +437,45 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default (version 1.0)
|
// Default (version 1.0)
|
||||||
return FILE_VERSION_DIVISOR + 0;
|
return FILE_VERSION_DIVISOR + 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void saveComponent(RocketComponent component) throws IOException {
|
private void saveComponent(RocketComponent component) throws IOException {
|
||||||
|
|
||||||
log.debug("Saving component " + component.getComponentName());
|
log.debug("Saving component " + component.getComponentName());
|
||||||
|
|
||||||
Reflection.Method m = Reflection.findMethod(METHOD_PACKAGE, component, METHOD_SUFFIX,
|
Reflection.Method m = Reflection.findMethod(METHOD_PACKAGE, component, METHOD_SUFFIX,
|
||||||
"getElements", RocketComponent.class);
|
"getElements", RocketComponent.class);
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
throw new BugException("Unable to find saving class for component " +
|
throw new BugException("Unable to find saving class for component " +
|
||||||
component.getComponentName());
|
component.getComponentName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the strings to save
|
// Get the strings to save
|
||||||
List<String> list = (List<String>) m.invokeStatic(component);
|
List<String> list = (List<String>) m.invokeStatic(component);
|
||||||
int length = list.size();
|
int length = list.size();
|
||||||
|
|
||||||
if (length == 0) // Nothing to do
|
if (length == 0) // Nothing to do
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (length < 2) {
|
if (length < 2) {
|
||||||
throw new RuntimeException("BUG, component data length less than two lines.");
|
throw new RuntimeException("BUG, component data length less than two lines.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open element
|
// Open element
|
||||||
writeln(list.get(0));
|
writeln(list.get(0));
|
||||||
indent++;
|
indent++;
|
||||||
|
|
||||||
// Write parameters
|
// Write parameters
|
||||||
for (int i = 1; i < length - 1; i++) {
|
for (int i = 1; i < length - 1; i++) {
|
||||||
writeln(list.get(i));
|
writeln(list.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively write subcomponents
|
// Recursively write subcomponents
|
||||||
if (component.getChildCount() > 0) {
|
if (component.getChildCount() > 0) {
|
||||||
writeln("");
|
writeln("");
|
||||||
@ -351,25 +491,25 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
indent--;
|
indent--;
|
||||||
writeln("</subcomponents>");
|
writeln("</subcomponents>");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close element
|
// Close element
|
||||||
indent--;
|
indent--;
|
||||||
writeln(list.get(length - 1));
|
writeln(list.get(length - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void saveSimulation(Simulation simulation, double timeSkip) throws IOException {
|
private void saveSimulation(Simulation simulation, double timeSkip) throws IOException {
|
||||||
SimulationOptions cond = simulation.getOptions();
|
SimulationOptions cond = simulation.getOptions();
|
||||||
|
|
||||||
writeln("<simulation status=\"" + enumToXMLName(simulation.getStatus()) + "\">");
|
writeln("<simulation status=\"" + enumToXMLName(simulation.getStatus()) + "\">");
|
||||||
indent++;
|
indent++;
|
||||||
|
|
||||||
writeln("<name>" + escapeXML(simulation.getName()) + "</name>");
|
writeln("<name>" + escapeXML(simulation.getName()) + "</name>");
|
||||||
// TODO: MEDIUM: Other simulators/calculators
|
// TODO: MEDIUM: Other simulators/calculators
|
||||||
|
|
||||||
writeln("<simulator>RK4Simulator</simulator>");
|
writeln("<simulator>RK4Simulator</simulator>");
|
||||||
writeln("<calculator>BarrowmanCalculator</calculator>");
|
writeln("<calculator>BarrowmanCalculator</calculator>");
|
||||||
|
|
||||||
writeln("<conditions>");
|
writeln("<conditions>");
|
||||||
indent++;
|
indent++;
|
||||||
|
|
||||||
@ -383,7 +523,7 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
writeElement("launchlatitude", cond.getLaunchLatitude());
|
writeElement("launchlatitude", cond.getLaunchLatitude());
|
||||||
writeElement("launchlongitude", cond.getLaunchLongitude());
|
writeElement("launchlongitude", cond.getLaunchLongitude());
|
||||||
writeElement("geodeticmethod", cond.getGeodeticComputation().name().toLowerCase(Locale.ENGLISH));
|
writeElement("geodeticmethod", cond.getGeodeticComputation().name().toLowerCase(Locale.ENGLISH));
|
||||||
|
|
||||||
if (cond.isISAAtmosphere()) {
|
if (cond.isISAAtmosphere()) {
|
||||||
writeln("<atmosphere model=\"isa\"/>");
|
writeln("<atmosphere model=\"isa\"/>");
|
||||||
} else {
|
} else {
|
||||||
@ -394,19 +534,19 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
indent--;
|
indent--;
|
||||||
writeln("</atmosphere>");
|
writeln("</atmosphere>");
|
||||||
}
|
}
|
||||||
|
|
||||||
writeElement("timestep", cond.getTimeStep());
|
writeElement("timestep", cond.getTimeStep());
|
||||||
|
|
||||||
indent--;
|
indent--;
|
||||||
writeln("</conditions>");
|
writeln("</conditions>");
|
||||||
|
|
||||||
|
|
||||||
for (String s : simulation.getSimulationListeners()) {
|
for (String s : simulation.getSimulationListeners()) {
|
||||||
writeElement("listener", escapeXML(s));
|
writeElement("listener", escapeXML(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write basic simulation data
|
// Write basic simulation data
|
||||||
|
|
||||||
FlightData data = simulation.getSimulatedData();
|
FlightData data = simulation.getSimulatedData();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
String str = "<flightdata";
|
String str = "<flightdata";
|
||||||
@ -431,53 +571,53 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
str += ">";
|
str += ">";
|
||||||
writeln(str);
|
writeln(str);
|
||||||
indent++;
|
indent++;
|
||||||
|
|
||||||
for (Warning w : data.getWarningSet()) {
|
for (Warning w : data.getWarningSet()) {
|
||||||
writeElement("warning", escapeXML(w.toString()));
|
writeElement("warning", escapeXML(w.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether to store data
|
// Check whether to store data
|
||||||
if (simulation.getStatus() == Simulation.Status.EXTERNAL) // Always store external data
|
if (simulation.getStatus() == Simulation.Status.EXTERNAL) // Always store external data
|
||||||
timeSkip = 0;
|
timeSkip = 0;
|
||||||
|
|
||||||
if (timeSkip != StorageOptions.SIMULATION_DATA_NONE) {
|
if (timeSkip != StorageOptions.SIMULATION_DATA_NONE) {
|
||||||
for (int i = 0; i < data.getBranchCount(); i++) {
|
for (int i = 0; i < data.getBranchCount(); i++) {
|
||||||
FlightDataBranch branch = data.getBranch(i);
|
FlightDataBranch branch = data.getBranch(i);
|
||||||
saveFlightDataBranch(branch, timeSkip);
|
saveFlightDataBranch(branch, timeSkip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indent--;
|
indent--;
|
||||||
writeln("</flightdata>");
|
writeln("</flightdata>");
|
||||||
}
|
}
|
||||||
|
|
||||||
indent--;
|
indent--;
|
||||||
writeln("</simulation>");
|
writeln("</simulation>");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void saveFlightDataBranch(FlightDataBranch branch, double timeSkip)
|
private void saveFlightDataBranch(FlightDataBranch branch, double timeSkip)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
double previousTime = -100000;
|
double previousTime = -100000;
|
||||||
|
|
||||||
if (branch == null)
|
if (branch == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Retrieve the types from the branch
|
// Retrieve the types from the branch
|
||||||
FlightDataType[] types = branch.getTypes();
|
FlightDataType[] types = branch.getTypes();
|
||||||
|
|
||||||
if (types.length == 0)
|
if (types.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Retrieve the data from the branch
|
// Retrieve the data from the branch
|
||||||
List<List<Double>> data = new ArrayList<List<Double>>(types.length);
|
List<List<Double>> data = new ArrayList<List<Double>>(types.length);
|
||||||
for (int i = 0; i < types.length; i++) {
|
for (int i = 0; i < types.length; i++) {
|
||||||
data.add(branch.get(types[i]));
|
data.add(branch.get(types[i]));
|
||||||
}
|
}
|
||||||
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
|
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
|
||||||
|
|
||||||
// Build the <databranch> tag
|
// Build the <databranch> tag
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("<databranch name=\"");
|
sb.append("<databranch name=\"");
|
||||||
@ -502,20 +642,20 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
sb.append("\">");
|
sb.append("\">");
|
||||||
writeln(sb.toString());
|
writeln(sb.toString());
|
||||||
indent++;
|
indent++;
|
||||||
|
|
||||||
// Write events
|
// Write events
|
||||||
for (FlightEvent event : branch.getEvents()) {
|
for (FlightEvent event : branch.getEvents()) {
|
||||||
writeln("<event time=\"" + TextUtil.doubleToString(event.getTime())
|
writeln("<event time=\"" + TextUtil.doubleToString(event.getTime())
|
||||||
+ "\" type=\"" + enumToXMLName(event.getType()) + "\"/>");
|
+ "\" type=\"" + enumToXMLName(event.getType()) + "\"/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the data
|
// Write the data
|
||||||
int length = branch.getLength();
|
int length = branch.getLength();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
writeDataPointString(data, 0, sb);
|
writeDataPointString(data, 0, sb);
|
||||||
previousTime = timeData.get(0);
|
previousTime = timeData.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < length - 1; i++) {
|
for (int i = 1; i < length - 1; i++) {
|
||||||
if (timeData != null) {
|
if (timeData != null) {
|
||||||
if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) {
|
if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) {
|
||||||
@ -527,61 +667,61 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
writeDataPointString(data, i, sb);
|
writeDataPointString(data, i, sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
writeDataPointString(data, length - 1, sb);
|
writeDataPointString(data, length - 1, sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
indent--;
|
indent--;
|
||||||
writeln("</databranch>");
|
writeln("</databranch>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: LOW: This is largely duplicated from above! */
|
/* TODO: LOW: This is largely duplicated from above! */
|
||||||
private int countFlightDataBranchPoints(FlightDataBranch branch, double timeSkip) {
|
private int countFlightDataBranchPoints(FlightDataBranch branch, double timeSkip) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
double previousTime = -100000;
|
double previousTime = -100000;
|
||||||
|
|
||||||
if (branch == null)
|
if (branch == null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Retrieve the types from the branch
|
// Retrieve the types from the branch
|
||||||
FlightDataType[] types = branch.getTypes();
|
FlightDataType[] types = branch.getTypes();
|
||||||
|
|
||||||
if (types.length == 0)
|
if (types.length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
|
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
|
||||||
if (timeData == null) {
|
if (timeData == null) {
|
||||||
// If time data not available, store all points
|
// If time data not available, store all points
|
||||||
return branch.getLength();
|
return branch.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the data
|
// Write the data
|
||||||
int length = branch.getLength();
|
int length = branch.getLength();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
count++;
|
count++;
|
||||||
previousTime = timeData.get(0);
|
previousTime = timeData.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < length - 1; i++) {
|
for (int i = 1; i < length - 1; i++) {
|
||||||
if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) {
|
if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) {
|
||||||
count++;
|
count++;
|
||||||
previousTime = timeData.get(i);
|
previousTime = timeData.get(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void writeDataPointString(List<List<Double>> data, int index, StringBuilder sb)
|
private void writeDataPointString(List<List<Double>> data, int index, StringBuilder sb)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sb.setLength(0);
|
sb.setLength(0);
|
||||||
@ -594,17 +734,17 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
sb.append("</datapoint>");
|
sb.append("</datapoint>");
|
||||||
writeln(sb.toString());
|
writeln(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void writeElement(String element, Object content) throws IOException {
|
private void writeElement(String element, Object content) throws IOException {
|
||||||
if (content == null)
|
if (content == null)
|
||||||
content = "";
|
content = "";
|
||||||
writeln("<" + element + ">" + content + "</" + element + ">");
|
writeln("<" + element + ">" + content + "</" + element + ">");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void writeln(String str) throws IOException {
|
private void writeln(String str) throws IOException {
|
||||||
if (str.length() == 0) {
|
if (str.length() == 0) {
|
||||||
dest.write("\n");
|
dest.write("\n");
|
||||||
@ -616,10 +756,10 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
s = s + str + "\n";
|
s = s + str + "\n";
|
||||||
dest.write(s);
|
dest.write(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the XML equivalent of an enum name.
|
* Return the XML equivalent of an enum name.
|
||||||
*
|
*
|
||||||
@ -629,5 +769,5 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
public static String enumToXMLName(Enum<?> e) {
|
public static String enumToXMLName(Enum<?> e) {
|
||||||
return e.name().toLowerCase(Locale.ENGLISH).replace("_", "");
|
return e.name().toLowerCase(Locale.ENGLISH).replace("_", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
import net.sf.openrocket.aerodynamics.Warning;
|
import net.sf.openrocket.aerodynamics.Warning;
|
||||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||||
|
import net.sf.openrocket.appearance.AppearanceBuilder;
|
||||||
|
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
||||||
import net.sf.openrocket.database.Databases;
|
import net.sf.openrocket.database.Databases;
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.document.Simulation;
|
import net.sf.openrocket.document.Simulation;
|
||||||
@ -166,7 +168,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
|
|||||||
class DocumentConfig {
|
class DocumentConfig {
|
||||||
|
|
||||||
/* Remember to update OpenRocketSaver as well! */
|
/* Remember to update OpenRocketSaver as well! */
|
||||||
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5" };
|
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divisor used in converting an integer version to the point-represented version.
|
* Divisor used in converting an integer version to the point-represented version.
|
||||||
@ -744,6 +746,7 @@ class DatatypeHandler extends AbstractElementHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CustomExpressionHandler extends AbstractElementHandler {
|
class CustomExpressionHandler extends AbstractElementHandler {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final DocumentLoadingContext context;
|
private final DocumentLoadingContext context;
|
||||||
private final OpenRocketContentHandler contentHandler;
|
private final OpenRocketContentHandler contentHandler;
|
||||||
public CustomExpression currentExpression;
|
public CustomExpression currentExpression;
|
||||||
@ -854,6 +857,9 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
|||||||
if (element.equals("subcomponents")) {
|
if (element.equals("subcomponents")) {
|
||||||
return new ComponentHandler(component, context);
|
return new ComponentHandler(component, context);
|
||||||
}
|
}
|
||||||
|
if ( element.equals("appearance")) {
|
||||||
|
return new AppearanceHandler(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."));
|
||||||
@ -885,7 +891,8 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
|||||||
String content, WarningSet warnings) {
|
String content, WarningSet warnings) {
|
||||||
|
|
||||||
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")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,6 +920,95 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AppearanceHandler extends AbstractElementHandler {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final DocumentLoadingContext context;
|
||||||
|
private final RocketComponent component;
|
||||||
|
|
||||||
|
private final AppearanceBuilder builder = new AppearanceBuilder();
|
||||||
|
private boolean isInDecal = false;
|
||||||
|
public AppearanceHandler( RocketComponent component, DocumentLoadingContext context ) {
|
||||||
|
this.context = context;
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public ElementHandler openElement(String element,HashMap<String, String> attributes, WarningSet warnings)
|
||||||
|
throws SAXException {
|
||||||
|
if ( "decal".equals(element) ) {
|
||||||
|
String name = attributes.remove("name");
|
||||||
|
builder.setImage(name);
|
||||||
|
double rotation = Double.parseDouble(attributes.remove("rotation"));
|
||||||
|
builder.setRotation(rotation);
|
||||||
|
String edgeModeName = attributes.remove("edgemode");
|
||||||
|
EdgeMode edgeMode = EdgeMode.valueOf(edgeModeName);
|
||||||
|
builder.setEdgeMode(edgeMode);
|
||||||
|
isInDecal = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return PlainTextHandler.INSTANCE;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void closeElement(String element,HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
|
||||||
|
if ( "ambient".equals(element) ) {
|
||||||
|
int red = Integer.parseInt(attributes.get("red"));
|
||||||
|
int green = Integer.parseInt(attributes.get("green"));
|
||||||
|
int blue = Integer.parseInt(attributes.get("blue"));
|
||||||
|
builder.setAmbient( new Color(red,green,blue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( "diffuse".equals(element) ) {
|
||||||
|
int red = Integer.parseInt(attributes.get("red"));
|
||||||
|
int green = Integer.parseInt(attributes.get("green"));
|
||||||
|
int blue = Integer.parseInt(attributes.get("blue"));
|
||||||
|
builder.setDiffuse( new Color(red,green,blue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( "specular".equals(element) ) {
|
||||||
|
int red = Integer.parseInt(attributes.get("red"));
|
||||||
|
int green = Integer.parseInt(attributes.get("green"));
|
||||||
|
int blue = Integer.parseInt(attributes.get("blue"));
|
||||||
|
builder.setSpecular( new Color(red,green,blue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( isInDecal && "center".equals(element) ) {
|
||||||
|
double x = Double.parseDouble(attributes.get("x"));
|
||||||
|
double y = Double.parseDouble(attributes.get("y"));
|
||||||
|
builder.setCenter(x,y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( isInDecal && "offset".equals(element) ) {
|
||||||
|
double x = Double.parseDouble(attributes.get("x"));
|
||||||
|
double y = Double.parseDouble(attributes.get("y"));
|
||||||
|
builder.setOffset(x,y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( isInDecal && "scale".equals(element) ) {
|
||||||
|
double x = Double.parseDouble(attributes.get("x"));
|
||||||
|
double y = Double.parseDouble(attributes.get("y"));
|
||||||
|
builder.setScale(x,y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( isInDecal && "decal".equals(element) ) {
|
||||||
|
isInDecal = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.closeElement(element, attributes, content, warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endHandler(String element, HashMap<String, String> attributes,
|
||||||
|
String content, WarningSet warnings) throws SAXException {
|
||||||
|
if ( "decal".equals(element) ) {
|
||||||
|
isInDecal = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
component.setAppearance(builder.getAppearance());
|
||||||
|
super.endHandler(element, attributes, content, warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A handler that reads the <point> specifications within the freeformfinset's
|
* A handler that reads the <point> specifications within the freeformfinset's
|
||||||
|
@ -5,6 +5,9 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
|
import net.sf.openrocket.appearance.Decal;
|
||||||
|
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
||||||
import net.sf.openrocket.file.RocketSaver;
|
import net.sf.openrocket.file.RocketSaver;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.material.Material;
|
import net.sf.openrocket.material.Material;
|
||||||
@ -18,51 +21,73 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
|||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.LineStyle;
|
import net.sf.openrocket.util.LineStyle;
|
||||||
|
|
||||||
|
|
||||||
public class RocketComponentSaver {
|
public class RocketComponentSaver {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
protected RocketComponentSaver() {
|
protected RocketComponentSaver() {
|
||||||
// Prevent instantiation from outside the package
|
// Prevent instantiation from outside the package
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List<String> elements) {
|
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List<String> elements) {
|
||||||
elements.add("<name>" + RocketSaver.escapeXML(c.getName()) + "</name>");
|
elements.add("<name>" + RocketSaver.escapeXML(c.getName()) + "</name>");
|
||||||
|
|
||||||
ComponentPreset preset = c.getPresetComponent();
|
ComponentPreset preset = c.getPresetComponent();
|
||||||
if (preset != null) {
|
if (preset != null) {
|
||||||
elements.add("<preset type=\"" + preset.getType() +
|
elements.add("<preset type=\"" + preset.getType() +
|
||||||
"\" manufacturer=\"" + preset.getManufacturer().getSimpleName() +
|
"\" manufacturer=\"" + preset.getManufacturer().getSimpleName() +
|
||||||
"\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() + "\"/>");
|
"\" partno=\"" + preset.getPartNo() + "\" digest=\"" + preset.getDigest() + "\"/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Appearance ap = c.getAppearance();
|
||||||
|
if ( ap != null ) {
|
||||||
|
elements.add("<appearance>");
|
||||||
|
Color ambient = ap.getAmbient();
|
||||||
|
emitColor("ambient",elements,ambient);
|
||||||
|
Color diffuse = ap.getDiffuse();
|
||||||
|
emitColor("diffuse",elements,diffuse);
|
||||||
|
Color specular = ap.getSpecular();
|
||||||
|
emitColor("specular",elements,specular);
|
||||||
|
Decal decal = ap.getTexture();
|
||||||
|
if ( decal != null ) {
|
||||||
|
String name = decal.getImage();
|
||||||
|
double rotation = decal.getRotation();
|
||||||
|
EdgeMode edgeMode = decal.getEdgeMode();
|
||||||
|
elements.add("<decal name=\""+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>");
|
||||||
|
}
|
||||||
|
|
||||||
// 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)) {
|
||||||
Color color = c.getColor();
|
Color color = c.getColor();
|
||||||
if (color != null) {
|
emitColor("color", elements, color);
|
||||||
elements.add("<color red=\"" + color.getRed() + "\" green=\"" + color.getGreen()
|
|
||||||
+ "\" blue=\"" + color.getBlue() + "\"/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
LineStyle style = c.getLineStyle();
|
LineStyle style = c.getLineStyle();
|
||||||
if (style != null) {
|
if (style != null) {
|
||||||
// Type names currently equivalent to the enum names except for case.
|
// Type names currently equivalent to the enum names except for case.
|
||||||
elements.add("<linestyle>" + style.name().toLowerCase(Locale.ENGLISH) + "</linestyle>");
|
elements.add("<linestyle>" + style.name().toLowerCase(Locale.ENGLISH) + "</linestyle>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Save position unless "AFTER"
|
// Save position unless "AFTER"
|
||||||
if (c.getRelativePosition() != RocketComponent.Position.AFTER) {
|
if (c.getRelativePosition() != RocketComponent.Position.AFTER) {
|
||||||
// The type names are currently equivalent to the enum names except for case.
|
// The type names are currently equivalent to the enum names except for case.
|
||||||
String type = c.getRelativePosition().name().toLowerCase(Locale.ENGLISH);
|
String type = c.getRelativePosition().name().toLowerCase(Locale.ENGLISH);
|
||||||
elements.add("<position type=\"" + type + "\">" + c.getPositionValue() + "</position>");
|
elements.add("<position type=\"" + type + "\">" + c.getPositionValue() + "</position>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Overrides
|
// Overrides
|
||||||
boolean overridden = false;
|
boolean overridden = false;
|
||||||
if (c.isMassOverridden()) {
|
if (c.isMassOverridden()) {
|
||||||
@ -77,26 +102,26 @@ public class RocketComponentSaver {
|
|||||||
elements.add("<overridesubcomponents>" + c.getOverrideSubcomponents()
|
elements.add("<overridesubcomponents>" + c.getOverrideSubcomponents()
|
||||||
+ "</overridesubcomponents>");
|
+ "</overridesubcomponents>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Comment
|
// Comment
|
||||||
if (c.getComment().length() > 0) {
|
if (c.getComment().length() > 0) {
|
||||||
elements.add("<comment>" + RocketSaver.escapeXML(c.getComment()) + "</comment>");
|
elements.add("<comment>" + RocketSaver.escapeXML(c.getComment()) + "</comment>");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected final String materialParam(Material mat) {
|
protected final String materialParam(Material mat) {
|
||||||
return materialParam("material", mat);
|
return materialParam("material", mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected final String materialParam(String tag, Material mat) {
|
protected final String materialParam(String tag, Material mat) {
|
||||||
String str = "<" + tag;
|
String str = "<" + tag;
|
||||||
|
|
||||||
switch (mat.getType()) {
|
switch (mat.getType()) {
|
||||||
case LINE:
|
case LINE:
|
||||||
str += " type=\"line\"";
|
str += " type=\"line\"";
|
||||||
@ -110,29 +135,29 @@ public class RocketComponentSaver {
|
|||||||
default:
|
default:
|
||||||
throw new BugException("Unknown material type: " + mat.getType());
|
throw new BugException("Unknown material type: " + mat.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
String baseName = trans.getBaseText("material", mat.getName());
|
String baseName = trans.getBaseText("material", mat.getName());
|
||||||
|
|
||||||
return str + " density=\"" + mat.getDensity() + "\">" + RocketSaver.escapeXML(baseName) + "</" + tag + ">";
|
return str + " density=\"" + mat.getDensity() + "\">" + RocketSaver.escapeXML(baseName) + "</" + tag + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected final List<String> motorMountParams(MotorMount mount) {
|
protected final List<String> motorMountParams(MotorMount mount) {
|
||||||
if (!mount.isMotorMount())
|
if (!mount.isMotorMount())
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
||||||
String[] motorConfigIDs = ((RocketComponent) mount).getRocket().getMotorConfigurationIDs();
|
String[] motorConfigIDs = ((RocketComponent) mount).getRocket().getMotorConfigurationIDs();
|
||||||
List<String> elements = new ArrayList<String>();
|
List<String> elements = new ArrayList<String>();
|
||||||
|
|
||||||
elements.add("<motormount>");
|
elements.add("<motormount>");
|
||||||
|
|
||||||
for (String id : motorConfigIDs) {
|
for (String id : motorConfigIDs) {
|
||||||
Motor motor = mount.getMotor(id);
|
Motor motor = mount.getMotor(id);
|
||||||
|
|
||||||
// Nothing is stored if no motor loaded
|
// Nothing is stored if no motor loaded
|
||||||
if (motor == null)
|
if (motor == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
elements.add(" <motor configid=\"" + id + "\">");
|
elements.add(" <motor configid=\"" + id + "\">");
|
||||||
if (motor.getMotorType() != Motor.Type.UNKNOWN) {
|
if (motor.getMotorType() != Motor.Type.UNKNOWN) {
|
||||||
elements.add(" <type>" + motor.getMotorType().name().toLowerCase(Locale.ENGLISH) + "</type>");
|
elements.add(" <type>" + motor.getMotorType().name().toLowerCase(Locale.ENGLISH) + "</type>");
|
||||||
@ -146,27 +171,35 @@ public class RocketComponentSaver {
|
|||||||
elements.add(" <designation>" + RocketSaver.escapeXML(motor.getDesignation()) + "</designation>");
|
elements.add(" <designation>" + RocketSaver.escapeXML(motor.getDesignation()) + "</designation>");
|
||||||
elements.add(" <diameter>" + motor.getDiameter() + "</diameter>");
|
elements.add(" <diameter>" + motor.getDiameter() + "</diameter>");
|
||||||
elements.add(" <length>" + motor.getLength() + "</length>");
|
elements.add(" <length>" + motor.getLength() + "</length>");
|
||||||
|
|
||||||
// Motor delay
|
// Motor delay
|
||||||
if (mount.getMotorDelay(id) == Motor.PLUGGED) {
|
if (mount.getMotorDelay(id) == Motor.PLUGGED) {
|
||||||
elements.add(" <delay>none</delay>");
|
elements.add(" <delay>none</delay>");
|
||||||
} else {
|
} else {
|
||||||
elements.add(" <delay>" + mount.getMotorDelay(id) + "</delay>");
|
elements.add(" <delay>" + mount.getMotorDelay(id) + "</delay>");
|
||||||
}
|
}
|
||||||
|
|
||||||
elements.add(" </motor>");
|
elements.add(" </motor>");
|
||||||
}
|
}
|
||||||
|
|
||||||
elements.add(" <ignitionevent>"
|
elements.add(" <ignitionevent>"
|
||||||
+ mount.getIgnitionEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "")
|
+ mount.getIgnitionEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "")
|
||||||
+ "</ignitionevent>");
|
+ "</ignitionevent>");
|
||||||
|
|
||||||
elements.add(" <ignitiondelay>" + mount.getIgnitionDelay() + "</ignitiondelay>");
|
elements.add(" <ignitiondelay>" + mount.getIgnitionDelay() + "</ignitiondelay>");
|
||||||
elements.add(" <overhang>" + mount.getMotorOverhang() + "</overhang>");
|
elements.add(" <overhang>" + mount.getMotorOverhang() + "</overhang>");
|
||||||
|
|
||||||
elements.add("</motormount>");
|
elements.add("</motormount>");
|
||||||
|
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static void emitColor( String elementName, List<String> elements, Color color ) {
|
||||||
|
if (color != null) {
|
||||||
|
elements.add("<" + elementName+ " red=\"" + color.getRed() + "\" green=\"" + color.getGreen()
|
||||||
|
+ "\" blue=\"" + color.getBlue() + "\"/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
package net.sf.openrocket.file.rocksim.export;
|
package net.sf.openrocket.file.rocksim.export;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.Marshaller;
|
||||||
|
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.document.StorageOptions;
|
import net.sf.openrocket.document.StorageOptions;
|
||||||
import net.sf.openrocket.file.RocketSaver;
|
import net.sf.openrocket.file.RocketSaver;
|
||||||
@ -12,14 +21,6 @@ import net.sf.openrocket.rocketcomponent.Rocket;
|
|||||||
import net.sf.openrocket.rocketcomponent.Stage;
|
import net.sf.openrocket.rocketcomponent.Stage;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.Marshaller;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for converting an OpenRocket design to a Rocksim design.
|
* This class is responsible for converting an OpenRocket design to a Rocksim design.
|
||||||
*/
|
*/
|
||||||
@ -55,7 +56,7 @@ public class RocksimSaver extends RocketSaver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
|
public void save(String fileName, OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
|
||||||
log.info("Saving .rkt file");
|
log.info("Saving .rkt file");
|
||||||
|
|
||||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, "UTF-8"));
|
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, "UTF-8"));
|
||||||
|
@ -82,7 +82,7 @@ public class RockSimAppearanceBuilder extends AppearanceBuilder {
|
|||||||
//Find out how to get path of current rocksim file
|
//Find out how to get path of current rocksim file
|
||||||
//so I can look in it's directory
|
//so I can look in it's directory
|
||||||
}
|
}
|
||||||
setImage(f.toURI().toURL());
|
setImage(value);
|
||||||
}
|
}
|
||||||
} else if ("repeat".equals(name)) {
|
} else if ("repeat".equals(name)) {
|
||||||
repeat = "1".equals(value);
|
repeat = "1".equals(value);
|
||||||
@ -136,6 +136,23 @@ public class RockSimAppearanceBuilder extends AppearanceBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Color parseColor(String s) {
|
static Color parseColor(String s) {
|
||||||
|
// blue and white came from a real file.
|
||||||
|
if ( "blue".equals(s) ) {
|
||||||
|
return new Color(0,0,255);
|
||||||
|
}
|
||||||
|
if ( "white".equals(s) ) {
|
||||||
|
return new Color(255,255,255);
|
||||||
|
}
|
||||||
|
// I guessed these are valid color names in Rksim.
|
||||||
|
if ( "red".equals(s) ) {
|
||||||
|
return new Color(255,0,0);
|
||||||
|
}
|
||||||
|
if( "green".equals(s) ) {
|
||||||
|
return new Color(0,255,0);
|
||||||
|
}
|
||||||
|
if ( "black".equals(s) ) {
|
||||||
|
return new Color(0,0,0);
|
||||||
|
}
|
||||||
s = s.replace("rgb(", "");
|
s = s.replace("rgb(", "");
|
||||||
s = s.replace(")", "");
|
s = s.replace(")", "");
|
||||||
String ss[] = s.split(",");
|
String ss[] = s.split(",");
|
||||||
|
@ -5,8 +5,6 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.EventObject;
|
import java.util.EventObject;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
@ -233,25 +231,12 @@ public class AppearancePanel extends JPanel {
|
|||||||
choose.addActionListener(new ActionListener() {
|
choose.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
URL u = ab.getImage();
|
|
||||||
File current = lastImageDir;
|
File current = lastImageDir;
|
||||||
if (u != null && u.getProtocol().equals("file")) {
|
|
||||||
try {
|
|
||||||
current = new File(u.toURI()).getParentFile();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastImageDir = current;
|
lastImageDir = current;
|
||||||
|
|
||||||
JFileChooser fc = new JFileChooser(current);
|
JFileChooser fc = new JFileChooser(current);
|
||||||
if (fc.showOpenDialog(AppearancePanel.this) == JFileChooser.APPROVE_OPTION) {
|
if (fc.showOpenDialog(AppearancePanel.this) == JFileChooser.APPROVE_OPTION) {
|
||||||
try {
|
ab.setImage(fc.getSelectedFile().getAbsolutePath());
|
||||||
ab.setImage(fc.getSelectedFile().toURI().toURL());
|
|
||||||
} catch (MalformedURLException e1) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ import net.sf.openrocket.util.Color;
|
|||||||
public class FigureRenderStrategy extends RenderStrategy {
|
public class FigureRenderStrategy extends RenderStrategy {
|
||||||
private final float[] color = new float[4];
|
private final float[] color = new float[4];
|
||||||
|
|
||||||
|
public FigureRenderStrategy() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDrawn(RocketComponent c) {
|
public boolean isDrawn(RocketComponent c) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package net.sf.openrocket.gui.figure3d;
|
package net.sf.openrocket.gui.figure3d;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -14,26 +13,34 @@ import javax.media.opengl.GLProfile;
|
|||||||
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
||||||
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
||||||
|
|
||||||
import com.jogamp.opengl.util.texture.Texture;
|
|
||||||
import com.jogamp.opengl.util.texture.TextureData;
|
|
||||||
import com.jogamp.opengl.util.texture.TextureIO;
|
|
||||||
|
|
||||||
import net.sf.openrocket.appearance.Appearance;
|
import net.sf.openrocket.appearance.Appearance;
|
||||||
import net.sf.openrocket.appearance.Decal;
|
import net.sf.openrocket.appearance.Decal;
|
||||||
|
import net.sf.openrocket.document.DecalRegistry;
|
||||||
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.logging.LogHelper;
|
import net.sf.openrocket.logging.LogHelper;
|
||||||
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.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
|
|
||||||
|
import com.jogamp.opengl.util.texture.Texture;
|
||||||
|
import com.jogamp.opengl.util.texture.TextureData;
|
||||||
|
import com.jogamp.opengl.util.texture.TextureIO;
|
||||||
|
|
||||||
public class RealisticRenderStrategy extends RenderStrategy {
|
public class RealisticRenderStrategy extends RenderStrategy {
|
||||||
|
|
||||||
private final float[] colorBlack = { 0, 0, 0, 1 };
|
private final float[] colorBlack = { 0, 0, 0, 1 };
|
||||||
private final float[] color = new float[4];
|
private final float[] color = new float[4];
|
||||||
private static final LogHelper log = Application.getLogger();
|
private static final LogHelper log = Application.getLogger();
|
||||||
|
|
||||||
|
private final DecalRegistry decalLoader;
|
||||||
private boolean needClearCache = false;
|
private boolean needClearCache = false;
|
||||||
private Map<URI, Texture> oldTexCache = new HashMap<URI, Texture>();
|
private Map<String, Texture> oldTexCache = new HashMap<String, Texture>();
|
||||||
private Map<URI, Texture> texCache = new HashMap<URI, Texture>();
|
private Map<String, Texture> texCache = new HashMap<String, Texture>();
|
||||||
|
|
||||||
|
public RealisticRenderStrategy(OpenRocketDocument document) {
|
||||||
|
super(document);
|
||||||
|
this.decalLoader = document.getDecalRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateFigure() {
|
public void updateFigure() {
|
||||||
@ -42,8 +49,8 @@ public class RealisticRenderStrategy extends RenderStrategy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(GLAutoDrawable drawable) {
|
public void init(GLAutoDrawable drawable) {
|
||||||
oldTexCache = new HashMap<URI,Texture>();
|
oldTexCache = new HashMap<String,Texture>();
|
||||||
texCache = new HashMap<URI,Texture>();
|
texCache = new HashMap<String,Texture>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,7 +107,7 @@ public class RealisticRenderStrategy extends RenderStrategy {
|
|||||||
if (t != null && tex != null) {
|
if (t != null && tex != null) {
|
||||||
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
|
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
|
||||||
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
|
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
|
||||||
|
|
||||||
tex.enable(gl);
|
tex.enable(gl);
|
||||||
tex.bind(gl);
|
tex.bind(gl);
|
||||||
gl.glMatrixMode(GL.GL_TEXTURE);
|
gl.glMatrixMode(GL.GL_TEXTURE);
|
||||||
@ -138,46 +145,40 @@ public class RealisticRenderStrategy extends RenderStrategy {
|
|||||||
|
|
||||||
private void clearCaches(GL2 gl) {
|
private void clearCaches(GL2 gl) {
|
||||||
log.debug("ClearCaches");
|
log.debug("ClearCaches");
|
||||||
for (Map.Entry<URI, Texture> e : oldTexCache.entrySet()) {
|
for (Map.Entry<String, Texture> e : oldTexCache.entrySet()) {
|
||||||
log.debug("Destroying Texture for " + e.getKey());
|
log.debug("Destroying Texture for " + e.getKey());
|
||||||
if (e.getValue() != null)
|
if (e.getValue() != null)
|
||||||
e.getValue().destroy(gl);
|
e.getValue().destroy(gl);
|
||||||
}
|
}
|
||||||
oldTexCache = texCache;
|
oldTexCache = texCache;
|
||||||
texCache = new HashMap<URI, Texture>();
|
texCache = new HashMap<String, Texture>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Texture getTexture(Decal t) {
|
private Texture getTexture(Decal t) {
|
||||||
URL url = t.getImageURL();
|
String imageName = t.getImage();
|
||||||
URI uri; // NEVER use a URL as a key!
|
|
||||||
try {
|
|
||||||
uri = url.toURI();
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the Cached value if available
|
// Return the Cached value if available
|
||||||
if (texCache.containsKey(uri))
|
if (texCache.containsKey(imageName))
|
||||||
return texCache.get(uri);
|
return texCache.get(imageName);
|
||||||
|
|
||||||
// If the texture is in the Old Cache, save it.
|
// If the texture is in the Old Cache, save it.
|
||||||
if (oldTexCache.containsKey(uri)) {
|
if (oldTexCache.containsKey(imageName)) {
|
||||||
texCache.put(uri, oldTexCache.get(uri));
|
texCache.put(imageName, oldTexCache.get(imageName));
|
||||||
oldTexCache.remove(uri);
|
oldTexCache.remove(imageName);
|
||||||
return texCache.get(uri);
|
return texCache.get(imageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise load it.
|
// Otherwise load it.
|
||||||
Texture tex = null;
|
Texture tex = null;
|
||||||
try {
|
try {
|
||||||
log.debug("Loading texture " + t);
|
log.debug("Loading texture " + t);
|
||||||
TextureData data = TextureIO.newTextureData(GLProfile.getDefault(), url.openStream(), true, null);
|
InputStream is = decalLoader.getDecal(imageName);
|
||||||
|
TextureData data = TextureIO.newTextureData(GLProfile.getDefault(), is, true, null);
|
||||||
tex = TextureIO.newTexture(data);
|
tex = TextureIO.newTexture(data);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
log.error("Error loading Texture", e);
|
log.error("Error loading Texture", e);
|
||||||
}
|
}
|
||||||
texCache.put(uri, tex);
|
texCache.put(imageName, tex);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
|
|
||||||
|
@ -3,9 +3,17 @@ package net.sf.openrocket.gui.figure3d;
|
|||||||
import javax.media.opengl.GL2;
|
import javax.media.opengl.GL2;
|
||||||
import javax.media.opengl.GLAutoDrawable;
|
import javax.media.opengl.GLAutoDrawable;
|
||||||
|
|
||||||
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
|
||||||
public abstract class RenderStrategy {
|
public abstract class RenderStrategy {
|
||||||
|
|
||||||
|
protected final OpenRocketDocument document;
|
||||||
|
|
||||||
|
public RenderStrategy( OpenRocketDocument document ) {
|
||||||
|
this.document = document;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract boolean isDrawn(RocketComponent c);
|
public abstract boolean isDrawn(RocketComponent c);
|
||||||
|
|
||||||
public abstract boolean isDrawnTransparent(RocketComponent c);
|
public abstract boolean isDrawnTransparent(RocketComponent c);
|
||||||
|
@ -31,6 +31,7 @@ import javax.swing.JPopupMenu;
|
|||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.event.MouseInputAdapter;
|
import javax.swing.event.MouseInputAdapter;
|
||||||
|
|
||||||
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.gui.figureelements.CGCaret;
|
import net.sf.openrocket.gui.figureelements.CGCaret;
|
||||||
import net.sf.openrocket.gui.figureelements.CPCaret;
|
import net.sf.openrocket.gui.figureelements.CPCaret;
|
||||||
import net.sf.openrocket.gui.figureelements.FigureElement;
|
import net.sf.openrocket.gui.figureelements.FigureElement;
|
||||||
@ -65,6 +66,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
private static double fovX = Double.NaN;
|
private static double fovX = Double.NaN;
|
||||||
private static final int CARET_SIZE = 20;
|
private static final int CARET_SIZE = 20;
|
||||||
|
|
||||||
|
private OpenRocketDocument document;
|
||||||
private Configuration configuration;
|
private Configuration configuration;
|
||||||
private GLCanvas canvas;
|
private GLCanvas canvas;
|
||||||
|
|
||||||
@ -87,7 +89,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
|
|
||||||
RocketRenderer rr = new RocketRenderer();
|
RocketRenderer rr = new RocketRenderer();
|
||||||
|
|
||||||
public RocketFigure3d(Configuration config) {
|
public RocketFigure3d(OpenRocketDocument document, Configuration config) {
|
||||||
|
this.document = document;
|
||||||
this.configuration = config;
|
this.configuration = config;
|
||||||
this.setLayout(new BorderLayout());
|
this.setLayout(new BorderLayout());
|
||||||
|
|
||||||
@ -627,7 +630,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
if ( t == TYPE_FIGURE ){
|
if ( t == TYPE_FIGURE ){
|
||||||
rr.setRenderStrategy(new FigureRenderStrategy());
|
rr.setRenderStrategy(new FigureRenderStrategy());
|
||||||
} else {
|
} else {
|
||||||
rr.setRenderStrategy(new RealisticRenderStrategy());
|
rr.setRenderStrategy(new RealisticRenderStrategy(document));
|
||||||
}
|
}
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ public class BasicFrame extends JFrame {
|
|||||||
/**
|
/**
|
||||||
* The RocketLoader instance used for loading all rocket designs.
|
* The RocketLoader instance used for loading all rocket designs.
|
||||||
*/
|
*/
|
||||||
private static final RocketLoader ROCKET_LOADER = new GeneralRocketLoader();
|
private static final GeneralRocketLoader ROCKET_LOADER = new GeneralRocketLoader();
|
||||||
|
|
||||||
private static final RocketSaver ROCKET_SAVER = new OpenRocketSaver();
|
private static final RocketSaver ROCKET_SAVER = new OpenRocketSaver();
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
|
|
||||||
// Create figure and custom scroll pane
|
// Create figure and custom scroll pane
|
||||||
figure = new RocketFigure(configuration);
|
figure = new RocketFigure(configuration);
|
||||||
figure3d = new RocketFigure3d(configuration);
|
figure3d = new RocketFigure3d(document, configuration);
|
||||||
|
|
||||||
figureHolder = new JPanel(new BorderLayout());
|
figureHolder = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import javax.swing.SwingWorker;
|
|||||||
|
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.file.DatabaseMotorFinder;
|
import net.sf.openrocket.file.DatabaseMotorFinder;
|
||||||
import net.sf.openrocket.file.RocketLoader;
|
import net.sf.openrocket.file.GeneralRocketLoader;
|
||||||
import net.sf.openrocket.logging.LogHelper;
|
import net.sf.openrocket.logging.LogHelper;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
@ -28,22 +28,22 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
|
|||||||
|
|
||||||
private final File file;
|
private final File file;
|
||||||
private final InputStream stream;
|
private final InputStream stream;
|
||||||
private final RocketLoader loader;
|
private final GeneralRocketLoader loader;
|
||||||
|
|
||||||
public OpenFileWorker(File file, RocketLoader loader) {
|
public OpenFileWorker(File file, GeneralRocketLoader loader) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.stream = null;
|
this.stream = null;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public OpenFileWorker(InputStream stream, RocketLoader loader) {
|
public OpenFileWorker(InputStream stream, GeneralRocketLoader loader) {
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.file = null;
|
this.file = null;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RocketLoader getRocketLoader() {
|
public GeneralRocketLoader getRocketLoader() {
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
|
|||||||
is = new ProgressInputStream(is);
|
is = new ProgressInputStream(is);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return loader.load(is, new DatabaseMotorFinder());
|
return loader.load(is, file, new DatabaseMotorFinder());
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
|
@ -41,8 +41,10 @@ public class SaveFileWorker extends SwingWorker<Void, Void> {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
String rawFilename = file.getName();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
saver.save(os, document);
|
saver.save(rawFilename, os, document);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
os.close();
|
os.close();
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package net.sf.openrocket;
|
package net.sf.openrocket;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@ -91,7 +96,7 @@ public class IntegrationTest extends BaseTestCase {
|
|||||||
GeneralRocketLoader loader = new GeneralRocketLoader();
|
GeneralRocketLoader loader = new GeneralRocketLoader();
|
||||||
InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
|
InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
|
||||||
assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
|
assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
|
||||||
document = loader.load(is, new DatabaseMotorFinder());
|
document = loader.load(is, new File("simplerocket.ork"), new DatabaseMotorFinder());
|
||||||
is.close();
|
is.close();
|
||||||
|
|
||||||
undoAction = UndoRedoAction.newUndoAction(document);
|
undoAction = UndoRedoAction.newUndoAction(document);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user