Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_convert_object.c
| Show All 38 Lines | |||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "ED_object.h" | #include "ED_object.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_convert.h" | #include "transform_convert.h" | ||||
| #include "transform_data.h" | |||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Object Mode Custom Data | /** \name Object Mode Custom Data | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct TransDataObject { | typedef struct TransDataObject { | ||||
| /** | /** | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
| * | * | ||||
| * Instead of transforming the selection, move the 2D/3D cursor. | * Instead of transforming the selection, move the 2D/3D cursor. | ||||
| * | * | ||||
| * \{ */ | * \{ */ | ||||
| /* *********************** Object Transform data ******************* */ | /* *********************** Object Transform data ******************* */ | ||||
| /* transcribe given object into TransData for Transforming */ | /* transcribe given object into TransData for Transforming */ | ||||
| static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) | static void ObjectToTransData(TransInfo *t, const TransData *td, const int tdi, Object *ob) | ||||
| { | { | ||||
| Scene *scene = t->scene; | Scene *scene = t->scene; | ||||
| bool constinv; | bool constinv; | ||||
| bool skip_invert = false; | bool skip_invert = false; | ||||
| if (t->mode != TFM_DUMMY && ob->rigidbody_object) { | if (t->mode != TFM_DUMMY && ob->rigidbody_object) { | ||||
| float rot[3][3], scale[3]; | float rot[3][3], scale[3]; | ||||
| float ctime = BKE_scene_frame_get(scene); | float ctime = BKE_scene_frame_get(scene); | ||||
| /* only use rigid body transform if simulation is running, | /* only use rigid body transform if simulation is running, | ||||
| * avoids problems with initial setup of rigid bodies */ | * avoids problems with initial setup of rigid bodies */ | ||||
| if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) { | if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) { | ||||
| /* save original object transform */ | /* save original object transform */ | ||||
| copy_v3_v3(td->ext->oloc, ob->loc); | copy_v3_v3(td->ext[tdi].oloc, ob->loc); | ||||
| if (ob->rotmode > 0) { | if (ob->rotmode > 0) { | ||||
| copy_v3_v3(td->ext->orot, ob->rot); | copy_v3_v3(td->ext[tdi].orot, ob->rot); | ||||
| } | } | ||||
| else if (ob->rotmode == ROT_MODE_AXISANGLE) { | else if (ob->rotmode == ROT_MODE_AXISANGLE) { | ||||
| td->ext->orotAngle = ob->rotAngle; | td->ext[tdi].orotAngle = ob->rotAngle; | ||||
| copy_v3_v3(td->ext->orotAxis, ob->rotAxis); | copy_v3_v3(td->ext[tdi].orotAxis, ob->rotAxis); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_qt_qt(td->ext->oquat, ob->quat); | copy_qt_qt(td->ext[tdi].oquat, ob->quat); | ||||
| } | } | ||||
| /* update object's loc/rot to get current rigid body transform */ | /* update object's loc/rot to get current rigid body transform */ | ||||
| mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); | mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); | ||||
| sub_v3_v3(ob->loc, ob->dloc); | sub_v3_v3(ob->loc, ob->dloc); | ||||
| BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ | BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ | ||||
| } | } | ||||
| } | } | ||||
| /* axismtx has the real orientation */ | /* axismtx has the real orientation */ | ||||
| copy_m3_m4(td->axismtx, ob->obmat); | copy_m3_m4(td->space[tdi].axismtx, ob->obmat); | ||||
| normalize_m3(td->axismtx); | normalize_m3(td->space[tdi].axismtx); | ||||
| td->con = ob->constraints.first; | td->object[tdi].con = ob->constraints.first; | ||||
| /* hack: temporarily disable tracking and/or constraints when getting | /* hack: temporarily disable tracking and/or constraints when getting | ||||
| * object matrix, if tracking is on, or if constraints don't need | * object matrix, if tracking is on, or if constraints don't need | ||||
| * inverse correction to stop it from screwing up space conversion | * inverse correction to stop it from screwing up space conversion | ||||
| * matrix later | * matrix later | ||||
| */ | */ | ||||
| constinv = constraints_list_needinv(t, &ob->constraints); | constinv = constraints_list_needinv(t, &ob->constraints); | ||||
| /* disable constraints inversion for dummy pass */ | /* disable constraints inversion for dummy pass */ | ||||
| if (t->mode == TFM_DUMMY) { | if (t->mode == TFM_DUMMY) { | ||||
| skip_invert = true; | skip_invert = true; | ||||
| } | } | ||||
| /* NOTE: This is not really following copy-on-write design and we should not | /* NOTE: This is not really following copy-on-write design and we should not | ||||
| * be re-evaluating the evaluated object. But as the comment above mentioned | * be re-evaluating the evaluated object. But as the comment above mentioned | ||||
| * this is part of a hack. | * this is part of a hack. | ||||
| * More proper solution would be to make a shallow copy of the object and | * More proper solution would be to make a shallow copy of the object and | ||||
| * evaluate that, and access matrix of that evaluated copy of the object. | * evaluate that, and access matrix of that evaluated copy of the object. | ||||
| * Might be more tricky than it sounds, if some logic later on accesses the | * Might be more tricky than it sounds, if some logic later on accesses the | ||||
| * object matrix via td->ob->obmat. */ | * object matrix via td->object[tdi].ob->obmat. */ | ||||
| Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob); | Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob); | ||||
| if (skip_invert == false && constinv == false) { | if (skip_invert == false && constinv == false) { | ||||
| object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */ | object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */ | ||||
| /* It is possible to have transform data initialization prior to a | /* It is possible to have transform data initialization prior to a | ||||
| * complete dependency graph evaluated. Happens, for example, when | * complete dependency graph evaluated. Happens, for example, when | ||||
| * changing transformation mode. */ | * changing transformation mode. */ | ||||
| BKE_object_tfm_copy(object_eval, ob); | BKE_object_tfm_copy(object_eval, ob); | ||||
| BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval); | BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval); | ||||
| object_eval->transflag &= ~OB_NO_CONSTRAINTS; | object_eval->transflag &= ~OB_NO_CONSTRAINTS; | ||||
| } | } | ||||
| else { | else { | ||||
| BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval); | BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval); | ||||
| } | } | ||||
| /* Copy newly evaluated fields to the original object, similar to how | /* Copy newly evaluated fields to the original object, similar to how | ||||
| * active dependency graph will do it. */ | * active dependency graph will do it. */ | ||||
| copy_m4_m4(ob->obmat, object_eval->obmat); | copy_m4_m4(ob->obmat, object_eval->obmat); | ||||
| /* Only copy negative scale flag, this is the only flag which is modified by | /* Only copy negative scale flag, this is the only flag which is modified by | ||||
| * the BKE_object_where_is_calc(). The rest of the flags we need to keep, | * the BKE_object_where_is_calc(). The rest of the flags we need to keep, | ||||
| * otherwise we might loose dupli flags (see T61787). */ | * otherwise we might loose dupli flags (see T61787). */ | ||||
| ob->transflag &= ~OB_NEG_SCALE; | ob->transflag &= ~OB_NEG_SCALE; | ||||
| ob->transflag |= (object_eval->transflag & OB_NEG_SCALE); | ob->transflag |= (object_eval->transflag & OB_NEG_SCALE); | ||||
| td->ob = ob; | td->object[tdi].ob = ob; | ||||
| td->loc = ob->loc; | td->basic[tdi].loc = ob->loc; | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(td->basic[tdi].iloc, td->basic[tdi].loc); | ||||
| if (ob->rotmode > 0) { | if (ob->rotmode > 0) { | ||||
| td->ext->rot = ob->rot; | td->ext[tdi].rot = ob->rot; | ||||
| td->ext->rotAxis = NULL; | td->ext[tdi].rotAxis = NULL; | ||||
| td->ext->rotAngle = NULL; | td->ext[tdi].rotAngle = NULL; | ||||
| td->ext->quat = NULL; | td->ext[tdi].quat = NULL; | ||||
| copy_v3_v3(td->ext->irot, ob->rot); | copy_v3_v3(td->ext[tdi].irot, ob->rot); | ||||
| copy_v3_v3(td->ext->drot, ob->drot); | copy_v3_v3(td->ext[tdi].drot, ob->drot); | ||||
| } | } | ||||
| else if (ob->rotmode == ROT_MODE_AXISANGLE) { | else if (ob->rotmode == ROT_MODE_AXISANGLE) { | ||||
| td->ext->rot = NULL; | td->ext[tdi].rot = NULL; | ||||
| td->ext->rotAxis = ob->rotAxis; | td->ext[tdi].rotAxis = ob->rotAxis; | ||||
| td->ext->rotAngle = &ob->rotAngle; | td->ext[tdi].rotAngle = &ob->rotAngle; | ||||
| td->ext->quat = NULL; | td->ext[tdi].quat = NULL; | ||||
| td->ext->irotAngle = ob->rotAngle; | td->ext[tdi].irotAngle = ob->rotAngle; | ||||
| copy_v3_v3(td->ext->irotAxis, ob->rotAxis); | copy_v3_v3(td->ext[tdi].irotAxis, ob->rotAxis); | ||||
| // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented | // td->ext[tdi].drotAngle = ob->drotAngle; // XXX, not implemented | ||||
| // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented | // copy_v3_v3(td->ext[tdi].drotAxis, ob->drotAxis); // XXX, not implemented | ||||
| } | } | ||||
| else { | else { | ||||
| td->ext->rot = NULL; | td->ext[tdi].rot = NULL; | ||||
| td->ext->rotAxis = NULL; | td->ext[tdi].rotAxis = NULL; | ||||
| td->ext->rotAngle = NULL; | td->ext[tdi].rotAngle = NULL; | ||||
| td->ext->quat = ob->quat; | td->ext[tdi].quat = ob->quat; | ||||
| copy_qt_qt(td->ext->iquat, ob->quat); | copy_qt_qt(td->ext[tdi].iquat, ob->quat); | ||||
| copy_qt_qt(td->ext->dquat, ob->dquat); | copy_qt_qt(td->ext[tdi].dquat, ob->dquat); | ||||
| } | } | ||||
| td->ext->rotOrder = ob->rotmode; | td->ext[tdi].rotOrder = ob->rotmode; | ||||
| td->ext->size = ob->scale; | td->ext[tdi].size = ob->scale; | ||||
| copy_v3_v3(td->ext->isize, ob->scale); | copy_v3_v3(td->ext[tdi].isize, ob->scale); | ||||
| copy_v3_v3(td->ext->dscale, ob->dscale); | copy_v3_v3(td->ext[tdi].dscale, ob->dscale); | ||||
| copy_v3_v3(td->center, ob->obmat[3]); | copy_v3_v3(td->center[tdi], ob->obmat[3]); | ||||
| copy_m4_m4(td->ext->obmat, ob->obmat); | copy_m4_m4(td->ext[tdi].obmat, ob->obmat); | ||||
| /* is there a need to set the global<->data space conversion matrices? */ | /* is there a need to set the global<->data space conversion matrices? */ | ||||
| if (ob->parent || constinv) { | if (ob->parent || constinv) { | ||||
| float obmtx[3][3], totmat[3][3], obinv[3][3]; | float obmtx[3][3], totmat[3][3], obinv[3][3]; | ||||
| /* Get the effect of parenting, and/or certain constraints. | /* Get the effect of parenting, and/or certain constraints. | ||||
| * NOTE: some Constraints, and also Tracking should never get this | * NOTE: some Constraints, and also Tracking should never get this | ||||
| * done, as it doesn't work well. | * done, as it doesn't work well. | ||||
| */ | */ | ||||
| BKE_object_to_mat3(ob, obmtx); | BKE_object_to_mat3(ob, obmtx); | ||||
| copy_m3_m4(totmat, ob->obmat); | copy_m3_m4(totmat, ob->obmat); | ||||
| invert_m3_m3(obinv, totmat); | invert_m3_m3(obinv, totmat); | ||||
| mul_m3_m3m3(td->smtx, obmtx, obinv); | mul_m3_m3m3(td->space[tdi].smtx, obmtx, obinv); | ||||
| invert_m3_m3(td->mtx, td->smtx); | invert_m3_m3(td->space[tdi].mtx, td->space[tdi].smtx); | ||||
| } | } | ||||
| else { | else { | ||||
| /* no conversion to/from dataspace */ | /* no conversion to/from dataspace */ | ||||
| unit_m3(td->smtx); | unit_m3(td->space[tdi].smtx); | ||||
| unit_m3(td->mtx); | unit_m3(td->space[tdi].mtx); | ||||
| } | } | ||||
| } | } | ||||
| static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer) | static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer) | ||||
| { | { | ||||
| LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | ||||
| base->object->id.tag &= ~LIB_TAG_DOIT; | base->object->id.tag &= ~LIB_TAG_DOIT; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | for (base = view_layer->object_bases.first; base; base = base->next) { | ||||
| base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | | base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | | ||||
| BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT | | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT | | ||||
| BA_TRANSFORM_LOCKED_IN_PLACE); | BA_TRANSFORM_LOCKED_IN_PLACE); | ||||
| } | } | ||||
| } | } | ||||
| void createTransObject(bContext *C, TransInfo *t) | void createTransObject(bContext *C, TransInfo *t) | ||||
| { | { | ||||
| TransData *td = NULL; | |||||
| TransDataExtension *tx; | |||||
| const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; | const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; | ||||
| set_trans_object_base_flags(t); | set_trans_object_base_flags(t); | ||||
| TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | ||||
| /* count */ | /* count */ | ||||
| tc->data_len = CTX_DATA_COUNT(C, selected_bases); | tc->data_len = CTX_DATA_COUNT(C, selected_bases); | ||||
| if (!tc->data_len) { | if (!tc->data_len) { | ||||
| /* clear here, main transform function escapes too */ | /* clear here, main transform function escapes too */ | ||||
| clear_trans_object_base_flags(t); | clear_trans_object_base_flags(t); | ||||
| return; | return; | ||||
| } | } | ||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| tc->data_len += count_proportional_objects(t); | tc->data_len += count_proportional_objects(t); | ||||
| } | } | ||||
| td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb"); | TransData *td = tc->data = transform_data_alloc(tc->data_len, TD_ALL_COMP); | ||||
| tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension"); | int tdi = 0; | ||||
| TransDataObject *tdo = MEM_callocN(sizeof(*tdo), __func__); | TransDataObject *tdo = MEM_callocN(sizeof(*tdo), __func__); | ||||
| t->custom.type.data = tdo; | t->custom.type.data = tdo; | ||||
| t->custom.type.free_cb = freeTransObjectCustomData; | t->custom.type.free_cb = freeTransObjectCustomData; | ||||
| if (t->options & CTX_OBMODE_XFORM_OBDATA) { | if (t->options & CTX_OBMODE_XFORM_OBDATA) { | ||||
| tdo->xds = ED_object_data_xform_container_create(); | tdo->xds = ED_object_data_xform_container_create(); | ||||
| } | } | ||||
| CTX_DATA_BEGIN (C, Base *, base, selected_bases) { | CTX_DATA_BEGIN (C, Base *, base, selected_bases) { | ||||
| Object *ob = base->object; | Object *ob = base->object; | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| td->protectflag = ob->protectflag; | td->object[tdi].protectflag = ob->protectflag; | ||||
| td->ext = tx; | td->ext[tdi].rotOrder = ob->rotmode; | ||||
| td->ext->rotOrder = ob->rotmode; | |||||
| if (base->flag & BA_TRANSFORM_CHILD) { | if (base->flag & BA_TRANSFORM_CHILD) { | ||||
| td->flag |= TD_NOCENTER; | td->basic[tdi].flag |= TD_NOCENTER; | ||||
| td->flag |= TD_NO_LOC; | td->basic[tdi].flag |= TD_NO_LOC; | ||||
| } | } | ||||
| /* select linked objects, but skip them later */ | /* select linked objects, but skip them later */ | ||||
| if (ID_IS_LINKED(ob)) { | if (ID_IS_LINKED(ob)) { | ||||
| td->flag |= TD_SKIP; | td->basic[tdi].flag |= TD_SKIP; | ||||
| } | } | ||||
| if (t->options & CTX_OBMODE_XFORM_OBDATA) { | if (t->options & CTX_OBMODE_XFORM_OBDATA) { | ||||
| ID *id = ob->data; | ID *id = ob->data; | ||||
| if (!id || id->lib) { | if (!id || id->lib) { | ||||
| td->flag |= TD_SKIP; | td->basic[tdi].flag |= TD_SKIP; | ||||
| } | } | ||||
| else if (BKE_object_is_in_editmode(ob)) { | else if (BKE_object_is_in_editmode(ob)) { | ||||
| /* The object could have edit-mode data from another view-layer, | /* The object could have edit-mode data from another view-layer, | ||||
| * it's such a corner-case it can be skipped for now - Campbell. */ | * it's such a corner-case it can be skipped for now - Campbell. */ | ||||
| td->flag |= TD_SKIP; | td->basic[tdi].flag |= TD_SKIP; | ||||
| } | } | ||||
| } | } | ||||
| if (t->options & CTX_OBMODE_XFORM_OBDATA) { | if (t->options & CTX_OBMODE_XFORM_OBDATA) { | ||||
| if ((td->flag & TD_SKIP) == 0) { | if ((td->basic[tdi].flag & TD_SKIP) == 0) { | ||||
| ED_object_data_xform_container_item_ensure(tdo->xds, ob); | ED_object_data_xform_container_item_ensure(tdo->xds, ob); | ||||
| } | } | ||||
| } | } | ||||
| ObjectToTransData(t, td, ob); | ObjectToTransData(t, td, tdi, ob); | ||||
| td->val = NULL; | td->special[tdi].val = NULL; | ||||
| td++; | |||||
| tx++; | tdi++; | ||||
| } | } | ||||
| CTX_DATA_END; | CTX_DATA_END; | ||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| ViewLayer *view_layer = t->view_layer; | ViewLayer *view_layer = t->view_layer; | ||||
| View3D *v3d = t->view; | View3D *v3d = t->view; | ||||
| Base *base; | Base *base; | ||||
| for (base = view_layer->object_bases.first; base; base = base->next) { | for (base = view_layer->object_bases.first; base; base = base->next) { | ||||
| Object *ob = base->object; | Object *ob = base->object; | ||||
| /* if base is not selected, not a parent of selection | /* if base is not selected, not a parent of selection | ||||
| * or not a child of selection and it is editable and selectable */ | * or not a child of selection and it is editable and selectable */ | ||||
| if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && | if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && | ||||
| (base->flag & BASE_SELECTED) == 0 && BASE_EDITABLE(v3d, base) && | (base->flag & BASE_SELECTED) == 0 && BASE_EDITABLE(v3d, base) && | ||||
| BASE_SELECTABLE(v3d, base)) { | BASE_SELECTABLE(v3d, base)) { | ||||
| td->protectflag = ob->protectflag; | td->object[tdi].protectflag = ob->protectflag; | ||||
| td->ext = tx; | td->ext[tdi].rotOrder = ob->rotmode; | ||||
| td->ext->rotOrder = ob->rotmode; | |||||
| ObjectToTransData(t, td, tdi, ob); | |||||
| ObjectToTransData(t, td, ob); | td->special[tdi].val = NULL; | ||||
| td->val = NULL; | |||||
| td++; | tdi++; | ||||
| tx++; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (t->options & CTX_OBMODE_XFORM_OBDATA) { | if (t->options & CTX_OBMODE_XFORM_OBDATA) { | ||||
| GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len); | GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len); | ||||
| td = tc->data; | TransData *td = tc->data; | ||||
| for (int i = 0; i < tc->data_len; i++, td++) { | for (int i = 0; i < tc->data_len; i++) { | ||||
| if ((td->flag & TD_SKIP) == 0) { | if (!(td->basic[i].flag & TD_SKIP)) { | ||||
| BLI_gset_add(objects_in_transdata, td->ob); | BLI_gset_add(objects_in_transdata, td->object[i].ob); | ||||
| } | } | ||||
| } | } | ||||
| ViewLayer *view_layer = t->view_layer; | ViewLayer *view_layer = t->view_layer; | ||||
| View3D *v3d = t->view; | View3D *v3d = t->view; | ||||
| LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | ||||
| Object *ob = base->object; | Object *ob = base->object; | ||||
| Show All 28 Lines | if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) { | ||||
| tdo->xcs = ED_object_xform_skip_child_container_create(); | tdo->xcs = ED_object_xform_skip_child_container_create(); | ||||
| #define BASE_XFORM_INDIRECT(base) \ | #define BASE_XFORM_INDIRECT(base) \ | ||||
| ((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0) | ((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0) | ||||
| GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len); | GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len); | ||||
| GHash *objects_parent_root = BLI_ghash_ptr_new_ex(__func__, tc->data_len); | GHash *objects_parent_root = BLI_ghash_ptr_new_ex(__func__, tc->data_len); | ||||
| td = tc->data; | TransData *td = tc->data; | ||||
| for (int i = 0; i < tc->data_len; i++, td++) { | for (int i = 0; i < tc->data_len; i++) { | ||||
| if ((td->flag & TD_SKIP) == 0) { | if (!(td->basic[i].flag & TD_SKIP)) { | ||||
| BLI_gset_add(objects_in_transdata, td->ob); | BLI_gset_add(objects_in_transdata, td->object[i].ob); | ||||
| } | } | ||||
| } | } | ||||
| ViewLayer *view_layer = t->view_layer; | ViewLayer *view_layer = t->view_layer; | ||||
| LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | ||||
| Object *ob = base->object; | Object *ob = base->object; | ||||
| if (ob->parent != NULL) { | if (ob->parent != NULL) { | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
| * | * | ||||
| * Instead of transforming the selection, move the 2D/3D cursor. | * Instead of transforming the selection, move the 2D/3D cursor. | ||||
| * | * | ||||
| * \{ */ | * \{ */ | ||||
| void createTransTexspace(TransInfo *t) | void createTransTexspace(TransInfo *t) | ||||
| { | { | ||||
| ViewLayer *view_layer = t->view_layer; | ViewLayer *view_layer = t->view_layer; | ||||
| TransData *td; | |||||
| Object *ob; | Object *ob; | ||||
| ID *id; | ID *id; | ||||
| short *texflag; | short *texflag; | ||||
| ob = OBACT(view_layer); | ob = OBACT(view_layer); | ||||
| if (ob == NULL) { // Shouldn't logically happen, but still... | if (ob == NULL) { // Shouldn't logically happen, but still... | ||||
| return; | return; | ||||
| } | } | ||||
| id = ob->data; | id = ob->data; | ||||
| if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { | if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { | ||||
| BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); | BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); | ||||
| return; | return; | ||||
| } | } | ||||
| if (BKE_object_obdata_is_libdata(ob)) { | if (BKE_object_obdata_is_libdata(ob)) { | ||||
| BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); | BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); | ||||
| return; | return; | ||||
| } | } | ||||
| { | |||||
| BLI_assert(t->data_container_len == 1); | BLI_assert(t->data_container_len == 1); | ||||
| TransDataContainer *tc = t->data_container; | TransDataContainer *tc = t->data_container; | ||||
| tc->data_len = 1; | tc->data_len = 1; | ||||
| td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); | TransData *td = tc->data = transform_data_alloc(tc->data_len, TD_ALL_COMP); | ||||
| td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); | TransDataExtension *ext = &td->ext[0]; | ||||
| } | |||||
| td->flag = TD_SELECTED; | |||||
| copy_v3_v3(td->center, ob->obmat[3]); | |||||
| td->ob = ob; | |||||
| copy_m3_m4(td->mtx, ob->obmat); | float *loc; | ||||
| copy_m3_m4(td->axismtx, ob->obmat); | float mtx[3][3], axismtx[3][3], smtx[3][3]; | ||||
| normalize_m3(td->axismtx); | copy_m3_m4(mtx, ob->obmat); | ||||
| pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); | copy_m3_m4(axismtx, ob->obmat); | ||||
| normalize_m3(axismtx); | |||||
| pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); | |||||
| if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size)) { | if (BKE_object_obdata_texspace_get(ob, &texflag, &loc, &ext->size)) { | ||||
| ob->dtx |= OB_TEXSPACE; | ob->dtx |= OB_TEXSPACE; | ||||
| *texflag &= ~ME_AUTOSPACE; | *texflag &= ~ME_AUTOSPACE; | ||||
| } | } | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(ext->isize, ext->size); | ||||
| copy_v3_v3(td->ext->isize, td->ext->size); | |||||
| const int tdi = 0; | |||||
| td->object[tdi].ob = ob; | |||||
| td->basic[tdi].loc = loc; | |||||
| copy_v3_v3(td->basic[tdi].iloc, loc); | |||||
| copy_v3_v3(td->center[tdi], ob->obmat[3]); | |||||
| unit_m3(td->space[tdi].mtx); | |||||
| unit_m3(td->space[tdi].smtx); | |||||
| unit_m3(td->space[tdi].axismtx); | |||||
| td->basic[tdi].flag = TD_SELECTED; | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||