diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2018-08-12 14:59:39 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2018-08-12 14:59:39 +0300 |
commit | b8ab411185c11ce98e7e791b0d30a9d9b1ce6d69 (patch) | |
tree | 9c219e06fc6a1f9b09d6fbf7d86c8526cfa6d775 /source/blender/editors/transform | |
parent | 209686f1c8189bc01f91d14a922651844df8b201 (diff) | |
parent | dc2d841b7c50565302af2986d62ddbd29c332acd (diff) |
Merge branch 'hair_guides' into hair_guides_groominghair_guides_grooming
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r-- | source/blender/editors/transform/transform.c | 387 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 6 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_constraints.c | 18 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 332 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 36 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_gizmo_2d.c | 28 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_gizmo_3d.c | 234 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_ops.c | 70 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 8 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap_object.c | 203 |
10 files changed, 946 insertions, 376 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ad7b5d55ba5..142460bb7fa 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -41,9 +41,11 @@ #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_mask_types.h" +#include "DNA_mesh_types.h" #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ #include "DNA_workspace_types.h" +#include "DNA_gpencil_types.h" #include "BLI_alloca.h" #include "BLI_utildefines.h" @@ -64,6 +66,7 @@ #include "BKE_unit.h" #include "BKE_scene.h" #include "BKE_mask.h" +#include "BKE_mesh.h" #include "BKE_report.h" #include "BKE_workspace.h" @@ -85,6 +88,7 @@ #include "ED_mesh.h" #include "ED_clip.h" #include "ED_node.h" +#include "ED_gpencil.h" #include "WM_types.h" #include "WM_api.h" @@ -95,6 +99,7 @@ #include "UI_resources.h" #include "RNA_access.h" +#include "RNA_define.h" #include "BLF_api.h" #include "BLT_translation.h" @@ -115,6 +120,7 @@ static void postInputRotation(TransInfo *t, float values[3]); static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around); static void initSnapSpatial(TransInfo *t, float r_snap[3]); +static void storeCustomLNorValue(TransDataContainer *t, BMesh *bm); /* Transform Callbacks */ static void initBend(TransInfo *t); @@ -140,6 +146,9 @@ static void applyToSphere(TransInfo *t, const int mval[2]); static void initRotation(TransInfo *t); static void applyRotation(TransInfo *t, const int mval[2]); +static void initNormalRotation(TransInfo *t); +static void applyNormalRotation(TransInfo *t, const int mval[2]); + static void initShrinkFatten(TransInfo *t); static void applyShrinkFatten(TransInfo *t, const int mval[2]); @@ -571,6 +580,10 @@ void removeAspectRatio(TransInfo *t, float vec[2]) static void viewRedrawForce(const bContext *C, TransInfo *t) { if (t->options & CTX_GPENCIL_STROKES) { + bGPdata *gpd = ED_gpencil_data_get_active(C); + if (gpd) { + DEG_id_tag_update(&gpd->id, OB_RECALC_DATA); + } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else if (t->spacetype == SPACE_VIEW3D) { @@ -1546,6 +1559,18 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } break; + case NKEY: + if (ELEM(t->mode, TFM_ROTATION)) { + if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initNormalRotation(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + } + break; default: break; } @@ -1689,13 +1714,13 @@ typedef enum { } ArrowDirection; #define POS_INDEX 0 -/* NOTE: this --^ is a bit hackish, but simplifies Gwn_VertFormat usage among functions +/* NOTE: this --^ is a bit hackish, but simplifies GPUVertFormat usage among functions * private to this file - merwin */ static void drawArrow(ArrowDirection d, short offset, short length, short size) { - immBegin(GWN_PRIM_LINES, 6); + immBegin(GPU_PRIM_LINES, 6); switch (d) { case LEFT: @@ -1732,7 +1757,7 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) static void drawArrowHead(ArrowDirection d, short size) { - immBegin(GWN_PRIM_LINES, 4); + immBegin(GPU_PRIM_LINES, 4); switch (d) { case LEFT: @@ -1765,7 +1790,7 @@ static void drawArc(float size, float angle_start, float angle_end, int segments float angle; int a; - immBegin(GWN_PRIM_LINE_STRIP, segments + 1); + immBegin(GPU_PRIM_LINE_STRIP, segments + 1); for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); @@ -1784,7 +1809,7 @@ static bool helpline_poll(bContext *C) return 0; } -static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) +static void drawHelpline(bContext *C, int x, int y, void *customdata) { TransInfo *t = (TransInfo *)customdata; @@ -1800,7 +1825,31 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) (float)t->mval[1], }; - projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + /* grease pencil only can edit one object at time because GP has + * multiframe edition that replaces multiobject edition. + * If multiobject edition is added, maybe this code will need + * an update + */ + if ((t->flag & T_POINTS) && (t->options & CTX_GPENCIL_STROKES) && + (t->around != V3D_AROUND_ACTIVE)) + { + Object *ob = CTX_data_active_object(C); + if ((ob) && (ob->type == OB_GPENCIL)) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + float vecrot[3]; + copy_v3_v3(vecrot, t->center_global); + mul_m4_v3(ob->obmat, vecrot); + projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO); + } + } + else { + /* normally, never must be used */ + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + } + } + else { + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + } /* Offset the values for the area region. */ const float offset[2] = { @@ -1813,11 +1862,11 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) tmval[i] += offset[i]; } - gpuPushMatrix(); + GPU_matrix_push(); /* Dashed lines first. */ if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { - const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ BLI_assert(shdr_pos == POS_INDEX); @@ -1835,7 +1884,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) immUniform1f("dash_width", 6.0f); immUniform1f("dash_factor", 0.5f); - immBegin(GWN_PRIM_LINES, 2); + immBegin(GPU_PRIM_LINES, 2); immVertex2fv(POS_INDEX, cent); immVertex2f(POS_INDEX, tmval[0], tmval[1]); immEnd(); @@ -1844,7 +1893,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) } /* And now, solid lines. */ - uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); UNUSED_VARS_NDEBUG(pos); /* silence warning */ BLI_assert(pos == POS_INDEX); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -1853,8 +1902,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) case HLP_SPRING: immUniformThemeColor(TH_VIEW_OVERLAY); - gpuTranslate3fv(mval); - gpuRotateAxis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); + GPU_matrix_translate_3fv(mval); + GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); GPU_line_width(3.0f); drawArrow(UP, 5, 10, 5); @@ -1862,7 +1911,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) break; case HLP_HARROW: immUniformThemeColor(TH_VIEW_OVERLAY); - gpuTranslate3fv(mval); + GPU_matrix_translate_3fv(mval); GPU_line_width(3.0f); drawArrow(RIGHT, 5, 10, 5); @@ -1871,7 +1920,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) case HLP_VARROW: immUniformThemeColor(TH_VIEW_OVERLAY); - gpuTranslate3fv(mval); + GPU_matrix_translate_3fv(mval); GPU_line_width(3.0f); drawArrow(UP, 5, 10, 5); @@ -1887,23 +1936,23 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) immUniformThemeColor(TH_VIEW_OVERLAY); - gpuTranslate3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); + GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); GPU_line_width(3.0f); drawArc(dist, angle - delta_angle, angle - spacing_angle, 10); drawArc(dist, angle + spacing_angle, angle + delta_angle, 10); - gpuPushMatrix(); + GPU_matrix_push(); - gpuTranslate3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); - gpuRotateAxis(RAD2DEGF(angle - delta_angle), 'Z'); + GPU_matrix_translate_3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z'); drawArrowHead(DOWN, 5); - gpuPopMatrix(); + GPU_matrix_pop(); - gpuTranslate3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); - gpuRotateAxis(RAD2DEGF(angle + delta_angle), 'Z'); + GPU_matrix_translate_3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z'); drawArrowHead(UP, 5); break; @@ -1913,7 +1962,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) unsigned char col[3], col2[3]; UI_GetThemeColor3ubv(TH_GRID, col); - gpuTranslate3fv(mval); + GPU_matrix_translate_3fv(mval); GPU_line_width(3.0f); @@ -1933,7 +1982,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) } immUnbindProgram(); - gpuPopMatrix(); + GPU_matrix_pop(); } } @@ -2153,7 +2202,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } - RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + /* Only set if needed, so we can hide in the UI when nothing is set. + * See 'transform_poll_property'. */ + if (ELEM(true, UNPACK3(constraint_axis))) { + RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + } } { @@ -2501,6 +2554,9 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve case TFM_SEQ_SLIDE: initSeqSlide(t); break; + case TFM_NORMAL_ROTATION: + initNormalRotation(t); + break; } if (t->state == TRANS_CANCEL) { @@ -2508,6 +2564,39 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve return 0; } + if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) { + if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { + + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) { + BMEditMesh *em = NULL;// BKE_editmesh_from_object(t->obedit); + bool do_skip = false; + + /* Currently only used for two of three most frequent transform ops, can include more ops. + * Note that scaling cannot be included here, non-uniform scaling will affect normals. */ + if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) { + if (em->bm->totvertsel == em->bm->totvert) { + /* No need to invalidate if whole mesh is selected. */ + do_skip = true; + } + } + + if (t->flag & T_MODAL) { + RNA_property_boolean_set(op->ptr, prop, false); + } + else if (!do_skip) { + const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); + if (preserve_clnor) { + BKE_editmesh_lnorspace_update(em); + t->flag |= T_CLNOR_REBUILD; + } + BM_lnorspace_invalidate(em->bm, true); + } + } + } + } + } + t->context = NULL; return 1; @@ -2568,6 +2657,12 @@ int transformEnd(bContext *C, TransInfo *t) restoreTransObjects(t); // calls recalcData() } else { + if (t->flag & T_CLNOR_REBUILD) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BM_lnorspace_rebuild(em->bm, true); + } + } exit_code = OPERATOR_FINISHED; } @@ -3547,7 +3642,25 @@ static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, f else sub_v3_v3(vec, td->center); - mul_v3_fl(vec, td->factor); + /* grease pencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); + + /* scale stroke thickness */ + if (td->val) { + snapGridIncrement(t, t->values); + applyNumInput(&t->num, t->values); + + float ratio = t->values[0]; + *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; + CLAMP_MIN(*td->val, 0.001f); + } + + } + else { + mul_v3_fl(vec, td->factor); + } if (t->flag & (T_OBJECT | T_POSE)) { mul_m3_v3(td->smtx, vec); @@ -3886,6 +3999,28 @@ static void initRotation(TransInfo *t) copy_v3_v3(t->axis_orig, t->axis); } +/* Used by Transform Rotation and Transform Normal Rotation */ +static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) +{ + size_t ofs = 0; + + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + + outputNumInput(&(t->num), c, &t->scene->unit); + + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); + } + else { + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %.2f%s %s"), + RAD2DEGF(final), t->con.text, t->proptext); + } + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } +} + /** * Applies values of rotation to `td->loc` and `td->ext->quat` * based on a rotation matrix (mat) and a pivot (center). @@ -3901,6 +4036,20 @@ static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData * mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); + /* apply gpencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + float sx = smat[0][0]; + float sy = smat[1][1]; + float sz = smat[2][2]; + + mul_m3_fl(smat, gps->runtime.multi_frame_falloff); + /* fix scale */ + smat[0][0] = sx; + smat[1][1] = sy; + smat[2][2] = sz; + } + sub_v3_v3v3(vec, td->iloc, center); mul_m3_v3(smat, vec); @@ -4149,7 +4298,6 @@ static void applyRotationValue(TransInfo *t, float angle, float axis[3]) static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; - size_t ofs = 0; float final; @@ -4172,21 +4320,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - - outputNumInput(&(t->num), c, &t->scene->unit); - - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); - } - else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Rot: %.2f%s %s"), - RAD2DEGF(final), t->con.text, t->proptext); - } - - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } + headerRotation(t, str, final); applyRotationValue(t, final, t->axis); @@ -4315,6 +4449,127 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) /* -------------------------------------------------------------------- */ +/* Transform (Normal Rotation) */ + +/** \name Transform Normal Rotation +* \{ */ + +static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm) +{ + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + + tc->custom.mode.data = lnors_ed_arr; + tc->custom.mode.free_cb = freeCustomNormalArray; +} + +void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data) +{ + BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data; + + if (t->state == TRANS_CANCEL) { + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { /* Restore custom loop normal on cancel */ + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data); + } + } + + BM_loop_normal_editdata_array_free(lnors_ed_arr); + + tc->custom.mode.data = NULL; + tc->custom.mode.free_cb = NULL; +} + +static void initNormalRotation(TransInfo *t) +{ + t->mode = TFM_NORMAL_ROTATION; + t->transform = applyNormalRotation; + + setInputPostFct(&t->mouse, postInputRotation); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); + + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; + + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + BKE_editmesh_lnorspace_update(em); + + storeCustomLNorValue(tc, bm); + } + + negate_v3_v3(t->axis, t->viewinv[2]); + normalize_v3(t->axis); + + copy_v3_v3(t->axis_orig, t->axis); +} + +/* Works by getting custom normal from clnor_data, transform, then store */ +static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) +{ + char str[UI_MAX_DRAW_STR]; + + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { + t->con.applyRot(t, NULL, NULL, t->axis, NULL); + } + else { + /* reset axis if constraint is not set */ + copy_v3_v3(t->axis, t->axis_orig); + } + + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data; + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + + float axis[3]; + float mat[3][3]; + float angle = t->values[0]; + copy_v3_v3(axis, t->axis); + + snapGridIncrement(t, &angle); + + applySnapping(t, &angle); + + applyNumInput(&t->num, &angle); + + headerRotation(t, str, angle); + + axis_angle_normalized_to_mat3(mat, axis, angle); + + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { + mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc); + + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data); + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ /* Transform (Translation) */ static void initSnapSpatial(TransInfo *t, float r_snap[3]) @@ -4574,7 +4829,21 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) } mul_m3_v3(td->smtx, tvec); - mul_v3_fl(tvec, td->factor); + + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + mul_v3_fl(tvec, td->factor); + } + } + else { + /* proportional editing falloff */ + mul_v3_fl(tvec, td->factor); + } protectedTransBits(td->protectflag, tvec); @@ -6654,7 +6923,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t if (t->spacetype == SPACE_VIEW3D) { v3d = t->sa ? t->sa->spacedata.first : NULL; rv3d = t->ar ? t->ar->regiondata : NULL; - use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE); + use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->shading.type > OB_WIRE); } calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true); @@ -6849,7 +7118,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *t if (t->spacetype == SPACE_VIEW3D) { v3d = t->sa ? t->sa->spacedata.first : NULL; rv3d = t->ar ? t->ar->regiondata : NULL; - use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE); + use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->shading.type > OB_WIRE); } calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false); @@ -7049,10 +7318,10 @@ static void drawEdgeSlide(TransInfo *t) GPU_blend(true); GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - gpuPushMatrix(); - gpuMultMatrix(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); @@ -7069,7 +7338,7 @@ static void drawEdgeSlide(TransInfo *t) GPU_line_width(line_size); immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBeginAtMost(GWN_PRIM_LINES, 4); + immBeginAtMost(GPU_PRIM_LINES, 4); if (curr_sv->v_side[0]) { immVertex3fv(pos, curr_sv->v_side[0]->co); immVertex3fv(pos, curr_sv->v_co_orig); @@ -7082,7 +7351,7 @@ static void drawEdgeSlide(TransInfo *t) immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); GPU_point_size(ctrl_size); - immBegin(GWN_PRIM_POINTS, 1); + immBegin(GPU_PRIM_POINTS, 1); if (slp->flipped) { if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co); } @@ -7093,7 +7362,7 @@ static void drawEdgeSlide(TransInfo *t) immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); GPU_point_size(guide_size); - immBegin(GWN_PRIM_POINTS, 1); + immBegin(GPU_PRIM_POINTS, 1); interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); immVertex3fv(pos, co_mark); immEnd(); @@ -7107,7 +7376,7 @@ static void drawEdgeSlide(TransInfo *t) GPU_line_width(line_size); immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBegin(GWN_PRIM_LINES, sld->totsv * 2); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); /* TODO(campbell): Loop over all verts */ sv = sld->sv; @@ -7138,7 +7407,7 @@ static void drawEdgeSlide(TransInfo *t) immUnbindProgram(); - gpuPopMatrix(); + GPU_matrix_pop(); GPU_blend(false); @@ -7682,17 +7951,17 @@ static void drawVertSlide(TransInfo *t) GPU_blend(true); GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - gpuPushMatrix(); - gpuMultMatrix(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); GPU_line_width(line_size); - const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBegin(GWN_PRIM_LINES, sld->totsv * 2); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); if (is_clamp) { sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { @@ -7718,7 +7987,7 @@ static void drawVertSlide(TransInfo *t) GPU_point_size(ctrl_size); - immBegin(GWN_PRIM_POINTS, 1); + immBegin(GPU_PRIM_POINTS, 1); immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ? curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : curr_sv->co_orig_3d); @@ -7761,7 +8030,7 @@ static void drawVertSlide(TransInfo *t) immUniform1f("dash_width", 6.0f); immUniform1f("dash_factor", 0.5f); - immBegin(GWN_PRIM_LINES, 2); + immBegin(GPU_PRIM_LINES, 2); immVertex3fv(shdr_pos, curr_sv->co_orig_3d); immVertex3fv(shdr_pos, co_dest_3d); immEnd(); @@ -7769,7 +8038,7 @@ static void drawVertSlide(TransInfo *t) immUnbindProgram(); } - gpuPopMatrix(); + GPU_matrix_pop(); GPU_depth_test(true); } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a74a0dc7a11..688e90b3936 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -505,7 +505,7 @@ typedef struct TransInfo { short current_orientation; TransformOrientation *custom_orientation; /* this gets used when current_orientation is V3D_MANIP_CUSTOM */ - short mpr_flag; /* backup from view3d, to restore on end */ + short gizmo_flag; /* backup from view3d, to restore on end */ short prop_mode; @@ -609,6 +609,8 @@ typedef struct TransInfo { #define T_MODAL_CURSOR_SET (1 << 26) +#define T_CLNOR_REBUILD (1 << 27) + /* TransInfo->modifiers */ #define MOD_CONSTRAINT_SELECT 0x01 #define MOD_PRECISION 0x02 @@ -878,6 +880,8 @@ bool applyTransformOrientation(const struct TransformOrientation *ts, float r_ma int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around); int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]); +void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data); + void freeEdgeSlideTempFaces(EdgeSlideData *sld); void freeEdgeSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data); void projectEdgeSlideData(TransInfo *t, bool is_final); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index d40602f8d43..b24ef4e0ba2 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -560,7 +560,9 @@ static void applyObjectConstraintRot( /* on setup call, use first object */ if (td == NULL) { - td = TRANS_DATA_CONTAINER_FIRST_OK(t)->data; + BLI_assert(tc == NULL); + tc = TRANS_DATA_CONTAINER_FIRST_OK(t); + td = tc->data; } if (t->flag & T_EDIT) { @@ -747,7 +749,7 @@ void drawConstraint(TransInfo *t) if (depth_test_enabled) GPU_depth_test(false); - const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); @@ -760,7 +762,7 @@ void drawConstraint(TransInfo *t) immUniform1f("dash_width", 2.0f); immUniform1f("dash_factor", 0.5f); - immBegin(GWN_PRIM_LINES, 2); + immBegin(GPU_PRIM_LINES, 2); immVertex3fv(shdr_pos, t->center_global); immVertex3fv(shdr_pos, vec); immEnd(); @@ -800,13 +802,13 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) unit_m4(imat); } - gpuPushMatrix(); + GPU_matrix_push(); if (t->spacetype == SPACE_VIEW3D) { /* pass */ } else if (t->spacetype == SPACE_IMAGE) { - gpuScale2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]); + GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]); } else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { /* only scale y */ @@ -816,14 +818,14 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) float ysize = BLI_rctf_size_y(datamask); float xmask = BLI_rcti_size_x(mask); float ymask = BLI_rcti_size_y(mask); - gpuScale2f(1.0f, (ysize / xsize) * (xmask / ymask)); + 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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_GRID); @@ -837,7 +839,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) if (depth_test_enabled) GPU_depth_test(true); - gpuPopMatrix(); + GPU_matrix_pop(); } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9ae75a8909f..215bb56bec9 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -92,6 +92,7 @@ #include "BKE_editmesh.h" #include "BKE_tracking.h" #include "BKE_mask.h" +#include "BKE_colortools.h" #include "BIK_api.h" @@ -749,7 +750,7 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb) /* sets transform flags in the bones * returns total number of bones with BONE_TRANSFORM */ -int count_set_pose_transflags(Object *ob, const int mode, short around, bool has_translate_rotate[2]) +int count_set_pose_transflags(Object *ob, const int mode, const short around, bool has_translate_rotate[2]) { bArmature *arm = ob->data; bPoseChannel *pchan; @@ -3850,6 +3851,8 @@ static void posttrans_gpd_clean(bGPdata *gpd) } #endif } + /* set cache flag to dirty */ + DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA); } static void posttrans_mask_clean(Mask *mask) @@ -8327,7 +8330,14 @@ void flushTransPaintCurve(TransInfo *t) static void createTransGPencil(bContext *C, TransInfo *t) { + Depsgraph *depsgraph = CTX_data_depsgraph(C); \ bGPdata *gpd = ED_gpencil_data_get_active(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_BRUSHEDIT_FLAG_FRAME_FALLOFF) != 0; + + Object *obact = CTX_data_active_object(C); bGPDlayer *gpl; TransData *td = NULL; float mtx[3][3], smtx[3][3]; @@ -8351,50 +8361,67 @@ static void createTransGPencil(bContext *C, TransInfo *t) if (gpd == NULL) return; + /* initialize falloff curve */ + if (is_multiedit) { + curvemapping_initialize(ts->gp_sculpt.cur_falloff); + } + /* First Pass: Count the number of datapoints required for the strokes, * (and additional info about the configuration - e.g. 2D/3D?) */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { - bGPDframe *gpf = gpl->actframe; + bGPDframe *gpf; bGPDstroke *gps; + bGPDframe *init_gpf = gpl->actframe; + if (is_multiedit) { + init_gpf = gpl->frames.first; + } - for (gps = gpf->strokes.first; gps; gps = gps->next) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { - continue; - } + for (gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + for (gps = gpf->strokes.first; gps; gps = gps->next) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + continue; + } - if (is_prop_edit) { - /* Proportional Editing... */ - if (is_prop_edit_connected) { - /* connected only - so only if selected */ - if (gps->flag & GP_STROKE_SELECT) - tc->data_len += gps->totpoints; - } - else { - /* everything goes - connection status doesn't matter */ - tc->data_len += gps->totpoints; - } - } - else { - /* only selected stroke points are considered */ - if (gps->flag & GP_STROKE_SELECT) { - bGPDspoint *pt; - int i; - - // TODO: 2D vs 3D? - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) - tc->data_len++; + if (is_prop_edit) { + /* Proportional Editing... */ + if (is_prop_edit_connected) { + /* connected only - so only if selected */ + if (gps->flag & GP_STROKE_SELECT) + tc->data_len += gps->totpoints; + } + else { + /* everything goes - connection status doesn't matter */ + tc->data_len += gps->totpoints; + } + } + else { + /* only selected stroke points are considered */ + if (gps->flag & GP_STROKE_SELECT) { + bGPDspoint *pt; + int i; + + // TODO: 2D vs 3D? + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->flag & GP_SPOINT_SELECT) + tc->data_len++; + } + } } } } + /* if not multiedit out of loop */ + if (!is_multiedit) { + break; + } } } } @@ -8421,153 +8448,166 @@ static void createTransGPencil(bContext *C, TransInfo *t) float diff_mat[4][4]; float inverse_diff_mat[4][4]; - /* calculate difference matrix if parent object */ - if (gpl->parent != NULL) { - ED_gpencil_parent_location(gpl, diff_mat); - /* undo matrix */ - invert_m4_m4(inverse_diff_mat, diff_mat); + bGPDframe *init_gpf = gpl->actframe; + if (is_multiedit) { + init_gpf = gpl->frames.first; } + /* init multiframe falloff options */ + int f_init = 0; + int f_end = 0; + + if (use_multiframe_falloff) { + BKE_gpencil_get_range_selected(gpl, &f_init, &f_end); + } + + /* calculate difference matrix */ + ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); + /* undo matrix */ + invert_m4_m4(inverse_diff_mat, diff_mat); /* Make a new frame to work on if the layer's frame and the current scene frame don't match up * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame... */ - if (gpf->framenum != cfra) { + // XXX: should this be allowed when framelock is enabled? + if ((gpf->framenum != cfra) && (!is_multiedit)) { gpf = BKE_gpencil_frame_addcopy(gpl, cfra); /* in some weird situations (framelock enabled) return NULL */ if (gpf == NULL) { continue; } + if (!is_multiedit) { + init_gpf = gpf; + } } /* Loop over strokes, adding TransData for points as needed... */ - for (gps = gpf->strokes.first; gps; gps = gps->next) { - TransData *head = td; - TransData *tail = td; - bool stroke_ok; - - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(gpl, gps) == false) { - continue; - } - /* What we need to include depends on proportional editing settings... */ - if (is_prop_edit) { - if (is_prop_edit_connected) { - /* A) "Connected" - Only those in selected strokes */ - stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; - } - else { - /* B) All points, always */ - stroke_ok = true; - } - } - else { - /* C) Only selected points in selected strokes */ - stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; - } - - /* Do stroke... */ - if (stroke_ok && gps->totpoints) { - bGPDspoint *pt; - int i; - -#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */ - const float ninv = 1.0f / gps->totpoints; - float center[3] = {0.0f}; - - /* compute midpoint of stroke */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - madd_v3_v3v3fl(center, center, &pt->x, ninv); + for (gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + + /* if multiframe and falloff, recalculate and save value */ + float falloff = 1.0f; /* by default no falloff */ + if ((is_multiedit) && (use_multiframe_falloff)) { + /* Faloff depends on distance to active frame (relative to the overall frame range) */ + falloff = BKE_gpencil_multiframe_falloff_calc(gpf, gpl->actframe->framenum, + f_init, f_end, ts->gp_sculpt.cur_falloff); } -#endif - /* add all necessary points... */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - bool point_ok; + for (gps = gpf->strokes.first; gps; gps = gps->next) { + TransData *head = td; + TransData *tail = td; + bool stroke_ok; - /* include point? */ + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + continue; + } + /* What we need to include depends on proportional editing settings... */ if (is_prop_edit) { - /* Always all points in strokes that get included */ - point_ok = true; + if (is_prop_edit_connected) { + /* A) "Connected" - Only those in selected strokes */ + stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; + } + else { + /* B) All points, always */ + stroke_ok = true; + } } else { - /* Only selected points in selected strokes */ - point_ok = (pt->flag & GP_SPOINT_SELECT) != 0; + /* C) Only selected points in selected strokes */ + stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; } - /* do point... */ - if (point_ok) { - copy_v3_v3(td->iloc, &pt->x); - copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local? - - td->loc = &pt->x; - - td->flag = 0; + /* Do stroke... */ + if (stroke_ok && gps->totpoints) { + bGPDspoint *pt; + int i; - if (pt->flag & GP_SPOINT_SELECT) - td->flag |= TD_SELECTED; - - /* for other transform modes (e.g. shrink-fatten), need to additional data */ - if (t->mode == TFM_GPENCIL_SHRINKFATTEN) { - td->val = &pt->pressure; - td->ival = pt->pressure; - } + /* save falloff factor */ + gps->runtime.multi_frame_falloff = falloff; - /* screenspace needs special matrices... */ - if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) { - /* screenspace */ - td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; + /* add all necessary points... */ + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + bool point_ok; - /* apply parent transformations */ - if (gpl->parent == NULL) { - copy_m3_m4(td->smtx, t->persmat); - copy_m3_m4(td->mtx, t->persinv); - unit_m3(td->axismtx); + /* include point? */ + if (is_prop_edit) { + /* Always all points in strokes that get included */ + point_ok = true; } else { - /* apply matrix transformation relative to parent */ - copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ - copy_m3_m4(td->mtx, diff_mat); /* display position */ - copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ - } - } - else { - /* configure 2D dataspace points so that they don't play up... */ - if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) { - td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; - // XXX: matrices may need to be different? + /* Only selected points in selected strokes */ + point_ok = (pt->flag & GP_SPOINT_SELECT) != 0; } - /* apply parent transformations */ - if (gpl->parent == NULL) { - copy_m3_m3(td->smtx, smtx); - copy_m3_m3(td->mtx, mtx); - unit_m3(td->axismtx); // XXX? - } - else { - /* apply matrix transformation relative to parent */ - copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ - copy_m3_m4(td->mtx, diff_mat); /* display position */ - copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ + /* do point... */ + if (point_ok) { + copy_v3_v3(td->iloc, &pt->x); + copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local? + + td->loc = &pt->x; + + td->flag = 0; + + if (pt->flag & GP_SPOINT_SELECT) + td->flag |= TD_SELECTED; + + /* for other transform modes (e.g. shrink-fatten), need to additional data + * but never for scale or mirror + */ + if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) { + td->val = &pt->pressure; + td->ival = pt->pressure; + } + + /* screenspace needs special matrices... */ + if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) { + /* screenspace */ + td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; + + /* apply matrix transformation relative to parent */ + copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ + copy_m3_m4(td->mtx, diff_mat); /* display position */ + copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ + } + else { + /* configure 2D dataspace points so that they don't play up... */ + if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) { + td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; + // XXX: matrices may need to be different? + } + + /* apply parent transformations */ + copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ + copy_m3_m4(td->mtx, diff_mat); /* display position */ + copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ + } + /* Triangulation must be calculated again, so save the stroke for recalc function */ + td->extra = gps; + + /* save pointer to object */ + td->ob = obact; + + td++; + tail++; } } - /* Triangulation must be calculated again, so save the stroke for recalc function */ - td->extra = gps; - td++; - tail++; + /* March over these points, and calculate the proportional editing distances */ + if (is_prop_edit && (head != tail)) { + /* XXX: for now, we are similar enough that this works... */ + calc_distanceCurveVerts(head, tail - 1); + } } } - - /* March over these points, and calculate the proportional editing distances */ - if (is_prop_edit && (head != tail)) { - /* XXX: for now, we are similar enough that this works... */ - calc_distanceCurveVerts(head, tail - 1); - } + } + /* if not multiedit out of loop */ + if (!is_multiedit) { + break; } } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 6bb3da4b229..6eb1eca1d18 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -74,6 +74,7 @@ #include "BKE_armature.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_gpencil.h" #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_main.h" @@ -105,6 +106,7 @@ #include "ED_curve.h" /* for curve_editnurbs */ #include "ED_clip.h" #include "ED_screen.h" +#include "ED_gpencil.h" #include "WM_types.h" #include "WM_api.h" @@ -379,7 +381,8 @@ static void recalcData_actedit(TransInfo *t) /* flush transform values back to actual coordinates */ flushTransIntFrameActionData(t); } - else { + + if (ac.datatype != ANIMCONT_MASK) { /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -1123,7 +1126,7 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis if (t->spacetype == SPACE_VIEW3D) { View3D *v3d = t->view; - gpuPushMatrix(); + GPU_matrix_push(); copy_v3_v3(v3, dir); mul_v3_fl(v3, v3d->far); @@ -1139,19 +1142,19 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis } UI_make_axis_color(col, col2, axis); - uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor3ubv(col2); - immBegin(GWN_PRIM_LINES, 2); + immBegin(GPU_PRIM_LINES, 2); immVertex3fv(pos, v1); immVertex3fv(pos, v2); immEnd(); immUnbindProgram(); - gpuPopMatrix(); + GPU_matrix_pop(); } } @@ -1318,7 +1321,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } /* GPencil editing context */ - if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) { + if (GPENCIL_ANY_MODE(gpd)) { t->options |= CTX_GPENCIL_STROKES; } @@ -1357,8 +1360,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* turn gizmo off during transform */ if (t->flag & T_MODAL) { - t->mpr_flag = v3d->mpr_flag; - v3d->mpr_flag = V3D_GIZMO_HIDE; + t->gizmo_flag = v3d->gizmo_flag; + v3d->gizmo_flag = V3D_GIZMO_HIDE; } if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) { @@ -1697,7 +1700,7 @@ void postTrans(bContext *C, TransInfo *t) View3D *v3d = t->sa->spacedata.first; /* restore gizmo */ if (t->flag & T_MODAL) { - v3d->mpr_flag = t->mpr_flag; + v3d->gizmo_flag = t->gizmo_flag; } } @@ -1830,6 +1833,21 @@ void calculateCenterCursor(TransInfo *t, float r_center[3]) } r_center[2] = 0.0f; } + else if (t->options & CTX_GPENCIL_STROKES) { + /* move cursor in local space */ + TransData *td = NULL; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + float mat[3][3], imat[3][3]; + + td = tc->data; + Object *ob = td->ob; + + sub_v3_v3v3(r_center, r_center, ob->obmat[3]); + copy_m3_m4(mat, ob->obmat); + invert_m3_m3(imat, mat); + mul_m3_v3(imat, r_center); + } + } } void calculateCenterCursor2D(TransInfo *t, float r_center[2]) diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index 995faae8333..ff69c2859fc 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -128,16 +128,16 @@ static void gizmo2d_get_axis_color(const int axis_idx, float *r_col, float *r_co r_col_hi[3] *= alpha_hi; } -static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *mgroup) +static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup) { - const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_2d", true); - const wmGizmoType *wt_cage = WM_gizmotype_find("GIZMO_WT_cage_2d", true); + const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true); + const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true); GizmoGroup2D *man = MEM_callocN(sizeof(GizmoGroup2D), __func__); - man->translate_x = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL); - man->translate_y = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL); - man->cage = WM_gizmo_new_ptr(wt_cage, mgroup, NULL); + man->translate_x = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); + man->translate_y = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); + man->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL); RNA_enum_set(man->cage->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | @@ -197,11 +197,11 @@ static int gizmo2d_modal( return OPERATOR_RUNNING_MODAL; } -void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup) +void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true); - GizmoGroup2D *man = gizmogroup2d_init(mgroup); - mgroup->customdata = man; + GizmoGroup2D *man = gizmogroup2d_init(gzgroup); + gzgroup->customdata = man; MAN2D_ITER_AXES_BEGIN(axis, axis_idx) { @@ -271,9 +271,9 @@ void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *mgrou } } -void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *mgroup) +void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - GizmoGroup2D *man = mgroup->customdata; + GizmoGroup2D *man = gzgroup->customdata; float origin[3]; gizmo2d_calc_bounds(C, origin, man->min, man->max); copy_v2_v2(man->origin, origin); @@ -321,10 +321,10 @@ void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *mgroup) } } -void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *mgroup) +void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { ARegion *ar = CTX_wm_region(C); - GizmoGroup2D *man = mgroup->customdata; + GizmoGroup2D *man = gzgroup->customdata; float origin[3] = {UNPACK2(man->origin), 0.0f}; float origin_aa[3] = {UNPACK2(man->origin), 0.0f}; @@ -346,7 +346,7 @@ void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *mgroup * - 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_poll(const bContext *C, wmGizmoGroupType *UNUSED(wgt)) +bool ED_widgetgroup_gizmo2d_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) { return false; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 7d608c433c3..5fe7bbbf45e 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -107,7 +107,7 @@ #define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z) /* threshold for testing view aligned gizmo axis */ -struct { +static struct { float min, max; } g_tw_axis_range[2] = { /* Regular range */ @@ -148,7 +148,9 @@ enum { #define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X #define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1) - MAN_AXIS_LAST = MAN_AXIS_RANGE_SCALE_END, + MAN_AXIS_APRON_C, + + MAN_AXIS_LAST = MAN_AXIS_APRON_C + 1, }; /* axis types */ @@ -162,6 +164,7 @@ enum { typedef struct GizmoGroup { bool all_hidden; int twtype; + int axis_type_default; /* Users may change the twtype, detect changes to re-setup gizmo options. */ int twtype_init; @@ -193,7 +196,7 @@ static wmGizmo *gizmo_get_axis_from_index(const GizmoGroup *man, const short axi return man->gizmos[axis_idx]; } -static short gizmo_get_axis_type(const int axis_idx) +static short gizmo_get_axis_type(const int axis_idx, const int axis_type_default) { if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { return MAN_AXES_TRANSLATE; @@ -204,6 +207,9 @@ static short gizmo_get_axis_type(const int axis_idx) if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) { return MAN_AXES_SCALE; } + if (axis_idx == MAN_AXIS_APRON_C) { + return axis_type_default; + } BLI_assert(0); return -1; } @@ -326,6 +332,8 @@ static bool gizmo_is_axis_visible( rv3d->twdrawflag & MAN_SCALE_X && (twtype & SCE_MANIP_TRANSLATE) == 0 && (twtype & SCE_MANIP_ROTATE) == 0); + case MAN_AXIS_APRON_C: + return true; } return false; } @@ -604,6 +612,7 @@ int ED_transform_calc_gizmo_stats( ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *obedit = CTX_data_edit_object(C); View3D *v3d = sa->spacedata.first; @@ -611,7 +620,7 @@ int ED_transform_calc_gizmo_stats( Base *base; Object *ob = OBACT(view_layer); bGPdata *gpd = CTX_data_gpencil_data(C); - const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); + const bool is_gp_edit = GPENCIL_ANY_MODE(gpd); int a, totsel = 0; const int pivot_point = scene->toolsettings->transform_pivot_point; @@ -728,10 +737,8 @@ int ED_transform_calc_gizmo_stats( /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { - /* calculate difference matrix if parent object */ - if (gpl->parent != NULL) { - ED_gpencil_parent_location(gpl, diff_mat); - } + /* calculate difference matrix */ + ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat); for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) { /* skip strokes that are invalid for current view */ @@ -1137,13 +1144,13 @@ static void gizmo_line_range(const int twtype, const short axis_type, float *r_s } static void gizmo_xform_message_subscribe( - wmGizmoGroup *mgroup, struct wmMsgBus *mbus, + wmGizmoGroup *gzgroup, struct wmMsgBus *mbus, Scene *scene, bScreen *UNUSED(screen), ScrArea *UNUSED(sa), ARegion *ar, const void *type_fn) { /* Subscribe to view properties */ - wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = { + wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = { .owner = ar, - .user_data = mgroup->parent_mmap, + .user_data = gzgroup->parent_gzmap, .notify = WM_gizmo_do_msg_notify_tag_refresh, }; @@ -1159,7 +1166,7 @@ static void gizmo_xform_message_subscribe( }; for (int i = 0; i < ARRAY_SIZE(props); i++) { if (props[i]) { - WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__); + WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__); } } } @@ -1167,25 +1174,27 @@ static void gizmo_xform_message_subscribe( PointerRNA toolsettings_ptr; RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr); - if (type_fn == TRANSFORM_WGT_gizmo) { + if (type_fn == TRANSFORM_GGT_gizmo) { extern PropertyRNA rna_ToolSettings_transform_pivot_point; extern PropertyRNA rna_ToolSettings_use_gizmo_mode; + extern PropertyRNA rna_ToolSettings_use_gizmo_apron; const PropertyRNA *props[] = { &rna_ToolSettings_transform_pivot_point, &rna_ToolSettings_use_gizmo_mode, + &rna_ToolSettings_use_gizmo_apron, }; for (int i = 0; i < ARRAY_SIZE(props); i++) { - WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__); + WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__); } } - else if (type_fn == VIEW3D_WGT_xform_cage) { + else if (type_fn == VIEW3D_GGT_xform_cage) { /* pass */ } else { BLI_assert(0); } - WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_mpr_tag_refresh); + WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh); } /** \} */ @@ -1195,26 +1204,32 @@ static void gizmo_xform_message_subscribe( /** \name Transform Gizmo * \{ */ -static GizmoGroup *gizmogroup_init(wmGizmoGroup *mgroup) +static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup) { GizmoGroup *man; man = MEM_callocN(sizeof(GizmoGroup), "gizmo_data"); - const wmGizmoType *wt_arrow = WM_gizmotype_find("GIZMO_WT_arrow_3d", true); - const wmGizmoType *wt_dial = WM_gizmotype_find("GIZMO_WT_dial_3d", true); - const wmGizmoType *wt_prim = WM_gizmotype_find("GIZMO_WT_primitive_3d", true); + const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true); + const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true); + const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true); + + /* Fallback action. */ + { + const wmGizmoType *gzt_mask = WM_gizmotype_find("GIZMO_GT_blank_3d", true); + man->gizmos[MAN_AXIS_APRON_C] = WM_gizmo_new_ptr(gzt_mask, gzgroup, NULL); + } #define GIZMO_NEW_ARROW(v, draw_style) { \ - man->gizmos[v] = WM_gizmo_new_ptr(wt_arrow, mgroup, NULL); \ + man->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \ RNA_enum_set(man->gizmos[v]->ptr, "draw_style", draw_style); \ } ((void)0) #define GIZMO_NEW_DIAL(v, draw_options) { \ - man->gizmos[v] = WM_gizmo_new_ptr(wt_dial, mgroup, NULL); \ + man->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \ RNA_enum_set(man->gizmos[v]->ptr, "draw_options", draw_options); \ } ((void)0) #define GIZMO_NEW_PRIM(v, draw_style) { \ - man->gizmos[v] = WM_gizmo_new_ptr(wt_prim, mgroup, NULL); \ + man->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \ RNA_enum_set(man->gizmos[v]->ptr, "draw_style", draw_style); \ } ((void)0) @@ -1286,15 +1301,29 @@ static int gizmo_modal( return OPERATOR_RUNNING_MODAL; } -static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *mgroup) +static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup) { struct { wmOperatorType *translate, *rotate, *trackball, *resize; } ot_store = {NULL}; - GizmoGroup *man = mgroup->customdata; + GizmoGroup *man = gzgroup->customdata; + + if (man->twtype & SCE_MANIP_TRANSLATE) { + man->axis_type_default = MAN_AXES_TRANSLATE; + } + else if (man->twtype & SCE_MANIP_ROTATE) { + man->axis_type_default = MAN_AXES_ROTATE; + } + else if (man->twtype & SCE_MANIP_SCALE) { + man->axis_type_default = MAN_AXES_SCALE; + } + else { + man->axis_type_default = 0; + } + MAN_ITER_AXES_BEGIN(axis, axis_idx) { - const short axis_type = gizmo_get_axis_type(axis_idx); + const short axis_type = gizmo_get_axis_type(axis_idx, man->axis_type_default); bool constraint_axis[3] = {1, 0, 0}; PointerRNA *ptr; @@ -1357,6 +1386,9 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *mgroup) WM_gizmo_set_scale(axis, 0.2f); } break; + case MAN_AXIS_APRON_C: + WM_gizmo_set_scale(axis, 1.2f); + break; } switch (axis_type) { @@ -1406,11 +1438,11 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *mgroup) MAN_ITER_AXES_END; } -static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *mgroup) +static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup) { - GizmoGroup *man = gizmogroup_init(mgroup); + GizmoGroup *man = gizmogroup_init(gzgroup); - mgroup->customdata = man; + gzgroup->customdata = man; { man->twtype = 0; @@ -1436,12 +1468,12 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *mgroup) } /* *** set properties for axes *** */ - gizmogroup_init_properties_from_twtype(mgroup); + gizmogroup_init_properties_from_twtype(gzgroup); } -static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup) +static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - GizmoGroup *man = mgroup->customdata; + GizmoGroup *man = gzgroup->customdata; ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = sa->spacedata.first; @@ -1453,7 +1485,7 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup) man->twtype = scene->toolsettings->gizmo_flag & man->twtype_init; if (man->twtype != man->twtype_prev) { man->twtype_prev = man->twtype; - gizmogroup_init_properties_from_twtype(mgroup); + gizmogroup_init_properties_from_twtype(gzgroup); } } @@ -1473,7 +1505,7 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup) MAN_ITER_AXES_BEGIN(axis, axis_idx) { - const short axis_type = gizmo_get_axis_type(axis_idx); + const short axis_type = gizmo_get_axis_type(axis_idx, man->axis_type_default); const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL); WM_gizmo_set_matrix_location(axis, rv3d->twmat[3]); @@ -1527,18 +1559,19 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *mgroup) } static void WIDGETGROUP_gizmo_message_subscribe( - const bContext *C, wmGizmoGroup *mgroup, struct wmMsgBus *mbus) + const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus) { Scene *scene = CTX_data_scene(C); bScreen *screen = CTX_wm_screen(C); ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - gizmo_xform_message_subscribe(mgroup, mbus, scene, screen, sa, ar, TRANSFORM_WGT_gizmo); + gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, TRANSFORM_GGT_gizmo); } -static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgroup) +static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { - GizmoGroup *man = mgroup->customdata; + const Scene *scene = CTX_data_scene(C); + GizmoGroup *man = gzgroup->customdata; // ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); // View3D *v3d = sa->spacedata.first; @@ -1561,9 +1594,13 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgro MAN_ITER_AXES_BEGIN(axis, axis_idx) { - const short axis_type = gizmo_get_axis_type(axis_idx); + const short axis_type = gizmo_get_axis_type(axis_idx, man->axis_type_default); /* XXX maybe unset _HIDDEN flag on redraw? */ - if (gizmo_is_axis_visible(rv3d, man->twtype, idot, axis_type, axis_idx)) { + + if (axis_idx == MAN_AXIS_APRON_C) { + WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, (scene->toolsettings->gizmo_flag & SCE_MANIP_DISABLE_APRON) != 0); + } + else if (gizmo_is_axis_visible(rv3d, man->twtype, idot, axis_type, axis_idx)) { WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false); } else { @@ -1581,6 +1618,7 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgro case MAN_AXIS_ROT_C: case MAN_AXIS_SCALE_C: case MAN_AXIS_ROT_T: + case MAN_AXIS_APRON_C: WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]); break; } @@ -1588,39 +1626,39 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *mgro MAN_ITER_AXES_END; } -static bool WIDGETGROUP_gizmo_poll(const struct bContext *C, struct wmGizmoGroupType *wgt) +static bool WIDGETGROUP_gizmo_poll(const struct bContext *C, struct wmGizmoGroupType *gzgt) { /* it's a given we only use this in 3D view */ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); if ((tref_rt == NULL) || - !STREQ(wgt->idname, tref_rt->gizmo_group)) + !STREQ(gzgt->idname, tref_rt->gizmo_group)) { - WM_gizmo_group_type_unlink_delayed_ptr(wgt); + WM_gizmo_group_type_unlink_delayed_ptr(gzgt); return false; } View3D *v3d = CTX_wm_view3d(C); - if (v3d->mpr_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) { + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) { return false; } return true; } -void TRANSFORM_WGT_gizmo(wmGizmoGroupType *wgt) +void TRANSFORM_GGT_gizmo(wmGizmoGroupType *gzgt) { - wgt->name = "Transform Gizmo"; - wgt->idname = "TRANSFORM_WGT_gizmo"; + gzgt->name = "Transform Gizmo"; + gzgt->idname = "TRANSFORM_GGT_gizmo"; - wgt->flag |= WM_GIZMOGROUPTYPE_3D; + gzgt->flag |= WM_GIZMOGROUPTYPE_3D; - wgt->mmap_params.spaceid = SPACE_VIEW3D; - wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + gzgt->gzmap_params.spaceid = SPACE_VIEW3D; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; - wgt->poll = WIDGETGROUP_gizmo_poll; - wgt->setup = WIDGETGROUP_gizmo_setup; - wgt->refresh = WIDGETGROUP_gizmo_refresh; - wgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe; - wgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare; + gzgt->poll = WIDGETGROUP_gizmo_poll; + gzgt->setup = WIDGETGROUP_gizmo_setup; + gzgt->refresh = WIDGETGROUP_gizmo_refresh; + gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe; + gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare; } /** \} */ @@ -1634,31 +1672,31 @@ struct XFormCageWidgetGroup { wmGizmo *gizmo; }; -static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *wgt) +static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt) { bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); - if (!STREQ(wgt->idname, tref_rt->gizmo_group)) { - WM_gizmo_group_type_unlink_delayed_ptr(wgt); + if (!STREQ(gzgt->idname, tref_rt->gizmo_group)) { + WM_gizmo_group_type_unlink_delayed_ptr(gzgt); return false; } return true; } -static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *mgroup) +static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - struct XFormCageWidgetGroup *xmgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__); - const wmGizmoType *wt_cage = WM_gizmotype_find("GIZMO_WT_cage_3d", true); - xmgroup->gizmo = WM_gizmo_new_ptr(wt_cage, mgroup, NULL); - wmGizmo *mpr = xmgroup->gizmo; + struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__); + const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true); + xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL); + wmGizmo *gz = xgzgroup->gizmo; - RNA_enum_set(mpr->ptr, "transform", + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE); - mpr->color[0] = 1; - mpr->color_hi[0] = 1; + gz->color[0] = 1; + gz->color_hi[0] = 1; - mgroup->customdata = xmgroup; + gzgroup->customdata = xgzgroup; { wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true); @@ -1673,7 +1711,7 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { bool constraint[3] = {x != 1, y != 1, z != 1}; - ptr = WM_gizmo_operator_set(mpr, i, ot_resize, NULL); + ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL); if (prop_release_confirm == NULL) { prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm"); prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis"); @@ -1687,15 +1725,15 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup } } -static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgroup) +static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; - struct XFormCageWidgetGroup *xmgroup = mgroup->customdata; - wmGizmo *mpr = xmgroup->gizmo; + struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata; + wmGizmo *gz = xgzgroup->gizmo; struct TransformBounds tbounds; @@ -1705,22 +1743,22 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgro }, &tbounds) == 0) || equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) { - WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, true); + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); } else { gizmo_prepare_mat(C, v3d, rv3d, &tbounds); - WM_gizmo_set_flag(mpr, WM_GIZMO_HIDDEN, false); - WM_gizmo_set_flag(mpr, WM_GIZMO_GRAB_CURSOR, true); + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + WM_gizmo_set_flag(gz, WM_GIZMO_GRAB_CURSOR, true); float dims[3]; sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min); - RNA_float_set_array(mpr->ptr, "dimensions", dims); + RNA_float_set_array(gz->ptr, "dimensions", dims); mul_v3_fl(dims, 0.5f); - copy_m4_m3(mpr->matrix_offset, rv3d->tw_axis_matrix); - mid_v3_v3v3(mpr->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min); - mul_m3_v3(rv3d->tw_axis_matrix, mpr->matrix_offset[3]); + copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix); + mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min); + mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]); PropertyRNA *prop_center_override = NULL; float center[3]; @@ -1732,11 +1770,11 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgro center[1] = (float)(1 - y) * dims[1]; for (int z = 0; z < 3; z++) { center[2] = (float)(1 - z) * dims[2]; - struct wmGizmoOpElem *mpop = WM_gizmo_operator_get(mpr, i); + struct wmGizmoOpElem *mpop = WM_gizmo_operator_get(gz, i); if (prop_center_override == NULL) { prop_center_override = RNA_struct_find_property(&mpop->ptr, "center_override"); } - mul_v3_m4v3(center_global, mpr->matrix_offset, center); + mul_v3_m4v3(center_global, gz->matrix_offset, center); RNA_property_float_set_array(&mpop->ptr, prop_center_override, center_global); i++; } @@ -1746,45 +1784,45 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *mgro } static void WIDGETGROUP_xform_cage_message_subscribe( - const bContext *C, wmGizmoGroup *mgroup, struct wmMsgBus *mbus) + const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus) { Scene *scene = CTX_data_scene(C); bScreen *screen = CTX_wm_screen(C); ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - gizmo_xform_message_subscribe(mgroup, mbus, scene, screen, sa, ar, VIEW3D_WGT_xform_cage); + gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_cage); } -static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *mgroup) +static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { - struct XFormCageWidgetGroup *xmgroup = mgroup->customdata; - wmGizmo *mpr = xmgroup->gizmo; + struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata; + wmGizmo *gz = xgzgroup->gizmo; ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); if (ob && ob->mode & OB_MODE_EDIT) { - copy_m4_m4(mpr->matrix_space, ob->obmat); + copy_m4_m4(gz->matrix_space, ob->obmat); } else { - unit_m4(mpr->matrix_space); + unit_m4(gz->matrix_space); } } -void VIEW3D_WGT_xform_cage(wmGizmoGroupType *wgt) +void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt) { - wgt->name = "Transform Cage"; - wgt->idname = "VIEW3D_WGT_xform_cage"; + gzgt->name = "Transform Cage"; + gzgt->idname = "VIEW3D_GGT_xform_cage"; - wgt->flag |= WM_GIZMOGROUPTYPE_3D; + gzgt->flag |= WM_GIZMOGROUPTYPE_3D; - wgt->mmap_params.spaceid = SPACE_VIEW3D; - wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + gzgt->gzmap_params.spaceid = SPACE_VIEW3D; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; - wgt->poll = WIDGETGROUP_xform_cage_poll; - wgt->setup = WIDGETGROUP_xform_cage_setup; - wgt->refresh = WIDGETGROUP_xform_cage_refresh; - wgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe; - wgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare; + gzgt->poll = WIDGETGROUP_xform_cage_poll; + gzgt->setup = WIDGETGROUP_xform_cage_setup; + gzgt->refresh = WIDGETGROUP_xform_cage_refresh; + gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe; + gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare; } /** \} */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index c9a97c8530c..1f1cc646f20 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -82,6 +82,7 @@ static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide"; static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease"; static const char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight"; static const char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide"; +static const char OP_NORMAL_ROTATION[] = "TRANSFORM_OT_rotate_normal"; static void TRANSFORM_OT_translate(struct wmOperatorType *ot); static void TRANSFORM_OT_rotate(struct wmOperatorType *ot); @@ -100,6 +101,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot); static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot); +static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot); static TransformModeItem transform_modes[] = { @@ -120,6 +122,7 @@ static TransformModeItem transform_modes[] = {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease}, {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight}, {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide}, + {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal}, {NULL, 0} }; @@ -507,6 +510,36 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) } } +static bool transform_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + + /* Orientation/Constraints. */ + { + /* Hide orientation axis if no constraints are set, since it wont be used. */ + PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "constraint_axis"); + if (prop_con && !RNA_property_is_set(op->ptr, prop_con)) { + if (STRPREFIX(prop_id, "constraint")) { + return false; + } + } + } + + /* Proportional Editing. */ + { + PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional"); + if (prop_pet && (prop_pet != prop) && + (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF)) + { + if (STRPREFIX(prop_id, "proportional")) { + return false; + } + } + } + + return true; +} + void Transform_Properties(struct wmOperatorType *ot, int flags) { PropertyRNA *prop; @@ -615,6 +648,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); @@ -640,6 +674,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); @@ -673,6 +708,7 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = skin_resize_poll; + ot->poll_property = transform_poll_property; RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); @@ -695,6 +731,7 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; /* Maybe we could use float_vector_xyz here too? */ RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); @@ -718,6 +755,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -744,6 +782,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editcurve_3d; + ot->poll_property = transform_poll_property; RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -766,6 +805,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_region_view3d_active; + ot->poll_property = transform_poll_property; RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -788,6 +828,7 @@ static void TRANSFORM_OT_shear(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX); @@ -811,6 +852,7 @@ static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX); @@ -833,6 +875,7 @@ static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh; + ot->poll_property = transform_poll_property; RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX); @@ -858,6 +901,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1); @@ -880,6 +924,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER); } @@ -900,6 +945,7 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh_region_view3d; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); @@ -932,6 +978,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh_region_view3d; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); RNA_def_boolean(ot->srna, "use_even", false, "Even", @@ -961,6 +1008,7 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh; + ot->poll_property = transform_poll_property; RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); @@ -1034,6 +1082,27 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot) Transform_Properties(ot, P_SNAP); } +static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Normal Rotate"; + ot->description = "Rotate split normal of selected items"; + ot->idname = OP_NORMAL_ROTATION; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh_auto_smooth; + + RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); + + Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_MIRROR); +} + + static void TRANSFORM_OT_transform(struct wmOperatorType *ot) { PropertyRNA *prop; @@ -1050,6 +1119,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; + ot->poll_property = transform_poll_property; prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); RNA_def_property_flag(prop, PROP_HIDDEN); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index dc922b5c9ba..54253e36351 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -165,7 +165,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) invert_m4_m4(imat, rv3d->viewmat); - uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); @@ -190,7 +190,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) if (usingSnappingNormal(t) && validSnappingNormal(t)) { immUniformColor4ubv(activeCol); - immBegin(GWN_PRIM_LINES, 2); + immBegin(GPU_PRIM_LINES, 2); immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1], @@ -219,7 +219,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) GPU_blend(true); - uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -1462,7 +1462,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2]) float xmouse, ymouse; int frame; int mframe; - TransSeq *ts = t->custom.type.data; + TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; /* reuse increment, strictly speaking could be another snap mode, but leave as is */ if (!(t->modifiers & MOD_SNAP_INVERT)) return; diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index e19320fa220..6dfcfe11af2 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -111,6 +111,10 @@ typedef struct SnapObjectData_EditMesh { SnapObjectData sd; BVHTreeFromEditMesh *bvh_trees[3]; + /* It's like a boundbox. It is tested first to avoid + * to create a bvhtree for all the edited objects. */ + float min[3], max[3]; + } SnapObjectData_EditMesh; struct SnapObjectContext { @@ -156,6 +160,39 @@ struct SnapObjectContext { typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data); +static void min_max_from_bmesh( + BMesh *bm, float r_min[3], float r_max[3]) +{ + BMIter iter; + BMVert *eve; + + INIT_MINMAX(r_min, r_max); + BM_ITER_MESH(eve, &iter, bm, BM_VERTS_OF_MESH) { + minmax_v3v3_v3(r_min, r_max, eve->co); + } +} + +static SnapObjectData_Mesh *snap_object_data_mesh_create(SnapObjectContext *sctx) +{ + SnapObjectData_Mesh *sod = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_MESH; + /* start assuming that it has each of these element types */ + sod->has_looptris = true; + sod->has_loose_edge = true; + sod->has_loose_vert = true; + + return sod; +} + +static SnapObjectData_EditMesh *snap_object_data_editmesh_create(SnapObjectContext *sctx, BMesh *bm) +{ + SnapObjectData_EditMesh *sod = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_EDIT_MESH; + min_max_from_bmesh(bm, sod->min, sod->max); + + return sod; +} + /** * Walks through all objects in the scene to create the list of objets to snap. * @@ -169,9 +206,9 @@ static void iter_snap_objects( IterSnapObjsCallback sob_callback, void *data) { - ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph); - Object *obedit = params->use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL; + ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph); const eSnapSelect snap_select = params->snap_select; + const bool use_object_edit_cage = params->use_object_edit_cage; Base *base_act = view_layer->basact; for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { @@ -179,20 +216,17 @@ static void iter_snap_objects( !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || (snap_select == SNAP_NOT_ACTIVE && base == base_act))) { - bool use_obedit; - Object *obj = base->object; - if (obj->transflag & OB_DUPLI) { + Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object); + if (obj_eval->transflag & OB_DUPLI) { DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj); + ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - use_obedit = obedit && dupli_ob->ob->data == obedit->data; - sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data); + sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); } free_object_duplilist(lb); } - use_obedit = obedit && obj->data == obedit->data; - sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); + sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data); } } } @@ -372,13 +406,12 @@ static bool raycastMesh( sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; + sod = *sod_p = snap_object_data_mesh_create(sctx); } BVHTreeFromMesh *treedata = &sod->treedata; - /* The tree is owned by the DM and may have been freed since we last used. */ + /* The tree is owned by the Mesh and may have been freed since we last used. */ if (treedata->tree) { BLI_assert(treedata->cached); if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) { @@ -502,14 +535,30 @@ static bool raycastEditMesh( SnapObjectData_EditMesh *sod = NULL; BVHTreeFromEditMesh *treedata = NULL; + Object *em_ob = em->ob; + + BLI_assert(em_ob->data == BKE_object_get_pre_modified_mesh(ob)); void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &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. */ + if (BLI_ghash_ensure_p(sctx->cache.object_map, em_ob, &sod_p)) { sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; + sod = *sod_p = snap_object_data_editmesh_create(sctx, em->bm); + } + + { + float min[3], max[3]; + mul_v3_m4v3(min, obmat, sod->min); + mul_v3_m4v3(max, obmat, sod->max); + + if (!isect_ray_aabb_v3_simple( + ray_start, ray_dir, min, max, NULL, NULL)) + { + return retval; + } } if (sod->bvh_trees[2] == NULL) { @@ -517,7 +566,17 @@ static bool raycastEditMesh( } treedata = sod->bvh_trees[2]; + BVHCache *em_bvh_cache = ((Mesh *)em_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! */ + if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) { + free_bvhtree_from_editmesh(treedata); + } + } + if (treedata->tree == NULL) { + BVHCache **bvh_cache = NULL; BLI_bitmap *elem_mask = NULL; int looptri_num_active = -1; @@ -527,7 +586,15 @@ static bool raycastEditMesh( em->bm, elem_mask, sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); } - bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); + else { + /* Only cache if bvhtree is created without a mask. + * This helps keep a standardized bvhtree in cache. */ + bvh_cache = &em_bvh_cache; + } + + bvhtree_from_editmesh_looptri_ex( + treedata, em, elem_mask, looptri_num_active, + 0.0f, 4, 6, bvh_cache); if (elem_mask) { MEM_freeN(elem_mask); @@ -669,7 +736,7 @@ static bool raycastObj( switch (ob->type) { case OB_MESH: - if (use_obedit) { + if (use_obedit && BKE_object_is_in_editmode(ob)) { BMEditMesh *em = BKE_editmesh_from_object(ob); retval = raycastEditMesh( sctx, @@ -718,7 +785,7 @@ struct RaycastObjUserData { bool ret; }; -static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) +static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data) { struct RaycastObjUserData *dt = data; @@ -726,7 +793,7 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, sctx, dt->ray_start, dt->ray_dir, ob, obmat, dt->ob_index++, - is_obedit, dt->use_occlusion_test, + use_obedit, dt->use_occlusion_test, dt->ray_depth, dt->r_loc, dt->r_no, dt->r_index, dt->r_ob, dt->r_obmat, @@ -1118,6 +1185,13 @@ static short snap_mesh_polygon( }; 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); + } + BLI_assert(sod != NULL); if (sod->type == SNAP_MESH) { @@ -1335,6 +1409,8 @@ static short snapArmature( dist_squared_to_projected_aabb_precalc( &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); + use_obedit = use_obedit && BKE_object_is_in_editmode(ob); + if (use_obedit == false) { /* Test BoundBox */ BoundBox *bb = BKE_armature_boundbox_get(ob); @@ -1469,6 +1545,8 @@ static short snapCurve( dist_squared_to_projected_aabb_precalc( &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); + use_obedit = use_obedit && BKE_object_is_in_editmode(ob); + if (use_obedit == false) { /* Test BoundBox */ BoundBox *bb = BKE_curve_boundbox_get(ob); @@ -1779,12 +1857,7 @@ static short snapMesh( sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; - /* start assuming that it has each of these element types */ - sod->has_looptris = true; - sod->has_loose_edge = true; - sod->has_loose_vert = true; + sod = *sod_p = snap_object_data_mesh_create(sctx); } BVHTreeFromMesh *treedata, dummy_treedata; @@ -1792,7 +1865,7 @@ static short snapMesh( treedata = &sod->treedata; bvhtree = sod->bvhtree; - /* the tree is owned by the DM and may have been freed since we last used! */ + /* The tree is owned by the Mesh and may have been freed since we last used! */ if ((sod->has_looptris && treedata->tree && !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) || (sod->has_loose_edge && bvhtree[0] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) || (sod->has_loose_vert && bvhtree[1] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) @@ -1982,21 +2055,57 @@ static short snapEditMesh( SnapObjectData_EditMesh *sod = NULL; BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL; + Object *em_ob = em->ob; + + BLI_assert(em_ob->data == BKE_object_get_pre_modified_mesh(ob)); + UNUSED_VARS_NDEBUG(ob); void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &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. */ + if (BLI_ghash_ensure_p(sctx->cache.object_map, em_ob, &sod_p)) { sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; + sod = *sod_p = snap_object_data_editmesh_create(sctx, em->bm); } + float dist_px_sq = SQUARE(*dist_px); + + { + float min[3], max[3]; + mul_v3_m4v3(min, obmat, sod->min); + mul_v3_m4v3(max, obmat, sod->max); + + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ + struct DistProjectedAABBPrecalc data_precalc; + dist_squared_to_projected_aabb_precalc( + &data_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval); + + bool dummy[3]; + float bb_dist_px_sq = dist_squared_to_projected_aabb( + &data_precalc, min, max, dummy); + + if (bb_dist_px_sq > dist_px_sq) { + return 0; + } + } + + BVHCache *em_bvh_cache = ((Mesh *)em_ob->data)->runtime.bvh_cache; + if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { if (sod->bvh_trees[0] == NULL) { sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); } treedata_vert = sod->bvh_trees[0]; + + if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) { + /* The tree is owned by the Mesh and may have been freed since we last used! */ + if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) { + free_bvhtree_from_editmesh(treedata_vert); + } + } + if (treedata_vert->tree == NULL) { BLI_bitmap *verts_mask = NULL; int verts_num_active = -1; @@ -2006,9 +2115,13 @@ static short snapEditMesh( BM_VERTS_OF_MESH, em->bm, verts_mask, (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, sctx->callbacks.edit_mesh.user_data); + + bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); + MEM_freeN(verts_mask); + } + else { + bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache); } - bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); - MEM_SAFE_FREE(verts_mask); } } @@ -2017,6 +2130,14 @@ static short snapEditMesh( sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); } treedata_edge = sod->bvh_trees[1]; + + if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) { + /* The tree is owned by the Mesh and may have been freed since we last used! */ + if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) { + free_bvhtree_from_editmesh(treedata_edge); + } + } + if (treedata_edge->tree == NULL) { BLI_bitmap *edges_mask = NULL; int edges_num_active = -1; @@ -2027,9 +2148,12 @@ static short snapEditMesh( (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, sctx->callbacks.edit_mesh.user_data); + bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); + MEM_freeN(edges_mask); + } + else { + bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache); } - bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); - MEM_SAFE_FREE(edges_mask); } } @@ -2043,7 +2167,7 @@ static short snapEditMesh( BVHTreeNearest nearest = { .index = -1, - .dist_sq = SQUARE(*dist_px), + .dist_sq = dist_px_sq, }; int last_index = nearest.index; short elem = SCE_SNAP_MODE_VERTEX; @@ -2119,7 +2243,7 @@ static short snapObject( switch (ob->type) { case OB_MESH: - if (use_obedit) { + if (use_obedit && BKE_object_is_in_editmode(ob)) { BMEditMesh *em = BKE_editmesh_from_object(ob); retval = snapEditMesh( sctx, snapdata, ob, em, obmat, @@ -2156,7 +2280,12 @@ static short snapObject( dist_px, r_loc, r_no, r_index); break; - + case OB_GPENCIL: + retval = snapEmpty( + snapdata, ob, obmat, + dist_px, + r_loc, r_no, r_index); + break; case OB_CAMERA: retval = snapCamera( sctx, snapdata, ob, obmat, |