diff options
Diffstat (limited to 'source/blender')
11 files changed, 760 insertions, 5 deletions
diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h index 80703321490..7166292147e 100644 --- a/source/blender/editors/include/ED_manipulator_library.h +++ b/source/blender/editors/include/ED_manipulator_library.h @@ -33,6 +33,7 @@ /* initialize manipulators */ void ED_manipulatortypes_arrow_2d(void); void ED_manipulatortypes_arrow_3d(void); +void ED_manipulatortypes_button_2d(void); void ED_manipulatortypes_cage_2d(void); void ED_manipulatortypes_cage_3d(void); void ED_manipulatortypes_dial_3d(void); diff --git a/source/blender/editors/manipulator_library/CMakeLists.txt b/source/blender/editors/manipulator_library/CMakeLists.txt index 9f7df8c6425..86e1bb3b6d7 100644 --- a/source/blender/editors/manipulator_library/CMakeLists.txt +++ b/source/blender/editors/manipulator_library/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC geometry/geom_dial_manipulator.c manipulator_types/arrow2d_manipulator.c manipulator_types/arrow3d_manipulator.c + manipulator_types/button2d_manipulator.c manipulator_types/cage2d_manipulator.c manipulator_types/cage3d_manipulator.c manipulator_types/dial3d_manipulator.c diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c new file mode 100644 index 00000000000..32c1dbae0a6 --- /dev/null +++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c @@ -0,0 +1,202 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file button2d_manipulator.c + * \ingroup wm + * + * \name Button Manipulator + * + * 3D Manipulator, also works in 2D views. + * + * \brief Single click button action for use in manipulator groups. + * + * Note: currently only very basic icon buttons supported. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +#include "UI_interface_icons.h" +#include "UI_resources.h" + +/* own includes */ +#include "../manipulator_geometry.h" +#include "../manipulator_library_intern.h" + +typedef struct ButtonManipulator3D { + wmManipulator manipulator; + /* Added to 'matrix_basis' when calculating the matrix. */ + float prop_co[3]; +} ButtonManipulator3D; + +#define DIAL_RESOLUTION 32 + +/* -------------------------------------------------------------------- */ + +static void button_geom_draw( + const wmManipulator *mpr, const float color[4], const bool select) +{ + glLineWidth(mpr->line_width); + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + immUniformColor4fv(color); + + /* TODO, other draw styles */ + imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION); + + immUnbindProgram(); + + UNUSED_VARS(select); +} + +static void button3d_draw_intern( + const bContext *UNUSED(C), wmManipulator *mpr, + const bool select, const bool highlight) +{ + float color[4]; + float matrix_final[4][4]; + + manipulator_color_get(mpr, highlight, color); + WM_manipulator_calc_matrix_final(mpr, matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + glEnable(GL_BLEND); + button_geom_draw(mpr, color, select); + gpuPopMatrix(); + + + if (select == false) { + int icon = RNA_enum_get(mpr->ptr, "icon"); + if (icon != ICON_NONE) { + UI_icon_draw( + mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * U.pixelsize, + mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * U.pixelsize, + icon); + } + } + glDisable(GL_BLEND); +} + +static void manipulator_button_draw_select(const bContext *C, wmManipulator *mpr, int select_id) +{ + GPU_select_load_id(select_id); + button3d_draw_intern(C, mpr, true, false); +} + +static void manipulator_button_draw(const bContext *C, wmManipulator *mpr) +{ + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + + glEnable(GL_BLEND); + button3d_draw_intern(C, mpr, false, is_highlight); + glDisable(GL_BLEND); +} + +static int manipulator_button_test_select( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + float point_local[2]; + + if (0) { + /* correct, but unnecessarily slow. */ + if (manipulator_window_project_2d( + C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false) + { + return -1; + } + } + else { + copy_v2_v2(point_local, (float [2]){UNPACK2(event->mval)}); + sub_v2_v2(point_local, mpr->matrix_basis[3]); + mul_v2_fl(point_local, 1.0f / mpr->scale_basis); + } + + /* The 'mpr->scale_final' is already applied when projecting. */ + if (len_squared_v2(point_local) < 1.0f) { + return 0; + } + + return -1; +} + +static int manipulator_button_cursor_get(wmManipulator *UNUSED(mpr)) +{ + return BC_HANDCURSOR; +} + +/* -------------------------------------------------------------------- */ +/** \name Button Manipulator API + * + * \{ */ + +static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_button_2d"; + + /* api callbacks */ + wt->draw = manipulator_button_draw; + wt->draw_select = manipulator_button_draw_select; + wt->test_select = manipulator_button_test_select; + wt->cursor_get = manipulator_button_cursor_get; + + wt->struct_size = sizeof(ButtonManipulator3D); + + /* rna */ + PropertyRNA *prop; + prop = RNA_def_property(wt->srna, "icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_icon_items); + RNA_def_property_ui_text(prop, "Icon", "Override automatic icon of the item"); +} + +void ED_manipulatortypes_button_2d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_button_2d); +} + +/** \} */ // Button Manipulator API diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 32f6ac40d12..e417026640e 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -127,6 +127,7 @@ void ED_spacetypes_init(void) ED_operatortypes_ui(); /* manipulator types */ + ED_manipulatortypes_button_2d(); ED_manipulatortypes_dial_3d(); ED_manipulatortypes_grab_3d(); ED_manipulatortypes_arrow_2d(); diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index de8380aa8bb..11ef781b229 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -64,6 +64,8 @@ set(SRC view3d_manipulator_empty.c view3d_manipulator_forcefield.c view3d_manipulator_lamp.c + view3d_manipulator_navigate.c + view3d_manipulator_navigate_type.c view3d_manipulator_ruler.c view3d_ops.c view3d_project.c diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 984ab82ee60..3430351b756 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -729,6 +729,9 @@ static void view3d_widgets(void) WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler); WM_manipulatortype_append(VIEW3D_WT_ruler_item); + + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate); + WM_manipulatortype_append(VIEW3D_WT_navigate_rotate); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index a7368a84eb6..ee0b628fdad 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -153,7 +153,7 @@ void draw_object_select( const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); -void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]); +void draw_mesh_object_outline(View3D *v3d, struct Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]); bool draw_glsl_material(Scene *scene, struct ViewLayer *view_layer, struct Object *ob, View3D *v3d, const char dt); void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]); @@ -304,7 +304,7 @@ void ED_view3d_cameracontrol_update( void ED_view3d_cameracontrol_release( struct View3DCameraControl *vctrl, const bool restore); -Object *ED_view3d_cameracontrol_object_get( +struct Object *ED_view3d_cameracontrol_object_get( struct View3DCameraControl *vctrl); /* view3d_toolbar.c */ @@ -338,11 +338,14 @@ void VIEW3D_WGT_camera_view(struct wmManipulatorGroupType *wgt); void VIEW3D_WGT_force_field(struct wmManipulatorGroupType *wgt); void VIEW3D_WGT_empty_image(struct wmManipulatorGroupType *wgt); void VIEW3D_WGT_armature_spline(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_navigate(struct wmManipulatorGroupType *wgt); void VIEW3D_WGT_ruler(struct wmManipulatorGroupType *wgt); void VIEW3D_WT_ruler_item(struct wmManipulatorType *wt); void VIEW3D_OT_ruler_add(struct wmOperatorType *ot); +void VIEW3D_WT_navigate_rotate(struct wmManipulatorType *wt); + /* draw_volume.c */ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, const float min[3], const float max[3], @@ -365,7 +368,7 @@ extern bool view3d_camera_border_hack_test; void VP_legacy_drawcursor(Scene *scene, struct ViewLayer *view_layer, ARegion *ar, View3D *v3d); void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect); void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect); -void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect); +void VP_legacy_draw_selected_name(Scene *scene, struct Object *ob, rcti *rect); void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit); void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth); void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c new file mode 100644 index 00000000000..553d3b03687 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c @@ -0,0 +1,231 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_navigate.c + * \ingroup spview3d + */ + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/** \name View3D Navigation Manipulator Group + * \{ */ + +/* Offset from screen edge. */ +#define MANIPULATOR_OFFSET_FAC 2.5 +/* Size of main icon. */ +#define MANIPULATOR_SIZE 64 +/* Factor for size of smaller button. */ +#define MANIPULATOR_MINI_FAC 0.4 +/* How much mini buttons offset from the primary. */ +#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f + + +enum { + MPR_MOVE = 0, + MPR_ROTATE = 1, + MPR_ZOOM = 2, + /* just buttons */ + MPR_PERSP_ORTHO = 3, + MPR_CAMERA = 4, + + MPR_TOTAL = 5, +}; + +struct NavigateManipulatorInfo { + const char *opname; + const char *manipulator; + int icon; +}; + +struct NavigateManipulatorInfo g_navigate_params[MPR_TOTAL] = { + { + .opname = "VIEW3D_OT_move", + .manipulator = "MANIPULATOR_WT_button_2d", + .icon = ICON_HAND, + }, { + .opname = "VIEW3D_OT_rotate", + .manipulator = "VIEW3D_WT_navigate_rotate", + .icon = ICON_NONE, + }, { + .opname = "VIEW3D_OT_zoom", + .manipulator = "MANIPULATOR_WT_button_2d", + .icon = ICON_VIEWZOOM, + }, { + .opname = "VIEW3D_OT_view_persportho", + .manipulator = "MANIPULATOR_WT_button_2d", + .icon = ICON_MESH_CUBE, + }, { + .opname = "VIEW3D_OT_viewnumpad", + .manipulator = "MANIPULATOR_WT_button_2d", + .icon = ICON_OUTLINER_OB_CAMERA, + }, +}; + +struct NavigateWidgetGroup { + wmManipulator *mpr_array[MPR_TOTAL]; + int region_size[2]; +}; + +static bool WIDGETGROUP_navigate_poll(const bContext *UNUSED(C), wmManipulatorGroupType *UNUSED(wgt)) +{ + if (U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) { + return true; + } + return false; + +} + +static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__); + + navgroup->region_size[0] = -1; + navgroup->region_size[1] = -1; + + wmOperatorType *ot_viewnumpad = WM_operatortype_find("VIEW3D_OT_viewnumpad", true); + + for (int i = 0; i < MPR_TOTAL; i++) { + const struct NavigateManipulatorInfo *info = &g_navigate_params[i]; + navgroup->mpr_array[i] = WM_manipulator_new(info->manipulator, mgroup, NULL); + wmManipulator *mpr = navgroup->mpr_array[i]; + mpr->flag |= WM_MANIPULATOR_GRAB_CURSOR; + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL); + copy_v3_fl(mpr->color, 1.0f); + mpr->color[3] = 0.4f; + + /* may be overwritten later */ + mpr->scale_basis = (MANIPULATOR_SIZE * MANIPULATOR_MINI_FAC) / 2; + if (info->icon != ICON_NONE) { + RNA_enum_set(mpr->ptr, "icon", info->icon); + } + + wmOperatorType *ot = WM_operatortype_find(info->opname, true); + WM_manipulator_operator_set(mpr, 0, ot, NULL); + } + + { + wmManipulator *mpr = navgroup->mpr_array[MPR_CAMERA]; + PointerRNA *ptr = WM_manipulator_operator_set(mpr, 0, ot_viewnumpad, NULL); + RNA_enum_set(ptr, "type", RV3D_VIEW_CAMERA); + } + + { + wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE]; + mpr->scale_basis = MANIPULATOR_SIZE / 2; + char mapping[6] = { + RV3D_VIEW_LEFT, + RV3D_VIEW_RIGHT, + RV3D_VIEW_FRONT, + RV3D_VIEW_BACK, + RV3D_VIEW_BOTTOM, + RV3D_VIEW_TOP, + }; + + for (int part_index = 0; part_index < 6; part_index+= 1) { + PointerRNA *ptr = WM_manipulator_operator_set(mpr, mapping[part_index], ot_viewnumpad, NULL); + RNA_enum_set(ptr, "type", RV3D_VIEW_FRONT + part_index); + } + } + + mgroup->customdata = navgroup; +} + +static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NavigateWidgetGroup *navgroup = mgroup->customdata; + ARegion *ar = CTX_wm_region(C); + const RegionView3D *rv3d = ar->regiondata; + + for (int i = 0; i < 3; i++) { + copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]); + } + + if ((navgroup->region_size[0] == ar->winx) && + (navgroup->region_size[1] == ar->winy)) + { + return; + } + + navgroup->region_size[0] = ar->winx; + navgroup->region_size[1] = ar->winy; + + const float icon_size = MANIPULATOR_SIZE; + const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * U.pixelsize; + const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * U.pixelsize; + const float co[2] = {ar->winx - icon_offset, ar->winy - icon_offset}; + + wmManipulator *mpr; + mpr = navgroup->mpr_array[MPR_ROTATE]; + mpr->matrix_basis[3][0] = co[0]; + mpr->matrix_basis[3][1] = co[1]; + + mpr = navgroup->mpr_array[MPR_MOVE]; + mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; + + mpr = navgroup->mpr_array[MPR_ZOOM]; + mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; + + mpr = navgroup->mpr_array[MPR_PERSP_ORTHO]; + mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + + mpr = navgroup->mpr_array[MPR_CAMERA]; + mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; +} + +void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt) +{ + wgt->name = "View3D Navigate"; + wgt->idname = "VIEW3D_WGT_navigate"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_SCALE); + + wgt->poll = WIDGETGROUP_navigate_poll; + wgt->setup = WIDGETGROUP_navigate_setup; + wgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c new file mode 100644 index 00000000000..d57656ce42a --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c @@ -0,0 +1,305 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file view3d_manipulator_navigate_type.c + * \ingroup wm + * + * \name Custom Orientation/Navigation Manipulator for the 3D View + * + * \brief Simple manipulator to axis and translate. + * + * matrix_offset is used to store the orientation. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_sort_utils.h" + +#include "BKE_context.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +#include "view3d_intern.h" + +#define DIAL_RESOLUTION 32 + +#define HANDLE_SIZE 0.33 + +static void axis_geom_draw( + const wmManipulator *mpr, const float color[4], const bool UNUSED(select)) +{ + glLineWidth(mpr->line_width); + + Gwn_VertFormat *format = immVertexFormat(); + const uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + /* flip z for reverse */ + const float cone_coords[5][3] = { + {-1, -1, 4}, + {-1, +1, 4}, + {+1, +1, 4}, + {+1, -1, 4}, + {0, 0, 2}, + }; + + struct { + float depth; + char index; + char axis; + char is_pos; + } axis_order[6] = { + {-mpr->matrix_offset[0][2], 0, 0, false}, + {+mpr->matrix_offset[0][2], 1, 0, true}, + {-mpr->matrix_offset[1][2], 2, 1, false}, + {+mpr->matrix_offset[1][2], 3, 1, true}, + {-mpr->matrix_offset[2][2], 4, 2, false}, + {+mpr->matrix_offset[2][2], 5, 2, true}, + }; + qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float); + + const float scale_axis = 0.33f; + static const float axis_highlight[4] = {1, 1, 1, 1}; + static const float axis_black[4] = {0, 0, 0, 1}; + static float axis_color[3][4]; + gpuPushMatrix(); + gpuMultMatrix(mpr->matrix_offset); + + bool draw_center_done = false; + + for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) { + const int index = axis_order[axis_index].index; + const int axis = axis_order[axis_index].axis; + const bool is_pos = axis_order[axis_index].is_pos; + + /* Draw slightly before, so axis aligned arrows draw ontop. */ + if ((draw_center_done == false) && (axis_order[axis_index].depth > -0.01f)) { + + /* Circle defining active area (revert back to 2D space). */ + { + gpuPopMatrix(); + immUniformColor4fv(color); + imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION); + gpuPushMatrix(); + gpuMultMatrix(mpr->matrix_offset); + } + + /* Center cube. */ + { + float center[3], size[3]; + + zero_v3(center); + copy_v3_fl(size, HANDLE_SIZE); + + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + glDepthFunc(GL_LEQUAL); + glBlendFunc(GL_ONE, GL_ZERO); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glLineWidth(1.0f); + immUniformColor4fv(axis_highlight); + imm_draw_cube_fill_3d(pos_id, center, size); + immUniformColor4fv(axis_black); + madd_v3_v3fl( + center, + (float [3]){ + mpr->matrix_offset[0][2], + mpr->matrix_offset[1][2], + mpr->matrix_offset[2][2]}, + 0.08f); + imm_draw_cube_wire_3d(pos_id, center, size); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_DEPTH_TEST); + } + + draw_center_done = true; + } + UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]); + axis_color[axis][3] = 1.0f; + + const int index_z = axis; + const int index_y = (axis + 1) % 3; + const int index_x = (axis + 2) % 3; + +#define ROTATED_VERT(v_orig) \ + { \ + float v[3]; \ + copy_v3_v3(v, v_orig); \ + if (is_pos == 0) { \ + v[2] *= -1.0f; \ + } \ + immVertex3f(pos_id, v[index_x] * scale_axis, v[index_y] * scale_axis, v[index_z] * scale_axis); \ + } ((void)0) + + bool ok = true; + + /* skip view align axis */ + if (len_squared_v2(mpr->matrix_offset[axis]) < 1e-6f && (mpr->matrix_offset[axis][2] > 0.0f) == is_pos) { + ok = false; + } + if (ok) { + immUniformColor4fv(index + 1 == mpr->highlight_part ? axis_highlight : axis_color[axis]); + immBegin(GWN_PRIM_TRI_FAN, 6); + ROTATED_VERT(cone_coords[4]); + for (int j = 0; j <= 4; j++) { + ROTATED_VERT(cone_coords[j % 4]); + } + immEnd(); + } + +#undef ROTATED_VERT + } + + gpuPopMatrix(); + immUnbindProgram(); +} + +static void axis3d_draw_intern( + const bContext *UNUSED(C), wmManipulator *mpr, + const bool select, const bool highlight) +{ + const float *color = highlight ? mpr->color_hi : mpr->color; + float matrix_final[4][4]; + float matrix_unit[4][4]; + + unit_m4(matrix_unit); + + WM_manipulator_calc_matrix_final_params( + mpr, + &((struct WM_ManipulatorMatrixParams) { + .matrix_offset = matrix_unit, + }), matrix_final); + + gpuPushMatrix(); + gpuMultMatrix(matrix_final); + + glEnable(GL_BLEND); + axis_geom_draw(mpr, color, select); + glDisable(GL_BLEND); + gpuPopMatrix(); +} + +static void manipulator_axis_draw(const bContext *C, wmManipulator *mpr) +{ + const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL; + const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0 && (mpr->highlight_part == 0); + + (void)is_modal; + + glEnable(GL_BLEND); + axis3d_draw_intern(C, mpr, false, is_highlight); + glDisable(GL_BLEND); +} + +static int manipulator_axis_test_select( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + float point_local[2] = {UNPACK2(event->mval)}; + sub_v2_v2(point_local, mpr->matrix_basis[3]); + mul_v2_fl(point_local, 1.0f / mpr->scale_basis); + + const float len_sq = len_squared_v2(point_local); + if (len_sq > SQUARE(1.0 + HANDLE_SIZE)) { + return -1; + } + + int part_best = -1; + int part_index = 1; + float i_best_len_sq = SQUARE(HANDLE_SIZE); + for (int i = 0; i < 3; i++) { + for (int is_pos = 0; is_pos < 2; is_pos++) { + float co[2] = { + mpr->matrix_offset[i][0] * (is_pos ? 1 : -1), + mpr->matrix_offset[i][1] * (is_pos ? 1 : -1), + }; + + bool ok = true; + + /* Check if we're viewing on an axis, there is no point to clicking on the current axis so show the reverse. */ + if (len_squared_v2(co) < 1e-6f && (mpr->matrix_offset[i][2] > 0.0f) == is_pos) { + ok = false; + } + + if (ok) { + const float len_axis_sq = len_squared_v2v2(co, point_local); + if (len_axis_sq < i_best_len_sq) { + part_best = part_index; + i_best_len_sq = len_axis_sq; + } + } + part_index += 1; + } + } + + if (part_best != -1) { + return part_best; + } + + /* The 'mpr->scale_final' is already applied when projecting. */ + if (len_sq < 1.0f) { + return 0; + } + + return -1; +} + +static int manipulator_axis_cursor_get(wmManipulator *mpr) +{ + if (mpr->highlight_part > 0) { + return BC_CROSSCURSOR; + } + return BC_NSEW_SCROLLCURSOR; +} + +void VIEW3D_WT_navigate_rotate(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "VIEW3D_WT_navigate_rotate"; + + /* api callbacks */ + wt->draw = manipulator_axis_draw; + wt->test_select = manipulator_axis_test_select; + wt->cursor_get = manipulator_axis_cursor_get; + + wt->struct_size = sizeof(wmManipulator); +} diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 92ec93d8f20..e4747f733e5 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -817,8 +817,9 @@ typedef enum eGP_UserdefSettings { } eGP_UserdefSettings; enum { - USER_MANIPULATOR_DRAW = (1 << 0), - USER_MANIPULATOR_SHADED = (1 << 1), + USER_MANIPULATOR_DRAW = (1 << 0), + USER_MANIPULATOR_DRAW_NAVIGATE = (1 << 1), + USER_MANIPULATOR_SHADED = (1 << 8), }; /* Color Picker Types. diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 273f9fcf280..bff6cdcf1bd 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3525,6 +3525,11 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Manipulator", "Use 3D transform manipulator"); RNA_def_property_update(prop, 0, "rna_userdef_show_manipulator_update"); + prop = RNA_def_property(srna, "show_manipulator_navigate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "manipulator_flag", USER_MANIPULATOR_DRAW_NAVIGATE); + RNA_def_property_ui_text(prop, "Navigate Manipulator", "Use 3D navigation manipulator"); + RNA_def_property_update(prop, 0, "rna_userdef_show_manipulator_update"); + /* TODO, expose once it's working. */ #if 0 prop = RNA_def_property(srna, "show_manipulator_shaded", PROP_BOOLEAN, PROP_NONE); |