/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, 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 . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #ifndef hsTimedValue_inc #define hsTimedValue_inc #include "hsStream.h" template class hsTimedValue { public: enum { kIdle = 0x1, kInstant = 0x2 }; protected: UInt32 fFlags; hsScalar fDuration; hsScalar fStartTime; T fValue; T fGoal; T fFrom; public: hsTimedValue() : fFlags(kIdle|kInstant), fDuration(0) {} hsTimedValue(const T& v) : fFlags(kIdle|kInstant), fDuration(0) { SetValue(v); } UInt32 GetFlags() { return fFlags; } void SetDuration(hsScalar duration); hsScalar GetDuration() const { return fDuration; } hsBool32 operator==(const hsTimedValue& v); hsTimedValue& operator=(const T& v) { SetValue(v); return *this; } hsTimedValue& operator+=(const T& v) { SetValue(v + fValue); return *this; } void SetTempValue(const T& v) { fValue = v; } void SetValue(const T& v) { fFrom = fGoal = fValue = v; fFlags |= kIdle; } const T& GetValue() const { return fValue; } void SetGoal(const T& g) { fGoal = g; } const T& GetGoal() const { return fGoal; } void Reset() { fFlags |= (kIdle | kInstant); } void StartClock(hsScalar s); hsScalar GetStartTime() const { return fStartTime; } const T& GetFrom() const { return fFrom; } void Update(hsScalar s); void WriteScalar(hsStream* s, hsScalar currSecs); void Write(hsStream* s, hsScalar currSecs); void ReadScalar(hsStream* s, hsScalar currSecs); void Read(hsStream* s, hsScalar currSecs); }; template void hsTimedValue::WriteScalar(hsStream* s, hsScalar currSecs) { s->WriteSwap32(fFlags); s->WriteSwapScalar(fValue); if( !(fFlags & kIdle) ) { s->WriteSwapScalar(fDuration); s->WriteSwapScalar(currSecs - fStartTime); s->WriteSwapScalar(fGoal); s->WriteSwapScalar(fFrom); } } template void hsTimedValue::Write(hsStream* s, hsScalar currSecs) { s->WriteSwap32(fFlags); fValue.Write(s); if( !(fFlags & kIdle) ) { s->WriteSwapScalar(fDuration); s->WriteSwapScalar(currSecs - fStartTime); fGoal.Write(s); fFrom.Write(s); } } template void hsTimedValue::ReadScalar(hsStream* s, hsScalar currSecs) { fFlags = s->ReadSwap32(); fValue = s->ReadSwapScalar(); if( !(fFlags & kIdle) ) { fDuration = s->ReadSwapScalar(); fStartTime = currSecs - s->ReadSwapScalar(); fGoal = s->ReadSwapScalar(); fFrom = s->ReadSwapScalar(); } } template void hsTimedValue::Read(hsStream* s, hsScalar currSecs) { fFlags = s->ReadSwap32(); fValue.Read(s); if( !(fFlags & kIdle) ) { fDuration = s->ReadSwapScalar(); fStartTime = currSecs - s->ReadSwapScalar(); fGoal.Read(s); fFrom.Read(s); } } template void hsTimedValue::SetDuration(hsScalar duration) { fDuration = duration; if( fDuration > 0 ) fFlags &= ~kInstant; else fFlags |= kInstant; } template hsBool32 hsTimedValue::operator==(const hsTimedValue& v) { if ((fFlags == v.fFlags) && (fDuration == v.fDuration) && (fStartTime == v.fStartTime) && (fValue == v.fValue) && (fGoal == v.fGoal) && (fFrom == v.fFrom)) { return true; } return false; } template void hsTimedValue::StartClock(hsScalar s) { fStartTime = s; if( fFlags & kInstant ) { fFlags |= kIdle; fValue = fGoal; return; } fFlags &= ~kIdle; if( fValue == fGoal ) fFlags |= kIdle; fFrom = fValue; } template void hsTimedValue::Update(hsScalar s) { if( fFlags & kIdle ) return; hsAssert(fDuration > 0, "Instant should always be idle"); hsScalar interp = (s - fStartTime) / fDuration; if( interp >= hsScalar1 ) { fValue = fGoal; interp = hsScalar1; fFlags |= kIdle; } else fValue = fFrom + (fGoal - fFrom) * interp; } #endif // hsTimedValue_inc