1
0
forked from 0ad/0ad

#Cinematic changes

-Eliminated tracks, rotation is per node

This was SVN commit r4929.
This commit is contained in:
pyrolink 2007-02-27 02:14:18 +00:00
parent 236224eea9
commit a4c0ea9d07
17 changed files with 749 additions and 1336 deletions

View File

@ -16,10 +16,54 @@
#include "lib/res/mem.h"
CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline)
: CCinemaData(data), TNSpline(spline), m_TimeElapsed(0.f)
: CCinemaData(data), TNSpline(spline), m_TimeElapsed(0.f)
{
DistStylePtr = &CCinemaPath::EaseDefault;
DistModePtr = &CCinemaPath::EaseIn;
m_TimeElapsed = 0;
BuildSpline();
//Set distortion mode and style
switch(data.m_Mode)
{
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 ", data.m_Mode);
break;
}
switch (data.m_Style)
{
case CCinemaPath::ES_DEFAULT:
DistStylePtr = &CCinemaPath::EaseDefault;
break;
case CCinemaPath::ES_GROWTH:
DistStylePtr = &CCinemaPath::EaseGrowth;
break;
case CCinemaPath::ES_EXPO:
DistStylePtr = &CCinemaPath::EaseExpo;
break;
case CCinemaPath::ES_CIRCLE:
DistStylePtr = &CCinemaPath::EaseCircle;
break;
case CCinemaPath::ES_SINE:
DistStylePtr = &CCinemaPath::EaseSine;
break;
default:
debug_printf("Cinematic mode not found for %d !", data.m_Style);
break;
}
//UpdateDuration();
}
void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines) const
@ -75,16 +119,18 @@ void CCinemaPath::DrawSpline(const CVector4D& RGBA, int smoothness, bool lines)
glDisable(GL_POINT_SMOOTH);
}
}
void CCinemaPath::MoveToPointAt(float t, const CVector3D &startRotation)
void CCinemaPath::MoveToPointAt(float t, float nodet, const CVector3D& startRotation)
{
CCamera *Cam=g_Game->GetView()->GetCamera();
CCamera *Cam = g_Game->GetView()->GetCamera();
t = (this->*DistModePtr)(t);
CVector3D nodeRotation = Node[m_CurrentNode + 1].Rotation;
CQuaternion start, end;
start.FromEulerAngles(startRotation.X, startRotation.Y, startRotation.Z);
end.FromEulerAngles(m_TotalRotation.X, m_TotalRotation.Y, m_TotalRotation.Z);
start.Slerp(start, end, t);
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);
@ -153,338 +199,120 @@ float CCinemaPath::EaseSine(float t) const
return t;
}
//-------CinemaTrack functions------
//AddPath-For building tracks from loaded file
CCinemaTrack::CCinemaTrack() : m_AbsoluteTime(0), m_Timescale(1),
m_TotalDuration(0)
bool CCinemaPath::Validate()
{
m_CPA = m_Paths.end();
}
void CCinemaTrack::AddPath(const CCinemaData& data, const TNSpline& spline)
{
CCinemaPath path(data, spline);
path.m_TimeElapsed=0;
path.BuildSpline();
m_Paths.push_back(path);
std::vector<CCinemaPath>::iterator SetTemp;
SetTemp=m_Paths.end() - 1;
//Set distortion mode and style
switch(data.m_Mode)
if ( m_TimeElapsed < GetDuration() && m_TimeElapsed > 0.0f )
{
case CCinemaPath::EM_IN:
SetTemp->DistModePtr = &CCinemaPath::EaseIn;
break;
case CCinemaPath::EM_OUT:
SetTemp->DistModePtr = &CCinemaPath::EaseOut;
break;
case CCinemaPath::EM_INOUT:
SetTemp->DistModePtr = &CCinemaPath::EaseInOut;
break;
case CCinemaPath::EM_OUTIN:
SetTemp->DistModePtr = &CCinemaPath::EaseOutIn;
break;
default:
debug_printf("Cinematic mode not found for %d ", data.m_Mode);
break;
}
switch (data.m_Style)
{
case CCinemaPath::ES_DEFAULT:
SetTemp->DistStylePtr = &CCinemaPath::EaseDefault;
break;
case CCinemaPath::ES_GROWTH:
SetTemp->DistStylePtr = &CCinemaPath::EaseGrowth;
break;
case CCinemaPath::ES_EXPO:
SetTemp->DistStylePtr = &CCinemaPath::EaseExpo;
break;
case CCinemaPath::ES_CIRCLE:
SetTemp->DistStylePtr = &CCinemaPath::EaseCircle;
break;
case CCinemaPath::ES_SINE:
SetTemp->DistStylePtr = &CCinemaPath::EaseSine;
break;
default:
debug_printf("Cinematic mode not found for %d !", data.m_Style);
break;
}
UpdateDuration();
}
void CCinemaTrack::AddPath(const CCinemaPath& path)
{
m_Paths.push_back(path);
m_Paths.back().BuildSpline();
m_Paths.back().m_TimeElapsed = 0;
UpdateDuration();
}
void CCinemaTrack::UpdateDuration()
{
m_TotalDuration=0;
for ( std::vector<CCinemaPath>::iterator it=m_Paths.begin(); it!=m_Paths.end(); it++ )
{
m_TotalDuration += it->MaxDistance;
}
}
bool CCinemaTrack::Validate()
{
if ( m_CPA->m_TimeElapsed > 0.f )
return ValidateForward();
else
return ValidateRewind();
}
bool CCinemaTrack::ValidateRewind()
{
if (m_CPA->m_TimeElapsed < 0)
{
if (m_CPA == m_Paths.begin())
//Find current node and past "node time"
float previousTime = 0.0f, cumulation = 0.0f;
//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 )
{
m_CPA->m_TimeElapsed = 0.0f;
m_CPA->MoveToPointAt(0.0f, m_StartRotation);
return false;
}
//Make sure it's within limits of path
else
{
float Pos=m_CPA->m_TimeElapsed;
m_CPA--;
while (1)
cumulation += Node[i].Distance;
if ( m_TimeElapsed < cumulation )
{
if (m_CPA->GetDuration() + Pos < 0)
{
if (m_CPA == m_Paths.begin())
{
m_CPA->m_TimeElapsed = m_CPA->MaxDistance;
m_CPA->MoveToPointAt(0.0f, m_StartRotation );
return false;
}
Pos+=m_CPA->GetDuration();
m_CPA->m_TimeElapsed=0;
m_CPA--;
}
else
{
m_CPA->m_TimeElapsed+=Pos;
break;
}
m_PreviousNodeTime = previousTime;
m_PreviousRotation = Node[i].Rotation;
m_CurrentNode = i; //We're moving toward this next node, so use its rotation
return true;
}
} //inside limits
}
return true;
}
bool CCinemaTrack::ValidateForward()
{
if (m_CPA->m_TimeElapsed >= m_CPA->MaxDistance)
{
if (m_CPA == m_Paths.end() - 1)
{
if ( m_CPA->GetDuration() < .0001f ) //blank path
return false;
m_CPA->MoveToPointAt(1.f, CalculateRotation());
return false;
else
previousTime += Node[i].Distance;
}
//Make sure it's within limits of path
else
{
float Pos = m_CPA->m_TimeElapsed - m_CPA->MaxDistance;
m_CPA++;
while (1)
{
if (Pos > m_CPA->MaxDistance)
{
if (m_CPA == m_Paths.end() -1)
{
if ( m_CPA->MaxDistance < .0001f ) //blank path
return false;
m_CPA->m_TimeElapsed = m_CPA->MaxDistance;
m_CPA->MoveToPointAt(1.0f, m_StartRotation );
return false;
}
Pos -= m_CPA->MaxDistance;
m_CPA->m_TimeElapsed = m_CPA->MaxDistance;
m_CPA++;
}
else
{
m_CPA->m_TimeElapsed = Pos;
break;
}
}
} //inside limits of path
}
return true;
}
CVector3D CCinemaTrack::CalculateRotation()
{
CVector3D rotation;
if ( m_CPA == m_Paths.begin() )
return m_StartRotation;
else
return (m_CPA-1)->GetData()->m_TotalRotation;
}
return false;
}
bool CCinemaTrack::Play(float DeltaTime)
bool CCinemaPath::Play(float DeltaTime)
{
m_CPA->m_TimeElapsed += m_Timescale*DeltaTime;
m_AbsoluteTime += m_Timescale*DeltaTime;
m_TimeElapsed += m_Timescale*DeltaTime;
if (!Validate())
return false;
m_CPA->MoveToPointAt( m_CPA->GetElapsedTime() / m_CPA->GetDuration(), CalculateRotation() );
MoveToPointAt( m_TimeElapsed / GetDuration(), GetNodeFraction(), m_PreviousRotation );
return true;
}
CCinemaManager::CCinemaManager() : m_DrawCurrentSpline(false),
m_DrawAllSplines(false), m_Active(true), m_CurrentTrack(false)
CCinemaManager::CCinemaManager() : m_DrawCurrentSpline(false), m_Active(true)
{
m_CurrentPath = m_Paths.end();
}
void CCinemaManager::AddTrack(CCinemaTrack track, const CStrW& name)
void CCinemaManager::AddPath(CCinemaPath path, const CStrW& name)
{
debug_assert( m_Tracks.find( name ) == m_Tracks.end() );
m_Tracks[name] = track;
debug_assert( m_Paths.find( name ) == m_Paths.end() );
m_Paths[name] = path;
}
void CCinemaManager::QueueTrack(const CStrW& name, bool queue )
void CCinemaManager::QueuePath(const CStrW& name, bool queue )
{
if (!m_TrackQueue.empty() && queue == false)
if (!m_PathQueue.empty() && queue == false)
{
return;
}
else
{
debug_assert(HasTrack(name));
if ( m_Tracks[name].m_Paths.empty() )
return;
m_TrackQueue.push_back(m_Tracks[name]);
m_TrackQueue.back().m_CPA = m_TrackQueue.back().m_Paths.begin();
m_PathQueue.push_back(m_Paths[name]);
}
}
void CCinemaManager::OverrideTrack(const CStrW& name)
void CCinemaManager::OverridePath(const CStrW& name)
{
m_TrackQueue.clear();
m_PathQueue.clear();
debug_assert(HasTrack(name));
if ( m_Tracks[name].m_Paths.empty() )
return;
m_TrackQueue.push_back( m_Tracks[name] );
m_TrackQueue.back().m_CPA = m_TrackQueue.back().m_Paths.begin();
m_PathQueue.push_back( m_Paths[name] );
}
void CCinemaManager::SetAllTracks( const std::map<CStrW, CCinemaTrack>& tracks)
void CCinemaManager::SetAllPaths( const std::map<CStrW, CCinemaPath>& paths)
{
m_Tracks = tracks;
// TODO: this just assumes that if you had any track selected, it was the
// first. (We need to change m_CurrentTrack because it was pointing into
// the old m_Tracks.)
if (m_CurrentTrack)
m_CurrentTrack = (tracks.empty() ? NULL : &m_Tracks.begin()->second);
for ( std::map<CStrW, CCinemaTrack>::iterator it=m_Tracks.begin();
it != m_Tracks.end(); ++it )
{
it->second.m_CPA = it->second.m_Paths.begin();
}
CStrW name;
m_Paths = paths;
}
void CCinemaManager::SetCurrentTrack(const CStrW& name, bool all, bool current, bool drawLines)
void CCinemaManager::SetCurrentPath(const CStrW& name, bool current, bool drawLines)
{
debug_assert(HasTrack(name));
m_CurrentTrack = &m_Tracks[name];
m_DrawAllSplines = all;
m_CurrentPath = m_Paths.find(name);
m_DrawCurrentSpline = current;
m_DrawLines = drawLines;
DrawAllSplines();
}
void CCinemaManager::SetCurrentPath(const int path)
{
debug_assert(m_CurrentTrack);
m_CurrentPath = path;
m_CurrentTrack->m_CPA = m_CurrentTrack->m_Paths.begin() + path;
DrawSpline();
}
bool CCinemaManager::HasTrack(const CStrW& name) const
{
return m_Tracks.find(name) != m_Tracks.end();
return m_Paths.find(name) != m_Paths.end();
}
void CCinemaManager::DrawAllSplines() const
void CCinemaManager::DrawSpline() const
{
if ( !(m_DrawAllSplines || m_DrawCurrentSpline) || !m_CurrentTrack )
if ( !(m_DrawCurrentSpline || m_CurrentPath != m_Paths.end()) )
return;
static const int smoothness = 200;
if ( m_DrawAllSplines )
{
for ( std::vector<CCinemaPath>::iterator it = m_CurrentTrack->m_Paths.begin();
it != m_CurrentTrack->m_Paths.end(); ++it )
{
it->DrawSpline(CVector4D(0.f, 0.f, 1.f, 1.f), smoothness, m_DrawLines);
}
}
if ( m_DrawCurrentSpline && m_CurrentTrack->m_CPA !=
m_CurrentTrack->m_Paths.end() )
{
if ( m_DrawAllSplines )
{
m_CurrentTrack->m_CPA->DrawSpline(CVector4D(1.f, 0.f, 0.f, 1.f),
smoothness, m_DrawLines);
}
else
{
m_CurrentTrack->m_CPA->DrawSpline(CVector4D(0.f, 0.f, 1.f, 1.f),
smoothness, m_DrawLines);
}
}
m_CurrentPath->second.DrawSpline(CVector4D(0.f, 0.f, 1.f, 1.f), smoothness, m_DrawLines);
}
void CCinemaManager::MoveToPointAt(float time)
{
debug_assert(m_CurrentTrack);
debug_assert(m_CurrentPath != m_Paths.end());
StopPlaying();
if ( m_CurrentTrack->m_Paths.empty() )
m_CurrentPath->second.m_TimeElapsed = time;
if ( !m_CurrentPath->second.Validate() )
return;
m_CurrentTrack->m_CPA->m_TimeElapsed = time;
if ( !m_CurrentTrack->Validate() )
return;
m_CurrentTrack->m_CPA->MoveToPointAt(m_CurrentTrack->m_CPA->m_TimeElapsed /
m_CurrentTrack->m_CPA->GetDuration(), m_CurrentTrack->CalculateRotation());
m_CurrentPath->second.MoveToPointAt(m_CurrentPath->second.m_TimeElapsed /
m_CurrentPath->second.GetDuration(), m_CurrentPath->second.GetNodeFraction(),
m_CurrentPath->second.m_PreviousRotation );
}
void CCinemaManager::MoveToPointAbsolute(float time)
{
debug_assert(m_CurrentTrack);
g_Game->GetView()->GetCinema()->StopPlaying();
if ( m_CurrentTrack->m_Paths.empty() )
return;
m_CurrentTrack->m_CPA = m_CurrentTrack->m_Paths.begin();
//Small adjustment for blank paths at end of track (so it doesn't count the last path)
m_CurrentTrack->m_AbsoluteTime = m_CurrentTrack->m_CPA->m_TimeElapsed = time - .0001f;
if (!m_CurrentTrack->ValidateForward())
return;
float duration = m_CurrentTrack->m_CPA->GetDuration();
/* if ( duration < .0001f ) //blank path, used for finishing rotation
{
m_CurrentTrack->m_CPA->MoveToPointAt(1.0f, m_CurrentTrack->CalculateRotation());
return;
}*/
m_CurrentTrack->m_CPA->MoveToPointAt(m_CurrentTrack->m_CPA->m_TimeElapsed / duration,
m_CurrentTrack->CalculateRotation());
}
bool CCinemaManager::Update(float DeltaTime)
{
if (!m_TrackQueue.front().Play(DeltaTime))
if (!m_PathQueue.front().Play(DeltaTime))
{
m_TrackQueue.pop_front();
m_PathQueue.pop_front();
return false;
}
return true;

View File

@ -10,7 +10,7 @@
/*
Andrew Decker (aka pyrolink)
Contact: ajdecker1022@msn.com
desc: contains various functions used for cinematic camera tracks
desc: contains various functions used for cinematic camera paths
See also: CinemaHandler.cpp, Cinematic.h/.cpp
*/
@ -23,27 +23,30 @@ class CCinemaData
{
public:
CCinemaData() : m_GrowthCount(0), m_Growth(0), m_Switch(0),
m_Mode(0), m_Style(0) {}
m_Mode(0), m_Style(0), m_Timescale(1) {}
virtual ~CCinemaData() {}
const CCinemaData* GetData() const { return this; }
CVector3D m_TotalRotation;
//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
};
//Once the data is part of the path, it shouldn't be changeable
//Once the data is part of the path, it shouldn't be changeable, so use private inheritance.
//This class encompasses the spline and the information which determines how the path will operate
//and also provides the functionality for doing so
class CCinemaPath : private CCinemaData, public TNSpline
{
//friend class CCinemaTrack;
public:
CCinemaPath() { m_TimeElapsed = 0.0f; m_PreviousNodeTime = 0.0f; }
CCinemaPath(const CCinemaData& data, const TNSpline& spline);
~CCinemaPath() { DistStylePtr = NULL; DistModePtr = NULL; }
@ -51,7 +54,7 @@ public:
enum { ES_DEFAULT, ES_GROWTH, ES_EXPO, ES_CIRCLE, ES_SINE };
//sets camera position to calculated point on spline
void MoveToPointAt(float t, const CVector3D &startRotation);
void MoveToPointAt(float t, float nodet, const CVector3D& );
//Distortion mode functions-change how ratio is passed to distortion style functions
float EaseIn(float t) const;
@ -78,86 +81,62 @@ public:
inline CVector3D GetNodePosition(const int index) const { return Node[index].Position; }
inline float GetNodeDuration(const int index) const { return Node[index].Distance; }
inline float GetDuration() const { return MaxDistance; }
inline float GetNodeFraction() const { return (m_TimeElapsed - m_PreviousNodeTime) / Node[m_CurrentNode].Distance; }
inline float GetElapsedTime() const { return m_TimeElapsed; }
const std::vector<SplineData>& GetAllNodes() const { return Node; }
inline void SetTimescale(float scale) { m_Timescale = scale; }
float m_TimeElapsed;
};
class CCinemaTrack
{
friend class CCinemaManager;
public:
CCinemaTrack();
~CCinemaTrack() {}
float m_PreviousNodeTime; //How much time has passed before the current node
void AddPath(const CCinemaData& data, const TNSpline& spline);
void AddPath(const CCinemaPath& path);
inline void SetTimescale(float scale) { m_Timescale = scale; }
inline void SetStartRotation(CVector3D rotation) { m_StartRotation = rotation; }
void UpdateDuration();
size_t m_CurrentNode;
CVector3D m_PreviousRotation;
public:
//Returns false if finished
bool Play(float DeltaTime);
bool Validate();
inline const CVector3D& GetRotation() const { return m_StartRotation; }
inline float GetTimescale() const { return m_Timescale; }
inline float GetTotalDuration() const { return m_TotalDuration; }
inline const std::vector<CCinemaPath>& GetAllPaths() const { return m_Paths; }
private:
std::vector<CCinemaPath> m_Paths;
std::vector<CCinemaPath>::iterator m_CPA; //current path
CVector3D m_StartRotation;
float m_Timescale; //a negative timescale results in backwards play
float m_AbsoluteTime; //Current time of track, in absolute terms (not path)
float m_TotalDuration;
bool ValidateForward();
bool ValidateRewind();
CVector3D CalculateRotation();
inline float GetTimescale() const { return m_Timescale; }
};
//Class for in game playing of cinematics. Should only be instantiated
//in CGameView.
//Class for in game playing of cinematics. Should only be instantiated in CGameView.
class CCinemaManager
{
public:
CCinemaManager();
~CCinemaManager() {}
void AddTrack(CCinemaTrack track, const CStrW& name);
void AddPath(CCinemaPath path, const CStrW& name);
//Adds track to list of being played.
void QueueTrack(const CStrW& name, bool queue);
void OverrideTrack(const CStrW& name); //clears track queue and replaces with 'name'
void QueuePath(const CStrW& name, bool queue);
void OverridePath(const CStrW& name); //clears track queue and replaces with 'name'
bool Update(float DeltaTime);
//These stop track play, and accept time, not ratio of time
void MoveToPointAt(float time);
void MoveToPointAbsolute(float time); //Time in terms of track
inline void StopPlaying() { m_TrackQueue.clear(); }
void DrawAllSplines() const;
inline void StopPlaying() { m_PathQueue.clear(); }
void DrawSpline() const;
inline bool IsPlaying() const { return !m_TrackQueue.empty(); }
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, CCinemaTrack>& GetAllTracks() { return m_Tracks; }
void SetAllTracks( const std::map<CStrW, CCinemaTrack>& tracks);
void SetCurrentTrack(const CStrW& name, bool all, bool current, bool lines);
void SetCurrentPath(int path);
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);
private:
bool m_Active, m_DrawCurrentSpline, m_DrawAllSplines, m_DrawLines;
int m_CurrentPath;
CCinemaTrack* m_CurrentTrack;
std::map<CStrW, CCinemaTrack> m_Tracks;
std::list<CCinemaTrack> m_TrackQueue;
bool m_Active, m_DrawCurrentSpline, m_DrawLines;
std::map<CStrW, CCinemaPath>::iterator m_CurrentPath;
std::map<CStrW, CCinemaPath> m_Paths;
std::list<CCinemaPath> m_PathQueue;
};
#endif

