Files
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

1714 lines
52 KiB
C++

#include "rpl4.h"
#pragma hdrstop
#include "rpl4vid.h"
#include "..\rp\chute.h"
#include "..\munga\door.h"
#include "..\munga\doorfram.h"
#include "..\munga_l4\l4vidrnd.h"
#include "..\munga\mission.h"
#include "..\rp\rpplayer.h"
#include "..\rp\weapsys.h"
#include "..\munga\notation.h"
#include "..\munga\namelist.h"
#include "..\rp\vtv.h"
#include "..\munga\app.h"
// RB 1/14/07
//#include <dpl\dpl.h>
//#include <dpl\dplutils.h>
//#include <dpl\dpl_vpx.h>
extern Entity
*Entity_Being_Created; // !!! temp, till callback handlers become a class
// HACK, this code makes sure the left and right engine geometry is loaded
// one time and re-used. A more generic solution using the connection
// manager will be created once we are sure it is safe to apply this
// optimization to all cases.
d3d_OBJECT
*left_engine,
*right_engine;
//
//#############################################################################
// Constructor for the video renderer
//#############################################################################
//
RPL4VideoRenderer::RPL4VideoRenderer(
HWND hWnd,
unsigned int screenWidth,
unsigned int screenHeight,
bool fullscreen,
InterestType interest_type,
InterestDepth depth_calibration
) : DPLRenderer(hWnd, screenWidth, screenHeight, fullscreen, interest_type, depth_calibration)
{
//STUBBED: DPL RB 1/14/07
vtvCount = 0;
vtvsExpected = 999;
////
//// Preload a couple of things for DPL
////
// dpl_LoadObject ( "chg", dpl_load_normal );
// dpl_LoadObject ( "rivet", dpl_load_normal );
// dpl_LoadObject ( "lsaber", dpl_load_normal );
// dpl_LoadObject ( "bst", dpl_load_normal );
// dpl_LoadObject ( "tsphere", dpl_load_normal );
}
//
//#############################################################################
// Destructor for the video renderer
//#############################################################################
//
RPL4VideoRenderer::~RPL4VideoRenderer()
{
}
#if 0
void
RPL4VideoRenderer::MakeJointedMoverRenderables(
Entity *entity
ViewFrom view_type
)
{
bool inDeathZone
dpl_ISECT_MODE
intersect_mode;
uint32
intersect_mask;
char
my_filename[40];
dpl_LOAD_MODE
cache_mode;
JointedMover
*jointed_mover;
Verify(entity->IsDerivedFrom(JointedMover::GetClassDerivations());
jointed_mover = Cast_Object(
JointedMover*,
entity
);
cache_mode = dpl_load_nocache;
//
//~~~~~~~~~~~~~~~~~~~~~~~
// Outside or Inside View
//~~~~~~~~~~~~~~~~~~~~~~~
//
if (type == inside_entity)
{
inDepthZone = true;
//buildInZone = dplDeathZone;
intersect_mode = dpl_isect_mode_obj;
intersect_mask = NULL;
skl_type = EntitySegment::SkeletonType_A;
}
else
{
inDepthZone = true;
//buildInZone = dplDeathZone;
intersect_mode = dpl_isect_mode_geometry;
intersect_mask = INTERSECT_ALL;
skl_type = EntitySegment::SkeletonType_N;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the root renderable and tie it to the entity
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RootRenderable *this_root =
new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Dynamic, // How/when to execute the renderable
NULL, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask); // intersection mask for the object
Register_Object(this_root);
if(eyeRelative && (entity == GetLinkedEntity()))
{
dpl_DCS* aDCS=this_root->GetDCS();
Check_Pointer(aDCS);
Check_Pointer(dplTestEyeDCS);
dpl_AddDCSToDCS( aDCS, dplTestEyeDCS );
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// create an array for the parent DCS' sizeof(segmentTable)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
dpl_DCS **dcs_array = new (dpl_DCS(*[jointed_mover->segmentCount]));
Register_Pointer(dcs_array);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// Get The Joint Subsystem
//~~~~~~~~~~~~~~~~~~~~~~~~
//
CString *object_file_name;
JointSubsystem* joint_subsystem = jointed_mover->GetJointSubsystem();
Check(joint_subsystem);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the Segment table for this jointed Mover
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EntitySegment::SegmentTableIterator segment_iterator(jointed_mover->segmentTable);
EntitySegment *current_segment;
while ((current_segment = segment_iterator.ReadAndNext()) != NULL)
{
Check(current_segment);
//
//~~~~~~~~~~~~~~~~~~~~~~
// Get the offset matrix
//~~~~~~~~~~~~~~~~~~~~~~
//
LinearMatrix offset_matrix;
offset_matrix = current_segment->GetBaseOffset();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the parent DCS of the DCS we will be creating
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
dpl_DCS *parent_DCS;
if(!current_segment->GetParent())
{
parent_DCS = this_root->GetDCS();
}
else
{
int parent_index;
parent_index = current_segment->GetParentIndex();
Verify(
(parent_index >= 0) &&
(parent_index < jointed_mover->segmentCount)
);
parent_DCS = dcs_array[parent_index];
}
Check_Pointer(parent_DCS);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// See if this segment is a Site
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if(current_segment->IsSiteSegment())
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// If this is an eye site build the eye renderable
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if(type == insideEntity &&
strcmp(current_segment->GetName(), "siteeyepoint") == 0)
{
EulerAngles* eyepoint_rotation =
(EulerAngles*)entity->GetAttributePointer("EyepointRotation");
#if 0 //DEBUG_LEVEL > 0
DPLEyeRenderable* this_eye =
#endif
mCamera =
new DPLEyeRenderable(
entity,
false,
offset_matrix,
parent_DCS,
dplMainView,
eyepoint_rotation
);
Register_Object(this_eye);
}
continue;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the dpl object and load it
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
object_file_name = current_segment->GetVideoObjectName(skl_type);
if(object_file_name)
{
Dump(*object_file_name);
//cout<<"normal object "<<*object_file_name<<"\n";
strcpy(my_filename,*object_file_name);
*(my_filename + (strlen(my_filename) - 4)) = '\0';
this_object = dpl_LoadObject ( my_filename,cache_mode );
}
else
{
this_object = NULL;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the segment index
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int this_segment_index;
this_segment_index = current_segment->GetIndex();
Verify(
(this_segment_index >= 0) &&
(this_segment_index < jointed_mover->segmentCount)
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// If this segment has a joint Get it
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int joint_index;
joint_index = current_segment->GetJointIndex();
Joint::JointType joint_type;
Joint *this_joint = NULL;
if(joint_index == -1)
{
joint_type = Joint::StaticJointType;
}
else
{
Verify(joint_index < joint_subsystem->GetJointCount());
this_joint = joint_subsystem->GetJoint(joint_index);
Check(this_joint);
joint_type = this_joint->GetJointType();
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Make the appropriate renderable
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
switch(joint_type)
{
case Joint::HingeXJointType:
case Joint::HingeYJointType:
case Joint::HingeZJointType:
{
HingeRenderable *this_child =
new HingeRenderable(
entity, // Entity to attach the renderable to
HingeRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
parent_DCS, // the parent DCS we will be offsetting from
&offset_matrix, // offset matrix to be applied prior to joint DCS
this_joint->GetHingePtr()); // Hinge attribute we will use to control the joint
Register_Object(this_child);
dcs_array[this_segment_index] = this_child->GetDCS();
}
break;
}
case Joint::BallJointType:
{
BallJointRenderable *this_child =
new BallJointRenderable(
entity, // Entity to attach the renderable to
BallJointRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
parent_DCS, // the parent DCS we will be offsetting from
&offset_matrix, // offset matrix to be applied prior to joint DCS
this_joint->GetEulerAnglesPtr());// Euler angles to control rotation of the ball joint
Register_Object(this_child);
dcs_array[this_segment_index] = this_child->GetDCS();
break;
}
case Joint::BallTranslationJointType:
{
BallTranslateJointRenderable *this_child =
new BallTranslateJointRenderable(
entity, // Entity to attach the renderable to
BallTranslateJointRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
parent_DCS, // the parent DCS we will be offsetting from
&offset_matrix, // offset matrix to be applied prior to joint DCS
this_joint->GetEulerAnglesPtr(), // Euler angles to control rotation of the ball joint
this_joint->GetTranslationPtr() // offset for the translation part of the joint
);
Register_Object(this_child);
dcs_array[this_segment_index] = this_child->GetDCS();
break;
}
case Joint::StaticJointType:
default:
{
DPLStaticChildRenderable *this_child =
new DPLStaticChildRenderable(
entity,
false,
this_object,
intersect_mode,
intersect_mask,
offset_matrix,
parent_DCS
);
Register_Object(this_child);
dcs_array[this_segment_index] = this_child->GetDCS();
break;
}
}
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Cycle through the VTV's subsystems and create the site renderables
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
for(int ii=0;ii<entity->GetSubsystemCount();++ii)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Controls Mapper is not propagated across
// the network so we must ignore it here for replicants
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if (ii == VTV::ControlsMapperSubsystem)
{
continue;
}
Subsystem *current_subsystem = entity->GetSubsystem(ii);
Check(current_subsystem);
int site_index = current_subsystem->GetSegmentIndex();
if (site_index != -1)
{
EntitySegment *site_segment = entity->GetSegment(site_index);
Check(site_segment);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the parentDCS for this site
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
dpl_DCS *parent_DCS;
if(!site_segment->GetParent())
{
parent_DCS = this_root->GetDCS();
}
else
{
int parent_index;
parent_index = site_segment->GetParentIndex();
Verify(
(parent_index >= 0) &&
(parent_index < jointed_mover->segmentCount)
);
parent_DCS = dcs_array[parent_index];
}
Check_Pointer(parent_DCS);
//
//~~~~~~~~~~~~~~~~~~~~
// Get the base offset
//~~~~~~~~~~~~~~~~~~~~
//
LinearMatrix base_offset = site_segment->GetBaseOffset();
switch(current_subsystem->GetClassID())
{
class LaserDrillClassID:
this_object = dpl_LoadObject ( "lsaber", dpl_load_normal );
Check_Pointer(this_object);
Vector3D* laser_scale =
(Vector3D*)current_subsystem->GetAttributePointer("LaserScale");
Logical* laser_on =
(Logical*)current_subsystem->GetAttributePointer("LaserOn");
DPLScaleRenderable *this_scaler =
new DPLScaleRenderable(
entity,
buildInZone,
this_object,
dpl_isect_mode,
NULL,
base_offset,
parent_DCS,
laser_scale,
laser_on
);
Register_Object(this_scaler);
break;
}
}
}
Unregister_Pointer(dcs_array);
delete[] dcs_array;
Check_Fpu();
}
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// RPL4VideoRenderer::RecurseSKLFile This routine is called recursively to
// to descend the hiearchy of a notation file and create all the renderables
// needed to get an object visible.
//
void
RPL4VideoRenderer::RecurseSKLFile(
Entity *entity,
HierarchicalDrawComponent *parent,
NotationFile *mech_skeleton,
const char *page_name,
int recursion_depth,
ViewFrom type,
int *joint_counter,
dpl_LOAD_MODE cache_mode
)
{
//STUBBED: DPL RB 1/14/07
NameList
*joint_pages,
*site_pages;
NameList::Entry
*entry;
const char
*site_page_name,
*next_joint_page_name; // The next joint name (argument to a recursive call)
const char
*object_file_name,
*my_joint_type;
char
*gun_name,
*gun_attribute_name,
my_filename[40];
int
gun_site;
#ifdef NOISY_RENDERER
int
i; // loop counter
#endif
Point3D
translation(0,0,0);
EulerAngles
rotation(0,0,0);
HierarchicalDrawComponent
*next_parent;
d3d_OBJECT *this_object = NULL;
dpl_ISECT_MODE
intersect_mode;
uint32
intersect_mask;
bool inDeathZone;
//
// get the intersect mode hooked up properly
//
if(type == insideEntity)
{
inDeathZone = true;
//buildInZone = dplDeathZone;
// intersect_mode = dpl_isect_mode_obj;
intersect_mask = NULL;
}
else
{
inDeathZone = false;
//buildInZone = dplMainZone;
// intersect_mode = dpl_isect_mode_geometry;
intersect_mask = INTERSECT_ALL;
}
//
// indent by the recursion depth and print out the current page name
//
#ifdef NOISY_RENDERER
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Tell(page_name << "\n");
#endif
//
// suck the brains out of this page to create the renderable from
//
mech_skeleton->GetEntry(page_name, "tranx" ,&translation.x);
mech_skeleton->GetEntry(page_name, "trany" ,&translation.y);
mech_skeleton->GetEntry(page_name, "tranz" ,&translation.z);
mech_skeleton->GetEntry(page_name, "pitch" ,&rotation.pitch.angle);
mech_skeleton->GetEntry(page_name, "yaw" ,&rotation.yaw.angle);
mech_skeleton->GetEntry(page_name, "roll" ,&rotation.roll.angle);
if(mech_skeleton->GetEntry(page_name, "Object" ,&object_file_name))
{
strcpy(my_filename,object_file_name);
*(my_filename + (strlen(my_filename) - 4)) = '\0';
#ifdef NOISY_RENDERER
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Tell("BGF file: " << my_filename << "\n");
#endif
// // HACK, this code makes sure the left and right engine geometry is loaded
// // one time and re-used. A more generic solution using the connection
// // manager will be created once we are sure it is safe to apply this
// // optimization to all cases.
// if( (strcmp("vra",my_filename) == 0) ||
// (strcmp("vrc",my_filename) == 0) ||
// (strcmp("vrn",my_filename) == 0) ||
// (strcmp("vrt",my_filename) == 0))
// {
// if(right_engine == 0)
// {
// char *file = new char[strlen(my_filename) + 5];
// strcpy_s(file,strlen(my_filename)+5,my_filename);
// strcat_s(file,strlen(my_filename)+5,".bgf");
// this_object = d3d_OBJECT::LoadObject ( GetDevice(), file );
// right_engine = this_object;
//// cout<<"Load right engine\n";
// }
// else
// {
// this_object = right_engine;
//// cout<<"re-use right engine\n";
// }
// }
// else if( (strcmp("vla",my_filename) == 0) ||
// (strcmp("vlc",my_filename) == 0) ||
// (strcmp("vln",my_filename) == 0) ||
// (strcmp("vlt",my_filename) == 0))
// {
// if(left_engine == 0)
// {
// char *file = new char[strlen(my_filename) + 5];
// strcpy_s(file,strlen(my_filename)+5,my_filename);
// strcat_s(file,strlen(my_filename)+5,".bgf");
// this_object = d3d_OBJECT::LoadObject ( GetDevice(), file );
// left_engine = this_object;
//// cout<<"Load left engine\n";
// }
// else
// {
// this_object = left_engine;
//// cout<<"re-use left engine\n";
// }
// }
// else
{
char *file = new char[strlen(my_filename) + 5];
strcpy_s(file,strlen(my_filename)+5,my_filename);
strcat_s(file,strlen(my_filename)+5,".bgf");
this_object = d3d_OBJECT::LoadObject ( GetDevice(), file );
}
}
else
{
this_object = NULL;
}
//
// dump out the data for me to look at
//
#ifdef NOISY_RENDERER
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Dump(translation);
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Dump(rotation);
#endif
//
// Construct the renderable to display this part of the thing
//
LinearMatrix Offset_Matrix;
Offset_Matrix = translation;
Offset_Matrix = rotation;
my_joint_type = "none";
mech_skeleton->GetEntry(page_name, "Type" ,&my_joint_type);
if(recursion_depth>1)
(*joint_counter)++;
if(strncmp(my_joint_type,"hinge",5) == 0)
{
Tell("Hinge Joint " << (*joint_counter) << "\n");
VTV *vtv = (VTV*) entity;
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
Verify(
(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
Joint::HingeXJointType) ||
(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
Joint::HingeYJointType) ||
(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
Joint::HingeZJointType)
);
const Hinge *hinge_joint =
&joint_subsystem->GetJoint(*joint_counter)->GetHinge();
HingeRenderable *this_child =
new HingeRenderable(
entity, // Entity to attach the renderable to
HingeRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
inDeathZone, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
parent, // the parent DCS we will be offsetting from
&Offset_Matrix, // offset matrix to be applied prior to joint DCS
hinge_joint); // Hinge attribute we will use to control the joint
Register_Object(this_child);
next_parent = this_child;
}
else if(strcmp(my_joint_type,"ball") == 0)
{
Tell("Ball Joint " << (*joint_counter) << "\n");
VTV *vtv = (VTV*) entity;
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
const EulerAngles *euler_angles =
&joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles();
Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
Joint::BallJointType);
BallJointRenderable *this_child =
new BallJointRenderable(
entity, // Entity to attach the renderable to
BallJointRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
parent, // the parent DCS we will be offsetting from
&Offset_Matrix, // offset matrix to be applied prior to joint DCS
euler_angles); // Euler angles to control rotation of the ball joint
Register_Object(this_child);
next_parent = this_child;
}
else if(strcmp(my_joint_type,"balltranslate") == 0)
{
Tell("Ball Translation Joint " << (*joint_counter) << "\n");
VTV *vtv = (VTV*) entity;
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
const EulerAngles *euler_angles =
&joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles();
const Point3D *point_3D =
&joint_subsystem->GetJoint(*joint_counter)->GetTranslation();
Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
Joint::BallTranslationJointType);
BallTranslateJointRenderable *this_child =
new BallTranslateJointRenderable(
entity, // Entity to attach the renderable to
BallTranslateJointRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
parent, // the parent DCS we will be offsetting from
&Offset_Matrix, // offset matrix to be applied prior to joint DCS
euler_angles, // Euler angles to control rotation of the ball joint
point_3D); // offset for the translation part of the joint
Register_Object(this_child);
next_parent = this_child;
}
else
{
// Tell("Static Joint" << (*joint_counter) << "\n");
DPLStaticChildRenderable *this_child =
new DPLStaticChildRenderable(
entity,
inDeathZone,
this_object,
intersect_mode,
intersect_mask,
Offset_Matrix,
parent
);
Register_Object(this_child);
next_parent = this_child;
}
//
// Get a the list of joint pages from the current page
//
if(type == insideEntity)
{
// dpl_SetDCSNearField ( next_parent_dcs, True );
// dpl_FlushDCS(next_parent_dcs);
}
joint_pages = mech_skeleton->MakeEntryList(page_name,"joint");
Register_Object(joint_pages);
recursion_depth++;
//
// Recursively process all the joint pages on the current page
//
for( entry = joint_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
// Get the name of the next joint page
next_joint_page_name = (char *)entry->dataReference;
// Process the next page recursively through this routine
RecurseSKLFile(
entity,
next_parent,
mech_skeleton,
next_joint_page_name,
recursion_depth,
type,
joint_counter,
cache_mode);
}
//
// now check the list of sites for stuff to hook up
//
site_pages = mech_skeleton->MakeEntryList(page_name,"site");
Register_Object(site_pages);
//
// process all the site pages on the current page
//
for( entry = site_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
// Get the name of the next joint page
site_page_name = (char *)entry->dataReference;
//
// Setup a eyepoint site, connect it to a rotation attribute so we can move it
// arround.
//
if(type == insideEntity &&
strcmp(site_page_name, "siteeyepoint") == 0)
{
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
mech_skeleton->GetEntry(site_page_name, "pitch" ,&rotation.pitch.angle);
mech_skeleton->GetEntry(site_page_name, "yaw" ,&rotation.yaw.angle);
mech_skeleton->GetEntry(site_page_name, "roll" ,&rotation.roll.angle);
#ifdef NOISY_RENDERER
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Tell(site_page_name << "\n");
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Dump(translation);
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Dump(rotation);
#endif
EulerAngles* eyepoint_rotation = (EulerAngles*)entity->GetAttributePointer("EyepointRotation");
Offset_Matrix = translation;
Offset_Matrix = rotation;
#if 0 //DEBUG_LEVEL > 0
DPLEyeRenderable* this_eye =
#endif
mCamera =
new DPLEyeRenderable(
entity,
// buildInZone,
Offset_Matrix,
next_parent,
eyepoint_rotation
);
Register_Object(this_eye);
}
//
// Setup a gunport site, this works for all the sites
// this is kind of funky but will be replaced as the VID file goes on line.
// !!! Hack
//
gun_site = False;
gun_name = "";
gun_attribute_name = "";
if(strcmp(site_page_name,"sitefrontrightport") == 0)
{
gun_site = True;
gun_name = "LaserGun1";
gun_attribute_name = "FrontLaserOn";
}
else if(strcmp(site_page_name,"sitefrontleftport") == 0)
{
gun_site = True;
gun_name = "LaserGun2";
gun_attribute_name = "FrontLaserOn";
}
else if(strcmp(site_page_name,"sitefrontcenterport") == 0)
{
gun_site = True;
gun_name = "LaserGun";
gun_attribute_name = "FrontLaserOn";
}
else if(strcmp(site_page_name,"sitebackrightport") == 0)
{
gun_site = True;
gun_name = "LaserGun1";
gun_attribute_name = "RearLaserOn";
}
else if(strcmp(site_page_name,"sitebackleftport") == 0)
{
gun_site = True;
gun_name = "LaserGun2";
gun_attribute_name = "RearLaserOn";
}
else if(strcmp(site_page_name,"sitebackcenterport") == 0)
{
gun_site = True;
gun_name = "LaserGun";
gun_attribute_name = "RearLaserOn";
}
if(gun_site)
{
LaserGun* laser_subsystem=
(LaserGun*)entity->FindSubsystem(gun_name);
if(laser_subsystem)
{
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
mech_skeleton->GetEntry(site_page_name, "pitch" ,&rotation.pitch.angle);
mech_skeleton->GetEntry(site_page_name, "yaw" ,&rotation.yaw.angle);
mech_skeleton->GetEntry(site_page_name, "roll" ,&rotation.roll.angle);
Vector3D* laser_scale =
(Vector3D*)laser_subsystem->GetAttributePointer("LaserScale");
Logical* laser_on =
(Logical*)laser_subsystem->GetAttributePointer(gun_attribute_name);
this_object = d3d_OBJECT::LoadObject ( GetDevice(), "lsaber.bgf" );
if( laser_subsystem && laser_scale && laser_on && this_object)
{
Tell("Hooked "<<gun_name<<" to site "<<site_page_name<<"\n");
Check(laser_scale);
Check_Pointer(laser_on);
Offset_Matrix.BuildIdentity();
Offset_Matrix = translation;
Offset_Matrix = rotation;
#if DEBUG_LEVEL > 0
DPLScaleRenderable *this_scaler =
#endif
new DPLScaleRenderable(
entity,
inDeathZone,
this_object,
intersect_mode,
intersect_mask,
Offset_Matrix,
next_parent,
laser_scale,
laser_on);
Register_Object(this_scaler);
}
}
}
//
// Setup a chute site, get the position and attributes to control it and bind
// them all up for use.
//
if(strcmp(site_page_name, "sitechute") == 0)
{
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
Chute* chute_subsystem=
(Chute*)entity->FindSubsystem("Chute");
if (chute_subsystem)
{
Check(chute_subsystem);
Quaternion* chute_rotation =
(Quaternion*)chute_subsystem->GetAttributePointer("ChuteDirection");
Vector3D* chute_scale =
(Vector3D*)chute_subsystem->GetAttributePointer("ScaleFactor");
Logical* chute_open =
(Logical*)chute_subsystem->GetAttributePointer("ChuteOn");
this_object = d3d_OBJECT::LoadObject ( GetDevice(), "cht.bgf" );
if(chute_rotation && chute_scale && chute_open && this_object)
{
Check(chute_rotation);
Check(chute_scale);
Check_Pointer(chute_open);
Check_Pointer(this_object);
Offset_Matrix.BuildIdentity();
Offset_Matrix = translation;
#if DEBUG_LEVEL > 0
DPLScaleQuatRenderable *this_scaler =
#endif
new DPLScaleQuatRenderable(
entity,
inDeathZone,
this_object,
intersect_mode,
intersect_mask,
Offset_Matrix,
next_parent,
chute_rotation,
chute_scale,
chute_open);
Register_Object(this_scaler);
}
else
{
if(!chute_rotation)
DEBUG_STREAM<<"ChuteSite couldn't find ChuteDirection attribute\n" << std::flush;
if(!chute_scale)
DEBUG_STREAM<<"ChuteSite couldn't find ChuteScale attribute\n" << std::flush;
if(!chute_open)
DEBUG_STREAM<<"ChuteSite couldn't find ChuteOn attribute\n" << std::flush;
if(!this_object)
DEBUG_STREAM<<"ChuteSite couldn't find chute DPL object\n" << std::flush;
}
}
}
//
// Setup a booster site, get the site position and the attribute(s) that will
// control the booster. Setup origin matrix and renderables to control the
// appearance of the booster.
//
if(strcmp(site_page_name, "sitebooster") == 0)
{
#ifdef NOISY_RENDERER
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Tell(site_page_name << "\n");
Tell(recursion_depth);
for (i = 0; i < recursion_depth; i++)
Tell("..");
Dump(translation);
#endif
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
Vector3D* booster_scale =
(Vector3D*)entity->GetAttributePointer("BoosterScale");
Logical* booster_on =
(Logical*)entity->GetAttributePointer("BoosterOn");
this_object = d3d_OBJECT::LoadObject ( GetDevice(), "bst.bgf" );
if( booster_scale && booster_on && this_object)
{
Check(booster_scale);
Check_Pointer(booster_on);
Offset_Matrix.BuildIdentity();
Offset_Matrix = translation;
#if DEBUG_LEVEL > 0
DPLScaleRenderable* this_scaler =
#endif
/*new DPLScaleRenderable(
entity,
inDeathZone,
this_object,
intersect_mode,
intersect_mask,
Offset_Matrix,
next_parent,
booster_scale,
booster_on);*/
}
else
{
if(!booster_scale)
DEBUG_STREAM<<"BoosterSite couldn't find BoosterScale attribute\n" << std::flush;
if(!booster_on)
DEBUG_STREAM<<"BoosterSite couldn't find BoosterOn attribute\n" << std::flush;
if(!this_object)
DEBUG_STREAM<<"BoosterSite couldn't find booster DPL object\n" << std::flush;
}
Scalar* booster_smoke_density =
(Scalar*)entity->GetAttributePointer("BoosterSmokeDensity");
if( booster_smoke_density )
{
translation.z +=3.0;
#if 1
#if DEBUG_LEVEL > 0
DPLRepeatSFXRenderable* this_effect =
#endif
new DPLRepeatSFXRenderable(
entity,
inDeathZone,
translation,
next_parent, // offset is relative to this
0, // type code for the effect
booster_smoke_density);
Register_Object(this_effect);
#else
DPLPSFXRenderable* this_effect =
new DPLPSFXRenderable(
entity, // Entity to attach the renderable to
DPLPSFXRenderable::Dynamic, // How/when to execute the renderable
booster_on, // address containing the trigger
myPSFXDescriptons[4], // Pointer to the psfx description in memory
next_parent_dcs, // DCS the effect is relative to (may be NULL)
&translation); // Offset (or world coordinants if DCS is NULL)
Register_Object(this_effect);
#endif
}
else
{
if(!booster_smoke_density)
DEBUG_STREAM<<"BoosterSite couldn't find BoosterSmokeDensity attribute\n" << std::flush;
}
}
}
//
// Unregister the namelist objects we created in this subroutine
//
Check(joint_pages);
Unregister_Object(joint_pages);
delete joint_pages;
Check(site_pages);
Unregister_Object(site_pages);
delete site_pages;
}
//
//#############################################################################
// This starts the process for of reading in a .skl file for a vtv.
//#############################################################################
//
HierarchicalDrawComponent*
RPL4VideoRenderer::ReadSKLFile(
Entity *entity, // The entity we are dealing with
ResourceDescription *model_resource, // Pointer to the video resource
ViewFrom type, // type of reference to create
char skeleton_type) // TEMPORARY!!!! to handle color substitutions
{
//STUBBED: DPL RB 1/14/07
//dpl_ZONE
// *buildInZone;
bool inDeathZone;
int
joint_counter;
char
*skl_filename,
TempFileName[256];
NotationFile
*object_skeleton;
dpl_ISECT_MODE
intersect_mode;
uint32
intersect_mask;
// test code for load size reduction
left_engine = 0;
right_engine = 0;
//
// Currently, the name of the .skl file to read in is in the video resource
// After reading in the .skl file we die if the page count was zero,
// indicating an empty file.
//
strcpy(TempFileName,"video\\");
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// HACK to test video resource format changes
skl_filename = (char *)model_resource->resourceAddress;
skl_filename += sizeof(int);
strcat(TempFileName, skl_filename);
//strcat(TempFileName, ".skl");
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// !!! Temporary hack to get proper vtv skl file to load
TempFileName[8] = skeleton_type;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#ifdef NOISY_RENDERER
Tell("RPL4VID.cpp loading .skl file "<<TempFileName<<"\n");
#endif
object_skeleton = new NotationFile(TempFileName);
if(object_skeleton->PageCount() == 0)
{
DEBUG_STREAM << "RPL4VID.cpp couldn't load .skl file "<<TempFileName<<"\n" << std::flush;
delete object_skeleton;
return NULL;
}
//
// Register the notation file and check it
//
Register_Object(object_skeleton);
Check(object_skeleton);
//
// Create the root renderable and tie it to the entity
//
if(type == insideEntity)
{
inDeathZone = true;
//buildInZone = dplDeathZone;
// intersect_mode = dpl_isect_mode_obj;
intersect_mask = NULL;
}
else
{
inDeathZone = false;
//buildInZone = dplMainZone;
// intersect_mode = dpl_isect_mode_geometry;
intersect_mask = INTERSECT_ALL;
}
RootRenderable *this_root =
new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Dynamic, // How/when to execute the renderable
NULL, // object to hang on the DCS, may be a list later <NULL>
inDeathZone, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask); // intersection mask for the object
Register_Object(this_root);
if(eyeRelative && entity == GetLinkedEntity())
{
dpl_DCS* aDCS=this_root->GetDCS();
Check_Pointer(aDCS);
Check_Pointer(dplTestEyeDCS);
// dpl_AddDCSToDCS( aDCS, dplTestEyeDCS );
}
//
// Process all the interesting notation file pages
//
Check(object_skeleton);
joint_counter = -1;
LinearMatrix starting_matrix(True);
dpl_LOAD_MODE dpl_load_nocache;
RecurseSKLFile(
entity,
this_root,
object_skeleton,
"ROOT",
1,
type,
&joint_counter,
dpl_load_nocache);
//
// Close the notation file
//
Unregister_Object(object_skeleton);
delete object_skeleton;
return this_root;
}
//
//#############################################################################
// This is the routine that will eventually process the script to create all
// the renderables necessary to get an object on the screen. For the moment it
// is just executing a hardwired script.
//#############################################################################
//
void
RPL4VideoRenderer::MakeEntityRenderables(
Entity *entity, // The entity we are dealing with
ResourceDescription *model_resource, // Pointer to the video resource
ViewFrom view_type) // Type of reference (inside/outside...etc.)
{
#define MAX_DOS_FILENAME 15
HierarchicalDrawComponent
*root;
//
// Make sure the callback system knows what entity is being created
// !!!! This global will be replaced later.
//
Entity_Being_Created = entity;
//
// Examine the class id of the entity and call the appropriate creation script.
// If we don't recognize the entity ID here we fall through to the inhereted
// level and let it take care of it.
//
switch(entity->GetClassID())
{
case VTVClassID:
{
vtvCount++;
Tell("-------Creating VTV #"<<vtvCount<<"-------\n");
//
// Call routine to setup material substitution
//
char geo_sub = SetupMaterialSubstitutionList(entity,view_type);
//
// Go on with VTV creation
//
root = ReadSKLFile(entity,model_resource,view_type,geo_sub);
if(view_type == insideEntity)
{
//
// Script for renderables needed for inside view of the vehicle
//
vehicleReticle = (Reticle *)entity->GetAttributePointer("TargetReticle");
if(vehicleReticle)
{
Tell("RPL4VideoRenderer::vehicleReticle should be hooked up\n");
mReticle = new ReticleRenderable(
entity, // Entity to attach the renderable to
ReticleRenderable::Dynamic, // How/when to execute the renderable
&vehicleReticle, // Pointer to the reticle structure in the entity
dplMainView); // the view associated with our eye
Register_Object(this_reticle);
}
else
{
Tell("RPL4VideoRenderer::vehicleReticle NOT hooked up\n");
}
StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
if(simulation_state)
{
Tell("RPL4VideoRenderer::translocate effect hooked up\n");
#if DEBUG_LEVEL > 0
POVTranslocateRenderable* translocate =
#endif
new POVTranslocateRenderable(
entity, // Entity to attach the renderable to
POVTranslocateRenderable::Watcher, // How/when to execute the renderable
true, // DPL zone the world is in
dplDeathZone, // DPL zone the player's VTV and death effect are in
root, // the parent DCS we will be offsetting from
simulation_state, // State dial we use to control the translocation
VTV::BurningState); // State that controls start/end of the effect
Register_Object(translocate);
}
else
{
Tell("RPL4VideoRenderer::translocate effect NOT hooked up\n");
}
}
else
{
//
// Script for renderables needed for outside view of the vehicle
//
Point3D my_offset_point(0.0, 0.0, 0.0);
StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
if(simulation_state)
{
Tell("RPL4VideoRenderer::death effect hooked up\n");
#if 1
#if DEBUG_LEVEL > 0
DPLSFXRenderable* my_death_effect =
#endif
new DPLSFXRenderable(
entity, // Entity to attach the effect to
false, // DPL zone everything will be in
my_offset_point, // Point offset from the parent DCS
root, // Parent DCS (can be NULL for world)
simulation_state, // Trigger effect when this attribute changes
VTV::BurningState, // Trigger effect when in this state
6, // Type of effect to trigger
0.1); // Effect repeat speed.
#else
#if DEBUG_LEVEL > 0
DPLPSFXStateRenderable* my_death_effect =
#endif
new DPLPSFXStateRenderable(
entity, // Entity to attach the renderable to
DPLPSFXStateRenderable::Watcher, // How/when to execute the renderable
simulation_state, // Trigger effect when this state changes
VTV::BurningState, // The state to edge trigger on
myPSFXDescriptons[2], // name of file with the PFX description in it
root_DCS, // DCS the effect is relative to (may be NULL)
&my_offset_point); // Offset (or world coordinants if DCS is NULL)
#endif
Register_Object(my_death_effect);
}
else
{
Tell("RPL4VideoRenderer::death effect NOT hooked up\n");
}
StateIndicator* collision_state = (StateIndicator *)entity->GetAttributePointer("CollisionState");
if(simulation_state)
{
Tell("RPL4VideoRenderer::collision effects hooked up\n");
#if DEBUG_LEVEL > 0
DPLSFXRenderable* initial_collision_effect =
#endif
new DPLSFXRenderable(
entity, // Entity to attach the effect to
false, // DPL zone everything will be in
my_offset_point, // Point offset from the parent DCS
root, // Parent DCS (can be NULL for world)
collision_state, // Trigger effect when this attribute changes
VTV::InitialHitState, // Trigger effect when in this state
1, // Type of effect to trigger
0.1); // Effect repeat speed.
Register_Object(initial_collision_effect);
#if DEBUG_LEVEL > 0
DPLSFXRenderable* scrape_collision_effect =
#endif
new DPLSFXRenderable(
entity, // Entity to attach the effect to
false, // DPL zone everything will be in
my_offset_point, // Point offset from the parent DCS
root, // Parent DCS (can be NULL for world)
collision_state, // Trigger effect when this attribute changes
VTV::SlideState, // Trigger effect when in this state
1, // Type of effect to trigger
0.1); // Effect repeat speed.
Register_Object(scrape_collision_effect);
}
else
{
Tell("RPL4VideoRenderer::collision effects NOT hooked up\n");
}
}
//
// Teardown the vtv materal substitution namelists and disconnect DPL substitution handler
//
TearDownMaterialSubstitutionList();
#if 0
//
// Check for all players loaded
//
if((vtvCount >= vtvsExpected) &&
(GetRendererStatus() == LoadingRendererStatus))
{
Tell("Renderer Status set to running in RPL4VideoRenderer::MakeEntityRenderables\n");
SetRendererStatusToRunning();
}
#endif
break;
}
//
// This constructs the renderables needed for the player class
//
case CrusherClassID:
case BlockerClassID:
case RunnerClassID:
case PlayerClassID:
case RPPlayerClassID:
{
//
// We need to construct the translocate effect but only if this is a
// player on another computer. We check this by asking if this is
// a replicant instance.
//
StateIndicator* player_simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
if(entity->GetInstance() == Player::ReplicantInstance)
{
//
// Setup the translocation effect for third party view
//
Point3D* drop_zone_position = (Point3D *)entity->GetAttributePointer("DropZoneLocation");
if(player_simulation_state && drop_zone_position)
{
Tell("third party translocate effect is hooked up\n");
#if DEBUG_LEVEL > 0
TranslocationRenderable *my_translocate=
#endif
new TranslocationRenderable(
entity, // Entity to attach the renderable to
TranslocationRenderable::Watcher, // How/when to execute the renderable
false, // DPL zone everything will be in
player_simulation_state, // Trigger effects off of this state dial
drop_zone_position, // Attribute that holds where the new drop will be
RPPlayer::DropZoneAcquiredState); // State that indicates drop zone is valid (starts effect)
Register_Object(my_translocate);
}
else
{
Tell("third party translocate effect NOT hooked up\n");
}
}
else
{
if(player_simulation_state)
{
Tell("Start/end effect hooked up\n");
#if DEBUG_LEVEL > 0
POVStartEndRenderable* start_end =
#endif
new POVStartEndRenderable(
entity, // Entity to attach the renderable to
POVStartEndRenderable::Watcher, // How/when to execute the renderable
true, // DPL zone the world is in
dplDeathZone, // DPL zone the player's VTV and death effect are in
dplMainView, // The view containing our eye
player_simulation_state, // State dial we use to control the translocation
fogRed, // Fog color
fogGreen,
fogBlue,
fogNear, // The near fog plane
fogFar, // The far fog plane
RPPlayer::MissionStartingState, // State that signals start of mission
RPPlayer::MissionEndingState); // State that signals end of mission
Register_Object(start_end);
}
else
{
Tell("Start/end effect NOT hooked up\n");
}
}
break;
}
//
// At the RP level we have no default method for creating objects so we call the
// next level down (l4) and let it have a try at creating the renderables.
//
default:
{
DPLRenderer::MakeEntityRenderables(
entity, // The entity we are dealing with
model_resource, // video resource for this entity
view_type); // type of reference to create !!! should be enum
break;
}
}
//
// Make sure the callback system knows what entity is being created
// !!!! This global will be replaced later.
//
Entity_Being_Created = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LoadMissionImplementation For the moment it doesn't do much, just determines
// how many players we should be expecting and sets a variable in the renderer
// about it.
//
void
RPL4VideoRenderer::LoadMissionImplementation(Mission* mission)
{
Tell("RPL4VideoRenderer::LoadMissionImplementation has been called\n");
//
// First call our inhereted method to make sure the division card is initialized right
//
DPLRenderer::LoadMissionImplementation(mission);
#if 0
//
// This is a !!! HACK to figure out in advance how many VTV's to expect so we can
// setup the game state properly.
//
Mission::HostAddressIterator mission_iterator(mission);
vtvsExpected = mission_iterator.GetSize();
//
// Check for all players loaded
//
if((vtvCount >= vtvsExpected) &&
(GetRendererStatus() == LoadingRendererStatus))
{
Tell("Renderer Status set to running in RPL4VideoRenderer::LoadMissionImplementation\n");
SetRendererStatusToRunning();
}
#endif
}
//
//#############################################################################
// SetupMaterialSubstitutionList This routine sets up the material substitution
// prior to loading a vehicle.
//#############################################################################
//
char
RPL4VideoRenderer::SetupMaterialSubstitutionList(
Entity* entity,
ViewFrom view_type) // The entity we will be substituting for.
{
//STUBBED: DPL RB 1/14/07
extern NameList
*materialSubstitutionList;
static const char
* const color_parameter = "%color%",
* const badge_parameter = "%badge%";
static int
color_parm_len = strlen(color_parameter),
badge_parm_len = strlen(badge_parameter);
NotationFile
*veh_tbl; // vehicle table from resource file
NameList::Entry
*entry; // used to loop through namelists
const char
*egg_color, // color name in egg file (from entity)
*egg_badge, // badge name in egg file (from entity)
*veh_color, // color code from vehicle table
*veh_badge; // badge code from vehicle table
const char
*source, // tracks progress in source string
*pc; // jumps ahead of source pointer
char
*destination, // tracks progress in destination string
buffer[80]; // holds result while being constructed
int
len; // misc. length
char
*vehicleTableResource;
long
vehicleTableResourceLength;
char geometry_substitution = 'n';
Verify(materialSubstitutionList == NULL);
//
// Get the vehicle table out of resources.
//
ResourceDescription *res =
application->GetResourceFile()->FindResourceDescription(
"vehicletable",
ResourceDescription::VehicleTableResourceType
);
if (!res)
{
return(geometry_substitution);
}
Check(res);
res->Lock();
vehicleTableResource = (char *)res->resourceAddress;
vehicleTableResourceLength = (long)res->resourceSize;
char
*vehicle_table = new char[vehicleTableResourceLength];
Register_Pointer(vehicle_table);
memcpy(vehicle_table, vehicleTableResource, vehicleTableResourceLength);
veh_tbl = new NotationFile;
Register_Object(veh_tbl);
veh_tbl->ReadText(vehicle_table, vehicleTableResourceLength);
Unregister_Pointer(vehicle_table);
delete vehicle_table;
res->Unlock();
//
// Fetch the color and badge pointers out of the entity and into our local stuff
//
egg_color = ((VTV *)entity)->vehicleColor;
egg_badge = ((VTV *)entity)->vehicleBadge;
Check_Pointer(egg_color);
Check_Pointer(egg_badge);
if (!veh_tbl->GetEntry("color", egg_color, &veh_color))
{
veh_color = NULL;
}
if (!veh_tbl->GetEntry("badge", egg_badge, &veh_badge))
{
veh_badge = NULL;
}
else
{
if(view_type == insideEntity)
{
geometry_substitution = *(veh_badge + strlen(veh_badge) - 2); //ourself
}
else
{
geometry_substitution = *(veh_badge + strlen(veh_badge) - 1); //someone else
}
}
//--------------------------------------------------
// get generic substitution list from vehicle table
//--------------------------------------------------
materialSubstitutionList = veh_tbl->MakeEntryList("substitute");
Register_Object(materialSubstitutionList);
//-------------------------------------------------------------
// fill in % place holders with specifics for vtv being loaded
//-------------------------------------------------------------
entry = materialSubstitutionList->GetFirstEntry();
while (entry)
{
source = entry->GetChar();
*(destination = buffer) = '\0';
while ((pc = strchr(source, '%')) != NULL)
{
if ((len = pc-source) != 0)
{
strncpy(destination, source, len);
source = pc;
destination += len;
}
if (!strncmp(pc, color_parameter, color_parm_len))
{
if (veh_color)
{
Str_Copy(
destination,
veh_color,
sizeof(buffer)-(destination-buffer)
);
destination += strlen(veh_color);
}
source += color_parm_len;
}
else if (!strncmp(pc, badge_parameter, badge_parm_len))
{
if (veh_badge)
{
const char
*qc = veh_badge;
while (isgraph(*qc))
{
++qc;
}
if ((len = qc - veh_badge) != 0)
{
strncpy(destination, veh_badge, len);
destination += len;
}
}
source += badge_parm_len;
}
else
{
//-------------------------------------
// % was not from recognized parameter
//-------------------------------------
*destination++ = *source++;
}
}
if (*source)
{
Str_Copy(
destination,
source,
sizeof(buffer)-(destination-buffer)
);
}
else
{
*destination = '\0';
}
//---------------------------------------
// make copy of result and store in list
//---------------------------------------
destination = new char[strlen(buffer)+1];
Register_Pointer(destination);
strcpy(destination, buffer);
entry->dataReference = (void *)destination;
entry = entry->GetNextEntry();
}
Unregister_Object(veh_tbl);
delete veh_tbl;
//dpl_SetMaterialNameCallback(substituteMaterial);
return geometry_substitution;
}
//
//#############################################################################
// TearDownMaterialSubstitutionList This routine destroys and disconnects the
// material substitution stuff after a vehicle has been loaded.
//#############################################################################
//
void
RPL4VideoRenderer::TearDownMaterialSubstitutionList()
{
//STUBBED: DPL RB 1/14/07
NameList::Entry
*entry;
char
*p;
extern NameList
*materialSubstitutionList;
if (materialSubstitutionList)
{
entry = materialSubstitutionList->GetFirstEntry();
while (entry)
{
if ((p = entry->GetChar()) != NULL)
{
Unregister_Pointer(p);
delete p;
entry->dataReference = NULL;
}
entry = entry->GetNextEntry();
}
Unregister_Object(materialSubstitutionList);
delete materialSubstitutionList;
materialSubstitutionList = NULL;
}
//dpl_SetMaterialNameCallback(NULL);
}
//===========================================================================//