/* | |
* Copyright (c) 2009-2010 jMonkeyEngine | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* | |
* * Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
package com.jme3.scene.plugins.blender.file; | |
import com.jme3.scene.plugins.blender.BlenderContext; | |
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; | |
/** | |
* A class that holds the header data of a file block. The file block itself is not implemented. This class holds its | |
* start position in the stream and using this the structure can fill itself with the proper data. | |
* @author Marcin Roguski | |
*/ | |
public class FileBlockHeader { | |
public static final int BLOCK_TE00 = 'T' << 24 | 'E' << 16; //TE00 | |
public static final int BLOCK_ME00 = 'M' << 24 | 'E' << 16; //ME00 | |
public static final int BLOCK_SR00 = 'S' << 24 | 'R' << 16; //SR00 | |
public static final int BLOCK_CA00 = 'C' << 24 | 'A' << 16; //CA00 | |
public static final int BLOCK_LA00 = 'L' << 24 | 'A' << 16; //LA00 | |
public static final int BLOCK_OB00 = 'O' << 24 | 'B' << 16; //OB00 | |
public static final int BLOCK_MA00 = 'M' << 24 | 'A' << 16; //MA00 | |
public static final int BLOCK_SC00 = 'S' << 24 | 'C' << 16; //SC00 | |
public static final int BLOCK_WO00 = 'W' << 24 | 'O' << 16; //WO00 | |
public static final int BLOCK_TX00 = 'T' << 24 | 'X' << 16; //TX00 | |
public static final int BLOCK_IP00 = 'I' << 24 | 'P' << 16; //IP00 | |
public static final int BLOCK_AC00 = 'A' << 24 | 'C' << 16; //AC00 | |
public static final int BLOCK_GLOB = 'G' << 24 | 'L' << 16 | 'O' << 8 | 'B'; //GLOB | |
public static final int BLOCK_REND = 'R' << 24 | 'E' << 16 | 'N' << 8 | 'D'; //REND | |
public static final int BLOCK_DATA = 'D' << 24 | 'A' << 16 | 'T' << 8 | 'A'; //DATA | |
public static final int BLOCK_DNA1 = 'D' << 24 | 'N' << 16 | 'A' << 8 | '1'; //DNA1 | |
public static final int BLOCK_ENDB = 'E' << 24 | 'N' << 16 | 'D' << 8 | 'B'; //ENDB | |
/** Identifier of the file-block [4 bytes]. */ | |
private int code; | |
/** Total length of the data after the file-block-header [4 bytes]. */ | |
private int size; | |
/** | |
* Memory address the structure was located when written to disk [4 or 8 bytes (defined in file header as a pointer | |
* size)]. | |
*/ | |
private long oldMemoryAddress; | |
/** Index of the SDNA structure [4 bytes]. */ | |
private int sdnaIndex; | |
/** Number of structure located in this file-block [4 bytes]. */ | |
private int count; | |
/** Start position of the block's data in the stream. */ | |
private int blockPosition; | |
/** | |
* Constructor. Loads the block header from the given stream during instance creation. | |
* @param inputStream | |
* the stream we read the block header from | |
* @param blenderContext | |
* the blender context | |
* @throws BlenderFileException | |
* this exception is thrown when the pointer size is neither 4 nor 8 | |
*/ | |
public FileBlockHeader(BlenderInputStream inputStream, BlenderContext blenderContext) throws BlenderFileException { | |
inputStream.alignPosition(4); | |
code = inputStream.readByte() << 24 | inputStream.readByte() << 16 | |
| inputStream.readByte() << 8 | inputStream.readByte(); | |
size = inputStream.readInt(); | |
oldMemoryAddress = inputStream.readPointer(); | |
sdnaIndex = inputStream.readInt(); | |
count = inputStream.readInt(); | |
blockPosition = inputStream.getPosition(); | |
if (FileBlockHeader.BLOCK_DNA1 == code) { | |
blenderContext.setBlockData(new DnaBlockData(inputStream, blenderContext)); | |
} else { | |
inputStream.setPosition(blockPosition + size); | |
blenderContext.addFileBlockHeader(Long.valueOf(oldMemoryAddress), this); | |
} | |
} | |
/** | |
* This method returns the structure described by the header filled with appropriate data. | |
* @param blenderContext | |
* the blender context | |
* @return structure filled with data | |
* @throws BlenderFileException | |
*/ | |
public Structure getStructure(BlenderContext blenderContext) throws BlenderFileException { | |
blenderContext.getInputStream().setPosition(blockPosition); | |
Structure structure = blenderContext.getDnaBlockData().getStructure(sdnaIndex); | |
structure.fill(blenderContext.getInputStream()); | |
return structure; | |
} | |
/** | |
* This method returns the code of this data block. | |
* @return the code of this data block | |
*/ | |
public int getCode() { | |
return code; | |
} | |
/** | |
* This method returns the size of the data stored in this block. | |
* @return the size of the data stored in this block | |
*/ | |
public int getSize() { | |
return size; | |
} | |
/** | |
* This method returns the memory address. | |
* @return the memory address | |
*/ | |
public long getOldMemoryAddress() { | |
return oldMemoryAddress; | |
} | |
/** | |
* This method returns the sdna index. | |
* @return the sdna index | |
*/ | |
public int getSdnaIndex() { | |
return sdnaIndex; | |
} | |
/** | |
* This data returns the number of structure stored in the data block after this header. | |
* @return the number of structure stored in the data block after this header | |
*/ | |
public int getCount() { | |
return count; | |
} | |
/** | |
* This method returns the start position of the data block in the blend file stream. | |
* @return the start position of the data block | |
*/ | |
public int getBlockPosition() { | |
return blockPosition; | |
} | |
/** | |
* This method indicates if the block is the last block in the file. | |
* @return true if this block is the last one in the file nad false otherwise | |
*/ | |
public boolean isLastBlock() { | |
return FileBlockHeader.BLOCK_ENDB == code; | |
} | |
/** | |
* This method indicates if the block is the SDNA block. | |
* @return true if this block is the SDNA block and false otherwise | |
*/ | |
public boolean isDnaBlock() { | |
return FileBlockHeader.BLOCK_DNA1 == code; | |
} | |
@Override | |
public String toString() { | |
return "FILE BLOCK HEADER [" + this.codeToString(code) + " : " + size + " : " + oldMemoryAddress + " : " + sdnaIndex + " : " + count + "]"; | |
} | |
/** | |
* This method transforms the coded bloch id into a string value. | |
* @param code | |
* the id of the block | |
* @return the string value of the block id | |
*/ | |
protected String codeToString(int code) { | |
char c1 = (char) ((code & 0xFF000000) >> 24); | |
char c2 = (char) ((code & 0xFF0000) >> 16); | |
char c3 = (char) ((code & 0xFF00) >> 8); | |
char c4 = (char) (code & 0xFF); | |
return String.valueOf(c1) + c2 + c3 + c4; | |
} | |
} |