diff options
author | Matt Ebb <matt@mke3.net> | 2009-11-22 16:44:09 +0300 |
---|---|---|
committer | Matt Ebb <matt@mke3.net> | 2009-11-22 16:44:09 +0300 |
commit | 8be7b757e3a467e464f59d2de42ccac85d2cc47d (patch) | |
tree | 5760eacb5db3bf1c025680e96cd8379c2249177a /source/blender | |
parent | 8fdaa263c0a2e9e85a86aa9ef5159b1554bc9aab (diff) |
* New option on modifiers that don't change topology: Apply as Shape
Rather than applying the modifier to the object data, it will create a new shape
with the deformed vertices in there. Only mesh at the moment, other object
types on the todo.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_key.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_modifier.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 20 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/key.c | 43 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 6 | ||||
-rw-r--r-- | source/blender/editors/include/ED_object.h | 7 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 10 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 85 | ||||
-rw-r--r-- | source/blender/editors/object/object_shapekey.c | 43 |
10 files changed, 156 insertions, 65 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 076747cb845..514411e137d 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -54,6 +54,7 @@ struct Object; struct Scene; struct Mesh; struct EditMesh; +struct KeyBlock; struct ModifierData; struct MCol; struct ColorBand; @@ -318,6 +319,10 @@ int DM_release(DerivedMesh *dm); */ void DM_to_mesh(DerivedMesh *dm, struct Mesh *me); +/* utility function to convert a DerivedMesh to a shape key block + */ +void DM_to_meshkey(DerivedMesh *dm, struct Mesh *me, struct KeyBlock *kb); + /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is * zero for the layer type, so only layer types specified by the mask * will be copied diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index c81d837689f..d5bae00d32e 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -59,6 +59,7 @@ void key_curve_normal_weights(float t, float *data, int type); float *do_ob_key(struct Scene *scene, struct Object *ob); struct Key *ob_get_key(struct Object *ob); +struct KeyBlock *add_keyblock(struct Scene *scene, struct Key *key); struct KeyBlock *ob_get_keyblock(struct Object *ob); struct KeyBlock *ob_get_reference_keyblock(struct Object *ob); struct KeyBlock *key_get_keyblock(struct Key *key, int index); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 245db7e35ff..c30bfa3e247 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -281,6 +281,7 @@ int modifier_dependsOnTime(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md); int modifier_couldBeCage(struct ModifierData *md); int modifier_isDeformer(struct ModifierData *md); +int modifier_sameTopology(ModifierData *md); int modifier_isEnabled(struct ModifierData *md, int required_mode); void modifier_setError(struct ModifierData *md, char *format, ...); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index f9abaa9da02..209e4610c6a 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -277,6 +277,26 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) *me = tmp; } +void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb) +{ + int a, totvert = dm->getNumVerts(dm); + float *fp; + MVert *mvert; + + if(totvert==0 || me->totvert==0 || me->totvert!=totvert) return; + + if(kb->data) MEM_freeN(kb->data); + kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data"); + kb->totelem= totvert; + + fp= kb->data; + mvert=dm->getVertDataArray(dm, CD_MVERT); + + for(a=0; a<kb->totelem; a++, fp+=3, mvert++) { + VECCOPY(fp, mvert->co); + } +} + void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask) { CustomData_set_only_copy(&dm->vertData, mask); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 3822e0322f7..c7b79756263 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1395,6 +1395,49 @@ Key *ob_get_key(Object *ob) return NULL; } +KeyBlock *add_keyblock(Scene *scene, Key *key) +{ + KeyBlock *kb; + float curpos= -0.1; + int tot; + + kb= key->block.last; + if(kb) curpos= kb->pos; + + kb= MEM_callocN(sizeof(KeyBlock), "Keyblock"); + BLI_addtail(&key->block, kb); + kb->type= KEY_CARDINAL; + + tot= BLI_countlist(&key->block); + if(tot==1) strcpy(kb->name, "Basis"); + else sprintf(kb->name, "Key %d", tot-1); + + // XXX this is old anim system stuff? (i.e. the 'index' of the shapekey) + kb->adrcode= tot-1; + + key->totkey++; + if(key->totkey==1) key->refkey= kb; + + kb->slidermin= 0.0f; + kb->slidermax= 1.0f; + + // XXX kb->pos is the confusing old horizontal-line RVK crap in old IPO Editor... + if(key->type == KEY_RELATIVE) + kb->pos= curpos+0.1; + else { +#if 0 // XXX old animation system + curpos= bsystem_time(scene, 0, (float)CFRA, 0.0); + if(calc_ipo_spec(key->ipo, KEY_SPEED, &curpos)==0) { + curpos /= 100.0; + } + kb->pos= curpos; + + sort_keys(key); +#endif // XXX old animation system + } + return kb; +} + /* only the active keyblock */ KeyBlock *ob_get_keyblock(Object *ob) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index ed7fbe58ea4..b5e0ca9ea5c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -8924,6 +8924,12 @@ int modifier_couldBeCage(ModifierData *md) modifier_supportsMapping(md)); } +int modifier_sameTopology(ModifierData *md) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + return ( mti->type == eModifierTypeType_OnlyDeform || mti->type == eModifierTypeType_Nonconstructive); +} + void modifier_setError(ModifierData *md, char *format, ...) { char buffer[2048]; diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 8bc7fc8c4d6..e48a98a65f1 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -114,12 +114,17 @@ void key_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb) void curve_to_key(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); /* object_modifier.c */ +enum { + MODIFIER_APPLY_DATA=1, + MODIFIER_APPLY_SHAPE, +} eModifier_Apply_Mode; + struct ModifierData *ED_object_modifier_add(struct ReportList *reports, struct Scene *scene, struct Object *ob, int type); int ED_object_modifier_remove(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md); int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md); int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md); int ED_object_modifier_convert(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md); -int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md); +int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md, int mode); int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md); #endif /* ED_OBJECT_H */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index dbf5eb1d0ea..c263729f4fe 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -656,7 +656,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i uiLayout *box; box= uiLayoutBox(column); - row= uiLayoutRow(box, 1); + row= uiLayoutRow(box, 0); if(!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) { /* only here obdata, the rest of modifiers is ob level */ @@ -669,8 +669,12 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i if(ELEM3(psys->part->ren_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) uiItemO(row, "Convert", 0, "OBJECT_OT_modifier_convert"); } - else - uiItemO(row, "Apply", 0, "OBJECT_OT_modifier_apply"); + else + uiItemEnumO(row, "Apply", 0, "OBJECT_OT_modifier_apply", "apply_as", MODIFIER_APPLY_DATA); + + if (modifier_sameTopology(md)) + uiItemEnumO(row, "Apply as Shape", 0, "OBJECT_OT_modifier_apply", "apply_as", MODIFIER_APPLY_SHAPE); + uiBlockClearButLock(block); uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index f32d4e7efbd..58f2ed443ca 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -33,6 +33,7 @@ #include "DNA_action_types.h" #include "DNA_curve_types.h" +#include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -51,6 +52,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_mesh.h" #include "BKE_modifier.h" @@ -66,6 +68,7 @@ #include "RNA_enum_types.h" #include "ED_armature.h" +#include "ED_object.h" #include "ED_screen.h" #include "WM_api.h" @@ -328,7 +331,7 @@ int ED_object_modifier_convert(ReportList *reports, Scene *scene, Object *ob, Mo return 1; } -int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md) +int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode) { DerivedMesh *dm; Mesh *me = ob->data; @@ -346,27 +349,64 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected."); if (ob->type==OB_MESH) { - if(me->key) { - BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys"); - return 0; + if (mode == MODIFIER_APPLY_SHAPE) { + Key *key=me->key; + KeyBlock *kb; + int newkey=0; + + if(!modifier_sameTopology(md)) { + BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes"); + return 0; + } + mesh_pmv_off(ob, me); + + dm = mesh_create_derived_for_modifier(scene, ob, md); + if (!dm) { + BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply"); + return 0; + } + + if(key == NULL) { + key= me->key= add_key((ID *)me); + key->type= KEY_RELATIVE; + newkey= 1; + } + kb= add_keyblock(scene, key); + + if (newkey) { + /* if that was the first key block added, then it was the basis. + * Initialise it with the mesh, and add another for the modifier */ + mesh_to_key(me, kb); + kb= add_keyblock(scene, key); + } + DM_to_meshkey(dm, me, kb); + converted = 1; + + dm->release(dm); } - - mesh_pmv_off(ob, me); + else { /* MODIFIER_APPLY_DATA */ + if( me->key) { + BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys"); + return 0; + } + + mesh_pmv_off(ob, me); - /* Multires: ensure that recent sculpting is applied */ - if(md->type == eModifierType_Multires) - multires_force_update(ob); + /* Multires: ensure that recent sculpting is applied */ + if(md->type == eModifierType_Multires) + multires_force_update(ob); - dm = mesh_create_derived_for_modifier(scene, ob, md); - if (!dm) { - BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply"); - return 0; - } + dm = mesh_create_derived_for_modifier(scene, ob, md); + if (!dm) { + BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply"); + return 0; + } - DM_to_mesh(dm, me); - converted = 1; + DM_to_mesh(dm, me); + converted = 1; - dm->release(dm); + dm->release(dm); + } } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -598,8 +638,9 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); Object *ob= ptr.id.data; ModifierData *md= ptr.data; + int apply_as= RNA_enum_get(op->ptr, "apply_as"); - if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md)) + if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) return OPERATOR_CANCELLED; DAG_id_flush_update(&ob->id, OB_RECALC_DATA); @@ -608,6 +649,11 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static EnumPropertyItem modifier_apply_as_items[] = { + {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"}, + {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"}, + {0, NULL, 0, NULL, NULL}}; + void OBJECT_OT_modifier_apply(wmOperatorType *ot) { ot->name= "Apply Modifier"; @@ -615,11 +661,14 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) ot->idname= "OBJECT_OT_modifier_apply"; ot->poll= ED_operator_object_active; + //ot->invoke= WM_menu_invoke; ot->exec= modifier_apply_exec; ot->poll= modifier_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry"); } /************************ convert modifier operator *********************/ diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 878c61aac48..f8eff578839 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -119,49 +119,6 @@ void key_to_mesh(KeyBlock *kb, Mesh *me) } } -static KeyBlock *add_keyblock(Scene *scene, Key *key) -{ - KeyBlock *kb; - float curpos= -0.1; - int tot; - - kb= key->block.last; - if(kb) curpos= kb->pos; - - kb= MEM_callocN(sizeof(KeyBlock), "Keyblock"); - BLI_addtail(&key->block, kb); - kb->type= KEY_CARDINAL; - - tot= BLI_countlist(&key->block); - if(tot==1) strcpy(kb->name, "Basis"); - else sprintf(kb->name, "Key %d", tot-1); - - // XXX this is old anim system stuff? (i.e. the 'index' of the shapekey) - kb->adrcode= tot-1; - - key->totkey++; - if(key->totkey==1) key->refkey= kb; - - kb->slidermin= 0.0f; - kb->slidermax= 1.0f; - - // XXX kb->pos is the confusing old horizontal-line RVK crap in old IPO Editor... - if(key->type == KEY_RELATIVE) - kb->pos= curpos+0.1; - else { -#if 0 // XXX old animation system - curpos= bsystem_time(scene, 0, (float)CFRA, 0.0); - if(calc_ipo_spec(key->ipo, KEY_SPEED, &curpos)==0) { - curpos /= 100.0; - } - kb->pos= curpos; - - sort_keys(key); -#endif // XXX old animation system - } - return kb; -} - static void insert_meshkey(Scene *scene, Object *ob) { Mesh *me= ob->data; |