diff --git a/source/graphics/CinemaTrack.cpp b/source/graphics/CinemaTrack.cpp index e49fc288de..8cad863592 100644 --- a/source/graphics/CinemaTrack.cpp +++ b/source/graphics/CinemaTrack.cpp @@ -15,86 +15,95 @@ #include "lib/res/mem.h" CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline) -: CCinemaData(data), TNSpline(spline) +: CCinemaData(data), TNSpline(spline), m_TimeElapsed(0.f) { DistStylePtr = &CCinemaPath::EaseDefault; DistModePtr = &CCinemaPath::EaseIn; } -void CCinemaPath::DrawSpline(CVector4D RGBA, int smoothness) +void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) const { - if (NodeCount < 3 || DistModePtr == NULL) + if (NodeCount < 2 || DistModePtr == NULL) return; + if ( NodeCount == 2 ) + smoothness = 2; + float start = MaxDistance / smoothness; - CVector3D tmp; float time=0; - + glColor4f( RGBA.m_X, RGBA.m_Y, RGBA.m_Z, RGBA.m_W ); - glLineWidth(2.0f); - glBegin(GL_LINE_STRIP); - for (int i=0; i*DistModePtr)(start*i / MaxDistance); - tmp = GetPosition(time); - glVertex3f( tmp.X, tmp.Y, tmp.Z ); - } - glEnd(); - glLineWidth(1.0f); + if ( lines ) + { + glLineWidth(1.8f); + glEnable(GL_LINE_SMOOTH); + glBegin(GL_LINE_STRIP); - glPointSize(6.0f); - //Draw spline endpoints - glBegin(GL_POINTS); - tmp = GetPosition(0); - glVertex3f( tmp.X, tmp.Y, tmp.Z ); - tmp = GetPosition(1); - glVertex3f( tmp.X, tmp.Y, tmp.Z ); - glEnd(); - glPointSize(1.0f); + for (int i=0; i*DistModePtr)(start*i / MaxDistance); + CVector3D tmp = GetPosition(time); + glVertex3f( tmp.X, tmp.Y, tmp.Z ); + } + glColor3f(1.0f, 1.0f, 0.0f); //yellow + + for ( size_t i=0; iGetView()->GetCamera(); t = (this->*DistModePtr)(t); CVector3D rot = startRotation + m_TotalRotation * t; - Cam->m_Orientation.SetXRotation(fmodf(rot.X, 360.0f)); - Cam->m_Orientation.RotateY(fmodf(rot.Y, 360.0f)); - Cam->m_Orientation.RotateZ(fmodf(rot.Z, 360.0f)); + Cam->m_Orientation.SetXRotation(fmodf(rot.X, DEGTORAD(360.0f)) ); + Cam->m_Orientation.RotateY( fmodf(rot.Y, DEGTORAD(360.0f)) ); + Cam->m_Orientation.RotateZ( fmodf(rot.Z, DEGTORAD(360.0f)) ); CVector3D pos = GetPosition(t); Cam->m_Orientation.Translate(pos); + Cam->UpdateFrustum(); } - -void CCinemaPath::ResetRotation(float t) -{ - CCamera *Cam=g_Game->GetView()->GetCamera(); - t = (this->*DistModePtr)(t); - CVector3D rot = m_TotalRotation * t; - - //rotate in reverse order and reverse angles - Cam->m_Orientation.RotateZ(-fmodf(rot.Z, 360)); - Cam->m_Orientation.RotateY(-fmodf(rot.Y, 360)); - Cam->m_Orientation.RotateX(-fmodf(rot.X, 360)); -} - - //Distortion mode functions -float CCinemaPath::EaseIn(float t) +float CCinemaPath::EaseIn(float t) const { return (this->*DistStylePtr)(t); } -float CCinemaPath::EaseOut(float t) +float CCinemaPath::EaseOut(float t) const { return 1.0f - EaseIn(1.0f-t); } -float CCinemaPath::EaseInOut(float t) +float CCinemaPath::EaseInOut(float t) const { if (t < m_Switch) return EaseIn(1.0f/m_Switch * t) * m_Switch; return EaseOut(1.0f/m_Switch * (t-m_Switch)) * m_Switch + m_Switch; } -float CCinemaPath::EaseOutIn(float t) +float CCinemaPath::EaseOutIn(float t) const { if (t < m_Switch) return EaseOut(1.0f/m_Switch * t) * m_Switch; @@ -103,22 +112,22 @@ float CCinemaPath::EaseOutIn(float t) //Distortion style functions -float CCinemaPath::EaseDefault(float t) +float CCinemaPath::EaseDefault(float t) const { return t; } -float CCinemaPath::EaseGrowth(float t) +float CCinemaPath::EaseGrowth(float t) const { return pow(t, m_Growth); } -float CCinemaPath::EaseExpo(float t) +float CCinemaPath::EaseExpo(float t) const { if(t == 0) return t; return powf(m_Growth, 10*(t-1.0f)); } -float CCinemaPath::EaseCircle(float t) +float CCinemaPath::EaseCircle(float t) const { t = -(sqrt(1.0f - t*t) - 1.0f); if(m_GrowthCount > 1.0f) @@ -129,7 +138,7 @@ float CCinemaPath::EaseCircle(float t) return t; } -float CCinemaPath::EaseSine(float t) +float CCinemaPath::EaseSine(float t) const { t = 1.0f - cos(t * PI/2); if(m_GrowthCount > 1.0f) @@ -140,10 +149,14 @@ float CCinemaPath::EaseSine(float t) return t; } - //-------CinemaTrack functions------ //AddPath-For building tracks from loaded file -void CCinemaTrack::AddPath(CCinemaData& data, TNSpline& spline) +CCinemaTrack::CCinemaTrack() : m_AbsoluteTime(0), m_Timescale(1), + m_TotalDuration(0) +{ + m_CPA = m_Paths.end(); +} +void CCinemaTrack::AddPath(const CCinemaData& data, const TNSpline& spline) { CCinemaPath path(data, spline); path.m_TimeElapsed=0; @@ -156,16 +169,16 @@ void CCinemaTrack::AddPath(CCinemaData& data, TNSpline& spline) //Set distortion mode and style switch(data.m_Mode) { - case EM_IN: + case CCinemaPath::EM_IN: SetTemp->DistModePtr = &CCinemaPath::EaseIn; break; - case EM_OUT: + case CCinemaPath::EM_OUT: SetTemp->DistModePtr = &CCinemaPath::EaseOut; break; - case EM_INOUT: + case CCinemaPath::EM_INOUT: SetTemp->DistModePtr = &CCinemaPath::EaseInOut; break; - case EM_OUTIN: + case CCinemaPath::EM_OUTIN: SetTemp->DistModePtr = &CCinemaPath::EaseOutIn; break; default: @@ -175,19 +188,19 @@ void CCinemaTrack::AddPath(CCinemaData& data, TNSpline& spline) switch (data.m_Style) { - case ES_DEFAULT: + case CCinemaPath::ES_DEFAULT: SetTemp->DistStylePtr = &CCinemaPath::EaseDefault; break; - case ES_GROWTH: + case CCinemaPath::ES_GROWTH: SetTemp->DistStylePtr = &CCinemaPath::EaseGrowth; break; - case ES_EXPO: + case CCinemaPath::ES_EXPO: SetTemp->DistStylePtr = &CCinemaPath::EaseExpo; break; - case ES_CIRCLE: + case CCinemaPath::ES_CIRCLE: SetTemp->DistStylePtr = &CCinemaPath::EaseCircle; break; - case ES_SINE: + case CCinemaPath::ES_SINE: SetTemp->DistStylePtr = &CCinemaPath::EaseSine; break; default: @@ -195,8 +208,16 @@ void CCinemaTrack::AddPath(CCinemaData& data, TNSpline& spline) break; } UpdateDuration(); - } +void CCinemaTrack::AddPath(const CCinemaPath& path) +{ + m_Paths.push_back(path); + m_Paths.back().BuildSpline(); + m_Paths.back().m_TimeElapsed = 0; + + UpdateDuration(); +} + void CCinemaTrack::UpdateDuration() { m_TotalDuration=0; @@ -257,6 +278,7 @@ bool CCinemaTrack::ValidateForward() { if (m_CPA == m_Paths.end() - 1) { + m_CPA->MoveToPointAt(1.f, CalculateRotation()); return false; } //Make sure it's within limits of path @@ -281,7 +303,7 @@ bool CCinemaTrack::ValidateForward() } else { - m_CPA->m_TimeElapsed+=Pos; + m_CPA->m_TimeElapsed = Pos; break; } } @@ -289,46 +311,31 @@ bool CCinemaTrack::ValidateForward() } return true; } +CVector3D CCinemaTrack::CalculateRotation() +{ + if ( m_CPA == m_Paths.begin() ) + return m_StartRotation; + CVector3D startRotation(0.f, 0.f, 0.f); + for ( std::vector::iterator it=m_Paths.begin(); it!=m_CPA; ++it ) + startRotation += it->GetData()->m_TotalRotation; + return startRotation + m_StartRotation; +} + bool CCinemaTrack::Play(float DeltaTime) { - if (m_CPA->m_TimeElapsed == 0) - { - if (m_CPA == m_Paths.begin()) - { - //Set camera to start at starting rotations - CCamera *Cam=g_Game->GetView()->GetCamera(); - Cam->m_Orientation.SetIdentity(); - Cam->SetProjection (1, 5000, DEGTORAD(20)); - Cam->m_Orientation.SetXRotation(m_StartRotation.X); - Cam->m_Orientation.RotateY(m_StartRotation.Y); - Cam->m_Orientation.RotateZ(m_StartRotation.Z); - - } - } - m_CPA->m_TimeElapsed += m_TimeScale*DeltaTime; - m_AbsoluteTime += m_TimeScale*DeltaTime; + m_CPA->m_TimeElapsed += m_Timescale*DeltaTime; + m_AbsoluteTime += m_Timescale*DeltaTime; if (!Validate()) return false; - m_CPA->MoveToPointAt( m_CPA->GetElapsedTime() / m_CPA->GetDuration(), m_StartRotation); + CVector3D rotation = CalculateRotation(); + m_CPA->MoveToPointAt( m_CPA->GetElapsedTime() / m_CPA->GetDuration(), rotation); return true; } -void CCinemaTrack::MoveToPointAt(float t) + +CCinemaManager::CCinemaManager() : m_DrawCurrentSpline(false), + m_DrawAllSplines(false), m_Active(true), m_CurrentTrack(false) { - m_CPA->m_TimeElapsed = t; - if ( !Validate() ) - return; - MoveToPointAt(m_CPA->m_TimeElapsed / m_CPA->GetDuration()); -} -void CCinemaTrack::MoveToPointAbsolute(float time) -{ - m_CPA = m_Paths.begin(); - m_AbsoluteTime = m_CPA->m_TimeElapsed = time; - - if (!ValidateForward()) - return; - else - m_CPA->MoveToPointAt(m_CPA->m_TimeElapsed, m_StartRotation); } void CCinemaManager::AddTrack(CCinemaTrack track, const CStrW& name) @@ -346,6 +353,8 @@ void CCinemaManager::QueueTrack(const CStrW& name, bool queue ) else { debug_assert(HasTrack(name)); + if ( m_Tracks[name].m_Paths.empty() ) + return; m_TrackQueue.push_back(m_Tracks[name]); m_TrackQueue.back().m_CPA = m_TrackQueue.back().m_Paths.begin(); } @@ -354,7 +363,96 @@ void CCinemaManager::OverrideTrack(const CStrW& name) { m_TrackQueue.clear(); debug_assert(HasTrack(name)); + if ( m_Tracks[name].m_Paths.empty() ) + return; m_TrackQueue.push_back( m_Tracks[name] ); + m_TrackQueue.back().m_CPA = m_TrackQueue.back().m_Paths.begin(); +} +void CCinemaManager::SetAllTracks( const std::map& tracks) +{ + m_Tracks = tracks; + for ( std::map::iterator it=m_Tracks.begin(); + it != m_Tracks.end(); ++it ) + { + it->second.m_CPA = it->second.m_Paths.begin(); + } +} +void CCinemaManager::SetCurrentTrack(const CStrW& name, bool all, bool current, bool drawLines) +{ + debug_assert(HasTrack(name)); + m_CurrentTrack = &m_Tracks[name]; + m_DrawAllSplines = all; + m_DrawCurrentSpline = current; + m_DrawLines = drawLines; + DrawAllSplines(); +} +void CCinemaManager::SetCurrentPath(const int path) +{ + debug_assert(m_CurrentTrack); + m_CurrentPath = path; + m_CurrentTrack->m_CPA = m_CurrentTrack->m_Paths.begin() + path; +} +bool CCinemaManager::HasTrack(const CStrW& name) const +{ + return m_Tracks.find(name) != m_Tracks.end(); +} + +void CCinemaManager::DrawAllSplines() const +{ + if ( !(m_DrawAllSplines || m_DrawCurrentSpline) ) + return; + static const int smoothness = 200; + + if ( m_DrawAllSplines ) + { + for ( std::vector::iterator it = m_CurrentTrack->m_Paths.begin(); + it != m_CurrentTrack->m_Paths.end(); ++it ) + { + it->DrawSpline(CVector4D(0.f, 0.f, 1.f, 1.f), smoothness, m_DrawLines); + } + } + if ( m_DrawCurrentSpline && m_CurrentTrack->m_CPA != + m_CurrentTrack->m_Paths.end() ) + { + if ( m_DrawAllSplines ) + { + m_CurrentTrack->m_CPA->DrawSpline(CVector4D(1.f, 0.f, 0.f, 1.f), + smoothness, m_DrawLines); + } + else + { + m_CurrentTrack->m_CPA->DrawSpline(CVector4D(0.f, 0.f, 1.f, 1.f), + smoothness, m_DrawLines); + } + } +} +void CCinemaManager::MoveToPointAt(float time) +{ + debug_assert(m_CurrentTrack); + StopPlaying(); + if ( m_CurrentTrack->m_Paths.empty() ) + return; + + m_CurrentTrack->m_CPA->m_TimeElapsed = time; + if ( !m_CurrentTrack->Validate() ) + return; + m_CurrentTrack->m_CPA->MoveToPointAt(m_CurrentTrack->m_CPA->m_TimeElapsed / + m_CurrentTrack->m_CPA->GetDuration(), m_CurrentTrack->CalculateRotation()); +} +void CCinemaManager::MoveToPointAbsolute(float time) +{ + debug_assert(m_CurrentTrack); + g_Game->GetView()->GetCinema()->StopPlaying(); + if ( m_CurrentTrack->m_Paths.empty() ) + return; + + m_CurrentTrack->m_CPA = m_CurrentTrack->m_Paths.begin(); + m_CurrentTrack->m_AbsoluteTime = m_CurrentTrack->m_CPA->m_TimeElapsed = time; + + if (!m_CurrentTrack->ValidateForward()) + return; + m_CurrentTrack->m_CPA->MoveToPointAt(m_CurrentTrack->m_CPA->m_TimeElapsed / + m_CurrentTrack->m_CPA->GetDuration(), m_CurrentTrack->CalculateRotation()); } bool CCinemaManager::Update(float DeltaTime) { @@ -365,70 +463,3 @@ bool CCinemaManager::Update(float DeltaTime) } return true; } - -int CCinemaManager::LoadTracks() -{ - unsigned int fileID; - int numTracks; - - //NOTE: How do you find the current scenario's cinematics? - FileIOBuf buf; size_t size; - RETURN_ERR(vfs_load("FILENAME", buf, size)); - std::istringstream Stream(std::string((const char*)buf, (int)size), std::istringstream::binary); - (void)file_buf_free(buf); - - //Read in lone data - Stream >> fileID; - Stream >> numTracks; - - if (fileID != 0x0ADC) - { - debug_printf("Cinematic file not found for (FILENAME)!"); - return 0; - } - for (int i=0; i < numTracks; i++) - { - CCinemaTrack tmpTrack; - - CVector3D tmpPos; - float tmpTime; - int numPaths; - CStr Name; - - Stream >> Name; - Stream >> numPaths; - Stream >> tmpTrack.m_StartRotation.X; - Stream >> tmpTrack.m_StartRotation.Y; - Stream >> tmpTrack.m_StartRotation.Z; - - for (int j=0; j < numPaths; j++) - { - CCinemaData tmpData; - TNSpline tmpSpline; - int numNodes; - //load main data - Stream >> numNodes; - Stream >> tmpData.m_TotalRotation.X; - Stream >> tmpData.m_TotalRotation.Y; - Stream >> tmpData.m_TotalRotation.Z; - Stream >> tmpData.m_Growth; - tmpData.m_GrowthCount = tmpData.m_Growth; - Stream >> tmpData.m_Switch; - Stream >> tmpData.m_Mode; - Stream >> tmpData.m_Style; - - //Get point data for path - for (int x=0; x> tmpPos.X; - Stream >> tmpPos.Y; - Stream >> tmpPos.Z; - Stream >> tmpTime; - tmpSpline.AddNode( tmpPos, tmpTime ); - } - tmpTrack.AddPath(tmpData, tmpSpline); - } - AddTrack(tmpTrack, Name); - } - return 0; -} \ No newline at end of file diff --git a/source/graphics/CinemaTrack.h b/source/graphics/CinemaTrack.h index 92ecb3c8fb..edc6a5a2c0 100644 --- a/source/graphics/CinemaTrack.h +++ b/source/graphics/CinemaTrack.h @@ -2,17 +2,6 @@ #ifndef H_CinemaTracks_H #define H_CinemaTracks_H -#define EM_IN 0 -#define EM_OUT 1 -#define EM_INOUT 2 -#define EM_OUTIN 3 - -#define ES_DEFAULT 0 -#define ES_GROWTH 1 -#define ES_EXPO 2 -#define ES_CIRCLE 3 -#define ES_SINE 4 - #include #include #include "ps/CStr.h" @@ -22,6 +11,7 @@ Andrew (aka pyrolink) Contact: ajdecker1022@msn.com desc: contains various functions used for cinematic camera tracks + See also: CinemaHandler.cpp, Cinematic.h/.cpp */ class CVector3D; @@ -32,15 +22,16 @@ class CCamera; class CCinemaData { public: - CCinemaData() {} - ~CCinemaData() {} + CCinemaData() : m_GrowthCount(0), m_Growth(0), m_Switch(0), + m_Mode(0), m_Style(0) {} + virtual ~CCinemaData() {} const CCinemaData* GetData() const { return this; } CVector3D m_TotalRotation; //Distortion variables - float m_GrowthCount; + mutable float m_GrowthCount; float m_Growth; float m_Switch; int m_Mode; @@ -51,112 +42,120 @@ public: //Once the data is part of the path, it shouldn't be changeable class CCinemaPath : private CCinemaData, public TNSpline { - friend class CCinemaTrack; + //friend class CCinemaTrack; public: CCinemaPath(const CCinemaData& data, const TNSpline& spline); ~CCinemaPath() { DistStylePtr = NULL; DistModePtr = NULL; } - void ResetRotation(float t); + enum { EM_IN, EM_OUT, EM_INOUT, EM_OUTIN }; + enum { ES_DEFAULT, ES_GROWTH, ES_EXPO, ES_CIRCLE, ES_SINE }; + //sets camera position to calculated point on spline void MoveToPointAt(float t, const CVector3D &startRotation); - //void MoveToPointAt(float t); - //Distortion mode functions-change how ratio is passed to distortion style functions - float EaseIn(float t); - float EaseOut(float t); - float EaseInOut(float t); - float EaseOutIn(float t); + float EaseIn(float t) const; + float EaseOut(float t) const; + float EaseInOut(float t) const; + float EaseOutIn(float t) const; //Distortion style functions - float EaseDefault(float t); - float EaseGrowth(float t); - float EaseExpo(float t); - float EaseCircle(float t); - float EaseSine(float t); + float EaseDefault(float t) const; + float EaseGrowth(float t) const; + float EaseExpo(float t) const; + float EaseCircle(float t) const; + float EaseSine(float t) const; - float (CCinemaPath::*DistStylePtr)(float ratio); - float (CCinemaPath::*DistModePtr)(float ratio); + float (CCinemaPath::*DistStylePtr)(float ratio) const; + float (CCinemaPath::*DistModePtr)(float ratio) const; const CCinemaData* GetData() const { return CCinemaData::GetData(); } public: - void DrawSpline(CVector4D RGBA, int smoothness); + void DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) const; inline CVector3D GetNodePosition(const int index) const { return Node[index].Position; } inline float GetNodeDuration(const int index) const { return Node[index].Distance; } inline float GetDuration() const { return MaxDistance; } inline float GetElapsedTime() const { return m_TimeElapsed; } const std::vector& GetAllNodes() const { return Node; } -// inline void SetElapsedTime(float time) { m_TimeElapsed = time; } -private: float m_TimeElapsed; - }; class CCinemaTrack { friend class CCinemaManager; public: - CCinemaTrack() {} + CCinemaTrack(); ~CCinemaTrack() {} - void AddPath(CCinemaData& data, TNSpline& spline); - inline void SetTimeScale(float scale) { m_TimeScale = scale; } + void AddPath(const CCinemaData& data, const TNSpline& spline); + void AddPath(const CCinemaPath& path); + inline void SetTimescale(float scale) { m_Timescale = scale; } inline void SetStartRotation(CVector3D rotation) { m_StartRotation = rotation; } void UpdateDuration(); - //DOES NOT set CPA to Paths.begin(). Returns-false indicates it's finished, - //true means it's still playing. + //Returns false if finished bool Play(float DeltaTime); bool Validate(); - void MoveToPointAt(float t); - void MoveToPointAbsolute(float time); //Time, not ratio, in terms of track inline const CVector3D& GetRotation() const { return m_StartRotation; } - inline float GetTimeScale() const { return m_TimeScale; } + inline float GetTimescale() const { return m_Timescale; } inline float GetTotalDuration() const { return m_TotalDuration; } inline const std::vector& GetAllPaths() const { return m_Paths; } - + + private: std::vector m_Paths; std::vector::iterator m_CPA; //current path CVector3D m_StartRotation; - float m_TimeScale; //a negative timescale results in backwards play + float m_Timescale; //a negative timescale results in backwards play float m_AbsoluteTime; //Current time of track, in absolute terms (not path) float m_TotalDuration; bool ValidateForward(); bool ValidateRewind(); + CVector3D CalculateRotation(); }; -//Class for in game playing of cinematics +//Class for in game playing of cinematics. Should only be instantiated +//in CGameView. class CCinemaManager { public: - CCinemaManager() { m_Active=false; } + CCinemaManager(); ~CCinemaManager() {} - + void AddTrack(CCinemaTrack track, const CStrW& name); - int LoadTracks(); //Loads tracks from file - - //Adds track to list of being played. (Called by triggers?) + + //Adds track to list of being played. void QueueTrack(const CStrW& name, bool queue); void OverrideTrack(const CStrW& name); //clears track queue and replaces with 'name' bool Update(float DeltaTime); + //These stop track play, and accept time, not ratio of time + void MoveToPointAt(float time); + void MoveToPointAbsolute(float time); //Time in terms of track + + inline void StopPlaying() { m_TrackQueue.clear(); } + void DrawAllSplines() const; + inline bool IsPlaying() const { return !m_TrackQueue.empty(); } - bool HasTrack(const CStrW& name) const { return m_Tracks.find(name) != m_Tracks.end(); } + bool HasTrack(const CStrW& name) const; inline bool IsActive() const { return m_Active; } inline void SetActive(bool active) { m_Active=active; } - CCinemaTrack* GetTrack(const CStrW& name) { debug_assert(HasTrack(name)); return &m_Tracks[name]; } inline const std::map& GetAllTracks() { return m_Tracks; } - inline void SetAllTracks( const std::map& tracks) { m_Tracks = tracks; } + void SetAllTracks( const std::map& tracks); + void SetCurrentTrack(const CStrW& name, bool all, bool current, bool lines); + void SetCurrentPath(int path); + private: - bool m_Active; + bool m_Active, m_DrawCurrentSpline, m_DrawAllSplines, m_DrawLines; + int m_CurrentPath; + CCinemaTrack* m_CurrentTrack; std::map m_Tracks; std::list m_TrackQueue; }; diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp index 704dcdc222..33bf5482d3 100644 --- a/source/graphics/GameView.cpp +++ b/source/graphics/GameView.cpp @@ -431,7 +431,6 @@ void CGameView::Update(float DeltaTime) if(!m_TrackManager.Update(DeltaTime)) ResetCamera(); } - m_ViewCamera.UpdateFrustum(); return; } diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index e3c3115178..7a7eec5eb0 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -14,6 +14,7 @@ #include "maths/MathUtil.h" #include "Camera.h" #include "graphics/Patch.h" +#include "graphics/GameView.h" #include "renderer/WaterManager.h" #include "renderer/SkyManager.h" @@ -38,7 +39,7 @@ CMapReader::CMapReader() // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager *pUnitMan_, WaterManager* pWaterMan_, SkyManager* pSkyMan_, - CLightEnv *pLightEnv_, CCamera *pCamera_) + CLightEnv *pLightEnv_, CCamera *pCamera_, CCinemaManager* pCinema_) { // latch parameters (held until DelayedLoadFinished) pTerrain = pTerrain_; @@ -47,6 +48,7 @@ void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, pCamera = pCamera_; pWaterMan = pWaterMan_; pSkyMan = pSkyMan_; + pCinema = pCinema_; // [25ms] unpacker.Read(filename, "PSMP"); @@ -180,6 +182,57 @@ int CMapReader::UnpackTerrain() return 0; } +int CMapReader::UnpackCinema() +{ + size_t numTracks; + unpacker.UnpackRaw(&numTracks, (u32)sizeof(size_t)); + + for ( size_t track=0; track < numTracks; ++track ) + { + CCinemaTrack trackObj; + std::vector paths; + CStr name; + size_t numPaths; + CVector3D startRotation; + float timescale; + + unpacker.UnpackString(name); + unpacker.UnpackRaw(×cale, sizeof(float)); + unpacker.UnpackRaw(&numPaths, sizeof(size_t)); + unpacker.UnpackRaw(&startRotation, sizeof(CVector3D)); + + trackObj.SetStartRotation(startRotation); + trackObj.SetTimescale(timescale); + + for ( size_t i=0; im_Orientation.Translate(translation); m_MapReader.pCamera->UpdateFrustum(); } +void CXMLReader::ReadCinema(XMBElement parent) +{ + #define EL(x) int el_##x = xmb_file.getElementID(#x) + #define AT(x) int at_##x = xmb_file.getAttributeID(#x) + EL(track); + EL(startrotation); + EL(path); + EL(rotation); + EL(distortion); + EL(node); + AT(name); + AT(timescale); + AT(mode); + AT(style); + AT(growth); + AT(switch); + AT(x); + AT(y); + AT(z); + AT(t); + +#undef EL +#undef AT + + std::map trackList; + XERO_ITER_EL(parent, element) + { + int elementName = element.getNodeName(); + + if ( elementName == el_track ) + { + CCinemaTrack track; + XMBAttributeList attrs = element.getAttributes(); + CStrW name( CStr(attrs.getNamedItem(at_name)) ); + float timescale = CStr(attrs.getNamedItem(at_timescale)).ToFloat(); + track.SetTimescale(timescale); + + XERO_ITER_EL(element, trackChild) + { + elementName = trackChild.getNodeName(); + + if ( elementName == el_startrotation ) + { + attrs = trackChild.getAttributes(); + float x = CStr(attrs.getNamedItem(at_x)).ToFloat(); + float y = CStr(attrs.getNamedItem(at_y)).ToFloat(); + float z = CStr(attrs.getNamedItem(at_z)).ToFloat(); + track.SetStartRotation(CVector3D(x, y, z)); + } + else if ( elementName == el_path ) + { + CCinemaData pathData; + TNSpline spline, backwardSpline; + + XERO_ITER_EL(trackChild, pathChild) + { + elementName = pathChild.getNodeName(); + attrs = pathChild.getAttributes(); + + if ( elementName == el_rotation ) + { + float x = CStr(attrs.getNamedItem(at_x)).ToFloat(); + float y = CStr(attrs.getNamedItem(at_y)).ToFloat(); + float z = CStr(attrs.getNamedItem(at_z)).ToFloat(); + pathData.m_TotalRotation = CVector3D(x, y, z); + } + else if ( elementName == el_distortion ) + { + pathData.m_Mode = CStr(attrs.getNamedItem(at_mode)).ToInt(); + pathData.m_Style = CStr(attrs.getNamedItem(at_style)).ToInt(); + pathData.m_Growth = CStr(attrs.getNamedItem(at_growth)).ToInt(); + pathData.m_Switch = CStr(attrs.getNamedItem(at_switch)).ToInt(); + } + else if ( elementName == el_node ) + { + SplineData data; + data.Position.X = CStr(attrs.getNamedItem(at_x)).ToFloat(); + data.Position.Y = CStr(attrs.getNamedItem(at_y)).ToFloat(); + data.Position.Z = CStr(attrs.getNamedItem(at_z)).ToFloat(); + data.Distance = CStr(attrs.getNamedItem(at_t)).ToFloat(); + backwardSpline.AddNode(data.Position, data.Distance); + } + else + debug_warn("Invalid cinematic element for path child"); + } //node loop + CCinemaPath temp(pathData, backwardSpline); + const std::vector& nodes = temp.GetAllNodes(); + if ( nodes.empty() ) + { + debug_warn("Failure loading cinematics"); + return; + } + + for ( std::vector::const_reverse_iterator + it=nodes.rbegin(); it != nodes.rend(); ++it ) + { + spline.AddNode(it->Position, it->Distance); + } + track.AddPath(pathData, spline); + + } // == el_path + else + debug_warn("Invalid cinematic element for track child"); + } + trackList[name] = track; + } + else + debug_warn("Invalid cinematic element for root track child"); + } + g_Game->GetView()->GetCinema()->SetAllTracks(trackList); +} int CXMLReader::ReadEntities(XMBElement parent, double end_time) { @@ -663,6 +830,10 @@ int CXMLReader::ProgressiveRead() if (ret != 0) // error or timed out return ret; } + else if (name == "Tracks") + { + ReadCinema(node); + } else debug_warn("Invalid map XML data"); diff --git a/source/graphics/MapReader.h b/source/graphics/MapReader.h index 3a3701a7e0..fc89e6f31c 100644 --- a/source/graphics/MapReader.h +++ b/source/graphics/MapReader.h @@ -5,6 +5,7 @@ #include "lib/res/handle.h" #include "ps/CStr.h" #include "LightEnv.h" +#include "CinemaTrack.h" #include "ps/FileUnpacker.h" class CObjectEntry; @@ -14,6 +15,7 @@ class WaterManager; class SkyManager; class CLightEnv; class CCamera; +class CCinemaManager; class CXMLReader; @@ -26,11 +28,13 @@ public: CMapReader(); // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful void LoadMap(const char* filename, CTerrain *pTerrain, CUnitManager *pUnitMan, - WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv *pLightEnv, CCamera *pCamera); + WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv *pLightEnv, CCamera *pCamera, CCinemaManager* pCinema); private: // UnpackTerrain: unpack the terrain from the input stream int UnpackTerrain(); + //UnpackCinema: unpack the cinematic tracks from the input stream + int UnpackCinema(); // UnpackObjects: unpack world objects from the input stream void UnpackObjects(); // UnpackObjects: unpack lighting parameters from the input stream @@ -56,6 +60,8 @@ private: std::vector m_TerrainTextures; // tile descriptions for each tile std::vector m_Tiles; + // cinematic tracks used by cinema manager + std::map m_Tracks; // list of object types used by map std::vector m_ObjectTypes; // descriptions for each objects @@ -71,6 +77,7 @@ private: SkyManager* pSkyMan; CLightEnv* pLightEnv; CCamera* pCamera; + CCinemaManager* pCinema; CStr filename_xml; // UnpackTerrain generator state diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp index eb61d75d29..e2ca946e9e 100644 --- a/source/graphics/MapWriter.cpp +++ b/source/graphics/MapWriter.cpp @@ -4,6 +4,7 @@ #include "lib/res/file/vfs.h" #include "Camera.h" +#include "CinemaTrack.h" #include "LightEnv.h" #include "MapReader.h" #include "MapWriter.h" @@ -18,6 +19,7 @@ #include "UnitManager.h" #include "maths/MathUtil.h" +#include "maths/NUSpline.h" #include "ps/Loader.h" #include "ps/Player.h" #include "ps/VFSUtil.h" @@ -38,7 +40,7 @@ CMapWriter::CMapWriter() // SaveMap: try to save the current map to the given file void CMapWriter::SaveMap(const char* filename, CTerrain* pTerrain, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, - CLightEnv* pLightEnv, CCamera* pCamera) + CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema) { CFilePacker packer(FILE_VERSION, "PSMP"); @@ -50,7 +52,7 @@ void CMapWriter::SaveMap(const char* filename, CTerrain* pTerrain, CStr filename_xml (filename); filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml"; - WriteXML(filename_xml, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera); + WriteXML(filename_xml, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -156,12 +158,9 @@ void CMapWriter::PackTerrain(CFilePacker& packer, CTerrain* pTerrain) // pack tile data packer.PackRaw(&tiles[0],(u32)(sizeof(STileDesc)*tiles.size())); } - - - void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, - CLightEnv* pLightEnv, CCamera* pCamera) + CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema) { Handle h = vfs_open(filename, FILE_WRITE_TO_TARGET|FILE_NO_AIO); if (h <= 0) @@ -318,6 +317,71 @@ void CMapWriter::WriteXML(const char* filename, } } } + const std::map& tracks = pCinema->GetAllTracks(); + std::map::const_iterator it = tracks.begin(); + + { + XML_Element("Tracks"); + + for ( ; it != tracks.end(); it++ ) + { + const std::vector& paths = it->second.GetAllPaths(); + CStrW name = it->first; + size_t numPaths = paths.size(); + CVector3D startRotation = it->second.GetRotation(); + float timescale = it->second.GetTimescale(); + + { + XML_Element("Track"); + XML_Attribute("name", name); + XML_Attribute("timescale", timescale); + + { + XML_Element("StartRotation"); + XML_Attribute("x", startRotation.X); + XML_Attribute("y", startRotation.Y); + XML_Attribute("z", startRotation.Z); + } + + for ( size_t i=0; i& nodes = + paths[i].GetAllNodes(); + const CCinemaData* data = paths[i].GetData(); + { + XML_Element("Path"); + + { + CVector3D rot = data->m_TotalRotation; + XML_Element("Rotation"); + XML_Attribute("x", rot.X); + XML_Attribute("y", rot.Y); + XML_Attribute("z", rot.Z); + } + + { + XML_Element("Distortion"); + XML_Attribute("mode", data->m_Mode); + XML_Attribute("style", data->m_Style); + XML_Attribute("growth", data->m_Growth); + XML_Attribute("switch", data->m_Switch); + } + + for ( int j=(int)nodes.size()-1; j >= 0; --j ) + { + { + XML_Element("Node"); + XML_Attribute("x", nodes[j].Position.X); + XML_Attribute("y", nodes[j].Position.Y); + XML_Attribute("z", nodes[j].Position.Z); + XML_Attribute("t", nodes[j].Distance); + } + } + } //path data + } + } //track data + } + } //(Did this really happen) - I blame XML } if (! XML_StoreVFS(h)) @@ -331,7 +395,7 @@ void CMapWriter::WriteXML(const char* filename, // RewriteAllMaps void CMapWriter::RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, - CLightEnv* pLightEnv, CCamera* pCamera) + CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema) { VFSUtil::FileList files; VFSUtil::FindFiles("maps/scenarios", "*.pmp", files); @@ -340,13 +404,13 @@ void CMapWriter::RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan, { CMapReader* reader = new CMapReader; LDR_BeginRegistering(); - reader->LoadMap(*it, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera); + reader->LoadMap(*it, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema); LDR_EndRegistering(); LDR_NonprogressiveLoad(); CStr n (*it); n.Replace("scenarios/", "scenarios/new/"); CMapWriter writer; - writer.SaveMap(n, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera); + writer.SaveMap(n, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema); } } diff --git a/source/graphics/MapWriter.h b/source/graphics/MapWriter.h index d31597e650..67dd511ccf 100644 --- a/source/graphics/MapWriter.h +++ b/source/graphics/MapWriter.h @@ -10,6 +10,7 @@ class CLightEnv; class CTerrain; class CUnitManager; class CCamera; +class CCinemaManager; class WaterManager; class SkyManager; @@ -19,11 +20,11 @@ public: // constructor CMapWriter(); // SaveMap: try to save the current map to the given file - void SaveMap(const char* filename, CTerrain* pTerr, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera); + void SaveMap(const char* filename, CTerrain* pTerr, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema); // RewriteAllMaps: for use during development: load/save all maps, to // update them to the newest format. - static void RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera); + static void RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema); private: // PackMap: pack the current world into a raw data stream @@ -37,7 +38,7 @@ private: std::vector& tileIndices); // WriteXML: output some other data (entities, etc) in XML format - void WriteXML(const char* filename, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera); + void WriteXML(const char* filename, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema); }; #endif diff --git a/source/maths/NUSpline.cpp b/source/maths/NUSpline.cpp index cd0dcbfebf..44a40aa61e 100644 --- a/source/maths/NUSpline.cpp +++ b/source/maths/NUSpline.cpp @@ -76,7 +76,7 @@ void RNSpline::BuildSpline() } // spline access function. time is 0 -> 1 -CVector3D RNSpline::GetPosition(float time) +CVector3D RNSpline::GetPosition(float time) const { if ( NodeCount < 2 ) return CVector3D(0.0f, 0.0f, 0.0f); diff --git a/source/maths/NUSpline.h b/source/maths/NUSpline.h index f983f3244d..6e3aaabffb 100644 --- a/source/maths/NUSpline.h +++ b/source/maths/NUSpline.h @@ -21,9 +21,10 @@ class RNSpline public: RNSpline() { NodeCount = 0; } + virtual ~RNSpline() {} void AddNode(const CVector3D &pos); void BuildSpline(); - CVector3D GetPosition(float time); + CVector3D GetPosition(float time) const; float MaxDistance; int NodeCount; @@ -37,6 +38,7 @@ protected: class SNSpline : public RNSpline { public: + virtual ~SNSpline() {} void BuildSpline(){ RNSpline::BuildSpline(); Smooth(); Smooth(); Smooth(); } void Smooth(); }; @@ -44,6 +46,7 @@ public: class TNSpline : public SNSpline { public: + virtual ~TNSpline() {} void AddNode(const CVector3D &pos, float timePeriod); void PushNode() { Node.push_back( SplineData() ); } void InsertNode(const int index, const CVector3D &pos, float timePeriod); diff --git a/source/maths/Quaternion.cpp b/source/maths/Quaternion.cpp index 89b59de59c..63ecb1cd55 100644 --- a/source/maths/Quaternion.cpp +++ b/source/maths/Quaternion.cpp @@ -91,6 +91,35 @@ void CQuaternion::FromEulerAngles (float x, float y, float z) (*this) = QYaw * QPitch * QRoll; } +CVector3D CQuaternion::ToEulerAngles() +{ + float heading, attitude, bank; + float sqw = m_W * m_W; + float sqx = m_V.X*m_V.X; + float sqy = m_V.Y*m_V.Y; + float sqz = m_V.Z*m_V.Z; + float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor + float test = m_V.X*m_V.Y + m_V.Z*m_W; + if (test > (.5f-EPSILON)*unit) + { // singularity at north pole + heading = 2 * atan2( m_V.X, m_W); + attitude = PI/2; + bank = 0; + } + else if (test < (-.5f+EPSILON)*unit) + { // singularity at south pole + heading = -2 * atan2(m_V.X, m_W); + attitude = -PI/2; + bank = 0; + } + else + { + heading = atan2(2.f * (m_V.X*m_V.Y + m_V.Z*m_W),(sqx - sqy - sqz + sqw)); + bank = atan2(2.f * (m_V.Y*m_V.Z + m_V.X*m_W),(-sqx - sqy + sqz + sqw)); + attitude = asin(-2.f * (m_V.X*m_V.Z - m_V.Y*m_W)); + } + return CVector3D(bank, attitude, heading); +} CMatrix3D CQuaternion::ToMatrix () const { diff --git a/source/maths/Quaternion.h b/source/maths/Quaternion.h index 6156efca7c..d1dc936819 100644 --- a/source/maths/Quaternion.h +++ b/source/maths/Quaternion.h @@ -33,6 +33,7 @@ public: CQuaternion &operator *= (const CQuaternion &quat); void FromEulerAngles (float x, float y, float z); + CVector3D ToEulerAngles(); //convert the quaternion to matrix CMatrix3D ToMatrix() const; diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index d4f123309d..e1e83a3010 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -365,12 +365,18 @@ void Render() PROFILE_END( "render entity bars" ); glPopAttrib(); + glMatrixMode(GL_MODELVIEW); // Depth test is now enabled PROFILE_START( "render rally points" ); g_Selection.renderRallyPoints(); g_Mouseover.renderRallyPoints(); PROFILE_END( "render rally points" ); + + PROFILE_START( "render cinematic splines" ); + //Sets/resets renderering properties itself + g_Game->GetView()->GetCinema()->DrawAllSplines(); + PROFILE_END( "render cinematic splines" ); } else { diff --git a/source/ps/World.cpp b/source/ps/World.cpp index 738825396c..dcca5bcff6 100644 --- a/source/ps/World.cpp +++ b/source/ps/World.cpp @@ -58,7 +58,7 @@ void CWorld::Initialize(CGameAttributes *pAttribs) try { reader = new CMapReader; reader->LoadMap(mapfilename, m_Terrain, m_UnitManager, g_Renderer.GetWaterManager(), - g_Renderer.GetSkyManager(), &g_LightEnv, m_pGame->GetView()->GetCamera()); + g_Renderer.GetSkyManager(), &g_LightEnv, m_pGame->GetView()->GetCamera(), m_pGame->GetView()->GetCinema()); // fails immediately, or registers for delay loading } catch (PSERROR_File&) { delete reader; @@ -89,5 +89,6 @@ void CWorld::RewriteMap() { CMapWriter::RewriteAllMaps(m_Terrain, m_UnitManager, g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(), - &g_LightEnv, m_pGame->GetView()->GetCamera()); + &g_LightEnv, m_pGame->GetView()->GetCamera(), + m_pGame->GetView()->GetCinema()); } diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.cpp index 43a6809962..c5956051db 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.cpp @@ -3,16 +3,68 @@ #include "Cinematic.h" #include "GameInterface/Messages.h" +#include "CustomControls/Buttons/ActionButton.h" +//#include "CustomControls/Buttons/FloatingSpinCtrl.h" +#include "General/DataFile.h" +#include "ScenarioEditor/Tools/Common/Tools.h" +#include "HighResTimer/HighResTimer.h" +#include using namespace AtlasMessage; +#define CINEMA_EPSILON .032f +struct eCinemaButton +{ + enum { + previous/*, rewind, reverse*/, stop, + play, pause, /*forward,*/ next }; +}; + +float CinemaTextFloat(wxTextCtrl&, size_t, float, float, float); + +class CinematicBottomBar : public wxPanel +{ + friend void TimescaleSpin(void*); +public: + CinematicBottomBar(wxWindow* parent, CinematicSidebar* side); + void AddLists(CinematicSidebar* side, TrackListCtrl* tracks, + PathListCtrl* paths, NodeListCtrl* nodes); + void OnText(wxCommandEvent& WXUNUSED(event)) + { + m_OldScale = CinemaTextFloat(*m_TimeText, 2, -5.f, 5.f, m_OldScale); + m_Sidebar->UpdateTrack(m_Name->GetLineText(0).wc_str(), m_OldScale); + } + void Update(std::wstring name, float scale) + { + m_Name->SetValue( wxString(name.c_str()) ); + m_TimeText->SetValue( wxString::Format(L"%f", scale) ); + if ( m_OldTrackIndex != m_Sidebar->GetSelectedTrack() ) + { + m_OldTrackIndex = m_Sidebar->GetSelectedTrack(); + m_OldScale = 0.f; + } + CinemaTextFloat(*m_TimeText, 2, -5.f, 5.f, 0.f); + } +private: + wxStaticBoxSizer* m_Sizer; + CinematicSidebar* m_Sidebar; + wxTextCtrl* m_Name, *m_TimeText; + float m_OldScale; + ssize_t m_OldTrackIndex; + DECLARE_EVENT_TABLE(); +}; +BEGIN_EVENT_TABLE(CinematicBottomBar, wxPanel) +EVT_TEXT_ENTER(wxID_ANY, CinematicBottomBar::OnText) +END_EVENT_TABLE() + +///////////////////////////////////////////////////////////////////// class TrackListCtrl : public wxListCtrl { public: - TrackListCtrl(CinematicSidebar* parent) + TrackListCtrl(wxWindow* parent, CinematicSidebar* side) : wxListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|/*wxLC_EDIT_LABELS|*/wxLC_SINGLE_SEL), - m_Sidebar(parent) + m_Sidebar(side) { InsertColumn(0, _("Tracks"), wxLIST_FORMAT_LEFT, 180); } @@ -20,6 +72,26 @@ public: void OnSelect(wxListEvent& event) { m_Sidebar->SelectTrack(event.GetIndex()); + m_Sidebar->UpdateTexts(); + } + void AddTrack() + { + std::wstringstream message; + message << "Track " << GetItemCount(); + std::wstring msgString = message.str(); + wxString fmt( msgString.c_str(), msgString.length() ); + InsertItem(GetItemCount(), fmt); + + qGetCameraInfo qry; + qry.Post(); + sCameraInfo info = qry.info; + m_Sidebar->AddTrack(info.rX, info.rY, info.rZ, msgString, + GetItemCount()-1); + } + void DeleteTrack() + { + DeleteItem(m_Sidebar->GetSelectedTrack()); + m_Sidebar->DeleteTrack(); } private: @@ -31,13 +103,12 @@ BEGIN_EVENT_TABLE(TrackListCtrl, wxListCtrl) EVT_LIST_ITEM_SELECTED(wxID_ANY, TrackListCtrl::OnSelect) END_EVENT_TABLE() - class PathListCtrl : public wxListCtrl { public: - PathListCtrl(CinematicSidebar* parent) + PathListCtrl(wxWindow* parent, CinematicSidebar* side) : wxListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL), - m_Sidebar(parent) + m_Sidebar(side) { InsertColumn(0, _("Paths"), wxLIST_FORMAT_LEFT, 180); } @@ -45,75 +116,896 @@ public: void OnSelect(wxListEvent& event) { m_Sidebar->SelectPath(event.GetIndex()); + m_Sidebar->UpdateTexts(); + } + void AddPath() + { + std::wstringstream message; + message << "Path " << GetItemCount(); + std::wstring msgString = message.str(); + wxString fmt( msgString.c_str(), msgString.length() ); + InsertItem(GetItemCount(), fmt); + + qGetCameraInfo qry; + qry.Post(); + sCameraInfo info = qry.info; + m_Sidebar->AddPath(info.rX, info.rY, info.rZ, GetItemCount()-1); + } + void DeletePath() + { + DeleteItem(m_Sidebar->GetSelectedPath()); + m_Sidebar->DeletePath(); + } + void UpdatePath() + { + qGetCameraInfo qry; + qry.Post(); + sCameraInfo info = qry.info; + m_Sidebar->UpdatePath(info.rX, info.rY, info.rZ); } private: CinematicSidebar* m_Sidebar; - + DECLARE_EVENT_TABLE(); }; BEGIN_EVENT_TABLE(PathListCtrl, wxListCtrl) EVT_LIST_ITEM_SELECTED(wxID_ANY, PathListCtrl::OnSelect) END_EVENT_TABLE() - class NodeListCtrl : public wxListCtrl { public: - NodeListCtrl(CinematicSidebar* parent) - : wxListCtrl(parent, wxID_ANY, wxDefaultPosition, wxSize(190, -1), wxLC_REPORT|wxLC_SINGLE_SEL), - m_Sidebar(parent) + NodeListCtrl(wxWindow* parent, CinematicSidebar* side) + : wxListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL), + m_Sidebar(side) { InsertColumn(0, _("Nodes"), wxLIST_FORMAT_LEFT, 180); } - void OnSelect(wxListEvent& event) { - m_Sidebar->SelectSplineNode(event.GetIndex()); - } + m_Sidebar->SelectSplineNode(event.GetIndex(), GetItemCount()); + m_Sidebar->UpdateTexts(); + } + void AddNode() + { + std::wstringstream message; + message << "Node " << GetItemCount(); + std::wstring msgString = message.str(); + wxString fmt( msgString.c_str(), msgString.length() ); + InsertItem(GetItemCount(), fmt); + qGetCameraInfo qry; + qry.Post(); + sCameraInfo info = qry.info; + m_Sidebar->AddNode(info.pX, info.pY, info.pZ, GetItemCount()-1); + } + void DeleteNode() + { + DeleteItem(m_Sidebar->GetSelectedNode()); + m_Sidebar->DeleteNode(); + } + void UpdateNode() + { + qGetCameraInfo qry; + qry.Post(); + sCameraInfo info = qry.info; + m_Sidebar->UpdateNode(info.pX, info.pY, info.pZ); + } + void GotoNode() + { + m_Sidebar->GotoNode(); + } private: CinematicSidebar* m_Sidebar; - + DECLARE_EVENT_TABLE(); }; BEGIN_EVENT_TABLE(NodeListCtrl, wxListCtrl) EVT_LIST_ITEM_SELECTED(wxID_ANY, NodeListCtrl::OnSelect) END_EVENT_TABLE() -////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// -class CinematicBottomBar : public wxPanel +void CinemaTrackAdd(void* data) +{ + TrackListCtrl* list = reinterpret_cast(data); + list->AddTrack(); +} +void CinemaPathAdd(void* data) +{ + PathListCtrl* list = reinterpret_cast(data); + list->AddPath(); +} +void CinemaNodeAdd(void* data) +{ + NodeListCtrl* list = reinterpret_cast(data); + list->AddNode(); +} +void CinemaTrackDel(void* data) +{ + TrackListCtrl* list = reinterpret_cast(data); + list->DeleteTrack(); +} +void CinemaPathDel(void* data) +{ + PathListCtrl* list = reinterpret_cast(data); + list->DeletePath(); +} +void CinemaNodeDel(void* data) +{ + NodeListCtrl* list = reinterpret_cast(data); + list->DeleteNode(); +} + +void CinemaPathUpdate(void* data) +{ + PathListCtrl* list = reinterpret_cast(data); + list->UpdatePath(); +} +void CinemaNodeUpdate(void* data) +{ + NodeListCtrl* list = reinterpret_cast(data); + list->UpdateNode(); +} +void CinemaNodeGoto(void* data) +{ + NodeListCtrl* list = reinterpret_cast(data); + list->GotoNode(); +} + +/////////////////////////////////////////////////////////// + +void CinemaStringToFloat(wxString& text, size_t decimals) +{ + size_t i, j; + if ( (i = text.find(L".")) == wxString::npos) + { + text.Append('.'); + text.Append('0', decimals); + } + else + { + j = text.find_last_not_of(L"0"); + text.Remove(j+1); + //Too many numbers + if ( j - i > decimals ) + text.Remove(i+decimals+1); + else + text.Append('0', decimals - (j-i)); + } +} +float CinemaTextFloat(wxTextCtrl& ctrl, size_t decimals, float min, + float max, float oldval) +{ + wxString text = ctrl.GetLineText(0); + double val; + if ( !text.ToDouble(&val) ) + { + wxBell(); + val = oldval; + text = wxString::Format(L"%f", val); + CinemaStringToFloat(text, decimals); + } + + if ( val > max ) + val = oldval; + else if ( val < min ) + val = oldval; + text = wxString::Format(L"%f", val); + CinemaStringToFloat(text, decimals); + ctrl.SetValue(text); + return val; + +} +void WrapCinemaPath(sCinemaPath& path) +{ + if ( path.x > 360 ) + path.x = 360; + else if ( path.x < -360 ) + path.x = -360; + + if ( path.y > 360 ) + path.y = 360; + else if ( path.y < -360 ) + path.y = -360; + + if ( path.y > 360 ) + path.z = 360; + else if ( path.x < -360 ) + path.z = -360; +} +///////////////////////////////////////////////////////////// + +class CinemaSpinnerBox : public wxPanel { public: - CinematicBottomBar(wxWindow* parent) - : wxPanel(parent) + enum { TrackX_ID, TrackY_ID, TrackZ_ID, + PathX_ID, PathY_ID, PathZ_ID, + NodeX_ID, NodeY_ID, NodeZ_ID }; + CinemaSpinnerBox(wxWindow* parent, CinematicSidebar* side) + : wxPanel(parent), m_OldT(0), m_OldIndex(0) { - // TODO: there needs to be stuff here. + m_MainSizer = new wxBoxSizer(wxHORIZONTAL); + SetSizer(m_MainSizer); + m_Sidebar = side; + + wxStaticBoxSizer* tracks = new wxStaticBoxSizer(wxHORIZONTAL, + this, _T("Start Rotation")); + wxStaticBoxSizer* paths = new wxStaticBoxSizer(wxHORIZONTAL, + this, _T("Rotation")); + wxStaticBoxSizer* nodes = new wxStaticBoxSizer(wxHORIZONTAL, + this, _T("Position")); + + m_TrackX = new wxSpinCtrl(this, TrackX_ID, _T("x"), + wxDefaultPosition, wxSize(50, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_TrackY = new wxSpinCtrl(this, TrackY_ID, _T("y"), + wxDefaultPosition, wxSize(50, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_TrackZ = new wxSpinCtrl(this, TrackZ_ID, _T("z"), + wxDefaultPosition, wxSize(50, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + + m_PathX = new wxSpinCtrl(this, PathX_ID, _T("x"), + wxDefaultPosition, wxSize(50, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_PathY = new wxSpinCtrl(this, PathY_ID, _T("y"), + wxDefaultPosition, wxSize(50, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_PathZ = new wxSpinCtrl(this, PathZ_ID, _T("z"), + wxDefaultPosition, wxSize(50, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + + m_NodeX = new wxSpinCtrl(this, NodeX_ID, _T("x"), + wxDefaultPosition, wxSize(55, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_NodeY = new wxSpinCtrl(this, NodeY_ID, _T("y"), + wxDefaultPosition, wxSize(55, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_NodeZ = new wxSpinCtrl(this, NodeZ_ID, _T("z"), + wxDefaultPosition, wxSize(55, 15), wxSP_ARROW_KEYS|wxSP_WRAP ); + m_NodeT = new wxTextCtrl(this, wxID_ANY, _T("0.00"), + wxDefaultPosition, wxSize(55, 15), wxTE_PROCESS_ENTER ); + + m_TrackX->SetRange(-360, 360); + m_TrackY->SetRange(-360, 360); + m_TrackZ->SetRange(-360, 360); + m_PathX->SetRange(-360, 360); + m_PathY->SetRange(-360, 360); + m_PathZ->SetRange(-360, 360); + m_NodeX->SetRange(-1000, 1000); //TODO make these more exact + m_NodeY->SetRange(-200, 600); + m_NodeZ->SetRange(-1000, 1000); + + tracks->Add(m_TrackX); + tracks->Add(m_TrackY); + tracks->Add(m_TrackZ); + paths->Add(m_PathX); + paths->Add(m_PathY); + paths->Add(m_PathZ); + nodes->Add(m_NodeX); + nodes->Add(m_NodeY); + nodes->Add(m_NodeZ); + nodes->Add(m_NodeT); + + m_MainSizer->Add(tracks); + m_MainSizer->Add(paths); + m_MainSizer->Add(nodes); + } + + void OnTrackPush(wxSpinEvent& WXUNUSED(event)) + { + m_Sidebar->UpdateTrack( m_TrackX->GetValue(), + m_TrackY->GetValue(), m_TrackZ->GetValue()); + } + void OnPathPush(wxSpinEvent& WXUNUSED(event)) + { + m_Sidebar->UpdatePath( m_PathX->GetValue(), + m_PathY->GetValue(), m_PathZ->GetValue()); + } + void OnNodePush(wxSpinEvent& WXUNUSED(event)) + { + m_OldT = CinemaTextFloat(*m_NodeT, 2, 0.f, 100.f, m_OldT); + m_Sidebar->UpdateNode( m_NodeX->GetValue(), + m_NodeY->GetValue(), m_NodeZ->GetValue(), m_OldT); + } + void OnText(wxCommandEvent& WXUNUSED(event)) + { + m_OldT = CinemaTextFloat(*m_NodeT, 2, 0.f, 100.f, m_OldT); + m_Sidebar->UpdateNode( m_NodeX->GetValue(), + m_NodeY->GetValue(), m_NodeZ->GetValue(), m_OldT); + } + + void UpdateTrackSpinners(int x, int y, int z) + { + m_TrackX->SetValue(x); + m_TrackY->SetValue(y); + m_TrackZ->SetValue(z); + } + void UpdatePathSpinners(int x, int y, int z) + { + m_PathX->SetValue(x); + m_PathY->SetValue(y); + m_PathZ->SetValue(z); + } + void UpdateNodeSpinners(int x, int y, int z, float t, ssize_t index) + { + m_NodeX->SetValue(x); + m_NodeY->SetValue(y); + m_NodeZ->SetValue(z); + m_NodeT->SetValue(wxString::Format(L"%f", t)); + if ( m_OldIndex != index ) + { + m_OldT = 0.f; + m_OldIndex = index; + } + m_OldT = CinemaTextFloat(*m_NodeT, 2, 0.f, 100.f, m_OldT); } private: + wxSpinCtrl* m_TrackX, *m_TrackY, *m_TrackZ, *m_PathX, *m_PathY, *m_PathZ, *m_NodeX, *m_NodeY, *m_NodeZ; + wxTextCtrl* m_NodeT; + float m_OldT; + int m_OldIndex; + wxBoxSizer* m_MainSizer; + CinematicSidebar* m_Sidebar; + DECLARE_EVENT_TABLE(); +}; +BEGIN_EVENT_TABLE(CinemaSpinnerBox, wxPanel) +EVT_SPINCTRL(CinemaSpinnerBox::TrackX_ID, CinemaSpinnerBox::OnTrackPush) +EVT_SPINCTRL(CinemaSpinnerBox::TrackY_ID, CinemaSpinnerBox::OnTrackPush) +EVT_SPINCTRL(CinemaSpinnerBox::TrackZ_ID, CinemaSpinnerBox::OnTrackPush) +EVT_SPINCTRL(CinemaSpinnerBox::PathX_ID, CinemaSpinnerBox::OnPathPush) +EVT_SPINCTRL(CinemaSpinnerBox::PathY_ID, CinemaSpinnerBox::OnPathPush) +EVT_SPINCTRL(CinemaSpinnerBox::PathZ_ID, CinemaSpinnerBox::OnPathPush) +EVT_SPINCTRL(CinemaSpinnerBox::NodeX_ID, CinemaSpinnerBox::OnNodePush) +EVT_SPINCTRL(CinemaSpinnerBox::NodeY_ID, CinemaSpinnerBox::OnNodePush) +EVT_SPINCTRL(CinemaSpinnerBox::NodeZ_ID, CinemaSpinnerBox::OnNodePush) +EVT_TEXT_ENTER(wxID_ANY, CinemaSpinnerBox::OnText) +END_EVENT_TABLE() + +///////////////////////////////////////////////////////////// +CinematicBottomBar::CinematicBottomBar(wxWindow* parent, CinematicSidebar* side) +: wxPanel(parent), m_Sidebar(side), m_OldScale(0), m_OldTrackIndex(-1) +{ + m_Sizer = new wxStaticBoxSizer(wxVERTICAL, this); + SetSizer(m_Sizer); +} +void CinematicBottomBar::AddLists(CinematicSidebar* side, + TrackListCtrl* tracks, PathListCtrl* paths, NodeListCtrl* nodes) +{ + wxBoxSizer* top = new wxBoxSizer(wxHORIZONTAL); + CinemaSpinnerBox* spinners = new CinemaSpinnerBox(this, side); + side->SetSpinners(spinners); + wxBoxSizer* trackButtons = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* pathButtons = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* nodeButtons = new wxBoxSizer(wxVERTICAL); + + ActionButton* TrackAdd = new ActionButton(this, _T("Add"), + &CinemaTrackAdd, tracks, wxSize(40, 18)); + ActionButton* PathAdd = new ActionButton(this, _T("Add"), + &CinemaPathAdd, paths, wxSize(40, 18)); + ActionButton* NodeAdd = new ActionButton(this, _T("Add"), + &CinemaNodeAdd, nodes, wxSize(40, 18)); + ActionButton* TrackDel = new ActionButton(this, _T("Del"), + &CinemaTrackDel, tracks, wxSize(40, 18)); + ActionButton* PathDel = new ActionButton(this, _T("Del"), + &CinemaPathDel, paths, wxSize(40, 18)); + ActionButton* NodeDel = new ActionButton(this, _T("Del"), + &CinemaNodeDel, nodes, wxSize(40, 18)); + ActionButton* PathUpdate = new ActionButton(this, _T("Mod"), + &CinemaPathUpdate, paths, wxSize(40, 18)); + ActionButton* NodeUpdate = new ActionButton(this, _T("Mod"), + &CinemaNodeUpdate, nodes, wxSize(40, 18)); + ActionButton* NodeGoto = new ActionButton(this, _T("Goto"), + &CinemaNodeGoto, nodes, wxSize(44, 18)); + + wxBoxSizer* textBoxes = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* timescale = new wxBoxSizer(wxHORIZONTAL); + + timescale->Add( new wxStaticText(this, wxID_ANY, _T("Timescale:")) ); + m_TimeText = new wxTextCtrl(this, wxID_ANY, _T("1.00"), + wxDefaultPosition, wxSize(55, 20)); + timescale->Add( m_TimeText ); + + wxBoxSizer* nameBox = new wxBoxSizer(wxHORIZONTAL); + nameBox->Add( new wxStaticText(this, wxID_ANY, _T("Name:")), 0, + wxALIGN_CENTER | wxLEFT | wxRIGHT, 5); + m_Name = new wxTextCtrl(this, wxID_ANY, _T(""), wxDefaultPosition, + wxSize(55, 20)); + nameBox->Add( m_Name ); + + textBoxes->Add(timescale); + textBoxes->Add(nameBox, 0, wxEXPAND); + + trackButtons->Add(TrackAdd, 0); + trackButtons->Add(TrackDel, 0); + pathButtons->Add(PathAdd, 0); + pathButtons->Add(PathDel, 0); + pathButtons->Add(PathUpdate, 0); + nodeButtons->Add(NodeAdd, 0); + nodeButtons->Add(NodeDel, 0); + nodeButtons->Add(NodeUpdate, 0); + nodeButtons->Add(NodeGoto, 0); + + top->Add(tracks, 0); + top->Add(trackButtons, 0); + top->Add(textBoxes, 0); + top->Add(paths, 0); + top->Add(pathButtons, 0); + top->Add(nodes, 0); + top->Add(nodeButtons, 0); + + m_Sizer->Add(top, 0); + m_Sizer->Add(spinners, 0); +} + +class CinemaInfoBox : public wxPanel +{ +public: + enum { Mode_ID, Style_ID, Rotation_ID, Spline_ID }; + + CinemaInfoBox(CinematicSidebar* side) : wxPanel(side), + m_Sidebar(side), m_OldGrowth(0), m_OldSwitch(0), m_OldTrackIndex(-1) + { + m_Sizer = new wxBoxSizer(wxVERTICAL); + SetSizer(m_Sizer); + //Use individual static boxes for nicer looks + wxBoxSizer* radios = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer* spinners = new wxBoxSizer(wxHORIZONTAL); + + wxString style[5] = {_T("Default"), _T("Growth"), _T("Expo"), + _T("Circle"), _T("Sine") }; + m_StyleBox = new wxRadioBox(this, Style_ID, _T("Style"), wxDefaultPosition, + wxDefaultSize, 5, style, 5, wxRA_SPECIFY_ROWS ); + radios->Add(m_StyleBox, 0, wxALIGN_CENTER); + + //Mode radio box + wxString mode[4]= { _T("Ease in"), _T("Ease Out"), + _T("In-out"), _T("Out-in") }; + m_ModeBox = new wxRadioBox(this, Mode_ID, _T("Mode"), wxDefaultPosition, + wxDefaultSize, 4, mode, 4, wxRA_SPECIFY_ROWS ); + radios->Add(m_ModeBox, 0, wxEXPAND | wxALIGN_CENTER); + + wxStaticText* growth = new wxStaticText(this, wxID_ANY, _T("Growth")); + wxStaticText* change = new wxStaticText(this, wxID_ANY, _T("Switch")); + m_Growth = new wxTextCtrl(this, wxID_ANY, _T("0.00"), wxDefaultPosition, + wxSize(50, 15), wxTE_PROCESS_ENTER); + m_Switch = new wxTextCtrl(this, wxID_ANY, _T("0.00"), wxDefaultPosition, + wxSize(50, 15), wxTE_PROCESS_ENTER); + + wxStaticBoxSizer* growthBox = new wxStaticBoxSizer(wxHORIZONTAL, this); + growthBox->Add(growth, 0, wxALIGN_CENTER); + growthBox->Add(m_Growth, 0, wxALIGN_CENTER); + wxStaticBoxSizer* switchBox = new wxStaticBoxSizer(wxHORIZONTAL, this); + switchBox->Add(change, 0, wxALIGN_CENTER); + switchBox->Add(m_Switch, 0, wxALIGN_CENTER); + + spinners->Add(growthBox); + spinners->Add(switchBox); + m_Sizer->Add(radios, 0, wxALIGN_CENTER); + m_Sizer->Add(spinners, 0, wxALIGN_CENTER); + + //Put this here since there isn't any other place yet + wxBoxSizer* displayH = new wxBoxSizer(wxHORIZONTAL); + m_DrawAll = new wxCheckBox(this, wxID_ANY, _T("Draw all")); + m_DrawCurrent = new wxCheckBox(this, wxID_ANY, _T("Draw current")); + + wxString splineStrings[2] = { _T("Points"), _T("Lines") }; + m_SplineDisplay = new wxRadioBox(this, Spline_ID, _T("Spline Display"), + wxDefaultPosition, wxDefaultSize, 2, splineStrings, 2, wxRA_SPECIFY_ROWS); + wxString angle[2] = { _T("Relative"), _T("Absolute") }; + m_RotationDisplay = new wxRadioBox(this, Rotation_ID, _T("Rotation Display"), + wxDefaultPosition, wxDefaultSize, 2, angle, 2, wxRA_SPECIFY_ROWS ); + + displayH->Add(m_SplineDisplay, 0); + displayH->Add(m_RotationDisplay, 0); + m_Sizer->Add(displayH, 0, wxTop | wxALIGN_CENTER, 10); + m_Sizer->Add(m_DrawAll, 0); + m_Sizer->Add(m_DrawCurrent, 0); + + } + void Update(const sCinemaPath& path) + { + m_ModeBox->SetSelection(path.mode); + m_StyleBox->SetSelection(path.style); + float growth = path.growth; //wxFormat doesn't like to share(able) + float change = path.change; + m_Growth->SetValue( wxString::Format(L"%f", growth) ); + m_Switch->SetValue( wxString::Format(L"%f", change) ); + UpdateOldIndex(); + CinemaTextFloat(*m_Growth, 2, 0.f, 10.f, m_OldGrowth); + CinemaTextFloat(*m_Switch, 2, 0.f, 10.f, m_OldSwitch); + } + void OnChange(wxCommandEvent& WXUNUSED(event)) + { + m_OldGrowth = CinemaTextFloat(*m_Growth, 2, 0.f, 10.f, m_OldGrowth); + m_OldSwitch = CinemaTextFloat(*m_Switch, 2, 0.f, 10.f, m_OldSwitch); + UpdateOldIndex(); + m_Sidebar->UpdatePathInfo( m_ModeBox->GetSelection(), + m_StyleBox->GetSelection(), m_OldGrowth, m_OldSwitch, + m_DrawAll->IsChecked(), m_DrawCurrent->IsChecked(), + m_SplineDisplay->GetSelection()!=0 ); + } + void OnRotation(wxCommandEvent& WXUNUSED(event)) + { + m_Sidebar->m_RotationAbsolute = m_RotationDisplay->GetSelection()!=0; + m_Sidebar->UpdateSpinners(); + } + void UpdateOldIndex() + { + if ( m_Sidebar->GetSelectedTrack() != m_OldTrackIndex ) + { + m_OldTrackIndex = m_Sidebar->GetSelectedTrack(); + m_OldGrowth = m_OldSwitch = 0.f; + } + } + bool GetDrawAll() { return m_DrawAll->IsChecked(); } + bool GetDrawCurrent() { return m_DrawCurrent->IsChecked(); } + bool GetDrawLines() { return m_SplineDisplay->GetSelection()!=0; } + +private: + wxBoxSizer* m_Sizer; + CinematicSidebar* m_Sidebar; + wxRadioBox* m_ModeBox, *m_StyleBox, *m_RotationDisplay, *m_SplineDisplay; + wxTextCtrl* m_Growth, *m_Switch; + wxCheckBox* m_DrawAll, *m_DrawCurrent; + + float m_OldGrowth, m_OldSwitch; + ssize_t m_OldTrackIndex; + DECLARE_EVENT_TABLE(); +}; +BEGIN_EVENT_TABLE(CinemaInfoBox, wxPanel) +EVT_RADIOBOX(CinemaInfoBox::Mode_ID, CinemaInfoBox::OnChange) +EVT_RADIOBOX(CinemaInfoBox::Style_ID, CinemaInfoBox::OnChange) +EVT_RADIOBOX(CinemaInfoBox::Spline_ID, CinemaInfoBox::OnChange) +EVT_CHECKBOX(wxID_ANY, CinemaInfoBox::OnChange) +EVT_RADIOBOX(CinemaInfoBox::Rotation_ID, CinemaInfoBox::OnRotation) +EVT_TEXT_ENTER(wxID_ANY, CinemaInfoBox::OnChange) +END_EVENT_TABLE() + +class PathSlider; +class CinemaSliderBox; + +class TrackSlider : public wxSlider +{ + static const int range=1024; +public: + TrackSlider(CinematicSidebar* side, CinemaSliderBox* parent) + : wxSlider((wxWindow*)parent, wxID_ANY, 0, 0, range), + m_Sidebar(side), m_Parent(parent) + { + } + void OnScroll(wxScrollEvent& event); + void Update(float interval); + void SetPathSlider(PathSlider* slider) + { + m_Path = slider; + } + +private: + PathSlider* m_Path; + CinematicSidebar* m_Sidebar; + CinemaSliderBox* m_Parent; + + DECLARE_EVENT_TABLE(); +}; +BEGIN_EVENT_TABLE(TrackSlider, wxSlider) + EVT_SCROLL(OnScroll) +END_EVENT_TABLE() + +class PathSlider : public wxSlider +{ + static const int range=1024; +public: + PathSlider(CinematicSidebar* side, wxWindow* parent) + : wxSlider(parent, wxID_ANY, 0, 0, range, wxDefaultPosition, + wxDefaultSize, wxSL_HORIZONTAL, wxDefaultValidator, _("Path")), + m_Sidebar(side) + { + } + + void OnScroll(wxScrollEvent& WXUNUSED(event)); + + void SetTrackSlider(TrackSlider* slider) + { + m_Track = slider; + } +private: + TrackSlider* m_Track; + CinematicSidebar* m_Sidebar; + + DECLARE_EVENT_TABLE(); +}; +BEGIN_EVENT_TABLE(PathSlider, wxSlider) + EVT_SCROLL(OnScroll) +END_EVENT_TABLE() + +class CinemaSliderBox : public wxPanel +{ +public: + CinemaSliderBox(CinematicSidebar* parent, const wxString& label) + : wxPanel(parent), m_Sidebar(parent), m_OldTime(0), m_NewTime(0) + { + m_Sizer = new wxStaticBoxSizer(wxVERTICAL, this, label); + SetSizer(m_Sizer); + m_Path = new PathSlider(parent, this); + m_Track = new TrackSlider(parent, this); + m_Path->SetTrackSlider(m_Track); + m_Track->SetPathSlider(m_Path); + + m_Sizer->Add(m_Track, 0); + m_Sizer->Add(m_Path, 0); + + m_Timer = new wxTimer(this, wxID_ANY); + } + void Update() + { + m_Track->Update(0); + } + void OnTick(wxTimerEvent& WXUNUSED(event)) + { + m_NewTime = m_HighResTimer.GetTime(); + m_Track->Update(m_NewTime - m_OldTime); + m_OldTime = m_NewTime; + } + void PrepareTimers() + { + m_OldTime = m_NewTime = m_HighResTimer.GetTime(); + m_Timer->Start(10); + } + void Reset() + { + m_Track->SetValue(0); + m_Path->SetValue(0); + } + + float m_OldTime; + float m_NewTime; + wxTimer* m_Timer; +private: + TrackSlider* m_Track; + HighResTimer m_HighResTimer; + PathSlider* m_Path; + wxStaticBoxSizer* m_Sizer; + CinematicSidebar* m_Sidebar; + + DECLARE_EVENT_TABLE(); +}; +BEGIN_EVENT_TABLE(CinemaSliderBox, wxPanel) + EVT_TIMER(wxID_ANY, OnTick) +END_EVENT_TABLE() + +void TrackSlider::OnScroll(wxScrollEvent& WXUNUSED(event)) +{ + //Move path and send movement message + m_Sidebar->m_SliderBox->m_Timer->Stop(); + if ( m_Sidebar->m_SelectedTrack < 0 || m_Sidebar->m_SelectedPath < 0 ) + { + SetValue(0); + return; + } + float ratio = (float)GetValue() / (float)range; + float time = ratio * m_Sidebar->m_Tracks[m_Sidebar->m_SelectedTrack].duration; + + POST_MESSAGE(CinemaEvent, + ( *m_Sidebar->m_Tracks[m_Sidebar->m_SelectedTrack].name, + eCinemaEventMode::IMMEDIATE_TRACK, time, + m_Sidebar->m_InfoBox->GetDrawAll(), m_Sidebar->m_InfoBox->GetDrawCurrent(), + m_Sidebar->m_InfoBox->GetDrawLines() ) ); + + m_Sidebar->m_AbsoluteTime = time; + m_Path->SetValue( (int)( m_Sidebar->UpdateSelectedPath() / + m_Sidebar->GetCurrentPath().duration * range ) ); +} +void PathSlider::OnScroll(wxScrollEvent& WXUNUSED(event)) +{ + m_Sidebar->m_SliderBox->m_Timer->Stop(); + if ( m_Sidebar->m_SelectedTrack < 0 || m_Sidebar->m_SelectedPath < 0 ) + { + SetValue(0); + return; + } + //Move path and send movement message + float ratio = (float)GetValue() / (float)range; + float time = ratio * m_Sidebar->GetCurrentPath().duration; + float trackTime = m_Sidebar->m_AbsoluteTime / m_Sidebar-> + m_Tracks[m_Sidebar->m_SelectedTrack].duration * range; + m_Sidebar->m_AbsoluteTime += time - m_Sidebar->m_TimeElapsed; + m_Sidebar->m_TimeElapsed = time; + + m_Track->SetValue( trackTime ); + POST_MESSAGE(CinemaEvent, + ( *m_Sidebar->m_Tracks[m_Sidebar->m_SelectedTrack].name, + eCinemaEventMode::IMMEDIATE_TRACK, trackTime, + m_Sidebar->m_InfoBox->GetDrawAll(), m_Sidebar->m_InfoBox->GetDrawCurrent(), + m_Sidebar->m_InfoBox->GetDrawLines()) ); + +} + +void TrackSlider::Update(float interval) +{ + if ( m_Sidebar->m_SelectedTrack < 0 || m_Sidebar->m_SelectedPath < 0 ) + { + SetValue(0); + return; + } + interval *= m_Sidebar->m_Tracks[m_Sidebar->m_SelectedTrack].timescale; + m_Sidebar->m_AbsoluteTime += interval; + int move = m_Sidebar->m_AbsoluteTime / m_Sidebar->m_Tracks + [m_Sidebar->m_SelectedTrack].duration * (float)range; + if ( move > range ) + move = range; + SetValue( move ); + m_Path->SetValue( (int)( m_Sidebar->UpdateSelectedPath() / + m_Sidebar->GetCurrentPath().duration * range ) ); + + if ( move == range && m_Sidebar->m_Playing ) + { + m_Parent->m_Timer->Stop(); + SetValue(0); + m_Path->SetValue(0); + m_Sidebar->GotoNode(0); + m_Sidebar->m_Playing = false; + } +} +////////////////////////////////////////////////////////////////////////// + +class CinemaButtonBox : public wxPanel +{ +public: + CinemaButtonBox(CinematicSidebar* parent) : wxPanel(parent), m_Parent(parent) + { + m_Sizer = new wxStaticBoxSizer(wxHORIZONTAL, this); + SetSizer(m_Sizer); + } + void Add(wxBitmapButton* button) + { + m_Sizer->Add(button); + } + void OnPrevious(wxCommandEvent& WXUNUSED(event)) + { + if ( m_Parent->m_SelectedTrack < 0 ) + return; + m_Parent->m_SliderBox->m_Timer->Stop(); + m_Parent->m_Playing = false; + std::wstring name=*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name; + + if ( m_Parent->m_SelectedPath > 0 && m_Parent->m_TimeElapsed + < CINEMA_EPSILON) + { + m_Parent->SelectPath(m_Parent->m_SelectedPath-1); + float t = -m_Parent->GetCurrentPath().duration; + m_Parent->m_AbsoluteTime += t; + m_Parent->m_TimeElapsed = 0.f; + + POST_MESSAGE(CinemaEvent, + ( name, eCinemaEventMode::IMMEDIATE_PATH, t, + m_Parent->m_InfoBox->GetDrawAll(), m_Parent->m_InfoBox->GetDrawCurrent(), + m_Parent->m_InfoBox->GetDrawLines() ) ); + } + else + { + m_Parent->m_AbsoluteTime -= m_Parent->m_TimeElapsed; + m_Parent->m_TimeElapsed = 0.0f; + POST_MESSAGE(CinemaEvent, + ( name, eCinemaEventMode::IMMEDIATE_PATH, 0.0f, + m_Parent->m_InfoBox->GetDrawAll(), m_Parent->m_InfoBox->GetDrawCurrent(), + m_Parent->m_InfoBox->GetDrawLines()) ); + } + m_Parent->m_SliderBox->Update(); + } + //void OnRewind(wxCommandEvent& event) + + //void OnReverse(wxCommandEvent& event) + void OnStop(wxCommandEvent& WXUNUSED(event)) + { + if ( m_Parent->m_SelectedTrack < 0 || m_Parent->m_SelectedPath < 0) + return; + m_Parent->m_SliderBox->m_Timer->Stop(); + m_Parent->m_Playing = false; + m_Parent->m_AbsoluteTime = m_Parent->m_TimeElapsed = 0.0f; + m_Parent->SelectPath(0); + m_Parent->m_SliderBox->Update(); + + POST_MESSAGE(CinemaEvent, + (*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name, + eCinemaEventMode::IMMEDIATE_TRACK, 0.0f, + m_Parent->m_InfoBox->GetDrawAll(), m_Parent->m_InfoBox->GetDrawCurrent(), + m_Parent->m_InfoBox->GetDrawLines()) ); + } + void OnPlay(wxCommandEvent& WXUNUSED(event)) + { + if ( m_Parent->m_SelectedTrack < 0 ) + return; + m_Parent->m_SliderBox->m_Timer->Stop(); + m_Parent->m_SliderBox->PrepareTimers(); + + POST_MESSAGE(CinemaEvent, + (*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name, + eCinemaEventMode::SMOOTH, 0.0f, + m_Parent->m_InfoBox->GetDrawAll(), m_Parent->m_InfoBox->GetDrawCurrent(), + m_Parent->m_InfoBox->GetDrawLines()) ); + + m_Parent->m_Playing = true; + } + void OnPause(wxCommandEvent& WXUNUSED(event)) + { + if ( m_Parent->m_SelectedTrack < 0 ) + return; + m_Parent->m_SliderBox->m_Timer->Stop(); + m_Parent->m_SliderBox->Reset(); + //m_Parent->m_NodeList->Thaw(); + m_Parent->m_Playing = false; + + POST_MESSAGE(CinemaEvent, + (*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name, + eCinemaEventMode::IMMEDIATE_PATH, m_Parent->m_TimeElapsed, + m_Parent->m_InfoBox->GetDrawAll(), m_Parent->m_InfoBox->GetDrawCurrent(), + m_Parent->m_InfoBox->GetDrawLines()) ); + } + //void OnForward(wxCommandEvent& event) + void OnNext(wxCommandEvent& WXUNUSED(event)) + { + m_Parent->m_SliderBox->m_Timer->Stop(); + m_Parent->m_Playing = false; + std::wstring name=*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name; + sCinemaPath path = m_Parent->GetCurrentPath(); + float t = path.duration - m_Parent->m_TimeElapsed; + + if ( m_Parent->m_SelectedPath < (ssize_t)m_Parent->m_Tracks + [m_Parent->m_SelectedTrack].paths.GetSize()-1 ) + { + m_Parent->SelectPath(m_Parent->m_SelectedPath+1); + m_Parent->m_TimeElapsed = 0.f; + } + else + m_Parent->m_TimeElapsed = path.duration; + m_Parent->m_AbsoluteTime += t; + + POST_MESSAGE(CinemaEvent, + ( name, eCinemaEventMode::IMMEDIATE_PATH, path.duration+CINEMA_EPSILON, + m_Parent->m_InfoBox->GetDrawAll(), m_Parent->m_InfoBox->GetDrawCurrent(), + m_Parent->m_InfoBox->GetDrawLines()) ); + + m_Parent->m_SliderBox->Update(); + } + CinematicSidebar* m_Parent; + wxStaticBoxSizer* m_Sizer; + DECLARE_EVENT_TABLE(); }; +BEGIN_EVENT_TABLE(CinemaButtonBox, wxPanel) + EVT_BUTTON(eCinemaButton::previous, CinemaButtonBox::OnPrevious) + //EVT_BUTTON(eCinemaButton::rewind, CinemaButtonBox::OnRewind) + //EVT_BUTTON(eCinemaButton::reverse, CinemaButtonBox::OnReverse) + EVT_BUTTON(eCinemaButton::stop, CinemaButtonBox::OnStop) + EVT_BUTTON(eCinemaButton::play, CinemaButtonBox::OnPlay) + EVT_BUTTON(eCinemaButton::pause, CinemaButtonBox::OnPause) +// EVT_BUTTON(eCinemaButton::forward, CinemaButtonBox::OnForward) + EVT_BUTTON(eCinemaButton::next, CinemaButtonBox::OnNext) +END_EVENT_TABLE() ////////////////////////////////////////////////////////////////////////// CinematicSidebar::CinematicSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer) -: Sidebar(sidebarContainer, bottomBarContainer), -m_SelectedTrack(-1), m_SelectedPath(-1), m_SelectedSplineNode(-1) +: Sidebar(sidebarContainer, bottomBarContainer), m_SelectedTrack(-1), +m_SelectedPath(-1), m_SelectedSplineNode(-1), m_TimeElapsed(0.f), +m_AbsoluteTime(0.f), m_RotationAbsolute(false), m_UpdatePathEcho(false), +m_Playing(false) { - m_TrackList = new TrackListCtrl(this); - m_MainSizer->Add(m_TrackList, wxSizerFlags().Expand().Proportion(1)); - - m_PathList = new PathListCtrl(this); - m_MainSizer->Add(m_PathList, wxSizerFlags().Expand().Proportion(1)); - - m_BottomBar = new CinematicBottomBar(bottomBarContainer); + m_SliderBox = new CinemaSliderBox(this, _T("Timeline")); + m_MainSizer->Add(m_SliderBox, 0, wxALIGN_CENTER); + m_IconSizer = new CinemaButtonBox(this); + LoadIcons(); //do this here; buttons must be added before box is + m_MainSizer->Add(m_IconSizer, 0, wxALIGN_CENTER); + m_InfoBox = new CinemaInfoBox(this); + m_MainSizer->Add(m_InfoBox, 0, wxALIGN_CENTER); + + CinematicBottomBar* bottom = new CinematicBottomBar(bottomBarContainer, this); + m_BottomBar = bottom; + m_CinemaBottomBar = bottom; //avoid casting later + m_TrackList = new TrackListCtrl(bottom, this); + m_PathList = new PathListCtrl(bottom, this); + m_NodeList = new NodeListCtrl(bottom, this); + bottom->AddLists(this, m_TrackList, m_PathList, m_NodeList); } void CinematicSidebar::OnFirstDisplay() { qGetCinemaTracks qry; qry.Post(); - m_Tracks = *qry.tracks; m_TrackList->Freeze(); @@ -122,18 +1014,23 @@ void CinematicSidebar::OnFirstDisplay() m_TrackList->InsertItem((long)track, wxString(m_Tracks[track].name.c_str())); } m_TrackList->Thaw(); -} + +} void CinematicSidebar::SelectTrack(ssize_t n) { if (n == -1) { - m_PathList->DeleteAllItems(); + m_SelectedTrack = -1; + SelectPath(-1); + return; } else { wxCHECK_RET (n >= 0 && n < (ssize_t)m_Tracks.size(), _T("SelectTrack out of bounds")); - + + m_SelectedTrack = n; + SelectPath(-1); m_PathList->Freeze(); m_PathList->DeleteAllItems(); @@ -142,15 +1039,13 @@ void CinematicSidebar::SelectTrack(ssize_t n) std::vector paths = *m_Tracks[n].paths; for (size_t path = 0; path < paths.size(); ++path) { - m_PathList->InsertItem((long)path, wxString::Format(_("Path #%d"), path+1)); + m_PathList->InsertItem((long)path, wxString::Format(_("Path %d"), path)); } } - m_PathList->Thaw(); } - m_SelectedTrack = n; - SelectPath(-1); + UpdateSpinners(); } void CinematicSidebar::SelectPath(ssize_t n) @@ -158,21 +1053,482 @@ void CinematicSidebar::SelectPath(ssize_t n) if (n == -1 || m_SelectedTrack == -1) { m_PathList->DeleteAllItems(); + //Do this here to avoid thinking that there's still a path + m_SelectedPath = n; + SelectSplineNode(-1); + return; } else { std::vector paths = *m_Tracks[m_SelectedTrack].paths; - wxCHECK_RET (n >= 0 && n < (ssize_t)paths.size(), _T("SelectPath out of bounds")); + ssize_t size = (ssize_t)paths.size(); + wxCHECK_RET (n >= 0 && n < size, _T("SelectPath out of bounds")); + + m_SelectedPath = n; + SelectSplineNode(-1); + m_NodeList->Freeze(); + m_NodeList->DeleteAllItems(); - // TODO: modify the node-list (which doesn't yet exist) to contain - // the data about the selected path + if (n != -1) + { + std::vector nodes = *paths[n].nodes; + for ( size_t i=0; iInsertItem((long)i, wxString::Format(_("Node %d"), i)); + } + } + + m_NodeList->Thaw(); } - - m_SelectedPath = n; - SelectSplineNode(-1); + POST_MESSAGE(CinemaEvent, ( *GetCurrentTrack()->name, + eCinemaEventMode::SELECT, (int)m_SelectedPath, m_InfoBox->GetDrawAll(), + m_InfoBox->GetDrawCurrent(), m_InfoBox->GetDrawLines() )); + + UpdateSpinners(); } -void CinematicSidebar::SelectSplineNode(ssize_t n) +void CinematicSidebar::SelectSplineNode(ssize_t n, ssize_t size) { - // TODO: modify the controls that allow modification of this node + if (n == -1 || m_SelectedPath == -1) + { + m_NodeList->DeleteAllItems(); + } + else + wxCHECK_RET (n < size, _T("SelectNode out of bounds")); + m_SelectedSplineNode = n; + UpdateSpinners(); +} +const sCinemaTrack* CinematicSidebar::GetCurrentTrack() +{ + return &m_Tracks[m_SelectedTrack]; +} +sCinemaPath CinematicSidebar::GetCurrentPath() +{ + if ( m_SelectedPath < 0 ) + { + wxFAIL_MSG(L"CurrentPath() request out of range. The game will attempt to continue."); + return sCinemaPath(); + } + return (*m_Tracks[m_SelectedTrack].paths)[m_SelectedPath]; +} +sCinemaSplineNode CinematicSidebar::GetCurrentNode() +{ + return (* (*m_Tracks[m_SelectedTrack].paths)[m_SelectedPath].nodes ) + [m_SelectedSplineNode]; +} +//copied from sectionlayout's addpage() +wxImage CinematicSidebar::LoadIcon(const wxString& filename) +{ + wxImage img (1, 1, true); + + // Load the icon + wxFileName iconPath (_T("mods/official/art/textures/ui/session/icons/single/atlas/")); + iconPath.MakeAbsolute(Datafile::GetDataDirectory()); + iconPath.SetFullName(filename); + wxFileInputStream fstr (iconPath.GetFullPath()); + if (! fstr.Ok()) + { + wxLogError(_("Failed to open cinematic icon file '%s'"), iconPath.GetFullPath()); + } + else + { + img = wxImage(fstr, wxBITMAP_TYPE_BMP); + if (! img.Ok()) + { + wxLogError(_("Failed to load cinematic icon image '%s'"), iconPath.GetFullPath()); + img = wxImage (1, 1, true); + } + } + return img; +} +void CinematicSidebar::LoadIcons() +{ + wxBitmapButton* previous = new wxBitmapButton(m_IconSizer, + eCinemaButton::previous, LoadIcon( _T("previous_s.bmp") )); + m_IconSizer->Add(previous); + wxBitmapButton* stop = new wxBitmapButton(m_IconSizer, + eCinemaButton::stop, LoadIcon( _T("stop_s.bmp") )); + m_IconSizer->Add(stop); + wxBitmapButton* play = new wxBitmapButton(m_IconSizer, + eCinemaButton::play, LoadIcon( _T("play_s.bmp") )); + m_IconSizer->Add(play); + wxBitmapButton* pause = new wxBitmapButton(m_IconSizer, + eCinemaButton::pause, LoadIcon( _T("pause_s.bmp") )); + m_IconSizer->Add(pause); + wxBitmapButton* next = new wxBitmapButton(m_IconSizer, + eCinemaButton::next, LoadIcon( _T("next_s.bmp") )); + m_IconSizer->Add(next); +} +void CinematicSidebar::AddTrack(float x, float y, float z, + std::wstring& name, int count) +{ + m_Tracks.push_back(sCinemaTrack(x, y, z, name)); + SelectPath(-1); + SelectTrack(count); + UpdateEngineData(); +} +void CinematicSidebar::AddPath(int x, int y, int z, int count) //rotation +{ + if ( m_SelectedTrack < 0 ) + return; + std::vector paths=*m_Tracks[m_SelectedTrack].paths; + + //x, y, and z should always be absolute, so adjust here + if ( count == 0 ) + { + paths.push_back( sCinemaPath(x - m_Tracks[m_SelectedTrack].x, + y-m_Tracks[m_SelectedTrack].y, z-m_Tracks[m_SelectedTrack].z) ); + } + else + { + int x2 = paths[count-1].x, y2 = paths[count-1].y, + z2 = paths[count-1].z; + GetAbsoluteRotation(x2, y2, z2, count-1); + paths.push_back( sCinemaPath(x - x2, y - y2, z - z2) ); + } + + m_Tracks[m_SelectedTrack].paths = paths; + SelectSplineNode(-1); + SelectPath(count); + UpdateEngineData(); +} +void CinematicSidebar::AddNode(float x, float y, float z, int count) +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 ) + return; + + std::vector paths=*m_Tracks[m_SelectedTrack].paths; + std::vector nodes=*(*m_Tracks[m_SelectedTrack].paths) + [m_SelectedPath].nodes; + nodes.push_back(sCinemaSplineNode(x, y, z)); + paths[m_SelectedPath].nodes = nodes; + m_Tracks[m_SelectedTrack].paths = paths; + UpdateEngineData(); + SelectSplineNode(count, count+1); +} +void CinematicSidebar::DeleteTrack() +{ + m_Tracks.erase( m_Tracks.begin() + m_SelectedTrack ); + ssize_t size = (ssize_t)m_Tracks.size(); + + m_SelectedPath = -1; + m_SelectedSplineNode = -1; + if ( size == 0 ) + SelectTrack(-1); + else if ( m_SelectedTrack > size-1 ) + SelectTrack(size-1); + else + SelectTrack(m_SelectedTrack); + + UpdateEngineData(); +} +void CinematicSidebar::DeletePath() +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 ) + return; + std::vector paths = *m_Tracks[m_SelectedTrack].paths; + paths.erase( paths.begin() + m_SelectedPath ); + m_Tracks[m_SelectedTrack].paths = paths; + ssize_t size = (ssize_t)paths.size(); + + m_SelectedSplineNode = -1; + if ( size == 0 ) + SelectPath(-1); + else if ( m_SelectedPath > size-1 ) + SelectPath(size-1); + else + SelectPath(m_SelectedPath); + + SelectTrack(m_SelectedTrack); + UpdateEngineData(); +} +void CinematicSidebar::DeleteNode() +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 || + m_SelectedSplineNode < 0 ) + { + return; + } + std::vector paths = *m_Tracks[m_SelectedTrack].paths; + std::vector nodes = *paths[m_SelectedPath].nodes; + m_Tracks[m_SelectedTrack].duration = m_Tracks[m_SelectedTrack].duration - + nodes[m_SelectedSplineNode].t; + paths[m_SelectedPath].duration = paths[m_SelectedPath].duration - + nodes[m_SelectedSplineNode].t; + + if ( m_AbsoluteTime > m_Tracks[m_SelectedTrack].duration ) + m_AbsoluteTime = m_Tracks[m_SelectedTrack].duration; + if ( m_TimeElapsed > paths[m_SelectedPath].duration ) + m_TimeElapsed = paths[m_SelectedPath].duration; + + nodes.erase( nodes.begin() + m_SelectedSplineNode ); + paths[m_SelectedPath].nodes = nodes; + m_Tracks[m_SelectedTrack].paths = paths; + ssize_t size = (ssize_t)nodes.size(); + + if ( size == 0 ) + SelectSplineNode(-1); + else if ( m_SelectedSplineNode > size-1 ) + SelectSplineNode(size-1, size); + else + SelectSplineNode(m_SelectedSplineNode, size); + SelectPath(m_SelectedPath); //Correct numbering + UpdateEngineData(); + +} + +void CinematicSidebar::UpdateTrack(std::wstring name, float timescale) +{ + if ( m_SelectedTrack < 0 ) + return; + m_Tracks[m_SelectedTrack].name = name; + m_Tracks[m_SelectedTrack].timescale = timescale; + m_TrackList->SetItemText(m_SelectedTrack, wxString(name.c_str())); + UpdateEngineData(); +} +void CinematicSidebar::UpdateTrack(float x, float y, float z) +{ + if ( m_SelectedTrack < 0 ) + return; + + m_Tracks[m_SelectedTrack].x = x; + m_Tracks[m_SelectedTrack].y = y; + m_Tracks[m_SelectedTrack].z = z; + + if ( m_Tracks[m_SelectedTrack].paths.GetSize() > 0 ) + { + //Recalculate relative rotation for path + int x, y, z; + bool marker = m_RotationAbsolute; + m_RotationAbsolute = false; + GetAbsoluteRotation(x, y, z, 0); + //(Track rotation is always absolute) + UpdatePath(x-m_Tracks[m_SelectedTrack].x, y-m_Tracks[m_SelectedTrack].y, + z - m_Tracks[m_SelectedTrack].z, 0); + m_RotationAbsolute = marker; + } + + UpdateEngineData(); +} +void CinematicSidebar::UpdatePath(int x, int y, int z, ssize_t index) +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 ) + return; + if ( index < 0 ) + index = m_SelectedPath; + + std::vector paths=*m_Tracks[m_SelectedTrack].paths; + + //Convert to relative rotation + if ( m_RotationAbsolute ) + { + if ( index == 0 ) + { + paths[index].x = x - m_Tracks[m_SelectedTrack].x; + paths[index].y = y - m_Tracks[m_SelectedTrack].y; + paths[index].z = z - m_Tracks[m_SelectedTrack].z; + } + else + { + int x2, y2, z2; + GetAbsoluteRotation(x2, y2, z2); + paths[index].x = x - x2; + paths[index].y = y - y2; + paths[index].z = z - z2; + } + } + else + { + paths[index].x = x; + paths[index].y = y; + paths[index].z = z; + } + + if ( index != (ssize_t)paths.size()-1 && !m_UpdatePathEcho ) + { + //Recalculate relative rotation for path + m_Tracks[m_SelectedTrack].paths = paths; + int x2, y2, z2; + bool marker = m_RotationAbsolute; + m_RotationAbsolute = false; + GetAbsoluteRotation(x, y, z, index); + GetAbsoluteRotation(x2, y2, z2, index+1); + + m_UpdatePathEcho = true; + UpdatePath(x2 - x, y2 - y, z2 - z, m_SelectedPath+1); + m_RotationAbsolute = marker; + } + else if ( m_UpdatePathEcho ) + m_UpdatePathEcho = false; + + + m_Tracks[m_SelectedTrack].paths = paths; + UpdateEngineData(); +} +void CinematicSidebar::UpdateNode(float x, float y, float z, float t) +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 || + m_SelectedSplineNode < 0 ) + { + return; + } + else if ( m_SelectedSplineNode == 0 ) + { + wxBell(); //Let them know: the first node has no meaning + return; + } + std::vector paths=*m_Tracks[m_SelectedTrack].paths; + std::vector nodes=*(*m_Tracks[m_SelectedTrack].paths) + [m_SelectedPath].nodes; + if ( t < 0 ) + t = nodes[m_SelectedSplineNode].t; + sCinemaSplineNode newNode(x, y, z); + newNode.SetTime(t); + float delta = newNode.t - nodes[m_SelectedSplineNode].t; + paths[m_SelectedPath].duration = paths[m_SelectedPath].duration + + delta; + m_Tracks[m_SelectedTrack].duration = m_Tracks[m_SelectedTrack] + .duration + delta; + + nodes[m_SelectedSplineNode] = newNode; + paths[m_SelectedPath].nodes = nodes; + m_Tracks[m_SelectedTrack].paths = paths; + UpdateEngineData(); +} +void CinematicSidebar::UpdateSpinners() +{ + if ( m_SelectedTrack < 0 ) + return; + int x = m_Tracks[m_SelectedTrack].x, y = m_Tracks[m_SelectedTrack].y, + z = m_Tracks[m_SelectedTrack].z; + m_SpinnerBox->UpdateTrackSpinners(x, y, z); + + if ( m_SelectedPath < 0 ) + return; + sCinemaPath path = GetCurrentPath(); + x = path.x, y = path.y, z = path.z; + + if ( m_RotationAbsolute ) + GetAbsoluteRotation(x, y, z); + m_SpinnerBox->UpdatePathSpinners(x, y, z); + + if ( m_SelectedSplineNode < 0 ) + return; + + sCinemaSplineNode node = (*path.nodes)[m_SelectedSplineNode]; + x = node.x, y = node.y, z = node.z; + float t = node.t; + m_SpinnerBox->UpdateNodeSpinners(x, y, z, t, m_SelectedSplineNode); +} +void CinematicSidebar::UpdateTexts() +{ + if ( m_SelectedTrack < 0 ) + return; + + m_CinemaBottomBar->Update(* m_Tracks[m_SelectedTrack].name, + m_Tracks[m_SelectedTrack].timescale ); + if ( m_SelectedPath >= 0 ) + { + sCinemaPath path = GetCurrentPath(); + m_InfoBox->Update(path); + } +} +void CinematicSidebar::UpdatePathInfo(int mode, int style, float growth, + float change, bool drawAll, bool drawCurrent, bool drawLine) +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 ) + return; + std::vector paths = *m_Tracks[m_SelectedTrack].paths; + paths[m_SelectedPath].mode = mode; + paths[m_SelectedPath].style = style; + paths[m_SelectedPath].growth = growth; + paths[m_SelectedPath].change = change; + m_Tracks[m_SelectedTrack].paths = paths; + UpdateEngineData(); + POST_MESSAGE( CinemaEvent, (*m_Tracks[m_SelectedTrack].name, + eCinemaEventMode::SELECT, (int)m_SelectedPath, drawAll, + drawCurrent, drawLine) ); +} +void CinematicSidebar::UpdateEngineData() +{ + POST_COMMAND(SetCinemaTracks, (m_Tracks) ); + UpdateSpinners(); +} +void CinematicSidebar::GotoNode(ssize_t index) +{ + if ( m_SelectedTrack < 0 || m_SelectedPath < 0 || + m_SelectedSplineNode < 0 ) + { + return; + } + if ( index < 0 ) + index = m_SelectedSplineNode; + + std::vector paths=*m_Tracks[m_SelectedTrack].paths; + std::vector nodes=*(*m_Tracks[m_SelectedTrack].paths) + [m_SelectedPath].nodes; + float nodeTime=0; + float pathTime=0; + for ( ssize_t i=0; i<=index; ++i ) + nodeTime += nodes[i].t; + for ( ssize_t i=0; iGetDrawAll(), m_InfoBox->GetDrawCurrent(), + m_InfoBox->GetDrawLines() ) ); + //this is just an echo if false + if ( m_AbsoluteTime / m_Tracks[m_SelectedTrack].duration + + CINEMA_EPSILON < 1.f || !m_Playing ) + { + m_SliderBox->Update(); + } +} + +void CinematicSidebar::GetAbsoluteRotation(int& x, int& y, int& z, ssize_t index) +{ + if ( index < 0 ) + index = m_SelectedPath; + if ( m_SelectedTrack < 0 || index < 0 ) + return; + + std::vector paths=*m_Tracks[m_SelectedTrack].paths; + sCinemaPath path; + for (ssize_t i=0; i <= index; ++i) + path = path + paths[i]; + + path.x = path.x + m_Tracks[m_SelectedTrack].x; + path.y = path.y + m_Tracks[m_SelectedTrack].y; + path.z = path.z + m_Tracks[m_SelectedTrack].z; + WrapCinemaPath(path); + x = path.x; + y = path.y; + z = path.z; +} + +float CinematicSidebar::UpdateSelectedPath() +{ + size_t i=0; + std::vectorpaths = *m_Tracks[m_SelectedTrack].paths; + for ( float time=0.0f; i < paths.size(); ++i ) + { + float duration = paths[i].duration; + time += duration; + if ( time > m_AbsoluteTime ) + { + static size_t index=(size_t)-1; + if ( index != i ) + { + SelectPath((ssize_t)i); + index = i; + } + m_TimeElapsed = m_AbsoluteTime-(time-duration); + return m_TimeElapsed; + } + } + return m_TimeElapsed; } \ No newline at end of file diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.h b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.h index 9675c22cb0..8e8500d4c8 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.h +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Cinematic/Cinematic.h @@ -1,15 +1,75 @@ +/* Andrew Decker, a.k.a pyrolink + Contact ajdecker1022@msn.com + Desc: receives user input and communicates with the engine + to perform various cinematic functions. +*/ + #include "../Common/Sidebar.h" #include "GameInterface/Messages.h" +class TrackListCtrl; +class PathListCtrl; +class NodeListCtrl; +class CinemaSliderBox; +class CinemaSpinnerBox; +class CinemaInfoBox; +class CinematicBottomBar; +class wxImage; + class CinematicSidebar : public Sidebar { + //For ease (from lazyness) + friend class CinemaButtonBox; + friend class TrackSlider; + friend class PathSlider; public: CinematicSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer); - + //The actual data is stored in bottom bar, but is controled from here void SelectTrack(ssize_t n); void SelectPath(ssize_t n); - void SelectSplineNode(ssize_t n); + //avoid excessive shareable->vector conversion with size paramater + void SelectSplineNode(ssize_t n, ssize_t size = -1); + + void AddTrack(float x, float y, float z, std::wstring& name, + int count); + void AddPath(int x, int y, int z, int count); + void AddNode(float x, float y, float z, int count); + void UpdateTrack(std::wstring name, float timescale); + void UpdateTrack(float x, float y, float z); + void UpdatePath(int x, int y, int z, ssize_t index=-1); + void UpdateNode(float x, float y, float z, float t=-1); + + void DeleteTrack(); + void DeletePath(); + void DeleteNode(); + + void SetSpinners(CinemaSpinnerBox* box) { m_SpinnerBox = box; } + + const AtlasMessage::sCinemaTrack* GetCurrentTrack(); + AtlasMessage::sCinemaPath GetCurrentPath(); + AtlasMessage::sCinemaSplineNode GetCurrentNode(); + + int GetSelectedTrack() { return m_SelectedTrack; } + int GetSelectedPath() { return m_SelectedPath; } + int GetSelectedNode() { return m_SelectedSplineNode; } + + void GotoNode(ssize_t index=-1); + void GetAbsoluteRotation(int& x, int& y, int& z, ssize_t index=-1); + + float UpdateSelectedPath(); + void UpdatePathInfo(int mode, int style, float growth, float change, + bool drawAll, bool drawCurrent, bool drawLine); + void UpdateSpinners(); + void UpdateTexts(); + void UpdateEngineData(); + + float m_TimeElapsed; //path time + float m_AbsoluteTime; //track time + + bool m_RotationAbsolute; //rotation display flag in spinner box + bool m_UpdatePathEcho; + bool m_Playing; protected: virtual void OnFirstDisplay(); @@ -18,11 +78,28 @@ private: // Stores all cinematics data for this map. Initialised by OnFirstDisplay. // Sent back to the game by [TODO]. (TODO: handle 'undo' correctly) std::vector m_Tracks; + CinemaButtonBox* m_IconSizer; ssize_t m_SelectedTrack; // -1 for none ssize_t m_SelectedPath; // -1 for none ssize_t m_SelectedSplineNode; // -1 for none + + TrackListCtrl* m_TrackList; + PathListCtrl* m_PathList; + NodeListCtrl* m_NodeList; - wxListCtrl* m_TrackList; - wxListCtrl* m_PathList; + CinemaSliderBox* m_SliderBox; + CinemaSpinnerBox* m_SpinnerBox; //We must update the display + CinemaInfoBox* m_InfoBox; // ^same^ + CinematicBottomBar* m_CinemaBottomBar; + + struct eCinemaButton + { + enum { + previous/*, rewind, reverse*/, stop, + play, pause, /*forward,*/ next }; + }; + + wxImage LoadIcon(const wxString& filename); + void LoadIcons(); }; diff --git a/source/tools/atlas/GameInterface/GameLoop.cpp b/source/tools/atlas/GameInterface/GameLoop.cpp index fa26d68f8f..19d693157f 100644 --- a/source/tools/atlas/GameInterface/GameLoop.cpp +++ b/source/tools/atlas/GameInterface/GameLoop.cpp @@ -199,8 +199,14 @@ bool BeginAtlas(int argc, char* argv[], void* dll) // Be nice to the processor (by sleeping lots) if we're not doing anything // useful, and nice to the user (by just yielding to other threads) if we are - - if (time - last_activity > 0.5) // if there was no recent activity... + bool yield = time - last_activity > 0.5; + if ( state.worldloaded ) + { + if ( g_Game->GetView()->GetCinema()->IsPlaying() ) + g_Game->GetView()->GetCinema()->Update(state.frameLength); + yield = false; + } + if (yield) // if there was no recent activity... { double sleepUntil = time + 0.5; // only redraw at 2fps while (time < sleepUntil) diff --git a/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp index 5425a73ea2..d8480f5c3a 100644 --- a/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp @@ -16,6 +16,8 @@ namespace AtlasMessage { MESSAGEHANDLER(ScrollConstant) { + if ( g_Game->GetView()->GetCinema()->IsPlaying() ) + return; if (msg->dir < 0 || msg->dir > 3) { debug_warn("ScrollConstant: invalid direction"); @@ -28,6 +30,8 @@ MESSAGEHANDLER(ScrollConstant) MESSAGEHANDLER(Scroll) { + if ( g_Game->GetView()->GetCinema()->IsPlaying() ) + return; static CVector3D targetPos; static float targetDistance = 0.f; @@ -75,11 +79,15 @@ MESSAGEHANDLER(Scroll) MESSAGEHANDLER(SmoothZoom) { + if ( g_Game->GetView()->GetCinema()->IsPlaying() ) + return; g_GameLoop->input.zoomDelta += msg->amount; } MESSAGEHANDLER(RotateAround) { + if ( g_Game->GetView()->GetCinema()->IsPlaying() ) + return; static CVector3D focusPos; static float lastX = 0.f, lastY = 0.f; diff --git a/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp b/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp index 4cbbc37084..ee581a4bfd 100644 --- a/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp +++ b/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp @@ -7,31 +7,33 @@ #include "ps/CStr.h" #include "ps/CLogger.h" #include "ps/VFSUtil.h" -#include "lib/res/graphics/tex.h" +#include "maths/Quaternion.h" +#include "lib/res/graphics/ogl_tex.h" #define LOG_CATEGORY "Cinema" namespace AtlasMessage { -sCinemaTrack ConstructCinemaTrack(const CCinemaTrack& _track) +sCinemaTrack ConstructCinemaTrack(const CCinemaTrack& data) { sCinemaTrack track; - const CVector3D& rotation = _track.GetRotation(); - track.x = rotation.X; - track.y = rotation.Y; - track.z = rotation.Z; - track.timescale = _track.GetTimeScale(); - track.duration = _track.GetTotalDuration(); + const CVector3D& rotation = data.GetRotation(); + track.x = RADTODEG(rotation.X); + track.y = RADTODEG(rotation.Y); + track.z = RADTODEG(rotation.Z); + track.timescale = data.GetTimescale(); + track.duration = data.GetTotalDuration(); return track; } -sCinemaPath ConstructCinemaPath(const CCinemaData* data) +sCinemaPath ConstructCinemaPath(const CCinemaPath* source) { sCinemaPath path; + const CCinemaData* data = source->GetData(); - path.x = data->m_TotalRotation.X; - path.y = data->m_TotalRotation.Y; - path.z = data->m_TotalRotation.Z; + path.x = RADTODEG(data->m_TotalRotation.X); + path.y = RADTODEG(data->m_TotalRotation.Y); + path.z = RADTODEG(data->m_TotalRotation.Z); path.mode = data->m_Mode; path.style = data->m_Style; path.growth = data->m_Growth; @@ -42,7 +44,8 @@ sCinemaPath ConstructCinemaPath(const CCinemaData* data) CCinemaData ConstructCinemaData(const sCinemaPath& path) { CCinemaData data; - data.m_TotalRotation = CVector3D(path.x, path.y, path.z); + data.m_TotalRotation = CVector3D(DEGTORAD(path.x), DEGTORAD(path.y), + DEGTORAD(path.z)); data.m_Growth = data.m_GrowthCount = path.growth; data.m_Switch = path.change; data.m_Mode = path.mode; @@ -77,7 +80,7 @@ std::vector GetCurrentTracks() for ( std::vector::const_iterator it2=paths.begin(); it2!=paths.end(); it2++ ) { - sCinemaPath path = ConstructCinemaPath(it2->GetData()); //Get data part of path + sCinemaPath path = ConstructCinemaPath(&*it2); const std::vector& nodes = it2->GetAllNodes(); std::vector atlasNodes; @@ -86,7 +89,19 @@ std::vector GetCurrentTracks() { atlasNodes.push_back( ConstructCinemaNode(nodes[i]) ); } + if ( !atlasNodes.empty() ) + { + float back = atlasNodes.back().t; + if ( atlasNodes.size() > 2 ) + { + for ( size_t i=atlasNodes.size()-2; i>0; --i ) + atlasNodes[i].t = atlasNodes[i-1].t; + } + atlasNodes.back().t = atlasNodes.front().t; + atlasNodes.front().t = back; + } path.nodes = atlasNodes; + path.duration = it2->GetDuration(); atlasPaths.push_back(path); } atlasTrack.paths = atlasPaths; @@ -102,77 +117,65 @@ void SetCurrentTracks(const std::vector& atlasTracks) { CStrW trackName(*it->name); tracks[trackName] = CCinemaTrack(); - tracks[trackName].SetStartRotation( CVector3D(it->x, it->y, it->z) ); - tracks[trackName].SetTimeScale(it->timescale); + tracks[trackName].SetStartRotation( CVector3D(DEGTORAD(it->x), + DEGTORAD(it->y), DEGTORAD(it->z)) ); + tracks[trackName].SetTimescale(it->timescale); const std::vector paths = *it->paths; - - for ( std::vector::const_iterator it2=paths.begin(); it2!=paths.end(); it2++ ) + size_t i=0; + + for ( std::vector::const_iterator it2=paths.begin(); + it2!=paths.end(); it2++, ++i ) { const sCinemaPath& atlasPath = *it2; const std::vector nodes = *atlasPath.nodes; TNSpline spline; CCinemaData data = ConstructCinemaData(atlasPath); - for ( size_t i=0; iGetView()->GetCinema()->SetAllTracks(tracks); } - -QUERYHANDLER(GetCinemaIcons) +QUERYHANDLER(GetCameraInfo) { - VFSUtil::FileList files; - VFSUtil::FindFiles("art/textures/ui/session/icons/cinematic/","", files); - FileIOBuf buf; - size_t bufsize; - std::vector iconList; + sCameraInfo info; + CMatrix3D* cam = &g_Game->GetView()->GetCamera()->m_Orientation; - for ( VFSUtil::FileList::iterator it=files.begin(); it != files.end(); it++ ) - { - if ( tex_is_known_extension(*it) ) - { - const char* file = it->c_str(); - - if ( vfs_load(file, buf, bufsize) < 0 ) - { - LOG( ERROR, LOG_CATEGORY, "Failure on loading cinematic icon %s", file ); - file_buf_free(buf); - continue; - } - sCinemaIcon icon; - std::wstring name( CStrW( *it->AfterLast("/").BeforeFirst(".").c_str() ) ); - std::vector data; - data.resize(sizeof(data)); - - //Copy the buffer to the icon - for ( size_t i=0; *buf++; i++ ) - { - data.push_back(*buf); - } - file_buf_free(buf); - icon.name = name; - icon.imageData = data; - iconList.push_back(icon); - } - } - msg->images = iconList; + CQuaternion quatRot = cam->GetRotation(); + quatRot.Normalize(); + CVector3D rotation = quatRot.ToEulerAngles(); + rotation.X = RADTODEG(rotation.X); + rotation.Y = RADTODEG(rotation.Y); + rotation.Z = RADTODEG(rotation.Z); + CVector3D translation = cam->GetTranslation(); + + info.pX = translation.X; + info.pY = translation.Y; + info.pZ = translation.Z; + info.rX = rotation.X; + info.rY = rotation.Y; + info.rZ = rotation.Z; + msg->info = info; } -MESSAGEHANDLER(CinemaMovement) +MESSAGEHANDLER(CinemaEvent) { CCinemaManager* manager = g_Game->GetView()->GetCinema(); - CCinemaTrack* track = manager->GetTrack(*msg->track); + manager->SetCurrentTrack(*msg->track, msg->drawAll, + msg->drawCurrent, msg->lines); - if ( msg->mode == eCinemaMovementMode::SMOOTH ) + if ( msg->mode == eCinemaEventMode::SMOOTH ) manager->OverrideTrack(*msg->track); - else if ( msg->mode == eCinemaMovementMode::IMMEDIATE_PATH ) - track->MoveToPointAt(msg->t); - else if ( msg->mode == eCinemaMovementMode::IMMEDIATE_TRACK ) - track->MoveToPointAbsolute(msg->t); + else if ( msg->mode == eCinemaEventMode::IMMEDIATE_PATH ) + manager->MoveToPointAt(msg->t); + else if ( msg->mode == eCinemaEventMode::IMMEDIATE_TRACK ) + manager->MoveToPointAbsolute(msg->t); + else + manager->SetCurrentPath((int)msg->t); } BEGIN_COMMAND(SetCinemaTracks) diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp index c7971c28b2..0f7f8b225b 100644 --- a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp @@ -110,7 +110,7 @@ MESSAGEHANDLER(SaveMap) writer.SaveMap(CStr(L"maps/scenarios/" + *msg->filename), g_Game->GetWorld()->GetTerrain(), g_Game->GetWorld()->GetUnitManager(), g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(), - &g_LightEnv, g_Game->GetView()->GetCamera()); + &g_LightEnv, g_Game->GetView()->GetCamera(), g_Game->GetView()->GetCinema()); } } diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h index 002031e362..bf22a47c27 100644 --- a/source/tools/atlas/GameInterface/Messages.h +++ b/source/tools/atlas/GameInterface/Messages.h @@ -279,6 +279,10 @@ COMMAND(SetObjectSettings, NOMERGE, struct sCinemaSplineNode { Shareable x, y, z, t; +public: + sCinemaSplineNode(float px, float py, float pz) : x(px), y(py), z(pz), t(0.0f){} + sCinemaSplineNode() {} + void SetTime(float _t) { t = _t; } }; SHAREABLE_STRUCT(sCinemaSplineNode); @@ -287,6 +291,22 @@ struct sCinemaPath Shareable > nodes; Shareable duration, x, y, z; Shareable mode, growth, change, style; //change == switch point + + sCinemaPath(float rx, float ry, float rz) : x(rx), y(ry), z(rz), + mode(0), style(0), change(0), growth(0), duration(0) {} + sCinemaPath() : x(0), y(0), z(0), mode(0), style(0), + change(0), growth(0), duration(0) {} + + AtlasMessage::sCinemaPath operator-(const AtlasMessage::sCinemaPath& path) + { + return AtlasMessage::sCinemaPath(x - path.x, y - path.y, + z - path.z); + } + AtlasMessage::sCinemaPath operator+(const AtlasMessage::sCinemaPath& path) + { + return AtlasMessage::sCinemaPath(x + path.x, y + path.y, + z + path.z); + } }; SHAREABLE_STRUCT(sCinemaPath); @@ -295,38 +315,44 @@ struct sCinemaTrack Shareable name; Shareable x, y, z, timescale, duration; Shareable > paths; + +public: + sCinemaTrack(float rx, float ry, float rz, std::wstring track) + : x(rx), y(ry), z(rz), timescale(1.f), duration(0) + { name = track; } + sCinemaTrack() : x(0), y(0), z(0), timescale(1.f), duration(0) {} }; SHAREABLE_STRUCT(sCinemaTrack); -struct eCinemaMovementMode { enum { SMOOTH, IMMEDIATE_PATH, IMMEDIATE_TRACK }; }; - -struct sCinemaIcon +struct eCinemaEventMode { enum { SMOOTH, SELECT, IMMEDIATE_PATH, + IMMEDIATE_TRACK }; }; +struct sCameraInfo { - Shareable name; - Shareable > imageData; + Shareable pX, pY, pZ, rX, rY, rZ; //position and rotation }; -SHAREABLE_STRUCT(sCinemaIcon); +SHAREABLE_STRUCT(sCameraInfo); QUERY(GetCinemaTracks, , //no input ((std::vector , tracks)) ); -QUERY(GetCinemaIcons, +QUERY(GetCameraInfo, , - ((std::vector, images)) + ((AtlasMessage::sCameraInfo, info)) ); - -COMMAND(SetCinemaTracks, MERGE, +COMMAND(SetCinemaTracks, NOMERGE, ((std::vector, tracks)) - ((float, timescale)) ); -MESSAGE(CinemaMovement, +MESSAGE(CinemaEvent, ((std::wstring, track)) ((int, mode)) ((float, t)) + ((bool, drawAll)) + ((bool, drawCurrent)) + ((bool, lines)) ); //////////////////////////////////////////////////////////////////////////