SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, const STR_String& propval, const STR_String& propmaxval, KX_PROPSENSOR_TYPE checktype) : SCA_ISensor(gameobj,eventmgr), m_checktype(checktype), m_checkpropval(propval), m_checkpropmaxval(propmaxval), m_checkpropname(propname), m_range_expr(NULL) { //CParser pars; //pars.SetContext(this->AddRef()); //CValue* resultval = m_rightexpr->Calculate(); CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { m_previoustext = orgprop->GetText(); } orgprop->Release(); if (m_checktype==KX_PROPSENSOR_INTERVAL) { PrecalculateRangeExpression(); } Init(); }
void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr) { bool expressionresult = false; if (!m_exprCache) { 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()) { printf("%s\n", value->GetText().ReadPtr()); } else { float num = (float)value->GetNumber(); expressionresult = !MT_fuzzyZero(num); } value->Release(); } } for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { SCA_IActuator* actua = *i; logicmgr->AddActiveActuator(actua,expressionresult); } }
int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) { if (attrdef->m_type != KX_PYATTRIBUTE_TYPE_STRING || attrdef->m_length != 1) { PyErr_SetString(PyExc_AttributeError, "inconsistent check function for attribute type, report to blender.org"); return 1; } SCA_ILogicBrick* brick = reinterpret_cast<SCA_ILogicBrick*>(self); STR_String* var = reinterpret_cast<STR_String*>((char*)self+attrdef->m_offset); CValue* prop = brick->GetParent()->FindIdentifier(*var); bool error = prop->IsError(); prop->Release(); if (error) { PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); return 1; } return 0; }
bool SCA_PropertySensor::CheckPropertyCondition() { m_recentresult=false; bool result=false; bool reverse = false; switch (m_checktype) { case KX_PROPSENSOR_NOTEQUAL: reverse = true; case KX_PROPSENSOR_EQUAL: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { const STR_String& testprop = orgprop->GetText(); // Force strings to upper case, to avoid confusion in // bool tests. It's stupid the prop's identity is lost // on the way here... if ((&testprop == &CBoolValue::sTrueString) || (&testprop == &CBoolValue::sFalseString)) { m_checkpropval.Upper(); } result = (testprop == m_checkpropval); /* Patch: floating point values cant use strings usefully since you can have "0.0" == "0.0000" * this could be made into a generic Value class function for comparing values with a string. */ if (result==false && dynamic_cast<CFloatValue *>(orgprop) != NULL) { float f; if (EOF == sscanf(m_checkpropval.ReadPtr(), "%f", &f)) { //error } else { result = (f == ((CFloatValue *)orgprop)->GetFloat()); } } /* end patch */ } orgprop->Release(); if (reverse) result = !result; break; } case KX_PROPSENSOR_EXPRESSION: { /* if (m_rightexpr) { CValue* resultval = m_rightexpr->Calculate(); if (resultval->IsError()) { int i=0; STR_String errortest = resultval->GetText(); printf(errortest); } else { result = resultval->GetNumber() != 0; } } */ break; } case KX_PROPSENSOR_INTERVAL: { //CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); //if (orgprop) //{ if (m_range_expr) { CValue* vallie = m_range_expr->Calculate(); if (vallie) { const STR_String& errtext = vallie->GetText(); if (&errtext == &CBoolValue::sTrueString) { result = true; } else { if (vallie->IsError()) { //printf (errtext.ReadPtr()); } } vallie->Release(); } } //} //cout << " \nSens:Prop:interval!"; /* need implementation here!!! */ break; } case KX_PROPSENSOR_CHANGED: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { if (m_previoustext != orgprop->GetText()) { m_previoustext = orgprop->GetText(); result = true; } } orgprop->Release(); //cout << " \nSens:Prop:changed!"; /* need implementation here!!! */ break; } default: ; /* error */ } //the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED //see Game Engine bugtracker [ #3809 ] if (m_checktype != KX_PROPSENSOR_CHANGED) { m_recentresult=result; } else { m_recentresult=result;//true; } return result; }
bool SCA_PropertySensor::CheckPropertyCondition() { m_recentresult=false; bool result=false; bool reverse = false; switch (m_checktype) { case KX_PROPSENSOR_NOTEQUAL: reverse = true; /* fall-through */ case KX_PROPSENSOR_EQUAL: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { const std::string& testprop = orgprop->GetText(); // Force strings to upper case, to avoid confusion in // bool tests. It's stupid the prop's identity is lost // on the way here... if ((testprop == CBoolValue::sTrueString) || (testprop == CBoolValue::sFalseString)) { boost::to_upper(m_checkpropval); } result = (testprop == m_checkpropval); /* Patch: floating point values cant use strings usefully since you can have "0.0" == "0.0000" * this could be made into a generic Value class function for comparing values with a string. */ if (result==false && (orgprop->GetValueType() == VALUE_FLOAT_TYPE)) { float f = std::stof(m_checkpropval); result = (f == ((CFloatValue *)orgprop)->GetFloat()); } /* end patch */ } orgprop->Release(); if (reverse) result = !result; break; } case KX_PROPSENSOR_EXPRESSION: { break; } case KX_PROPSENSOR_INTERVAL: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { const float min = std::stof(m_checkpropval); const float max = std::stof(m_checkpropmaxval); float val; if (orgprop->GetValueType() == VALUE_STRING_TYPE) { val = std::stof(orgprop->GetText()); } else { val = orgprop->GetNumber(); } result = (min <= val) && (val <= max); } orgprop->Release(); break; } case KX_PROPSENSOR_CHANGED: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { if (m_previoustext != orgprop->GetText()) { m_previoustext = orgprop->GetText(); result = true; } } orgprop->Release(); break; } case KX_PROPSENSOR_LESSTHAN: reverse = true; /* fall-through */ case KX_PROPSENSOR_GREATERTHAN: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { const float ref = std::stof(m_checkpropval); float val; if (orgprop->GetValueType() == VALUE_STRING_TYPE) { val = std::stof(orgprop->GetText()); } else { val = orgprop->GetNumber(); } if (reverse) { result = val < ref; } else { result = val > ref; } } orgprop->Release(); break; } default: ; /* error */ } //the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED //see Game Engine bugtracker [ #3809 ] m_recentresult = result; return result; }