Manipulator: view3d navigation buttons

Added for Blender101 template.
Disabled by default, enable as a preference.

Exposes rotate, pan, zoom, persp-ortho & camera toggle.
This commit is contained in:
Campbell Barton 2017-12-16 03:57:20 +11:00
parent c2cc42742d
commit 468ac90317
Notes: blender-bot 2023-02-14 09:33:11 +01:00
Referenced by issue #53568, OpenGL framebuffer creation error on macOS
12 changed files with 761 additions and 5 deletions

View File

@ -287,6 +287,7 @@ class USERPREF_PT_interface(Panel):
#col.prop(view, "open_left_mouse_delay", text="Hold LMB")
#col.prop(view, "open_right_mouse_delay", text="Hold RMB")
col.prop(view, "show_manipulator")
col.prop(view, "show_manipulator_navigate")
## Currently not working
# col.prop(view, "show_manipulator_shaded")
sub = col.column()

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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);
}

View File

@ -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]);

View File

@ -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;
}
/** \} */

View File

@ -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);
}

View File

@ -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.

View File

@ -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);