Gizmo: add depth bias for 3D selection
[blender.git] / source / blender / windowmanager / gizmo / WM_gizmo_types.h
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2016 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup wm
22  *
23  * \name Gizmo Types
24  * \brief Gizmo defines for external use.
25  *
26  * Only included in WM_types.h and lower level files.
27  */
28
29 #ifndef __WM_GIZMO_TYPES_H__
30 #define __WM_GIZMO_TYPES_H__
31
32 #include "BLI_compiler_attrs.h"
33
34 struct wmGizmo;
35 struct wmGizmoGroup;
36 struct wmGizmoGroupType;
37 struct wmGizmoMapType;
38 struct wmGizmoProperty;
39 struct wmKeyConfig;
40
41 #include "DNA_listBase.h"
42
43 /* -------------------------------------------------------------------- */
44 /* Enum Typedef's */
45
46 /**
47  * #wmGizmo.state
48  */
49 typedef enum eWM_GizmoFlagState {
50   /** While hovered. */
51   WM_GIZMO_STATE_HIGHLIGHT = (1 << 0),
52   /** While dragging. */
53   WM_GIZMO_STATE_MODAL = (1 << 1),
54   WM_GIZMO_STATE_SELECT = (1 << 2),
55 } eWM_GizmoFlagState;
56
57 /**
58  * #wmGizmo.flag
59  * Flags for individual gizmos.
60  */
61 typedef enum eWM_GizmoFlag {
62   /** Draw *only* while hovering. */
63   WM_GIZMO_DRAW_HOVER = (1 << 0),
64   /** Draw while dragging. */
65   WM_GIZMO_DRAW_MODAL = (1 << 1),
66   /** Draw an indicator for the current value while dragging. */
67   WM_GIZMO_DRAW_VALUE = (1 << 2),
68   WM_GIZMO_HIDDEN = (1 << 3),
69   WM_GIZMO_HIDDEN_SELECT = (1 << 4),
70   /**
71    * When set 'scale_final' value also scales the offset.
72    * Use when offset is to avoid screen-space overlap instead of absolute positioning. */
73   WM_GIZMO_DRAW_OFFSET_SCALE = (1 << 5),
74   /**
75    * User should still use 'scale_final' for any handles and UI elements.
76    * This simply skips scale when calculating the final matrix.
77    * Needed when the gizmo needs to align with the interface underneath it. */
78   WM_GIZMO_DRAW_NO_SCALE = (1 << 6),
79   /**
80    * Hide the cursor and lock it's position while interacting with this gizmo.
81    */
82   WM_GIZMO_MOVE_CURSOR = (1 << 7),
83   /** Don't write into the depth buffer when selecting. */
84   WM_GIZMO_SELECT_BACKGROUND = (1 << 8),
85
86   /** Use the active tools operator properties when running as an operator. */
87   WM_GIZMO_OPERATOR_TOOL_INIT = (1 << 9),
88 } eWM_GizmoFlag;
89
90 /**
91  * #wmGizmoGroupType.flag
92  * Flags that influence the behavior of all gizmos in the group.
93  */
94 typedef enum eWM_GizmoFlagGroupTypeFlag {
95   /** Mark gizmo-group as being 3D */
96   WM_GIZMOGROUPTYPE_3D = (1 << 0),
97   /** Scale gizmos as 3D object that respects zoom (otherwise zoom independent draw size).
98    * note: currently only for 3D views, 2D support needs adding. */
99   WM_GIZMOGROUPTYPE_SCALE = (1 << 1),
100   /** Gizmos can be depth culled with scene objects (covered by other geometry - TODO) */
101   WM_GIZMOGROUPTYPE_DEPTH_3D = (1 << 2),
102   /** Gizmos can be selected. */
103   WM_GIZMOGROUPTYPE_SELECT = (1 << 3),
104   /** The gizmo group is to be kept (not removed on loading a new file for eg). */
105   WM_GIZMOGROUPTYPE_PERSISTENT = (1 << 4),
106   /** Show all other gizmos when interacting. */
107   WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL = (1 << 5),
108   /**
109    * When used with tool, only run when activating the tool,
110    * instead of linking the gizmo while the tool is active.
111    *
112    * \warning this option has some limitations, we might even re-implement this differently.
113    * Currently it's quite minimal so we can see how it works out.
114    * The main issue is controlling how a gizmo is activated with a tool
115    * when a tool can activate multiple operators based on the key-map.
116    * We could even move the options into the key-map item.
117    * ~ campbell. */
118   WM_GIZMOGROUPTYPE_TOOL_INIT = (1 << 6),
119 } eWM_GizmoFlagGroupTypeFlag;
120
121 /**
122  * #wmGizmoGroup.init_flag
123  */
124 typedef enum eWM_GizmoFlagGroupInitFlag {
125   /** Gizmo-group has been initialized. */
126   WM_GIZMOGROUP_INIT_SETUP = (1 << 0),
127   WM_GIZMOGROUP_INIT_REFRESH = (1 << 1),
128 } eWM_GizmoFlagGroupInitFlag;
129
130 /**
131  * #wmGizmoMapType.type_update_flag
132  * Gizmo-map type update flag
133  */
134 typedef enum eWM_GizmoFlagMapTypeUpdateFlag {
135   /** A new type has been added, needs to be initialized for all views. */
136   WM_GIZMOMAPTYPE_UPDATE_INIT = (1 << 0),
137   WM_GIZMOMAPTYPE_UPDATE_REMOVE = (1 << 1),
138
139   /** Needed because keymap may be registered before and after window initialization.
140    * So we need to keep track of keymap initialization separately. */
141   WM_GIZMOMAPTYPE_KEYMAP_INIT = (1 << 2),
142 } eWM_GizmoFlagMapTypeUpdateFlag;
143
144 /* -------------------------------------------------------------------- */
145 /* wmGizmo */
146
147 /**
148  * \brief Gizmo tweak flag.
149  * Bitflag passed to gizmo while tweaking.
150  *
151  * \note Gizmos are responsible for handling this #wmGizmo.modal callback!.
152  */
153 typedef enum {
154   /* Drag with extra precision (Shift). */
155   WM_GIZMO_TWEAK_PRECISE = (1 << 0),
156   /* Drag with snap enabled (Ctrl).  */
157   WM_GIZMO_TWEAK_SNAP = (1 << 1),
158 } eWM_GizmoFlagTweak;
159
160 #include "wm_gizmo_fn.h"
161
162 typedef struct wmGizmoOpElem {
163   struct wmOperatorType *type;
164   /** Operator properties if gizmo spawns and controls an operator,
165    * or owner pointer if gizmo spawns and controls a property. */
166   PointerRNA ptr;
167
168   bool is_redo;
169 } wmGizmoOpElem;
170
171 /* gizmos are set per region by registering them on gizmo-maps */
172 struct wmGizmo {
173   struct wmGizmo *next, *prev;
174
175   /** While we don't have a real type, use this to put type-like vars. */
176   const struct wmGizmoType *type;
177
178   /** Overrides 'type->modal' when set.
179    * Note that this is a workaround, remove if we can. */
180   wmGizmoFnModal custom_modal;
181
182   /** Pointer back to group this gizmo is in (just for quick access). */
183   struct wmGizmoGroup *parent_gzgroup;
184
185   void *py_instance;
186
187   /** Rna pointer to access properties. */
188   struct PointerRNA *ptr;
189
190   /** Flags that influence the behavior or how the gizmos are drawn. */
191   eWM_GizmoFlag flag;
192   /** State flags (active, highlighted, selected) */
193   eWM_GizmoFlagState state;
194
195   /** Optional ID for highlighting different parts of this gizmo.
196    * -1 when unset, otherwise a valid index. (Used as index to 'op_data'). */
197   int highlight_part;
198   /** For single click button gizmos, use a different part as a fallback, -1 when unused. */
199   int drag_part;
200
201   /** Distance to bias this gizmo above others when picking
202    * (in worldspace, scaled by the gizmo scale - when used). */
203   float select_bias;
204
205   /**
206    * Transformation of the gizmo in 2d or 3d space.
207    * - Matrix axis are expected to be unit length (scale is applied after).
208    * - Behavior when axis aren't orthogonal depends on each gizmo.
209    * - Typically the +Z is the primary axis for gizmos to use.
210    * - 'matrix[3]' must be used for location,
211    *   besides this it's up to the gizmos internal code how the
212    *   rotation components are used for drawing and interaction.
213    */
214
215   /** The space this gizmo is being modified in. */
216   float matrix_space[4][4];
217   /** Transformation of this gizmo. */
218   float matrix_basis[4][4];
219   /** Custom offset from origin. */
220   float matrix_offset[4][4];
221   /** Runtime property, set the scale while drawing on the viewport. */
222   float scale_final;
223   /** User defined scale, in addition to the original one. */
224   float scale_basis;
225   /** User defined width for line drawing. */
226   float line_width;
227   /** Gizmo colors (uses default fallbacks if not defined). */
228   float color[4], color_hi[4];
229
230   /** Data used during interaction. */
231   void *interaction_data;
232
233   /** Operator to spawn when activating the gizmo (overrides property editing),
234    * an array of items (aligned with #wmGizmo.highlight_part). */
235   wmGizmoOpElem *op_data;
236   int op_data_len;
237
238   struct IDProperty *properties;
239
240   /** Temporary data (assume dirty). */
241   union {
242     float f;
243   } temp;
244
245   /* over alloc target_properties after 'wmGizmoType.struct_size' */
246 };
247
248 /** Similar to #PropertyElemRNA, but has an identifier. */
249 typedef struct wmGizmoProperty {
250   const struct wmGizmoPropertyType *type;
251
252   PointerRNA ptr;
253   PropertyRNA *prop;
254   int index;
255
256   /* Optional functions for converting to/from RNA  */
257   struct {
258     wmGizmoPropertyFnGet value_get_fn;
259     wmGizmoPropertyFnSet value_set_fn;
260     wmGizmoPropertyFnRangeGet range_get_fn;
261     wmGizmoPropertyFnFree free_fn;
262     void *user_data;
263   } custom_func;
264 } wmGizmoProperty;
265
266 typedef struct wmGizmoPropertyType {
267   struct wmGizmoPropertyType *next, *prev;
268   /** #PropertyType, typically #PROP_FLOAT. */
269   int data_type;
270   int array_length;
271
272   /* index within 'wmGizmoType' */
273   int index_in_type;
274
275   /** over alloc. */
276   char idname[0];
277 } wmGizmoPropertyType;
278
279 /**
280  * Simple utility wrapper for storing a single gizmo as wmGizmoGroup.customdata (which gets freed).
281  */
282 typedef struct wmGizmoWrapper {
283   struct wmGizmo *gizmo;
284 } wmGizmoWrapper;
285
286 struct wmGizmoMapType_Params {
287   short spaceid;
288   short regionid;
289 };
290
291 typedef struct wmGizmoType {
292
293   const char *idname; /* MAX_NAME */
294
295   /** Set to 'sizeof(wmGizmo)' or larger for instances of this type,
296    * use so we can cant to other types without the hassle of a custom-data pointer. */
297   uint struct_size;
298
299   /** Initialize struct (calloc'd 'struct_size' region). */
300   wmGizmoFnSetup setup;
301
302   /** Draw gizmo. */
303   wmGizmoFnDraw draw;
304
305   /** Determines 3d intersection by rendering the gizmo in a selection routine. */
306   wmGizmoFnDrawSelect draw_select;
307
308   /** Determine if the mouse intersects with the gizmo.
309    * The calculation should be done in the callback itself, -1 for no seleciton. */
310   wmGizmoFnTestSelect test_select;
311
312   /** Handler used by the gizmo. Usually handles interaction tied to a gizmo type. */
313   wmGizmoFnModal modal;
314
315   /** Gizmo-specific handler to update gizmo attributes based on the property value. */
316   wmGizmoFnPropertyUpdate property_update;
317
318   /** Returns the final transformation which may be different from the 'matrix',
319    * depending on the gizmo.
320    * Notes:
321    * - Scale isn't applied (wmGizmo.scale/user_scale).
322    * - Offset isn't applied (wmGizmo.matrix_offset).
323    */
324   wmGizmoFnMatrixBasisGet matrix_basis_get;
325
326   /** Activate a gizmo state when the user clicks on it. */
327   wmGizmoFnInvoke invoke;
328
329   /** Called when gizmo tweaking is done - used to free data and reset property when cancelling. */
330   wmGizmoFnExit exit;
331
332   wmGizmoFnCursorGet cursor_get;
333
334   /** Called when gizmo selection state changes. */
335   wmGizmoFnSelectRefresh select_refresh;
336
337   /** Free data (not the gizmo it's self), use when the gizmo allocates it's own members. */
338   wmGizmoFnFree free;
339
340   /** RNA for properties. */
341   struct StructRNA *srna;
342
343   /** RNA integration. */
344   ExtensionRNA ext;
345
346   ListBase target_property_defs;
347   int target_property_defs_len;
348
349 } wmGizmoType;
350
351 /* -------------------------------------------------------------------- */
352 /* wmGizmoGroup */
353
354 /** Factory class for a gizmo-group type, gets called every time a new area is spawned. */
355 typedef struct wmGizmoGroupTypeRef {
356   struct wmGizmoGroupTypeRef *next, *prev;
357   struct wmGizmoGroupType *type;
358 } wmGizmoGroupTypeRef;
359
360 /* factory class for a gizmo-group type, gets called every time a new area is spawned */
361 typedef struct wmGizmoGroupType {
362   const char *idname; /* MAX_NAME */
363   /** Gizmo-group name - displayed in UI (keymap editor). */
364   const char *name;
365   char owner_id[64]; /* MAX_NAME */
366
367   /** Poll if gizmo-map should be visible. */
368   wmGizmoGroupFnPoll poll;
369   /** Initially create gizmos and set permanent data - stuff you only need to do once. */
370   wmGizmoGroupFnInit setup;
371   /** Refresh data, only called if recreate flag is set (WM_gizmomap_tag_refresh). */
372   wmGizmoGroupFnRefresh refresh;
373   /** Refresh data for drawing, called before each redraw. */
374   wmGizmoGroupFnDrawPrepare draw_prepare;
375   /** Initialize data for before invoke. */
376   wmGizmoGroupFnInvokePrepare invoke_prepare;
377
378   /** Keymap init callback for this gizmo-group (optional),
379    * will fall back to default tweak keymap when left NULL. */
380   wmGizmoGroupFnSetupKeymap setup_keymap;
381
382   /** Optionally subscribe to wmMsgBus events,
383    * these are calculated automatically from RNA properties,
384    * only needed if gizmos depend indirectly on properties. */
385   wmGizmoGroupFnMsgBusSubscribe message_subscribe;
386
387   /** Keymap created with callback from above. */
388   struct wmKeyMap *keymap;
389   /** Only for convenient removal. */
390   struct wmKeyConfig *keyconf;
391
392   /* Note: currently gizmo-group instances don't store properties,
393    * they're kept in the tool properties. */
394
395   /** RNA for properties. */
396   struct StructRNA *srna;
397
398   /** RNA integration. */
399   ExtensionRNA ext;
400
401   eWM_GizmoFlagGroupTypeFlag flag;
402
403   /** So we know which group type to update. */
404   eWM_GizmoFlagMapTypeUpdateFlag type_update_flag;
405
406   /** Same as gizmo-maps, so registering/unregistering goes to the correct region. */
407   struct wmGizmoMapType_Params gzmap_params;
408
409 } wmGizmoGroupType;
410
411 typedef struct wmGizmoGroup {
412   struct wmGizmoGroup *next, *prev;
413
414   struct wmGizmoGroupType *type;
415   ListBase gizmos;
416
417   struct wmGizmoMap *parent_gzmap;
418
419   /** Python stores the class instance here. */
420   void *py_instance;
421   /** Errors and warnings storage. */
422   struct ReportList *reports;
423
424   void *customdata;
425   /** For freeing customdata from above. */
426   void (*customdata_free)(void *);
427   eWM_GizmoFlagGroupInitFlag init_flag;
428 } wmGizmoGroup;
429
430 /* -------------------------------------------------------------------- */
431 /* wmGizmoMap */
432
433 /**
434  * Pass a value of this enum to #WM_gizmomap_draw to tell it what to draw.
435  */
436 typedef enum eWM_GizmoFlagMapDrawStep {
437   /** Draw 2D gizmo-groups (#WM_GIZMOGROUPTYPE_3D not set). */
438   WM_GIZMOMAP_DRAWSTEP_2D = 0,
439   /** Draw 3D gizmo-groups (#WM_GIZMOGROUPTYPE_3D set). */
440   WM_GIZMOMAP_DRAWSTEP_3D,
441 } eWM_GizmoFlagMapDrawStep;
442 #define WM_GIZMOMAP_DRAWSTEP_MAX 2
443
444 #endif /* __WM_GIZMO_TYPES_H__ */