1
0
forked from 0ad/0ad

Move visibility component activation check to C++. Patch by Itms.

This improves performance quite a lot because it avoids a huge number of
calls from C++ to JS. Check the ticket for performance measurements.
Refs #2913

This was SVN commit r16337.
This commit is contained in:
Yves 2015-02-14 17:13:50 +00:00
parent f18a6981bb
commit c229b46ac2
6 changed files with 41 additions and 25 deletions

View File

@ -21,32 +21,27 @@ Visibility.prototype.Init = function()
this.alwaysVisible = this.template.AlwaysVisible == "true"; this.alwaysVisible = this.template.AlwaysVisible == "true";
this.preview = this.template.Preview == "true"; this.preview = this.template.Preview == "true";
this.activated = false;
if (this.preview) if (this.preview)
this.activated = true; this.SetActivated(true);
}; };
/** /**
* If this function returns true, the range manager will call the GetVisibility function * Sets the range manager scriptedVisibility flag for this entity.
* instead of computing the visibility.
*/ */
Visibility.prototype.IsActivated = function() Visibility.prototype.SetActivated = function(status)
{ {
return this.activated; let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
cmpRangeManager.ActivateScriptedVisibility(this.entity, status);
}; };
/** /**
* This function is called if IsActivated returns true. * This function is called if the range manager scriptedVisibility flag is set to true for this entity.
* If so, the return value supersedes the visibility computed by the range manager. * If so, the return value supersedes the visibility computed by the range manager.
* isVisible: true if the entity is in the vision range of a unit, false otherwise * isVisible: true if the entity is in the vision range of a unit, false otherwise
* isExplored: true if the entity is in explored territory, false otherwise * isExplored: true if the entity is in explored territory, false otherwise
*/ */
Visibility.prototype.GetVisibility = function(player, isVisible, isExplored) Visibility.prototype.GetVisibility = function(player, isVisible, isExplored)
{ {
if (!this.activated)
warn("The Visibility component was asked to provide a superseding visibility while not activated, this should not happen");
if (this.preview) if (this.preview)
{ {
// For the owner only, mock the "RetainInFog" behaviour // For the owner only, mock the "RetainInFog" behaviour

View File

@ -174,7 +174,7 @@ static std::map<entity_id_t, EntityParabolicRangeOutline> ParabolicRangesOutline
*/ */
struct EntityData struct EntityData
{ {
EntityData() : visibilities(0), retainInFog(0), owner(-1), inWorld(0), flags(1) { } EntityData() : visibilities(0), retainInFog(0), owner(-1), inWorld(0), flags(1), scriptedVisibility(0) { }
entity_pos_t x, z; entity_pos_t x, z;
entity_pos_t visionRange; entity_pos_t visionRange;
u32 visibilities; // 2-bit visibility, per player u32 visibilities; // 2-bit visibility, per player
@ -182,9 +182,10 @@ struct EntityData
i8 owner; i8 owner;
u8 inWorld; // boolean u8 inWorld; // boolean
u8 flags; // See GetEntityFlagMask u8 flags; // See GetEntityFlagMask
u8 scriptedVisibility; // boolean, see ComputeLosVisibility
}; };
cassert(sizeof(EntityData) == 20); cassert(sizeof(EntityData) == 24);
/** /**
* Serialization helper template for Query * Serialization helper template for Query
@ -1415,6 +1416,13 @@ public:
return CLosQuerier(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); return CLosQuerier(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide);
} }
virtual void ActivateScriptedVisibility(entity_id_t ent, bool status)
{
EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
if (it != m_EntityData.end())
it->second.scriptedVisibility = status ? 1 : 0;
}
ELosVisibility ComputeLosVisibility(CEntityHandle ent, player_id_t player) ELosVisibility ComputeLosVisibility(CEntityHandle ent, player_id_t player)
{ {
// Entities not with positions in the world are never visible // Entities not with positions in the world are never visible
@ -1445,10 +1453,15 @@ public:
// Get visible regions // Get visible regions
CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide);
// Ask the Visibility component about special situations
CmpPtr<ICmpVisibility> cmpVisibility(ent); CmpPtr<ICmpVisibility> cmpVisibility(ent);
if (cmpVisibility && cmpVisibility->IsActivated())
return cmpVisibility->GetVisibility(player, los.IsVisible(i, j), los.IsExplored(i, j)); // Possibly ask the scripted Visibility component
EntityMap<EntityData>::iterator it = m_EntityData.find(ent.GetId());
if (it != m_EntityData.end())
{
if (it->second.scriptedVisibility == 1 && cmpVisibility)
return cmpVisibility->GetVisibility(player, los.IsVisible(i, j), los.IsExplored(i, j));
}
// Else, default behavior // Else, default behavior
@ -1464,8 +1477,17 @@ public:
return VIS_HIDDEN; return VIS_HIDDEN;
// Invisible if the 'retain in fog' flag is not set, and in a non-visible explored region // Invisible if the 'retain in fog' flag is not set, and in a non-visible explored region
if (!(cmpVisibility && cmpVisibility->GetRetainInFog())) // Try using the 'retainInFog' flag in m_EntityData to save a script call
return VIS_HIDDEN; if (it != m_EntityData.end())
{
if (it->second.retainInFog != 1)
return VIS_HIDDEN;
}
else
{
if (!(cmpVisibility && cmpVisibility->GetRetainInFog()))
return VIS_HIDDEN;
}
if (cmpMirage) if (cmpMirage)
return VIS_FOGGED; return VIS_FOGGED;

View File

@ -51,6 +51,7 @@ DEFINE_INTERFACE_METHOD_0("ExploreTerritories", void, ICmpRangeManager, ExploreT
DEFINE_INTERFACE_METHOD_2("SetLosRevealAll", void, ICmpRangeManager, SetLosRevealAll, player_id_t, bool) DEFINE_INTERFACE_METHOD_2("SetLosRevealAll", void, ICmpRangeManager, SetLosRevealAll, player_id_t, bool)
DEFINE_INTERFACE_METHOD_1("GetLosRevealAll", bool, ICmpRangeManager, GetLosRevealAll, player_id_t) DEFINE_INTERFACE_METHOD_1("GetLosRevealAll", bool, ICmpRangeManager, GetLosRevealAll, player_id_t)
DEFINE_INTERFACE_METHOD_5("GetElevationAdaptedRange", entity_pos_t, ICmpRangeManager, GetElevationAdaptedRange, CFixedVector3D, CFixedVector3D, entity_pos_t, entity_pos_t, entity_pos_t) DEFINE_INTERFACE_METHOD_5("GetElevationAdaptedRange", entity_pos_t, ICmpRangeManager, GetElevationAdaptedRange, CFixedVector3D, CFixedVector3D, entity_pos_t, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_2("ActivateScriptedVisibility", void, ICmpRangeManager, ActivateScriptedVisibility, entity_id_t, bool)
DEFINE_INTERFACE_METHOD_2("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, player_id_t) DEFINE_INTERFACE_METHOD_2("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, player_id_t)
DEFINE_INTERFACE_METHOD_1("RequestVisibilityUpdate", void, ICmpRangeManager, RequestVisibilityUpdate, entity_id_t) DEFINE_INTERFACE_METHOD_1("RequestVisibilityUpdate", void, ICmpRangeManager, RequestVisibilityUpdate, entity_id_t)
DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool) DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool)

View File

@ -314,6 +314,11 @@ public:
* (or other players it shares LOS with). * (or other players it shares LOS with).
*/ */
virtual CLosQuerier GetLosQuerier(player_id_t player) = 0; virtual CLosQuerier GetLosQuerier(player_id_t player) = 0;
/**
* Toggle the scripted Visibility component activation for entity ent.
*/
virtual void ActivateScriptedVisibility(entity_id_t ent, bool status) = 0;
/** /**
* Returns the visibility status of the given entity, with respect to the given player. * Returns the visibility status of the given entity, with respect to the given player.

View File

@ -30,11 +30,6 @@ class CCmpVisibilityScripted : public ICmpVisibility
public: public:
DEFAULT_SCRIPT_WRAPPER(VisibilityScripted) DEFAULT_SCRIPT_WRAPPER(VisibilityScripted)
virtual bool IsActivated()
{
return m_Script.Call<bool>("IsActivated");
}
virtual ICmpRangeManager::ELosVisibility GetVisibility(player_id_t player, bool isVisible, bool isExplored) virtual ICmpRangeManager::ELosVisibility GetVisibility(player_id_t player, bool isVisible, bool isExplored)
{ {
int visibility = m_Script.Call<int, player_id_t, bool, bool>("GetVisibility", player, isVisible, isExplored); int visibility = m_Script.Call<int, player_id_t, bool, bool>("GetVisibility", player, isVisible, isExplored);

View File

@ -35,8 +35,6 @@
class ICmpVisibility : public IComponent class ICmpVisibility : public IComponent
{ {
public: public:
virtual bool IsActivated() = 0;
virtual ICmpRangeManager::ELosVisibility GetVisibility(player_id_t player, bool isVisible, bool isExplored) = 0; virtual ICmpRangeManager::ELosVisibility GetVisibility(player_id_t player, bool isVisible, bool isExplored) = 0;
virtual bool GetRetainInFog() = 0; virtual bool GetRetainInFog() = 0;