mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-21 01:04:06 +00:00
Revamp CinemaManager component
Clean up the the implementation, improve the naming, and add some more documentation as well as more in-depth tests.
This commit is contained in:
@@ -1,22 +1,21 @@
|
|||||||
Trigger.prototype.CounterMessage = function(data)
|
Trigger.prototype.CounterMessage = function(data)
|
||||||
{
|
{
|
||||||
var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
|
Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface)?.PushNotification({
|
||||||
cmpGUIInterface.PushNotification({
|
|
||||||
"players": [1, 2],
|
"players": [1, 2],
|
||||||
"message": markForTranslation("Cutscene starts after 5 seconds"),
|
"message": markForTranslation("Cutscene starts after 5 seconds"),
|
||||||
"translateMessage": true
|
"translateMessage": true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Trigger.prototype.StartCutscene = function(data)
|
Trigger.prototype.StartCutscene = function()
|
||||||
{
|
{
|
||||||
var cmpCinemaManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinemaManager);
|
const cmpCinemaManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinemaManager);
|
||||||
if (!cmpCinemaManager)
|
if (!cmpCinemaManager)
|
||||||
return;
|
return;
|
||||||
cmpCinemaManager.AddCinemaPathToQueue("test");
|
cmpCinemaManager.PushPathToQueue("test");
|
||||||
cmpCinemaManager.Play();
|
cmpCinemaManager.StartPlayingQueue();
|
||||||
};
|
};
|
||||||
|
|
||||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
const cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
||||||
cmpTrigger.DoAfterDelay(1000, "CounterMessage", {});
|
cmpTrigger.DoAfterDelay(1000, "CounterMessage", {});
|
||||||
cmpTrigger.DoAfterDelay(6000, "StartCutscene", {});
|
cmpTrigger.DoAfterDelay(5000, "StartCutscene", {});
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ GuiInterface.prototype.GetSimulationState = function()
|
|||||||
|
|
||||||
const cmpCinemaManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinemaManager);
|
const cmpCinemaManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinemaManager);
|
||||||
if (cmpCinemaManager)
|
if (cmpCinemaManager)
|
||||||
ret.cinemaPlaying = cmpCinemaManager.IsPlaying();
|
ret.cinemaPlaying = cmpCinemaManager.IsPlayingQueue();
|
||||||
|
|
||||||
const cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
const cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
||||||
ret.victoryConditions = cmpEndGameManager.GetVictoryConditions();
|
ret.victoryConditions = cmpEndGameManager.GetVictoryConditions();
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ void CCinemaManager::Update(const float deltaRealTime) const
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (IsPlaying())
|
if (IsPlaying())
|
||||||
cmpCinemaManager->PlayQueue(deltaRealTime, g_Game->GetView()->GetCamera());
|
cmpCinemaManager->UpdateActivePath(deltaRealTime, g_Game->GetView()->GetCamera());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCinemaManager::Render(Renderer::Backend::IDeviceCommandContext& deviceCommandContext) const
|
void CCinemaManager::Render(Renderer::Backend::IDeviceCommandContext& deviceCommandContext) const
|
||||||
{
|
{
|
||||||
if (!IsEnabled() && m_DrawPaths)
|
if (!IsPlaying() && m_DrawPaths)
|
||||||
DrawPaths(deviceCommandContext);
|
DrawPaths(deviceCommandContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,15 +121,10 @@ void CCinemaManager::DrawNodes(Renderer::Backend::IDeviceCommandContext& deviceC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCinemaManager::IsEnabled() const
|
|
||||||
{
|
|
||||||
CmpPtr<ICmpCinemaManager> cmpCinemaManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity());
|
|
||||||
return cmpCinemaManager && cmpCinemaManager->IsEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CCinemaManager::IsPlaying() const
|
bool CCinemaManager::IsPlaying() const
|
||||||
{
|
{
|
||||||
return IsEnabled() && g_Game && !g_Game->m_Paused;
|
CmpPtr<ICmpCinemaManager> cmpCinemaManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity());
|
||||||
|
return cmpCinemaManager && cmpCinemaManager->IsPlayingQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCinemaManager::GetPathsDrawing() const
|
bool CCinemaManager::GetPathsDrawing() const
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ public:
|
|||||||
void Render(Renderer::Backend::IDeviceCommandContext& deviceCommandContext) const;
|
void Render(Renderer::Backend::IDeviceCommandContext& deviceCommandContext) const;
|
||||||
|
|
||||||
bool IsPlaying() const;
|
bool IsPlaying() const;
|
||||||
bool IsEnabled() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates CCinemManager and current path
|
* Updates CCinemManager and current path
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -291,6 +291,9 @@ void CGameView::Update(const float deltaRealTime)
|
|||||||
{
|
{
|
||||||
m->MiniMapTexture.Update(deltaRealTime);
|
m->MiniMapTexture.Update(deltaRealTime);
|
||||||
|
|
||||||
|
m->CinemaManager.Update(deltaRealTime);
|
||||||
|
if (m->CinemaManager.IsPlaying())
|
||||||
|
return;
|
||||||
// If camera movement is being handled by the touch-input system,
|
// If camera movement is being handled by the touch-input system,
|
||||||
// then we should stop to avoid conflicting with it
|
// then we should stop to avoid conflicting with it
|
||||||
if (g_TouchInput.IsEnabled())
|
if (g_TouchInput.IsEnabled())
|
||||||
@@ -299,10 +302,6 @@ void CGameView::Update(const float deltaRealTime)
|
|||||||
if (!g_app_has_focus)
|
if (!g_app_has_focus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m->CinemaManager.Update(deltaRealTime);
|
|
||||||
if (m->CinemaManager.IsEnabled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m->CameraController->Update(deltaRealTime);
|
m->CameraController->Update(deltaRealTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +353,7 @@ entity_id_t CGameView::GetFollowedEntity()
|
|||||||
InReaction game_view_handler(const SDL_Event_* ev)
|
InReaction game_view_handler(const SDL_Event_* ev)
|
||||||
{
|
{
|
||||||
// put any events that must be processed even if inactive here
|
// put any events that must be processed even if inactive here
|
||||||
if (!g_app_has_focus || !g_Game || !g_Game->IsGameStarted() || g_Game->GetView()->GetCinema()->IsEnabled())
|
if (!g_app_has_focus || !g_Game || !g_Game->IsGameStarted() || g_Game->GetView()->GetCinema()->IsPlaying())
|
||||||
return IN_PASS;
|
return IN_PASS;
|
||||||
|
|
||||||
CGameView *pView=g_Game->GetView();
|
CGameView *pView=g_Game->GetView();
|
||||||
|
|||||||
@@ -26,11 +26,10 @@
|
|||||||
#include "ps/CLogger.h"
|
#include "ps/CLogger.h"
|
||||||
#include "ps/CStr.h"
|
#include "ps/CStr.h"
|
||||||
#include "ps/Game.h"
|
#include "ps/Game.h"
|
||||||
|
#include "renderer/Renderer.h"
|
||||||
|
#include "renderer/SceneRenderer.h"
|
||||||
#include "simulation2/MessageTypes.h"
|
#include "simulation2/MessageTypes.h"
|
||||||
#include "simulation2/components/ICmpOverlayRenderer.h"
|
|
||||||
#include "simulation2/components/ICmpRangeManager.h"
|
#include "simulation2/components/ICmpRangeManager.h"
|
||||||
#include "simulation2/components/ICmpSelectable.h"
|
|
||||||
#include "simulation2/components/ICmpTerritoryManager.h"
|
|
||||||
#include "simulation2/helpers/CinemaPath.h"
|
#include "simulation2/helpers/CinemaPath.h"
|
||||||
#include "simulation2/system/Component.h"
|
#include "simulation2/system/Component.h"
|
||||||
#include "simulation2/system/Entity.h"
|
#include "simulation2/system/Entity.h"
|
||||||
@@ -50,6 +49,7 @@ public:
|
|||||||
static void ClassInit(CComponentManager& componentManager)
|
static void ClassInit(CComponentManager& componentManager)
|
||||||
{
|
{
|
||||||
componentManager.SubscribeToMessageType(MT_Update);
|
componentManager.SubscribeToMessageType(MT_Update);
|
||||||
|
componentManager.SubscribeToMessageType(MT_Deserialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_COMPONENT_ALLOCATOR(CinemaManager)
|
DEFAULT_COMPONENT_ALLOCATOR(CinemaManager)
|
||||||
@@ -61,11 +61,11 @@ public:
|
|||||||
|
|
||||||
void Init(const CParamNode&) override
|
void Init(const CParamNode&) override
|
||||||
{
|
{
|
||||||
m_Enabled = false;
|
m_IsPlayingPathQueue = false;
|
||||||
m_MapRevealed = false;
|
m_QueuePlayingElapsedTime = fixed::Zero();
|
||||||
m_ElapsedTime = fixed::Zero();
|
m_PathQueueDuration = fixed::Zero();
|
||||||
m_TotalTime = fixed::Zero();
|
m_ActivePathElapsedTime = fixed::Zero();
|
||||||
m_CurrentPathElapsedTime = fixed::Zero();
|
m_WasMapRevealed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Deinit() override
|
void Deinit() override
|
||||||
@@ -74,10 +74,10 @@ public:
|
|||||||
|
|
||||||
void Serialize(ISerializer& serializer) override
|
void Serialize(ISerializer& serializer) override
|
||||||
{
|
{
|
||||||
serializer.Bool("Enabled", m_Enabled);
|
serializer.Bool("IsPlayingPathQueue", m_IsPlayingPathQueue);
|
||||||
serializer.NumberFixed_Unbounded("ElapsedTime", m_ElapsedTime);
|
serializer.NumberFixed_Unbounded("QueueElapsedTime", m_QueuePlayingElapsedTime);
|
||||||
serializer.NumberFixed_Unbounded("CurrentPathElapsedTime", m_CurrentPathElapsedTime);
|
serializer.NumberFixed_Unbounded("CurrentPathElapsedTime", m_ActivePathElapsedTime);
|
||||||
serializer.Bool("MapRevealed", m_MapRevealed);
|
serializer.Bool("WasMapRevealed", m_WasMapRevealed);
|
||||||
|
|
||||||
serializer.NumberU32_Unbounded("NumberOfPaths", m_Paths.size());
|
serializer.NumberU32_Unbounded("NumberOfPaths", m_Paths.size());
|
||||||
for (const std::pair<const CStrW, CCinemaPath>& it : m_Paths)
|
for (const std::pair<const CStrW, CCinemaPath>& it : m_Paths)
|
||||||
@@ -85,15 +85,15 @@ public:
|
|||||||
|
|
||||||
serializer.NumberU32_Unbounded("NumberOfQueuedPaths", m_PathQueue.size());
|
serializer.NumberU32_Unbounded("NumberOfQueuedPaths", m_PathQueue.size());
|
||||||
for (const CCinemaPath& path : m_PathQueue)
|
for (const CCinemaPath& path : m_PathQueue)
|
||||||
serializer.String("PathName", path.GetName(), 1, 128);
|
serializer.String("QueuedPathName", path.GetName(), 1, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Deserialize(const CParamNode&, IDeserializer& deserializer) override
|
void Deserialize(const CParamNode&, IDeserializer& deserializer) override
|
||||||
{
|
{
|
||||||
deserializer.Bool("Enabled", m_Enabled);
|
deserializer.Bool("IsPlayingPathQueue", m_IsPlayingPathQueue);
|
||||||
deserializer.NumberFixed_Unbounded("ElapsedTime", m_ElapsedTime);
|
deserializer.NumberFixed_Unbounded("QueueElapsedTime", m_QueuePlayingElapsedTime);
|
||||||
deserializer.NumberFixed_Unbounded("CurrentPathElapsedTime", m_CurrentPathElapsedTime);
|
deserializer.NumberFixed_Unbounded("CurrentPathElapsedTime", m_ActivePathElapsedTime);
|
||||||
deserializer.Bool("MapRevealed", m_MapRevealed);
|
deserializer.Bool("WasMapRevealed", m_WasMapRevealed);
|
||||||
|
|
||||||
uint32_t numberOfPaths = 0;
|
uint32_t numberOfPaths = 0;
|
||||||
deserializer.NumberU32_Unbounded("NumberOfPaths", numberOfPaths);
|
deserializer.NumberU32_Unbounded("NumberOfPaths", numberOfPaths);
|
||||||
@@ -108,55 +108,53 @@ public:
|
|||||||
for (uint32_t i = 0; i < numberOfQueuedPaths; ++i)
|
for (uint32_t i = 0; i < numberOfQueuedPaths; ++i)
|
||||||
{
|
{
|
||||||
CStrW pathName;
|
CStrW pathName;
|
||||||
deserializer.String("PathName", pathName, 1, 128);
|
deserializer.String("QueuedPathName", pathName, 1, 128);
|
||||||
ENSURE(HasPath(pathName));
|
ENSURE(HasPath(pathName));
|
||||||
AddCinemaPathToQueue(pathName);
|
PushPathToQueue(pathName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_PathQueue.empty())
|
if (!m_PathQueue.empty())
|
||||||
{
|
{
|
||||||
m_PathQueue.front().m_TimeElapsed = m_CurrentPathElapsedTime.ToFloat();
|
m_PathQueue.front().m_TimeElapsed = m_ActivePathElapsedTime.ToFloat();
|
||||||
m_PathQueue.front().Validate();
|
m_PathQueue.front().Validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEnabled(m_Enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleMessage(const CMessage& msg, bool /*global*/) override
|
void HandleMessage(const CMessage& msg, bool /*global*/) override
|
||||||
{
|
{
|
||||||
switch (msg.GetType())
|
switch (msg.GetType())
|
||||||
{
|
{
|
||||||
|
case MT_Deserialized:
|
||||||
|
if (!m_IsPlayingPathQueue)
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_IsPlayingPathQueue = false;
|
||||||
|
StartPlayingQueue();
|
||||||
|
break;
|
||||||
case MT_Update:
|
case MT_Update:
|
||||||
{
|
{
|
||||||
const CMessageUpdate &msgData = static_cast<const CMessageUpdate&>(msg);
|
const CMessageUpdate &msgData = static_cast<const CMessageUpdate&>(msg);
|
||||||
if (!m_Enabled)
|
if (!m_IsPlayingPathQueue)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// The paths play at a fixed speed, no matter the sim rate.
|
// The paths play at a fixed speed, no matter the sim rate.
|
||||||
// The turn length we have received here, however, is scaled by that rate.
|
// The turn length we have received here, however, is scaled by that rate.
|
||||||
const fixed realTurnLength{msgData.turnLength / fixed::FromFloat(g_Game ? g_Game->GetSimRate() : 1.0f)};
|
const fixed realTurnLength{msgData.turnLength / fixed::FromFloat(g_Game ? g_Game->GetSimRate() : 1.0f)};
|
||||||
m_ElapsedTime += realTurnLength;
|
m_QueuePlayingElapsedTime += realTurnLength;
|
||||||
m_CurrentPathElapsedTime += realTurnLength;
|
m_ActivePathElapsedTime += realTurnLength;
|
||||||
if (m_CurrentPathElapsedTime >= m_PathQueue.front().GetDuration())
|
if (m_ActivePathElapsedTime >= m_PathQueue.front().GetDuration())
|
||||||
{
|
{
|
||||||
CMessageCinemaPathEnded msgCinemaPathEnded(m_PathQueue.front().GetName());
|
CMessageCinemaPathEnded msgCinemaPathEnded(m_PathQueue.front().GetName());
|
||||||
m_PathQueue.pop_front();
|
m_PathQueue.pop_front();
|
||||||
GetSimContext().GetComponentManager().PostMessage(SYSTEM_ENTITY, msgCinemaPathEnded);
|
GetSimContext().GetComponentManager().PostMessage(SYSTEM_ENTITY, msgCinemaPathEnded);
|
||||||
m_CurrentPathElapsedTime = fixed::Zero();
|
m_ActivePathElapsedTime = fixed::Zero();
|
||||||
|
|
||||||
if (!m_PathQueue.empty())
|
if (!m_PathQueue.empty())
|
||||||
m_PathQueue.front().Reset();
|
m_PathQueue.front().Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ElapsedTime >= m_TotalTime)
|
if (m_QueuePlayingElapsedTime >= m_PathQueueDuration)
|
||||||
{
|
StopPlayingQueue();
|
||||||
m_CurrentPathElapsedTime = fixed::Zero();
|
|
||||||
m_ElapsedTime = fixed::Zero();
|
|
||||||
m_TotalTime = fixed::Zero();
|
|
||||||
SetEnabled(false);
|
|
||||||
GetSimContext().GetComponentManager().PostMessage(SYSTEM_ENTITY, CMessageCinemaQueueEnded());
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -168,57 +166,28 @@ public:
|
|||||||
{
|
{
|
||||||
if (m_Paths.find(path.GetName()) != m_Paths.end())
|
if (m_Paths.find(path.GetName()) != m_Paths.end())
|
||||||
{
|
{
|
||||||
LOGWARNING("Path with name '%s' already exists", path.GetName().ToUTF8());
|
LOGWARNING("Cinema path with name '%s' already exists", path.GetName().ToUTF8());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_Paths[path.GetName()] = path;
|
m_Paths[path.GetName()] = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCinemaPathToQueue(const CStrW& name) override
|
|
||||||
{
|
|
||||||
if (!HasPath(name))
|
|
||||||
{
|
|
||||||
LOGWARNING("Path with name '%s' doesn't exist", name.ToUTF8());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_PathQueue.push_back(m_Paths[name]);
|
|
||||||
|
|
||||||
if (m_PathQueue.size() == 1)
|
|
||||||
m_PathQueue.front().Reset();
|
|
||||||
m_TotalTime += m_Paths[name].GetDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Play() override
|
|
||||||
{
|
|
||||||
SetEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Stop() override
|
|
||||||
{
|
|
||||||
SetEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasPath(const CStrW& name) const override
|
|
||||||
{
|
|
||||||
return m_Paths.find(name) != m_Paths.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearQueue() override
|
|
||||||
{
|
|
||||||
m_PathQueue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePath(const CStrW& name) override
|
void DeletePath(const CStrW& name) override
|
||||||
{
|
{
|
||||||
if (!HasPath(name))
|
if (!HasPath(name))
|
||||||
{
|
{
|
||||||
LOGWARNING("Path with name '%s' doesn't exist", name.ToUTF8());
|
LOGWARNING("Cinema path with name '%s' doesn't exist", name.ToUTF8());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_PathQueue.remove_if([name](const CCinemaPath& path) { return path.GetName() == name; });
|
m_PathQueue.remove_if([name](const CCinemaPath& path) { return path.GetName() == name; });
|
||||||
m_Paths.erase(name);
|
m_Paths.erase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasPath(const CStrW& name) const override
|
||||||
|
{
|
||||||
|
return m_Paths.find(name) != m_Paths.end();
|
||||||
|
}
|
||||||
|
|
||||||
const std::map<CStrW, CCinemaPath>& GetPaths() const override
|
const std::map<CStrW, CCinemaPath>& GetPaths() const override
|
||||||
{
|
{
|
||||||
return m_Paths;
|
return m_Paths;
|
||||||
@@ -229,41 +198,85 @@ public:
|
|||||||
m_Paths = newPaths;
|
m_Paths = newPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::list<CCinemaPath>& GetQueue() const override
|
void PushPathToQueue(const CStrW& name) override
|
||||||
{
|
{
|
||||||
return m_PathQueue;
|
if (!HasPath(name))
|
||||||
|
{
|
||||||
|
LOGWARNING("Cinema path with name '%s' doesn't exist", name.ToUTF8());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_PathQueue.push_back(m_Paths[name]);
|
||||||
|
|
||||||
|
if (m_PathQueue.size() == 1)
|
||||||
|
m_PathQueue.front().Reset();
|
||||||
|
m_PathQueueDuration += m_Paths[name].GetDuration();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEnabled() const override
|
void ClearQueue() override
|
||||||
{
|
{
|
||||||
return m_Enabled;
|
m_PathQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEnabled(bool enabled) override
|
void StartPlayingQueue() override
|
||||||
{
|
{
|
||||||
if (m_PathQueue.empty() && enabled)
|
if (m_IsPlayingPathQueue || m_PathQueue.empty())
|
||||||
enabled = false;
|
|
||||||
|
|
||||||
if (m_Enabled == enabled)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext().GetSystemEntity());
|
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext().GetSystemEntity());
|
||||||
if (cmpRangeManager)
|
if (cmpRangeManager)
|
||||||
{
|
{
|
||||||
if (enabled)
|
m_WasMapRevealed = cmpRangeManager->GetLosRevealWholeMapForAll();
|
||||||
m_MapRevealed = cmpRangeManager->GetLosRevealWholeMapForAll();
|
// Note: this results in all fogged entities seen during the cinema path being revealed/updated in FOW
|
||||||
// TODO: improve m_MapRevealed state and without fade in
|
// after the queue has ended.
|
||||||
cmpRangeManager->SetLosRevealWholeMapForAll(enabled);
|
cmpRangeManager->SetLosRevealWholeMapForAll(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Enabled = enabled;
|
m_IsPlayingPathQueue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayQueue(const float deltaRealTime, CCamera* camera) override
|
void StopPlayingQueue() override
|
||||||
{
|
{
|
||||||
if (m_PathQueue.empty())
|
if (!m_IsPlayingPathQueue)
|
||||||
return;
|
return;
|
||||||
m_PathQueue.front().Play(deltaRealTime, camera);
|
|
||||||
|
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext().GetSystemEntity());
|
||||||
|
if (cmpRangeManager)
|
||||||
|
cmpRangeManager->SetLosRevealWholeMapForAll(m_WasMapRevealed);
|
||||||
|
|
||||||
|
GetSimContext().GetComponentManager().PostMessage(SYSTEM_ENTITY, CMessageCinemaQueueEnded());
|
||||||
|
|
||||||
|
m_ActivePathElapsedTime = fixed::Zero();
|
||||||
|
m_QueuePlayingElapsedTime = fixed::Zero();
|
||||||
|
m_PathQueueDuration = fixed::Zero();
|
||||||
|
for (const CCinemaPath& path : m_PathQueue)
|
||||||
|
m_PathQueueDuration += path.GetDuration();
|
||||||
|
m_IsPlayingPathQueue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPlayingQueue() const override
|
||||||
|
{
|
||||||
|
return m_IsPlayingPathQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateActivePath(const float deltaRealTime, CCamera* camera) override
|
||||||
|
{
|
||||||
|
if (m_IsPlayingPathQueue)
|
||||||
|
{
|
||||||
|
if (m_PathQueue.empty())
|
||||||
|
StopPlayingQueue();
|
||||||
|
else
|
||||||
|
m_PathQueue.front().Play(deltaRealTime, camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CStrW GetActivePath() const override
|
||||||
|
{
|
||||||
|
return m_IsPlayingPathQueue ? m_PathQueue.front().GetName() : CStrW();
|
||||||
|
}
|
||||||
|
|
||||||
|
const fixed GetActivePathElapsedTime() const override
|
||||||
|
{
|
||||||
|
return m_ActivePathElapsedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -364,16 +377,22 @@ private:
|
|||||||
return CCinemaPath(data, pathSpline, targetSpline);
|
return CCinemaPath(data, pathSpline, targetSpline);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_Enabled;
|
bool m_IsPlayingPathQueue;
|
||||||
std::map<CStrW, CCinemaPath> m_Paths;
|
std::map<CStrW, CCinemaPath> m_Paths;
|
||||||
std::list<CCinemaPath> m_PathQueue;
|
std::list<CCinemaPath> m_PathQueue;
|
||||||
|
fixed m_PathQueueDuration;
|
||||||
|
|
||||||
// States before playing
|
// Total time elapsed since starting to play the queue.
|
||||||
bool m_MapRevealed;
|
fixed m_QueuePlayingElapsedTime;
|
||||||
|
|
||||||
fixed m_ElapsedTime;
|
// Time elapsed since the currently active path first started playing.
|
||||||
fixed m_TotalTime;
|
fixed m_ActivePathElapsedTime;
|
||||||
fixed m_CurrentPathElapsedTime;
|
|
||||||
|
// Time elapsed since the
|
||||||
|
fixed m_QueueEndedElapsedTime;
|
||||||
|
|
||||||
|
// Whether the map was revealed before playing the queue.
|
||||||
|
bool m_WasMapRevealed;
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_COMPONENT_TYPE(CinemaManager)
|
REGISTER_COMPONENT_TYPE(CinemaManager)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -24,9 +24,13 @@
|
|||||||
|
|
||||||
BEGIN_INTERFACE_WRAPPER(CinemaManager)
|
BEGIN_INTERFACE_WRAPPER(CinemaManager)
|
||||||
DEFINE_INTERFACE_METHOD("AddPath", ICmpCinemaManager, AddPath)
|
DEFINE_INTERFACE_METHOD("AddPath", ICmpCinemaManager, AddPath)
|
||||||
DEFINE_INTERFACE_METHOD("AddCinemaPathToQueue", ICmpCinemaManager, AddCinemaPathToQueue)
|
DEFINE_INTERFACE_METHOD("HasPath", ICmpCinemaManager, HasPath)
|
||||||
DEFINE_INTERFACE_METHOD("DeletePath", ICmpCinemaManager, DeletePath)
|
DEFINE_INTERFACE_METHOD("DeletePath", ICmpCinemaManager, DeletePath)
|
||||||
DEFINE_INTERFACE_METHOD("IsPlaying", ICmpCinemaManager, IsEnabled)
|
DEFINE_INTERFACE_METHOD("PushPathToQueue", ICmpCinemaManager, PushPathToQueue)
|
||||||
DEFINE_INTERFACE_METHOD("Play", ICmpCinemaManager, Play)
|
DEFINE_INTERFACE_METHOD("ClearQueue", ICmpCinemaManager, ClearQueue)
|
||||||
DEFINE_INTERFACE_METHOD("Stop", ICmpCinemaManager, Stop)
|
DEFINE_INTERFACE_METHOD("StartPlayingQueue", ICmpCinemaManager, StartPlayingQueue)
|
||||||
|
DEFINE_INTERFACE_METHOD("IsPlayingQueue", ICmpCinemaManager, IsPlayingQueue)
|
||||||
|
DEFINE_INTERFACE_METHOD("GetActivePath", ICmpCinemaManager, GetActivePath)
|
||||||
|
DEFINE_INTERFACE_METHOD("GetActivePathElapsedTime", ICmpCinemaManager, GetActivePathElapsedTime)
|
||||||
|
DEFINE_INTERFACE_METHOD("StopPlayingQueue", ICmpCinemaManager, StopPlayingQueue)
|
||||||
END_INTERFACE_WRAPPER(CinemaManager)
|
END_INTERFACE_WRAPPER(CinemaManager)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -31,54 +31,83 @@ class CCinemaPath;
|
|||||||
class CStrW;
|
class CStrW;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component for CCinemaManager class
|
* Manages a dynamic list of cinema paths (predefined camera movements/cutscenes) as well as a queue of paths that
|
||||||
* TODO: write description
|
* is played one by one on command to all players. Simulation messages are sent each time a path ends and also when
|
||||||
|
* the queue finishes as a whole.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ICmpCinemaManager : public IComponent
|
class ICmpCinemaManager : public IComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Adds the path to the path list
|
* Register a new path.
|
||||||
* @param CCinemaPath path data
|
* @param path path data
|
||||||
*/
|
*/
|
||||||
virtual void AddPath(const CCinemaPath& path) = 0;
|
virtual void AddPath(const CCinemaPath& path) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the path to the playlist
|
* Remove a path and its data entirely.
|
||||||
* @param name path name
|
* @param name path name
|
||||||
*/
|
*/
|
||||||
virtual void AddCinemaPathToQueue(const CStrW& name) = 0;
|
|
||||||
|
|
||||||
virtual void Play() = 0;
|
|
||||||
virtual void Stop() = 0;
|
|
||||||
virtual void PlayQueue(const float deltaRealTime, CCamera* camera) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks the path name in the path list
|
|
||||||
* @param name path name
|
|
||||||
* @return true if path with that name exists, else false
|
|
||||||
*/
|
|
||||||
virtual bool HasPath(const CStrW& name) const = 0;
|
|
||||||
|
|
||||||
virtual void DeletePath(const CStrW& name) = 0;
|
virtual void DeletePath(const CStrW& name) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the playlist
|
* Check whether a path exists (is registered under the given name)..
|
||||||
|
* @param name path name
|
||||||
|
*/
|
||||||
|
virtual bool HasPath(const CStrW& name) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all registered paths, keyed by their names.
|
||||||
|
*/
|
||||||
|
virtual const std::map<CStrW, CCinemaPath>& GetPaths() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the entire list of existing paths.
|
||||||
|
* @param newPaths new list of paths
|
||||||
|
*/
|
||||||
|
virtual void SetPaths(const std::map<CStrW, CCinemaPath>& newPaths) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a path to the back of the queue.
|
||||||
|
* @param name path name
|
||||||
|
*/
|
||||||
|
virtual void PushPathToQueue(const CStrW& name) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all paths from the queue.
|
||||||
*/
|
*/
|
||||||
virtual void ClearQueue() = 0;
|
virtual void ClearQueue() = 0;
|
||||||
|
|
||||||
virtual const std::map<CStrW, CCinemaPath>& GetPaths() const = 0;
|
/**
|
||||||
virtual void SetPaths(const std::map<CStrW, CCinemaPath>& newPaths) = 0;
|
* Start playing the paths in the queue one by one.
|
||||||
virtual const std::list<CCinemaPath>& GetQueue() const = 0;
|
*/
|
||||||
|
virtual void StartPlayingQueue() = 0;
|
||||||
virtual bool IsEnabled() const = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets enable state of the cinema manager (shows/hide gui, show/hide rings, etc)
|
* Stop playing the active path and the queue altogether.
|
||||||
* @param enable new state
|
*/
|
||||||
*/
|
virtual void StopPlayingQueue() = 0;
|
||||||
virtual void SetEnabled(bool enabled) = 0;
|
|
||||||
|
/**
|
||||||
|
* Whether the first path of the queue is being played at the moment.
|
||||||
|
*/
|
||||||
|
virtual bool IsPlayingQueue() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an update to the path currently playing for it to determine the new camera position.
|
||||||
|
* Called every frame.
|
||||||
|
*/
|
||||||
|
virtual void UpdateActivePath(const float deltaRealTime, CCamera* camera) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the path currently playing, if any.
|
||||||
|
*/
|
||||||
|
virtual const CStrW GetActivePath() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time elapsed since the currently active path started playing.
|
||||||
|
*/
|
||||||
|
virtual const fixed GetActivePathElapsedTime() const = 0;
|
||||||
|
|
||||||
DECLARE_INTERFACE_TYPE(CinemaManager)
|
DECLARE_INTERFACE_TYPE(CinemaManager)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -37,33 +37,91 @@
|
|||||||
class TestCmpCinemaManager : public CxxTest::TestSuite
|
class TestCmpCinemaManager : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void test_basic()
|
void test_managing_paths()
|
||||||
{
|
{
|
||||||
CXeromycesEngine xeromycesEngine;
|
CXeromycesEngine xeromycesEngine;
|
||||||
ComponentTestHelper test(*g_ScriptContext);
|
ComponentTestHelper test(*g_ScriptContext);
|
||||||
|
|
||||||
ICmpCinemaManager* cmp = test.Add<ICmpCinemaManager>(CID_CinemaManager, "", SYSTEM_ENTITY);
|
ICmpCinemaManager* cmp = test.Add<ICmpCinemaManager>(CID_CinemaManager, "", SYSTEM_ENTITY);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(cmp->HasPath(L"test"), false);
|
TS_ASSERT(!cmp->HasPath(L"test"));
|
||||||
cmp->AddPath(generatePath(L"test"));
|
cmp->AddPath(generatePath(L"test"));
|
||||||
TS_ASSERT_EQUALS(cmp->HasPath(L"test"), true);
|
TS_ASSERT(cmp->HasPath(L"test"));
|
||||||
cmp->DeletePath(L"test");
|
TS_ASSERT(!cmp->HasPath(L"test_2"));
|
||||||
TS_ASSERT_EQUALS(cmp->HasPath(L"test"), false);
|
cmp->SetPaths(std::map<CStrW, CCinemaPath>{{L"test_2", generatePath(L"test_2")}});
|
||||||
|
TS_ASSERT(!cmp->HasPath(L"test"));
|
||||||
|
TS_ASSERT(cmp->HasPath(L"test_2"));
|
||||||
|
cmp->DeletePath(L"test_2");
|
||||||
|
TS_ASSERT(!cmp->HasPath(L"test_2"));
|
||||||
|
}
|
||||||
|
|
||||||
cmp->AddPath(generatePath(L"long_path", fixed::FromInt(3600)));
|
void test_playing_queue()
|
||||||
TS_ASSERT_EQUALS(cmp->HasPath(L"long_path"), true);
|
{
|
||||||
|
CXeromycesEngine xeromycesEngine;
|
||||||
|
ComponentTestHelper test(*g_ScriptContext);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(cmp->IsEnabled(), false);
|
ICmpCinemaManager* cmp = test.Add<ICmpCinemaManager>(CID_CinemaManager, "", SYSTEM_ENTITY);
|
||||||
cmp->AddCinemaPathToQueue(L"long_path");
|
|
||||||
cmp->Play();
|
CMessageUpdate updateMsg(fixed::FromInt(200));
|
||||||
size_t number_of_turns = 0;
|
|
||||||
while (cmp->IsEnabled())
|
cmp->AddPath(generatePath(L"path_1", fixed::FromInt(10000)));
|
||||||
|
cmp->AddPath(generatePath(L"path_2", fixed::FromInt(5000)));
|
||||||
|
|
||||||
|
// Try getting the active path if there is none.
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"");
|
||||||
|
|
||||||
|
// Try to start playing the queue if it's empty.
|
||||||
|
cmp->StartPlayingQueue();
|
||||||
|
TS_ASSERT(!cmp->IsPlayingQueue());
|
||||||
|
|
||||||
|
// Try stopping playing the queue if it's not playing in the first place.
|
||||||
|
cmp->StartPlayingQueue();
|
||||||
|
TS_ASSERT(!cmp->IsPlayingQueue());
|
||||||
|
|
||||||
|
cmp->PushPathToQueue(L"path_1");
|
||||||
|
cmp->PushPathToQueue(L"path_2");
|
||||||
|
// Try getting the active path if there is none.
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"");
|
||||||
|
|
||||||
|
cmp->StartPlayingQueue();
|
||||||
|
TS_ASSERT(cmp->IsPlayingQueue());
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"path_1");
|
||||||
|
TS_ASSERT_EQUALS(cmp->GetActivePathElapsedTime(), fixed::FromInt(0));
|
||||||
|
|
||||||
|
for (int i = 0; i < 35; i++)
|
||||||
|
cmp->HandleMessage(updateMsg, true);
|
||||||
|
TS_ASSERT(cmp->IsPlayingQueue());
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"path_1");
|
||||||
|
TS_ASSERT_EQUALS(cmp->GetActivePathElapsedTime(), fixed::FromInt(7000));
|
||||||
|
|
||||||
|
// Finish path_1 and start with path_2
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
cmp->HandleMessage(updateMsg, true);
|
||||||
|
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"path_2");
|
||||||
|
TS_ASSERT_EQUALS(cmp->GetActivePathElapsedTime(), fixed::FromInt(1000));
|
||||||
|
|
||||||
|
// Try restarting while a path is being played.
|
||||||
|
// This should result in the active path starting again from the beginning.
|
||||||
|
cmp->StopPlayingQueue();
|
||||||
|
cmp->StartPlayingQueue();
|
||||||
|
TS_ASSERT(cmp->IsPlayingQueue());
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"path_2");
|
||||||
|
|
||||||
|
size_t remainingTurns = 0;
|
||||||
|
while (cmp->IsPlayingQueue())
|
||||||
{
|
{
|
||||||
CMessageUpdate msg(fixed::FromInt(36));
|
cmp->HandleMessage(updateMsg, true);
|
||||||
cmp->HandleMessage(msg, true);
|
remainingTurns++;
|
||||||
++number_of_turns;
|
|
||||||
}
|
}
|
||||||
TS_ASSERT_EQUALS(number_of_turns, 100);
|
TS_ASSERT_EQUALS(remainingTurns, 25);
|
||||||
|
TS_ASSERT(!cmp->IsPlayingQueue());
|
||||||
|
TS_ASSERT_WSTR_EQUALS(cmp->GetActivePath(), L"");
|
||||||
|
TS_ASSERT_EQUALS(cmp->GetActivePathElapsedTime(), fixed::FromInt(0));
|
||||||
|
|
||||||
|
// Make sure the queue is empty.
|
||||||
|
cmp->StartPlayingQueue();
|
||||||
|
TS_ASSERT(!cmp->IsPlayingQueue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -41,7 +41,7 @@ namespace AtlasMessage {
|
|||||||
|
|
||||||
MESSAGEHANDLER(CameraReset)
|
MESSAGEHANDLER(CameraReset)
|
||||||
{
|
{
|
||||||
if (!g_Game || g_Game->GetView()->GetCinema()->IsEnabled())
|
if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CVector3D focus = g_Game->GetView()->GetCamera()->GetFocus();
|
CVector3D focus = g_Game->GetView()->GetCamera()->GetFocus();
|
||||||
@@ -64,7 +64,7 @@ MESSAGEHANDLER(CameraReset)
|
|||||||
|
|
||||||
MESSAGEHANDLER(ScrollConstant)
|
MESSAGEHANDLER(ScrollConstant)
|
||||||
{
|
{
|
||||||
if (!g_Game || g_Game->GetView()->GetCinema()->IsEnabled())
|
if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (msg->dir < 0 || msg->dir > 5)
|
if (msg->dir < 0 || msg->dir > 5)
|
||||||
@@ -82,7 +82,7 @@ MESSAGEHANDLER(ScrollConstant)
|
|||||||
|
|
||||||
MESSAGEHANDLER(Scroll)
|
MESSAGEHANDLER(Scroll)
|
||||||
{
|
{
|
||||||
if (!g_Game || g_Game->GetView()->GetCinema()->IsEnabled()) // TODO: do this better (probably a separate AtlasView class for cinematics)
|
if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying()) // TODO: do this better (probably a separate AtlasView class for cinematics)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static CVector3D targetPos;
|
static CVector3D targetPos;
|
||||||
@@ -131,7 +131,7 @@ MESSAGEHANDLER(Scroll)
|
|||||||
|
|
||||||
MESSAGEHANDLER(SmoothZoom)
|
MESSAGEHANDLER(SmoothZoom)
|
||||||
{
|
{
|
||||||
if (!g_Game || g_Game->GetView()->GetCinema()->IsEnabled())
|
if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_AtlasGameLoop->input.zoomDelta += msg->amount;
|
g_AtlasGameLoop->input.zoomDelta += msg->amount;
|
||||||
@@ -139,7 +139,7 @@ MESSAGEHANDLER(SmoothZoom)
|
|||||||
|
|
||||||
MESSAGEHANDLER(RotateAround)
|
MESSAGEHANDLER(RotateAround)
|
||||||
{
|
{
|
||||||
if (!g_Game || g_Game->GetView()->GetCinema()->IsEnabled())
|
if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static CVector3D focusPos;
|
static CVector3D focusPos;
|
||||||
@@ -245,7 +245,7 @@ QUERYHANDLER(GetView)
|
|||||||
|
|
||||||
MESSAGEHANDLER(SetView)
|
MESSAGEHANDLER(SetView)
|
||||||
{
|
{
|
||||||
if (!g_Game || g_Game->GetView()->GetCinema()->IsEnabled())
|
if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CGameView* view = g_Game->GetView();
|
CGameView* view = g_Game->GetView();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -189,7 +189,7 @@ MESSAGEHANDLER(CinemaEvent)
|
|||||||
|
|
||||||
if (msg->mode == eCinemaEventMode::SMOOTH)
|
if (msg->mode == eCinemaEventMode::SMOOTH)
|
||||||
{
|
{
|
||||||
cmpCinemaManager->AddCinemaPathToQueue(*msg->path);
|
cmpCinemaManager->PushPathToQueue(*msg->path);
|
||||||
}
|
}
|
||||||
else if ( msg->mode == eCinemaEventMode::RESET )
|
else if ( msg->mode == eCinemaEventMode::RESET )
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user