#pragma once #include #define Clamp(x, min, max) x = (x struct CTimeEvent { typedef T value_type; float m_fTime; T m_Value; }; template bool operator<(const CTimeEvent& lhs, const CTimeEvent& rhs) { return lhs.m_fTime < rhs.m_fTime; } template bool operator<(const CTimeEvent& lhs, const float& rhs) { return lhs.m_fTime < rhs; } template bool operator<(const float& lhs, const CTimeEvent& rhs) { return lhs < rhs.m_fTime; } typedef struct SEffectPosition : public CTimeEvent { // For Bezier Curve int m_iMovingType; D3DXVECTOR3 m_vecControlPoint; } TEffectPosition; #define AG_MASK 0xff00ff00 #define RB_MASK 0x00ff00ff struct DWORDCOLOR { DWORD m_dwColor; DWORDCOLOR() { } DWORDCOLOR(const DWORDCOLOR& r) : m_dwColor(r.m_dwColor) { } DWORDCOLOR(DWORD dwColor) : m_dwColor(dwColor) { } DWORDCOLOR& operator = (const DWORDCOLOR& r) { m_dwColor = r.m_dwColor; return *this; } DWORDCOLOR& operator *= (float f) { DWORD idx = DWORD(f * 256); m_dwColor = (((DWORD)(((m_dwColor & AG_MASK) >> 8) * idx)) & AG_MASK) + ((DWORD)(((m_dwColor & RB_MASK) * idx) >> 8) & RB_MASK); return *this; } DWORDCOLOR& operator += (const DWORDCOLOR& r) { m_dwColor += r.m_dwColor; return *this; } operator DWORD() { return m_dwColor; } }; #undef AG_MASK #undef RB_MASK inline DWORDCOLOR operator * (DWORDCOLOR dc, float f) { DWORDCOLOR tmp(dc); tmp *= f; return tmp; } inline DWORDCOLOR operator * (float f, DWORDCOLOR dc) { DWORDCOLOR tmp(dc); tmp *= f; return tmp; } typedef CTimeEvent TTimeEventTypeCharacter; typedef CTimeEvent TTimeEventTypeShort; typedef CTimeEvent TTimeEventTypeFloat; typedef CTimeEvent TTimeEventTypeWord; typedef CTimeEvent TTimeEventTypeDoubleWord; typedef CTimeEvent TTimeEventTypeColor; typedef CTimeEvent TTimeEventTypeVector2; typedef CTimeEvent TTimeEventTypeVector3; typedef std::vector TTimeEventTable; typedef std::vector TTimeEventTablePosition; typedef std::vector TTimeEventTableCharacter; typedef std::vector TTimeEventTableShort; typedef std::vector TTimeEventTableFloat; typedef std::vector TTimeEventTableWord; typedef std::vector TTimeEventTableDoubleWord; typedef std::vector TTimeEventTableColor; typedef std::vector TTimeEventTableVector2; typedef std::vector TTimeEventTableVector3; template T BlendSingleValue(float time, const CTimeEvent& low, const CTimeEvent& high) { const float timeDiff = high.m_fTime - low.m_fTime; const float perc = (time - low.m_fTime) / timeDiff; const T valueDiff = high.m_Value - low.m_Value; return static_cast(low.m_Value + perc * valueDiff); } inline D3DXVECTOR3 BlendSingleValue(float time, const TEffectPosition& low, const TEffectPosition& high) { const float timeDiff = high.m_fTime - low.m_fTime; const float perc = (time - low.m_fTime) / timeDiff; if (low.m_iMovingType == MOVING_TYPE_DIRECT) return low.m_Value + ((high.m_Value - low.m_Value) * perc); if (low.m_iMovingType == MOVING_TYPE_BEZIER_CURVE) { const float invPerc = 1.0f - perc; return low.m_Value * invPerc * invPerc + (low.m_Value + low.m_vecControlPoint) * invPerc * perc * 2.0f + high.m_Value * perc * perc; } // Unknown moving type - impossible(?) return D3DXVECTOR3(); } inline DWORDCOLOR BlendSingleValue(float time, const TTimeEventTypeColor& low, const TTimeEventTypeColor& high) { const float timeDiff = high.m_fTime - low.m_fTime; const float perc = (time - low.m_fTime) / timeDiff; return low.m_Value * (1.0f - perc) + high.m_Value * perc; } template auto GetTimeEventBlendValue(float time, const std::vector& vec) -> typename T::value_type { if (vec.empty()) return typename T::value_type(); // Single element is easy... if (vec.begin() + 1 == vec.end()) return vec.front().m_Value; // All elements are greater than |time| - pick the smallest if (time < vec.front().m_fTime) return vec.front().m_Value; // All elements are smaller than |time| - pick the greatest if (time > vec.back().m_fTime) return vec.back().m_Value; // The two checks above make sure that result doesn't contain vec.end() // (We could simply check for vec.end() ourself, but above code lets us // skip std::equal_range() altogether, making it faster.) auto result = std::equal_range(vec.begin(), vec.end(), time); // We have one or more equal elements - pick the first if (result.first != result.second) return result.first->m_Value; // We need first to point to an element smaller than |time| // (Note that decrementing first is safe here, we already accounted for // vec.begin() being greater-or-equal to |time|.) --result.first; return BlendSingleValue(time, *result.first, *result.second); } extern BOOL GetTokenTimeEventFloat(CTextFileLoader & rTextFileLoader, const char * c_szKey, TTimeEventTableFloat * pTimeEventTableFloat); //extern void InsertItemTimeEventFloat(TTimeEventTableFloat * pTable, float fTime, float fValue); template void InsertItemTimeEvent(std::vector >* pTable, float fTime, T fValue) { typedef std::vector >::iterator iterator; iterator itor = std::lower_bound(pTable->begin(), pTable->end(), fTime); CTimeEvent TimeEvent; TimeEvent.m_fTime = fTime; TimeEvent.m_Value = fValue; pTable->insert(itor, TimeEvent); }