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:
parent
f18a6981bb
commit
c229b46ac2
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -315,6 +315,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
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.
|
||||||
* Returns VIS_HIDDEN if the entity doesn't exist or is not in the world.
|
* Returns VIS_HIDDEN if the entity doesn't exist or is not in the world.
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user