View File

@ -121,7 +121,6 @@ public:
CLightEnv CachedLightEnv;
CCinemaManager TrackManager;
CCinemaTrack TestTrack;
////////////////////////////////////////
// Settings

View File

@ -508,12 +508,12 @@ void CXMLReader::ReadCinema(XMBElement parent)
#define EL(x) int el_##x = xmb_file.getElementID(#x)
#define AT(x) int at_##x = xmb_file.getAttributeID(#x)
EL(track);
EL(startrotation);
EL(path);
EL(rotation);
EL(distortion);
EL(node);
EL(position);
EL(time);
AT(name);
AT(timescale);
AT(mode);
@ -523,97 +523,98 @@ void CXMLReader::ReadCinema(XMBElement parent)
AT(x);
AT(y);
AT(z);
AT(t);
#undef EL
#undef AT
std::map<CStrW, CCinemaTrack> trackList;
std::map<CStrW, CCinemaPath> pathList;
XERO_ITER_EL(parent, element)
{
int elementName = element.getNodeName();
if ( elementName == el_track )
if ( elementName == el_path )
{
CCinemaTrack track;
XMBAttributeList attrs = element.getAttributes();
CStrW name( CStr(attrs.getNamedItem(at_name)) );
float timescale = CStr(attrs.getNamedItem(at_timescale)).ToFloat();
track.SetTimescale(timescale);
CCinemaData pathData;
pathData.m_Timescale = timescale;
TNSpline spline, backwardSpline;
XERO_ITER_EL(element, trackChild)
XERO_ITER_EL(element, pathChild)
{
elementName = trackChild.getNodeName();
elementName = pathChild.getNodeName();
attrs = pathChild.getAttributes();
if ( elementName == el_startrotation )
//Load distortion attributes
if ( elementName == el_distortion )
{
attrs = trackChild.getAttributes();
float x = CStr(attrs.getNamedItem(at_x)).ToFloat();
float y = CStr(attrs.getNamedItem(at_y)).ToFloat();
float z = CStr(attrs.getNamedItem(at_z)).ToFloat();
track.SetStartRotation(CVector3D(x, y, z));
pathData.m_Mode = CStr(attrs.getNamedItem(at_mode)).ToInt();
pathData.m_Style = CStr(attrs.getNamedItem(at_style)).ToInt();
pathData.m_Growth = CStr(attrs.getNamedItem(at_growth)).ToInt();
pathData.m_Switch = CStr(attrs.getNamedItem(at_switch)).ToInt();
}
else if ( elementName == el_path )
//Load node data used for spline
else if ( elementName == el_node )
{
CCinemaData pathData;
TNSpline spline, backwardSpline;
XERO_ITER_EL(trackChild, pathChild)
SplineData data;
XERO_ITER_EL(pathChild, nodeChild)
{
elementName = pathChild.getNodeName();
attrs = pathChild.getAttributes();
if ( elementName == el_rotation )
elementName = nodeChild.getNodeName();
attrs = nodeChild.getAttributes();
//Fix?: assumes that time is last element
if ( elementName == el_position )
{
float x = CStr(attrs.getNamedItem(at_x)).ToFloat();
float y = CStr(attrs.getNamedItem(at_y)).ToFloat();
float z = CStr(attrs.getNamedItem(at_z)).ToFloat();
pathData.m_TotalRotation = CVector3D(x, y, z);
}
else if ( elementName == el_distortion )
{
pathData.m_Mode = CStr(attrs.getNamedItem(at_mode)).ToInt();
pathData.m_Style = CStr(attrs.getNamedItem(at_style)).ToInt();
pathData.m_Growth = CStr(attrs.getNamedItem(at_growth)).ToInt();
pathData.m_Switch = CStr(attrs.getNamedItem(at_switch)).ToInt();
}
else if ( elementName == el_node )
{
SplineData data;
data.Position.X = CStr(attrs.getNamedItem(at_x)).ToFloat();
data.Position.Y = CStr(attrs.getNamedItem(at_y)).ToFloat();
data.Position.Z = CStr(attrs.getNamedItem(at_z)).ToFloat();
data.Distance = CStr(attrs.getNamedItem(at_t)).ToFloat();
backwardSpline.AddNode(data.Position, data.Distance);
continue;
}
else
debug_warn("Invalid cinematic element for path child");
} //node loop
CCinemaPath temp(pathData, backwardSpline);
const std::vector<SplineData>& nodes = temp.GetAllNodes();
if ( nodes.empty() )
{
debug_warn("Failure loading cinematics");
return;
}
else if ( elementName == el_rotation )
{
data.Rotation.X = CStr(attrs.getNamedItem(at_x)).ToFloat();
data.Rotation.Y = CStr(attrs.getNamedItem(at_y)).ToFloat();
data.Rotation.Z = CStr(attrs.getNamedItem(at_z)).ToFloat();
continue;
}
else if ( elementName == el_time )
data.Distance = CStr( nodeChild.getText() ).ToFloat();
else
debug_warn("Invalid cinematic element for node child");
for ( std::vector<SplineData>::const_reverse_iterator
it=nodes.rbegin(); it != nodes.rend(); ++it )
{
spline.AddNode(it->Position, it->Distance);
backwardSpline.AddNode(data.Position, data.Rotation, data.Distance);
}
track.AddPath(pathData, spline);
} // == el_path
}
else
debug_warn("Invalid cinematic element for track child");
debug_warn("Invalid cinematic element for path child");
}
trackList[name] = track;
//Construct cinema path with data gathered
CCinemaPath temp(pathData, backwardSpline);
const std::vector<SplineData>& nodes = temp.GetAllNodes();
if ( nodes.empty() )
{
debug_warn("Failure loading cinematics");
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;
}
else
debug_warn("Invalid cinematic element for root track child");
else
debug_assert("Invalid cinema child");
}
g_Game->GetView()->GetCinema()->SetAllTracks(trackList);
g_Game->GetView()->GetCinema()->SetAllPaths(pathList);
}
void CXMLReader::ReadTriggers(XMBElement parent)
@ -987,7 +988,7 @@ int CXMLReader::ProgressiveRead()
if (ret != 0) // error or timed out
return ret;
}
else if (name == "Tracks")
else if (name == "Paths")
{
ReadCinema(node);
}

