static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, int from_mix) { if(object_insert_shape_key(scene, ob, NULL, from_mix)) { Key *key= ob_get_key(ob); ob->shapenr= BLI_countlist(&key->block); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); } }
static Key *rna_ShapeKey_find_key(ID *id) { switch(GS(id->name)) { case ID_CU: return ((Curve*)id)->key; case ID_KE: return (Key*)id; case ID_LT: return ((Lattice*)id)->key; case ID_ME: return ((Mesh*)id)->key; case ID_OB: return ob_get_key((Object*)id); default: return NULL; } }
static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *UNUSED(editData), DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { Key *key= ob_get_key(ob); if(key && key->type == KEY_RELATIVE) deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0); }
static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Key *key= ptr->id.data; Object *ob; for(ob=bmain->object.first; ob; ob= ob->id.next) { if(ob_get_key(ob) == key) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT|ND_MODIFIER, ob); } } }
static int shape_key_move_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; int type= RNA_enum_get(op->ptr, "type"); Key *key= ob_get_key(ob); if(key) { KeyBlock *kb, *kb_other; int shapenr_act= ob->shapenr-1; int shapenr_swap= shapenr_act + type; kb= BLI_findlink(&key->block, shapenr_act); if((type==-1 && kb->prev==NULL) || (type==1 && kb->next==NULL)) { return OPERATOR_CANCELLED; } for(kb_other= key->block.first; kb_other; kb_other= kb_other->next) { if(kb_other->relative == shapenr_act) { kb_other->relative += type; } else if(kb_other->relative == shapenr_swap) { kb_other->relative -= type; } } if(type==-1) { /* move back */ kb_other= kb->prev; BLI_remlink(&key->block, kb); BLI_insertlinkbefore(&key->block, kb_other, kb); ob->shapenr--; } else { /* move next */ kb_other= kb->next; BLI_remlink(&key->block, kb); BLI_insertlinkafter(&key->block, kb_other, kb); ob->shapenr++; } } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; }
static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; Key *key= ob_get_key(ob); KeyBlock *kb= ob_get_keyblock(ob); if(!key || !kb) return OPERATOR_CANCELLED; for(kb=key->block.first; kb; kb=kb->next) kb->curval= 0.0f; DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; }
static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) { Key *key= ob_get_key(ob); KeyBlock *kb= ob_get_keyblock(ob); float scale[3][3]; (void)vertexCos; /* unused */ if(kb && kb->totelem==numVerts && kb!=key->refkey) { int a; if(ob->shapeflag & OB_SHAPE_LOCK) scale_m3_fl(scale, 1); else scale_m3_fl(scale, kb->curval); for(a=0; a<numVerts; a++) copy_m3_m3(defMats[a], scale); } deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0); }
static void deformMatricesEM(ModifierData *UNUSED(md), Object *ob, struct EditMesh *UNUSED(editData), DerivedMesh *UNUSED(derivedData), float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) { Key *key= ob_get_key(ob); KeyBlock *kb= ob_get_keyblock(ob); float scale[3][3]; (void)vertexCos; /* unused */ if(kb && kb->totelem==numVerts && kb!=key->refkey) { int a; scale_m3_fl(scale, kb->curval); for(a=0; a<numVerts; a++) copy_m3_m3(defMats[a], scale); } }
ModifierData *modifiers_getVirtualModifierList(Object *ob) { /* Kinda hacky, but should be fine since we are never * reentrant and avoid free hassles. */ static ArmatureModifierData amd; static CurveModifierData cmd; static LatticeModifierData lmd; static ShapeKeyModifierData smd; static int init = 1; ModifierData *md; if (init) { md = modifier_new(eModifierType_Armature); amd = *((ArmatureModifierData*) md); modifier_free(md); md = modifier_new(eModifierType_Curve); cmd = *((CurveModifierData*) md); modifier_free(md); md = modifier_new(eModifierType_Lattice); lmd = *((LatticeModifierData*) md); modifier_free(md); md = modifier_new(eModifierType_ShapeKey); smd = *((ShapeKeyModifierData*) md); modifier_free(md); amd.modifier.mode |= eModifierMode_Virtual; cmd.modifier.mode |= eModifierMode_Virtual; lmd.modifier.mode |= eModifierMode_Virtual; smd.modifier.mode |= eModifierMode_Virtual; init = 0; } md = ob->modifiers.first; if(ob->parent) { if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) { amd.object = ob->parent; amd.modifier.next = md; amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag; md = &amd.modifier; } else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) { cmd.object = ob->parent; cmd.defaxis = ob->trackflag + 1; cmd.modifier.next = md; md = &cmd.modifier; } else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) { lmd.object = ob->parent; lmd.modifier.next = md; md = &lmd.modifier; } } /* shape key modifier, not yet for curves */ if(ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) { if(ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE)) smd.modifier.mode |= eModifierMode_Editmode|eModifierMode_OnCage; else smd.modifier.mode &= ~eModifierMode_Editmode|eModifierMode_OnCage; smd.modifier.next = md; md = &smd.modifier; } return md; }
static int ED_object_shape_key_remove(bContext *C, Object *ob) { Main *bmain= CTX_data_main(C); KeyBlock *kb, *rkb; Key *key; //IpoCurve *icu; key= ob_get_key(ob); if(key==NULL) return 0; kb= BLI_findlink(&key->block, ob->shapenr-1); if(kb) { for(rkb= key->block.first; rkb; rkb= rkb->next) if(rkb->relative == ob->shapenr-1) rkb->relative= 0; BLI_remlink(&key->block, kb); key->totkey--; if(key->refkey== kb) { key->refkey= key->block.first; if(key->refkey) { /* apply new basis key on original data */ switch(ob->type) { case OB_MESH: key_to_mesh(key->refkey, ob->data); break; case OB_CURVE: case OB_SURF: key_to_curve(key->refkey, ob->data, BKE_curve_nurbs(ob->data)); break; case OB_LATTICE: key_to_latt(key->refkey, ob->data); break; } } } if(kb->data) MEM_freeN(kb->data); MEM_freeN(kb); for(kb= key->block.first; kb; kb= kb->next) if(kb->adrcode>=ob->shapenr) kb->adrcode--; #if 0 // XXX old animation system if(key->ipo) { for(icu= key->ipo->curve.first; icu; icu= icu->next) { if(icu->adrcode==ob->shapenr-1) { BLI_remlink(&key->ipo->curve, icu); free_ipo_curve(icu); break; } } for(icu= key->ipo->curve.first; icu; icu= icu->next) if(icu->adrcode>=ob->shapenr) icu->adrcode--; } #endif // XXX old animation system if(ob->shapenr>1) ob->shapenr--; } if(key->totkey==0) { if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL; else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL; else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL; free_libblock_us(&(bmain->key), key); } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return 1; }
static int object_shape_key_mirror(bContext *C, Object *ob) { KeyBlock *kb; Key *key; key= ob_get_key(ob); if(key==NULL) return 0; kb= BLI_findlink(&key->block, ob->shapenr-1); if(kb) { int i1, i2; float *fp1, *fp2; float tvec[3]; char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror"); if(ob->type==OB_MESH) { Mesh *me= ob->data; MVert *mv; mesh_octree_table(ob, NULL, NULL, 's'); for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) { i2= mesh_get_x_mirror_vert(ob, i1); if(i2==i1) { fp1= ((float *)kb->data) + i1*3; fp1[0] = -fp1[0]; tag_elem[i1]= 1; } else if(i2 != -1) { if(tag_elem[i1]==0 && tag_elem[i2]==0) { fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; copy_v3_v3(tvec, fp1); copy_v3_v3(fp1, fp2); copy_v3_v3(fp2, tvec); /* flip x axis */ fp1[0] = -fp1[0]; fp2[0] = -fp2[0]; } tag_elem[i1]= tag_elem[i2]= 1; } } mesh_octree_table(ob, NULL, NULL, 'e'); } else if (ob->type == OB_LATTICE) { Lattice *lt= ob->data; int i1, i2; float *fp1, *fp2; int u, v, w; /* half but found up odd value */ const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ; /* currently editmode isnt supported by mesh so * ignore here for now too */ /* if(lt->editlatt) lt= lt->editlatt->latt; */ for(w=0; w<lt->pntsw; w++) { for(v=0; v<lt->pntsv; v++) { for(u=0; u<pntsu_half; u++) { int u_inv= (lt->pntsu - 1) - u; float tvec[3]; if(u == u_inv) { i1= LT_INDEX(lt, u, v, w); fp1= ((float *)kb->data) + i1*3; fp1[0]= -fp1[0]; } else { i1= LT_INDEX(lt, u, v, w); i2= LT_INDEX(lt, u_inv, v, w); fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; copy_v3_v3(tvec, fp1); copy_v3_v3(fp1, fp2); copy_v3_v3(fp2, tvec); fp1[0]= -fp1[0]; fp2[0]= -fp2[0]; } } } } } MEM_freeN(tag_elem); } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return 1; }
/* This function is used to loop over the keyframe data in an Object */ static short ob_keyframes_loop(KeyframeEditData *ked, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag) { Key *key= ob_get_key(ob); /* sanity check */ if (ob == NULL) return 0; /* firstly, Object's own AnimData */ if (ob->adt) { if (adt_keyframes_loop(ked, ob->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } /* shapekeys */ if ((key && key->adt) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) { if (adt_keyframes_loop(ked, key->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } /* Add material keyframes */ if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) { int a; for (a=1; a <= ob->totcol; a++) { Material *ma= give_current_material(ob, a); /* there might not be a material */ if (ELEM(NULL, ma, ma->adt)) continue; /* add material's data */ if (adt_keyframes_loop(ked, ma->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } /* Add object data keyframes */ switch (ob->type) { case OB_CAMERA: /* ------- Camera ------------ */ { Camera *ca= (Camera *)ob->data; if ((ca->adt) && !(filterflag & ADS_FILTER_NOCAM)) { if (adt_keyframes_loop(ked, ca->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; case OB_LAMP: /* ---------- Lamp ----------- */ { Lamp *la= (Lamp *)ob->data; if ((la->adt) && !(filterflag & ADS_FILTER_NOLAM)) { if (adt_keyframes_loop(ked, la->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; case OB_CURVE: /* ------- Curve ---------- */ case OB_SURF: /* ------- Nurbs Surface ---------- */ case OB_FONT: /* ------- Text Curve ---------- */ { Curve *cu= (Curve *)ob->data; if ((cu->adt) && !(filterflag & ADS_FILTER_NOCUR)) { if (adt_keyframes_loop(ked, cu->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; case OB_MBALL: /* ------- MetaBall ---------- */ { MetaBall *mb= (MetaBall *)ob->data; if ((mb->adt) && !(filterflag & ADS_FILTER_NOMBA)) { if (adt_keyframes_loop(ked, mb->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; case OB_ARMATURE: /* ------- Armature ---------- */ { bArmature *arm= (bArmature *)ob->data; if ((arm->adt) && !(filterflag & ADS_FILTER_NOARM)) { if (adt_keyframes_loop(ked, arm->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; case OB_MESH: /* ------- Mesh ---------- */ { Mesh *me= (Mesh *)ob->data; if ((me->adt) && !(filterflag & ADS_FILTER_NOMESH)) { if (adt_keyframes_loop(ked, me->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; case OB_LATTICE: /* ---- Lattice ------ */ { Lattice *lt= (Lattice *)ob->data; if ((lt->adt) && !(filterflag & ADS_FILTER_NOLAT)) { if (adt_keyframes_loop(ked, lt->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } break; } /* Add Particle System Keyframes */ if ((ob->particlesystem.first) && !(filterflag & ADS_FILTER_NOPART)) { ParticleSystem *psys = ob->particlesystem.first; for(; psys; psys=psys->next) { if (ELEM(NULL, psys->part, psys->part->adt)) continue; if (adt_keyframes_loop(ked, psys->part->adt, key_ok, key_cb, fcu_cb, filterflag)) return 1; } } return 0; }
static void do_nla(Scene *scene, Object *ob, int blocktype) { bPose *tpose= NULL; Key *key= NULL; ListBase tchanbase={NULL, NULL}, chanbase={NULL, NULL}; bActionStrip *strip, *striplast=NULL, *stripfirst=NULL; float striptime, frametime, length, actlength; float blendfac, stripframe; float scene_cfra= BKE_curframe(scene); int doit, dostride; if(blocktype==ID_AR) { copy_pose(&tpose, ob->pose, 1); rest_pose(ob->pose); // potentially destroying current not-keyed pose } else { key= ob_get_key(ob); } /* check on extend to left or right, when no strip is hit by 'cfra' */ for (strip=ob->nlastrips.first; strip; strip=strip->next) { /* escape loop on a hit */ if( scene_cfra >= strip->start && scene_cfra <= strip->end + 0.1f) /* note 0.1 comes back below */ break; if(scene_cfra < strip->start) { if(stripfirst==NULL) stripfirst= strip; else if(stripfirst->start > strip->start) stripfirst= strip; } else if(scene_cfra > strip->end) { if(striplast==NULL) striplast= strip; else if(striplast->end < strip->end) striplast= strip; } } if(strip==NULL) { /* extend */ if(striplast) scene_cfra= striplast->end; else if(stripfirst) scene_cfra= stripfirst->start; } /* and now go over all strips */ for (strip=ob->nlastrips.first; strip; strip=strip->next){ doit=dostride= 0; if (strip->act && !(strip->flag & ACTSTRIP_MUTE)) { /* so theres an action */ /* Determine if the current frame is within the strip's range */ length = strip->end-strip->start; actlength = strip->actend-strip->actstart; striptime = (scene_cfra-(strip->start)) / length; stripframe = (scene_cfra-(strip->start)) ; if (striptime>=0.0){ if(blocktype==ID_AR) rest_pose(tpose); /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ if (striptime < 1.0f + 0.1f/length) { /* Handle path */ if ((strip->flag & ACTSTRIP_USESTRIDE) && (blocktype==ID_AR) && (ob->ipoflag & OB_DISABLE_PATH)==0){ Object *parent= get_parent_path(ob); if (parent) { Curve *cu = parent->data; float ctime, pdist; if (cu->flag & CU_PATH){ /* Ensure we have a valid path */ if(cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(scene, parent, 0); if(cu->path) { /* Find the position on the path */ ctime= bsystem_time(scene, ob, scene_cfra, 0.0); if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { /* correct for actions not starting on zero */ ctime= (ctime - strip->actstart)/cu->pathlen; CLAMP(ctime, 0.0, 1.0); } pdist = ctime*cu->path->totdist; if(tpose && strip->stridechannel[0]) { striptime= stridechannel_frame(parent, ob->size[0], strip, cu->path, pdist, tpose->stride_offset); } else { if (strip->stridelen) { striptime = pdist / strip->stridelen; striptime = (float)fmod (striptime+strip->actoffs, 1.0); } else striptime = 0; } frametime = (striptime * actlength) + strip->actstart; frametime= bsystem_time(scene, ob, frametime, 0.0); if(blocktype==ID_AR) { extract_pose_from_action (tpose, strip->act, frametime); } else if(blocktype==ID_OB) { extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); if(key) extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); } doit=dostride= 1; } } } } /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ else { /* Mod to repeat */ if(strip->repeat!=1.0f) { float cycle= striptime*strip->repeat; striptime = (float)fmod (cycle, 1.0f + 0.1f/length); cycle-= striptime; if(blocktype==ID_AR) cyclic_offs_bone(ob, tpose, strip, cycle); } frametime = (striptime * actlength) + strip->actstart; frametime= nla_time(scene, frametime, (float)strip->repeat); if(blocktype==ID_AR) { extract_pose_from_action (tpose, strip->act, frametime); } else if(blocktype==ID_OB) { extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); if(key) extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); } doit=1; } } /* Handle extend */ else { if (strip->flag & ACTSTRIP_HOLDLASTFRAME){ /* we want the strip to hold on the exact fraction of the repeat value */ frametime = actlength * (strip->repeat-(int)strip->repeat); if(frametime<=0.000001f) frametime= actlength; /* rounding errors... */ frametime= bsystem_time(scene, ob, frametime+strip->actstart, 0.0); if(blocktype==ID_AR) extract_pose_from_action (tpose, strip->act, frametime); else if(blocktype==ID_OB) { extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); if(key) extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); } /* handle cycle hold */ if(strip->repeat!=1.0f) { if(blocktype==ID_AR) cyclic_offs_bone(ob, tpose, strip, strip->repeat-1.0f); } doit=1; } } /* Handle blendin & blendout */ if (doit){ /* Handle blendin */ if (strip->blendin>0.0 && stripframe<=strip->blendin && scene_cfra>=strip->start){ blendfac = stripframe/strip->blendin; } else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && scene_cfra<=strip->end){ blendfac = (length-stripframe)/(strip->blendout); } else blendfac = 1; if(blocktype==ID_AR) {/* Blend this pose with the accumulated pose */ /* offset bone, for matching cycles */ blend_pose_offset_bone (strip, ob->pose, tpose, blendfac, strip->mode); blend_poses (ob->pose, tpose, blendfac, strip->mode); if(dostride) blend_pose_strides (ob->pose, tpose, blendfac, strip->mode); } else { blend_ipochannels(&chanbase, &tchanbase, blendfac, strip->mode); BLI_freelistN(&tchanbase); } } } } } if(blocktype==ID_OB) { execute_ipochannels(&chanbase); } else if(blocktype==ID_AR) { /* apply stride offset to object */ add_v3_v3(ob->obmat[3], ob->pose->stride_offset); } /* free */ if (tpose) free_pose(tpose); if(chanbase.first) BLI_freelistN(&chanbase); }