diff options
Diffstat (limited to '3dc/win95/SHPCHUNK.CPP')
| -rw-r--r-- | 3dc/win95/SHPCHUNK.CPP | 3869 |
1 files changed, 3869 insertions, 0 deletions
diff --git a/3dc/win95/SHPCHUNK.CPP b/3dc/win95/SHPCHUNK.CPP new file mode 100644 index 0000000..a494767 --- /dev/null +++ b/3dc/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; +} + |
