Blender V4.3
wm_operators.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12#include <algorithm>
13#include <cctype>
14#include <cerrno>
15#include <cfloat>
16#include <cstddef>
17#include <cstdio>
18#include <cstring>
19#include <iostream>
20#include <sstream>
21
22#include <fmt/format.h>
23
24#ifdef WIN32
25# include "GHOST_C-api.h"
26#endif
27
28#include "MEM_guardedalloc.h"
29
30#include "CLG_log.h"
31
32#include "DNA_ID.h"
33#include "DNA_armature_types.h"
34#include "DNA_brush_types.h"
35#include "DNA_object_types.h"
36#include "DNA_scene_types.h"
37#include "DNA_screen_types.h"
38#include "DNA_userdef_types.h"
40
41#include "BLT_translation.hh"
42
43#include "BLI_blenlib.h"
44#include "BLI_dial_2d.h"
45#include "BLI_math_matrix.hh"
46#include "BLI_math_rotation.h"
48#include "BLI_string_utils.hh"
49#include "BLI_time.h"
50#include "BLI_utildefines.h"
51
52#include "BKE_anim_data.hh"
53#include "BKE_brush.hh"
54#include "BKE_colortools.hh"
55#include "BKE_context.hh"
56#include "BKE_global.hh"
57#include "BKE_idprop.hh"
58#include "BKE_image.hh"
59#include "BKE_image_format.hh"
60#include "BKE_lib_id.hh"
61#include "BKE_lib_query.hh"
62#include "BKE_main.hh"
63#include "BKE_material.h"
64#include "BKE_preview_image.hh"
65#include "BKE_report.hh"
66#include "BKE_scene.hh"
67#include "BKE_screen.hh" /* #BKE_ST_MAXNAME. */
68#include "BKE_unit.hh"
69
70#include "BKE_idtype.hh"
71
72#include "BLF_api.hh"
73
74#include "GPU_immediate.hh"
75#include "GPU_immediate_util.hh"
76#include "GPU_matrix.hh"
77#include "GPU_state.hh"
78
79#include "IMB_imbuf_types.hh"
80
81#include "ED_fileselect.hh"
82#include "ED_gpencil_legacy.hh"
83#include "ED_grease_pencil.hh"
84#include "ED_numinput.hh"
85#include "ED_screen.hh"
86#include "ED_undo.hh"
87#include "ED_view3d.hh"
88
90
91#include "RNA_access.hh"
92#include "RNA_define.hh"
93#include "RNA_enum_types.hh"
94#include "RNA_path.hh"
95#include "RNA_prototypes.hh"
96
97#include "UI_interface.hh"
98#include "UI_interface_icons.hh"
99#include "UI_resources.hh"
100
101#include "WM_api.hh"
102#include "WM_types.hh"
103
104#include "wm.hh"
105#include "wm_draw.hh"
106#include "wm_event_system.hh"
107#include "wm_event_types.hh"
108#include "wm_files.hh"
109#include "wm_window.hh"
110#ifdef WITH_XR_OPENXR
111# include "wm_xr.hh"
112#endif
113
114#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
115
116/* -------------------------------------------------------------------- */
120#define OP_BL_SEP_STRING "_OT_"
121#define OP_BL_SEP_LEN 4
122
123#define OP_PY_SEP_CHAR '.'
124#define OP_PY_SEP_LEN 1
125
126/* Difference between python 'identifier' and BL/C code one ("." separator replaced by "_OT_"),
127 * and final `\0` char. */
128#define OP_MAX_PY_IDNAME (OP_MAX_TYPENAME - OP_BL_SEP_LEN + OP_PY_SEP_LEN - 1)
129
130size_t WM_operator_py_idname(char *dst, const char *src)
131{
132 const char *sep = strstr(src, OP_BL_SEP_STRING);
133 if (sep) {
134 const size_t sep_offset = size_t(sep - src);
135
136 /* NOTE: we use ascii `tolower` instead of system `tolower`, because the
137 * latter depends on the locale, and can lead to `idname` mismatch. */
138 memcpy(dst, src, sep_offset);
139 BLI_str_tolower_ascii(dst, sep_offset);
140
141 dst[sep_offset] = OP_PY_SEP_CHAR;
142 return BLI_strncpy_rlen(dst + (sep_offset + OP_PY_SEP_LEN),
143 sep + OP_BL_SEP_LEN,
144 OP_MAX_TYPENAME - sep_offset - OP_PY_SEP_LEN) +
145 (sep_offset + OP_PY_SEP_LEN);
146 }
147 /* Should not happen but support just in case. */
148 return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
149}
150
151size_t WM_operator_bl_idname(char *dst, const char *src)
152{
153 const size_t from_len = size_t(strlen(src));
154
155 const char *sep = strchr(src, OP_PY_SEP_CHAR);
156 if (sep && (from_len <= OP_MAX_PY_IDNAME)) {
157 const size_t sep_offset = size_t(sep - src);
158 memcpy(dst, src, sep_offset);
159 BLI_str_toupper_ascii(dst, sep_offset);
160
161 memcpy(dst + sep_offset, OP_BL_SEP_STRING, OP_BL_SEP_LEN);
162 BLI_strncpy(dst + sep_offset + OP_BL_SEP_LEN,
163 sep + OP_PY_SEP_LEN,
164 from_len - sep_offset - OP_PY_SEP_LEN + 1);
165 return from_len + OP_BL_SEP_LEN - OP_PY_SEP_LEN;
166 }
167 /* Should not happen but support just in case. */
168 return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
169}
170
171bool WM_operator_bl_idname_is_valid(const char *idname)
172{
173 const char *sep = strstr(idname, OP_BL_SEP_STRING);
174 /* Separator missing or at string beginning/end. */
175 if ((sep == nullptr) || (sep == idname) || (sep[OP_BL_SEP_LEN] == '\0')) {
176 return false;
177 }
178
179 for (const char *ch = idname; ch < sep; ch++) {
180 if ((*ch >= 'A' && *ch <= 'Z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
181 continue;
182 }
183 return false;
184 }
185
186 for (const char *ch = sep + OP_BL_SEP_LEN; *ch; ch++) {
187 if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
188 continue;
189 }
190 return false;
191 }
192 return true;
193}
194
196 const char *classname,
197 const char *idname)
198{
199 const char *ch = idname;
200 int dot = 0;
201 int i;
202 for (i = 0; *ch; i++, ch++) {
203 if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
204 /* Pass. */
205 }
206 else if (*ch == '.') {
207 if (ch == idname || (*(ch + 1) == '\0')) {
208 BKE_reportf(reports,
209 RPT_ERROR,
210 "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
211 classname,
212 idname,
213 i);
214 return false;
215 }
216 dot++;
217 }
218 else {
219 BKE_reportf(reports,
220 RPT_ERROR,
221 "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
222 classname,
223 idname,
224 i);
225 return false;
226 }
227 }
228
229 if (i > OP_MAX_PY_IDNAME) {
230 BKE_reportf(reports,
231 RPT_ERROR,
232 "Registering operator class: '%s', invalid bl_idname '%s', "
233 "is too long, maximum length is %d",
234 classname,
235 idname,
237 return false;
238 }
239
240 if (dot != 1) {
242 reports,
243 RPT_ERROR,
244 "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
245 classname,
246 idname);
247 return false;
248 }
249 return true;
250}
251
253 wmOperator *op,
254 const bool all_args,
255 const bool macro_args,
257 PointerRNA *opptr)
258{
259 char idname_py[OP_MAX_TYPENAME];
260
261 /* For building the string. */
262 std::stringstream ss;
263
264 /* Arbitrary, but can get huge string with stroke painting otherwise. */
265 int max_prop_length = 10;
266
267 WM_operator_py_idname(idname_py, ot->idname);
268 ss << "bpy.ops." << idname_py << "(";
269
270 if (op && op->macro.first) {
271 /* Special handling for macros, else we only get default values in this case... */
272 wmOperator *opm;
273 bool first_op = true;
274
275 opm = static_cast<wmOperator *>(macro_args ? op->macro.first : nullptr);
276
277 for (; opm; opm = opm->next) {
278 PointerRNA *opmptr = opm->ptr;
279 PointerRNA opmptr_default;
280 if (opmptr == nullptr) {
281 WM_operator_properties_create_ptr(&opmptr_default, opm->type);
282 opmptr = &opmptr_default;
283 }
284
285 std::string string_args = RNA_pointer_as_string_id(C, opmptr);
286 if (first_op) {
287 ss << opm->type->idname << '=' << string_args;
288 first_op = false;
289 }
290 else {
291 ss << ", " << opm->type->idname << '=' << string_args;
292 }
293
294 if (opmptr == &opmptr_default) {
295 WM_operator_properties_free(&opmptr_default);
296 }
297 }
298 }
299 else {
300 /* Only to get the original props for comparisons. */
301 PointerRNA opptr_default;
302 const bool macro_args_test = ot->macro.first ? macro_args : true;
303
304 if (opptr == nullptr) {
305 WM_operator_properties_create_ptr(&opptr_default, ot);
306 opptr = &opptr_default;
307 }
308
310 C, opptr, false, all_args, macro_args_test, max_prop_length);
311
312 if (opptr == &opptr_default) {
313 WM_operator_properties_free(&opptr_default);
314 }
315 }
316
317 ss << ')';
318
319 return ss.str();
320}
321
323 wmOperator *op,
324 const bool all_args,
325 const bool macro_args)
326{
327 return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr);
328}
329
330std::string WM_operator_pystring_abbreviate(std::string str, int str_len_max)
331{
332 const int str_len = str.size();
333 const size_t parens_start = str.find('(');
334 if (parens_start == std::string::npos) {
335 return str;
336 }
337
338 const size_t parens_end = str.find(parens_start + 1, ')');
339 if (parens_end == std::string::npos) {
340 return str;
341 }
342
343 const int parens_len = parens_end - parens_start;
344 if (parens_len <= str_len_max) {
345 return str;
346 }
347
348 /* Truncate after the first comma. */
349 const size_t comma_first = str.find(parens_start, ',');
350 if (comma_first == std::string::npos) {
351 return str;
352 }
353 const char end_str[] = " ... )";
354 const int end_str_len = sizeof(end_str) - 1;
355
356 /* Leave a place for the first argument. */
357 const int new_str_len = (comma_first - parens_start) + 1;
358
359 if (str_len < new_str_len + parens_start + end_str_len + 1) {
360 return str;
361 }
362
363 return str.substr(0, comma_first) + end_str;
364}
365
366/* Return nullptr if no match is found. */
367#if 0
368static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr, bool *r_is_id)
369{
370 /* Loop over all context items and do 2 checks
371 *
372 * - See if the pointer is in the context.
373 * - See if the pointers ID is in the context.
374 */
375
376 /* Don't get from the context store since this is normally
377 * set only for the UI and not usable elsewhere. */
378 ListBase lb = CTX_data_dir_get_ex(C, false, true, true);
379 LinkData *link;
380
381 const char *member_found = nullptr;
382 const char *member_id = nullptr;
383 bool member_found_is_id = false;
384
385 for (link = lb.first; link; link = link->next) {
386 const char *identifier = link->data;
387 PointerRNA ctx_item_ptr = {{0}};
388 // CTX_data_pointer_get(C, identifier); /* XXX, this isn't working. */
389
390 if (ctx_item_ptr.type == nullptr) {
391 continue;
392 }
393
394 if (ptr->owner_id == ctx_item_ptr.owner_id) {
395 const bool is_id = RNA_struct_is_ID(ctx_item_ptr.type);
396 if ((ptr->data == ctx_item_ptr.data) && (ptr->type == ctx_item_ptr.type)) {
397 /* Found! */
398 member_found = identifier;
399 member_found_is_id = is_id;
400 break;
401 }
402 if (is_id) {
403 /* Found a reference to this ID, so fallback to it if there is no direct reference. */
404 member_id = identifier;
405 }
406 }
407 }
408 BLI_freelistN(&lb);
409
410 if (member_found) {
411 *r_is_id = member_found_is_id;
412 return member_found;
413 }
414 else if (member_id) {
415 *r_is_id = true;
416 return member_id;
417 }
418 else {
419 return nullptr;
420 }
421}
422
423#else
424
425/* Use hard coded checks for now. */
426
441static const char *wm_context_member_from_ptr(const bContext *C,
442 const PointerRNA *ptr,
443 bool *r_is_id)
444{
445 const char *member_id = nullptr;
446 bool is_id = false;
447
448# define CTX_TEST_PTR_ID(C, member, idptr) \
449 { \
450 const char *ctx_member = member; \
451 PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
452 if (ctx_item_ptr.owner_id == idptr) { \
453 member_id = ctx_member; \
454 is_id = true; \
455 break; \
456 } \
457 } \
458 (void)0
459
460# define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \
461 { \
462 const char *ctx_member = member; \
463 const char *ctx_member_full = member_full; \
464 PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
465 if (ctx_item_ptr.owner_id && (ID *)cast(ctx_item_ptr.owner_id) == idptr) { \
466 member_id = ctx_member_full; \
467 is_id = true; \
468 break; \
469 } \
470 } \
471 (void)0
472
473# define TEST_PTR_DATA_TYPE(member, rna_type, rna_ptr, dataptr_cmp) \
474 { \
475 const char *ctx_member = member; \
476 if (RNA_struct_is_a((rna_ptr)->type, &(rna_type)) && (rna_ptr)->data == (dataptr_cmp)) { \
477 member_id = ctx_member; \
478 break; \
479 } \
480 } \
481 (void)0
482
483/* A version of #TEST_PTR_DATA_TYPE that calls `CTX_data_pointer_get_type(C, member)`. */
484# define TEST_PTR_DATA_TYPE_FROM_CONTEXT(member, rna_type, rna_ptr) \
485 { \
486 const char *ctx_member = member; \
487 if (RNA_struct_is_a((rna_ptr)->type, &(rna_type)) && \
488 (rna_ptr)->data == (CTX_data_pointer_get_type(C, ctx_member, &(rna_type)).data)) \
489 { \
490 member_id = ctx_member; \
491 break; \
492 } \
493 } \
494 (void)0
495
496 /* General checks (multiple ID types). */
497 if (ptr->owner_id) {
498 const ID_Type ptr_id_type = GS(ptr->owner_id->name);
499
500 /* Support break in the macros for an early exit. */
501 do {
502 /* Animation Data. */
503 if (id_type_can_have_animdata(ptr_id_type)) {
504 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_nla_track", RNA_NlaTrack, ptr);
505 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_nla_strip", RNA_NlaStrip, ptr);
506 }
507 } while (false);
508 }
509
510 /* Specific ID type checks. */
511 if (ptr->owner_id && (member_id == nullptr)) {
512
513 const ID_Type ptr_id_type = GS(ptr->owner_id->name);
514 switch (ptr_id_type) {
515 case ID_SCE: {
516 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_sequence_strip", RNA_Sequence, ptr);
517
518 CTX_TEST_PTR_ID(C, "scene", ptr->owner_id);
519 break;
520 }
521 case ID_OB: {
522 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_pose_bone", RNA_PoseBone, ptr);
523
524 CTX_TEST_PTR_ID(C, "object", ptr->owner_id);
525 break;
526 }
527 /* From #rna_Main_objects_new. */
529
530 if (ptr_id_type == ID_AR) {
531 const bArmature *arm = (bArmature *)ptr->owner_id;
532 if (arm->edbo != nullptr) {
533 TEST_PTR_DATA_TYPE("active_bone", RNA_EditBone, ptr, arm->act_edbone);
534 }
535 else {
536 TEST_PTR_DATA_TYPE("active_bone", RNA_Bone, ptr, arm->act_bone);
537 }
538 }
539
540# define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data)
541 CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->owner_id);
542 break;
543# undef ID_CAST_OBDATA
544 }
545 case ID_MA: {
546# define ID_CAST_OBMATACT(id_pt) \
547 BKE_object_material_get(((Object *)id_pt), ((Object *)id_pt)->actcol)
549 C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->owner_id);
550 break;
551# undef ID_CAST_OBMATACT
552 }
553 case ID_WO: {
554# define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world)
555 CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->owner_id);
556 break;
557# undef ID_CAST_SCENEWORLD
558 }
559 case ID_SCR: {
560 CTX_TEST_PTR_ID(C, "screen", ptr->owner_id);
561
562 TEST_PTR_DATA_TYPE("area", RNA_Area, ptr, CTX_wm_area(C));
563 TEST_PTR_DATA_TYPE("region", RNA_Region, ptr, CTX_wm_region(C));
564
565 SpaceLink *space_data = CTX_wm_space_data(C);
566 if (space_data != nullptr) {
567 TEST_PTR_DATA_TYPE("space_data", RNA_Space, ptr, space_data);
568
569 switch (space_data->spacetype) {
570 case SPACE_VIEW3D: {
571 const View3D *v3d = (View3D *)space_data;
572 const View3DShading *shading = &v3d->shading;
573
574 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_View3DOverlay, ptr, v3d);
575 TEST_PTR_DATA_TYPE("space_data.shading", RNA_View3DShading, ptr, shading);
576 break;
577 }
578 case SPACE_GRAPH: {
579 const SpaceGraph *sipo = (SpaceGraph *)space_data;
580 const bDopeSheet *ads = sipo->ads;
581 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
582 break;
583 }
584 case SPACE_FILE: {
585 const SpaceFile *sfile = (SpaceFile *)space_data;
587 TEST_PTR_DATA_TYPE("space_data.params", RNA_FileSelectParams, ptr, params);
588 break;
589 }
590 case SPACE_IMAGE: {
591 const SpaceImage *sima = (SpaceImage *)space_data;
592 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceImageOverlay, ptr, sima);
593 TEST_PTR_DATA_TYPE("space_data.uv_editor", RNA_SpaceUVEditor, ptr, sima);
594 break;
595 }
596 case SPACE_NLA: {
597 const SpaceNla *snla = (SpaceNla *)space_data;
598 const bDopeSheet *ads = snla->ads;
599 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
600 break;
601 }
602 case SPACE_ACTION: {
603 const SpaceAction *sact = (SpaceAction *)space_data;
604 const bDopeSheet *ads = &sact->ads;
605 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
606 break;
607 }
608 case SPACE_NODE: {
609 const SpaceNode *snode = (SpaceNode *)space_data;
610 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceNodeOverlay, ptr, snode);
611 break;
612 }
613 case SPACE_SEQ: {
614 const SpaceSeq *sseq = (SpaceSeq *)space_data;
616 "space_data.preview_overlay", RNA_SequencerPreviewOverlay, ptr, sseq);
618 "space_data.timeline_overlay", RNA_SequencerTimelineOverlay, ptr, sseq);
619 TEST_PTR_DATA_TYPE("space_data.cache_overlay", RNA_SequencerCacheOverlay, ptr, sseq);
620 break;
621 }
622 }
623 }
624
625 break;
626 }
627 default:
628 break;
629 }
630# undef CTX_TEST_PTR_ID
631# undef CTX_TEST_PTR_ID_CAST
632# undef TEST_PTR_DATA_TYPE
633 }
634
635 *r_is_id = is_id;
636
637 return member_id;
638}
639#endif
640
641std::optional<std::string> WM_context_path_resolve_property_full(const bContext *C,
642 const PointerRNA *ptr,
643 PropertyRNA *prop,
644 int index)
645{
646 bool is_id;
647 const char *member_id = wm_context_member_from_ptr(C, ptr, &is_id);
648 if (!member_id) {
649 return std::nullopt;
650 }
651 std::string member_id_data_path;
652 if (is_id && !RNA_struct_is_ID(ptr->type)) {
653 std::optional<std::string> data_path = RNA_path_from_ID_to_struct(ptr);
654 if (data_path) {
655 if (prop != nullptr) {
656 std::string prop_str = RNA_path_property_py(ptr, prop, index);
657 if (prop_str[0] == '[') {
658 member_id_data_path = fmt::format("{}.{}{}", member_id, *data_path, prop_str);
659 }
660 else {
661 member_id_data_path = fmt::format("{}.{}.{}", member_id, *data_path, prop_str);
662 }
663 }
664 else {
665 member_id_data_path = fmt::format("{}.{}", member_id, *data_path);
666 }
667 }
668 }
669 else {
670 if (prop != nullptr) {
671 std::string prop_str = RNA_path_property_py(ptr, prop, index);
672 if (prop_str[0] == '[') {
673 member_id_data_path = fmt::format("{}{}", member_id, prop_str);
674 }
675 else {
676 member_id_data_path = fmt::format("{}.{}", member_id, prop_str);
677 }
678 }
679 else {
680 member_id_data_path = member_id;
681 }
682 }
683
684 return member_id_data_path;
685}
686
687std::optional<std::string> WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr)
688{
689 return WM_context_path_resolve_property_full(C, ptr, nullptr, -1);
690}
691
692static std::optional<std::string> wm_prop_pystring_from_context(bContext *C,
694 PropertyRNA *prop,
695 int index)
696{
697 std::optional<std::string> member_id_data_path = WM_context_path_resolve_property_full(
698 C, ptr, prop, index);
699 if (!member_id_data_path.has_value()) {
700 return std::nullopt;
701 }
702 return "bpy.context." + member_id_data_path.value();
703}
704
705std::optional<std::string> WM_prop_pystring_assign(bContext *C,
707 PropertyRNA *prop,
708 int index)
709{
710 std::optional<std::string> lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) :
711 std::nullopt;
712
713 if (!lhs.has_value()) {
714 /* Fallback to `bpy.data.foo[id]` if we don't find in the context. */
715 if (std::optional<std::string> lhs_str = RNA_path_full_property_py(ptr, prop, index)) {
716 lhs = lhs_str;
717 }
718 else {
719 return std::nullopt;
720 }
721 }
722
723 std::string rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX);
724
725 std::string ret = fmt::format("{} = {}", lhs.value(), rhs);
726 return ret;
727}
728
730{
731 /* Set the ID so the context can be accessed: see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
732 *ptr = RNA_pointer_create(static_cast<ID *>(G_MAIN->wm.first), ot->srna, nullptr);
733}
734
735void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
736{
737 wmOperatorType *ot = WM_operatortype_find(opstring, false);
738
739 if (ot) {
741 }
742 else {
743 /* Set the ID so the context can be accessed: see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
745 static_cast<ID *>(G_MAIN->wm.first), &RNA_OperatorProperties, nullptr);
746 }
747}
748
749void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
750{
751 IDProperty *tmp_properties = nullptr;
752 /* Allow passing nullptr for properties, just create the properties here then. */
753 if (properties == nullptr) {
754 properties = &tmp_properties;
755 }
756
757 if (*properties == nullptr) {
758 *properties = blender::bke::idprop::create_group("wmOpItemProp").release();
759 }
760
761 if (*ptr == nullptr) {
762 *ptr = MEM_new<PointerRNA>("wmOpItemPtr");
764 }
765
766 (*ptr)->data = *properties;
767}
768
769void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
770{
771 RNA_STRUCT_BEGIN (ptr, prop) {
772 switch (RNA_property_type(prop)) {
773 case PROP_ENUM:
774 if (no_context) {
776 }
777 else {
779 }
780 break;
781 case PROP_POINTER: {
783
784 /* Recurse into operator properties. */
785 if (RNA_struct_is_a(ptype, &RNA_OperatorProperties)) {
787 WM_operator_properties_sanitize(&opptr, no_context);
788 }
789 break;
790 }
791 default:
792 break;
793 }
794 }
796}
797
799{
800 bool changed = false;
801 RNA_STRUCT_BEGIN (ptr, prop) {
802 switch (RNA_property_type(prop)) {
803 case PROP_POINTER: {
805 if (ptype != &RNA_Struct) {
807 changed |= WM_operator_properties_default(&opptr, do_update);
808 }
809 break;
810 }
811 default:
812 if ((do_update == false) || (RNA_property_is_set(ptr, prop) == false)) {
813 if (RNA_property_reset(ptr, prop, -1)) {
814 changed = true;
815 }
816 }
817 break;
818 }
819 }
821
822 return changed;
823}
824
826{
827 if (op->ptr->data) {
829
830 RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
831 PropertyRNA *prop = static_cast<PropertyRNA *>(itemptr.data);
832
833 if ((RNA_property_flag(prop) & (PROP_SKIP_SAVE | PROP_SKIP_PRESET)) == 0) {
834 const char *identifier = RNA_property_identifier(prop);
835 RNA_struct_idprops_unset(op->ptr, identifier);
836 }
837 }
839 }
840}
841
843{
844 IDProperty *properties = static_cast<IDProperty *>(ptr->data);
845
846 if (properties) {
847 IDP_ClearProperty(properties);
848 }
849}
850
852{
853 IDProperty *properties = static_cast<IDProperty *>(ptr->data);
854
855 if (properties) {
856 IDP_FreeProperty(properties);
857 ptr->data = nullptr; /* Just in case. */
858 }
859}
860
863/* -------------------------------------------------------------------- */
867#if 1 /* May want to disable operator remembering previous state for testing. */
868
870{
871 bool changed = false;
872 IDProperty *replaceprops = blender::bke::idprop::create_group("wmOperatorProperties").release();
873
875
876 RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
877 PropertyRNA *prop = static_cast<PropertyRNA *>(itemptr.data);
878 if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
879 if (!RNA_property_is_set(op->ptr, prop)) { /* Don't override a setting already set. */
880 const char *identifier = RNA_property_identifier(prop);
881 IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, identifier);
882 if (idp_src) {
883 IDProperty *idp_dst = IDP_CopyProperty(idp_src);
884
885 /* NOTE: in the future this may need to be done recursively,
886 * but for now RNA doesn't access nested operators. */
887 idp_dst->flag |= IDP_FLAG_GHOST;
888
889 /* Add to temporary group instead of immediate replace,
890 * because we are iterating over this group. */
891 IDP_AddToGroup(replaceprops, idp_dst);
892 changed = true;
893 }
894 }
895 }
896 }
898
899 if (changed) {
900 CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
901 }
902 IDP_MergeGroup(op->properties, replaceprops, true);
903 IDP_FreeProperty(replaceprops);
904 return changed;
905}
906
908{
909 bool changed = false;
910 if (op->type->last_properties) {
912 LISTBASE_FOREACH (wmOperator *, opm, &op->macro) {
913 IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname);
914 if (idp_src) {
915 changed |= operator_last_properties_init_impl(opm, idp_src);
916 }
917 }
918 }
919 return changed;
920}
921
923{
924 if (op->type->last_properties) {
926 op->type->last_properties = nullptr;
927 }
928
929 if (op->properties) {
931 CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname);
932 }
934 }
935
936 if (op->macro.first != nullptr) {
937 LISTBASE_FOREACH (wmOperator *, opm, &op->macro) {
938 if (opm->properties) {
939 if (op->type->last_properties == nullptr) {
940 op->type->last_properties =
941 blender::bke::idprop::create_group("wmOperatorProperties").release();
942 }
943 IDProperty *idp_macro = IDP_CopyProperty(opm->properties);
944 STRNCPY(idp_macro->name, opm->type->idname);
945 IDP_ReplaceInGroup(op->type->last_properties, idp_macro);
946 }
947 }
948 }
949
950 return (op->type->last_properties != nullptr);
951}
952
953#else
954
956{
957 return false;
958}
959
961{
962 return false;
963}
964
965#endif
966
969/* -------------------------------------------------------------------- */
974{
975 PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
976 "wait_to_deselect_others");
977 const short init_event_type = short(POINTER_AS_INT(op->customdata));
978 int ret_value = 0;
979
980 /* Get settings from RNA properties for operator. */
981 const int mval[2] = {RNA_int_get(op->ptr, "mouse_x"), RNA_int_get(op->ptr, "mouse_y")};
982
983 if (init_event_type == 0) {
984 if (event->val == KM_PRESS) {
985 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, true);
986
987 ret_value = op->type->exec(C, op);
988 OPERATOR_RETVAL_CHECK(ret_value);
989 op->customdata = POINTER_FROM_INT(int(event->type));
990 if (ret_value & OPERATOR_RUNNING_MODAL) {
992 }
993 return ret_value | OPERATOR_PASS_THROUGH;
994 }
995 /* If we are in init phase, and cannot validate init of modal operations,
996 * just fall back to basic exec.
997 */
998 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
999
1000 ret_value = op->type->exec(C, op);
1001 OPERATOR_RETVAL_CHECK(ret_value);
1002
1003 return ret_value | OPERATOR_PASS_THROUGH;
1004 }
1005 if (event->type == init_event_type && event->val == KM_RELEASE) {
1006 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
1007
1008 ret_value = op->type->exec(C, op);
1009 OPERATOR_RETVAL_CHECK(ret_value);
1010
1011 return ret_value | OPERATOR_PASS_THROUGH;
1012 }
1013 if (ISMOUSE_MOTION(event->type)) {
1014 const int drag_delta[2] = {
1015 mval[0] - event->mval[0],
1016 mval[1] - event->mval[1],
1017 };
1018 /* If user moves mouse more than defined threshold, we consider select operator as
1019 * finished. Otherwise, it is still running until we get an 'release' event. In any
1020 * case, we pass through event, but select op is not finished yet. */
1021 if (WM_event_drag_test_with_delta(event, drag_delta)) {
1023 }
1024 /* Important not to return anything other than PASS_THROUGH here,
1025 * otherwise it prevents underlying drag detection code to work properly. */
1026 return OPERATOR_PASS_THROUGH;
1027 }
1028
1030}
1031
1033{
1034 ARegion *region = CTX_wm_region(C);
1035
1036 int mval[2];
1037 WM_event_drag_start_mval(event, region, mval);
1038
1039 RNA_int_set(op->ptr, "mouse_x", mval[0]);
1040 RNA_int_set(op->ptr, "mouse_y", mval[1]);
1041
1043
1044 return op->type->modal(C, op, event);
1045}
1046
1048{
1049 if (op->flag & OP_IS_INVOKE) {
1050 Scene *scene = CTX_data_scene(C);
1051 View3D *v3d = CTX_wm_view3d(C);
1052
1053 const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
1054 ED_scene_grid_scale(scene, nullptr);
1055
1056 /* Always run, so the values are initialized,
1057 * otherwise we may get differ behavior when `dia != 1.0`. */
1058 RNA_STRUCT_BEGIN (op->ptr, prop) {
1059 if (RNA_property_type(prop) == PROP_FLOAT) {
1061 if (pstype == PROP_DISTANCE) {
1062 /* We don't support arrays yet. */
1063 BLI_assert(RNA_property_array_check(prop) == false);
1064 /* Initialize. */
1065 if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
1066 const float value = RNA_property_float_get_default(op->ptr, prop) * dia;
1067 RNA_property_float_set(op->ptr, prop, value);
1068 }
1069 }
1070 }
1071 }
1073 }
1074}
1075
1077{
1078 return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0;
1079}
1080
1082{
1083 PropertyRNA *prop = op->type->prop;
1084
1085 if (prop == nullptr) {
1086 CLOG_ERROR(WM_LOG_OPERATORS, "'%s' has no enum property set", op->type->idname);
1087 }
1088 else if (RNA_property_type(prop) != PROP_ENUM) {
1090 "'%s', '%s' is not an enum property",
1091 op->type->idname,
1093 }
1094 else if (RNA_property_is_set(op->ptr, prop)) {
1095 const int retval = op->type->exec(C, op);
1096 OPERATOR_RETVAL_CHECK(retval);
1097 return retval;
1098 }
1099 else {
1101 C, WM_operatortype_name(op->type, op->ptr).c_str(), ICON_NONE);
1102 uiLayout *layout = UI_popup_menu_layout(pup);
1103 /* Set this so the default execution context is the same as submenus. */
1104 uiLayoutSetOperatorContext(layout, opcontext);
1105 uiItemsFullEnumO(layout,
1106 op->type->idname,
1108 static_cast<IDProperty *>(op->ptr->data),
1109 opcontext,
1110 UI_ITEM_NONE);
1111 UI_popup_menu_end(C, pup);
1112 return OPERATOR_INTERFACE;
1113 }
1114
1115 return OPERATOR_CANCELLED;
1116}
1117
1118int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
1119{
1121}
1122
1124 wmOperator *op; /* The operator that will be executed when selecting an item. */
1125};
1126
1128static uiBlock *wm_enum_search_menu(bContext *C, ARegion *region, void *arg)
1129{
1130 EnumSearchMenu *search_menu = static_cast<EnumSearchMenu *>(arg);
1131 wmWindow *win = CTX_wm_window(C);
1132 wmOperator *op = search_menu->op;
1133 /* `template_ID` uses `4 * widget_unit` for width,
1134 * we use a bit more, some items may have a suffix to show. */
1135 const int width = UI_searchbox_size_x();
1136 const int height = UI_searchbox_size_y();
1137 static char search[256] = "";
1138
1139 uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
1142
1143 search[0] = '\0';
1144#if 0 /* Ok, this isn't so easy. */
1145 uiDefBut(block,
1147 0,
1148 WM_operatortype_name(op->type, op->ptr),
1149 10,
1150 10,
1152 UI_UNIT_Y,
1153 nullptr,
1154 0.0,
1155 0.0,
1156 "");
1157#endif
1158 uiBut *but = uiDefSearchButO_ptr(block,
1159 op->type,
1160 static_cast<IDProperty *>(op->ptr->data),
1161 search,
1162 0,
1163 ICON_VIEWZOOM,
1164 sizeof(search),
1165 10,
1166 10,
1167 width,
1168 UI_UNIT_Y,
1169 "");
1170
1171 /* Fake button, it holds space for search items. */
1172 uiDefBut(block,
1174 0,
1175 "",
1176 10,
1177 10 - UI_searchbox_size_y(),
1178 width,
1179 height,
1180 nullptr,
1181 0,
1182 0,
1183 nullptr);
1184
1185 /* Move it downwards, mouse over button. */
1186 UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, blender::int2{0, -UI_UNIT_Y});
1187
1189
1190 return block;
1191}
1192
1193int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
1194{
1195 static EnumSearchMenu search_menu;
1196 search_menu.op = op;
1197 /* Refreshing not supported, because operator might get freed. */
1198 const bool can_refresh = false;
1199 UI_popup_block_invoke_ex(C, wm_enum_search_menu, &search_menu, nullptr, can_refresh);
1200 return OPERATOR_INTERFACE;
1201}
1202
1204 wmOperator *op,
1205 const char *title,
1206 const int icon,
1207 const char *message,
1208 const wmOperatorCallContext /*opcontext*/)
1209{
1210 int alert_icon = ALERT_ICON_QUESTION;
1211 switch (icon) {
1212 case ICON_NONE:
1213 alert_icon = ALERT_ICON_NONE;
1214 break;
1215 case ICON_ERROR:
1216 alert_icon = ALERT_ICON_WARNING;
1217 break;
1218 case ICON_QUESTION:
1219 alert_icon = ALERT_ICON_QUESTION;
1220 break;
1221 case ICON_CANCEL:
1222 alert_icon = ALERT_ICON_ERROR;
1223 break;
1224 case ICON_INFO:
1225 alert_icon = ALERT_ICON_INFO;
1226 break;
1227 }
1228 return WM_operator_confirm_ex(C, op, IFACE_(title), nullptr, IFACE_(message), alert_icon, false);
1229}
1230
1231int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
1232{
1234 C, op, IFACE_(message), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1235}
1236
1237int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent * /*event*/)
1238{
1240 C, op, IFACE_(op->type->name), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1241}
1242
1244{
1245 const bool confirm = RNA_boolean_get(op->ptr, "confirm");
1246 if (confirm) {
1248 C, op, IFACE_(op->type->name), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1249 }
1250 return op->type->exec(C, op);
1251}
1252
1253int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent * /*event*/)
1254{
1255 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
1256 return WM_operator_call_notest(C, op); /* Call exec direct. */
1257 }
1260}
1261
1263{
1264 char filepath[FILE_MAX];
1265 /* Don't nullptr check prop, this can only run on ops with a 'filepath'. */
1266 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
1267 RNA_property_string_get(op->ptr, prop, filepath);
1268 if (BKE_image_path_ext_from_imformat_ensure(filepath, sizeof(filepath), im_format)) {
1269 RNA_property_string_set(op->ptr, prop, filepath);
1270 /* NOTE: we could check for and update 'filename' here,
1271 * but so far nothing needs this. */
1272 return true;
1273 }
1274 return false;
1275}
1276
1278{
1279 if (CTX_wm_window(C) == nullptr) {
1280 return false;
1281 }
1282 return true;
1283}
1284
1285bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
1286{
1288 Scene *scene = CTX_data_scene(C);
1289
1290 return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY));
1291}
1292
1294{
1296
1297 /* Only for operators that are registered and did an undo push. */
1299 if ((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO)) {
1300 return op;
1301 }
1302 }
1303
1304 return nullptr;
1305}
1306
1308{
1309 if (ot->last_properties == nullptr) {
1310 ot->last_properties = blender::bke::idprop::create_group("wmOperatorProperties").release();
1311 }
1312 return ot->last_properties;
1313}
1314
1320
1322{
1323 Main *bmain = CTX_data_main(C);
1324 ID *id = nullptr;
1325
1326 /* Check input variables. */
1327 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
1328 const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
1329 char filepath[FILE_MAX];
1330 bool exists = false;
1331
1332 RNA_string_get(op->ptr, "filepath", filepath);
1333
1334 errno = 0;
1335
1336 if (idcode == ID_IM) {
1337 id = reinterpret_cast<ID *>(BKE_image_load_exists(bmain, filepath, &exists));
1338 }
1339 else {
1341 }
1342
1343 if (!id) {
1344 BKE_reportf(op->reports,
1345 RPT_ERROR,
1346 "Cannot read %s '%s': %s",
1348 filepath,
1349 errno ? strerror(errno) : RPT_("unsupported format"));
1350 return nullptr;
1351 }
1352
1353 if (is_relative_path) {
1354 if (exists == false) {
1355 if (idcode == ID_IM) {
1356 BLI_path_rel(((Image *)id)->filepath, BKE_main_blendfile_path(bmain));
1357 }
1358 else {
1360 }
1361 }
1362 }
1363
1364 return id;
1365 }
1366
1368 return nullptr;
1369 }
1370
1371 /* Lookup an already existing ID. */
1373
1374 if (!id) {
1375 /* Print error with the name if the name is available. */
1376
1377 if (RNA_struct_property_is_set(op->ptr, "name")) {
1378 char name[MAX_ID_NAME - 2];
1379 RNA_string_get(op->ptr, "name", name);
1381 op->reports, RPT_ERROR, "%s '%s' not found", BKE_idtype_idcode_to_name(idcode), name);
1382 return nullptr;
1383 }
1384
1385 BKE_reportf(op->reports, RPT_ERROR, "%s not found", BKE_idtype_idcode_to_name(idcode));
1386 return nullptr;
1387 }
1388
1389 id_us_plus(id);
1390 return id;
1391}
1392
1393static void wm_block_redo_cb(bContext *C, void *arg_op, int /*arg_event*/)
1394{
1395 wmOperator *op = static_cast<wmOperator *>(arg_op);
1396
1397 if (op == WM_operator_last_redo(C)) {
1398 /* Operator was already executed once? undo & repeat. */
1400 }
1401 else {
1402 /* Operator not executed yet, call it. */
1403 ED_undo_push_op(C, op);
1404 wm_operator_register(C, op);
1405
1406 WM_operator_repeat(C, op);
1407 }
1408}
1409
1410static void wm_block_redo_cancel_cb(bContext *C, void *arg_op)
1411{
1412 wmOperator *op = static_cast<wmOperator *>(arg_op);
1413
1414 /* If operator never got executed, free it. */
1415 if (op != WM_operator_last_redo(C)) {
1416 WM_operator_free(op);
1417 }
1418}
1419
1420static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
1421{
1422 wmOperator *op = static_cast<wmOperator *>(arg_op);
1423 const uiStyle *style = UI_style_get_dpi();
1424 int width = 15 * UI_UNIT_X;
1425
1426 uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
1429
1430 /* #UI_BLOCK_NUMSELECT for layer buttons. */
1432
1433 /* If register is not enabled, the operator gets freed on #OPERATOR_FINISHED
1434 * ui_apply_but_funcs_after calls #ED_undo_operator_repeate_cb and crashes. */
1436
1438 UI_popup_dummy_panel_set(region, block);
1439 uiLayout *layout = UI_block_layout(
1440 block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style);
1441
1442 if (op == WM_operator_last_redo(C)) {
1443 if (!WM_operator_check_ui_enabled(C, op->type->name)) {
1444 uiLayoutSetEnabled(layout, false);
1445 }
1446 }
1447
1448 uiItemL_ex(layout, WM_operatortype_name(op->type, op->ptr).c_str(), ICON_NONE, true, false);
1450 uiItemS_ex(layout, 0.5f);
1451
1452 uiLayout *col = uiLayoutColumn(layout, false);
1454
1455 UI_block_bounds_set_popup(block, 7 * UI_SCALE_FAC, nullptr);
1456
1457 return block;
1458}
1459
1474
1475/* Only invoked by OK button in popups created with #wm_block_dialog_create(). */
1476static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
1477{
1478 wmOperator *op;
1479 {
1480 /* Execute will free the operator.
1481 * In this case, wm_operator_ui_popup_cancel won't run. */
1482 wmOpPopUp *data = static_cast<wmOpPopUp *>(arg1);
1483 op = data->op;
1484 MEM_delete(data);
1485 }
1486
1487 uiBlock *block = static_cast<uiBlock *>(arg2);
1488 /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled
1489 * in case WM_operator_call_ex exits/reloads the current file (#49199). */
1490
1492
1493 /* Get context data *after* WM_operator_call_ex
1494 * which might have closed the current file and changed context. */
1495 wmWindow *win = CTX_wm_window(C);
1496 UI_popup_block_close(C, win, block);
1497
1498 WM_operator_call_ex(C, op, true);
1499}
1500
1501static void wm_operator_ui_popup_cancel(bContext *C, void *user_data);
1502
1503/* Only invoked by Cancel button in popups created with #wm_block_dialog_create(). */
1504static void dialog_cancel_cb(bContext *C, void *arg1, void *arg2)
1505{
1507 uiBlock *block = static_cast<uiBlock *>(arg2);
1509 wmWindow *win = CTX_wm_window(C);
1510 UI_popup_block_close(C, win, block);
1511}
1512
1516static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_data)
1517{
1518 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1519 wmOperator *op = data->op;
1520 const uiStyle *style = UI_style_get_dpi();
1521 const bool small = data->size == WM_POPUP_SIZE_SMALL;
1522 const short icon_size = (small ? 32 : 64) * UI_SCALE_FAC;
1523
1524 uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
1527 UI_popup_dummy_panel_set(region, block);
1528
1529 if (data->mouse_move_quit) {
1531 }
1532 if (data->icon < ALERT_ICON_NONE || data->icon >= ALERT_ICON_MAX) {
1533 data->icon = ALERT_ICON_QUESTION;
1534 }
1535
1537
1538 UI_fontstyle_set(&style->widget);
1539 /* Width based on the text lengths. */
1540 int text_width = std::max(
1541 120 * UI_SCALE_FAC,
1542 BLF_width(style->widget.uifont_id, data->title.c_str(), BLF_DRAW_STR_DUMMY_MAX));
1543
1544 /* Break Message into multiple lines. */
1545 blender::Vector<std::string> message_lines;
1546 blender::StringRef messaged_trimmed = blender::StringRef(data->message).trim();
1547 std::istringstream message_stream(messaged_trimmed);
1548 std::string line;
1549 while (std::getline(message_stream, line)) {
1550 message_lines.append(line);
1551 text_width = std::max(
1552 text_width, int(BLF_width(style->widget.uifont_id, line.c_str(), BLF_DRAW_STR_DUMMY_MAX)));
1553 }
1554
1555 int dialog_width = std::max(text_width + int(style->columnspace * 2.5), data->width);
1556
1557 /* Adjust width if the button text is long. */
1558 const int longest_button_text = std::max(
1559 BLF_width(style->widget.uifont_id, data->confirm_text.c_str(), BLF_DRAW_STR_DUMMY_MAX),
1561 dialog_width = std::max(dialog_width, 3 * longest_button_text);
1562
1563 uiLayout *layout;
1564 if (data->icon != ALERT_ICON_NONE) {
1565 layout = uiItemsAlertBox(
1566 block, style, dialog_width + icon_size, eAlertIcon(data->icon), icon_size);
1567 }
1568 else {
1569 layout = UI_block_layout(
1570 block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style);
1571 }
1572
1573 /* Title. */
1574 if (!data->title.empty()) {
1575 uiItemL_ex(layout, data->title.c_str(), ICON_NONE, true, false);
1576
1577 /* Line under the title if there are properties but no message body. */
1578 if (data->include_properties && message_lines.size() == 0) {
1580 };
1581 }
1582
1583 /* Message lines. */
1584 for (auto &st : message_lines) {
1585 uiItemL(layout, st.c_str(), ICON_NONE);
1586 }
1587
1588 if (data->include_properties) {
1589 uiItemS_ex(layout, 0.5f);
1591 }
1592
1593 uiItemS_ex(layout, small ? 0.1f : 2.0f);
1594
1595 /* Clear so the OK button is left alone. */
1596 UI_block_func_set(block, nullptr, nullptr, nullptr);
1597
1598#ifdef _WIN32
1599 const bool windows_layout = true;
1600#else
1601 const bool windows_layout = false;
1602#endif
1603
1604 /* Check there are no active default buttons, allowing a dialog to define it's own
1605 * confirmation buttons which are shown instead of these, see: #124098. */
1607 /* New column so as not to interfere with custom layouts, see: #26436. */
1608 uiLayout *col = uiLayoutColumn(layout, false);
1609 uiBlock *col_block = uiLayoutGetBlock(col);
1610 uiBut *confirm_but;
1611 uiBut *cancel_but;
1612
1613 col = uiLayoutSplit(col, 0.0f, true);
1614 uiLayoutSetScaleY(col, small ? 1.0f : 1.2f);
1615
1616 if (windows_layout) {
1617 confirm_but = uiDefBut(col_block,
1619 0,
1620 data->confirm_text.c_str(),
1621 0,
1622 0,
1623 0,
1624 UI_UNIT_Y,
1625 nullptr,
1626 0,
1627 0,
1628 "");
1629 uiLayoutColumn(col, false);
1630 }
1631
1632 cancel_but = uiDefBut(
1633 col_block, UI_BTYPE_BUT, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, nullptr, 0, 0, "");
1634
1635 if (!windows_layout) {
1636 uiLayoutColumn(col, false);
1637 confirm_but = uiDefBut(col_block,
1639 0,
1640 data->confirm_text.c_str(),
1641 0,
1642 0,
1643 0,
1644 UI_UNIT_Y,
1645 nullptr,
1646 0,
1647 0,
1648 "");
1649 }
1650
1651 UI_but_func_set(confirm_but, dialog_exec_cb, data, col_block);
1652 UI_but_func_set(cancel_but, dialog_cancel_cb, data, col_block);
1653 UI_but_flag_enable((data->cancel_default) ? cancel_but : confirm_but, UI_BUT_ACTIVE_DEFAULT);
1654 }
1655
1656 const int padding = (small ? 7 : 14) * UI_SCALE_FAC;
1657
1658 if (data->position == WM_POPUP_POSITION_MOUSE) {
1659 const float button_center_x = windows_layout ? -0.4f : -0.90f;
1660 const float button_center_y = small ? 2.0f : 3.1f;
1661 const int bounds_offset[2] = {int(button_center_x * uiLayoutGetWidth(layout)),
1662 int(button_center_y * UI_UNIT_X)};
1663 UI_block_bounds_set_popup(block, padding, bounds_offset);
1664 }
1665 else if (data->position == WM_POPUP_POSITION_CENTER) {
1667 }
1668
1669 return block;
1670}
1671
1672static uiBlock *wm_operator_ui_create(bContext *C, ARegion *region, void *user_data)
1673{
1674 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1675 wmOperator *op = data->op;
1676 const uiStyle *style = UI_style_get_dpi();
1677
1678 uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
1682
1683 UI_popup_dummy_panel_set(region, block);
1684
1685 uiLayout *layout = UI_block_layout(
1686 block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, 0, 0, style);
1687
1688 /* Since UI is defined the auto-layout args are not used. */
1690
1691 UI_block_func_set(block, nullptr, nullptr, nullptr);
1692
1693 UI_block_bounds_set_popup(block, 6 * UI_SCALE_FAC, nullptr);
1694
1695 return block;
1696}
1697
1698static void wm_operator_ui_popup_cancel(bContext *C, void *user_data)
1699{
1700 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1701 wmOperator *op = data->op;
1702
1703 if (op) {
1704 if (op->type->cancel) {
1705 op->type->cancel(C, op);
1706 }
1707
1708 if (data->free_op) {
1709 WM_operator_free(op);
1710 }
1711 }
1712
1713 MEM_delete(data);
1714}
1715
1716static void wm_operator_ui_popup_ok(bContext *C, void *arg, int retval)
1717{
1718 wmOpPopUp *data = static_cast<wmOpPopUp *>(arg);
1719 wmOperator *op = data->op;
1720
1721 if (op && retval > 0) {
1722 WM_operator_call_ex(C, op, true);
1723 }
1724
1725 MEM_delete(data);
1726}
1727
1729 wmOperator *op,
1730 const char *title,
1731 const char *message,
1732 const char *confirm_text,
1733 int icon,
1734 bool cancel_default)
1735{
1736 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1737 data->op = op;
1738
1739 /* Larger dialog needs a wider minimum width to balance with the big icon. */
1740 const float min_width = (message == nullptr) ? 180.0f : 230.0f;
1741 data->width = int(min_width * UI_SCALE_FAC * UI_style_get()->widget.points /
1743
1744 data->free_op = true;
1745 data->title = (title == nullptr) ? WM_operatortype_name(op->type, op->ptr) : title;
1746 data->message = (message == nullptr) ? std::string() : message;
1747 data->confirm_text = (confirm_text == nullptr) ? IFACE_("OK") : confirm_text;
1748 data->icon = eAlertIcon(icon);
1749 data->size = (message == nullptr) ? WM_POPUP_SIZE_SMALL : WM_POPUP_SIZE_LARGE;
1750 data->position = (message == nullptr) ? WM_POPUP_POSITION_MOUSE : WM_POPUP_POSITION_CENTER;
1751 data->cancel_default = cancel_default;
1752 data->mouse_move_quit = (message == nullptr) ? true : false;
1753 data->include_properties = false;
1754
1757
1759}
1760
1762{
1763 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1764 data->op = op;
1765 data->width = width * UI_SCALE_FAC;
1766 data->free_op = true; /* If this runs and gets registered we may want not to free it. */
1769}
1770
1777 wmOperator *op,
1778 const bool do_call,
1779 const bool do_redo,
1780 std::optional<std::string> title = std::nullopt,
1781 std::optional<std::string> confirm_text = std::nullopt,
1782 const bool cancel_default = false)
1783{
1784 if ((op->type->flag & OPTYPE_REGISTER) == 0) {
1785 BKE_reportf(op->reports,
1786 RPT_ERROR,
1787 "Operator '%s' does not have register enabled, incorrect invoke function",
1788 op->type->idname);
1789 return OPERATOR_CANCELLED;
1790 }
1791
1792 if (do_redo) {
1793 if ((op->type->flag & OPTYPE_UNDO) == 0) {
1794 BKE_reportf(op->reports,
1795 RPT_ERROR,
1796 "Operator '%s' does not have undo enabled, incorrect invoke function",
1797 op->type->idname);
1798 return OPERATOR_CANCELLED;
1799 }
1800 }
1801
1802 /* If we don't have global undo, we can't do undo push for automatic redo,
1803 * so we require manual OK clicking in this popup. */
1804 if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) {
1805 return WM_operator_props_dialog_popup(C, op, 300, title, confirm_text, cancel_default);
1806 }
1807
1809
1810 if (do_call) {
1811 wm_block_redo_cb(C, op, 0);
1812 }
1813
1815}
1816
1818 wmOperator *op,
1819 const wmEvent * /*event*/,
1820 std::optional<std::string> title,
1821 std::optional<std::string> confirm_text,
1822 const bool cancel_default)
1823{
1824 return wm_operator_props_popup_ex(C, op, false, false, title, confirm_text, cancel_default);
1825}
1826
1828{
1829 return wm_operator_props_popup_ex(C, op, false, false, {}, {});
1830}
1831
1833{
1834 return wm_operator_props_popup_ex(C, op, true, true);
1835}
1836
1838{
1839 return wm_operator_props_popup_ex(C, op, false, true);
1840}
1841
1843 wmOperator *op,
1844 int width,
1845 std::optional<std::string> title,
1846 std::optional<std::string> confirm_text,
1847 const bool cancel_default)
1848{
1849 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1850 data->op = op;
1851 data->width = int(float(width) * UI_SCALE_FAC * UI_style_get()->widget.points /
1853 data->free_op = true; /* If this runs and gets registered we may want not to free it. */
1854 data->title = title ? std::move(*title) : WM_operatortype_name(op->type, op->ptr);
1855 data->confirm_text = confirm_text ? std::move(*confirm_text) : IFACE_("OK");
1856 data->icon = ALERT_ICON_NONE;
1857 data->size = WM_POPUP_SIZE_SMALL;
1858 data->position = WM_POPUP_POSITION_MOUSE;
1859 data->cancel_default = cancel_default;
1860 data->mouse_move_quit = false;
1861 data->include_properties = true;
1862
1863 /* The operator is not executed until popup OK button is clicked. */
1866
1868}
1869
1871{
1872 /* `CTX_wm_reports(C)` because operator is on stack, not active in event system. */
1873 if ((op->type->flag & OPTYPE_REGISTER) == 0) {
1875 RPT_ERROR,
1876 "Operator redo '%s' does not have register enabled, incorrect invoke function",
1877 op->type->idname);
1878 return OPERATOR_CANCELLED;
1879 }
1880 if (op->type->poll && op->type->poll(C) == 0) {
1882 CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context", op->type->idname);
1883 return OPERATOR_CANCELLED;
1884 }
1885
1886 /* Operator is stored and kept alive in the window manager. So passing a pointer to the UI is
1887 * fine, it will remain valid. */
1889
1890 return OPERATOR_CANCELLED;
1891}
1892
1895/* -------------------------------------------------------------------- */
1902{
1903 G.debug_value = RNA_int_get(op->ptr, "debug_value");
1905 WM_event_add_notifier(C, NC_WINDOW, nullptr);
1906
1907 return OPERATOR_FINISHED;
1908}
1909
1910static int wm_debug_menu_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
1911{
1912 RNA_int_set(op->ptr, "debug_value", G.debug_value);
1913 return WM_operator_props_dialog_popup(C, op, 250, IFACE_("Set Debug Value"), IFACE_("Set"));
1914}
1915
1917{
1918 ot->name = "Debug Menu";
1919 ot->idname = "WM_OT_debug_menu";
1920 ot->description = "Open a popup to set the debug level";
1921
1925
1926 ot->prop = RNA_def_int(
1927 ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000);
1928}
1929
1932/* -------------------------------------------------------------------- */
1937{
1938 PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator);
1939
1940 if (!ptr.data) {
1941 BKE_report(op->reports, RPT_ERROR, "No operator in context");
1942 return OPERATOR_CANCELLED;
1943 }
1944
1946 return OPERATOR_FINISHED;
1947}
1948
1949/* Used by operator preset menu. pre-2.65 this was a 'Reset' button. */
1951{
1952 ot->name = "Restore Operator Defaults";
1953 ot->idname = "WM_OT_operator_defaults";
1954 ot->description = "Set the active operator to its default values";
1955
1957
1959}
1960
1963/* -------------------------------------------------------------------- */
1972
1978
1979static char g_search_text[256] = "";
1980
1981static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdata)
1982{
1983 const SearchPopupInit_Data *init_data = static_cast<const SearchPopupInit_Data *>(userdata);
1984
1985 uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
1988
1989 uiBut *but = uiDefSearchBut(block,
1991 0,
1992 ICON_VIEWZOOM,
1993 sizeof(g_search_text),
1994 10,
1995 10,
1996 init_data->size[0],
1997 UI_UNIT_Y,
1998 "");
1999
2000 if (init_data->search_type == SEARCH_TYPE_OPERATOR) {
2002 }
2003 else if (init_data->search_type == SEARCH_TYPE_MENU) {
2005 }
2006 else if (init_data->search_type == SEARCH_TYPE_SINGLE_MENU) {
2007 UI_but_func_menu_search(but, init_data->single_menu_idname.c_str());
2009 }
2010 else {
2012 }
2013
2015
2016 /* Fake button, it holds space for search items. */
2017 uiDefBut(block,
2019 0,
2020 "",
2021 10,
2022 10 - init_data->size[1],
2023 init_data->size[0],
2024 init_data->size[1],
2025 nullptr,
2026 0,
2027 0,
2028 nullptr);
2029
2030 /* Move it downwards, mouse over button. */
2031 UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, blender::int2{0, -UI_UNIT_Y});
2032
2033 return block;
2034}
2035
2036static int wm_search_menu_exec(bContext * /*C*/, wmOperator * /*op*/)
2037{
2038 return OPERATOR_FINISHED;
2039}
2040
2041static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2042{
2043 /* Exception for launching via space-bar. */
2044 if (event->type == EVT_SPACEKEY) {
2045 bool ok = true;
2046 ScrArea *area = CTX_wm_area(C);
2047 if (area) {
2048 if (area->spacetype == SPACE_CONSOLE) {
2049 /* So we can use the shortcut in the console. */
2050 ok = false;
2051 }
2052 else if (area->spacetype == SPACE_TEXT) {
2053 /* So we can use the space-bar in the text editor. */
2054 ok = false;
2055 }
2056 }
2057 else {
2058 Object *editob = CTX_data_edit_object(C);
2059 if (editob && editob->type == OB_FONT) {
2060 /* So we can use the space-bar for entering text. */
2061 ok = false;
2062 }
2063 }
2064 if (!ok) {
2065 return OPERATOR_PASS_THROUGH;
2066 }
2067 }
2068
2069 SearchType search_type;
2070 if (STREQ(op->type->idname, "WM_OT_search_menu")) {
2071 search_type = SEARCH_TYPE_MENU;
2072 }
2073 else if (STREQ(op->type->idname, "WM_OT_search_single_menu")) {
2074 search_type = SEARCH_TYPE_SINGLE_MENU;
2075 }
2076 else {
2077 search_type = SEARCH_TYPE_OPERATOR;
2078 }
2079
2080 static SearchPopupInit_Data data{};
2081
2082 if (search_type == SEARCH_TYPE_SINGLE_MENU) {
2083 {
2084 char *buffer = RNA_string_get_alloc(op->ptr, "menu_idname", nullptr, 0, nullptr);
2085 data.single_menu_idname = buffer;
2086 MEM_SAFE_FREE(buffer);
2087 }
2088 {
2089 char *buffer = RNA_string_get_alloc(op->ptr, "initial_query", nullptr, 0, nullptr);
2090 STRNCPY(g_search_text, buffer);
2091 MEM_SAFE_FREE(buffer);
2092 }
2093 }
2094 else {
2095 g_search_text[0] = '\0';
2096 }
2097
2098 data.search_type = search_type;
2099 data.size[0] = UI_searchbox_size_x() * 2;
2100 data.size[1] = UI_searchbox_size_y();
2101
2102 UI_popup_block_invoke_ex(C, wm_block_search_menu, &data, nullptr, false);
2103
2104 return OPERATOR_INTERFACE;
2105}
2106
2108{
2109 ot->name = "Search Menu";
2110 ot->idname = "WM_OT_search_menu";
2111 ot->description = "Pop-up a search over all menus in the current context";
2112
2116}
2117
2119{
2120 ot->name = "Search Operator";
2121 ot->idname = "WM_OT_search_operator";
2122 ot->description = "Pop-up a search over all available operators in current context";
2123
2127}
2128
2130{
2131 ot->name = "Search Single Menu";
2132 ot->idname = "WM_OT_search_single_menu";
2133 ot->description = "Pop-up a search for a menu in current context";
2134
2138
2139 RNA_def_string(ot->srna, "menu_idname", nullptr, 0, "Menu Name", "Menu to search in");
2141 "initial_query",
2142 nullptr,
2143 0,
2144 "Initial Query",
2145 "Query to insert into the search box");
2146}
2147
2149{
2150 char idname[BKE_ST_MAXNAME];
2151 RNA_string_get(op->ptr, "name", idname);
2152
2153 return UI_popup_menu_invoke(C, idname, op->reports);
2154}
2155
2157{
2158 char idname[BKE_ST_MAXNAME];
2159 RNA_string_get(ptr, "name", idname);
2160 MenuType *mt = WM_menutype_find(idname, true);
2161 return (mt) ? CTX_IFACE_(mt->translation_context, mt->label) :
2163}
2164
2166{
2167 ot->name = "Call Menu";
2168 ot->idname = "WM_OT_call_menu";
2169 ot->description = "Open a predefined menu";
2170
2174
2176
2177 PropertyRNA *prop;
2178
2179 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the menu");
2181 prop,
2183 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2185}
2186
2187static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2188{
2189 char idname[BKE_ST_MAXNAME];
2190 RNA_string_get(op->ptr, "name", idname);
2191
2192 return UI_pie_menu_invoke(C, idname, event);
2193}
2194
2196{
2197 char idname[BKE_ST_MAXNAME];
2198 RNA_string_get(op->ptr, "name", idname);
2199
2200 return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate);
2201}
2202
2204{
2205 ot->name = "Call Pie Menu";
2206 ot->idname = "WM_OT_call_menu_pie";
2207 ot->description = "Open a predefined pie menu";
2208
2213
2215
2216 PropertyRNA *prop;
2217
2218 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the pie menu");
2220 prop,
2222 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2224}
2225
2227{
2228 char idname[BKE_ST_MAXNAME];
2229 RNA_string_get(op->ptr, "name", idname);
2230 const bool keep_open = RNA_boolean_get(op->ptr, "keep_open");
2231
2232 return UI_popover_panel_invoke(C, idname, keep_open, op->reports);
2233}
2234
2236{
2237 char idname[BKE_ST_MAXNAME];
2238 RNA_string_get(ptr, "name", idname);
2239 PanelType *pt = WM_paneltype_find(idname, true);
2240 return (pt) ? CTX_IFACE_(pt->translation_context, pt->label) :
2242}
2243
2245{
2246 ot->name = "Call Panel";
2247 ot->idname = "WM_OT_call_panel";
2248 ot->description = "Open a predefined panel";
2249
2253
2255
2256 PropertyRNA *prop;
2257
2258 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the menu");
2260 prop,
2262 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2265 prop = RNA_def_boolean(ot->srna, "keep_open", true, "Keep Open", "");
2267}
2268
2269static int asset_shelf_popover_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
2270{
2271 char *asset_shelf_id = RNA_string_get_alloc(op->ptr, "name", nullptr, 0, nullptr);
2272 BLI_SCOPED_DEFER([&]() { MEM_freeN(asset_shelf_id); });
2273
2274 if (!blender::ui::asset_shelf_popover_invoke(*C, asset_shelf_id, *op->reports)) {
2276 }
2277
2278 return OPERATOR_INTERFACE;
2279}
2280
2281/* Needs to be defined at WM level to be globally accessible. */
2283{
2284 /* identifiers */
2285 ot->name = "Call Asset Shelf Popover";
2286 ot->idname = "WM_OT_call_asset_shelf_popover";
2287 ot->description = "Open a predefined asset shelf in a popup";
2288
2289 /* api callbacks */
2291
2293
2295 "name",
2296 nullptr,
2297 0,
2298 "Asset Shelf Name",
2299 "Identifier of the asset shelf to display");
2300}
2301
2304/* -------------------------------------------------------------------- */
2313{
2314 wmWindow *win = CTX_wm_window(C);
2315 bScreen *screen;
2316
2317 if (win == nullptr) {
2318 return false;
2319 }
2320 if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL))) {
2321 return false;
2322 }
2323 if (G.background) {
2324 return false;
2325 }
2326
2327 return true;
2328}
2329
2331{
2332 wmWindow *win = CTX_wm_window(C);
2333 bScreen *screen;
2334
2335 if (win == nullptr) {
2336 return false;
2337 }
2338 if (!((screen = WM_window_get_active_screen(win)) && (screen->state != SCREENFULL))) {
2339 return false;
2340 }
2341 if (G.background) {
2342 return false;
2343 }
2344
2345 return true;
2346}
2347
2348/* Included for script-access. */
2350{
2351 ot->name = "Close Window";
2352 ot->idname = "WM_OT_window_close";
2353 ot->description = "Close the current window";
2354
2357}
2358
2360{
2361 ot->name = "New Window";
2362 ot->idname = "WM_OT_window_new";
2363 ot->description = "Create a new window";
2364
2367}
2368
2370{
2371 ot->name = "New Main Window";
2372 ot->idname = "WM_OT_window_new_main";
2373 ot->description = "Create a new main window with its own workspace and scene selection";
2374
2377}
2378
2380{
2381 ot->name = "Toggle Window Fullscreen";
2382 ot->idname = "WM_OT_window_fullscreen_toggle";
2383 ot->description = "Toggle the current window full-screen";
2384
2387}
2388
2390{
2392 return OPERATOR_FINISHED;
2393}
2394
2395static int wm_exit_blender_invoke(bContext *C, wmOperator * /*op*/, const wmEvent * /*event*/)
2396{
2397 if (U.uiflag & USER_SAVE_PROMPT) {
2399 }
2400 else {
2402 }
2403 return OPERATOR_FINISHED;
2404}
2405
2407{
2408 ot->name = "Quit Blender";
2409 ot->idname = "WM_OT_quit_blender";
2410 ot->description = "Quit Blender";
2411
2414}
2415
2418/* -------------------------------------------------------------------- */
2422#if defined(WIN32)
2423
2424static int wm_console_toggle_exec(bContext * /*C*/, wmOperator * /*op*/)
2425{
2427 return OPERATOR_FINISHED;
2428}
2429
2430static void WM_OT_console_toggle(wmOperatorType *ot)
2431{
2432 /* XXX Have to mark these for xgettext, as under linux they do not exists... */
2433 ot->name = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console");
2434 ot->idname = "WM_OT_console_toggle";
2435 ot->description = N_("Toggle System Console");
2436
2437 ot->exec = wm_console_toggle_exec;
2439}
2440
2441#endif
2442
2445/* -------------------------------------------------------------------- */
2455 short region_type,
2456 bool (*poll)(bContext *C),
2457 wmPaintCursorDraw draw,
2458 void *customdata)
2459{
2460 wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
2461
2462 wmPaintCursor *pc = static_cast<wmPaintCursor *>(
2463 MEM_callocN(sizeof(wmPaintCursor), "paint cursor"));
2464
2465 BLI_addtail(&wm->paintcursors, pc);
2466
2467 pc->customdata = customdata;
2468 pc->poll = poll;
2469 pc->draw = draw;
2470
2471 pc->space_type = space_type;
2472 pc->region_type = region_type;
2473
2474 return pc;
2475}
2476
2478{
2479 wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
2481 if (pc == (wmPaintCursor *)handle) {
2482 BLI_remlink(&wm->paintcursors, pc);
2483 MEM_freeN(pc);
2484 return true;
2485 }
2486 }
2487 return false;
2488}
2489
2490void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void (*free)(void *))
2491{
2493 if (pc->draw == draw_fn) {
2494 if (free) {
2495 free(pc->customdata);
2496 }
2497 BLI_remlink(&wm->paintcursors, pc);
2498 MEM_freeN(pc);
2499 }
2500 }
2501}
2502
2505/* -------------------------------------------------------------------- */
2509#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_SCALE_FAC)
2510#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * UI_SCALE_FAC)
2511#define WM_RADIAL_CONTROL_DISPLAY_WIDTH \
2512 (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE)
2513#define WM_RADIAL_MAX_STR 10
2514
2536
2538{
2539 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
2540 char msg[UI_MAX_DRAW_STR];
2541 ScrArea *area = CTX_wm_area(C);
2542 Scene *scene = CTX_data_scene(C);
2543
2544 if (hasNumInput(&rc->num_input)) {
2545 char num_str[NUM_STR_REP_LEN];
2546 outputNumInput(&rc->num_input, num_str, &scene->unit);
2547 SNPRINTF(msg, "%s: %s", RNA_property_ui_name(rc->prop), num_str);
2548 }
2549 else {
2550 const char *ui_name = RNA_property_ui_name(rc->prop);
2551 switch (rc->subtype) {
2552 case PROP_NONE:
2553 case PROP_DISTANCE:
2554 SNPRINTF(msg, "%s: %0.4f", ui_name, rc->current_value);
2555 break;
2556 case PROP_PIXEL:
2557 SNPRINTF(msg, "%s: %d", ui_name, int(rc->current_value)); /* XXX: round to nearest? */
2558 break;
2559 case PROP_PERCENTAGE:
2560 SNPRINTF(msg, "%s: %3.1f%%", ui_name, rc->current_value);
2561 break;
2562 case PROP_FACTOR:
2563 SNPRINTF(msg, "%s: %1.3f", ui_name, rc->current_value);
2564 break;
2565 case PROP_ANGLE:
2566 SNPRINTF(msg, "%s: %3.2f", ui_name, RAD2DEGF(rc->current_value));
2567 break;
2568 default:
2569 SNPRINTF(msg, "%s", ui_name); /* XXX: No value? */
2570 break;
2571 }
2572 }
2573
2574 ED_area_status_text(area, msg);
2575}
2576
2578{
2579 float d[2] = {0, 0};
2580 float zoom[2] = {1, 1};
2581
2582 copy_v2_v2_int(rc->initial_mouse, event->xy);
2583 copy_v2_v2_int(rc->initial_co, event->xy);
2584
2585 switch (rc->subtype) {
2586 case PROP_NONE:
2587 case PROP_DISTANCE:
2588 case PROP_PIXEL:
2589 d[0] = rc->initial_value;
2590 break;
2591 case PROP_PERCENTAGE:
2592 d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
2594 break;
2595 case PROP_FACTOR:
2598 break;
2599 case PROP_ANGLE:
2602 break;
2603 default:
2604 return;
2605 }
2606
2607 if (rc->zoom_prop) {
2609 d[0] *= zoom[0];
2610 d[1] *= zoom[1];
2611 }
2612
2613 rc->initial_mouse[0] -= d[0];
2614 rc->initial_mouse[1] -= d[1];
2615}
2616
2618{
2619 ImBuf *ibuf;
2620
2621 switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) {
2622 case ID_BR:
2624 static_cast<Brush *>(rc->image_id_ptr.data),
2627 {
2628
2629 rc->texture = GPU_texture_create_2d("radial_control",
2630 ibuf->x,
2631 ibuf->y,
2632 1,
2633 GPU_R8,
2635 ibuf->float_buffer.data);
2636
2638 GPU_texture_swizzle_set(rc->texture, "111r");
2639
2641 MEM_freeN(ibuf);
2642 }
2643 break;
2644 default:
2645 break;
2646 }
2647}
2648
2649static void radial_control_paint_tex(RadialControl *rc, float radius, float alpha)
2650{
2651
2652 /* Set fill color. */
2653 float col[3] = {0, 0, 0};
2654 if (rc->fill_col_prop) {
2655 PointerRNA *fill_ptr;
2656 PropertyRNA *fill_prop;
2657
2658 if (rc->fill_col_override_prop &&
2660 {
2661 fill_ptr = &rc->fill_col_override_ptr;
2662 fill_prop = rc->fill_col_override_prop;
2663 }
2664 else {
2665 fill_ptr = &rc->fill_col_ptr;
2666 fill_prop = rc->fill_col_prop;
2667 }
2668
2669 RNA_property_float_get_array(fill_ptr, fill_prop, col);
2670 }
2671
2674
2675 if (rc->texture) {
2676 uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2677
2678 /* Set up rotation if available. */
2679 if (rc->rot_prop) {
2680 float rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop);
2683 }
2684
2686
2688 immBindTexture("image", rc->texture);
2689
2690 /* Draw textured quad. */
2692
2693 immAttr2f(texCoord, 0, 0);
2694 immVertex2f(pos, -radius, -radius);
2695
2696 immAttr2f(texCoord, 1, 0);
2697 immVertex2f(pos, radius, -radius);
2698
2699 immAttr2f(texCoord, 1, 1);
2700 immVertex2f(pos, radius, radius);
2701
2702 immAttr2f(texCoord, 0, 1);
2703 immVertex2f(pos, -radius, radius);
2704
2705 immEnd();
2706
2708
2709 /* Undo rotation. */
2710 if (rc->rot_prop) {
2712 }
2713 }
2714 else {
2715 /* Flat color if no texture available. */
2718 imm_draw_circle_fill_2d(pos, 0.0f, 0.0f, radius, 40);
2719 }
2720
2722}
2723
2724static void radial_control_paint_curve(uint pos, Brush *br, float radius, int line_segments)
2725{
2726 GPU_line_width(2.0f);
2727 immUniformColor4f(0.8f, 0.8f, 0.8f, 0.85f);
2728 float step = (radius * 2.0f) / float(line_segments);
2730 immBegin(GPU_PRIM_LINES, line_segments * 2);
2731 for (int i = 0; i < line_segments; i++) {
2732 float h1 = BKE_brush_curve_strength_clamped(br, fabsf((i * step) - radius), radius);
2733 immVertex2f(pos, -radius + (i * step), h1 * radius);
2734 float h2 = BKE_brush_curve_strength_clamped(br, fabsf(((i + 1) * step) - radius), radius);
2735 immVertex2f(pos, -radius + ((i + 1) * step), h2 * radius);
2736 }
2737 immEnd();
2738}
2739
2740static void radial_control_paint_cursor(bContext * /*C*/, int x, int y, void *customdata)
2741{
2742 RadialControl *rc = static_cast<RadialControl *>(customdata);
2743 const uiStyle *style = UI_style_get();
2744 const uiFontStyle *fstyle = &style->widget;
2745 const int fontid = fstyle->uifont_id;
2746 short fstyle_points = fstyle->points;
2747 char str[WM_RADIAL_MAX_STR];
2748 short strdrawlen = 0;
2749 float strwidth, strheight;
2750 float r1 = 0.0f, r2 = 0.0f, rmin = 0.0, tex_radius, alpha;
2751 float zoom[2], col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2752 float text_color[4];
2753
2754 switch (rc->subtype) {
2755 case PROP_NONE:
2756 case PROP_DISTANCE:
2757 case PROP_PIXEL:
2758 r1 = rc->current_value;
2759 r2 = rc->initial_value;
2760 tex_radius = r1;
2761 alpha = 0.75;
2762 break;
2763 case PROP_PERCENTAGE:
2766 r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2768 SNPRINTF(str, "%3.1f%%", rc->current_value);
2769 strdrawlen = BLI_strlen_utf8(str);
2770 tex_radius = r1;
2771 alpha = 0.75;
2772 break;
2773 case PROP_FACTOR:
2776 r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2778 alpha = rc->current_value / 2.0f + 0.5f;
2779 SNPRINTF(str, "%1.3f", rc->current_value);
2780 strdrawlen = BLI_strlen_utf8(str);
2781 break;
2782 case PROP_ANGLE:
2783 r1 = r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2784 alpha = 0.75;
2786 SNPRINTF(str, "%3.2f", RAD2DEGF(rc->current_value));
2787 strdrawlen = BLI_strlen_utf8(str);
2788 break;
2789 default:
2790 tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* NOTE: this is a dummy value. */
2791 alpha = 0.75;
2792 break;
2793 }
2794
2795 if (rc->subtype == PROP_ANGLE) {
2796 /* Use the initial mouse position to draw the rotation preview. This avoids starting the
2797 * rotation in a random direction. */
2798 x = rc->initial_mouse[0];
2799 y = rc->initial_mouse[1];
2800 }
2801 else {
2802 /* Keep cursor in the original place. */
2803 x = rc->initial_co[0];
2804 y = rc->initial_co[1];
2805 }
2806 GPU_matrix_translate_2f(float(x), float(y));
2807
2809 GPU_line_smooth(true);
2810
2811 /* Apply zoom if available. */
2812 if (rc->zoom_prop) {
2815 }
2816
2817 /* Draw rotated texture. */
2818 radial_control_paint_tex(rc, tex_radius, alpha);
2819
2820 /* Set line color. */
2821 if (rc->col_prop) {
2823 }
2824
2827
2829
2830 if (rc->subtype == PROP_ANGLE) {
2832
2833 /* Draw original angle line. */
2834 GPU_matrix_rotate_3f(RAD2DEGF(rc->initial_value), 0.0f, 0.0f, 1.0f);
2838 immEnd();
2839
2840 /* Draw new angle line. */
2841 GPU_matrix_rotate_3f(RAD2DEGF(rc->current_value - rc->initial_value), 0.0f, 0.0f, 1.0f);
2845 immEnd();
2846
2848 }
2849
2850 /* Draw circles on top. */
2851 GPU_line_width(2.0f);
2853 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 80);
2854
2855 GPU_line_width(1.0f);
2857 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 80);
2858 if (rmin > 0.0f) {
2859 /* Inner fill circle to increase the contrast of the value. */
2860 const float black[3] = {0.0f};
2861 immUniformColor3fvAlpha(black, 0.2f);
2862 imm_draw_circle_fill_2d(pos, 0.0, 0.0f, rmin, 80);
2863
2865 imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 80);
2866 }
2867
2868 /* Draw curve falloff preview. */
2870 Brush *br = static_cast<Brush *>(rc->image_id_ptr.data);
2871 if (br) {
2872 radial_control_paint_curve(pos, br, r2, 120);
2873 }
2874 }
2875
2877
2878 BLF_size(fontid, 1.75f * fstyle_points * UI_SCALE_FAC);
2879 UI_GetThemeColor4fv(TH_TEXT_HI, text_color);
2880 BLF_color4fv(fontid, text_color);
2881
2882 /* Draw value. */
2883 BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight);
2884 BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
2885 BLF_draw(fontid, str, strdrawlen);
2886
2888 GPU_line_smooth(false);
2889}
2890
2896
2903 wmOperator *op,
2904 const char *name,
2905 PointerRNA *r_ptr,
2906 PropertyRNA **r_prop,
2907 int req_length,
2908 RCPropFlags flags)
2909{
2910 PropertyRNA *unused_prop;
2911
2912 /* Check flags. */
2913 if ((flags & RC_PROP_REQUIRE_BOOL) && (flags & RC_PROP_REQUIRE_FLOAT)) {
2914 BKE_report(op->reports, RPT_ERROR, "Property cannot be both boolean and float");
2915 return 0;
2916 }
2917
2918 /* Get an rna string path from the operator's properties. */
2919 char *str;
2920 if (!(str = RNA_string_get_alloc(op->ptr, name, nullptr, 0, nullptr))) {
2921 return 1;
2922 }
2923
2924 if (str[0] == '\0') {
2925 if (r_prop) {
2926 *r_prop = nullptr;
2927 }
2928 MEM_freeN(str);
2929 return 1;
2930 }
2931
2932 if (!r_prop) {
2933 r_prop = &unused_prop;
2934 }
2935
2936 /* Get rna from path. */
2937 if (!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) {
2938 MEM_freeN(str);
2939 if (flags & RC_PROP_ALLOW_MISSING) {
2940 return 1;
2941 }
2942 BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name);
2943 return 0;
2944 }
2945
2946 /* Check property type. */
2948 PropertyType prop_type = RNA_property_type(*r_prop);
2949
2950 if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) ||
2951 ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT)))
2952 {
2953 MEM_freeN(str);
2954 BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name);
2955 return 0;
2956 }
2957 }
2958
2959 /* Check property's array length. */
2960 int len;
2961 if (*r_prop && (len = RNA_property_array_length(r_ptr, *r_prop)) != req_length) {
2962 MEM_freeN(str);
2963 BKE_reportf(op->reports,
2964 RPT_ERROR,
2965 "Property from path '%s' has length %d instead of %d",
2966 name,
2967 len,
2968 req_length);
2969 return 0;
2970 }
2971
2972 /* Success. */
2973 MEM_freeN(str);
2974 return 1;
2975}
2976
2977/* Initialize the rna pointers and properties using rna paths. */
2979{
2980 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
2981
2982 PointerRNA ctx_ptr = RNA_pointer_create(nullptr, &RNA_Context, C);
2983
2984 /* Check if we use primary or secondary path. */
2985 PointerRNA use_secondary_ptr;
2986 PropertyRNA *use_secondary_prop = nullptr;
2987 if (!radial_control_get_path(&ctx_ptr,
2988 op,
2989 "use_secondary",
2990 &use_secondary_ptr,
2991 &use_secondary_prop,
2992 0,
2994 {
2995 return 0;
2996 }
2997
2998 const char *data_path;
2999 if (use_secondary_prop && RNA_property_boolean_get(&use_secondary_ptr, use_secondary_prop)) {
3000 data_path = "data_path_secondary";
3001 }
3002 else {
3003 data_path = "data_path_primary";
3004 }
3005
3006 if (!radial_control_get_path(&ctx_ptr, op, data_path, &rc->ptr, &rc->prop, 0, RCPropFlags(0))) {
3007 return 0;
3008 }
3009
3010 /* Data path is required. */
3011 if (!rc->prop) {
3012 return 0;
3013 }
3014
3016 &ctx_ptr, op, "rotation_path", &rc->rot_ptr, &rc->rot_prop, 0, RC_PROP_REQUIRE_FLOAT))
3017 {
3018 return 0;
3019 }
3020
3022 &ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 4, RC_PROP_REQUIRE_FLOAT))
3023 {
3024 return 0;
3025 }
3026
3027 if (!radial_control_get_path(&ctx_ptr,
3028 op,
3029 "fill_color_path",
3030 &rc->fill_col_ptr,
3031 &rc->fill_col_prop,
3032 3,
3034 {
3035 return 0;
3036 }
3037
3038 if (!radial_control_get_path(&ctx_ptr,
3039 op,
3040 "fill_color_override_path",
3043 3,
3045 {
3046 return 0;
3047 }
3048 if (!radial_control_get_path(&ctx_ptr,
3049 op,
3050 "fill_color_override_test_path",
3053 0,
3055 {
3056 return 0;
3057 }
3058
3059 /* Slightly ugly; allow this property to not resolve correctly.
3060 * Needed because 3d texture paint shares the same key-map as 2d image paint. */
3061 if (!radial_control_get_path(&ctx_ptr,
3062 op,
3063 "zoom_path",
3064 &rc->zoom_ptr,
3065 &rc->zoom_prop,
3066 2,
3068 {
3069 return 0;
3070 }
3071
3073 &ctx_ptr, op, "image_id", &rc->image_id_ptr, nullptr, 0, RCPropFlags(0)))
3074 {
3075 return 0;
3076 }
3077 if (rc->image_id_ptr.data) {
3078 /* Extra check, pointer must be to an ID. */
3080 BKE_report(op->reports, RPT_ERROR, "Pointer from path image_id is not an ID");
3081 return 0;
3082 }
3083 }
3084
3085 rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex");
3086
3087 return 1;
3088}
3089
3090static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
3091{
3092 wmWindowManager *wm;
3093 RadialControl *rc;
3094
3095 if (!(op->customdata = rc = static_cast<RadialControl *>(
3096 MEM_callocN(sizeof(RadialControl), "RadialControl"))))
3097 {
3098 return OPERATOR_CANCELLED;
3099 }
3100
3101 if (!radial_control_get_properties(C, op)) {
3102 MEM_freeN(rc);
3103 return OPERATOR_CANCELLED;
3104 }
3105
3106 /* Get type, initial, min, and max values of the property. */
3107 switch (rc->type = RNA_property_type(rc->prop)) {
3108 case PROP_INT: {
3109 int value, min, max, step;
3110
3111 value = RNA_property_int_get(&rc->ptr, rc->prop);
3112 RNA_property_int_ui_range(&rc->ptr, rc->prop, &min, &max, &step);
3113
3114 rc->initial_value = value;
3115 rc->min_value = min_ii(value, min);
3116 rc->max_value = max_ii(value, max);
3117 break;
3118 }
3119 case PROP_FLOAT: {
3120 float value, min, max, step, precision;
3121
3122 value = RNA_property_float_get(&rc->ptr, rc->prop);
3123 RNA_property_float_ui_range(&rc->ptr, rc->prop, &min, &max, &step, &precision);
3124
3125 rc->initial_value = value;
3126 rc->min_value = min_ff(value, min);
3127 rc->max_value = max_ff(value, max);
3128 break;
3129 }
3130 default:
3131 BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float");
3132 MEM_freeN(rc);
3133 return OPERATOR_CANCELLED;
3134 }
3135
3136 /* Initialize numerical input. */
3137 initNumInput(&rc->num_input);
3138 rc->num_input.idx_max = 0;
3142
3143 /* Get subtype of property. */
3145 if (!ELEM(rc->subtype,
3146 PROP_NONE,
3150 PROP_ANGLE,
3151 PROP_PIXEL))
3152 {
3153 BKE_report(op->reports,
3154 RPT_ERROR,
3155 "Property must be a none, distance, factor, percentage, angle, or pixel");
3156 MEM_freeN(rc);
3157 return OPERATOR_CANCELLED;
3158 }
3159
3160 rc->current_value = rc->initial_value;
3163
3165
3166 /* Temporarily disable other paint cursors. */
3167 wm = CTX_wm_manager(C);
3170
3171 /* Add radial control paint cursor. */
3174
3176
3178}
3179
3180static void radial_control_set_value(RadialControl *rc, float val)
3181{
3182 switch (rc->type) {
3183 case PROP_INT:
3184 RNA_property_int_set(&rc->ptr, rc->prop, val);
3185 break;
3186 case PROP_FLOAT:
3187 RNA_property_float_set(&rc->ptr, rc->prop, val);
3188 break;
3189 default:
3190 break;
3191 }
3192}
3193
3195{
3196 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3198 ScrArea *area = CTX_wm_area(C);
3199
3200 MEM_SAFE_FREE(rc->dial);
3201
3202 ED_area_status_text(area, nullptr);
3203
3204 WM_paint_cursor_end(static_cast<wmPaintCursor *>(rc->cursor));
3205
3206 /* Restore original paint cursors. */
3208
3209 /* Not sure if this is a good notifier to use;
3210 * intended purpose is to update the UI so that the
3211 * new value is displayed in sliders/number-fields. */
3212 WM_event_add_notifier(C, NC_WINDOW, nullptr);
3213
3214 if (rc->texture != nullptr) {
3216 }
3217
3218 MEM_freeN(rc);
3219}
3220
3221static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
3222{
3223 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3224 float new_value, dist = 0.0f, zoom[2];
3225 float delta[2];
3227 float angle_precision = 0.0f;
3228 const bool has_numInput = hasNumInput(&rc->num_input);
3229 bool handled = false;
3230 float numValue;
3231 /* TODO: fix hard-coded events. */
3232
3233 bool snap = (event->modifier & KM_CTRL) != 0;
3234
3235 /* Modal numinput active, try to handle numeric inputs first... */
3236 if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) {
3237 handled = true;
3238 applyNumInput(&rc->num_input, &numValue);
3239
3240 if (rc->subtype == PROP_ANGLE) {
3241 numValue = fmod(numValue, 2.0f * float(M_PI));
3242 if (numValue < 0.0f) {
3243 numValue += 2.0f * float(M_PI);
3244 }
3245 }
3246
3247 CLAMP(numValue, rc->min_value, rc->max_value);
3248 new_value = numValue;
3249
3250 radial_control_set_value(rc, new_value);
3251 rc->current_value = new_value;
3254 }
3255
3256 handled = false;
3257 switch (event->type) {
3258 case EVT_ESCKEY:
3259 case RIGHTMOUSE:
3260 /* Canceled; restore original value. */
3261 if (rc->init_event != RIGHTMOUSE) {
3264 }
3265 break;
3266
3267 case LEFTMOUSE:
3268 case EVT_PADENTER:
3269 case EVT_RETKEY:
3270 /* Done; value already set. */
3271 RNA_property_update(C, &rc->ptr, rc->prop);
3273 break;
3274
3275 case MOUSEMOVE:
3276 if (!has_numInput) {
3277 if (rc->slow_mode) {
3278 if (rc->subtype == PROP_ANGLE) {
3279 /* Calculate the initial angle here first. */
3280 delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
3281 delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
3282
3283 /* Precision angle gets calculated from dial and gets added later. */
3284 angle_precision = -0.1f * BLI_dial_angle(rc->dial,
3285 blender::float2{float(event->xy[0]),
3286 float(event->xy[1])});
3287 }
3288 else {
3289 delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
3290 delta[1] = 0.0f;
3291
3292 if (rc->zoom_prop) {
3294 delta[0] /= zoom[0];
3295 }
3296
3297 dist = len_v2(delta);
3298
3299 delta[0] = event->xy[0] - rc->slow_mouse[0];
3300
3301 if (rc->zoom_prop) {
3302 delta[0] /= zoom[0];
3303 }
3304
3305 dist = dist + 0.1f * (delta[0]);
3306 }
3307 }
3308 else {
3309 delta[0] = float(rc->initial_mouse[0] - event->xy[0]);
3310 delta[1] = float(rc->initial_mouse[1] - event->xy[1]);
3311 if (rc->zoom_prop) {
3313 delta[0] /= zoom[0];
3314 delta[1] /= zoom[1];
3315 }
3316 if (rc->subtype == PROP_ANGLE) {
3317 dist = len_v2(delta);
3318 }
3319 else {
3320 dist = clamp_f(-delta[0], 0.0f, FLT_MAX);
3321 }
3322 }
3323
3324 /* Calculate new value and apply snapping. */
3325 switch (rc->subtype) {
3326 case PROP_NONE:
3327 case PROP_DISTANCE:
3328 case PROP_PIXEL:
3329 new_value = dist;
3330 if (snap) {
3331 new_value = (int(new_value) + 5) / 10 * 10;
3332 }
3333 break;
3334 case PROP_PERCENTAGE:
3335 new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) /
3337 100.0f;
3338 if (snap) {
3339 new_value = int(new_value + 2.5f) / 5 * 5;
3340 }
3341 break;
3342 case PROP_FACTOR:
3344 if (snap) {
3345 new_value = (int(ceil(new_value * 10.0f)) * 10.0f) / 100.0f;
3346 }
3347 /* Invert new value to increase the factor moving the mouse to the right. */
3348 new_value = 1 - new_value;
3349 break;
3350 case PROP_ANGLE:
3351 new_value = atan2f(delta[1], delta[0]) + float(M_PI) + angle_precision;
3352 new_value = fmod(new_value, 2.0f * float(M_PI));
3353 if (new_value < 0.0f) {
3354 new_value += 2.0f * float(M_PI);
3355 }
3356 if (snap) {
3357 new_value = DEG2RADF((int(RAD2DEGF(new_value)) + 5) / 10 * 10);
3358 }
3359 break;
3360 default:
3361 new_value = dist; /* NOTE(@ideasman42): Dummy value, should this ever happen? */
3362 break;
3363 }
3364
3365 /* Clamp and update. */
3366 CLAMP(new_value, rc->min_value, rc->max_value);
3367 radial_control_set_value(rc, new_value);
3368 rc->current_value = new_value;
3369 handled = true;
3370 break;
3371 }
3372 break;
3373
3374 case EVT_LEFTSHIFTKEY:
3375 case EVT_RIGHTSHIFTKEY: {
3376 if (event->val == KM_PRESS) {
3377 rc->slow_mouse[0] = event->xy[0];
3378 rc->slow_mouse[1] = event->xy[1];
3379 rc->slow_mode = true;
3380 if (rc->subtype == PROP_ANGLE) {
3381 const float initial_position[2] = {float(rc->initial_mouse[0]),
3382 float(rc->initial_mouse[1])};
3383 const float current_position[2] = {float(rc->slow_mouse[0]), float(rc->slow_mouse[1])};
3384 rc->dial = BLI_dial_init(initial_position, 0.0f);
3385 /* Immediately set the position to get a an initial direction. */
3386 BLI_dial_angle(rc->dial, current_position);
3387 }
3388 handled = true;
3389 }
3390 if (event->val == KM_RELEASE) {
3391 rc->slow_mode = false;
3392 handled = true;
3393 MEM_SAFE_FREE(rc->dial);
3394 }
3395 break;
3396 }
3397 }
3398
3399 /* Modal numinput inactive, try to handle numeric inputs last... */
3400 if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) {
3401 applyNumInput(&rc->num_input, &numValue);
3402
3403 if (rc->subtype == PROP_ANGLE) {
3404 numValue = fmod(numValue, 2.0f * float(M_PI));
3405 if (numValue < 0.0f) {
3406 numValue += 2.0f * float(M_PI);
3407 }
3408 }
3409
3410 CLAMP(numValue, rc->min_value, rc->max_value);
3411 new_value = numValue;
3412
3413 radial_control_set_value(rc, new_value);
3414
3415 rc->current_value = new_value;
3418 }
3419
3420 if (!handled && (event->val == KM_RELEASE) && (rc->init_event == event->type) &&
3421 RNA_boolean_get(op->ptr, "release_confirm"))
3422 {
3424 }
3425
3428
3429 if (ret & OPERATOR_FINISHED) {
3431 if (wm->op_undo_depth == 0) {
3432 ID *id = rc->ptr.owner_id;
3434 ED_undo_push(C, op->type->name);
3435 }
3436 }
3437 }
3438
3439 if (ret != OPERATOR_RUNNING_MODAL) {
3440 radial_control_cancel(C, op);
3441 }
3442
3443 return ret;
3444}
3445
3447{
3448 ot->name = "Radial Control";
3449 ot->idname = "WM_OT_radial_control";
3450 ot->description = "Set some size property (e.g. brush size) with mouse wheel";
3451
3455
3457
3458 /* All paths relative to the context. */
3459 PropertyRNA *prop;
3460 prop = RNA_def_string(ot->srna,
3461 "data_path_primary",
3462 nullptr,
3463 0,
3464 "Primary Data Path",
3465 "Primary path of property to be set by the radial control");
3467
3468 prop = RNA_def_string(ot->srna,
3469 "data_path_secondary",
3470 nullptr,
3471 0,
3472 "Secondary Data Path",
3473 "Secondary path of property to be set by the radial control");
3475
3476 prop = RNA_def_string(ot->srna,
3477 "use_secondary",
3478 nullptr,
3479 0,
3480 "Use Secondary",
3481 "Path of property to select between the primary and secondary data paths");
3483
3484 prop = RNA_def_string(ot->srna,
3485 "rotation_path",
3486 nullptr,
3487 0,
3488 "Rotation Path",
3489 "Path of property used to rotate the texture display");
3491
3492 prop = RNA_def_string(ot->srna,
3493 "color_path",
3494 nullptr,
3495 0,
3496 "Color Path",
3497 "Path of property used to set the color of the control");
3499
3500 prop = RNA_def_string(ot->srna,
3501 "fill_color_path",
3502 nullptr,
3503 0,
3504 "Fill Color Path",
3505 "Path of property used to set the fill color of the control");
3507
3508 prop = RNA_def_string(
3509 ot->srna, "fill_color_override_path", nullptr, 0, "Fill Color Override Path", "");
3511 prop = RNA_def_string(
3512 ot->srna, "fill_color_override_test_path", nullptr, 0, "Fill Color Override Test", "");
3514
3515 prop = RNA_def_string(ot->srna,
3516 "zoom_path",
3517 nullptr,
3518 0,
3519 "Zoom Path",
3520 "Path of property used to set the zoom level for the control");
3522
3523 prop = RNA_def_string(ot->srna,
3524 "image_id",
3525 nullptr,
3526 0,
3527 "Image ID",
3528 "Path of ID that is used to generate an image for the control");
3530
3531 prop = RNA_def_boolean(
3532 ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
3534
3535 prop = RNA_def_boolean(
3536 ot->srna, "release_confirm", false, "Confirm On Release", "Finish operation on key release");
3538}
3539
3542/* -------------------------------------------------------------------- */
3548/* Uses no type defines, fully local testing function anyway. */
3549
3551{
3552 wmWindow *win = CTX_wm_window(C);
3553 bScreen *screen = CTX_wm_screen(C);
3554
3555 CTX_wm_region_popup_set(C, nullptr);
3556
3557 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3558 ED_area_tag_redraw(area);
3559 }
3560 wm_draw_update(C);
3561
3562 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3563}
3564
3565enum {
3573};
3574
3576 {eRTDrawRegion, "DRAW", 0, "Draw Region", "Draw region"},
3577 {eRTDrawRegionSwap, "DRAW_SWAP", 0, "Draw Region & Swap", "Draw region and swap"},
3578 {eRTDrawWindow, "DRAW_WIN", 0, "Draw Window", "Draw window"},
3579 {eRTDrawWindowSwap, "DRAW_WIN_SWAP", 0, "Draw Window & Swap", "Draw window and swap"},
3580 {eRTAnimationStep, "ANIM_STEP", 0, "Animation Step", "Animation steps"},
3581 {eRTAnimationPlay, "ANIM_PLAY", 0, "Animation Play", "Animation playback"},
3582 {eRTUndo, "UNDO", 0, "Undo/Redo", "Undo and redo"},
3583 {0, nullptr, 0, nullptr, nullptr},
3584};
3585
3587 Scene *scene,
3588 Depsgraph *depsgraph,
3589 wmWindow *win,
3590 ScrArea *area,
3591 ARegion *region,
3592 const int type,
3593 const int cfra)
3594{
3595 if (type == eRTDrawRegion) {
3596 if (region) {
3597 wm_draw_region_test(C, area, region);
3598 }
3599 }
3600 else if (type == eRTDrawRegionSwap) {
3601 CTX_wm_region_popup_set(C, nullptr);
3602
3603 ED_region_tag_redraw(region);
3604 wm_draw_update(C);
3605
3606 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3607 }
3608 else if (type == eRTDrawWindow) {
3609 bScreen *screen = WM_window_get_active_screen(win);
3610
3611 CTX_wm_region_popup_set(C, nullptr);
3612
3613 LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
3614 CTX_wm_area_set(C, area_iter);
3615 LISTBASE_FOREACH (ARegion *, region_iter, &area_iter->regionbase) {
3616 if (!region_iter->visible) {
3617 continue;
3618 }
3619 CTX_wm_region_set(C, region_iter);
3620 wm_draw_region_test(C, area_iter, region_iter);
3621 }
3622 }
3623
3624 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3625
3626 CTX_wm_area_set(C, area);
3627 CTX_wm_region_set(C, region);
3628 }
3629 else if (type == eRTDrawWindowSwap) {
3631 }
3632 else if (type == eRTAnimationStep) {
3633 scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1;
3635 }
3636 else if (type == eRTAnimationPlay) {
3637 /* Play anim, return on same frame as started with. */
3638 int tot = (scene->r.efra - scene->r.sfra) + 1;
3639
3640 while (tot--) {
3641 /* TODO: ability to escape! */
3642 scene->r.cfra++;
3643 if (scene->r.cfra > scene->r.efra) {
3644 scene->r.cfra = scene->r.sfra;
3645 }
3646
3649 }
3650 }
3651 else { /* #eRTUndo. */
3652 /* Undo and redo, including depsgraph update since that can be a
3653 * significant part of the cost. */
3654 ED_undo_pop(C);
3656 ED_undo_redo(C);
3658 }
3659}
3660
3662{
3663 /* Check background mode as many of these actions use redrawing.
3664 * NOTE(@ideasman42): if it's useful to support undo or animation step this could
3665 * be allowed at the moment this seems like a corner case that isn't needed. */
3666 return !G.background && WM_operator_winactive(C);
3667}
3668
3670{
3671 Scene *scene = CTX_data_scene(C);
3672 wmWindow *win = CTX_wm_window(C);
3673 ScrArea *area = CTX_wm_area(C);
3674 ARegion *region = CTX_wm_region(C);
3676 const int type = RNA_enum_get(op->ptr, "type");
3677 const int iter = RNA_int_get(op->ptr, "iterations");
3678 const double time_limit = double(RNA_float_get(op->ptr, "time_limit"));
3679 const int cfra = scene->r.cfra;
3680 const char *infostr = "";
3681
3682 /* NOTE: Depsgraph is used to update scene for a new state, so no need to ensure evaluation
3683 * here.
3684 */
3685 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
3686
3687 WM_cursor_wait(true);
3688
3689 double time_start = BLI_time_now_seconds();
3690
3691 wm_window_make_drawable(wm, win);
3692
3693 int iter_steps = 0;
3694 for (int a = 0; a < iter; a++) {
3695 redraw_timer_step(C, scene, depsgraph, win, area, region, type, cfra);
3696 iter_steps += 1;
3697
3698 if (time_limit != 0.0) {
3699 if ((BLI_time_now_seconds() - time_start) > time_limit) {
3700 break;
3701 }
3702 a = 0;
3703 }
3704 }
3705
3706 double time_delta = (BLI_time_now_seconds() - time_start) * 1000;
3707
3709
3710 WM_cursor_wait(false);
3711
3712 BKE_reportf(op->reports,
3714 "%d \u00D7 %s: %.4f ms, average: %.8f ms",
3715 iter_steps,
3716 infostr,
3717 time_delta,
3718 time_delta / iter_steps);
3719
3720 return OPERATOR_FINISHED;
3721}
3722
3724{
3725 ot->name = "Redraw Timer";
3726 ot->idname = "WM_OT_redraw_timer";
3727 ot->description = "Simple redraw timer to test the speed of updating the interface";
3728
3732
3733 ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, eRTDrawRegion, "Type", "");
3735 ot->srna, "iterations", 10, 1, INT_MAX, "Iterations", "Number of times to redraw", 1, 1000);
3737 "time_limit",
3738 0.0,
3739 0.0,
3740 FLT_MAX,
3741 "Time Limit",
3742 "Seconds to run the test for (override iterations)",
3743 0.0,
3744 60.0);
3745}
3746
3749/* -------------------------------------------------------------------- */
3755static int memory_statistics_exec(bContext * /*C*/, wmOperator * /*op*/)
3756{
3758 return OPERATOR_FINISHED;
3759}
3760
3762{
3763 ot->name = "Memory Statistics";
3764 ot->idname = "WM_OT_memory_statistics";
3765 ot->description = "Print memory statistics to the console";
3766
3768}
3769
3772/* -------------------------------------------------------------------- */
3782
3783static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
3784{
3785 BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA));
3786
3787 /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
3788 * Same goes for ID with no user. */
3789 if (ID_IS_EDITABLE(id) && (id->us != 0)) {
3790 UI_icon_render_id(C, scene, id, ICON_SIZE_ICON, false);
3791 UI_icon_render_id(C, scene, id, ICON_SIZE_PREVIEW, false);
3792 }
3793}
3794
3796{
3797 const int cb_flag = cb_data->cb_flag;
3798
3800 return IDWALK_RET_NOP;
3801 }
3802
3803 PreviewsIDEnsureData *data = static_cast<PreviewsIDEnsureData *>(cb_data->user_data);
3804 ID *id = *cb_data->id_pointer;
3805
3806 if (id && (id->tag & ID_TAG_DOIT)) {
3807 BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA));
3808 previews_id_ensure(data->C, data->scene, id);
3809 id->tag &= ~ID_TAG_DOIT;
3810 }
3811
3812 return IDWALK_RET_NOP;
3813}
3814
3816{
3817 Main *bmain = CTX_data_main(C);
3818 ListBase *lb[] = {&bmain->materials,
3819 &bmain->textures,
3820 &bmain->images,
3821 &bmain->worlds,
3822 &bmain->lights,
3823 nullptr};
3824 PreviewsIDEnsureData preview_id_data;
3825
3826 /* We use ID_TAG_DOIT to check whether we have already handled a given ID or not. */
3827 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3828 for (int i = 0; lb[i]; i++) {
3830 }
3831
3832 preview_id_data.C = C;
3833 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3834 preview_id_data.scene = scene;
3835 ID *id = (ID *)scene;
3836
3838 nullptr, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
3839 }
3840
3841 /* Check a last time for ID not used (fake users only, in theory), and
3842 * do our best for those, using current scene... */
3843 for (int i = 0; lb[i]; i++) {
3844 LISTBASE_FOREACH (ID *, id, lb[i]) {
3845 if (id->tag & ID_TAG_DOIT) {
3846 previews_id_ensure(C, nullptr, id);
3847 id->tag &= ~ID_TAG_DOIT;
3848 }
3849 }
3850 }
3851
3852 return OPERATOR_FINISHED;
3853}
3854
3856{
3857 ot->name = "Refresh Data-Block Previews";
3858 ot->idname = "WM_OT_previews_ensure";
3859 ot->description =
3860 "Ensure data-block previews are available and up-to-date "
3861 "(to be saved in .blend file, only for some types like materials, textures, etc.)";
3862
3864}
3865
3868/* -------------------------------------------------------------------- */
3885
3886/* Only types supporting previews currently. */
3888 {PREVIEW_FILTER_ALL, "ALL", 0, "All Types", ""},
3890 "GEOMETRY",
3891 0,
3892 "All Geometry Types",
3893 "Clear previews for scenes, collections and objects"},
3895 "SHADING",
3896 0,
3897 "All Shading Types",
3898 "Clear previews for materials, lights, worlds, textures and images"},
3899 {PREVIEW_FILTER_SCENE, "SCENE", 0, "Scenes", ""},
3900 {PREVIEW_FILTER_COLLECTION, "COLLECTION", 0, "Collections", ""},
3901 {PREVIEW_FILTER_OBJECT, "OBJECT", 0, "Objects", ""},
3902 {PREVIEW_FILTER_MATERIAL, "MATERIAL", 0, "Materials", ""},
3903 {PREVIEW_FILTER_LIGHT, "LIGHT", 0, "Lights", ""},
3904 {PREVIEW_FILTER_WORLD, "WORLD", 0, "Worlds", ""},
3905 {PREVIEW_FILTER_TEXTURE, "TEXTURE", 0, "Textures", ""},
3906 {PREVIEW_FILTER_IMAGE, "IMAGE", 0, "Images", ""},
3907#if 0 /* XXX: TODO. */
3908 {PREVIEW_FILTER_BRUSH, "BRUSH", 0, "Brushes", ""},
3909#endif
3910 {0, nullptr, 0, nullptr, nullptr},
3911};
3912
3914{
3915 switch (filter) {
3916 case PREVIEW_FILTER_ALL:
3924 return FILTER_ID_SCE;
3926 return FILTER_ID_GR;
3928 return FILTER_ID_OB;
3930 return FILTER_ID_MA;
3932 return FILTER_ID_LA;
3934 return FILTER_ID_WO;
3936 return FILTER_ID_TE;
3938 return FILTER_ID_IM;
3939 }
3940
3941 return 0;
3942}
3943
3945{
3946 Main *bmain = CTX_data_main(C);
3947 ListBase *lb[] = {
3948 &bmain->objects,
3949 &bmain->collections,
3950 &bmain->materials,
3951 &bmain->worlds,
3952 &bmain->lights,
3953 &bmain->textures,
3954 &bmain->images,
3955 nullptr,
3956 };
3957
3958 const int id_filters = preview_filter_to_idfilter(
3959 PreviewFilterID(RNA_enum_get(op->ptr, "id_type")));
3960
3961 for (int i = 0; lb[i]; i++) {
3962 ID *id = static_cast<ID *>(lb[i]->first);
3963 if (!id) {
3964 continue;
3965 }
3966
3967#if 0
3968 printf("%s: %d, %d, %d -> %d\n",
3969 id->name,
3970 GS(id->name),
3972 id_filters,
3973 BKE_idtype_idcode_to_idfilter(GS(id->name)) & id_filters);
3974#endif
3975
3976 if (!(BKE_idtype_idcode_to_idfilter(GS(id->name)) & id_filters)) {
3977 continue;
3978 }
3979
3980 for (; id; id = static_cast<ID *>(id->next)) {
3982
3983 BKE_previewimg_clear(prv_img);
3984 }
3985 }
3986
3987 return OPERATOR_FINISHED;
3988}
3989
3991{
3992 ot->name = "Clear Data-Block Previews";
3993 ot->idname = "WM_OT_previews_clear";
3994 ot->description =
3995 "Clear data-block previews (only for some types like objects, materials, textures, etc.)";
3996
3999
4001 "id_type",
4004 "Data-Block Type",
4005 "Which data-block previews to clear");
4006}
4007
4010/* -------------------------------------------------------------------- */
4015{
4016 PointerRNA ptr_props;
4017 short retval = OPERATOR_CANCELLED;
4018
4019 if (std::optional<std::string> manual_id = UI_but_online_manual_id_from_active(C)) {
4020 WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
4021 RNA_string_set(&ptr_props, "doc_id", manual_id.value().c_str());
4022
4023 retval = WM_operator_name_call_ptr(C,
4024 WM_operatortype_find("WM_OT_doc_view_manual", false),
4026 &ptr_props,
4027 nullptr);
4028
4029 WM_operator_properties_free(&ptr_props);
4030 }
4031
4032 return retval;
4033}
4034
4036{
4037 /* Identifiers. */
4038 ot->name = "View Online Manual";
4039 ot->idname = "WM_OT_doc_view_manual_ui_context";
4040 ot->description = "View a context based online manual in a web browser";
4041
4042 /* Callbacks. */
4045}
4046
4049/* -------------------------------------------------------------------- */
4056{
4057 PropertyRNA *prop;
4058
4059 ot->name = "Set Stereo 3D";
4060 ot->idname = "WM_OT_set_stereo_3d";
4061 ot->description = "Toggle 3D stereo support for current window (or change the display mode)";
4062
4069
4070 prop = RNA_def_enum(ot->srna,
4071 "display_mode",
4074 "Display Mode",
4075 "");
4077 prop = RNA_def_enum(ot->srna,
4078 "anaglyph_type",
4081 "Anaglyph Type",
4082 "");
4084 prop = RNA_def_enum(ot->srna,
4085 "interlace_type",
4088 "Interlace Type",
4089 "");
4091 prop = RNA_def_boolean(ot->srna,
4092 "use_interlace_swap",
4093 false,
4094 "Swap Left/Right",
4095 "Swap left and right stereo channels");
4097 prop = RNA_def_boolean(ot->srna,
4098 "use_sidebyside_crosseyed",
4099 false,
4100 "Cross-Eyed",
4101 "Right eye should see left image and vice versa");
4103}
4104
4107/* -------------------------------------------------------------------- */
4112{
4151#if defined(WIN32)
4152 WM_operatortype_append(WM_OT_console_toggle);
4153#endif
4157
4158#ifdef WITH_XR_OPENXR
4160#endif
4161
4162 /* Gizmos. */
4165}
4166
4167/* Circle-select-like modal operators. */
4169{
4170 static const EnumPropertyItem modal_items[] = {
4171 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4172 {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
4173 {GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""},
4174 {GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""},
4175 {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""},
4176
4177 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4178 {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""},
4179 {GESTURE_MODAL_NOP, "NOP", 0, "No Operation", ""},
4180
4181 {0, nullptr, 0, nullptr, nullptr},
4182 };
4183
4184 /* WARNING: Name is incorrect, use for non-3d views. */
4185 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Gesture Circle");
4186
4187 /* This function is called for each space-type, only needs to add map once. */
4188 if (keymap && keymap->modal_items) {
4189 return;
4190 }
4191
4192 keymap = WM_modalkeymap_ensure(keyconf, "View3D Gesture Circle", modal_items);
4193
4194 /* Assign map to operators. */
4195 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle");
4196 WM_modalkeymap_assign(keymap, "UV_OT_select_circle");
4197 WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle");
4198 WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
4199 WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
4200 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
4201 WM_modalkeymap_assign(keymap, "ACTION_OT_select_circle");
4202}
4203
4204/* Straight line modal operators. */
4206{
4207 static const EnumPropertyItem modal_items[] = {
4208 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4209 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4210 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4211 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4212 {GESTURE_MODAL_SNAP, "SNAP", 0, "Snap", ""},
4213 {GESTURE_MODAL_FLIP, "FLIP", 0, "Flip", ""},
4214 {0, nullptr, 0, nullptr, nullptr},
4215 };
4216
4217 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Straight Line");
4218
4219 /* This function is called for each space-type, only needs to add map once. */
4220 if (keymap && keymap->modal_items) {
4221 return;
4222 }
4223
4224 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Straight Line", modal_items);
4225
4226 /* Assign map to operators. */
4227 WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line");
4228 WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
4229 WM_modalkeymap_assign(keymap, "MESH_OT_bisect");
4230 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_line_gesture");
4231 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_line_gesture");
4232 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_line_gesture");
4233 WM_modalkeymap_assign(keymap, "SCULPT_OT_project_line_gesture");
4234 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_line_gesture");
4235}
4236
4237/* Box_select-like modal operators. */
4239{
4240 static const EnumPropertyItem modal_items[] = {
4241 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4242 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4243 {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""},
4244 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4245 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4246 {0, nullptr, 0, nullptr, nullptr},
4247 };
4248
4249 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Box");
4250
4251 /* This function is called for each space-type, only needs to add map once. */
4252 if (keymap && keymap->modal_items) {
4253 return;
4254 }
4255
4256 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Box", modal_items);
4257
4258 /* Assign map to operators. */
4259 WM_modalkeymap_assign(keymap, "ACTION_OT_select_box");
4260 WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_box");
4261 WM_modalkeymap_assign(keymap, "ANIM_OT_previewrange_set");
4262 WM_modalkeymap_assign(keymap, "INFO_OT_select_box");
4263 WM_modalkeymap_assign(keymap, "FILE_OT_select_box");
4264 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_box");
4265 WM_modalkeymap_assign(keymap, "MARKER_OT_select_box");
4266 WM_modalkeymap_assign(keymap, "NLA_OT_select_box");
4267 WM_modalkeymap_assign(keymap, "NODE_OT_select_box");
4268 WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border");
4269 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show");
4270 WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_box");
4271#if 0 /* Template. */
4272 WM_modalkeymap_assign(keymap, "SCREEN_OT_box_select");
4273#endif
4274 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_box");
4275 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border");
4276 WM_modalkeymap_assign(keymap, "UV_OT_select_box");
4277 WM_modalkeymap_assign(keymap, "CLIP_OT_select_box");
4278 WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box");
4279 WM_modalkeymap_assign(keymap, "MASK_OT_select_box");
4280 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_box_gesture");
4281 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_box_gesture");
4282 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_box_gesture");
4283 WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
4284 WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border");
4285 WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border");
4286 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_box");
4287 /* XXX TODO: zoom border should perhaps map right-mouse to zoom out instead of in+cancel. */
4288 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border");
4289 WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border");
4290 WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
4291}
4292
4293/* Lasso modal operators. */
4295{
4296 static const EnumPropertyItem modal_items[] = {
4297 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4298 {0, nullptr, 0, nullptr, nullptr},
4299 };
4300
4301 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Lasso");
4302
4303 /* This function is called for each space-type, only needs to add map once. */
4304 if (keymap && keymap->modal_items) {
4305 return;
4306 }
4307
4308 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Lasso", modal_items);
4309
4310 /* Assign map to operators. */
4311 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_lasso");
4312 WM_modalkeymap_assign(keymap, "MASK_OT_select_lasso");
4313 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_lasso_gesture");
4314 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_lasso_gesture");
4315 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_lasso_gesture");
4316 WM_modalkeymap_assign(keymap, "ACTION_OT_select_lasso");
4317 WM_modalkeymap_assign(keymap, "CLIP_OT_select_lasso");
4318 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_lasso");
4319 WM_modalkeymap_assign(keymap, "NODE_OT_select_lasso");
4320 WM_modalkeymap_assign(keymap, "UV_OT_select_lasso");
4321 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_lasso_gesture");
4322}
4323
4324/* Polyline modal operators */
4326{
4327 static const EnumPropertyItem modal_items[] = {
4328 {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
4329 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4330 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4331 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4332 {0, nullptr, 0, nullptr, nullptr},
4333 };
4334
4335 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Polyline");
4336
4337 /* This function is called for each space-type, only needs to add map once. */
4338 if (keymap && keymap->modal_items) {
4339 return;
4340 }
4341
4342 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Polyline", modal_items);
4343
4344 /* assign map to operators */
4345 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_polyline_gesture");
4346 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_polyline_gesture");
4347 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_polyline_gesture");
4348 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_polyline_gesture");
4349}
4350
4351/* Zoom to border modal operators. */
4353{
4354 static const EnumPropertyItem modal_items[] = {
4355 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4356 {GESTURE_MODAL_IN, "IN", 0, "In", ""},
4357 {GESTURE_MODAL_OUT, "OUT", 0, "Out", ""},
4358 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4359 {0, nullptr, 0, nullptr, nullptr},
4360 };
4361
4362 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Zoom Border");
4363
4364 /* This function is called for each space-type, only needs to add map once. */
4365 if (keymap && keymap->modal_items) {
4366 return;
4367 }
4368
4369 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Zoom Border", modal_items);
4370
4371 /* Assign map to operators. */
4372 WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
4373 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border");
4374 WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
4375}
4376
4378{
4379 WM_keymap_ensure(keyconf, "Window", SPACE_EMPTY, RGN_TYPE_WINDOW);
4380
4381 wm_gizmos_keymap(keyconf);
4383 gesture_box_modal_keymap(keyconf);
4388
4390}
4391
4394/* -------------------------------------------------------------------- */
4402static bool rna_id_enum_filter_single(const ID *id, void *user_data)
4403{
4404 return (id != user_data);
4405}
4406
4407/* Generic itemf's for operators that take library args. */
4408static const EnumPropertyItem *rna_id_itemf(bool *r_free,
4409 ID *id,
4410 bool local,
4411 bool (*filter_ids)(const ID *id, void *user_data),
4412 void *user_data)
4413{
4414 EnumPropertyItem item_tmp = {0}, *item = nullptr;
4415 int totitem = 0;
4416 int i = 0;
4417
4418 if (id != nullptr) {
4419 const short id_type = GS(id->name);
4420 for (; id; id = static_cast<ID *>(id->next)) {
4421 if ((filter_ids != nullptr) && filter_ids(id, user_data) == false) {
4422 i++;
4423 continue;
4424 }
4425 if (local == false || !ID_IS_LINKED(id)) {
4426 item_tmp.identifier = item_tmp.name = id->name + 2;
4427 item_tmp.value = i++;
4428
4429 /* Show collection color tag icons in menus. */
4430 if (id_type == ID_GR) {
4432 }
4433
4434 RNA_enum_item_add(&item, &totitem, &item_tmp);
4435 }
4436 }
4437 }
4438
4439 RNA_enum_item_end(&item, &totitem);
4440 *r_free = true;
4441
4442 return item;
4443}
4444
4445/* Can add more ID types as needed. */
4446
4448 PointerRNA * /*ptr*/,
4449 PropertyRNA * /*prop*/,
4450 bool *r_free)
4451{
4452
4453 return rna_id_itemf(
4454 r_free, C ? (ID *)CTX_data_main(C)->actions.first : nullptr, false, nullptr, nullptr);
4455}
4456#if 0 /* UNUSED. */
4457const EnumPropertyItem *RNA_action_local_itemf(bContext *C,
4458 PointerRNA * /*ptr*/,
4459 PropertyRNA * /*prop*/,
4460 bool *r_free)
4461{
4462 return rna_id_itemf(r_free, C ? (ID *)CTX_data_main(C)->action.first : nullptr, true);
4463}
4464#endif
4465
4467 PointerRNA * /*ptr*/,
4468 PropertyRNA * /*prop*/,
4469 bool *r_free)
4470{
4471 return rna_id_itemf(
4472 r_free, C ? (ID *)CTX_data_main(C)->collections.first : nullptr, false, nullptr, nullptr);
4473}
4475 PointerRNA * /*ptr*/,
4476 PropertyRNA * /*prop*/,
4477 bool *r_free)
4478{
4479 return rna_id_itemf(
4480 r_free, C ? (ID *)CTX_data_main(C)->collections.first : nullptr, true, nullptr, nullptr);
4481}
4482
4484 PointerRNA * /*ptr*/,
4485 PropertyRNA * /*prop*/,
4486 bool *r_free)
4487{
4488 return rna_id_itemf(
4489 r_free, C ? (ID *)CTX_data_main(C)->images.first : nullptr, false, nullptr, nullptr);
4490}
4492 PointerRNA * /*ptr*/,
4493 PropertyRNA * /*prop*/,
4494 bool *r_free)
4495{
4496 return rna_id_itemf(
4497 r_free, C ? (ID *)CTX_data_main(C)->images.first : nullptr, true, nullptr, nullptr);
4498}
4499
4501 PointerRNA * /*ptr*/,
4502 PropertyRNA * /*prop*/,
4503 bool *r_free)
4504{
4505 return rna_id_itemf(
4506 r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, false, nullptr, nullptr);
4507}
4509 PointerRNA * /*ptr*/,
4510 PropertyRNA * /*prop*/,
4511 bool *r_free)
4512{
4513 return rna_id_itemf(
4514 r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, true, nullptr, nullptr);
4515}
4517 PointerRNA * /*ptr*/,
4518 PropertyRNA * /*prop*/,
4519 bool *r_free)
4520{
4521 Scene *scene_active = C ? CTX_data_scene(C) : nullptr;
4522 return rna_id_itemf(r_free,
4523 C ? (ID *)CTX_data_main(C)->scenes.first : nullptr,
4524 false,
4526 scene_active);
4527}
4529 PointerRNA * /*ptr*/,
4530 PropertyRNA * /*prop*/,
4531 bool *r_free)
4532{
4533 return rna_id_itemf(
4534 r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : nullptr, false, nullptr, nullptr);
4535}
4537 PointerRNA * /*ptr*/,
4538 PropertyRNA * /*prop*/,
4539 bool *r_free)
4540{
4541 return rna_id_itemf(
4542 r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : nullptr, true, nullptr, nullptr);
4543}
4544
4546 PointerRNA * /*ptr*/,
4547 PropertyRNA * /*prop*/,
4548 bool *r_free)
4549{
4550 return rna_id_itemf(
4551 r_free, C ? (ID *)CTX_data_main(C)->masks.first : nullptr, false, nullptr, nullptr);
4552}
4554 PointerRNA * /*ptr*/,
4555 PropertyRNA * /*prop*/,
4556 bool *r_free)
4557{
4558 return rna_id_itemf(
4559 r_free, C ? (ID *)CTX_data_main(C)->masks.first : nullptr, true, nullptr, nullptr);
4560}
4561
bool id_type_can_have_animdata(short id_type)
Definition anim_data.cc:70
ImBuf * BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
Definition brush.cc:1484
float BKE_brush_curve_strength_clamped(const Brush *br, float p, float len)
Definition brush.cc:1444
void BKE_curvemapping_init(CurveMapping *cumap)
ReportList * CTX_wm_reports(const bContext *C)
bScreen * CTX_wm_screen(const bContext *C)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
ListBase CTX_data_dir_get_ex(const bContext *C, bool use_store, bool use_rna, bool use_all)
SpaceLink * CTX_wm_space_data(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
void CTX_wm_window_set(bContext *C, wmWindow *win)
Main * CTX_data_main(const bContext *C)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void CTX_wm_region_popup_set(bContext *C, ARegion *region_popup)
View3D * CTX_wm_view3d(const bContext *C)
#define G_MAIN
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:763
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1227
void IDP_ClearProperty(IDProperty *prop)
Definition idprop.cc:1233
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:722
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, bool do_overwrite) ATTR_NONNULL()
Definition idprop.cc:717
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:669
uint64_t BKE_idtype_idcode_to_idfilter(short idcode)
Definition idtype.cc:369
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:168
Image * BKE_image_load_exists(Main *bmain, const char *filepath, bool *r_exists=nullptr)
int BKE_image_path_ext_from_imformat_ensure(char *filepath, size_t filepath_maxncpy, const ImageFormatData *im_format)
void id_us_plus(ID *id)
Definition lib_id.cc:351
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1175
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1198
@ IDWALK_RET_NOP
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_EMBEDDED
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, int flag)
Definition lib_query.cc:416
@ IDWALK_RECURSE
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
General operations, lookup, etc. for materials.
PreviewImage * BKE_previewimg_id_ensure(ID *id)
void BKE_previewimg_clear(PreviewImage *prv)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2647
#define BKE_ST_MAXNAME
Definition BKE_screen.hh:66
void BLF_size(int fontid, float size)
Definition blf.cc:426
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition blf.cc:778
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:488
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:393
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:568
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:791
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:371
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
Dial * BLI_dial_init(const float start_position[2], float threshold)
Definition BLI_dial_2d.c:37
float BLI_dial_angle(Dial *dial, const float current_position[2])
Definition BLI_dial_2d.c:47
void BLI_kdtree_nd_ free(KDTree *tree)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
#define M_PI
#define DEG2RADF(_deg)
#define RAD2DEGF(_rad)
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
#define BLI_SCOPED_DEFER(function_to_defer)
#define FILE_MAX
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
void BLI_str_toupper_ascii(char *str, size_t len) ATTR_NONNULL(1)
Definition string.c:961
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
void BLI_str_tolower_ascii(char *str, size_t len) ATTR_NONNULL(1)
Definition string.c:952
char char size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define CLAMP(a, b, c)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define STREQ(a, b)
#define RPT_(msgid)
#define CTX_N_(context, msgid)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
typedef double(DMatrix)[4][4]
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
ID and Library types, which are fundamental for SDNA.
#define FILTER_ID_OB
Definition DNA_ID.h:1181
#define FILTER_ID_MA
Definition DNA_ID.h:1175
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define MAX_ID_NAME
Definition DNA_ID.h:377
#define FILTER_ID_LA
Definition DNA_ID.h:1172
#define FILTER_ID_GR
Definition DNA_ID.h:1170
#define FILTER_ID_TE
Definition DNA_ID.h:1187
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
#define FILTER_ID_IM
Definition DNA_ID.h:1171
#define FILTER_ID_SCE
Definition DNA_ID.h:1184
#define FILTER_ID_WO
Definition DNA_ID.h:1190
@ ICON_SIZE_PREVIEW
@ ICON_SIZE_ICON
ID_Type
@ ID_AR
@ ID_TE
@ ID_IM
@ ID_LA
@ ID_SCE
@ ID_BR
@ ID_WO
@ ID_MA
@ ID_SCR
@ ID_GR
@ ID_OB
@ IDP_FLAG_GHOST
Object is a sort of wrapper for general info.
@ OB_FONT
#define OB_DATA_SUPPORT_ID_CASE
@ USER_UNIT_NONE
@ S3D_ANAGLYPH_REDCYAN
@ S3D_DISPLAY_ANAGLYPH
@ S3D_INTERLACE_ROW
@ SCREENFULL
@ SCREENNORMAL
@ RGN_TYPE_WINDOW
#define RGN_TYPE_ANY
@ SPACE_TEXT
@ SPACE_ACTION
@ SPACE_CONSOLE
@ SPACE_NODE
@ SPACE_FILE
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
#define SPACE_TYPE_ANY
@ USER_SAVE_PROMPT
@ USER_GLOBALUNDO
#define UI_SCALE_FAC
#define OP_MAX_TYPENAME
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define OPERATOR_RETVAL_CHECK(ret)
FileSelectParams * ED_fileselect_get_active_params(const SpaceFile *sfile)
Definition filesel.cc:380
void initNumInput(NumInput *n)
Definition numinput.cc:70
#define NUM_STR_REP_LEN
void outputNumInput(NumInput *n, char *str, const UnitSettings *unit_settings)
Definition numinput.cc:88
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:312
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:190
@ NUM_NO_NEGATIVE
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:803
void ED_screen_refresh(bContext *C, wmWindowManager *wm, wmWindow *win)
bool ED_operator_regionactive(bContext *C)
Definition screen_ops.cc:94
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:104
void ED_undo_push_op(bContext *C, wmOperator *op)
Definition ed_undo.cc:381
bool ED_undo_is_legacy_compatible_for_property(bContext *C, ID *id)
Definition ed_undo.cc:427
bool ED_undo_is_valid(const bContext *C, const char *undoname)
Definition ed_undo.cc:403
int ED_undo_operator_repeat(bContext *C, wmOperator *op)
Definition ed_undo.cc:644
void ED_undo_redo(bContext *C)
Definition ed_undo.cc:376
void ED_undo_pop(bContext *C)
Definition ed_undo.cc:372
float ED_view3d_grid_scale(const Scene *scene, const View3D *v3d, const char **r_grid_unit)
float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit)
GHOST C-API function and type declarations.
bool GHOST_setConsoleWindowState(GHOST_TConsoleWindowState action)
@ GHOST_kConsoleWindowStateToggle
void immEnd()
void immUnbindProgram()
void immUniformColor4f(float r, float g, float b, float a)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBindTexture(const char *name, GPUTexture *tex)
GPUVertFormat * immVertexFormat()
void immAttr2f(uint attr_id, float x, float y)
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
void GPU_matrix_scale_2fv(const float vec[2])
void GPU_matrix_push()
void GPU_matrix_rotate_2d(float deg)
void GPU_matrix_rotate_3f(float deg, float x, float y, float z)
void GPU_matrix_pop()
void GPU_matrix_translate_2f(float x, float y)
@ GPU_PRIM_TRI_FAN
@ GPU_PRIM_LINES
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_IMAGE_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_line_width(float width)
Definition gpu_state.cc:161
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
void GPU_texture_unbind(GPUTexture *texture)
@ GPU_TEXTURE_USAGE_SHADER_READ
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
@ GPU_R8
void GPU_texture_swizzle_set(GPUTexture *texture, const char swizzle[4])
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
#define RNA_PROP_END
#define RNA_STRUCT_BEGIN(sptr, prop)
#define RNA_STRUCT_END
short RNA_type_to_ID_code(const StructRNA *type)
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
#define RNA_SUBTYPE_UNIT_VALUE(subtype)
Definition RNA_types.hh:123
@ PROP_STRING_SEARCH_SUGGESTION
Definition RNA_types.hh:584
@ PROP_STRING_SEARCH_SORT
Definition RNA_types.hh:577
PropertyType
Definition RNA_types.hh:64
@ PROP_FLOAT
Definition RNA_types.hh:67
@ PROP_BOOLEAN
Definition RNA_types.hh:65
@ PROP_ENUM
Definition RNA_types.hh:69
@ PROP_INT
Definition RNA_types.hh:66
@ PROP_POINTER
Definition RNA_types.hh:70
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:319
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_SKIP_PRESET
Definition RNA_types.hh:343
PropertySubType
Definition RNA_types.hh:135
@ PROP_DISTANCE
Definition RNA_types.hh:159
@ PROP_PIXEL
Definition RNA_types.hh:151
@ PROP_ANGLE
Definition RNA_types.hh:155
@ PROP_NONE
Definition RNA_types.hh:136
@ PROP_PERCENTAGE
Definition RNA_types.hh:153
@ PROP_FACTOR
Definition RNA_types.hh:154
#define C
Definition RandGen.cpp:29
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
@ UI_RETURN_CANCEL
@ UI_RETURN_OK
#define UI_UNIT_Y
void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, const int active=-1)
@ UI_EMBOSS
void UI_popup_menu_retval_set(const uiBlock *block, int retval, bool enable)
void UI_block_theme_style_set(uiBlock *block, char theme_style)
void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
@ UI_BLOCK_SEARCH_MENU
@ UI_BLOCK_NUMSELECT
@ UI_BLOCK_LOOP
@ UI_BLOCK_MOVEMOUSE_QUIT
@ UI_BLOCK_KEEP_OPEN
uiLayout * uiItemsAlertBox(uiBlock *block, const uiStyle *style, const int dialog_width, const eAlertIcon icon, const int icon_size)
void uiLayoutSetScaleY(uiLayout *layout, float scale)
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
Definition interface.cc:590
@ UI_BUT2_ACTIVATE_ON_INIT_NO_SELECT
void UI_popup_dummy_panel_set(ARegion *region, uiBlock *block)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
void uiItemL(uiLayout *layout, const char *name, int icon)
void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
const uiStyle * UI_style_get_dpi()
std::optional< std::string > UI_but_online_manual_id_from_active(const bContext *C) ATTR_WARN_UNUSED_RESULT
void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, wmOperator *op)
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free, bool can_refresh)
void UI_block_flag_disable(uiBlock *block, int flag)
void UI_but_flag2_enable(uiBut *but, int flag)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss)
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
@ UI_BUT_LABEL_ALIGN_SPLIT_COLUMN
@ UI_BUT_LABEL_ALIGN_NONE
@ UI_BUT_LABEL_ALIGN_COLUMN
void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
int UI_searchbox_size_x()
bool UI_block_has_active_default_button(const uiBlock *block)
void uiItemS_ex(uiLayout *layout, float factor, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiBut * uiDefSearchButO_ptr(uiBlock *block, wmOperatorType *ot, IDProperty *properties, void *arg, int retval, int icon, int maxncpy, int x, int y, short width, short height, const char *tip)
#define UI_ITEM_NONE
void UI_but_func_operator_search(uiBut *but)
const uiStyle * UI_style_get()
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
void uiTemplateOperatorPropertyButs(const bContext *C, uiLayout *layout, wmOperator *op, eButLabelAlign label_align, short flag)
void UI_fontstyle_set(const uiFontStyle *fs)
#define UI_MAX_DRAW_STR
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
@ UI_LAYOUT_VERTICAL
int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, ReportList *reports)
int UI_searchbox_size_y()
@ UI_LAYOUT_PANEL
uiBut * uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxncpy, int x, int y, short width, short height, const char *tip)
@ UI_BLOCK_THEME_STYLE_REGULAR
@ UI_BLOCK_THEME_STYLE_POPUP
int uiLayoutGetWidth(uiLayout *layout)
void UI_block_bounds_set_centered(uiBlock *block, int addval)
Definition interface.cc:616
int UI_pie_menu_invoke(bContext *C, const char *idname, const wmEvent *event)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
uiLayout * uiLayoutSplit(uiLayout *layout, float percentage, bool align)
void UI_but_func_menu_search(uiBut *but, const char *single_menu_idname=nullptr)
#define UI_DEFAULT_TEXT_POINTS
#define UI_UNIT_X
void UI_block_flag_enable(uiBlock *block, int flag)
@ UI_BTYPE_BUT
@ UI_BTYPE_LABEL
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) ATTR_NONNULL(1
uiBut * uiItemL_ex(uiLayout *layout, const char *name, int icon, bool highlight, bool redalert)
void UI_but_flag_enable(uiBut *but, int flag)
@ UI_BUT_ACTIVE_DEFAULT
@ UI_BUT_ACTIVATE_ON_INIT
void UI_icon_render_id(const bContext *C, Scene *scene, ID *id, enum eIconSizes size, bool use_job)
@ ALERT_ICON_MAX
@ ALERT_ICON_NONE
@ ALERT_ICON_INFO
@ ALERT_ICON_WARNING
@ ALERT_ICON_QUESTION
@ ALERT_ICON_ERROR
int UI_icon_color_from_collection(const Collection *collection)
@ TH_TEXT_HI
void UI_GetThemeColor4fv(int colorid, float col[4])
@ WM_JOB_TYPE_ANY
Definition WM_api.hh:1575
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
@ OPTYPE_BLOCKING
Definition WM_types.hh:164
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_WINDOW
Definition WM_types.hh:342
CLG_LogRef * WM_LOG_OPERATORS
@ KM_PRESS
Definition WM_types.hh:284
@ KM_RELEASE
Definition WM_types.hh:285
wmPopupSize
Definition WM_types.hh:939
@ WM_POPUP_SIZE_LARGE
Definition WM_types.hh:941
@ WM_POPUP_SIZE_SMALL
Definition WM_types.hh:940
void(*)(bContext *C, int, int, void *customdata) wmPaintCursorDraw
Definition WM_types.hh:1148
wmOperatorCallContext
Definition WM_types.hh:216
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:219
@ WM_OP_EXEC_DEFAULT
Definition WM_types.hh:225
@ KM_CTRL
Definition WM_types.hh:256
wmPopupPosition
Definition WM_types.hh:944
@ WM_POPUP_POSITION_MOUSE
Definition WM_types.hh:945
@ WM_POPUP_POSITION_CENTER
Definition WM_types.hh:946
unsigned int U
Definition btGjkEpa3.h:78
constexpr StringRef trim() const
int64_t size() const
void append(const T &value)
local_group_size(16, 16) .push_constant(Type rhs
#define printf
const Depsgraph * depsgraph
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define fabsf(x)
int len
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define rot(x, k)
#define str(s)
uint col
uint padding(uint offset, uint alignment)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition iris.cc:202
format
void(* MEM_printmemlist_stats)(void)
Definition mallocn.cc:58
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float3 ceil(const float3 a)
#define G(x, y, z)
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
bool asset_shelf_popover_invoke(bContext &C, blender::StringRef asset_shelf_idname, ReportList &reports)
vector snap(vector a, vector b)
Definition node_math.h:65
return ret
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
bool RNA_property_array_check(PropertyRNA *prop)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
std::string RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
bool RNA_struct_is_ID(const StructRNA *type)
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
PropertyUnit RNA_property_unit(PropertyRNA *prop)
bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
PropertyType RNA_property_type(PropertyRNA *prop)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
std::string RNA_pointer_as_string_keywords(bContext *C, PointerRNA *ptr, const bool as_function, const bool all_args, const bool nested_args, const int max_prop_length)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_property_float_get_default(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_flag(PropertyRNA *prop)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_enum_description(const EnumPropertyItem *item, const int value, const char **r_description)
const char * RNA_property_ui_name(const PropertyRNA *prop)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
std::string RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
std::string RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length)
PropertyRNA * RNA_struct_iterator_property(StructRNA *type)
const char * RNA_property_identifier(const PropertyRNA *prop)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void RNA_def_property_string_search_func_runtime(PropertyRNA *prop, StringPropertySearchFunc search_fn, const eStringPropertySearchFlag search_flag)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
std::optional< std::string > RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition rna_path.cc:1007
std::optional< std::string > RNA_path_full_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
Definition rna_path.cc:1311
std::string RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
Definition rna_path.cc:1345
bool RNA_path_resolve(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:525
const EnumPropertyItem rna_enum_stereo3d_display_items[]
Definition rna_scene.cc:502
const EnumPropertyItem rna_enum_stereo3d_anaglyph_type_items[]
Definition rna_scene.cc:534
const EnumPropertyItem rna_enum_stereo3d_interlace_type_items[]
Definition rna_scene.cc:541
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
struct CurveMapping * curve
const char * identifier
Definition RNA_types.hh:506
const char * name
Definition RNA_types.hh:510
wmOperator * op
ListBase group
Definition DNA_ID.h:146
short flag
Definition DNA_ID.h:161
char name[64]
Definition DNA_ID.h:163
IDPropertyData data
Definition DNA_ID.h:168
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
ImBufFloatBuffer float_buffer
void * data
struct LinkData * next
void * first
ListBase scenes
Definition BKE_main.hh:210
ListBase textures
Definition BKE_main.hh:217
ListBase lights
Definition BKE_main.hh:220
ListBase materials
Definition BKE_main.hh:216
ListBase worlds
Definition BKE_main.hh:224
ListBase collections
Definition BKE_main.hh:231
ListBase images
Definition BKE_main.hh:218
ListBase objects
Definition BKE_main.hh:212
char label[BKE_ST_MAXNAME]
char translation_context[BKE_ST_MAXNAME]
short idx_max
short val_flag[NUM_MAX_ELEMENTS]
int unit_type[NUM_MAX_ELEMENTS]
char translation_context[BKE_ST_MAXNAME]
char label[BKE_ST_MAXNAME]
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
PropertySubType subtype
GPUTexture * texture
PropertyRNA * prop
PointerRNA fill_col_override_test_ptr
PropertyRNA * zoom_prop
PointerRNA fill_col_ptr
ListBase orig_paintcursors
PropertyRNA * rot_prop
PointerRNA rot_ptr
PropertyRNA * col_prop
PropertyRNA * fill_col_override_test_prop
PropertyRNA * fill_col_override_prop
PointerRNA fill_col_override_ptr
PointerRNA col_ptr
PropertyType type
PointerRNA zoom_ptr
PropertyRNA * fill_col_prop
StructRNA * image_id_srna
PointerRNA image_id_ptr
std::string single_menu_idname
struct bDopeSheet * ads
struct bDopeSheet * ads
View3DShading shading
struct EditBone * act_edbone
ListBase * edbo
uiFontStyle widget
short val
Definition WM_types.hh:724
int xy[2]
Definition WM_types.hh:726
short type
Definition WM_types.hh:722
const void * modal_items
std::string title
wmPopupSize size
std::string message
eAlertIcon icon
bool mouse_move_quit
wmPopupPosition position
std::string confirm_text
bool cancel_default
bool include_properties
wmOperator * op
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
bool(* check)(bContext *C, wmOperator *op)
Definition WM_types.hh:1014
std::string(* get_name)(wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1068
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * translation_context
Definition WM_types.hh:994
const char * description
Definition WM_types.hh:996
IDProperty * last_properties
Definition WM_types.hh:1083
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
PropertyRNA * prop
Definition WM_types.hh:1092
ListBase macro
Definition WM_types.hh:1095
StructRNA * srna
Definition WM_types.hh:1080
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
IDProperty * properties
struct wmOperator * next
struct wmOperatorType * type
struct PointerRNA * ptr
void(* draw)(bContext *C, int, int, void *customdata)
Definition wm.hh:21
bool(* poll)(bContext *C)
Definition wm.hh:20
void * customdata
Definition wm.hh:18
short region_type
Definition wm.hh:24
short space_type
Definition wm.hh:23
float max
#define N_(msgid)
void wm_operator_register(bContext *C, wmOperator *op)
Definition wm.cc:357
void WM_operator_free(wmOperator *op)
Definition wm.cc:283
void WM_cursor_wait(bool val)
void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:1608
void wm_draw_update(bContext *C)
Definition wm_draw.cc:1541
bool WM_event_drag_test_with_delta(const wmEvent *event, const int drag_delta[2])
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
int WM_userdef_event_type_from_keymap_type(int kmitype)
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
int WM_operator_repeat(bContext *C, wmOperator *op)
int WM_operator_call_notest(bContext *C, wmOperator *op)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_call_ex(bContext *C, wmOperator *op, const bool store)
#define ISMOUSE_MOTION(event_type)
@ GESTURE_MODAL_CIRCLE_SIZE
@ GESTURE_MODAL_OUT
@ GESTURE_MODAL_SNAP
@ GESTURE_MODAL_CIRCLE_ADD
@ GESTURE_MODAL_CANCEL
@ GESTURE_MODAL_CIRCLE_SUB
@ GESTURE_MODAL_MOVE
@ GESTURE_MODAL_NOP
@ GESTURE_MODAL_DESELECT
@ GESTURE_MODAL_CONFIRM
@ GESTURE_MODAL_IN
@ GESTURE_MODAL_FLIP
@ GESTURE_MODAL_BEGIN
@ GESTURE_MODAL_SELECT
@ RIGHTMOUSE
@ EVT_PADENTER
@ EVT_SPACEKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
@ EVT_RETKEY
void WM_OT_read_history(wmOperatorType *ot)
Definition wm_files.cc:2779
void WM_OT_save_as_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3762
void WM_OT_open_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3317
PointerRNA * ptr
Definition wm_files.cc:4126
void WM_OT_recover_last_session(wmOperatorType *ot)
Definition wm_files.cc:3464
void WM_OT_read_userpref(wmOperatorType *ot)
Definition wm_files.cc:2716
void WM_OT_save_homefile(wmOperatorType *ot)
Definition wm_files.cc:2560
void WM_OT_read_factory_userpref(wmOperatorType *ot)
Definition wm_files.cc:2752
void WM_OT_save_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3851
void WM_OT_recover_auto_save(wmOperatorType *ot)
Definition wm_files.cc:3524
void WM_OT_read_factory_settings(wmOperatorType *ot)
Definition wm_files.cc:3014
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_OT_read_homefile(wmOperatorType *ot)
Definition wm_files.cc:2940
void WM_OT_save_userpref(wmOperatorType *ot)
Definition wm_files.cc:2589
void WM_OT_clear_recent_files(wmOperatorType *ot)
Definition wm_files.cc:3941
void WM_OT_revert_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3398
void GIZMOGROUP_OT_gizmo_select(wmOperatorType *ot)
void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot)
void wm_gizmos_keymap(wmKeyConfig *keyconf)
void wm_exit_schedule_delayed(const bContext *C)
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:223
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:933
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:960
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:897
void WM_keymap_fix_linking()
void WM_menutype_idname_visit_for_search(const bContext *, PointerRNA *, PropertyRNA *, const char *, blender::FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
MenuType * WM_menutype_find(const char *idname, bool quiet)
bool WM_operator_properties_id_lookup_is_set(PointerRNA *ptr)
ID * WM_operator_properties_id_lookup_from_name_or_session_uid(Main *bmain, PointerRNA *ptr, const ID_Type type)
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
static uiBlock * wm_block_dialog_create(bContext *C, ARegion *region, void *user_data)
int WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallContext opcontext)
static uiBlock * wm_block_search_menu(bContext *C, ARegion *region, void *userdata)
static void WM_OT_call_menu_pie(wmOperatorType *ot)
static void gesture_box_modal_keymap(wmKeyConfig *keyconf)
#define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr)
static void WM_OT_search_menu(wmOperatorType *ot)
#define ID_CAST_SCENEWORLD(id_pt)
const EnumPropertyItem * RNA_movieclip_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
int WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot)
std::optional< std::string > WM_context_path_resolve_property_full(const bContext *C, const PointerRNA *ptr, PropertyRNA *prop, int index)
SearchType
@ SEARCH_TYPE_MENU
@ SEARCH_TYPE_SINGLE_MENU
@ SEARCH_TYPE_OPERATOR
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *)
int WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)
static bool wm_operator_winactive_not_full(bContext *C)
static void radial_control_paint_tex(RadialControl *rc, float radius, float alpha)
size_t WM_operator_py_idname(char *dst, const char *src)
static void redraw_timer_step(bContext *C, Scene *scene, Depsgraph *depsgraph, wmWindow *win, ScrArea *area, ARegion *region, const int type, const int cfra)
int WM_operator_redo_popup(bContext *C, wmOperator *op)
static void wm_block_redo_cancel_cb(bContext *C, void *arg_op)
static int wm_call_panel_exec(bContext *C, wmOperator *op)
static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
static void radial_control_set_tex(RadialControl *rc)
static void gesture_zoom_border_modal_keymap(wmKeyConfig *keyconf)
static void radial_control_cancel(bContext *C, wmOperator *op)
static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
static void dialog_cancel_cb(bContext *C, void *arg1, void *arg2)
int WM_operator_ui_popup(bContext *C, wmOperator *op, int width)
void wm_window_keymap(wmKeyConfig *keyconf)
static uiBlock * wm_enum_search_menu(bContext *C, ARegion *region, void *arg)
void WM_operator_last_properties_ensure(wmOperatorType *ot, PointerRNA *ptr)
int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *)
static void WM_OT_search_single_menu(wmOperatorType *ot)
static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op, const char *name, PointerRNA *r_ptr, PropertyRNA **r_prop, int req_length, RCPropFlags flags)
int WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
static void WM_OT_memory_statistics(wmOperatorType *ot)
static const EnumPropertyItem * rna_id_itemf(bool *r_free, ID *id, bool local, bool(*filter_ids)(const ID *id, void *user_data), void *user_data)
#define CTX_TEST_PTR_ID(C, member, idptr)
static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define ID_CAST_OBDATA(id_pt)
static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *)
static void radial_control_update_header(wmOperator *op, bContext *C)
const EnumPropertyItem * RNA_mask_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
const EnumPropertyItem * RNA_collection_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
#define TEST_PTR_DATA_TYPE_FROM_CONTEXT(member, rna_type, rna_ptr)
size_t WM_operator_bl_idname(char *dst, const char *src)
void WM_operator_properties_reset(wmOperator *op)
static void WM_OT_debug_menu(wmOperatorType *ot)
static int previews_clear_exec(bContext *C, wmOperator *op)
#define ID_CAST_OBMATACT(id_pt)
static void gesture_lasso_modal_keymap(wmKeyConfig *keyconf)
static void WM_OT_radial_control(wmOperatorType *ot)
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
static bool rna_id_enum_filter_single(const ID *id, void *user_data)
#define OP_MAX_PY_IDNAME
static void WM_OT_call_asset_shelf_popover(wmOperatorType *ot)
bool WM_operator_last_properties_store(wmOperator *op)
void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
#define OP_BL_SEP_LEN
#define WM_RADIAL_CONTROL_DISPLAY_WIDTH
static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int radial_control_get_properties(bContext *C, wmOperator *op)
const EnumPropertyItem * RNA_action_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static int wm_exit_blender_invoke(bContext *C, wmOperator *, const wmEvent *)
static int wm_call_pie_menu_exec(bContext *C, wmOperator *op)
void WM_operator_view3d_unit_defaults(bContext *C, wmOperator *op)
static int wm_debug_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
static bool redraw_timer_poll(bContext *C)
static void WM_OT_call_menu(wmOperatorType *ot)
static int wm_call_menu_exec(bContext *C, wmOperator *op)
#define OP_BL_SEP_STRING
bool WM_operator_winactive(bContext *C)
static void wm_block_redo_cb(bContext *C, void *arg_op, int)
int WM_operator_smooth_viewtx_get(const wmOperator *op)
bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
bool WM_paint_cursor_end(wmPaintCursor *handle)
static int previews_id_ensure_callback(LibraryIDLinkCallbackData *cb_data)
@ eRTDrawWindowSwap
@ eRTAnimationStep
@ eRTDrawRegionSwap
@ eRTDrawWindow
@ eRTUndo
@ eRTDrawRegion
@ eRTAnimationPlay
void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void(*free)(void *))
static int wm_exit_blender_exec(bContext *C, wmOperator *)
static std::optional< std::string > wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
const EnumPropertyItem * RNA_scene_local_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void WM_OT_redraw_timer(wmOperatorType *ot)
int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *)
const EnumPropertyItem * RNA_movieclip_local_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static void WM_OT_search_operator(wmOperatorType *ot)
static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event)
std::string WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args, wmOperatorType *ot, PointerRNA *opptr)
std::optional< std::string > WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr)
static uiBlock * wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
static void WM_OT_previews_clear(wmOperatorType *ot)
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
wmOperator * WM_operator_last_redo(const bContext *C)
static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const bool do_call, const bool do_redo, std::optional< std::string > title=std::nullopt, std::optional< std::string > confirm_text=std::nullopt, const bool cancel_default=false)
static bool wm_operator_winactive_normal(bContext *C)
const EnumPropertyItem * RNA_scene_without_active_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void wm_operatortypes_register()
bool WM_operator_last_properties_init(wmOperator *op)
static void WM_OT_stereo3d_set(wmOperatorType *ot)
const EnumPropertyItem * RNA_mask_local_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static void redraw_timer_window_swap(bContext *C)
bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const ImageFormatData *im_format)
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static std::string wm_call_panel_get_name(wmOperatorType *ot, PointerRNA *ptr)
bool WM_operator_bl_idname_is_valid(const char *idname)
static void WM_OT_call_panel(wmOperatorType *ot)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
const EnumPropertyItem * RNA_collection_local_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static void WM_OT_quit_blender(wmOperatorType *ot)
static int memory_statistics_exec(bContext *, wmOperator *)
IDProperty * WM_operator_last_properties_ensure_idprops(wmOperatorType *ot)
static char g_search_text[256]
static std::string wm_call_menu_get_name(wmOperatorType *ot, PointerRNA *ptr)
static void wm_operator_ui_popup_ok(bContext *C, void *arg, int retval)
bool WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
static int wm_search_menu_exec(bContext *, wmOperator *)
static const EnumPropertyItem preview_id_type_items[]
static void WM_OT_window_new_main(wmOperatorType *ot)
static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_properties)
static int wm_operator_defaults_exec(bContext *C, wmOperator *op)
std::optional< std::string > WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
static void gesture_polyline_modal_keymap(wmKeyConfig *keyconf)
int WM_operator_confirm_message_ex(bContext *C, wmOperator *op, const char *title, const int icon, const char *message, const wmOperatorCallContext)
static void WM_OT_window_new(wmOperatorType *ot)
static int redraw_timer_exec(bContext *C, wmOperator *op)
void WM_operator_properties_clear(PointerRNA *ptr)
RCPropFlags
@ RC_PROP_REQUIRE_FLOAT
@ RC_PROP_REQUIRE_BOOL
@ RC_PROP_ALLOW_MISSING
#define TEST_PTR_DATA_TYPE(member, rna_type, rna_ptr, dataptr_cmp)
static int wm_debug_menu_exec(bContext *C, wmOperator *op)
int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *)
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_previews_ensure(wmOperatorType *ot)
static int previews_ensure_exec(bContext *C, wmOperator *)
static uint preview_filter_to_idfilter(enum PreviewFilterID filter)
int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *)
static const EnumPropertyItem redraw_timer_type_items[]
static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
std::string WM_operator_pystring(bContext *C, wmOperator *op, const bool all_args, const bool macro_args)
static void radial_control_set_value(RadialControl *rc, float val)
void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE
static void radial_control_paint_curve(uint pos, Brush *br, float radius, int line_segments)
static int asset_shelf_popover_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void WM_OT_window_close(wmOperatorType *ot)
static const char * wm_context_member_from_ptr(const bContext *C, const PointerRNA *ptr, bool *r_is_id)
#define OP_PY_SEP_LEN
void WM_operator_properties_free(PointerRNA *ptr)
#define OP_PY_SEP_CHAR
ID * WM_operator_drop_load_path(bContext *C, wmOperator *op, const short idcode)
wmPaintCursor * WM_paint_cursor_activate(short space_type, short region_type, bool(*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata)
static void radial_control_paint_cursor(bContext *, int x, int y, void *customdata)
static void wm_operator_ui_popup_cancel(bContext *C, void *user_data)
PreviewFilterID
@ PREVIEW_FILTER_WORLD
@ PREVIEW_FILTER_TEXTURE
@ PREVIEW_FILTER_GEOMETRY
@ PREVIEW_FILTER_LIGHT
@ PREVIEW_FILTER_MATERIAL
@ PREVIEW_FILTER_COLLECTION
@ PREVIEW_FILTER_ALL
@ PREVIEW_FILTER_IMAGE
@ PREVIEW_FILTER_OBJECT
@ PREVIEW_FILTER_SCENE
@ PREVIEW_FILTER_SHADING
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
bool WM_operator_py_idname_ok_or_report(ReportList *reports, const char *classname, const char *idname)
#define WM_RADIAL_MAX_STR
std::string WM_operator_pystring_abbreviate(std::string str, int str_len_max)
#define WM_RADIAL_CONTROL_DISPLAY_SIZE
const EnumPropertyItem * RNA_image_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static uiBlock * wm_operator_ui_create(bContext *C, ARegion *region, void *user_data)
const EnumPropertyItem * RNA_scene_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_operator_defaults(wmOperatorType *ot)
const EnumPropertyItem * RNA_image_local_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
PanelType * WM_paneltype_find(const char *idname, bool quiet)
void WM_paneltype_idname_visit_for_search(const bContext *, PointerRNA *, PropertyRNA *, const char *, blender::FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
void WM_OT_splash_about(wmOperatorType *ot)
void WM_OT_splash(wmOperatorType *ot)
void wm_stereo3d_set_cancel(bContext *, wmOperator *op)
Definition wm_stereo.cc:402
int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition wm_stereo.cc:346
int wm_stereo3d_set_exec(bContext *C, wmOperator *op)
Definition wm_stereo.cc:257
bool wm_stereo3d_set_check(bContext *, wmOperator *)
Definition wm_stereo.cc:394
void wm_stereo3d_set_draw(bContext *, wmOperator *op)
Definition wm_stereo.cc:356
int wm_window_new_main_exec(bContext *C, wmOperator *op)
int wm_window_close_exec(bContext *C, wmOperator *)
int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *)
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
Definition wm_window.cc:397
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
int wm_window_new_exec(bContext *C, wmOperator *op)
bScreen * WM_window_get_active_screen(const wmWindow *win)
void wm_xr_operatortypes_register()