1075 lines
36 KiB
C++
1075 lines
36 KiB
C++
//===========================================================================
|
|
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// Component: AnimDynaPhysLoader
|
|
//
|
|
// Description: Loader for instanced, animated, dynaphys DSG objects
|
|
//
|
|
// Authors: Michael Riegger
|
|
//
|
|
//===========================================================================
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Includes
|
|
//===========================================================================
|
|
#include <constants/chunks.h>
|
|
#include <constants/chunkids.hpp>
|
|
#include <render/Loaders/AnimDynaPhysLoader.h>
|
|
#include <render/DSG/InstAnimDynaPhysDSG.h>
|
|
#include <atc/atcmanager.h>
|
|
#include <constants/srrchunks.h>
|
|
#include <memory/srrmemory.h>
|
|
#include <simcollision/collisionobject.hpp>
|
|
#include <simphysics/physicsobject.hpp>
|
|
#include <render/Loaders/GeometryWrappedLoader.h>
|
|
#include <p3d/anim/multicontroller.hpp>
|
|
#include <render/Loaders/AllWrappers.h>
|
|
#include <render/Loaders/BillboardWrappedLoader.h>
|
|
#include <p3d/anim/skeleton.hpp>
|
|
#include <p3d/anim/animate.hpp>
|
|
#include <p3d/anim/compositedrawable.hpp>
|
|
#include <p3d/chunkfile.hpp>
|
|
#include <p3d/inventory.hpp>
|
|
#include <render/AnimEntityDSGManager/AnimEntityDSGManager.h>
|
|
#include <render/DSG/StatePropDSG.h>
|
|
#include <stateprop/statepropdata.hpp>
|
|
#include <p3d/anim/animatedobject.hpp>
|
|
#include <constants/physprop.h>
|
|
#include <data/persistentworldmanager.h>
|
|
#include <main/game.h>
|
|
#include <radmath/random.hpp>
|
|
#ifndef RAD_RELEASE
|
|
#include <memory/propstats.h>
|
|
#endif
|
|
|
|
//===========================================================================
|
|
// Local Constants, Typedefs, and Macros
|
|
//===========================================================================
|
|
|
|
Map< tUID, tUID > AnimDynaPhysLoader::s_ShadowList;
|
|
|
|
|
|
//===========================================================================
|
|
// Global Data, Local Data, Local Classes
|
|
//===========================================================================
|
|
|
|
|
|
|
|
//===========================================================================
|
|
// Member Functions
|
|
//===========================================================================
|
|
|
|
//===========================================================================
|
|
// AnimDynaPhysLoader::AnimDynaPhysLoader
|
|
//===========================================================================
|
|
// Description:
|
|
// AnimDynaPhysLoader ctor
|
|
//
|
|
// Constraints:
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
|
|
AnimDynaPhysLoader::AnimDynaPhysLoader() : tSimpleChunkHandler(SRR2::ChunkID::INSTA_ANIM_DYNA_PHYS_DSG)
|
|
{
|
|
|
|
mpListenerCB = NULL;
|
|
mUserData = -1;
|
|
|
|
if ( s_ShadowList.capacity() == 0 )
|
|
{
|
|
s_ShadowList.reserve( 20 );
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
// AnimDynaPhysLoader::~AnimDynaPhysLoader
|
|
//===========================================================================
|
|
// Description:
|
|
// AnimDynaPhysLoader dtor
|
|
//
|
|
// Constraints:
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
|
|
AnimDynaPhysLoader::~AnimDynaPhysLoader()
|
|
{
|
|
|
|
}
|
|
|
|
//===========================================================================
|
|
// AnimDynaPhysLoader::LoadObject
|
|
//===========================================================================
|
|
// Description:
|
|
// Loads an InstAnimDynaPhysDSG chunk and creates all the instances
|
|
//
|
|
// Constraints:
|
|
// Expecting file format to be:
|
|
// string name (max size 255)
|
|
// long version
|
|
// long hasalpha flag
|
|
//
|
|
//
|
|
// Parameters:
|
|
// Chunk file, and store
|
|
//
|
|
// Return:
|
|
// NULL, no final chunk going specifically into the inventory via return
|
|
//
|
|
//===========================================================================
|
|
|
|
tEntity* AnimDynaPhysLoader::LoadObject(tChunkFile* file, tEntityStore* store)
|
|
{
|
|
IEntityDSG::msDeletionsSafe=true;
|
|
// Grab the name
|
|
char typeName[255];
|
|
file->GetPString(typeName);
|
|
|
|
// Quick test to see if we are dealing with an animated BV object
|
|
int simAnimJoint = -1;
|
|
if ( strstr ( typeName, "crate" ) != NULL )
|
|
simAnimJoint = 3;
|
|
else if ( strstr ( typeName, "vending" ) != NULL )
|
|
simAnimJoint = 1;
|
|
else if ( strstr ( typeName, "l2_monkiesgag" ) != NULL )
|
|
simAnimJoint = 1;
|
|
else if ( strstr ( typeName, "l7_spider" ) != NULL )
|
|
simAnimJoint = 1;
|
|
|
|
|
|
#ifndef RAD_RELEASE
|
|
PropStats::StartTracking(typeName);
|
|
#endif
|
|
|
|
int instanceCount = 0;
|
|
|
|
// Grab version info
|
|
int version = file->GetLong();
|
|
// Grab the flag that tell us whether or not the object has alpha or not
|
|
int hasAlpha = file->GetLong();
|
|
|
|
// Does this chunk contain a subchunk for instances
|
|
bool foundInstances = false;
|
|
bool persistance = true;
|
|
|
|
// Is this object a global entity (i.e. is it loaded once at level startup and
|
|
// all subsequent instances are cloned off this thing?)
|
|
StatePropDSG* globalStatepropEntity = static_cast<StatePropDSG*>(GetAllWrappers()->GetGlobalEntity(tName::MakeUID(typeName)));
|
|
if(strstr(typeName, "phonestop_Shape"))
|
|
{
|
|
persistance = false;
|
|
}
|
|
bool haveGlobal = globalStatepropEntity != 0;
|
|
#ifndef RAD_RELEASE
|
|
if ( haveGlobal )
|
|
{
|
|
rAssert( dynamic_cast< StatePropDSG* >( globalStatepropEntity ) != NULL );
|
|
}
|
|
#endif
|
|
CollisionAttributes* pCollAttr = NULL;
|
|
AnimDynaPhysWrapper* pWrappedObject = NULL;
|
|
|
|
// Is this a mission prop?
|
|
|
|
bool isMissionProp = IsMissionProp( typeName );
|
|
|
|
|
|
while( file->ChunksRemaining() )
|
|
{
|
|
file->BeginChunk();
|
|
switch(file->GetCurrentID())
|
|
{
|
|
case SRR2::ChunkID::ANIM_OBJ_DSG_WRAPPER:
|
|
// We are loading a stateprop
|
|
{
|
|
if(!haveGlobal)
|
|
{
|
|
HeapMgr()->PushHeap( GMA_TEMP );
|
|
AnimObjDSGWrapperLoader* pObjWrapperLoader = new AnimObjDSGWrapperLoader;
|
|
HeapMgr()->PopHeap( GMA_TEMP );
|
|
pWrappedObject = (AnimDynaPhysWrapper*) pObjWrapperLoader->LoadObject( file, store );
|
|
pWrappedObject->AddRef ();
|
|
pObjWrapperLoader->ReleaseVerified();
|
|
}
|
|
m_IsStateProp = true;
|
|
}
|
|
break;
|
|
|
|
case SRR2::ChunkID::ANIM_DSG_WRAPPER:
|
|
{
|
|
if(!haveGlobal)
|
|
{
|
|
// This is the wrapped object and contains a whole load of crap, meshes, comp drawables, billboards
|
|
// load them all
|
|
// Format of the wrapped object is
|
|
// string name
|
|
// ULONG version
|
|
// ULONG hasalpha
|
|
// pWrappedObject = new (GMA_TEMP ) WrappedObject;
|
|
// LoadAnimWrapper( file, store, pWrappedObject );
|
|
|
|
HeapMgr()->PushHeap( GMA_TEMP );
|
|
AnimDynaPhysWrapperLoader* pWrapperLoader = new AnimDynaPhysWrapperLoader;
|
|
HeapMgr()->PopHeap( GMA_TEMP );
|
|
|
|
pWrappedObject = (AnimDynaPhysWrapper*) pWrapperLoader->LoadObject( file, store );
|
|
pWrappedObject->AddRef ();
|
|
pWrapperLoader->Release();
|
|
}
|
|
m_IsStateProp = false;
|
|
}
|
|
break;
|
|
// Relies on ObjectAttributes and the Wrapped DSG object being loaded first
|
|
|
|
case SRR2::ChunkID::OBJECT_ATTRIBUTES:
|
|
{
|
|
if(!haveGlobal)
|
|
{
|
|
rAssert( pWrappedObject != NULL );
|
|
// Relies on the Wrapped Object being loaded first
|
|
int classType = file->GetLong();
|
|
int physPropID = file->GetLong();
|
|
char tempsound [64];
|
|
|
|
file->GetString(tempsound); //Chuck: Reading the new sound properties since we dont use the sound returned from the ATC manager.
|
|
|
|
float volume;
|
|
if ( classType == PROP_MOVEABLE ||
|
|
classType == PROP_BREAKABLE ||
|
|
classType == PROP_ONETIME_MOVEABLE ||
|
|
classType == 8 )
|
|
{
|
|
volume = pWrappedObject->GetVolume();
|
|
}
|
|
else
|
|
{
|
|
volume = 0.0f;
|
|
}
|
|
pCollAttr = GetATCManager()->CreateCollisionAttributes(classType, physPropID, volume);
|
|
pCollAttr->AddRef ();
|
|
pCollAttr->SetSound(tempsound); //Chuck: Setting the CollAttr to use the correct sound from the OTC chunk.
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SRR2::ChunkID::INSTANCES:
|
|
{
|
|
foundInstances = true;
|
|
|
|
//Instances >> Scenegraph
|
|
file->BeginChunk();
|
|
//Scenegraph >> ScenegraphRoot
|
|
file->BeginChunk();
|
|
//ScenegraphRoot >> ScenegraphBranch
|
|
file->BeginChunk();
|
|
//ScenegraphBranch >> ScenegraphTransform
|
|
file->BeginChunk();
|
|
|
|
//ScenegraphTransform >> real ScenegraphTransform
|
|
//f->BeginChunk();
|
|
|
|
while( file->ChunksRemaining() )
|
|
{
|
|
instanceCount++;
|
|
|
|
|
|
file->BeginChunk();
|
|
char name[256];
|
|
file->GetPString(name);
|
|
int numChild = file->GetLong();
|
|
|
|
rmt::Matrix matrix;
|
|
file->GetData( &matrix,16, tFile::DWORD );
|
|
|
|
if ( m_IsStateProp )
|
|
{
|
|
short persistentID = -1;
|
|
if(persistance && ((haveGlobal && globalStatepropEntity->GetCollisionAttributes()->GetClasstypeid()) || (!haveGlobal && ((pCollAttr->GetClasstypeid() == PROP_BREAKABLE) || (pCollAttr->GetClasstypeid() == PROP_MOVEABLE)))))
|
|
{
|
|
if ( isMissionProp == false )
|
|
persistentID = GetPersistentWorldManager()->GetPersistentObjectID( tEntity::MakeUID( file->GetFilename() ),tEntity::MakeUID(typeName) );
|
|
else
|
|
persistentID = -1;
|
|
}
|
|
if( persistentID >= -1 )
|
|
{
|
|
StatePropDSG* pStatePropDSG = NULL;
|
|
|
|
// Should we clone off the global entity (if it exists?)
|
|
if (haveGlobal)
|
|
{
|
|
pStatePropDSG = globalStatepropEntity->Clone( name, matrix );
|
|
}
|
|
else
|
|
{
|
|
rAssert( pCollAttr != NULL );
|
|
rAssert( pWrappedObject != NULL );
|
|
bool useSharedtPose = pWrappedObject->HasAnimation() ? false : true;
|
|
pStatePropDSG = new StatePropDSG();
|
|
pStatePropDSG->LoadSetup( pWrappedObject->GetStatePropData(), 0, matrix, pCollAttr, true, store, useSharedtPose, pWrappedObject->GetCollisionObject(), pWrappedObject->GetPhysicsObject() );
|
|
pStatePropDSG->SetName( name );
|
|
pStatePropDSG->SetSimJoint( simAnimJoint );
|
|
}
|
|
|
|
|
|
|
|
#ifndef FINAL
|
|
if( !haveGlobal && (pWrappedObject->GetStatePropData() == NULL))
|
|
{
|
|
char outbuffer [255];
|
|
sprintf(outbuffer,"Error: %s is missing a StateProp Chunk \n",pWrappedObject->GetName());
|
|
rTuneAssertMsg( 0,outbuffer );
|
|
}
|
|
#endif
|
|
|
|
|
|
mpListenerCB->OnChunkLoaded( pStatePropDSG, mUserData, _id );
|
|
pStatePropDSG->mPersistentObjectID = persistentID;
|
|
|
|
// Check to see if there is a shadow associated with this object
|
|
tUID compDrawUID = pStatePropDSG->GetDrawableUID();
|
|
|
|
tUID shadowElementName = GetShadowElement( compDrawUID );
|
|
if ( shadowElementName != static_cast< tUID >( 0 ) )
|
|
{
|
|
pStatePropDSG->SetShadowElement( shadowElementName );
|
|
}
|
|
|
|
// place it into the inventory so that locators can access it by name
|
|
bool collision = store->TestCollision( pStatePropDSG->GetUID(), pStatePropDSG );
|
|
if( !collision )
|
|
{
|
|
store->Store( pStatePropDSG );
|
|
}
|
|
else
|
|
{
|
|
HandleCollision( pStatePropDSG );
|
|
}
|
|
// Lets offset the animation so that every crate or vending machine
|
|
// instance isn't jumping together
|
|
// Make the stateprop instances each start at a different point in time
|
|
static rmt::Randomizer randomizer( Game::GetRandomSeed () );
|
|
const float RANDOM_TIME_MS = 10000.0f;
|
|
// Advance animations by 0 - 10 seconds
|
|
float randomUpdateTime = randomizer.Float() * RANDOM_TIME_MS;
|
|
pStatePropDSG->AdvanceAnimation( randomUpdateTime );
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InstAnimDynaPhysDSG* pAnimDSG = new InstAnimDynaPhysDSG();
|
|
// Make sure that each name is unique
|
|
// things like the powerboxes are set via lookup
|
|
pAnimDSG->SetName( name );
|
|
|
|
if( hasAlpha || pWrappedObject->HasAlpha() )
|
|
{
|
|
pAnimDSG->mTranslucent = true;
|
|
}
|
|
else
|
|
{
|
|
pAnimDSG->mTranslucent = false;
|
|
}
|
|
|
|
rAssert( pCollAttr != NULL );
|
|
pAnimDSG->LoadSetUp( pCollAttr, matrix, pWrappedObject->GetDrawable(), pWrappedObject->GetController(), store );
|
|
mpListenerCB->OnChunkLoaded( static_cast< InstDynaPhysDSG*> (pAnimDSG), mUserData, _id );
|
|
|
|
// place it into the inventory so that locators can access it by name
|
|
store->Store( pAnimDSG );
|
|
}
|
|
file->EndChunk();
|
|
|
|
#ifndef RAD_RELEASE
|
|
if ( instanceCount == 1 )
|
|
{
|
|
PropStats::StopTracking( typeName, 1 );
|
|
PropStats::StartTracking( typeName );
|
|
instanceCount = 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
}
|
|
//ScenegraphBranch >> ScenegraphTransform
|
|
file->EndChunk();
|
|
//ScenegraphRoot >> ScenegraphBranch
|
|
file->EndChunk();
|
|
//Scenegraph >> ScenegraphRoot
|
|
file->EndChunk();
|
|
//Instances >> Scenegraph
|
|
file->EndChunk();
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
rAssertMsg( false, "Unknown chunk in AnimatedDynaPhysDSG file");
|
|
break;
|
|
};
|
|
file->EndChunk();
|
|
}
|
|
|
|
if(0&&!foundInstances && !haveGlobal )
|
|
{
|
|
// No instance chunk!
|
|
// Therefore this MUST be a global entity
|
|
// Dump it into the global entity list
|
|
// so that subsequent instances of this type
|
|
// will get cloned off the global entity instead of loading all this crap again
|
|
//This must be a global entity.
|
|
StatePropDSG* globalEntityStateProp = new StatePropDSG();
|
|
rAssert(globalEntityStateProp);
|
|
// Give this thing the name of the type
|
|
|
|
bool useSharedtPose = pWrappedObject->HasAnimation() ? false : true;
|
|
rmt::Matrix identity;
|
|
identity.Identity();
|
|
globalEntityStateProp->LoadSetup( pWrappedObject->GetStatePropData(),
|
|
0,
|
|
identity,
|
|
pCollAttr,
|
|
false,
|
|
NULL,
|
|
useSharedtPose,
|
|
pWrappedObject->GetCollisionObject(),
|
|
pWrappedObject->GetPhysicsObject() );
|
|
globalEntityStateProp->SetName( typeName );
|
|
GetAllWrappers()->AddGlobalEntity( globalEntityStateProp );
|
|
globalEntityStateProp->SetSimJoint( simAnimJoint );
|
|
instanceCount++;
|
|
}
|
|
|
|
if( pWrappedObject != NULL)
|
|
{
|
|
pWrappedObject->ReleaseVerified ();
|
|
}
|
|
if ( pCollAttr != NULL )
|
|
{
|
|
pCollAttr->Release ();
|
|
}
|
|
|
|
#ifndef RAD_RELEASE
|
|
PropStats::StopTracking( typeName, instanceCount );
|
|
#endif
|
|
|
|
|
|
IEntityDSG::msDeletionsSafe=false;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
// AnimDynaPhysLoader::SetRegdListener
|
|
//===========================================================================
|
|
// Description:
|
|
// Informs the loader its listener is.
|
|
//
|
|
// Constraints:
|
|
//
|
|
// Parameters:
|
|
// Pointer to the new listener. Integer for the data it sends to it OnChunkLoaded()
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
void AnimDynaPhysLoader::SetRegdListener( ChunkListenerCallback* pListenerCB,
|
|
int iUserData )
|
|
{
|
|
//
|
|
// Follow protocol; notify old Listener, that it has been
|
|
// "disconnected".
|
|
//
|
|
if( mpListenerCB != NULL )
|
|
{
|
|
mpListenerCB->OnChunkLoaded( NULL, iUserData, 0 );
|
|
}
|
|
mpListenerCB = pListenerCB;
|
|
mUserData = iUserData;
|
|
}
|
|
|
|
//===========================================================================
|
|
// AnimDynaPhysLoader::ModRegdListener
|
|
//===========================================================================
|
|
// Description:
|
|
// Changes the data that gets sent to the listener
|
|
//
|
|
// Constraints:
|
|
// Listener must have been set already via SetRegdListener
|
|
//
|
|
// Parameters:
|
|
// Pointer to the listener. Integer holding the new data
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
void AnimDynaPhysLoader::ModRegdListener( ChunkListenerCallback* pListenerCB, int iUserData )
|
|
{
|
|
rAssert( pListenerCB == mpListenerCB );
|
|
|
|
mUserData = iUserData;
|
|
}
|
|
|
|
void AnimDynaPhysLoader::SetShadowElement( const char* compDrawName,
|
|
const char* drawableElementName )
|
|
{
|
|
s_ShadowList.insert( tName::MakeUID( compDrawName ), tName::MakeUID( drawableElementName ) );
|
|
}
|
|
|
|
void AnimDynaPhysLoader::ClearShadowList()
|
|
{
|
|
s_ShadowList.clear();
|
|
}
|
|
|
|
tUID AnimDynaPhysLoader::GetShadowElement( tUID compDrawName )
|
|
{
|
|
tUID elementName;
|
|
Map< tUID, tUID >::const_iterator it;
|
|
it = s_ShadowList.find( compDrawName );
|
|
if ( it != s_ShadowList.end() )
|
|
elementName = it->second;
|
|
else
|
|
elementName = 0;
|
|
|
|
return elementName;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// AnimDyaPhysWrapperLoader methods
|
|
///////////////////////////////////////////////////////////
|
|
|
|
AnimDynaPhysWrapperLoader::AnimDynaPhysWrapperLoader() : tSimpleChunkHandler(SRR2::ChunkID::ANIM_DSG_WRAPPER)
|
|
{
|
|
|
|
mpListenerCB = NULL;
|
|
mUserData = -1;
|
|
|
|
mpCompDLoader = new tCompositeDrawableLoader;
|
|
mpCompDLoader->AddRef();
|
|
|
|
mpMCLoader = new tMultiControllerLoader;
|
|
mpMCLoader->AddRef();
|
|
|
|
mpSkelLoader = new tSkeletonLoader;
|
|
mpSkelLoader->AddRef();
|
|
|
|
mpAnimationLoader = new tAnimationLoader;
|
|
mpAnimationLoader->AddRef();
|
|
|
|
mpCollObjLoader = new sim::CollisionObjectLoader;
|
|
mpCollObjLoader->AddRef();
|
|
|
|
mpPhysObjLoader = new sim::PhysicsObjectLoader;
|
|
mpPhysObjLoader->AddRef();
|
|
|
|
mpFCLoader = new tFrameControllerLoader;
|
|
mpFCLoader->AddRef();
|
|
}
|
|
|
|
AnimDynaPhysWrapperLoader::~AnimDynaPhysWrapperLoader()
|
|
{
|
|
mpCollObjLoader->ReleaseVerified();
|
|
mpPhysObjLoader->ReleaseVerified();
|
|
mpCompDLoader->ReleaseVerified();
|
|
mpMCLoader->ReleaseVerified();
|
|
mpSkelLoader->ReleaseVerified();
|
|
mpAnimationLoader->ReleaseVerified();
|
|
mpFCLoader->ReleaseVerified();
|
|
}
|
|
|
|
|
|
|
|
tEntity* AnimDynaPhysWrapperLoader::LoadObject( tChunkFile* file, tEntityStore* store )
|
|
{
|
|
HeapMgr()->PushHeap( GMA_LEVEL_OTHER );
|
|
AnimDynaPhysWrapper* wrapper = new AnimDynaPhysWrapper;
|
|
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
|
|
rAssert( file != NULL );
|
|
rAssert( store != NULL );
|
|
|
|
// Grab the name
|
|
char buffer[256];
|
|
file->GetPString( buffer );
|
|
|
|
wrapper->SetName( buffer );
|
|
|
|
// Grab version info
|
|
int version = file->GetLong();
|
|
// Grab the flag that tell us whether or not the object has alpha or not
|
|
int hasAlpha = file->GetLong();
|
|
|
|
wrapper->mHasAlpha = ( hasAlpha != 0x00000000 );
|
|
bool collisionObjectFound = false;
|
|
|
|
while( file->ChunksRemaining() )
|
|
{
|
|
file->BeginChunk();
|
|
switch( file->GetCurrentID() )
|
|
{
|
|
case P3D_COMPOSITE_DRAWABLE:
|
|
{
|
|
// We will save the composite drawable since we need it
|
|
// for our DSG objects
|
|
rAssertMsg( wrapper->mCompDraw == NULL, "There must only be one composite drawable in the wrapper!" );
|
|
wrapper->mCompDraw = (tCompositeDrawable*)mpCompDLoader->LoadObject( file, store );
|
|
wrapper->mCompDraw->AddRef();
|
|
store->Store( wrapper->mCompDraw );
|
|
rAssert( wrapper->mCompDraw != NULL );
|
|
}
|
|
break;
|
|
case P3D_MULTI_CONTROLLER:
|
|
{
|
|
rAssert( wrapper->mMultiController == NULL );
|
|
wrapper->mMultiController = (tMultiController*)mpMCLoader->LoadObject( file, store );
|
|
rAssert( wrapper->mMultiController != NULL );
|
|
// This should be inserted into the list of world render multicontrollers that
|
|
// get advanced every frame
|
|
wrapper->mMultiController->SetCycleMode( FORCE_CYCLIC );
|
|
wrapper->mMultiController->AddRef();
|
|
|
|
bool collision = store->TestCollision( wrapper->mMultiController->GetUID(), wrapper->mMultiController );
|
|
if( !collision )
|
|
{
|
|
store->Store( wrapper->mMultiController );
|
|
}
|
|
else
|
|
{
|
|
HandleCollision( wrapper->mMultiController );
|
|
}
|
|
}
|
|
break;
|
|
case Pure3D::Animation::FrameControllerData::FRAME_CONTROLLER:
|
|
{
|
|
tFrameController* pFC = static_cast< tFrameController* >( mpFCLoader->LoadObject( file, store ) );
|
|
rAssert( pFC != NULL );
|
|
store->Store( pFC );
|
|
}
|
|
break;
|
|
case Simulation::Collision::OBJECT:
|
|
{
|
|
collisionObjectFound = true;
|
|
rAssert( wrapper->mCollisionObject == NULL );
|
|
wrapper->mCollisionObject = static_cast< sim::CollisionObject* > (mpCollObjLoader->LoadObject( file, store ));
|
|
rAssert( wrapper->mCollisionObject != NULL );
|
|
wrapper->mCollisionObject->AddRef();
|
|
store->Store( wrapper->mCollisionObject );
|
|
}
|
|
break;
|
|
case Pure3D::BillboardObject::QUAD_GROUP:
|
|
{
|
|
// Remember that we have our own billboard loader
|
|
// make sure that these don't get dumped into the DSG, override first
|
|
|
|
// Grab the loader
|
|
BillboardWrappedLoader::OverrideLoader( true );
|
|
BillboardWrappedLoader* pBBQLoader = static_cast<BillboardWrappedLoader*>(AllWrappers::GetInstance()->mpLoader(AllWrappers::msBillboard));
|
|
|
|
tBillboardQuadGroup* pGroup = static_cast<tBillboardQuadGroup*>( pBBQLoader->LoadObject( file, store ) );
|
|
rAssert( pGroup != NULL );
|
|
store->Store( pGroup );
|
|
|
|
// Set the loader back to its normal state
|
|
BillboardWrappedLoader::OverrideLoader( false );
|
|
}
|
|
break;
|
|
case Pure3D::Mesh::MESH:
|
|
{
|
|
GeometryWrappedLoader* pGeoLoader = (GeometryWrappedLoader*)AllWrappers::GetInstance()->mpLoader( AllWrappers::msGeometry );
|
|
tGeometry* pGeo = static_cast<tGeometry*>(pGeoLoader->LoadObject( file, store ) );
|
|
rAssert( pGeo != NULL );
|
|
store->Store( pGeo );
|
|
}
|
|
break;
|
|
case Pure3D::Animation::AnimationData::ANIMATION:
|
|
{
|
|
tAnimation* pAnimation = static_cast< tAnimation*> ( mpAnimationLoader->LoadObject( file, store ) );
|
|
rAssert( pAnimation != NULL );
|
|
store->Store( pAnimation );
|
|
wrapper->SetHasAnimation( true );
|
|
}
|
|
break;
|
|
case Simulation::Physics::OBJECT:
|
|
|
|
rAssert( wrapper->mPhysicsObject == NULL );
|
|
wrapper->mPhysicsObject = (sim::PhysicsObject*)mpPhysObjLoader->LoadObject( file,store );
|
|
rAssert( wrapper->mPhysicsObject != NULL );
|
|
store->Store( wrapper->mPhysicsObject );
|
|
wrapper->mPhysicsObject->AddRef ();
|
|
|
|
break;
|
|
case P3D_SKELETON:
|
|
{
|
|
|
|
tSkeleton* pSkeleton = static_cast< tSkeleton* > (mpSkelLoader->LoadObject( file, store ) );
|
|
rAssert( pSkeleton != NULL );
|
|
store->Store( pSkeleton );
|
|
}
|
|
break;
|
|
default:
|
|
rAssertMsg( false, "Unknown chunk in animated wrapper chunk file");
|
|
break;
|
|
};
|
|
file->EndChunk();
|
|
}
|
|
if ( collisionObjectFound == false )
|
|
{
|
|
rReleasePrintf("WARNING - Stateprop %s is missing a collision volume!\n", buffer );
|
|
}
|
|
return wrapper;
|
|
}
|
|
//===========================================================================
|
|
// AnimDynaPhysWrapperLoader::SetRegdListener
|
|
//===========================================================================
|
|
// Description:
|
|
// Informs the loader its listener is.
|
|
//
|
|
// Constraints:
|
|
//
|
|
// Parameters:
|
|
// Pointer to the new listener. Integer for the data it sends to it OnChunkLoaded()
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
void AnimDynaPhysWrapperLoader::SetRegdListener( ChunkListenerCallback* pListenerCB,
|
|
int iUserData )
|
|
{
|
|
//
|
|
// Follow protocol; notify old Listener, that it has been
|
|
// "disconnected".
|
|
//
|
|
if( mpListenerCB != NULL )
|
|
{
|
|
mpListenerCB->OnChunkLoaded( NULL, iUserData, 0 );
|
|
}
|
|
mpListenerCB = pListenerCB;
|
|
mUserData = iUserData;
|
|
}
|
|
|
|
//===========================================================================
|
|
// AnimDynaPhysWrapperLoader::ModRegdListener
|
|
//===========================================================================
|
|
// Description:
|
|
// Changes the data that gets sent to the listener
|
|
//
|
|
// Constraints:
|
|
// Listener must have been set already via SetRegdListener
|
|
//
|
|
// Parameters:
|
|
// Pointer to the listener. Integer holding the new data
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
void AnimDynaPhysWrapperLoader::ModRegdListener( ChunkListenerCallback* pListenerCB, int iUserData )
|
|
{
|
|
rAssert( pListenerCB == mpListenerCB );
|
|
|
|
mUserData = iUserData;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// ANIM_OBJ_DSG_WRAPPER methods
|
|
///////////////////////////////////////////////////////////
|
|
|
|
AnimObjDSGWrapperLoader::AnimObjDSGWrapperLoader() : tSimpleChunkHandler(SRR2::ChunkID::ANIM_OBJ_DSG_WRAPPER)
|
|
{
|
|
|
|
mpListenerCB = NULL;
|
|
mUserData = -1;
|
|
|
|
mpCompDLoader = new tCompositeDrawableLoader;
|
|
mpCompDLoader->AddRef();
|
|
|
|
mpMCLoader = new tMultiControllerLoader;
|
|
mpMCLoader->AddRef();
|
|
|
|
mpSkelLoader = new tSkeletonLoader;
|
|
mpSkelLoader->AddRef();
|
|
|
|
mpAnimationLoader = new tAnimationLoader;
|
|
mpAnimationLoader->AddRef();
|
|
|
|
mpCollObjLoader = new sim::CollisionObjectLoader;
|
|
mpCollObjLoader->AddRef();
|
|
|
|
mpPhysObjLoader = new sim::PhysicsObjectLoader;
|
|
mpPhysObjLoader->AddRef();
|
|
|
|
mpFCLoader = new tFrameControllerLoader;
|
|
mpFCLoader->AddRef();
|
|
|
|
mpStatePropLoader = new CStatePropDataLoader;
|
|
mpStatePropLoader->AddRef();
|
|
|
|
mpFactoryLoader = new tAnimatedObjectFactoryLoader;
|
|
mpAnimObjectLoader = new tAnimatedObjectLoader;
|
|
|
|
}
|
|
|
|
AnimObjDSGWrapperLoader::~AnimObjDSGWrapperLoader()
|
|
{
|
|
mpCollObjLoader->ReleaseVerified();
|
|
mpPhysObjLoader->ReleaseVerified();
|
|
mpCompDLoader->ReleaseVerified();
|
|
mpMCLoader->ReleaseVerified();
|
|
mpSkelLoader->ReleaseVerified();
|
|
mpAnimationLoader->ReleaseVerified();
|
|
mpFCLoader->ReleaseVerified();
|
|
mpStatePropLoader->ReleaseVerified();
|
|
mpFactoryLoader->ReleaseVerified();
|
|
mpAnimObjectLoader->ReleaseVerified();
|
|
}
|
|
|
|
|
|
|
|
tEntity* AnimObjDSGWrapperLoader::LoadObject( tChunkFile* file, tEntityStore* store )
|
|
{
|
|
HeapMgr()->PushHeap( GMA_LEVEL_OTHER );
|
|
AnimDynaPhysWrapper* wrapper = new AnimDynaPhysWrapper;
|
|
HeapMgr()->PopHeap( GMA_LEVEL_OTHER );
|
|
rAssert( file != NULL );
|
|
rAssert( store != NULL );
|
|
|
|
// Grab the name
|
|
char buffer[256];
|
|
file->GetPString( buffer );
|
|
|
|
wrapper->SetName( buffer );
|
|
|
|
|
|
|
|
// Grab version info
|
|
int version = file->GetUChar();
|
|
// Grab the flag that tell us whether or not the object has alpha or not
|
|
int hasAlpha = file->GetUChar();
|
|
|
|
wrapper->mHasAlpha = ( hasAlpha != 0x00000000 );
|
|
|
|
while( file->ChunksRemaining() )
|
|
{
|
|
file->BeginChunk();
|
|
unsigned int id = file->GetCurrentID();
|
|
switch( id )
|
|
{
|
|
case P3D_COMPOSITE_DRAWABLE:
|
|
{
|
|
// We will save the composite drawable since we need it
|
|
// for our DSG objects
|
|
rAssertMsg( wrapper->mCompDraw == NULL, "There must only be one composite drawable in the wrapper!" );
|
|
wrapper->mCompDraw = (tCompositeDrawable*)mpCompDLoader->LoadObject( file, store );
|
|
wrapper->mCompDraw->AddRef();
|
|
store->Store( wrapper->mCompDraw );
|
|
rAssert( wrapper->mCompDraw != NULL );
|
|
}
|
|
break;
|
|
case P3D_MULTI_CONTROLLER:
|
|
{
|
|
rAssert( wrapper->mMultiController == NULL );
|
|
wrapper->mMultiController = (tMultiController*)mpMCLoader->LoadObject( file, store );
|
|
rAssert( wrapper->mMultiController != NULL );
|
|
// This should be inserted into the list of world render multicontrollers that
|
|
// get advanced every frame
|
|
wrapper->mMultiController->SetCycleMode( FORCE_CYCLIC );
|
|
wrapper->mMultiController->AddRef();
|
|
bool collision = store->TestCollision( wrapper->mMultiController->GetUID(), wrapper->mMultiController );
|
|
if( !collision )
|
|
{
|
|
store->Store( wrapper->mMultiController );
|
|
}
|
|
else
|
|
{
|
|
HandleCollision( wrapper->mMultiController );
|
|
}
|
|
}
|
|
break;
|
|
case Pure3D::Animation::FrameControllerData::FRAME_CONTROLLER:
|
|
{
|
|
tFrameController* pFC = static_cast< tFrameController* >( mpFCLoader->LoadObject( file, store ) );
|
|
rAssert( pFC != NULL );
|
|
store->Store( pFC );
|
|
}
|
|
break;
|
|
case Simulation::Collision::OBJECT:
|
|
{
|
|
|
|
rAssert( wrapper->mCollisionObject == NULL );
|
|
wrapper->mCollisionObject = static_cast< sim::CollisionObject* > (mpCollObjLoader->LoadObject( file, store ));
|
|
rAssert( wrapper->mCollisionObject != NULL );
|
|
wrapper->mCollisionObject->AddRef();
|
|
store->Store( wrapper->mCollisionObject );
|
|
//wrapper->mCollisionObject->AddRef ();
|
|
}
|
|
break;
|
|
case Pure3D::BillboardObject::QUAD_GROUP:
|
|
{
|
|
// Remember that we have our own billboard loader
|
|
// make sure that these don't get dumped into the DSG, override first
|
|
|
|
// Grab the loader
|
|
BillboardWrappedLoader::OverrideLoader( true );
|
|
BillboardWrappedLoader* pBBQLoader = static_cast<BillboardWrappedLoader*>(AllWrappers::GetInstance()->mpLoader(AllWrappers::msBillboard));
|
|
|
|
tBillboardQuadGroup* pGroup = static_cast<tBillboardQuadGroup*>( pBBQLoader->LoadObject( file, store ) );
|
|
rAssert( pGroup != NULL );
|
|
store->Store( pGroup );
|
|
|
|
// Set the loader back to its normal state
|
|
BillboardWrappedLoader::OverrideLoader( false );
|
|
}
|
|
break;
|
|
case Pure3D::Mesh::MESH:
|
|
{
|
|
GeometryWrappedLoader* pGeoLoader = (GeometryWrappedLoader*)AllWrappers::GetInstance()->mpLoader( AllWrappers::msGeometry );
|
|
tGeometry* pGeo = static_cast<tGeometry*>(pGeoLoader->LoadObject( file, store ) );
|
|
rAssert( pGeo != NULL );
|
|
store->Store( pGeo );
|
|
}
|
|
break;
|
|
case Pure3D::Animation::AnimationData::ANIMATION:
|
|
{
|
|
tAnimation* pAnimation = static_cast< tAnimation*> ( mpAnimationLoader->LoadObject( file, store ) );
|
|
rAssert( pAnimation != NULL );
|
|
store->Store( pAnimation );
|
|
}
|
|
break;
|
|
case Simulation::Physics::OBJECT:
|
|
|
|
rAssert( wrapper->mPhysicsObject == NULL );
|
|
wrapper->mPhysicsObject = (sim::PhysicsObject*)mpPhysObjLoader->LoadObject( file,store );
|
|
rAssert( wrapper->mPhysicsObject != NULL );
|
|
store->Store( wrapper->mPhysicsObject );
|
|
wrapper->mPhysicsObject->AddRef ();
|
|
|
|
break;
|
|
case P3D_SKELETON:
|
|
{
|
|
|
|
tSkeleton* pSkeleton = static_cast< tSkeleton* > (mpSkelLoader->LoadObject( file, store ) );
|
|
rAssert( pSkeleton != NULL );
|
|
store->Store( pSkeleton );
|
|
}
|
|
break;
|
|
case StateProp::STATEPROP:
|
|
{
|
|
CStatePropData* pPropData = static_cast< CStatePropData* > (mpStatePropLoader->LoadObject( file, store ) );
|
|
rAssert( dynamic_cast< CStatePropData* >( pPropData ) != NULL );
|
|
rAssert( pPropData != NULL );
|
|
tRefCounted::Assign(wrapper->mStatePropData, pPropData);
|
|
store->Store( pPropData );
|
|
}
|
|
break;
|
|
case Pure3D::AnimatedObject::FACTORY:
|
|
{
|
|
|
|
tEntity* entity = mpFactoryLoader->LoadObject( file, store );
|
|
rAssert( dynamic_cast< tAnimatedObjectFactory* >(entity) != NULL );
|
|
store->Store( entity );
|
|
}
|
|
break;
|
|
case Pure3D::AnimatedObject::OBJECT:
|
|
{
|
|
tEntity* pEntity = mpAnimObjectLoader->LoadObject( file, store );
|
|
rAssert( pEntity != NULL );
|
|
store->Store( pEntity );
|
|
}
|
|
break;
|
|
default:
|
|
rAssertMsg( false, "Unknown chunk in animated wrapper chunk file");
|
|
break;
|
|
};
|
|
file->EndChunk();
|
|
}
|
|
|
|
return wrapper;
|
|
}
|
|
//===========================================================================
|
|
// AnimObjDSGWrapperLoader::SetRegdListener
|
|
//===========================================================================
|
|
// Description:
|
|
// Informs the loader its listener is.
|
|
//
|
|
// Constraints:
|
|
//
|
|
// Parameters:
|
|
// Pointer to the new listener. Integer for the data it sends to it OnChunkLoaded()
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
void AnimObjDSGWrapperLoader::SetRegdListener( ChunkListenerCallback* pListenerCB,
|
|
int iUserData )
|
|
{
|
|
//
|
|
// Follow protocol; notify old Listener, that it has been
|
|
// "disconnected".
|
|
//
|
|
if( mpListenerCB != NULL )
|
|
{
|
|
mpListenerCB->OnChunkLoaded( NULL, iUserData, 0 );
|
|
}
|
|
mpListenerCB = pListenerCB;
|
|
mUserData = iUserData;
|
|
}
|
|
|
|
//===========================================================================
|
|
// AnimObjDSGWrapperLoader::ModRegdListener
|
|
//===========================================================================
|
|
// Description:
|
|
// Changes the data that gets sent to the listener
|
|
//
|
|
// Constraints:
|
|
// Listener must have been set already via SetRegdListener
|
|
//
|
|
// Parameters:
|
|
// Pointer to the listener. Integer holding the new data
|
|
//
|
|
// Return:
|
|
//
|
|
//===========================================================================
|
|
void AnimObjDSGWrapperLoader::ModRegdListener( ChunkListenerCallback* pListenerCB, int iUserData )
|
|
{
|
|
rAssert( pListenerCB == mpListenerCB );
|
|
|
|
mUserData = iUserData;
|
|
}
|
|
|
|
//===========================================================================
|
|
// AnimObjDSGWrapperLoader::IsMissionProp
|
|
//===========================================================================
|
|
// Description:
|
|
// Returns boolean indicating if the prop is used in a mission
|
|
//
|
|
// Constraints:
|
|
// Only one stateprop mission prop - the powerbox
|
|
//
|
|
// Parameters:
|
|
// none
|
|
//
|
|
// Return:
|
|
// bool indicating if this prop is used in a mission
|
|
//
|
|
//===========================================================================
|
|
bool AnimDynaPhysLoader::IsMissionProp( const char* name )const
|
|
{
|
|
if ( strcmp( name, "l1z6_powerbox_Shape" ) == 0 )
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|