Update ifdef condition for MCST-LCC compiler (E2K)
[0ad.git] / source / tools / atlas / GameInterface / View.cpp
blob06c8262c6de32b9ec43f6eaa7471aff1e7e4a7db
1 /* Copyright (C) 2022 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 "View.h"
22 #include "ActorViewer.h"
23 #include "GameLoop.h"
24 #include "Messages.h"
25 #include "SimState.h"
27 #include "graphics/Canvas2D.h"
28 #include "graphics/CinemaManager.h"
29 #include "graphics/GameView.h"
30 #include "graphics/ParticleManager.h"
31 #include "graphics/UnitManager.h"
32 #include "lib/timer.h"
33 #include "lib/utf8.h"
34 #include "maths/MathUtil.h"
35 #include "ps/Game.h"
36 #include "ps/GameSetup/GameSetup.h"
37 #include "ps/VideoMode.h"
38 #include "ps/World.h"
39 #include "renderer/backend/IDevice.h"
40 #include "renderer/DebugRenderer.h"
41 #include "renderer/Renderer.h"
42 #include "renderer/SceneRenderer.h"
43 #include "simulation2/components/ICmpObstructionManager.h"
44 #include "simulation2/components/ICmpParticleManager.h"
45 #include "simulation2/components/ICmpPathfinder.h"
46 #include "simulation2/Simulation2.h"
47 #include "soundmanager/ISoundManager.h"
49 extern void (*Atlas_GLSwapBuffers)(void* context);
51 extern int g_xres, g_yres;
53 //////////////////////////////////////////////////////////////////////////
55 void AtlasView::SetParam(const std::wstring& UNUSED(name), bool UNUSED(value))
59 void AtlasView::SetParam(const std::wstring& UNUSED(name), const AtlasMessage::Color& UNUSED(value))
63 void AtlasView::SetParam(const std::wstring& UNUSED(name), const std::wstring& UNUSED(value))
67 void AtlasView::SetParam(const std::wstring& UNUSED(name), int UNUSED(value))
71 //////////////////////////////////////////////////////////////////////////
73 AtlasViewActor::AtlasViewActor()
74 : m_SpeedMultiplier(1.f), m_ActorViewer(new ActorViewer())
78 AtlasViewActor::~AtlasViewActor()
80 delete m_ActorViewer;
83 void AtlasViewActor::Update(float realFrameLength)
85 m_ActorViewer->Update(realFrameLength * m_SpeedMultiplier, realFrameLength);
88 void AtlasViewActor::Render()
90 SViewPort vp = { 0, 0, g_xres, g_yres };
91 CCamera& camera = GetCamera();
92 camera.SetViewPort(vp);
93 camera.SetPerspectiveProjection(2.f, 512.f, DEGTORAD(20.f));
94 camera.UpdateFrustum();
96 m_ActorViewer->Render();
97 Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);
100 CCamera& AtlasViewActor::GetCamera()
102 return m_Camera;
105 CSimulation2* AtlasViewActor::GetSimulation2()
107 return m_ActorViewer->GetSimulation2();
110 entity_id_t AtlasViewActor::GetEntityId(AtlasMessage::ObjectID UNUSED(obj))
112 return m_ActorViewer->GetEntity();
115 bool AtlasViewActor::WantsHighFramerate()
117 if (m_SpeedMultiplier != 0.f)
118 return true;
120 return false;
123 void AtlasViewActor::SetEnabled(bool enabled)
125 m_ActorViewer->SetEnabled(enabled);
128 void AtlasViewActor::SetSpeedMultiplier(float speedMultiplier)
130 m_SpeedMultiplier = speedMultiplier;
133 ActorViewer& AtlasViewActor::GetActorViewer()
135 return *m_ActorViewer;
138 void AtlasViewActor::SetParam(const std::wstring& name, bool value)
140 if (name == L"wireframe")
141 g_Renderer.GetSceneRenderer().SetModelRenderMode(value ? WIREFRAME : SOLID);
142 else if (name == L"walk")
143 m_ActorViewer->SetWalkEnabled(value);
144 else if (name == L"ground")
145 m_ActorViewer->SetGroundEnabled(value);
146 // TODO: this causes corruption of WaterManager's global state
147 // which should be asociated with terrain or simulation instead
148 // see http://trac.wildfiregames.com/ticket/2692
149 //else if (name == L"water")
150 //m_ActorViewer->SetWaterEnabled(value);
151 else if (name == L"shadows")
152 m_ActorViewer->ToggleShadows();
153 else if (name == L"stats")
154 m_ActorViewer->SetStatsEnabled(value);
155 else if (name == L"bounding_box")
156 m_ActorViewer->SetBoundingBoxesEnabled(value);
157 else if (name == L"axes_marker")
158 m_ActorViewer->SetAxesMarkerEnabled(value);
161 void AtlasViewActor::SetParam(const std::wstring& name, int value)
163 if (name == L"prop_points")
164 m_ActorViewer->SetPropPointsMode(value);
167 void AtlasViewActor::SetParam(const std::wstring& UNUSED(name), const AtlasMessage::Color& UNUSED(value))
172 //////////////////////////////////////////////////////////////////////////
174 AtlasViewGame::AtlasViewGame()
175 : m_SpeedMultiplier(0.f), m_IsTesting(false), m_DrawMoveTool(false)
177 ENSURE(g_Game);
180 AtlasViewGame::~AtlasViewGame()
182 for (const std::pair<const std::wstring, SimState*>& p : m_SavedStates)
183 delete p.second;
186 CSimulation2* AtlasViewGame::GetSimulation2()
188 return g_Game->GetSimulation2();
191 void AtlasViewGame::Update(float realFrameLength)
193 const float actualFrameLength = realFrameLength * m_SpeedMultiplier;
195 // Clean up any entities destroyed during UI message processing
196 g_Game->GetSimulation2()->FlushDestroyedEntities();
198 if (m_SpeedMultiplier == 0.f)
200 // Update unit interpolation
201 g_Game->Interpolate(0.0, realFrameLength);
203 else
205 // Update the whole world
206 // (Tell the game update not to interpolate graphics - we'll do that
207 // ourselves)
208 g_Game->Update(actualFrameLength, false);
210 // Interpolate the graphics - we only want to do this once per visual frame,
211 // not in every call to g_Game->Update
212 g_Game->Interpolate(actualFrameLength, realFrameLength);
215 // Run sound idle tasks every frame.
216 if (g_SoundManager)
217 g_SoundManager->IdleTask();
219 // Cinematic motion should be independent of simulation update, so we can
220 // preview the cinematics by themselves
221 g_Game->GetView()->GetCinema()->Update(realFrameLength);
224 void AtlasViewGame::Render()
226 SViewPort vp = { 0, 0, g_xres, g_yres };
227 CCamera& camera = GetCamera();
228 camera.SetViewPort(vp);
229 camera.SetProjectionFromCamera(*g_Game->GetView()->GetCamera());
230 camera.UpdateFrustum();
232 g_Renderer.RenderFrame(false);
233 Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);
234 // In case of atlas the device's present will do only internal stuff
235 // without calling a real backbuffer swap.
236 g_VideoMode.GetBackendDevice()->Present();
239 void AtlasViewGame::DrawCinemaPathTool()
241 if (!m_DrawMoveTool)
242 return;
244 const CVector3D focus = m_MoveTool;
245 const CVector3D camera = GetCamera().GetOrientation().GetTranslation();
246 const float scale = (focus - camera).Length();
247 const float axisLength = scale / 10.0f;
248 const float lineWidth = scale / 1e3f;
250 g_Renderer.GetDebugRenderer().DrawLine(
251 focus, focus + CVector3D(axisLength, 0, 0),
252 CColor(1.0f, 0.0f, 0.0f, 1.0f), lineWidth, false);
253 g_Renderer.GetDebugRenderer().DrawLine(
254 focus, focus + CVector3D(0, axisLength, 0),
255 CColor(0.0f, 1.0f, 0.0f, 1.0f), lineWidth, false);
256 g_Renderer.GetDebugRenderer().DrawLine(
257 focus, focus + CVector3D(0, 0, axisLength),
258 CColor(0.0f, 0.0f, 1.0f, 1.0f), lineWidth, false);
261 void AtlasViewGame::DrawOverlays(CCanvas2D& canvas)
263 if (m_Bandbox.left >= m_Bandbox.right || m_Bandbox.top >= m_Bandbox.bottom)
264 return;
266 const std::vector<CVector2D> outerPoints = {
267 m_Bandbox.TopLeft() + CVector2D(-1.0f, -1.0f),
268 m_Bandbox.TopRight() + CVector2D(1.0f, -1.0f),
269 m_Bandbox.BottomRight() + CVector2D(1.0f, 1.0f),
270 m_Bandbox.BottomLeft() + CVector2D(-1.0f, 1.0f),
271 m_Bandbox.TopLeft() + CVector2D(-1.0f, -1.0f)
273 canvas.DrawLine(outerPoints, 1.5f, CColor(0.0f, 0.0f, 0.0f, 1.0f));
275 const std::vector<CVector2D> innerPoints = {
276 m_Bandbox.TopLeft(),
277 m_Bandbox.TopRight(),
278 m_Bandbox.BottomRight(),
279 m_Bandbox.BottomLeft(),
280 m_Bandbox.TopLeft()
282 canvas.DrawLine(innerPoints, 1.5f, CColor(1.0f, 1.0f, 1.0f, 1.0f));
285 void AtlasViewGame::SetParam(const std::wstring& name, bool value)
287 if (name == L"priorities")
288 g_Renderer.GetSceneRenderer().SetDisplayTerrainPriorities(value);
289 else if (name == L"movetool")
290 m_DrawMoveTool = value;
293 void AtlasViewGame::SetParam(const std::wstring& name, float value)
295 if (name == L"movetool_x")
296 m_MoveTool.X = value;
297 else if (name == L"movetool_y")
298 m_MoveTool.Y = value;
299 else if (name == L"movetool_z")
300 m_MoveTool.Z = value;
303 void AtlasViewGame::SetParam(const std::wstring& name, const std::wstring& value)
305 if (name == L"passability")
307 m_DisplayPassability = CStrW(value).ToUTF8();
309 CmpPtr<ICmpPathfinder> cmpPathfinder(*GetSimulation2(), SYSTEM_ENTITY);
310 if (cmpPathfinder)
312 if (!value.empty())
313 cmpPathfinder->SetAtlasOverlay(true, cmpPathfinder->GetPassabilityClass(m_DisplayPassability));
314 else
315 cmpPathfinder->SetAtlasOverlay(false);
320 CCamera& AtlasViewGame::GetCamera()
322 return *g_Game->GetView()->GetCamera();
325 bool AtlasViewGame::WantsHighFramerate()
327 if (g_Game->GetView()->GetCinema()->IsPlaying())
328 return true;
330 if (m_SpeedMultiplier != 0.f)
331 return true;
333 return false;
336 void AtlasViewGame::SetSpeedMultiplier(float speed)
338 m_SpeedMultiplier = speed;
341 void AtlasViewGame::SetTesting(bool testing)
343 m_IsTesting = testing;
344 // If we're testing, particles should freeze on pause (like in-game), otherwise they keep going
345 CmpPtr<ICmpParticleManager> cmpParticleManager(*GetSimulation2(), SYSTEM_ENTITY);
346 if (cmpParticleManager)
347 cmpParticleManager->SetUseSimTime(m_IsTesting);
350 void AtlasViewGame::SaveState(const std::wstring& label)
352 delete m_SavedStates[label]; // in case it already exists
353 m_SavedStates[label] = SimState::Freeze();
356 void AtlasViewGame::RestoreState(const std::wstring& label)
358 SimState* simState = m_SavedStates[label];
359 if (! simState)
360 return;
362 simState->Thaw();
365 std::wstring AtlasViewGame::DumpState(bool binary)
367 std::stringstream stream;
368 if (binary)
370 if (! g_Game->GetSimulation2()->SerializeState(stream))
371 return L"(internal error)";
372 // We can't return raw binary data, because we want to handle it with wxJS which
373 // doesn't like \0 bytes in strings, so return it as hex
374 static const char digits[] = "0123456789abcdef";
375 std::string str = stream.str();
376 std::wstring ret;
377 ret.reserve(str.length()*3);
378 for (size_t i = 0; i < str.length(); ++i)
380 ret += digits[(unsigned char)str[i] >> 4];
381 ret += digits[(unsigned char)str[i] & 0x0f];
382 ret += ' ';
384 return ret;
386 else
388 if (! g_Game->GetSimulation2()->DumpDebugState(stream))
389 return L"(internal error)";
390 return wstring_from_utf8(stream.str());
394 void AtlasViewGame::SetBandbox(bool visible, float x0, float y0, float x1, float y1)
396 if (visible)
398 // Make sure corners are arranged in correct order
399 if (x0 > x1)
400 std::swap(x0, x1);
401 if (y0 > y1)
402 std::swap(y0, y1);
404 m_Bandbox = CRect(x0, y0, x1, y1);
406 else
408 m_Bandbox = CRect{};
412 //////////////////////////////////////////////////////////////////////////
414 AtlasViewNone* view_None = NULL;
415 AtlasViewGame* view_Game = NULL;
416 AtlasViewActor* view_Actor = NULL;
418 AtlasView::~AtlasView()
422 AtlasView* AtlasView::GetView(int /*eRenderView*/ view)
424 switch (view)
426 case AtlasMessage::eRenderView::NONE: return AtlasView::GetView_None();
427 case AtlasMessage::eRenderView::GAME: return AtlasView::GetView_Game();
428 case AtlasMessage::eRenderView::ACTOR: return AtlasView::GetView_Actor();
429 default:
430 debug_warn(L"Invalid view type");
431 return AtlasView::GetView_None();
435 AtlasView* AtlasView::GetView_None()
437 if (! view_None)
438 view_None = new AtlasViewNone();
439 return view_None;
442 AtlasViewGame* AtlasView::GetView_Game()
444 if (! view_Game)
445 view_Game = new AtlasViewGame();
446 return view_Game;
449 AtlasViewActor* AtlasView::GetView_Actor()
451 if (! view_Actor)
452 view_Actor = new AtlasViewActor();
453 return view_Actor;
456 void AtlasView::DestroyViews()
458 delete view_None; view_None = NULL;
459 delete view_Game; view_Game = NULL;
460 delete view_Actor; view_Actor = NULL;