Home | History | Annotate | Download | only in blender
      1 /*
      2  * Copyright (c) 2009-2012 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 package com.jme3.scene.plugins.blender;
     33 
     34 import java.io.IOException;
     35 import java.util.ArrayList;
     36 import java.util.EmptyStackException;
     37 import java.util.HashMap;
     38 import java.util.List;
     39 import java.util.Map;
     40 import java.util.Stack;
     41 import java.util.logging.Level;
     42 import java.util.logging.Logger;
     43 
     44 import com.jme3.animation.Skeleton;
     45 import com.jme3.asset.AssetManager;
     46 import com.jme3.asset.BlenderKey;
     47 import com.jme3.material.Material;
     48 import com.jme3.math.ColorRGBA;
     49 import com.jme3.scene.plugins.blender.animations.BoneContext;
     50 import com.jme3.scene.plugins.blender.animations.Ipo;
     51 import com.jme3.scene.plugins.blender.constraints.Constraint;
     52 import com.jme3.scene.plugins.blender.file.BlenderInputStream;
     53 import com.jme3.scene.plugins.blender.file.DnaBlockData;
     54 import com.jme3.scene.plugins.blender.file.FileBlockHeader;
     55 import com.jme3.scene.plugins.blender.file.Structure;
     56 import com.jme3.scene.plugins.blender.materials.MaterialContext;
     57 import com.jme3.scene.plugins.blender.meshes.MeshContext;
     58 import com.jme3.scene.plugins.blender.modifiers.Modifier;
     59 import com.jme3.scene.plugins.ogre.AnimData;
     60 
     61 /**
     62  * The class that stores temporary data and manages it during loading the belnd
     63  * file. This class is intended to be used in a single loading thread. It holds
     64  * the state of loading operations.
     65  *
     66  * @author Marcin Roguski (Kaelthas)
     67  */
     68 public class BlenderContext {
     69 	private static final Logger					LOGGER					= Logger.getLogger(BlenderContext.class.getName());
     70 
     71 	/** The blender file version. */
     72 	private int									blenderVersion;
     73 	/** The blender key. */
     74 	private BlenderKey							blenderKey;
     75 	/** The header of the file block. */
     76 	private DnaBlockData						dnaBlockData;
     77 	/** The input stream of the blend file. */
     78 	private BlenderInputStream					inputStream;
     79 	/** The asset manager. */
     80 	private AssetManager						assetManager;
     81 	/**
     82 	 * A map containing the file block headers. The key is the old pointer
     83 	 * address.
     84 	 */
     85 	private Map<Long, FileBlockHeader>			fileBlockHeadersByOma	= new HashMap<Long, FileBlockHeader>();
     86 	/** A map containing the file block headers. The key is the block code. */
     87 	private Map<Integer, List<FileBlockHeader>>	fileBlockHeadersByCode	= new HashMap<Integer, List<FileBlockHeader>>();
     88 	/**
     89 	 * This map stores the loaded features by their old memory address. The
     90 	 * first object in the value table is the loaded structure and the second -
     91 	 * the structure already converted into proper data.
     92 	 */
     93 	private Map<Long, Object[]>					loadedFeatures			= new HashMap<Long, Object[]>();
     94 	/**
     95 	 * This map stores the loaded features by their name. Only features with ID
     96 	 * structure can be stored here. The first object in the value table is the
     97 	 * loaded structure and the second - the structure already converted into
     98 	 * proper data.
     99 	 */
    100 	private Map<String, Object[]>				loadedFeaturesByName	= new HashMap<String, Object[]>();
    101 	/** A stack that hold the parent structure of currently loaded feature. */
    102 	private Stack<Structure>					parentStack				= new Stack<Structure>();
    103 	/**
    104 	 * A map storing loaded ipos. The key is the ipo's owner old memory address
    105 	 * and the value is the ipo.
    106 	 */
    107 	private Map<Long, Ipo>						loadedIpos				= new HashMap<Long, Ipo>();
    108 	/** A list of modifiers for the specified object. */
    109 	protected Map<Long, List<Modifier>>			modifiers				= new HashMap<Long, List<Modifier>>();
    110 	/** A list of constraints for the specified object. */
    111 	protected Map<Long, List<Constraint>>		constraints				= new HashMap<Long, List<Constraint>>();
    112 	/** Anim data loaded for features. */
    113 	private Map<Long, AnimData>					animData				= new HashMap<Long, AnimData>();
    114 	/** Loaded skeletons. */
    115 	private Map<Long, Skeleton>					skeletons				= new HashMap<Long, Skeleton>();
    116 	/** A map of mesh contexts. */
    117 	protected Map<Long, MeshContext>			meshContexts			= new HashMap<Long, MeshContext>();
    118 	/** A map of bone contexts. */
    119 	protected Map<Long, BoneContext>			boneContexts			= new HashMap<Long, BoneContext>();
    120 	/** A map of material contexts. */
    121 	protected Map<Material, MaterialContext>	materialContexts		= new HashMap<Material, MaterialContext>();
    122 	/** A map og helpers that perform loading. */
    123 	private Map<String, AbstractBlenderHelper>	helpers					= new HashMap<String, AbstractBlenderHelper>();
    124 
    125 	/**
    126 	 * This method sets the blender file version.
    127 	 *
    128 	 * @param blenderVersion
    129 	 *            the blender file version
    130 	 */
    131 	public void setBlenderVersion(String blenderVersion) {
    132 		this.blenderVersion = Integer.parseInt(blenderVersion);
    133 	}
    134 
    135 	/**
    136 	 * @return the blender file version
    137 	 */
    138 	public int getBlenderVersion() {
    139 		return blenderVersion;
    140 	}
    141 
    142 	/**
    143 	 * This method sets the blender key.
    144 	 *
    145 	 * @param blenderKey
    146 	 *            the blender key
    147 	 */
    148 	public void setBlenderKey(BlenderKey blenderKey) {
    149 		this.blenderKey = blenderKey;
    150 	}
    151 
    152 	/**
    153 	 * This method returns the blender key.
    154 	 *
    155 	 * @return the blender key
    156 	 */
    157 	public BlenderKey getBlenderKey() {
    158 		return blenderKey;
    159 	}
    160 
    161 	/**
    162 	 * This method sets the dna block data.
    163 	 *
    164 	 * @param dnaBlockData
    165 	 *            the dna block data
    166 	 */
    167 	public void setBlockData(DnaBlockData dnaBlockData) {
    168 		this.dnaBlockData = dnaBlockData;
    169 	}
    170 
    171 	/**
    172 	 * This method returns the dna block data.
    173 	 *
    174 	 * @return the dna block data
    175 	 */
    176 	public DnaBlockData getDnaBlockData() {
    177 		return dnaBlockData;
    178 	}
    179 
    180 	/**
    181 	 * This method returns the asset manager.
    182 	 *
    183 	 * @return the asset manager
    184 	 */
    185 	public AssetManager getAssetManager() {
    186 		return assetManager;
    187 	}
    188 
    189 	/**
    190 	 * This method sets the asset manager.
    191 	 *
    192 	 * @param assetManager
    193 	 *            the asset manager
    194 	 */
    195 	public void setAssetManager(AssetManager assetManager) {
    196 		this.assetManager = assetManager;
    197 	}
    198 
    199 	/**
    200 	 * This method returns the input stream of the blend file.
    201 	 *
    202 	 * @return the input stream of the blend file
    203 	 */
    204 	public BlenderInputStream getInputStream() {
    205 		return inputStream;
    206 	}
    207 
    208 	/**
    209 	 * This method sets the input stream of the blend file.
    210 	 *
    211 	 * @param inputStream
    212 	 *            the input stream of the blend file
    213 	 */
    214 	public void setInputStream(BlenderInputStream inputStream) {
    215 		this.inputStream = inputStream;
    216 	}
    217 
    218 	/**
    219 	 * This method adds a file block header to the map. Its old memory address
    220 	 * is the key.
    221 	 *
    222 	 * @param oldMemoryAddress
    223 	 *            the address of the block header
    224 	 * @param fileBlockHeader
    225 	 *            the block header to store
    226 	 */
    227 	public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
    228 		fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
    229 		List<FileBlockHeader> headers = fileBlockHeadersByCode.get(Integer.valueOf(fileBlockHeader.getCode()));
    230 		if (headers == null) {
    231 			headers = new ArrayList<FileBlockHeader>();
    232 			fileBlockHeadersByCode.put(Integer.valueOf(fileBlockHeader.getCode()), headers);
    233 		}
    234 		headers.add(fileBlockHeader);
    235 	}
    236 
    237 	/**
    238 	 * This method returns the block header of a given memory address. If the
    239 	 * header is not present then null is returned.
    240 	 *
    241 	 * @param oldMemoryAddress
    242 	 *            the address of the block header
    243 	 * @return loaded header or null if it was not yet loaded
    244 	 */
    245 	public FileBlockHeader getFileBlock(Long oldMemoryAddress) {
    246 		return fileBlockHeadersByOma.get(oldMemoryAddress);
    247 	}
    248 
    249 	/**
    250 	 * This method returns a list of file blocks' headers of a specified code.
    251 	 *
    252 	 * @param code
    253 	 *            the code of file blocks
    254 	 * @return a list of file blocks' headers of a specified code
    255 	 */
    256 	public List<FileBlockHeader> getFileBlocks(Integer code) {
    257 		return fileBlockHeadersByCode.get(code);
    258 	}
    259 
    260 	/**
    261 	 * This method clears the saved block headers stored in the features map.
    262 	 */
    263 	public void clearFileBlocks() {
    264 		fileBlockHeadersByOma.clear();
    265 		fileBlockHeadersByCode.clear();
    266 	}
    267 
    268 	/**
    269 	 * This method adds a helper instance to the helpers' map.
    270 	 *
    271 	 * @param <T>
    272 	 *            the type of the helper
    273 	 * @param clazz
    274 	 *            helper's class definition
    275 	 * @param helper
    276 	 *            the helper instance
    277 	 */
    278 	public <T> void putHelper(Class<T> clazz, AbstractBlenderHelper helper) {
    279 		helpers.put(clazz.getSimpleName(), helper);
    280 	}
    281 
    282 	@SuppressWarnings("unchecked")
    283 	public <T> T getHelper(Class<?> clazz) {
    284 		return (T) helpers.get(clazz.getSimpleName());
    285 	}
    286 
    287 	/**
    288 	 * This method adds a loaded feature to the map. The key is its unique old
    289 	 * memory address.
    290 	 *
    291 	 * @param oldMemoryAddress
    292 	 *            the address of the feature
    293 	 * @param featureName
    294 	 *            the name of the feature
    295 	 * @param structure
    296 	 *            the filled structure of the feature
    297 	 * @param feature
    298 	 *            the feature we want to store
    299 	 */
    300 	public void addLoadedFeatures(Long oldMemoryAddress, String featureName, Structure structure, Object feature) {
    301 		if (oldMemoryAddress == null || structure == null || feature == null) {
    302 			throw new IllegalArgumentException("One of the given arguments is null!");
    303 		}
    304 		Object[] storedData = new Object[] { structure, feature };
    305 		loadedFeatures.put(oldMemoryAddress, storedData);
    306 		if (featureName != null) {
    307 			loadedFeaturesByName.put(featureName, storedData);
    308 		}
    309 	}
    310 
    311 	/**
    312 	 * This method returns the feature of a given memory address. If the feature
    313 	 * is not yet loaded then null is returned.
    314 	 *
    315 	 * @param oldMemoryAddress
    316 	 *            the address of the feature
    317 	 * @param loadedFeatureDataType
    318 	 *            the type of data we want to retreive it can be either filled
    319 	 *            structure or already converted feature
    320 	 * @return loaded feature or null if it was not yet loaded
    321 	 */
    322 	public Object getLoadedFeature(Long oldMemoryAddress, LoadedFeatureDataType loadedFeatureDataType) {
    323 		Object[] result = loadedFeatures.get(oldMemoryAddress);
    324 		if (result != null) {
    325 			return result[loadedFeatureDataType.getIndex()];
    326 		}
    327 		return null;
    328 	}
    329 
    330 	/**
    331 	 * This method returns the feature of a given name. If the feature is not
    332 	 * yet loaded then null is returned.
    333 	 *
    334 	 * @param featureName
    335 	 *            the name of the feature
    336 	 * @param loadedFeatureDataType
    337 	 *            the type of data we want to retreive it can be either filled
    338 	 *            structure or already converted feature
    339 	 * @return loaded feature or null if it was not yet loaded
    340 	 */
    341 	public Object getLoadedFeature(String featureName, LoadedFeatureDataType loadedFeatureDataType) {
    342 		Object[] result = loadedFeaturesByName.get(featureName);
    343 		if (result != null) {
    344 			return result[loadedFeatureDataType.getIndex()];
    345 		}
    346 		return null;
    347 	}
    348 
    349 	/**
    350 	 * This method clears the saved features stored in the features map.
    351 	 */
    352 	public void clearLoadedFeatures() {
    353 		loadedFeatures.clear();
    354 	}
    355 
    356 	/**
    357 	 * This method adds the structure to the parent stack.
    358 	 *
    359 	 * @param parent
    360 	 *            the structure to be added to the stack
    361 	 */
    362 	public void pushParent(Structure parent) {
    363 		parentStack.push(parent);
    364 	}
    365 
    366 	/**
    367 	 * This method removes the structure from the top of the parent's stack.
    368 	 *
    369 	 * @return the structure that was removed from the stack
    370 	 */
    371 	public Structure popParent() {
    372 		try {
    373 			return parentStack.pop();
    374 		} catch (EmptyStackException e) {
    375 			return null;
    376 		}
    377 	}
    378 
    379 	/**
    380 	 * This method retreives the structure at the top of the parent's stack but
    381 	 * does not remove it.
    382 	 *
    383 	 * @return the structure from the top of the stack
    384 	 */
    385 	public Structure peekParent() {
    386 		try {
    387 			return parentStack.peek();
    388 		} catch (EmptyStackException e) {
    389 			return null;
    390 		}
    391 	}
    392 
    393 	/**
    394 	 * This method adds new ipo curve for the feature.
    395 	 *
    396 	 * @param ownerOMA
    397 	 *            the OMA of blender feature that owns the ipo
    398 	 * @param ipo
    399 	 *            the ipo to be added
    400 	 */
    401 	public void addIpo(Long ownerOMA, Ipo ipo) {
    402 		loadedIpos.put(ownerOMA, ipo);
    403 	}
    404 
    405 	/**
    406 	 * This method removes the ipo curve from the feature.
    407 	 *
    408 	 * @param ownerOma
    409 	 *            the OMA of blender feature that owns the ipo
    410 	 */
    411 	public Ipo removeIpo(Long ownerOma) {
    412 		return loadedIpos.remove(ownerOma);
    413 	}
    414 
    415 	/**
    416 	 * This method returns the ipo curve of the feature.
    417 	 *
    418 	 * @param ownerOMA
    419 	 *            the OMA of blender feature that owns the ipo
    420 	 */
    421 	public Ipo getIpo(Long ownerOMA) {
    422 		return loadedIpos.get(ownerOMA);
    423 	}
    424 
    425 	/**
    426 	 * This method adds a new modifier to the list.
    427 	 *
    428 	 * @param ownerOMA
    429 	 *            the owner's old memory address
    430 	 * @param modifier
    431 	 *            the object's modifier
    432 	 */
    433 	public void addModifier(Long ownerOMA, Modifier modifier) {
    434 		List<Modifier> objectModifiers = this.modifiers.get(ownerOMA);
    435 		if (objectModifiers == null) {
    436 			objectModifiers = new ArrayList<Modifier>();
    437 			this.modifiers.put(ownerOMA, objectModifiers);
    438 		}
    439 		objectModifiers.add(modifier);
    440 	}
    441 
    442 	/**
    443 	 * This method returns modifiers for the object specified by its old memory
    444 	 * address and the modifier type. If no modifiers are found - empty list is
    445 	 * returned. If the type is null - all modifiers for the object are
    446 	 * returned.
    447 	 *
    448 	 * @param objectOMA
    449 	 *            object's old memory address
    450 	 * @param type
    451 	 *            the type of the modifier
    452 	 * @return the list of object's modifiers
    453 	 */
    454 	public List<Modifier> getModifiers(Long objectOMA, String type) {
    455 		List<Modifier> result = new ArrayList<Modifier>();
    456 		List<Modifier> readModifiers = modifiers.get(objectOMA);
    457 		if (readModifiers != null && readModifiers.size() > 0) {
    458 			for (Modifier modifier : readModifiers) {
    459 				if (type == null || type.isEmpty() || modifier.getType().equals(type)) {
    460 					result.add(modifier);
    461 				}
    462 			}
    463 		}
    464 		return result;
    465 	}
    466 
    467 	/**
    468 	 * This method adds a new modifier to the list.
    469 	 *
    470 	 * @param ownerOMA
    471 	 *            the owner's old memory address
    472 	 * @param constraints
    473 	 *            the object's constraints
    474 	 */
    475 	public void addConstraints(Long ownerOMA, List<Constraint> constraints) {
    476 		List<Constraint> objectConstraints = this.constraints.get(ownerOMA);
    477 		if (objectConstraints == null) {
    478 			objectConstraints = new ArrayList<Constraint>();
    479 			this.constraints.put(ownerOMA, objectConstraints);
    480 		}
    481 		objectConstraints.addAll(constraints);
    482 	}
    483 
    484 	/**
    485 	 * This method returns constraints for the object specified by its old
    486 	 * memory address. If no modifiers are found - <b>null</b> is returned.
    487 	 *
    488 	 * @param objectOMA
    489 	 *            object's old memory address
    490 	 * @return the list of object's modifiers or null
    491 	 */
    492 	public List<Constraint> getConstraints(Long objectOMA) {
    493 		return objectOMA == null ? null : constraints.get(objectOMA);
    494 	}
    495 
    496 	/**
    497 	 * This method sets the anim data for the specified OMA of its owner.
    498 	 *
    499 	 * @param ownerOMA
    500 	 *            the owner's old memory address
    501 	 * @param animData
    502 	 *            the animation data for the feature specified by ownerOMA
    503 	 */
    504 	public void setAnimData(Long ownerOMA, AnimData animData) {
    505 		this.animData.put(ownerOMA, animData);
    506 	}
    507 
    508 	/**
    509 	 * This method returns the animation data for the specified owner.
    510 	 *
    511 	 * @param ownerOMA
    512 	 *            the old memory address of the animation data owner
    513 	 * @return the animation data or null if none exists
    514 	 */
    515 	public AnimData getAnimData(Long ownerOMA) {
    516 		return this.animData.get(ownerOMA);
    517 	}
    518 
    519 	/**
    520 	 * This method sets the skeleton for the specified OMA of its owner.
    521 	 *
    522 	 * @param skeletonOMA
    523 	 *            the skeleton's old memory address
    524 	 * @param skeleton
    525 	 *            the skeleton specified by the given OMA
    526 	 */
    527 	public void setSkeleton(Long skeletonOMA, Skeleton skeleton) {
    528 		this.skeletons.put(skeletonOMA, skeleton);
    529 	}
    530 
    531 	/**
    532 	 * This method returns the skeleton for the specified OMA of its owner.
    533 	 *
    534 	 * @param skeletonOMA
    535 	 *            the skeleton's old memory address
    536 	 * @return the skeleton specified by the given OMA
    537 	 */
    538 	public Skeleton getSkeleton(Long skeletonOMA) {
    539 		return this.skeletons.get(skeletonOMA);
    540 	}
    541 
    542 	/**
    543 	 * This method sets the mesh context for the given mesh old memory address.
    544 	 * If the context is already set it will be replaced.
    545 	 *
    546 	 * @param meshOMA
    547 	 *            the mesh's old memory address
    548 	 * @param meshContext
    549 	 *            the mesh's context
    550 	 */
    551 	public void setMeshContext(Long meshOMA, MeshContext meshContext) {
    552 		this.meshContexts.put(meshOMA, meshContext);
    553 	}
    554 
    555 	/**
    556 	 * This method returns the mesh context for the given mesh old memory
    557 	 * address. If no context exists then <b>null</b> is returned.
    558 	 *
    559 	 * @param meshOMA
    560 	 *            the mesh's old memory address
    561 	 * @return mesh's context
    562 	 */
    563 	public MeshContext getMeshContext(Long meshOMA) {
    564 		return this.meshContexts.get(meshOMA);
    565 	}
    566 
    567 	/**
    568 	 * This method sets the bone context for the given bone old memory address.
    569 	 * If the context is already set it will be replaced.
    570 	 *
    571 	 * @param boneOMA
    572 	 *            the bone's old memory address
    573 	 * @param boneContext
    574 	 *            the bones's context
    575 	 */
    576 	public void setBoneContext(Long boneOMA, BoneContext boneContext) {
    577 		this.boneContexts.put(boneOMA, boneContext);
    578 	}
    579 
    580 	/**
    581 	 * This method returns the bone context for the given bone old memory
    582 	 * address. If no context exists then <b>null</b> is returned.
    583 	 *
    584 	 * @param boneOMA
    585 	 *            the bone's old memory address
    586 	 * @return bone's context
    587 	 */
    588 	public BoneContext getBoneContext(Long boneOMA) {
    589 		return boneContexts.get(boneOMA);
    590 	}
    591 
    592 	/**
    593 	 * This method sets the material context for the given material. If the
    594 	 * context is already set it will be replaced.
    595 	 *
    596 	 * @param material
    597 	 *            the material
    598 	 * @param materialContext
    599 	 *            the material's context
    600 	 */
    601 	public void setMaterialContext(Material material, MaterialContext materialContext) {
    602 		this.materialContexts.put(material, materialContext);
    603 	}
    604 
    605 	/**
    606 	 * This method returns the material context for the given material. If no
    607 	 * context exists then <b>null</b> is returned.
    608 	 *
    609 	 * @param material
    610 	 *            the material
    611 	 * @return material's context
    612 	 */
    613 	public MaterialContext getMaterialContext(Material material) {
    614 		return materialContexts.get(material);
    615 	}
    616 
    617 	/**
    618 	 * This metod returns the default material.
    619 	 *
    620 	 * @return the default material
    621 	 */
    622 	public synchronized Material getDefaultMaterial() {
    623 		if (blenderKey.getDefaultMaterial() == null) {
    624 			Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    625 			defaultMaterial.setColor("Color", ColorRGBA.DarkGray);
    626 			blenderKey.setDefaultMaterial(defaultMaterial);
    627 		}
    628 		return blenderKey.getDefaultMaterial();
    629 	}
    630 
    631 	public void dispose() {
    632 		try {
    633 			inputStream.close();
    634 		} catch (IOException e) {
    635 			LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
    636 		}
    637 		loadedFeatures.clear();
    638 		loadedFeaturesByName.clear();
    639 	}
    640 
    641 	/**
    642 	 * This enum defines what loaded data type user wants to retreive. It can be
    643 	 * either filled structure or already converted data.
    644 	 *
    645 	 * @author Marcin Roguski
    646 	 */
    647 	public static enum LoadedFeatureDataType {
    648 
    649 		LOADED_STRUCTURE(0), LOADED_FEATURE(1);
    650 		private int	index;
    651 
    652 		private LoadedFeatureDataType(int index) {
    653 			this.index = index;
    654 		}
    655 
    656 		public int getIndex() {
    657 			return index;
    658 		}
    659 	}
    660 }
    661