Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
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.
8 : *
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.
13 : *
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/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "simulation2/system/Component.h"
21 : #include "ICmpCinemaManager.h"
22 :
23 : #include "ps/CLogger.h"
24 : #include "simulation2/components/ICmpOverlayRenderer.h"
25 : #include "simulation2/components/ICmpRangeManager.h"
26 : #include "simulation2/components/ICmpSelectable.h"
27 : #include "simulation2/components/ICmpTerritoryManager.h"
28 : #include "simulation2/MessageTypes.h"
29 : #include "simulation2/Simulation2.h"
30 :
31 :
32 12 : class CCmpCinemaManager final : public ICmpCinemaManager
33 : {
34 : public:
35 116 : static void ClassInit(CComponentManager& componentManager)
36 : {
37 116 : componentManager.SubscribeToMessageType(MT_Update);
38 116 : }
39 :
40 8 : DEFAULT_COMPONENT_ALLOCATOR(CinemaManager)
41 :
42 116 : static std::string GetSchema()
43 : {
44 116 : return "<a:component type='system'/><empty/>";
45 : }
46 :
47 4 : void Init(const CParamNode& UNUSED(paramNode)) override
48 : {
49 4 : m_Enabled = false;
50 4 : m_MapRevealed = false;
51 4 : m_ElapsedTime = fixed::Zero();
52 4 : m_TotalTime = fixed::Zero();
53 4 : m_CurrentPathElapsedTime = fixed::Zero();
54 4 : }
55 :
56 4 : void Deinit() override
57 : {
58 4 : }
59 :
60 0 : void Serialize(ISerializer& serializer) override
61 : {
62 0 : serializer.Bool("Enabled", m_Enabled);
63 0 : serializer.NumberFixed_Unbounded("ElapsedTime", m_ElapsedTime);
64 0 : serializer.NumberFixed_Unbounded("CurrentPathElapsedTime", m_CurrentPathElapsedTime);
65 0 : serializer.Bool("MapRevealed", m_MapRevealed);
66 :
67 0 : serializer.NumberU32_Unbounded("NumberOfPaths", m_Paths.size());
68 0 : for (const std::pair<const CStrW, CCinemaPath>& it : m_Paths)
69 0 : SerializePath(it.second, serializer);
70 :
71 0 : serializer.NumberU32_Unbounded("NumberOfQueuedPaths", m_PathQueue.size());
72 0 : for (const CCinemaPath& path : m_PathQueue)
73 0 : serializer.String("PathName", path.GetName(), 1, 128);
74 0 : }
75 :
76 0 : void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserializer) override
77 : {
78 0 : deserializer.Bool("Enabled", m_Enabled);
79 0 : deserializer.NumberFixed_Unbounded("ElapsedTime", m_ElapsedTime);
80 0 : deserializer.NumberFixed_Unbounded("CurrentPathElapsedTime", m_CurrentPathElapsedTime);
81 0 : deserializer.Bool("MapRevealed", m_MapRevealed);
82 :
83 0 : uint32_t numberOfPaths = 0;
84 0 : deserializer.NumberU32_Unbounded("NumberOfPaths", numberOfPaths);
85 0 : for (uint32_t i = 0; i < numberOfPaths; ++i)
86 : {
87 0 : CCinemaPath path = DeserializePath(deserializer);
88 0 : m_Paths[path.GetName()] = path;
89 : }
90 :
91 0 : uint32_t numberOfQueuedPaths = 0;
92 0 : deserializer.NumberU32_Unbounded("NumberOfQueuedPaths", numberOfQueuedPaths);
93 0 : for (uint32_t i = 0; i < numberOfQueuedPaths; ++i)
94 : {
95 0 : CStrW pathName;
96 0 : deserializer.String("PathName", pathName, 1, 128);
97 0 : ENSURE(HasPath(pathName));
98 0 : AddCinemaPathToQueue(pathName);
99 : }
100 :
101 0 : if (!m_PathQueue.empty())
102 : {
103 0 : m_PathQueue.front().m_TimeElapsed = m_CurrentPathElapsedTime.ToFloat();
104 0 : m_PathQueue.front().Validate();
105 : }
106 :
107 0 : SetEnabled(m_Enabled);
108 0 : }
109 :
110 100 : void HandleMessage(const CMessage& msg, bool UNUSED(global)) override
111 : {
112 100 : switch (msg.GetType())
113 : {
114 100 : case MT_Update:
115 : {
116 100 : const CMessageUpdate &msgData = static_cast<const CMessageUpdate&>(msg);
117 100 : if (!m_Enabled)
118 0 : break;
119 :
120 100 : m_ElapsedTime += msgData.turnLength;
121 100 : m_CurrentPathElapsedTime += msgData.turnLength;
122 100 : if (m_CurrentPathElapsedTime >= m_PathQueue.front().GetDuration())
123 : {
124 2 : CMessageCinemaPathEnded msgCinemaPathEnded(m_PathQueue.front().GetName());
125 1 : m_PathQueue.pop_front();
126 1 : GetSimContext().GetComponentManager().PostMessage(SYSTEM_ENTITY, msgCinemaPathEnded);
127 1 : m_CurrentPathElapsedTime = fixed::Zero();
128 :
129 1 : if (!m_PathQueue.empty())
130 0 : m_PathQueue.front().Reset();
131 : }
132 :
133 100 : if (m_ElapsedTime >= m_TotalTime)
134 : {
135 1 : m_CurrentPathElapsedTime = fixed::Zero();
136 1 : m_ElapsedTime = fixed::Zero();
137 1 : m_TotalTime = fixed::Zero();
138 1 : SetEnabled(false);
139 1 : GetSimContext().GetComponentManager().PostMessage(SYSTEM_ENTITY, CMessageCinemaQueueEnded());
140 : }
141 :
142 100 : break;
143 : }
144 0 : default:
145 0 : break;
146 : }
147 100 : }
148 :
149 2 : void AddPath(const CCinemaPath& path) override
150 : {
151 2 : if (m_Paths.find(path.GetName()) != m_Paths.end())
152 : {
153 0 : LOGWARNING("Path with name '%s' already exists", path.GetName().ToUTF8());
154 0 : return;
155 : }
156 2 : m_Paths[path.GetName()] = path;
157 : }
158 :
159 1 : void AddCinemaPathToQueue(const CStrW& name) override
160 : {
161 1 : if (!HasPath(name))
162 : {
163 0 : LOGWARNING("Path with name '%s' doesn't exist", name.ToUTF8());
164 0 : return;
165 : }
166 1 : m_PathQueue.push_back(m_Paths[name]);
167 :
168 1 : if (m_PathQueue.size() == 1)
169 1 : m_PathQueue.front().Reset();
170 1 : m_TotalTime += m_Paths[name].GetDuration();
171 : }
172 :
173 1 : void Play() override
174 : {
175 1 : SetEnabled(true);
176 1 : }
177 :
178 0 : void Stop() override
179 : {
180 0 : SetEnabled(false);
181 0 : }
182 :
183 6 : bool HasPath(const CStrW& name) const override
184 : {
185 6 : return m_Paths.find(name) != m_Paths.end();
186 : }
187 :
188 0 : void ClearQueue() override
189 : {
190 0 : m_PathQueue.clear();
191 0 : }
192 :
193 1 : void DeletePath(const CStrW& name) override
194 : {
195 1 : if (!HasPath(name))
196 : {
197 0 : LOGWARNING("Path with name '%s' doesn't exist", name.ToUTF8());
198 0 : return;
199 : }
200 2 : m_PathQueue.remove_if([name](const CCinemaPath& path) { return path.GetName() == name; });
201 1 : m_Paths.erase(name);
202 : }
203 :
204 0 : const std::map<CStrW, CCinemaPath>& GetPaths() const override
205 : {
206 0 : return m_Paths;
207 : }
208 :
209 0 : void SetPaths(const std::map<CStrW, CCinemaPath>& newPaths) override
210 : {
211 0 : m_Paths = newPaths;
212 0 : }
213 :
214 0 : const std::list<CCinemaPath>& GetQueue() const override
215 : {
216 0 : return m_PathQueue;
217 : }
218 :
219 102 : bool IsEnabled() const override
220 : {
221 102 : return m_Enabled;
222 : }
223 :
224 2 : void SetEnabled(bool enabled) override
225 : {
226 2 : if (m_PathQueue.empty() && enabled)
227 0 : enabled = false;
228 :
229 2 : if (m_Enabled == enabled)
230 0 : return;
231 :
232 2 : CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext().GetSystemEntity());
233 2 : CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSimContext().GetSystemEntity());
234 2 : if (cmpRangeManager)
235 : {
236 0 : if (enabled)
237 0 : m_MapRevealed = cmpRangeManager->GetLosRevealAll(-1);
238 : // TODO: improve m_MapRevealed state and without fade in
239 0 : cmpRangeManager->SetLosRevealAll(-1, enabled);
240 : }
241 2 : if (cmpTerritoryManager)
242 0 : cmpTerritoryManager->SetVisibility(!enabled);
243 2 : ICmpSelectable::SetOverrideVisibility(!enabled);
244 2 : ICmpOverlayRenderer::SetOverrideVisibility(!enabled);
245 :
246 2 : m_Enabled = enabled;
247 : }
248 :
249 0 : void PlayQueue(const float deltaRealTime, CCamera* camera) override
250 : {
251 0 : if (m_PathQueue.empty())
252 0 : return;
253 0 : m_PathQueue.front().Play(deltaRealTime, camera);
254 : }
255 :
256 : private:
257 :
258 0 : void SerializePath(const CCinemaPath& path, ISerializer& serializer)
259 : {
260 0 : const CCinemaData* data = path.GetData();
261 :
262 0 : serializer.String("PathName", data->m_Name, 1, 128);
263 0 : serializer.String("PathOrientation", data->m_Orientation, 1, 128);
264 0 : serializer.String("PathMode", data->m_Mode, 1, 128);
265 0 : serializer.String("PathStyle", data->m_Style, 1, 128);
266 0 : serializer.NumberFixed_Unbounded("PathTimescale", data->m_Timescale);
267 0 : serializer.Bool("LookAtTarget", data->m_LookAtTarget);
268 :
269 0 : serializer.NumberU32("NumberOfNodes", path.GetAllNodes().size(), 1, MAX_SPLINE_NODES);
270 0 : const std::vector<SplineData>& nodes = path.GetAllNodes();
271 0 : for (size_t i = 0; i < nodes.size(); ++i)
272 : {
273 0 : if (i > 0)
274 0 : serializer.NumberFixed_Unbounded("NodeDeltaTime", nodes[i - 1].Distance);
275 : else
276 0 : serializer.NumberFixed_Unbounded("NodeDeltaTime", fixed::Zero());
277 :
278 0 : serializer.NumberFixed_Unbounded("PositionX", nodes[i].Position.X);
279 0 : serializer.NumberFixed_Unbounded("PositionY", nodes[i].Position.Y);
280 0 : serializer.NumberFixed_Unbounded("PositionZ", nodes[i].Position.Z);
281 :
282 0 : serializer.NumberFixed_Unbounded("RotationX", nodes[i].Rotation.X);
283 0 : serializer.NumberFixed_Unbounded("RotationY", nodes[i].Rotation.Y);
284 0 : serializer.NumberFixed_Unbounded("RotationZ", nodes[i].Rotation.Z);
285 : }
286 :
287 0 : if (!data->m_LookAtTarget)
288 0 : return;
289 :
290 0 : const std::vector<SplineData>& targetNodes = path.GetTargetSpline().GetAllNodes();
291 0 : serializer.NumberU32("NumberOfTargetNodes", targetNodes.size(), 1, MAX_SPLINE_NODES);
292 0 : for (size_t i = 0; i < targetNodes.size(); ++i)
293 : {
294 0 : if (i > 0)
295 0 : serializer.NumberFixed_Unbounded("NodeDeltaTime", targetNodes[i - 1].Distance);
296 : else
297 0 : serializer.NumberFixed_Unbounded("NodeDeltaTime", fixed::Zero());
298 0 : serializer.NumberFixed_Unbounded("PositionX", targetNodes[i].Position.X);
299 0 : serializer.NumberFixed_Unbounded("PositionY", targetNodes[i].Position.Y);
300 0 : serializer.NumberFixed_Unbounded("PositionZ", targetNodes[i].Position.Z);
301 : }
302 : }
303 :
304 0 : CCinemaPath DeserializePath(IDeserializer& deserializer)
305 : {
306 0 : CCinemaData data;
307 :
308 0 : deserializer.String("PathName", data.m_Name, 1, 128);
309 0 : deserializer.String("PathOrientation", data.m_Orientation, 1, 128);
310 0 : deserializer.String("PathMode", data.m_Mode, 1, 128);
311 0 : deserializer.String("PathStyle", data.m_Style, 1, 128);
312 0 : deserializer.NumberFixed_Unbounded("PathTimescale", data.m_Timescale);
313 0 : deserializer.Bool("LookAtTarget", data.m_LookAtTarget);
314 :
315 0 : TNSpline pathSpline, targetSpline;
316 0 : uint32_t numberOfNodes = 0;
317 0 : deserializer.NumberU32("NumberOfNodes", numberOfNodes, 1, MAX_SPLINE_NODES);
318 0 : for (uint32_t j = 0; j < numberOfNodes; ++j)
319 : {
320 0 : SplineData node;
321 0 : deserializer.NumberFixed_Unbounded("NodeDeltaTime", node.Distance);
322 :
323 0 : deserializer.NumberFixed_Unbounded("PositionX", node.Position.X);
324 0 : deserializer.NumberFixed_Unbounded("PositionY", node.Position.Y);
325 0 : deserializer.NumberFixed_Unbounded("PositionZ", node.Position.Z);
326 :
327 0 : deserializer.NumberFixed_Unbounded("RotationX", node.Rotation.X);
328 0 : deserializer.NumberFixed_Unbounded("RotationY", node.Rotation.Y);
329 0 : deserializer.NumberFixed_Unbounded("RotationZ", node.Rotation.Z);
330 :
331 0 : pathSpline.AddNode(node.Position, node.Rotation, node.Distance);
332 : }
333 :
334 0 : if (data.m_LookAtTarget)
335 : {
336 0 : uint32_t numberOfTargetNodes = 0;
337 0 : deserializer.NumberU32("NumberOfTargetNodes", numberOfTargetNodes, 1, MAX_SPLINE_NODES);
338 0 : for (uint32_t j = 0; j < numberOfTargetNodes; ++j)
339 : {
340 0 : SplineData node;
341 0 : deserializer.NumberFixed_Unbounded("NodeDeltaTime", node.Distance);
342 :
343 0 : deserializer.NumberFixed_Unbounded("PositionX", node.Position.X);
344 0 : deserializer.NumberFixed_Unbounded("PositionY", node.Position.Y);
345 0 : deserializer.NumberFixed_Unbounded("PositionZ", node.Position.Z);
346 :
347 0 : targetSpline.AddNode(node.Position, CFixedVector3D(), node.Distance);
348 : }
349 : }
350 :
351 0 : return CCinemaPath(data, pathSpline, targetSpline);
352 : }
353 :
354 : bool m_Enabled;
355 : std::map<CStrW, CCinemaPath> m_Paths;
356 : std::list<CCinemaPath> m_PathQueue;
357 :
358 : // States before playing
359 : bool m_MapRevealed;
360 :
361 : fixed m_ElapsedTime;
362 : fixed m_TotalTime;
363 : fixed m_CurrentPathElapsedTime;
364 : };
365 :
366 119 : REGISTER_COMPONENT_TYPE(CinemaManager)
|