#include "precompiled.h" #include "View.h" #include "ActorViewer.h" #include "GameLoop.h" #include "Messages.h" #include "SimState.h" #include "graphics/CinemaTrack.h" #include "graphics/GameView.h" #include "graphics/SColor.h" #include "graphics/UnitManager.h" #include "lib/timer.h" #include "ps/Game.h" #include "ps/GameSetup/GameSetup.h" #include "ps/World.h" #include "renderer/Renderer.h" #include "simulation/Simulation.h" extern void (*Atlas_GLSwapBuffers)(void* context); extern int g_xres, g_yres; ////////////////////////////////////////////////////////////////////////// void View::SetParam(const std::wstring& UNUSED(name), bool UNUSED(value)) { } void View::SetParam(const std::wstring& UNUSED(name), const AtlasMessage::Colour& UNUSED(value)) { } ////////////////////////////////////////////////////////////////////////// ViewActor::ViewActor() : m_SpeedMultiplier(1.f), m_ActorViewer(new ActorViewer()) { } ViewActor::~ViewActor() { delete m_ActorViewer; } void ViewActor::Update(float frameLength) { m_ActorViewer->Update(frameLength * m_SpeedMultiplier); } void ViewActor::Render() { SViewPort vp = { 0, 0, g_xres, g_yres }; CCamera& camera = GetCamera(); camera.SetViewPort(&vp); camera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV); camera.UpdateFrustum(); m_ActorViewer->Render(); Atlas_GLSwapBuffers((void*)g_GameLoop->glCanvas); } CCamera& ViewActor::GetCamera() { return m_Camera; } CUnit* ViewActor::GetUnit(AtlasMessage::ObjectID UNUSED(id)) { return m_ActorViewer->GetUnit(); } bool ViewActor::WantsHighFramerate() { if (m_SpeedMultiplier != 0.f && m_ActorViewer->HasAnimation()) return true; return false; } void ViewActor::SetSpeedMultiplier(float speed) { m_SpeedMultiplier = speed; } ActorViewer& ViewActor::GetActorViewer() { return *m_ActorViewer; } void ViewActor::SetParam(const std::wstring& name, bool value) { if (name == L"wireframe") g_Renderer.SetModelRenderMode(value ? WIREFRAME : SOLID); else if (name == L"walk") m_ActorViewer->SetWalkEnabled(value); else if (name == L"ground") m_ActorViewer->SetGroundEnabled(value); else if (name == L"shadows") m_ActorViewer->SetShadowsEnabled(value); else if (name == L"stats") m_ActorViewer->SetStatsEnabled(value); } void ViewActor::SetParam(const std::wstring& name, const AtlasMessage::Colour& value) { if (name == L"background") { m_ActorViewer->SetBackgroundColour(SColor4ub(value.r, value.g, value.b, 255)); } } ////////////////////////////////////////////////////////////////////////// namespace AtlasMessage { extern void AtlasRenderSelection(); } template static void delete_pair_2nd(std::pair v) { delete v.second; } ViewGame::ViewGame() : m_SpeedMultiplier(0.f) { debug_assert(g_Game); } ViewGame::~ViewGame() { std::for_each(m_SavedStates.begin(), m_SavedStates.end(), delete_pair_2nd); } void ViewGame::Update(float frameLength) { float actualFrameLength = frameLength * m_SpeedMultiplier; if (m_SpeedMultiplier == 0.f) { // Update unit interpolation g_Game->GetSimulation()->Interpolate(0.0); } else { // Update the whole world // (Tell the game update not to interpolate graphics - we'll do that // ourselves) bool ok = g_Game->Update(actualFrameLength, false); if (! ok) { // Whoops, we're trying to go faster than the simulation can manage. // It's probably better to run at the right sim rate, at the expense // of framerate, so let's try simulating a few more times. double t = get_time(); while (!ok && get_time() < t + 0.1) // don't go much worse than 10fps { ok = g_Game->Update(0.0, false); // don't add on any extra sim time } } // Interpolate the graphics - we only want to do this once per visual frame, // not in every call to g_Game->Update g_Game->GetSimulation()->Interpolate(actualFrameLength); // If we still couldn't keep up, just drop the sim rate instead of building // up a (potentially very large) backlog of required updates g_Game->GetSimulation()->DiscardMissedUpdates(); } // Cinematic motion should be independent of simulation update, so we can // preview the cinematics by themselves if (g_Game->GetView()->GetCinema()->IsPlaying()) g_Game->GetView()->GetCinema()->Update(frameLength); } void ViewGame::Render() { SViewPort vp = { 0, 0, g_xres, g_yres }; CCamera& camera = GetCamera(); camera.SetViewPort(&vp); camera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV); camera.UpdateFrustum(); ::Render(); AtlasMessage::AtlasRenderSelection(); Atlas_GLSwapBuffers((void*)g_GameLoop->glCanvas); } CCamera& ViewGame::GetCamera() { return *g_Game->GetView()->GetCamera(); } CUnit* ViewGame::GetUnit(AtlasMessage::ObjectID id) { return g_Game->GetWorld()->GetUnitManager().FindByID(id); } bool ViewGame::WantsHighFramerate() { if (g_Game->GetView()->GetCinema()->IsPlaying()) return true; if (m_SpeedMultiplier != 0.f) return true; return false; } void ViewGame::SetSpeedMultiplier(float speed) { m_SpeedMultiplier = speed; } void ViewGame::SaveState(const std::wstring& label, bool onlyEntities) { delete m_SavedStates[label]; // in case it already exists m_SavedStates[label] = SimState::Freeze(onlyEntities); } void ViewGame::RestoreState(const std::wstring& label) { SimState* simState = m_SavedStates[label]; if (! simState) return; simState->Thaw(); } ////////////////////////////////////////////////////////////////////////// ViewNone* view_None = NULL; ViewGame* view_Game = NULL; ViewActor* view_Actor = NULL; View::~View() { } View* View::GetView(int /*eRenderView*/ view) { switch (view) { case AtlasMessage::eRenderView::NONE: return View::GetView_None(); case AtlasMessage::eRenderView::GAME: return View::GetView_Game(); case AtlasMessage::eRenderView::ACTOR: return View::GetView_Actor(); default: debug_warn("Invalid view type"); return View::GetView_None(); } } View* View::GetView_None() { if (! view_None) view_None = new ViewNone(); return view_None; } ViewGame* View::GetView_Game() { if (! view_Game) view_Game = new ViewGame(); return view_Game; } ViewActor* View::GetView_Actor() { if (! view_Actor) view_Actor = new ViewActor(); return view_Actor; } void View::DestroyViews() { delete view_None; view_None = NULL; delete view_Game; view_Game = NULL; delete view_Actor; view_Actor = NULL; }