diff --git a/engine/src/blender/com/jme3/asset/BlenderKey.java b/engine/src/blender/com/jme3/asset/BlenderKey.java index 86311aae9..b45b15278 100644 --- a/engine/src/blender/com/jme3/asset/BlenderKey.java +++ b/engine/src/blender/com/jme3/asset/BlenderKey.java @@ -65,748 +65,785 @@ import com.jme3.texture.Texture; */ public class BlenderKey extends ModelKey { - protected static final int DEFAULT_FPS = 25; - /** - * Animation definitions. The key is the object name that owns the animation. The value is a map between animation - * name and its start and stop frames. Blender stores a pointer for animation within object. Therefore one object - * can only have one animation at the time. We want to be able to switch between animations for one object so we - * need to map the object name to animation names the object will use. - */ - protected Map> animations; - /** - * FramesPerSecond parameter describe how many frames there are in each second. It allows to calculate the time - * between the frames. - */ - protected int fps = DEFAULT_FPS; - /** Width of generated textures (in pixels). */ - protected int generatedTextureWidth = 20; - /** Height of generated textures (in pixels). */ - protected int generatedTextureHeight = 20; - /** Depth of generated textures (in pixels). */ - protected int generatedTextureDepth = 20; - /** - * This variable is a bitwise flag of FeatureToLoad interface values; By default everything is being loaded. - */ - protected int featuresToLoad = FeaturesToLoad.ALL; - /** The root path for all the assets. */ - protected String assetRootPath; - /** This variable indicate if Y axis is UP axis. If not then Z is up. By default set to true. */ - protected boolean fixUpAxis = true; - /** - * The name of world settings that the importer will use. If not set or specified name does not occur in the file - * then the first world settings in the file will be used. - */ - protected String usedWorld; - /** - * User's default material that is set fo objects that have no material definition in blender. The default value is - * null. If the value is null the importer will use its own default material (gray color - like in blender). - */ - protected Material defaultMaterial; - /** Face cull mode. By default it is disabled. */ - protected FaceCullMode faceCullMode = FaceCullMode.Off; - /** - * Variable describes which layers will be loaded. N-th bit set means N-th layer will be loaded. - * If set to -1 then the current layer will be loaded. - */ - protected int layersToLoad = -1; - - /** - * Constructor used by serialization mechanisms. - */ - public BlenderKey() { - } - - /** - * Constructor. Creates a key for the given file name. - * @param name - * the name (path) of a file - */ - public BlenderKey(String name) { - super(name); - } - - /** - * This method adds an animation definition. If a definition already eixists in the key then it is replaced. - * @param objectName - * the name of animation's owner - * @param name - * the name of the animation - * @param start - * the start frame of the animation - * @param stop - * the stop frame of the animation - */ - public synchronized void addAnimation(String objectName, String name, int start, int stop) { - if (objectName == null) { - throw new IllegalArgumentException("Object name cannot be null!"); - } - if (name == null) { - throw new IllegalArgumentException("Animation name cannot be null!"); - } - if (start > stop) { - throw new IllegalArgumentException("Start frame cannot be greater than stop frame!"); - } - if (animations == null) { - animations = new HashMap>(); - animations.put(objectName, new HashMap()); - } - Map objectAnimations = animations.get(objectName); - if (objectAnimations == null) { - objectAnimations = new HashMap(); - animations.put(objectName, objectAnimations); - } - objectAnimations.put(name, new int[]{start, stop}); - } - - /** - * This method returns the animation frames boundaries. - * @param objectName - * the name of animation's owner - * @param name - * animation name - * @return animation frame boundaries in a table [start, stop] or null if animation of the given name does not - * exists - */ - public int[] getAnimationFrames(String objectName, String name) { - Map objectAnimations = animations == null ? null : animations.get(objectName); - int[] frames = objectAnimations == null ? null : objectAnimations.get(name); - return frames == null ? null : frames.clone(); - } - - /** - * This method returns the animation names for the given object name. - * @param objectName - * the name of the object - * @return an array of animations for this object - */ - public Set getAnimationNames(String objectName) { - Map objectAnimations = animations == null ? null : animations.get(objectName); - return objectAnimations == null ? null : objectAnimations.keySet(); - } - - /** - * This method returns the animations map. - * The key is the animated spatial name. The value is a map where the key - * is the animation name and the value is 2-element array of int that has - * start and stop frame of the animation. - * @return the animations map - */ - public Map> getAnimations() { - return animations; - } - - /** - * This method returns frames per second amount. The default value is BlenderKey.DEFAULT_FPS = 25. - * @return the frames per second amount - */ - public int getFps() { - return fps; - } - - /** - * This method sets frames per second amount. - * @param fps - * the frames per second amount - */ - public void setFps(int fps) { - this.fps = fps; - } - - /** - * This method sets the width of generated texture (in pixels). By default the value is 140 px. - * @param generatedTextureWidth - * the width of generated texture - */ - public void setGeneratedTextureWidth(int generatedTextureWidth) { - this.generatedTextureWidth = generatedTextureWidth; - } - - /** - * This method returns the width of generated texture (in pixels). By default the value is 140 px. - * @return the width of generated texture - */ - public int getGeneratedTextureWidth() { - return generatedTextureWidth; - } - - /** - * This method sets the height of generated texture (in pixels). By default the value is 20 px. - * @param generatedTextureHeight - * the height of generated texture - */ - public void setGeneratedTextureHeight(int generatedTextureHeight) { - this.generatedTextureHeight = generatedTextureHeight; - } - - /** - * This method returns the height of generated texture (in pixels). By default the value is 20 px. - * @return the height of generated texture - */ - public int getGeneratedTextureHeight() { - return generatedTextureHeight; - } - - /** - * This method returns the depth of generated texture (in pixels). By default the value is 20 px. - * @return the depth of generated texture - */ - public int getGeneratedTextureDepth() { - return generatedTextureDepth; - } - - /** - * This method returns the face cull mode. - * @return the face cull mode - */ - public FaceCullMode getFaceCullMode() { - return faceCullMode; - } - - /** - * This method sets the face cull mode. - * @param faceCullMode - * the face cull mode - */ - public void setFaceCullMode(FaceCullMode faceCullMode) { - this.faceCullMode = faceCullMode; - } - - /** - * This method sets layers to be loaded. - * @param layersToLoad layers to be loaded - */ - public void setLayersToLoad(int layersToLoad) { - this.layersToLoad = layersToLoad; - } - - /** - * This method returns layers to be loaded. - * @return layers to be loaded - */ - public int getLayersToLoad() { - return layersToLoad; - } - - /** - * This method sets the asset root path. - * @param assetRootPath - * the assets root path - */ - public void setAssetRootPath(String assetRootPath) { - this.assetRootPath = assetRootPath; - } - - /** - * This method returns the asset root path. - * @return the asset root path - */ - public String getAssetRootPath() { - return assetRootPath; - } - - /** - * This method adds features to be loaded. - * @param featuresToLoad - * bitwise flag of FeaturesToLoad interface values - */ - public void includeInLoading(int featuresToLoad) { - this.featuresToLoad |= featuresToLoad; - } - - /** - * This method removes features from being loaded. - * @param featuresToLoad - * bitwise flag of FeaturesToLoad interface values - */ - public void excludeFromLoading(int featuresNotToLoad) { - this.featuresToLoad &= ~featuresNotToLoad; - } - - /** - * This method returns bitwise value of FeaturesToLoad interface value. It describes features that will be loaded by - * the blender file loader. - * @return features that will be loaded by the blender file loader - */ - public int getFeaturesToLoad() { - return featuresToLoad; - } - - /** - * This method creates an object where loading results will be stores. Only those features will be allowed to store - * that were specified by features-to-load flag. - * @return an object to store loading results - */ - public LoadingResults prepareLoadingResults() { - return new LoadingResults(featuresToLoad); - } - - /** - * This method sets the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By default Y - * is up axis. - * @param fixUpAxis - * the up axis state variable - */ - public void setFixUpAxis(boolean fixUpAxis) { - this.fixUpAxis = fixUpAxis; - } - - /** - * This method returns the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By - * default Y is up axis. - * @return the up axis state variable - */ - public boolean isFixUpAxis() { - return fixUpAxis; - } - - /** - * This mehtod sets the name of the WORLD data block taht should be used during file loading. By default the name is - * not set. If no name is set or the given name does not occur in the file - the first WORLD data block will be used - * during loading (assumin any exists in the file). - * @param usedWorld - * the name of the WORLD block used during loading - */ - public void setUsedWorld(String usedWorld) { - this.usedWorld = usedWorld; - } - - /** - * This mehtod returns the name of the WORLD data block taht should be used during file loading. - * @return the name of the WORLD block used during loading - */ - public String getUsedWorld() { - return usedWorld; - } - - /** - * This method sets the default material for objects. - * @param defaultMaterial - * the default material - */ - public void setDefaultMaterial(Material defaultMaterial) { - this.defaultMaterial = defaultMaterial; - } - - /** - * This method returns the default material. - * @return the default material - */ - public Material getDefaultMaterial() { - return defaultMaterial; - } - - @Override - public void write(JmeExporter e) throws IOException { - super.write(e); - OutputCapsule oc = e.getCapsule(this); - //saving animations - oc.write(animations == null ? 0 : animations.size(), "anim-size", 0); - if (animations != null) { - int objectCounter = 0; - for (Entry> animEntry : animations.entrySet()) { - oc.write(animEntry.getKey(), "animated-object-" + objectCounter, null); - int animsAmount = animEntry.getValue().size(); - oc.write(animsAmount, "anims-amount-" + objectCounter, 0); - for (Entry animsEntry : animEntry.getValue().entrySet()) { - oc.write(animsEntry.getKey(), "anim-name-" + objectCounter, null); - oc.write(animsEntry.getValue(), "anim-frames-" + objectCounter, null); - } - ++objectCounter; - } - } - //saving the rest of the data - oc.write(fps, "fps", DEFAULT_FPS); - oc.write(featuresToLoad, "features-to-load", FeaturesToLoad.ALL); - oc.write(assetRootPath, "asset-root-path", null); - oc.write(fixUpAxis, "fix-up-axis", true); - oc.write(usedWorld, "used-world", null); - oc.write(defaultMaterial, "default-material", null); - oc.write(faceCullMode, "face-cull-mode", FaceCullMode.Off); - oc.write(layersToLoad, "layers-to-load", -1); - } - - @Override - public void read(JmeImporter e) throws IOException { - super.read(e); - InputCapsule ic = e.getCapsule(this); - //reading animations - int animSize = ic.readInt("anim-size", 0); - if (animSize > 0) { - if (animations == null) { - animations = new HashMap>(animSize); - } else { - animations.clear(); - } - for (int i = 0; i < animSize; ++i) { - String objectName = ic.readString("animated-object-" + i, null); - int animationsAmount = ic.readInt("anims-amount-" + i, 0); - Map objectAnimations = new HashMap(animationsAmount); - for (int j = 0; j < animationsAmount; ++j) { - String animName = ic.readString("anim-name-" + i, null); - int[] animFrames = ic.readIntArray("anim-frames-" + i, null); - objectAnimations.put(animName, animFrames); - } - animations.put(objectName, objectAnimations); - } - } - - //reading the rest of the data - fps = ic.readInt("fps", DEFAULT_FPS); - featuresToLoad = ic.readInt("features-to-load", FeaturesToLoad.ALL); - assetRootPath = ic.readString("asset-root-path", null); - fixUpAxis = ic.readBoolean("fix-up-axis", true); - usedWorld = ic.readString("used-world", null); - defaultMaterial = (Material) ic.readSavable("default-material", null); - faceCullMode = ic.readEnum("face-cull-mode", FaceCullMode.class, FaceCullMode.Off); - layersToLoad = ic.readInt("layers-to=load", -1); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + (animations == null ? 0 : animations.hashCode()); - result = prime * result + (assetRootPath == null ? 0 : assetRootPath.hashCode()); - result = prime * result + (defaultMaterial == null ? 0 : defaultMaterial.hashCode()); - result = prime * result + (faceCullMode == null ? 0 : faceCullMode.hashCode()); - result = prime * result + featuresToLoad; - result = prime * result + (fixUpAxis ? 1231 : 1237); - result = prime * result + fps; - result = prime * result + generatedTextureHeight; - result = prime * result + generatedTextureWidth; - result = prime * result + layersToLoad; - result = prime * result + (usedWorld == null ? 0 : usedWorld.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (this.getClass() != obj.getClass()) { - return false; - } - BlenderKey other = (BlenderKey) obj; - if (animations == null) { - if (other.animations != null) { - return false; - } - } else if (!animations.equals(other.animations)) { - return false; - } - if (assetRootPath == null) { - if (other.assetRootPath != null) { - return false; - } - } else if (!assetRootPath.equals(other.assetRootPath)) { - return false; - } - if (defaultMaterial == null) { - if (other.defaultMaterial != null) { - return false; - } - } else if (!defaultMaterial.equals(other.defaultMaterial)) { - return false; - } - if (faceCullMode != other.faceCullMode) { - return false; - } - if (featuresToLoad != other.featuresToLoad) { - return false; - } - if (fixUpAxis != other.fixUpAxis) { - return false; - } - if (fps != other.fps) { - return false; - } - if (generatedTextureHeight != other.generatedTextureHeight) { - return false; - } - if (generatedTextureWidth != other.generatedTextureWidth) { - return false; - } - if (layersToLoad != other.layersToLoad) { - return false; - } - if (usedWorld == null) { - if (other.usedWorld != null) { - return false; - } - } else if (!usedWorld.equals(other.usedWorld)) { - return false; - } - return true; - } - - /** - * This interface describes the features of the scene that are to be loaded. - * @author Marcin Roguski (Kaelthas) - */ - public static interface FeaturesToLoad { - - int SCENES = 0x0000FFFF; - int OBJECTS = 0x0000000B; - int ANIMATIONS = 0x00000004; - int MATERIALS = 0x00000003; - int TEXTURES = 0x00000001; - int CAMERAS = 0x00000020; - int LIGHTS = 0x00000010; - int ALL = 0xFFFFFFFF; - } - - /** - * This class holds the loading results according to the given loading flag. - * @author Marcin Roguski (Kaelthas) - */ - public static class LoadingResults extends Spatial { - - /** Bitwise mask of features that are to be loaded. */ - private final int featuresToLoad; - /** The scenes from the file. */ - private List scenes; - /** Objects from all scenes. */ - private List objects; - /** Materials from all objects. */ - private List materials; - /** Textures from all objects. */ - private List textures; - /** Animations of all objects. */ - private List animations; - /** All cameras from the file. */ - private List cameras; - /** All lights from the file. */ - private List lights; - - /** - * Private constructor prevents users to create an instance of this class from outside the - * @param featuresToLoad - * bitwise mask of features that are to be loaded - * @see FeaturesToLoad FeaturesToLoad - */ - private LoadingResults(int featuresToLoad) { - this.featuresToLoad = featuresToLoad; - if ((featuresToLoad & FeaturesToLoad.SCENES) != 0) { - scenes = new ArrayList(); - } - if ((featuresToLoad & FeaturesToLoad.OBJECTS) != 0) { - objects = new ArrayList(); - if ((featuresToLoad & FeaturesToLoad.MATERIALS) != 0) { - materials = new ArrayList(); - if ((featuresToLoad & FeaturesToLoad.TEXTURES) != 0) { - textures = new ArrayList(); - } - } - if ((featuresToLoad & FeaturesToLoad.ANIMATIONS) != 0) { - animations = new ArrayList(); - } - } - if ((featuresToLoad & FeaturesToLoad.CAMERAS) != 0) { - cameras = new ArrayList(); - } - if ((featuresToLoad & FeaturesToLoad.LIGHTS) != 0) { - lights = new ArrayList(); - } - } - - /** - * This method returns a bitwise flag describing what features of the blend file will be included in the result. - * @return bitwise mask of features that are to be loaded - * @see FeaturesToLoad FeaturesToLoad - */ - public int getLoadedFeatures() { - return featuresToLoad; - } - - /** - * This method adds a scene to the result set. - * @param scene - * scene to be added to the result set - */ - public void addScene(Node scene) { - if (scenes != null) { - scenes.add(scene); - } - } - - /** - * This method adds an object to the result set. - * @param object - * object to be added to the result set - */ - public void addObject(Node object) { - if (objects != null) { - objects.add(object); - } - } - - /** - * This method adds a material to the result set. - * @param material - * material to be added to the result set - */ - public void addMaterial(Material material) { - if (materials != null) { - materials.add(material); - } - } - - /** - * This method adds a texture to the result set. - * @param texture - * texture to be added to the result set - */ - public void addTexture(Texture texture) { - if (textures != null) { - textures.add(texture); - } - } - - /** - * This method adds a camera to the result set. - * @param camera - * camera to be added to the result set - */ - public void addCamera(Camera camera) { - if (cameras != null) { - cameras.add(camera); - } - } - - /** - * This method adds a light to the result set. - * @param light - * light to be added to the result set - */ - @Override - public void addLight(Light light) { - if (lights != null) { - lights.add(light); - } - } - - /** - * This method returns all loaded scenes. - * @return all loaded scenes - */ - public List getScenes() { - return scenes; - } - - /** - * This method returns all loaded objects. - * @return all loaded objects - */ - public List getObjects() { - return objects; - } - - /** - * This method returns all loaded materials. - * @return all loaded materials - */ - public List getMaterials() { - return materials; - } - - /** - * This method returns all loaded textures. - * @return all loaded textures - */ - public List getTextures() { - return textures; - } - - /** - * This method returns all loaded animations. - * @return all loaded animations - */ - public List getAnimations() { - return animations; - } - - /** - * This method returns all loaded cameras. - * @return all loaded cameras - */ - public List getCameras() { - return cameras; - } - - /** - * This method returns all loaded lights. - * @return all loaded lights - */ - public List getLights() { - return lights; - } - - @Override - public int collideWith(Collidable other, CollisionResults results) throws UnsupportedCollisionException { - return 0; - } - - @Override - public void updateModelBound() { - } - - @Override - public void setModelBound(BoundingVolume modelBound) { - } - - @Override - public int getVertexCount() { - return 0; - } - - @Override - public int getTriangleCount() { - return 0; - } - - @Override - public Spatial deepClone() { - return null; - } - - @Override - public void depthFirstTraversal(SceneGraphVisitor visitor) { - } - - @Override - protected void breadthFirstTraversal(SceneGraphVisitor visitor, Queue queue) { - } - } - - /** - * The WORLD file block contains various data that could be added to the scene. The contained data includes: ambient - * light. - * @author Marcin Roguski (Kaelthas) - */ - public static class WorldData { - - /** The ambient light. */ - private AmbientLight ambientLight; - - /** - * This method returns the world's ambient light. - * @return the world's ambient light - */ - public AmbientLight getAmbientLight() { - return ambientLight; - } - - /** - * This method sets the world's ambient light. - * @param ambientLight - * the world's ambient light - */ - public void setAmbientLight(AmbientLight ambientLight) { - this.ambientLight = ambientLight; - } - } + protected static final int DEFAULT_FPS = 25; + /** + * Animation definitions. The key is the object name that owns the animation. The value is a map between animation + * name and its start and stop frames. Blender stores a pointer for animation within object. Therefore one object + * can only have one animation at the time. We want to be able to switch between animations for one object so we + * need to map the object name to animation names the object will use. + */ + protected Map> animations; + /** + * FramesPerSecond parameter describe how many frames there are in each second. It allows to calculate the time + * between the frames. + */ + protected int fps = DEFAULT_FPS; + /** Width of generated textures (in pixels). */ + protected int generatedTextureWidth = 20; + /** Height of generated textures (in pixels). */ + protected int generatedTextureHeight = 20; + /** Depth of generated textures (in pixels). */ + protected int generatedTextureDepth = 20; + /** + * This variable is a bitwise flag of FeatureToLoad interface values; By default everything is being loaded. + */ + protected int featuresToLoad = FeaturesToLoad.ALL; + /** This variable determines if assets that are not linked to the objects should be loaded. */ + protected boolean loadUnlinkedAssets; + /** The root path for all the assets. */ + protected String assetRootPath; + /** This variable indicate if Y axis is UP axis. If not then Z is up. By default set to true. */ + protected boolean fixUpAxis = true; + /** + * The name of world settings that the importer will use. If not set or specified name does not occur in the file + * then the first world settings in the file will be used. + */ + protected String usedWorld; + /** + * User's default material that is set fo objects that have no material definition in blender. The default value is + * null. If the value is null the importer will use its own default material (gray color - like in blender). + */ + protected Material defaultMaterial; + /** Face cull mode. By default it is disabled. */ + protected FaceCullMode faceCullMode = FaceCullMode.Off; + /** + * Variable describes which layers will be loaded. N-th bit set means N-th layer will be loaded. + * If set to -1 then the current layer will be loaded. + */ + protected int layersToLoad = -1; + + /** + * Constructor used by serialization mechanisms. + */ + public BlenderKey() {} + + /** + * Constructor. Creates a key for the given file name. + * @param name + * the name (path) of a file + */ + public BlenderKey(String name) { + super(name); + } + + /** + * This method adds an animation definition. If a definition already eixists in the key then it is replaced. + * @param objectName + * the name of animation's owner + * @param name + * the name of the animation + * @param start + * the start frame of the animation + * @param stop + * the stop frame of the animation + */ + public synchronized void addAnimation(String objectName, String name, int start, int stop) { + if (objectName == null) { + throw new IllegalArgumentException("Object name cannot be null!"); + } + if (name == null) { + throw new IllegalArgumentException("Animation name cannot be null!"); + } + if (start > stop) { + throw new IllegalArgumentException("Start frame cannot be greater than stop frame!"); + } + if (animations == null) { + animations = new HashMap>(); + animations.put(objectName, new HashMap()); + } + Map objectAnimations = animations.get(objectName); + if (objectAnimations == null) { + objectAnimations = new HashMap(); + animations.put(objectName, objectAnimations); + } + objectAnimations.put(name, new int[] { start, stop }); + } + + /** + * This method returns the animation frames boundaries. + * @param objectName + * the name of animation's owner + * @param name + * animation name + * @return animation frame boundaries in a table [start, stop] or null if animation of the given name does not + * exists + */ + public int[] getAnimationFrames(String objectName, String name) { + Map objectAnimations = animations == null ? null : animations.get(objectName); + int[] frames = objectAnimations == null ? null : objectAnimations.get(name); + return frames == null ? null : frames.clone(); + } + + /** + * This method returns the animation names for the given object name. + * @param objectName + * the name of the object + * @return an array of animations for this object + */ + public Set getAnimationNames(String objectName) { + Map objectAnimations = animations == null ? null : animations.get(objectName); + return objectAnimations == null ? null : objectAnimations.keySet(); + } + + /** + * This method returns the animations map. + * The key is the animated spatial name. The value is a map where the key + * is the animation name and the value is 2-element array of int that has + * start and stop frame of the animation. + * @return the animations map + */ + public Map> getAnimations() { + return animations; + } + + /** + * This method returns frames per second amount. The default value is BlenderKey.DEFAULT_FPS = 25. + * @return the frames per second amount + */ + public int getFps() { + return fps; + } + + /** + * This method sets frames per second amount. + * @param fps + * the frames per second amount + */ + public void setFps(int fps) { + this.fps = fps; + } + + /** + * This method sets the width of generated texture (in pixels). By default the value is 140 px. + * @param generatedTextureWidth + * the width of generated texture + */ + public void setGeneratedTextureWidth(int generatedTextureWidth) { + this.generatedTextureWidth = generatedTextureWidth; + } + + /** + * This method returns the width of generated texture (in pixels). By default the value is 140 px. + * @return the width of generated texture + */ + public int getGeneratedTextureWidth() { + return generatedTextureWidth; + } + + /** + * This method sets the height of generated texture (in pixels). By default the value is 20 px. + * @param generatedTextureHeight + * the height of generated texture + */ + public void setGeneratedTextureHeight(int generatedTextureHeight) { + this.generatedTextureHeight = generatedTextureHeight; + } + + /** + * This method returns the height of generated texture (in pixels). By default the value is 20 px. + * @return the height of generated texture + */ + public int getGeneratedTextureHeight() { + return generatedTextureHeight; + } + + /** + * This method returns the depth of generated texture (in pixels). By default the value is 20 px. + * @return the depth of generated texture + */ + public int getGeneratedTextureDepth() { + return generatedTextureDepth; + } + + /** + * This method returns the face cull mode. + * @return the face cull mode + */ + public FaceCullMode getFaceCullMode() { + return faceCullMode; + } + + /** + * This method sets the face cull mode. + * @param faceCullMode + * the face cull mode + */ + public void setFaceCullMode(FaceCullMode faceCullMode) { + this.faceCullMode = faceCullMode; + } + + /** + * This method sets layers to be loaded. + * @param layersToLoad + * layers to be loaded + */ + public void setLayersToLoad(int layersToLoad) { + this.layersToLoad = layersToLoad; + } + + /** + * This method returns layers to be loaded. + * @return layers to be loaded + */ + public int getLayersToLoad() { + return layersToLoad; + } + + /** + * This method sets the asset root path. + * @param assetRootPath + * the assets root path + */ + public void setAssetRootPath(String assetRootPath) { + this.assetRootPath = assetRootPath; + } + + /** + * This method returns the asset root path. + * @return the asset root path + */ + public String getAssetRootPath() { + return assetRootPath; + } + + /** + * This method adds features to be loaded. + * @param featuresToLoad + * bitwise flag of FeaturesToLoad interface values + */ + public void includeInLoading(int featuresToLoad) { + this.featuresToLoad |= featuresToLoad; + } + + /** + * This method removes features from being loaded. + * @param featuresToLoad + * bitwise flag of FeaturesToLoad interface values + */ + public void excludeFromLoading(int featuresNotToLoad) { + this.featuresToLoad &= ~featuresNotToLoad; + } + + /** + * This method returns bitwise value of FeaturesToLoad interface value. It describes features that will be loaded by + * the blender file loader. + * @return features that will be loaded by the blender file loader + */ + public int getFeaturesToLoad() { + return featuresToLoad; + } + + /** + * This method determines if unlinked assets should be loaded. + * If not then only objects on selected layers will be loaded and their assets if required. + * If yes then all assets will be loaded even if they are on inactive layers or are not linked + * to anything. + * @return true if unlinked assets should be loaded and false otherwise + */ + public boolean isLoadUnlinkedAssets() { + return loadUnlinkedAssets; + } + + /** + * This method sets if unlinked assets should be loaded. + * If not then only objects on selected layers will be loaded and their assets if required. + * If yes then all assets will be loaded even if they are on inactive layers or are not linked + * to anything. + * @param loadUnlinkedAssets + * true if unlinked assets should be loaded and false otherwise + */ + public void setLoadUnlinkedAssets(boolean loadUnlinkedAssets) { + this.loadUnlinkedAssets = loadUnlinkedAssets; + } + + /** + * This method creates an object where loading results will be stores. Only those features will be allowed to store + * that were specified by features-to-load flag. + * @return an object to store loading results + */ + public LoadingResults prepareLoadingResults() { + return new LoadingResults(featuresToLoad); + } + + /** + * This method sets the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By default Y + * is up axis. + * @param fixUpAxis + * the up axis state variable + */ + public void setFixUpAxis(boolean fixUpAxis) { + this.fixUpAxis = fixUpAxis; + } + + /** + * This method returns the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By + * default Y is up axis. + * @return the up axis state variable + */ + public boolean isFixUpAxis() { + return fixUpAxis; + } + + /** + * This mehtod sets the name of the WORLD data block taht should be used during file loading. By default the name is + * not set. If no name is set or the given name does not occur in the file - the first WORLD data block will be used + * during loading (assumin any exists in the file). + * @param usedWorld + * the name of the WORLD block used during loading + */ + public void setUsedWorld(String usedWorld) { + this.usedWorld = usedWorld; + } + + /** + * This mehtod returns the name of the WORLD data block taht should be used during file loading. + * @return the name of the WORLD block used during loading + */ + public String getUsedWorld() { + return usedWorld; + } + + /** + * This method sets the default material for objects. + * @param defaultMaterial + * the default material + */ + public void setDefaultMaterial(Material defaultMaterial) { + this.defaultMaterial = defaultMaterial; + } + + /** + * This method returns the default material. + * @return the default material + */ + public Material getDefaultMaterial() { + return defaultMaterial; + } + + @Override + public void write(JmeExporter e) throws IOException { + super.write(e); + OutputCapsule oc = e.getCapsule(this); + // saving animations + oc.write(animations == null ? 0 : animations.size(), "anim-size", 0); + if (animations != null) { + int objectCounter = 0; + for (Entry> animEntry : animations.entrySet()) { + oc.write(animEntry.getKey(), "animated-object-" + objectCounter, null); + int animsAmount = animEntry.getValue().size(); + oc.write(animsAmount, "anims-amount-" + objectCounter, 0); + for (Entry animsEntry : animEntry.getValue().entrySet()) { + oc.write(animsEntry.getKey(), "anim-name-" + objectCounter, null); + oc.write(animsEntry.getValue(), "anim-frames-" + objectCounter, null); + } + ++objectCounter; + } + } + // saving the rest of the data + oc.write(fps, "fps", DEFAULT_FPS); + oc.write(generatedTextureWidth, "generated-texture-width", 20); + oc.write(generatedTextureHeight, "generated-texture-height", 20); + oc.write(generatedTextureDepth, "generated-texture-depth", 20); + oc.write(featuresToLoad, "features-to-load", FeaturesToLoad.ALL); + oc.write(loadUnlinkedAssets, "load-unlinked-assets", false); + oc.write(assetRootPath, "asset-root-path", null); + oc.write(fixUpAxis, "fix-up-axis", true); + oc.write(usedWorld, "used-world", null); + oc.write(defaultMaterial, "default-material", null); + oc.write(faceCullMode, "face-cull-mode", FaceCullMode.Off); + oc.write(layersToLoad, "layers-to-load", -1); + } + + @Override + public void read(JmeImporter e) throws IOException { + super.read(e); + InputCapsule ic = e.getCapsule(this); + // reading animations + int animSize = ic.readInt("anim-size", 0); + if (animSize > 0) { + if (animations == null) { + animations = new HashMap>(animSize); + } else { + animations.clear(); + } + for (int i = 0; i < animSize; ++i) { + String objectName = ic.readString("animated-object-" + i, null); + int animationsAmount = ic.readInt("anims-amount-" + i, 0); + Map objectAnimations = new HashMap(animationsAmount); + for (int j = 0; j < animationsAmount; ++j) { + String animName = ic.readString("anim-name-" + i, null); + int[] animFrames = ic.readIntArray("anim-frames-" + i, null); + objectAnimations.put(animName, animFrames); + } + animations.put(objectName, objectAnimations); + } + } + + // reading the rest of the data + fps = ic.readInt("fps", DEFAULT_FPS); + generatedTextureWidth = ic.readInt("generated-texture-width", 20); + generatedTextureHeight = ic.readInt("generated-texture-height", 20); + generatedTextureDepth = ic.readInt("generated-texture-depth", 20); + featuresToLoad = ic.readInt("features-to-load", FeaturesToLoad.ALL); + loadUnlinkedAssets = ic.readBoolean("load-unlinked-assets", false); + assetRootPath = ic.readString("asset-root-path", null); + fixUpAxis = ic.readBoolean("fix-up-axis", true); + usedWorld = ic.readString("used-world", null); + defaultMaterial = (Material) ic.readSavable("default-material", null); + faceCullMode = ic.readEnum("face-cull-mode", FaceCullMode.class, FaceCullMode.Off); + layersToLoad = ic.readInt("layers-to=load", -1); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (animations == null ? 0 : animations.hashCode()); + result = prime * result + (assetRootPath == null ? 0 : assetRootPath.hashCode()); + result = prime * result + (defaultMaterial == null ? 0 : defaultMaterial.hashCode()); + result = prime * result + (faceCullMode == null ? 0 : faceCullMode.hashCode()); + result = prime * result + featuresToLoad; + result = prime * result + (fixUpAxis ? 1231 : 1237); + result = prime * result + fps; + result = prime * result + generatedTextureDepth; + result = prime * result + generatedTextureHeight; + result = prime * result + generatedTextureWidth; + result = prime * result + layersToLoad; + result = prime * result + (loadUnlinkedAssets ? 1231 : 1237); + result = prime * result + (usedWorld == null ? 0 : usedWorld.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (this.getClass() != obj.getClass()) { + return false; + } + BlenderKey other = (BlenderKey) obj; + if (animations == null) { + if (other.animations != null) { + return false; + } + } else if (!animations.equals(other.animations)) { + return false; + } + if (assetRootPath == null) { + if (other.assetRootPath != null) { + return false; + } + } else if (!assetRootPath.equals(other.assetRootPath)) { + return false; + } + if (defaultMaterial == null) { + if (other.defaultMaterial != null) { + return false; + } + } else if (!defaultMaterial.equals(other.defaultMaterial)) { + return false; + } + if (faceCullMode != other.faceCullMode) { + return false; + } + if (featuresToLoad != other.featuresToLoad) { + return false; + } + if (fixUpAxis != other.fixUpAxis) { + return false; + } + if (fps != other.fps) { + return false; + } + if (generatedTextureDepth != other.generatedTextureDepth) { + return false; + } + if (generatedTextureHeight != other.generatedTextureHeight) { + return false; + } + if (generatedTextureWidth != other.generatedTextureWidth) { + return false; + } + if (layersToLoad != other.layersToLoad) { + return false; + } + if (loadUnlinkedAssets != other.loadUnlinkedAssets) { + return false; + } + if (usedWorld == null) { + if (other.usedWorld != null) { + return false; + } + } else if (!usedWorld.equals(other.usedWorld)) { + return false; + } + return true; + } + + /** + * This interface describes the features of the scene that are to be loaded. + * @author Marcin Roguski (Kaelthas) + */ + public static interface FeaturesToLoad { + + int SCENES = 0x0000FFFF; + int OBJECTS = 0x0000000B; + int ANIMATIONS = 0x00000004; + int MATERIALS = 0x00000003; + int TEXTURES = 0x00000001; + int CAMERAS = 0x00000020; + int LIGHTS = 0x00000010; + int ALL = 0xFFFFFFFF; + } + + /** + * This class holds the loading results according to the given loading flag. + * @author Marcin Roguski (Kaelthas) + */ + public static class LoadingResults extends Spatial { + + /** Bitwise mask of features that are to be loaded. */ + private final int featuresToLoad; + /** The scenes from the file. */ + private List scenes; + /** Objects from all scenes. */ + private List objects; + /** Materials from all objects. */ + private List materials; + /** Textures from all objects. */ + private List textures; + /** Animations of all objects. */ + private List animations; + /** All cameras from the file. */ + private List cameras; + /** All lights from the file. */ + private List lights; + + /** + * Private constructor prevents users to create an instance of this class from outside the + * @param featuresToLoad + * bitwise mask of features that are to be loaded + * @see FeaturesToLoad FeaturesToLoad + */ + private LoadingResults(int featuresToLoad) { + this.featuresToLoad = featuresToLoad; + if ((featuresToLoad & FeaturesToLoad.SCENES) != 0) { + scenes = new ArrayList(); + } + if ((featuresToLoad & FeaturesToLoad.OBJECTS) != 0) { + objects = new ArrayList(); + if ((featuresToLoad & FeaturesToLoad.MATERIALS) != 0) { + materials = new ArrayList(); + if ((featuresToLoad & FeaturesToLoad.TEXTURES) != 0) { + textures = new ArrayList(); + } + } + if ((featuresToLoad & FeaturesToLoad.ANIMATIONS) != 0) { + animations = new ArrayList(); + } + } + if ((featuresToLoad & FeaturesToLoad.CAMERAS) != 0) { + cameras = new ArrayList(); + } + if ((featuresToLoad & FeaturesToLoad.LIGHTS) != 0) { + lights = new ArrayList(); + } + } + + /** + * This method returns a bitwise flag describing what features of the blend file will be included in the result. + * @return bitwise mask of features that are to be loaded + * @see FeaturesToLoad FeaturesToLoad + */ + public int getLoadedFeatures() { + return featuresToLoad; + } + + /** + * This method adds a scene to the result set. + * @param scene + * scene to be added to the result set + */ + public void addScene(Node scene) { + if (scenes != null) { + scenes.add(scene); + } + } + + /** + * This method adds an object to the result set. + * @param object + * object to be added to the result set + */ + public void addObject(Node object) { + if (objects != null) { + objects.add(object); + } + } + + /** + * This method adds a material to the result set. + * @param material + * material to be added to the result set + */ + public void addMaterial(Material material) { + if (materials != null) { + materials.add(material); + } + } + + /** + * This method adds a texture to the result set. + * @param texture + * texture to be added to the result set + */ + public void addTexture(Texture texture) { + if (textures != null) { + textures.add(texture); + } + } + + /** + * This method adds a camera to the result set. + * @param camera + * camera to be added to the result set + */ + public void addCamera(Camera camera) { + if (cameras != null) { + cameras.add(camera); + } + } + + /** + * This method adds a light to the result set. + * @param light + * light to be added to the result set + */ + @Override + public void addLight(Light light) { + if (lights != null) { + lights.add(light); + } + } + + /** + * This method returns all loaded scenes. + * @return all loaded scenes + */ + public List getScenes() { + return scenes; + } + + /** + * This method returns all loaded objects. + * @return all loaded objects + */ + public List getObjects() { + return objects; + } + + /** + * This method returns all loaded materials. + * @return all loaded materials + */ + public List getMaterials() { + return materials; + } + + /** + * This method returns all loaded textures. + * @return all loaded textures + */ + public List getTextures() { + return textures; + } + + /** + * This method returns all loaded animations. + * @return all loaded animations + */ + public List getAnimations() { + return animations; + } + + /** + * This method returns all loaded cameras. + * @return all loaded cameras + */ + public List getCameras() { + return cameras; + } + + /** + * This method returns all loaded lights. + * @return all loaded lights + */ + public List getLights() { + return lights; + } + + @Override + public int collideWith(Collidable other, CollisionResults results) throws UnsupportedCollisionException { + return 0; + } + + @Override + public void updateModelBound() {} + + @Override + public void setModelBound(BoundingVolume modelBound) {} + + @Override + public int getVertexCount() { + return 0; + } + + @Override + public int getTriangleCount() { + return 0; + } + + @Override + public Spatial deepClone() { + return null; + } + + @Override + public void depthFirstTraversal(SceneGraphVisitor visitor) {} + + @Override + protected void breadthFirstTraversal(SceneGraphVisitor visitor, Queue queue) {} + } + + /** + * The WORLD file block contains various data that could be added to the scene. The contained data includes: ambient + * light. + * @author Marcin Roguski (Kaelthas) + */ + public static class WorldData { + + /** The ambient light. */ + private AmbientLight ambientLight; + + /** + * This method returns the world's ambient light. + * @return the world's ambient light + */ + public AmbientLight getAmbientLight() { + return ambientLight; + } + + /** + * This method sets the world's ambient light. + * @param ambientLight + * the world's ambient light + */ + public void setAmbientLight(AmbientLight ambientLight) { + this.ambientLight = ambientLight; + } + } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java index 6ed96351f..bc5db85fa 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java @@ -153,7 +153,7 @@ public class BlenderLoader implements AssetLoader { } break; case FileBlockHeader.BLOCK_MA00://Material - if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) { + if (blenderKey.isLoadUnlinkedAssets() && (blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) { loadingResults.addMaterial(converter.toMaterial(block.getStructure(dataRepository))); } break; @@ -163,7 +163,7 @@ public class BlenderLoader implements AssetLoader { } break; case FileBlockHeader.BLOCK_WO00://World - if (worldData == null) {//onlu one world data is used + if (blenderKey.isLoadUnlinkedAssets() && worldData == null) {//onlu one world data is used Structure worldStructure = block.getStructure(dataRepository); String worldName = worldStructure.getName(); if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {