示例#1
0
文件: Value.cpp 项目: mik0001/Blender
void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */
{
	m_refcount = 1;
	
#ifdef _DEBUG
	//gRefCountValue++;
#endif
	PyObjectPlus::ProcessReplica();

	m_ValFlags.RefCountDisabled = false;

	/* copy all props */
	if (m_pNamedPropertyArray)
	{
		std::map<STR_String,CValue*> *pOldArray = m_pNamedPropertyArray;
		m_pNamedPropertyArray=NULL;
		std::map<STR_String,CValue*>::iterator it;
		for (it= pOldArray->begin(); (it != pOldArray->end()); it++)
		{
			CValue *val = (*it).second->GetReplica();
			SetProperty((*it).first,val);
			val->Release();
		}
	}
}
示例#2
0
CValue* CIfExpr::Calculate()
/*
pre:
ret: a new object containing the value of m_e1 if m_guard is a boolean TRUE
	 a new object containing the value of m_e2 if m_guard is a boolean FALSE
	 an new errorvalue if m_guard is not a boolean
*/
{
	CValue *guardval;
	guardval = m_guard->Calculate();
	const STR_String& text = guardval->GetText();
	guardval->Release();

	if (&text == &CBoolValue::sTrueString)
	{
		return m_e1->Calculate();
	}
	else if (&text == &CBoolValue::sFalseString)
	{
		return m_e2->Calculate();
	}
	else
	{
		return new CErrorValue("Guard should be of boolean type");
	}
}
示例#3
0
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);
	}
}
示例#4
0
PyObject *CListValue::Pyindex(PyObject *value)
{
	PyObject *result = NULL;

	CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, ");
	if (checkobj==NULL)
		return NULL; /* ConvertPythonToValue sets the error */

	int numelem = GetCount();
	for (int i=0;i<numelem;i++)
	{
		CValue* elem = GetValue(i);
		if (checkobj==elem || CheckEqual(checkobj,elem))
		{
			result = PyLong_FromLong(i);
			break;
		}
	}
	checkobj->Release();

	if (result==NULL) {
		PyErr_SetString(PyExc_ValueError, "CList.index(x): x not in CListValue");
	}
	return result;

}
示例#5
0
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();
}
示例#6
0
CValue * COperator1Expr::Calculate()
/*
pre:
ret: a new object containing the result of applying the operator m_op to the
	 value of m_lhs
*/
{
	CValue *ret;
	CValue *temp = m_lhs->Calculate();
	CValue* empty = new CEmptyValue();
	ret = empty->Calc(m_op, temp);
	empty->Release();
	temp->Release();
	
	return ret;
}
示例#7
0
CValue* SCA_ILogicBrick::Calc(VALUE_OPERATOR op, CValue *val)
{
	CValue* temp = new CBoolValue(false,"");
	CValue* result = temp->Calc(op,val);
	temp->Release();

	return result;
} 
示例#8
0
CValue* COperator2Expr::Calculate()
/*
pre:
ret: a new object containing the result of applying operator m_op to m_lhs
and m_rhs
*/
{

	bool leftmodified,rightmodified;
	leftmodified = m_lhs->NeedsRecalculated();
	rightmodified = m_rhs->NeedsRecalculated();

	// if no modifications on both left and right subtree, and result is already calculated
	// then just return cached result...
	if (!leftmodified && !rightmodified && (m_cached_calculate))
	{
		// not modified, just return m_cached_calculate
	} else {
		// if not yet calculated, or modified...


		if (m_cached_calculate) {
			m_cached_calculate->Release();
			m_cached_calculate=NULL;
		}

		CValue* ffleft = m_lhs->Calculate();
		CValue* ffright = m_rhs->Calculate();

		ffleft->SetOwnerExpression(this);//->m_pOwnerExpression=this;
		ffright->SetOwnerExpression(this);//->m_pOwnerExpression=this;

		m_cached_calculate = ffleft->Calc(m_op,ffright);

		//if (m_cached_calculate)
		//	m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE));

		ffleft->Release();
		ffright->Release();
	}

	return m_cached_calculate->AddRef();

}
示例#9
0
CValue* SCA_ILogicBrick::CalcFinal(VALUE_DATA_TYPE dtype,
								   VALUE_OPERATOR op,
								   CValue *val)
{
	// same as bool implementation, so...
	CValue* temp = new CBoolValue(false,"");
	CValue* result = temp->CalcFinal(dtype,op,val);
	temp->Release();

	return result;
}
示例#10
0
bool CListValue::CheckEqual(CValue* first,CValue* second)
{
	bool result = false;

	CValue* eqval =  ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second);

	if (eqval==NULL)
		return false;
	const STR_String& text = eqval->GetText();
	if (&text==&CBoolValue::sTrueString)
	{
		result = true;
	}
	eqval->Release();
	return result;

}
示例#11
0
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;
}
示例#12
0
文件: Value.cpp 项目: mik0001/Blender
//
// Clear all properties
//
void CValue::ClearProperties()
{		
	// Check if we have any properties
	if (m_pNamedPropertyArray == NULL)
		return;

	// Remove all properties
	std::map<STR_String,CValue*>::iterator it;
	for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
	{
		CValue* tmpval = (*it).second;
		//STR_String name = (*it).first;
		tmpval->Release();
	}

	// Delete property array
	delete m_pNamedPropertyArray;
	m_pNamedPropertyArray=NULL;
}
int KX_FontObject::pyattr_set_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
	KX_FontObject* self = static_cast<KX_FontObject*>(self_v);
	if (!PyUnicode_Check(value))
		return PY_SET_ATTR_FAIL;
	char* chars = _PyUnicode_AsString(value);

	/* Allow for some logic brick control */
	CValue* tprop = self->GetProperty("Text");
	if (tprop) {
		CValue *newstringprop = new CStringValue(STR_String(chars), "Text");
		self->SetProperty("Text", newstringprop);
		newstringprop->Release();
	}
	else {
		self->m_text = split_string(STR_String(chars));
	}

	return PY_SET_ATTR_SUCCESS;
}
示例#14
0
文件: IfExpr.cpp 项目: UPBGE/blender
/**
 * pre:
 * ret: a new object containing the value of m_e1 if m_guard is a boolean true
 *      a new object containing the value of m_e2 if m_guard is a boolean false
 *      an new errorvalue if m_guard is not a boolean
 */
CValue* CIfExpr::Calculate()
{
	CValue *guardval;
	guardval = m_guard->Calculate();
	const std::string& text = guardval->GetText();
	guardval->Release();

	if (text == CBoolValue::sTrueString)
	{
		return m_e1->Calculate();
	}
	else if (text == CBoolValue::sFalseString)
	{
		return m_e2->Calculate();
	}
	else
	{
		return new CErrorValue("Guard should be of boolean type");
	}
}
示例#15
0
文件: Value.cpp 项目: mik0001/Blender
void CValue::SetProperty(const char* name,CValue* ioProperty)
{
	if (ioProperty==NULL)
	{	// Check if somebody is setting an empty property
		trace("Warning:trying to set empty property!");
		return;
	}

	if (m_pNamedPropertyArray)
	{	// Try to replace property (if so -> exit as soon as we replaced it)
		CValue* oldval = (*m_pNamedPropertyArray)[name];
		if (oldval)
			oldval->Release();
	}
	else { // Make sure we have a property array
		m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
	}
	
	// Add property at end of array
	(*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
}
示例#16
0
PyObject *CListValue::Pycount(PyObject *value)
{
	int numfound = 0;

	CValue* checkobj = ConvertPythonToValue(value, ""); /* error ignored */

	if (checkobj==NULL) { /* in this case just return that there are no items in the list */
		PyErr_Clear();
		return PyLong_FromLong(0);
	}

	int numelem = GetCount();
	for (int i=0;i<numelem;i++)
	{
		CValue* elem = 			GetValue(i);
		if (checkobj==elem || CheckEqual(checkobj,elem))
		{
			numfound ++;
		}
	}
	checkobj->Release();

	return PyLong_FromLong(numfound);
}
bool BL_ActionActuator::Update(double curtime, bool frame)
{
	bool bNegativeEvent = false;
	bool bPositiveEvent = false;
	bool bUseContinue = false;
	KX_GameObject *obj = (KX_GameObject*)GetParent();
	short playtype = BL_Action::ACT_MODE_PLAY;
	float start = m_startframe;
	float end = m_endframe;

	// If we don't have an action, we can't do anything
	if (!m_action)
		return false;

	// Convert our playtype to one that BL_Action likes
	switch(m_playtype)
	{
		case ACT_ACTION_LOOP_END:
		case ACT_ACTION_LOOP_STOP:
			playtype = BL_Action::ACT_MODE_LOOP;
			break;

		case ACT_ACTION_PINGPONG:
			// We handle ping pong ourselves to increase compabitility
			// with files made prior to animation changes from GSoC 2011.
			playtype = BL_Action::ACT_MODE_PLAY;
		
			if (m_flag & ACT_FLAG_REVERSE)
			{
				start = m_endframe;
				end = m_startframe;
			}

			break;
		case ACT_ACTION_FROM_PROP:
			CValue* prop = GetParent()->GetProperty(m_propname);

			// If we don't have a property, we can't do anything, so just bail
			if (!prop) return false;

			playtype = BL_Action::ACT_MODE_PLAY;
			start = end = prop->GetNumber();

			break;
	}

	if (m_flag & ACT_FLAG_CONTINUE)
		bUseContinue = true;
	
	
	// Handle events
	if (frame)
	{
		bNegativeEvent = m_negevent;
		bPositiveEvent = m_posevent;
		RemoveAllEvents();
	}

	// "Active" actions need to keep updating their current frame
	if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE))
		m_localtime = obj->GetActionFrame(m_layer);

	if (m_flag & ACT_FLAG_ATTEMPT_PLAY)
		SetLocalTime(curtime);
	else
		ResetStartTime(curtime);

	// Handle a frame property if it's defined
	if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0)
	{
		CValue* oldprop = obj->GetProperty(m_framepropname);
		CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer));
		if (oldprop)
			oldprop->SetValue(newval);
		else
			obj->SetProperty(m_framepropname, newval);

		newval->Release();
	}

	// Handle a finished animation
	if ((m_flag & ACT_FLAG_PLAY_END) && (m_flag & ACT_FLAG_ACTIVE) && obj->IsActionDone(m_layer))
	{
		m_flag &= ~ACT_FLAG_ACTIVE;
		m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;

		if (m_playtype == ACT_ACTION_PINGPONG)
			m_flag ^= ACT_FLAG_REVERSE;
		return false;
	}
	
	// If a different action is playing, we've been overruled and are no longer active
	if (obj->GetCurrentAction(m_layer) != m_action && !obj->IsActionDone(m_layer))
		m_flag &= ~ACT_FLAG_ACTIVE;

	if (bPositiveEvent || (m_flag & ACT_FLAG_ATTEMPT_PLAY && !(m_flag & ACT_FLAG_ACTIVE)))
	{
		if (bPositiveEvent && m_playtype == ACT_ACTION_PLAY)
		{
			if (obj->IsActionDone(m_layer))
				m_localtime = start;
			ResetStartTime(curtime);
		}

		if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags))
		{
			m_flag |= ACT_FLAG_ACTIVE;
			if (bUseContinue)
				obj->SetActionFrame(m_layer, m_localtime);

			if (m_playtype == ACT_ACTION_PLAY || m_playtype == ACT_ACTION_PINGPONG)
				m_flag |= ACT_FLAG_PLAY_END;
			else
				m_flag &= ~ACT_FLAG_PLAY_END;
		}
		m_flag |= ACT_FLAG_ATTEMPT_PLAY;
	}
	else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent)
	{	
		m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
		m_localtime = obj->GetActionFrame(m_layer);
		bAction *curr_action = obj->GetCurrentAction(m_layer);
		if (curr_action && curr_action != m_action)
		{
			// Someone changed the action on us, so we wont mess with it
			// Hopefully there wont be too many problems with two actuators using
			// the same action...
			m_flag &= ~ACT_FLAG_ACTIVE;
			return false;
		}

		switch(m_playtype)
		{
			case ACT_ACTION_LOOP_STOP:
				obj->StopAction(m_layer); // Stop the action after getting the frame

				// We're done
				m_flag &= ~ACT_FLAG_ACTIVE;
				return false;
			case ACT_ACTION_LOOP_END:
				// Convert into a play and let it finish
				obj->SetPlayMode(m_layer, BL_Action::ACT_MODE_PLAY);

				m_flag |= ACT_FLAG_PLAY_END;
				break;
	
			case ACT_ACTION_FLIPPER:
				// Convert into a play action and play back to the beginning
				end = start;
				start = obj->GetActionFrame(m_layer);
				obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);

				m_flag |= ACT_FLAG_PLAY_END;
				break;
		}
	}

	return m_flag & ACT_FLAG_ACTIVE;
}
示例#18
0
CExpression *CParser::Ex(int i)
{
	// parses an expression in the input, starting at priority i, and
	// returns an CExpression, containing the parsed input
	CExpression *e1 = NULL, *e2 = NULL;
	int opkind2;

	if (i < NUM_PRIORITY) {
		e1 = Ex(i + 1);
		while ((sym == opsym) && (Priority(opkind) == i)) {
			opkind2 = opkind;
			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;
				case OPdivide: e1 = new COperator2Expr(VALUE_DIV_OPERATOR,e1, e2); break;
				case OPand: e1 = new COperator2Expr(VALUE_AND_OPERATOR,e1, e2); break;
				case OPor: e1 = new COperator2Expr(VALUE_OR_OPERATOR,e1, e2); break;
				case OPequal: e1 = new COperator2Expr(VALUE_EQL_OPERATOR,e1, e2); break;
				case OPunequal: e1 = new COperator2Expr(VALUE_NEQ_OPERATOR,e1, e2); break;
				case OPgreater: e1 = new COperator2Expr(VALUE_GRE_OPERATOR,e1, e2); break;
				case OPless: e1 = new COperator2Expr(VALUE_LES_OPERATOR,e1, e2); break;
				case OPgreaterequal: e1 = new COperator2Expr(VALUE_GEQ_OPERATOR,e1, e2); break;
				case OPlessequal: e1 = new COperator2Expr(VALUE_LEQ_OPERATOR,e1, e2); break;
				default: MT_assert(false);	break; // should not happen
			}
		}
	} else if (i == NUM_PRIORITY) {
		if ((sym == opsym)
		    && ( (opkind == OPminus) || (opkind == OPnot) || (opkind == OPplus) )
		    )
		{
			NextSym();
			switch (opkind) {
				/* +1 is also a valid number! */
				case OPplus: e1 = new COperator1Expr(VALUE_POS_OPERATOR, Ex(NUM_PRIORITY)); break;
				case OPminus: e1 = new COperator1Expr(VALUE_NEG_OPERATOR, Ex(NUM_PRIORITY)); break;
				case OPnot: e1 = new COperator1Expr(VALUE_NOT_OPERATOR, Ex(NUM_PRIORITY)); break;
				default:
				{
					// should not happen
					e1 = Error("operator +, - or ! expected");
				}
			}
		}
		else {
			switch (sym) {
				case constsym:
				{
					switch (constkind) {
						case booltype:
							e1 = new CConstExpr(new CBoolValue(boolvalue));
							break;
						case inttype:
						{
							cInt temp;
							temp = strtoll(const_as_string, NULL, 10); /* atoi is for int only */
							e1 = new CConstExpr(new CIntValue(temp));
							break;
						}
						case floattype:
						{
							double temp;
							temp = atof(const_as_string);
							e1 = new CConstExpr(new CFloatValue(temp));
							break;
						}
						case stringtype:
							e1 = new CConstExpr(new CStringValue(const_as_string,""));
							break;
						default :
							MT_assert(false);
							break;
					}
					NextSym();
					break;
				}
				case lbracksym:
					NextSym();
					e1 = Ex(1);
					Term(rbracksym);
					break;
				case ifsym:
				{
					CExpression *e3;
					NextSym();
					Term(lbracksym);
					e1 = Ex(1);
					Term(commasym);
					e2 = Ex(1);
					if (sym == commasym) {
						NextSym();
						e3 = Ex(1);
					} else {
						e3 = new CConstExpr(new CEmptyValue());
					}
					Term(rbracksym);
					e1 = new CIfExpr(e1, e2, e3);
					break;
				}
				case idsym:
				{
					e1 = new CIdentifierExpr(const_as_string,m_identifierContext);
					NextSym();

					break;
				}
				case errorsym:
				{
					MT_assert(!e1);
					STR_String errtext="[no info]";
					if (errmsg)
					{
						CValue* errmsgval = errmsg->Calculate();
						errtext=errmsgval->GetText();
						errmsgval->Release();

						//e1 = Error(errmsg->Calculate()->GetText());//new CConstExpr(errmsg->Calculate());

						if ( !(errmsg->Release()) )
						{
							errmsg=NULL;
						} else {
							// does this happen ?
							MT_assert("does this happen");
						}
					}
					e1 = Error(errtext);

					break;
				}
				default:
					NextSym();
					//return Error("Expression expected");
					MT_assert(!e1);
					e1 = Error("Expression expected");
			}
		}
	}
	return e1;
}
示例#19
0
bool BL_ActionActuator::Update(double curtime, bool frame)
{
	bool bNegativeEvent = false;
	bool bPositiveEvent = false;
	bool keepgoing = true;
	bool wrap = false;
	bool apply=true;
	int	priority;
	float newweight;

	curtime -= KX_KetsjiEngine::GetSuspendedDelta();
	
	// result = true if animation has to be continued, false if animation stops
	// maybe there are events for us in the queue !
	if (frame)
	{
		bNegativeEvent = m_negevent;
		bPositiveEvent = m_posevent;
		RemoveAllEvents();
		
		if (bPositiveEvent)
			m_flag |= ACT_FLAG_ACTIVE;
		
		if (bNegativeEvent)
		{
			// dont continue where we left off when restarting
			if (m_end_reset) {
				m_flag &= ~ACT_FLAG_LOCKINPUT;
			}
			
			if (!(m_flag & ACT_FLAG_ACTIVE))
				return false;
			m_flag &= ~ACT_FLAG_ACTIVE;
		}
	}
	
	/*	We know that action actuators have been discarded from all non armature objects:
	if we're being called, we're attached to a BL_ArmatureObject */
	BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
	float length = m_endframe - m_startframe;
	
	priority = m_priority;
	
	/* Determine pre-incrementation behaviour and set appropriate flags */
	switch (m_playtype){
	case ACT_ACTION_MOTION:
		if (bNegativeEvent){
			keepgoing=false;
			apply=false;
		};
		break;
	case ACT_ACTION_FROM_PROP:
		if (bNegativeEvent){
			apply=false;
			keepgoing=false;
		}
		break;
	case ACT_ACTION_LOOP_END:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_KEYUP;
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag |= ACT_FLAG_LOCKINPUT;
				m_localtime = m_startframe;
				m_starttime = curtime;
			}
		}
		if (bNegativeEvent){
			m_flag |= ACT_FLAG_KEYUP;
		}
		break;
	case ACT_ACTION_LOOP_STOP:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag &= ~ACT_FLAG_KEYUP;
				m_flag |= ACT_FLAG_LOCKINPUT;
				SetStartTime(curtime);
			}
		}
		if (bNegativeEvent){
			m_flag |= ACT_FLAG_KEYUP;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
			keepgoing=false;
			apply=false;
		}
		break;
	case ACT_ACTION_FLIPPER:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag |= ACT_FLAG_LOCKINPUT;
				SetStartTime(curtime);
			}
		}
		else if (bNegativeEvent){
			m_flag |= ACT_FLAG_REVERSE;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
			SetStartTime(curtime);
		}
		break;
	case ACT_ACTION_PLAY:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_localtime = m_starttime;
				m_starttime = curtime;
				m_flag |= ACT_FLAG_LOCKINPUT;
			}
		}
		break;
	default:
		break;
	}
	
	/* Perform increment */
	if (keepgoing){
		if (m_playtype == ACT_ACTION_MOTION){
			MT_Point3	newpos;
			MT_Point3	deltapos;
			
			newpos = obj->NodeGetWorldPosition();
			
			/* Find displacement */
			deltapos = newpos-m_lastpos;
			m_localtime += (length/m_stridelength) * deltapos.length();
			m_lastpos = newpos;
		}
		else{
			SetLocalTime(curtime);
		}
	}
	
	/* Check if a wrapping response is needed */
	if (length){
		if (m_localtime < m_startframe || m_localtime > m_endframe)
		{
			m_localtime = m_startframe + fmod(m_localtime, length);
			wrap = true;
		}
	}
	else
		m_localtime = m_startframe;
	
	/* Perform post-increment tasks */
	switch (m_playtype){
	case ACT_ACTION_FROM_PROP:
		{
			CValue* propval = GetParent()->GetProperty(m_propname);
			if (propval)
				m_localtime = propval->GetNumber();
			
			if (bNegativeEvent){
				keepgoing=false;
			}
		}
		break;
	case ACT_ACTION_MOTION:
		break;
	case ACT_ACTION_LOOP_STOP:
		break;
	case ACT_ACTION_FLIPPER:
		if (wrap){
			if (!(m_flag & ACT_FLAG_REVERSE)){
				m_localtime=m_endframe;
				//keepgoing = false;
			}
			else {
				m_localtime=m_startframe;
				keepgoing = false;
			}
		}
		break;
	case ACT_ACTION_LOOP_END:
		if (wrap){
			if (m_flag & ACT_FLAG_KEYUP){
				keepgoing = false;
				m_localtime = m_endframe;
				m_flag &= ~ACT_FLAG_LOCKINPUT;
			}
			SetStartTime(curtime);
		}
		break;
	case ACT_ACTION_PLAY:
		if (wrap){
			m_localtime = m_endframe;
			keepgoing = false;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
		}
		break;
	default:
		keepgoing = false;
		break;
	}
	
	/* Set the property if its defined */
	if (m_framepropname[0] != '\0') {
		CValue* propowner = GetParent();
		CValue* oldprop = propowner->GetProperty(m_framepropname);
		CValue* newval = new CFloatValue(m_localtime);
		if (oldprop) {
			oldprop->SetValue(newval);
		} else {
			propowner->SetProperty(m_framepropname, newval);
		}
		newval->Release();
	}
	
	if (bNegativeEvent)
		m_blendframe=0.0;
	
	/* Apply the pose if necessary*/
	if (apply){

		/* Priority test */
		if (obj->SetActiveAction(this, priority, curtime)){
			
			/* Get the underlying pose from the armature */
			obj->GetPose(&m_pose);

// 2.4x function, 
			/* Override the necessary channels with ones from the action */
			// XXX extract_pose_from_action(m_pose, m_action, m_localtime);
			
			
// 2.5x - replacement for extract_pose_from_action(...) above.
			{
				struct PointerRNA id_ptr;
				Object *arm= obj->GetArmatureObject();
				bPose *pose_back= arm->pose;
				
				arm->pose= m_pose;
				RNA_id_pointer_create((ID *)arm, &id_ptr);
				animsys_evaluate_action(&id_ptr, m_action, NULL, m_localtime);
				
				arm->pose= pose_back;
			
// 2.5x - could also do this but looks too high level, constraints use this, it works ok.
//				Object workob; /* evaluate using workob */
//				what_does_obaction((Scene *)obj->GetScene(), obj->GetArmatureObject(), &workob, m_pose, m_action, NULL, m_localtime);
			}

			// done getting the pose from the action
			
			/* Perform the user override (if any) */
			if (m_userpose){
				extract_pose_from_pose(m_pose, m_userpose);
				game_free_pose(m_userpose); //cant use MEM_freeN(m_userpose) because the channels need freeing too.
				m_userpose = NULL;
			}
#if 1
			/* Handle blending */
			if (m_blendin && (m_blendframe<m_blendin)){
				/* If this is the start of a blending sequence... */
				if ((m_blendframe==0.0) || (!m_blendpose)){
					obj->GetMRDPose(&m_blendpose);
					m_blendstart = curtime;
				}
				
				/* Find percentages */
				newweight = (m_blendframe/(float)m_blendin);
				game_blend_poses(m_pose, m_blendpose, 1.0 - newweight);

				/* Increment current blending percentage */
				m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
				if (m_blendframe>m_blendin)
					m_blendframe = m_blendin;
				
			}
#endif
			m_lastUpdate = m_localtime;
			obj->SetPose (m_pose);
		}
		else{
			m_blendframe = 0.0;
		}
	}
	
	if (!keepgoing){
		m_blendframe = 0.0;
	}
	return keepgoing;
};
示例#20
0
void BL_ConvertTextProperty(Object* object, KX_FontObject* fontobj,SCA_TimeEventManager* timemgr,SCA_IScene* scene, bool isInActiveLayer)
{
	CValue* tprop = fontobj->GetProperty("Text");
	if(!tprop) return;
	bProperty* prop = get_ob_property(object, "Text");
	if(!prop) return;

	Curve *curve = static_cast<Curve *>(object->data);
	STR_String str = curve->str;
	CValue* propval = NULL;

	switch(prop->type) {
		case GPROP_BOOL:
		{
			int value = atoi(str);
			propval = new CBoolValue((bool)(value != 0));
			tprop->SetValue(propval);
			break;
		}
		case GPROP_INT:
		{
			int value = atoi(str);
			propval = new CIntValue(value);
			tprop->SetValue(propval);
			break;
		}
		case GPROP_FLOAT:
		{
			float floatprop = atof(str);
			propval = new CFloatValue(floatprop);
			tprop->SetValue(propval);
			break;
		}
		case GPROP_STRING:
		{
			propval = new CStringValue(str, "");
			tprop->SetValue(propval);
			break;
		}
		case GPROP_TIME:
		{
			float floatprop = atof(str);

			CValue* timeval = new CFloatValue(floatprop);
			// set a subproperty called 'timer' so that
			// we can register the replica of this property
			// at the time a game object is replicated (AddObjectActuator triggers this)
			CValue *bval = new CBoolValue(true);
			timeval->SetProperty("timer",bval);
			bval->Release();
			if (isInActiveLayer)
			{
				timemgr->AddTimeProperty(timeval);
			}

			propval = timeval;
			tprop->SetValue(timeval);
		}
		default:
		{
			// todo make an assert etc.
		}
	}

	if (propval) {
		propval->Release();
	}
}
bool KX_IpoActuator::Update(double curtime, bool frame)
{
	// result = true if animation has to be continued, false if animation stops
	// maybe there are events for us in the queue !
	bool bNegativeEvent = false;
	bool numevents = false;
	bool bIpoStart = false;

	curtime -= KX_KetsjiEngine::GetSuspendedDelta();

	if (frame)
	{
		numevents = m_posevent || m_negevent;
		bNegativeEvent = IsNegativeEvent();
		RemoveAllEvents();
	}
	
	float  start_smaller_then_end = ( m_startframe < m_endframe ? 1.0f : -1.0f);

	bool result=true;
	if (!bNegativeEvent)
	{
		if (m_starttime < -2.0f*fabs(m_endframe - m_startframe))
		{
			// start for all Ipo, initial start for LOOP_STOP
			m_starttime = curtime;
			m_bIpoPlaying = true;
			bIpoStart = true;
		}
	}

	switch ((IpoActType)m_type)
	{
		
	case KX_ACT_IPO_PLAY:
	{
		// Check if playing forwards.  result = ! finished
		
		if (start_smaller_then_end > 0.f)
			result = (m_localtime < m_endframe && m_bIpoPlaying);
		else
			result = (m_localtime > m_endframe && m_bIpoPlaying);
		
		if (result)
		{
			SetLocalTime(curtime);
		
			/* Perform clamping */
			ClampLocalTime();
	
			if (bIpoStart)
				((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
			((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
		} else
		{
			m_localtime=m_startframe;
			m_direction=1;
		}
		break;
	}
	case KX_ACT_IPO_PINGPONG:
	{
		result = true;
		if (bNegativeEvent && !m_bIpoPlaying)
			result = false;
		else
			SetLocalTime(curtime);
			
		if (ClampLocalTime())
		{
			result = false;
			m_direction = -m_direction;
		}
		
		if (bIpoStart && m_direction > 0)
			((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
		((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
		break;
	}
	case KX_ACT_IPO_FLIPPER:
	{
		if (bNegativeEvent && !m_bIpoPlaying)
			result = false;
		if (numevents)
		{
			float oldDirection = m_direction;
			if (bNegativeEvent)
				m_direction = -1;
			else
				m_direction = 1;
			if (m_direction != oldDirection)
				// changing direction, reset start time
				SetStartTime(curtime);
		}
		
		SetLocalTime(curtime);
		
		if (ClampLocalTime() && m_localtime == m_startframe)
			result = false;

		if (bIpoStart)
			((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
		((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
		break;
	}

	case KX_ACT_IPO_LOOPSTOP:
	{
		if (numevents)
		{
			if (bNegativeEvent)
			{
				result = false;
				m_bNegativeEvent = false;
				numevents = false;
			}
			if (!m_bIpoPlaying)
			{
				// Ipo was stopped, make sure we will restart from where it stopped
				SetStartTime(curtime);
				if (!bNegativeEvent)
					// positive signal will restart the Ipo
					m_bIpoPlaying = true;
			}

		} // fall through to loopend, and quit the ipo animation immediatly 
	}
	case KX_ACT_IPO_LOOPEND:
	{
		if (numevents) {
			if (bNegativeEvent && m_bIpoPlaying) {
				m_bNegativeEvent = true;
			}
		}
		
		if (bNegativeEvent && !m_bIpoPlaying) {
			result = false;
		} 
		else
		{
			if (m_localtime*start_smaller_then_end < m_endframe*start_smaller_then_end)
			{
				SetLocalTime(curtime);
			}
			else {
				if (!m_bNegativeEvent) {
					/* Perform wraparound */
					SetLocalTime(curtime);
					if (start_smaller_then_end > 0.f)
						m_localtime = m_startframe + fmod(m_localtime - m_startframe, m_endframe - m_startframe);
					else
						m_localtime = m_startframe - fmod(m_startframe - m_localtime, m_startframe - m_endframe);
					SetStartTime(curtime);
					bIpoStart = true;
				}
				else
				{
					/* Perform clamping */
					m_localtime=m_endframe;
					result = false;
					m_bNegativeEvent = false;
				}
			}
		}
		
		if (m_bIpoPlaying && bIpoStart)
			((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
		((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
		break;
	}
	
	case KX_ACT_IPO_KEY2KEY:
	{
		// not implemented yet
		result = false;
		break;
	}
	
	case KX_ACT_IPO_FROM_PROP:
	{
		result = !bNegativeEvent;

		CValue* propval = GetParent()->GetProperty(m_propname);
		if (propval)
		{
			m_localtime = propval->GetNumber(); 
	
			if (bIpoStart)
				((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
			((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
		} else
		{
			result = false;
		}
		break;
	}
		
	default:
		result = false;
	}

	/* Set the property if its defined */
	if (m_framepropname[0] != '\0') {
		CValue* propowner = GetParent();
		CValue* oldprop = propowner->GetProperty(m_framepropname);
		CValue* newval = new CFloatValue(m_localtime);
		if (oldprop) {
			oldprop->SetValue(newval);
		} else {
			propowner->SetProperty(m_framepropname, newval);
		}
		newval->Release();
	}

	if (!result)
	{
		if (m_type != KX_ACT_IPO_LOOPSTOP)
			this->ResetStartTime();
		m_bIpoPlaying = false;
	}

	return result;
}
示例#22
0
void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventManager* timemgr,SCA_IScene* scene, bool isInActiveLayer)
{
	
	bProperty* prop = (bProperty*)object->prop.first;
	CValue* propval;	
	bool show_debug_info;
	while(prop)
	{
	
		propval = NULL;
		show_debug_info = bool (prop->flag & PROP_DEBUG);

		switch(prop->type) {
			case GPROP_BOOL:
			{
				propval = new CBoolValue((bool)(prop->data != 0));
				gameobj->SetProperty(prop->name,propval);
				//promp->poin= &prop->data;
				break;
			}
			case GPROP_INT:
			{
				propval = new CIntValue((int)prop->data);
				gameobj->SetProperty(prop->name,propval);
				break;
			}
			case GPROP_FLOAT:
			{
				//prop->poin= &prop->data;
				float floatprop = *((float*)&prop->data);
				propval = new CFloatValue(floatprop);
				gameobj->SetProperty(prop->name,propval);
			}
			break;
			case GPROP_STRING:
			{
				//prop->poin= callocN(MAX_PROPSTRING, "property string");
				propval = new CStringValue((char*)prop->poin,"");
				gameobj->SetProperty(prop->name,propval);
				break;
			}
			case GPROP_TIME:
			{
				float floatprop = *((float*)&prop->data);

				CValue* timeval = new CFloatValue(floatprop);
				// set a subproperty called 'timer' so that 
				// we can register the replica of this property 
				// at the time a game object is replicated (AddObjectActuator triggers this)
				CValue *bval = new CBoolValue(true);
				timeval->SetProperty("timer",bval);
				bval->Release();
				if (isInActiveLayer)
				{
					timemgr->AddTimeProperty(timeval);
				}
				
				propval = timeval;
				gameobj->SetProperty(prop->name,timeval);

			}
			default:
			{
				// todo make an assert etc.
			}
		}
		
		if (propval)
		{
			if (show_debug_info)
			{
				scene->AddDebugProperty(gameobj,STR_String(prop->name));
			}
			// done with propval, release it
			propval->Release();
		}
		
#ifdef WITH_PYTHON
		/* Warn if we double up on attributes, this isnt quite right since it wont find inherited attributes however there arnt many */
		for(PyAttributeDef *attrdef = KX_GameObject::Attributes; attrdef->m_name; attrdef++) {
			if(strcmp(prop->name, attrdef->m_name)==0) {
				printf("Warning! user defined property name \"%s\" is also a python attribute for object \"%s\"\n\tUse ob[\"%s\"] syntax to avoid conflict\n", prop->name, object->id.name+2, prop->name);
				break;
			}
		}
		for(PyMethodDef *methdef = KX_GameObject::Methods; methdef->ml_name; methdef++) {
			if(strcmp(prop->name, methdef->ml_name)==0) {
				printf("Warning! user defined property name \"%s\" is also a python method for object \"%s\"\n\tUse ob[\"%s\"] syntax to avoid conflict\n", prop->name, object->id.name+2, prop->name);
				break;
			}
		}
		/* end warning check */
#endif // WITH_PYTHON

		prop = prop->next;
	}
	// check if state needs to be debugged
	if (object->scaflag & OB_DEBUGSTATE)
	{
		//  reserve name for object state
		scene->AddDebugProperty(gameobj,STR_String("__state__"));
	}

	/* Font Objects need to 'copy' the Font Object data body to ["Text"] */
	if (object->type == OB_FONT)
	{
		BL_ConvertTextProperty(object, (KX_FontObject *)gameobj, timemgr, scene, isInActiveLayer);
	}
}
示例#23
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;
}
示例#24
0
bool SCA_PropertyActuator::Update()
{
	bool result = false;

	bool bNegativeEvent = IsNegativeEvent();
	RemoveAllEvents();


	if (bNegativeEvent)
		return false; // do nothing on negative events


	CValue* propowner = GetParent();
	CParser parser;
	parser.SetContext( propowner->AddRef());
	
	CExpression* userexpr= NULL;
	
	if (m_type==KX_ACT_PROP_TOGGLE)
	{
		/* dont use */
		CValue* newval;
		CValue* oldprop = propowner->GetProperty(m_propname);
		if (oldprop)
		{
			newval = new CBoolValue((oldprop->GetNumber()==0.0) ? true:false);
			oldprop->SetValue(newval);
		} else
		{	/* as not been assigned, evaluate as false, so assign true */
			newval = new CBoolValue(true);
			propowner->SetProperty(m_propname,newval);
		}
		newval->Release();
	}
	else if ((userexpr = parser.ProcessText(m_exprtxt))) {
		switch (m_type)
		{

		case KX_ACT_PROP_ASSIGN:
			{
				
				CValue* newval = userexpr->Calculate();
				CValue* oldprop = propowner->GetProperty(m_propname);
				if (oldprop)
				{
					oldprop->SetValue(newval);
				} else
				{
					propowner->SetProperty(m_propname,newval);
				}
				newval->Release();
				break;
			}
		case KX_ACT_PROP_ADD:
			{
				CValue* oldprop = propowner->GetProperty(m_propname);
				if (oldprop)
				{
					// int waarde = (int)oldprop->GetNumber();  /*unused*/
					CExpression* expr = new COperator2Expr(VALUE_ADD_OPERATOR,new CConstExpr(oldprop->AddRef()),
															userexpr->AddRef());

					CValue* newprop = expr->Calculate();
					oldprop->SetValue(newprop);
					newprop->Release();
					expr->Release();

				}

				break;
			}
		case KX_ACT_PROP_COPY:
			{
				if (m_sourceObj)
				{
					CValue* copyprop = m_sourceObj->GetProperty(m_exprtxt);
					if (copyprop)
					{
						CValue *val = copyprop->GetReplica();
						GetParent()->SetProperty(
							 m_propname,
							 val);
						val->Release();

					}
				}
				break;
			}
		/* case KX_ACT_PROP_TOGGLE: */ /* accounted for above, no need for userexpr */
		default:
			{

			}
		}

		userexpr->Release();
	}
	
	return result;
}
示例#25
0
bool BL_ShapeActionActuator::Update(double curtime, bool frame)
{
	bool bNegativeEvent = false;
	bool bPositiveEvent = false;
	bool keepgoing = true;
	bool wrap = false;
	bool apply=true;
	int	priority;
	float newweight;

	curtime -= KX_KetsjiEngine::GetSuspendedDelta();
	
	// result = true if animation has to be continued, false if animation stops
	// maybe there are events for us in the queue !
	if (frame)
	{
		bNegativeEvent = m_negevent;
		bPositiveEvent = m_posevent;
		RemoveAllEvents();
		
		if (bPositiveEvent)
			m_flag |= ACT_FLAG_ACTIVE;
		
		if (bNegativeEvent)
		{
			if (!(m_flag & ACT_FLAG_ACTIVE))
				return false;
			m_flag &= ~ACT_FLAG_ACTIVE;
		}
	}
	
	/*	This action can only be attached to a deform object */
	BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent();
	float length = m_endframe - m_startframe;
	
	priority = m_priority;
	
	/* Determine pre-incrementation behaviour and set appropriate flags */
	switch (m_playtype){
	case ACT_ACTION_MOTION:
		if (bNegativeEvent){
			keepgoing=false;
			apply=false;
		};
		break;
	case ACT_ACTION_FROM_PROP:
		if (bNegativeEvent){
			apply=false;
			keepgoing=false;
		}
		break;
	case ACT_ACTION_LOOP_END:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_KEYUP;
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag |= ACT_FLAG_LOCKINPUT;
				m_localtime = m_startframe;
				m_starttime = curtime;
			}
		}
		if (bNegativeEvent){
			m_flag |= ACT_FLAG_KEYUP;
		}
		break;
	case ACT_ACTION_LOOP_STOP:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag &= ~ACT_FLAG_KEYUP;
				m_flag |= ACT_FLAG_LOCKINPUT;
				SetStartTime(curtime);
			}
		}
		if (bNegativeEvent){
			m_flag |= ACT_FLAG_KEYUP;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
			keepgoing=false;
			apply=false;
		}
		break;
	case ACT_ACTION_PINGPONG:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_KEYUP;
				m_localtime = m_starttime;
				m_starttime = curtime;
				m_flag |= ACT_FLAG_LOCKINPUT;
			}
		}
		break;
	case ACT_ACTION_FLIPPER:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag |= ACT_FLAG_LOCKINPUT;
				SetStartTime(curtime);
			}
		}
		else if (bNegativeEvent){
			m_flag |= ACT_FLAG_REVERSE;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
			SetStartTime(curtime);
		}
		break;
	case ACT_ACTION_PLAY:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_localtime = m_starttime;
				m_starttime = curtime;
				m_flag |= ACT_FLAG_LOCKINPUT;
			}
		}
		break;
	default:
		break;
	}
	
	/* Perform increment */
	if (keepgoing){
		if (m_playtype == ACT_ACTION_MOTION){
			MT_Point3	newpos;
			MT_Point3	deltapos;
			
			newpos = obj->NodeGetWorldPosition();
			
			/* Find displacement */
			deltapos = newpos-m_lastpos;
			m_localtime += (length/m_stridelength) * deltapos.length();
			m_lastpos = newpos;
		}
		else{
			SetLocalTime(curtime);
		}
	}
	
	/* Check if a wrapping response is needed */
	if (length){
		if (m_localtime < m_startframe || m_localtime > m_endframe)
		{
			m_localtime = m_startframe + fmod(m_localtime, length);
			wrap = true;
		}
	}
	else
		m_localtime = m_startframe;
	
	/* Perform post-increment tasks */
	switch (m_playtype){
	case ACT_ACTION_FROM_PROP:
		{
			CValue* propval = GetParent()->GetProperty(m_propname);
			if (propval)
				m_localtime = propval->GetNumber();
			
			if (bNegativeEvent){
				keepgoing=false;
			}
		}
		break;
	case ACT_ACTION_MOTION:
		break;
	case ACT_ACTION_LOOP_STOP:
		break;
	case ACT_ACTION_PINGPONG:
		if (wrap){
			if (!(m_flag & ACT_FLAG_REVERSE))
				m_localtime = m_endframe;
			else 
				m_localtime = m_startframe;

			m_flag &= ~ACT_FLAG_LOCKINPUT;
			m_flag ^= ACT_FLAG_REVERSE; //flip direction
			keepgoing = false;
		}
		break;
	case ACT_ACTION_FLIPPER:
		if (wrap){
			if (!(m_flag & ACT_FLAG_REVERSE)){
				m_localtime=m_endframe;
				//keepgoing = false;
			}
			else {
				m_localtime=m_startframe;
				keepgoing = false;
			}
		}
		break;
	case ACT_ACTION_LOOP_END:
		if (wrap){
			if (m_flag & ACT_FLAG_KEYUP){
				keepgoing = false;
				m_localtime = m_endframe;
				m_flag &= ~ACT_FLAG_LOCKINPUT;
			}
			SetStartTime(curtime);
		}
		break;
	case ACT_ACTION_PLAY:
		if (wrap){
			m_localtime = m_endframe;
			keepgoing = false;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
		}
		break;
	default:
		keepgoing = false;
		break;
	}
	
	/* Set the property if its defined */
	if (m_framepropname[0] != '\0') {
		CValue* propowner = GetParent();
		CValue* oldprop = propowner->GetProperty(m_framepropname);
		CValue* newval = new CFloatValue(m_localtime);
		if (oldprop) {
			oldprop->SetValue(newval);
		} else {
			propowner->SetProperty(m_framepropname, newval);
		}
		newval->Release();
	}
	
	if (bNegativeEvent)
		m_blendframe=0.0f;
	
	/* Apply the pose if necessary*/
	if (apply) {

		/* Priority test */
		if (obj->SetActiveAction(this, priority, curtime)){
			BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
			Key *key = NULL;

			if (shape_deformer)
				key = shape_deformer->GetKey();

			if (!key) {
				// this could happen if the mesh was changed in the middle of an action
				// and the new mesh has no key, stop the action
				keepgoing = false;
			}
			else {
				ListBase tchanbase= {NULL, NULL};
			
				if (m_blendin && m_blendframe==0.0f){
					// this is the start of the blending, remember the startup shape
					obj->GetShape(m_blendshape);
					m_blendstart = curtime;
				}

				KeyBlock *kb;
				// We go through and clear out the keyblocks so there isn't any interference
				// from other shape actions
				for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
					kb->curval = 0.f;

				animsys_evaluate_action(m_idptr, m_action, NULL, m_localtime);

				// XXX - in 2.5 theres no way to do this. possibly not that important to support - Campbell
				if (0) { // XXX !execute_ipochannels(&tchanbase)) {
					// no update, this is possible if action does not match the keys, stop the action
					keepgoing = false;
				} 
				else {
					// the key have changed, apply blending if needed
					if (m_blendin && (m_blendframe<m_blendin)){
						newweight = (m_blendframe/(float)m_blendin);

						BlendShape(key, 1.0f - newweight);

						/* Increment current blending percentage */
						m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
						if (m_blendframe>m_blendin)
							m_blendframe = m_blendin;
					}
					m_lastUpdate = m_localtime;
				}
				BLI_freelistN(&tchanbase);
			}
		}
		else{
			m_blendframe = 0.0f;
		}
	}
	
	if (!keepgoing){
		m_blendframe = 0.0f;
	}
	return keepgoing;
};
示例#26
0
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;
}