void ui_but_anim_autokey(uiBut *but, Scene *scene, float cfra) { ID *id; bAction *action; FCurve *fcu; int driven; fcu= ui_but_get_fcurve(but, &action, &driven); if(fcu && !driven) { id= but->rnapoin.id.data; // TODO: this should probably respect the keyingset only option for anim if(autokeyframe_cfra_can_key(scene, id)) { short flag = 0; if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; if (IS_AUTOKEY_MODE(scene, EDITKEYS)) flag |= INSERTKEY_REPLACE; fcu->flag &= ~FCURVE_SELECTED; insert_keyframe(id, action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); } } }
PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw) { /* args, pyrna_struct_keyframe_parse handles these */ const char *path_full = NULL; int index = -1; float cfra = FLT_MAX; const char *group_name = NULL; int options = 0; PYRNA_STRUCT_CHECK_OBJ(self); if (pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name, &options) == -1) { return NULL; } else { short result; ReportList reports; BKE_reports_init(&reports, RPT_STORE); result = insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, options); MEM_freeN((void *)path_full); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) return NULL; return PyBool_FromLong(result); } }
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) { ID *id; bAction *action; FCurve *fcu; bool driven; fcu = ui_but_get_fcurve(but, NULL, &action, &driven); if (fcu && !driven) { id = but->rnapoin.id.data; /* TODO: this should probably respect the keyingset only option for anim */ if (autokeyframe_cfra_can_key(scene, id)) { ReportList *reports = CTX_wm_reports(C); short flag = ANIM_get_keyframing_flags(scene, 1); fcu->flag &= ~FCURVE_SELECTED; /* Note: We use but->rnaindex instead of fcu->array_index, * because a button may control all items of an array at once. * E.g., color wheels (see T42567). */ BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1)); insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, but->rnaindex, cfra, flag); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } }
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) { ID *id; bAction *action; FCurve *fcu; bool driven; bool special; fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special); if (fcu == NULL) return; if (special) { /* NLA Strip property */ if (IS_AUTOKEY_ON(scene)) { ReportList *reports = CTX_wm_reports(C); ToolSettings *ts = scene->toolsettings; insert_keyframe_direct(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 0); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } else if (driven) { /* Driver - Try to insert keyframe using the driver's input as the frame, * making it easier to set up corrective drivers */ if (IS_AUTOKEY_ON(scene)) { ReportList *reports = CTX_wm_reports(C); ToolSettings *ts = scene->toolsettings; insert_keyframe_direct(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } else { id = but->rnapoin.id.data; /* TODO: this should probably respect the keyingset only option for anim */ if (autokeyframe_cfra_can_key(scene, id)) { ReportList *reports = CTX_wm_reports(C); ToolSettings *ts = scene->toolsettings; short flag = ANIM_get_keyframing_flags(scene, 1); fcu->flag &= ~FCURVE_SELECTED; /* Note: We use but->rnaindex instead of fcu->array_index, * because a button may control all items of an array at once. * E.g., color wheels (see T42567). */ BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1)); insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, but->rnaindex, cfra, ts->keyframe_type, flag); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } }
/* this function is responsible for snapping keyframes to frame-times */ static void insert_action_keys(bAnimContext *ac, short mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; ReportList *reports = ac->reports; Scene *scene = ac->scene; short flag = 0; /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); if (mode == 2) filter |= ANIMFILTER_SEL; else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED; ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* init keyframing flag */ flag = ANIM_get_keyframing_flags(scene, 1); /* insert keyframes */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->key_data; float cfra; /* adjust current frame for NLA-scaling */ if (adt) cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; /* read value from property the F-Curve represents, or from the curve only? * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone, * so it's easier for now to just read the F-Curve directly. * (TODO: add the full-blown PointerRNA relative parsing case here...) */ if (ale->id && !ale->owner) insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); else insert_vert_fcurve(fcu, cfra, fcu->curval, 0); ale->update |= ANIM_UPDATE_DEFAULT; } ANIM_animdata_update(ac, &anim_data); ANIM_animdata_freelist(&anim_data); }
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) { ID *id; bAction *action; FCurve *fcu; bool driven; bool special; fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special); if (fcu == NULL) return; if (special) { /* NLA Strip property */ if (IS_AUTOKEY_ON(scene)) { ReportList *reports = CTX_wm_reports(C); PointerRNA ptr = {{NULL}}; PropertyRNA *prop = NULL; int index; UI_context_active_but_prop_get(C, &ptr, &prop, &index); insert_keyframe_direct(reports, ptr, prop, fcu, cfra, 0); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } else if (!driven) { id = but->rnapoin.id.data; /* TODO: this should probably respect the keyingset only option for anim */ if (autokeyframe_cfra_can_key(scene, id)) { ReportList *reports = CTX_wm_reports(C); short flag = ANIM_get_keyframing_flags(scene, 1); fcu->flag &= ~FCURVE_SELECTED; /* Note: We use but->rnaindex instead of fcu->array_index, * because a button may control all items of an array at once. * E.g., color wheels (see T42567). */ BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1)); insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, but->rnaindex, cfra, flag); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } }
/* this function is responsible for snapping keyframes to frame-times */ static void insert_action_keys(bAnimContext *ac, short mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; Scene *scene= ac->scene; float cfra= (float)CFRA; short flag = 0; /* filter data */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); if (mode == 2) filter |= ANIMFILTER_SEL; else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED; ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* init keyframing flag */ if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; if (IS_AUTOKEY_MODE(scene, EDITKEYS)) flag |= INSERTKEY_REPLACE; /* insert keyframes */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(ac, ale); FCurve *fcu= (FCurve *)ale->key_data; /* adjust current frame for NLA-scaling */ if (adt) cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra= (float)CFRA; /* if there's an id */ if (ale->id) insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); else insert_vert_fcurve(fcu, cfra, fcu->curval, 0); } BLI_freelistN(&anim_data); }
/* this function is responsible for snapping keyframes to frame-times */ static void insert_action_keys(bAnimContext *ac, short mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; ReportList *reports = ac->reports; Scene *scene = ac->scene; short flag = 0; /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); if (mode == 2) filter |= ANIMFILTER_SEL; else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED; ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* init keyframing flag */ flag = ANIM_get_keyframing_flags(scene, 1); /* insert keyframes */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->key_data; float cfra; /* adjust current frame for NLA-scaling */ if (adt) cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; /* if there's an id */ if (ale->id) insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); else insert_vert_fcurve(fcu, cfra, fcu->curval, 0); } BLI_freelistN(&anim_data); }
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) { ID *id; bAction *action; FCurve *fcu; bool driven; fcu = ui_but_get_fcurve(but, &action, &driven); if (fcu && !driven) { id = but->rnapoin.id.data; /* TODO: this should probably respect the keyingset only option for anim */ if (autokeyframe_cfra_can_key(scene, id)) { ReportList *reports = CTX_wm_reports(C); short flag = ANIM_get_keyframing_flags(scene, 1); fcu->flag &= ~FCURVE_SELECTED; insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } }
/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets. * Returns the number of channels that keyframes were added to */ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) { Scene *scene = CTX_data_scene(C); ReportList *reports = CTX_wm_reports(C); KS_Path *ksp; int kflag = 0, success = 0; char *groupname = NULL; /* sanity checks */ if (ks == NULL) return 0; /* get flags to use */ if (mode == MODIFYKEY_MODE_INSERT) { /* use KeyingSet's flags as base */ kflag = ks->keyingflag; /* suppliment with info from the context */ kflag |= ANIM_get_keyframing_flags(scene, 1); } else if (mode == MODIFYKEY_MODE_DELETE) kflag = 0; /* if relative Keying Sets, poll and build up the paths */ success = ANIM_validate_keyingset(C, dsources, ks); if (success != 0) { /* return error code if failed */ return success; } /* apply the paths as specified in the KeyingSet now */ for (ksp = ks->paths.first; ksp; ksp = ksp->next) { int arraylen, i; short kflag2; /* skip path if no ID pointer is specified */ if (ksp->id == NULL) { BKE_reportf(reports, RPT_WARNING, "Skipping path in keying set, as it has no ID (KS = '%s', path = '%s[%d]')", ks->name, ksp->rna_path, ksp->array_index); continue; } /* since keying settings can be defined on the paths too, extend the path before using it */ kflag2 = (kflag | ksp->keyingflag); /* get pointer to name of group to add channels to */ if (ksp->groupmode == KSP_GROUP_NONE) groupname = NULL; else if (ksp->groupmode == KSP_GROUP_KSNAME) groupname = ks->name; else groupname = ksp->group; /* init arraylen and i - arraylen should be greater than i so that * normal non-array entries get keyframed correctly */ i = ksp->array_index; arraylen = i; /* get length of array if whole array option is enabled */ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) { PointerRNA id_ptr, ptr; PropertyRNA *prop; RNA_id_pointer_create(ksp->id, &id_ptr); if (RNA_path_resolve_property(&id_ptr, ksp->rna_path, &ptr, &prop)) arraylen = RNA_property_array_length(&ptr, prop); } /* we should do at least one step */ if (arraylen == i) arraylen++; /* for each possible index, perform operation * - assume that arraylen is greater than index */ for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) success += insert_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); else if (mode == MODIFYKEY_MODE_DELETE) success += delete_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); } /* set recalc-flags */ switch (GS(ksp->id->name)) { case ID_OB: /* Object (or Object-Related) Keyframes */ { Object *ob = (Object *)ksp->id; // XXX: only object transforms? DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; } } /* send notifiers for updates (this doesn't require context to work!) */ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } /* return the number of channels successfully affected */ return success; }
///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->IsDynamic()) { //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); if (blenderObject->adt==NULL) BKE_id_add_animdata(&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 } } } } }