//===========================================================================// // File: AnimIterator.hpp // Project: MechWarrior 4 // Contents: // This defines the iterator classes for animation. The iterators // can walk keyframes forward and backward by an absolute or relitive // frame, percent, or time. Got it? //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 07/01/98 JSE Initial coding, //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive, Inc. // All Rights reserved worldwide // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //===========================================================================// #pragma once namespace MW4Animation { class AnimIterator; } #include #include namespace MW4Animation { //############################################################################# //####################### AnimIterator ######################### //############################################################################# class AnimIterator : public Stuff::Plug { private: Stuff::Scalar currentTime; Stuff::Scalar velocityScale; AnimData *animationData; BYTE *nextFrame; Stuff::Scalar blendValue; bool skipChannels; public: AnimInstance *animationInstance; enum{ MaxKeyFrame=255 }; public: // note: you must reset the animation to the start // or end before animating. AnimIterator(AnimInstance *animation_instance); ~AnimIterator(); //skips everything but velocity! void SkipChannels() { //skipChannels = true; } void DontSkipChannels() { //skipChannels = false; } bool DoISkipChannels() { return skipChannels; } void SetVelocityScale(Stuff::Scalar vel_scale) { velocityScale = vel_scale; } Stuff::Scalar GetVelocityScale() { return velocityScale; } Stuff::Scalar GetBlendValue() { return blendValue; } void SetBlendValue(Stuff::Scalar blend_value) { Verify(blend_value >= 0); blendValue = blend_value; } AnimData* GetAnimData() { return animationData; } //---------------------------------------- // Convert to and from absolute channels //---------------------------------------- int ToAbsoluteChannel( BYTE joint_number, BYTE channel_number ); void FromAbsoluteChannel( int absolute_Channel, BYTE& joint_number, BYTE& channel_number ); //------------------------------ // Get counts if you need them //------------------------------ BYTE GetJointCount(); BYTE GetJointChannelCount(BYTE joint_number); int GetAnimChannelCount(); int GetKeyFrameCount(int absolute_channel_number); //------------------------------ // Get frames and indexes. //------------------------------ // -1 means that there are no more keyframes in that direction int GetForwardFrameIndex(int absolute_channel_number); int GetReverseFrameIndex(int absolute_channel_number); // NULL means that there are no more keyframes in that direction BaseKeyframe * GetForwardKeyFrame(int absolute_channel_number); BaseKeyframe * GetReverseKeyFrame(int absolute_channel_number); // If there is only one keyframe these will return the same keyframe BaseKeyframe * GetFirstKeyFrame(int absolute_channel_number); BaseKeyframe * GetLastKeyFrame(int absolute_channel_number); // A little diffrent from getfirst, this gets the keyframe at the start position // if a keyframe is out of range ( less than or greater than the time span of the // animation, than this will find the first real keyframe. // If there is only one keyframe these will return the same keyframe BaseKeyframe * GetStartKeyFrame(int absolute_channel_number); BaseKeyframe * GetStopKeyFrame(int absolute_channel_number); // NULL means that there is no such keyframe BaseKeyframe * GetKeyFrame(int absolute_channel_number, int index); // NULL means that there are no more keyframes in that direction BaseKeyframeTime * GetForwardKeyFrameTime(int absolute_channel_number); BaseKeyframeTime * GetReverseKeyFrameTime(int absolute_channel_number); // If there is only one keyframe these will return the same keyframe BaseKeyframeTime * GetFirstKeyFrameTime(int absolute_channel_number); BaseKeyframeTime * GetLastKeyFrameTime(int absolute_channel_number); // A little diffrent from getfirst, this gets the keyframe at the start position // if a keyframe is out of range ( less than or greater than the time span of the // animation, than this will find the first real keyframe. // If there is only one keyframe these will return the same keyframe BaseKeyframeTime * GetStartKeyFrameTime(int absolute_channel_number); BaseKeyframeTime * GetStopKeyFrameTime(int absolute_channel_number); // NULL means that there is no such keyframe BaseKeyframeTime * GetKeyFrameTime(int absolute_channel_number, int index); //----------------------------------------------------------------------- // Reset start makes the animation snap to start, end goes to the end // use this instead of settime if you want to go the beginning // it's cheaper. //----------------------------------------------------------------------- void ResetStart(); void ResetEnd(); // all of the frame methods down here treat frame 0 as the frame // at starttime, not keyframe index 0, like above. a frame down // here is more of an intangeble thing. // time down here is also reletive to startTime // // percents are 1.0 > 0 // Carryover functions // these are the "smart" functions, they figure out back or forward. Stuff::Scalar GetCarryOverTime(); int GetCarryOverFrame(int frames_per_second); Stuff::Scalar GetCarryOverPosition(); // forward carryovers Stuff::Scalar GetCarryOverTimeForward(); int GetCarryOverFrameForward(int frames_per_second); Stuff::Scalar GetCarryOverPositionForward(); // reverse carryovers Stuff::Scalar GetCarryOverTimeReverse(); int GetCarryOverFrameReverse(int frames_per_second); Stuff::Scalar GetCarryOverPositionReverse(); Stuff::Scalar GetRealTime() { return currentTime; } //------------------------------ // Absolute Settings, adjusted though, so time at the start // of an anim is 0 //------------------------------ void SetTime(Stuff::Scalar time); Stuff::Scalar GetTime(); void SetFrame(int frame, int frames_per_second); int GetFrame(int frames_per_second); void SetPosition(Stuff::Scalar percentage_of_animation); Stuff::Scalar GetPosition(); //------------------------------ // Relative Settings //------------------------------ // The Move commands check to see if the number is going forward or backward // the increment/decrement commands assume the command is in the correct direction bool MoveTime(Stuff::Scalar time_slice); bool MoveFrame(int frame_count, int frames_per_second); bool MovePosition(Stuff::Scalar percent); // Don't pass zeros to increment/decrement functions or I'll kick your ass!!! bool IncrementTime(Stuff::Scalar time_slice); bool DecrementTime(Stuff::Scalar time_slice); bool IncrementFrame(int frame_count, int frames_per_second); bool DecrementFrame(int frame_count, int frames_per_second); bool IncrementPosition(Stuff::Scalar percent); bool DecrementPosition(Stuff::Scalar percent); BaseKeyframe * GetKeyFrameAtTime(int absolute_channel_number, Stuff::Scalar time); BaseKeyframe * GetKeyFrameAtFrame(int absolute_channel_number, int frame, int frames_per_second); BaseKeyframe * GetKeyFrameAtPosition(int absolute_channel_number, Stuff::Scalar percentage_of_animation); BaseKeyframeTime * GetKeyFrameTimeAtTime(int absolute_channel_number, Stuff::Scalar time); BaseKeyframeTime * GetKeyFrameTimeAtFrame(int absolute_channel_number, int frame, int frames_per_second); BaseKeyframeTime * GetKeyFrameTimeAtPosition(int absolute_channel_number, Stuff::Scalar percentage_of_animation); public: void TestInstance() const {} static bool TestClass() {return true;} }; // Inlines // //############################################################################# //############################################################################# // inline BYTE AnimIterator::GetJointCount() { Check_Pointer(animationData); return animationData->GetJointCount(); } // //############################################################################# //############################################################################# // inline BYTE AnimIterator::GetJointChannelCount(BYTE joint_number) { Verify(joint_number < animationData->GetJointCount()); return animationData->animJointBlock[joint_number].channelsUsed; } // //############################################################################# //############################################################################# // inline int AnimIterator::GetAnimChannelCount() { Check_Pointer(animationData); return animationData->GetChannelCount(); } // //############################################################################# //############################################################################# // inline int AnimIterator::GetKeyFrameCount(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); return animationData->animChannelBlock[absolute_channel_number].keyframeCount; } // //############################################################################# //############################################################################# // inline Stuff::Scalar AnimIterator::GetTime() { return currentTime -= animationData->animHeaderBlock->startTime; } // //############################################################################# //############################################################################# // inline void AnimIterator::SetFrame(int frame, int frames_per_second) { Verify(frames_per_second > 0); SetTime((Stuff::Scalar)frame / frames_per_second); } // //############################################################################# //############################################################################# // inline int AnimIterator::GetFrame(int frames_per_second) { Verify(frames_per_second > 0); return (int)(GetTime()*frames_per_second); } // //############################################################################# //############################################################################# // inline void AnimIterator::SetPosition(Stuff::Scalar percentage_of_animation) { if (percentage_of_animation == 0.0f) { ResetStart(); return; } Verify(percentage_of_animation > 0.0f); Verify(percentage_of_animation <= 1.0f); SetTime( Stuff::Lerp( 0.0f, animationData->animHeaderBlock->endTime-animationData->animHeaderBlock->startTime, percentage_of_animation ) ); } // //############################################################################# //############################################################################# // inline Stuff::Scalar AnimIterator::GetPosition() { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar percent = (currentTime-animationData->animHeaderBlock->startTime) / (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime); Verify(percent >= 0.0f); Verify(percent <= 1.0f); return percent; } // //############################################################################# //############################################################################# // inline bool AnimIterator::MoveFrame(int frame_count, int frames_per_second) { Verify(frame_count != 0); Verify(frames_per_second > 0); return MoveTime((Stuff::Scalar)frame_count / frames_per_second); } // //############################################################################# //############################################################################# // inline bool AnimIterator::MovePosition(Stuff::Scalar percent) { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar time = (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) * percent; Verify(time > 0.0f); Verify(time <= 1.0f); return MoveTime(time); } // //############################################################################# //############################################################################# // inline bool AnimIterator::IncrementFrame(int frame_count, int frames_per_second) { Verify(frame_count != 0); Verify(frames_per_second > 0); return IncrementTime((Stuff::Scalar)frame_count / frames_per_second); } // //############################################################################# //############################################################################# // inline bool AnimIterator::DecrementFrame(int frame_count, int frames_per_second) { Verify(frame_count != 0); Verify(frames_per_second > 0); return DecrementTime((Stuff::Scalar)frame_count / frames_per_second); } // //############################################################################# //############################################################################# // inline bool AnimIterator::IncrementPosition(Stuff::Scalar percent) { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar time = (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) * percent; //Verify(time > 0.0f); //Verify(time <= 1.0f); return IncrementTime(time); } // //############################################################################# //############################################################################# // inline bool AnimIterator::DecrementPosition(Stuff::Scalar percent) { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar time = (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) * percent; //Verify(time > 0.0f); //Verify(time <= 1.0f); return DecrementTime(time); } // //############################################################################# //############################################################################# // inline BaseKeyframe * AnimIterator::GetKeyFrameAtFrame(int absolute_channel_number, int frame, int frames_per_second) { Verify(frames_per_second > 0); return GetKeyFrameAtTime(absolute_channel_number, (Stuff::Scalar)frame / frames_per_second); } // //############################################################################# //############################################################################# // inline BaseKeyframe * AnimIterator::GetKeyFrameAtPosition(int absolute_channel_number, Stuff::Scalar percentage_of_animation) { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar time = (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) * percentage_of_animation; Verify(time > 0.0f); Verify(time <= 1.0f); return GetKeyFrameAtTime(absolute_channel_number, time); } // //############################################################################# //############################################################################# // inline BaseKeyframeTime * AnimIterator::GetKeyFrameTimeAtFrame(int absolute_channel_number, int frame, int frames_per_second) { Verify(frames_per_second > 0); return GetKeyFrameTimeAtTime(absolute_channel_number, (Stuff::Scalar)frame / frames_per_second); } // //############################################################################# //############################################################################# // inline BaseKeyframeTime * AnimIterator::GetKeyFrameTimeAtPosition(int absolute_channel_number, Stuff::Scalar percentage_of_animation) { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar time = (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) * percentage_of_animation; Verify(time > 0.0f); Verify(time <= 1.0f); return GetKeyFrameTimeAtTime(absolute_channel_number, time); } }