Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <cmath> 00034 00035 #include "SCA_LogicManager.h" 00036 #include "BL_ShapeActionActuator.h" 00037 #include "BL_ShapeDeformer.h" 00038 #include "KX_GameObject.h" 00039 #include "STR_HashedString.h" 00040 #include "DNA_nla_types.h" 00041 #include "DNA_action_types.h" 00042 #include "DNA_anim_types.h" 00043 #include "DNA_scene_types.h" 00044 #include "BKE_action.h" 00045 #include "DNA_armature_types.h" 00046 #include "MEM_guardedalloc.h" 00047 #include "BLI_blenlib.h" 00048 #include "BLI_math.h" 00049 #include "MT_Matrix4x4.h" 00050 00051 #include "FloatValue.h" 00052 #include "PyObjectPlus.h" 00053 00054 extern "C" { 00055 #include "BKE_animsys.h" 00056 #include "BKE_key.h" 00057 #include "RNA_access.h" 00058 } 00059 00060 BL_ShapeActionActuator::BL_ShapeActionActuator(SCA_IObject* gameobj, 00061 const STR_String& propname, 00062 const STR_String& framepropname, 00063 float starttime, 00064 float endtime, 00065 struct bAction *action, 00066 short playtype, 00067 short blendin, 00068 short priority, 00069 float stride) 00070 : SCA_IActuator(gameobj, KX_ACT_SHAPEACTION), 00071 00072 m_lastpos(0, 0, 0), 00073 m_blendframe(0), 00074 m_flag(0), 00075 m_startframe (starttime), 00076 m_endframe(endtime) , 00077 m_starttime(0), 00078 m_localtime(starttime), 00079 m_lastUpdate(-1), 00080 m_blendin(blendin), 00081 m_blendstart(0), 00082 m_stridelength(stride), 00083 m_playtype(playtype), 00084 m_priority(priority), 00085 m_action(action), 00086 m_framepropname(framepropname), 00087 m_propname(propname) 00088 { 00089 m_idptr = new PointerRNA(); 00090 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent(); 00091 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); 00092 RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_idptr); 00093 }; 00094 00095 BL_ShapeActionActuator::~BL_ShapeActionActuator() 00096 { 00097 if (m_idptr) 00098 delete m_idptr; 00099 } 00100 00101 void BL_ShapeActionActuator::ProcessReplica() 00102 { 00103 SCA_IActuator::ProcessReplica(); 00104 m_localtime=m_startframe; 00105 m_lastUpdate=-1; 00106 } 00107 00108 void BL_ShapeActionActuator::SetBlendTime (float newtime) 00109 { 00110 m_blendframe = newtime; 00111 } 00112 00113 CValue* BL_ShapeActionActuator::GetReplica() 00114 { 00115 BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName()); 00116 replica->ProcessReplica(); 00117 return replica; 00118 } 00119 00120 bool BL_ShapeActionActuator::ClampLocalTime() 00121 { 00122 if (m_startframe < m_endframe) { 00123 if (m_localtime < m_startframe) 00124 { 00125 m_localtime = m_startframe; 00126 return true; 00127 } 00128 else if (m_localtime > m_endframe) 00129 { 00130 m_localtime = m_endframe; 00131 return true; 00132 } 00133 } else { 00134 if (m_localtime > m_startframe) 00135 { 00136 m_localtime = m_startframe; 00137 return true; 00138 } 00139 else if (m_localtime < m_endframe) 00140 { 00141 m_localtime = m_endframe; 00142 return true; 00143 } 00144 } 00145 return false; 00146 } 00147 00148 void BL_ShapeActionActuator::SetStartTime(float curtime) 00149 { 00150 float direction = m_startframe < m_endframe ? 1.0 : -1.0; 00151 00152 if (!(m_flag & ACT_FLAG_REVERSE)) 00153 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate(); 00154 else 00155 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate(); 00156 } 00157 00158 void BL_ShapeActionActuator::SetLocalTime(float curtime) 00159 { 00160 float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate(); 00161 00162 if (m_endframe < m_startframe) 00163 delta_time = -delta_time; 00164 00165 if (!(m_flag & ACT_FLAG_REVERSE)) 00166 m_localtime = m_startframe + delta_time; 00167 else 00168 m_localtime = m_endframe - delta_time; 00169 } 00170 00171 void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight) 00172 { 00173 vector<float>::const_iterator it; 00174 float dstweight; 00175 KeyBlock *kb; 00176 00177 dstweight = 1.0F - srcweight; 00178 00179 for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first; 00180 kb && it != m_blendshape.end(); 00181 kb = (KeyBlock*)kb->next, it++) 00182 { 00183 kb->curval = kb->curval * dstweight + (*it) * srcweight; 00184 } 00185 } 00186 00187 bool BL_ShapeActionActuator::Update(double curtime, bool frame) 00188 { 00189 bool bNegativeEvent = false; 00190 bool bPositiveEvent = false; 00191 bool keepgoing = true; 00192 bool wrap = false; 00193 bool apply=true; 00194 int priority; 00195 float newweight; 00196 00197 curtime -= KX_KetsjiEngine::GetSuspendedDelta(); 00198 00199 // result = true if animation has to be continued, false if animation stops 00200 // maybe there are events for us in the queue ! 00201 if (frame) 00202 { 00203 bNegativeEvent = m_negevent; 00204 bPositiveEvent = m_posevent; 00205 RemoveAllEvents(); 00206 00207 if (bPositiveEvent) 00208 m_flag |= ACT_FLAG_ACTIVE; 00209 00210 if (bNegativeEvent) 00211 { 00212 if (!(m_flag & ACT_FLAG_ACTIVE)) 00213 return false; 00214 m_flag &= ~ACT_FLAG_ACTIVE; 00215 } 00216 } 00217 00218 /* This action can only be attached to a deform object */ 00219 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent(); 00220 float length = m_endframe - m_startframe; 00221 00222 priority = m_priority; 00223 00224 /* Determine pre-incrementation behaviour and set appropriate flags */ 00225 switch (m_playtype){ 00226 case ACT_ACTION_MOTION: 00227 if (bNegativeEvent){ 00228 keepgoing=false; 00229 apply=false; 00230 }; 00231 break; 00232 case ACT_ACTION_FROM_PROP: 00233 if (bNegativeEvent){ 00234 apply=false; 00235 keepgoing=false; 00236 } 00237 break; 00238 case ACT_ACTION_LOOP_END: 00239 if (bPositiveEvent){ 00240 if (!(m_flag & ACT_FLAG_LOCKINPUT)){ 00241 m_flag &= ~ACT_FLAG_KEYUP; 00242 m_flag &= ~ACT_FLAG_REVERSE; 00243 m_flag |= ACT_FLAG_LOCKINPUT; 00244 m_localtime = m_startframe; 00245 m_starttime = curtime; 00246 } 00247 } 00248 if (bNegativeEvent){ 00249 m_flag |= ACT_FLAG_KEYUP; 00250 } 00251 break; 00252 case ACT_ACTION_LOOP_STOP: 00253 if (bPositiveEvent){ 00254 if (!(m_flag & ACT_FLAG_LOCKINPUT)){ 00255 m_flag &= ~ACT_FLAG_REVERSE; 00256 m_flag &= ~ACT_FLAG_KEYUP; 00257 m_flag |= ACT_FLAG_LOCKINPUT; 00258 SetStartTime(curtime); 00259 } 00260 } 00261 if (bNegativeEvent){ 00262 m_flag |= ACT_FLAG_KEYUP; 00263 m_flag &= ~ACT_FLAG_LOCKINPUT; 00264 keepgoing=false; 00265 apply=false; 00266 } 00267 break; 00268 case ACT_ACTION_PINGPONG: 00269 if (bPositiveEvent){ 00270 if (!(m_flag & ACT_FLAG_LOCKINPUT)){ 00271 m_flag &= ~ACT_FLAG_KEYUP; 00272 m_localtime = m_starttime; 00273 m_starttime = curtime; 00274 m_flag |= ACT_FLAG_LOCKINPUT; 00275 } 00276 } 00277 break; 00278 case ACT_ACTION_FLIPPER: 00279 if (bPositiveEvent){ 00280 if (!(m_flag & ACT_FLAG_LOCKINPUT)){ 00281 m_flag &= ~ACT_FLAG_REVERSE; 00282 m_flag |= ACT_FLAG_LOCKINPUT; 00283 SetStartTime(curtime); 00284 } 00285 } 00286 else if (bNegativeEvent){ 00287 m_flag |= ACT_FLAG_REVERSE; 00288 m_flag &= ~ACT_FLAG_LOCKINPUT; 00289 SetStartTime(curtime); 00290 } 00291 break; 00292 case ACT_ACTION_PLAY: 00293 if (bPositiveEvent){ 00294 if (!(m_flag & ACT_FLAG_LOCKINPUT)){ 00295 m_flag &= ~ACT_FLAG_REVERSE; 00296 m_localtime = m_starttime; 00297 m_starttime = curtime; 00298 m_flag |= ACT_FLAG_LOCKINPUT; 00299 } 00300 } 00301 break; 00302 default: 00303 break; 00304 } 00305 00306 /* Perform increment */ 00307 if (keepgoing){ 00308 if (m_playtype == ACT_ACTION_MOTION){ 00309 MT_Point3 newpos; 00310 MT_Point3 deltapos; 00311 00312 newpos = obj->NodeGetWorldPosition(); 00313 00314 /* Find displacement */ 00315 deltapos = newpos-m_lastpos; 00316 m_localtime += (length/m_stridelength) * deltapos.length(); 00317 m_lastpos = newpos; 00318 } 00319 else{ 00320 SetLocalTime(curtime); 00321 } 00322 } 00323 00324 /* Check if a wrapping response is needed */ 00325 if (length){ 00326 if (m_localtime < m_startframe || m_localtime > m_endframe) 00327 { 00328 m_localtime = m_startframe + fmod(m_localtime, length); 00329 wrap = true; 00330 } 00331 } 00332 else 00333 m_localtime = m_startframe; 00334 00335 /* Perform post-increment tasks */ 00336 switch (m_playtype){ 00337 case ACT_ACTION_FROM_PROP: 00338 { 00339 CValue* propval = GetParent()->GetProperty(m_propname); 00340 if (propval) 00341 m_localtime = propval->GetNumber(); 00342 00343 if (bNegativeEvent){ 00344 keepgoing=false; 00345 } 00346 } 00347 break; 00348 case ACT_ACTION_MOTION: 00349 break; 00350 case ACT_ACTION_LOOP_STOP: 00351 break; 00352 case ACT_ACTION_PINGPONG: 00353 if (wrap){ 00354 if (!(m_flag & ACT_FLAG_REVERSE)) 00355 m_localtime = m_endframe; 00356 else 00357 m_localtime = m_startframe; 00358 00359 m_flag &= ~ACT_FLAG_LOCKINPUT; 00360 m_flag ^= ACT_FLAG_REVERSE; //flip direction 00361 keepgoing = false; 00362 } 00363 break; 00364 case ACT_ACTION_FLIPPER: 00365 if (wrap){ 00366 if (!(m_flag & ACT_FLAG_REVERSE)){ 00367 m_localtime=m_endframe; 00368 //keepgoing = false; 00369 } 00370 else { 00371 m_localtime=m_startframe; 00372 keepgoing = false; 00373 } 00374 } 00375 break; 00376 case ACT_ACTION_LOOP_END: 00377 if (wrap){ 00378 if (m_flag & ACT_FLAG_KEYUP){ 00379 keepgoing = false; 00380 m_localtime = m_endframe; 00381 m_flag &= ~ACT_FLAG_LOCKINPUT; 00382 } 00383 SetStartTime(curtime); 00384 } 00385 break; 00386 case ACT_ACTION_PLAY: 00387 if (wrap){ 00388 m_localtime = m_endframe; 00389 keepgoing = false; 00390 m_flag &= ~ACT_FLAG_LOCKINPUT; 00391 } 00392 break; 00393 default: 00394 keepgoing = false; 00395 break; 00396 } 00397 00398 /* Set the property if its defined */ 00399 if (m_framepropname[0] != '\0') { 00400 CValue* propowner = GetParent(); 00401 CValue* oldprop = propowner->GetProperty(m_framepropname); 00402 CValue* newval = new CFloatValue(m_localtime); 00403 if (oldprop) { 00404 oldprop->SetValue(newval); 00405 } else { 00406 propowner->SetProperty(m_framepropname, newval); 00407 } 00408 newval->Release(); 00409 } 00410 00411 if (bNegativeEvent) 00412 m_blendframe=0.0f; 00413 00414 /* Apply the pose if necessary*/ 00415 if (apply) { 00416 00417 /* Priority test */ 00418 if (obj->SetActiveAction(this, priority, curtime)){ 00419 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); 00420 Key *key = NULL; 00421 00422 if (shape_deformer) 00423 key = shape_deformer->GetKey(); 00424 00425 if (!key) { 00426 // this could happen if the mesh was changed in the middle of an action 00427 // and the new mesh has no key, stop the action 00428 keepgoing = false; 00429 } 00430 else { 00431 ListBase tchanbase= {NULL, NULL}; 00432 00433 if (m_blendin && m_blendframe==0.0f){ 00434 // this is the start of the blending, remember the startup shape 00435 obj->GetShape(m_blendshape); 00436 m_blendstart = curtime; 00437 } 00438 00439 KeyBlock *kb; 00440 // We go through and clear out the keyblocks so there isn't any interference 00441 // from other shape actions 00442 for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next) 00443 kb->curval = 0.f; 00444 00445 animsys_evaluate_action(m_idptr, m_action, NULL, m_localtime); 00446 00447 // XXX - in 2.5 theres no way to do this. possibly not that important to support - Campbell 00448 if (0) { // XXX !execute_ipochannels(&tchanbase)) { 00449 // no update, this is possible if action does not match the keys, stop the action 00450 keepgoing = false; 00451 } 00452 else { 00453 // the key have changed, apply blending if needed 00454 if (m_blendin && (m_blendframe<m_blendin)){ 00455 newweight = (m_blendframe/(float)m_blendin); 00456 00457 BlendShape(key, 1.0f - newweight); 00458 00459 /* Increment current blending percentage */ 00460 m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate(); 00461 if (m_blendframe>m_blendin) 00462 m_blendframe = m_blendin; 00463 } 00464 m_lastUpdate = m_localtime; 00465 } 00466 BLI_freelistN(&tchanbase); 00467 } 00468 } 00469 else{ 00470 m_blendframe = 0.0f; 00471 } 00472 } 00473 00474 if (!keepgoing){ 00475 m_blendframe = 0.0f; 00476 } 00477 return keepgoing; 00478 }; 00479 00480 #ifdef WITH_PYTHON 00481 00482 /* ------------------------------------------------------------------------- */ 00483 /* Python functions */ 00484 /* ------------------------------------------------------------------------- */ 00485 00486 /* Integration hooks ------------------------------------------------------- */ 00487 00488 PyTypeObject BL_ShapeActionActuator::Type = { 00489 PyVarObject_HEAD_INIT(NULL, 0) 00490 "BL_ShapeActionActuator", 00491 sizeof(PyObjectPlus_Proxy), 00492 0, 00493 py_base_dealloc, 00494 0, 00495 0, 00496 0, 00497 0, 00498 py_base_repr, 00499 0,0,0,0,0,0,0,0,0, 00500 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00501 0,0,0,0,0,0,0, 00502 Methods, 00503 0, 00504 0, 00505 &SCA_IActuator::Type, 00506 0,0,0,0,0,0, 00507 py_base_new 00508 }; 00509 00510 00511 PyMethodDef BL_ShapeActionActuator::Methods[] = { 00512 {NULL,NULL} //Sentinel 00513 }; 00514 00515 PyAttributeDef BL_ShapeActionActuator::Attributes[] = { 00516 KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe), 00517 KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe), 00518 KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin), 00519 KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ShapeActionActuator, pyattr_get_action, pyattr_set_action), 00520 KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ShapeActionActuator, m_priority), 00521 KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ShapeActionActuator, m_localtime, CheckFrame), 00522 KX_PYATTRIBUTE_STRING_RW("propName", 0, MAX_PROP_NAME, false, BL_ShapeActionActuator, m_propname), 00523 KX_PYATTRIBUTE_STRING_RW("framePropName", 0, MAX_PROP_NAME, false, BL_ShapeActionActuator, m_framepropname), 00524 KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendframe, CheckBlendTime), 00525 KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ShapeActionActuator,m_playtype,CheckType), 00526 { NULL } //Sentinel 00527 }; 00528 00529 PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00530 { 00531 BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v); 00532 return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); 00533 } 00534 00535 int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00536 { 00537 BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v); 00538 /* exact copy of BL_ActionActuator's function from here down */ 00539 if (!PyUnicode_Check(value)) 00540 { 00541 PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action"); 00542 return PY_SET_ATTR_FAIL; 00543 } 00544 00545 bAction *action= NULL; 00546 STR_String val = _PyUnicode_AsString(value); 00547 00548 if (val != "") 00549 { 00550 action= (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val); 00551 if (action==NULL) 00552 { 00553 PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, action not found!"); 00554 return PY_SET_ATTR_FAIL; 00555 } 00556 } 00557 00558 self->SetAction(action); 00559 return PY_SET_ATTR_SUCCESS; 00560 00561 } 00562 00563 #endif // WITH_PYTHON