Re: Change Entity property

#13
I've got this from entity:propertyset, as already i mentioned many times before, but this is complex enough to analyze for me :( :

Code: Select all

SmartScriptTable DoResolveScriptTable(IScriptTable* pTable, const string& key, string& outKey)
{
ScriptAnyValue value;

string token;
int pos = 0;
token = key.Tokenize(".", pos);
pTable->GetValueAny(token, value);

token = key.Tokenize(".", pos);
if (token.empty())
return 0;

string nextToken = key.Tokenize(".", pos);
while (nextToken.empty() == false)
{
if (value.type != ANY_TTABLE)
return 0;
ScriptAnyValue temp;
value.table->GetValueAny(token, temp);
value = temp;
token = nextToken;
nextToken = token.Tokenize(".", pos);
}
outKey = token;
return value.table;
}

SmartScriptTable ResolveScriptTable(IScriptTable* pTable, const char* sKey, bool bPerArchetype, string& outKey)
{
string key = bPerArchetype ? "Properties." : "PropertiesInstance.";
key += sKey;
return DoResolveScriptTable(pTable, key, outKey);
}

void OnEntityEvent(IEntity* pEntity, SEntityEvent& event) {}

virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
{
CFlowEntityNodeBase::ProcessEvent(event, pActInfo);

switch (event)
{
case eFE_Activate:
OnActivate(pActInfo);
break;

case eFE_Initialize:
OnInitialize(pActInfo);
break;
}
}

void OnInitialize(SActivationInfo* pActInfo)
{
if (!s_propertyHistoryMap.empty())
{
for (const TPropertyHistoryMap::value_type& entry : s_propertyHistoryMap)
{
const EntityId entityId = entry.first.entityId;
if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entityId))
{
if (IScriptTable* pScriptTable = pEntity->GetScriptTable())
{
const string& propertyName = entry.first.propertyName;
const bool bPerArchetype = entry.first.bPerArchetype;
const ScriptAnyValue& value = entry.second;

string realPropertyName;
if (SmartScriptTable smartScriptTable = ResolveScriptTable(pScriptTable, propertyName, bPerArchetype, realPropertyName))
{
smartScriptTable->SetValueAny(realPropertyName.c_str(), value);

if (pScriptTable->HaveValue("OnPropertyChange"))
{
Script::CallMethod(pScriptTable, "OnPropertyChange");
}
}
}
}
}
s_propertyHistoryMap.clear();
}
}

void OnActivate(SActivationInfo* pActInfo)
{
IEntity* pEntity = GetEntity();
if (!pEntity)
return;

const bool bValuePort = IsPortActive(pActInfo, IN_SMARTNAME);
const bool bTriggerPort = IsPortActive(pActInfo, IN_ACTIVATE);

if (bValuePort || bTriggerPort)
{
if (IScriptTable* pScriptTable = pEntity->GetScriptTable())
{
const string inputPropertyName = GetPortString(pActInfo, IN_SMARTNAME);
const string inputPropertyValue = GetPortString(pActInfo, IN_VALUE);
const bool bPerArchetype = GetPortBool(pActInfo, IN_PERARCHETYPE);

const size_t pos = inputPropertyName.find_first_of(":");
string plainPropertyName = inputPropertyName.substr(pos + 1, inputPropertyName.length() - pos);
plainPropertyName.replace(":", ".");

string realPropertyName;
SmartScriptTable smartScriptTable = ResolveScriptTable(pScriptTable, plainPropertyName.c_str(), bPerArchetype, realPropertyName);

if (!smartScriptTable)
{
GameWarning("[flow] CFlowNode_EntitySetProperty: Cannot resolve property '%s' in entity '%s'",
plainPropertyName.c_str(), pEntity->GetName());
ActivateOutput(pActInfo, 0, 0);
return;
}

if (gEnv->IsEditor())
{
SPropertyKey propertyKey = { pEntity->GetId(), plainPropertyName, bPerArchetype };
TPropertyHistoryMap::iterator it = s_propertyHistoryMap.find(propertyKey);

if (it == s_propertyHistoryMap.end())
{
ScriptAnyValue anyValue;
const ScriptVarType scriptVarType = smartScriptTable->GetValueType(realPropertyName.c_str());

if (scriptVarType == svtObject)
{
if (GetColorAnyValue(smartScriptTable, realPropertyName, anyValue))
{
s_propertyHistoryMap[propertyKey] = anyValue;
}
}
else if (scriptVarType == svtBool || scriptVarType == svtNumber || scriptVarType == svtString)
{
if (smartScriptTable->GetValueAny(realPropertyName.c_str(), anyValue))
{
s_propertyHistoryMap[propertyKey] = anyValue;
}
}
}
}

ChangeProperty(pActInfo, pEntity, pScriptTable, smartScriptTable, realPropertyName, inputPropertyValue);
}
}
}

