static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) { bAnimContext ac; SpaceNla *snla; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* ensure that filters are set so that the effect will be immediately visible */ snla = (SpaceNla *)ac.sl; if (snla && snla->ads) { snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT; } /* operate on selected objects... */ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { /* ensure that object has AnimData... that's all */ BKE_animdata_add_id(&ob->id); }
/* Get (or add relevant data to be able to do so) F-Curve from the driver stack, * for the given Animation Data block. This assumes that all the destinations are valid. * * - add: 0 - don't add anything if not found, * 1 - add new Driver FCurve (with keyframes for visual tweaking), * 2 - add new Driver FCurve (with generator, for script backwards compatibility) * -1 - add new Driver FCurve without driver stuff (for pasting) */ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add) { AnimData *adt; FCurve *fcu; /* sanity checks */ if (ELEM(NULL, id, rna_path)) { return NULL; } /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if ((adt == NULL) && (add)) { adt = BKE_animdata_add_id(id); } if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ return NULL; } /* try to find f-curve matching for this setting * - add if not found and allowed to add one * TODO: add auto-grouping support? how this works will need to be resolved */ fcu = list_find_fcurve(&adt->drivers, rna_path, array_index); if ((fcu == NULL) && (add)) { /* use default settings to make a F-Curve */ fcu = MEM_callocN(sizeof(FCurve), "FCurve"); fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; /* store path - make copy, and store that */ fcu->rna_path = BLI_strdup(rna_path); fcu->array_index = array_index; /* If add is negative, don't init this data yet, * since it will be filled in by the pasted driver. */ if (add > 0) { BezTriple *bezt; size_t i; /* add some new driver data */ fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); /* F-Modifier or Keyframes? */ // FIXME: replace these magic numbers with defines if (add == 2) { /* Python API Backwards compatibility hack: * Create FModifier so that old scripts won't break * for now before 2.7 series -- (September 4, 2013) */ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu); } else { /* add 2 keyframes so that user has something to work with * - These are configured to 0,0 and 1,1 to give a 1-1 mapping * which can be easily tweaked from there. */ insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); /* configure this curve to extrapolate */ for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) { bezt->h1 = bezt->h2 = HD_VECT; } fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; calchandles_fcurve(fcu); } } /* just add F-Curve to end of driver list */ BLI_addtail(&adt->drivers, fcu); } /* return the F-Curve */ return fcu; }
static AnimData * rna_ID_animation_data_create(ID *id, Main *bmain) { AnimData *adt = BKE_animdata_add_id(id); DAG_relations_tag_update(bmain); return adt; }
// this generates ipo curves for position, rotation, allowing to use game physics in animation void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) { KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; for (i = 0; i < numScenes; i++) { KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); CListValue *parentList = scene->GetObjectList(); int numObjects = parentList->GetCount(); int g; for (g = 0; g < numObjects; g++) { KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); Object *blenderObject = gameObj->GetBlenderObject(); if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) { if (blenderObject->adt == NULL) BKE_animdata_add_id(&blenderObject->id); if (blenderObject->adt) { const MT_Point3 &position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation(); position.getValue(blenderObject->loc); float tmat[3][3]; for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) tmat[r][c] = (float)orn[c][r]; mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); insert_keyframe(NULL, &blenderObject->id, NULL, NULL, "location", -1, (float)frameNumber, INSERTKEY_FAST); insert_keyframe(NULL, &blenderObject->id, NULL, NULL, "rotation_euler", -1, (float)frameNumber, INSERTKEY_FAST); #if 0 const MT_Point3& position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); float eulerAngles[3]; float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f}; float tmat[3][3]; // XXX animato Ipo* ipo = blenderObject->ipo; //create the curves, if not existing, set linear if new IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu_lx) { icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); if (icu_lx) icu_lx->ipo = IPO_LIN; } IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu_ly) { icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); if (icu_ly) icu_ly->ipo = IPO_LIN; } IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu_lz) { icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); if (icu_lz) icu_lz->ipo = IPO_LIN; } IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu_rx) { icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); if (icu_rx) icu_rx->ipo = IPO_LIN; } IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu_ry) { icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); if (icu_ry) icu_ry->ipo = IPO_LIN; } IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu_rz) { icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); if (icu_rz) icu_rz->ipo = IPO_LIN; } if (icu_rx) eulerAnglesOld[0] = eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); if (icu_ry) eulerAnglesOld[1] = eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); if (icu_rz) eulerAnglesOld[2] = eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) tmat[r][c] = orn[c][r]; // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul mat3_to_compatible_eul( eulerAngles, eulerAnglesOld,tmat); //eval_icu for (int x = 0; x < 3; x++) eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0); //fill the curves with data if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1); if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1); if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1); if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1); if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1); if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1); // Handles are corrected at the end, testhandles_ipocurve isn't needed yet #endif } } } } }