View File

@ -333,62 +333,51 @@ void CMapWriter::WriteXML(const char* filename,
}
}
const std::map<CStrW, CCinemaTrack>& tracks = pCinema->GetAllTracks();
std::map<CStrW, CCinemaTrack>::const_iterator it = tracks.begin();
const std::map<CStrW, CCinemaPath>& paths = pCinema->GetAllPaths();
std::map<CStrW, CCinemaPath>::const_iterator it = paths.begin();
{
XML_Element("Tracks");
XML_Element("Paths");
for ( ; it != tracks.end(); it++ )
for ( ; it != paths.end(); it++ )
{
const std::vector<CCinemaPath>& paths = it->second.GetAllPaths();
CStrW name = it->first;
size_t numPaths = paths.size();
CVector3D startRotation = it->second.GetRotation();
float timescale = it->second.GetTimescale();
XML_Element("Track");
XML_Element("Path");
XML_Attribute("name", name);
XML_Attribute("timescale", timescale);
const std::vector<SplineData>& nodes = it->second.GetAllNodes();
const CCinemaData* data = it->second.GetData();
{
XML_Element("StartRotation");
XML_Attribute("x", startRotation.X);
XML_Attribute("y", startRotation.Y);
XML_Attribute("z", startRotation.Z);
XML_Element("Distortion");
XML_Attribute("mode", data->m_Mode);
XML_Attribute("style", data->m_Style);
XML_Attribute("growth", data->m_Growth);
XML_Attribute("switch", data->m_Switch);
}
for ( size_t i=0; i<numPaths; ++i )
for ( int j=(int)nodes.size()-1; j >= 0; --j )
{
const std::vector<SplineData>& nodes = paths[i].GetAllNodes();
const CCinemaData* data = paths[i].GetData();
XML_Element("Path");
{
CVector3D rot = data->m_TotalRotation;
XML_Element("Rotation");
XML_Attribute("x", rot.X);
XML_Attribute("y", rot.Y);
XML_Attribute("z", rot.Z);
}
XML_Element("Node");
{
XML_Element("Distortion");
XML_Attribute("mode", data->m_Mode);
XML_Attribute("style", data->m_Style);
XML_Attribute("growth", data->m_Growth);
XML_Attribute("switch", data->m_Switch);
}
for ( int j=(int)nodes.size()-1; j >= 0; --j )
{
XML_Element("Node");
XML_Element("Position");
XML_Attribute("x", nodes[j].Position.X);
XML_Attribute("y", nodes[j].Position.Y);
XML_Attribute("z", nodes[j].Position.Z);
XML_Attribute("t", nodes[j].Distance);
}
{
XML_Element("Rotation");
XML_Attribute("x", nodes[j].Rotation.X);
XML_Attribute("y", nodes[j].Rotation.Y);
XML_Attribute("z", nodes[j].Rotation.Z);
}
XML_Setting("Time", nodes[j].Distance);
}
}
}

