| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Combat/animcontrol.cpp $*
- * *
- * $Author:: Byon_g $*
- * *
- * $Modtime:: 1/04/02 10:26a $*
- * *
- * $Revision:: 53 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "animcontrol.h"
- #include "assets.h"
- #include "debug.h"
- #include "rendobj.h"
- #include "chunkio.h"
- #include "saveload.h"
- #include "htree.h"
- /*
- **
- */
- enum {
- XXXCHUNKID_LEGS = 910991512,
- XXXCHUNKID_TORSO,
- CHUNKID_CHANNEL,
- CHUNKID_VARIABLES,
- CHUNKID_OLD,
- CHUNKID_NEW,
- CHUNKID_PARENT,
- CHUNKID_CHANNEL1,
- CHUNKID_CHANNEL2,
- MICROCHUNKID_BLEND_TIMER = 1,
- MICROCHUNKID_BLEND_TOTAL,
- MICROCHUNKID_FRAME,
- XXXMICROCHUNKID_WEIGHT,
- MICROCHUNKID_MODE,
- MICROCHUNKID_ANIMATION_NAME,
- MICROCHUNKID_MODEL_PTR,
- MICROCHUNKID_CHANNEL2_RATIO,
- MICROCHUNKID_TARGET_FRAME,
- MICROCHUNKID_SKELETON,
- };
- /*
- ** AnimChannelClass
- */
- AnimChannelClass::AnimChannelClass( void ) :
- Animation( NULL ),
- Frame( 0.0f ),
- NumFrames( 1 ),
- TargetFrame( 0.0f ),
- Mode( ANIM_MODE_ONCE )
- {
- }
- AnimChannelClass::~AnimChannelClass( void )
- {
- if ( Animation ) {
- Animation->Release_Ref();
- Animation = NULL;
- }
- }
- AnimChannelClass & AnimChannelClass::operator = (const AnimChannelClass & src)
- {
- if (Animation != NULL) {
- Animation->Release_Ref();
- }
- Animation = src.Animation;
- if (Animation != NULL) {
- Animation->Add_Ref();
- }
- Frame = src.Frame;
- NumFrames = src.NumFrames;
- Mode = src.Mode;
- TargetFrame = src.TargetFrame;
- return *this;
- }
- bool AnimChannelClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- // save the anim first, because the load will stomp the frame & weight
- if ( Animation ) {
- csave.Begin_Micro_Chunk( MICROCHUNKID_ANIMATION_NAME );
- const char * anim_name = Animation->Get_Name();
- csave.Write( anim_name, strlen( anim_name ) + 1);
- csave.End_Micro_Chunk();
- }
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_FRAME, Frame );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_MODE, Mode );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TARGET_FRAME, TargetFrame );
- csave.End_Chunk();
- return true;
- }
- bool AnimChannelClass::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_FRAME, Frame );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_MODE, Mode );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_TARGET_FRAME, TargetFrame );
- case MICROCHUNKID_ANIMATION_NAME:
- {
- char anim_name[80];
- cload.Read( anim_name, cload.Cur_Micro_Chunk_Length() );
- Set_Animation( anim_name );
- break;
- }
- default:
- Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- void AnimChannelClass::Set_Animation( const char *name )
- {
- // If this is our current anim, bail
- if ( ( Animation != NULL ) && ( name != NULL ) ) {
- if ( stricmp( Animation->Get_Name(), name ) == 0 ) {
- return;
- }
- }
- if ( ( Animation == NULL ) && ( name == NULL ) ) {
- return;
- }
- // Release the old anim
- if ( Animation ) {
- Animation->Release_Ref();
- Animation = NULL;
- }
- // we need to switch anims
- if (( name != NULL ) && ( name[0] != 0 ) ) {
- Animation = WW3DAssetManager::Get_Instance()->Get_HAnim( name );
- }
- if ( Animation ) {
- SET_REF_OWNER( Animation );
- NumFrames = Animation->Get_Num_Frames();
- Mode = ANIM_MODE_ONCE;
- Frame = 0;
- TargetFrame = 0;
- }
- }
- void AnimChannelClass::Set_Animation( const HAnimClass *anim )
- {
- // If this is our current anim, bail
- if ( Animation == anim ) {
- return;
- }
- // Release the old anim
- if ( Animation ) {
- Animation->Release_Ref();
- Animation = NULL;
- }
- // we need to switch anims
- Animation = (HAnimClass *)anim;
- if ( Animation ) {
- Animation->Add_Ref();
- NumFrames = Animation->Get_Num_Frames();
- Mode = ANIM_MODE_ONCE;
- Frame = 0;
- TargetFrame = 0;
- }
- }
- void AnimChannelClass::Set_Mode( AnimMode mode, float frame )
- {
- Mode = mode;
- if ( frame >= 0 ) {
- Frame = frame;
- }
- }
- void AnimChannelClass::Update( float dtime )
- {
- if ( Mode == ANIM_MODE_STOP ) {
- return;
- }
- if ( Animation != NULL ) {
- switch ( Mode )
- {
- case ANIM_MODE_LOOP:
-
- //
- // Increment the frame based on the current timeslice
- //
- Frame += dtime * Animation->Get_Frame_Rate();
-
- //
- // Handle wrapping
- //
- if ( Frame >= NumFrames-1 ) {
- Frame -= NumFrames-1;
- }
- if ( Frame >= NumFrames ) {
- Frame = 0;
- }
- break;
- case ANIM_MODE_TARGET:
-
- //
- // Which direction are we animating?
- //
- if ( Frame < TargetFrame ) {
- Frame += dtime * Animation->Get_Frame_Rate();
-
- //
- // If we overshoot targetframe, snap to targetframe
- //
- if (Frame >= TargetFrame) {
- Frame = TargetFrame;
- }
- } else if ( Frame > TargetFrame ) {
- Frame -= dtime * Animation->Get_Frame_Rate();
-
- //
- // If we overshoot targetframe, snap to targetframe
- //
- if ( Frame <= TargetFrame ) {
- Frame = TargetFrame;
- }
- }
- break;
- case ANIM_MODE_ONCE:
- //
- // Increment the frame based on the current timeslice
- //
- Frame += dtime * Animation->Get_Frame_Rate();
- //
- // Make sure we don't go past the end
- //
- if ( Frame > NumFrames-1 ) {
- Frame = NumFrames-1;
- }
- break;
- }
- #if 0
- if ( dtime != 0 ) {
- Debug_Say(( "Anim %s frame %1.3f\n", Animation->Get_Name(), Frame ));
- }
- #endif
- }
- }
- void AnimChannelClass::Get_Animation_Data( AnimationDataList & list, float weight )
- {
- if ( Animation != NULL && weight > 0 ) {
- AnimationDataRecord * record = list.Uninitialized_Add();
- WWASSERT( record != NULL );
- record->Animation = Animation;
- record->Frame = Frame;
- record->Weight = weight;
- }
- }
- void AnimChannelClass::Update_Model( RenderObjClass *anim_model )
- {
- if ( Animation ) {
- anim_model->Set_Animation( Animation, Frame );
- } else {
- anim_model->Set_Animation();
- }
- }
- /*
- ** BlendableAnimChannelClass
- */
- BlendableAnimChannelClass::BlendableAnimChannelClass( void ) :
- BlendTimer( 0 ),
- BlendTotal( 0 )
- {
- }
- bool BlendableAnimChannelClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_NEW );
- NewChannel.Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_OLD );
- OldChannel.Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_BLEND_TIMER, BlendTimer );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_BLEND_TOTAL, BlendTotal );
- csave.End_Chunk();
- return true;
- }
- bool BlendableAnimChannelClass::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_NEW:
- NewChannel.Load( cload );
- break;
-
- case CHUNKID_OLD:
- OldChannel.Load( cload );
- break;
-
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_BLEND_TIMER, BlendTimer );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_BLEND_TOTAL, BlendTotal );
- default:
- Debug_Say(( "Unrecognized BlendableAnimChannel Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- Debug_Say(( "Unrecognized BlendableAnimChannel chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- void BlendableAnimChannelClass::Set_Animation( const char *name, float blendtime, float start_frame )
- {
- // if setting to our current anim, bail
- if ( ( NewChannel.Peek_Animation() == NULL ) && ( name == NULL ) ) {
- return;
- }
- if ( ( NewChannel.Peek_Animation() != NULL ) && ( name != NULL ) ) {
- if ( stricmp( NewChannel.Peek_Animation()->Get_Name(), name ) == 0 ) {
- return;
- }
- }
- // if no current channel, or no blend, or no new name, don't blend
- if ( (NewChannel.Peek_Animation() == NULL) || (blendtime == 0) || (name == NULL) ) {
- BlendTotal = 0.0f;
- BlendTimer = 0.0f;
- } else if ( BlendTotal == 0.0 ) { //if not currently blending
- OldChannel = NewChannel;
- BlendTimer = 0.0f;
- BlendTotal = blendtime;
- #if 0
- } else if ( OldChannel.Peek_Animation() == new_anim.Peek_Animation() ) { // if old anim is the new one
- OldChannel.Copy_From( NewChannel );
- BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
- BlendTotal = blendtime;
- #endif
- } else if ( (BlendTimer / BlendTotal) > 0.5 ) { // if more than halfway through the old blend
- OldChannel = NewChannel;
- BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
- BlendTotal = blendtime;
- } else {
- BlendTimer = (BlendTimer / BlendTotal) * blendtime;
- BlendTotal = blendtime;
- }
- NewChannel.Set_Animation( name );
- if ( NewChannel.Peek_Animation() != NULL ) {
- NewChannel.Set_Frame( start_frame );
- }
- if ( name == NULL ) {
- OldChannel.Set_Animation( (const char *)NULL );
- }
- }
- void BlendableAnimChannelClass::Set_Animation( const HAnimClass * anim, float blendtime, float start_frame )
- {
- // if setting to our current anim, bail
- if ( ( NewChannel.Peek_Animation() == NULL ) && ( anim == NULL ) ) {
- return;
- }
- if ( ( NewChannel.Peek_Animation() != NULL ) && ( anim != NULL ) ) {
- if ( NewChannel.Peek_Animation() == anim ) {
- return;
- }
- }
- // if no current channel, or no blend, or no new name, don't blend
- if ( (NewChannel.Peek_Animation() == NULL) || (blendtime == 0) || (anim == NULL) ) {
- BlendTotal = 0.0f;
- BlendTimer = 0.0f;
- } else if ( BlendTotal == 0.0 ) { //if not currently blending
- OldChannel = NewChannel;
- BlendTimer = 0.0f;
- BlendTotal = blendtime;
- #if 0
- } else if ( OldChannel.Peek_Animation() == new_anim.Peek_Animation() ) { // if old anim is the new one
- OldChannel.Copy_From( NewChannel );
- BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
- BlendTotal = blendtime;
- #endif
- } else if ( (BlendTimer / BlendTotal) > 0.5 ) { // if more than halfway through the old blend
- OldChannel = NewChannel;
- BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
- BlendTotal = blendtime;
- } else {
- BlendTimer = (BlendTimer / BlendTotal) * blendtime;
- BlendTotal = blendtime;
- }
- NewChannel.Set_Animation( anim );
- if ( NewChannel.Peek_Animation() != NULL ) {
- NewChannel.Set_Frame( start_frame );
- }
- if ( anim == NULL ) {
- OldChannel.Set_Animation( (const HAnimClass *)NULL );
- }
- }
- void BlendableAnimChannelClass::Update( float dtime )
- {
- if ( BlendTotal != 0.0f ) { // if blending between two animations
- BlendTimer += dtime; // Bump blend timer forward
- if ( BlendTimer >= BlendTotal ) // blend complete, remove oldanim
- {
- BlendTotal = 0.0f;
- BlendTimer = 0.0f;
- OldChannel.Set_Animation( (const char *)NULL );
- }
- }
- // Calculate which frame we are on in each of the animations
- NewChannel.Update( dtime );
- OldChannel.Update( dtime );
- }
- void BlendableAnimChannelClass::Get_Animation_Data( AnimationDataList & list, float weight )
- {
- float blend_ratio = 1.0f; // assume no blending
- if ( BlendTotal != 0.0f ) { // if blending between two animations
- // Calculate the blend percentage between the two animations.
- // This starts at 0.0 (all OldAnimation) and proceeds to 1.0 (all Animation)
- blend_ratio = WWMath::Clamp( BlendTimer / BlendTotal, 0, 1 );
- }
- NewChannel.Get_Animation_Data( list, weight * blend_ratio );
- OldChannel.Get_Animation_Data( list, weight * ( 1 - blend_ratio ) );
- }
- void BlendableAnimChannelClass::Update_Model( RenderObjClass *anim_model )
- {
- float blend_ratio = 1.0f; // assume no blending
- if ( BlendTotal != 0.0f ) { // if blending between two animations
- // Calculate the blend percentage between the two animations.
- // This starts at 0.0 (all OldAnimation) and proceeds to 1.0 (all Animation)
- blend_ratio = WWMath::Clamp( BlendTimer / BlendTotal, 0, 1 );
- }
- if ( OldChannel.Peek_Animation() ) {
- anim_model->Set_Animation( OldChannel.Peek_Animation(), OldChannel.Get_Frame(),
- NewChannel.Peek_Animation(), NewChannel.Get_Frame(),
- blend_ratio );
- } else if ( NewChannel.Peek_Animation() ) {
- anim_model->Set_Animation( NewChannel.Peek_Animation(), NewChannel.Get_Frame() );
- } else {
- anim_model->Set_Animation();
- }
- }
- /*
- ** AnimControlClass
- */
- AnimControlClass::AnimControlClass( void ) :
- Model( NULL )
- {
- }
- AnimControlClass::~AnimControlClass( void )
- {
- REF_PTR_RELEASE( Model );
- }
- bool AnimControlClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_MODEL_PTR, Model );
- csave.End_Chunk();
- return true;
- }
- bool AnimControlClass::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_VARIABLES:
- WWASSERT( Model == NULL );
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_MODEL_PTR, Model );
- default:
- Debug_Say(( "Unrecognized AnimControl Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- if ( Model != NULL ) {
- REQUEST_REF_COUNTED_POINTER_REMAP( (RefCountClass **)&Model );
- } else {
- Debug_Say(( "Loaded NULL model\n" ));
- }
- break;
- default:
- Debug_Say(( "Unrecognized AnimControl chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- void AnimControlClass::Set_Model( RenderObjClass *anim_model )
- {
- REF_PTR_SET( Model, anim_model );
- }
- /*
- ** SimpleAnimControlClass
- */
- SimpleAnimControlClass::SimpleAnimControlClass( void )
- {
- }
- SimpleAnimControlClass::~SimpleAnimControlClass( void )
- {
- }
- bool SimpleAnimControlClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_PARENT );
- AnimControlClass::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_CHANNEL );
- Channel.Save( csave );
- csave.End_Chunk();
- return true;
- }
- bool SimpleAnimControlClass::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_PARENT:
- AnimControlClass::Load( cload );
- break;
-
- case CHUNKID_CHANNEL:
- Channel.Load( cload );
- break;
-
- default:
- Debug_Say(( "Unrecognized HumanAnimControl chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- void SimpleAnimControlClass::Set_Animation( const char *name, float blendtime, float start_frame )
- {
- Channel.Set_Animation( name, blendtime, start_frame );
- }
- void SimpleAnimControlClass::Set_Animation( const HAnimClass * anim, float blendtime, float start_frame )
- {
- Channel.Set_Animation( anim, blendtime, start_frame );
- }
- void SimpleAnimControlClass::Update( float dtime )
- {
- Channel.Update( dtime );
- // Setup the model for the current frame(s)
- assert( Model != NULL );
- Channel.Update_Model( Model );
- }
- /*
- ** HumanAnimControlClass
- */
- HumanAnimControlClass::HumanAnimControlClass( void ) :
- AnimCombo( 2 ),
- Channel2Ratio( 0 ),
- Skeleton( 'A' ),
- AnimSpeedScale( 1 )
- {
- }
- HumanAnimControlClass::~HumanAnimControlClass( void )
- {
- }
- bool HumanAnimControlClass::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_PARENT );
- AnimControlClass::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CHANNEL2_RATIO, Channel2Ratio );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SKELETON, Skeleton );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_CHANNEL1 );
- Channel1.Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_CHANNEL2 );
- Channel2.Save( csave );
- csave.End_Chunk();
- // Don't need to save the animcombo
- return true;
- }
- bool HumanAnimControlClass::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_PARENT:
- AnimControlClass::Load( cload );
- break;
-
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_CHANNEL2_RATIO, Channel2Ratio );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_SKELETON, Skeleton );
- default:
- Debug_Say(( "Unrecognized HumanAnimControl Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- case CHUNKID_CHANNEL1:
- Channel1.Load( cload );
- break;
-
- case CHUNKID_CHANNEL2:
- Channel2.Load( cload );
- break;
-
- default:
- Debug_Say(( "Unrecognized HumanAnimControl chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- void HumanAnimControlClass::Build_Skeleton_Anim_Name( StringClass& new_name, const char * name )
- {
- if (name == NULL) return;
- if (*name == NULL) {
- Debug_Say(( "No name in Build_Skeleton_Anim_Name\n" ));
- return;
- }
- new_name = name;
- if ( Skeleton == 'V' ) { // Special case for visceroids
- return;
- }
- // If the anim doesn't start with "S_A_HUMAN.", add it
- if ( ::strnicmp( name, "S_", 2 ) != 0 ) {
- new_name.Format( "S_%c_HUMAN.%s", Skeleton, name );
- }
- // If the anim name is "S_A_HUMAN.H_A_*", and the Skeleton is not 'A', use
- // the other skeleton anim, if found
- if ( new_name.Get_Length() > 14 && Skeleton != 'A' && ::strnicmp( new_name, "S_A_HUMAN.H_A_", 14 ) == 0 ) {
- StringClass mod_name(new_name,true);
- mod_name[2] = Skeleton;
- mod_name[12] = Skeleton;
- // can we find the anim name?
- HAnimClass * anim = WW3DAssetManager::Get_Instance()->Get_HAnim( mod_name );
- if ( anim != NULL ) {
- anim->Release_Ref();
- new_name=mod_name;
- }
- }
- }
- void HumanAnimControlClass::Set_Animation( const char *name, float blendtime, float start_frame )
- {
- StringClass new_name(0,true);
- Build_Skeleton_Anim_Name( new_name, name );
- Channel1.Set_Animation( new_name, blendtime, start_frame );
- Channel2.Set_Animation( (const char *)NULL );
- Channel2Ratio = 0;
- }
- void HumanAnimControlClass::Set_Animation( const HAnimClass * anim, float blendtime, float start_frame )
- {
- if ( anim != NULL ) {
- Set_Animation( anim->Get_Name(), blendtime, start_frame );
- } else {
- Set_Animation( (const char *)NULL, blendtime, start_frame );
- }
- }
- void HumanAnimControlClass::Set_Animation( const char *name1, const char * name2, float ratio, float blendtime )
- {
- StringClass new_name1(0,true);
- Build_Skeleton_Anim_Name( new_name1, name1 );
- StringClass new_name2(0,true);
- Build_Skeleton_Anim_Name( new_name2, name2 );
- if ( ratio == 0 ) {
- Set_Animation( new_name1, blendtime );
- return;
- }
- if ( Channel2Ratio == 0 ) {
- Channel2 = Channel1;
- }
- Channel1.Set_Animation( new_name1, blendtime );
- Channel2.Set_Animation( new_name2, blendtime );
- Channel2Ratio = ratio;
- }
- void HumanAnimControlClass::Set_Mode( AnimMode mode, float frame )
- {
- Channel1.Set_Mode( mode, frame );
- Channel2.Set_Mode( mode, frame );
- }
- void HumanAnimControlClass::Set_Model( RenderObjClass *anim_model )
- {
- AnimControlClass::Set_Model( anim_model );
- // Update the skeleton
- if( anim_model != NULL ) {
- const HTreeClass * tree = anim_model->Get_HTree();
- if ( tree != NULL ) {
- const char * name = tree->Get_Name();
- Skeleton = name[2];
- }
- }
- }
- /*
- **
- */
- StringClass _MonitorAnimDescription;
- HumanAnimControlClass * _Monitor = NULL;
- void HumanAnimControlClass::Update( float dtime )
- {
- // Update channels
- Channel1.Update( dtime * AnimSpeedScale );
- Channel2.Update( dtime * AnimSpeedScale );
- if ( Model != NULL ) {
- // Get Animation data
- DataList.Reset_Active();
- Channel1.Get_Animation_Data( DataList, (1 - Channel2Ratio) );
- Channel2.Get_Animation_Data( DataList, Channel2Ratio );
- // Use the cheapest anim method possible
- int total_animations = DataList.Count();
- if ( total_animations == 0 ) {
- // Debug_Say(( "No animations to display!\n" ));
- Model->Set_Animation();
- } else if ( total_animations == 1 ) {
- // Debug_Say(( "1 animation to display!\n" ));
- Model->Set_Animation( DataList[0].Animation, DataList[0].Frame );
- } else if ( total_animations == 2 ) {
- // Debug_Say(( "2 animation to display!\n" ));
- float percent = DataList[1].Weight / (DataList[0].Weight + DataList[1].Weight);
- Model->Set_Animation( DataList[0].Animation, DataList[0].Frame,
- DataList[1].Animation, DataList[1].Frame, percent );
- } else {
- // Debug_Say(( ">2 animation to display!\n" ));
- // set up anim combo
- AnimCombo.Reset();
- for ( int i = 0; i < total_animations; i++ ) {
- HAnimComboDataClass * anim_data = new HAnimComboDataClass();
- anim_data->Set_HAnim( DataList[i].Animation );
- anim_data->Set_Frame( DataList[i].Frame );
- anim_data->Set_Weight( DataList[i].Weight );
- AnimCombo.Append_Anim_Combo_Data( anim_data );
- }
- // Setup the model for the current frame(s)
- Model->Set_Animation( &AnimCombo );
- }
- if ( _Monitor == this ) {
- for ( int i = 0; i < total_animations; i++ ) {
- if ( i == 0 ) {
- _MonitorAnimDescription = "";
- }
- StringClass a(0,true);
- a.Format( "%s %1.0f%% %1.0f\n", DataList[i].Animation->Get_Name()+10, DataList[i].Weight*100, DataList[i].Frame );
- _MonitorAnimDescription += a;
- }
- }
- }
- }
- /*
- **
- */
- void HumanAnimControlClass::Get_Information( StringClass & string )
- {
- _Monitor = this;
- string += _MonitorAnimDescription;
- }
|