void ChangeProperty(SActivationInfo* pActInfo, IEntity* pEntity, IScriptTable* pScriptTable, SmartScriptTable& smartScriptTable, const string& propertyName, const char* propertyValue)
{
const ScriptVarType scriptVarType = smartScriptTable->GetValueType(propertyName.c_str());

switch (scriptVarType)
{
case svtNull:
{
GameWarning("[flow] CFlowNode_EntitySetProperty: Cannot resolve property '%s' in entity '%s' -> Creating",
propertyName.c_str(), pEntity->GetName());
ActivateOutput(pActInfo, 0, 0);
break;
}

case svtNumber:
{
float fValue = (float)atof(propertyValue);
smartScriptTable->SetValue(propertyName.c_str(), fValue);
if (pScriptTable->HaveValue("OnPropertyChange"))
Script::CallMethod(pScriptTable, "OnPropertyChange");
break;
}

case svtBool:
{
float fValue = (float)atof(propertyValue);
bool bVal = (bool)(fabs(fValue) > 0.001f);
smartScriptTable->SetValue(propertyName.c_str(), bVal);
if (pScriptTable->HaveValue("OnPropertyChange"))
Script::CallMethod(pScriptTable, "OnPropertyChange");
break;
}

case svtString:
{
smartScriptTable->SetValue(propertyName.c_str(), propertyValue);
if (pScriptTable->HaveValue("OnPropertyChange"))
Script::CallMethod(pScriptTable, "OnPropertyChange");
break;
}

case svtObject:
{
if (IsColorType(propertyName))
{
Vec3 clrValue(ZERO);
StringToVec3(propertyValue, clrValue);

smartScriptTable->SetValue(propertyName.c_str(), clrValue);
if (pScriptTable->HaveValue("OnPropertyChange"))
Script::CallMethod(pScriptTable, "OnPropertyChange");
}
break;
}
}
}

inline bool IsColorType(const string& propertyName) const
{
return strcmp(propertyName.substr(propertyName.find_last_of(".") + 1, 3), "clr") == 0;
}

void StringToVec3(const string& propertyValue, Vec3& clrValue) const
{
const size_t commaFirst = propertyValue.find_first_of(",");
const size_t commaLast = propertyValue.find_last_of(",");

clrValue.x = (float)atof(propertyValue.substr(0, commaFirst));
clrValue.y = (float)atof(propertyValue.substr(commaFirst + 1, commaLast));
clrValue.z = (float)atof(propertyValue.substr(commaLast + 1, propertyValue.length()));

clrValue.x = fabs(min(clrValue.x, 255.f));
clrValue.y = fabs(min(clrValue.y, 255.f));
clrValue.z = fabs(min(clrValue.z, 255.f));

clrValue = clrValue / 255.f;
}

bool GetColorAnyValue(SmartScriptTable& smartScriptTable, const string& propertyName, ScriptAnyValue& outAnyValue) const
{
if (IsColorType(propertyName))
{
if (smartScriptTable->GetValueAny(propertyName.c_str(), outAnyValue))
{
if (outAnyValue.CopyFromTableToXYZ(outAnyValue.vec3.x, outAnyValue.vec3.y, outAnyValue.vec3.z))
{
outAnyValue.type = ANY_TVECTOR;
return true;
}
}
}
return false;
}

virtual void GetMemoryUsage(ICrySizer* s) const
{
s->Add(*this);
}

private:
struct SPropertyKey
{
inline bool operator<(const SPropertyKey& other) const
{
return (entityId < other.entityId) || (entityId == other.entityId
&& ((bPerArchetype < other.bPerArchetype)
|| (bPerArchetype == other.bPerArchetype && propertyName < other.propertyName))
);
}
EntityId entityId;
string propertyName;
bool bPerArchetype;
};

typedef std::map<SPropertyKey, ScriptAnyValue> TPropertyHistoryMap;
static TPropertyHistoryMap s_propertyHistoryMap;

//////////////////////////////////////////////////////////////////////////

Who is online

Users browsing this forum: No registered users and 3 guests