Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_constraint.c
| Show First 20 Lines • Show All 865 Lines • ▼ Show 20 Lines | void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot) | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| /* properties */ | /* properties */ | ||||
| edit_constraint_properties(ot); | edit_constraint_properties(ot); | ||||
| } | } | ||||
| /* ------------- Child-Of Constraint ------------------ */ | /* ------------- Child-Of Constraint ------------------ */ | ||||
| static void child_get_inverse_matrix_owner_bone( | |||||
| Depsgraph *depsgraph, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4]) | |||||
| { | |||||
| /* For bone owner we want to do this in evaluated domain. | |||||
| * BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene | |||||
| * and copying new evaluated stuff back to original. | |||||
| */ | |||||
| Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); | |||||
| bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF); | |||||
| /* nullify inverse matrix first */ | |||||
| unit_m4(invmat); | |||||
| bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval); | |||||
| /* try to find a pose channel - assume that this is the constraint owner */ | |||||
| /* TODO: get from context instead? */ | |||||
| if (ob_eval && ob_eval->pose && pchan_eval) { | |||||
| bConstraint *con_last; | |||||
| /* calculate/set inverse matrix: | |||||
| * We just calculate all transform-stack eval up to but not including this constraint. | |||||
| * This is because inverse should just inverse correct for just the constraint's influence | |||||
| * when it gets applied; that is, at the time of application, we don't know anything about | |||||
| * what follows. | |||||
| */ | |||||
| float imat[4][4], tmat[4][4]; | |||||
| float pmat[4][4]; | |||||
| /* make sure we passed the correct constraint */ | |||||
| BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1); | |||||
| /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above), | |||||
| * to use as baseline ("pmat") to derive delta from. This extra calc saves users | |||||
| * from having pressing "Clear Inverse" first | |||||
| */ | |||||
| BKE_pose_where_is(depsgraph, scene, ob_eval); | |||||
| copy_m4_m4(pmat, pchan_eval->pose_mat); | |||||
| /* 2. knock out constraints starting from this one */ | |||||
| con_last = pchan_eval->constraints.last; | |||||
| pchan_eval->constraints.last = con_eval->prev; | |||||
| if (con_eval->prev) { | |||||
| /* new end must not point to this one, else this chain cutting is useless */ | |||||
| con_eval->prev->next = NULL; | |||||
| } | |||||
| else { | |||||
| /* constraint was first */ | |||||
| pchan_eval->constraints.first = NULL; | |||||
| } | |||||
| /* 3. solve pose without disabled constraints */ | |||||
| BKE_pose_where_is(depsgraph, scene, ob_eval); | |||||
| /* 4. determine effect of constraint by removing the newly calculated | |||||
| * pchan->pose_mat from the original pchan->pose_mat, thus determining | |||||
| * the effect of the constraint | |||||
| */ | |||||
| invert_m4_m4(imat, pchan_eval->pose_mat); | |||||
| mul_m4_m4m4(tmat, pmat, imat); | |||||
| invert_m4_m4(invmat, tmat); | |||||
| /* 5. restore constraints */ | |||||
| pchan_eval->constraints.last = con_last; | |||||
| if (con_eval->prev) { | |||||
| /* hook up prev to this one again */ | |||||
| con_eval->prev->next = con_eval; | |||||
| } | |||||
| else { | |||||
| /* set as first again */ | |||||
| pchan_eval->constraints.first = con_eval; | |||||
| } | |||||
| /* 6. recalculate pose with new inv-mat applied */ | |||||
| /* this one is unnecessary? (DEG seems to update correctly without) | |||||
| + if we leave this in, we have to click "Set Inverse" twice to see updates... | |||||
| BKE_pose_where_is(depsgraph, scene, ob_eval); */ | |||||
| } | |||||
| } | |||||
| static void child_get_inverse_matrix_owner_object( | |||||
| Depsgraph *depsgraph, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4]) | |||||
| { | |||||
| /* nullify inverse matrix first */ | |||||
| unit_m4(invmat); | |||||
| if (ob) { | |||||
| Object workob; | |||||
| /* make sure we passed the correct constraint */ | |||||
| BLI_assert(BLI_findindex(&ob->constraints, con) != -1); | |||||
| UNUSED_VARS_NDEBUG(con); | |||||
| /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */ | |||||
| BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); | |||||
| invert_m4_m4(invmat, workob.obmat); | |||||
| } | |||||
| } | |||||
| /* ChildOf Constraint - set inverse callback */ | /* ChildOf Constraint - set inverse callback */ | ||||
| static int childof_set_inverse_exec(bContext *C, wmOperator *op) | static int childof_set_inverse_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | |||||
| Scene *scene = CTX_data_scene(C); | |||||
| Object *ob = ED_object_active_context(C); | Object *ob = ED_object_active_context(C); | ||||
| bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); | bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); | ||||
| bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL; | bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL; | ||||
| const int owner = RNA_enum_get(op->ptr, "owner"); | |||||
| /* despite 3 layers of checks, we may still not be able to find a constraint */ | /* despite 3 layers of checks, we may still not be able to find a constraint */ | ||||
| if (data == NULL) { | if (data == NULL) { | ||||
| printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>"); | printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>"); | ||||
| BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); | BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { | /* Set a flag to request recalculation on next update. */ | ||||
| child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat); | data->flag |= CHILDOF_SET_INVERSE; | ||||
| } | |||||
| else if (owner == EDIT_CONSTRAINT_OWNER_BONE) { | |||||
| child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat); | |||||
| } | |||||
| ED_object_constraint_update(bmain, ob); | ED_object_constraint_update(bmain, ob); | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | ||||
| ▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | RNA_def_int(ot->srna, | ||||
| MAXFRAME); | MAXFRAME); | ||||
| } | } | ||||
| /* ------------- Object Solver Constraint ------------------ */ | /* ------------- Object Solver Constraint ------------------ */ | ||||
| static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) | static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | |||||
| Scene *scene = CTX_data_scene(C); | |||||
| Object *ob = ED_object_active_context(C); | Object *ob = ED_object_active_context(C); | ||||
| bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER); | bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER); | ||||
| bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL; | bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL; | ||||
| const int owner = RNA_enum_get(op->ptr, "owner"); | |||||
| /* despite 3 layers of checks, we may still not be able to find a constraint */ | /* despite 3 layers of checks, we may still not be able to find a constraint */ | ||||
| if (data == NULL) { | if (data == NULL) { | ||||
| printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>"); | printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>"); | ||||
| BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); | BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { | /* Set a flag to request recalculation on next update. */ | ||||
| child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat); | data->flag |= OBJECTSOLVER_SET_INVERSE; | ||||
| } | |||||
| else if (owner == EDIT_CONSTRAINT_OWNER_BONE) { | |||||
| child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat); | |||||
| } | |||||
| ED_object_constraint_update(bmain, ob); | ED_object_constraint_update(bmain, ob); | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static int objectsolver_set_inverse_invoke(bContext *C, | static int objectsolver_set_inverse_invoke(bContext *C, | ||||
| ▲ Show 20 Lines • Show All 1,058 Lines • Show Last 20 Lines | |||||