Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / gizmo_library / gizmo_types / dial3d_gizmo.c
index 7ceb46f20de633aeda2e403538e07dc17638efa3..a6252cd55bdd07ac1743fe5be2949efd37934ddb 100644 (file)
@@ -67,7 +67,7 @@
 #include "../gizmo_geometry.h"
 #include "../gizmo_library_intern.h"
 
-/* to use custom dials exported to geom_dial_gizmo.c */
+/* To use custom dials exported to geom_dial_gizmo.c */
 // #define USE_GIZMO_CUSTOM_DIAL
 
 static int gizmo_dial_modal(
@@ -77,7 +77,7 @@ static int gizmo_dial_modal(
 typedef struct DialInteraction {
        struct {
                float mval[2];
-               /* only for when using properties */
+               /* Only for when using properties. */
                float prop_angle;
        } init;
        struct {
@@ -86,10 +86,10 @@ typedef struct DialInteraction {
                float angle;
        } prev;
 
-       /* number of full rotations */
+       /* Number of full rotations. */
        int rotations;
 
-       /* final output values, used for drawing */
+       /* Final output values, used for drawing. */
        struct {
                float angle_ofs;
                float angle_delta;
@@ -102,28 +102,15 @@ typedef struct DialInteraction {
 /* Could make option, negative to clip more (don't show when view aligned). */
 #define DIAL_CLIP_BIAS 0.02
 
-/**
- * We can't use this for the #wmGizmoType.matrix_basis_get callback, it conflicts with depth picking.
- */
-static void dial_calc_matrix(const wmGizmo *gz, float mat[4][4])
-{
-       float rot[3][3];
-       const float up[3] = {0.0f, 0.0f, 1.0f};
-
-       rotation_between_vecs_to_mat3(rot, up, gz->matrix_basis[2]);
-       copy_m4_m3(mat, rot);
-       copy_v3_v3(mat[3], gz->matrix_basis[3]);
-}
-
 /* -------------------------------------------------------------------- */
 
 static void dial_geom_draw(
         const wmGizmo *gz, const float color[4], const bool select,
-        float axis_modal_mat[4][4], float clip_plane[4])
+        float axis_modal_mat[4][4], float clip_plane[4], const float arc_inner_factor)
 {
 #ifdef USE_GIZMO_CUSTOM_DIAL
-       UNUSED_VARS(dial, col, axis_modal_mat, clip_plane);
-       wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select);
+       UNUSED_VARS(gz, axis_modal_mat, clip_plane);
+       wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select, color);
 #else
        const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
        const bool filled = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_FILL) != 0;
@@ -150,6 +137,9 @@ static void dial_geom_draw(
        }
        else {
                imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+               if (arc_inner_factor != 0.0f) {
+                       imm_draw_circle_wire_2d(pos, 0, 0, arc_inner_factor, DIAL_RESOLUTION);
+               }
        }
 
        immUnbindProgram();
@@ -161,10 +151,9 @@ static void dial_geom_draw(
 /**
  * Draws a line from (0, 0, 0) to \a co_outer, at \a angle.
  */
-static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[3], const float color[4])
+static void dial_ghostarc_draw_helpline(
+        const float angle, const float co_outer[3], const float color[4])
 {
-       GPU_line_width(1.0f);
-
        GPU_matrix_push();
        GPU_matrix_rotate_3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
 
@@ -175,7 +164,7 @@ static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[
        immUniformColor4fv(color);
 
        immBegin(GPU_PRIM_LINE_STRIP, 2);
-       immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+       immVertex3f(pos, 0.0f, 0, 0.0f);
        immVertex3fv(pos, co_outer);
        immEnd();
 
@@ -185,24 +174,32 @@ static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[
 }
 
 static void dial_ghostarc_draw(
-        const wmGizmo *gz, const float angle_ofs, const float angle_delta, const float color[4])
+        const float angle_ofs, const float angle_delta,
+        const float arc_inner_factor, const float color[4])
 {
-       const float width_inner = DIAL_WIDTH - gz->line_width * 0.5f / U.gizmo_size;
-
+       const float width_inner = DIAL_WIDTH;
        GPUVertFormat *format = immVertexFormat();
        uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
        immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+       if (arc_inner_factor != 0.0) {
+               float color_dark[4] = {0};
+               color_dark[3] = color[3] / 2;
+               immUniformColor4fv(color_dark);
+               imm_draw_disk_partial_fill_2d(
+                       pos, 0, 0, arc_inner_factor, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(M_PI * 2));
+       }
+
        immUniformColor4fv(color);
        imm_draw_disk_partial_fill_2d(
-               pos, 0, 0, 0.0, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta));
+               pos, 0, 0, arc_inner_factor, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta));
        immUnbindProgram();
 }
 
 static void dial_ghostarc_get_angles(
-        struct Depsgraph *depsgraph,
         const wmGizmo *gz,
         const wmEvent *event,
-        const ARegion *ar, const View3D *v3d,
+        const ARegion *ar,
         float mat[4][4], const float co_outer[3],
         float *r_start, float *r_delta)
 {
@@ -210,7 +207,7 @@ static void dial_ghostarc_get_angles(
        const RegionView3D *rv3d = ar->regiondata;
        const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
 
-       /* we might need to invert the direction of the angles */
+       /* We might need to invert the direction of the angles. */
        float view_vec[3], axis_vec[3];
        ED_view3d_global_to_vector(rv3d, gz->matrix_basis[3], view_vec);
        normalize_v3_v3(axis_vec, gz->matrix_basis[2]);
@@ -222,48 +219,42 @@ static void dial_ghostarc_get_angles(
        float proj_mval_new_rel[3];
        float proj_mval_init_rel[3];
        float dial_plane[4];
-       float ray_co[3], ray_no[3];
-       float ray_lambda;
 
        plane_from_point_normal_v3(dial_plane, gz->matrix_basis[3], axis_vec);
 
-       if (!ED_view3d_win_to_ray(depsgraph, ar, v3d, inter->init.mval, ray_co, ray_no, false) ||
-           !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false))
-       {
+       if (!ED_view3d_win_to_3d_on_plane(ar, dial_plane, inter->init.mval, false, proj_mval_init_rel)) {
                goto fail;
        }
-       madd_v3_v3v3fl(proj_mval_init_rel, ray_co, ray_no, ray_lambda);
        sub_v3_v3(proj_mval_init_rel, gz->matrix_basis[3]);
 
-       if (!ED_view3d_win_to_ray(depsgraph, ar, v3d, mval, ray_co, ray_no, false) ||
-           !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false))
-       {
+       if (!ED_view3d_win_to_3d_on_plane(ar, dial_plane, mval, false, proj_mval_new_rel)) {
                goto fail;
        }
-       madd_v3_v3v3fl(proj_mval_new_rel, ray_co, ray_no, ray_lambda);
        sub_v3_v3(proj_mval_new_rel, gz->matrix_basis[3]);
 
        const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
 
-       /* Start direction from mouse or set by user */
+       /* Start direction from mouse or set by user. */
        const float *proj_init_rel =
                (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y) ?
                gz->matrix_basis[1] : proj_mval_init_rel;
 
-       /* return angles */
+       /* Return angles. */
        const float start = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_init_rel, axis_vec));
        const float delta = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_mval_init_rel, proj_mval_new_rel, axis_vec));
 
        /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn
         * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2.
