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:
authorYimingWu <xp8110@outlook.com>2020-02-01 05:35:40 +0300
committerYimingWu <xp8110@outlook.com>2020-02-01 05:35:40 +0300
commitf7770cb97bb9d19d0806f67da9377129fd4d09b0 (patch)
tree2cd22d612ffba3a509d5548332c9cc8a06a1a638 /source/blender/editors/transform
parentb47883a990ee68e659a8a8b44729be9b8e0d002f (diff)
parentdc3f073d1c5255e79763dfff3ef17f6216f1b391 (diff)
Merge remote-tracking branch 'origin/master' into temp-lanpr-review
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/transform.c17
-rw-r--r--source/blender/editors/transform/transform_convert.c20
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c65
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c4
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c20
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c10
-rw-r--r--source/blender/editors/transform/transform_draw.c114
-rw-r--r--source/blender/editors/transform/transform_generics.c88
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c413
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/transform/transform_snap_object.c71
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);