Blender V4.3
view3d_gizmo_navigate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_math_vector.h"
10#include "BLI_utildefines.h"
11
12#include "BKE_context.hh"
13
14#include "DNA_object_types.h"
15
16#include "ED_gizmo_library.hh"
17#include "ED_screen.hh"
18
19#include "UI_interface.hh"
20#include "UI_resources.hh"
21
22#include "MEM_guardedalloc.h"
23
24#include "RNA_access.hh"
25
26#include "WM_api.hh"
27#include "WM_types.hh"
28
29#include "view3d_intern.hh" /* own include */
30
31/* -------------------------------------------------------------------- */
35/* Size of main icon. */
36#define GIZMO_SIZE U.gizmo_size_navigate_v3d
37
38/* Main gizmo offset from screen edges in unscaled pixels. */
39#define GIZMO_OFFSET 10.0f
40
41/* Width of smaller buttons in unscaled pixels. */
42#define GIZMO_MINI_SIZE 28.0f
43
44/* Margin around the smaller buttons. */
45#define GIZMO_MINI_OFFSET 2.0f
46
47enum {
51
52 /* just buttons */
53 /* overlaps GZ_INDEX_ORTHO (switch between) */
56
59
62
64};
65
66struct NavigateGizmoInfo {
67 const char *opname;
68 const char *gizmo;
69 uint icon;
71};
72
74{
75 RNA_string_set(ptr, "data_path", "space_data.lock_camera");
76}
77
79 {
80 "VIEW3D_OT_move",
81 "GIZMO_GT_button_2d",
82 ICON_VIEW_PAN,
83 nullptr,
84 },
85 {
86 "VIEW3D_OT_rotate",
87 "VIEW3D_GT_navigate_rotate",
88 ICON_NONE,
89 nullptr,
90 },
91 {
92 "VIEW3D_OT_zoom",
93 "GIZMO_GT_button_2d",
94 ICON_VIEW_ZOOM,
95 nullptr,
96 },
97 {
98 "VIEW3D_OT_view_persportho",
99 "GIZMO_GT_button_2d",
100 ICON_VIEW_PERSPECTIVE,
101 nullptr,
102 },
103 {
104 "VIEW3D_OT_view_persportho",
105 "GIZMO_GT_button_2d",
106 ICON_VIEW_ORTHO,
107 nullptr,
108 },
109 {
110 "VIEW3D_OT_view_camera",
111 "GIZMO_GT_button_2d",
112 ICON_VIEW_CAMERA_UNSELECTED,
113 nullptr,
114 },
115 {
116 "VIEW3D_OT_view_camera",
117 "GIZMO_GT_button_2d",
118 ICON_VIEW_CAMERA,
119 nullptr,
120 },
121 {
122 "WM_OT_context_toggle",
123 "GIZMO_GT_button_2d",
124 ICON_VIEW_LOCKED,
126 },
127 {
128 "WM_OT_context_toggle",
129 "GIZMO_GT_button_2d",
130 ICON_VIEW_UNLOCKED,
132 },
133};
134
135struct NavigateWidgetGroup {
137 /* Store the view state to check for changes. */
138 struct {
140 struct {
147};
148
149static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType * /*gzgt*/)
150{
151 View3D *v3d = CTX_wm_view3d(C);
152 if ((((U.uiflag & USER_SHOW_GIZMO_NAVIGATE) == 0) &&
153 (U.mini_axis_type != USER_MINI_AXIS_TYPE_GIZMO)) ||
155 {
156 return false;
157 }
158 return true;
159}
160
161static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
162{
163 NavigateWidgetGroup *navgroup = static_cast<NavigateWidgetGroup *>(
164 MEM_callocN(sizeof(NavigateWidgetGroup), __func__));
165
166 wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true);
167 wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true);
168
169 for (int i = 0; i < GZ_INDEX_TOTAL; i++) {
170 const NavigateGizmoInfo *info = &g_navigate_params[i];
171 navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, nullptr);
172 wmGizmo *gz = navgroup->gz_array[i];
174
175 if (i == GZ_INDEX_ROTATE) {
176 gz->color[3] = 0.0f;
177 copy_v3_fl(gz->color_hi, 0.5f);
178 gz->color_hi[3] = 0.5f;
179 }
180 else {
181 uchar icon_color[3];
182 UI_GetThemeColor3ubv(TH_TEXT, icon_color);
183 int color_tint, color_tint_hi;
184 if (icon_color[0] > 128) {
185 color_tint = -40;
186 color_tint_hi = 60;
187 gz->color[3] = 0.5f;
188 gz->color_hi[3] = 0.5f;
189 }
190 else {
191 color_tint = 60;
192 color_tint_hi = 60;
193 gz->color[3] = 0.5f;
194 gz->color_hi[3] = 0.75f;
195 }
196 UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color);
197 UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi);
198 }
199
200 /* may be overwritten later */
201 gz->scale_basis = GIZMO_MINI_SIZE / 2.0f;
202 if (info->icon != ICON_NONE) {
203 PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
204 RNA_property_enum_set(gz->ptr, prop, info->icon);
207 }
208
210 PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot, nullptr);
211 if (info->op_prop_fn != nullptr) {
212 info->op_prop_fn(ptr);
213 }
214 }
215
216 {
217 wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA_OFF];
218 WM_gizmo_operator_set(gz, 0, ot_view_camera, nullptr);
219 }
220 {
221 wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA_ON];
222 WM_gizmo_operator_set(gz, 0, ot_view_camera, nullptr);
223 }
224
225 /* Click only buttons (not modal). */
226 {
227 int gz_ids[] = {GZ_INDEX_PERSP,
233 for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
234 wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
235 RNA_boolean_set(gz->ptr, "show_drag", false);
236 }
237 }
238
239 /* Modal operators, don't use initial mouse location since we're clicking on a button. */
240 {
242 for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
243 wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
245 RNA_boolean_set(&gzop->ptr, "use_cursor_init", false);
246 }
247 }
248
249 {
250 wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE];
251 gz->scale_basis = GIZMO_SIZE / 2.0f;
252 const char mapping[6] = {
259 };
260
261 for (int part_index = 0; part_index < 6; part_index += 1) {
262 PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, nullptr);
263 RNA_enum_set(ptr, "type", mapping[part_index]);
264 }
265
266 /* When dragging an axis, use this instead. */
269 gz->drag_part = 0;
270 }
271
272 gzgroup->customdata = navgroup;
273}
274
276{
277 NavigateWidgetGroup *navgroup = static_cast<NavigateWidgetGroup *>(gzgroup->customdata);
278 ARegion *region = CTX_wm_region(C);
279 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
280 const View3D *v3d = CTX_wm_view3d(C);
281
282 for (int i = 0; i < 3; i++) {
283 copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
284 }
285
286 const rcti *rect_visible = ED_region_visible_rect(region);
287
288 /* Ensure types match so bits are never lost on assignment. */
289 CHECK_TYPE_PAIR(navgroup->state.rv3d.viewlock, rv3d->viewlock);
290
291 if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) &&
292 (navgroup->state.rect_visible.ymax == rect_visible->ymax) &&
293 (navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
294 (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
295 (navgroup->state.rv3d.cameralock == (v3d->flag2 & V3D_LOCK_CAMERA)) &&
296 (navgroup->state.rv3d.viewlock == RV3D_LOCK_FLAGS(rv3d)))
297 {
298 return;
299 }
300
301 navgroup->state.rect_visible = *rect_visible;
302 navgroup->state.rv3d.is_persp = rv3d->is_persp;
303 navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
304 navgroup->state.rv3d.viewlock = RV3D_LOCK_FLAGS(rv3d);
305 navgroup->state.rv3d.cameralock = v3d->flag2 & V3D_LOCK_CAMERA;
306
307 const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0;
308 const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO);
309 const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_SCALE_FAC;
310 const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_SCALE_FAC;
311 const float co_rotate[2] = {
312 rect_visible->xmax - icon_offset,
313 rect_visible->ymax - icon_offset,
314 };
315
316 float icon_offset_from_axis = 0.0f;
317 switch ((eUserpref_MiniAxisType)U.mini_axis_type) {
319 icon_offset_from_axis = icon_offset * 2.1f;
320 break;
322 icon_offset_from_axis = (UI_UNIT_X * 2.5) + (U.rvisize * U.pixelsize * 2.0f);
323 break;
325 icon_offset_from_axis = icon_offset_mini * 0.75f;
326 break;
327 }
328
329 const float co[2] = {
330 roundf(rect_visible->xmax - icon_offset_mini * 0.75f),
331 roundf(rect_visible->ymax - icon_offset_from_axis),
332 };
333
334 wmGizmo *gz;
335
336 for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) {
337 gz = navgroup->gz_array[i];
339 }
340
341 if (show_rotate_gizmo) {
342 gz = navgroup->gz_array[GZ_INDEX_ROTATE];
343 gz->matrix_basis[3][0] = roundf(co_rotate[0]);
344 gz->matrix_basis[3][1] = roundf(co_rotate[1]);
346 }
347
348 if (show_navigate) {
349 int icon_mini_slot = 0;
350 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY) == 0) {
351 gz = navgroup->gz_array[GZ_INDEX_ZOOM];
352 gz->matrix_basis[3][0] = roundf(co[0]);
353 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
355 }
356
357 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION) == 0) {
358 gz = navgroup->gz_array[GZ_INDEX_MOVE];
359 gz->matrix_basis[3][0] = roundf(co[0]);
360 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
362 }
363
364 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
365 gz = navgroup
367 gz->matrix_basis[3][0] = roundf(co[0]);
368 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
370
371 if (navgroup->state.rv3d.is_camera == false) {
372 gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO];
373 gz->matrix_basis[3][0] = roundf(co[0]);
374 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
376 }
377 }
378
379 if (navgroup->state.rv3d.is_camera == true) {
380 gz = navgroup->gz_array[(v3d->flag2 & V3D_LOCK_CAMERA) ? GZ_INDEX_CAMERA_LOCK :
382 gz->matrix_basis[3][0] = roundf(co[0]);
383 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
385 }
386 }
387}
388
390{
391 gzgt->name = "View3D Navigate";
392 gzgt->idname = "VIEW3D_GGT_navigate";
393
396
400}
401
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
#define CHECK_TYPE_PAIR(var_a, var_b)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
unsigned char uchar
unsigned int uint
#define ARRAY_SIZE(arr)
Object is a sort of wrapper for general info.
@ USER_SHOW_GIZMO_NAVIGATE
eUserpref_MiniAxisType
@ USER_MINI_AXIS_TYPE_GIZMO
@ USER_MINI_AXIS_TYPE_MINIMAL
@ USER_MINI_AXIS_TYPE_NONE
#define UI_SCALE_FAC
#define RV3D_LOCK_FLAGS(rv3d)
@ V3D_GIZMO_HIDE
@ V3D_GIZMO_HIDE_NAVIGATE
@ RV3D_CAMOB
@ RV3D_LOCK_ROTATION
@ RV3D_LOCK_LOCATION
@ RV3D_LOCK_ZOOM_AND_DOLLY
@ V3D_LOCK_CAMERA
@ RV3D_VIEW_FRONT
@ RV3D_VIEW_BOTTOM
@ RV3D_VIEW_LEFT
@ RV3D_VIEW_RIGHT
@ RV3D_VIEW_TOP
@ RV3D_VIEW_BACK
@ ED_GIZMO_BUTTON_SHOW_BACKDROP
@ ED_GIZMO_BUTTON_SHOW_OUTLINE
const rcti * ED_region_visible_rect(ARegion *region)
Definition area.cc:4010
Read Guarded memory(de)allocation.
#define UI_UNIT_X
@ TH_HEADER
@ TH_TEXT
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
@ WM_GIZMO_HIDDEN
@ WM_GIZMO_MOVE_CURSOR
@ WM_GIZMO_DRAW_MODAL
@ WM_GIZMOGROUPTYPE_SCALE
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL
@ WM_GIZMOGROUPTYPE_PERSISTENT
unsigned int U
Definition btGjkEpa3.h:78
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void(* op_prop_fn)(PointerRNA *ptr)
struct NavigateWidgetGroup::@407 state
struct NavigateWidgetGroup::@534::@535 rv3d
wmGizmo * gz_array[GZ_INDEX_TOTAL]
float viewmat[4][4]
int ymax
int xmax
wmGizmoGroupFnInit setup
const char * idname
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
wmGizmoGroupFnDrawPrepare draw_prepare
float matrix_basis[4][4]
float matrix_offset[4][4]
float color_hi[4]
float color[4]
PointerRNA * ptr
float scale_basis
eWM_GizmoFlag flag
wmKeyMap * keymap
static NavigateGizmoInfo g_navigate_params[GZ_INDEX_TOTAL]
static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
#define GIZMO_MINI_OFFSET
#define GIZMO_MINI_SIZE
void VIEW3D_GGT_navigate(wmGizmoGroupType *gzgt)
static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *)
#define GIZMO_SIZE
@ GZ_INDEX_CAMERA_ON
@ GZ_INDEX_CAMERA_LOCK
@ GZ_INDEX_ROTATE
@ GZ_INDEX_CAMERA_UNLOCK
@ GZ_INDEX_CAMERA_OFF
#define GIZMO_OFFSET
static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
static void navigate_context_toggle_camera_lock_init(PointerRNA *ptr)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition wm_gizmo.cc:195
wmGizmo * WM_gizmo_new(const char *idname, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition wm_gizmo.cc:94
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition wm_gizmo.cc:303
PointerRNA * WM_gizmo_operator_set(wmGizmo *gz, int part_index, wmOperatorType *ot, IDProperty *properties)
Definition wm_gizmo.cc:203
wmKeyMap * WM_gizmo_keymap_generic_click_drag(wmWindowManager *wm)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)