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;
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
@ -10,7 +11,7 @@ import net.sf.openrocket.database.ComponentPresetDatabase;
|
||||
import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
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.scalefigure.RocketPanel;
|
||||
import net.sf.openrocket.gui.util.GUIUtil;
|
||||
@ -47,22 +48,14 @@ public class TextureTest {
|
||||
|
||||
@Override
|
||||
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);
|
||||
|
||||
OpenRocketDocument doc = new RocksimLoader().load(
|
||||
TextureTest.class.getResourceAsStream("al1 Apocalypse_54mmtestFr.rkt.xml"), new DatabaseMotorFinder());
|
||||
OpenRocketDocument doc = new GeneralRocketLoader().load(
|
||||
new File("3d-Test-Junk/net/sf/openrocket/startup/al1 Apocalypse_54mmtestFr.rkt.xml"),
|
||||
new DatabaseMotorFinder());
|
||||
|
||||
GUIUtil.setBestLAF();
|
||||
|
||||
|
@ -233,7 +233,7 @@
|
||||
<PartDesc>Plastic nose cone</PartDesc>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -292,7 +292,7 @@
|
||||
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -460,7 +460,7 @@
|
||||
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -571,7 +571,7 @@
|
||||
<PartDesc><![CDATA[3.9" Airframe Tube]]></PartDesc>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -851,7 +851,7 @@
|
||||
<DensityType>0</DensityType>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -1095,7 +1095,7 @@
|
||||
<DensityType>0</DensityType>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -1339,7 +1339,7 @@
|
||||
<DensityType>0</DensityType>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
@ -1583,7 +1583,7 @@
|
||||
<DensityType>0</DensityType>
|
||||
<RadialLoc>0.</RadialLoc>
|
||||
<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>
|
||||
<Opacity>1.</Opacity>
|
||||
<Specular>0.</Specular>
|
||||
|
@ -1041,6 +1041,8 @@ StorageOptChooser.lbl.seconds = seconds
|
||||
StorageOptChooser.rdbut.Onlyprimfig = Only primary figures
|
||||
StorageOptChooser.lbl.longC1 = <html>Store only the values shown in the summary table.<br>
|
||||
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.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.
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.sf.openrocket.appearance;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
||||
import net.sf.openrocket.util.AbstractChangeSource;
|
||||
import net.sf.openrocket.util.Color;
|
||||
@ -26,7 +24,7 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
||||
private double centerU, centerV;
|
||||
private double scaleU, scaleV;
|
||||
private double rotation;
|
||||
private URL image;
|
||||
private String image;
|
||||
private Decal.EdgeMode edgeMode;
|
||||
|
||||
public AppearanceBuilder() {
|
||||
@ -47,7 +45,7 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
||||
setScale(d.getScale().x, d.getScale().y);
|
||||
setRotation(d.getRotation());
|
||||
setEdgeMode(d.getEdgeMode());
|
||||
setImage(d.getImageURL());
|
||||
setImage(d.getImage());
|
||||
}
|
||||
// TODO Critical the rest of this!
|
||||
}
|
||||
@ -199,11 +197,11 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public URL getImage() {
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(URL image) {
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.sf.openrocket.appearance;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
|
||||
@ -26,11 +24,11 @@ public class Decal {
|
||||
|
||||
private final Coordinate offset, center, scale;
|
||||
private final double rotation;
|
||||
private final URL image;
|
||||
private final String image;
|
||||
private final EdgeMode mode;
|
||||
|
||||
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.center = center;
|
||||
this.scale = scale;
|
||||
@ -59,7 +57,7 @@ public class Decal {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public URL getImageURL() {
|
||||
public String getImage() {
|
||||
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 ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
|
||||
|
||||
|
||||
/*
|
||||
* 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 storedDescription = null;
|
||||
|
||||
private DecalRegistry decalRegistry = new DecalRegistry();
|
||||
|
||||
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() {
|
||||
return file;
|
||||
}
|
||||
|
@ -15,32 +15,6 @@ public abstract class AbstractRocketLoader implements RocketLoader {
|
||||
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.
|
||||
*/
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.sf.openrocket.file;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
@ -9,6 +11,7 @@ import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
|
||||
import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
|
||||
@ -23,7 +26,9 @@ import net.sf.openrocket.util.TextUtil;
|
||||
*
|
||||
* @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;
|
||||
|
||||
@ -36,7 +41,46 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
||||
|
||||
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,
|
||||
RocketLoadException {
|
||||
|
||||
@ -56,12 +100,14 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
||||
throw new RocketLoadException("Unsupported or corrupt file.");
|
||||
}
|
||||
|
||||
|
||||
// Detect the appropriate loader
|
||||
|
||||
// Check for GZIP
|
||||
if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
|
||||
OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source), motorFinder);
|
||||
doc.getDefaultStorageOptions().setCompressionEnabled(true);
|
||||
doc.getDecalRegistry().setIsZipFile(false);
|
||||
return doc;
|
||||
}
|
||||
|
||||
@ -77,6 +123,7 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
||||
if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
|
||||
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
||||
doc.getDefaultStorageOptions().setCompressionEnabled(true);
|
||||
doc.getDecalRegistry().setIsZipFile(true);
|
||||
return doc;
|
||||
} else if ( entry.getName().matches(".*\\.[rR][kK][tT]$")) {
|
||||
OpenRocketDocument doc = loadFromStream(in, motorFinder);
|
||||
@ -91,7 +138,9 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
||||
if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
|
||||
match++;
|
||||
if (match == OPENROCKET_SIGNATURE.length) {
|
||||
return loadUsing(source, openRocketLoader, motorFinder);
|
||||
OpenRocketDocument doc = loadUsing(openRocketLoader, source, motorFinder);
|
||||
doc.getDecalRegistry().setIsZipFile(false);
|
||||
return doc;
|
||||
}
|
||||
} else {
|
||||
match = 0;
|
||||
@ -100,12 +149,14 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
|
||||
|
||||
byte[] typeIdentifier = ArrayUtils.copyOf(buffer, ROCKSIM_SIGNATURE.length);
|
||||
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.");
|
||||
}
|
||||
|
||||
private OpenRocketDocument loadUsing(InputStream source, RocketLoader loader, MotorFinder motorFinder)
|
||||
private OpenRocketDocument loadUsing(RocketLoader loader, InputStream source, MotorFinder motorFinder)
|
||||
throws RocketLoadException {
|
||||
warnings.clear();
|
||||
OpenRocketDocument doc = loader.load(source, motorFinder);
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.sf.openrocket.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
@ -8,8 +7,6 @@ import net.sf.openrocket.document.OpenRocketDocument;
|
||||
|
||||
public interface RocketLoader {
|
||||
|
||||
public OpenRocketDocument load(File source, MotorFinder motorFinder) throws RocketLoadException;
|
||||
|
||||
public OpenRocketDocument load(InputStream source, MotorFinder motorFinder) throws RocketLoadException;
|
||||
|
||||
public WarningSet getWarnings();
|
||||
|
@ -36,7 +36,7 @@ public abstract class RocketSaver {
|
||||
throws IOException {
|
||||
OutputStream s = new BufferedOutputStream(new FileOutputStream(dest));
|
||||
try {
|
||||
save(s, document, options);
|
||||
save(dest.getName(), s, document, options);
|
||||
} finally {
|
||||
s.close();
|
||||
}
|
||||
@ -50,8 +50,8 @@ public abstract class RocketSaver {
|
||||
* @param doc the document to save.
|
||||
* @throws IOException in case of an I/O error.
|
||||
*/
|
||||
public final void save(OutputStream dest, OpenRocketDocument doc) throws IOException {
|
||||
save(dest, doc, doc.getDefaultStorageOptions());
|
||||
public final void save(String fileName, OutputStream dest, OpenRocketDocument doc) throws IOException {
|
||||
save(fileName, dest, doc, doc.getDefaultStorageOptions());
|
||||
}
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ public abstract class RocketSaver {
|
||||
* @param options the storage options.
|
||||
* @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;
|
||||
|
||||
|
||||
|
@ -1,17 +1,26 @@
|
||||
package net.sf.openrocket.file.openrocket;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
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.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.Simulation;
|
||||
import net.sf.openrocket.document.StorageOptions;
|
||||
@ -69,7 +78,126 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
private Writer dest;
|
||||
|
||||
@Override
|
||||
public void save(OutputStream output, OpenRocketDocument document, StorageOptions options)
|
||||
public void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options)
|
||||
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");
|
||||
@ -168,6 +296,8 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
|
||||
long size = 0;
|
||||
|
||||
// FIXME - estimate decals
|
||||
|
||||
// Size per component
|
||||
int componentCount = 0;
|
||||
Rocket rocket = doc.getRocket();
|
||||
@ -224,6 +354,9 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
*/
|
||||
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:
|
||||
* - saving designs using ComponentPrests
|
||||
* - recovery device deployment on lower stage separation
|
||||
@ -240,6 +373,13 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
* 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)
|
||||
for (RocketComponent c : document.getRocket()) {
|
||||
if (c.getPresetComponent() != null) {
|
||||
|
@ -13,6 +13,8 @@ import java.util.regex.Pattern;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.Warning;
|
||||
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.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
@ -166,7 +168,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
|
||||
class DocumentConfig {
|
||||
|
||||
/* 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.
|
||||
@ -744,6 +746,7 @@ class DatatypeHandler extends AbstractElementHandler {
|
||||
}
|
||||
|
||||
class CustomExpressionHandler extends AbstractElementHandler {
|
||||
@SuppressWarnings("unused")
|
||||
private final DocumentLoadingContext context;
|
||||
private final OpenRocketContentHandler contentHandler;
|
||||
public CustomExpression currentExpression;
|
||||
@ -854,6 +857,9 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
||||
if (element.equals("subcomponents")) {
|
||||
return new ComponentHandler(component, context);
|
||||
}
|
||||
if ( element.equals("appearance")) {
|
||||
return new AppearanceHandler(component,context);
|
||||
}
|
||||
if (element.equals("motormount")) {
|
||||
if (!(component instanceof MotorMount)) {
|
||||
warnings.add(Warning.fromString("Illegal component defined as motor mount."));
|
||||
@ -885,7 +891,8 @@ class ComponentParameterHandler extends AbstractElementHandler {
|
||||
String content, WarningSet warnings) {
|
||||
|
||||
if (element.equals("subcomponents") || element.equals("motormount") ||
|
||||
element.equals("finpoints") || element.equals("motorconfiguration")) {
|
||||
element.equals("finpoints") || element.equals("motorconfiguration") ||
|
||||
element.equals("appearance")) {
|
||||
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
|
||||
|
@ -5,6 +5,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
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.l10n.Translator;
|
||||
import net.sf.openrocket.material.Material;
|
||||
@ -18,9 +21,9 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
import net.sf.openrocket.util.Color;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
import net.sf.openrocket.util.LineStyle;
|
||||
|
||||
|
||||
public class RocketComponentSaver {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
@ -38,14 +41,36 @@ public class RocketComponentSaver {
|
||||
"\" 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
|
||||
if (!(c instanceof Rocket || c instanceof ComponentAssembly)) {
|
||||
Color color = c.getColor();
|
||||
if (color != null) {
|
||||
elements.add("<color red=\"" + color.getRed() + "\" green=\"" + color.getGreen()
|
||||
+ "\" blue=\"" + color.getBlue() + "\"/>");
|
||||
}
|
||||
emitColor("color", elements, color);
|
||||
|
||||
LineStyle style = c.getLineStyle();
|
||||
if (style != null) {
|
||||
@ -169,4 +194,12 @@ public class RocketComponentSaver {
|
||||
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;
|
||||
|
||||
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.StorageOptions;
|
||||
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.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.
|
||||
*/
|
||||
@ -55,7 +56,7 @@ public class RocksimSaver extends RocketSaver {
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
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
|
||||
//so I can look in it's directory
|
||||
}
|
||||
setImage(f.toURI().toURL());
|
||||
setImage(value);
|
||||
}
|
||||
} else if ("repeat".equals(name)) {
|
||||
repeat = "1".equals(value);
|
||||
@ -136,6 +136,23 @@ public class RockSimAppearanceBuilder extends AppearanceBuilder {
|
||||
}
|
||||
|
||||
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(")", "");
|
||||
String ss[] = s.split(",");
|
||||
|
@ -5,8 +5,6 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.EventObject;
|
||||
|
||||
import javax.swing.JButton;
|
||||
@ -233,25 +231,12 @@ public class AppearancePanel extends JPanel {
|
||||
choose.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
URL u = ab.getImage();
|
||||
File current = lastImageDir;
|
||||
if (u != null && u.getProtocol().equals("file")) {
|
||||
try {
|
||||
current = new File(u.toURI()).getParentFile();
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
lastImageDir = current;
|
||||
|
||||
JFileChooser fc = new JFileChooser(current);
|
||||
if (fc.showOpenDialog(AppearancePanel.this) == JFileChooser.APPROVE_OPTION) {
|
||||
try {
|
||||
ab.setImage(fc.getSelectedFile().toURI().toURL());
|
||||
} catch (MalformedURLException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
ab.setImage(fc.getSelectedFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,10 @@ import net.sf.openrocket.util.Color;
|
||||
public class FigureRenderStrategy extends RenderStrategy {
|
||||
private final float[] color = new float[4];
|
||||
|
||||
public FigureRenderStrategy() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDrawn(RocketComponent c) {
|
||||
return true;
|
||||
|
@ -1,8 +1,7 @@
|
||||
package net.sf.openrocket.gui.figure3d;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -14,26 +13,34 @@ import javax.media.opengl.GLProfile;
|
||||
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
||||
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.Decal;
|
||||
import net.sf.openrocket.document.DecalRegistry;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
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 {
|
||||
|
||||
private final float[] colorBlack = { 0, 0, 0, 1 };
|
||||
private final float[] color = new float[4];
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
|
||||
private final DecalRegistry decalLoader;
|
||||
private boolean needClearCache = false;
|
||||
private Map<URI, Texture> oldTexCache = new HashMap<URI, Texture>();
|
||||
private Map<URI, Texture> texCache = new HashMap<URI, Texture>();
|
||||
private Map<String, Texture> oldTexCache = new HashMap<String, Texture>();
|
||||
private Map<String, Texture> texCache = new HashMap<String, Texture>();
|
||||
|
||||
public RealisticRenderStrategy(OpenRocketDocument document) {
|
||||
super(document);
|
||||
this.decalLoader = document.getDecalRegistry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFigure() {
|
||||
@ -42,8 +49,8 @@ public class RealisticRenderStrategy extends RenderStrategy {
|
||||
|
||||
@Override
|
||||
public void init(GLAutoDrawable drawable) {
|
||||
oldTexCache = new HashMap<URI,Texture>();
|
||||
texCache = new HashMap<URI,Texture>();
|
||||
oldTexCache = new HashMap<String,Texture>();
|
||||
texCache = new HashMap<String,Texture>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -138,46 +145,40 @@ public class RealisticRenderStrategy extends RenderStrategy {
|
||||
|
||||
private void clearCaches(GL2 gl) {
|
||||
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());
|
||||
if (e.getValue() != null)
|
||||
e.getValue().destroy(gl);
|
||||
}
|
||||
oldTexCache = texCache;
|
||||
texCache = new HashMap<URI, Texture>();
|
||||
texCache = new HashMap<String, Texture>();
|
||||
}
|
||||
|
||||
private Texture getTexture(Decal t) {
|
||||
URL url = t.getImageURL();
|
||||
URI uri; // NEVER use a URL as a key!
|
||||
try {
|
||||
uri = url.toURI();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
String imageName = t.getImage();
|
||||
|
||||
// Return the Cached value if available
|
||||
if (texCache.containsKey(uri))
|
||||
return texCache.get(uri);
|
||||
if (texCache.containsKey(imageName))
|
||||
return texCache.get(imageName);
|
||||
|
||||
// If the texture is in the Old Cache, save it.
|
||||
if (oldTexCache.containsKey(uri)) {
|
||||
texCache.put(uri, oldTexCache.get(uri));
|
||||
oldTexCache.remove(uri);
|
||||
return texCache.get(uri);
|
||||
if (oldTexCache.containsKey(imageName)) {
|
||||
texCache.put(imageName, oldTexCache.get(imageName));
|
||||
oldTexCache.remove(imageName);
|
||||
return texCache.get(imageName);
|
||||
}
|
||||
|
||||
// Otherwise load it.
|
||||
Texture tex = null;
|
||||
try {
|
||||
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);
|
||||
} catch (Throwable e) {
|
||||
log.error("Error loading Texture", e);
|
||||
}
|
||||
texCache.put(uri, tex);
|
||||
texCache.put(imageName, tex);
|
||||
|
||||
return tex;
|
||||
|
||||
|
@ -3,9 +3,17 @@ package net.sf.openrocket.gui.figure3d;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.GLAutoDrawable;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
|
||||
public abstract class RenderStrategy {
|
||||
|
||||
protected final OpenRocketDocument document;
|
||||
|
||||
public RenderStrategy( OpenRocketDocument document ) {
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public abstract boolean isDrawn(RocketComponent c);
|
||||
|
||||
public abstract boolean isDrawnTransparent(RocketComponent c);
|
||||
|
@ -31,6 +31,7 @@ import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.gui.figureelements.CGCaret;
|
||||
import net.sf.openrocket.gui.figureelements.CPCaret;
|
||||
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 final int CARET_SIZE = 20;
|
||||
|
||||
private OpenRocketDocument document;
|
||||
private Configuration configuration;
|
||||
private GLCanvas canvas;
|
||||
|
||||
@ -87,7 +89,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
|
||||
RocketRenderer rr = new RocketRenderer();
|
||||
|
||||
public RocketFigure3d(Configuration config) {
|
||||
public RocketFigure3d(OpenRocketDocument document, Configuration config) {
|
||||
this.document = document;
|
||||
this.configuration = config;
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
@ -627,7 +630,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
if ( t == TYPE_FIGURE ){
|
||||
rr.setRenderStrategy(new FigureRenderStrategy());
|
||||
} else {
|
||||
rr.setRenderStrategy(new RealisticRenderStrategy());
|
||||
rr.setRenderStrategy(new RealisticRenderStrategy(document));
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public class BasicFrame extends JFrame {
|
||||
/**
|
||||
* 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();
|
||||
|
||||
|
@ -164,7 +164,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
||||
|
||||
// Create figure and custom scroll pane
|
||||
figure = new RocketFigure(configuration);
|
||||
figure3d = new RocketFigure3d(configuration);
|
||||
figure3d = new RocketFigure3d(document, configuration);
|
||||
|
||||
figureHolder = new JPanel(new BorderLayout());
|
||||
|
||||
|
@ -12,7 +12,7 @@ import javax.swing.SwingWorker;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
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.startup.Application;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
@ -28,22 +28,22 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
|
||||
|
||||
private final File file;
|
||||
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.stream = null;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
|
||||
public OpenFileWorker(InputStream stream, RocketLoader loader) {
|
||||
public OpenFileWorker(InputStream stream, GeneralRocketLoader loader) {
|
||||
this.stream = stream;
|
||||
this.file = null;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public RocketLoader getRocketLoader() {
|
||||
public GeneralRocketLoader getRocketLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
|
||||
is = new ProgressInputStream(is);
|
||||
|
||||
try {
|
||||
return loader.load(is, new DatabaseMotorFinder());
|
||||
return loader.load(is, file, new DatabaseMotorFinder());
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
|
@ -41,8 +41,10 @@ public class SaveFileWorker extends SwingWorker<Void, Void> {
|
||||
|
||||
};
|
||||
|
||||
String rawFilename = file.getName();
|
||||
|
||||
try {
|
||||
saver.save(os, document);
|
||||
saver.save(rawFilename, os, document);
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
|
@ -1,8 +1,13 @@
|
||||
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.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -91,7 +96,7 @@ public class IntegrationTest extends BaseTestCase {
|
||||
GeneralRocketLoader loader = new GeneralRocketLoader();
|
||||
InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
|
||||
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();
|
||||
|
||||
undoAction = UndoRedoAction.newUndoAction(document);
|
||||
|
Loading…
x
Reference in New Issue
Block a user