Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -71,7 +71,7 @@ ; if false, actors won't be rendered but anything entity will be. renderactors = true - +maxcorpsecount = -1 ; When enabled, limits the number of corpses to the number specified. watereffects=true ; When disabled, force usage of the fixed pipeline water. This is faster, but really, really ugly. waterfancyeffects = false waterrealdepth = true Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -257,6 +257,14 @@ "config": "adaptivefps.session", "min": 20, "max": 100 + }, + { + "type": "number", + "label": "Max number of corpses", + "tooltip": "To save CPU workload, limits the number of corpses to display. -1 is unlimited.", + "config": "maxcorpsecount", + "min": -1, + "max": 600 } ] }, Index: source/renderer/RenderingOptions.h =================================================================== --- source/renderer/RenderingOptions.h +++ source/renderer/RenderingOptions.h @@ -105,6 +105,7 @@ OPTION(DisplayFrustum, bool); OPTION(DisplayShadowsFrustum, bool); + OPTION(MaxCorpseCount, int); OPTION(RenderActors, bool); #undef OPTION_DEFAULT_SETTER Index: source/renderer/RenderingOptions.cpp =================================================================== --- source/renderer/RenderingOptions.cpp +++ source/renderer/RenderingOptions.cpp @@ -98,6 +98,7 @@ m_DisplayFrustum = false; m_DisplayShadowsFrustum = false; m_RenderActors = true; + m_MaxCorpseCount = -1; } CRenderingOptions::~CRenderingOptions() @@ -180,6 +181,7 @@ m_GPUSkinning = true; }); + m_ConfigHooks->Setup("maxcorpsecount", m_MaxCorpseCount); m_ConfigHooks->Setup("renderactors", m_RenderActors); } Index: source/simulation2/components/CCmpDecay.cpp =================================================================== --- source/simulation2/components/CCmpDecay.cpp +++ source/simulation2/components/CCmpDecay.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -24,6 +24,7 @@ #include "ICmpPosition.h" #include "ICmpTerrain.h" +#include "ICmpUnitRenderer.h" #include "ICmpVisual.h" #include "ps/Profile.h" @@ -107,8 +108,17 @@ m_Active = false; } - if (m_Active) + if (!m_Active) + return; + + CmpPtr cmpUnitRenderer(GetSystemEntity()); + if (cmpUnitRenderer && cmpUnitRenderer->ShouldCreateCorpse()) + { GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_Interpolate, this, true); + cmpUnitRenderer->RegisterCorpse(GetEntityId()); + } + else + m_Active = false; } virtual void Deinit() Index: source/simulation2/components/CCmpUnitRenderer.cpp =================================================================== --- source/simulation2/components/CCmpUnitRenderer.cpp +++ source/simulation2/components/CCmpUnitRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,6 +35,7 @@ #include "graphics/Unit.h" #include "maths/BoundingSphere.h" #include "maths/Matrix3D.h" +#include "ps/Game.h" #include "ps/GameSetup/Config.h" #include "ps/Profile.h" #include "renderer/RenderingOptions.h" @@ -42,6 +43,9 @@ #include "tools/atlas/GameInterface/GameLoop.h" +#include +#include + /** * Efficiently(ish) renders all the units in the world. * @@ -117,6 +121,10 @@ std::vector m_Units; std::vector m_UnitTagsFree; + /** + * Contains the list of corpses currently displayed. + */ + std::deque m_Corpses; int m_FrameNumber; float m_FrameOffset; @@ -189,6 +197,27 @@ return &m_Units[tag.n - 1]; } + virtual void RegisterCorpse(entity_id_t entity) + { + const int maxCorpses = g_RenderingOptions.GetMaxCorpseCount(); + if (maxCorpses <= 0) + return; + + if (m_Corpses.size() == static_cast(maxCorpses)) + { + const entity_id_t ent = m_Corpses.front(); + GetSimContext().GetComponentManager().DestroyComponentsSoon(ent); + m_Corpses.pop_front(); + } + + m_Corpses.push_back(entity); + } + + virtual bool ShouldCreateCorpse() const + { + return g_RenderingOptions.GetMaxCorpseCount() != 0; + } + virtual tag_t AddUnit(CEntityHandle entity, CUnit* actor, const CBoundingSphere& boundsApprox, int flags) { ENSURE(actor != NULL); Index: source/simulation2/components/ICmpUnitRenderer.h =================================================================== --- source/simulation2/components/ICmpUnitRenderer.h +++ source/simulation2/components/ICmpUnitRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -52,6 +52,10 @@ virtual void RemoveUnit(tag_t tag) = 0; + virtual void RegisterCorpse(entity_id_t entity) = 0; + + virtual bool ShouldCreateCorpse() const = 0; + virtual void UpdateUnit(tag_t tag, CUnit* unit, const CBoundingSphere& boundsApprox) = 0; virtual void UpdateUnitPos(tag_t tag, bool inWorld, const CVector3D& pos0, const CVector3D& pos1) = 0; Index: source/simulation2/components/ICmpUnitRenderer.cpp =================================================================== --- source/simulation2/components/ICmpUnitRenderer.cpp +++ source/simulation2/components/ICmpUnitRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify