diff options
author | YimingWu <xp8110@outlook.com> | 2020-02-01 05:35:40 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2020-02-01 05:35:40 +0300 |
commit | f7770cb97bb9d19d0806f67da9377129fd4d09b0 (patch) | |
tree | 2cd22d612ffba3a509d5548332c9cc8a06a1a638 /source/blender/editors/transform | |
parent | b47883a990ee68e659a8a8b44729be9b8e0d002f (diff) | |
parent | dc3f073d1c5255e79763dfff3ef17f6216f1b391 (diff) |
Merge remote-tracking branch 'origin/master' into temp-lanpr-review
Diffstat (limited to 'source/blender/editors/transform')
12 files changed, 455 insertions, 371 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 7112444655b..ec39b457082 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -856,7 +856,7 @@ static bool transform_modal_item_poll(const wmOperator *op, int value) if (t->spacetype != SPACE_VIEW3D) { return false; } - else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) { + else if ((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) == 0) { return false; } else if (!validSnap(t)) { @@ -2479,7 +2479,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve else if (!do_skip) { const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); if (preserve_clnor) { - BKE_editmesh_lnorspace_update(em); + BKE_editmesh_lnorspace_update(em, tc->obedit->data); t->flag |= T_CLNOR_REBUILD; } BM_lnorspace_invalidate(em->bm, true); @@ -2561,7 +2561,7 @@ int transformEnd(bContext *C, TransInfo *t) /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */ special_aftertrans_update(C, t); - /* free data */ + /* Free data, also handles overlap [in freeTransCustomData()]. */ postTrans(C, t); /* send events out for redraws */ @@ -4657,8 +4657,8 @@ static void initNormalRotation(TransInfo *t) BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; - BKE_editmesh_ensure_autosmooth(em); - BKE_editmesh_lnorspace_update(em); + BKE_editmesh_ensure_autosmooth(em, tc->obedit->data); + BKE_editmesh_lnorspace_update(em, tc->obedit->data); storeCustomLNorValue(tc, bm); } @@ -8777,9 +8777,10 @@ static void applyTimeTranslateValue(TransInfo *t, float value) /* It doesn't matter whether we apply to t->data or * t->data2d, but t->data2d is more convenient. */ for (i = 0; i < tc->data_len; i++, td++, td2d++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from + /* It is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from. * (this is only valid when not in NLA) + * (also: masks and gpencil dont have animadata) */ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; @@ -8810,7 +8811,7 @@ static void applyTimeTranslateValue(TransInfo *t, float value) val = floorf(val + 0.5f); } - *(td->val) = td->ival + val; + *(td->val) = td->ival + val * td->factor; } /* apply nearest snapping */ diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index db8f36883f8..869c23de74c 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -450,20 +450,15 @@ int count_set_pose_transflags(Object *ob, for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; + bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR); if (PBONE_VISIBLE(arm, bone)) { if ((bone->flag & BONE_SELECTED)) { bone->flag |= BONE_TRANSFORM; } - else { - bone->flag &= ~BONE_TRANSFORM; - } bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM; bone->flag &= ~BONE_TRANSFORM_CHILD; } - else { - bone->flag &= ~BONE_TRANSFORM; - } } /* make sure no bone can be transformed when a parent is transformed */ @@ -1350,6 +1345,15 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) return true; } } + else if (con->type == CONSTRAINT_TYPE_ACTION) { + /* The Action constraint only does this in the Before mode. */ + bActionConstraint *data = (bActionConstraint *)con->data; + + if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE) && + ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) { + return true; + } + } else if (con->type == CONSTRAINT_TYPE_TRANSFORM) { /* Transform constraint needs it for rotation at least (r.57309), * but doing so when translating may also mess things up [#36203] @@ -1888,8 +1892,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t) SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first; - /* marker transform, not especially nice but we may want to move markers - * at the same time as keyframes in the dope sheet. */ + /* Marker transform, not especially nice but we may want to move markers + * at the same time as strips in the Video Sequencer. */ if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) { /* cant use TFM_TIME_EXTEND * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */ diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index cc023688c8e..0edf55ece7e 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -86,6 +86,7 @@ static void add_pose_transdata( td->flag |= TD_NO_LOC; } + td->extra = pchan; td->protectflag = pchan->protectflag; td->loc = pchan->loc; @@ -364,7 +365,7 @@ static short pose_grab_with_ik(Main *bmain, Object *ob) * (but they must be selected, and only one ik-solver per chain should get added) */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->layer & arm->layer) { - if (pchan->bone->flag & BONE_SELECTED) { + if (pchan->bone->flag & (BONE_SELECTED | BONE_TRANSFORM_MIRROR)) { /* Rule: no IK for solitatry (unconnected) bones */ for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) { if (bonec->flag & BONE_CONNECTED) { @@ -379,7 +380,7 @@ static short pose_grab_with_ik(Main *bmain, Object *ob) if (pchan->parent) { /* only adds if there's no IK yet (and no parent bone was selected) */ for (parent = pchan->parent; parent; parent = parent->parent) { - if (parent->bone->flag & BONE_SELECTED) { + if (parent->bone->flag & (BONE_SELECTED | BONE_TRANSFORM_MIRROR)) { break; } } @@ -513,14 +514,6 @@ void createTransPose(TransInfo *t) } } - /* do we need to add temporal IK chains? */ - if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) { - if (pose_grab_with_ik(bmain, ob)) { - t->flag |= T_AUTOIK; - has_translate_rotate[0] = true; - } - } - if (mirror) { int total_mirrored = 0; for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { @@ -541,16 +534,6 @@ void createTransPose(TransInfo *t) } } - /* if there are no translatable bones, do rotation */ - if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) { - if (has_translate_rotate[1]) { - t->mode = TFM_ROTATION; - } - else { - t->mode = TFM_RESIZE; - } - } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->data_len == 0) { continue; @@ -582,20 +565,32 @@ void createTransPose(TransInfo *t) td->val = NULL; } - /* use pose channels to fill trans data */ - td = tc->data; - for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->bone->flag & BONE_TRANSFORM) { - add_pose_transdata(t, pchan, ob, tc, td); - - if (mirror) { + if (mirror) { + for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name); if (pchan_mirror) { + pchan_mirror->bone->flag |= BONE_TRANSFORM_MIRROR; pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative); pid_index++; } } + } + } + /* do we need to add temporal IK chains? */ + if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) { + if (pose_grab_with_ik(bmain, ob)) { + t->flag |= T_AUTOIK; + has_translate_rotate[0] = true; + } + } + + /* use pose channels to fill trans data */ + td = tc->data; + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { + add_pose_transdata(t, pchan, ob, tc, td); td++; } } @@ -603,10 +598,20 @@ void createTransPose(TransInfo *t) if (td != (tc->data + tc->data_len)) { BKE_report(t->reports, RPT_DEBUG, "Bone selection count error"); } + } - /* initialize initial auto=ik chainlen's? */ - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, 0); + /* initialize initial auto=ik chainlen's? */ + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, 0); + } + + /* if there are no translatable bones, do rotation */ + if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) { + if (has_translate_rotate[1]) { + t->mode = TFM_ROTATION; + } + else { + t->mode = TFM_RESIZE; } } diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index 234e383be5f..80c0afc3f56 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -63,6 +63,10 @@ static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3]) void createTransGPencil(bContext *C, TransInfo *t) { + if (t->data_container_len == 0) { + return; + } + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 8b7dcecf9e8..5d3d1d936a2 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1451,7 +1451,8 @@ void createTransUVs(bContext *C, TransInfo *t) if (is_prop_connected || is_island_center) { /* create element map with island information */ const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0; - elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true); + const bool use_uvsel = !is_prop_connected; + elementmap = BM_uv_element_map_create(em->bm, scene, use_facesel, use_uvsel, false, true); if (elementmap == NULL) { continue; } @@ -1547,16 +1548,17 @@ void createTransUVs(bContext *C, TransInfo *t) if (is_prop_connected || is_island_center) { UvElement *element = BM_uv_element_get(elementmap, efa, l); - - if (is_prop_connected) { - if (!BLI_BITMAP_TEST(island_enabled, element->island)) { - count_rejected++; - continue; + if (element) { + if (is_prop_connected) { + if (!BLI_BITMAP_TEST(island_enabled, element->island)) { + count_rejected++; + continue; + } } - } - if (is_island_center) { - center = island_center[element->island].co; + if (is_island_center) { + center = island_center[element->island].co; + } } } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 86b6ebe3ffa..4baf0e8a3cb 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -381,6 +381,10 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } if (overlap) { + const bool use_sync_markers = (((SpaceSeq *)t->sa->spacedata.first)->flag & + SEQ_MARKER_TRANS) != 0; + ListBase *markers = &t->scene->markers; + bool has_effect_root = false, has_effect_any = false; for (seq = seqbasep->first; seq; seq = seq->next) { seq->tmp = NULL; @@ -425,7 +429,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } } - BKE_sequence_base_shuffle_time(seqbasep, t->scene); + BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->machine >= MAXSEQ * 2) { @@ -437,10 +441,10 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } } - BKE_sequence_base_shuffle_time(seqbasep, t->scene); + BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); } else { - BKE_sequence_base_shuffle_time(seqbasep, t->scene); + BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); } if (has_effect_any) { diff --git a/source/blender/editors/transform/transform_draw.c b/source/blender/editors/transform/transform_draw.c deleted file mode 100644 index e44442b7e49..00000000000 --- a/source/blender/editors/transform/transform_draw.c +++ /dev/null @@ -1,114 +0,0 @@ - -/* -------------------------------------------------------------------- */ -/** \name Auto-Key (Pixel Space) - * \{ */ - -/* just draw a little warning message in the top-right corner of the viewport - * to warn that autokeying is enabled */ -static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) -{ - const char *printable = IFACE_("Auto Keying On"); - float printable_size[2]; - int xco, yco; - - const rcti *rect = ED_region_visible_rect(ar); - - const int font_id = BLF_default(); - BLF_width_and_height( - font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - - xco = (rect->xmax - U.widget_unit) - (int)printable_size[0]; - yco = (rect->ymax - U.widget_unit); - - /* warning text (to clarify meaning of overlays) - * - original color was red to match the icon, but that clashes badly with a less nasty border - */ - unsigned char color[3]; - UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color); - BLF_color3ubv(font_id, color); -#ifdef WITH_INTERNATIONAL - BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); -#else - BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); -#endif - - /* autokey recording icon... */ - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - xco -= U.widget_unit; - yco -= (int)printable_size[1] / 2; - - UI_icon_draw(xco, yco, ICON_REC); - - GPU_blend(false); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Constraints (View Space) - * \{ */ - -/* called from drawview.c, as an extra per-window draw option */ -void drawPropCircle(const struct bContext *C, TransInfo *t) -{ - if (t->flag & T_PROP_EDIT) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - float tmat[4][4], imat[4][4]; - int depth_test_enabled; - - if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) { - copy_m4_m4(tmat, rv3d->viewmat); - invert_m4_m4(imat, tmat); - } - else { - unit_m4(tmat); - unit_m4(imat); - } - - GPU_matrix_push(); - - if (t->spacetype == SPACE_VIEW3D) { - /* pass */ - } - else if (t->spacetype == SPACE_IMAGE) { - GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]); - } - else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_ACTION)) { - /* only scale y */ - rcti *mask = &t->ar->v2d.mask; - rctf *datamask = &t->ar->v2d.cur; - float xsize = BLI_rctf_size_x(datamask); - float ysize = BLI_rctf_size_y(datamask); - float xmask = BLI_rcti_size_x(mask); - float ymask = BLI_rcti_size_y(mask); - GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask)); - } - - depth_test_enabled = GPU_depth_test_enabled(); - if (depth_test_enabled) { - GPU_depth_test(false); - } - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformThemeColor(TH_GRID); - - GPU_logic_op_invert_set(true); - imm_drawcircball(t->center_global, t->prop_size, imat, pos); - GPU_logic_op_invert_set(false); - - immUnbindProgram(); - - if (depth_test_enabled) { - GPU_depth_test(true); - } - - GPU_matrix_pop(); - } -} - -/** \} */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 9031dc06e3f..5595c3a0e38 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -31,6 +31,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" +#include "DNA_constraint_types.h" #include "DNA_gpencil_types.h" #include "DNA_lattice_types.h" #include "DNA_screen_types.h" @@ -785,50 +786,61 @@ static void recalcData_spaceclip(TransInfo *t) * if pose bone (partial) selected, copy data. * context; posemode armature, with mirror editing enabled. * - * \param pid: Optional, apply relative transform when set. + * \param pid: Optional, apply relative transform when set (has no effect on mirrored bones). */ -static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid) +static void pose_transform_mirror_update(TransInfo *t, + TransDataContainer *tc, + Object *ob, + PoseInitData_Mirror *pid) { float flip_mtx[4][4]; unit_m4(flip_mtx); flip_mtx[0][0] = -1; - for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig; - pchan_orig = pchan_orig->next) { - /* Clear the MIRROR flag from previous runs */ - pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR; - } - - for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig; - pchan_orig = pchan_orig->next) { - /* no layer check, correct mirror is more important */ - if (pchan_orig->bone->flag & BONE_TRANSFORM) { - bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name); - - if (pchan) { - /* also do bbone scaling */ - pchan->bone->xwidth = pchan_orig->bone->xwidth; - pchan->bone->zwidth = pchan_orig->bone->zwidth; - - /* we assume X-axis flipping for now */ - pchan->curve_in_x = pchan_orig->curve_in_x * -1; - pchan->curve_out_x = pchan_orig->curve_out_x * -1; - pchan->roll1 = pchan_orig->roll1 * -1; // XXX? - pchan->roll2 = pchan_orig->roll2 * -1; // XXX? - - float pchan_mtx_final[4][4]; - BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final); - mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx); - mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final); - if (pid) { - mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final); - pid++; - } - BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false); + TransData *td = tc->data; + for (int i = tc->data_len; i--; td++) { + bPoseChannel *pchan_orig = td->extra; + BLI_assert(pchan_orig->bone->flag & BONE_TRANSFORM); + /* No layer check, correct mirror is more important. */ + bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name); + if (pchan == NULL) { + continue; + } + + /* Also do bbone scaling. */ + pchan->bone->xwidth = pchan_orig->bone->xwidth; + pchan->bone->zwidth = pchan_orig->bone->zwidth; - /* set flag to let autokeyframe know to keyframe the mirrred bone */ - pchan->bone->flag |= BONE_TRANSFORM_MIRROR; + /* We assume X-axis flipping for now. */ + pchan->curve_in_x = pchan_orig->curve_in_x * -1; + pchan->curve_out_x = pchan_orig->curve_out_x * -1; + pchan->roll1 = pchan_orig->roll1 * -1; // XXX? + pchan->roll2 = pchan_orig->roll2 * -1; // XXX? + + float pchan_mtx_final[4][4]; + BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final); + mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx); + mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final); + if (pid) { + mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final); + } + BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false); + + /* In this case we can do target-less IK grabbing. */ + if (t->mode == TFM_TRANSLATION) { + bKinematicConstraint *data = has_targetless_ik(pchan); + if (data == NULL) { + continue; } + mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc); + if (pid) { + /* TODO(germano): Realitve Mirror support */ + } + data->flag |= CONSTRAINT_IK_AUTO; + } + + if (pid) { + pid++; } } } @@ -1045,7 +1057,7 @@ static void recalcData_objects(TransInfo *t) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); bPose *pose = ob->pose; if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) { - pose_transform_mirror_update(ob, NULL); + pose_transform_mirror_update(t, tc, ob, NULL); } } } @@ -1063,7 +1075,7 @@ static void recalcData_objects(TransInfo *t) if (pose->flag & POSE_MIRROR_RELATIVE) { pid = tc->custom.type.data; } - pose_transform_mirror_update(ob, pid); + pose_transform_mirror_update(t, tc, ob, pid); } else { restoreMirrorPoseBones(tc); diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index 3f0032cc7cc..793552865a6 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -44,7 +44,9 @@ #include "WM_api.h" #include "WM_types.h" #include "wm.h" /* XXX */ +#include "WM_message.h" +#include "ED_gizmo_utils.h" #include "ED_image.h" #include "ED_screen.h" #include "ED_uvedit.h" @@ -53,14 +55,79 @@ #include "transform.h" /* own include */ /* -------------------------------------------------------------------- */ +/** \name Shared Callback's + */ + +static bool gizmo2d_generic_poll(const bContext *C, wmGizmoGroupType *gzgt) +{ + if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) { + return false; + } + + if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) { + return false; + } + + ScrArea *sa = CTX_wm_area(C); + switch (sa->spacetype) { + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + Object *obedit = CTX_data_edit_object(C); + if (!ED_space_image_show_uvedit(sima, obedit)) { + return false; + } + } + } + + return true; +} + +static void gizmo2d_pivot_point_message_subscribe(struct wmGizmoGroup *gzgroup, + struct wmMsgBus *mbus, + /* Additional args. */ + bScreen *screen, + ScrArea *sa, + ARegion *ar) +{ + wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = { + .owner = ar, + .user_data = gzgroup->parent_gzmap, + .notify = WM_gizmo_do_msg_notify_tag_refresh, + }; + + switch (sa->spacetype) { + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceImageEditor, sima, &ptr); + { + extern PropertyRNA rna_SpaceImageEditor_pivot_point; + extern PropertyRNA rna_SpaceImageEditor_cursor_location; + const PropertyRNA *props[] = { + &rna_SpaceImageEditor_pivot_point, + (sima->around == V3D_AROUND_CURSOR) ? &rna_SpaceImageEditor_cursor_location : NULL, + }; + for (int i = 0; i < ARRAY_SIZE(props); i++) { + if (props[i] == NULL) { + continue; + } + WM_msg_subscribe_rna(mbus, &ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__); + } + } + break; + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Arrow / Cage Gizmo Group * * Defines public functions, not the gizmo it's self: * - * - #ED_widgetgroup_gizmo2d_xform_setup - * - #ED_widgetgroup_gizmo2d_xform_refresh - * - #ED_widgetgroup_gizmo2d_xform_draw_prepare - * - #ED_widgetgroup_gizmo2d_xform_poll + * - #ED_widgetgroup_gizmo2d_xform_callbacks_set + * - #ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set * * \{ */ @@ -115,7 +182,7 @@ static void gizmo2d_get_axis_color(const int axis_idx, float *r_col, float *r_co static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup) { - const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true); + const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true); const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true); const wmGizmoType *gzt_button = WM_gizmotype_find("GIZMO_GT_button_2d", true); @@ -137,7 +204,7 @@ static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup) /** * Calculates origin in view space, use with #gizmo2d_origin_to_region. */ -static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max) +static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max) { float min_buf[2], max_buf[2]; if (r_min == NULL) { @@ -148,24 +215,42 @@ static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min } ScrArea *sa = CTX_wm_area(C); + bool changed = false; if (sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Image *ima = ED_space_image(sima); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, NULL, &objects_len); - if (!ED_uvedit_minmax_multi(CTX_data_scene(C), ima, objects, objects_len, r_min, r_max)) { - zero_v2(r_min); - zero_v2(r_max); + if (ED_uvedit_minmax_multi(scene, ima, objects, objects_len, r_min, r_max)) { + changed = true; } MEM_freeN(objects); } - else { + + if (changed == false) { zero_v2(r_min); zero_v2(r_max); } + mid_v2_v2v2(r_center, r_min, r_max); + return changed; +} + +static bool gizmo2d_calc_center(const bContext *C, float r_center[2]) +{ + ScrArea *sa = CTX_wm_area(C); + bool has_select = false; + zero_v2(r_center); + if (sa->spacetype == SPACE_IMAGE) { + SpaceImage *sima = sa->spacedata.first; + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ED_uvedit_center_from_pivot_ex(sima, scene, view_layer, r_center, sima->around, &has_select); + } + return has_select; } /** @@ -187,7 +272,7 @@ static int gizmo2d_modal(bContext *C, ARegion *ar = CTX_wm_region(C); float origin[3]; - gizmo2d_calc_bounds(C, origin, NULL, NULL); + gizmo2d_calc_center(C, origin); gizmo2d_origin_to_region(ar, origin); WM_gizmo_set_matrix_location(widget, origin); @@ -196,7 +281,7 @@ static int gizmo2d_modal(bContext *C, return OPERATOR_RUNNING_MODAL; } -void ED_widgetgroup_gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true); GizmoGroup2D *ggd = gizmogroup2d_init(gzgroup); @@ -204,23 +289,30 @@ void ED_widgetgroup_gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) { wmGizmo *gz = ggd->translate_xy[i]; - const float offset[3] = {0.0f, 0.2f}; /* custom handler! */ WM_gizmo_set_fn_custom_modal(gz, gizmo2d_modal); - WM_gizmo_set_scale(gz, U.gizmo_size); if (i < 2) { float color[4], color_hi[4]; gizmo2d_get_axis_color(i, color, color_hi); /* set up widget data */ - RNA_float_set(gz->ptr, "angle", -M_PI_2 * i); RNA_float_set(gz->ptr, "length", 0.8f); + float axis[3] = {0.0f}; + axis[(i + 1) % 2] = 1.0f; + WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis); + + float offset[3] = {0, 0, 0}; + offset[2] = 0.18f; WM_gizmo_set_matrix_offset_location(gz, offset); + gz->flag |= WM_GIZMO_DRAW_OFFSET_SCALE; + WM_gizmo_set_line_width(gz, GIZMO_AXIS_LINE_WIDTH); WM_gizmo_set_color(gz, color); WM_gizmo_set_color_highlight(gz, color_hi); + + WM_gizmo_set_scale(gz, 1.0f); } else { PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); @@ -230,6 +322,9 @@ void ED_widgetgroup_gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup /* Make the center low alpha. */ WM_gizmo_set_line_width(gz, 2.0f); RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.0); + WM_gizmo_set_color(gz, (const float[4]){1, 1, 1, 0.6}); + + WM_gizmo_set_scale(gz, 0.2f); } /* Assign operator. */ @@ -289,18 +384,24 @@ void ED_widgetgroup_gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup } } -void ED_widgetgroup_gizmo2d_xform_setup_no_cage(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_xform_setup_no_cage(const bContext *C, wmGizmoGroup *gzgroup) { - ED_widgetgroup_gizmo2d_xform_setup(C, gzgroup); + gizmo2d_xform_setup(C, gzgroup); GizmoGroup2D *ggd = gzgroup->customdata; ggd->no_cage = true; } -void ED_widgetgroup_gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgroup) { GizmoGroup2D *ggd = gzgroup->customdata; float origin[3]; - gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max); + bool has_select; + if (ggd->no_cage) { + has_select = gizmo2d_calc_center(C, origin); + } + else { + has_select = gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max); + } copy_v2_v2(ggd->origin, origin); bool show_cage = !ggd->no_cage && !equals_v2v2(ggd->min, ggd->max); @@ -314,62 +415,70 @@ void ED_widgetgroup_gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgro } } - if (show_cage) { - ggd->cage->flag &= ~WM_GIZMO_HIDDEN; + if (has_select == false) { for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) { - wmGizmo *gz = ggd->translate_xy[i]; - gz->flag |= WM_GIZMO_HIDDEN; + ggd->translate_xy[i]->flag |= WM_GIZMO_HIDDEN; } + ggd->cage->flag |= WM_GIZMO_HIDDEN; } else { - ggd->cage->flag |= WM_GIZMO_HIDDEN; - for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) { - wmGizmo *gz = ggd->translate_xy[i]; - gz->flag &= ~WM_GIZMO_HIDDEN; + if (show_cage) { + ggd->cage->flag &= ~WM_GIZMO_HIDDEN; + for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) { + wmGizmo *gz = ggd->translate_xy[i]; + gz->flag |= WM_GIZMO_HIDDEN; + } + } + else { + ggd->cage->flag |= WM_GIZMO_HIDDEN; + for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) { + wmGizmo *gz = ggd->translate_xy[i]; + gz->flag &= ~WM_GIZMO_HIDDEN; + } } - } - if (show_cage) { - wmGizmoOpElem *gzop; - float mid[2]; - const float *min = ggd->min; - const float *max = ggd->max; - mid_v2_v2v2(mid, min, max); - - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X); - PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override"); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f}); - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f}); - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f}); - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f}); - - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f}); - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f}); - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f}); - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f}); - - gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE); - RNA_property_float_set_array( - &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f}); + if (show_cage) { + wmGizmoOpElem *gzop; + float mid[2]; + const float *min = ggd->min; + const float *max = ggd->max; + mid_v2_v2v2(mid, min, max); + + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X); + PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override"); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f}); + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f}); + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f}); + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f}); + + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f}); + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f}); + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f}); + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f}); + + gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE); + RNA_property_float_set_array( + &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f}); + } } } -void ED_widgetgroup_gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { ARegion *ar = CTX_wm_region(C); GizmoGroup2D *ggd = gzgroup->customdata; @@ -389,44 +498,30 @@ void ED_widgetgroup_gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup * ggd->cage->matrix_offset[1][1] = (ggd->max[1] - ggd->min[1]); } -/* TODO (Julian) - * - Called on every redraw, better to do a more simple poll and check for selection in _refresh - * - UV editing only, could be expanded for other things. - */ -bool ED_widgetgroup_gizmo2d_xform_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +static void gizmo2d_xform_no_cage_message_subscribe(const struct bContext *C, + struct wmGizmoGroup *gzgroup, + struct wmMsgBus *mbus) { - if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) { - return false; - } - - SpaceImage *sima = CTX_wm_space_image(C); - Object *obedit = CTX_data_edit_object(C); - - if (ED_space_image_show_uvedit(sima, obedit)) { - Image *ima = ED_space_image(sima); - Scene *scene = CTX_data_scene(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* check if there's a selected poly */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, sa, ar); +} - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - return true; - } - } - } - } +void ED_widgetgroup_gizmo2d_xform_callbacks_set(wmGizmoGroupType *gzgt) +{ + gzgt->poll = gizmo2d_generic_poll; + gzgt->setup = gizmo2d_xform_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->refresh = gizmo2d_xform_refresh; + gzgt->draw_prepare = gizmo2d_xform_draw_prepare; +} - return false; +void ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set(wmGizmoGroupType *gzgt) +{ + ED_widgetgroup_gizmo2d_xform_callbacks_set(gzgt); + gzgt->setup = gizmo2d_xform_setup_no_cage; + gzgt->message_subscribe = gizmo2d_xform_no_cage_message_subscribe; } /** \} */ @@ -436,10 +531,7 @@ bool ED_widgetgroup_gizmo2d_xform_poll(const bContext *C, wmGizmoGroupType *UNUS * * Defines public functions, not the gizmo it's self: * - * - #ED_widgetgroup_gizmo2d_resize_setup - * - #ED_widgetgroup_gizmo2d_resize_refresh - * - #ED_widgetgroup_gizmo2d_resize_draw_prepare - * - #ED_widgetgroup_gizmo2d_resize_poll + * - #ED_widgetgroup_gizmo2d_resize_callbacks_set * * \{ */ @@ -450,7 +542,7 @@ typedef struct GizmoGroup_Resize2D { static GizmoGroup_Resize2D *gizmogroup2d_resize_init(wmGizmoGroup *gzgroup) { - const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true); + const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true); const wmGizmoType *gzt_button = WM_gizmotype_find("GIZMO_GT_button_2d", true); GizmoGroup_Resize2D *ggd = MEM_callocN(sizeof(GizmoGroup_Resize2D), __func__); @@ -462,15 +554,26 @@ static GizmoGroup_Resize2D *gizmogroup2d_resize_init(wmGizmoGroup *gzgroup) return ggd; } -void ED_widgetgroup_gizmo2d_resize_refresh(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_resize_refresh(const bContext *C, wmGizmoGroup *gzgroup) { GizmoGroup_Resize2D *ggd = gzgroup->customdata; float origin[3]; - gizmo2d_calc_bounds(C, origin, NULL, NULL); - copy_v2_v2(ggd->origin, origin); + const bool has_select = gizmo2d_calc_center(C, origin); + + if (has_select == false) { + for (int i = 0; i < ARRAY_SIZE(ggd->gizmo_xy); i++) { + ggd->gizmo_xy[i]->flag |= WM_GIZMO_HIDDEN; + } + } + else { + for (int i = 0; i < ARRAY_SIZE(ggd->gizmo_xy); i++) { + ggd->gizmo_xy[i]->flag &= ~WM_GIZMO_HIDDEN; + } + copy_v2_v2(ggd->origin, origin); + } } -void ED_widgetgroup_gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { ARegion *ar = CTX_wm_region(C); GizmoGroup_Resize2D *ggd = gzgroup->customdata; @@ -494,12 +597,7 @@ void ED_widgetgroup_gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup } } -bool ED_widgetgroup_gizmo2d_resize_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) -{ - return ED_widgetgroup_gizmo2d_xform_poll(C, NULL); -} - -void ED_widgetgroup_gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true); @@ -511,22 +609,24 @@ void ED_widgetgroup_gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup /* custom handler! */ WM_gizmo_set_fn_custom_modal(gz, gizmo2d_modal); - WM_gizmo_set_scale(gz, U.gizmo_size); if (i < 2) { - const float offset[3] = {0.0f, 0.2f}; float color[4], color_hi[4]; gizmo2d_get_axis_color(i, color, color_hi); /* set up widget data */ - RNA_float_set(gz->ptr, "angle", -M_PI_2 * i); - RNA_float_set(gz->ptr, "length", 0.8f); + RNA_float_set(gz->ptr, "length", 1.0f); + float axis[3] = {0.0f}; + axis[(i + 1) % 2] = 1.0f; + WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis); + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX); - WM_gizmo_set_matrix_offset_location(gz, offset); WM_gizmo_set_line_width(gz, GIZMO_AXIS_LINE_WIDTH); WM_gizmo_set_color(gz, color); WM_gizmo_set_color_highlight(gz, color_hi); + + WM_gizmo_set_scale(gz, 1.0f); } else { PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); @@ -536,6 +636,9 @@ void ED_widgetgroup_gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup /* Make the center low alpha. */ WM_gizmo_set_line_width(gz, 2.0f); RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.0); + WM_gizmo_set_color(gz, (const float[4]){1, 1, 1, 0.6}); + + WM_gizmo_set_scale(gz, 1.2f); } /* Assign operator. */ @@ -551,6 +654,26 @@ void ED_widgetgroup_gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup } } +static void gizmo2d_resize_message_subscribe(const struct bContext *C, + struct wmGizmoGroup *gzgroup, + struct wmMsgBus *mbus) +{ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, sa, ar); +} + +void ED_widgetgroup_gizmo2d_resize_callbacks_set(wmGizmoGroupType *gzgt) +{ + gzgt->poll = gizmo2d_generic_poll; + gzgt->setup = gizmo2d_resize_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->refresh = gizmo2d_resize_refresh; + gzgt->draw_prepare = gizmo2d_resize_draw_prepare; + gzgt->message_subscribe = gizmo2d_resize_message_subscribe; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -559,9 +682,6 @@ void ED_widgetgroup_gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup * Defines public functions, not the gizmo it's self: * * - #ED_widgetgroup_gizmo2d_rotate_setup - * - #ED_widgetgroup_gizmo2d_rotate_refresh - * - #ED_widgetgroup_gizmo2d_rotate_draw_prepare - * - #ED_widgetgroup_gizmo2d_rotate_poll * * \{ */ @@ -581,15 +701,22 @@ static GizmoGroup_Rotate2D *gizmogroup2d_rotate_init(wmGizmoGroup *gzgroup) return ggd; } -void ED_widgetgroup_gizmo2d_rotate_refresh(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_rotate_refresh(const bContext *C, wmGizmoGroup *gzgroup) { GizmoGroup_Rotate2D *ggd = gzgroup->customdata; float origin[3]; - gizmo2d_calc_bounds(C, origin, NULL, NULL); - copy_v2_v2(ggd->origin, origin); + const bool has_select = gizmo2d_calc_center(C, origin); + + if (has_select == false) { + ggd->gizmo->flag |= WM_GIZMO_HIDDEN; + } + else { + ggd->gizmo->flag &= ~WM_GIZMO_HIDDEN; + copy_v2_v2(ggd->origin, origin); + } } -void ED_widgetgroup_gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +static void gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { ARegion *ar = CTX_wm_region(C); GizmoGroup_Rotate2D *ggd = gzgroup->customdata; @@ -611,12 +738,7 @@ void ED_widgetgroup_gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup WM_gizmo_set_matrix_location(gz, origin); } -bool ED_widgetgroup_gizmo2d_rotate_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) -{ - return ED_widgetgroup_gizmo2d_xform_poll(C, NULL); -} - -void ED_widgetgroup_gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +static void gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_rotate", true); @@ -629,7 +751,7 @@ void ED_widgetgroup_gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup /* custom handler! */ WM_gizmo_set_fn_custom_modal(gz, gizmo2d_modal); - WM_gizmo_set_scale(gz, U.gizmo_size); + WM_gizmo_set_scale(gz, 1.2f); { PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); @@ -639,6 +761,7 @@ void ED_widgetgroup_gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup /* Make the center low alpha. */ WM_gizmo_set_line_width(gz, 2.0f); RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.0); + WM_gizmo_set_color(gz, (const float[4]){1, 1, 1, 0.6}); } /* Assign operator. */ @@ -647,4 +770,24 @@ void ED_widgetgroup_gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup } } +static void gizmo2d_rotate_message_subscribe(const struct bContext *C, + struct wmGizmoGroup *gzgroup, + struct wmMsgBus *mbus) +{ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, sa, ar); +} + +void ED_widgetgroup_gizmo2d_rotate_callbacks_set(wmGizmoGroupType *gzgt) +{ + gzgt->poll = gizmo2d_generic_poll; + gzgt->setup = gizmo2d_rotate_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->refresh = gizmo2d_rotate_refresh; + gzgt->draw_prepare = gizmo2d_rotate_draw_prepare; + gzgt->message_subscribe = gizmo2d_rotate_message_subscribe; +} + /** \} */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index b2d8671fbce..09992e8be0e 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -720,7 +720,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) ot->poll = ED_operator_screenactive; ot->poll_property = transform_poll_property; - RNA_def_float_vector_xyz( + RNA_def_float_translation( ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Move", "", -FLT_MAX, FLT_MAX); WM_operatortype_props_advanced_begin(ot); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 3159464072e..1952a2c862e 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -413,7 +413,7 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) int total = 0; for (bone = lb->first; bone; bone = bone->next) { - bone->flag &= ~BONE_TRANSFORM; + bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR); do_next = do_it; if (do_it) { if (bone->layer & arm->layer) { diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 604ecb984a9..63b9eb3937a 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -130,6 +130,8 @@ struct SnapObjectContext { /* Object -> SnapObjectData map */ struct { GHash *object_map; + /** Map object-data to objects so objects share edit mode data. */ + GHash *data_to_object_map; MemArena *mem_arena; } cache; @@ -164,6 +166,21 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3]) } } +static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob) +{ + SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); + if (sod == NULL) { + if (sctx->cache.data_to_object_map != NULL) { + ob = BLI_ghash_lookup(sctx->cache.data_to_object_map, ob->data); + /* Could be NULl when mixing edit-mode and non edit-mode objects. */ + if (ob != NULL) { + sod = BLI_ghash_lookup(sctx->cache.object_map, ob); + } + } + } + return sod; +} + static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob) { void **sod_p; @@ -182,13 +199,28 @@ static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, O return *sod_p; } -/* Use `em->ob` as the key in ghash since the editmesh is used - * to create bvhtree and is the same for each linked object. */ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx, + Object *ob, BMEditMesh *em) { void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) { + + { + /* Use object-data as the key in ghash since the editmesh + * is used to create bvhtree and is the same for each linked object. */ + if (sctx->cache.data_to_object_map == NULL) { + sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__); + } + void **ob_p; + if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob->data, &ob_p)) { + ob = *ob_p; + } + else { + *ob_p = ob; + } + } + + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH); } else { @@ -617,8 +649,6 @@ static bool raycastEditMesh(SnapObjectContext *sctx, return retval; } - BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob)); - float imat[4][4]; float ray_start_local[3], ray_normal_local[3]; float local_scale, local_depth, len_diff = 0.0f; @@ -638,7 +668,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, local_depth *= local_scale; } - SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em); + SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em); /* Test BoundBox */ @@ -666,7 +696,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, BVHTreeFromEditMesh *treedata = sod->bvh_trees[2]; - BVHCache **em_bvh_cache = &((Mesh *)em->ob->data)->runtime.bvh_cache; + BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache; if (sctx->callbacks.edit_mesh.test_face_fn == NULL) { /* The tree is owned by the Mesh and may have been freed since we last used! */ @@ -803,7 +833,7 @@ static bool raycastObj(SnapObjectContext *sctx, { bool retval = false; if (use_occlusion_test) { - if (use_obedit && sctx->use_v3d && XRAY_ENABLED(sctx->v3d_data.v3d)) { + if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) { /* Use of occlude geometry in editing mode disabled. */ return false; } @@ -1365,13 +1395,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, .dist_sq = SQUARE(*dist_px), }; - SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); - if (sod == NULL) { - /* The object is in edit mode, and the key used - * was the object referenced in BMEditMesh */ - BMEditMesh *em = BKE_editmesh_from_object(ob); - sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob); - } + SnapObjectData *sod = snap_object_data_lookup(sctx, ob); BLI_assert(sod != NULL); @@ -1492,13 +1516,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, return elem; } - SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); - if (sod == NULL) { - /* The object is in edit mode, and the key used - * was the object referenced in BMEditMesh */ - BMEditMesh *em = BKE_editmesh_from_object(ob); - sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob); - } + SnapObjectData *sod = snap_object_data_lookup(sctx, ob); BLI_assert(sod != NULL); @@ -2380,7 +2398,7 @@ static short snapEditMesh(SnapObjectContext *sctx, float dist_px_sq = SQUARE(*dist_px); - SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em); + SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em); /* Test BoundBox */ @@ -2390,7 +2408,7 @@ static short snapEditMesh(SnapObjectContext *sctx, return 0; } - BVHCache **em_bvh_cache = &((Mesh *)em->ob->data)->runtime.bvh_cache; + BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache; if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { if (sod->bvh_trees[0] == NULL) { @@ -2750,6 +2768,8 @@ SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain, sctx->depsgraph = depsgraph; sctx->cache.object_map = BLI_ghash_ptr_new(__func__); + /* Initialize as needed (edit-mode only). */ + sctx->cache.data_to_object_map = NULL; sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); return sctx; @@ -2797,6 +2817,9 @@ static void snap_object_data_free(void *sod_v) void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); + if (sctx->cache.data_to_object_map != NULL) { + BLI_ghash_free(sctx->cache.data_to_object_map, NULL, NULL); + } BLI_memarena_free(sctx->cache.mem_arena); MEM_freeN(sctx); |