1
0
forked from 0ad/0ad

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.
This commit is contained in:
Yves 2016-01-03 12:41:04 +00:00
parent d313a1934a
commit 89aef0b6eb
30 changed files with 1110 additions and 341 deletions

View File

@ -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);

View File

@ -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

View File

@ -18,98 +18,280 @@
#include "precompiled.h"
#include <string>
#include <sstream>
#include <string>
#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<CStrW, CCinemaPath>& paths)
{
CStrW name;
m_Paths = paths;
}
void CCinemaManager::SetCurrentPath(const CStrW& name, bool current, bool drawLines)
{
if ( !HasTrack(name) )
m_ValidCurrent = false;
else
m_ValidCurrent = true;
m_CurrentPath = m_Paths.find(name);
m_DrawCurrentSpline = current;
m_DrawLines = drawLines;
DrawSpline();
m_CinematicSimulationData.m_Paths = paths;
}
bool CCinemaManager::HasTrack(const CStrW& name) const
bool CCinemaManager::HasPath(const CStrW& name) const
{
return m_Paths.find(name) != m_Paths.end();
return m_CinematicSimulationData.m_Paths.find(name) != m_CinematicSimulationData.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<ICmpRangeManager> cmpRangeManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity());
CmpPtr<ICmpTerritoryManager> 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<CStrW, CCinemaPath>& 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;
}

View File

@ -22,48 +22,121 @@
#include <list>
#include <map>
#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<CStrW, CCinemaPath> m_Paths;
std::list<CCinemaPath> 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<CStrW, CCinemaPath>& GetAllPaths();
void SetAllPaths( const std::map<CStrW, CCinemaPath>& 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);
void Update(const float deltaRealTime);
//These stop track play, and accept time, not ratio of time
void MoveToPointAt(float time);
InReaction HandleEvent(const SDL_Event_* ev);
inline void StopPlaying() { m_PathQueue.clear(); }
void DrawSpline() const;
CinematicSimulationData* GetCinematicSimulationData();
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; }
inline const std::map<CStrW, CCinemaPath>& GetAllPaths() { return m_Paths; }
void SetAllPaths( const std::map<CStrW, CCinemaPath>& tracks);
void SetCurrentPath(const CStrW& name, bool current, bool lines);
bool GetPathsDrawing() const;
void SetPathsDrawing(const bool drawPath);
private:
bool m_DrawPaths;
bool m_Active, m_DrawCurrentSpline, m_DrawLines, m_ValidCurrent;
std::map<CStrW, CCinemaPath>::iterator m_CurrentPath;
std::map<CStrW, CCinemaPath> m_Paths;
std::list<CCinemaPath> m_PathQueue;
// Cinematic data is accessed from the simulation
CinematicSimulationData m_CinematicSimulationData;
};
extern InReaction cinema_manager_handler(const SDL_Event_* ev);
#endif

View File

@ -23,73 +23,81 @@
#include <string>
#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;
}

View File

@ -15,19 +15,11 @@
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_CINEMAPATH
#define INCLUDED_CINEMAPATH
#include <list>
#include <map>
#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,13 +57,10 @@ 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&);
@ -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

View File

@ -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;
}

View File

@ -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<CStrW, CCinemaPath> 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_time)
data.Distance = nodeChild.GetText().ToFloat();
else
debug_warn(L"Invalid cinematic element for node child");
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));
backwardSpline.AddNode(data.Position, data.Rotation, data.Distance);
targetSpline.AddNode(targetPosition, CFixedVector3D(), lastTargetTime);
lastTargetTime = fixed::Zero();
}
else
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<SplineData>& 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<SplineData>::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")
{

View File

@ -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<SplineData>& 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);
}
}
}

View File

@ -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;

View File

@ -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));
}
}

View File

@ -24,14 +24,18 @@
#define MAX_SPLINE_NODES 40
#include <stdlib.h>
#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<SplineData>& 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(); } }

View File

@ -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();
@ -569,6 +575,8 @@ static void InitInput()
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);
}

View File

@ -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

View File

@ -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)

View File

@ -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 <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)

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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)

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)
};

View File

@ -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)

View File

@ -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);

View File

@ -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<sCinemaPath>& 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<sCinemaSplineNode> nodes = *atlasPath.nodes;
@ -121,10 +121,10 @@ void SetCurrentPaths(const std::vector<sCinemaPath>& atlasPaths)
for ( size_t j=0; j<nodes.size(); ++j )
{
spline.AddNode( CVector3D(nodes[j].px, nodes[j].py, nodes[j].pz),
CVector3D(nodes[j].rx, nodes[j].ry, nodes[j].rz), nodes[j].t );
spline.AddNode(CFixedVector3D(fixed::FromFloat(nodes[j].px), fixed::FromFloat(nodes[j].py), fixed::FromFloat(nodes[j].pz)),
CFixedVector3D(fixed::FromFloat(nodes[j].rx), fixed::FromFloat(nodes[j].ry), fixed::FromFloat(nodes[j].rz)), fixed::FromFloat(nodes[j].t));
}
paths[pathName] = CCinemaPath(data, spline);
paths[pathName] = CCinemaPath(data, spline, TNSpline());
}
g_Game->GetView()->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);
}

View File

@ -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);