fix request-attack broken by rP19247
[0ad.git] / source / graphics / CinemaPath.cpp
blob9421014e5afdc165ecc616c1a5a82ba6e4a5a3cf
1 /* Copyright (C) 2017 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "CinemaPath.h"
22 #include <sstream>
23 #include <string>
25 #include "Camera.h"
26 #include "CinemaManager.h"
27 #include "GameView.h"
28 #include "gui/CGUI.h"
29 #include "gui/GUIManager.h"
30 #include "gui/IGUIObject.h"
31 #include "lib/ogl.h"
32 #include "maths/MathUtil.h"
33 #include "maths/Quaternion.h"
34 #include "maths/Vector3D.h"
35 #include "maths/Vector4D.h"
36 #include "ps/CLogger.h"
37 #include "ps/CStr.h"
38 #include "ps/Game.h"
39 #include "renderer/Renderer.h"
42 CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline, const TNSpline& targetSpline)
43 : CCinemaData(data), TNSpline(spline), m_TargetSpline(targetSpline), m_TimeElapsed(0.f)
45 // Calculate curves by nodes
46 BuildSpline();
47 m_TargetSpline.BuildSpline();
49 if (m_Orientation == L"target")
51 m_LookAtTarget = true;
52 ENSURE(!m_TargetSpline.GetAllNodes().empty());
55 // Set distortion mode and style
56 if (data.m_Mode == L"ease_in")
57 DistModePtr = &CCinemaPath::EaseIn;
58 else if (data.m_Mode == L"ease_out")
59 DistModePtr = &CCinemaPath::EaseOut;
60 else if (data.m_Mode == L"ease_inout")
61 DistModePtr = &CCinemaPath::EaseInOut;
62 else if (data.m_Mode == L"ease_outin")
63 DistModePtr = &CCinemaPath::EaseOutIn;
64 else
66 LOGWARNING("Cinematic mode not found for '%s'", data.m_Mode.ToUTF8().c_str());
67 DistModePtr = &CCinemaPath::EaseInOut;
70 if (data.m_Style == L"default")
71 DistStylePtr = &CCinemaPath::EaseDefault;
72 else if (data.m_Style == L"growth")
73 DistStylePtr = &CCinemaPath::EaseGrowth;
74 else if (data.m_Style == L"expo")
75 DistStylePtr = &CCinemaPath::EaseExpo;
76 else if (data.m_Style == L"circle")
77 DistStylePtr = &CCinemaPath::EaseCircle;
78 else if (data.m_Style == L"sine")
79 DistStylePtr = &CCinemaPath::EaseSine;
80 else
82 LOGWARNING("Cinematic style not found for '%s'", data.m_Style.ToUTF8().c_str());
83 DistStylePtr = &CCinemaPath::EaseDefault;
87 CVector3D CCinemaPath::GetNodePosition(const int index) const
89 return Node[index].Position;
92 fixed CCinemaPath::GetNodeDuration(const int index) const
94 return Node[index].Distance;
97 fixed CCinemaPath::GetDuration() const
99 return MaxDistance;
102 float CCinemaPath::GetNodeFraction() const
104 return (m_TimeElapsed - m_PreviousNodeTime) / Node[m_CurrentNode].Distance.ToFloat();
107 float CCinemaPath::GetElapsedTime() const
109 return m_TimeElapsed;
112 const CStrW& CCinemaPath::GetName() const
114 return m_Name;
117 void CCinemaPath::SetTimescale(fixed scale)
119 m_Timescale = scale;
122 void CCinemaPath::MoveToPointAt(float t, float nodet, const CVector3D& startRotation, CCamera* camera) const
124 t = (this->*DistModePtr)(t);
126 CVector3D pos = GetPosition(t);
128 if (m_LookAtTarget)
130 if (m_TimeElapsed <= m_TargetSpline.MaxDistance.ToFloat())
131 camera->LookAt(pos, m_TargetSpline.GetPosition(m_TimeElapsed / m_TargetSpline.MaxDistance.ToFloat()), CVector3D(0, 1, 0));
132 else
133 camera->LookAt(pos, m_TargetSpline.GetAllNodes().back().Position, CVector3D(0, 1, 0));
135 else
137 CVector3D nodeRotation = Node[m_CurrentNode + 1].Rotation;
138 CQuaternion start, end;
139 start.FromEulerAngles(DEGTORAD(startRotation.X), DEGTORAD(startRotation.Y), DEGTORAD(startRotation.Z));
140 end.FromEulerAngles(DEGTORAD(nodeRotation.X), DEGTORAD(nodeRotation.Y), DEGTORAD(nodeRotation.Z));
141 start.Slerp(start, end, nodet);
143 camera->m_Orientation.SetIdentity();
144 camera->m_Orientation.Rotate(start);
145 camera->m_Orientation.Translate(pos);
147 camera->UpdateFrustum();
150 // Distortion mode functions
151 float CCinemaPath::EaseIn(float t) const
153 return (this->*DistStylePtr)(t);
156 float CCinemaPath::EaseOut(float t) const
158 return 1.0f - EaseIn(1.0f-t);
161 float CCinemaPath::EaseInOut(float t) const
163 if (t < m_Switch)
164 return EaseIn(1.0f/m_Switch * t) * m_Switch;
165 return EaseOut(1.0f/m_Switch * (t-m_Switch)) * m_Switch + m_Switch;
168 float CCinemaPath::EaseOutIn(float t) const
170 if (t < m_Switch)
171 return EaseOut(1.0f/m_Switch * t) * m_Switch;
172 return EaseIn(1.0f/m_Switch * (t-m_Switch)) * m_Switch + m_Switch;
175 // Distortion style functions
176 float CCinemaPath::EaseDefault(float t) const
178 return t;
181 float CCinemaPath::EaseGrowth(float t) const
183 return pow(t, m_Growth);
186 float CCinemaPath::EaseExpo(float t) const
188 if (t == 0)
189 return t;
190 return powf(m_Growth, 10*(t-1.0f));
193 float CCinemaPath::EaseCircle(float t) const
195 t = -(sqrt(1.0f - t*t) - 1.0f);
196 if (m_GrowthCount > 1.0f)
198 --m_GrowthCount;
199 return (this->*DistStylePtr)(t);
201 return t;
204 float CCinemaPath::EaseSine(float t) const
206 t = 1.0f - cos(t * (float)M_PI/2);
207 if (m_GrowthCount > 1.0f)
209 --m_GrowthCount;
210 return (this->*DistStylePtr)(t);
212 return t;
215 const CCinemaData* CCinemaPath::GetData() const
217 return CCinemaData::GetData();
220 bool CCinemaPath::Validate()
222 if (m_TimeElapsed > GetDuration().ToFloat() || m_TimeElapsed < 0.0f)
223 return false;
225 // Find current node and past "node time"
226 float previousTime = 0.0f, cumulation = 0.0f;
228 // Ignore the last node, since it is a blank (node time values are shifted down one from interface)
229 for (size_t i = 0; i < Node.size() - 1; ++i)
231 cumulation += Node[i].Distance.ToFloat();
232 if (m_TimeElapsed <= cumulation)
234 m_PreviousNodeTime = previousTime;
235 m_PreviousRotation = Node[i].Rotation;
236 m_CurrentNode = i; // We're moving toward this next node, so use its rotation
237 return true;
239 previousTime += Node[i].Distance.ToFloat();
241 debug_warn("validation of cinema path is wrong\n");
242 return false;
245 bool CCinemaPath::Play(const float deltaRealTime, CCamera* camera)
247 m_TimeElapsed += m_Timescale.ToFloat() * deltaRealTime;
248 if (!Validate())
249 return false;
251 MoveToPointAt(m_TimeElapsed / GetDuration().ToFloat(), GetNodeFraction(), m_PreviousRotation, camera);
252 return true;
255 bool CCinemaPath::Empty() const
257 return Node.empty();
260 void CCinemaPath::Reset()
262 m_TimeElapsed = 0.0f;
265 fixed CCinemaPath::GetTimescale() const
267 return m_Timescale;
270 const TNSpline& CCinemaPath::GetTargetSpline() const
272 return m_TargetSpline;