forked from bartvdbraak/blender
BGE patch 18368: Modulus (ie %) expression controller in BGE. Implement a cache for the expression for better performance.
This commit is contained in:
parent
0ac3e70160
commit
a37cec2802
@ -127,6 +127,9 @@ ret: a new object containing the result of applying operator op to val and
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case VALUE_MOD_OPERATOR:
|
||||
ret = new CFloatValue(fmod(((CIntValue *) val)->GetInt(), m_float));
|
||||
break;
|
||||
case VALUE_ADD_OPERATOR:
|
||||
ret = new CFloatValue(((CIntValue *) val)->GetInt() + m_float);
|
||||
break;
|
||||
@ -171,6 +174,9 @@ ret: a new object containing the result of applying operator op to val and
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case VALUE_MOD_OPERATOR:
|
||||
ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_float));
|
||||
break;
|
||||
case VALUE_ADD_OPERATOR:
|
||||
ret = new CFloatValue(((CFloatValue *) val)->GetFloat() + m_float);
|
||||
break;
|
||||
|
@ -175,6 +175,9 @@ void CParser::NextSym()
|
||||
case ',':
|
||||
sym = commasym; NextCh();
|
||||
break;
|
||||
case '%' :
|
||||
sym = opsym; opkind = OPmodulus; NextCh();
|
||||
break;
|
||||
case '+' :
|
||||
sym = opsym; opkind = OPplus; NextCh();
|
||||
break;
|
||||
@ -370,6 +373,7 @@ int CParser::Priority(int optorkind) {
|
||||
case OPunequal: return 3;
|
||||
case OPplus:
|
||||
case OPminus: return 4;
|
||||
case OPmodulus:
|
||||
case OPtimes:
|
||||
case OPdivide: return 5;
|
||||
}
|
||||
@ -390,6 +394,7 @@ CExpression *CParser::Ex(int i) {
|
||||
NextSym();
|
||||
e2 = Ex(i + 1);
|
||||
switch(opkind2) {
|
||||
case OPmodulus: e1 = new COperator2Expr(VALUE_MOD_OPERATOR,e1, e2); break;
|
||||
case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break;
|
||||
case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break;
|
||||
case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break;
|
||||
|
@ -49,6 +49,7 @@ private:
|
||||
}; // all kinds of symbols
|
||||
|
||||
enum optype {
|
||||
OPmodulus,
|
||||
OPplus,
|
||||
OPminus,
|
||||
OPtimes,
|
||||
|
@ -125,6 +125,9 @@ this object
|
||||
case VALUE_INT_TYPE:
|
||||
{
|
||||
switch (op) {
|
||||
case VALUE_MOD_OPERATOR:
|
||||
ret = new CIntValue (((CIntValue *) val)->GetInt() % m_int);
|
||||
break;
|
||||
case VALUE_ADD_OPERATOR:
|
||||
ret = new CIntValue (((CIntValue *) val)->GetInt() + m_int);
|
||||
break;
|
||||
@ -181,6 +184,9 @@ this object
|
||||
case VALUE_FLOAT_TYPE:
|
||||
{
|
||||
switch (op) {
|
||||
case VALUE_MOD_OPERATOR:
|
||||
ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_int));
|
||||
break;
|
||||
case VALUE_ADD_OPERATOR:
|
||||
ret = new CFloatValue (((CFloatValue *) val)->GetFloat() + m_int);
|
||||
break;
|
||||
|
@ -52,6 +52,10 @@ PyObject* cvalue_div(PyObject*v, PyObject*w)
|
||||
{
|
||||
return ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
|
||||
}
|
||||
PyObject* cvalue_mod(PyObject*v, PyObject*w)
|
||||
{
|
||||
return ((CValue*)v)->Calc(VALUE_MOD_OPERATOR,(CValue*)w);
|
||||
}
|
||||
PyObject* cvalue_neg(PyObject*v)
|
||||
{
|
||||
return ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
|
||||
@ -112,7 +116,7 @@ static PyNumberMethods cvalue_as_number = {
|
||||
(binaryfunc)cvalue_sub, /*nb_subtract*/
|
||||
(binaryfunc)cvalue_mul, /*nb_multiply*/
|
||||
(binaryfunc)cvalue_div, /*nb_divide*/
|
||||
0,//(binaryfunc)cvalue_remainder, /*nb_remainder*/
|
||||
(binaryfunc)cvalue_mod, /*nb_remainder*/
|
||||
0,//(binaryfunc)cvalue_divmod, /*nb_divmod*/
|
||||
0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
|
||||
(unaryfunc)cvalue_neg, /*nb_negative*/
|
||||
@ -257,6 +261,9 @@ STR_String CValue::op2str (VALUE_OPERATOR op)
|
||||
|
||||
STR_String opmsg;
|
||||
switch (op) {
|
||||
case VALUE_MOD_OPERATOR:
|
||||
opmsg = " % ";
|
||||
break;
|
||||
case VALUE_ADD_OPERATOR:
|
||||
opmsg = " + ";
|
||||
break;
|
||||
|
@ -75,6 +75,7 @@
|
||||
|
||||
enum VALUE_OPERATOR {
|
||||
|
||||
VALUE_MOD_OPERATOR, // %
|
||||
VALUE_ADD_OPERATOR, // +
|
||||
VALUE_SUB_OPERATOR, // -
|
||||
VALUE_MUL_OPERATOR, // *
|
||||
|
@ -49,7 +49,8 @@ SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj,
|
||||
const STR_String& exprtext,
|
||||
PyTypeObject* T)
|
||||
:SCA_IController(gameobj,T),
|
||||
m_exprText(exprtext)
|
||||
m_exprText(exprtext),
|
||||
m_exprCache(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,6 +58,8 @@ SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj,
|
||||
|
||||
SCA_ExpressionController::~SCA_ExpressionController()
|
||||
{
|
||||
if (m_exprCache)
|
||||
m_exprCache->Release();
|
||||
}
|
||||
|
||||
|
||||
@ -65,6 +68,7 @@ CValue* SCA_ExpressionController::GetReplica()
|
||||
{
|
||||
SCA_ExpressionController* replica = new SCA_ExpressionController(*this);
|
||||
replica->m_exprText = m_exprText;
|
||||
replica->m_exprCache = NULL;
|
||||
// this will copy properties and so on...
|
||||
CValue::AddDataToReplica(replica);
|
||||
|
||||
@ -72,18 +76,32 @@ CValue* SCA_ExpressionController::GetReplica()
|
||||
}
|
||||
|
||||
|
||||
// Forced deletion of precalculated expression to break reference loop
|
||||
// Use this function when you know that you won't use the sensor anymore
|
||||
void SCA_ExpressionController::Delete()
|
||||
{
|
||||
if (m_exprCache)
|
||||
{
|
||||
m_exprCache->Release();
|
||||
m_exprCache = NULL;
|
||||
}
|
||||
Release();
|
||||
}
|
||||
|
||||
|
||||
void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr)
|
||||
{
|
||||
|
||||
bool expressionresult = false;
|
||||
|
||||
CParser parser;
|
||||
parser.SetContext(this->AddRef());
|
||||
CExpression* expr = parser.ProcessText(m_exprText);
|
||||
if (expr)
|
||||
if (!m_exprCache)
|
||||
{
|
||||
CValue* value = expr->Calculate();
|
||||
CParser parser;
|
||||
parser.SetContext(this->AddRef());
|
||||
m_exprCache = parser.ProcessText(m_exprText);
|
||||
}
|
||||
if (m_exprCache)
|
||||
{
|
||||
CValue* value = m_exprCache->Calculate();
|
||||
if (value)
|
||||
{
|
||||
if (value->IsError())
|
||||
@ -97,7 +115,8 @@ void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr)
|
||||
value->Release();
|
||||
|
||||
}
|
||||
expr->Release();
|
||||
//m_exprCache->Release();
|
||||
//m_exprCache = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -38,6 +38,7 @@ class SCA_ExpressionController : public SCA_IController
|
||||
{
|
||||
// Py_Header;
|
||||
STR_String m_exprText;
|
||||
CExpression* m_exprCache;
|
||||
|
||||
public:
|
||||
SCA_ExpressionController(SCA_IObject* gameobj,
|
||||
@ -48,6 +49,11 @@ public:
|
||||
virtual CValue* GetReplica();
|
||||
virtual void Trigger(SCA_LogicManager* logicmgr);
|
||||
virtual CValue* FindIdentifier(const STR_String& identifiername);
|
||||
/**
|
||||
* used to release the expression cache
|
||||
* so that self references are removed before the controller itself is released
|
||||
*/
|
||||
virtual void Delete();
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Python interface ---------------------------------------------------- */
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
SCA_IObject* GetParent();
|
||||
virtual void ReParent(SCA_IObject* parent);
|
||||
virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
|
||||
virtual void Delete() { Release(); }
|
||||
|
||||
// act as a BoolValue (with value IsPositiveTrigger)
|
||||
virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
|
||||
|
@ -59,7 +59,9 @@ SCA_IObject::~SCA_IObject()
|
||||
SCA_ControllerList::iterator itc;
|
||||
for (itc = m_controllers.begin(); !(itc == m_controllers.end()); ++itc)
|
||||
{
|
||||
((CValue*)(*itc))->Release();
|
||||
//Use Delete for controller to ensure proper cleaning (expression controller)
|
||||
(*itc)->Delete();
|
||||
//((CValue*)(*itc))->Release();
|
||||
}
|
||||
SCA_ActuatorList::iterator ita;
|
||||
for (ita = m_registeredActuators.begin(); !(ita==m_registeredActuators.end()); ++ita)
|
||||
|
@ -105,11 +105,6 @@ public:
|
||||
bool negmode,
|
||||
int freq);
|
||||
|
||||
/** Release sensor
|
||||
* For property sensor, it is used to release the pre-calculated expression
|
||||
* so that self references are removed before the sensor itself is released
|
||||
*/
|
||||
virtual void Delete() { Release(); }
|
||||
/** Set inversion of pulses on or off. */
|
||||
void SetInvert(bool inv);
|
||||
/** set the level detection on or off */
|
||||
|
@ -70,6 +70,10 @@ public:
|
||||
KX_PROPSENSOR_TYPE checktype,
|
||||
PyTypeObject* T=&Type );
|
||||
|
||||
/**
|
||||
* For property sensor, it is used to release the pre-calculated expression
|
||||
* so that self references are removed before the sensor itself is released
|
||||
*/
|
||||
virtual void Delete();
|
||||
virtual ~SCA_PropertySensor();
|
||||
virtual CValue* GetReplica();
|
||||
|
Loading…
Reference in New Issue
Block a user