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