mirror of
https://github.com/thug1src/thug.git
synced 2024-11-30 12:06:44 +00:00
877 lines
28 KiB
C++
877 lines
28 KiB
C++
|
//****************************************************************************
|
||
|
//* MODULE: Sk/Objects
|
||
|
//* FILENAME: ViewerObj.cpp
|
||
|
//* OWNER: Gary Jesdanun
|
||
|
//* CREATION DATE: 1/21/2002
|
||
|
//****************************************************************************
|
||
|
|
||
|
#include <sk/objects/viewerobj.h>
|
||
|
|
||
|
#include <gel/components/animationcomponent.h>
|
||
|
#include <gel/components/modelcomponent.h>
|
||
|
#include <gel/components/skeletoncomponent.h>
|
||
|
|
||
|
#include <gel/mainloop.h>
|
||
|
#include <gel/objman.h>
|
||
|
#include <gel/assman/assman.h>
|
||
|
#include <gel/scripting/script.h>
|
||
|
#include <gel/scripting/checksum.h>
|
||
|
#include <gel/scripting/struct.h>
|
||
|
#include <gel/scripting/symboltable.h>
|
||
|
#include <gel/net/server/netserv.h>
|
||
|
|
||
|
#include <gfx/bonedanim.h>
|
||
|
#include <gfx/gfxutils.h>
|
||
|
#include <gfx/modelappearance.h>
|
||
|
#include <gfx/nx.h>
|
||
|
#include <gfx/nxmodel.h>
|
||
|
#include <gfx/nxhierarchy.h>
|
||
|
#include <gfx/skeleton.h>
|
||
|
|
||
|
#include <sk/gamenet/exportmsg.h>
|
||
|
#include <sk/gamenet/gamenet.h>
|
||
|
#include <sk/modules/skate/skate.h>
|
||
|
#include <sk/modules/viewer/viewer.h>
|
||
|
#include <sk/objects/skaterprofile.h>
|
||
|
#include <sk/scripting/cfuncs.h>
|
||
|
#include <sk/scripting/gs_file.h>
|
||
|
#include <sk/scripting/skfuncs.h>
|
||
|
|
||
|
#include <sys/config/config.h>
|
||
|
|
||
|
// TODO: Remove the rest of the level when the viewer is active
|
||
|
// TODO: Launch a primary sequence by name, pointer, or index
|
||
|
// TODO: The shoulder buttons should increment the current anim (next/prev anim)
|
||
|
// TODO: Don't crash if can't find the animation...
|
||
|
// TODO: Add handlers so that it can launch new anims and such
|
||
|
// TODO: Camera controls
|
||
|
// TODO: Be able to go back to the game
|
||
|
// TODO: Wireframe mode
|
||
|
// TODO: Change skater profile, in real time
|
||
|
// TODO: Take LODs into account
|
||
|
|
||
|
namespace Obj
|
||
|
{
|
||
|
|
||
|
const float vSPEED_INCREMENT_AMOUNT = 0.25;
|
||
|
const Mth::Vector vPOS_VIEWEROBJECT( 0.0f, 0.0f, 0.0f );
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CViewerObject::s_handle_set_anim( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
CViewerObject* pViewerObject;
|
||
|
pViewerObject = (CViewerObject*) context->m_Data;
|
||
|
Dbg_Assert( pViewerObject );
|
||
|
|
||
|
Net::MsgViewObjSetAnim* p_msg;
|
||
|
p_msg = (Net::MsgViewObjSetAnim*) context->m_Msg;
|
||
|
pViewerObject->SetAnim( p_msg->m_AnimName );
|
||
|
|
||
|
Dbg_Message( "Got request to set anim %s...", Script::FindChecksumName(p_msg->m_AnimName) );
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CViewerObject::s_handle_set_anim_speed( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Dbg_Message( "Got request to set anim speed..." );
|
||
|
|
||
|
CViewerObject* pViewerObject;
|
||
|
pViewerObject = (CViewerObject*) context->m_Data;
|
||
|
Dbg_Assert( pViewerObject );
|
||
|
|
||
|
Net::MsgViewObjSetAnimSpeed* p_msg;
|
||
|
p_msg = (Net::MsgViewObjSetAnimSpeed*) context->m_Msg;
|
||
|
pViewerObject->ChangeAnimSpeed( p_msg->m_AnimSpeed );
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CViewerObject::s_handle_increment_frame( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Dbg_Message( "Got request to increment frame..." );
|
||
|
|
||
|
CViewerObject* pViewerObject;
|
||
|
pViewerObject = (CViewerObject*) context->m_Data;
|
||
|
Dbg_Assert( pViewerObject );
|
||
|
|
||
|
Net::MsgViewObjIncrementFrame* p_msg;
|
||
|
p_msg = (Net::MsgViewObjIncrementFrame*) context->m_Msg;
|
||
|
pViewerObject->IncrementFrame( p_msg->m_Forwards );
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CViewerObject::s_handle_reload_anim( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Dbg_Message( "Got request to reload anim..." );
|
||
|
|
||
|
CViewerObject* pViewerObject;
|
||
|
pViewerObject = (CViewerObject*) context->m_Data;
|
||
|
Dbg_Assert( pViewerObject );
|
||
|
|
||
|
Net::MsgViewObjSetAnimFile* p_msg;
|
||
|
p_msg = (Net::MsgViewObjSetAnimFile*) context->m_Msg;
|
||
|
pViewerObject->ReloadAnim( p_msg->m_Filename, p_msg->m_checksum );
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CViewerObject::s_handle_sequence_preview( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
char path[256];
|
||
|
char* script_name;
|
||
|
CViewerObject* pViewerObject;
|
||
|
pViewerObject = (CViewerObject*) context->m_Data;
|
||
|
Dbg_Assert( pViewerObject );
|
||
|
|
||
|
script_name = context->m_Msg;
|
||
|
sprintf( path, "scripts\\animview\\%s.qb", script_name );
|
||
|
SkateScript::LoadQB( path );
|
||
|
//Script::RunScriptOnObject("RunMeNow",NULL,pViewerObject);
|
||
|
Script::CScript *pNewScript=Script::SpawnScript(script_name,NULL,0,NULL);
|
||
|
pNewScript->mpObject = pViewerObject;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CViewerObject::s_handle_reload_cam_anim( Net::MsgHandlerContext* context )
|
||
|
{
|
||
|
Dbg_Message( "Got request to reload cam anim..." );
|
||
|
|
||
|
Net::MsgViewObjSetAnimFile* p_msg;
|
||
|
p_msg = (Net::MsgViewObjSetAnimFile*) context->m_Msg;
|
||
|
|
||
|
Script::CStruct* pTempStruct = new Script::CStruct;
|
||
|
|
||
|
pTempStruct->AddString( NONAME, p_msg->m_Filename );
|
||
|
pTempStruct->AddChecksum( NONAME, p_msg->m_checksum );
|
||
|
|
||
|
CFuncs::ScriptReloadSkaterCamAnim( pTempStruct, NULL );
|
||
|
|
||
|
delete pTempStruct;
|
||
|
|
||
|
return Net::HANDLER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CViewerObject::CViewerObject( Net::Server* pServer )
|
||
|
{
|
||
|
Inp::Manager * inp_manager = Inp::Manager::Instance();
|
||
|
mp_input_handler = new Inp::Handler< CViewerObject > ( 0, s_input_logic_code, *this, Tsk::BaseTask::Node::vNORMAL_PRIORITY );
|
||
|
inp_manager->AddHandler( *mp_input_handler );
|
||
|
|
||
|
m_animSpeed = 1.0f;
|
||
|
m_showPanel = true;
|
||
|
|
||
|
m_matrix.Ident();
|
||
|
|
||
|
m_paused = false;
|
||
|
|
||
|
mp_server = pServer;
|
||
|
|
||
|
Dbg_Assert( mp_server );
|
||
|
|
||
|
mp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_ANIM,
|
||
|
s_handle_set_anim,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
mp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_ANIM_SPEED,
|
||
|
s_handle_set_anim_speed,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
mp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_INCREMENT_FRAME,
|
||
|
s_handle_increment_frame,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
mp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_ANIM_FILE,
|
||
|
s_handle_reload_anim,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
mp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_SET_CAMANIM_FILE,
|
||
|
s_handle_reload_cam_anim,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
mp_server->m_Dispatcher.AddHandler( Net::vMSG_ID_VIEWOBJ_PREVIEW_SEQUENCE,
|
||
|
s_handle_sequence_preview,
|
||
|
Net::mHANDLE_LATE | Net::mHANDLE_FOREIGN, this );
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CViewerObject::~CViewerObject()
|
||
|
{
|
||
|
mp_input_handler->Remove();
|
||
|
|
||
|
delete mp_input_handler;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
static void s_remove_asset( const char* pFileName )
|
||
|
{
|
||
|
// if the file is in the asset manager, unload it so
|
||
|
// that the artists can display the latest version
|
||
|
// ("cas_artist" must be set to 1, or else it'll just
|
||
|
// reload it from the PRE file)
|
||
|
|
||
|
if ( !Script::GetInt( "cas_artist", false ) )
|
||
|
{
|
||
|
Dbg_Message( "Warning: Can't reload asset %s from disk (need to define cas_artist=1)", pFileName );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// get the assman
|
||
|
Ass::CAssMan * ass_man = Ass::CAssMan::Instance();
|
||
|
|
||
|
// kills the original asset
|
||
|
Ass::CAsset* pAsset = ass_man->GetAssetNode( Script::GenerateCRC( pFileName ), false );
|
||
|
|
||
|
if ( pAsset )
|
||
|
{
|
||
|
Dbg_Message( "Unloading asset %s", pFileName );
|
||
|
ass_man->DestroyReferences( pAsset );
|
||
|
ass_man->UnloadAsset( pAsset );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_Message( "Couldn't find asset %s to unload", pFileName );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::LoadModel( Script::CStruct* pNodeData )
|
||
|
{
|
||
|
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
|
||
|
skate_mod->GetObjectManager()->RegisterObject( *this );
|
||
|
MovingObjectCreateComponents();
|
||
|
MovingObjectInit( pNodeData, skate_mod->GetObjectManager() );
|
||
|
|
||
|
Nx::CEngine::sFinishRendering();
|
||
|
|
||
|
if (Config::GotExtraMemory())
|
||
|
{
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
|
||
|
}
|
||
|
|
||
|
Dbg_Assert( pNodeData );
|
||
|
|
||
|
// get rid of old model, if
|
||
|
// it was stored in the assman
|
||
|
int skaterProfileNumber;
|
||
|
const char* pModelName;
|
||
|
uint32 profileName;
|
||
|
|
||
|
for ( int i = 0; i < Obj::CModelComponent::vNUM_LODS; i++ )
|
||
|
{
|
||
|
char paramName[256];
|
||
|
sprintf( paramName, "model%d", i );
|
||
|
|
||
|
if ( pNodeData->GetText( paramName, &pModelName, false ) )
|
||
|
{
|
||
|
Dbg_Message( "Removing model LOD data from asset manager, in order to replace it with new data" );
|
||
|
|
||
|
Str::String fullModelName;
|
||
|
fullModelName = Gfx::GetModelFileName(pModelName, ".skin");
|
||
|
s_remove_asset( fullModelName.getString() );
|
||
|
|
||
|
fullModelName = Gfx::GetModelFileName(pModelName, ".mdl");
|
||
|
s_remove_asset( fullModelName.getString() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pNodeData->GetText( "modelName", &pModelName, false )
|
||
|
|| pNodeData->GetText( "model", &pModelName, false ) )
|
||
|
{
|
||
|
Dbg_Message( "Removing model data from asset manager, in order to replace it with new data" );
|
||
|
|
||
|
Str::String fullModelName;
|
||
|
fullModelName = Gfx::GetModelFileName(pModelName, ".skin");
|
||
|
s_remove_asset( fullModelName.getString() );
|
||
|
|
||
|
fullModelName = Gfx::GetModelFileName(pModelName, ".mdl");
|
||
|
s_remove_asset( fullModelName.getString() );
|
||
|
}
|
||
|
else if ( pNodeData->GetChecksum( "profile", &profileName, false ) )
|
||
|
{
|
||
|
Dbg_Message( "Warning: can't remove old model data from asset manager... asset not reloaded from disk." );
|
||
|
}
|
||
|
else if ( pNodeData->GetInteger( "skater_profile_index", &skaterProfileNumber, false ) )
|
||
|
{
|
||
|
Dbg_Message( "Warning: can't remove old model data from asset manager... asset not reloaded from disk." );
|
||
|
|
||
|
Obj::CSkaterProfile* pSkaterProfile = Mdl::Skate::Instance()->GetProfile( skaterProfileNumber );
|
||
|
Script::CStruct* pAppearanceStruct = pSkaterProfile->GetAppearance()->GetStructure();
|
||
|
Script::CStruct* pNewStruct = new Script::CStruct;
|
||
|
pNewStruct->AppendStructure( pAppearanceStruct );
|
||
|
pNodeData->AddStructurePointer( "profile", pNewStruct );
|
||
|
// don't need to delete the structure,
|
||
|
// because it gets added permanently to the struct
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Dbg_MsgAssert( 0, ( "Unrecognized parameters for model loading" ) );
|
||
|
}
|
||
|
|
||
|
m_pos = vPOS_VIEWEROBJECT;
|
||
|
m_matrix.Ident();
|
||
|
|
||
|
Script::RunScript( CRCD(0x24c71bc7,"viewerobj_add_components"), pNodeData, this );
|
||
|
|
||
|
Finalize();
|
||
|
|
||
|
Script::RunScript( CRCD(0xbbab79de,"viewerobj_init_model"), pNodeData, this );
|
||
|
|
||
|
// loop the idle anim, if it exists
|
||
|
CViewerObject::SetAnim( CRCD(0x23db4aea,"idle") );
|
||
|
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::UnloadModel()
|
||
|
{
|
||
|
Script::RunScript( "kill_viewer_object_panel" );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::SetAnim( uint32 animName )
|
||
|
{
|
||
|
if ( GetAnimationComponent() )
|
||
|
{
|
||
|
if ( GetAnimationComponent()->AnimExists( animName ) )
|
||
|
{
|
||
|
GetAnimationComponent()->PlayPrimarySequence( animName, false, 0.0f, GetAnimationComponent()->AnimDuration( animName ), Gfx::LOOPING_CYCLE);
|
||
|
|
||
|
/*
|
||
|
Script::CStruct* pTempStruct = new Script::CStruct;
|
||
|
pTempStruct->AddChecksum( "type", Script::GenerateCRC("partialAnim" ) );
|
||
|
pTempStruct->AddChecksum( "AnimName", Script::GetChecksum("TestPartialAnim" ) );
|
||
|
pTempStruct->AddChecksum( "from", Script::GenerateCRC("start") );
|
||
|
pTempStruct->AddChecksum( "to", Script::GenerateCRC("end") );
|
||
|
pTempStruct->AddChecksum( NONAME, Script::GenerateCRC("cycle") );
|
||
|
pTempStruct->AddFloat( "speed", 1.0f );
|
||
|
Script::RunScript( "AddAnimController", pTempStruct, this );
|
||
|
delete pTempStruct;
|
||
|
*/
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
Dbg_Message( "Unrecognized anim %s", Script::FindChecksumName(animName) );
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::SetRotation( float rotZ, float rotX )
|
||
|
{
|
||
|
m_matrix.Ident();
|
||
|
m_matrix.RotateZ( rotZ );
|
||
|
m_matrix.RotateX( rotX );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::ChangeAnimSpeed( float animSpeed )
|
||
|
{
|
||
|
m_animSpeed = animSpeed;
|
||
|
|
||
|
if ( m_animSpeed > 1.0f )
|
||
|
{
|
||
|
m_animSpeed = 1.0f;
|
||
|
}
|
||
|
|
||
|
if ( m_animSpeed < 0.0f )
|
||
|
{
|
||
|
m_animSpeed = 0.0f;
|
||
|
}
|
||
|
|
||
|
if ( GetAnimationComponent() )
|
||
|
{
|
||
|
GetAnimationComponent()->SetAnimSpeed( m_animSpeed, false );
|
||
|
|
||
|
// update partial anims
|
||
|
Script::CStruct* pTempStruct = new Script::CStruct;
|
||
|
pTempStruct->AddFloat( CRCD(0xf0d90109,"speed"), m_animSpeed );
|
||
|
GetAnimationComponent()->CallMemberFunction( CRCD(0xbd4edd44,"SetPartialAnimSpeed"), pTempStruct, NULL );
|
||
|
delete pTempStruct;
|
||
|
}
|
||
|
|
||
|
if ( GetAnimationComponent() )
|
||
|
{
|
||
|
// reset the paused state...
|
||
|
GetAnimationComponent()->Suspend( false );
|
||
|
}
|
||
|
|
||
|
m_paused = false;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::IncrementFrame( bool forwards )
|
||
|
{
|
||
|
if ( GetAnimationComponent() )
|
||
|
{
|
||
|
if ( forwards )
|
||
|
{
|
||
|
// frame-rate independent
|
||
|
GetAnimationComponent()->AddTime( 1.0f / 60.0f );
|
||
|
GetAnimationComponent()->PrintStatus();
|
||
|
|
||
|
Script::CStruct* pTempStruct = new Script::CStruct;
|
||
|
pTempStruct->AddFloat( CRCD(0x06c9f278,"incVal"), 1.0f / 60.0f );
|
||
|
GetAnimationComponent()->CallMemberFunction( CRCD(0x6aaeb76f,"IncrementPartialAnimTime"), pTempStruct, NULL );
|
||
|
delete pTempStruct;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// reverse direction so that it loops properly
|
||
|
GetAnimationComponent()->ReverseDirection( false );
|
||
|
|
||
|
// frame-rate independent
|
||
|
GetAnimationComponent()->AddTime( -1.0f / 60.0f );
|
||
|
GetAnimationComponent()->PrintStatus();
|
||
|
|
||
|
GetAnimationComponent()->ReverseDirection( false );
|
||
|
|
||
|
GetAnimationComponent()->CallMemberFunction( CRCD(0xf5e2b871,"ReversePartialAnimDirection"), NULL, NULL );
|
||
|
|
||
|
Script::CStruct* pTempStruct = new Script::CStruct;
|
||
|
pTempStruct->AddFloat( CRCD(0x06c9f278,"incVal"), -1.0f / 60.0f );
|
||
|
GetAnimationComponent()->CallMemberFunction( CRCD(0x6aaeb76f,"IncrementPartialAnimTime"), pTempStruct, NULL );
|
||
|
delete pTempStruct;
|
||
|
|
||
|
GetAnimationComponent()->CallMemberFunction( CRCD(0xf5e2b871,"ReversePartialAnimDirection"), NULL, NULL );
|
||
|
}
|
||
|
|
||
|
// don't want to call the animation component's
|
||
|
// Update() function, because that changes the
|
||
|
// time... instead, call UpdateSkeleton()
|
||
|
// which syncs the skeleton to the current time
|
||
|
GetAnimationComponent()->UpdateSkeleton();
|
||
|
|
||
|
// reset the paused state...
|
||
|
GetAnimationComponent()->Suspend( true );
|
||
|
}
|
||
|
|
||
|
m_paused = true;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::ReloadAnim( const char* pFileName, uint32 animName )
|
||
|
{
|
||
|
if ( GetAnimationComponent() )
|
||
|
{
|
||
|
Dbg_Message( "Reloading anim..." );
|
||
|
Dbg_Message( "Warning! This function fragments memory. Use it at your own risk!" );
|
||
|
|
||
|
// get the assman
|
||
|
Ass::CAssMan * ass_man = Ass::CAssMan::Instance();
|
||
|
|
||
|
// kills the original asset
|
||
|
Ass::CAsset* pAsset = ass_man->GetAssetNode( Script::GenerateCRC( pFileName ), false );
|
||
|
if ( pAsset )
|
||
|
{
|
||
|
ass_man->DestroyReferences( pAsset );
|
||
|
ass_man->UnloadAsset( pAsset );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
Dbg_Message( "Couldn't find asset %s to unload", Script::FindChecksumName( animName ) );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// load anim asset here!!!!
|
||
|
ass_man->LoadAnim( pFileName, animName, GetAnimationComponent()->GetAnimScriptName(), false, false );
|
||
|
|
||
|
this->SetAnim( animName );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::UpdateWheels()
|
||
|
{
|
||
|
Nx::CHierarchyObject* pHierarchyObjects = GetModel()->GetHierarchy();
|
||
|
Dbg_Assert( pHierarchyObjects );
|
||
|
|
||
|
Gfx::CSkeleton* pCarSkeleton = GetSkeletonComponent()->GetSkeleton();
|
||
|
Dbg_Assert( pCarSkeleton );
|
||
|
|
||
|
Dbg_MsgAssert( GetModel()->GetNumObjectsInHierarchy()==pCarSkeleton->GetNumBones(),
|
||
|
( "Skeleton and hierarchy doesn't match (%d hierarchy objs vs %d bones)",
|
||
|
GetModel()->GetNumObjectsInHierarchy(), pCarSkeleton->GetNumBones() ) );
|
||
|
|
||
|
static float s_wheelRotationX = 0.0f;
|
||
|
|
||
|
// not frame rate independent (doesn't have valid m_time)
|
||
|
s_wheelRotationX += ( Script::GetFloat("max_wheel_speed", Script::ASSERT) * m_animSpeed );
|
||
|
|
||
|
// make sure it's within bounds
|
||
|
while ( s_wheelRotationX > 360.0f )
|
||
|
{
|
||
|
s_wheelRotationX -= 360.0f;
|
||
|
}
|
||
|
|
||
|
while ( s_wheelRotationX < 0.0f )
|
||
|
{
|
||
|
s_wheelRotationX += 360.0f;
|
||
|
}
|
||
|
|
||
|
if ( GetModel()->GetNumObjectsInHierarchy() > 5 )
|
||
|
{
|
||
|
Mth::Matrix* pMatrices = pCarSkeleton->GetMatrices();
|
||
|
Dbg_Assert( pMatrices );
|
||
|
|
||
|
// initialize the setup matrix once per frame
|
||
|
for ( int i = 0; i < GetModel()->GetNumObjectsInHierarchy(); i++ )
|
||
|
{
|
||
|
*(pMatrices + i) = ( pHierarchyObjects + i )->GetSetupMatrix();
|
||
|
}
|
||
|
|
||
|
// apply the appropriate rotations to the wheels
|
||
|
for ( int i = 2; i < 6; i++ )
|
||
|
{
|
||
|
(pMatrices + i)->RotateXLocal( s_wheelRotationX * 2.0f * Mth::PI / 360.0f );
|
||
|
}
|
||
|
|
||
|
// get children into object space
|
||
|
for ( int i = 1; i < 6; i++ )
|
||
|
{
|
||
|
*(pMatrices + i) *= *(pMatrices + 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::Update()
|
||
|
{
|
||
|
if ( GetAnimationComponent() )
|
||
|
{
|
||
|
if ( m_showPanel )
|
||
|
{
|
||
|
if ( GetAnimationComponent()->AnimExists(GetAnimationComponent()->GetCurrentSequence()) )
|
||
|
{
|
||
|
// pass the pertinent info to the panel:
|
||
|
Script::CStruct* pTempStruct = new Script::CStruct;
|
||
|
|
||
|
char line1[128];
|
||
|
sprintf( line1, "name %s",
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
Script::FindChecksumName( GetAnimationComponent()->GetCurrentSequence() )
|
||
|
#else
|
||
|
"Unknown"
|
||
|
#endif
|
||
|
);
|
||
|
|
||
|
pTempStruct->AddString( "line1", (const char*)&line1 );
|
||
|
|
||
|
char line2[128];
|
||
|
sprintf( line2, "speed %f", m_paused ? 0.0f : m_animSpeed );
|
||
|
pTempStruct->AddString( "line2", (const char*)&line2 );
|
||
|
|
||
|
char line3[128];
|
||
|
sprintf( line3, "time %f of %f",
|
||
|
GetAnimationComponent()->GetCurrentAnimTime(),
|
||
|
GetAnimationComponent()->AnimDuration( GetAnimationComponent()->GetCurrentSequence() ) );
|
||
|
pTempStruct->AddString( "line3", (const char*)&line3 );
|
||
|
|
||
|
char line4[128];
|
||
|
sprintf( line4, "frame %d of %d", (int)(GetAnimationComponent()->GetCurrentAnimTime() * 60.0f),
|
||
|
(int)(GetAnimationComponent()->AnimDuration( GetAnimationComponent()->GetCurrentSequence() ) * 60.0f) );
|
||
|
pTempStruct->AddString( "line4", (const char*)&line4 );
|
||
|
|
||
|
// TODO: Print out anim size
|
||
|
|
||
|
Script::RunScript( "draw_viewer_object_panel", pTempStruct );
|
||
|
delete pTempStruct;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( GetModel()->GetNumObjectsInHierarchy() )
|
||
|
{
|
||
|
UpdateWheels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::s_input_logic_code ( const Inp::Handler < CViewerObject >& handler )
|
||
|
{
|
||
|
CViewerObject& obj = handler.GetData();
|
||
|
|
||
|
// this is the minimum amount of time
|
||
|
// you need to hold down the left/right keys
|
||
|
// before it will auto repeat
|
||
|
int vAUTO_REPEAT_TIME = Script::GetInteger( CRCD(0xe60442d5,"ViewerAutoRepeatTime"), Script::NO_ASSERT );
|
||
|
|
||
|
// this is how fast it auto repeats
|
||
|
int vAUTO_REPEAT_SPEED = Script::GetInteger( CRCD(0x2da212e5,"ViewerAutoRepeatSpeed"), Script::NO_ASSERT );
|
||
|
|
||
|
static int s_auto_repeat_delay = vAUTO_REPEAT_TIME;
|
||
|
|
||
|
// GJ: no longer clearing the last frame's data
|
||
|
// at the beginning of the loop... this allows
|
||
|
// us to override the m_commands from an external
|
||
|
// class (useful for doing custom controller
|
||
|
// configs for different viewer modes)
|
||
|
// obj.m_commands.ClearAll();
|
||
|
|
||
|
if( handler.m_Input->m_Makes & Inp::Data::mD_TRIANGLE )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mTOGGLE_PANEL );
|
||
|
}
|
||
|
|
||
|
if ( handler.m_Input->m_Makes & Inp::Data::mD_LEFT )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mDECREMENT_FRAME );
|
||
|
s_auto_repeat_delay = vAUTO_REPEAT_TIME;
|
||
|
}
|
||
|
else if ( handler.m_Input->m_Makes & Inp::Data::mD_RIGHT )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mINCREMENT_FRAME );
|
||
|
s_auto_repeat_delay = vAUTO_REPEAT_TIME;
|
||
|
}
|
||
|
else if ( handler.m_Input->m_Buttons & Inp::Data::mD_LEFT )
|
||
|
{
|
||
|
s_auto_repeat_delay--;
|
||
|
if ( s_auto_repeat_delay <= 0 )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mDECREMENT_FRAME );
|
||
|
s_auto_repeat_delay = vAUTO_REPEAT_SPEED;
|
||
|
}
|
||
|
}
|
||
|
else if ( handler.m_Input->m_Buttons & Inp::Data::mD_RIGHT )
|
||
|
{
|
||
|
s_auto_repeat_delay--;
|
||
|
if ( s_auto_repeat_delay <= 0 )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mINCREMENT_FRAME );
|
||
|
s_auto_repeat_delay = vAUTO_REPEAT_SPEED;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_auto_repeat_delay = vAUTO_REPEAT_TIME;
|
||
|
}
|
||
|
|
||
|
// the viewer uses the global var "viewer_controls_enabled"
|
||
|
// to decide whether certain viewer controls should be
|
||
|
// active while in the regular viewer/light viewer.
|
||
|
// rather than adding a new global var to distinguish
|
||
|
// between the model viewer/light viewer, i've decided
|
||
|
// to just have the viewer object handle those viewer
|
||
|
// controls here
|
||
|
if( handler.m_Input->m_Makes & Inp::Data::mD_L3 )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mTOGGLE_ROTATE_MODE );
|
||
|
}
|
||
|
|
||
|
if ( handler.m_Input->m_Buttons & Inp::Data::mD_R1 )
|
||
|
{
|
||
|
if( !( handler.m_Input->m_Buttons & Inp::Data::mD_R2 ))
|
||
|
{
|
||
|
obj.m_commands.SetMask( mSTRAFE_UP );
|
||
|
}
|
||
|
}
|
||
|
else if ( handler.m_Input->m_Buttons & Inp::Data::mD_R2 )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mSTRAFE_DOWN );
|
||
|
}
|
||
|
|
||
|
if ( handler.m_Input->m_Makes & Inp::Data::mD_L1 )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mINCREASE_SPEED );
|
||
|
}
|
||
|
else if ( handler.m_Input->m_Makes & Inp::Data::mD_L2 )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mDECREASE_SPEED );
|
||
|
}
|
||
|
|
||
|
if ( !GetAnimationComponentFromObject( &obj ) )
|
||
|
{
|
||
|
if ( handler.m_Input->m_Buttons & Inp::Data::mD_CIRCLE )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mROLL_LEFT );
|
||
|
}
|
||
|
else if ( handler.m_Input->m_Buttons & Inp::Data::mD_SQUARE )
|
||
|
{
|
||
|
obj.m_commands.SetMask( mROLL_RIGHT );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CViewerObject::DoGameLogic()
|
||
|
{
|
||
|
if ( m_commands.TestMask( mTOGGLE_PANEL ) )
|
||
|
{
|
||
|
m_showPanel = !m_showPanel;
|
||
|
|
||
|
Script::RunScript( "kill_viewer_object_panel" );
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mINCREASE_SPEED ) )
|
||
|
{
|
||
|
ChangeAnimSpeed( m_animSpeed + vSPEED_INCREMENT_AMOUNT );
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mDECREASE_SPEED ) )
|
||
|
{
|
||
|
ChangeAnimSpeed( m_animSpeed - vSPEED_INCREMENT_AMOUNT );
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mINCREMENT_FRAME ) )
|
||
|
{
|
||
|
IncrementFrame( true );
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mDECREMENT_FRAME ) )
|
||
|
{
|
||
|
IncrementFrame( false );
|
||
|
}
|
||
|
|
||
|
// yuck: the following creates a cyclic dependency
|
||
|
// on viewer... should get rid of this later.
|
||
|
if ( m_commands.TestMask( mTOGGLE_ROTATE_MODE ) )
|
||
|
{
|
||
|
Mdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();
|
||
|
if ( pViewer )
|
||
|
{
|
||
|
pViewer->SetCommand( Mdl::CViewer::mTOGGLE_ROTATE_MODE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mSTRAFE_UP ) )
|
||
|
{
|
||
|
Mdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();
|
||
|
if ( pViewer )
|
||
|
{
|
||
|
pViewer->SetCommand( Mdl::CViewer::mSTRAFE_UP );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mSTRAFE_DOWN ) )
|
||
|
{
|
||
|
Mdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();
|
||
|
if ( pViewer )
|
||
|
{
|
||
|
pViewer->SetCommand( Mdl::CViewer::mSTRAFE_DOWN );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mROLL_LEFT ) )
|
||
|
{
|
||
|
Mdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();
|
||
|
if ( pViewer )
|
||
|
{
|
||
|
pViewer->SetCommand( Mdl::CViewer::mROLL_LEFT );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_commands.TestMask( mROLL_RIGHT ) )
|
||
|
{
|
||
|
Mdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();
|
||
|
if ( pViewer )
|
||
|
{
|
||
|
pViewer->SetCommand( Mdl::CViewer::mROLL_RIGHT );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Update();
|
||
|
|
||
|
// GJ: clear the frame's data, now that we're done with it
|
||
|
// (this used to be done at the beginning of the loop)
|
||
|
m_commands.ClearAll();
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
} // namespace Obj
|