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