From 89aef0b6eb1b180fcb92075f35ac02fbb0ecf2fd Mon Sep 17 00:00:00 2001 From: Yves Date: Sun, 3 Jan 2016 12:41:04 +0000 Subject: [PATCH] Cinematic camera core functionality. Patch by Vladislav Belov. Based on existing code that was still around from an old(not working) implementation. Supports basic control from trigger scirpts (queue, start and stop camera paths) and works in multiplayer. This was SVN commit r17594. --- .../public/simulation/components/Trigger.js | 14 + source/collada/CommonConvert.cpp | 2 +- source/graphics/CinemaManager.cpp | 320 ++++++++++++++---- source/graphics/CinemaManager.h | 125 +++++-- source/graphics/CinemaPath.cpp | 186 ++++++---- source/graphics/CinemaPath.h | 74 ++-- source/graphics/GameView.cpp | 7 +- source/graphics/MapReader.cpp | 115 +++---- source/graphics/MapWriter.cpp | 30 +- source/lib/input.cpp | 2 +- source/maths/NUSpline.cpp | 65 ++-- source/maths/NUSpline.h | 22 +- source/ps/GameSetup/GameSetup.cpp | 8 + source/simulation2/MessageTypes.h | 25 ++ source/simulation2/TypeList.h | 5 + .../components/CCmpCinemaManager.cpp | 253 ++++++++++++++ .../components/CCmpOverlayRenderer.cpp | 2 +- .../simulation2/components/CCmpSelectable.cpp | 3 + .../components/CCmpTerritoryManager.cpp | 13 + .../components/ICmpCinemaManager.cpp | 28 ++ .../components/ICmpCinemaManager.h | 42 +++ .../components/ICmpOverlayRenderer.cpp | 2 + .../components/ICmpOverlayRenderer.h | 12 + .../simulation2/components/ICmpSelectable.cpp | 1 + .../simulation2/components/ICmpSelectable.h | 12 + .../components/ICmpTerritoryManager.h | 5 + .../scripting/MessageTypeConversions.cpp | 30 ++ .../simulation2/system/ComponentManager.cpp | 1 + .../GameInterface/Handlers/CinemaHandler.cpp | 43 ++- .../GameInterface/Handlers/MiscHandlers.cpp | 4 - 30 files changed, 1110 insertions(+), 341 deletions(-) create mode 100644 source/simulation2/components/CCmpCinemaManager.cpp create mode 100644 source/simulation2/components/ICmpCinemaManager.cpp create mode 100644 source/simulation2/components/ICmpCinemaManager.h diff --git a/binaries/data/mods/public/simulation/components/Trigger.js b/binaries/data/mods/public/simulation/components/Trigger.js index 3375d50b55..043c0aac0e 100644 --- a/binaries/data/mods/public/simulation/components/Trigger.js +++ b/binaries/data/mods/public/simulation/components/Trigger.js @@ -19,6 +19,8 @@ Trigger.prototype.eventNames = "Interval", "Range", "TreasureCollected", + "CinemaPathEnded", + "CinemaQueueEnded" ]; Trigger.prototype.Init = function() @@ -242,6 +244,18 @@ Trigger.prototype.OnGlobalResearchFinished = function(msg) // "tech": tech} }; +// Handles "OnCinemaPathEnded" event. +Trigger.prototype.OnGlobalCinemaPathEnded = function(msg) +{ + this.CallEvent("CinemaPathEnded", msg); +} + +// Handles "OnCinemaQueueEnded" event. +Trigger.prototype.OnGlobalCinemaQueueEnded = function(msg) +{ + this.CallEvent("CinemaQueueEnded", msg); +} + Trigger.prototype.OnGlobalOwnershipChanged = function(msg) { this.CallEvent("OwnershipChanged", msg); diff --git a/source/collada/CommonConvert.cpp b/source/collada/CommonConvert.cpp index 49497422bf..1f0a4745d0 100644 --- a/source/collada/CommonConvert.cpp +++ b/source/collada/CommonConvert.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2016 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify diff --git a/source/graphics/CinemaManager.cpp b/source/graphics/CinemaManager.cpp index 3d14db2f84..904be50def 100644 --- a/source/graphics/CinemaManager.cpp +++ b/source/graphics/CinemaManager.cpp @@ -18,98 +18,280 @@ #include "precompiled.h" -#include #include +#include -#include "CinemaManager.h" - -#include "CinemaPath.h" -#include "ps/CStr.h" +#include "graphics/Camera.h" +#include "graphics/CinemaManager.h" +#include "graphics/GameView.h" +#include "gui/CGUI.h" +#include "gui/GUIManager.h" +#include "gui/IGUIObject.h" +#include "lib/ogl.h" +#include "maths/MathUtil.h" +#include "maths/Quaternion.h" +#include "maths/Vector3D.h" #include "maths/Vector4D.h" +#include "ps/CLogger.h" +#include "ps/CStr.h" +#include "ps/Game.h" +#include "ps/Hotkey.h" +#include "simulation2/components/ICmpOverlayRenderer.h" +#include "simulation2/components/ICmpRangeManager.h" +#include "simulation2/components/ICmpSelectable.h" +#include "simulation2/components/ICmpTerritoryManager.h" +#include "simulation2/MessageTypes.h" +#include "simulation2/system/ComponentManager.h" +#include "simulation2/Simulation2.h" +#include "renderer/Renderer.h" -CCinemaManager::CCinemaManager() : m_DrawCurrentSpline(false), m_Active(true), m_ValidCurrent(false) + +CCinemaManager::CCinemaManager() + : m_DrawPaths(false) { - m_CurrentPath = m_Paths.end(); } -void CCinemaManager::AddPath(CCinemaPath path, const CStrW& name) +void CCinemaManager::AddPath(const CStrW& name, const CCinemaPath& path) { - ENSURE( m_Paths.find( name ) == m_Paths.end() ); - m_Paths[name] = path; -} - -void CCinemaManager::QueuePath(const CStrW& name, bool queue) -{ - if (!m_PathQueue.empty() && queue == false) + if (m_CinematicSimulationData.m_Paths.find(name) != m_CinematicSimulationData.m_Paths.end()) { + LOGWARNING("Path with name '%s' already exists", name.ToUTF8()); return; } - else - { - ENSURE(HasTrack(name)); - m_PathQueue.push_back(m_Paths[name]); - } + m_CinematicSimulationData.m_Paths[name] = path; } -void CCinemaManager::OverridePath(const CStrW& name) +void CCinemaManager::AddPathToQueue(const CStrW& name) { - m_PathQueue.clear(); - ENSURE(HasTrack(name)); - m_PathQueue.push_back( m_Paths[name] ); + if (!HasPath(name)) + { + LOGWARNING("Path with name '%s' doesn't exist", name.ToUTF8()); + return; + } + m_CinematicSimulationData.m_PathQueue.push_back(m_CinematicSimulationData.m_Paths[name]); +} + +void CCinemaManager::ClearQueue() +{ + m_CinematicSimulationData.m_PathQueue.clear(); } void CCinemaManager::SetAllPaths(const std::map& paths) { - CStrW name; - m_Paths = paths; + m_CinematicSimulationData.m_Paths = paths; } -void CCinemaManager::SetCurrentPath(const CStrW& name, bool current, bool drawLines) + +bool CCinemaManager::HasPath(const CStrW& name) const { - if ( !HasTrack(name) ) - m_ValidCurrent = false; - else - m_ValidCurrent = true; - - m_CurrentPath = m_Paths.find(name); - m_DrawCurrentSpline = current; - m_DrawLines = drawLines; - DrawSpline(); + return m_CinematicSimulationData.m_Paths.find(name) != m_CinematicSimulationData.m_Paths.end(); } -bool CCinemaManager::HasTrack(const CStrW& name) const -{ - return m_Paths.find(name) != m_Paths.end(); -} - -void CCinemaManager::DrawSpline() const +void CCinemaManager::SetEnabled(bool enabled) { - if ( !(m_DrawCurrentSpline && m_ValidCurrent) ) - return; - static const int smoothness = 200; - - m_CurrentPath->second.DrawSpline(CVector4D(0.f, 0.f, 1.f, 1.f), smoothness, m_DrawLines); -} - -void CCinemaManager::MoveToPointAt(float time) -{ - ENSURE(m_CurrentPath != m_Paths.end()); - StopPlaying(); - - m_CurrentPath->second.m_TimeElapsed = time; - if (!m_CurrentPath->second.Validate()) - return; - - m_CurrentPath->second.MoveToPointAt(m_CurrentPath->second.m_TimeElapsed / - m_CurrentPath->second.GetDuration(), m_CurrentPath->second.GetNodeFraction(), - m_CurrentPath->second.m_PreviousRotation); -} - -bool CCinemaManager::Update(const float deltaRealTime) -{ - if (!m_PathQueue.front().Play(deltaRealTime)) + // TODO: maybe assert? + if (m_CinematicSimulationData.m_PathQueue.empty() && enabled) { - m_PathQueue.pop_front(); - return false; + enabled = false; + m_CinematicSimulationData.m_Paused = true; } - return true; + + if (m_CinematicSimulationData.m_Enabled == enabled) + return; + + // TODO: Enabling/Disabling does not work if the session GUI page is not the top page. + // This can happen in various situations, for example when the player wins/looses the game + // while the cinematic is running (a message box is the top page in this case). + // It might be better to disable the whole GUI during the cinematic instead of a specific + // GUI object. + + // sn - session gui object + IGUIObject *sn = g_GUI->FindObjectByName("sn"); + CmpPtr cmpRangeManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity()); + CmpPtr cmpTerritoryManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity()); + + // GUI visibility + if (sn) + { + if (enabled) + sn->SetSetting("hidden", L"true"); + else + sn->SetSetting("hidden", L"false"); + } + + // Overlay visibility + g_Renderer.SetOptionBool(CRenderer::Option::OPT_SILHOUETTES, !enabled); + if (cmpRangeManager) + { + if (enabled) + m_CinematicSimulationData.m_MapRevealed = cmpRangeManager->GetLosRevealAll(-1); + // TODO: improve m_MapRevealed state and without fade in + cmpRangeManager->SetLosRevealAll(-1, enabled); + } + if (cmpTerritoryManager) + cmpTerritoryManager->SetVisibility(!enabled); + ICmpSelectable::SetOverrideVisibility(!enabled); + ICmpOverlayRenderer::SetOverrideVisibility(!enabled); + + m_CinematicSimulationData.m_Enabled = enabled; } + +void CCinemaManager::Play() +{ + m_CinematicSimulationData.m_Paused = false; +} + +void CCinemaManager::Stop() +{ + m_CinematicSimulationData.m_PathQueue.clear(); +} + +void CCinemaManager::Update(const float deltaRealTime) +{ + if (g_Game->m_Paused != m_CinematicSimulationData.m_Paused) + { + m_CinematicSimulationData.m_Paused = g_Game->m_Paused; + + // sn - session gui object + IGUIObject *sn = g_GUI->FindObjectByName("sn"); + + // GUI visibility + if (sn) + { + if (m_CinematicSimulationData.m_Paused) + sn->SetSetting("hidden", L"false"); + else + sn->SetSetting("hidden", L"true"); + } + } + + if (m_CinematicSimulationData.m_PathQueue.empty() || !m_CinematicSimulationData.m_Enabled || m_CinematicSimulationData.m_Paused) + return; + + if (HotkeyIsPressed("leave")) + { + // TODO: implement skip + } + + m_CinematicSimulationData.m_PathQueue.front().Play(deltaRealTime); +} + +void CCinemaManager::Render() +{ + if (GetEnabled()) + { + DrawBars(); + return; + } + + if (!m_DrawPaths) + return; + + // draw all paths + for (auto it : m_CinematicSimulationData.m_Paths) + it.second.Draw(); +} + +void CCinemaManager::DrawBars() const +{ + int height = (float)g_xres / 2.39f; + int shift = (g_yres - height) / 2; + if (shift <= 0) + return; + +#if CONFIG2_GLES + #warning TODO : implement bars for GLES +#else + // Set up transform for GL bars + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + CMatrix3D transform; + transform.SetOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f); + glLoadMatrixf(&transform._11); + + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + + glBegin(GL_QUADS); + glVertex2i(0, 0); + glVertex2i(g_xres, 0); + glVertex2i(g_xres, shift); + glVertex2i(0, shift); + glEnd(); + + glBegin(GL_QUADS); + glVertex2i(0, g_yres - shift); + glVertex2i(g_xres, g_yres - shift); + glVertex2i(g_xres, g_yres); + glVertex2i(0, g_yres); + glEnd(); + + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Restore transform + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +#endif +} + +InReaction cinema_manager_handler(const SDL_Event_* ev) +{ + // put any events that must be processed even if inactive here + if (!g_Game || !g_Game->IsGameStarted()) + return IN_PASS; + + CCinemaManager* pCinemaManager = g_Game->GetView()->GetCinema(); + + return pCinemaManager->HandleEvent(ev); +} + +InReaction CCinemaManager::HandleEvent(const SDL_Event_* ev) +{ + switch (ev->ev.type) + { + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if (GetEnabled() && !m_CinematicSimulationData.m_Paused) + return IN_HANDLED; + default: + return IN_PASS; + } +} + +bool CCinemaManager::GetEnabled() const +{ + return m_CinematicSimulationData.m_Enabled; +} + +bool CCinemaManager::IsPlaying() const +{ + return !m_CinematicSimulationData.m_Paused; +} + +const std::map& CCinemaManager::GetAllPaths() +{ + return m_CinematicSimulationData.m_Paths; +} + +CinematicSimulationData* CCinemaManager::GetCinematicSimulationData() +{ + return &m_CinematicSimulationData; +} + +bool CCinemaManager::GetPathsDrawing() const +{ + return m_DrawPaths; +} + +void CCinemaManager::SetPathsDrawing(const bool drawPath) +{ + m_DrawPaths = drawPath; +} \ No newline at end of file diff --git a/source/graphics/CinemaManager.h b/source/graphics/CinemaManager.h index 567b62b198..45e44b65c3 100644 --- a/source/graphics/CinemaManager.h +++ b/source/graphics/CinemaManager.h @@ -22,48 +22,121 @@ #include #include +#include "lib/input.h" // InReaction - can't forward-declare enum + #include "graphics/CinemaPath.h" #include "ps/CStr.h" -//Class for in game playing of cinematics. Should only be instantiated in CGameView. +/* + desc: contains various functions used for cinematic camera paths + See also: CinemaHandler.cpp, CinemaPath.cpp +*/ + +// Cinematic structure for data accessable from the simulation +struct CinematicSimulationData +{ + bool m_Enabled; + bool m_Paused; + std::map m_Paths; + std::list m_PathQueue; + + // States before playing + bool m_MapRevealed; + + fixed m_ElapsedTime, m_TotalTime, m_CurrentPathElapsedTime; + + CinematicSimulationData() + : m_Enabled(false), + m_Paused(true), + m_MapRevealed(false), + m_ElapsedTime(fixed::Zero()), + m_TotalTime(fixed::Zero()), + m_CurrentPathElapsedTime(fixed::Zero()) + {} +}; + +/** + * Class for in game playing of cinematics. Should only be instantiated in CGameView. + */ + class CCinemaManager { public: CCinemaManager(); ~CCinemaManager() {} - void AddPath(CCinemaPath path, const CStrW& name); - - //Adds track to list of being played. - void QueuePath(const CStrW& name, bool queue); - void OverridePath(const CStrW& name); //clears track queue and replaces with 'name' + /** + * Adds the path to the path list + * @param name path name + * @param CCinemaPath path data + */ + void AddPath(const CStrW& name, const CCinemaPath& path); /** + * Adds the path to the playlist + * @param name path name + */ + void AddPathToQueue(const CStrW& name); + + /** + * Clears the playlist + */ + void ClearQueue(); + + /** + * Checks the path name in the path list + * @param name path name + * @return true if path with that name exists, else false + */ + bool HasPath(const CStrW& name) const; + + const std::map& GetAllPaths(); + void SetAllPaths( const std::map& tracks); + + /** + * Starts play paths + */ + void Play(); + void Stop(); + bool IsPlaying() const; + + /** + * Renders black bars and paths (if enabled) + */ + void Render(); + void DrawBars() const; + + /** + * Get current enable state of the cinema manager + */ + bool GetEnabled() const; + + /** + * Sets enable state of the cinema manager (shows/hide gui, show/hide rings, etc) + * @enable new state + */ + void SetEnabled(bool enabled); + + /** + * Updates CCinemManager and current path * @param deltaRealTime Elapsed real time since the last frame. */ - bool Update(const float deltaRealTime); - - //These stop track play, and accept time, not ratio of time - void MoveToPointAt(float time); + void Update(const float deltaRealTime); - inline void StopPlaying() { m_PathQueue.clear(); } - void DrawSpline() const; - - inline bool IsPlaying() const { return !m_PathQueue.empty(); } - bool HasTrack(const CStrW& name) const; - inline bool IsActive() const { return m_Active; } - inline void SetActive(bool active) { m_Active=active; } + InReaction HandleEvent(const SDL_Event_* ev); - inline const std::map& GetAllPaths() { return m_Paths; } - void SetAllPaths( const std::map& tracks); - void SetCurrentPath(const CStrW& name, bool current, bool lines); + CinematicSimulationData* GetCinematicSimulationData(); -private: - - bool m_Active, m_DrawCurrentSpline, m_DrawLines, m_ValidCurrent; - std::map::iterator m_CurrentPath; - std::map m_Paths; - std::list m_PathQueue; + bool GetPathsDrawing() const; + void SetPathsDrawing(const bool drawPath); + +private: + bool m_DrawPaths; + + // Cinematic data is accessed from the simulation + CinematicSimulationData m_CinematicSimulationData; }; +extern InReaction cinema_manager_handler(const SDL_Event_* ev); + #endif diff --git a/source/graphics/CinemaPath.cpp b/source/graphics/CinemaPath.cpp index c2dbdf247c..e661127e77 100644 --- a/source/graphics/CinemaPath.cpp +++ b/source/graphics/CinemaPath.cpp @@ -23,73 +23,81 @@ #include #include "Camera.h" +#include "CinemaManager.h" #include "GameView.h" +#include "gui/CGUI.h" +#include "gui/GUIManager.h" +#include "gui/IGUIObject.h" #include "lib/ogl.h" #include "maths/MathUtil.h" #include "maths/Quaternion.h" #include "maths/Vector3D.h" #include "maths/Vector4D.h" +#include "ps/CLogger.h" #include "ps/CStr.h" #include "ps/Game.h" +#include "renderer/Renderer.h" -CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline) - : CCinemaData(data), TNSpline(spline), m_TimeElapsed(0.f) -{ +CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline, const TNSpline& targetSpline) + : CCinemaData(data), TNSpline(spline), m_TargetSpline(targetSpline), m_TimeElapsed(0.f) +{ m_TimeElapsed = 0; BuildSpline(); - // Set distortion mode and style - switch(data.m_Mode) + if (m_Orientation == L"target") { - case CCinemaPath::EM_IN: - DistModePtr = &CCinemaPath::EaseIn; - break; - case CCinemaPath::EM_OUT: - DistModePtr = &CCinemaPath::EaseOut; - break; - case CCinemaPath::EM_INOUT: - DistModePtr = &CCinemaPath::EaseInOut; - break; - case CCinemaPath::EM_OUTIN: - DistModePtr = &CCinemaPath::EaseOutIn; - break; - default: - debug_printf("Cinematic mode not found for %d\n", data.m_Mode); - break; + m_LookAtTarget = true; + ENSURE(!m_TargetSpline.GetAllNodes().empty()); } - switch (data.m_Style) + // Set distortion mode and style + if (data.m_Mode == L"ease_in") + DistModePtr = &CCinemaPath::EaseIn; + else if (data.m_Mode == L"ease_out") + DistModePtr = &CCinemaPath::EaseOut; + else if (data.m_Mode == L"ease_inout") + DistModePtr = &CCinemaPath::EaseInOut; + else if (data.m_Mode == L"ease_outin") + DistModePtr = &CCinemaPath::EaseOutIn; + else { - case CCinemaPath::ES_DEFAULT: + LOGWARNING("Cinematic mode not found for '%s'", data.m_Mode.ToUTF8().c_str()); + DistModePtr = &CCinemaPath::EaseInOut; + } + + if (data.m_Style == L"default") DistStylePtr = &CCinemaPath::EaseDefault; - break; - case CCinemaPath::ES_GROWTH: + else if (data.m_Style == L"growth") DistStylePtr = &CCinemaPath::EaseGrowth; - break; - case CCinemaPath::ES_EXPO: + else if (data.m_Style == L"expo") DistStylePtr = &CCinemaPath::EaseExpo; - break; - case CCinemaPath::ES_CIRCLE: + else if (data.m_Style == L"circle") DistStylePtr = &CCinemaPath::EaseCircle; - break; - case CCinemaPath::ES_SINE: + else if (data.m_Style == L"sine") DistStylePtr = &CCinemaPath::EaseSine; - break; - default: - debug_printf("Cinematic mode not found for %d\n", data.m_Style); - break; + else + { + LOGWARNING("Cinematic style not found for '%s'", data.m_Style.ToUTF8().c_str()); + DistStylePtr = &CCinemaPath::EaseDefault; } } -void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) const +void CCinemaPath::Draw() const { - if (NodeCount < 2 || DistModePtr == NULL) + DrawSpline(*this, CVector4D(0.2f, 0.2f, 1.f, 0.5f), 100, true); + DrawSpline(m_TargetSpline, CVector4D(1.0f, 0.2f, 0.2f, 0.5f), 100, true); + DrawNodes(CVector4D(0.5f, 1.0f, 0.f, 0.5f)); +} + +void CCinemaPath::DrawSpline(const RNSpline& spline, const CVector4D& RGBA, int smoothness, bool lines) const +{ + if (spline.NodeCount < 2 || DistModePtr == NULL) return; - if (NodeCount == 2 && lines) + if (spline.NodeCount == 2 && lines) smoothness = 2; - float start = MaxDistance / smoothness; + float start = spline.MaxDistance.ToFloat() / smoothness; float time = 0; #if CONFIG2_GLES @@ -106,8 +114,8 @@ void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) for (int i = 0; i <= smoothness; ++i) { // Find distorted time - time = start*i / MaxDistance; - CVector3D tmp = GetPosition(time); + time = start*i / spline.MaxDistance.ToFloat(); + CVector3D tmp = spline.GetPosition(time); glVertex3f(tmp.X, tmp.Y, tmp.Z); } glEnd(); @@ -117,7 +125,7 @@ void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) else { smoothness /= 2; - start = MaxDistance / smoothness; + start = spline.MaxDistance.ToFloat() / smoothness; glEnable(GL_POINT_SMOOTH); glPointSize(3.0f); glBegin(GL_POINTS); @@ -125,14 +133,18 @@ void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) for (int i = 0; i <= smoothness; ++i) { // Find distorted time - time = (this->*DistModePtr)(start*i / MaxDistance); - CVector3D tmp = GetPosition(time); + time = (this->*DistModePtr)(start*i / spline.MaxDistance.ToFloat()); + CVector3D tmp = spline.GetPosition(time); glVertex3f(tmp.X, tmp.Y, tmp.Z); } glColor3f(1.0f, 1.0f, 0.0f); // yellow - for (size_t i = 0; i < Node.size(); ++i) - glVertex3f(Node[i].Position.X, Node[i].Position.Y, Node[i].Position.Z); + for (size_t i = 0; i < spline.GetAllNodes().size(); ++i) + glVertex3f( + spline.GetAllNodes()[i].Position.X.ToFloat(), + spline.GetAllNodes()[i].Position.Y.ToFloat(), + spline.GetAllNodes()[i].Position.Z.ToFloat() + ); glEnd(); glPointSize(1.0f); @@ -142,23 +154,70 @@ void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) #endif } +void CCinemaPath::DrawNodes(const CVector4D& RGBA) const +{ +#if CONFIG2_GLES + #warning TODO : do something about CCinemaPath on GLES +#else + glEnable(GL_POINT_SMOOTH); + glPointSize(5.0f); + + glColor4f(RGBA.X, RGBA.Y, RGBA.Z, RGBA.W); + glBegin(GL_POINTS); + for (size_t i = 0; i < Node.size(); ++i) + glVertex3f(Node[i].Position.X.ToFloat(), Node[i].Position.Y.ToFloat(), Node[i].Position.Z.ToFloat()); + glEnd(); + + if (!m_LookAtTarget) + { + glPointSize(1.0f); + glDisable(GL_POINT_SMOOTH); + return; + } + + // draw target nodes + glColor4f(RGBA.Y, RGBA.X, RGBA.Z, RGBA.W); + glBegin(GL_POINTS); + for (size_t i = 0; i < m_TargetSpline.GetAllNodes().size(); ++i) + glVertex3f( + m_TargetSpline.GetAllNodes()[i].Position.X.ToFloat(), + m_TargetSpline.GetAllNodes()[i].Position.Y.ToFloat(), + m_TargetSpline.GetAllNodes()[i].Position.Z.ToFloat() + ); + glEnd(); + + glPointSize(1.0f); + glDisable(GL_POINT_SMOOTH); +#endif +} + void CCinemaPath::MoveToPointAt(float t, float nodet, const CVector3D& startRotation) { - CCamera *Cam = g_Game->GetView()->GetCamera(); + CCamera *camera = g_Game->GetView()->GetCamera(); t = (this->*DistModePtr)(t); - - CVector3D nodeRotation = Node[m_CurrentNode + 1].Rotation; - CQuaternion start, end; - start.FromEulerAngles(DEGTORAD(startRotation.X), DEGTORAD(startRotation.Y), DEGTORAD(startRotation.Z)); - end.FromEulerAngles(DEGTORAD(nodeRotation.X), DEGTORAD(nodeRotation.Y), DEGTORAD(nodeRotation.Z)); - start.Slerp(start, end, nodet); + CVector3D pos = GetPosition(t); - CQuaternion quat; - - Cam->m_Orientation.SetIdentity(); - Cam->m_Orientation.Rotate(start); - Cam->m_Orientation.Translate(pos); - Cam->UpdateFrustum(); + + if (m_LookAtTarget) + { + if (m_TimeElapsed <= m_TargetSpline.MaxDistance.ToFloat()) + camera->LookAt(pos, m_TargetSpline.GetPosition(m_TimeElapsed / m_TargetSpline.MaxDistance.ToFloat()), CVector3D(0, 1, 0)); + else + camera->LookAt(pos, m_TargetSpline.GetAllNodes().back().Position, CVector3D(0, 1, 0)); + } + else + { + CVector3D nodeRotation = Node[m_CurrentNode + 1].Rotation; + CQuaternion start, end; + start.FromEulerAngles(DEGTORAD(startRotation.X), DEGTORAD(startRotation.Y), DEGTORAD(startRotation.Z)); + end.FromEulerAngles(DEGTORAD(nodeRotation.X), DEGTORAD(nodeRotation.Y), DEGTORAD(nodeRotation.Z)); + start.Slerp(start, end, nodet); + + camera->m_Orientation.SetIdentity(); + camera->m_Orientation.Rotate(start); + camera->m_Orientation.Translate(pos); + } + camera->UpdateFrustum(); } // Distortion mode functions @@ -228,7 +287,7 @@ float CCinemaPath::EaseSine(float t) const bool CCinemaPath::Validate() { - if (m_TimeElapsed > GetDuration() || m_TimeElapsed < 0.0f) + if (m_TimeElapsed > GetDuration().ToFloat() || m_TimeElapsed < 0.0f) return false; // Find current node and past "node time" @@ -237,7 +296,7 @@ bool CCinemaPath::Validate() // Ignore the last node, since it is a blank (node time values are shifted down one from interface) for (size_t i = 0; i < Node.size() - 1; ++i) { - cumulation += Node[i].Distance; + cumulation += Node[i].Distance.ToFloat(); if (m_TimeElapsed <= cumulation) { m_PreviousNodeTime = previousTime; @@ -245,20 +304,21 @@ bool CCinemaPath::Validate() m_CurrentNode = i; // We're moving toward this next node, so use its rotation return true; } - previousTime += Node[i].Distance; + previousTime += Node[i].Distance.ToFloat(); } + debug_warn("validation of cinema path is wrong\n"); return false; } bool CCinemaPath::Play(const float deltaRealTime) { - m_TimeElapsed += m_Timescale * deltaRealTime; + m_TimeElapsed += m_Timescale.ToFloat() * deltaRealTime; if (!Validate()) { m_TimeElapsed = 0.0f; return false; } - MoveToPointAt(m_TimeElapsed / GetDuration(), GetNodeFraction(), m_PreviousRotation); + MoveToPointAt(m_TimeElapsed / GetDuration().ToFloat(), GetNodeFraction(), m_PreviousRotation); return true; } \ No newline at end of file diff --git a/source/graphics/CinemaPath.h b/source/graphics/CinemaPath.h index 5b2a222f78..1e789f8e71 100644 --- a/source/graphics/CinemaPath.h +++ b/source/graphics/CinemaPath.h @@ -15,19 +15,11 @@ * along with 0 A.D. If not, see . */ - #ifndef INCLUDED_CINEMAPATH #define INCLUDED_CINEMAPATH -#include -#include -#include "ps/CStr.h" #include "maths/NUSpline.h" - -/* - desc: contains various functions used for cinematic camera paths - See also: CinemaHandler.cpp, Cinematic.h/.cpp -*/ +#include "ps/CStr.h" class CVector3D; class CVector4D; @@ -37,20 +29,24 @@ class CCamera; class CCinemaData { public: - CCinemaData() : m_GrowthCount(0), m_Growth(0), m_Switch(0), - m_Mode(0), m_Style(0), m_Timescale(1) {} + CCinemaData() : m_LookAtTarget(false), m_GrowthCount(0), m_Growth(1), m_Switch(1), m_Timescale(fixed::FromInt(1)) {} virtual ~CCinemaData() {} const CCinemaData* GetData() const { return this; } - + + CStrW m_Name; + CStrW m_Orientation; + CStrW m_Mode; + CStrW m_Style; + + bool m_LookAtTarget; + + fixed m_Timescale; // a negative timescale results in backwards play + // Distortion variables mutable float m_GrowthCount; float m_Growth; float m_Switch; - int m_Mode; - int m_Style; - float m_Timescale; // a negative timescale results in backwards play - }; @@ -61,16 +57,13 @@ public: class CCinemaPath : private CCinemaData, public TNSpline { public: - CCinemaPath() { m_TimeElapsed = 0.0f; m_PreviousNodeTime = 0.0f; } - CCinemaPath(const CCinemaData& data, const TNSpline& spline); + CCinemaPath() : m_TimeElapsed(0), m_PreviousNodeTime(0) {} + CCinemaPath(const CCinemaData& data, const TNSpline& spline, const TNSpline& targetSpline); ~CCinemaPath() { DistStylePtr = NULL; DistModePtr = NULL; } - - 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, float nodet, const CVector3D&); - + // Distortion mode functions-change how ratio is passed to distortion style functions float EaseIn(float t) const; float EaseOut(float t) const; @@ -91,16 +84,20 @@ public: public: - void DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) const; + void Draw() const; + void DrawSpline(const RNSpline& spline, const CVector4D& RGBA, int smoothness, bool lines) const; + void DrawNodes(const CVector4D& RGBA) 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 fixed GetNodeDuration(const int index) const { return Node[index].Distance; } + inline fixed GetDuration() const { return MaxDistance; } - inline float GetNodeFraction() const { return (m_TimeElapsed - m_PreviousNodeTime) / Node[m_CurrentNode].Distance; } + inline float GetNodeFraction() const { return (m_TimeElapsed - m_PreviousNodeTime) / Node[m_CurrentNode].Distance.ToFloat(); } inline float GetElapsedTime() const { return m_TimeElapsed; } - inline void SetTimescale(float scale) { m_Timescale = scale; } + CStrW GetName() const { return m_Name; } + + inline void SetTimescale(fixed scale) { m_Timescale = scale; } float m_TimeElapsed; float m_PreviousNodeTime; // How much time has passed before the current node @@ -112,13 +109,28 @@ public: /** * Returns false if finished. - * * @param deltaRealTime Elapsed real time since the last frame. */ bool Play(const float deltaRealTime); + + /** + * Validate the path + * @return true if the path is valid + */ bool Validate(); - inline float GetTimescale() const { return m_Timescale; } + /** + * Returns true if path doesn't contain nodes + */ + bool Empty() { return Node.empty(); } + + fixed GetTimescale() const { return m_Timescale; } + + TNSpline* getTargetSpline() { return &m_TargetSpline; } + +private: + + TNSpline m_TargetSpline; }; -#endif +#endif // INCLUDED_CINEMAPATH diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp index daeb634d09..30cc654030 100644 --- a/source/graphics/GameView.cpp +++ b/source/graphics/GameView.cpp @@ -626,12 +626,9 @@ void CGameView::Update(const float deltaRealTime) if (!g_app_has_focus) return; - if (m->CinemaManager.IsActive() && m->CinemaManager.IsPlaying()) + if (m->CinemaManager.GetEnabled()) { - if (! m->CinemaManager.Update(deltaRealTime)) - { -// ResetCamera(); - } + m->CinemaManager.Update(deltaRealTime); return; } diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index 84d915b265..4dc0667809 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -456,7 +456,7 @@ private: void ReadTerrain(XMBElement parent); void ReadEnvironment(XMBElement parent); void ReadCamera(XMBElement parent); - void ReadCinema(XMBElement parent); + void ReadPaths(XMBElement parent); void ReadTriggers(XMBElement parent); int ReadEntities(XMBElement parent, double end_time); }; @@ -839,120 +839,115 @@ void CXMLReader::ReadCamera(XMBElement parent) } } -void CXMLReader::ReadCinema(XMBElement parent) +void CXMLReader::ReadPaths(XMBElement parent) { #define EL(x) int el_##x = xmb_file.GetElementID(#x) #define AT(x) int at_##x = xmb_file.GetAttributeID(#x) EL(path); EL(rotation); - EL(distortion); EL(node); EL(position); - EL(time); + EL(target); AT(name); AT(timescale); + AT(orientation); AT(mode); AT(style); - AT(growth); - AT(switch); AT(x); AT(y); AT(z); + AT(deltatime); #undef EL #undef AT - - std::map pathList; + XERO_ITER_EL(parent, element) { int elementName = element.GetNodeName(); if (elementName == el_path) { - XMBAttributeList attrs = element.GetAttributes(); - CStrW name(attrs.GetNamedItem(at_name).FromUTF8()); - float timescale = attrs.GetNamedItem(at_timescale).ToFloat(); CCinemaData pathData; - pathData.m_Timescale = timescale; - TNSpline spline, backwardSpline; + XMBAttributeList attrs = element.GetAttributes(); + CStrW pathName(attrs.GetNamedItem(at_name).FromUTF8()); + pathData.m_Timescale = fixed::FromString(attrs.GetNamedItem(at_timescale)); + TNSpline pathSpline, targetSpline; + fixed lastTargetTime = fixed::Zero(); + + pathData.m_Name = pathName; + pathData.m_Orientation = attrs.GetNamedItem(at_orientation).FromUTF8(); + pathData.m_Mode = attrs.GetNamedItem(at_mode).FromUTF8(); + pathData.m_Style = attrs.GetNamedItem(at_style).FromUTF8(); XERO_ITER_EL(element, pathChild) { elementName = pathChild.GetNodeName(); attrs = pathChild.GetAttributes(); - //Load distortion attributes - if (elementName == el_distortion) - { - pathData.m_Mode = attrs.GetNamedItem(at_mode).ToInt(); - pathData.m_Style = attrs.GetNamedItem(at_style).ToInt(); - pathData.m_Growth = attrs.GetNamedItem(at_growth).ToInt(); - pathData.m_Switch = attrs.GetNamedItem(at_switch).ToInt(); - } - - //Load node data used for spline - else if (elementName == el_node) + // Load node data used for spline + if (elementName == el_node) { + bool positionDeclared = false; SplineData data; + data.Distance = fixed::FromString(attrs.GetNamedItem(at_deltatime)); + lastTargetTime += fixed::FromString(attrs.GetNamedItem(at_deltatime)); XERO_ITER_EL(pathChild, nodeChild) { elementName = nodeChild.GetNodeName(); attrs = nodeChild.GetAttributes(); - - //Fix?: assumes that time is last element + if (elementName == el_position) { - data.Position.X = attrs.GetNamedItem(at_x).ToFloat(); - data.Position.Y = attrs.GetNamedItem(at_y).ToFloat(); - data.Position.Z = attrs.GetNamedItem(at_z).ToFloat(); - continue; + data.Position.X = fixed::FromString(attrs.GetNamedItem(at_x)); + data.Position.Y = fixed::FromString(attrs.GetNamedItem(at_y)); + data.Position.Z = fixed::FromString(attrs.GetNamedItem(at_z)); + positionDeclared = true; } else if (elementName == el_rotation) { - data.Rotation.X = attrs.GetNamedItem(at_x).ToFloat(); - data.Rotation.Y = attrs.GetNamedItem(at_y).ToFloat(); - data.Rotation.Z = attrs.GetNamedItem(at_z).ToFloat(); - continue; + data.Rotation.X = fixed::FromString(attrs.GetNamedItem(at_x)); + data.Rotation.Y = fixed::FromString(attrs.GetNamedItem(at_y)); + data.Rotation.Z = fixed::FromString(attrs.GetNamedItem(at_z)); + } + else if (elementName == el_target) + { + CFixedVector3D targetPosition; + targetPosition.X = fixed::FromString(attrs.GetNamedItem(at_x)); + targetPosition.Y = fixed::FromString(attrs.GetNamedItem(at_y)); + targetPosition.Z = fixed::FromString(attrs.GetNamedItem(at_z)); + + targetSpline.AddNode(targetPosition, CFixedVector3D(), lastTargetTime); + lastTargetTime = fixed::Zero(); } - else if (elementName == el_time) - data.Distance = nodeChild.GetText().ToFloat(); else - debug_warn(L"Invalid cinematic element for node child"); - - backwardSpline.AddNode(data.Position, data.Rotation, data.Distance); + LOGWARNING("Invalid cinematic element for node child"); } + + // Skip the node if no position + if (positionDeclared) + pathSpline.AddNode(data.Position, data.Rotation, data.Distance); } else - debug_warn(L"Invalid cinematic element for path child"); - - + LOGWARNING("Invalid cinematic element for path child"); } - //Construct cinema path with data gathered - CCinemaPath temp(pathData, backwardSpline); - const std::vector& nodes = temp.GetAllNodes(); - if (nodes.empty()) + // Construct cinema path with data gathered + CCinemaPath path(pathData, pathSpline, targetSpline); + if (path.Empty()) { - debug_warn(L"Failure loading cinematics"); + LOGWARNING("Path with name '%s' is empty", pathName.ToUTF8()); return; } - for (std::vector::const_reverse_iterator it = nodes.rbegin(); - it != nodes.rend(); ++it) - { - spline.AddNode(it->Position, it->Rotation, it->Distance); - } - - CCinemaPath path(pathData, spline); - pathList[name] = path; + if (!m_MapReader.pCinema->HasPath(pathName)) + m_MapReader.pCinema->AddPath(pathName, path); + else + LOGWARNING("Path with name '%s' already exists", pathName.ToUTF8()); } else - ENSURE("Invalid cinema child"); + LOGWARNING("Invalid path child with name '%s'", element.GetText()); } - - if (m_MapReader.pCinema) - m_MapReader.pCinema->SetAllPaths(pathList); } void CXMLReader::ReadTriggers(XMBElement UNUSED(parent)) @@ -1125,7 +1120,7 @@ void CXMLReader::ReadXML() } else if (name == "Paths") { - ReadCinema(node); + ReadPaths(node); } else if (name == "Triggers") { diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp index 20e407d18f..dd850a844d 100644 --- a/source/graphics/MapWriter.cpp +++ b/source/graphics/MapWriter.cpp @@ -408,27 +408,25 @@ void CMapWriter::WriteXML(const VfsPath& filename, for ( ; it != paths.end(); ++it ) { - CStrW name = it->first; - float timescale = it->second.GetTimescale(); - - XML_Element("Path"); - XML_Attribute("name", name); - XML_Attribute("timescale", timescale); - + fixed timescale = it->second.GetTimescale(); const std::vector& nodes = it->second.GetAllNodes(); const CCinemaData* data = it->second.GetData(); - { - 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); - } + XML_Element("Path"); + XML_Attribute("name", data->m_Name); + XML_Attribute("timescale", timescale); + XML_Attribute("orientation", data->m_Orientation); + XML_Attribute("mode", data->m_Mode); + XML_Attribute("style", data->m_Style); - for ( ssize_t j=nodes.size()-1; j >= 0; --j ) + // TODO: write target nodes + for (size_t j = 0; j < nodes.size(); ++j) { XML_Element("Node"); + if (j > 0) + XML_Attribute("deltatime", nodes[j - 1].Distance); + else + XML_Attribute("deltatime", 0.0f); { XML_Element("Position"); @@ -443,8 +441,6 @@ void CMapWriter::WriteXML(const VfsPath& filename, XML_Attribute("y", nodes[j].Rotation.Y); XML_Attribute("z", nodes[j].Rotation.Z); } - - XML_Setting("Time", nodes[j].Distance); } } } diff --git a/source/lib/input.cpp b/source/lib/input.cpp index e8965ae596..3b2d9277d6 100644 --- a/source/lib/input.cpp +++ b/source/lib/input.cpp @@ -32,7 +32,7 @@ #include "lib/external_libraries/libsdl.h" -const size_t MAX_HANDLERS = 8; +const size_t MAX_HANDLERS = 9; static InHandler handler_stack[MAX_HANDLERS]; static size_t handler_stack_top = 0; diff --git a/source/maths/NUSpline.cpp b/source/maths/NUSpline.cpp index 8712f96e9f..a52ffd2ca7 100644 --- a/source/maths/NUSpline.cpp +++ b/source/maths/NUSpline.cpp @@ -45,13 +45,12 @@ CVector3D GetPositionOnCubic(const CVector3D& startPos, const CVector3D& startVe /*********************************** R N S **************************************************/ // adds node and updates segment length -void RNSpline::AddNode(const CVector3D& pos) +void RNSpline::AddNode(const CFixedVector3D& pos) { if (NodeCount >= MAX_SPLINE_NODES) return; - if (NodeCount == 0) - MaxDistance = 0.f; + MaxDistance = fixed::Zero(); else { Node[NodeCount-1].Distance = (Node[NodeCount-1].Position - pos).Length(); @@ -97,25 +96,32 @@ CVector3D RNSpline::GetPosition(float time) const { if (NodeCount < 2) return CVector3D(0.0f, 0.0f, 0.0f); - + if (time < 0.0f) + time = 0.0f; if (time > 1.0f) time = 1.0f; - float Distance = time * MaxDistance; + float Distance = time * MaxDistance.ToFloat(); float CurrentDistance = 0.f; int i = 0; - //Find which node we're on - while (CurrentDistance + Node[i].Distance < Distance && i < NodeCount - 2) + // Find which node we're on + while (CurrentDistance + Node[i].Distance.ToFloat() < Distance && i < NodeCount - 2) { - CurrentDistance += Node[i].Distance; + CurrentDistance += Node[i].Distance.ToFloat(); ++i; } ENSURE(i < NodeCount - 1); float t = Distance - CurrentDistance; - t /= Node[i].Distance; // scale t in range 0 - 1 - CVector3D startVel = Node[i].Velocity * Node[i].Distance; - CVector3D endVel = Node[i+1].Velocity * Node[i].Distance; - return GetPositionOnCubic(Node[i].Position, startVel, Node[i+1].Position, endVel, t); + // TODO: reimplement CVector3D comparator (float comparing is bad without EPS) + if (Node[i].Position == Node[i+1].Position || Node[i].Distance.ToFloat() < 1e-7) // distance too small or zero + { + return Node[i+1].Position; + } + t /= Node[i].Distance.ToFloat(); // scale t in range 0 - 1 + CVector3D startVel = Node[i].Velocity * Node[i].Distance.ToFloat(); + CVector3D endVel = Node[i+1].Velocity * Node[i].Distance.ToFloat(); + return GetPositionOnCubic(Node[i].Position, startVel, + Node[i+1].Position, endVel, t); } // internal. Based on Equation 14 @@ -123,8 +129,7 @@ CVector3D RNSpline::GetStartVelocity(int index) { if (index >= NodeCount - 1 || index < 0) return CVector3D(0.0f, 0.0f, 0.0f); - - CVector3D temp = (Node[index+1].Position - Node[index].Position) * 3.0f * (1.0f / Node[index].Distance); + CVector3D temp = CVector3D(Node[index+1].Position - Node[index].Position) * 3.0f * (1.0f / Node[index].Distance.ToFloat()); return (temp - Node[index+1].Velocity)*0.5f; } @@ -133,8 +138,7 @@ CVector3D RNSpline::GetEndVelocity(int index) { if (index >= NodeCount || index < 1) return CVector3D(0.0f, 0.0f, 0.0f); - - CVector3D temp = (Node[index].Position - Node[index-1].Position) * 3.0f * (1.0f / Node[index-1].Distance); + CVector3D temp = CVector3D(Node[index].Position - Node[index-1].Position) * 3.0f * (1.0f / Node[index-1].Distance.ToFloat()); return (temp - Node[index-1].Velocity) * 0.5f; } @@ -151,8 +155,8 @@ void SNSpline::Smooth() for (int i = 1; i < NodeCount-1; ++i) { // Equation 12 - newVel = GetEndVelocity(i) * Node[i].Distance + GetStartVelocity(i) * Node[i-1].Distance; - newVel = newVel * ( 1 / (Node[i-1].Distance + Node[i].Distance) ); + newVel = GetEndVelocity(i) * Node[i].Distance.ToFloat() + GetStartVelocity(i) * Node[i-1].Distance.ToFloat(); + newVel = newVel * (1 / (Node[i-1].Distance + Node[i].Distance).ToFloat()); Node[i-1].Velocity = oldVel; oldVel = newVel; } @@ -164,13 +168,13 @@ void SNSpline::Smooth() // as with RNSpline but use timePeriod in place of actual node spacing // ie time period is time from last node to this node -void TNSpline::AddNode(const CVector3D& pos, const CVector3D& rotation, float timePeriod) +void TNSpline::AddNode(const CFixedVector3D& pos, const CFixedVector3D& rotation, fixed timePeriod) { if (NodeCount >= MAX_SPLINE_NODES) return; if (NodeCount == 0) - MaxDistance = 0.f; + MaxDistance = fixed::Zero(); else { Node[NodeCount-1].Distance = timePeriod; @@ -181,7 +185,7 @@ void TNSpline::AddNode(const CVector3D& pos, const CVector3D& rotation, float ti temp.Position = pos; //make sure we don't end up using undefined numbers... - temp.Distance = 0.0f; + temp.Distance = fixed::Zero(); temp.Velocity = CVector3D(0.0f, 0.0f, 0.0f); temp.Rotation = rotation; Node.push_back(temp); @@ -189,13 +193,12 @@ void TNSpline::AddNode(const CVector3D& pos, const CVector3D& rotation, float ti } //Inserts node before position -void TNSpline::InsertNode(const int index, const CVector3D& pos, const CVector3D& rotation, float timePeriod) +void TNSpline::InsertNode(const int index, const CFixedVector3D& pos, const CFixedVector3D& rotation, fixed timePeriod) { if (NodeCount >= MAX_SPLINE_NODES || index < NodeCount - 1) return; - if (NodeCount == 0) - MaxDistance = 0.f; + MaxDistance = fixed::Zero(); else { Node[NodeCount-1].Distance = timePeriod; @@ -216,20 +219,18 @@ void TNSpline::RemoveNode(const int index) MaxDistance -= Node[index].Distance; MaxDistance -= Node[index-1].Distance; - Node[index-1].Distance = 0.0f; + Node[index-1].Distance = fixed::Zero(); Node.erase(Node.begin() + index, Node.begin() + index + 1); --NodeCount; } - -void TNSpline::UpdateNodeTime(const int index, float time) +void TNSpline::UpdateNodeTime(const int index, fixed time) { if (NodeCount == 0 || index > NodeCount - 1) return; Node[index].Distance = time; } - -void TNSpline::UpdateNodePos(const int index, const CVector3D& pos) +void TNSpline::UpdateNodePos(const int index, const CFixedVector3D& pos) { if (NodeCount == 0 || index > NodeCount - 1) return; @@ -245,9 +246,9 @@ void TNSpline::Constrain() for (int i = 1; i < NodeCount-1; ++i) { // Equation 13 - float r0 = (Node[i].Position-Node[i-1].Position).Length() / Node[i-1].Distance; - float r1 = (Node[i+1].Position - Node[i].Position).Length() / Node[i].Distance; - Node[i].Velocity *= 4.0f*r0*r1/((r0+r1)*(r0+r1)); + float r0 = (Node[i].Position - Node[i - 1].Position).Length().ToFloat() / Node[i-1].Distance.ToFloat(); + float r1 = (Node[i+1].Position - Node[i].Position).Length().ToFloat() / Node[i].Distance.ToFloat(); + Node[i].Velocity *= 4.0f*r0*r1 / ((r0 + r1)*(r0 + r1)); } } diff --git a/source/maths/NUSpline.h b/source/maths/NUSpline.h index afcee72ffe..e6c11710d5 100644 --- a/source/maths/NUSpline.h +++ b/source/maths/NUSpline.h @@ -24,14 +24,18 @@ #define MAX_SPLINE_NODES 40 #include + +#include "FixedVector3D.h" #include "Vector3D.h" struct SplineData { - CVector3D Position; + // Should be fixed, because used in the simulation + CFixedVector3D Position; CVector3D Velocity; - CVector3D Rotation; - float Distance/*, DistanceOffset*/; //DistanceOffset is to keep track of how far into the spline this node is + // TODO: make rotation as other spline + CFixedVector3D Rotation; + fixed Distance/*, DistanceOffset*/; //DistanceOffset is to keep track of how far into the spline this node is }; class RNSpline @@ -41,13 +45,13 @@ public: RNSpline() { NodeCount = 0; } virtual ~RNSpline() {} - void AddNode(const CVector3D& pos); + void AddNode(const CFixedVector3D& pos); void BuildSpline(); CVector3D GetPosition(float time) const; CVector3D GetRotation(float time) const; const std::vector& GetAllNodes() const { return Node; } - float MaxDistance; + fixed MaxDistance; int NodeCount; protected: @@ -70,12 +74,12 @@ class TNSpline : public SNSpline public: virtual ~TNSpline() {} - void AddNode(const CVector3D& pos, const CVector3D& rotation, float timePeriod); + void AddNode(const CFixedVector3D& pos, const CFixedVector3D& rotation, fixed timePeriod); void PushNode() { Node.push_back( SplineData() ); } - void InsertNode(const int index, const CVector3D& pos, const CVector3D& rotation, float timePeriod); + void InsertNode(const int index, const CFixedVector3D& pos, const CFixedVector3D& rotation, fixed timePeriod); void RemoveNode(const int index); - void UpdateNodeTime(const int index, float time); - void UpdateNodePos(const int index, const CVector3D& pos); + void UpdateNodeTime(const int index, fixed time); + void UpdateNodePos(const int index, const CFixedVector3D& pos); void BuildSpline(){ RNSpline::BuildSpline(); Smooth(); Smooth(); Smooth(); } void Smooth(){ for (int x = 0; x < 3; ++x) { SNSpline::Smooth(); Constrain(); } } diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 4a926db09f..7af1286781 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -35,6 +35,7 @@ #include "lib/sysdep/os/win/wversion.h" #endif +#include "graphics/CinemaManager.h" #include "graphics/CinemaPath.h" #include "graphics/FontMetrics.h" #include "graphics/GameView.h" @@ -228,6 +229,11 @@ void Render() g_Renderer.RenderTextOverlays(); + if (g_Game && g_Game->IsGameStarted()) + g_Game->GetView()->GetCinema()->Render(); + + ogl_WarnIfError(); + if (g_DoRenderGui) g_GUI->Draw(); @@ -568,6 +574,8 @@ static void InitInput() in_add_handler(gui_handler); in_add_handler(touch_input_handler); + + in_add_handler(cinema_manager_handler); // must be registered after (called before) the GUI which relies on these globals in_add_handler(GlobalsInputHandler); diff --git a/source/simulation2/MessageTypes.h b/source/simulation2/MessageTypes.h index fa9a52115f..5c0f4ba094 100644 --- a/source/simulation2/MessageTypes.h +++ b/source/simulation2/MessageTypes.h @@ -29,6 +29,8 @@ #include "maths/Vector3D.h" +#include "ps/CStr.h" + #define DEFAULT_MESSAGE_IMPL(name) \ virtual int GetType() const { return MT_##name; } \ virtual const char* GetScriptHandlerName() const { return "On" #name; } \ @@ -538,4 +540,27 @@ public: } }; +/** +* Cinematics events +*/ + +class CMessageCinemaPathEnded : public CMessage +{ +public: + DEFAULT_MESSAGE_IMPL(CinemaPathEnded) + + CMessageCinemaPathEnded(CStrW name) : + name(name) + { + } + + CStrW name; +}; + +class CMessageCinemaQueueEnded : public CMessage +{ +public: + DEFAULT_MESSAGE_IMPL(CinemaQueueEnded) +}; + #endif // INCLUDED_MESSAGETYPES diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h index 7b71ce1f46..e0d9c6ad88 100644 --- a/source/simulation2/TypeList.h +++ b/source/simulation2/TypeList.h @@ -57,6 +57,8 @@ MESSAGE(ValueModification) MESSAGE(TemplateModification) MESSAGE(VisionRangeChanged) MESSAGE(MinimapPing) +MESSAGE(CinemaPathEnded) +MESSAGE(CinemaQueueEnded) // TemplateManager must come before all other (non-test) components, // so that it is the first to be (de)serialized @@ -75,6 +77,9 @@ COMPONENT(AIInterfaceScripted) INTERFACE(AIManager) COMPONENT(AIManager) +INTERFACE(CinemaManager) +COMPONENT(CinemaManager) + INTERFACE(CommandQueue) COMPONENT(CommandQueue) diff --git a/source/simulation2/components/CCmpCinemaManager.cpp b/source/simulation2/components/CCmpCinemaManager.cpp new file mode 100644 index 0000000000..360e5117ad --- /dev/null +++ b/source/simulation2/components/CCmpCinemaManager.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2016 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "simulation2/system/Component.h" +#include "ICmpCinemaManager.h" + +#include "graphics/GameView.h" +#include "graphics/CinemaManager.h" +#include "ps/CLogger.h" +#include "ps/Game.h" +#include "simulation2/MessageTypes.h" +#include "simulation2/Simulation2.h" + + +class CCmpCinemaManager : public ICmpCinemaManager +{ +public: + static void ClassInit(CComponentManager& componentManager) + { + componentManager.SubscribeToMessageType(MT_Update); + } + + DEFAULT_COMPONENT_ALLOCATOR(CinemaManager) + + static std::string GetSchema() + { + return "" + "" + ; + } + + virtual void Init(const CParamNode& UNUSED(paramNode)) + { + // ... + } + + virtual void Deinit() + { + // ... + } + + virtual void Serialize(ISerializer& serialize) + { + if (!g_Game || !g_Game->GetView()) + { + LOGERROR("Trying to serialize cinematics when GameView isn't initialized!"); + return; + } + CinematicSimulationData* p_CinematicSimulationData = g_Game->GetView()->GetCinema()->GetCinematicSimulationData(); + serialize.Bool("MapRevealed", p_CinematicSimulationData->m_MapRevealed); + serialize.NumberU32_Unbounded("NumberOfPaths", p_CinematicSimulationData->m_Paths.size()); + for (auto it : p_CinematicSimulationData->m_Paths) + { + CCinemaPath& path = it.second; + const CCinemaData* data = path.GetData(); + + // TODO: maybe implement String_Unbounded + serialize.String("PathName", data->m_Name, 1, 2048); + serialize.String("PathOrientation", data->m_Orientation, 1, 2048); + serialize.String("PathMode", data->m_Mode, 1, 2048); + serialize.String("PathStyle", data->m_Style, 1, 2048); + serialize.NumberFixed_Unbounded("PathTimescale", data->m_Timescale); + serialize.Bool("LookAtTarget", data->m_LookAtTarget); + + serialize.NumberU32("NumberOfNodes", path.GetAllNodes().size(), 1, MAX_SPLINE_NODES); + const std::vector& nodes = path.GetAllNodes(); + for (size_t i = 0; i < nodes.size(); ++i) + { + if (i > 0) + serialize.NumberFixed_Unbounded("NodeDeltaTime", nodes[i - 1].Distance); + else + serialize.NumberFixed_Unbounded("NodeDeltaTime", fixed::Zero()); + serialize.NumberFixed_Unbounded("PositionX", nodes[i].Position.X); + serialize.NumberFixed_Unbounded("PositionY", nodes[i].Position.Y); + serialize.NumberFixed_Unbounded("PositionZ", nodes[i].Position.Z); + + serialize.NumberFixed_Unbounded("RotationX", nodes[i].Rotation.X); + serialize.NumberFixed_Unbounded("RotationY", nodes[i].Rotation.Y); + serialize.NumberFixed_Unbounded("RotationZ", nodes[i].Rotation.Z); + } + + if (!data->m_LookAtTarget) + continue; + + const std::vector& targetNodes = path.getTargetSpline()->GetAllNodes(); + serialize.NumberU32("NumberOfTargetNodes", targetNodes.size(), 1, MAX_SPLINE_NODES); + for (size_t i = 0; i < targetNodes.size(); ++i) + { + if (i > 0) + serialize.NumberFixed_Unbounded("NodeDeltaTime", nodes[i - 1].Distance); + else + serialize.NumberFixed_Unbounded("NodeDeltaTime", fixed::Zero()); + serialize.NumberFixed_Unbounded("PositionX", nodes[i].Position.X); + serialize.NumberFixed_Unbounded("PositionY", nodes[i].Position.Y); + serialize.NumberFixed_Unbounded("PositionZ", nodes[i].Position.Z); + } + } + } + + virtual void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize) + { + if (!g_Game || !g_Game->GetView()) + { + LOGERROR("Trying to deserialize cinematics when GameView isn't initialized!"); + return; + } + CinematicSimulationData* p_CinematicSimulationData = g_Game->GetView()->GetCinema()->GetCinematicSimulationData(); + deserialize.Bool("MapRevealed", p_CinematicSimulationData->m_MapRevealed); + uint32_t numberOfPaths = 0; + deserialize.NumberU32_Unbounded("NumberOfPaths", numberOfPaths); + for (uint32_t i = 0; i < numberOfPaths; ++i) + { + CCinemaData data; + + deserialize.String("PathName", data.m_Name, 1, 2048); + deserialize.String("PathOrientation", data.m_Orientation, 1, 2048); + deserialize.String("PathMode", data.m_Mode, 1, 2048); + deserialize.String("PathStyle", data.m_Style, 1, 2048); + deserialize.NumberFixed_Unbounded("PathTimescale", data.m_Timescale); + deserialize.Bool("LookAtTarget", data.m_LookAtTarget); + + TNSpline pathSpline, targetSpline; + uint32_t numberOfNodes = 0; + deserialize.NumberU32("NumberOfNodes", numberOfNodes, 1, MAX_SPLINE_NODES); + for (uint32_t j = 0; j < numberOfNodes; ++j) + { + SplineData node; + deserialize.NumberFixed_Unbounded("NodeDeltaTime", node.Distance); + + deserialize.NumberFixed_Unbounded("PositionX", node.Position.X); + deserialize.NumberFixed_Unbounded("PositionY", node.Position.Y); + deserialize.NumberFixed_Unbounded("PositionZ", node.Position.Z); + + deserialize.NumberFixed_Unbounded("RotationX", node.Rotation.X); + deserialize.NumberFixed_Unbounded("RotationY", node.Rotation.Y); + deserialize.NumberFixed_Unbounded("RotationZ", node.Rotation.Z); + + pathSpline.AddNode(node.Position, node.Rotation, node.Distance); + } + + if (data.m_LookAtTarget) + { + uint32_t numberOfTargetNodes = 0; + deserialize.NumberU32("NumberOfTargetNodes", numberOfTargetNodes, 1, MAX_SPLINE_NODES); + for (uint32_t j = 0; j < numberOfTargetNodes; ++j) + { + SplineData node; + deserialize.NumberFixed_Unbounded("NodeDeltaTime", node.Distance); + + deserialize.NumberFixed_Unbounded("PositionX", node.Position.X); + deserialize.NumberFixed_Unbounded("PositionY", node.Position.Y); + deserialize.NumberFixed_Unbounded("PositionZ", node.Position.Z); + + targetSpline.AddNode(node.Position, CFixedVector3D(), node.Distance); + } + } + + // Construct cinema path with data gathered + CCinemaPath path(data, pathSpline, targetSpline); + p_CinematicSimulationData->m_Paths[data.m_Name] = path; + } + g_Game->GetView()->GetCinema()->SetEnabled(p_CinematicSimulationData->m_Enabled); + } + + virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) + { + switch (msg.GetType()) + { + case MT_Update: + { + const CMessageUpdate &msgData = static_cast(msg); + CinematicSimulationData* pCinematicSimulationData = g_Game->GetView()->GetCinema()->GetCinematicSimulationData(); + if (!pCinematicSimulationData->m_Enabled) + break; + + if (pCinematicSimulationData->m_ElapsedTime >= pCinematicSimulationData->m_TotalTime) + { + pCinematicSimulationData->m_ElapsedTime = fixed::Zero(); + pCinematicSimulationData->m_TotalTime = fixed::Zero(); + g_Game->GetView()->GetCinema()->SetEnabled(false); + g_Game->GetSimulation2()->PostMessage(SYSTEM_ENTITY, CMessageCinemaQueueEnded()); + } + else + { + pCinematicSimulationData->m_ElapsedTime += msgData.turnLength; + pCinematicSimulationData->m_CurrentPathElapsedTime += msgData.turnLength; + if (pCinematicSimulationData->m_CurrentPathElapsedTime >= pCinematicSimulationData->m_PathQueue.front().GetDuration()) + { + CMessageCinemaPathEnded msgCinemaPathEnded(pCinematicSimulationData->m_PathQueue.front().GetName()); + pCinematicSimulationData->m_PathQueue.pop_front(); + g_Game->GetSimulation2()->PostMessage(SYSTEM_ENTITY, msgCinemaPathEnded); + } + } + break; + } + default: + break; + } + } + + virtual void AddCinemaPathToQueue(CStrW name) + { + if (!g_Game || !g_Game->GetView()) + { + LOGERROR("Trying to add cinema path when GameView isn't initialized!"); + return; + } + g_Game->GetView()->GetCinema()->AddPathToQueue(name); + CinematicSimulationData* pGetCinematicSimulationData = g_Game->GetView()->GetCinema()->GetCinematicSimulationData(); + pGetCinematicSimulationData->m_TotalTime += pGetCinematicSimulationData->m_Paths[name].GetDuration(); + } + + virtual void Play() + { + if (!g_Game || !g_Game->GetView()) + { + LOGERROR("Trying to play cinematics when GameView isn't initialized!"); + return; + } + g_Game->GetView()->GetCinema()->Play(); + g_Game->GetView()->GetCinema()->SetEnabled(true); + } + + virtual void Stop() + { + if (!g_Game || !g_Game->GetView()) + { + LOGERROR("Trying to stop cinematics when GameView isn't initialized!"); + return; + } + g_Game->GetView()->GetCinema()->Stop(); + g_Game->GetView()->GetCinema()->SetEnabled(false); + } + +}; + +REGISTER_COMPONENT_TYPE(CinemaManager) diff --git a/source/simulation2/components/CCmpOverlayRenderer.cpp b/source/simulation2/components/CCmpOverlayRenderer.cpp index abcc0e126b..33736e9c0a 100644 --- a/source/simulation2/components/CCmpOverlayRenderer.cpp +++ b/source/simulation2/components/CCmpOverlayRenderer.cpp @@ -166,7 +166,7 @@ public: void RenderSubmit(SceneCollector& collector) { - if (!m_Enabled) + if (!m_Enabled || !ICmpOverlayRenderer::m_OverrideVisible) return; for (size_t i = 0; i < m_Sprites.size(); ++i) diff --git a/source/simulation2/components/CCmpSelectable.cpp b/source/simulation2/components/CCmpSelectable.cpp index 5146fe1fad..1e942a11dd 100644 --- a/source/simulation2/components/CCmpSelectable.cpp +++ b/source/simulation2/components/CCmpSelectable.cpp @@ -587,6 +587,9 @@ void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) void CCmpSelectable::RenderSubmit(SceneCollector& collector) { // don't render selection overlay if it's not gonna be visible + if (!ICmpSelectable::m_OverrideVisible) + return; + if (m_Visible && m_Color.a > 0) { if (!m_Cached) diff --git a/source/simulation2/components/CCmpTerritoryManager.cpp b/source/simulation2/components/CCmpTerritoryManager.cpp index 1f453a9196..109d1f5247 100644 --- a/source/simulation2/components/CCmpTerritoryManager.cpp +++ b/source/simulation2/components/CCmpTerritoryManager.cpp @@ -123,6 +123,7 @@ public: m_TriggerEvent = true; m_EnableLineDebugOverlays = false; m_DirtyID = 1; + m_Visible = true; m_AnimTime = 0.0; @@ -275,6 +276,15 @@ public: void Interpolate(float frameTime, float frameOffset); void RenderSubmit(SceneCollector& collector); + + void SetVisibility(bool visible) + { + m_Visible = visible; + } + +private: + + bool m_Visible; }; REGISTER_COMPONENT_TYPE(TerritoryManager) @@ -644,6 +654,9 @@ void CCmpTerritoryManager::Interpolate(float frameTime, float UNUSED(frameOffset void CCmpTerritoryManager::RenderSubmit(SceneCollector& collector) { + if (!m_Visible) + return; + for (size_t i = 0; i < m_BoundaryLines.size(); ++i) collector.Submit(&m_BoundaryLines[i].overlay); diff --git a/source/simulation2/components/ICmpCinemaManager.cpp b/source/simulation2/components/ICmpCinemaManager.cpp new file mode 100644 index 0000000000..51e4fb42af --- /dev/null +++ b/source/simulation2/components/ICmpCinemaManager.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2016 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "ICmpCinemaManager.h" + +#include "simulation2/system/InterfaceScripted.h" + +BEGIN_INTERFACE_WRAPPER(CinemaManager) +DEFINE_INTERFACE_METHOD_1("AddCinemaPathToQueue", void, ICmpCinemaManager, AddCinemaPathToQueue, CStrW) +DEFINE_INTERFACE_METHOD_0("Play", void, ICmpCinemaManager, Play) +DEFINE_INTERFACE_METHOD_0("Stop", void, ICmpCinemaManager, Stop) +END_INTERFACE_WRAPPER(CinemaManager) diff --git a/source/simulation2/components/ICmpCinemaManager.h b/source/simulation2/components/ICmpCinemaManager.h new file mode 100644 index 0000000000..8b694e3c50 --- /dev/null +++ b/source/simulation2/components/ICmpCinemaManager.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2016 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_ICMPCINEMAMANAGER +#define INCLUDED_ICMPCINEMAMANAGER + +#include "simulation2/system/Interface.h" + +#include "ps/CStr.h" + +/** + * Component for CCinemaManager class + * TODO: write description + */ + +class ICmpCinemaManager : public IComponent +{ +public: + // TODO: add path name and description + virtual void AddCinemaPathToQueue(CStrW name) = 0; + + virtual void Play() = 0; + virtual void Stop() = 0; + + DECLARE_INTERFACE_TYPE(CinemaManager) +}; + +#endif // INCLUDED_ICMPCINEMAMANAGER \ No newline at end of file diff --git a/source/simulation2/components/ICmpOverlayRenderer.cpp b/source/simulation2/components/ICmpOverlayRenderer.cpp index 1fc287bdc1..3bc0baaed6 100644 --- a/source/simulation2/components/ICmpOverlayRenderer.cpp +++ b/source/simulation2/components/ICmpOverlayRenderer.cpp @@ -25,3 +25,5 @@ BEGIN_INTERFACE_WRAPPER(OverlayRenderer) DEFINE_INTERFACE_METHOD_0("Reset", void, ICmpOverlayRenderer, Reset) DEFINE_INTERFACE_METHOD_5("AddSprite", void, ICmpOverlayRenderer, AddSprite, VfsPath, CFixedVector2D, CFixedVector2D, CFixedVector3D, std::string) END_INTERFACE_WRAPPER(OverlayRenderer) + +bool ICmpOverlayRenderer::m_OverrideVisible = true; \ No newline at end of file diff --git a/source/simulation2/components/ICmpOverlayRenderer.h b/source/simulation2/components/ICmpOverlayRenderer.h index 3e6e4ca32d..9dfb18c05b 100644 --- a/source/simulation2/components/ICmpOverlayRenderer.h +++ b/source/simulation2/components/ICmpOverlayRenderer.h @@ -52,7 +52,19 @@ public: */ virtual void AddSprite(VfsPath textureName, CFixedVector2D corner0, CFixedVector2D corner1, CFixedVector3D offset, std::string color = "255 255 255 255") = 0; + /** + * Enables or disables rendering of all sprites. + * @param visible Whether the selectable should be visible. + */ + static void SetOverrideVisibility(bool visible) + { + ICmpOverlayRenderer::m_OverrideVisible = visible; + } + DECLARE_INTERFACE_TYPE(OverlayRenderer) + +protected: + static bool m_OverrideVisible; }; #endif // INCLUDED_ICMPOVERLAYRENDERER diff --git a/source/simulation2/components/ICmpSelectable.cpp b/source/simulation2/components/ICmpSelectable.cpp index a947855d04..a4caea4989 100644 --- a/source/simulation2/components/ICmpSelectable.cpp +++ b/source/simulation2/components/ICmpSelectable.cpp @@ -28,3 +28,4 @@ DEFINE_INTERFACE_METHOD_2("SetSelectionHighlight", void, ICmpSelectable, SetSele END_INTERFACE_WRAPPER(Selectable) bool ICmpSelectable::ms_EnableDebugOverlays = false; +bool ICmpSelectable::m_OverrideVisible = true; diff --git a/source/simulation2/components/ICmpSelectable.h b/source/simulation2/components/ICmpSelectable.h index 37339ce29f..57eb55c86f 100644 --- a/source/simulation2/components/ICmpSelectable.h +++ b/source/simulation2/components/ICmpSelectable.h @@ -66,6 +66,15 @@ public: */ virtual void SetVisibility(bool visible) = 0; + /** + * Enables or disables rendering of all entities selectable. + * @param visible Whether the selectable should be visible. + */ + static void SetOverrideVisibility(bool visible) + { + ICmpSelectable::m_OverrideVisible = visible; + } + /** * Set the alpha of the selection highlight. Set to 0 to hide the highlight. */ @@ -77,6 +86,9 @@ public: // and methods, where we can keep settings like these. Note that any such data store would need to be per-component-manager // and not entirely global, to support multiple simulation instances. static bool ms_EnableDebugOverlays; // ms for member static + +protected: + static bool m_OverrideVisible; }; #endif // INCLUDED_ICMPSELECTABLE diff --git a/source/simulation2/components/ICmpTerritoryManager.h b/source/simulation2/components/ICmpTerritoryManager.h index df123bddeb..a2768914bf 100644 --- a/source/simulation2/components/ICmpTerritoryManager.h +++ b/source/simulation2/components/ICmpTerritoryManager.h @@ -78,6 +78,11 @@ public: */ virtual u8 GetTerritoryPercentage(player_id_t player) = 0; + /** + * Enables or disables rendering of an territory borders. + */ + virtual void SetVisibility(bool visible) = 0; + DECLARE_INTERFACE_TYPE(TerritoryManager) }; diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index ed951e0b4c..01518a4d2c 100644 --- a/source/simulation2/scripting/MessageTypeConversions.cpp +++ b/source/simulation2/scripting/MessageTypeConversions.cpp @@ -470,6 +470,36 @@ CMessage* CMessageMinimapPing::FromJSVal(ScriptInterface& UNUSED(scriptInterface return new CMessageMinimapPing(); } +//////////////////////////////// + +JS::Value CMessageCinemaPathEnded::ToJSVal(ScriptInterface& scriptInterface) const +{ + TOJSVAL_SETUP(); + SET_MSG_PROPERTY(name); + return JS::ObjectValue(*obj); +} + +CMessage* CMessageCinemaPathEnded::FromJSVal(ScriptInterface& scriptInterface, JS::HandleValue val) +{ + FROMJSVAL_SETUP(); + GET_MSG_PROPERTY(CStrW, name); + return new CMessageCinemaPathEnded(name); +} + +//////////////////////////////// + +JS::Value CMessageCinemaQueueEnded::ToJSVal(ScriptInterface& scriptInterface) const +{ + TOJSVAL_SETUP(); + return JS::ObjectValue(*obj); +} + +CMessage* CMessageCinemaQueueEnded::FromJSVal(ScriptInterface& scriptInterface, JS::HandleValue val) +{ + FROMJSVAL_SETUP(); + return new CMessageCinemaQueueEnded(); +} + //////////////////////////////////////////////////////////////// CMessage* CMessageFromJSVal(int mtid, ScriptInterface& scriptingInterface, JS::HandleValue val) diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index fb8e0383e4..b4f4f38830 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -711,6 +711,7 @@ void CComponentManager::AddSystemComponents(bool skipScriptedComponents, bool sk { CParamNode noParam; AddComponent(m_SystemEntity, CID_TemplateManager, noParam); + AddComponent(m_SystemEntity, CID_CinemaManager, noParam); AddComponent(m_SystemEntity, CID_CommandQueue, noParam); AddComponent(m_SystemEntity, CID_ObstructionManager, noParam); AddComponent(m_SystemEntity, CID_ParticleManager, noParam); diff --git a/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp b/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp index 22c96f6274..ad237efb50 100644 --- a/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp +++ b/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp @@ -38,10 +38,10 @@ sCinemaPath ConstructCinemaPath(const CCinemaPath* source) { sCinemaPath path; const CCinemaData* data = source->GetData(); - path.mode = data->m_Mode; - path.style = data->m_Style; + //path.mode = data->m_Mode; + //path.style = data->m_Style; path.growth = data->m_Growth; - path.timescale = data->m_Timescale; + path.timescale = data->m_Timescale.ToFloat(); path.change = data->m_Switch; return path; @@ -51,22 +51,22 @@ CCinemaData ConstructCinemaData(const sCinemaPath& path) CCinemaData data; data.m_Growth = data.m_GrowthCount = path.growth; data.m_Switch = path.change; - data.m_Mode = path.mode; - data.m_Style = path.style; + //data.m_Mode = path.mode; + //data.m_Style = path.style; return data; } sCinemaSplineNode ConstructCinemaNode(const SplineData& data) { sCinemaSplineNode node; - node.px = data.Position.X; - node.py = data.Position.Y; - node.pz = data.Position.Z; + node.px = data.Position.X.ToFloat(); + node.py = data.Position.Y.ToFloat(); + node.pz = data.Position.Z.ToFloat(); - node.rx = data.Rotation.X; - node.ry = data.Rotation.Y; - node.rz = data.Rotation.Z; - node.t = data.Distance; + node.rx = data.Rotation.X.ToFloat(); + node.ry = data.Rotation.Y.ToFloat(); + node.rz = data.Rotation.Z.ToFloat(); + node.t = data.Distance.ToFloat(); return node; } @@ -112,7 +112,7 @@ void SetCurrentPaths(const std::vector& atlasPaths) { CStrW pathName(*it->name); paths[pathName] = CCinemaPath(); - paths[pathName].SetTimescale(it->timescale); + paths[pathName].SetTimescale(fixed::FromFloat(it->timescale)); const sCinemaPath& atlasPath = *it; const std::vector nodes = *atlasPath.nodes; @@ -121,10 +121,10 @@ void SetCurrentPaths(const std::vector& atlasPaths) for ( size_t j=0; jGetView()->GetCinema()->SetAllPaths(paths); @@ -155,16 +155,15 @@ MESSAGEHANDLER(CinemaEvent) { CCinemaManager* manager = g_Game->GetView()->GetCinema(); - if ( msg->mode == eCinemaEventMode::SMOOTH ) - manager->OverridePath(*msg->path); - else if ( msg->mode == eCinemaEventMode::IMMEDIATE_PATH ) - manager->MoveToPointAt(msg->t); + if (msg->mode == eCinemaEventMode::SMOOTH) + { + manager->ClearQueue(); + manager->AddPathToQueue(*msg->path); + } else if ( msg->mode == eCinemaEventMode::RESET ) { // g_Game->GetView()->ResetCamera(); } - else if ( msg->mode == eCinemaEventMode::SELECT ) - manager->SetCurrentPath(*msg->path, msg->drawCurrent, msg->lines); else ENSURE(false); } diff --git a/source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp index f7ac490bc7..7ca7b9cd73 100644 --- a/source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp @@ -56,9 +56,6 @@ MESSAGEHANDLER(Screenshot) QUERYHANDLER(CinemaRecord) { - CCinemaManager* manager = g_Game->GetView()->GetCinema(); - manager->SetCurrentPath(*msg->path, false, false); - const int w = msg->width, h = msg->height; { @@ -82,7 +79,6 @@ QUERYHANDLER(CinemaRecord) { AtlasView::GetView_Game()->Update(1.f / msg->framerate); - manager->MoveToPointAt((float)frame/msg->framerate); Render(); Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);