Browse Source

Disabling loading all assets by default. Now unlinked assets or those being on inactive layers will not be loaded if they are not requested to.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8042 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 14 years ago
parent
commit
daa86cfec7

+ 781 - 744
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<String, Map<String, int[]>> 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<String, Map<String, int[]>>();
-            animations.put(objectName, new HashMap<String, int[]>());
-        }
-        Map<String, int[]> objectAnimations = animations.get(objectName);
-        if (objectAnimations == null) {
-            objectAnimations = new HashMap<String, int[]>();
-            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<String, int[]> 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<String> getAnimationNames(String objectName) {
-        Map<String, int[]> 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<String, Map<String, int[]>> 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<String, Map<String, int[]>> 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<String, int[]> 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<String, Map<String, int[]>>(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<String, int[]> objectAnimations = new HashMap<String, int[]>(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<Node> scenes;
-        /** Objects from all scenes. */
-        private List<Node> objects;
-        /** Materials from all objects. */
-        private List<Material> materials;
-        /** Textures from all objects. */
-        private List<Texture> textures;
-        /** Animations of all objects. */
-        private List<AnimData> animations;
-        /** All cameras from the file. */
-        private List<Camera> cameras;
-        /** All lights from the file. */
-        private List<Light> 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<Node>();
-            }
-            if ((featuresToLoad & FeaturesToLoad.OBJECTS) != 0) {
-                objects = new ArrayList<Node>();
-                if ((featuresToLoad & FeaturesToLoad.MATERIALS) != 0) {
-                    materials = new ArrayList<Material>();
-                    if ((featuresToLoad & FeaturesToLoad.TEXTURES) != 0) {
-                        textures = new ArrayList<Texture>();
-                    }
-                }
-                if ((featuresToLoad & FeaturesToLoad.ANIMATIONS) != 0) {
-                    animations = new ArrayList<AnimData>();
-                }
-            }
-            if ((featuresToLoad & FeaturesToLoad.CAMERAS) != 0) {
-                cameras = new ArrayList<Camera>();
-            }
-            if ((featuresToLoad & FeaturesToLoad.LIGHTS) != 0) {
-                lights = new ArrayList<Light>();
-            }
-        }
-
-        /**
-         * 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<Node> getScenes() {
-            return scenes;
-        }
-
-        /**
-         * This method returns all loaded objects.
-         * @return all loaded objects
-         */
-        public List<Node> getObjects() {
-            return objects;
-        }
-
-        /**
-         * This method returns all loaded materials.
-         * @return all loaded materials
-         */
-        public List<Material> getMaterials() {
-            return materials;
-        }
-
-        /**
-         * This method returns all loaded textures.
-         * @return all loaded textures
-         */
-        public List<Texture> getTextures() {
-            return textures;
-        }
-
-        /**
-         * This method returns all loaded animations.
-         * @return all loaded animations
-         */
-        public List<AnimData> getAnimations() {
-            return animations;
-        }
-
-        /**
-         * This method returns all loaded cameras.
-         * @return all loaded cameras
-         */
-        public List<Camera> getCameras() {
-            return cameras;
-        }
-
-        /**
-         * This method returns all loaded lights.
-         * @return all loaded lights
-         */
-        public List<Light> 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<Spatial> 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<String, Map<String, int[]>>	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<String, Map<String, int[]>>();
+			animations.put(objectName, new HashMap<String, int[]>());
+		}
+		Map<String, int[]> objectAnimations = animations.get(objectName);
+		if (objectAnimations == null) {
+			objectAnimations = new HashMap<String, int[]>();
+			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<String, int[]> 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<String> getAnimationNames(String objectName) {
+		Map<String, int[]> 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<String, Map<String, int[]>> 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 <b>true</b> if unlinked assets should be loaded and <b>false</b> 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
+	 *        <b>true</b> if unlinked assets should be loaded and <b>false</b> 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<String, Map<String, int[]>> 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<String, int[]> 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<String, Map<String, int[]>>(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<String, int[]> objectAnimations = new HashMap<String, int[]>(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<Node>		scenes;
+		/** Objects from all scenes. */
+		private List<Node>		objects;
+		/** Materials from all objects. */
+		private List<Material>	materials;
+		/** Textures from all objects. */
+		private List<Texture>	textures;
+		/** Animations of all objects. */
+		private List<AnimData>	animations;
+		/** All cameras from the file. */
+		private List<Camera>	cameras;
+		/** All lights from the file. */
+		private List<Light>		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<Node>();
+			}
+			if ((featuresToLoad & FeaturesToLoad.OBJECTS) != 0) {
+				objects = new ArrayList<Node>();
+				if ((featuresToLoad & FeaturesToLoad.MATERIALS) != 0) {
+					materials = new ArrayList<Material>();
+					if ((featuresToLoad & FeaturesToLoad.TEXTURES) != 0) {
+						textures = new ArrayList<Texture>();
+					}
+				}
+				if ((featuresToLoad & FeaturesToLoad.ANIMATIONS) != 0) {
+					animations = new ArrayList<AnimData>();
+				}
+			}
+			if ((featuresToLoad & FeaturesToLoad.CAMERAS) != 0) {
+				cameras = new ArrayList<Camera>();
+			}
+			if ((featuresToLoad & FeaturesToLoad.LIGHTS) != 0) {
+				lights = new ArrayList<Light>();
+			}
+		}
+
+		/**
+		 * 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<Node> getScenes() {
+			return scenes;
+		}
+
+		/**
+		 * This method returns all loaded objects.
+		 * @return all loaded objects
+		 */
+		public List<Node> getObjects() {
+			return objects;
+		}
+
+		/**
+		 * This method returns all loaded materials.
+		 * @return all loaded materials
+		 */
+		public List<Material> getMaterials() {
+			return materials;
+		}
+
+		/**
+		 * This method returns all loaded textures.
+		 * @return all loaded textures
+		 */
+		public List<Texture> getTextures() {
+			return textures;
+		}
+
+		/**
+		 * This method returns all loaded animations.
+		 * @return all loaded animations
+		 */
+		public List<AnimData> getAnimations() {
+			return animations;
+		}
+
+		/**
+		 * This method returns all loaded cameras.
+		 * @return all loaded cameras
+		 */
+		public List<Camera> getCameras() {
+			return cameras;
+		}
+
+		/**
+		 * This method returns all loaded lights.
+		 * @return all loaded lights
+		 */
+		public List<Light> 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<Spatial> 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;
+		}
+	}
 }

+ 2 - 2
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)) {