avp/src/win95/hierchnk.cpp
2019-08-20 02:22:36 +02:00

610 lines
13 KiB
C++

#include "hierchnk.hpp"
#include "obchunk.hpp"
//#include "animobs.hpp"
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(hierchnk)
/////////////Object_Hierarchy_Chunk////////////////////
RIF_IMPLEMENT_DYNCREATE("OBJCHIER",Object_Hierarchy_Chunk)
//loader for Object_Hierarchy_Chunk
CHUNK_WITH_CHILDREN_LOADER("OBJCHIER",Object_Hierarchy_Chunk)
/*
children for Object_Hierarchy_Chunk:
"OBJCHIER" Object_Hierarchy_Chunk)
"OBJHIERD" Object_Hierarchy_Data_Chunk)
"OBHIERNM" Object_Hierarchy_Name_Chunk)
"HIERBBOX" Hierarchy_Bounding_Box_Chunk)
"OBANSEQS" Object_Animation_Sequences_Chunk)
"OBANALLS" Object_Animation_All_Sequence_Chunk)
*/
List <Object_Hierarchy_Chunk *> Object_Hierarchy_Chunk::list_h_children()
{
List <Chunk *> cl;
lookup_child ("OBJCHIER",cl);
List <Object_Hierarchy_Chunk *> h_l;
for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
{
h_l.add_entry((Object_Hierarchy_Chunk *)cli());
}
return(h_l);
}
Object_Hierarchy_Data_Chunk * Object_Hierarchy_Chunk::get_data ()
{
return((Object_Hierarchy_Data_Chunk *)lookup_single_child ("OBJHIERD"));
}
Object_Hierarchy_Name_Chunk * Object_Hierarchy_Chunk::get_name ()
{
return((Object_Hierarchy_Name_Chunk *)lookup_single_child ("OBHIERNM"));
}
//////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBJHIERD",Object_Hierarchy_Data_Chunk)
Object_Hierarchy_Data_Chunk::Object_Hierarchy_Data_Chunk (Object_Hierarchy_Chunk * parent, const char * obname)
: Chunk (parent, "OBJHIERD"), ob_name (0), object(0)
{
num_extra_data=0;
extra_data=0;
if (obname)
{
ob_name = new char [strlen(obname)+1];
strcpy (ob_name, obname);
Chunk_With_Children * root = GetRootChunk();
List<Chunk *> oblist;
root->lookup_child ("RBOBJECT",oblist);
for (LIF<Chunk *> oli(&oblist); !oli.done(); oli.next())
{
Object_Chunk * ob = (Object_Chunk *)oli();
if (!strcmp (ob->object_data.o_name, ob_name))
{
*((Object_Chunk **)&object) = ob;
break;
}
}
}
}
Object_Hierarchy_Data_Chunk::~Object_Hierarchy_Data_Chunk()
{
if (ob_name)
delete [] ob_name;
if(extra_data)
delete extra_data;
}
size_t Object_Hierarchy_Data_Chunk::size_chunk ()
{
if (ob_name)
{
chunk_size = 12 + 4+4*num_extra_data + strlen(ob_name) + 4 - strlen(ob_name)%4;
}
else
{
chunk_size = 12 + 4+4*num_extra_data + 4;
}
return chunk_size;
}
void Object_Hierarchy_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_extra_data;
data_start+=4;
for (int i=0; i<num_extra_data; i++)
{
*((int *) data_start) = extra_data[i];
data_start += 4;
}
if (ob_name)
{
sprintf (data_start, "%s", ob_name);
}
else
{
*data_start = 0;
}
}
#if UseOldChunkLoader
Object_Hierarchy_Data_Chunk::Object_Hierarchy_Data_Chunk (Object_Hierarchy_Chunk * parent, const char * data_start, size_t /*ssize*/)
: Chunk (parent, "OBJHIERD"), object(0), ob_name (0)
{
num_extra_data=0;
extra_data=0;
data_start+=40;
if (strlen(data_start))
{
ob_name = new char [strlen(data_start) + 1];
strcpy (ob_name, data_start);
}
}
#else
Object_Hierarchy_Data_Chunk::Object_Hierarchy_Data_Chunk (Chunk_With_Children * parent, const char * data_start, size_t /*ssize*/)
: Chunk (parent, "OBJHIERD"), object(0), ob_name (0)
{
num_extra_data=*(int*)data_start;
data_start+=4;
if(num_extra_data)
extra_data=new int[num_extra_data];
else
extra_data=0;
for (int i=0; i<num_extra_data; i++)
{
extra_data[i] = *((int *) data_start);
data_start += 4;
}
if (strlen(data_start))
{
ob_name = new char [strlen(data_start) + 1];
strcpy (ob_name, data_start);
}
}
#endif
void Object_Hierarchy_Data_Chunk::post_input_processing ()
{
find_object_for_this_section();
}
void Object_Hierarchy_Data_Chunk::find_object_for_this_section ()
{
*((Object_Chunk **)&object) = NULL;
Chunk_With_Children * root = GetRootChunk();
List<Chunk *> oblist;
root->lookup_child ("RBOBJECT",oblist);
for (LIF<Chunk *> oli(&oblist); !oli.done(); oli.next())
{
Object_Chunk * ob = (Object_Chunk *)oli();
if (!strcmp (ob->object_data.o_name, ob_name))
{
*((Object_Chunk **)&object) = ob;
break;
}
}
}
//////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBHIERNM",Object_Hierarchy_Name_Chunk)
Object_Hierarchy_Name_Chunk::Object_Hierarchy_Name_Chunk (Object_Hierarchy_Chunk * parent, const char * hname)
: Chunk (parent, "OBHIERNM")
{
if (hname)
{
hierarchy_name = new char [strlen(hname)+1];
strcpy (hierarchy_name, hname);
}
else
{
hierarchy_name = new char [1];
*hierarchy_name = 0;
}
}
Object_Hierarchy_Name_Chunk::~Object_Hierarchy_Name_Chunk()
{
if (hierarchy_name)
{
delete [] hierarchy_name;
}
}
void Object_Hierarchy_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, hierarchy_name);
}
Object_Hierarchy_Name_Chunk::Object_Hierarchy_Name_Chunk (Chunk_With_Children * parent, const char * data, size_t /*ssize*/)
: Chunk (parent, "OBHIERNM")
{
hierarchy_name = new char [strlen(data)+1];
strcpy (hierarchy_name, data);
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBHALTSH",Object_Hierarchy_Alternate_Shape_Set_Chunk)
Object_Hierarchy_Alternate_Shape_Set_Chunk::Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,int num,const char* name)
:Chunk(parent,"OBHALTSH")
{
Shape_Set_Name=new char[strlen(name)+1];
Shape_Set_Num=num;
strcpy(Shape_Set_Name,name);
flags=0;
spare[0]=spare[1]=spare[2]=0;
}
Object_Hierarchy_Alternate_Shape_Set_Chunk::Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,const char* name)
:Chunk(parent,"OBHALTSH")
{
Shape_Set_Name=new char[strlen(name)+1];
strcpy(Shape_Set_Name,name);
flags=0;
spare[0]=spare[1]=spare[2]=0;
Shape_Set_Num=-1;
//find next available shape set number
List<Chunk*> chlist;
parent->lookup_child("OBHALTSH",chlist);
int num=0;
for(LIF<Chunk*> chlif(&chlist);!chlif.done();)
{
Object_Hierarchy_Alternate_Shape_Set_Chunk* ohassc=(Object_Hierarchy_Alternate_Shape_Set_Chunk*) chlif();
if(ohassc->Shape_Set_Num==num)
{
num++;
chlif.restart();
}
else
{
chlif.next();
}
}
Shape_Set_Num=num;
}
Object_Hierarchy_Alternate_Shape_Set_Chunk::Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"OBHALTSH")
{
int i;
Shape_Set_Num=*(int*)data;
data+=4;
int name_length=strlen(data)+1;
Shape_Set_Name=new char[name_length];
strcpy(Shape_Set_Name,data);
data+=(name_length+3)&~3;
int num_shapes=*(int*)data;
data+=4;
for(i=0;i<num_shapes;i++)
{
Replaced_Shape_Details* rsd=new Replaced_Shape_Details;
name_length=strlen(data)+1;
rsd->old_object_name=new char[name_length];
strcpy(rsd->old_object_name,data);
data+=(name_length+3)&~3;
name_length=strlen(data)+1;
rsd->new_object_name=new char[name_length];
strcpy(rsd->new_object_name,data);
data+=(name_length+3)&~3;
Replaced_Shape_List.add_entry(rsd);
}
flags=*(int*)data;
data+=4;
for(i=0;i<3;i++)
{
spare[i]=*(int*)data;
data+=4;
}
}
Object_Hierarchy_Alternate_Shape_Set_Chunk::~Object_Hierarchy_Alternate_Shape_Set_Chunk()
{
if(Shape_Set_Name) delete Shape_Set_Name;
while(Replaced_Shape_List.size())
{
delete Replaced_Shape_List.first_entry();
Replaced_Shape_List.delete_first_entry();
}
}
void Object_Hierarchy_Alternate_Shape_Set_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=Shape_Set_Num;
data_start+=4;
strcpy(data_start,Shape_Set_Name);
data_start+=(strlen(Shape_Set_Name)+4)&~3;
*(int*)data_start=Replaced_Shape_List.size();
data_start+=4;
for(LIF<Replaced_Shape_Details*> rlif(&Replaced_Shape_List);!rlif.done();rlif.next())
{
strcpy(data_start,rlif()->old_object_name);
data_start+=(strlen(rlif()->old_object_name)+4)&~3;
strcpy(data_start,rlif()->new_object_name);
data_start+=(strlen(rlif()->new_object_name)+4)&~3;
}
*(int*)data_start=flags;
data_start+=4;
for(int i=0;i<3;i++)
{
*(int*)data_start=spare[i];
data_start+=4;
}
}
size_t Object_Hierarchy_Alternate_Shape_Set_Chunk::size_chunk()
{
chunk_size=36;
chunk_size+=(strlen(Shape_Set_Name)+4)&~3;
for(LIF<Replaced_Shape_Details*> rlif(&Replaced_Shape_List);!rlif.done();rlif.next())
{
chunk_size+=(strlen(rlif()->old_object_name)+4)&~3;
chunk_size+=(strlen(rlif()->new_object_name)+4)&~3;
}
return chunk_size;
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("HSETCOLL",Hierarchy_Shape_Set_Collection_Chunk)
Hierarchy_Shape_Set_Collection_Chunk::Hierarchy_Shape_Set_Collection_Chunk(Chunk_With_Children* parent,int num,const char* name)
:Chunk(parent,"HSETCOLL")
{
Set_Collection_Name=new char[strlen(name)+1];
Set_Collection_Num=num;
strcpy(Set_Collection_Name,name);
TypeIndex=flags=0;
}
Hierarchy_Shape_Set_Collection_Chunk::Hierarchy_Shape_Set_Collection_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"HSETCOLL")
{
Set_Collection_Num=*(int*)data;
data+=4;
int name_length=strlen(data)+1;
Set_Collection_Name=new char[name_length];
strcpy(Set_Collection_Name,data);
data+=(name_length+3)&~3;
int list_length=*(int*)data;
data+=4;
for(int i=0;i<list_length;i++)
{
Index_List.add_entry(*(int*)data);
data+=4;
}
TypeIndex=*(int*)data;
data+=4;
flags=*(int*)data;
data+=4;
}
Hierarchy_Shape_Set_Collection_Chunk::~Hierarchy_Shape_Set_Collection_Chunk()
{
if(Set_Collection_Name) delete Set_Collection_Name;
}
void Hierarchy_Shape_Set_Collection_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=Set_Collection_Num;
data_start+=4;
strcpy(data_start,Set_Collection_Name);
data_start+=(strlen(Set_Collection_Name)+4)&~3;
*(int*)data_start=Index_List.size();
data_start+=4;
for(LIF<int> slif(&Index_List);!slif.done();slif.next())
{
*(int*)data_start=slif();
data_start+=4;
}
*(int*)data_start=TypeIndex;
data_start+=4;
*(int*)data_start=flags;
data_start+=4;
}
size_t Hierarchy_Shape_Set_Collection_Chunk::size_chunk()
{
chunk_size=12+16;
chunk_size+=(strlen(Set_Collection_Name)+4)&~3;
chunk_size+=Index_List.size()*4;
return chunk_size;
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("HIDEGDIS",Hierarchy_Degradation_Distance_Chunk)
Hierarchy_Degradation_Distance_Chunk::Hierarchy_Degradation_Distance_Chunk(Chunk_With_Children* parent,int _num_detail_levels)
:Chunk(parent,"HIDEGDIS")
{
num_detail_levels=_num_detail_levels;
if(num_detail_levels)
{
distance_array=new int[num_detail_levels];
}
else
{
distance_array=0;
}
//fill in some arbitrary distance values
for(int i=0;i<num_detail_levels;i++)
{
distance_array[i]=i*10000;
}
}
Hierarchy_Degradation_Distance_Chunk::Hierarchy_Degradation_Distance_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"HIDEGDIS")
{
num_detail_levels=*(int*)data;
data+=sizeof(int);
if(num_detail_levels)
{
distance_array=new int[num_detail_levels];
}
else
{
distance_array=0;
}
for(int i=0;i<num_detail_levels;i++)
{
distance_array[i]=*(int*)data;
data+=sizeof(int);
}
}
Hierarchy_Degradation_Distance_Chunk::~Hierarchy_Degradation_Distance_Chunk()
{
if(distance_array)delete distance_array;
}
void Hierarchy_Degradation_Distance_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_detail_levels;
data_start+=4;
for(int i=0;i<num_detail_levels;i++)
{
*(int*)data_start=distance_array[i];
data_start+=4;
}
}
size_t Hierarchy_Degradation_Distance_Chunk::size_chunk()
{
chunk_size=16+num_detail_levels*4;
return chunk_size;
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("HIERBBOX",Hierarchy_Bounding_Box_Chunk)
#if UseOldChunkLoader
Hierarchy_Bounding_Box_Chunk::Hierarchy_Bounding_Box_Chunk(Chunk_With_Children* parent,const char* data,size_t datasize)
:Chunk(parent,"HIERBBOX")
{
assert(datasize==2*sizeof(ChunkVector));
min=*(ChunkVector*)data;
data+=sizeof(ChunkVector);
max=*(ChunkVector*)data;
}
#else
Hierarchy_Bounding_Box_Chunk::Hierarchy_Bounding_Box_Chunk(Chunk_With_Children* parent,const char* data,size_t datasize)
:Chunk(parent,"HIERBBOX")
{
assert(datasize==2*sizeof(ChunkVectorInt));
min=*(ChunkVectorInt*)data;
data+=sizeof(ChunkVectorInt);
max=*(ChunkVectorInt*)data;
}
#endif
void Hierarchy_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;
*(ChunkVectorInt*)data_start=min;
data_start+=sizeof(ChunkVectorInt);
*(ChunkVectorInt*)data_start=max;
}
///////////////////////////////////////////////////