Blender V5.0
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
8
9#include "BLI_math_vector.h"
10#include "BLI_utildefines.h"
11
12#include "BKE_context.hh"
13
14#include "ED_gizmo_library.hh"
15#include "ED_screen.hh"
16
17#include "UI_interface.hh"
18#include "UI_resources.hh"
19
20#include "MEM_guardedalloc.h"
21
22#include "RNA_access.hh"
23
24#include "WM_api.hh"
25#include "WM_types.hh"
26
27#include "view3d_intern.hh" /* own include */
28
29/* -------------------------------------------------------------------- */
32
33/* Size of main icon. */
34#define GIZMO_SIZE U.gizmo_size_navigate_v3d
35
36/* Main gizmo offset from screen edges in unscaled pixels. */
37#define GIZMO_OFFSET 10.0f
38
39/* Width of smaller buttons in unscaled pixels. */
40#define GIZMO_MINI_SIZE 28.0f
41
42/* Margin around the smaller buttons. */
43#define GIZMO_MINI_OFFSET 2.0f
44
45namespace {
46
47enum {
48 GZ_INDEX_MOVE = 0,
49 GZ_INDEX_ROTATE = 1,
50 GZ_INDEX_ZOOM = 2,
51
52 /* just buttons */
53 /* overlaps GZ_INDEX_ORTHO (switch between) */
54 GZ_INDEX_PERSP = 3,
55 GZ_INDEX_ORTHO = 4,
56
57 GZ_INDEX_CAMERA_OFF = 5,
58 GZ_INDEX_CAMERA_ON = 6,
59
60 GZ_INDEX_CAMERA_LOCK = 7,
61 GZ_INDEX_CAMERA_UNLOCK = 8,
62
63 GZ_INDEX_TOTAL = 9,
64};
65
66struct NavigateGizmoInfo {
67 const char *opname;
68 const char *gizmo;
69 uint icon;
70 void (*op_prop_fn)(PointerRNA *ptr);
71};
72
73struct NavigateWidgetGroup {
74 wmGizmo *gz_array[GZ_INDEX_TOTAL];
75 /* Store the view state to check for changes. */
76 struct {
77 rcti rect_visible;
78 struct {
79 char is_persp;
80 bool is_camera;
81 char viewlock;
82 char cameralock;
83 } rv3d;
84 } state;
85};
86
87} // namespace
88
90{
91 RNA_string_set(ptr, "data_path", "space_data.lock_camera");
92}
93
94static NavigateGizmoInfo g_navigate_params[GZ_INDEX_TOTAL] = {
95 {
96 "VIEW3D_OT_move",
97 "GIZMO_GT_button_2d",
98 ICON_VIEW_PAN,
99 nullptr,
100 },
101 {
102 "VIEW3D_OT_rotate",
103 "VIEW3D_GT_navigate_rotate",
104 ICON_NONE,
105 nullptr,
106 },
107 {
108 "VIEW3D_OT_zoom",
109 "GIZMO_GT_button_2d",
110 ICON_VIEW_ZOOM,
111 nullptr,
112 },
113 {
114 "VIEW3D_OT_view_persportho",
115 "GIZMO_GT_button_2d",
116 ICON_VIEW_PERSPECTIVE,
117 nullptr,
118 },
119 {
120 "VIEW3D_OT_view_persportho",
121 "GIZMO_GT_button_2d",
122 ICON_VIEW_ORTHO,
123 nullptr,
124 },
125 {
126 "VIEW3D_OT_view_camera",
127 "GIZMO_GT_button_2d",
128 ICON_VIEW_CAMERA_UNSELECTED,
129 nullptr,
130 },
131 {
132 "VIEW3D_OT_view_camera",
133 "GIZMO_GT_button_2d",
134 ICON_VIEW_CAMERA,
135 nullptr,
136 },
137 {
138 "WM_OT_context_toggle",
139 "GIZMO_GT_button_2d",
140 ICON_VIEW_LOCKED,
142 },
143 {
144 "WM_OT_context_toggle",
145 "GIZMO_GT_button_2d",
146 ICON_VIEW_UNLOCKED,
148 },
149};
150
152{
153 View3D *v3d = CTX_wm_view3d(C);
154 if ((((U.uiflag & USER_SHOW_GIZMO_NAVIGATE) == 0) &&
155 (U.mini_axis_type != USER_MINI_AXIS_TYPE_GIZMO)) ||
157 {
158 return false;
159 }
160 return true;
161}
162
164{
165 NavigateWidgetGroup *navgroup = MEM_callocN<NavigateWidgetGroup>(__func__);
166
167 wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true);
168 wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true);
169
170 for (int i = 0; i < GZ_INDEX_TOTAL; i++) {
171 const NavigateGizmoInfo *info = &g_navigate_params[i];
172 navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, nullptr);
173 wmGizmo *gz = navgroup->gz_array[i];
175
176 if (i == GZ_INDEX_ROTATE) {
177 gz->color[3] = 0.0f;
178 copy_v3_fl(gz->color_hi, 0.5f);
179 gz->color_hi[3] = 0.5f;
180 }
181 else {
182 uchar icon_color[3];
183 UI_GetThemeColor3ubv(TH_TEXT, icon_color);
184 int color_tint, color_tint_hi;
185 if (icon_color[0] > 128) {
186 color_tint = -40;
187 color_tint_hi = 60;
188 gz->color[3] = 0.5f;
189 gz->color_hi[3] = 0.5f;
190 }
191 else {
192 color_tint = 60;
193 color_tint_hi = 60;
194 gz->color[3] = 0.5f;
195 gz->color_hi[3] = 0.75f;
196 }
197 UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color);
198 UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi);
199 }
200
201 /* may be overwritten later */
202 gz->scale_basis = GIZMO_MINI_SIZE / 2.0f;
203 if (info->icon != ICON_NONE) {
204 PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
205 RNA_property_enum_set(gz->ptr, prop, info->icon);
208 }
209
210 wmOperatorType *ot = WM_operatortype_find(info->opname, true);
211#ifndef WITH_PYTHON
212 if (ot != nullptr)
213#endif
214 {
215 PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot, nullptr);
216 if (info->op_prop_fn != nullptr) {
217 info->op_prop_fn(ptr);
218 }
219 }
220 }
221
222 {
223 wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA_OFF];
224 WM_gizmo_operator_set(gz, 0, ot_view_camera, nullptr);
225 }
226 {
227 wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA_ON];
228 WM_gizmo_operator_set(gz, 0, ot_view_camera, nullptr);
229 }
230
231 /* Click only buttons (not modal). */
232 {
233 int gz_ids[] = {GZ_INDEX_PERSP,
234 GZ_INDEX_ORTHO,
235 GZ_INDEX_CAMERA_OFF,
236 GZ_INDEX_CAMERA_ON,
237 GZ_INDEX_CAMERA_LOCK,
238 GZ_INDEX_CAMERA_UNLOCK};
239 for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
240 wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
241 RNA_boolean_set(gz->ptr, "show_drag", false);
242 }
243 }
244
245 /* Modal operators, don't use initial mouse location since we're clicking on a button. */
246 {
247 int gz_ids[] = {GZ_INDEX_MOVE, GZ_INDEX_ROTATE, GZ_INDEX_ZOOM};
248 for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
249 wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
251 RNA_boolean_set(&gzop->ptr, "use_cursor_init", false);
252 }
253 }
254
255 {
256 wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE];
257 gz->scale_basis = GIZMO_SIZE / 2.0f;
258 const char mapping[6] = {
265 };
266
267 for (int part_index = 0; part_index < 6; part_index += 1) {
268 PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, nullptr);
269 RNA_enum_set(ptr, "type", mapping[part_index]);
270 }
271
272 /* When dragging an axis, use this instead. */
275 gz->drag_part = 0;
276 }
277
278 gzgroup->customdata = navgroup;
279}
280
282{
283 NavigateWidgetGroup *navgroup = static_cast<NavigateWidgetGroup *>(gzgroup->customdata);
284 ARegion *region = CTX_wm_region(C);
285 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
286 const View3D *v3d = CTX_wm_view3d(C);
287
288 for (int i = 0; i < 3; i++) {
289 copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
290 }
291
292 const rcti *rect_visible = ED_region_visible_rect(region);
293
294 /* Ensure types match so bits are never lost on assignment. */
295 CHECK_TYPE_PAIR(navgroup->state.rv3d.viewlock, rv3d->viewlock);
296
297 if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) &&
298 (navgroup->state.rect_visible.ymax == rect_visible->ymax) &&
299 (navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
300 (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
301 (navgroup->state.rv3d.cameralock == (v3d->flag2 & V3D_LOCK_CAMERA)) &&
302 (navgroup->state.rv3d.viewlock == RV3D_LOCK_FLAGS(rv3d)))
303 {
304 return;
305 }
306
307 navgroup->state.rect_visible = *rect_visible;
308 navgroup->state.rv3d.is_persp = rv3d->is_persp;
309 navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
310 navgroup->state.rv3d.viewlock = RV3D_LOCK_FLAGS(rv3d);
311 navgroup->state.rv3d.cameralock = v3d->flag2 & V3D_LOCK_CAMERA;
312
313 const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0;
314 const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO);
315 const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_SCALE_FAC;
316 const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_SCALE_FAC;
317 const float co_rotate[2] = {
318 rect_visible->xmax - icon_offset,
319 rect_visible->ymax - icon_offset,
320 };
321
322 float icon_offset_from_axis = 0.0f;
323 switch ((eUserpref_MiniAxisType)U.mini_axis_type) {
325 icon_offset_from_axis = icon_offset * 2.1f;
326 break;
328 icon_offset_from_axis = (UI_UNIT_X * 2.5) + (U.rvisize * U.pixelsize * 2.0f);
329 break;
331 icon_offset_from_axis = icon_offset_mini * 0.75f;
332 break;
333 }
334
335 const float co[2] = {
336 roundf(rect_visible->xmax - icon_offset_mini * 0.75f),
337 roundf(rect_visible->ymax - icon_offset_from_axis),
338 };
339
340 wmGizmo *gz;
341
342 for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) {
343 gz = navgroup->gz_array[i];
345 }
346
347 if (show_rotate_gizmo) {
348 gz = navgroup->gz_array[GZ_INDEX_ROTATE];
349 gz->matrix_basis[3][0] = roundf(co_rotate[0]);
350 gz->matrix_basis[3][1] = roundf(co_rotate[1]);
352 }
353
354 if (show_navigate) {
355 int icon_mini_slot = 0;
356 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY) == 0) {
357 gz = navgroup->gz_array[GZ_INDEX_ZOOM];
358 gz->matrix_basis[3][0] = roundf(co[0]);
359 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
361 }
362
363 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION) == 0) {
364 gz = navgroup->gz_array[GZ_INDEX_MOVE];
365 gz->matrix_basis[3][0] = roundf(co[0]);
366 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
368 }
369
370 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
371 gz = navgroup
372 ->gz_array[(rv3d->persp == RV3D_CAMOB) ? GZ_INDEX_CAMERA_ON : GZ_INDEX_CAMERA_OFF];
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 if (navgroup->state.rv3d.is_camera == false) {
378 gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO];
379 gz->matrix_basis[3][0] = roundf(co[0]);
380 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
382 }
383 }
384
385 if (navgroup->state.rv3d.is_camera == true) {
386 gz = navgroup->gz_array[(v3d->flag2 & V3D_LOCK_CAMERA) ? GZ_INDEX_CAMERA_LOCK :
387 GZ_INDEX_CAMERA_UNLOCK];
388 gz->matrix_basis[3][0] = roundf(co[0]);
389 gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
391 }
392 }
393}
394
396{
397 gzgt->name = "View3D Navigate";
398 gzgt->idname = "VIEW3D_GGT_navigate";
399
402
406}
407
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)
#define UI_SCALE_FAC
@ USER_SHOW_GIZMO_NAVIGATE
eUserpref_MiniAxisType
@ USER_MINI_AXIS_TYPE_GIZMO
@ USER_MINI_AXIS_TYPE_MINIMAL
@ USER_MINI_AXIS_TYPE_NONE
@ V3D_LOCK_CAMERA
@ V3D_GIZMO_HIDE
@ V3D_GIZMO_HIDE_NAVIGATE
@ RV3D_VIEW_FRONT
@ RV3D_VIEW_BOTTOM
@ RV3D_VIEW_LEFT
@ RV3D_VIEW_RIGHT
@ RV3D_VIEW_TOP
@ RV3D_VIEW_BACK
#define RV3D_LOCK_FLAGS(rv3d)
@ RV3D_CAMOB
@ RV3D_LOCK_ROTATION
@ RV3D_LOCK_LOCATION
@ RV3D_LOCK_ZOOM_AND_DOLLY
@ ED_GIZMO_BUTTON_SHOW_BACKDROP
@ ED_GIZMO_BUTTON_SHOW_OUTLINE
const rcti * ED_region_visible_rect(ARegion *region)
Definition area.cc:4301
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#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
#define U
#define roundf(x)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
static ulong state[N]
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 * regiondata
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
i
Definition text_draw.cc:230
static void WIDGETGROUP_navigate_setup(const bContext *, wmGizmoGroup *gzgroup)
static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *)
#define GIZMO_SIZE
static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
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_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:4238
wmOperatorType * ot
Definition wm_files.cc:4237
wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition wm_gizmo.cc:195
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition wm_gizmo.cc:307
PointerRNA * WM_gizmo_operator_set(wmGizmo *gz, int part_index, wmOperatorType *ot, IDProperty *properties)
Definition wm_gizmo.cc:203
wmGizmo * WM_gizmo_new(const StringRef idname, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition wm_gizmo.cc:98
wmKeyMap * WM_gizmo_keymap_generic_press_drag(wmWindowManager *wm)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)