Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object/object_relations.c')
-rw-r--r--source/blender/editors/object/object_relations.c138
1 files changed, 108 insertions, 30 deletions
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 446c0a51ed5..58c6959d6f0 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -423,29 +423,92 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
/********************** Clear Parent Operator ******************* */
+typedef enum eObClearParentTypes {
+ CLEAR_PARENT_ALL = 0,
+ CLEAR_PARENT_KEEP_TRANSFORM,
+ CLEAR_PARENT_INVERSE
+} eObClearParentTypes;
+
EnumPropertyItem prop_clear_parent_types[] = {
- {0, "CLEAR", 0, "Clear Parent", ""},
- {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation", ""},
- {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
+ {CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent", ""},
+ {CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation", ""},
+ {CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
{0, NULL, 0, NULL, NULL}
};
-void ED_object_parent_clear(Object *ob, int type)
+/* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */
+static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
{
+ if (ELEM3(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
+ ModifierData *md, *mdn;
+
+ /* assume that we only need to remove the first instance of matching deform modifier here */
+ for (md = ob->modifiers.first; md; md = mdn) {
+ short free = FALSE;
+
+ mdn = md->next;
+
+ /* need to match types (modifier + parent) and references */
+ if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object == par) {
+ free = TRUE;
+ }
+ }
+ else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ if (lmd->object == par) {
+ free = TRUE;
+ }
+ }
+ else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) {
+ CurveModifierData *cmd = (CurveModifierData *)md;
+ if (cmd->object == par) {
+ free = TRUE;
+ }
+ }
+
+ /* free modifier if match */
+ if (free) {
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+ }
+ }
+ }
+}
+void ED_object_parent_clear(Object *ob, int type)
+{
if (ob->parent == NULL)
return;
+
+ switch (type) {
+ case CLEAR_PARENT_ALL:
+ {
+ /* for deformers, remove corresponding modifiers to prevent a large number of modifiers building up */
+ object_remove_parent_deform_modifiers(ob, ob->parent);
+
+ /* clear parenting relationship completely */
+ ob->parent = NULL;
+ }
+ break;
- if (type == 0) {
- ob->parent = NULL;
- }
- else if (type == 1) {
- ob->parent = NULL;
- BKE_object_apply_mat4(ob, ob->obmat, TRUE, FALSE);
- }
- else if (type == 2)
- unit_m4(ob->parentinv);
+ case CLEAR_PARENT_KEEP_TRANSFORM:
+ {
+ /* remove parent, and apply the parented transform result as object's local transforms */
+ ob->parent = NULL;
+ BKE_object_apply_mat4(ob, ob->obmat, TRUE, FALSE);
+ }
+ break;
+ case CLEAR_PARENT_INVERSE:
+ {
+ /* object stays parented, but the parent inverse (i.e. offset from parent to retain binding state) is cleared */
+ unit_m4(ob->parentinv);
+ }
+ break;
+ }
+
ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
}
@@ -559,13 +622,13 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
/* fall back on regular parenting now (for follow only) */
if (partype == PAR_FOLLOW)
partype = PAR_OBJECT;
- }
+ }
}
else if (partype == PAR_BONE) {
pchan = BKE_pose_channel_active(par);
if (pchan == NULL) {
- BKE_report(reports, RPT_ERROR, "No active Bone");
+ BKE_report(reports, RPT_ERROR, "No active bone");
return 0;
}
}
@@ -604,25 +667,40 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
* NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers
*/
ob->partype = PAROBJECT; /* note, dna define, not operator property */
- //ob->partype= PARSKEL; /* note, dna define, not operator property */
+ //ob->partype = PARSKEL; /* note, dna define, not operator property */
- /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses */
+ /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
+ * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by
+ * assuming that the parent is selected too...
+ */
// XXX currently this should only happen for meshes, curves, surfaces, and lattices - this stuff isn't available for metas yet
if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
ModifierData *md;
switch (partype) {
case PAR_CURVE: /* curve deform */
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
- ((CurveModifierData *)md)->object = par;
+ if ( modifiers_isDeformedByCurve(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
+ if (md) {
+ ((CurveModifierData *)md)->object = par;
+ }
+ }
break;
case PAR_LATTICE: /* lattice deform */
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice);
- ((LatticeModifierData *)md)->object = par;
+ if (modifiers_isDeformedByLattice(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice);
+ if (md) {
+ ((LatticeModifierData *)md)->object = par;
+ }
+ }
break;
default: /* armature deform */
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature);
- ((ArmatureModifierData *)md)->object = par;
+ if (modifiers_isDeformedByArmature(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature);
+ if (md) {
+ ((ArmatureModifierData *)md)->object = par;
+ }
+ }
break;
}
}
@@ -958,7 +1036,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
if (CTX_data_edit_object(C)) {
- BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
return OPERATOR_CANCELLED;
}
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -1182,7 +1260,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op)
base->object->lay = lay;
base->object->flag &= ~SELECT;
base->flag &= ~SELECT;
- /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */
+ /* if (base->object->type == OB_LAMP) is_lamp = TRUE; */
}
CTX_DATA_END;
}
@@ -1195,7 +1273,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op)
local = base->lay & 0xFF000000;
base->lay = lay + local;
base->object->lay = lay;
- /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */
+ /* if (base->object->type == OB_LAMP) is_lamp = TRUE; */
}
CTX_DATA_END;
}
@@ -1272,17 +1350,17 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
if (scene_to == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Couldn't find scene");
+ BKE_report(op->reports, RPT_ERROR, "Could not find scene");
return OPERATOR_CANCELLED;
}
if (scene_to == CTX_data_scene(C)) {
- BKE_report(op->reports, RPT_ERROR, "Can't link objects into the same scene");
+ BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
return OPERATOR_CANCELLED;
}
if (scene_to->id.lib) {
- BKE_report(op->reports, RPT_ERROR, "Can't link objects into a linked scene");
+ BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
return OPERATOR_CANCELLED;
}
@@ -1632,7 +1710,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
break;
case OB_MESH:
ob->data = BKE_mesh_copy(ob->data);
- //me= ob->data;
+ //me = ob->data;
//if (me && me->key)
// ipo_idnew(me->key->ipo); /* drivers */
break;