-        * Logic taken from BLI_dial_angle */
+        * Logic taken from #BLI_dial_angle */
        if ((delta * inter->prev.angle < 0.0f) &&
            (fabsf(inter->prev.angle) > (float)M_PI_2))
        {
-               if (inter->prev.angle < 0.0f)
+               if (inter->prev.angle < 0.0f) {
                        inter->rotations--;
-               else
+               }
+               else {
                        inter->rotations++;
+               }
        }
        inter->prev.angle = delta;
 
@@ -279,11 +270,25 @@ fail:
        *r_delta = 0.0;
 }
 
+static void dial_ghostarc_draw_with_helplines(
+        const float angle_ofs, const float angle_delta,
+        const float arc_inner_factor, const float color_helpline[4], const int draw_options)
+{
+       /* Coordinate at which the arc drawing will be started. */
+       const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f};
+       dial_ghostarc_draw(angle_ofs, angle_delta, arc_inner_factor, (const float[4]){0.8f, 0.8f, 0.8f, 0.4f});
+       GPU_line_width(1.0f);
+       dial_ghostarc_draw_helpline(angle_ofs, co_outer, color_helpline);
+       if (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE) {
+               GPU_line_width(3.0f);
+       }
+       dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color_helpline);
+}
+
 static void dial_draw_intern(
         const bContext *C, wmGizmo *gz,
         const bool select, const bool highlight, float clip_plane[4])
 {
-       float matrix_basis_adjust[4][4];
        float matrix_final[4][4];
        float color[4];
 
@@ -291,55 +296,61 @@ static void dial_draw_intern(
 
        gizmo_color_get(gz, highlight, color);
 
-       dial_calc_matrix(gz, matrix_basis_adjust);
-
-       WM_gizmo_calc_matrix_final_params(
-               gz, &((struct WM_GizmoMatrixParams) {
-                   .matrix_basis = (void *)matrix_basis_adjust,
-               }), matrix_final);
+       WM_gizmo_calc_matrix_final(gz, matrix_final);
 
        GPU_matrix_push();
        GPU_matrix_mul(matrix_final);
 
-       /* draw rotation indicator arc first */
+       /* FIXME(campbell): look into removing this. */
        if ((gz->flag & WM_GIZMO_DRAW_VALUE) &&
            (gz->state & WM_GIZMO_STATE_MODAL))
        {
-               const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
-
-               DialInteraction *inter = gz->interaction_data;
-
                /* XXX, View3D rotation gizmo doesn't call modal. */
                if (!WM_gizmo_target_property_is_valid_any(gz)) {
                        wmWindow *win = CTX_wm_window(C);
                        gizmo_dial_modal((bContext *)C, gz, win->eventstate, 0);
                }
+       }
 
-               float angle_ofs = inter->output.angle_ofs;
-               float angle_delta = inter->output.angle_delta;
+       GPU_polygon_smooth(false);
 
-               /* draw! */
-               for (int i = 0; i < 2; i++) {
-                       GPU_polygon_smooth(false);
-                       dial_ghostarc_draw(gz, angle_ofs, angle_delta, (const float[4]){0.8f, 0.8f, 0.8f, 0.4f});
-                       GPU_polygon_smooth(true);
+       const float arc_inner_factor = RNA_float_get(gz->ptr, "arc_inner_factor");
+       if (select == false) {
+               float angle_ofs = 0.0f;
+               float angle_delta = 0.0f;
+               bool show_ghostarc = false;
 
-                       dial_ghostarc_draw_helpline(angle_ofs, co_outer, color); /* starting position */
-                       dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color); /* starting position + current value */
+               /* Draw rotation indicator arc first. */
+               wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
+               const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
 
-                       if (i == 0) {
-                               const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
-                               if ((draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR) == 0) {
-                                       break;
-                               }
-                       }
+               if (WM_gizmo_target_property_is_valid(gz_prop) &&
+                   (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE))
+               {
+                       angle_ofs = 0.0f;
+                       angle_delta = WM_gizmo_target_property_float_get(gz, gz_prop);
+                       show_ghostarc = true;
+               }
+               else if ((gz->flag & WM_GIZMO_DRAW_VALUE) &&
+                        (gz->state & WM_GIZMO_STATE_MODAL))
+               {
+                       DialInteraction *inter = gz->interaction_data;
+                       angle_ofs = inter->output.angle_ofs;
+                       angle_delta = inter->output.angle_delta;
+                       show_ghostarc = true;
+               }
 
-                       angle_ofs += (float)M_PI;
+               if (show_ghostarc) {
+                       dial_ghostarc_draw_with_helplines(angle_ofs, angle_delta, arc_inner_factor, color, draw_options);
+                       if ((draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR) != 0) {
+                               angle_ofs += M_PI;
+                               dial_ghostarc_draw_with_helplines(angle_ofs, angle_delta, arc_inner_factor, color, draw_options);
+                       }
                }
        }
 
-       /* draw actual dial gizmo */
-       dial_geom_draw(gz, color, select, matrix_basis_adjust, clip_plane);
+       /* Draw actual dial gizmo. */
+       dial_geom_draw(gz, color, select, gz->matrix_basis, clip_plane, arc_inner_factor);
 
        GPU_matrix_pop();
 }
@@ -350,7 +361,6 @@ static void gizmo_dial_draw_select(const bContext *C, wmGizmo *gz, int select_id
        const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
        float *clip_plane = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL;
 
-       /* enable clipping if needed */
        if (clip_plane) {
                ARegion *ar = CTX_wm_region(C);
                RegionView3D *rv3d = ar->regiondata;
@@ -377,7 +387,6 @@ static void gizmo_dial_draw(const bContext *C, wmGizmo *gz)
        const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
        float *clip_plane = (!is_modal && (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP)) ? clip_plane_buf : NULL;
 
-       /* enable clipping if needed */
        if (clip_plane) {
                ARegion *ar = CTX_wm_region(C);
                RegionView3D *rv3d = ar->regiondata;
@@ -406,17 +415,12 @@ static int gizmo_dial_modal(
        if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) {
                return OPERATOR_RUNNING_MODAL;
        }
-       const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
+       /* Coordinate at which the arc drawing will be started. */
+       const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f};
        float angle_ofs, angle_delta;
 
-       float matrix[4][4];
-
-       dial_calc_matrix(gz, matrix);
-
        dial_ghostarc_get_angles(
-               CTX_data_depsgraph(C),
-               gz, event, CTX_wm_region(C), CTX_wm_view3d(C), matrix, co_outer, &angle_ofs, &angle_delta);
-
+               gz, event, CTX_wm_region(C), gz->matrix_basis, co_outer, &angle_ofs, &angle_delta);
 
        if (tweak_flag & WM_GIZMO_TWEAK_SNAP) {
                const double snap = DEG2RAD(5);
@@ -428,7 +432,7 @@ static int gizmo_dial_modal(
        inter->output.angle_delta = angle_delta;
        inter->output.angle_ofs = angle_ofs;
 
-       /* set the property for the operator and call its modal function */
+       /* Set the property for the operator and call its modal function. */
        wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
        if (WM_gizmo_target_property_is_valid(gz_prop)) {
                WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init.prop_angle + angle_delta);
@@ -491,10 +495,12 @@ static void GIZMO_GT_dial_3d(wmGizmoType *gzt)
                {ED_GIZMO_DIAL_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
                {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR, "ANGLE_MIRROR", 0, "Angle Mirror", ""},
                {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y, "ANGLE_START_Y", 0, "Angle Start Y", ""},
+               {ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE, "ANGLE_VALUE", 0, "Show Angle Value", ""},
                {0, NULL, 0, NULL, NULL}
        };
        RNA_def_enum_flag(gzt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
        RNA_def_boolean(gzt->srna, "wrap_angle", true, "Wrap Angle", "");
+       RNA_def_float_factor(gzt->srna, "arc_inner_factor", 0.0f, 0.0f, 1.0f, "Arc Inner Factor", "", 0.0f, 1.0f);
 
        WM_gizmotype_target_property_def(gzt, "offset", PROP_FLOAT, 1);
 }