Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
| Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
| /* own includes */ | /* own includes */ | ||||
| #include "../gizmo_geometry.h" | #include "../gizmo_geometry.h" | ||||
| #include "../gizmo_library_intern.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 | // #define USE_GIZMO_CUSTOM_DIAL | ||||
| static int gizmo_dial_modal( | |||||
| bContext *C, wmGizmo *gz, const wmEvent *event, | |||||
| eWM_GizmoFlagTweak tweak_flag); | |||||
| typedef struct DialInteraction { | typedef struct DialInteraction { | ||||
| struct { | struct { | ||||
| float mval[2]; | float mval[2]; | ||||
| /* Only for when using properties. */ | /* Only for when using properties. */ | ||||
| float prop_angle; | float prop_angle; | ||||
| } init; | } init; | ||||
| struct { | struct { | ||||
| /* Cache the last angle to detect rotations bigger than -/+ PI. */ | /* Cache the last angle to detect rotations bigger than -/+ PI. */ | ||||
| eWM_GizmoFlagTweak tweak_flag; | eWM_GizmoFlagTweak tweak_flag; | ||||
| float angle; | float angle; | ||||
| } prev; | } prev; | ||||
| /* Number of full rotations. */ | /* Number of full rotations. */ | ||||
| int rotations; | int rotations; | ||||
| bool has_drag; | bool has_drag; | ||||
| /* Final output values, used for drawing. */ | /* Final output values, used for drawing. */ | ||||
| struct { | struct { | ||||
| float angle_ofs; | float angle_ofs; | ||||
| float angle_delta; | float angle_delta; | ||||
| float angle_increment; | |||||
campbellbarton: This isn't output as far as I can see, its a snap setting. Would move under `has_drag` | |||||
| } output; | } output; | ||||
| } DialInteraction; | } DialInteraction; | ||||
| #define DIAL_WIDTH 1.0f | #define DIAL_WIDTH 1.0f | ||||
| #define DIAL_RESOLUTION 48 | #define DIAL_RESOLUTION 48 | ||||
| /* Could make option, negative to clip more (don't show when view aligned). */ | /* Could make option, negative to clip more (don't show when view aligned). */ | ||||
| #define DIAL_CLIP_BIAS 0.02 | #define DIAL_CLIP_BIAS 0.02 | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| static void dial_geom_draw( | static void dial_geom_draw( | ||||
| const wmGizmo *gz, const float color[4], const bool select, | const float color[4], const float line_width, | ||||
| float axis_modal_mat[4][4], float clip_plane[4], | const bool select, | ||||
| const float arc_partial_angle, const float arc_inner_factor) | const float axis_modal_mat[4][4], const float clip_plane[4], | ||||
| const float arc_partial_angle, const float arc_inner_factor, | |||||
| const int draw_options) | |||||
| { | { | ||||
| #ifdef USE_GIZMO_CUSTOM_DIAL | #ifdef USE_GIZMO_CUSTOM_DIAL | ||||
| UNUSED_VARS(gz, axis_modal_mat, clip_plane); | UNUSED_VARS(gz, axis_modal_mat, clip_plane); | ||||
| wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select, color); | wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_dial, select, color); | ||||
| #else | #else | ||||
| const int draw_options = RNA_enum_get(gz->ptr, "draw_options"); | |||||
| const bool filled = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_FILL) != 0; | const bool filled = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_FILL) != 0; | ||||
| GPU_line_width(gz->line_width); | GPU_line_width(line_width); | ||||
| GPUVertFormat *format = immVertexFormat(); | GPUVertFormat *format = immVertexFormat(); | ||||
| uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | ||||
| if (clip_plane) { | if (clip_plane) { | ||||
| immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR); | immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR); | ||||
| float clip_plane_f[4] = {clip_plane[0], clip_plane[1], clip_plane[2], clip_plane[3]}; | immUniform4fv("ClipPlane", clip_plane); | ||||
| immUniform4fv("ClipPlane", clip_plane_f); | |||||
| immUniformMatrix4fv("ModelMatrix", axis_modal_mat); | immUniformMatrix4fv("ModelMatrix", axis_modal_mat); | ||||
| glEnable(GL_CLIP_DISTANCE0); | |||||
| } | } | ||||
| else { | else { | ||||
| immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); | immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); | ||||
| } | } | ||||
| immUniformColor4fv(color); | immUniformColor4fv(color); | ||||
| if (filled) { | if (filled) { | ||||
| Show All 16 Lines | #if 0 | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| immUnbindProgram(); | immUnbindProgram(); | ||||
| if (clip_plane) { | |||||
| glDisable(GL_CLIP_DISTANCE0); | |||||
| } | |||||
| UNUSED_VARS(select); | UNUSED_VARS(select); | ||||
| #endif | #endif | ||||
| } | } | ||||
| /** | /** | ||||
| * Draws a line from (0, 0, 0) to \a co_outer, at \a angle. | * Draws a line from (0, 0, 0) to \a co_outer, at \a angle. | ||||
| */ | */ | ||||
| static void dial_ghostarc_draw_helpline( | static void dial_ghostarc_draw_helpline( | ||||
| Show All 13 Lines | static void dial_ghostarc_draw_helpline( | ||||
| immVertex3fv(pos, co_outer); | immVertex3fv(pos, co_outer); | ||||
| immEnd(); | immEnd(); | ||||
| immUnbindProgram(); | immUnbindProgram(); | ||||
| GPU_matrix_pop(); | GPU_matrix_pop(); | ||||
| } | } | ||||
| /** | |||||
| * Draws segments to indicate the position of each increment. | |||||
| */ | |||||
| static void dial_ghostarc_draw_incremental_angle(const float incremental_angle) | |||||
| { | |||||
| const int tot_incr = (2 * M_PI) / incremental_angle; | |||||
| GPU_line_width(1.0f); | |||||
| uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | |||||
| immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); | |||||
| immUniformColor3f(1.0f, 1.0f, 1.0f); | |||||
| immBegin(GPU_PRIM_LINES, tot_incr * 2); | |||||
| float v[3] = { 0 }; | |||||
| for (int i = 0; i < tot_incr; i++) { | |||||
| v[0] = sinf(incremental_angle * i); | |||||
| v[1] = cosf(incremental_angle * i); | |||||
| mul_v2_fl(v, DIAL_WIDTH * 1.1f); | |||||
| immVertex3fv(pos, v); | |||||
| mul_v2_fl(v, 1.1f); | |||||
| immVertex3fv(pos, v); | |||||
| } | |||||
| immEnd(); | |||||
| immUnbindProgram(); | |||||
| } | |||||
| static void dial_ghostarc_draw( | static void dial_ghostarc_draw( | ||||
| const float angle_ofs, const float angle_delta, | const float angle_ofs, const float angle_delta, | ||||
| const float arc_inner_factor, const float color[4]) | const float arc_inner_factor, const float color[4]) | ||||
| { | { | ||||
| const float width_inner = DIAL_WIDTH; | const float width_inner = DIAL_WIDTH; | ||||
| GPUVertFormat *format = immVertexFormat(); | GPUVertFormat *format = immVertexFormat(); | ||||
| uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | ||||
| immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); | immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); | ||||
| ▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | static void dial_draw_intern( | ||||
| float color[4]; | float color[4]; | ||||
| BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D); | BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D); | ||||
| gizmo_color_get(gz, highlight, color); | gizmo_color_get(gz, highlight, color); | ||||
| WM_gizmo_calc_matrix_final(gz, matrix_final); | WM_gizmo_calc_matrix_final(gz, matrix_final); | ||||
| GPU_matrix_push(); | |||||
| GPU_matrix_mul(matrix_final); | |||||
| /* FIXME(campbell): look into removing this. */ | |||||
| if ((gz->flag & WM_GIZMO_DRAW_VALUE) && | |||||
| (gz->state & WM_GIZMO_STATE_MODAL)) | |||||
| { | |||||
| /* 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); | |||||
| } | |||||
| } | |||||
| GPU_polygon_smooth(false); | |||||
| const float arc_partial_angle = RNA_float_get(gz->ptr, "arc_partial_angle"); | const float arc_partial_angle = RNA_float_get(gz->ptr, "arc_partial_angle"); | ||||
| const float arc_inner_factor = RNA_float_get(gz->ptr, "arc_inner_factor"); | const float arc_inner_factor = RNA_float_get(gz->ptr, "arc_inner_factor"); | ||||
| if (select == false) { | int draw_options = RNA_enum_get(gz->ptr, "draw_options"); | ||||
| float angle_ofs = 0.0f; | float angle_ofs = 0.0f; | ||||
| float angle_delta = 0.0f; | float angle_delta = 0.0f; | ||||
| bool show_ghostarc = false; | float angle_increment = 0.0f; | ||||
| /* 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 (WM_gizmo_target_property_is_valid(gz_prop) && | if (select) { | ||||
| (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE)) | 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)) | if (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE && | ||||
| (gz->flag & WM_GIZMO_DRAW_VALUE)) | |||||
| { | { | ||||
| DialInteraction *inter = gz->interaction_data; | DialInteraction *inter = gz->interaction_data; | ||||
| if (inter) { | |||||
| angle_ofs = inter->output.angle_ofs; | angle_ofs = inter->output.angle_ofs; | ||||
| angle_delta = inter->output.angle_delta; | angle_delta = inter->output.angle_delta; | ||||
| show_ghostarc = true; | angle_increment = inter->output.angle_increment; | ||||
| } | } | ||||
| else { | |||||
| if (show_ghostarc) { | wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset"); | ||||
| dial_ghostarc_draw_with_helplines(angle_ofs, angle_delta, arc_inner_factor, color, draw_options); | if (WM_gizmo_target_property_is_valid(gz_prop)) { | ||||
| if ((draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR) != 0) { | angle_delta = WM_gizmo_target_property_float_get(gz, gz_prop); | ||||
| angle_ofs += M_PI; | |||||
| dial_ghostarc_draw_with_helplines(angle_ofs, angle_delta, arc_inner_factor, color, draw_options); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Draw actual dial gizmo. */ | ED_gizmotypes_dial_3d_draw_util( | ||||
| dial_geom_draw(gz, color, select, gz->matrix_basis, clip_plane, arc_partial_angle, arc_inner_factor); | gz->matrix_basis, matrix_final, gz->line_width, color, clip_plane, | ||||
| arc_partial_angle, arc_inner_factor, draw_options, angle_ofs, | |||||
| GPU_matrix_pop(); | angle_delta, angle_increment); | ||||
| } | } | ||||
| static void gizmo_dial_draw_select(const bContext *C, wmGizmo *gz, int select_id) | static void gizmo_dial_draw_select(const bContext *C, wmGizmo *gz, int select_id) | ||||
| { | { | ||||
| float clip_plane_buf[4]; | float clip_plane_buf[4]; | ||||
| const int draw_options = RNA_enum_get(gz->ptr, "draw_options"); | 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; | float *clip_plane = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL; | ||||
| if (clip_plane) { | if (clip_plane) { | ||||
| ARegion *ar = CTX_wm_region(C); | ARegion *ar = CTX_wm_region(C); | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| copy_v3_v3(clip_plane, rv3d->viewinv[2]); | copy_v3_v3(clip_plane, rv3d->viewinv[2]); | ||||
| clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]); | clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]); | ||||
| clip_plane[3] += DIAL_CLIP_BIAS; | clip_plane[3] += DIAL_CLIP_BIAS; | ||||
| glEnable(GL_CLIP_DISTANCE0); | |||||
| } | } | ||||
| GPU_select_load_id(select_id); | GPU_select_load_id(select_id); | ||||
| dial_draw_intern(C, gz, true, false, clip_plane); | dial_draw_intern(C, gz, true, false, clip_plane); | ||||
| if (clip_plane) { | if (clip_plane) { | ||||
| glDisable(GL_CLIP_DISTANCE0); | glDisable(GL_CLIP_DISTANCE0); | ||||
| } | } | ||||
| Show All 9 Lines | static void gizmo_dial_draw(const bContext *C, wmGizmo *gz) | ||||
| if (clip_plane) { | if (clip_plane) { | ||||
| ARegion *ar = CTX_wm_region(C); | ARegion *ar = CTX_wm_region(C); | ||||
| RegionView3D *rv3d = ar->regiondata; | RegionView3D *rv3d = ar->regiondata; | ||||
| copy_v3_v3(clip_plane, rv3d->viewinv[2]); | copy_v3_v3(clip_plane, rv3d->viewinv[2]); | ||||
| clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]); | clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]); | ||||
| clip_plane[3] += DIAL_CLIP_BIAS; | clip_plane[3] += DIAL_CLIP_BIAS; | ||||
| glEnable(GL_CLIP_DISTANCE0); | |||||
| } | } | ||||
| GPU_blend(true); | GPU_blend(true); | ||||
| dial_draw_intern(C, gz, false, is_highlight, clip_plane); | dial_draw_intern(C, gz, false, is_highlight, clip_plane); | ||||
| GPU_blend(false); | GPU_blend(false); | ||||
| if (clip_plane) { | |||||
| glDisable(GL_CLIP_DISTANCE0); | |||||
| } | |||||
| } | } | ||||
| static int gizmo_dial_modal( | static int gizmo_dial_modal( | ||||
| bContext *C, wmGizmo *gz, const wmEvent *event, | bContext *C, wmGizmo *gz, const wmEvent *event, | ||||
| eWM_GizmoFlagTweak tweak_flag) | eWM_GizmoFlagTweak tweak_flag) | ||||
| { | { | ||||
| DialInteraction *inter = gz->interaction_data; | DialInteraction *inter = gz->interaction_data; | ||||
| if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) { | if ((event->type != MOUSEMOVE) && (inter->prev.tweak_flag == tweak_flag)) { | ||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| } | } | ||||
| /* 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}; | const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; | ||||
| float angle_ofs, angle_delta; | float angle_ofs, angle_delta, angle_increment = 0.0f; | ||||
| dial_ghostarc_get_angles( | dial_ghostarc_get_angles( | ||||
| gz, event, CTX_wm_region(C), gz->matrix_basis, 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) { | if (tweak_flag & WM_GIZMO_TWEAK_SNAP) { | ||||
| const double snap = DEG2RAD(5); | angle_increment = DEG2RAD(5); | ||||
| angle_delta = (float)roundf((double)angle_delta / snap) * snap; | angle_delta = (float)roundf((double)angle_delta / angle_increment) * angle_increment; | ||||
Done Inline ActionsThis should use the angle_increment setting for snapping. Not hard coded value. campbellbarton: This should use the angle_increment setting for snapping. Not hard coded value. | |||||
| } | } | ||||
| if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) { | if (tweak_flag & WM_GIZMO_TWEAK_PRECISE) { | ||||
| angle_increment *= 0.1f; | |||||
| angle_delta *= 0.1f; | angle_delta *= 0.1f; | ||||
| } | } | ||||
| if (angle_delta != 0.0f) { | if (angle_delta != 0.0f) { | ||||
| inter->has_drag = true; | inter->has_drag = true; | ||||
| } | } | ||||
| inter->output.angle_increment = angle_increment; | |||||
| inter->output.angle_delta = angle_delta; | inter->output.angle_delta = angle_delta; | ||||
| inter->output.angle_ofs = angle_ofs; | 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"); | wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset"); | ||||
| if (WM_gizmo_target_property_is_valid(gz_prop)) { | 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); | WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init.prop_angle + angle_delta); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | static int gizmo_dial_invoke( | ||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Dial Gizmo API | /** \name Dial Gizmo API | ||||
| * | * | ||||
| * \{ */ | * \{ */ | ||||
| void ED_gizmotypes_dial_3d_draw_util( | |||||
| const float matrix_basis[4][4], | |||||
| const float matrix_final[4][4], | |||||
| const float line_width, | |||||
| const float color[4], | |||||
| const float clip_plane[4], | |||||
| const float arc_partial_angle, | |||||
| const float arc_inner_factor, | |||||
| const int draw_options, | |||||
| const float angle_ofs, | |||||
| const float angle_delta, | |||||
| const float angle_increment) | |||||
| { | |||||
| GPU_matrix_push(); | |||||
| GPU_matrix_mul(matrix_final); | |||||
| GPU_polygon_smooth(false); | |||||
| if ((draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE) != 0) { | |||||
| /* Draw rotation indicator arc first. */ | |||||
| 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) { | |||||
| dial_ghostarc_draw_with_helplines( | |||||
| angle_ofs + M_PI, angle_delta, | |||||
| arc_inner_factor, color, draw_options); | |||||
| } | |||||
| } | |||||
| if (angle_increment) { | |||||
| dial_ghostarc_draw_incremental_angle(angle_increment); | |||||
| } | |||||
| /* Draw actual dial gizmo. */ | |||||
| dial_geom_draw( | |||||
| color, line_width, false, matrix_basis, clip_plane, | |||||
| arc_partial_angle, arc_inner_factor, draw_options); | |||||
| GPU_matrix_pop(); | |||||
| } | |||||
| static void GIZMO_GT_dial_3d(wmGizmoType *gzt) | static void GIZMO_GT_dial_3d(wmGizmoType *gzt) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| gzt->idname = "GIZMO_GT_dial_3d"; | gzt->idname = "GIZMO_GT_dial_3d"; | ||||
| /* api callbacks */ | /* api callbacks */ | ||||
| gzt->draw = gizmo_dial_draw; | gzt->draw = gizmo_dial_draw; | ||||
| gzt->draw_select = gizmo_dial_draw_select; | gzt->draw_select = gizmo_dial_draw_select; | ||||
| Show All 34 Lines | |||||
This isn't output as far as I can see, its a snap setting. Would move under has_drag