View File

@ -146,7 +146,7 @@ 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, float timePeriod)
void TNSpline::AddNode(const CVector3D &pos, const CVector3D& rotation, float timePeriod)
{
if ( NodeCount >= MAX_SPLINE_NODES )
return;
@ -155,19 +155,22 @@ void TNSpline::AddNode(const CVector3D &pos, float timePeriod)
else
{
Node[NodeCount-1].Distance = timePeriod;
MaxDistance += Node[NodeCount-1].Distance;
MaxDistance += Node[NodeCount-1].Distance;
}
SplineData temp;
temp.Position = pos;
//make sure we don't end up using undefined numbers...
temp.Distance = 0.0f;
temp.Velocity = CVector3D( 0.0f, 0.0f, 0.0f );
temp.Rotation = rotation;
Node.push_back(temp);
NodeCount++;
}
//Inserts node before position
void TNSpline::InsertNode(const int index, const CVector3D &pos, float timePeriod)
void TNSpline::InsertNode(const int index, const CVector3D &pos, const CVector3D& rotation, float timePeriod)
{
if ( NodeCount >= MAX_SPLINE_NODES || index < NodeCount - 1 )
return;
@ -176,6 +179,7 @@ void TNSpline::InsertNode(const int index, const CVector3D &pos, float timePerio
else
{
Node[NodeCount-1].Distance = timePeriod;
Node[NodeCount-1].Rotation = rotation;
MaxDistance += Node[NodeCount-1].Distance;
}
SplineData temp;

View File

@ -13,7 +13,8 @@ struct SplineData
{
CVector3D Position;
CVector3D Velocity;
float Distance;
CVector3D Rotation;
float Distance/*, DistanceOffset*/; //DistanceOffset is to keep track of how far into the spline this node is
};
class RNSpline
@ -22,9 +23,12 @@ public:
RNSpline() { NodeCount = 0; }
virtual ~RNSpline() {}
void AddNode(const CVector3D &pos);
void BuildSpline();
CVector3D GetPosition(float time) const;
CVector3D GetRotation(float time) const;
const std::vector<SplineData>& GetAllNodes() const { return Node; }
float MaxDistance;
int NodeCount;
@ -47,9 +51,10 @@ class TNSpline : public SNSpline
{
public:
virtual ~TNSpline() {}
void AddNode(const CVector3D &pos, float timePeriod);
void AddNode(const CVector3D& pos, const CVector3D& rotation, float timePeriod);
void PushNode() { Node.push_back( SplineData() ); }
void InsertNode(const int index, const CVector3D &pos, float timePeriod);
void InsertNode(const int index, const CVector3D &pos, const CVector3D& rotation, float timePeriod);
void RemoveNode(const int index);
void UpdateNodeTime(const int index, float time);
void UpdateNodePos(const int index, const CVector3D &pos);

View File

@ -362,7 +362,7 @@ void Render()
PROFILE_START( "render cinematic splines" );
//Sets/resets renderering properties itself
g_Game->GetView()->GetCinema()->DrawAllSplines();
g_Game->GetView()->GetCinema()->DrawSpline();
PROFILE_END( "render cinematic splines" );
}

View File

@ -8,10 +8,8 @@
#include "GameInterface/Messages.h"
class TrackListCtrl;
class PathListCtrl;
class NodeListCtrl;
class CinemaSliderBox;
class CinemaSpinnerBox;
class CinemaInfoBox;
class CinematicBottomBar;
@ -22,23 +20,21 @@ class CinematicSidebar : public Sidebar
{
//For ease (from lazyness)
friend class CinemaButtonBox;
friend class TrackSlider;
friend class PathSlider;
public:
CinematicSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer);
//The actual data is stored in bottom bar, but is controled from here
void SelectTrack(ssize_t n);
void SelectPath(ssize_t n);
//avoid excessive shareable->vector conversion with size paramater
void SelectSplineNode(ssize_t n, ssize_t size = -1);
void AddTrack(std::wstring& name, int count);
void AddPath(int x, int y, int z, int count);
void AddNode(float x, float y, float z, int count);
void UpdateTrack(std::wstring name, float timescale);
//void UpdateTrack(float x, float y, float z);
void UpdatePath(int x, int y, int z, ssize_t index=-1);
void UpdateNode(float x, float y, float z, float t=-1);
void AddPath(std::wstring& name, int count);
void AddNode(float px, float py, float pz, float rx, float ry, float rz, int count);
void UpdatePath(std::wstring name, float timescale);
void UpdateNode(float px, float py, float pz, float rx, float ry, float rz, float t=-1);
void DeleteTrack();
void DeletePath();
@ -46,23 +42,21 @@ public:
void SetSpinners(CinemaSpinnerBox* box) { m_SpinnerBox = box; }
const AtlasMessage::sCinemaTrack* GetCurrentTrack();
AtlasMessage::sCinemaPath GetCurrentPath();
AtlasMessage::sCinemaSplineNode GetCurrentNode();
const AtlasMessage::sCinemaPath* GetCurrentPath() const;
AtlasMessage::sCinemaSplineNode GetCurrentNode() const;
int GetSelectedTrack() { return m_SelectedTrack; }
std::wstring GetSelectedTrackName() { return *m_Tracks[m_SelectedTrack].name; }
int GetSelectedPath() { return m_SelectedPath; }
int GetSelectedNode() { return m_SelectedSplineNode; }
std::wstring GetSelectedPathName() const;
int GetSelectedPath() const { return m_SelectedPath; }
int GetSelectedNode() const { return m_SelectedSplineNode; }
void GotoNode(ssize_t index=-1);
float UpdateSelectedPath();
void UpdatePathInfo(int mode, int style, float growth, float change,
bool drawAll, bool drawCurrent, bool drawLine);
void UpdatePathInfo(int mode, int style, float growth, float change, bool drawCurrent, bool drawLine);
void UpdateSpinners();
void UpdateTexts();
void UpdateEngineData();
void SendEngineSelection();
float m_TimeElapsed; //path time
float m_AbsoluteTime; //track time
@ -76,20 +70,18 @@ protected:
private:
// Stores all cinematics data for this map. Initialised by OnFirstDisplay.
// Sent back to the game by [TODO]. (TODO: handle 'undo' correctly)
std::vector<AtlasMessage::sCinemaTrack> m_Tracks;
std::vector<AtlasMessage::sCinemaPath> m_Paths;
CinemaButtonBox* m_IconSizer;
ssize_t m_SelectedTrack; // -1 for none
ssize_t m_SelectedPath; // -1 for none
ssize_t m_SelectedSplineNode; // -1 for none
TrackListCtrl* m_TrackList;
PathListCtrl* m_PathList;
NodeListCtrl* m_NodeList;
CinemaSliderBox* m_SliderBox;
CinemaSpinnerBox* m_SpinnerBox; //We must update the display
CinemaInfoBox* m_InfoBox; // ^same^
PathSlider* m_PathSlider;
CinemaSpinnerBox* m_SpinnerBox; //We must update the display
CinemaInfoBox* m_InfoBox; // ^same^
CinematicBottomBar* m_CinemaBottomBar;
wxImage LoadIcon(const wxString& filename);

View File

@ -287,13 +287,17 @@ public:
TriggerSidebar* m_Sidebar;
size_t m_CondCount, m_EffectCount;
bool m_Group;
std::list<int> m_BlockIndices, m_BlockEndIndices;
std::list<int> m_BlockIndices, m_BlockEndIndices; //index in sidebar list
void AddBlock(const int block, const int index)
{
std::vector<int> copy = *logicBlocks;
std::vector<bool> notCopy = *logicNots;
copy.push_back(block);
notCopy.push_back(false);
logicBlocks = copy;
logicNots = notCopy;
m_BlockIndices.push_back(index);
}
void AddBlockEnd(const int block, const int index)
@ -345,10 +349,10 @@ class TriggerBottomBar : public wxPanel
enum { ID_TimeEdit, ID_CondNameEdit, ID_EffectNameEdit, ID_TriggerNameEdit, ID_RunsEdit,
ID_EffectChoice, ID_CondChoice,
ID_TimeRadio, ID_LogicRadio,
ID_NotCheck, ID_ActiveCheck };
ID_NotCheck, ID_ActiveCheck, ID_LogicNotCheck };
public:
enum { NO_VIEW, TRIGGER_VIEW, CONDITION_VIEW, EFFECT_VIEW };
enum { NO_VIEW, TRIGGER_VIEW, CONDITION_VIEW, EFFECT_VIEW, LOGIC_END_VIEW, LOGIC_VIEW };
TriggerBottomBar(TriggerSidebar* sidebar, wxWindow* parent)
: wxPanel(parent), m_Sidebar(sidebar)
@ -477,6 +481,7 @@ public:
m_Sidebar->GetSelectedItemData()->maxRuns = iValue;
m_Sidebar->UpdateEngineData();
}
void onLogicRadio(wxCommandEvent& evt)
{
if ( m_Sidebar->m_SelectedCond == -1 )
@ -508,11 +513,22 @@ public:
m_Sidebar->UpdateEngineData();
}
void onLogicNotCheck(wxCommandEvent& evt)
{
TriggerItemData* data = m_Sidebar->GetSelectedItemData();
int logicIndex = m_Sidebar->GetLogicBlockCount(m_Sidebar->m_SelectedCond) - 1;
std::vector<bool> nots = *data->logicNots;
nots[logicIndex] = evt.IsChecked();
data->logicNots = nots;
}
void DisplayTriggerSpec(const sTriggerSpec& spec)
{
if ( m_Sizer->Detach(m_ParameterSizer) )
{
m_ParameterSizer->DeleteWindows();
delete m_ParameterSizer;
//m_Sizer->Layout();
// Layout();
}
@ -642,11 +658,13 @@ public:
void FillConditionData()
{
if ( m_Sidebar->m_SelectedCond== -1 )
if ( m_Sidebar->m_SelectedCond == -1 )
return;
TriggerItemData* itemData = m_Sidebar->GetSelectedItemData();
int iCondition = m_Sidebar->GetConditionCount(m_Sidebar->m_SelectedCond);
if ( iCondition <= 0 )
return;
sTriggerCondition condition = (*itemData->conditions)[iCondition-1];
wxString display( (*condition.displayName).c_str() );
m_ConditionEdit->SetValue( wxString(condition.name.c_str()) );
@ -708,6 +726,13 @@ public:
}
void FillLogicData()
{
std::vector<bool> nots = *m_Sidebar->GetSelectedItemData()->logicNots;
m_LogicNotCheck->SetValue( nots[m_Sidebar->GetLogicBlockCount(m_Sidebar->m_SelectedCond)-1] );
}
void ToEffectView()
{
DestroyChildren();
@ -828,6 +853,22 @@ public:
Layout();
m_DependentStatus = TRIGGER_VIEW;
}
//void ToLogicEndView();
void ToLogicView()
{
DestroyChildren();
m_Sizer = new wxBoxSizer(wxHORIZONTAL);
m_DependentSizer = new wxStaticBoxSizer(wxVERTICAL, this, wxString(L"Trigger Editor"));
SetSizer(m_Sizer, true);
m_LogicNotCheck = new wxCheckBox(this, ID_LogicNotCheck, L"Not");
m_DependentSizer->Add(m_LogicNotCheck);
m_Sizer->Add(m_DependentSizer, 0, wxTOP | wxLEFT | wxALIGN_LEFT, 10);
m_Sizer->Layout();
Layout();
m_DependentStatus = LOGIC_VIEW;
}
void ToNoView()
{
if ( m_DependentStatus == NO_VIEW )
@ -844,9 +885,9 @@ private:
wxStaticBoxSizer* m_DependentSizer; //dependent = effect/condition
wxTextCtrl* m_TimeEdit, *m_ConditionEdit, *m_EffectEdit, *m_TriggerEdit, *m_RunsEdit;
wxCheckBox* m_ActiveCheck, *m_NotCheck;
wxCheckBox* m_ActiveCheck, *m_NotCheck, *m_LogicNotCheck;
wxChoice* m_ConditionChoice, *m_EffectChoice;
wxRadioBox* m_LogicRadio, *m_TimeRadio;
wxRadioBox* m_LogicRadio, *m_TimeRadio, m_LogicEndRadio;
std::vector<sTriggerSpec> m_ConditionSpecs, m_EffectSpecs;
@ -868,6 +909,7 @@ EVT_CHOICE(TriggerBottomBar::ID_CondChoice, TriggerBottomBar::onCondChoice)
EVT_RADIOBOX(TriggerBottomBar::ID_LogicRadio, TriggerBottomBar::onLogicRadio)
EVT_CHECKBOX(TriggerBottomBar::ID_ActiveCheck, TriggerBottomBar::onActiveCheck)
EVT_CHECKBOX(TriggerBottomBar::ID_NotCheck, TriggerBottomBar::onNotCheck)
EVT_CHECKBOX(TriggerBottomBar::ID_LogicNotCheck, TriggerBottomBar::onLogicNotCheck)
//EVT_RADIOBOX(TriggerBotomBar::ID_TimeRadio, TriggerBottomBar::onTimeRadio)
END_EVENT_TABLE()
@ -892,9 +934,34 @@ void TriggerListCtrl::onClick(wxMouseEvent& evt)
if ( m_Condition )
{
//if ( m_Sidebar->m_TriggerBottom->GetDependentStatus() != TriggerBottomBar::CONDITION_VIEW )
/*if ( m_Sidebar->m_ConditionPage->m_List->GetItemText(m_Sidebar->m_SelectedCond)
== m_Sidebar->m_LogicBlockEndString )
{
m_Sidebar->m_TriggerBottom->ToLogicEndView();
if ( m_Sidebar->m_SelectedCond != -1 )
m_Sidebar->m_TriggerBottom->FillLogicEndData();
}*/
if ( m_Sidebar->m_ConditionPage->m_List->GetItemText(m_Sidebar->m_SelectedCond)
== m_Sidebar->m_LogicBlockEndString )
{
m_Sidebar->m_TriggerBottom->ToNoView();
}
else if ( m_Sidebar->m_ConditionPage->m_List->GetItemText(m_Sidebar->m_SelectedCond)
== m_Sidebar->m_LogicBlockString )
{
m_Sidebar->m_TriggerBottom->ToLogicView();
if ( m_Sidebar->m_SelectedCond != -1 )
m_Sidebar->m_TriggerBottom->FillLogicData();
}
else
{
m_Sidebar->m_TriggerBottom->ToConditionView();
if ( m_Sidebar->m_SelectedCond != -1 )
m_Sidebar->m_TriggerBottom->FillConditionData();
if ( m_Sidebar->m_SelectedCond != -1 )
m_Sidebar->m_TriggerBottom->FillConditionData();
}
}
else
{
@ -1233,6 +1300,8 @@ void onLogicBlockPush(void* data)
sidebar->GetSelectedItemData()->AddBlock(conditionCount, limit);
sidebar->UpdateLists();
sidebar->m_TriggerBottom->ToLogicView(); //Some data is not valid, so reset
sidebar->m_TriggerBottom->FillLogicData();
sidebar->UpdateEngineData();
}
@ -1336,12 +1405,22 @@ int TriggerSidebar::GetConditionCount(int limit)
for ( int i = 0; i <= limit; ++i )
{
if ( list->GetItemText(i) != m_LogicBlockString && list->GetItemText(i) != m_LogicBlockEndString)
{
++conditionCount;
}
}
return conditionCount;
}
int TriggerSidebar::GetLogicBlockCount(int limit)
{
int logicCount = 0;
wxListCtrl* list = m_ConditionPage->m_List;
for ( int i = 0; i <= limit; ++i )
{
if ( list->GetItemText(i) == m_LogicBlockString )
++logicCount;
}
return logicCount;
}
void TriggerSidebar::OnFirstDisplay()
{
qGetTriggerData dataQuery;
@ -1542,8 +1621,25 @@ void TriggerSidebar::onCondSelect(wxListEvent& evt)
{
m_SelectedCond = evt.GetIndex();
//if ( m_TriggerBottom->GetDependentStatus() != TriggerBottomBar::CONDITION_VIEW )
if ( m_ConditionPage->m_List->GetItemText(m_SelectedCond)
== m_LogicBlockEndString )
{
m_TriggerBottom->ToNoView();
}
else if ( m_ConditionPage->m_List->GetItemText(m_SelectedCond)
== m_LogicBlockString )
{
m_TriggerBottom->ToLogicView();
if ( m_SelectedCond != -1 )
m_TriggerBottom->FillLogicData();
}
else
{
m_TriggerBottom->ToConditionView();
m_TriggerBottom->FillConditionData();
if ( m_SelectedCond != -1 )
m_TriggerBottom->FillConditionData();
}
}
void TriggerSidebar::onEffectSelect(wxListEvent& evt)
{

View File

@ -37,6 +37,7 @@ public:
//Finds condition number (index+1) of m_SelectedCond [needed because of logic blocks]
int GetConditionCount(int limit);
int GetLogicBlockCount(int limit);
void UpdateLists();
void UpdateEngineData();

View File

@ -17,14 +17,7 @@
namespace AtlasMessage {
sCinemaTrack ConstructCinemaTrack(const CCinemaTrack& data)
{
sCinemaTrack track;
track.timescale = data.GetTimescale();
track.duration = data.GetTotalDuration();
return track;
}
sCinemaPath ConstructCinemaPath(const CCinemaPath* source)
{
sCinemaPath path;
@ -32,6 +25,7 @@ sCinemaPath ConstructCinemaPath(const CCinemaPath* source)
path.mode = data->m_Mode;
path.style = data->m_Style;
path.growth = data->m_Growth;
path.timescale = data->m_Timescale;
path.change = data->m_Switch;
return path;
@ -49,121 +43,75 @@ CCinemaData ConstructCinemaData(const sCinemaPath& path)
sCinemaSplineNode ConstructCinemaNode(const SplineData& data)
{
sCinemaSplineNode node;
node.x = data.Position.X;
node.y = data.Position.Y;
node.z = data.Position.Z;
node.px = data.Position.X;
node.py = data.Position.Y;
node.pz = data.Position.Z;
node.rx = data.Rotation.X;
node.ry = data.Rotation.Y;
node.rz = data.Rotation.Z;
node.t = data.Distance;
return node;
}
std::vector<sCinemaTrack> GetCurrentTracks()
std::vector<sCinemaPath> GetCurrentPaths()
{
const std::map<CStrW, CCinemaTrack>& tracks = g_Game->GetView()->GetCinema()->GetAllTracks();
std::vector<sCinemaTrack> atlasTracks;
const std::map<CStrW, CCinemaPath>& paths = g_Game->GetView()->GetCinema()->GetAllPaths();
std::vector<sCinemaPath> atlasPaths;
for ( std::map<CStrW, CCinemaTrack>::const_iterator it=tracks.begin(); it!=tracks.end(); it++ )
for ( std::map<CStrW, CCinemaPath>::const_iterator it=paths.begin(); it!=paths.end(); it++ )
{
sCinemaTrack atlasTrack = ConstructCinemaTrack(it->second);
atlasTrack.name = it->first;
const std::vector<CCinemaPath>& paths = it->second.GetAllPaths();
std::vector<sCinemaPath> atlasPaths;
for ( std::vector<CCinemaPath>::const_iterator it2=paths.begin(); it2!=paths.end(); it2++ )
sCinemaPath path = ConstructCinemaPath(&it->second);
path.name = it->first;
const std::vector<SplineData>& nodes = it->second.GetAllNodes();
std::vector<sCinemaSplineNode> atlasNodes;
for ( size_t i=0; i<nodes.size(); ++i )
atlasNodes.push_back( ConstructCinemaNode(nodes[i]) );
if ( !atlasNodes.empty() )
{
sCinemaPath path = ConstructCinemaPath(&*it2);
CVector3D rotation;
if ( it2 == paths.begin() )
rotation = it->second.GetRotation();
else
rotation = (it2-1)->GetData()->m_TotalRotation;
path.x = RADTODEG(rotation.X);
path.y = RADTODEG(rotation.Y);
path.z = RADTODEG(rotation.Z);
const std::vector<SplineData>& nodes = it2->GetAllNodes();
std::vector<sCinemaSplineNode> atlasNodes;
for ( size_t i=0; i<nodes.size(); ++i )
float back = atlasNodes.back().t;
if ( atlasNodes.size() > 2 )
{
atlasNodes.push_back( ConstructCinemaNode(nodes[i]) );
for ( size_t i=atlasNodes.size()-2; i>0; --i )
atlasNodes[i].t = atlasNodes[i-1].t;
}
if ( !atlasNodes.empty() )
{
float back = atlasNodes.back().t;
if ( atlasNodes.size() > 2 )
{
for ( size_t i=atlasNodes.size()-2; i>0; --i )
atlasNodes[i].t = atlasNodes[i-1].t;
}
atlasNodes.back().t = atlasNodes.front().t;
atlasNodes.front().t = back;
}
path.nodes = atlasNodes;
path.duration = it2->GetDuration();
atlasPaths.push_back(path);
atlasNodes.back().t = atlasNodes.front().t;
atlasNodes.front().t = back;
}
atlasTrack.paths = atlasPaths;
atlasTracks.push_back(atlasTrack);
path.nodes = atlasNodes;
atlasPaths.push_back(path);
}
return atlasTracks;
return atlasPaths;
}
void SetCurrentTracks(const std::vector<sCinemaTrack>& atlasTracks)
void SetCurrentPaths(const std::vector<sCinemaPath>& atlasPaths)
{
std::map<CStrW, CCinemaTrack> tracks;
std::map<CStrW, CCinemaPath> paths;
for ( std::vector<sCinemaTrack>::const_iterator it=atlasTracks.begin(); it!=atlasTracks.end(); it++ )
for ( std::vector<sCinemaPath>::const_iterator it=atlasPaths.begin(); it!=atlasPaths.end(); it++ )
{
CStrW trackName(*it->name);
tracks[trackName] = CCinemaTrack();
tracks[trackName].SetTimescale(it->timescale);
const std::vector<sCinemaPath> paths = *it->paths;
size_t i=0;
CStrW pathName(*it->name);
paths[pathName] = CCinemaPath();
paths[pathName].SetTimescale(it->timescale);
for ( std::vector<sCinemaPath>::const_iterator it2=paths.begin();
it2!=paths.end(); it2++, ++i )
{
const sCinemaPath& atlasPath = *it2;
const std::vector<sCinemaSplineNode> nodes = *atlasPath.nodes;
TNSpline spline;
CCinemaData data = ConstructCinemaData(atlasPath);
if ( i == 0 )
{
tracks[trackName].SetStartRotation( CVector3D(DEGTORAD(it2->x),
DEGTORAD(it2->y), DEGTORAD(it2->z)) );
if ( paths.size() == 1 )
{
data.m_TotalRotation = CVector3D( DEGTORAD(it2->x),
DEGTORAD(it2->y), DEGTORAD(it2->z) );
}
}
if ( i < paths.size() -1 )
{
data.m_TotalRotation = CVector3D(CVector3D(DEGTORAD((it2+1)->x),
DEGTORAD((it2+1)->y), DEGTORAD((it2+1)->z)));
}
else if ( i > 0 ) //no rotation (ending path)
{
data.m_TotalRotation = CVector3D(DEGTORAD((it2)->x),
DEGTORAD((it2)->y), DEGTORAD((it2)->z));
}
for ( size_t j=0; j<nodes.size(); ++j )
{
spline.AddNode( CVector3D(nodes[j].x, nodes[j].y, nodes[j].z), nodes[j].t );
}
tracks[trackName].AddPath(data, spline);
const sCinemaPath& atlasPath = *it;
const std::vector<sCinemaSplineNode> nodes = *atlasPath.nodes;
TNSpline spline;
CCinemaData data = ConstructCinemaData(atlasPath);
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 );
}
paths[pathName] = CCinemaPath(data, spline);
}
g_Game->GetView()->GetCinema()->SetAllTracks(tracks);
g_Game->GetView()->GetCinema()->SetAllPaths(paths);
}
QUERYHANDLER(GetCameraInfo)
{
@ -190,44 +138,43 @@ QUERYHANDLER(GetCameraInfo)
MESSAGEHANDLER(CinemaEvent)
{
CCinemaManager* manager = g_Game->GetView()->GetCinema();
manager->SetCurrentTrack(*msg->track, msg->drawAll,
msg->drawCurrent, msg->lines);
if ( msg->mode == eCinemaEventMode::SMOOTH )
manager->OverrideTrack(*msg->track);
manager->OverridePath(*msg->path);
else if ( msg->mode == eCinemaEventMode::IMMEDIATE_PATH )
manager->MoveToPointAt(msg->t);
else if ( msg->mode == eCinemaEventMode::IMMEDIATE_TRACK )
manager->MoveToPointAbsolute(msg->t);
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
manager->SetCurrentPath((int)msg->t);
debug_assert(false);
}
BEGIN_COMMAND(SetCinemaTracks)
BEGIN_COMMAND(SetCinemaPaths)
{
std::vector<sCinemaTrack> m_oldTracks, m_newTracks;
std::vector<sCinemaPath> m_oldPaths, m_newPaths;
void Do()
{
m_oldTracks = GetCurrentTracks();
m_newTracks = *msg->tracks;
m_oldPaths = GetCurrentPaths();
m_newPaths = *msg->paths;
Redo();
}
void Redo()
{
SetCurrentTracks(m_newTracks);
SetCurrentPaths(m_newPaths);
}
void Undo()
{
SetCurrentTracks(m_oldTracks);
SetCurrentPaths(m_oldPaths);
}
};
END_COMMAND(SetCinemaTracks)
END_COMMAND(SetCinemaPaths)
QUERYHANDLER(GetCinemaTracks)
QUERYHANDLER(GetCinemaPaths)
{
msg->tracks = GetCurrentTracks();
msg->paths = GetCurrentPaths();
}
}

View File

@ -32,7 +32,7 @@ MESSAGEHANDLER(Screenshot)
QUERYHANDLER(CinemaRecord)
{
CCinemaManager* manager = g_Game->GetView()->GetCinema();
manager->SetCurrentTrack(*msg->track, false, false, false);
manager->SetCurrentPath(*msg->path, false, false);
const int w = msg->width, h = msg->height;
@ -57,7 +57,7 @@ QUERYHANDLER(CinemaRecord)
{
View::GetView_Game()->Update(1.f / msg->framerate);
manager->MoveToPointAbsolute((float)frame/msg->framerate);
manager->MoveToPointAt((float)frame/msg->framerate);
Render();
Atlas_GLSwapBuffers((void*)g_GameLoop->glCanvas);

View File

@ -266,8 +266,8 @@ QUERYHANDLER(GetTriggerChoices)
if ( choices[0] == std::wstring(L"ATLAS_CINEMA_LIST") )
{
choices.clear();
const std::map<CStrW, CCinemaTrack>& tracks = g_Game->GetView()->GetCinema()->GetAllTracks();
for ( std::map<CStrW, CCinemaTrack>::const_iterator it = tracks.begin(); it != tracks.end(); ++it )
const std::map<CStrW, CCinemaPath>& paths = g_Game->GetView()->GetCinema()->GetAllPaths();
for ( std::map<CStrW, CCinemaPath>::const_iterator it = paths.begin(); it != paths.end(); ++it )
{
choices.push_back(it->first);
translations.push_back( L"\"" + it->first + L"\"" ); //Strings need quotes in JS

View File

@ -106,7 +106,7 @@ struct sCinemaRecordCB
SHAREABLE_STRUCT(sCinemaRecordCB);
QUERY(CinemaRecord,
((std::wstring, track))
((std::wstring, path))
((int, framerate))
((float, duration))
((int, width))
@ -354,9 +354,9 @@ COMMAND(SetObjectSettings, NOMERGE,
//////////////////////////////////////////////////////////////////////////
QUERY(GetCinemaTracks,
QUERY(GetCinemaPaths,
, // no inputs
((std::vector<AtlasMessage::sCinemaTrack> , tracks))
((std::vector<AtlasMessage::sCinemaPath> , paths))
);
QUERY(GetCameraInfo,
@ -364,15 +364,14 @@ QUERY(GetCameraInfo,
((AtlasMessage::sCameraInfo, info))
);
COMMAND(SetCinemaTracks, NOMERGE,
((std::vector<AtlasMessage::sCinemaTrack>, tracks))
COMMAND(SetCinemaPaths, NOMERGE,
((std::vector<AtlasMessage::sCinemaPath>, paths))
);
MESSAGE(CinemaEvent,
((std::wstring, track))
((std::wstring, path))
((int, mode))
((float, t))
((bool, drawAll))
((bool, drawCurrent))
((bool, lines))
);

View File

@ -70,9 +70,10 @@ inline bool ObjectIDIsValid(ObjectID id) { return (id >= 0); }
struct sCinemaSplineNode
{
Shareable<float> x, y, z, t;
Shareable<float> px, py, pz, rx, ry, rz, t;
public:
sCinemaSplineNode(float px, float py, float pz) : x(px), y(py), z(pz), t(0.0f) {}
sCinemaSplineNode(float _px, float _py, float _pz, float _rx, float _ry, float _rz)
: px(_px), py(_py), pz(_pz), rx(_rx), ry(_ry), rz(_rz), t(0.0f) {}
sCinemaSplineNode() {}
void SetTime(float _t) { t = _t; }
};
@ -81,39 +82,26 @@ SHAREABLE_STRUCT(sCinemaSplineNode);
struct sCinemaPath
{
Shareable<std::vector<AtlasMessage::sCinemaSplineNode> > nodes;
Shareable<float> duration, x, y, z;
Shareable<std::wstring> name;
Shareable<float> duration, timescale;
Shareable<int> mode, growth, change, style; // change == switch point
sCinemaPath(float rx, float ry, float rz) : x(rx), y(ry), z(rz),
mode(0), style(0), change(0), growth(0), duration(0) {}
sCinemaPath() : x(0), y(0), z(0), mode(0), style(0),
change(0), growth(0), duration(0) {}
sCinemaPath(const std::wstring& _name) : name(_name), mode(0), style(0), change(0), growth(0), duration(0), timescale(1) {}
sCinemaPath() : mode(0), style(0), change(0), growth(0), duration(0), timescale(1) {}
AtlasMessage::sCinemaPath operator-(const AtlasMessage::sCinemaPath& path)
/*AtlasMessage::sCinemaPath operator-(const AtlasMessage::sCinemaPath& path)
{
return AtlasMessage::sCinemaPath(x - path.x, y - path.y, z - path.z);
}
AtlasMessage::sCinemaPath operator+(const AtlasMessage::sCinemaPath& path)
{
return AtlasMessage::sCinemaPath(x + path.x, y + path.y, z + path.z);
}
}*/
};
SHAREABLE_STRUCT(sCinemaPath);
struct sCinemaTrack
{
Shareable<std::wstring> name;
Shareable<float> timescale, duration;
Shareable<std::vector<AtlasMessage::sCinemaPath> > paths;
public:
sCinemaTrack(std::wstring track)
: timescale(1.f), duration(0), name(track) {}
sCinemaTrack() : timescale(1.f), duration(0) {}
};
SHAREABLE_STRUCT(sCinemaTrack);
struct eCinemaEventMode { enum { SMOOTH, SELECT, IMMEDIATE_PATH, IMMEDIATE_TRACK, RESET }; };
struct eCinemaEventMode { enum { SMOOTH, SELECT, IMMEDIATE_PATH, RESET }; };
struct sCameraInfo
{
Shareable<float> pX, pY, pZ, rX, rY, rZ; // position and rotation