1 /* 2 * Copyright (c) 2009-2010 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.file; 33 34 import com.jme3.scene.plugins.blender.BlenderContext; 35 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 36 37 /** 38 * A class that holds the header data of a file block. The file block itself is not implemented. This class holds its 39 * start position in the stream and using this the structure can fill itself with the proper data. 40 * @author Marcin Roguski 41 */ 42 public class FileBlockHeader { 43 44 public static final int BLOCK_TE00 = 'T' << 24 | 'E' << 16; //TE00 45 public static final int BLOCK_ME00 = 'M' << 24 | 'E' << 16; //ME00 46 public static final int BLOCK_SR00 = 'S' << 24 | 'R' << 16; //SR00 47 public static final int BLOCK_CA00 = 'C' << 24 | 'A' << 16; //CA00 48 public static final int BLOCK_LA00 = 'L' << 24 | 'A' << 16; //LA00 49 public static final int BLOCK_OB00 = 'O' << 24 | 'B' << 16; //OB00 50 public static final int BLOCK_MA00 = 'M' << 24 | 'A' << 16; //MA00 51 public static final int BLOCK_SC00 = 'S' << 24 | 'C' << 16; //SC00 52 public static final int BLOCK_WO00 = 'W' << 24 | 'O' << 16; //WO00 53 public static final int BLOCK_TX00 = 'T' << 24 | 'X' << 16; //TX00 54 public static final int BLOCK_IP00 = 'I' << 24 | 'P' << 16; //IP00 55 public static final int BLOCK_AC00 = 'A' << 24 | 'C' << 16; //AC00 56 public static final int BLOCK_GLOB = 'G' << 24 | 'L' << 16 | 'O' << 8 | 'B'; //GLOB 57 public static final int BLOCK_REND = 'R' << 24 | 'E' << 16 | 'N' << 8 | 'D'; //REND 58 public static final int BLOCK_DATA = 'D' << 24 | 'A' << 16 | 'T' << 8 | 'A'; //DATA 59 public static final int BLOCK_DNA1 = 'D' << 24 | 'N' << 16 | 'A' << 8 | '1'; //DNA1 60 public static final int BLOCK_ENDB = 'E' << 24 | 'N' << 16 | 'D' << 8 | 'B'; //ENDB 61 /** Identifier of the file-block [4 bytes]. */ 62 private int code; 63 /** Total length of the data after the file-block-header [4 bytes]. */ 64 private int size; 65 /** 66 * Memory address the structure was located when written to disk [4 or 8 bytes (defined in file header as a pointer 67 * size)]. 68 */ 69 private long oldMemoryAddress; 70 /** Index of the SDNA structure [4 bytes]. */ 71 private int sdnaIndex; 72 /** Number of structure located in this file-block [4 bytes]. */ 73 private int count; 74 /** Start position of the block's data in the stream. */ 75 private int blockPosition; 76 77 /** 78 * Constructor. Loads the block header from the given stream during instance creation. 79 * @param inputStream 80 * the stream we read the block header from 81 * @param blenderContext 82 * the blender context 83 * @throws BlenderFileException 84 * this exception is thrown when the pointer size is neither 4 nor 8 85 */ 86 public FileBlockHeader(BlenderInputStream inputStream, BlenderContext blenderContext) throws BlenderFileException { 87 inputStream.alignPosition(4); 88 code = inputStream.readByte() << 24 | inputStream.readByte() << 16 89 | inputStream.readByte() << 8 | inputStream.readByte(); 90 size = inputStream.readInt(); 91 oldMemoryAddress = inputStream.readPointer(); 92 sdnaIndex = inputStream.readInt(); 93 count = inputStream.readInt(); 94 blockPosition = inputStream.getPosition(); 95 if (FileBlockHeader.BLOCK_DNA1 == code) { 96 blenderContext.setBlockData(new DnaBlockData(inputStream, blenderContext)); 97 } else { 98 inputStream.setPosition(blockPosition + size); 99 blenderContext.addFileBlockHeader(Long.valueOf(oldMemoryAddress), this); 100 } 101 } 102 103 /** 104 * This method returns the structure described by the header filled with appropriate data. 105 * @param blenderContext 106 * the blender context 107 * @return structure filled with data 108 * @throws BlenderFileException 109 */ 110 public Structure getStructure(BlenderContext blenderContext) throws BlenderFileException { 111 blenderContext.getInputStream().setPosition(blockPosition); 112 Structure structure = blenderContext.getDnaBlockData().getStructure(sdnaIndex); 113 structure.fill(blenderContext.getInputStream()); 114 return structure; 115 } 116 117 /** 118 * This method returns the code of this data block. 119 * @return the code of this data block 120 */ 121 public int getCode() { 122 return code; 123 } 124 125 /** 126 * This method returns the size of the data stored in this block. 127 * @return the size of the data stored in this block 128 */ 129 public int getSize() { 130 return size; 131 } 132 133 /** 134 * This method returns the memory address. 135 * @return the memory address 136 */ 137 public long getOldMemoryAddress() { 138 return oldMemoryAddress; 139 } 140 141 /** 142 * This method returns the sdna index. 143 * @return the sdna index 144 */ 145 public int getSdnaIndex() { 146 return sdnaIndex; 147 } 148 149 /** 150 * This data returns the number of structure stored in the data block after this header. 151 * @return the number of structure stored in the data block after this header 152 */ 153 public int getCount() { 154 return count; 155 } 156 157 /** 158 * This method returns the start position of the data block in the blend file stream. 159 * @return the start position of the data block 160 */ 161 public int getBlockPosition() { 162 return blockPosition; 163 } 164 165 /** 166 * This method indicates if the block is the last block in the file. 167 * @return true if this block is the last one in the file nad false otherwise 168 */ 169 public boolean isLastBlock() { 170 return FileBlockHeader.BLOCK_ENDB == code; 171 } 172 173 /** 174 * This method indicates if the block is the SDNA block. 175 * @return true if this block is the SDNA block and false otherwise 176 */ 177 public boolean isDnaBlock() { 178 return FileBlockHeader.BLOCK_DNA1 == code; 179 } 180 181 @Override 182 public String toString() { 183 return "FILE BLOCK HEADER [" + this.codeToString(code) + " : " + size + " : " + oldMemoryAddress + " : " + sdnaIndex + " : " + count + "]"; 184 } 185 186 /** 187 * This method transforms the coded bloch id into a string value. 188 * @param code 189 * the id of the block 190 * @return the string value of the block id 191 */ 192 protected String codeToString(int code) { 193 char c1 = (char) ((code & 0xFF000000) >> 24); 194 char c2 = (char) ((code & 0xFF0000) >> 16); 195 char c3 = (char) ((code & 0xFF00) >> 8); 196 char c4 = (char) (code & 0xFF); 197 return String.valueOf(c1) + c2 + c3 + c4; 198 } 199 } 200