LCOV - code coverage report
Current view: top level - source/tools/atlas/GameInterface - View.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 233 0.0 %
Date: 2023-01-19 00:18:29 Functions: 0 45 0.0 %

          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 "View.h"
      21             : 
      22             : #include "ActorViewer.h"
      23             : #include "GameLoop.h"
      24             : #include "Messages.h"
      25             : #include "SimState.h"
      26             : 
      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"
      48             : 
      49             : extern void (*Atlas_GLSwapBuffers)(void* context);
      50             : 
      51             : extern int g_xres, g_yres;
      52             : 
      53             : //////////////////////////////////////////////////////////////////////////
      54             : 
      55           0 : void AtlasView::SetParam(const std::wstring& UNUSED(name), bool UNUSED(value))
      56             : {
      57           0 : }
      58             : 
      59           0 : void AtlasView::SetParam(const std::wstring& UNUSED(name), const AtlasMessage::Color& UNUSED(value))
      60             : {
      61           0 : }
      62             : 
      63           0 : void AtlasView::SetParam(const std::wstring& UNUSED(name), const std::wstring& UNUSED(value))
      64             : {
      65           0 : }
      66             : 
      67           0 : void AtlasView::SetParam(const std::wstring& UNUSED(name), int UNUSED(value))
      68             : {
      69           0 : }
      70             : 
      71             : //////////////////////////////////////////////////////////////////////////
      72             : 
      73           0 : AtlasViewActor::AtlasViewActor()
      74           0 : : m_SpeedMultiplier(1.f), m_ActorViewer(new ActorViewer())
      75             : {
      76           0 : }
      77             : 
      78           0 : AtlasViewActor::~AtlasViewActor()
      79             : {
      80           0 :     delete m_ActorViewer;
      81           0 : }
      82             : 
      83           0 : void AtlasViewActor::Update(float realFrameLength)
      84             : {
      85           0 :     m_ActorViewer->Update(realFrameLength * m_SpeedMultiplier, realFrameLength);
      86           0 : }
      87             : 
      88           0 : void AtlasViewActor::Render()
      89             : {
      90           0 :     SViewPort vp = { 0, 0, g_xres, g_yres };
      91           0 :     CCamera& camera = GetCamera();
      92           0 :     camera.SetViewPort(vp);
      93           0 :     camera.SetPerspectiveProjection(2.f, 512.f, DEGTORAD(20.f));
      94           0 :     camera.UpdateFrustum();
      95             : 
      96           0 :     m_ActorViewer->Render();
      97           0 :     Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);
      98           0 : }
      99             : 
     100           0 : CCamera& AtlasViewActor::GetCamera()
     101             : {
     102           0 :     return m_Camera;
     103             : }
     104             : 
     105           0 : CSimulation2* AtlasViewActor::GetSimulation2()
     106             : {
     107           0 :     return m_ActorViewer->GetSimulation2();
     108             : }
     109             : 
     110           0 : entity_id_t AtlasViewActor::GetEntityId(AtlasMessage::ObjectID UNUSED(obj))
     111             : {
     112           0 :     return m_ActorViewer->GetEntity();
     113             : }
     114             : 
     115           0 : bool AtlasViewActor::WantsHighFramerate()
     116             : {
     117           0 :     if (m_SpeedMultiplier != 0.f)
     118           0 :         return true;
     119             : 
     120           0 :     return false;
     121             : }
     122             : 
     123           0 : void AtlasViewActor::SetEnabled(bool enabled)
     124             : {
     125           0 :     m_ActorViewer->SetEnabled(enabled);
     126           0 : }
     127             : 
     128           0 : void AtlasViewActor::SetSpeedMultiplier(float speedMultiplier)
     129             : {
     130           0 :     m_SpeedMultiplier = speedMultiplier;
     131           0 : }
     132             : 
     133           0 : ActorViewer& AtlasViewActor::GetActorViewer()
     134             : {
     135           0 :     return *m_ActorViewer;
     136             : }
     137             : 
     138           0 : void AtlasViewActor::SetParam(const std::wstring& name, bool value)
     139             : {
     140           0 :     if (name == L"wireframe")
     141           0 :         g_Renderer.GetSceneRenderer().SetModelRenderMode(value ? WIREFRAME : SOLID);
     142           0 :     else if (name == L"walk")
     143           0 :         m_ActorViewer->SetWalkEnabled(value);
     144           0 :     else if (name == L"ground")
     145           0 :         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           0 :     else if (name == L"shadows")
     152           0 :         m_ActorViewer->ToggleShadows();
     153           0 :     else if (name == L"stats")
     154           0 :         m_ActorViewer->SetStatsEnabled(value);
     155           0 :     else if (name == L"bounding_box")
     156           0 :         m_ActorViewer->SetBoundingBoxesEnabled(value);
     157           0 :     else if (name == L"axes_marker")
     158           0 :         m_ActorViewer->SetAxesMarkerEnabled(value);
     159           0 : }
     160             : 
     161           0 : void AtlasViewActor::SetParam(const std::wstring& name, int value)
     162             : {
     163           0 :     if (name == L"prop_points")
     164           0 :         m_ActorViewer->SetPropPointsMode(value);
     165           0 : }
     166             : 
     167           0 : void AtlasViewActor::SetParam(const std::wstring& UNUSED(name), const AtlasMessage::Color& UNUSED(value))
     168             : {
     169           0 : }
     170             : 
     171             : 
     172             : //////////////////////////////////////////////////////////////////////////
     173             : 
     174           0 : AtlasViewGame::AtlasViewGame()
     175           0 :     : m_SpeedMultiplier(0.f), m_IsTesting(false), m_DrawMoveTool(false)
     176             : {
     177           0 :     ENSURE(g_Game);
     178           0 : }
     179             : 
     180           0 : AtlasViewGame::~AtlasViewGame()
     181             : {
     182           0 :     for (const std::pair<const std::wstring, SimState*>& p : m_SavedStates)
     183           0 :         delete p.second;
     184           0 : }
     185             : 
     186           0 : CSimulation2* AtlasViewGame::GetSimulation2()
     187             : {
     188           0 :     return g_Game->GetSimulation2();
     189             : }
     190             : 
     191           0 : void AtlasViewGame::Update(float realFrameLength)
     192             : {
     193           0 :     const float actualFrameLength = realFrameLength * m_SpeedMultiplier;
     194             : 
     195             :     // Clean up any entities destroyed during UI message processing
     196           0 :     g_Game->GetSimulation2()->FlushDestroyedEntities();
     197             : 
     198           0 :     if (m_SpeedMultiplier == 0.f)
     199             :     {
     200             :         // Update unit interpolation
     201           0 :         g_Game->Interpolate(0.0, realFrameLength);
     202             :     }
     203             :     else
     204             :     {
     205             :         // Update the whole world
     206             :         // (Tell the game update not to interpolate graphics - we'll do that
     207             :         // ourselves)
     208           0 :         g_Game->Update(actualFrameLength, false);
     209             : 
     210             :         // Interpolate the graphics - we only want to do this once per visual frame,
     211             :         // not in every call to g_Game->Update
     212           0 :         g_Game->Interpolate(actualFrameLength, realFrameLength);
     213             :     }
     214             : 
     215             :     // Run sound idle tasks every frame.
     216           0 :     if (g_SoundManager)
     217           0 :         g_SoundManager->IdleTask();
     218             : 
     219             :     // Cinematic motion should be independent of simulation update, so we can
     220             :     // preview the cinematics by themselves
     221           0 :     g_Game->GetView()->GetCinema()->Update(realFrameLength);
     222           0 : }
     223             : 
     224           0 : void AtlasViewGame::Render()
     225             : {
     226           0 :     if (!g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer())
     227           0 :         return;
     228             : 
     229           0 :     SViewPort vp = { 0, 0, g_xres, g_yres };
     230           0 :     CCamera& camera = GetCamera();
     231           0 :     camera.SetViewPort(vp);
     232           0 :     camera.SetProjectionFromCamera(*g_Game->GetView()->GetCamera());
     233           0 :     camera.UpdateFrustum();
     234             : 
     235           0 :     g_Renderer.RenderFrame(false);
     236           0 :     Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);
     237             :     // In case of atlas the device's present will do only internal stuff
     238             :     // without calling a real backbuffer swap.
     239           0 :     g_VideoMode.GetBackendDevice()->Present();
     240             : }
     241             : 
     242           0 : void AtlasViewGame::DrawCinemaPathTool()
     243             : {
     244           0 :     if (!m_DrawMoveTool)
     245           0 :         return;
     246             : 
     247           0 :     const CVector3D focus = m_MoveTool;
     248           0 :     const CVector3D camera = GetCamera().GetOrientation().GetTranslation();
     249           0 :     const float scale = (focus - camera).Length();
     250           0 :     const float axisLength = scale / 10.0f;
     251           0 :     const float lineWidth = scale / 1e3f;
     252             : 
     253           0 :     g_Renderer.GetDebugRenderer().DrawLine(
     254           0 :         focus, focus + CVector3D(axisLength, 0, 0),
     255           0 :         CColor(1.0f, 0.0f, 0.0f, 1.0f), lineWidth, false);
     256           0 :     g_Renderer.GetDebugRenderer().DrawLine(
     257           0 :         focus, focus + CVector3D(0, axisLength, 0),
     258           0 :         CColor(0.0f, 1.0f, 0.0f, 1.0f), lineWidth, false);
     259           0 :     g_Renderer.GetDebugRenderer().DrawLine(
     260           0 :         focus, focus + CVector3D(0, 0, axisLength),
     261           0 :         CColor(0.0f, 0.0f, 1.0f, 1.0f), lineWidth, false);
     262             : }
     263             : 
     264           0 : void AtlasViewGame::DrawOverlays(CCanvas2D& canvas)
     265             : {
     266           0 :     if (m_Bandbox.left >= m_Bandbox.right || m_Bandbox.top >= m_Bandbox.bottom)
     267           0 :         return;
     268             : 
     269             :     const std::vector<CVector2D> outerPoints = {
     270           0 :         m_Bandbox.TopLeft() + CVector2D(-1.0f, -1.0f),
     271           0 :         m_Bandbox.TopRight() + CVector2D(1.0f, -1.0f),
     272           0 :         m_Bandbox.BottomRight() + CVector2D(1.0f, 1.0f),
     273           0 :         m_Bandbox.BottomLeft() + CVector2D(-1.0f, 1.0f),
     274           0 :         m_Bandbox.TopLeft() + CVector2D(-1.0f, -1.0f)
     275           0 :     };
     276           0 :     canvas.DrawLine(outerPoints, 1.5f, CColor(0.0f, 0.0f, 0.0f, 1.0f));
     277             : 
     278             :     const std::vector<CVector2D> innerPoints = {
     279           0 :         m_Bandbox.TopLeft(),
     280           0 :         m_Bandbox.TopRight(),
     281           0 :         m_Bandbox.BottomRight(),
     282           0 :         m_Bandbox.BottomLeft(),
     283           0 :         m_Bandbox.TopLeft()
     284           0 :     };
     285           0 :     canvas.DrawLine(innerPoints, 1.5f, CColor(1.0f, 1.0f, 1.0f, 1.0f));
     286             : }
     287             : 
     288           0 : void AtlasViewGame::SetParam(const std::wstring& name, bool value)
     289             : {
     290           0 :     if (name == L"priorities")
     291           0 :         g_Renderer.GetSceneRenderer().SetDisplayTerrainPriorities(value);
     292           0 :     else if (name == L"movetool")
     293           0 :         m_DrawMoveTool = value;
     294           0 : }
     295             : 
     296           0 : void AtlasViewGame::SetParam(const std::wstring& name, float value)
     297             : {
     298           0 :     if (name == L"movetool_x")
     299           0 :         m_MoveTool.X = value;
     300           0 :     else if (name == L"movetool_y")
     301           0 :         m_MoveTool.Y = value;
     302           0 :     else if (name == L"movetool_z")
     303           0 :         m_MoveTool.Z = value;
     304           0 : }
     305             : 
     306           0 : void AtlasViewGame::SetParam(const std::wstring& name, const std::wstring& value)
     307             : {
     308           0 :     if (name == L"passability")
     309             :     {
     310           0 :         m_DisplayPassability = CStrW(value).ToUTF8();
     311             : 
     312           0 :         CmpPtr<ICmpPathfinder> cmpPathfinder(*GetSimulation2(), SYSTEM_ENTITY);
     313           0 :         if (cmpPathfinder)
     314             :         {
     315           0 :             if (!value.empty())
     316           0 :                 cmpPathfinder->SetAtlasOverlay(true, cmpPathfinder->GetPassabilityClass(m_DisplayPassability));
     317             :             else
     318           0 :                 cmpPathfinder->SetAtlasOverlay(false);
     319             :         }
     320             :     }
     321           0 : }
     322             : 
     323           0 : CCamera& AtlasViewGame::GetCamera()
     324             : {
     325           0 :     return *g_Game->GetView()->GetCamera();
     326             : }
     327             : 
     328           0 : bool AtlasViewGame::WantsHighFramerate()
     329             : {
     330           0 :     if (g_Game->GetView()->GetCinema()->IsPlaying())
     331           0 :         return true;
     332             : 
     333           0 :     if (m_SpeedMultiplier != 0.f)
     334           0 :         return true;
     335             : 
     336           0 :     return false;
     337             : }
     338             : 
     339           0 : void AtlasViewGame::SetSpeedMultiplier(float speed)
     340             : {
     341           0 :     m_SpeedMultiplier = speed;
     342           0 : }
     343             : 
     344           0 : void AtlasViewGame::SetTesting(bool testing)
     345             : {
     346           0 :     m_IsTesting = testing;
     347             :     // If we're testing, particles should freeze on pause (like in-game), otherwise they keep going
     348           0 :     CmpPtr<ICmpParticleManager> cmpParticleManager(*GetSimulation2(), SYSTEM_ENTITY);
     349           0 :     if (cmpParticleManager)
     350           0 :         cmpParticleManager->SetUseSimTime(m_IsTesting);
     351           0 : }
     352             : 
     353           0 : void AtlasViewGame::SaveState(const std::wstring& label)
     354             : {
     355           0 :     delete m_SavedStates[label]; // in case it already exists
     356           0 :     m_SavedStates[label] = SimState::Freeze();
     357           0 : }
     358             : 
     359           0 : void AtlasViewGame::RestoreState(const std::wstring& label)
     360             : {
     361           0 :     SimState* simState = m_SavedStates[label];
     362           0 :     if (! simState)
     363           0 :         return;
     364             : 
     365           0 :     simState->Thaw();
     366             : }
     367             : 
     368           0 : std::wstring AtlasViewGame::DumpState(bool binary)
     369             : {
     370           0 :     std::stringstream stream;
     371           0 :     if (binary)
     372             :     {
     373           0 :         if (! g_Game->GetSimulation2()->SerializeState(stream))
     374           0 :             return L"(internal error)";
     375             :         // We can't return raw binary data, because we want to handle it with wxJS which
     376             :         // doesn't like \0 bytes in strings, so return it as hex
     377             :         static const char digits[] = "0123456789abcdef";
     378           0 :         std::string str = stream.str();
     379           0 :         std::wstring ret;
     380           0 :         ret.reserve(str.length()*3);
     381           0 :         for (size_t i = 0; i < str.length(); ++i)
     382             :         {
     383           0 :             ret += digits[(unsigned char)str[i] >> 4];
     384           0 :             ret += digits[(unsigned char)str[i] & 0x0f];
     385           0 :             ret += ' ';
     386             :         }
     387           0 :         return ret;
     388             :     }
     389             :     else
     390             :     {
     391           0 :         if (! g_Game->GetSimulation2()->DumpDebugState(stream))
     392           0 :             return L"(internal error)";
     393           0 :         return wstring_from_utf8(stream.str());
     394             :     }
     395             : }
     396             : 
     397           0 : void AtlasViewGame::SetBandbox(bool visible, float x0, float y0, float x1, float y1)
     398             : {
     399           0 :     if (visible)
     400             :     {
     401             :         // Make sure corners are arranged in correct order
     402           0 :         if (x0 > x1)
     403           0 :             std::swap(x0, x1);
     404           0 :         if (y0 > y1)
     405           0 :             std::swap(y0, y1);
     406             : 
     407           0 :         m_Bandbox = CRect(x0, y0, x1, y1);
     408             :     }
     409             :     else
     410             :     {
     411           0 :         m_Bandbox = CRect{};
     412             :     }
     413           0 : }
     414             : 
     415             : //////////////////////////////////////////////////////////////////////////
     416             : 
     417             : AtlasViewNone* view_None = NULL;
     418             : AtlasViewGame* view_Game = NULL;
     419             : AtlasViewActor* view_Actor = NULL;
     420             : 
     421           0 : AtlasView::~AtlasView()
     422             : {
     423           0 : }
     424             : 
     425           0 : AtlasView* AtlasView::GetView(int /*eRenderView*/ view)
     426             : {
     427           0 :     switch (view)
     428             :     {
     429           0 :     case AtlasMessage::eRenderView::NONE:  return AtlasView::GetView_None();
     430           0 :     case AtlasMessage::eRenderView::GAME:  return AtlasView::GetView_Game();
     431           0 :     case AtlasMessage::eRenderView::ACTOR: return AtlasView::GetView_Actor();
     432           0 :     default:
     433           0 :         debug_warn(L"Invalid view type");
     434           0 :         return AtlasView::GetView_None();
     435             :     }
     436             : }
     437             : 
     438           0 : AtlasView* AtlasView::GetView_None()
     439             : {
     440           0 :     if (! view_None)
     441           0 :         view_None = new AtlasViewNone();
     442           0 :     return view_None;
     443             : }
     444             : 
     445           0 : AtlasViewGame* AtlasView::GetView_Game()
     446             : {
     447           0 :     if (! view_Game)
     448           0 :         view_Game = new AtlasViewGame();
     449           0 :     return view_Game;
     450             : }
     451             : 
     452           0 : AtlasViewActor* AtlasView::GetView_Actor()
     453             : {
     454           0 :     if (! view_Actor)
     455           0 :         view_Actor = new AtlasViewActor();
     456           0 :     return view_Actor;
     457             : }
     458             : 
     459           0 : void AtlasView::DestroyViews()
     460             : {
     461           0 :     delete view_None; view_None = NULL;
     462           0 :     delete view_Game; view_Game = NULL;
     463           0 :     delete view_Actor; view_Actor = NULL;
     464           0 : }

Generated by: LCOV version 1.13