Blender  V3.3
view3d_gizmo_navigate.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_math.h"
8 #include "BLI_utildefines.h"
9 
10 #include "BKE_context.h"
11 
12 #include "DNA_object_types.h"
13 
14 #include "ED_gizmo_library.h"
15 #include "ED_screen.h"
16 
17 #include "UI_interface.h"
18 #include "UI_resources.h"
19 
20 #include "MEM_guardedalloc.h"
21 
22 #include "RNA_access.h"
23 
24 #include "WM_api.h"
25 #include "WM_types.h"
26 
27 #include "view3d_intern.h" /* own include */
28 
29 /* -------------------------------------------------------------------- */
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 
45 enum {
49 
50  /* just buttons */
51  /* overlaps GZ_INDEX_ORTHO (switch between) */
55 
57 };
58 
59 struct NavigateGizmoInfo {
60  const char *opname;
61  const char *gizmo;
62  uint icon;
63 };
64 
66  {
67  .opname = "VIEW3D_OT_move",
68  .gizmo = "GIZMO_GT_button_2d",
69  .icon = ICON_VIEW_PAN,
70  },
71  {
72  .opname = "VIEW3D_OT_rotate",
73  .gizmo = "VIEW3D_GT_navigate_rotate",
74  .icon = ICON_NONE,
75  },
76  {
77  .opname = "VIEW3D_OT_zoom",
78  .gizmo = "GIZMO_GT_button_2d",
79  .icon = ICON_VIEW_ZOOM,
80  },
81  {
82  .opname = "VIEW3D_OT_view_persportho",
83  .gizmo = "GIZMO_GT_button_2d",
84  .icon = ICON_VIEW_PERSPECTIVE,
85  },
86  {
87  .opname = "VIEW3D_OT_view_persportho",
88  .gizmo = "GIZMO_GT_button_2d",
89  .icon = ICON_VIEW_ORTHO,
90  },
91  {
92  .opname = "VIEW3D_OT_view_camera",
93  .gizmo = "GIZMO_GT_button_2d",
94  .icon = ICON_VIEW_CAMERA,
95  },
96 };
97 
98 struct NavigateWidgetGroup {
100  /* Store the view state to check for changes. */
101  struct {
103  struct {
104  char is_persp;
105  bool is_camera;
106  char viewlock;
107  } rv3d;
108  } state;
109  int region_size[2];
110 };
111 
113 {
114  View3D *v3d = CTX_wm_view3d(C);
115  if ((((U.uiflag & USER_SHOW_GIZMO_NAVIGATE) == 0) &&
116  (U.mini_axis_type != USER_MINI_AXIS_TYPE_GIZMO)) ||
118  return false;
119  }
120  return true;
121 }
122 
123 static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
124 {
125  struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
126 
127  navgroup->region_size[0] = -1;
128  navgroup->region_size[1] = -1;
129 
130  wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true);
131  wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true);
132 
133  for (int i = 0; i < GZ_INDEX_TOTAL; i++) {
134  const struct NavigateGizmoInfo *info = &g_navigate_params[i];
135  navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, NULL);
136  wmGizmo *gz = navgroup->gz_array[i];
138 
139  if (i == GZ_INDEX_ROTATE) {
140  gz->color[3] = 0.0f;
141  copy_v3_fl(gz->color_hi, 0.5f);
142  gz->color_hi[3] = 0.5f;
143  }
144  else {
145  uchar icon_color[3];
146  UI_GetThemeColor3ubv(TH_TEXT, icon_color);
147  int color_tint, color_tint_hi;
148  if (icon_color[0] > 128) {
149  color_tint = -40;
150  color_tint_hi = 60;
151  gz->color[3] = 0.5f;
152  gz->color_hi[3] = 0.5f;
153  }
154  else {
155  color_tint = 60;
156  color_tint_hi = 60;
157  gz->color[3] = 0.5f;
158  gz->color_hi[3] = 0.75f;
159  }
160  UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color);
161  UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi);
162  }
163 
164  /* may be overwritten later */
165  gz->scale_basis = GIZMO_MINI_SIZE / 2.0f;
166  if (info->icon != ICON_NONE) {
167  PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
168  RNA_property_enum_set(gz->ptr, prop, info->icon);
169  RNA_enum_set(
171  }
172 
174  WM_gizmo_operator_set(gz, 0, ot, NULL);
175  }
176 
177  {
178  wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA];
179  WM_gizmo_operator_set(gz, 0, ot_view_camera, NULL);
180  }
181 
182  /* Click only buttons (not modal). */
183  {
184  int gz_ids[] = {GZ_INDEX_PERSP, GZ_INDEX_ORTHO, GZ_INDEX_CAMERA};
185  for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
186  wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
187  RNA_boolean_set(gz->ptr, "show_drag", false);
188  }
189  }
190 
191  /* Modal operators, don't use initial mouse location since we're clicking on a button. */
192  {
193  int gz_ids[] = {GZ_INDEX_MOVE, GZ_INDEX_ROTATE, GZ_INDEX_ZOOM};
194  for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
195  wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
196  wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
197  RNA_boolean_set(&gzop->ptr, "use_cursor_init", false);
198  }
199  }
200 
201  {
202  wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE];
203  gz->scale_basis = GIZMO_SIZE / 2.0f;
204  const char mapping[6] = {
211  };
212 
213  for (int part_index = 0; part_index < 6; part_index += 1) {
214  PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, NULL);
215  RNA_enum_set(ptr, "type", mapping[part_index]);
216  }
217 
218  /* When dragging an axis, use this instead. */
221  gz->drag_part = 0;
222  }
223 
224  gzgroup->customdata = navgroup;
225 }
226 
228 {
229  struct NavigateWidgetGroup *navgroup = gzgroup->customdata;
230  ARegion *region = CTX_wm_region(C);
231  const RegionView3D *rv3d = region->regiondata;
232 
233  for (int i = 0; i < 3; i++) {
234  copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
235  }
236 
237  const rcti *rect_visible = ED_region_visible_rect(region);
238 
239  /* Ensure types match so bits are never lost on assignment. */
240  CHECK_TYPE_PAIR(navgroup->state.rv3d.viewlock, rv3d->viewlock);
241 
242  if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) &&
243  (navgroup->state.rect_visible.ymax == rect_visible->ymax) &&
244  (navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
245  (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
246  (navgroup->state.rv3d.viewlock == RV3D_LOCK_FLAGS(rv3d))) {
247  return;
248  }
249 
250  navgroup->state.rect_visible = *rect_visible;
251  navgroup->state.rv3d.is_persp = rv3d->is_persp;
252  navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
253  navgroup->state.rv3d.viewlock = RV3D_LOCK_FLAGS(rv3d);
254 
255  const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0;
256  const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO);
257  const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_DPI_FAC;
258  const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_DPI_FAC;
259  const float co_rotate[2] = {
260  rect_visible->xmax - icon_offset,
261  rect_visible->ymax - icon_offset,
262  };
263 
264  float icon_offset_from_axis = 0.0f;
265  switch ((eUserpref_MiniAxisType)U.mini_axis_type) {
267  icon_offset_from_axis = icon_offset * 2.1f;
268  break;
270  icon_offset_from_axis = (UI_UNIT_X * 2.5) + ((U.rvisize * U.pixelsize * 2.0f));
271  break;
273  icon_offset_from_axis = icon_offset_mini * 0.75f;
274  break;
275  }
276 
277  const float co[2] = {
278  roundf(rect_visible->xmax - icon_offset_mini * 0.75f),
279  roundf(rect_visible->ymax - icon_offset_from_axis),
280  };
281 
282  wmGizmo *gz;
283 
284  for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) {
285  gz = navgroup->gz_array[i];
287  }
288 
289  if (show_rotate_gizmo) {
290  gz = navgroup->gz_array[GZ_INDEX_ROTATE];
291  gz->matrix_basis[3][0] = roundf(co_rotate[0]);
292  gz->matrix_basis[3][1] = roundf(co_rotate[1]);
294  }
295 
296  if (show_navigate) {
297  int icon_mini_slot = 0;
299  gz = navgroup->gz_array[GZ_INDEX_ZOOM];
300  gz->matrix_basis[3][0] = roundf(co[0]);
301  gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
303  }
304 
305  if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION) == 0) {
306  gz = navgroup->gz_array[GZ_INDEX_MOVE];
307  gz->matrix_basis[3][0] = roundf(co[0]);
308  gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
310  }
311 
312  if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
313  gz = navgroup->gz_array[GZ_INDEX_CAMERA];
314  gz->matrix_basis[3][0] = roundf(co[0]);
315  gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
317 
318  if (navgroup->state.rv3d.is_camera == false) {
319  gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO];
320  gz->matrix_basis[3][0] = roundf(co[0]);
321  gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
323  }
324  }
325  }
326 }
327 
329 {
330  gzgt->name = "View3D Navigate";
331  gzgt->idname = "VIEW3D_GGT_navigate";
332 
335 
339 }
340 
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
#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
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define ARRAY_SIZE(arr)
#define UNUSED(x)
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 RV3D_LOCK_FLAGS(rv3d)
#define RV3D_CAMOB
#define RV3D_VIEW_BACK
@ RV3D_LOCK_ROTATION
@ RV3D_LOCK_LOCATION
@ RV3D_LOCK_ZOOM_AND_DOLLY
@ V3D_GIZMO_HIDE
@ V3D_GIZMO_HIDE_NAVIGATE
#define RV3D_VIEW_BOTTOM
#define RV3D_VIEW_LEFT
#define RV3D_VIEW_RIGHT
#define RV3D_VIEW_TOP
#define RV3D_VIEW_FRONT
@ ED_GIZMO_BUTTON_SHOW_BACKDROP
@ ED_GIZMO_BUTTON_SHOW_OUTLINE
const rcti * ED_region_visible_rect(ARegion *region)
Definition: area.c:3763
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
#define UI_DPI_FAC
Definition: UI_interface.h:305
#define UI_UNIT_X
@ TH_HEADER
Definition: UI_resources.h:50
@ TH_TEXT
Definition: UI_resources.h:42
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
Definition: resources.c:1191
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
Definition: resources.c:1323
@ 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.c:31
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3421
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
void * regiondata
wmGizmo * gz_array[GZ_INDEX_TOTAL]
struct NavigateWidgetGroup::@564::@565 rv3d
struct NavigateWidgetGroup::@445 state
char gizmo_flag
int ymax
Definition: DNA_vec_types.h:64
int xmax
Definition: DNA_vec_types.h:63
wmGizmoGroupFnInit setup
const char * idname
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
const char * name
wmGizmoGroupFnDrawPrepare draw_prepare
PointerRNA ptr
float matrix_basis[4][4]
float matrix_offset[4][4]
float color_hi[4]
struct wmKeyMap * keymap
float color[4]
struct PointerRNA * ptr
float scale_basis
eWM_GizmoFlag flag
static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
#define GIZMO_MINI_OFFSET
#define GIZMO_MINI_SIZE
static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
void VIEW3D_GGT_navigate(wmGizmoGroupType *gzgt)
#define GIZMO_SIZE
#define GIZMO_OFFSET
static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
static struct NavigateGizmoInfo g_navigate_params[GZ_INDEX_TOTAL]
@ GZ_INDEX_ZOOM
@ GZ_INDEX_MOVE
@ GZ_INDEX_TOTAL
@ GZ_INDEX_ORTHO
@ GZ_INDEX_ROTATE
@ GZ_INDEX_PERSP
@ GZ_INDEX_CAMERA
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
PointerRNA * WM_gizmo_operator_set(wmGizmo *gz, int part_index, wmOperatorType *ot, IDProperty *properties)
Definition: wm_gizmo.c:203
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition: wm_gizmo.c:304
struct wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition: wm_gizmo.c:195
wmGizmo * WM_gizmo_new(const char *idname, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition: wm_gizmo.c:94
struct wmKeyMap * WM_gizmo_keymap_generic_click_drag(wmWindowManager *wm)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)