summaryrefslogtreecommitdiff
path: root/src/win95/shpchunk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/win95/shpchunk.cpp')
-rw-r--r--src/win95/shpchunk.cpp3869
1 files changed, 3869 insertions, 0 deletions
diff --git a/src/win95/shpchunk.cpp b/src/win95/shpchunk.cpp
new file mode 100644
index 0000000..a494767
--- /dev/null
+++ b/src/win95/shpchunk.cpp
@@ -0,0 +1,3869 @@
+#include <math.h>
+
+#include "chunk.hpp"
+#include "chnktype.hpp"
+#include "shpchunk.hpp"
+#include "obchunk.hpp"
+
+
+#if cencon || InterfaceEngine
+#include "fnamefnc.hpp"
+#include "zsp.hpp"
+#include "bmpnames.hpp"
+#include "envchunk.hpp"
+#include "animchnk.hpp"
+#include "chunkpal.hpp"
+#include "fragchnk.hpp"
+#endif
+
+#ifdef cencon
+#define new my_new
+#endif
+//macro for helping to force inclusion of chunks when using libraries
+FORCE_CHUNK_INCLUDE_IMPLEMENT(shpchunk)
+
+RIF_IMPLEMENT_DYNCREATE("REBSHAPE",Shape_Chunk)
+
+int Shape_Chunk::max_id = 0;
+BOOL Shape_External_File_Chunk::UpdatingExternalShape=FALSE;
+
+// Class Shape_Chunk functions
+
+/*
+Children for Shape_Chunk :
+
+"SHPRAWVT" Shape_Vertex_Chunk
+"SHPPOLYS" Shape_Polygon_Chunk
+"SHPHEAD1" Shape_Header_Chunk
+"SHPVNORM" Shape_Vertex_Normal_Chunk
+"SHPPNORM" Shape_Polygon_Normal_Chunk
+"SHPTEXFN" Shape_Texture_Filenames_Chunk
+"SHPUVCRD" Shape_UV_Coord_Chunk
+"SHPMRGDT" Shape_Merge_Data_Chunk
+"SHPCENTR" Shape_Centre_Chunk
+"SHPMORPH" Shape_Morphing_Data_Chunk
+"SHPEXTFL" Shape_External_File_Chunk
+"SHPPCINF" Shape_Poly_Change_Info_Chunk
+"TEXTANIM" Animation_Chunk
+"SHPFRAGS" Shape_Fragments_Chunk
+"ANIMSEQU" Anim_Shape_Sequence_Chunk
+"PNOTINBB" Poly_Not_In_Bounding_Box_Chunk
+"ANSHCEN2" Anim_Shape_Centre_Chunk
+"ASALTTEX" Anim_Shape_Alternate_Texturing_Chunk
+"SHPPRPRO" Shape_Preprocessed_Data_Chunk
+*/
+
+Shape_Chunk::Shape_Chunk(Chunk_With_Children * parent, const char *data, size_t size)
+: Lockable_Chunk_With_Children (parent, "REBSHAPE"), shape_data ()
+{
+ const char * buffer_ptr = data;
+
+ shape_data_store = (ChunkShape *) &shape_data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+
+/*--------------------------------------------------------------------**
+** N.B. all changes to shape formats should be made to the sub shapes **
+**--------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------**
+** And of course the external file post input processing function should be **
+** changed so that any new chunks will be copied over **
+**--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------**
+** Oy READ THE NOTES, also destroy_auxiliary_chunks should be changed as well **
+**----------------------------------------------------------------------------*/
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+
+/*--------------------------------------------------------------------**
+** N.B. all changes to shape formats should be made to the sub shapes **
+**--------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------**
+** And of course the external file post input processing function should be **
+** changed so that any new chunks will be copied over **
+**--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------**
+** Oy READ THE NOTES, also destroy_auxiliary_chunks should be changed as well **
+**----------------------------------------------------------------------------*/
+
+ }
+ #if cencon || InterfaceEngine
+ List<Chunk*>chlist;
+ lookup_child("CONSHAPE",chlist);
+ for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
+ {
+ ((Console_Shape_Chunk*)chlif())->generate_console_chunkshape();
+ }
+ #endif
+}
+
+Shape_Chunk::Shape_Chunk (Chunk_With_Children * parent, ChunkShape &shp_dat)
+: Lockable_Chunk_With_Children (parent, "REBSHAPE"), shape_data (shp_dat)
+{
+ shape_data_store = (ChunkShape *) &shape_data;
+
+ new Shape_Header_Chunk (this);
+
+ if (shape_data.v_list) new Shape_Vertex_Chunk (this, shape_data.num_verts);
+ if (shape_data.v_normal_list) new Shape_Vertex_Normal_Chunk (this, shape_data.num_verts);
+ if (shape_data.p_normal_list) new Shape_Polygon_Normal_Chunk (this, shape_data.num_polys);
+ if (shape_data.poly_list) new Shape_Polygon_Chunk (this, shape_data.num_polys);
+ if (shape_data.uv_list) new Shape_UV_Coord_Chunk (this, shape_data.num_uvs);
+ if (shape_data.texture_fns) new Shape_Texture_Filenames_Chunk (this, shape_data.num_texfiles);
+
+
+
+ //calculate the shape's centre and radius_about_centre
+ shape_data_store->centre=(shape_data_store->min+shape_data_store->max)/2;
+ shape_data_store->radius_about_centre=0;
+ for(int i=0;i<shape_data_store->num_verts;i++)
+ {
+ float length = (float) mod(shape_data_store->v_list[i]-shape_data_store->centre);
+ if(length>shape_data_store->radius_about_centre)
+ {
+ shape_data_store->radius_about_centre=length;
+ }
+ }
+
+ //if the shape hasn't got a Shape_Centre_Chunk , create one.
+
+ if(!lookup_single_child("SHPCENTR"))
+ {
+ new Shape_Centre_Chunk(this);
+ }
+}
+
+Shape_Chunk::~Shape_Chunk ()
+{
+}
+
+Shape_Chunk* Shape_Chunk::make_copy_of_chunk()
+{
+ char* Data=this->make_data_block_from_chunk();
+ Shape_Chunk* NewShape=new Shape_Chunk(parent,Data+12,this->size_chunk()-12);
+ delete [] Data;
+ delete NewShape->get_header();
+ new Shape_Header_Chunk(NewShape);
+ //need to call post_input_processing in order to copy morphing data correctly
+ NewShape->post_input_processing();
+ NewShape->updated=TRUE;
+ return NewShape;
+}
+
+Shape_Header_Chunk * Shape_Chunk::get_header()
+{
+
+ return (Shape_Header_Chunk *) this->lookup_single_child ("SHPHEAD1");
+
+}
+
+List<Object_Chunk *> const & Shape_Chunk::list_assoc_objs()
+{
+ if (!get_header())
+ {
+ static List<Object_Chunk *> empty_list;
+ return empty_list;
+ }
+
+ return get_header()->associated_objects_store;
+}
+
+BOOL Shape_Chunk::assoc_with_object (Object_Chunk *obch)
+{
+ return obch->assoc_with_shape(this);
+}
+
+BOOL Shape_Chunk::deassoc_with_object (Object_Chunk *obch)
+{
+ return obch->deassoc_with_shape(this);
+}
+
+
+void Shape_Chunk::post_input_processing()
+{
+ if (get_header())
+ if (get_header()->flags & GENERAL_FLAG_LOCKED)
+ external_lock = TRUE;
+
+#if 0 //shouldn't need to recalculate extents each time shape is loaded
+ // recalculate the shape extents
+
+ ChunkVector max, min;
+
+ max.x = -1000000000;
+ max.y = -1000000000;
+ max.z = -1000000000;
+
+ min.x = 1000000000;
+ min.y = 1000000000;
+ min.z = 1000000000;
+
+ float radius = 0;
+
+ for (int i=0; i<shape_data_store->num_verts; i++)
+ {
+ max.x = max(max.x, shape_data_store->v_list[i].x);
+ max.y = max(max.y, shape_data_store->v_list[i].y);
+ max.z = max(max.z, shape_data_store->v_list[i].z);
+
+ min.x = min(min.x, shape_data_store->v_list[i].x);
+ min.y = min(min.y, shape_data_store->v_list[i].y);
+ min.z = min(min.z, shape_data_store->v_list[i].z);
+
+ float temp_rad =(float) mod(shape_data_store->v_list[i]);
+
+ radius = max (radius, temp_rad);
+ }
+
+ shape_data_store->max = max;
+ shape_data_store->min = min;
+ shape_data_store->radius = radius;
+#endif
+
+
+ Chunk_With_Children::post_input_processing();
+
+}
+
+void Shape_Chunk::destroy_auxiliary_chunks()
+{
+ //split up into different blocks to stop compiler crashing when optimizations are turned on
+
+ List<Chunk *> chlst;
+
+ lookup_child("SHPZSPDT",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("SHPMRGDT",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+
+ lookup_child("SHPMORPH",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+
+ lookup_child("TEXTANIM",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+
+ lookup_child("SHPPCINF",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("SHPFRAGS",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("ANIMSEQU",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("PNOTINBB",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("ANSHCEN2",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("CONSHAPE",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child("ASALTTEX",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+ lookup_child("SHPPRPRO",chlst);
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+}
+
+
+
+BOOL Shape_Chunk::file_equals(HANDLE &rif_file)
+{
+ unsigned long bytes_read;
+ int id;
+ Shape_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return (FALSE);
+
+ // get header list
+ List<int> obhead;
+ list_chunks_in_file (&obhead, rif_file, "SHPHEAD1");
+
+ if (obhead.size() != 1) return FALSE;
+
+ // get object identifier
+ SetFilePointer(rif_file,obhead.first_entry() + 32,0,FILE_BEGIN);
+ ReadFile (rif_file, (long *) &(id), 4, &bytes_read, 0);
+
+ if (hdptr->file_id_num == id) return TRUE;
+
+ return (FALSE);
+}
+
+const char * Shape_Chunk::get_head_id()
+{
+ Shape_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return (0);
+
+ return(hdptr->identifier);
+}
+
+void Shape_Chunk::set_lock_user (char * user)
+{
+ Shape_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return;
+
+ strncpy (hdptr->lock_user, user,16);
+
+ hdptr->lock_user[16] = 0;
+}
+
+BOOL Shape_Chunk::inc_v_no ()
+{
+ Shape_Header_Chunk * hdptr = get_header();
+
+ if (!hdptr) return (FALSE);
+
+ hdptr->version_no++;
+
+ return (TRUE);
+}
+
+BOOL Shape_Chunk::same_and_updated(Shape_Chunk & shp)
+{
+
+ Shape_Header_Chunk * hd1ptr = get_header();
+
+ if (!hd1ptr) return (0);
+
+ Shape_Header_Chunk * hd2ptr = shp.get_header();
+
+ if (!hd2ptr) return (0);
+
+ return (hd1ptr->version_no < hd2ptr->version_no && hd1ptr->file_id_num == hd2ptr->file_id_num);
+
+}
+
+BOOL Shape_Chunk::assoc_with_object_list(File_Chunk *fc)
+{
+ Shape_Header_Chunk * hdptr = get_header();
+ Object_Chunk * ob = NULL;
+
+ if (!hdptr) return (FALSE);
+
+ List<Chunk *> chlst;
+ fc->lookup_child("RBOBJECT",chlst);
+
+ for (LIF<char *> n(&(hdptr->object_names_store)); !n.done(); n.next())
+ {
+ for (LIF<Chunk *> l(&chlst); !l.done(); l.next())
+ {
+ ob = (Object_Chunk *)l();
+ if ( !strcmp(ob->object_data.o_name, n()) )
+ break;
+ }
+ if (!l.done())
+ assoc_with_object(ob);
+ else
+ {
+ return(FALSE);
+ }
+ }
+ return(TRUE);
+
+
+}
+
+BOOL Shape_Chunk::update_my_chunkshape (ChunkShape & cshp)
+{
+ // Firstly lose all the chunks that were with
+ // the old chunk shape
+ List <Chunk *> chlst;
+
+ lookup_child ("SHPRAWVT",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+ lookup_child ("SHPVNORM",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPPNORM",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPPOLYS",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPUVCRD",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPTEXFN",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+ *shape_data_store = cshp;
+
+ if (shape_data.v_list) new Shape_Vertex_Chunk (this, shape_data.num_verts);
+ if (shape_data.v_normal_list) new Shape_Vertex_Normal_Chunk (this, shape_data.num_verts);
+ if (shape_data.p_normal_list) new Shape_Polygon_Normal_Chunk (this, shape_data.num_polys);
+ if (shape_data.poly_list) new Shape_Polygon_Chunk (this, shape_data.num_polys);
+ if (shape_data.uv_list) new Shape_UV_Coord_Chunk (this, shape_data.num_uvs);
+ if (shape_data.texture_fns) new Shape_Texture_Filenames_Chunk (this, shape_data.num_texfiles);
+
+
+ //calculate the shape's centre and radius_about_centre
+ shape_data_store->centre=(shape_data_store->min+shape_data_store->max)/2;
+ shape_data_store->radius_about_centre=0;
+ for(int i=0;i<shape_data_store->num_verts;i++)
+ {
+ float length = (float) mod(shape_data_store->v_list[i]-shape_data_store->centre);
+ if(length>shape_data_store->radius_about_centre)
+ {
+ shape_data_store->radius_about_centre=length;
+ }
+ }
+
+ //if the shape hasn't got a Shape_Centre_Chunk , create one.
+
+ if(!lookup_single_child("SHPCENTR"))
+ {
+ new Shape_Centre_Chunk(this);
+ }
+
+
+ return TRUE;
+}
+
+Console_Shape_Chunk* Shape_Chunk::get_console_shape_data(Console_Type ct)
+{
+ List<Chunk*> chlist;
+ lookup_child("CONSHAPE",chlist);
+ for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
+ {
+ Console_Shape_Chunk* csc=(Console_Shape_Chunk*)chlif();
+ List<Chunk*> chlist2;
+ csc->lookup_child("CONSTYPE",chlist2);
+ if(chlist2.size())
+ {
+ if(((Console_Type_Chunk*)chlist2.first_entry())->console==ct)
+ return csc;
+ }
+ }
+
+ return 0;//no console specific shape data
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Vertex_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+
+// from buffer
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPRAWVT",Shape_Vertex_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPRAWVT",Shape_Vertex_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPRAWVT",Shape_Vertex_Chunk,"ANIMFRAM",Anim_Shape_Frame_Chunk)
+
+Shape_Vertex_Chunk::Shape_Vertex_Chunk(Shape_Chunk * parent, const char * vtdata , size_t vtsize)
+: Chunk (parent, "SHPRAWVT"), vert_data (NULL),
+ num_verts (vtsize / 12) // 12 bytes per vertex
+{
+ int i;
+
+ parent->shape_data_store->v_list = new ChunkVectorInt[num_verts];
+ parent->shape_data_store->num_verts = num_verts;
+
+ *((ChunkVectorInt**) &vert_data) = parent->shape_data_store->v_list;
+
+ for (i=0;i<num_verts;i++)
+ {
+ parent->shape_data_store->v_list[i] = *((ChunkVectorInt *) vtdata );
+ vtdata+=sizeof(ChunkVectorInt);
+ }
+
+}
+
+
+Shape_Vertex_Chunk::Shape_Vertex_Chunk(Shape_Sub_Shape_Chunk * parent, const char * vtdata , size_t vtsize)
+: Chunk (parent, "SHPRAWVT"), vert_data (NULL),
+ num_verts (vtsize / 12) // 12 bytes per vertex
+{
+ int i;
+
+ parent->shape_data_store->v_list = new ChunkVectorInt[num_verts];
+ parent->shape_data_store->num_verts = num_verts;
+
+ *((ChunkVectorInt**) &vert_data) = parent->shape_data_store->v_list;
+
+ for (i=0;i<num_verts;i++)
+ {
+ parent->shape_data_store->v_list[i] = *((ChunkVectorInt *) vtdata );
+ vtdata+=sizeof(ChunkVectorInt);
+ }
+
+}
+
+
+Shape_Vertex_Chunk::Shape_Vertex_Chunk(Anim_Shape_Frame_Chunk * parent, const char * vtdata , size_t vtsize)
+: Chunk (parent, "SHPRAWVT"), vert_data (NULL),
+ num_verts (vtsize / 12) // 12 bytes per vertex
+{
+ int i;
+
+ ChunkVectorInt* v_list = new ChunkVectorInt[num_verts];
+ *(ChunkVectorInt**)&vert_data=v_list;
+
+ for (i=0;i<num_verts;i++)
+ {
+ v_list[i] = *((ChunkVectorInt *) vtdata );
+ vtdata+=sizeof(ChunkVectorInt);
+ }
+
+}
+
+BOOL Shape_Vertex_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+
+}
+
+void Shape_Vertex_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ for (int i=0;i<num_verts;i++)
+ {
+ *(ChunkVectorInt *) data_start = vert_data[i];
+ data_start+=sizeof(ChunkVectorInt);
+
+ }
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Vertex_Normal_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPVNORM",Shape_Vertex_Normal_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPVNORM",Shape_Vertex_Normal_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+
+// from buffer
+Shape_Vertex_Normal_Chunk::Shape_Vertex_Normal_Chunk(Shape_Chunk * parent, const char * vtdata , size_t vtsize)
+: Chunk (parent, "SHPVNORM"), vert_norm_data (NULL),
+ num_verts (vtsize / sizeof(ChunkVectorInt))
+{
+ int i;
+
+ parent->shape_data_store->v_normal_list = new ChunkVectorFloat[num_verts];
+ *((ChunkVectorFloat**) &vert_norm_data) = parent->shape_data_store->v_normal_list;
+
+ for (i=0;i<num_verts;i++)
+ {
+ parent->shape_data_store->v_normal_list[i] = *((ChunkVectorFloat *) vtdata);
+ vtdata+=sizeof(ChunkVectorFloat);
+ }
+
+}
+
+Shape_Vertex_Normal_Chunk::Shape_Vertex_Normal_Chunk(Shape_Sub_Shape_Chunk * parent, const char * vtdata , size_t vtsize)
+: Chunk (parent, "SHPVNORM"), vert_norm_data (NULL),
+ num_verts (vtsize / sizeof(ChunkVectorInt))
+{
+ int i;
+
+ parent->shape_data_store->v_normal_list = new ChunkVectorFloat[num_verts];
+ *((ChunkVectorFloat**) &vert_norm_data) = parent->shape_data_store->v_normal_list;
+
+ for (i=0;i<num_verts;i++)
+ {
+ parent->shape_data_store->v_normal_list[i] = *((ChunkVectorFloat *) vtdata );
+ vtdata+=sizeof(ChunkVectorFloat);
+ }
+
+}
+
+BOOL Shape_Vertex_Normal_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+
+}
+
+void Shape_Vertex_Normal_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ for (int i=0;i<num_verts;i++)
+ {
+ *((ChunkVectorFloat *) data_start ) = vert_norm_data[i];
+ data_start+=sizeof(ChunkVectorFloat);
+ }
+
+}
+/////////////////////////////////////////
+
+// Class Shape_Polygon_Normal_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPPNORM",Shape_Polygon_Normal_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPPNORM",Shape_Polygon_Normal_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPPNORM",Shape_Polygon_Normal_Chunk,"ANIMFRAM",Anim_Shape_Frame_Chunk)
+
+// from buffer
+Shape_Polygon_Normal_Chunk::Shape_Polygon_Normal_Chunk(Shape_Chunk * parent, const char * pndata , size_t pnsize)
+: Chunk (parent, "SHPPNORM"), poly_norm_data (NULL),
+ num_polys (pnsize / sizeof(ChunkVectorFloat))
+{
+ int i;
+
+ parent->shape_data_store->p_normal_list = new ChunkVectorFloat[num_polys];
+ *((ChunkVectorFloat**) &poly_norm_data) = parent->shape_data_store->p_normal_list;
+
+ for (i=0;i<num_polys;i++)
+ {
+ parent->shape_data_store->p_normal_list[i] = *((ChunkVectorFloat *) pndata );
+ pndata+=sizeof(ChunkVectorFloat);
+ }
+
+}
+
+Shape_Polygon_Normal_Chunk::Shape_Polygon_Normal_Chunk(Shape_Sub_Shape_Chunk * parent, const char * pndata , size_t pnsize)
+: Chunk (parent, "SHPPNORM"), poly_norm_data (NULL),
+ num_polys (pnsize / sizeof(ChunkVectorFloat))
+{
+ int i;
+
+ parent->shape_data_store->p_normal_list = new ChunkVectorFloat[num_polys];
+ *((ChunkVectorFloat**) &poly_norm_data) = parent->shape_data_store->p_normal_list;
+
+ for (i=0;i<num_polys;i++)
+ {
+ parent->shape_data_store->p_normal_list[i] = *((ChunkVectorFloat *) pndata );
+ pndata+=sizeof(ChunkVectorFloat);
+ }
+
+}
+
+Shape_Polygon_Normal_Chunk::Shape_Polygon_Normal_Chunk(Anim_Shape_Frame_Chunk * parent, const char * pndata , size_t pnsize)
+: Chunk (parent, "SHPPNORM"), poly_norm_data (NULL),
+ num_polys (pnsize / sizeof(ChunkVectorFloat))
+{
+ int i;
+
+ ChunkVectorFloat* p_normal_list = new ChunkVectorFloat[num_polys];
+ *((ChunkVectorFloat**) &poly_norm_data) = p_normal_list;
+
+ for (i=0;i<num_polys;i++)
+ {
+ p_normal_list[i] = *((ChunkVectorFloat *) pndata );
+ pndata+=sizeof(ChunkVectorFloat);
+ }
+
+}
+
+BOOL Shape_Polygon_Normal_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+
+}
+
+void Shape_Polygon_Normal_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ for (int i=0;i<num_polys;i++)
+ {
+ *(ChunkVectorFloat *) data_start = poly_norm_data[i];
+ data_start+=sizeof(ChunkVectorFloat);
+ }
+
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Polygon_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPPOLYS",Shape_Polygon_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPPOLYS",Shape_Polygon_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPPOLYS",Shape_Polygon_Chunk,"CONSHAPE",Console_Shape_Chunk)
+
+// from buffer
+Shape_Polygon_Chunk::Shape_Polygon_Chunk (Shape_Chunk * parent, const char * pdata, size_t psize)
+: Chunk (parent, "SHPPOLYS"),
+ poly_data (parent->shape_data_store->poly_list), num_polys (psize / 36) // 9 * 4 bytes per polygon
+{
+ int i, j;
+
+ parent->shape_data_store->poly_list = new ChunkPoly [num_polys];
+ parent->shape_data_store->num_polys = num_polys;
+
+ *((ChunkPoly **) &poly_data) = parent->shape_data_store->poly_list;
+
+ for (i=0; i<num_polys; i++)
+ {
+ parent->shape_data_store->poly_list[i].engine_type = *((int *) (pdata + (36*i)));
+ parent->shape_data_store->poly_list[i].normal_index = *((int *) (pdata + (36*i) + 4));
+ parent->shape_data_store->poly_list[i].flags = *((int *) (pdata + (36*i) + 8));
+ parent->shape_data_store->poly_list[i].colour = *((int *) (pdata + (36*i) + 12));
+
+ parent->shape_data_store->poly_list[i].num_verts = 0;
+
+ for (j=0; *((int *) (pdata + (36*i) + 16 + (j*4))) != -1; j++)
+ {
+ parent->shape_data_store->poly_list[i].vert_ind[j] = *((int *) (pdata + (36*i) + 16 + (j*4)));
+ parent->shape_data_store->poly_list[i].num_verts++;
+ }
+
+ }
+
+}
+
+Shape_Polygon_Chunk::Shape_Polygon_Chunk (Shape_Sub_Shape_Chunk * parent, const char * pdata, size_t psize)
+: Chunk (parent, "SHPPOLYS"),
+ poly_data (parent->shape_data_store->poly_list), num_polys (psize / 36) // 9 * 4 bytes per polygon
+{
+ int i, j;
+
+ parent->shape_data_store->poly_list = new ChunkPoly [num_polys];
+ parent->shape_data_store->num_polys = num_polys;
+
+ *((ChunkPoly **) &poly_data) = parent->shape_data_store->poly_list;
+
+ for (i=0; i<num_polys; i++)
+ {
+ parent->shape_data_store->poly_list[i].engine_type = *((int *) (pdata + (36*i)));
+ parent->shape_data_store->poly_list[i].normal_index = *((int *) (pdata + (36*i) + 4));
+ parent->shape_data_store->poly_list[i].flags = *((int *) (pdata + (36*i) + 8));
+ parent->shape_data_store->poly_list[i].colour = *((int *) (pdata + (36*i) + 12));
+
+ parent->shape_data_store->poly_list[i].num_verts = 0;
+
+ for (j=0; *((int *) (pdata + (36*i) + 16 + (j*4))) != -1; j++)
+ {
+ parent->shape_data_store->poly_list[i].vert_ind[j] = *((int *) (pdata + (36*i) + 16 + (j*4)));
+ parent->shape_data_store->poly_list[i].num_verts++;
+ }
+
+ }
+
+}
+
+Shape_Polygon_Chunk::Shape_Polygon_Chunk (Console_Shape_Chunk * parent, const char * pdata, size_t psize)
+: Chunk (parent, "SHPPOLYS"),
+ poly_data(0), num_polys (psize / 36) // 9 * 4 bytes per polygon
+{
+ int i, j;
+
+ ChunkPoly* poly_list = new ChunkPoly [num_polys];
+
+ *((ChunkPoly **) &poly_data) =poly_list;
+
+ for (i=0; i<num_polys; i++)
+ {
+ poly_list[i].engine_type = *((int *) (pdata + (36*i)));
+ poly_list[i].normal_index = *((int *) (pdata + (36*i) + 4));
+ poly_list[i].flags = *((int *) (pdata + (36*i) + 8));
+ poly_list[i].colour = *((int *) (pdata + (36*i) + 12));
+
+ poly_list[i].num_verts = 0;
+
+ for (j=0; *((int *) (pdata + (36*i) + 16 + (j*4))) != -1; j++)
+ {
+ poly_list[i].vert_ind[j] = *((int *) (pdata + (36*i) + 16 + (j*4)));
+ poly_list[i].num_verts++;
+ }
+
+ }
+
+}
+
+BOOL Shape_Polygon_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+
+}
+
+void Shape_Polygon_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ for (int i=0;i<num_polys;i++) {
+ *((int *) (data_start + i*36)) = poly_data[i].engine_type;
+ *((int *) (data_start + i*36 + 4)) = poly_data[i].normal_index;
+ *((int *) (data_start + i*36 + 8)) = poly_data[i].flags;
+ *((int *) (data_start + i*36 + 12)) = poly_data[i].colour;
+ for (int j = 0; j<poly_data[i].num_verts; j++)
+ *((int *) (data_start + i*36 + 16 + j*4)) = poly_data[i].vert_ind[j];
+ for (; j<5; j++)
+ *((int *) (data_start + i*36 + 16 + j*4)) = -1;
+
+ }
+
+}
+/////////////////////////////////////////
+//Class Shape_Centre_Chunk :
+
+RIF_IMPLEMENT_DYNCREATE("SHPCENTR",Shape_Centre_Chunk)
+
+Shape_Centre_Chunk::Shape_Centre_Chunk(Chunk_With_Children* parent,const char* data, size_t datasize)
+:Chunk (parent,"SHPCENTR")
+{
+ assert(datasize==16);
+
+ //find parent's chunkshape
+ ChunkShape* cs=0;
+ if(!strcmp(parent->identifier,"REBSHAPE"))
+ {
+ cs=((Shape_Chunk*)parent)->shape_data_store;
+ }
+ else if(!strcmp(parent->identifier,"SUBSHAPE"))
+ {
+ cs=((Shape_Sub_Shape_Chunk*)parent)->shape_data_store;
+ }
+ assert(cs);
+
+ //fill in the appropriate entries
+ cs->centre=*(ChunkVectorInt*)data;
+ data+=sizeof(ChunkVectorInt);
+
+ cs->radius_about_centre=*(float*)data;
+}
+
+void Shape_Centre_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ //find parent's chunkshape
+ ChunkShape* cs=0;
+ if(!strcmp(parent->identifier,"REBSHAPE"))
+ {
+ cs=((Shape_Chunk*)parent)->shape_data_store;
+ }
+ else if(!strcmp(parent->identifier,"SUBSHAPE"))
+ {
+ cs=((Shape_Sub_Shape_Chunk*)parent)->shape_data_store;
+ }
+ assert(cs);
+
+
+ *(ChunkVectorInt*)data_start=cs->centre;
+ data_start+=sizeof(ChunkVectorInt);
+
+ *(float*)data_start=cs->radius;
+}
+
+
+/////////////////////////////////////////
+
+// Class Shape_UV_Coord_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPUVCRD",Shape_UV_Coord_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPUVCRD",Shape_UV_Coord_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPUVCRD",Shape_UV_Coord_Chunk,"CONSHAPE",Console_Shape_Chunk)
+
+// from buffer
+Shape_UV_Coord_Chunk::Shape_UV_Coord_Chunk (Shape_Chunk * parent, const char * uvdata, size_t /*uvsize*/)
+: Chunk (parent, "SHPUVCRD"),
+uv_data (NULL), num_uvs (*((int *) uvdata))
+{
+ int i,j;
+
+ if (num_uvs)
+ {
+ parent->shape_data_store->uv_list = new ChunkUV_List[num_uvs];
+ }
+ else
+ {
+ parent->shape_data_store->uv_list = 0;
+ }
+ *((ChunkUV_List**) &uv_data) = parent->shape_data_store->uv_list;
+
+ parent->shape_data_store->num_uvs = num_uvs;
+
+ uvdata += 4;
+
+ for (i=0;i<num_uvs;i++)
+ {
+ parent->shape_data_store->uv_list[i].num_verts = *((int *) uvdata);
+ uvdata += 4;
+
+ for (j=0; j<parent->shape_data_store->uv_list[i].num_verts; j++)
+ {
+ parent->shape_data_store->uv_list[i].vert[j] = *((ChunkUV *)uvdata);
+ uvdata += sizeof(ChunkUV);
+ }
+ }
+
+}
+
+Shape_UV_Coord_Chunk::Shape_UV_Coord_Chunk (Shape_Sub_Shape_Chunk * parent, const char * uvdata, size_t /*uvsize*/)
+: Chunk (parent, "SHPUVCRD"),
+uv_data (NULL), num_uvs (*((int *) uvdata))
+{
+ int i,j;
+
+ parent->shape_data_store->uv_list = new ChunkUV_List[num_uvs];
+ *((ChunkUV_List**) &uv_data) = parent->shape_data_store->uv_list;
+
+ parent->shape_data_store->num_uvs = num_uvs;
+
+ uvdata += 4;
+
+ for (i=0;i<num_uvs;i++)
+ {
+ parent->shape_data_store->uv_list[i].num_verts = *((int *) uvdata);
+ uvdata += 4;
+
+ for (j=0; j<parent->shape_data_store->uv_list[i].num_verts; j++)
+ {
+ parent->shape_data_store->uv_list[i].vert[j] = *((ChunkUV *)uvdata);
+ uvdata += sizeof(ChunkUV);
+ }
+ }
+
+}
+
+Shape_UV_Coord_Chunk::Shape_UV_Coord_Chunk (Console_Shape_Chunk * parent, const char * uvdata, size_t /*uvsize*/)
+: Chunk (parent, "SHPUVCRD"),
+uv_data (NULL), num_uvs (*((int *) uvdata))
+{
+ int i,j;
+
+ ChunkUV_List* uv_list= new ChunkUV_List[num_uvs];
+ *((ChunkUV_List**) &uv_data) = uv_list;
+
+ uvdata += 4;
+
+ for (i=0;i<num_uvs;i++)
+ {
+ uv_list[i].num_verts = *((int *) uvdata);
+ uvdata += 4;
+
+ for (j=0; j<uv_list[i].num_verts; j++)
+ {
+ uv_list[i].vert[j] = *((ChunkUV *)uvdata);
+ uvdata += sizeof(ChunkUV);
+ }
+ }
+
+}
+
+Shape_UV_Coord_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+
+}
+
+
+void Shape_UV_Coord_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = num_uvs;
+
+ data_start += 4;
+
+ for (int i=0;i<num_uvs;i++)
+ {
+ *((int *)data_start) = uv_data[i].num_verts;
+ data_start += 4;
+ for (int j = 0; j< uv_data[i].num_verts; j++)
+ {
+ *((ChunkUV *) data_start) = uv_data[i].vert[j];
+ data_start += sizeof(ChunkUV);
+ }
+ }
+
+}
+
+size_t Shape_UV_Coord_Chunk::size_chunk ()
+{
+ chunk_size = 12 + 4;
+ for (int i=0; i<num_uvs; i++)
+ chunk_size += (4+(sizeof(ChunkUV)*uv_data[i].num_verts));
+
+ return chunk_size;
+
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Texture_Filenames_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPTEXFN",Shape_Texture_Filenames_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPTEXFN",Shape_Texture_Filenames_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+// from buffer
+Shape_Texture_Filenames_Chunk::Shape_Texture_Filenames_Chunk (Shape_Chunk * parent, const char * tfndata, size_t /*tfnsize*/)
+: Chunk (parent, "SHPTEXFN"),
+tex_fns (), num_tex_fns (*((int *) tfndata))
+{
+ int i;
+
+ parent->shape_data_store->texture_fns = new char * [num_tex_fns];
+ *((char***) &tex_fns) = parent->shape_data_store->texture_fns;
+
+ parent->shape_data_store->num_texfiles = num_tex_fns;
+
+ tfndata += 4;
+
+ for (i=0; i<num_tex_fns; i++) {
+ parent->shape_data_store->texture_fns[i] = new char [strlen(tfndata)+1];
+ strcpy (parent->shape_data_store->texture_fns[i], tfndata);
+ tfndata += (strlen(tfndata)+1);
+ }
+
+}
+
+Shape_Texture_Filenames_Chunk::Shape_Texture_Filenames_Chunk (Shape_Sub_Shape_Chunk * parent, const char * tfndata, size_t /*tfnsize*/)
+: Chunk (parent, "SHPTEXFN"),
+tex_fns (), num_tex_fns (*((int *) tfndata))
+{
+ int i;
+
+ parent->shape_data_store->texture_fns = new char * [num_tex_fns];
+ *((char***) &tex_fns) = parent->shape_data_store->texture_fns;
+
+ parent->shape_data_store->num_texfiles = num_tex_fns;
+
+ tfndata += 4;
+
+ for (i=0; i<num_tex_fns; i++) {
+ parent->shape_data_store->texture_fns[i] = new char [strlen(tfndata)+1];
+ strcpy (parent->shape_data_store->texture_fns[i], tfndata);
+ tfndata += (strlen(tfndata)+1);
+ }
+
+}
+
+Shape_Texture_Filenames_Chunk::output_chunk (HANDLE &hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+
+}
+
+
+void Shape_Texture_Filenames_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = num_tex_fns;
+
+ data_start += 4;
+
+ for (int i=0;i<num_tex_fns;i++) {
+ sprintf(data_start, "%s", tex_fns[i]);
+ data_start += (strlen (tex_fns[i]) + 1);
+ }
+
+}
+
+size_t Shape_Texture_Filenames_Chunk::size_chunk()
+{
+ chunk_size = 16;
+
+ for (int i=0;i<num_tex_fns;i++)
+ chunk_size += (strlen (tex_fns[i]) + 1);
+
+ chunk_size += (4-chunk_size%4)%4;
+
+ return chunk_size;
+
+}
+
+
+/////////////////////////////////////////
+
+// Class Shape_Header_Chunk functions
+
+// These can only be children of Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPHEAD1",Shape_Header_Chunk,"REBSHAPE",Shape_Chunk)
+
+
+Shape_Header_Chunk::Shape_Header_Chunk (Shape_Chunk * parent, const char * hdata, size_t /*hsize*/)
+ : Chunk (parent, "SHPHEAD1"),
+ shape_data (parent->shape_data_store)
+{
+ int num_as_obj;
+
+ flags = *((int *) hdata);
+
+ strncpy (lock_user, (hdata + 4), 16);
+ lock_user[16] = '\0';
+ hdata+=20;
+
+ file_id_num = *((int *) hdata );
+ hdata+=4;
+
+
+ parent->shape_data_store->num_verts = *((int *) hdata );
+ hdata+=4;
+ parent->shape_data_store->num_polys = *((int *) hdata );
+ hdata+=4;
+
+ parent->shape_data_store->radius = *((float *) hdata);
+ hdata+=4;
+
+ parent->shape_data_store->max.x = *((int *) hdata);
+ hdata+=4;
+ parent->shape_data_store->min.x = *((int *) hdata);
+ hdata+=4;
+
+ parent->shape_data_store->max.y = *((int *) hdata);
+ hdata+=4;
+ parent->shape_data_store->min.y = *((int *) hdata);
+ hdata+=4;
+
+ parent->shape_data_store->max.z = *((int *) hdata);
+ hdata+=4;
+ parent->shape_data_store->min.z = *((int *) hdata);
+ hdata+=4;
+
+ version_no = *((int *) hdata);
+ hdata+=4;
+
+ num_as_obj = *((int *) hdata);
+ hdata+=4;
+
+ char * obj_store;
+
+ for (int i = 0; i< num_as_obj; i++)
+ {
+ obj_store = new char [strlen (hdata) +1];
+ strcpy (obj_store, (hdata));
+ object_names_store.add_entry(obj_store);
+ hdata += (strlen (hdata)+1);
+ }
+
+}
+
+Shape_Header_Chunk::~Shape_Header_Chunk()
+{
+ for (LIF<char *> aon(&object_names_store);
+ !aon.done(); aon.next() )
+ delete [] aon();
+}
+
+size_t Shape_Header_Chunk::size_chunk()
+{
+ int length = 80;
+
+ for (LIF<char *> aon(&object_names_store);
+ !aon.done(); aon.next() )
+ length += (strlen (aon()) + 1);
+
+ length += (4-length%4)%4;
+
+ chunk_size = length;
+
+ return length;
+}
+
+BOOL Shape_Header_Chunk::output_chunk(HANDLE & hand)
+{
+ unsigned long junk;
+ BOOL ok;
+ char * data_block;
+
+ data_block = this->make_data_block_from_chunk();
+
+ ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
+
+ delete [] data_block;
+
+ if (!ok) return FALSE;
+
+ return TRUE;
+}
+
+void Shape_Header_Chunk::fill_data_block(char * data_start)
+{
+
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = flags;
+ strncpy ((data_start + 4), lock_user, 16);
+ *((int *) (data_start+20)) = file_id_num;
+ data_start+=24;
+
+ *((int *) data_start) = shape_data->num_verts;
+ data_start+=4;
+ *((int *) data_start) = shape_data->num_polys;
+ data_start+=4;
+
+ *((float *) data_start) = shape_data->radius;
+ data_start+=4;
+
+ *((int *) data_start) = shape_data->max.x;
+ data_start+=4;
+ *((int *) data_start) = shape_data->min.x;
+ data_start+=4;
+
+ *((int *) data_start) = shape_data->max.y;
+ data_start+=4;
+ *((int *) data_start) = shape_data->min.y;
+ data_start+=4;
+
+ *((int *) data_start) = shape_data->max.z;
+ data_start+=4;
+ *((int *) data_start) = shape_data->min.z;
+ data_start+=4;
+
+ *((int *) data_start) = version_no;
+ data_start+=4;
+
+ *((int *) data_start) = object_names_store.size();
+ data_start+=4;
+
+
+ for (LIF<char *> ons(&object_names_store); !ons.done(); ons.next())
+ {
+ strcpy (data_start, ons());
+ data_start += (strlen(ons())+1);
+ }
+
+}
+
+
+void Shape_Header_Chunk::prepare_for_output()
+{
+// this will also set the object chunks numbers as well,
+// so that it is done in the right order
+
+ char * str;
+
+ if (file_id_num == -1) file_id_num = ++(Shape_Chunk::max_id);
+
+ while (object_names_store.size()) {
+ delete [] object_names_store.first_entry();
+ object_names_store.delete_first_entry();
+ }
+
+ for (LIF<Object_Chunk *> aosl(&associated_objects_store);
+ !aosl.done(); aosl.next() ) {
+
+ if (aosl()->get_header())
+ aosl()->get_header()->shape_id_no = file_id_num;
+
+ str = new char [strlen(aosl()->object_data.o_name) + 1];
+ strcpy(str, aosl()->object_data.o_name);
+ object_names_store.add_entry(str);
+
+ }
+
+ Shape_Chunk::max_id = max(Shape_Chunk::max_id, file_id_num);
+
+// this should always be the last thing
+
+ version_no ++;
+}
+
+
+
+/////////////////////////////////////////
+
+// Class Shape_Merge_Data_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPMRGDT",Shape_Merge_Data_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPMRGDT",Shape_Merge_Data_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+
+Shape_Merge_Data_Chunk::Shape_Merge_Data_Chunk(Shape_Chunk * parent, int * m_dt, int n_ps)
+: Chunk (parent, "SHPMRGDT"), num_polys (n_ps)
+{
+ merge_data = new int [n_ps];
+ for (int i=0; i<n_ps; i++)
+ {
+ merge_data[i] = m_dt[i];
+ }
+
+}
+
+Shape_Merge_Data_Chunk::Shape_Merge_Data_Chunk(Shape_Sub_Shape_Chunk * parent, int * m_dt, int n_ps)
+: Chunk (parent, "SHPMRGDT"), num_polys (n_ps)
+{
+ merge_data = new int [n_ps];
+ for (int i=0; i<n_ps; i++)
+ {
+ merge_data[i] = m_dt[i];
+ }
+
+}
+
+
+Shape_Merge_Data_Chunk::Shape_Merge_Data_Chunk (Shape_Chunk * parent, const char *md, size_t ms)
+: Chunk (parent, "SHPMRGDT"), num_polys (ms/4)
+{
+
+ merge_data = new int [num_polys];
+ for (int i=0; i<num_polys; i++)
+ {
+ merge_data[i] = *((int *)(md+4*i));
+ }
+}
+
+Shape_Merge_Data_Chunk::Shape_Merge_Data_Chunk (Shape_Sub_Shape_Chunk * parent, const char *md, size_t ms)
+: Chunk (parent, "SHPMRGDT"), num_polys (ms/4)
+{
+
+ merge_data = new int [num_polys];
+ for (int i=0; i<num_polys; i++)
+ {
+ merge_data[i] = *((int *)(md+4*i));
+ }
+}
+
+
+Shape_Merge_Data_Chunk::~Shape_Merge_Data_Chunk()
+{
+ if (num_polys) delete merge_data;
+}
+
+void Shape_Merge_Data_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ for (int i=0; i<num_polys; i++)
+ {
+ *((int *) (data_start+i*4) ) = merge_data[i];
+ }
+
+}
+
+
+/////////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("SHPEXTFL",Shape_External_File_Chunk)
+
+/*
+Children for Shape_External_File_Chunk :
+
+"SHPEXTFN" Shape_External_Filename_Chunk)
+"BMPLSTST" Bitmap_List_Store_Chunk)
+"BMNAMVER" BMP_Names_Version_Chunk)
+"BMNAMEXT" BMP_Names_ExtraData_Chunk)
+"RIFFNAME" RIF_Name_Chunk)
+"BMPMD5ID" Bitmap_MD5_Chunk)
+"EXTOBJNM" Shape_External_Object_Name_Chunk)
+*/
+
+CHUNK_WITH_CHILDREN_LOADER("SHPEXTFL",Shape_External_File_Chunk)
+
+
+
+Shape_External_File_Chunk::Shape_External_File_Chunk (Chunk_With_Children * parent, const char * fname)
+:Chunk_With_Children (parent, "SHPEXTFL")
+{
+ new Shape_External_Filename_Chunk (this, fname);
+ post_input_processing();
+}
+
+#if cencon || InterfaceEngine
+
+void Shape_External_File_Chunk::update_from_external_rif(BOOL force_scale_update)
+{
+ if(UpdatingExternalShape)
+ {
+ return;
+ }
+
+ Shape_Chunk * parent_shp = (Shape_Chunk *) parent;
+
+ Environment_Data_Chunk * envd = 0;
+ envd = (Environment_Data_Chunk *) parent_shp->parent->lookup_single_child("REBENVDT");
+
+ BOOL fixpal = IsFixedPalette(envd);
+
+ List<Chunk *> chlst;
+ lookup_child("SHPEXTFN",chlst);
+
+ if (chlst.size())
+ {
+ UpdatingExternalShape=TRUE;
+
+ Shape_External_Filename_Chunk * sefc = (Shape_External_Filename_Chunk *)chlst.first_entry();
+
+ #if cencon
+ twprintf("Locating %s\n",sefc->file_name);
+ char * locatedfile = FindExistingFileInPath_PreferWriteable(CWnd::GetActiveWindow(),sefc->file_name,"RifSearchPath");
+ twprintf("Loading %s\n",locatedfile ? locatedfile : sefc->file_name);
+ RIF_File_Chunk * rfc = new RIF_File_Chunk (this, locatedfile ? locatedfile : sefc->file_name);
+ #elif InterfaceEngine
+ RIF_File_Chunk * rfc;
+ char * locatedfile = FindExistingFile_PreferWriteable(sefc->file_name,"RifSearchPath",FALSE);
+ if (locatedfile)
+ {
+ rfc = new RIF_File_Chunk (this, locatedfile);
+ }
+ else
+ {
+ UpdatingExternalShape=FALSE;
+ return;
+ }
+ #endif
+
+ //Now loaded external file,so UpdatingExternalShape can now be reset
+ UpdatingExternalShape=FALSE;
+
+ if (rfc->error_code != 0)
+ {
+ #if cencon
+ extern BOOL SuppressFailedToFindShapeRifErrors;
+
+ if(!SuppressFailedToFindShapeRifErrors)
+ {
+ char message[300];
+ sprintf(message,"Error loading shape rif : %s",locatedfile ? locatedfile : sefc->file_name);
+ twMessageBox(CWnd::GetActiveWindow(),message,"Tools Control Area", MB_TASKMODAL+MB_OK+MB_ICONHAND);
+ }
+ #endif
+ if (locatedfile)
+ {
+ delete[] locatedfile;
+ }
+ delete rfc;
+ return;
+ }
+
+ Shape_Chunk* shp=0;
+ lookup_child("EXTOBJNM",chlst);
+
+
+ if(chlst.size())
+ {
+ //we have an object name so we need to search for the correct object in the file
+ Shape_External_Object_Name_Chunk* seonm=(Shape_External_Object_Name_Chunk*) chlst.first_entry();
+
+ rfc->lookup_child("RBOBJECT",chlst);
+ for(LIF<Chunk*> chlif(&chlst);!chlif.done();chlif.next())
+ {
+ Object_Chunk* oc=(Object_Chunk*)chlif();
+ if(!strcmp(oc->object_data.o_name,seonm->object_name))break;
+ }
+ if(chlif.done())
+ {
+ //can't find the object
+ #if cencon
+ char message[300];
+ sprintf(message,"Failed to find %s in %s\n(There may be several different rif files with the same name)",seonm->object_name,locatedfile);
+ twMessageBox(CWnd::GetActiveWindow(),message,"Tools Control Area", MB_TASKMODAL+MB_OK+MB_ICONHAND);
+ #endif
+ delete [] locatedfile;
+ delete rfc;
+ return;
+ }
+
+ shp=((Object_Chunk*)chlif())->get_assoc_shape();
+ }
+ else
+ {
+ //no object name,so there has to be just one shape in the file
+ rfc->lookup_child("REBSHAPE",chlst);
+
+ if (chlst.size() != 1)
+ {
+ #if cencon
+ char message[300];
+ sprintf(message,"There are %d shapes in %s\n(There should only be one)\n",chlst.size(),locatedfile);
+ twMessageBox(CWnd::GetActiveWindow(),message,"Tools Control Area", MB_TASKMODAL+MB_OK+MB_ICONHAND);
+ #endif
+ Environment_Data_Chunk * edc = 0;
+ edc = (Environment_Data_Chunk *)rfc->lookup_single_child("REBENVDT");
+ if(edc)
+ {
+ lookup_child("RIFFNAME",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+ edc->lookup_child("RIFFNAME",chlst);
+
+ if (chlst.size())
+ {
+ new RIF_Name_Chunk (this, ((RIF_Name_Chunk *)chlst.first_entry())->rif_name);
+ }
+ }
+ delete [] locatedfile;
+ delete rfc;
+ return;
+ }
+
+ shp = (Shape_Chunk *)chlst.first_entry();
+ }
+ delete [] locatedfile;
+ locatedfile=0;
+
+ // set so that it updates it whatever
+
+ if (shp->get_header()->version_no != sefc->version_no || TRUE)
+ {
+ //if the shape doesn't have any associated objects,get scale from external file's
+ //environment scale chunk.
+ //also get scale if force_scale_update is true
+ if(parent_shp->list_assoc_objs().size()==0 || force_scale_update)
+ {
+ if(force_scale_update)
+ {
+ sefc->rescale=1;
+ }
+ List<Chunk*> chlist=rfc->lookup_child("REBENVDT");
+ if(chlist.size())
+ {
+ chlist=((Chunk_With_Children*)chlist.first_entry())->lookup_child("ENVSDSCL");
+ if(chlist.size())
+ {
+ Environment_Scale_Chunk* esc =(Environment_Scale_Chunk*)chlist.first_entry();
+ sefc->rescale=esc->scale;
+ }
+ }
+ }
+ // copy all the data over from the loaded shape into the parent
+ ChunkShape cs = shp->shape_data;
+
+ cs.rescale(sefc->rescale);
+
+
+ // here we may want to sort out texture index nos.
+
+
+ // hmmm fix me
+ // definitely fixme...
+ // everytime the file is loaded,
+ // the shape is updated, and its bmps
+ // and thus the palette-up-to-date flag is reset,
+ // and the machine reckons on a new palette.
+
+ parent_shp->local_lock = TRUE;
+
+ parent_shp->update_my_chunkshape (cs);
+
+ parent_shp->local_lock = FALSE;
+
+ // delete all other chunks in the parent shape
+ // apart form the header !!!!
+
+ parent_shp->destroy_auxiliary_chunks();
+
+ char * tempbuffer;
+ Chunk* child_chunk;
+
+ child_chunk=shp->lookup_single_child("SHPZSPDT");
+ if (child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Shape_ZSP_Data_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+
+ child_chunk = shp->lookup_single_child("SHPMRGDT");
+ if (child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Shape_Merge_Data_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+
+ child_chunk = shp->lookup_single_child("SHPMORPH");
+ if (child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Shape_Morphing_Data_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+
+ child_chunk = shp->lookup_single_child("TEXTANIM");
+ if (child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Animation_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+
+ child_chunk = shp->lookup_single_child("SHPPCINF");
+ if (child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Shape_Poly_Change_Info_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+
+
+ child_chunk = shp->lookup_single_child("SHPFRAGS");
+ if (child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ Shape_Fragments_Chunk * sfc = new Shape_Fragments_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+
+ List<Chunk *> cl2;
+ sfc->lookup_child("SUBSHAPE",cl2);
+
+ for (LIF<Chunk *> cli2(&cl2); !cli2.done(); cli2.next())
+ {
+ Shape_Sub_Shape_Chunk * sssc = (Shape_Sub_Shape_Chunk *)cli2();
+
+ ChunkShape sscs = sssc->shape_data;
+ sscs.rescale(sefc->rescale);
+ sssc->update_my_chunkshape (sscs);
+
+ Shape_Fragment_Location_Chunk * sflc = (Shape_Fragment_Location_Chunk *)sssc->lookup_single_child("FRAGLOCN");
+ if (sflc)
+ {
+ sflc->frag_loc.x =(int) (sflc->frag_loc.x*sefc->rescale);
+ sflc->frag_loc.y =(int) (sflc->frag_loc.y*sefc->rescale);
+ sflc->frag_loc.z =(int) (sflc->frag_loc.z*sefc->rescale);
+ }
+
+ }
+
+ delete [] tempbuffer;
+ }
+
+ shp->lookup_child("ANIMSEQU",chlst);
+ for(LIF<Chunk*> chlif(&chlst);!chlif.done();chlif.next())
+ {
+ Anim_Shape_Sequence_Chunk* assc=(Anim_Shape_Sequence_Chunk*)chlif();
+ new Anim_Shape_Sequence_Chunk(parent_shp,&assc->sequence_data);
+ }
+
+ child_chunk = shp->lookup_single_child("PNOTINBB");
+ if(child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Poly_Not_In_Bounding_Box_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+ child_chunk = shp->lookup_single_child("ANSHCEN2");
+ if(child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Anim_Shape_Centre_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+ child_chunk = shp->lookup_single_child("ASALTTEX");
+ if(child_chunk)
+ {
+ tempbuffer = child_chunk->make_data_block_from_chunk();
+ new Anim_Shape_Alternate_Texturing_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ delete [] tempbuffer;
+ }
+ shp->lookup_child("CONSHAPE",chlst);
+ for(chlif.restart();!chlif.done();chlif.next())
+ {
+ tempbuffer = chlif()->make_data_block_from_chunk();
+ Console_Shape_Chunk* csc=new Console_Shape_Chunk (parent_shp, (tempbuffer + 12), (*(int *) (tempbuffer + 8))-12);
+ csc->generate_console_chunkshape();
+ delete [] tempbuffer;
+ }
+
+ parent_shp->updated = TRUE;
+
+ sefc->version_no = shp->get_header()->version_no;
+
+ }
+
+ Bitmap_List_Store_Chunk * blsc = 0;
+
+ Global_BMP_Name_Chunk * gbnc = 0;
+
+ Environment_Data_Chunk * edc = 0;
+
+ edc = (Environment_Data_Chunk *)rfc->lookup_single_child("REBENVDT");
+
+
+ if (edc)
+ {
+ gbnc = (Global_BMP_Name_Chunk *) edc->lookup_single_child("BMPNAMES");
+ if (gbnc)
+ {
+ if (!gbnc->bmps.size()) gbnc = 0;
+ }
+
+ List<Chunk *> oldlst;
+ lookup_child("BMPLSTST",oldlst);
+ if (oldlst.size()>1)
+ {
+ while (oldlst.size())
+ {
+ delete oldlst.first_entry();
+ oldlst.delete_first_entry();
+ }
+ }
+
+ if (oldlst.size())
+ {
+ blsc = (Bitmap_List_Store_Chunk *)oldlst.first_entry();
+ }
+ else
+ {
+ if (gbnc) blsc = new Bitmap_List_Store_Chunk(this);
+ }
+
+ BMP_Names_ExtraData * extended = 0;
+ if (blsc)
+ {
+ extended = blsc->GetExtendedData();
+ if (fixpal)
+ extended->flags = (GlobalBMPFlags)(extended->flags | GBF_FIXEDPALETTE);
+ else
+ extended->flags = (GlobalBMPFlags)(extended->flags & ~GBF_FIXEDPALETTE);
+ }
+ if (gbnc)
+ {
+ //if ((gbnc->get_version_num()!=blsc->get_version_num()) || (gbnc->bmps.size() != blsc->bmps.size()))
+ /*update regardless of version number*/
+ { // other checks could be done as well
+ if (blsc->bmps.size())
+ {
+ BOOL neednewpalette = FALSE;
+
+ List<BMP_Name> newlist = gbnc->bmps;
+ for (LIF<BMP_Name> newLIF(&newlist); !newLIF.done(); newLIF.next())
+ {
+ BMP_Name newcur = newLIF();
+ newcur.flags = (BMPN_Flags) (newcur.flags & ~(COMPLETED_BMPN_FLAGS | ChunkBMPFlag_FixedPalette));
+ if (fixpal) newcur.flags = (BMPN_Flags) (newcur.flags | ChunkBMPFlag_FixedPalette);
+ for (LIF<BMP_Name> oldLIF(&blsc->bmps); !oldLIF.done(); oldLIF.next())
+ {
+ BMP_Name oldcur = oldLIF();
+ if (newcur == oldcur)
+ {
+ // do we need to requantize?
+ if ((oldcur.flags ^ newcur.flags) & CHECKMODIFY_BMPN_FLAGS
+ || newcur.flags & ChunkBMPFlag_UsesTransparency
+ && !(newcur.flags & ChunkBMPFlag_IFF)
+ && !(oldcur.flags & ChunkBMPFlag_IFF)
+ && oldcur.DifferentTransparencyColour(newcur))
+ oldcur.flags = (BMPN_Flags)(oldcur.flags & ~COMPLETED_BMPN_FLAGS);
+ // keep some of the old flags - the ones that can differ
+ newcur.flags = (BMPN_Flags)(newcur.flags & COPY_BMPN_FLAGS);
+ newcur.flags = (BMPN_Flags)(newcur.flags | oldcur.flags & ~COPY_BMPN_FLAGS);
+ if (oldcur.version_num != newcur.version_num)
+ {
+ neednewpalette = TRUE;
+ newcur.flags = (BMPN_Flags)(newcur.flags & ~ChunkBMPFlag_HistogramExists);
+ extended->flags = (GlobalBMPFlags)(extended->flags & ~GBF_HISTOGRAMEXISTS);
+ }
+ break;
+ }
+ }
+ if (oldLIF.done())
+ {
+ // reset palette up to date flag
+ neednewpalette = TRUE;
+ newcur.flags = (BMPN_Flags)(newcur.flags & ~(ChunkBMPFlag_HistogramExists | COMPLETED_BMPN_FLAGS));
+ extended->flags = (GlobalBMPFlags)(extended->flags & ~GBF_HISTOGRAMEXISTS);
+ }
+ newLIF.change_current(newcur);
+ }
+
+ // check if any bitmaps have been removed
+ for (LIF<BMP_Name> bli(&blsc->bmps); !bli.done(); bli.next())
+ {
+ if (!newlist.contains(bli()))
+ {
+ // delete assoc files
+ neednewpalette = TRUE;
+ extended->flags = (GlobalBMPFlags)(extended->flags & ~GBF_HISTOGRAMEXISTS);
+ }
+ }
+
+ if (neednewpalette)
+ {
+ Palette_Outdated(envd);
+ if (fixpal) FixedPalette_Outdated(envd);
+ envd->updated = TRUE;
+ }
+ blsc->bmps = newlist;
+ }
+ else
+ {
+ blsc->bmps = gbnc->bmps;
+ for (LIF<BMP_Name> flagresetLIF(&blsc->bmps); !flagresetLIF.done(); flagresetLIF.next())
+ {
+ BMP_Name current = flagresetLIF();
+ current.flags = (BMPN_Flags)(current.flags & (COPY_BMPN_FLAGS & ~ChunkBMPFlag_FixedPalette));
+ if (fixpal) current.flags = (BMPN_Flags) (current.flags | ChunkBMPFlag_FixedPalette);
+ flagresetLIF.change_current(current);
+ }
+ // reset palette up to date flag
+ extended->flags = (GlobalBMPFlags)(extended->flags & ~GBF_HISTOGRAMEXISTS);
+ Palette_Outdated(envd);
+ if (fixpal) FixedPalette_Outdated(envd);
+ envd->updated = TRUE;
+ }
+ blsc->max_index = gbnc->max_index;
+ blsc->set_version_num(gbnc->get_version_num());
+ parent_shp->updated = TRUE;
+ }
+ }
+ else
+ {
+ if (blsc)
+ {
+ if (blsc->bmps.size())
+ {
+ // reset palette up to date flag
+ extended->flags = (GlobalBMPFlags)(extended->flags & ~GBF_HISTOGRAMEXISTS);
+ Palette_Outdated(envd);
+ if (fixpal) FixedPalette_Outdated(envd);
+ envd->updated = TRUE;
+ parent_shp->updated = TRUE;
+ }
+ delete blsc;
+ }
+ }
+ }
+
+ lookup_child("RIFFNAME",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+ if (edc)
+ {
+ edc->lookup_child("RIFFNAME",chlst);
+
+ if (chlst.size())
+ {
+ new RIF_Name_Chunk (this, ((RIF_Name_Chunk *)chlst.first_entry())->rif_name);
+ }
+
+ }
+
+ delete rfc;
+ }
+
+}
+
+void Shape_External_File_Chunk::post_input_processing()
+{
+
+ update_from_external_rif(FALSE);
+ Chunk_With_Children::post_input_processing();
+
+}
+#else
+void Shape_External_File_Chunk::post_input_processing()
+{
+ Chunk_With_Children::post_input_processing();
+}
+#endif
+
+const char* Shape_External_File_Chunk::get_shape_name()
+{
+ Shape_External_Object_Name_Chunk* seonc=(Shape_External_Object_Name_Chunk*)lookup_single_child("EXTOBJNM");
+ if(seonc)
+ {
+ return seonc->shape_name;
+ }
+
+ RIF_Name_Chunk* rnc=(RIF_Name_Chunk*)lookup_single_child("RIFFNAME");
+ if(rnc)
+ {
+ return rnc->rif_name;
+ }
+
+ return 0;
+
+}
+
+/////////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("SHPEXTFN",Shape_External_Filename_Chunk)
+
+Shape_External_Filename_Chunk::Shape_External_Filename_Chunk(Chunk_With_Children * parent, const char * fname)
+: Chunk (parent, "SHPEXTFN")
+{
+ file_name = new char [strlen(fname)+1];
+ strcpy (file_name, fname);
+
+ rescale = 1;
+ version_no = -1;
+
+}
+
+Shape_External_Filename_Chunk::Shape_External_Filename_Chunk (Chunk_With_Children * parent, const char *fdata, size_t /*fsize*/)
+: Chunk (parent, "SHPEXTFN")
+{
+ rescale = *((double *) fdata);
+ fdata += 8;
+ version_no = *((int *) fdata);
+ fdata += 4;
+ file_name = new char [strlen(fdata)+1];
+ strcpy (file_name, fdata);
+}
+
+Shape_External_Filename_Chunk::~Shape_External_Filename_Chunk()
+{
+ if (file_name)
+ delete [] file_name;
+}
+
+void Shape_External_Filename_Chunk::fill_data_block (char *data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((double *) data_start) = rescale;
+
+ data_start += 8;
+
+ *((int *) data_start) = version_no;
+
+ data_start += 4;
+
+ strcpy (data_start, file_name);
+
+}
+
+///////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("EXTOBJNM",Shape_External_Object_Name_Chunk)
+
+Shape_External_Object_Name_Chunk::Shape_External_Object_Name_Chunk(Chunk_With_Children * parent, const char * oname)
+: Chunk (parent, "EXTOBJNM")
+{
+ object_name = new char [strlen(oname)+1];
+ shape_name=0;
+ strcpy (object_name, oname);
+ pad=0;
+
+ RIF_Name_Chunk* rnc=(RIF_Name_Chunk*)parent->lookup_single_child("RIFFNAME");
+ if(rnc)
+ {
+ shape_name=new char[strlen(object_name)+strlen(rnc->rif_name)+2];
+ sprintf(shape_name,"%s@%s",object_name,rnc->rif_name);
+ }
+ else
+ {
+ shape_name=new char[strlen(object_name)+10+2];
+ sprintf(shape_name,"%s@*NotFound*",object_name);
+ }
+}
+
+Shape_External_Object_Name_Chunk::Shape_External_Object_Name_Chunk (Chunk_With_Children * parent, const char *data, size_t /*fsize*/)
+: Chunk (parent, "EXTOBJNM")
+{
+ pad=*(int*)data;
+ data+=4;
+ object_name = new char [strlen(data)+1];
+ strcpy (object_name, data);
+ shape_name=0;
+}
+
+Shape_External_Object_Name_Chunk::~Shape_External_Object_Name_Chunk()
+{
+ if (object_name)
+ delete [] object_name;
+ if(shape_name)
+ delete [] shape_name;
+}
+
+void Shape_External_Object_Name_Chunk::post_input_processing()
+{
+ RIF_Name_Chunk* rnc=(RIF_Name_Chunk*)parent->lookup_single_child("RIFFNAME");
+ if(rnc)
+ {
+ shape_name=new char[strlen(object_name)+strlen(rnc->rif_name)+2];
+ sprintf(shape_name,"%s@%s",object_name,rnc->rif_name);
+ }
+ else
+ {
+ shape_name=new char[strlen(object_name)+10+2];
+ sprintf(shape_name,"%s@*NotFound*",object_name);
+ }
+}
+
+void Shape_External_Object_Name_Chunk::fill_data_block (char *data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *(int*)data_start =pad;
+
+ data_start+=4;
+
+ strcpy (data_start, object_name);
+
+}
+
+///////////////////////////////////////
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPMORPH",Shape_Morphing_Data_Chunk,"REBSHAPE",Shape_Chunk)
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SHPMORPH",Shape_Morphing_Data_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+
+/*
+Children for Shape_Morphing_Data_Chunk :
+
+"SUBSHAPE" Shape_Sub_Shape_Chunk
+"FRMMORPH" Shape_Morphing_Frame_Data_Chunk
+*/
+
+
+Shape_Morphing_Data_Chunk::Shape_Morphing_Data_Chunk (Shape_Chunk * parent, const char *data, size_t size)
+: Chunk_With_Children (parent, "SHPMORPH"), parent_shape (parent), parent_sub_shape (0)
+{
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+
+ }
+
+}
+Shape_Morphing_Data_Chunk::Shape_Morphing_Data_Chunk (Shape_Sub_Shape_Chunk * parent, const char *data, size_t size)
+: Chunk_With_Children (parent, "SHPMORPH"), parent_sub_shape (parent), parent_shape (0)
+{
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+ DynCreate(data);
+ data += *(int *)(data + 8);
+
+
+ }
+
+}
+
+
+void Shape_Morphing_Data_Chunk::prepare_for_output()
+{
+ int max_id = 0;
+
+ List<Chunk *> cl;
+ lookup_child("SUBSHAPE",cl);
+
+ for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
+ {
+ max_id = max (max_id, ((Shape_Sub_Shape_Chunk *)cli())->get_header()->file_id_num);
+ }
+
+ for (cli.restart(); !cli.done(); cli.next())
+ {
+ if (((Shape_Sub_Shape_Chunk *)cli())->get_header()->file_id_num == -1)
+ {
+ ((Shape_Sub_Shape_Chunk *)cli())->get_header()->file_id_num = ++max_id;
+ }
+ }
+ Chunk_With_Children::prepare_for_output();
+
+}
+
+///////////////////////////////////////
+
+#ifdef new
+#pragma message("new defined")
+#endif
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("FRMMORPH",Shape_Morphing_Frame_Data_Chunk,"SHPMORPH",Shape_Morphing_Data_Chunk)
+
+Shape_Morphing_Frame_Data_Chunk::Shape_Morphing_Frame_Data_Chunk (Shape_Morphing_Data_Chunk * parent,const char *data, size_t /*size*/)
+: Chunk (parent, "FRMMORPH")
+{
+ a_flags = *((int *)data);
+ data +=4;
+ a_speed = *((int *)data);
+ data +=4;
+ num_frames = *((int *)data);
+ data +=4;
+
+ if (num_frames)
+ frame_store = new int [num_frames * 3];
+ else
+ frame_store=0;
+ for (int i=0; i<num_frames; i++)
+ {
+ frame_store[i*3] = *((int *)data);
+ data +=4;
+ frame_store[i*3+1] = *((int *)data);
+ data +=4;
+ frame_store[i*3+2] = *((int *)data);
+ data +=4;
+ }
+}
+
+void Shape_Morphing_Frame_Data_Chunk::fill_data_block ( char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+ *((int *) data_start) = a_flags;
+ data_start += 4;
+ *((int *) data_start) = a_speed;
+ data_start += 4;
+ *((int *) data_start) = num_frames;
+ data_start += 4;
+ for (int i=0; i<num_frames; i++)
+ {
+ *((int *) data_start) = frame_store[i*3];
+ data_start += 4;
+ *((int *) data_start) = frame_store[i*3 + 1];
+ data_start += 4;
+ *((int *) data_start) = frame_store[i*3 + 2];
+ data_start += 4;
+ }
+}
+
+Shape_Morphing_Frame_Data_Chunk::~Shape_Morphing_Frame_Data_Chunk()
+{
+ if (frame_store) delete [] frame_store;
+ while (anim_frames.size())
+ {
+ delete anim_frames.first_entry();
+ anim_frames.delete_first_entry();
+ }
+}
+
+void Shape_Morphing_Frame_Data_Chunk::prepare_for_output()
+{
+ // get the number of each shape in each frame
+
+ // N.B. this relies on the fact that the shapes are numbered
+ // but they will be by the parent class which will have it's prepare
+ // for output called first
+
+ if (frame_store)
+ delete [] frame_store;
+
+ if (anim_frames.size())
+ {
+ frame_store = new int [ anim_frames.size() * 3 ];
+ }
+ else
+ {
+ frame_store = 0;
+ }
+
+ int num_f = 0;
+
+ for (LIF<a_frame *> afi(&anim_frames); !afi.done(); afi.next())
+ {
+ int s1no, s2no;
+ if (afi()->shape1a)
+ s1no = afi()->shape1a->get_header()->file_id_num;
+ else
+ s1no = -1;
+ if (afi()->shape2a)
+ s2no = afi()->shape2a->get_header()->file_id_num;
+ else
+ s2no = -1;
+
+ frame_store[num_f] = s1no;
+ frame_store[num_f+1] = s2no;
+ frame_store[num_f+2] = afi()->spare;
+ num_f ++;
+ }
+ num_frames = num_f;
+}
+
+
+void Shape_Morphing_Frame_Data_Chunk::post_input_processing()
+{
+ List<Shape_Sub_Shape_Chunk *> shplist;
+ List<Chunk *> child_lists;
+
+ Shape_Morphing_Data_Chunk * pchnk = (Shape_Morphing_Data_Chunk *) parent;
+
+ pchnk->lookup_child("SUBSHAPE",child_lists);
+
+ while (child_lists.size()) {
+ shplist.add_entry((Shape_Sub_Shape_Chunk *)child_lists.first_entry());
+ child_lists.delete_first_entry();
+ }
+
+ LIF<Shape_Sub_Shape_Chunk *> sl(&shplist);
+
+ for (int i = 0; i<num_frames; i++)
+ {
+ Shape_Chunk * sh1b = 0, *sh2b = 0;
+ Shape_Sub_Shape_Chunk * sh1a = 0, *sh2a = 0;
+ a_frame * fr;
+
+ if (frame_store[i*2] == -1)
+ {
+ sh1b = pchnk->parent_shape;
+ }
+ else
+ {
+ for (; !sl.done(); sl.next()) {
+ if (sl()->get_header())
+ if (sl()->get_header()->file_id_num == frame_store[i])
+ break;
+ }
+ if (!sl.done())
+ {
+ sh1a = sl();
+ }
+ }
+
+ if (frame_store[i*2+1] == -1)
+ {
+ sh2b = pchnk->parent_shape;
+ }
+ else
+ {
+ for (sl.restart(); !sl.done(); sl.next()) {
+ if (sl()->get_header())
+ if (sl()->get_header()->file_id_num == frame_store[i+1])
+ break;
+ }
+ if (!sl.done())
+ {
+ sh2a = sl();
+ }
+ }
+ if ((sh1a || sh1b) && (sh2a || sh2b))
+ {
+ fr = new a_frame;
+ if (sh1a)
+ fr->shape1a = sh1a;
+ else if (sh1b)
+ fr->shape1b = sh1b;
+
+ if (sh2a)
+ fr->shape2a = sh2a;
+ else if (sh2b)
+ fr->shape2b = sh2b;
+
+ fr->spare = frame_store[i+2];
+ anim_frames.add_entry(fr);
+ }
+
+ }
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Sub_Shape_Chunk functions
+
+
+RIF_IMPLEMENT_DYNCREATE("SUBSHAPE",Shape_Sub_Shape_Chunk)
+/*
+Children for Shape_Sub_Shape_Chunk :
+
+"SHPRAWVT" Shape_Vertex_Chunk
+"SHPPOLYS" Shape_Polygon_Chunk
+"SUBSHPHD" Shape_Sub_Shape_Header_Chunk
+"SHPVNORM" Shape_Vertex_Normal_Chunk
+"SHPPNORM" Shape_Polygon_Normal_Chunk
+"SHPTEXFN" Shape_Texture_Filenames_Chunk
+"SHPUVCRD" Shape_UV_Coord_Chunk
+"SHPMRGDT" Shape_Merge_Data_Chunk
+"SHPCENTR" Shape_Centre_Chunk
+"SHPMORPH" Shape_Morphing_Data_Chunk
+"SHPEXTFL" Shape_External_File_Chunk
+"SHPPCINF" Shape_Poly_Change_Info_Chunk
+"TEXTANIM" Animation_Chunk
+"SHPFRAGS" Shape_Fragments_Chunk
+"ANIMSEQU" Anim_Shape_Sequence_Chunk
+"PNOTINBB" Poly_Not_In_Bounding_Box_Chunk
+"ANSHCEN2" Anim_Shape_Centre_Chunk
+"ASALTTEX" Anim_Shape_Alternate_Texturing_Chunk
+"SHPPRPRO" Shape_Preprocessed_Data_Chunk
+
+
+"SHPFNAME" Shape_Name_Chunk
+"FRAGDATA" Shape_Fragments_Data_Chunk
+"FRAGLOCN" Shape_Fragment_Location_Chunk
+*/
+
+Shape_Sub_Shape_Chunk::Shape_Sub_Shape_Chunk(Chunk_With_Children * parent, const char *data, size_t size)
+: Chunk_With_Children (parent, "SUBSHAPE"), shape_data ()
+{
+ const char * buffer_ptr = data;
+
+ shape_data_store = (ChunkShape *) &shape_data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+
+ }
+ #if cencon || InterfaceEngine
+ List<Chunk*>chlist;
+ lookup_child("CONSHAPE",chlist);
+ for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
+ {
+ ((Console_Shape_Chunk*)chlif())->generate_console_chunkshape();
+ }
+ #endif
+}
+
+Shape_Sub_Shape_Chunk::Shape_Sub_Shape_Chunk (Chunk_With_Children * parent, ChunkShape &shp_dat)
+: Chunk_With_Children (parent, "SUBSHAPE"), shape_data (shp_dat)
+{
+ shape_data_store = (ChunkShape *) &shape_data;
+
+ new Shape_Sub_Shape_Header_Chunk (this);
+
+ if (shape_data.v_list) new Shape_Vertex_Chunk (this, shape_data.num_verts);
+ if (shape_data.v_normal_list) new Shape_Vertex_Normal_Chunk (this, shape_data.num_verts);
+ if (shape_data.p_normal_list) new Shape_Polygon_Normal_Chunk (this, shape_data.num_polys);
+ if (shape_data.poly_list) new Shape_Polygon_Chunk (this, shape_data.num_polys);
+ if (shape_data.uv_list) new Shape_UV_Coord_Chunk (this, shape_data.num_uvs);
+ if (shape_data.texture_fns) new Shape_Texture_Filenames_Chunk (this, shape_data.num_texfiles);
+
+ //calculate the shape's centre and radius_about_centre
+ shape_data_store->centre=(shape_data_store->min+shape_data_store->max)/2;
+ shape_data_store->radius_about_centre=0;
+ for(int i=0;i<shape_data_store->num_verts;i++)
+ {
+ float length = (float) mod(shape_data_store->v_list[i]-shape_data_store->centre);
+ if(length>shape_data_store->radius_about_centre)
+ {
+ shape_data_store->radius_about_centre=length;
+ }
+ }
+
+ //if the shape hasn't got a Shape_Centre_Chunk , create one.
+
+ if(!lookup_single_child("SHPCENTR"))
+ {
+ new Shape_Centre_Chunk(this);
+ }
+}
+
+Shape_Sub_Shape_Chunk::~Shape_Sub_Shape_Chunk ()
+{
+}
+
+Shape_Sub_Shape_Chunk* Shape_Sub_Shape_Chunk::make_copy_of_chunk()
+{
+ char* Data=this->make_data_block_from_chunk();
+ Shape_Sub_Shape_Chunk* NewShape=new Shape_Sub_Shape_Chunk(parent,Data+12,this->size_chunk()-12);
+ delete [] Data;
+ delete NewShape->get_header();
+ new Shape_Sub_Shape_Header_Chunk(NewShape);
+ return NewShape;
+}
+
+Shape_Sub_Shape_Header_Chunk * Shape_Sub_Shape_Chunk::get_header()
+{
+
+ return (Shape_Sub_Shape_Header_Chunk *) this->lookup_single_child ("SUBSHPHD");
+
+}
+
+BOOL Shape_Sub_Shape_Chunk::update_my_chunkshape (ChunkShape & cshp)
+{
+ // Firstly lose all the chunks that were with
+ // the old chunk shape
+ List <Chunk *> chlst;
+
+ lookup_child ("SHPRAWVT",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+ lookup_child ("SHPVNORM",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPPNORM",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPPOLYS",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPUVCRD",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+
+ lookup_child ("SHPTEXFN",chlst);
+
+ while (chlst.size())
+ {
+ delete chlst.first_entry();
+ chlst.delete_first_entry();
+ }
+
+ *shape_data_store = cshp;
+
+ if (shape_data.v_list) new Shape_Vertex_Chunk (this, shape_data.num_verts);
+ if (shape_data.v_normal_list) new Shape_Vertex_Normal_Chunk (this, shape_data.num_verts);
+ if (shape_data.p_normal_list) new Shape_Polygon_Normal_Chunk (this, shape_data.num_polys);
+ if (shape_data.poly_list) new Shape_Polygon_Chunk (this, shape_data.num_polys);
+ if (shape_data.uv_list) new Shape_UV_Coord_Chunk (this, shape_data.num_uvs);
+ if (shape_data.texture_fns) new Shape_Texture_Filenames_Chunk (this, shape_data.num_texfiles);
+
+ //calculate the shape's centre and radius_about_centre
+ shape_data_store->centre=(shape_data_store->min+shape_data_store->max)/2;
+ shape_data_store->radius_about_centre=0;
+ for(int i=0;i<shape_data_store->num_verts;i++)
+ {
+ float length=(float)mod(shape_data_store->v_list[i]-shape_data_store->centre);
+ if(length>shape_data_store->radius_about_centre)
+ {
+ shape_data_store->radius_about_centre=length;
+ }
+ }
+
+ //if the shape hasn't got a Shape_Centre_Chunk , create one.
+
+ if(!lookup_single_child("SHPCENTR"))
+ {
+ new Shape_Centre_Chunk(this);
+ }
+
+
+ return TRUE;
+}
+
+
+const char * Shape_Sub_Shape_Chunk::get_shape_name()
+{
+ Shape_Name_Chunk* snc=(Shape_Name_Chunk*)lookup_single_child("SHPFNAME");
+ if (snc)
+ {
+ return snc->shape_name;
+ }
+ else
+ {
+ return(0);
+ }
+}
+
+Console_Shape_Chunk* Shape_Sub_Shape_Chunk::get_console_shape_data(Console_Type ct)
+{
+ List<Chunk*> chlist;
+ lookup_child("CONSHAPE",chlist);
+ for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
+ {
+ Console_Shape_Chunk* csc=(Console_Shape_Chunk*)chlif();
+ List<Chunk*> chlist2;
+ csc->lookup_child("CONSTYPE",chlist2);
+ if(chlist2.size())
+ {
+ if(((Console_Type_Chunk*)chlist2.first_entry())->console==ct)
+ return csc;
+ }
+ }
+
+ return 0;//no console specific shape data
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Sub_Shape_Header_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("SUBSHPHD",Shape_Sub_Shape_Header_Chunk,"SUBSHAPE",Shape_Sub_Shape_Chunk)
+
+// These can only be children of Shape_Sub_Shape_Chunks
+// the shape chunks data will automatically be updated by it is created
+
+Shape_Sub_Shape_Header_Chunk::Shape_Sub_Shape_Header_Chunk (Shape_Sub_Shape_Chunk * parent, const char * hdata, size_t /*hsize*/)
+ : Chunk (parent, "SUBSHPHD"),
+ shape_data (parent->shape_data_store)
+{
+ flags = *((int *) hdata);
+ hdata += 4;
+
+ file_id_num = *((int *) (hdata));
+ hdata += 4;
+
+ parent->shape_data_store->num_verts = *((int *) (hdata));
+ hdata += 4;
+ parent->shape_data_store->num_polys = *((int *) (hdata));
+ hdata += 4;
+
+ parent->shape_data_store->radius = *((float *) (hdata));
+ hdata += 4;
+
+ parent->shape_data_store->max.x = *((int *) (hdata));
+ hdata += 4;
+ parent->shape_data_store->min.x = *((int *) (hdata));
+ hdata += 4;
+
+ parent->shape_data_store->max.y = *((int *) (hdata));
+ hdata += 4;
+ parent->shape_data_store->min.y = *((int *) (hdata));
+ hdata += 4;
+
+ parent->shape_data_store->max.z = *((int *) (hdata));
+ hdata += 4;
+ parent->shape_data_store->min.z = *((int *) (hdata));
+}
+
+Shape_Sub_Shape_Header_Chunk::~Shape_Sub_Shape_Header_Chunk()
+{
+}
+
+size_t Shape_Sub_Shape_Header_Chunk::size_chunk()
+{
+ return chunk_size = 44 + 12;
+}
+
+
+void Shape_Sub_Shape_Header_Chunk::fill_data_block(char * data_start)
+{
+
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = flags;
+ data_start += 4;
+
+ *((int *) (data_start)) = file_id_num;
+ data_start += 4;
+
+ *((int *) (data_start)) = shape_data->num_verts;
+ data_start += 4;
+ *((int *) (data_start)) = shape_data->num_polys;
+ data_start += 4;
+
+ *((float *) (data_start)) = shape_data->radius;
+ data_start += 4;
+
+ *((int *) (data_start)) = shape_data->max.x;
+ data_start += 4;
+ *((int *) (data_start)) = shape_data->min.x;
+ data_start += 4;
+
+ *((int *) (data_start)) = shape_data->max.y;
+ data_start += 4;
+ *((int *) (data_start)) = shape_data->min.y;
+ data_start += 4;
+
+ *((int *) (data_start)) = shape_data->max.z;
+ data_start += 4;
+ *((int *) (data_start)) = shape_data->min.z;
+
+}
+
+/////////////////////////////////////////
+
+
+// Class Shape_Poly_Change_Info_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE("SHPPCINF",Shape_Poly_Change_Info_Chunk)
+
+void Shape_Poly_Change_Info_Chunk::fill_data_block(char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = original_num_verts;
+
+ data_start += 4;
+
+ *((int *) data_start) = change_list.size();
+
+ data_start += 4;
+
+ for (LIF<poly_change_info> pcii(&change_list); !pcii.done(); pcii.next())
+ {
+ *((int *) data_start) = pcii().poly_num;
+
+ data_start += 4;
+
+ *((int *) data_start) = pcii().vert_num_before;
+
+ data_start += 4;
+
+ *((int *) data_start) = pcii().vert_num_after;
+
+ data_start += 4;
+ }
+
+
+}
+
+Shape_Poly_Change_Info_Chunk::Shape_Poly_Change_Info_Chunk (Chunk_With_Children * parent,const char * data, size_t /*size*/)
+: Chunk (parent, "SHPPCINF")
+{
+ original_num_verts = *((int *) data);
+
+ data += 4;
+
+ int n_entries = *((int *) data);
+
+ data += 4;
+
+ for (int i=0; i<n_entries; i++)
+ {
+ poly_change_info pci;
+
+ pci.poly_num = *((int *) data);
+ data += 4;
+ pci.vert_num_before = *((int *) data);
+ data += 4;
+ pci.vert_num_after = *((int *) data);
+ data += 4;
+
+ change_list.add_entry(pci);
+ }
+
+}
+
+
+/////////////////////////////////////////
+
+// Class Shape_Name_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE("SHPFNAME",Shape_Name_Chunk)
+
+Shape_Name_Chunk::Shape_Name_Chunk (Chunk_With_Children * parent, const char * sname)
+: Chunk (parent, "SHPFNAME")
+{
+ shape_name = new char [strlen(sname)+1];
+ strcpy (shape_name, sname);
+}
+
+Shape_Name_Chunk::Shape_Name_Chunk (Chunk_With_Children * parent, const char * sndata, size_t /*rsize*/)
+: Chunk (parent, "SHPFNAME")
+{
+ shape_name = new char [strlen(sndata)+1];
+ strcpy (shape_name, sndata);
+}
+
+Shape_Name_Chunk::~Shape_Name_Chunk ()
+{
+ if (shape_name)
+ delete [] shape_name;
+}
+
+
+void Shape_Name_Chunk::fill_data_block (char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ strcpy (data_start, shape_name);
+
+}
+
+/////////////////////////////////////////
+
+// Class Shape_Fragments_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE("SHPFRAGS",Shape_Fragments_Chunk)
+
+CHUNK_WITH_CHILDREN_LOADER("SHPFRAGS",Shape_Fragments_Chunk)
+/*
+Children for Shape_Fragments_Chunk :
+
+"SUBSHAPE" Shape_Sub_Shape_Chunk
+"SHPFRGTP" Shape_Fragment_Type_Chunk
+"FRGSOUND" Fragment_Type_Sound_Chunk
+*/
+
+
+/////////////////////////////////////////
+
+// Class Shape_Fragments_Data_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("FRAGDATA",Shape_Fragments_Data_Chunk)
+
+void Shape_Fragments_Data_Chunk::fill_data_block (char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((int *) data_start) = num_fragments;
+
+ data_start += 4;
+
+ *((int *) data_start) = pad1;
+
+ data_start += 4;
+
+ *((int *) data_start) = pad2;
+
+ data_start += 4;
+
+ *((int *) data_start) = pad3;
+
+}
+
+Shape_Fragments_Data_Chunk::Shape_Fragments_Data_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/)
+: Chunk (parent, "FRAGDATA")
+{
+ num_fragments = *((int *) sdata);
+
+ sdata += 4;
+
+ pad1 = *((int *) sdata);
+
+ sdata += 4;
+
+ pad2 = *((int *) sdata);
+
+ sdata += 4;
+
+ pad3 = *((int *) sdata);
+
+ sdata += 4;
+
+}
+
+
+/////////////////////////////////////////
+
+// Class Shape_Fragments_Location_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("FRAGLOCN",Shape_Fragment_Location_Chunk)
+
+void Shape_Fragment_Location_Chunk::fill_data_block (char * data_start)
+{
+ strncpy (data_start, identifier, 8);
+
+ data_start += 8;
+
+ *((int *) data_start) = chunk_size;
+
+ data_start += 4;
+
+ *((ChunkVectorInt *) data_start) = frag_loc;
+
+ data_start += sizeof(ChunkVectorInt);
+
+
+ *((int *) data_start) = pad1;
+
+ data_start += 4;
+
+ *((int *) data_start) = pad2;
+
+ data_start += 4;
+
+ *((int *) data_start) = pad3;
+
+ data_start += 4;
+
+ *((int *) data_start) = pad4;
+
+}
+
+Shape_Fragment_Location_Chunk::Shape_Fragment_Location_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/)
+: Chunk (parent, "FRAGLOCN")
+{
+ frag_loc = *((ChunkVectorInt *) sdata);
+
+ sdata += sizeof(ChunkVectorInt);
+
+
+ pad1 = *((int *) sdata);
+
+ sdata += 4;
+
+ pad2 = *((int *) sdata);
+
+ sdata += 4;
+
+ pad3 = *((int *) sdata);
+
+ sdata += 4;
+
+ pad4 = *((int *) sdata);
+
+}
+
+/////////////////////////////////////////
+
+RIF_IMPLEMENT_DYNCREATE("SHPFRGTP",Shape_Fragment_Type_Chunk)
+Shape_Fragment_Type_Chunk::Shape_Fragment_Type_Chunk(Chunk_With_Children* parent,const char* name)
+:Chunk(parent,"SHPFRGTP")
+{
+ frag_type_name=new char[strlen(name)+1];
+ strcpy(frag_type_name,name);
+ pad1=pad2-0;
+}
+
+Shape_Fragment_Type_Chunk::Shape_Fragment_Type_Chunk(Chunk_With_Children* const parent,const char* data,size_t const )
+:Chunk(parent,"SHPFRGTP")
+{
+ int length=strlen(data)+1;
+ frag_type_name=new char[length];
+ strcpy(frag_type_name,data);
+ data+=(length+3)&~3;
+
+ pad1=*(int*)data;
+ data+=4;
+ pad2=*(int*)data;
+ data+=4;
+}
+
+Shape_Fragment_Type_Chunk::~Shape_Fragment_Type_Chunk()
+{
+ if(frag_type_name) delete frag_type_name;
+}
+
+void Shape_Fragment_Type_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ strcpy(data_start,frag_type_name);
+ data_start+=(strlen(frag_type_name)+4)&~3;
+
+ *(int*)data_start=pad1;
+ data_start+=4;
+ *(int*)data_start=pad2;
+ data_start+=4;
+
+}
+
+size_t Shape_Fragment_Type_Chunk::size_chunk()
+{
+ chunk_size=12+8;
+ chunk_size+=(strlen(frag_type_name)+4)&~3;
+ return chunk_size;
+}
+
+
+/////////////////////////////////////////
+
+// Class Anim_Shape_Sequence_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE("ANIMSEQU",Anim_Shape_Sequence_Chunk)
+
+/*
+Children for Anim_Shape_Sequence_Chunk :
+"ANISEQDT" Anim_Shape_Sequence_Data_Chunk
+"ANIMFRAM" Anim_Shape_Frame_Chunk
+*/
+
+Anim_Shape_Sequence_Chunk::Anim_Shape_Sequence_Chunk(Chunk_With_Children * const parent, const char *data, size_t const size)
+: Chunk_With_Children (parent, "ANIMSEQU")
+{
+
+ sequence_data_store=(ChunkAnimSequence*)&sequence_data;
+
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+
+ }
+ if(!ConstructSequenceDataFromChildren())
+ {
+ //this sequence is no longer valid
+ delete this;
+ }
+}
+Anim_Shape_Sequence_Chunk::Anim_Shape_Sequence_Chunk(Chunk_With_Children * const parent, int sequencenum,const char* name)
+: Chunk_With_Children (parent, "ANIMSEQU")
+{
+
+ sequence_data_store=(ChunkAnimSequence*)&sequence_data;
+
+ sequence_data_store->SequenceNum=sequencenum;
+ sequence_data_store->name=new char[strlen(name)+1];
+ strcpy(sequence_data_store->name,name);
+ RegenerateChildChunks();
+}
+
+Anim_Shape_Sequence_Chunk::Anim_Shape_Sequence_Chunk(Chunk_With_Children * const parent, ChunkAnimSequence const* cas )
+: Chunk_With_Children (parent, "ANIMSEQU")
+{
+
+ sequence_data_store=(ChunkAnimSequence*)&sequence_data;
+ *(ChunkAnimSequence*)&sequence_data=*cas;
+ RegenerateChildChunks();
+}
+
+
+int Anim_Shape_Sequence_Chunk::ConstructSequenceDataFromChildren()
+{
+ Anim_Shape_Sequence_Data_Chunk* assdc=(Anim_Shape_Sequence_Data_Chunk*)lookup_single_child("ANISEQDT");
+ if(!assdc)
+ {
+ return 0;
+ }
+ sequence_data_store->name=assdc->name;
+ sequence_data_store->SequenceNum=assdc->SequenceNum;
+ sequence_data_store->flags=assdc->flags;
+ sequence_data_store->pad2=assdc->pad2;
+ sequence_data_store->pad3=assdc->pad3;
+ sequence_data_store->pad4=assdc->pad4;
+
+ List<Chunk*> chlist;
+ lookup_child("ANIMFRAM",chlist);
+ sequence_data_store->NumFrames=chlist.size();
+ if(sequence_data_store->NumFrames)
+ {
+ sequence_data_store->Frames=new ChunkAnimFrame*[sequence_data_store->NumFrames];
+ for(int i=0;i<sequence_data_store->NumFrames;i++)
+ {
+ sequence_data_store->Frames[i]=0;
+ }
+ }
+ for(LIF<Chunk*> chlif(& chlist);!chlif.done();chlif.next())
+ {
+ Anim_Shape_Frame_Chunk* asfc=(Anim_Shape_Frame_Chunk*)chlif();
+
+ Anim_Shape_Frame_Data_Chunk* asfdc=(Anim_Shape_Frame_Data_Chunk*)asfc->lookup_single_child("ANIFRADT");
+ if(!asfdc) return 0;
+ if(asfdc->FrameNum>=sequence_data_store->NumFrames) return 0;
+
+ if(sequence_data_store->Frames[asfdc->FrameNum])return 0;
+ sequence_data_store->Frames[asfdc->FrameNum]=new ChunkAnimFrame;
+ ChunkAnimFrame* caf=sequence_data_store->Frames[asfdc->FrameNum];
+
+ Shape_Vertex_Chunk* svc=(Shape_Vertex_Chunk*) asfc->lookup_single_child("SHPRAWVT");
+ if(!svc)return 0;
+
+ Shape_Polygon_Normal_Chunk* spnc=(Shape_Polygon_Normal_Chunk*)asfc->lookup_single_child("SHPPNORM");
+ if(!spnc) return 0;
+
+ caf->name=asfdc->name;
+ caf->flags=asfdc->flags;
+ caf->num_interp_frames=asfdc->num_interp_frames;
+ caf->pad3=asfdc->pad3;
+ caf->pad4=asfdc->pad4;
+
+ caf->num_verts=svc->num_verts;
+ caf->v_list=(ChunkVectorInt*)svc->vert_data;
+
+ caf->num_polys=spnc->num_polys;
+ caf->p_normal_list=(ChunkVectorFloat*)spnc->poly_norm_data;
+
+ }
+ return 1;
+}
+void Anim_Shape_Sequence_Chunk::post_input_processing()
+{
+
+ List<int>* poly_not_in_bb=0;
+ List<Chunk*> chlist;
+ parent->lookup_child("PNOTINBB",chlist);
+ if(chlist.size())
+ poly_not_in_bb=&((Poly_Not_In_Bounding_Box_Chunk*)chlist.first_entry())->poly_no;
+ if(!strcmp(parent->identifier,"REBSHAPE"))
+ {
+ sequence_data_store->UpdateNormalsAndExtents(&((Shape_Chunk*)parent)->shape_data,poly_not_in_bb);
+ }
+ else if(!strcmp(parent->identifier,"SUBSHAPE"))
+ {
+ sequence_data_store->UpdateNormalsAndExtents(&((Shape_Sub_Shape_Chunk*)parent)->shape_data,poly_not_in_bb);
+ }
+
+ Chunk_With_Children::post_input_processing();
+}
+
+
+void Anim_Shape_Sequence_Chunk::update_my_sequencedata(ChunkAnimSequence & seq)
+{
+ *sequence_data_store=seq;
+ RegenerateChildChunks();
+}
+
+void Anim_Shape_Sequence_Chunk::set_sequence_flags(int flags)
+{
+ sequence_data_store->flags=flags;
+}
+void Anim_Shape_Sequence_Chunk::set_frame_flags(int frameno,int flags)
+{
+ if(frameno< sequence_data_store->NumFrames)
+ {
+ if(sequence_data_store->Frames[frameno])
+ {
+ sequence_data_store->Frames[frameno]->flags=flags;
+ }
+ }
+}
+
+void Anim_Shape_Sequence_Chunk::RegenerateChildChunks()
+{
+ List<Chunk*> chlist;
+ lookup_child("ANISEQDT",chlist);
+ while(chlist.size())
+ {
+ delete chlist.first_entry();
+ chlist.delete_first_entry();
+ }
+ lookup_child("ANIMFRAM",chlist);
+ while(chlist.size())
+ {
+ delete chlist.first_entry();
+ chlist.delete_first_entry();
+ }
+
+ new Anim_Shape_Sequence_Data_Chunk(this,sequence_data_store);
+ for(int i=0;i<sequence_data_store->NumFrames;i++)
+ {
+ if(sequence_data_store->Frames[i]->flags & animframeflag_interpolated_frame)continue;
+ new Anim_Shape_Frame_Chunk(this,sequence_data_store->Frames[i],i);
+ }
+}
+
+void Anim_Shape_Sequence_Chunk::GenerateInterpolatedFrames()
+{
+
+ if(!strcmp(parent->identifier,"REBSHAPE"))
+ {
+ sequence_data_store->GenerateInterpolatedFrames(&((Shape_Chunk*)parent)->shape_data);
+ }
+ else if(!strcmp(parent->identifier,"SUBSHAPE"))
+ {
+ sequence_data_store->GenerateInterpolatedFrames(&((Shape_Sub_Shape_Chunk*)parent)->shape_data);
+ }
+}
+/////////////////////////////////////////
+
+// Class Anim_Shape_Frame_Chunk functions
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("ANIMFRAM",Anim_Shape_Frame_Chunk,"ANIMSEQU",Anim_Shape_Sequence_Chunk)
+
+/*
+Children for Anim_Shape_Frame_Chunk :
+
+"ANIFRADT" Anim_Shape_Frame_Data_Chunk
+"SHPPNORM" Shape_Polygon_Normal_Chunk
+"SHPRAWVT" Shape_Vertex_Chunk
+*/
+
+Anim_Shape_Frame_Chunk::Anim_Shape_Frame_Chunk(Anim_Shape_Sequence_Chunk *const parent, const char *data, size_t const size)
+: Chunk_With_Children (parent, "ANIMFRAM")
+{
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+ DynCreate(data);
+ data += *(int *)(data + 8);
+ }
+}
+
+
+Anim_Shape_Frame_Chunk::Anim_Shape_Frame_Chunk(Anim_Shape_Sequence_Chunk * const parent,ChunkAnimFrame* caf,int frameno)
+: Chunk_With_Children (parent, "ANIMFRAM")
+{
+ new Anim_Shape_Frame_Data_Chunk(this,caf,frameno);
+ new Shape_Vertex_Chunk(this,caf->v_list,caf->num_verts);
+ new Shape_Polygon_Normal_Chunk(this,caf->p_normal_list,caf->num_polys);
+
+}
+/////////////////////////////////////////
+
+// Class Anim_Shape_Sequence_Data_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("ANISEQDT",Anim_Shape_Sequence_Data_Chunk,"ANIMSEQU",Anim_Shape_Sequence_Chunk)
+
+Anim_Shape_Sequence_Data_Chunk::Anim_Shape_Sequence_Data_Chunk(Anim_Shape_Sequence_Chunk* const parent,const char* data,size_t const/*datasize*/)
+: Chunk(parent, "ANISEQDT")
+{
+ SequenceNum=*(int*)data;
+ data+=4;
+ flags=*(int*)data;
+ data+=4;
+ pad2=*(int*)data;
+ data+=4;
+ pad3=*(int*)data;
+ data+=4;
+ pad4=*(int*)data;
+ data+=4;
+ name=new char[strlen(data)+1];
+ strcpy(name,data);
+
+}
+
+Anim_Shape_Sequence_Data_Chunk::Anim_Shape_Sequence_Data_Chunk(Anim_Shape_Sequence_Chunk* const parent,ChunkAnimSequence* cas)
+: Chunk(parent, "ANISEQDT")
+{
+ SequenceNum=cas->SequenceNum;
+ name=cas->name;
+ flags=cas->flags;
+ pad2=cas->pad2;
+ pad3=cas->pad3;
+ pad4=cas->pad4;
+
+}
+
+void Anim_Shape_Sequence_Data_Chunk::fill_data_block(char* datastart)
+{
+ strncpy (datastart, identifier, 8);
+ datastart += 8;
+ *((int *) datastart) = chunk_size;
+ datastart += 4;
+
+ *(int*)datastart=SequenceNum;
+ datastart+=4;
+ *(int*)datastart=flags;
+ datastart+=4;
+ *(int*)datastart=pad2;
+ datastart+=4;
+ *(int*)datastart=pad3;
+ datastart+=4;
+ *(int*)datastart=pad4;
+ datastart+=4;
+
+ strcpy(datastart,name ? name : "");
+
+}
+
+size_t Anim_Shape_Sequence_Data_Chunk::size_chunk()
+{
+ return chunk_size = 12+20
+ +(name ? strlen(name) : 0)
+ +3 +3&~3;
+}
+
+
+/////////////////////////////////////////
+
+// Class Anim_Shape_Frame_Data_Chunk functions
+RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT("ANIFRADT",Anim_Shape_Frame_Data_Chunk,"ANIMFRAM",Anim_Shape_Frame_Chunk)
+
+Anim_Shape_Frame_Data_Chunk::Anim_Shape_Frame_Data_Chunk(Anim_Shape_Frame_Chunk* const parent,const char* data,size_t const /*datasize*/)
+: Chunk(parent, "ANIFRADT")
+{
+ FrameNum=*(int*)data;
+ data+=4;
+ flags=*(int*)data;
+ data+=4;
+ num_interp_frames=*(int*)data;
+ data+=4;
+ pad3=*(int*)data;
+ data+=4;
+ pad4=*(int*)data;
+ data+=4;
+ name=new char[strlen(data)+1];
+ strcpy(name,data);
+
+}
+
+Anim_Shape_Frame_Data_Chunk::Anim_Shape_Frame_Data_Chunk(Anim_Shape_Frame_Chunk* const parent,ChunkAnimFrame* caf,int frameno)
+: Chunk(parent, "ANIFRADT")
+{
+ FrameNum=frameno;
+ name=caf->name;
+ flags=caf->flags;
+ num_interp_frames=caf->num_interp_frames;
+ pad3=caf->pad3;
+ pad4=caf->pad4;
+
+}
+
+
+void Anim_Shape_Frame_Data_Chunk::fill_data_block(char* datastart)
+{
+ strncpy (datastart, identifier, 8);
+ datastart += 8;
+ *((int *) datastart) = chunk_size;
+ datastart += 4;
+
+ *(int*)datastart=FrameNum;
+ datastart+=4;
+ *(int*)datastart=flags;
+ datastart+=4;
+ *(int*)datastart=num_interp_frames;
+ datastart+=4;
+ *(int*)datastart=pad3;
+ datastart+=4;
+ *(int*)datastart=pad4;
+ datastart+=4;
+
+ strcpy(datastart,name ? name : "");
+
+}
+
+size_t Anim_Shape_Frame_Data_Chunk::size_chunk()
+{
+ return chunk_size = 12+20
+ +(name ? strlen(name) : 0)
+ +3 +3&~3;
+}
+
+/////////////////////////////////////////
+
+// Class Anim_Shape_Alternate_Texturing_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("ASALTTEX",Anim_Shape_Alternate_Texturing_Chunk)
+
+/*
+Children for Anim_Shape_Alternate_Texturing_Chunk :
+"SUBSHAPE" Shape_Sub_Shape_Chunk
+*/
+
+Anim_Shape_Alternate_Texturing_Chunk::Anim_Shape_Alternate_Texturing_Chunk(Chunk_With_Children *const parent, const char *data, size_t const size)
+: Chunk_With_Children (parent, "ASALTTEX")
+{
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+ }
+ DynCreate(data);
+ data += *(int *)(data + 8);
+ }
+}
+
+Shape_Sub_Shape_Chunk* Anim_Shape_Alternate_Texturing_Chunk::CreateNewSubShape(const char* name)
+{
+ if(!name) return 0;
+ //check to make sure that name isn't already in use
+ List<Chunk*> chlist;
+ lookup_child("SUBSHAPE",chlist);
+ for(LIF<Chunk*> chlif(& chlist);!chlif.done();chlif.next())
+ {
+ Shape_Sub_Shape_Chunk* sssc=(Shape_Sub_Shape_Chunk*) chlif();
+ if(!_stricmp(name,sssc->get_shape_name()))return 0;
+ }
+ ChunkShape cs;
+ if(!_stricmp(parent->identifier,"REBSHAPE"))
+ cs=((Shape_Chunk*)parent)->shape_data;
+ else if(!_stricmp(parent->identifier,"SUBSHAPE"))
+ cs=((Shape_Sub_Shape_Chunk*)parent)->shape_data;
+ else
+ return 0;
+ Shape_Sub_Shape_Chunk* sssc=new Shape_Sub_Shape_Chunk(this,cs);
+ new Shape_Name_Chunk(sssc,name);
+
+
+ //copy the texture animation data
+ Chunk_With_Children* anim_chunk=(Chunk_With_Children*)parent->lookup_single_child("TEXTANIM");
+ if(anim_chunk)
+ {
+ char * tempbuffer = anim_chunk->make_data_block_from_chunk();
+ sssc->DynCreate(tempbuffer);
+ delete [] tempbuffer;
+
+ }
+
+ Shape_Merge_Data_Chunk* smdc=(Shape_Merge_Data_Chunk*)parent->lookup_single_child("SHPMRGDT");
+ if(smdc)
+ {
+ new Shape_Merge_Data_Chunk(sssc,smdc->merge_data,smdc->num_polys);
+ }
+ return sssc;
+
+}
+
+/////////////////////////////////////////
+
+// Class Poly_Not_In_Bounding_Box_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("PNOTINBB",Poly_Not_In_Bounding_Box_Chunk)
+
+Poly_Not_In_Bounding_Box_Chunk::Poly_Not_In_Bounding_Box_Chunk(Chunk_With_Children* const parent,const char* data,size_t const datasize)
+:Chunk(parent,"PNOTINBB")
+{
+ for(int i=0;i<( ( (signed)datasize ) /4)-2;i++)
+ {
+ poly_no.add_entry(*(int*)data);
+ data+=4;
+ }
+ pad1=*(int*)data;
+ data+=4;
+ pad2=*(int*)data;
+
+}
+
+Poly_Not_In_Bounding_Box_Chunk::Poly_Not_In_Bounding_Box_Chunk(Chunk_With_Children* const parent)
+:Chunk(parent,"PNOTINBB")
+{
+ pad1=pad2=0;
+}
+
+size_t Poly_Not_In_Bounding_Box_Chunk::size_chunk()
+{
+ return chunk_size=(20+4*poly_no.size());
+}
+
+void Poly_Not_In_Bounding_Box_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ for(LIF<int> plif(&poly_no);!plif.done();plif.next())
+ {
+ *(int*)data_start=plif();
+ data_start+=4;
+ }
+ *(int*)data_start=pad1;
+ data_start+=4;
+ *(int*)data_start=pad2;
+}
+
+
+/////////////////////////////////////////
+
+// Class Anim_Shape_Centre_Chunk functions
+
+RIF_IMPLEMENT_DYNCREATE("ANSHCEN2",Anim_Shape_Centre_Chunk)
+
+Anim_Shape_Centre_Chunk::Anim_Shape_Centre_Chunk(Chunk_With_Children* const parent,const char* data,size_t const /*datasize*/)
+:Chunk(parent,"ANSHCEN2")
+{
+ Centre=*(ChunkVectorInt*)data;
+ data+=sizeof(ChunkVectorInt);
+ flags=*(int*)data;
+ data+=4;
+ pad2=*(int*)data;
+
+}
+
+Anim_Shape_Centre_Chunk::Anim_Shape_Centre_Chunk(Chunk_With_Children* const parent)
+:Chunk(parent,"ANSHCEN2")
+{
+ Centre.x=0;
+ Centre.y=0;
+ Centre.z=0;
+ flags=pad2=0;
+}
+
+size_t Anim_Shape_Centre_Chunk::size_chunk()
+{
+ return chunk_size=(20+sizeof(ChunkVectorInt));
+}
+
+void Anim_Shape_Centre_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ *(ChunkVectorInt*)data_start=Centre;
+ data_start+=sizeof(ChunkVectorInt);
+ *(int*)data_start=flags;
+ data_start+=4;
+ *(int*)data_start=pad2;
+
+}
+
+
+
+/////////////////////////////////////////
+
+// Class Console_Shape_Chunk functions
+
+/*
+Children for Console_Shape_Chunk :
+
+"SHPPOLYS" Shape_Polygon_Chunk
+"SHPUVCRD" Shape_UV_Coord_Chunk
+"TEXTANIM" Animation_Chunk
+
+"CONSTYPE" Console_Type_Chunk
+*/
+
+
+Console_Shape_Chunk::Console_Shape_Chunk(Chunk_With_Children * const parent, const char *data, size_t size)
+: Chunk_With_Children (parent, "CONSHAPE")
+{
+
+ shape_data_store=(ChunkShape*)&shape_data;
+
+ const char * buffer_ptr = data;
+
+ while ((data-buffer_ptr)< (signed)size) {
+
+ if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed)size) {
+ Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;
+ break;
+
+ DynCreate(data);
+ data += *(int *)(data + 8);
+ }
+ }
+
+}
+
+Console_Shape_Chunk::Console_Shape_Chunk(Chunk_With_Children* const parent,Console_Type ct)
+:Chunk_With_Children(parent,"CONSHAPE")
+{
+ shape_data_store=(ChunkShape*)&shape_data;
+ new Console_Type_Chunk(this,ct);
+}
+void Console_Shape_Chunk::generate_console_chunkshape()
+{
+ //sort out the chunkshape
+ if(!strcmp(parent->identifier,"REBSHAPE"))
+ {
+ *shape_data_store=((Shape_Chunk*)parent)->shape_data;
+ }
+ else if(!strcmp(parent->identifier,"SUBSHAPE"))
+ {
+ *shape_data_store=((Shape_Sub_Shape_Chunk*)parent)->shape_data;
+ }
+ else
+ {
+ delete this;
+ return;
+ }
+
+ Shape_Polygon_Chunk* spc=(Shape_Polygon_Chunk*)lookup_single_child("SHPPOLYS");
+ if(spc)
+ {
+ if(spc->num_polys!=shape_data_store->num_polys)
+ {
+ //console shape is no longer valid.kill it.
+ delete this;
+ return;
+ }
+
+ ChunkPoly* poly_list=shape_data_store->poly_list;
+ shape_data_store->poly_list=(ChunkPoly*)spc->poly_data;
+ for(int i=0;i<shape_data_store->num_polys;i++)
+ {
+ for(int j=0;j<4;j++)
+ {
+ shape_data_store->poly_list[i].vert_ind[j]=poly_list[i].vert_ind[j];
+ }
+ }
+ delete [] poly_list;
+ }
+ Shape_UV_Coord_Chunk* succ=(Shape_UV_Coord_Chunk*)lookup_single_child("SHPUVCRD");
+ if(succ)
+ {
+ delete [] shape_data_store->uv_list;
+ shape_data_store->uv_list=(ChunkUV_List*)succ->uv_data;
+ shape_data_store->num_uvs=succ->num_uvs;
+ }
+}
+
+void Console_Shape_Chunk::update_my_chunkshape(ChunkShape & cshp)
+{
+ List<Chunk*> chlist;
+ lookup_child("SHPUVCRD",chlist);
+ while(chlist.size())
+ {
+ delete chlist.first_entry();
+ chlist.delete_first_entry();
+ }
+ lookup_child("SHPPOLYS",chlist);
+ while(chlist.size())
+ {
+ delete chlist.first_entry();
+ chlist.delete_first_entry();
+ }
+ *shape_data_store=cshp;
+ if (shape_data.poly_list) new Shape_Polygon_Chunk (this, shape_data.num_polys);
+ if (shape_data.uv_list) new Shape_UV_Coord_Chunk (this, shape_data.num_uvs);
+
+}
+
+
+/////////////////////////////////////////
+
+// Class Console_Type_Chunk functions
+RIF_IMPLEMENT_DYNCREATE("CONSTYPE",Console_Type_Chunk)
+
+void Console_Type_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ *(int*)data_start=(int)console;
+}
+
+
+/////////////////////////////////////////
+RIF_IMPLEMENT_DYNCREATE("SHPPRPRO",Shape_Preprocessed_Data_Chunk)
+
+Shape_Preprocessed_Data_Chunk::Shape_Preprocessed_Data_Chunk (Chunk_With_Children * parent, const char * data, size_t )
+:Chunk(parent,"SHPPRPRO")
+{
+ block_size=*(int*)data;
+ data+=4;
+ first_pointer=*(int*)data;
+ data+=4;
+
+ if(block_size)
+ {
+ memory_block=new unsigned int[block_size];
+ memcpy(memory_block,data,block_size*4);
+ data+=block_size*4;
+ }
+ else
+ {
+ memory_block=0;
+ }
+
+ num_extra_data=*(int*)data;
+ data+=4;
+
+ if(num_extra_data)
+ {
+ extra_data=new int[num_extra_data];
+ memcpy(extra_data,data,num_extra_data*4);
+ }
+ else
+ {
+ extra_data=0;
+ }
+}
+
+Shape_Preprocessed_Data_Chunk::Shape_Preprocessed_Data_Chunk (Chunk_With_Children * parent,int _block_size,int _first_pointer,unsigned int* _memory_block)
+:Chunk(parent,"SHPPRPRO")
+{
+ num_extra_data=0;
+ extra_data=0;
+ block_size=_block_size;
+ first_pointer=_first_pointer;
+
+ if(block_size)
+ {
+ memory_block=new unsigned int[block_size];
+ memcpy(memory_block,_memory_block,block_size*4);
+ }
+ else
+ {
+ memory_block=0;
+ }
+
+}
+
+void Shape_Preprocessed_Data_Chunk::fill_data_block(char* data_start)
+{
+ strncpy (data_start, identifier, 8);
+ data_start += 8;
+ *((int *) data_start) = chunk_size;
+ data_start += 4;
+
+ *(int*)data_start=block_size;
+ data_start+=4;
+ *(int*)data_start=first_pointer;
+ data_start+=4;
+
+ memcpy(data_start,memory_block,4*block_size);
+ data_start+=4*block_size;
+
+ *(int*)data_start=num_extra_data;
+ data_start+=4;
+ memcpy(data_start,extra_data,4*num_extra_data);
+}
+
+void* Shape_Preprocessed_Data_Chunk::GetMemoryBlock()
+{
+ void* retval=memory_block;
+
+ unsigned int* current=(unsigned int*)&first_pointer;
+ unsigned int* next;
+ while((*current>>16)!=0xffff)
+ {
+ next=&memory_block[(*current)>>16];
+ *current=(unsigned int)&memory_block[(*current)&0xffff];
+ current=next;
+ }
+ *current=(unsigned int)&memory_block[(*current)&0xffff];
+
+ memory_block=0;
+ block_size=0;
+ return retval;
+}
+