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.preview = this.template.Preview == "true";
this.activated = false;
if (this.preview)
this.activated = true;
this.SetActivated(true);
};
/**
* If this function returns true, the range manager will call the GetVisibility function
* instead of computing the visibility.
* Sets the range manager scriptedVisibility flag for this entity.
*/
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.
* 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
*/
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)
{
// For the owner only, mock the "RetainInFog" behaviour

View File

@ -174,7 +174,7 @@ static std::map<entity_id_t, EntityParabolicRangeOutline> ParabolicRangesOutline
*/
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 visionRange;
u32 visibilities; // 2-bit visibility, per player
@ -182,9 +182,10 @@ struct EntityData
i8 owner;
u8 inWorld; // boolean
u8 flags; // See GetEntityFlagMask
u8 scriptedVisibility; // boolean, see ComputeLosVisibility
};
cassert(sizeof(EntityData) == 20);
cassert(sizeof(EntityData) == 24);
/**
* Serialization helper template for Query
@ -1415,6 +1416,13 @@ public:
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)
{
// Entities not with positions in the world are never visible
@ -1445,10 +1453,15 @@ public:
// Get visible regions
CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide);
// Ask the Visibility component about special situations
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
@ -1464,8 +1477,17 @@ public:
return VIS_HIDDEN;
// Invisible if the 'retain in fog' flag is not set, and in a non-visible explored region
if (!(cmpVisibility && cmpVisibility->GetRetainInFog()))
return VIS_HIDDEN;
// Try using the 'retainInFog' flag in m_EntityData to save a script call
if (it != m_EntityData.end())
{
if (it->second.retainInFog != 1)
return VIS_HIDDEN;
}
else
{
if (!(cmpVisibility && cmpVisibility->GetRetainInFog()))
return VIS_HIDDEN;
}
if (cmpMirage)
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_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_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_1("RequestVisibilityUpdate", void, ICmpRangeManager, RequestVisibilityUpdate, entity_id_t)
DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool)

View File

@ -314,6 +314,11 @@ public:
* (or other players it shares LOS with).
*/
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.

View File

@ -30,11 +30,6 @@ class CCmpVisibilityScripted : public ICmpVisibility
public:
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)
{
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
{
public:
virtual bool IsActivated() = 0;
virtual ICmpRangeManager::ELosVisibility GetVisibility(player_id_t player, bool isVisible, bool isExplored) = 0;
virtual bool GetRetainInFog() = 0;