0ad/source/simulation2/components/CCmpCinemaManager.cpp
Yves 89aef0b6eb 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.
2016-01-03 12:41:04 +00:00

253 lines
8.7 KiB
C++

/* 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 <http://www.gnu.org/licenses/>.
*/
#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 "<a:component type='system'/>"
"<empty/>"
;
}
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<SplineData>& 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<SplineData>& 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<const CMessageUpdate&>(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)