Blender V4.5
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
11
12#include <algorithm>
13#include <cctype>
14#include <cerrno>
15#include <cfloat>
16#include <cstddef>
17#include <cstdio>
18#include <cstring>
19#include <sstream>
20
21#include <fmt/format.h>
22
23#ifdef WIN32
24# include "GHOST_C-api.h"
25#endif
26
27#include "MEM_guardedalloc.h"
28
29#include "CLG_log.h"
30
31#include "DNA_ID.h"
32#include "DNA_armature_types.h"
33#include "DNA_brush_types.h"
34#include "DNA_object_types.h"
35#include "DNA_scene_types.h"
36#include "DNA_screen_types.h"
37#include "DNA_userdef_types.h"
39
40#include "BLT_translation.hh"
41
42#include "BLI_dial_2d.h"
43#include "BLI_listbase.h"
44#include "BLI_math_rotation.h"
45#include "BLI_math_vector.h"
47#include "BLI_path_utils.hh"
48#include "BLI_string.h"
49#include "BLI_string_utf8.h"
50#include "BLI_time.h"
51#include "BLI_utildefines.h"
52
53#include "BKE_anim_data.hh"
54#include "BKE_brush.hh"
55#include "BKE_colortools.hh"
56#include "BKE_context.hh"
57#include "BKE_global.hh"
58#include "BKE_idprop.hh"
59#include "BKE_image.hh"
60#include "BKE_image_format.hh"
61#include "BKE_lib_id.hh"
62#include "BKE_lib_query.hh"
63#include "BKE_library.hh"
64#include "BKE_main.hh"
65#include "BKE_material.hh"
66#include "BKE_preview_image.hh"
67#include "BKE_report.hh"
68#include "BKE_scene.hh"
69#include "BKE_screen.hh" /* #BKE_ST_MAXNAME. */
70
71#include "BKE_idtype.hh"
72
73#include "BLF_api.hh"
74
75#include "GPU_immediate.hh"
76#include "GPU_immediate_util.hh"
77#include "GPU_matrix.hh"
78#include "GPU_state.hh"
79
80#include "IMB_imbuf_types.hh"
81
82#include "ED_fileselect.hh"
83#include "ED_gpencil_legacy.hh"
84#include "ED_grease_pencil.hh"
85#include "ED_numinput.hh"
86#include "ED_screen.hh"
87#include "ED_undo.hh"
88#include "ED_view3d.hh"
89
91
92#include "RNA_access.hh"
93#include "RNA_define.hh"
94#include "RNA_enum_types.hh"
95#include "RNA_path.hh"
96#include "RNA_prototypes.hh"
97
98#include "UI_interface.hh"
99#include "UI_interface_icons.hh"
100#include "UI_resources.hh"
101
102#include "WM_api.hh"
103#include "WM_keymap.hh"
104#include "WM_types.hh"
105
106#include "wm.hh"
107#include "wm_draw.hh"
108#include "wm_event_system.hh"
109#include "wm_event_types.hh"
110#include "wm_files.hh"
111#include "wm_window.hh"
112#ifdef WITH_XR_OPENXR
113# include "wm_xr.hh"
114#endif
115
116#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
117
118/* -------------------------------------------------------------------- */
121
122#define OP_BL_SEP_STRING "_OT_"
123#define OP_BL_SEP_LEN 4
124
125#define OP_PY_SEP_CHAR '.'
126#define OP_PY_SEP_LEN 1
127
128/* Difference between python 'identifier' and BL/C code one ("." separator replaced by "_OT_"),
129 * and final `\0` char. */
130#define OP_MAX_PY_IDNAME (OP_MAX_TYPENAME - OP_BL_SEP_LEN + OP_PY_SEP_LEN - 1)
131
132size_t WM_operator_py_idname(char *dst, const char *src)
133{
134 const char *sep = strstr(src, OP_BL_SEP_STRING);
135 if (sep) {
136 const size_t sep_offset = size_t(sep - src);
137
138 /* NOTE: we use ASCII `tolower` instead of system `tolower`, because the
139 * latter depends on the locale, and can lead to `idname` mismatch. */
140 memcpy(dst, src, sep_offset);
141 BLI_str_tolower_ascii(dst, sep_offset);
142
143 dst[sep_offset] = OP_PY_SEP_CHAR;
144 return BLI_strncpy_rlen(dst + (sep_offset + OP_PY_SEP_LEN),
145 sep + OP_BL_SEP_LEN,
146 OP_MAX_TYPENAME - sep_offset - OP_PY_SEP_LEN) +
147 (sep_offset + OP_PY_SEP_LEN);
148 }
149 /* Should not happen but support just in case. */
150 return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
151}
152
153size_t WM_operator_bl_idname(char *dst, const char *src)
154{
155 const size_t from_len = strlen(src);
156
157 const char *sep = strchr(src, OP_PY_SEP_CHAR);
158 if (sep && (from_len <= OP_MAX_PY_IDNAME)) {
159 const size_t sep_offset = size_t(sep - src);
160 memcpy(dst, src, sep_offset);
161 BLI_str_toupper_ascii(dst, sep_offset);
162
163 memcpy(dst + sep_offset, OP_BL_SEP_STRING, OP_BL_SEP_LEN);
164 BLI_strncpy(dst + sep_offset + OP_BL_SEP_LEN,
165 sep + OP_PY_SEP_LEN,
166 from_len - sep_offset - OP_PY_SEP_LEN + 1);
167 return from_len + OP_BL_SEP_LEN - OP_PY_SEP_LEN;
168 }
169 /* Should not happen but support just in case. */
170 return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
171}
172
173bool WM_operator_bl_idname_is_valid(const char *idname)
174{
175 const char *sep = strstr(idname, OP_BL_SEP_STRING);
176 /* Separator missing or at string beginning/end. */
177 if ((sep == nullptr) || (sep == idname) || (sep[OP_BL_SEP_LEN] == '\0')) {
178 return false;
179 }
180
181 for (const char *ch = idname; ch < sep; ch++) {
182 if ((*ch >= 'A' && *ch <= 'Z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
183 continue;
184 }
185 return false;
186 }
187
188 for (const char *ch = sep + OP_BL_SEP_LEN; *ch; ch++) {
189 if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
190 continue;
191 }
192 return false;
193 }
194 return true;
195}
196
198 const char *classname,
199 const char *idname)
200{
201 const char *ch = idname;
202 int dot = 0;
203 int i;
204 for (i = 0; *ch; i++, ch++) {
205 if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
206 /* Pass. */
207 }
208 else if (*ch == '.') {
209 if (ch == idname || (*(ch + 1) == '\0')) {
211 RPT_ERROR,
212 "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
213 classname,
214 idname,
215 i);
216 return false;
217 }
218 dot++;
219 }
220 else {
222 RPT_ERROR,
223 "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
224 classname,
225 idname,
226 i);
227 return false;
228 }
229 }
230
231 if (i > OP_MAX_PY_IDNAME) {
233 RPT_ERROR,
234 "Registering operator class: '%s', invalid bl_idname '%s', "
235 "is too long, maximum length is %d",
236 classname,
237 idname,
239 return false;
240 }
241
242 if (dot != 1) {
244 reports,
245 RPT_ERROR,
246 "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
247 classname,
248 idname);
249 return false;
250 }
251 return true;
252}
253
255 wmOperator *op,
256 const bool all_args,
257 const bool macro_args,
259 PointerRNA *opptr)
260{
261 char idname_py[OP_MAX_TYPENAME];
262
263 /* For building the string. */
264 std::stringstream ss;
265
266 /* Arbitrary, but can get huge string with stroke painting otherwise. */
267 int max_prop_length = 10;
268
269 WM_operator_py_idname(idname_py, ot->idname);
270 ss << "bpy.ops." << idname_py << "(";
271
272 if (op && op->macro.first) {
273 /* Special handling for macros, else we only get default values in this case... */
274 wmOperator *opm;
275 bool first_op = true;
276
277 opm = static_cast<wmOperator *>(macro_args ? op->macro.first : nullptr);
278
279 for (; opm; opm = opm->next) {
280 PointerRNA *opmptr = opm->ptr;
281 PointerRNA opmptr_default;
282 if (opmptr == nullptr) {
283 WM_operator_properties_create_ptr(&opmptr_default, opm->type);
284 opmptr = &opmptr_default;
285 }
286
287 std::string string_args = RNA_pointer_as_string_id(C, opmptr);
288 if (first_op) {
289 ss << opm->type->idname << '=' << string_args;
290 first_op = false;
291 }
292 else {
293 ss << ", " << opm->type->idname << '=' << string_args;
294 }
295
296 if (opmptr == &opmptr_default) {
297 WM_operator_properties_free(&opmptr_default);
298 }
299 }
300 }
301 else {
302 /* Only to get the original props for comparisons. */
303 PointerRNA opptr_default;
304 const bool macro_args_test = ot->macro.first ? macro_args : true;
305
306 if (opptr == nullptr) {
307 WM_operator_properties_create_ptr(&opptr_default, ot);
308 opptr = &opptr_default;
309 }
310
312 C, opptr, false, all_args, macro_args_test, max_prop_length);
313
314 if (opptr == &opptr_default) {
315 WM_operator_properties_free(&opptr_default);
316 }
317 }
318
319 ss << ')';
320
321 return ss.str();
322}
323
325 wmOperator *op,
326 const bool all_args,
327 const bool macro_args)
328{
329 return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr);
330}
331
332std::string WM_operator_pystring_abbreviate(std::string str, int str_len_max)
333{
334 const int str_len = str.size();
335 const size_t parens_start = str.find('(');
336 if (parens_start == std::string::npos) {
337 return str;
338 }
339
340 const size_t parens_end = str.find(parens_start + 1, ')');
341 if (parens_end == std::string::npos) {
342 return str;
343 }
344
345 const int parens_len = parens_end - parens_start;
346 if (parens_len <= str_len_max) {
347 return str;
348 }
349
350 /* Truncate after the first comma. */
351 const size_t comma_first = str.find(parens_start, ',');
352 if (comma_first == std::string::npos) {
353 return str;
354 }
355 const char end_str[] = " ... )";
356 const int end_str_len = sizeof(end_str) - 1;
357
358 /* Leave a place for the first argument. */
359 const int new_str_len = (comma_first - parens_start) + 1;
360
361 if (str_len < new_str_len + parens_start + end_str_len + 1) {
362 return str;
363 }
364
365 return str.substr(0, comma_first) + end_str;
366}
367
368/* Return nullptr if no match is found. */
369#if 0
370static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr, bool *r_is_id)
371{
372 /* Loop over all context items and do 2 checks
373 *
374 * - See if the pointer is in the context.
375 * - See if the pointers ID is in the context.
376 */
377
378 /* Don't get from the context store since this is normally
379 * set only for the UI and not usable elsewhere. */
380 ListBase lb = CTX_data_dir_get_ex(C, false, true, true);
381 LinkData *link;
382
383 const char *member_found = nullptr;
384 const char *member_id = nullptr;
385 bool member_found_is_id = false;
386
387 for (link = lb.first; link; link = link->next) {
388 const char *identifier = link->data;
389 PointerRNA ctx_item_ptr = {};
390 // CTX_data_pointer_get(C, identifier); /* XXX, this isn't working. */
391
392 if (ctx_item_ptr.type == nullptr) {
393 continue;
394 }
395
396 if (ptr->owner_id == ctx_item_ptr.owner_id) {
397 const bool is_id = RNA_struct_is_ID(ctx_item_ptr.type);
398 if ((ptr->data == ctx_item_ptr.data) && (ptr->type == ctx_item_ptr.type)) {
399 /* Found! */
400 member_found = identifier;
401 member_found_is_id = is_id;
402 break;
403 }
404 if (is_id) {
405 /* Found a reference to this ID, so fall back to it if there is no direct reference. */
406 member_id = identifier;
407 }
408 }
409 }
410 BLI_freelistN(&lb);
411
412 if (member_found) {
413 *r_is_id = member_found_is_id;
414 return member_found;
415 }
416 else if (member_id) {
417 *r_is_id = true;
418 return member_id;
419 }
420 else {
421 return nullptr;
422 }
423}
424
425#else
426
427/* Use hard coded checks for now. */
428
443static const char *wm_context_member_from_ptr(const bContext *C,
444 const PointerRNA *ptr,
445 bool *r_is_id)
446{
447 const char *member_id = nullptr;
448 bool is_id = false;
449
450# define CTX_TEST_PTR_ID(C, member, idptr) \
451 { \
452 const char *ctx_member = member; \
453 PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
454 if (ctx_item_ptr.owner_id == idptr) { \
455 member_id = ctx_member; \
456 is_id = true; \
457 break; \
458 } \
459 } \
460 (void)0
461
462# define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \
463 { \
464 const char *ctx_member = member; \
465 const char *ctx_member_full = member_full; \
466 PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
467 if (ctx_item_ptr.owner_id && (ID *)cast(ctx_item_ptr.owner_id) == idptr) { \
468 member_id = ctx_member_full; \
469 is_id = true; \
470 break; \
471 } \
472 } \
473 (void)0
474
475# define TEST_PTR_DATA_TYPE(member, rna_type, rna_ptr, dataptr_cmp) \
476 { \
477 const char *ctx_member = member; \
478 if (RNA_struct_is_a((rna_ptr)->type, &(rna_type)) && (rna_ptr)->data == (dataptr_cmp)) { \
479 member_id = ctx_member; \
480 break; \
481 } \
482 } \
483 (void)0
484
485/* A version of #TEST_PTR_DATA_TYPE that calls `CTX_data_pointer_get_type(C, member)`. */
486# define TEST_PTR_DATA_TYPE_FROM_CONTEXT(member, rna_type, rna_ptr) \
487 { \
488 const char *ctx_member = member; \
489 if (RNA_struct_is_a((rna_ptr)->type, &(rna_type)) && \
490 (rna_ptr)->data == (CTX_data_pointer_get_type(C, ctx_member, &(rna_type)).data)) \
491 { \
492 member_id = ctx_member; \
493 break; \
494 } \
495 } \
496 (void)0
497
498 /* General checks (multiple ID types). */
499 if (ptr->owner_id) {
500 const ID_Type ptr_id_type = GS(ptr->owner_id->name);
501
502 /* Support break in the macros for an early exit. */
503 do {
504 /* Animation Data. */
505 if (id_type_can_have_animdata(ptr_id_type)) {
506 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_nla_track", RNA_NlaTrack, ptr);
507 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_nla_strip", RNA_NlaStrip, ptr);
508 }
509 } while (false);
510 }
511
512 /* Specific ID type checks. */
513 if (ptr->owner_id && (member_id == nullptr)) {
514
515 const ID_Type ptr_id_type = GS(ptr->owner_id->name);
516 switch (ptr_id_type) {
517 case ID_SCE: {
518 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_strip", RNA_Strip, ptr);
519
520 CTX_TEST_PTR_ID(C, "scene", ptr->owner_id);
521 break;
522 }
523 case ID_OB: {
524 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_pose_bone", RNA_PoseBone, ptr);
525
526 CTX_TEST_PTR_ID(C, "object", ptr->owner_id);
527 break;
528 }
529 /* From #rna_Main_objects_new. */
531
532 if (ptr_id_type == ID_AR) {
533 const bArmature *arm = (bArmature *)ptr->owner_id;
534 if (arm->edbo != nullptr) {
535 TEST_PTR_DATA_TYPE("active_bone", RNA_EditBone, ptr, arm->act_edbone);
536 }
537 else {
538 TEST_PTR_DATA_TYPE("active_bone", RNA_Bone, ptr, arm->act_bone);
539 }
540 }
541
542# define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data)
543 CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->owner_id);
544 break;
545# undef ID_CAST_OBDATA
546 }
547 case ID_MA: {
548# define ID_CAST_OBMATACT(id_pt) \
549 BKE_object_material_get(((Object *)id_pt), ((Object *)id_pt)->actcol)
551 C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->owner_id);
552 break;
553# undef ID_CAST_OBMATACT
554 }
555 case ID_WO: {
556# define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world)
557 CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->owner_id);
558 break;
559# undef ID_CAST_SCENEWORLD
560 }
561 case ID_SCR: {
562 CTX_TEST_PTR_ID(C, "screen", ptr->owner_id);
563
564 TEST_PTR_DATA_TYPE("area", RNA_Area, ptr, CTX_wm_area(C));
565 TEST_PTR_DATA_TYPE("region", RNA_Region, ptr, CTX_wm_region(C));
566
567 SpaceLink *space_data = CTX_wm_space_data(C);
568 if (space_data != nullptr) {
569 TEST_PTR_DATA_TYPE("space_data", RNA_Space, ptr, space_data);
570
571 switch (space_data->spacetype) {
572 case SPACE_VIEW3D: {
573 const View3D *v3d = (View3D *)space_data;
574 const View3DShading *shading = &v3d->shading;
575
576 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_View3DOverlay, ptr, v3d);
577 TEST_PTR_DATA_TYPE("space_data.shading", RNA_View3DShading, ptr, shading);
578 break;
579 }
580 case SPACE_GRAPH: {
581 const SpaceGraph *sipo = (SpaceGraph *)space_data;
582 const bDopeSheet *ads = sipo->ads;
583 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
584 break;
585 }
586 case SPACE_FILE: {
587 const SpaceFile *sfile = (SpaceFile *)space_data;
589 TEST_PTR_DATA_TYPE("space_data.params", RNA_FileSelectParams, ptr, params);
590 break;
591 }
592 case SPACE_IMAGE: {
593 const SpaceImage *sima = (SpaceImage *)space_data;
594 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceImageOverlay, ptr, sima);
595 TEST_PTR_DATA_TYPE("space_data.uv_editor", RNA_SpaceUVEditor, ptr, sima);
596 break;
597 }
598 case SPACE_NLA: {
599 const SpaceNla *snla = (SpaceNla *)space_data;
600 const bDopeSheet *ads = snla->ads;
601 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
602 break;
603 }
604 case SPACE_ACTION: {
605 const SpaceAction *sact = (SpaceAction *)space_data;
606 const bDopeSheet *ads = &sact->ads;
607 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
608 break;
609 }
610 case SPACE_NODE: {
611 const SpaceNode *snode = (SpaceNode *)space_data;
612 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceNodeOverlay, ptr, snode);
613 break;
614 }
615 case SPACE_SEQ: {
616 const SpaceSeq *sseq = (SpaceSeq *)space_data;
618 "space_data.preview_overlay", RNA_SequencerPreviewOverlay, ptr, sseq);
620 "space_data.timeline_overlay", RNA_SequencerTimelineOverlay, ptr, sseq);
621 TEST_PTR_DATA_TYPE("space_data.cache_overlay", RNA_SequencerCacheOverlay, ptr, sseq);
622 break;
623 }
624 }
625 }
626
627 break;
628 }
629 default:
630 break;
631 }
632# undef CTX_TEST_PTR_ID
633# undef CTX_TEST_PTR_ID_CAST
634# undef TEST_PTR_DATA_TYPE
635 }
636
637 *r_is_id = is_id;
638
639 return member_id;
640}
641#endif
642
643std::optional<std::string> WM_context_path_resolve_property_full(const bContext *C,
644 const PointerRNA *ptr,
645 PropertyRNA *prop,
646 int index)
647{
648 bool is_id;
649 const char *member_id = wm_context_member_from_ptr(C, ptr, &is_id);
650 if (!member_id) {
651 return std::nullopt;
652 }
653 std::string member_id_data_path;
654 if (is_id && !RNA_struct_is_ID(ptr->type)) {
655 std::optional<std::string> data_path = RNA_path_from_ID_to_struct(ptr);
656 if (data_path) {
657 if (prop != nullptr) {
658 std::string prop_str = RNA_path_property_py(ptr, prop, index);
659 if (prop_str[0] == '[') {
660 member_id_data_path = fmt::format("{}.{}{}", member_id, *data_path, prop_str);
661 }
662 else {
663 member_id_data_path = fmt::format("{}.{}.{}", member_id, *data_path, prop_str);
664 }
665 }
666 else {
667 member_id_data_path = fmt::format("{}.{}", member_id, *data_path);
668 }
669 }
670 }
671 else {
672 if (prop != nullptr) {
673 std::string prop_str = RNA_path_property_py(ptr, prop, index);
674 if (prop_str[0] == '[') {
675 member_id_data_path = fmt::format("{}{}", member_id, prop_str);
676 }
677 else {
678 member_id_data_path = fmt::format("{}.{}", member_id, prop_str);
679 }
680 }
681 else {
682 member_id_data_path = member_id;
683 }
684 }
685
686 return member_id_data_path;
687}
688
689std::optional<std::string> WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr)
690{
691 return WM_context_path_resolve_property_full(C, ptr, nullptr, -1);
692}
693
694static std::optional<std::string> wm_prop_pystring_from_context(bContext *C,
696 PropertyRNA *prop,
697 int index)
698{
699 std::optional<std::string> member_id_data_path = WM_context_path_resolve_property_full(
700 C, ptr, prop, index);
701 if (!member_id_data_path.has_value()) {
702 return std::nullopt;
703 }
704 return "bpy.context." + member_id_data_path.value();
705}
706
707std::optional<std::string> WM_prop_pystring_assign(bContext *C,
709 PropertyRNA *prop,
710 int index)
711{
712 std::optional<std::string> lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) :
713 std::nullopt;
714
715 if (!lhs.has_value()) {
716 /* Fall back to `bpy.data.foo[id]` if we don't find in the context. */
717 if (std::optional<std::string> lhs_str = RNA_path_full_property_py(ptr, prop, index)) {
718 lhs = lhs_str;
719 }
720 else {
721 return std::nullopt;
722 }
723 }
724
725 std::string rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX);
726
727 std::string ret = fmt::format("{} = {}", lhs.value(), rhs);
728 return ret;
729}
730
732{
733 /* Set the ID so the context can be accessed: see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
734 *ptr = RNA_pointer_create_discrete(static_cast<ID *>(G_MAIN->wm.first), ot->srna, nullptr);
735}
736
737void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
738{
739 wmOperatorType *ot = WM_operatortype_find(opstring, false);
740
741 if (ot) {
743 }
744 else {
745 /* Set the ID so the context can be accessed: see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
747 static_cast<ID *>(G_MAIN->wm.first), &RNA_OperatorProperties, nullptr);
748 }
749}
750
751void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
752{
753 IDProperty *tmp_properties = nullptr;
754 /* Allow passing nullptr for properties, just create the properties here then. */
755 if (properties == nullptr) {
756 properties = &tmp_properties;
757 }
758
759 if (*properties == nullptr) {
760 *properties = blender::bke::idprop::create_group("wmOpItemProp").release();
761 }
762
763 if (*ptr == nullptr) {
764 *ptr = MEM_new<PointerRNA>("wmOpItemPtr");
766 }
767
768 (*ptr)->data = *properties;
769}
770
771void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
772{
773 RNA_STRUCT_BEGIN (ptr, prop) {
774 switch (RNA_property_type(prop)) {
775 case PROP_ENUM:
776 if (no_context) {
778 }
779 else {
781 }
782 break;
783 case PROP_POINTER: {
785
786 /* Recurse into operator properties. */
787 if (RNA_struct_is_a(ptype, &RNA_OperatorProperties)) {
789 WM_operator_properties_sanitize(&opptr, no_context);
790 }
791 break;
792 }
793 default:
794 break;
795 }
796 }
798}
799
801{
802 bool changed = false;
803 RNA_STRUCT_BEGIN (ptr, prop) {
804 switch (RNA_property_type(prop)) {
805 case PROP_POINTER: {
807 if (ptype != &RNA_Struct) {
809 changed |= WM_operator_properties_default(&opptr, do_update);
810 }
811 break;
812 }
813 default:
814 if ((do_update == false) || (RNA_property_is_set(ptr, prop) == false)) {
815 if (RNA_property_reset(ptr, prop, -1)) {
816 changed = true;
817 }
818 }
819 break;
820 }
821 }
823
824 return changed;
825}
826
828{
829 if (op->ptr->data) {
831
832 RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
833 PropertyRNA *prop = static_cast<PropertyRNA *>(itemptr.data);
834
835 if ((RNA_property_flag(prop) & (PROP_SKIP_SAVE | PROP_SKIP_PRESET)) == 0) {
836 const char *identifier = RNA_property_identifier(prop);
837 RNA_struct_idprops_unset(op->ptr, identifier);
838 }
839 }
841 }
842}
843
845{
846 IDProperty *properties = static_cast<IDProperty *>(ptr->data);
847
848 if (properties) {
849 IDP_ClearProperty(properties);
850 }
851}
852
854{
855 IDProperty *properties = static_cast<IDProperty *>(ptr->data);
856
857 if (properties) {
858 IDP_FreeProperty(properties);
859 ptr->data = nullptr; /* Just in case. */
860 }
861}
862
864
865/* -------------------------------------------------------------------- */
868
869#if 1 /* May want to disable operator remembering previous state for testing. */
870
872{
873 bool changed = false;
874 IDProperty *replaceprops = blender::bke::idprop::create_group("wmOperatorProperties").release();
875
877
878 RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
879 PropertyRNA *prop = static_cast<PropertyRNA *>(itemptr.data);
880 if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
881 if (!RNA_property_is_set(op->ptr, prop)) { /* Don't override a setting already set. */
882 const char *identifier = RNA_property_identifier(prop);
883 IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, identifier);
884 if (idp_src) {
885 IDProperty *idp_dst = IDP_CopyProperty(idp_src);
886
887 /* NOTE: in the future this may need to be done recursively,
888 * but for now RNA doesn't access nested operators. */
889 idp_dst->flag |= IDP_FLAG_GHOST;
890
891 /* Add to temporary group instead of immediate replace,
892 * because we are iterating over this group. */
893 IDP_AddToGroup(replaceprops, idp_dst);
894 changed = true;
895 }
896 }
897 }
898 }
900
901 if (changed) {
902 CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
903 }
904 IDP_MergeGroup(op->properties, replaceprops, true);
905 IDP_FreeProperty(replaceprops);
906 return changed;
907}
908
910{
911 bool changed = false;
912 if (op->type->last_properties) {
914 LISTBASE_FOREACH (wmOperator *, opm, &op->macro) {
915 IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname);
916 if (idp_src) {
917 changed |= operator_last_properties_init_impl(opm, idp_src);
918 }
919 }
920 }
921 return changed;
922}
923
925{
926 if (op->type->last_properties) {
928 op->type->last_properties = nullptr;
929 }
930
931 if (op->properties) {
933 CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname);
934 }
936 }
937
938 if (op->macro.first != nullptr) {
939 LISTBASE_FOREACH (wmOperator *, opm, &op->macro) {
940 if (opm->properties) {
941 if (op->type->last_properties == nullptr) {
942 op->type->last_properties =
943 blender::bke::idprop::create_group("wmOperatorProperties").release();
944 }
945 IDProperty *idp_macro = IDP_CopyProperty(opm->properties);
946 STRNCPY(idp_macro->name, opm->type->idname);
947 IDP_ReplaceInGroup(op->type->last_properties, idp_macro);
948 }
949 }
950 }
951
952 return (op->type->last_properties != nullptr);
953}
954
955#else
956
958{
959 return false;
960}
961
963{
964 return false;
965}
966
967#endif
968
970
971/* -------------------------------------------------------------------- */
974
976{
977 PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
978 "wait_to_deselect_others");
979 const short init_event_type = short(POINTER_AS_INT(op->customdata));
980
981 /* Get settings from RNA properties for operator. */
982 const int mval[2] = {RNA_int_get(op->ptr, "mouse_x"), RNA_int_get(op->ptr, "mouse_y")};
983
984 if (init_event_type == 0) {
985 if (event->val == KM_PRESS) {
986 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, true);
987
988 wmOperatorStatus retval = op->type->exec(C, op);
989 OPERATOR_RETVAL_CHECK(retval);
990
991 op->customdata = POINTER_FROM_INT(int(event->type));
992 if (retval & OPERATOR_RUNNING_MODAL) {
994 }
995 return retval | OPERATOR_PASS_THROUGH;
996 }
997 /* If we are in init phase, and cannot validate init of modal operations,
998 * just fall back to basic exec.
999 */
1000 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
1001
1002 wmOperatorStatus retval = op->type->exec(C, op);
1003 OPERATOR_RETVAL_CHECK(retval);
1004
1005 return retval | OPERATOR_PASS_THROUGH;
1006 }
1007 if (event->type == init_event_type && event->val == KM_RELEASE) {
1008 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
1009
1010 wmOperatorStatus retval = op->type->exec(C, op);
1011 OPERATOR_RETVAL_CHECK(retval);
1012
1013 return retval | OPERATOR_PASS_THROUGH;
1014 }
1015 if (ISMOUSE_MOTION(event->type)) {
1016 const int drag_delta[2] = {
1017 mval[0] - event->mval[0],
1018 mval[1] - event->mval[1],
1019 };
1020 /* If user moves mouse more than defined threshold, we consider select operator as
1021 * finished. Otherwise, it is still running until we get an 'release' event. In any
1022 * case, we pass through event, but select op is not finished yet. */
1023 if (WM_event_drag_test_with_delta(event, drag_delta)) {
1025 }
1026 /* Important not to return anything other than PASS_THROUGH here,
1027 * otherwise it prevents underlying drag detection code to work properly. */
1028 return OPERATOR_PASS_THROUGH;
1029 }
1030
1032}
1033
1035{
1036 ARegion *region = CTX_wm_region(C);
1037
1038 int mval[2];
1039 WM_event_drag_start_mval(event, region, mval);
1040
1041 RNA_int_set(op->ptr, "mouse_x", mval[0]);
1042 RNA_int_set(op->ptr, "mouse_y", mval[1]);
1043
1045
1046 wmOperatorStatus retval = op->type->modal(C, op, event);
1047 OPERATOR_RETVAL_CHECK(retval);
1048 return retval;
1049}
1050
1052{
1053 if (op->flag & OP_IS_INVOKE) {
1054 Scene *scene = CTX_data_scene(C);
1055 View3D *v3d = CTX_wm_view3d(C);
1056
1057 const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
1058 ED_scene_grid_scale(scene, nullptr);
1059
1060 /* Always run, so the values are initialized,
1061 * otherwise we may get differ behavior when `dia != 1.0`. */
1062 RNA_STRUCT_BEGIN (op->ptr, prop) {
1063 if (RNA_property_type(prop) == PROP_FLOAT) {
1065 if (pstype == PROP_DISTANCE) {
1066 /* We don't support arrays yet. */
1067 BLI_assert(RNA_property_array_check(prop) == false);
1068 /* Initialize. */
1069 if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
1070 const float value = RNA_property_float_get_default(op->ptr, prop) * dia;
1071 RNA_property_float_set(op->ptr, prop, value);
1072 }
1073 }
1074 }
1075 }
1077 }
1078}
1079
1081{
1082 return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0;
1083}
1084
1086{
1087 PropertyRNA *prop = op->type->prop;
1088
1089 if (prop == nullptr) {
1090 CLOG_ERROR(WM_LOG_OPERATORS, "'%s' has no enum property set", op->type->idname);
1091 }
1092 else if (RNA_property_type(prop) != PROP_ENUM) {
1094 "'%s', '%s' is not an enum property",
1095 op->type->idname,
1097 }
1098 else if (RNA_property_is_set(op->ptr, prop)) {
1099 const wmOperatorStatus retval = op->type->exec(C, op);
1100 OPERATOR_RETVAL_CHECK(retval);
1101 return retval;
1102 }
1103 else {
1105 C, WM_operatortype_name(op->type, op->ptr).c_str(), ICON_NONE);
1106 uiLayout *layout = UI_popup_menu_layout(pup);
1107 /* Set this so the default execution context is the same as submenus. */
1108 uiLayoutSetOperatorContext(layout, opcontext);
1109 uiItemsFullEnumO(layout,
1110 op->type->idname,
1112 static_cast<IDProperty *>(op->ptr->data),
1113 opcontext,
1114 UI_ITEM_NONE);
1115 UI_popup_menu_end(C, pup);
1116 return OPERATOR_INTERFACE;
1117 }
1118
1119 return OPERATOR_CANCELLED;
1120}
1121
1126
1128 wmOperator *op; /* The operator that will be executed when selecting an item. */
1129};
1130
1132static uiBlock *wm_enum_search_menu(bContext *C, ARegion *region, void *arg)
1133{
1134 EnumSearchMenu *search_menu = static_cast<EnumSearchMenu *>(arg);
1135 wmWindow *win = CTX_wm_window(C);
1136 wmOperator *op = search_menu->op;
1137 /* `template_ID` uses `4 * widget_unit` for width,
1138 * we use a bit more, some items may have a suffix to show. */
1139 const int width = UI_searchbox_size_x();
1140 const int height = UI_searchbox_size_y();
1141 static char search[256] = "";
1142
1143 uiBlock *block = UI_block_begin(C, region, "_popup", blender::ui::EmbossType::Emboss);
1146
1147 search[0] = '\0';
1148#if 0 /* Ok, this isn't so easy. */
1149 uiDefBut(block,
1151 0,
1152 WM_operatortype_name(op->type, op->ptr),
1153 0,
1154 0,
1156 UI_UNIT_Y,
1157 nullptr,
1158 0.0,
1159 0.0,
1160 "");
1161#endif
1162 uiBut *but = uiDefSearchButO_ptr(block,
1163 op->type,
1164 static_cast<IDProperty *>(op->ptr->data),
1165 search,
1166 0,
1167 ICON_VIEWZOOM,
1168 sizeof(search),
1169 0,
1170 0,
1171 width,
1172 UI_UNIT_Y,
1173 "");
1174
1175 /* Fake button, it holds space for search items. */
1176 uiDefBut(block, UI_BTYPE_LABEL, 0, "", 0, -height, width, height, nullptr, 0, 0, std::nullopt);
1177
1178 /* Move it downwards, mouse over button. */
1180
1182
1183 return block;
1184}
1185
1187{
1188 static EnumSearchMenu search_menu;
1189 search_menu.op = op;
1190 /* Refreshing not supported, because operator might get freed. */
1191 const bool can_refresh = false;
1192 UI_popup_block_invoke_ex(C, wm_enum_search_menu, &search_menu, nullptr, can_refresh);
1193 return OPERATOR_INTERFACE;
1194}
1195
1197 wmOperator *op,
1198 const char *title,
1199 const int icon,
1200 const char *message,
1201 const wmOperatorCallContext /*opcontext*/)
1202{
1203 int alert_icon = ALERT_ICON_QUESTION;
1204 switch (icon) {
1205 case ICON_NONE:
1206 alert_icon = ALERT_ICON_NONE;
1207 break;
1208 case ICON_ERROR:
1209 alert_icon = ALERT_ICON_WARNING;
1210 break;
1211 case ICON_QUESTION:
1212 alert_icon = ALERT_ICON_QUESTION;
1213 break;
1214 case ICON_CANCEL:
1215 alert_icon = ALERT_ICON_ERROR;
1216 break;
1217 case ICON_INFO:
1218 alert_icon = ALERT_ICON_INFO;
1219 break;
1220 }
1221 return WM_operator_confirm_ex(C, op, IFACE_(title), nullptr, IFACE_(message), alert_icon, false);
1222}
1223
1225{
1227 C, op, IFACE_(message), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1228}
1229
1231{
1233 C, op, IFACE_(op->type->name), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1234}
1235
1237 wmOperator *op,
1238 const wmEvent * /*event*/)
1239{
1240 const bool confirm = RNA_boolean_get(op->ptr, "confirm");
1241 if (confirm) {
1243 C, op, IFACE_(op->type->name), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1244 }
1245 return op->type->exec(C, op);
1246}
1247
1249{
1250 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
1251 return WM_operator_call_notest(C, op); /* Call exec direct. */
1252 }
1255}
1256
1258{
1259 char filepath[FILE_MAX];
1260 /* Don't nullptr check prop, this can only run on ops with a 'filepath'. */
1261 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
1262 RNA_property_string_get(op->ptr, prop, filepath);
1263 if (BKE_image_path_ext_from_imformat_ensure(filepath, sizeof(filepath), im_format)) {
1264 RNA_property_string_set(op->ptr, prop, filepath);
1265 /* NOTE: we could check for and update 'filename' here,
1266 * but so far nothing needs this. */
1267 return true;
1268 }
1269 return false;
1270}
1271
1273{
1274 if (CTX_wm_window(C) == nullptr) {
1275 return false;
1276 }
1277 return true;
1278}
1279
1280bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
1281{
1283 Scene *scene = CTX_data_scene(C);
1284
1285 return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY));
1286}
1287
1289{
1291
1292 /* Only for operators that are registered and did an undo push. */
1294 if ((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO)) {
1295 return op;
1296 }
1297 }
1298
1299 return nullptr;
1300}
1301
1303{
1304 if (ot->last_properties == nullptr) {
1305 ot->last_properties = blender::bke::idprop::create_group("wmOperatorProperties").release();
1306 }
1307 return ot->last_properties;
1308}
1309
1315
1317{
1318 Main *bmain = CTX_data_main(C);
1319 ID *id = nullptr;
1320
1321 /* Check input variables. */
1322 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
1323 const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
1324 char filepath[FILE_MAX];
1325 bool exists = false;
1326
1327 RNA_string_get(op->ptr, "filepath", filepath);
1328
1329 errno = 0;
1330
1331 if (idcode == ID_IM) {
1332 id = reinterpret_cast<ID *>(BKE_image_load_exists(bmain, filepath, &exists));
1333 }
1334 else {
1336 }
1337
1338 if (!id) {
1339 BKE_reportf(op->reports,
1340 RPT_ERROR,
1341 "Cannot read %s '%s': %s",
1343 filepath,
1344 errno ? strerror(errno) : RPT_("unsupported format"));
1345 return nullptr;
1346 }
1347
1348 if (is_relative_path) {
1349 if (exists == false) {
1350 if (idcode == ID_IM) {
1351 BLI_path_rel(((Image *)id)->filepath, BKE_main_blendfile_path(bmain));
1352 }
1353 else {
1355 }
1356 }
1357 }
1358
1359 return id;
1360 }
1361
1363 return nullptr;
1364 }
1365
1366 /* Lookup an already existing ID. */
1368
1369 if (!id) {
1370 /* Print error with the name if the name is available. */
1371
1372 if (RNA_struct_property_is_set(op->ptr, "name")) {
1373 char name[MAX_ID_NAME - 2];
1374 RNA_string_get(op->ptr, "name", name);
1376 op->reports, RPT_ERROR, "%s '%s' not found", BKE_idtype_idcode_to_name(idcode), name);
1377 return nullptr;
1378 }
1379
1380 BKE_reportf(op->reports, RPT_ERROR, "%s not found", BKE_idtype_idcode_to_name(idcode));
1381 return nullptr;
1382 }
1383
1384 id_us_plus(id);
1385 return id;
1386}
1387
1388static void wm_block_redo_cb(bContext *C, void *arg_op, int /*arg_event*/)
1389{
1390 wmOperator *op = static_cast<wmOperator *>(arg_op);
1391
1392 if (op == WM_operator_last_redo(C)) {
1393 /* Operator was already executed once? undo & repeat. */
1395 }
1396 else {
1397 /* Operator not executed yet, call it. */
1398 ED_undo_push_op(C, op);
1400
1401 WM_operator_repeat(C, op);
1402 }
1403}
1404
1405static void wm_block_redo_cancel_cb(bContext *C, void *arg_op)
1406{
1407 wmOperator *op = static_cast<wmOperator *>(arg_op);
1408
1409 /* If operator never got executed, free it. */
1410 if (op != WM_operator_last_redo(C)) {
1411 WM_operator_free(op);
1412 }
1413}
1414
1415static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
1416{
1417 wmOperator *op = static_cast<wmOperator *>(arg_op);
1418 const uiStyle *style = UI_style_get_dpi();
1419 int width = 15 * UI_UNIT_X;
1420
1421 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1424
1425 /* #UI_BLOCK_NUMSELECT for layer buttons. */
1427
1428 /* If register is not enabled, the operator gets freed on #OPERATOR_FINISHED
1429 * ui_apply_but_funcs_after calls #ED_undo_operator_repeate_cb and crashes. */
1431
1433 UI_popup_dummy_panel_set(region, block);
1434 uiLayout *layout = UI_block_layout(
1435 block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style);
1436
1437 if (op == WM_operator_last_redo(C)) {
1439 uiLayoutSetEnabled(layout, false);
1440 }
1441 }
1442
1443 uiItemL_ex(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE, true, false);
1444 layout->separator(0.2f, LayoutSeparatorType::Line);
1445 layout->separator(0.5f);
1446
1447 uiLayout *col = &layout->column(false);
1449
1450 UI_block_bounds_set_popup(block, 7 * UI_SCALE_FAC, nullptr);
1451
1452 return block;
1453}
1454
1469
1470/* Only invoked by OK button in popups created with #wm_block_dialog_create(). */
1471static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
1472{
1473 wmOperator *op;
1474 {
1475 /* Execute will free the operator.
1476 * In this case, wm_operator_ui_popup_cancel won't run. */
1477 wmOpPopUp *data = static_cast<wmOpPopUp *>(arg1);
1478 op = data->op;
1479 MEM_delete(data);
1480 }
1481
1482 uiBlock *block = static_cast<uiBlock *>(arg2);
1483 /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled
1484 * in case WM_operator_call_ex exits/reloads the current file (#49199). */
1485
1487
1488 /* Get context data *after* WM_operator_call_ex
1489 * which might have closed the current file and changed context. */
1490 wmWindow *win = CTX_wm_window(C);
1491 UI_popup_block_close(C, win, block);
1492
1493 WM_operator_call_ex(C, op, true);
1494}
1495
1496static void wm_operator_ui_popup_cancel(bContext *C, void *user_data);
1497
1498/* Only invoked by Cancel button in popups created with #wm_block_dialog_create(). */
1499static void dialog_cancel_cb(bContext *C, void *arg1, void *arg2)
1500{
1502 uiBlock *block = static_cast<uiBlock *>(arg2);
1504 wmWindow *win = CTX_wm_window(C);
1505 UI_popup_block_close(C, win, block);
1506}
1507
1511static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_data)
1512{
1513 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1514 wmOperator *op = data->op;
1515 const uiStyle *style = UI_style_get_dpi();
1516 const bool small = data->size == WM_POPUP_SIZE_SMALL;
1517 const short icon_size = (small ? 32 : 40) * UI_SCALE_FAC;
1518
1519 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1522 UI_popup_dummy_panel_set(region, block);
1523
1524 if (data->mouse_move_quit) {
1526 }
1527 if (data->icon < ALERT_ICON_NONE || data->icon >= ALERT_ICON_MAX) {
1528 data->icon = ALERT_ICON_QUESTION;
1529 }
1530
1532
1533 UI_fontstyle_set(&style->widget);
1534 /* Width based on the text lengths. */
1535 int text_width = std::max(
1536 120 * UI_SCALE_FAC,
1537 BLF_width(style->widget.uifont_id, data->title.c_str(), BLF_DRAW_STR_DUMMY_MAX));
1538
1539 /* Break Message into multiple lines. */
1540 blender::Vector<std::string> message_lines;
1541 blender::StringRef messaged_trimmed = blender::StringRef(data->message).trim();
1542 std::istringstream message_stream(messaged_trimmed);
1543 std::string line;
1544 while (std::getline(message_stream, line)) {
1545 message_lines.append(line);
1546 text_width = std::max(
1547 text_width, int(BLF_width(style->widget.uifont_id, line.c_str(), BLF_DRAW_STR_DUMMY_MAX)));
1548 }
1549
1550 int dialog_width = std::max(text_width + int(style->columnspace * 2.5), data->width);
1551
1552 /* Adjust width if the button text is long. */
1553 const int longest_button_text = std::max(
1554 BLF_width(style->widget.uifont_id, data->confirm_text.c_str(), BLF_DRAW_STR_DUMMY_MAX),
1556 dialog_width = std::max(dialog_width, 3 * longest_button_text);
1557
1558 uiLayout *layout;
1559 if (data->icon != ALERT_ICON_NONE) {
1560 layout = uiItemsAlertBox(
1561 block, style, dialog_width + icon_size, eAlertIcon(data->icon), icon_size);
1562 }
1563 else {
1564 layout = UI_block_layout(
1565 block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style);
1566 }
1567
1568 /* Title. */
1569 if (!data->title.empty()) {
1570 uiItemL_ex(layout, data->title, ICON_NONE, true, false);
1571
1572 /* Line under the title if there are properties but no message body. */
1573 if (data->include_properties && message_lines.size() == 0) {
1574 layout->separator(0.2f, LayoutSeparatorType::Line);
1575 };
1576 }
1577
1578 /* Message lines. */
1579 if (message_lines.size() > 0) {
1580 uiLayout *lines = &layout->column(false);
1581 uiLayoutSetScaleY(lines, 0.65f);
1582 lines->separator(0.1f);
1583 for (auto &st : message_lines) {
1584 lines->label(st, ICON_NONE);
1585 }
1586 }
1587
1588 if (data->include_properties) {
1589 layout->separator(0.5f);
1591 }
1592
1593 layout->separator(small ? 0.1f : 1.8f);
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 its 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 = &layout->column(false);
1609 uiBlock *col_block = uiLayoutGetBlock(col);
1610 uiBut *confirm_but;
1611 uiBut *cancel_but;
1612
1613 col = &col->split(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 col->column(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 col->column(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__, blender::ui::EmbossType::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 bContext *C,
1778 wmOperator *op,
1779 const bool do_call,
1780 const bool do_redo,
1781 std::optional<std::string> title = std::nullopt,
1782 std::optional<std::string> confirm_text = std::nullopt,
1783 const bool cancel_default = false)
1784{
1785 if ((op->type->flag & OPTYPE_REGISTER) == 0) {
1786 BKE_reportf(op->reports,
1787 RPT_ERROR,
1788 "Operator '%s' does not have register enabled, incorrect invoke function",
1789 op->type->idname);
1790 return OPERATOR_CANCELLED;
1791 }
1792
1793 if (do_redo) {
1794 if ((op->type->flag & OPTYPE_UNDO) == 0) {
1795 BKE_reportf(op->reports,
1796 RPT_ERROR,
1797 "Operator '%s' does not have undo enabled, incorrect invoke function",
1798 op->type->idname);
1799 return OPERATOR_CANCELLED;
1800 }
1801 }
1802
1803 /* If we don't have global undo, we can't do undo push for automatic redo,
1804 * so we require manual OK clicking in this popup. */
1805 if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) {
1806 return WM_operator_props_dialog_popup(C, op, 300, title, confirm_text, cancel_default);
1807 }
1808
1810
1811 if (do_call) {
1812 wm_block_redo_cb(C, op, 0);
1813 }
1814
1816}
1817
1819 wmOperator *op,
1820 const wmEvent * /*event*/,
1821 std::optional<std::string> title,
1822 std::optional<std::string> confirm_text,
1823 const bool cancel_default)
1824{
1825 return wm_operator_props_popup_ex(C, op, false, false, title, confirm_text, cancel_default);
1826}
1827
1829 wmOperator *op,
1830 const wmEvent * /*event*/)
1831{
1832 return wm_operator_props_popup_ex(C, op, false, false, {}, {});
1833}
1834
1836 wmOperator *op,
1837 const wmEvent * /*event*/)
1838{
1839 return wm_operator_props_popup_ex(C, op, true, true);
1840}
1841
1843{
1844 return wm_operator_props_popup_ex(C, op, false, true);
1845}
1846
1848 wmOperator *op,
1849 int width,
1850 std::optional<std::string> title,
1851 std::optional<std::string> confirm_text,
1852 const bool cancel_default)
1853{
1854 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1855 data->op = op;
1856 data->width = int(float(width) * UI_SCALE_FAC * UI_style_get()->widget.points /
1858 data->free_op = true; /* If this runs and gets registered we may want not to free it. */
1859 data->title = title ? std::move(*title) : WM_operatortype_name(op->type, op->ptr);
1860 data->confirm_text = confirm_text ? std::move(*confirm_text) : IFACE_("OK");
1861 data->icon = ALERT_ICON_NONE;
1862 data->size = WM_POPUP_SIZE_SMALL;
1863 data->position = WM_POPUP_POSITION_MOUSE;
1864 data->cancel_default = cancel_default;
1865 data->mouse_move_quit = false;
1866 data->include_properties = true;
1867
1868 /* The operator is not executed until popup OK button is clicked. */
1871
1873}
1874
1876{
1877 /* `CTX_wm_reports(C)` because operator is on stack, not active in event system. */
1878 if ((op->type->flag & OPTYPE_REGISTER) == 0) {
1880 RPT_ERROR,
1881 "Operator redo '%s' does not have register enabled, incorrect invoke function",
1882 op->type->idname);
1883 return OPERATOR_CANCELLED;
1884 }
1885 if (op->type->poll && op->type->poll(C) == 0) {
1887 CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context", op->type->idname);
1888 return OPERATOR_CANCELLED;
1889 }
1890
1891 /* Operator is stored and kept alive in the window manager. So passing a pointer to the UI is
1892 * fine, it will remain valid. */
1894
1895 return OPERATOR_CANCELLED;
1896}
1897
1899
1900/* -------------------------------------------------------------------- */
1905
1907{
1908 G.debug_value = RNA_int_get(op->ptr, "debug_value");
1911
1912 return OPERATOR_FINISHED;
1913}
1914
1916 wmOperator *op,
1917 const wmEvent * /*event*/)
1918{
1919 RNA_int_set(op->ptr, "debug_value", G.debug_value);
1920 return WM_operator_props_dialog_popup(C, op, 250, IFACE_("Set Debug Value"), IFACE_("Set"));
1921}
1922
1924{
1925 ot->name = "Debug Menu";
1926 ot->idname = "WM_OT_debug_menu";
1927 ot->description = "Open a popup to set the debug level";
1928
1929 ot->invoke = wm_debug_menu_invoke;
1930 ot->exec = wm_debug_menu_exec;
1931 ot->poll = WM_operator_winactive;
1932
1933 ot->prop = RNA_def_int(
1934 ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000);
1935}
1936
1938
1939/* -------------------------------------------------------------------- */
1942
1944{
1945 PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator);
1946
1947 if (!ptr.data) {
1948 BKE_report(op->reports, RPT_ERROR, "No operator in context");
1949 return OPERATOR_CANCELLED;
1950 }
1951
1953 return OPERATOR_FINISHED;
1954}
1955
1956/* Used by operator preset menu. pre-2.65 this was a 'Reset' button. */
1958{
1959 ot->name = "Restore Operator Defaults";
1960 ot->idname = "WM_OT_operator_defaults";
1961 ot->description = "Set the active operator to its default values";
1962
1964
1965 ot->flag = OPTYPE_INTERNAL;
1966}
1967
1969
1970/* -------------------------------------------------------------------- */
1973
1979
1985
1986static char g_search_text[256] = "";
1987
1988static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdata)
1989{
1990 const SearchPopupInit_Data *init_data = static_cast<const SearchPopupInit_Data *>(userdata);
1991
1992 uiBlock *block = UI_block_begin(C, region, "_popup", blender::ui::EmbossType::Emboss);
1995
1996 uiBut *but = uiDefSearchBut(block,
1998 0,
1999 ICON_VIEWZOOM,
2000 sizeof(g_search_text),
2001 0,
2002 0,
2003 init_data->size[0],
2004 UI_UNIT_Y,
2005 "");
2006
2007 if (init_data->search_type == SEARCH_TYPE_OPERATOR) {
2009 }
2010 else if (init_data->search_type == SEARCH_TYPE_MENU) {
2012 }
2013 else if (init_data->search_type == SEARCH_TYPE_SINGLE_MENU) {
2014 UI_but_func_menu_search(but, init_data->single_menu_idname.c_str());
2016 }
2017 else {
2019 }
2020
2022
2023 /* Fake button, it holds space for search items. */
2024 const int height = init_data->size[1] - UI_SEARCHBOX_BOUNDS;
2025 uiDefBut(block,
2027 0,
2028 "",
2029 0,
2030 -height,
2031 init_data->size[0],
2032 height,
2033 nullptr,
2034 0,
2035 0,
2036 std::nullopt);
2037
2038 /* Move it downwards, mouse over button. */
2040
2041 return block;
2042}
2043
2045{
2046 return OPERATOR_FINISHED;
2047}
2048
2050{
2051 /* Exception for launching via space-bar. */
2052 if (event->type == EVT_SPACEKEY) {
2053 bool ok = true;
2054 ScrArea *area = CTX_wm_area(C);
2055 if (area) {
2056 if (area->spacetype == SPACE_CONSOLE) {
2057 /* So we can use the shortcut in the console. */
2058 ok = false;
2059 }
2060 else if (area->spacetype == SPACE_TEXT) {
2061 /* So we can use the space-bar in the text editor. */
2062 ok = false;
2063 }
2064 }
2065 else {
2066 Object *editob = CTX_data_edit_object(C);
2067 if (editob && editob->type == OB_FONT) {
2068 /* So we can use the space-bar for entering text. */
2069 ok = false;
2070 }
2071 }
2072 if (!ok) {
2073 return OPERATOR_PASS_THROUGH;
2074 }
2075 }
2076
2077 SearchType search_type;
2078 if (STREQ(op->type->idname, "WM_OT_search_menu")) {
2079 search_type = SEARCH_TYPE_MENU;
2080 }
2081 else if (STREQ(op->type->idname, "WM_OT_search_single_menu")) {
2082 search_type = SEARCH_TYPE_SINGLE_MENU;
2083 }
2084 else {
2085 search_type = SEARCH_TYPE_OPERATOR;
2086 }
2087
2088 static SearchPopupInit_Data data{};
2089
2090 if (search_type == SEARCH_TYPE_SINGLE_MENU) {
2091 {
2092 char *buffer = RNA_string_get_alloc(op->ptr, "menu_idname", nullptr, 0, nullptr);
2093 data.single_menu_idname = buffer;
2094 MEM_SAFE_FREE(buffer);
2095 }
2096 {
2097 char *buffer = RNA_string_get_alloc(op->ptr, "initial_query", nullptr, 0, nullptr);
2098 STRNCPY(g_search_text, buffer);
2099 MEM_SAFE_FREE(buffer);
2100 }
2101 }
2102 else {
2103 g_search_text[0] = '\0';
2104 }
2105
2106 data.search_type = search_type;
2107 data.size[0] = UI_searchbox_size_x() * 2;
2108 data.size[1] = UI_searchbox_size_y();
2109
2111
2112 return OPERATOR_INTERFACE;
2113}
2114
2116{
2117 ot->name = "Search Menu";
2118 ot->idname = "WM_OT_search_menu";
2119 ot->description = "Pop-up a search over all menus in the current context";
2120
2121 ot->invoke = wm_search_menu_invoke;
2122 ot->exec = wm_search_menu_exec;
2123 ot->poll = WM_operator_winactive;
2124}
2125
2127{
2128 ot->name = "Search Operator";
2129 ot->idname = "WM_OT_search_operator";
2130 ot->description = "Pop-up a search over all available operators in current context";
2131
2132 ot->invoke = wm_search_menu_invoke;
2133 ot->exec = wm_search_menu_exec;
2134 ot->poll = WM_operator_winactive;
2135}
2136
2138{
2139 ot->name = "Search Single Menu";
2140 ot->idname = "WM_OT_search_single_menu";
2141 ot->description = "Pop-up a search for a menu in current context";
2142
2143 ot->invoke = wm_search_menu_invoke;
2144 ot->exec = wm_search_menu_exec;
2145 ot->poll = WM_operator_winactive;
2146
2147 RNA_def_string(ot->srna, "menu_idname", nullptr, 0, "Menu Name", "Menu to search in");
2148 RNA_def_string(ot->srna,
2149 "initial_query",
2150 nullptr,
2151 0,
2152 "Initial Query",
2153 "Query to insert into the search box");
2154}
2155
2157{
2158 char idname[BKE_ST_MAXNAME];
2159 RNA_string_get(op->ptr, "name", idname);
2160
2161 return UI_popup_menu_invoke(C, idname, op->reports);
2162}
2163
2165{
2166 char idname[BKE_ST_MAXNAME];
2167 RNA_string_get(ptr, "name", idname);
2168 MenuType *mt = WM_menutype_find(idname, true);
2169 return (mt) ? CTX_IFACE_(mt->translation_context, mt->label) :
2170 CTX_IFACE_(ot->translation_context, ot->name);
2171}
2172
2174{
2175 ot->name = "Call Menu";
2176 ot->idname = "WM_OT_call_menu";
2177 ot->description = "Open a predefined menu";
2178
2179 ot->exec = wm_call_menu_exec;
2180 ot->poll = WM_operator_winactive;
2181 ot->get_name = wm_call_menu_get_name;
2182
2183 ot->flag = OPTYPE_INTERNAL;
2184
2185 PropertyRNA *prop;
2186
2187 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the menu");
2189 prop,
2191 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
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, event);
2201}
2202
2204{
2205 char idname[BKE_ST_MAXNAME];
2206 RNA_string_get(op->ptr, "name", idname);
2207
2208 return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate);
2209}
2210
2212{
2213 ot->name = "Call Pie Menu";
2214 ot->idname = "WM_OT_call_menu_pie";
2215 ot->description = "Open a predefined pie menu";
2216
2217 ot->invoke = wm_call_pie_menu_invoke;
2218 ot->exec = wm_call_pie_menu_exec;
2219 ot->poll = WM_operator_winactive;
2220 ot->get_name = wm_call_menu_get_name;
2221
2222 ot->flag = OPTYPE_INTERNAL;
2223
2224 PropertyRNA *prop;
2225
2226 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the pie menu");
2228 prop,
2230 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2232}
2233
2235{
2236 char idname[BKE_ST_MAXNAME];
2237 RNA_string_get(op->ptr, "name", idname);
2238 const bool keep_open = RNA_boolean_get(op->ptr, "keep_open");
2239
2240 return UI_popover_panel_invoke(C, idname, keep_open, op->reports);
2241}
2242
2244{
2245 char idname[BKE_ST_MAXNAME];
2246 RNA_string_get(ptr, "name", idname);
2247 PanelType *pt = WM_paneltype_find(idname, true);
2248 return (pt) ? CTX_IFACE_(pt->translation_context, pt->label) :
2249 CTX_IFACE_(ot->translation_context, ot->name);
2250}
2251
2253{
2254 ot->name = "Call Panel";
2255 ot->idname = "WM_OT_call_panel";
2256 ot->description = "Open a predefined panel";
2257
2258 ot->exec = wm_call_panel_exec;
2259 ot->poll = WM_operator_winactive;
2260 ot->get_name = wm_call_panel_get_name;
2261
2262 ot->flag = OPTYPE_INTERNAL;
2263
2264 PropertyRNA *prop;
2265
2266 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the menu");
2268 prop,
2270 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2273 prop = RNA_def_boolean(ot->srna, "keep_open", true, "Keep Open", "");
2275}
2276
2278 wmOperator *op,
2279 const wmEvent * /*event*/)
2280{
2281 char *asset_shelf_id = RNA_string_get_alloc(op->ptr, "name", nullptr, 0, nullptr);
2282 BLI_SCOPED_DEFER([&]() { MEM_freeN(asset_shelf_id); });
2283
2284 if (!blender::ui::asset_shelf_popover_invoke(*C, asset_shelf_id, *op->reports)) {
2286 }
2287
2288 return OPERATOR_INTERFACE;
2289}
2290
2291/* Needs to be defined at WM level to be globally accessible. */
2293{
2294 /* identifiers */
2295 ot->name = "Call Asset Shelf Popover";
2296 ot->idname = "WM_OT_call_asset_shelf_popover";
2297 ot->description = "Open a predefined asset shelf in a popup";
2298
2299 /* API callbacks. */
2301
2302 ot->flag = OPTYPE_INTERNAL;
2303
2304 RNA_def_string(ot->srna,
2305 "name",
2306 nullptr,
2307 0,
2308 "Asset Shelf Name",
2309 "Identifier of the asset shelf to display");
2310}
2311
2313
2314/* -------------------------------------------------------------------- */
2317
2323{
2324 wmWindow *win = CTX_wm_window(C);
2325 bScreen *screen;
2326
2327 if (win == nullptr) {
2328 return false;
2329 }
2330 if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL))) {
2331 return false;
2332 }
2333 if (G.background) {
2334 return false;
2335 }
2336
2337 return true;
2338}
2339
2341{
2342 wmWindow *win = CTX_wm_window(C);
2343 bScreen *screen;
2344
2345 if (win == nullptr) {
2346 return false;
2347 }
2348 if (!((screen = WM_window_get_active_screen(win)) && (screen->state != SCREENFULL))) {
2349 return false;
2350 }
2351 if (G.background) {
2352 return false;
2353 }
2354
2355 return true;
2356}
2357
2358/* Included for script-access. */
2360{
2361 ot->name = "Close Window";
2362 ot->idname = "WM_OT_window_close";
2363 ot->description = "Close the current window";
2364
2365 ot->exec = wm_window_close_exec;
2366 ot->poll = WM_operator_winactive;
2367}
2368
2370{
2371 ot->name = "New Window";
2372 ot->idname = "WM_OT_window_new";
2373 ot->description = "Create a new window";
2374
2375 ot->exec = wm_window_new_exec;
2377}
2378
2380{
2381 ot->name = "New Main Window";
2382 ot->idname = "WM_OT_window_new_main";
2383 ot->description = "Create a new main window with its own workspace and scene selection";
2384
2387}
2388
2390{
2391 ot->name = "Toggle Window Fullscreen";
2392 ot->idname = "WM_OT_window_fullscreen_toggle";
2393 ot->description = "Toggle the current window full-screen";
2394
2396 ot->poll = WM_operator_winactive;
2397}
2398
2404
2406 wmOperator * /*op*/,
2407 const wmEvent * /*event*/)
2408{
2409 if (U.uiflag & USER_SAVE_PROMPT) {
2411 }
2412 else {
2414 }
2415 return OPERATOR_FINISHED;
2416}
2417
2419{
2420 ot->name = "Quit Blender";
2421 ot->idname = "WM_OT_quit_blender";
2422 ot->description = "Quit Blender";
2423
2424 ot->invoke = wm_exit_blender_invoke;
2425 ot->exec = wm_exit_blender_exec;
2426}
2427
2429
2430/* -------------------------------------------------------------------- */
2433
2434#if defined(WIN32)
2435
2436static wmOperatorStatus wm_console_toggle_exec(bContext * /*C*/, wmOperator * /*op*/)
2437{
2439 return OPERATOR_FINISHED;
2440}
2441
2442static void WM_OT_console_toggle(wmOperatorType *ot)
2443{
2444 /* XXX Have to mark these for xgettext, as under linux they do not exists... */
2445 ot->name = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console");
2446 ot->idname = "WM_OT_console_toggle";
2447 ot->description = N_("Toggle System Console");
2448
2449 ot->exec = wm_console_toggle_exec;
2450 ot->poll = WM_operator_winactive;
2451}
2452
2453#endif
2454
2456
2457/* -------------------------------------------------------------------- */
2465
2467 short region_type,
2468 bool (*poll)(bContext *C),
2469 wmPaintCursorDraw draw,
2470 void *customdata)
2471{
2472 wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
2473
2474 wmPaintCursor *pc = MEM_callocN<wmPaintCursor>("paint cursor");
2475
2476 BLI_addtail(&wm->paintcursors, pc);
2477
2478 pc->customdata = customdata;
2479 pc->poll = poll;
2480 pc->draw = draw;
2481
2482 pc->space_type = space_type;
2483 pc->region_type = region_type;
2484
2485 return pc;
2486}
2487
2489{
2490 wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
2492 if (pc == handle) {
2493 BLI_remlink(&wm->paintcursors, pc);
2494 MEM_freeN(pc);
2495 return true;
2496 }
2497 }
2498 return false;
2499}
2500
2501void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void (*free)(void *))
2502{
2504 if (pc->draw == draw_fn) {
2505 if (free) {
2506 free(pc->customdata);
2507 }
2508 BLI_remlink(&wm->paintcursors, pc);
2509 MEM_freeN(pc);
2510 }
2511 }
2512}
2513
2515
2516/* -------------------------------------------------------------------- */
2519
2520#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_SCALE_FAC)
2521#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * UI_SCALE_FAC)
2522#define WM_RADIAL_CONTROL_DISPLAY_WIDTH \
2523 (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE)
2524#define WM_RADIAL_MAX_STR 10
2525
2555
2557{
2558 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
2559 char msg[UI_MAX_DRAW_STR];
2560 ScrArea *area = CTX_wm_area(C);
2561 Scene *scene = CTX_data_scene(C);
2562
2563 if (hasNumInput(&rc->num_input)) {
2564 char num_str[NUM_STR_REP_LEN];
2565 outputNumInput(&rc->num_input, num_str, scene->unit);
2566 SNPRINTF(msg, "%s: %s", RNA_property_ui_name(rc->prop), num_str);
2567 }
2568 else {
2569 const char *ui_name = RNA_property_ui_name(rc->prop);
2570 switch (rc->subtype) {
2571 case PROP_NONE:
2572 case PROP_DISTANCE:
2573 SNPRINTF(msg, "%s: %0.4f", ui_name, rc->current_value);
2574 break;
2575 case PROP_PIXEL:
2576 SNPRINTF(msg, "%s: %d", ui_name, int(rc->current_value)); /* XXX: round to nearest? */
2577 break;
2578 case PROP_PERCENTAGE:
2579 SNPRINTF(msg, "%s: %3.1f%%", ui_name, rc->current_value);
2580 break;
2581 case PROP_FACTOR:
2582 SNPRINTF(msg, "%s: %1.3f", ui_name, rc->current_value);
2583 break;
2584 case PROP_ANGLE:
2585 SNPRINTF(msg, "%s: %3.2f", ui_name, RAD2DEGF(rc->current_value));
2586 break;
2587 default:
2588 SNPRINTF(msg, "%s", ui_name); /* XXX: No value? */
2589 break;
2590 }
2591 }
2592
2593 ED_area_status_text(area, msg);
2594}
2595
2597{
2598 float d[2] = {0, 0};
2599 float zoom[2] = {1, 1};
2600
2601 copy_v2_v2_int(rc->initial_mouse, event->xy);
2602 copy_v2_v2_int(rc->initial_co, event->xy);
2603
2604 switch (rc->subtype) {
2605 case PROP_NONE:
2606 case PROP_DISTANCE:
2607 case PROP_PIXEL:
2608 d[0] = rc->initial_value;
2609 break;
2610 case PROP_PERCENTAGE:
2611 d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
2613 break;
2614 case PROP_FACTOR:
2617 break;
2618 case PROP_ANGLE:
2621 break;
2622 default:
2623 return;
2624 }
2625
2626 if (rc->zoom_prop) {
2628 d[0] *= zoom[0];
2629 d[1] *= zoom[1];
2630 }
2631
2632 rc->initial_mouse[0] -= d[0];
2633 rc->initial_mouse[1] -= d[1];
2634}
2635
2637{
2638 ImBuf *ibuf;
2639
2640 switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) {
2641 case ID_BR:
2643 static_cast<Brush *>(rc->image_id_ptr.data),
2646 {
2647
2648 rc->texture = GPU_texture_create_2d("radial_control",
2649 ibuf->x,
2650 ibuf->y,
2651 1,
2652 GPU_R8,
2654 ibuf->float_buffer.data);
2655
2657 GPU_texture_swizzle_set(rc->texture, "111r");
2658
2660 MEM_freeN(ibuf);
2661 }
2662 break;
2663 default:
2664 break;
2665 }
2666}
2667
2668static void radial_control_paint_tex(RadialControl *rc, float radius, float alpha)
2669{
2670
2671 /* Set fill color. */
2672 float col[3] = {0, 0, 0};
2673 if (rc->fill_col_prop) {
2674 PointerRNA *fill_ptr;
2675 PropertyRNA *fill_prop;
2676
2677 if (rc->fill_col_override_prop &&
2679 {
2680 fill_ptr = &rc->fill_col_override_ptr;
2681 fill_prop = rc->fill_col_override_prop;
2682 }
2683 else {
2684 fill_ptr = &rc->fill_col_ptr;
2685 fill_prop = rc->fill_col_prop;
2686 }
2687
2688 RNA_property_float_get_array(fill_ptr, fill_prop, col);
2689 }
2690
2693
2694 if (rc->texture) {
2695 uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2696
2697 /* Set up rotation if available. */
2698 if (rc->rot_prop) {
2699 float rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop);
2702 }
2703
2705
2707 immBindTexture("image", rc->texture);
2708
2709 /* Draw textured quad. */
2711
2712 immAttr2f(texCoord, 0, 0);
2713 immVertex2f(pos, -radius, -radius);
2714
2715 immAttr2f(texCoord, 1, 0);
2716 immVertex2f(pos, radius, -radius);
2717
2718 immAttr2f(texCoord, 1, 1);
2719 immVertex2f(pos, radius, radius);
2720
2721 immAttr2f(texCoord, 0, 1);
2722 immVertex2f(pos, -radius, radius);
2723
2724 immEnd();
2725
2727
2728 /* Undo rotation. */
2729 if (rc->rot_prop) {
2731 }
2732 }
2733 else {
2734 /* Flat color if no texture available. */
2737 imm_draw_circle_fill_2d(pos, 0.0f, 0.0f, radius, 40);
2738 }
2739
2741}
2742
2743static void radial_control_paint_curve(uint pos, Brush *br, float radius, int line_segments)
2744{
2745 GPU_line_width(2.0f);
2746 immUniformColor4f(0.8f, 0.8f, 0.8f, 0.85f);
2747 float step = (radius * 2.0f) / float(line_segments);
2749 immBegin(GPU_PRIM_LINES, line_segments * 2);
2750 for (int i = 0; i < line_segments; i++) {
2751 float h1 = BKE_brush_curve_strength_clamped(br, fabsf((i * step) - radius), radius);
2752 immVertex2f(pos, -radius + (i * step), h1 * radius);
2753 float h2 = BKE_brush_curve_strength_clamped(br, fabsf(((i + 1) * step) - radius), radius);
2754 immVertex2f(pos, -radius + ((i + 1) * step), h2 * radius);
2755 }
2756 immEnd();
2757}
2758
2760 const blender::int2 & /*xy*/,
2761 const blender::float2 & /*tilt*/,
2762 void *customdata)
2763{
2764 RadialControl *rc = static_cast<RadialControl *>(customdata);
2765 const uiStyle *style = UI_style_get();
2766 const uiFontStyle *fstyle = &style->widget;
2767 const int fontid = fstyle->uifont_id;
2768 short fstyle_points = fstyle->points;
2769 char str[WM_RADIAL_MAX_STR];
2770 short strdrawlen = 0;
2771 float strwidth, strheight;
2772 float r1 = 0.0f, r2 = 0.0f, rmin = 0.0, tex_radius, alpha;
2773 float zoom[2], col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2774 float text_color[4];
2775
2776 switch (rc->subtype) {
2777 case PROP_NONE:
2778 case PROP_DISTANCE:
2779 case PROP_PIXEL:
2780 r1 = rc->current_value;
2781 r2 = rc->initial_value;
2782 tex_radius = r1;
2783 alpha = 0.75;
2784 break;
2785 case PROP_PERCENTAGE:
2788 r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2790 SNPRINTF(str, "%3.1f%%", rc->current_value);
2791 strdrawlen = BLI_strlen_utf8(str);
2792 tex_radius = r1;
2793 alpha = 0.75;
2794 break;
2795 case PROP_FACTOR:
2798 r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2800 alpha = rc->current_value / 2.0f + 0.5f;
2801 SNPRINTF(str, "%1.3f", rc->current_value);
2802 strdrawlen = BLI_strlen_utf8(str);
2803 break;
2804 case PROP_ANGLE:
2805 r1 = r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2806 alpha = 0.75;
2808 SNPRINTF(str, "%3.2f", RAD2DEGF(rc->current_value));
2809 strdrawlen = BLI_strlen_utf8(str);
2810 break;
2811 default:
2812 tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* NOTE: this is a dummy value. */
2813 alpha = 0.75;
2814 break;
2815 }
2816
2817 int x, y;
2818 if (rc->subtype == PROP_ANGLE) {
2819 /* Use the initial mouse position to draw the rotation preview. This avoids starting the
2820 * rotation in a random direction. */
2821 x = rc->initial_mouse[0];
2822 y = rc->initial_mouse[1];
2823 }
2824 else {
2825 /* Keep cursor in the original place. */
2826 x = rc->initial_co[0];
2827 y = rc->initial_co[1];
2828 }
2829 GPU_matrix_translate_2f(float(x), float(y));
2830
2832 GPU_line_smooth(true);
2833
2834 /* Apply zoom if available. */
2835 if (rc->zoom_prop) {
2838 }
2839
2840 /* Draw rotated texture. */
2841 radial_control_paint_tex(rc, tex_radius, alpha);
2842
2843 /* Set line color. */
2844 if (rc->col_prop) {
2846 }
2847
2850
2852
2853 if (rc->subtype == PROP_ANGLE) {
2855
2856 /* Draw original angle line. */
2857 GPU_matrix_rotate_3f(RAD2DEGF(rc->initial_value), 0.0f, 0.0f, 1.0f);
2861 immEnd();
2862
2863 /* Draw new angle line. */
2864 GPU_matrix_rotate_3f(RAD2DEGF(rc->current_value - rc->initial_value), 0.0f, 0.0f, 1.0f);
2868 immEnd();
2869
2871 }
2872
2873 /* Draw circles on top. */
2874 GPU_line_width(2.0f);
2876 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 80);
2877
2878 GPU_line_width(1.0f);
2880 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 80);
2881 if (rmin > 0.0f) {
2882 /* Inner fill circle to increase the contrast of the value. */
2883 const float black[3] = {0.0f};
2884 immUniformColor3fvAlpha(black, 0.2f);
2885 imm_draw_circle_fill_2d(pos, 0.0, 0.0f, rmin, 80);
2886
2888 imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 80);
2889 }
2890
2891 /* Draw curve falloff preview. */
2893 Brush *br = static_cast<Brush *>(rc->image_id_ptr.data);
2894 if (br) {
2895 radial_control_paint_curve(pos, br, r2, 120);
2896 }
2897 }
2898
2900
2901 BLF_size(fontid, 1.75f * fstyle_points * UI_SCALE_FAC);
2902 UI_GetThemeColor4fv(TH_TEXT_HI, text_color);
2903 BLF_color4fv(fontid, text_color);
2904
2905 /* Draw value. */
2906 BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight);
2907 BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
2908 BLF_draw(fontid, str, strdrawlen);
2909
2911 GPU_line_smooth(false);
2912}
2913
2919
2926 wmOperator *op,
2927 const char *name,
2928 PointerRNA *r_ptr,
2929 PropertyRNA **r_prop,
2930 int req_length,
2931 RCPropFlags flags)
2932{
2933 PropertyRNA *unused_prop;
2934
2935 /* Check flags. */
2936 if ((flags & RC_PROP_REQUIRE_BOOL) && (flags & RC_PROP_REQUIRE_FLOAT)) {
2937 BKE_report(op->reports, RPT_ERROR, "Property cannot be both boolean and float");
2938 return 0;
2939 }
2940
2941 /* Get an rna string path from the operator's properties. */
2942 char *str;
2943 if (!(str = RNA_string_get_alloc(op->ptr, name, nullptr, 0, nullptr))) {
2944 return 1;
2945 }
2946
2947 if (str[0] == '\0') {
2948 if (r_prop) {
2949 *r_prop = nullptr;
2950 }
2951 MEM_freeN(str);
2952 return 1;
2953 }
2954
2955 if (!r_prop) {
2956 r_prop = &unused_prop;
2957 }
2958
2959 /* Get rna from path. */
2960 if (!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) {
2961 MEM_freeN(str);
2962 if (flags & RC_PROP_ALLOW_MISSING) {
2963 return 1;
2964 }
2965 BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name);
2966 return 0;
2967 }
2968
2969 /* Check property type. */
2971 PropertyType prop_type = RNA_property_type(*r_prop);
2972
2973 if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) ||
2974 ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT)))
2975 {
2976 MEM_freeN(str);
2977 BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name);
2978 return 0;
2979 }
2980 }
2981
2982 /* Check property's array length. */
2983 int len;
2984 if (*r_prop && (len = RNA_property_array_length(r_ptr, *r_prop)) != req_length) {
2985 MEM_freeN(str);
2986 BKE_reportf(op->reports,
2987 RPT_ERROR,
2988 "Property from path '%s' has length %d instead of %d",
2989 name,
2990 len,
2991 req_length);
2992 return 0;
2993 }
2994
2995 /* Success. */
2996 MEM_freeN(str);
2997 return 1;
2998}
2999
3000/* Initialize the rna pointers and properties using rna paths. */
3002{
3003 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3004
3005 PointerRNA ctx_ptr = RNA_pointer_create_discrete(nullptr, &RNA_Context, C);
3006
3007 /* Check if we use primary or secondary path. */
3008 PointerRNA use_secondary_ptr;
3009 PropertyRNA *use_secondary_prop = nullptr;
3010 if (!radial_control_get_path(&ctx_ptr,
3011 op,
3012 "use_secondary",
3013 &use_secondary_ptr,
3014 &use_secondary_prop,
3015 0,
3017 {
3018 return 0;
3019 }
3020
3021 const char *data_path;
3022 if (use_secondary_prop && RNA_property_boolean_get(&use_secondary_ptr, use_secondary_prop)) {
3023 data_path = "data_path_secondary";
3024 }
3025 else {
3026 data_path = "data_path_primary";
3027 }
3028
3029 if (!radial_control_get_path(&ctx_ptr, op, data_path, &rc->ptr, &rc->prop, 0, RCPropFlags(0))) {
3030 return 0;
3031 }
3032
3033 /* Data path is required. */
3034 if (!rc->prop) {
3035 return 0;
3036 }
3037
3039 &ctx_ptr, op, "rotation_path", &rc->rot_ptr, &rc->rot_prop, 0, RC_PROP_REQUIRE_FLOAT))
3040 {
3041 return 0;
3042 }
3043
3045 &ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 4, RC_PROP_REQUIRE_FLOAT))
3046 {
3047 return 0;
3048 }
3049
3050 if (!radial_control_get_path(&ctx_ptr,
3051 op,
3052 "fill_color_path",
3053 &rc->fill_col_ptr,
3054 &rc->fill_col_prop,
3055 3,
3057 {
3058 return 0;
3059 }
3060
3061 if (!radial_control_get_path(&ctx_ptr,
3062 op,
3063 "fill_color_override_path",
3066 3,
3068 {
3069 return 0;
3070 }
3071 if (!radial_control_get_path(&ctx_ptr,
3072 op,
3073 "fill_color_override_test_path",
3076 0,
3078 {
3079 return 0;
3080 }
3081
3082 /* Slightly ugly; allow this property to not resolve correctly.
3083 * Needed because 3d texture paint shares the same key-map as 2d image paint. */
3084 if (!radial_control_get_path(&ctx_ptr,
3085 op,
3086 "zoom_path",
3087 &rc->zoom_ptr,
3088 &rc->zoom_prop,
3089 2,
3091 {
3092 return 0;
3093 }
3094
3096 &ctx_ptr, op, "image_id", &rc->image_id_ptr, nullptr, 0, RCPropFlags(0)))
3097 {
3098 return 0;
3099 }
3100 if (rc->image_id_ptr.data) {
3101 /* Extra check, pointer must be to an ID. */
3103 BKE_report(op->reports, RPT_ERROR, "Pointer from path image_id is not an ID");
3104 return 0;
3105 }
3106 }
3107
3108 rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex");
3109
3110 return 1;
3111}
3112
3114{
3115 op->customdata = MEM_new<RadialControl>(__func__);
3116 if (!op->customdata) {
3117 return OPERATOR_CANCELLED;
3118 }
3119 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3120
3121 if (!radial_control_get_properties(C, op)) {
3122 MEM_delete(rc);
3123 return OPERATOR_CANCELLED;
3124 }
3125
3126 /* Get type, initial, min, and max values of the property. */
3127 switch (rc->type = RNA_property_type(rc->prop)) {
3128 case PROP_INT: {
3129 int value, min, max, step;
3130
3131 value = RNA_property_int_get(&rc->ptr, rc->prop);
3132 RNA_property_int_ui_range(&rc->ptr, rc->prop, &min, &max, &step);
3133
3134 rc->initial_value = value;
3135 rc->min_value = min_ii(value, min);
3136 rc->max_value = max_ii(value, max);
3137 break;
3138 }
3139 case PROP_FLOAT: {
3140 float value, min, max, step, precision;
3141
3142 value = RNA_property_float_get(&rc->ptr, rc->prop);
3143 RNA_property_float_ui_range(&rc->ptr, rc->prop, &min, &max, &step, &precision);
3144
3145 rc->initial_value = value;
3146 rc->min_value = min_ff(value, min);
3147 rc->max_value = max_ff(value, max);
3148 break;
3149 }
3150 default:
3151 BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float");
3152 MEM_delete(rc);
3153 return OPERATOR_CANCELLED;
3154 }
3155
3156 /* Initialize numerical input. */
3157 initNumInput(&rc->num_input);
3158 rc->num_input.idx_max = 0;
3162
3163 /* Get subtype of property. */
3165 if (!ELEM(rc->subtype,
3166 PROP_NONE,
3170 PROP_ANGLE,
3171 PROP_PIXEL))
3172 {
3173 BKE_report(op->reports,
3174 RPT_ERROR,
3175 "Property must be a none, distance, factor, percentage, angle, or pixel");
3176 MEM_delete(rc);
3177 return OPERATOR_CANCELLED;
3178 }
3179
3180 rc->current_value = rc->initial_value;
3183
3185
3186 /* Temporarily disable other paint cursors. */
3190
3191 /* Add radial control paint cursor. */
3194
3196
3198}
3199
3200static void radial_control_set_value(RadialControl *rc, float val)
3201{
3202 switch (rc->type) {
3203 case PROP_INT:
3204 RNA_property_int_set(&rc->ptr, rc->prop, val);
3205 break;
3206 case PROP_FLOAT:
3207 RNA_property_float_set(&rc->ptr, rc->prop, val);
3208 break;
3209 default:
3210 break;
3211 }
3212}
3213
3215{
3216 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3218 ScrArea *area = CTX_wm_area(C);
3219
3220 if (rc->dial) {
3221 BLI_dial_free(rc->dial);
3222 rc->dial = nullptr;
3223 }
3224
3225 ED_area_status_text(area, nullptr);
3226
3227 WM_paint_cursor_end(static_cast<wmPaintCursor *>(rc->cursor));
3228
3229 /* Restore original paint cursors. */
3231
3232 /* Not sure if this is a good notifier to use;
3233 * intended purpose is to update the UI so that the
3234 * new value is displayed in sliders/number-fields. */
3236
3237 if (rc->texture != nullptr) {
3239 }
3240
3241 MEM_delete(rc);
3242}
3243
3245{
3246 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3247 float new_value, dist = 0.0f, zoom[2];
3248 float delta[2];
3250 float angle_precision = 0.0f;
3251 const bool has_numInput = hasNumInput(&rc->num_input);
3252 bool handled = false;
3253 float numValue;
3254 /* TODO: fix hard-coded events. */
3255
3256 bool snap = (event->modifier & KM_CTRL) != 0;
3257
3258 /* Modal numinput active, try to handle numeric inputs first... */
3259 if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) {
3260 handled = true;
3261 applyNumInput(&rc->num_input, &numValue);
3262
3263 if (rc->subtype == PROP_ANGLE) {
3264 numValue = fmod(numValue, 2.0f * float(M_PI));
3265 if (numValue < 0.0f) {
3266 numValue += 2.0f * float(M_PI);
3267 }
3268 }
3269
3270 CLAMP(numValue, rc->min_value, rc->max_value);
3271 new_value = numValue;
3272
3273 radial_control_set_value(rc, new_value);
3274 rc->current_value = new_value;
3277 }
3278
3279 handled = false;
3280 switch (event->type) {
3281 case EVT_ESCKEY:
3282 case RIGHTMOUSE:
3283 /* Canceled; restore original value. */
3284 if (rc->init_event != RIGHTMOUSE) {
3287 }
3288 break;
3289
3290 case LEFTMOUSE:
3291 case EVT_PADENTER:
3292 case EVT_RETKEY:
3293 /* Done; value already set. */
3294 /* Keep the RNA update separate from setting the value, for some properties this could lead
3295 * to a continues flickering due to invalidating the overlay texture. */
3296 RNA_property_update(C, &rc->ptr, rc->prop);
3298 break;
3299
3300 case MOUSEMOVE:
3301 if (!has_numInput) {
3302 if (rc->slow_mode) {
3303 if (rc->subtype == PROP_ANGLE) {
3304 /* Calculate the initial angle here first. */
3305 delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
3306 delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
3307
3308 /* Precision angle gets calculated from dial and gets added later. */
3309 angle_precision = -0.1f * BLI_dial_angle(rc->dial,
3310 blender::float2{float(event->xy[0]),
3311 float(event->xy[1])});
3312 }
3313 else {
3314 delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
3315 delta[1] = 0.0f;
3316
3317 if (rc->zoom_prop) {
3319 delta[0] /= zoom[0];
3320 }
3321
3322 dist = len_v2(delta);
3323
3324 delta[0] = event->xy[0] - rc->slow_mouse[0];
3325
3326 if (rc->zoom_prop) {
3327 delta[0] /= zoom[0];
3328 }
3329
3330 dist = dist + 0.1f * (delta[0]);
3331 }
3332 }
3333 else {
3334 delta[0] = float(rc->initial_mouse[0] - event->xy[0]);
3335 delta[1] = float(rc->initial_mouse[1] - event->xy[1]);
3336 if (rc->zoom_prop) {
3338 delta[0] /= zoom[0];
3339 delta[1] /= zoom[1];
3340 }
3341 if (rc->subtype == PROP_ANGLE) {
3342 dist = len_v2(delta);
3343 }
3344 else {
3345 dist = clamp_f(-delta[0], 0.0f, FLT_MAX);
3346 }
3347 }
3348
3349 /* Calculate new value and apply snapping. */
3350 switch (rc->subtype) {
3351 case PROP_NONE:
3352 case PROP_DISTANCE:
3353 case PROP_PIXEL:
3354 new_value = dist;
3355 if (snap) {
3356 new_value = (int(new_value) + 5) / 10 * 10;
3357 }
3358 break;
3359 case PROP_PERCENTAGE:
3360 new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) /
3362 100.0f;
3363 if (snap) {
3364 new_value = int(new_value + 2.5f) / 5 * 5;
3365 }
3366 break;
3367 case PROP_FACTOR:
3369 if (snap) {
3370 new_value = (int(ceil(new_value * 10.0f)) * 10.0f) / 100.0f;
3371 }
3372 /* Invert new value to increase the factor moving the mouse to the right. */
3373 new_value = 1 - new_value;
3374 break;
3375 case PROP_ANGLE:
3376 new_value = atan2f(delta[1], delta[0]) + float(M_PI) + angle_precision;
3377 new_value = fmod(new_value, 2.0f * float(M_PI));
3378 if (new_value < 0.0f) {
3379 new_value += 2.0f * float(M_PI);
3380 }
3381 if (snap) {
3382 new_value = DEG2RADF((int(RAD2DEGF(new_value)) + 5) / 10 * 10);
3383 }
3384 break;
3385 default:
3386 new_value = dist; /* NOTE(@ideasman42): Dummy value, should this ever happen? */
3387 break;
3388 }
3389
3390 /* Clamp and update. */
3391 CLAMP(new_value, rc->min_value, rc->max_value);
3392 radial_control_set_value(rc, new_value);
3393 rc->current_value = new_value;
3394 handled = true;
3395 break;
3396 }
3397 break;
3398
3399 case EVT_LEFTSHIFTKEY:
3400 case EVT_RIGHTSHIFTKEY: {
3401 if (event->val == KM_PRESS) {
3402 rc->slow_mouse[0] = event->xy[0];
3403 rc->slow_mouse[1] = event->xy[1];
3404 rc->slow_mode = true;
3405 if (rc->subtype == PROP_ANGLE) {
3406 const float initial_position[2] = {float(rc->initial_mouse[0]),
3407 float(rc->initial_mouse[1])};
3408 const float current_position[2] = {float(rc->slow_mouse[0]), float(rc->slow_mouse[1])};
3409 rc->dial = BLI_dial_init(initial_position, 0.0f);
3410 /* Immediately set the position to get a an initial direction. */
3411 BLI_dial_angle(rc->dial, current_position);
3412 }
3413 handled = true;
3414 }
3415 if (event->val == KM_RELEASE) {
3416 rc->slow_mode = false;
3417 handled = true;
3418 if (rc->dial) {
3419 BLI_dial_free(rc->dial);
3420 rc->dial = nullptr;
3421 }
3422 }
3423 break;
3424 }
3425 default: {
3426 break;
3427 }
3428 }
3429
3430 /* Modal numinput inactive, try to handle numeric inputs last... */
3431 if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) {
3432 applyNumInput(&rc->num_input, &numValue);
3433
3434 if (rc->subtype == PROP_ANGLE) {
3435 numValue = fmod(numValue, 2.0f * float(M_PI));
3436 if (numValue < 0.0f) {
3437 numValue += 2.0f * float(M_PI);
3438 }
3439 }
3440
3441 CLAMP(numValue, rc->min_value, rc->max_value);
3442 new_value = numValue;
3443
3444 radial_control_set_value(rc, new_value);
3445
3446 rc->current_value = new_value;
3449 }
3450
3451 if (!handled && (event->val == KM_RELEASE) && (rc->init_event == event->type) &&
3452 RNA_boolean_get(op->ptr, "release_confirm"))
3453 {
3454 /* Keep the RNA update separate from setting the value, for some properties this could lead to
3455 * a continues flickering due to invalidating the overlay texture. */
3456 RNA_property_update(C, &rc->ptr, rc->prop);
3458 }
3459
3462
3463 if (ret & OPERATOR_FINISHED) {
3465 if (wm->op_undo_depth == 0) {
3466 ID *id = rc->ptr.owner_id;
3468 ED_undo_push(C, op->type->name);
3469 }
3470 }
3471 }
3472
3473 if (ret != OPERATOR_RUNNING_MODAL) {
3475 }
3476
3477 return ret;
3478}
3479
3481{
3482 ot->name = "Radial Control";
3483 ot->idname = "WM_OT_radial_control";
3484 ot->description = "Set some size property (e.g. brush size) with mouse wheel";
3485
3486 ot->invoke = radial_control_invoke;
3487 ot->modal = radial_control_modal;
3488 ot->cancel = radial_control_cancel;
3489
3491
3492 /* All paths relative to the context. */
3493 PropertyRNA *prop;
3494 prop = RNA_def_string(ot->srna,
3495 "data_path_primary",
3496 nullptr,
3497 0,
3498 "Primary Data Path",
3499 "Primary path of property to be set by the radial control");
3501
3502 prop = RNA_def_string(ot->srna,
3503 "data_path_secondary",
3504 nullptr,
3505 0,
3506 "Secondary Data Path",
3507 "Secondary path of property to be set by the radial control");
3509
3510 prop = RNA_def_string(ot->srna,
3511 "use_secondary",
3512 nullptr,
3513 0,
3514 "Use Secondary",
3515 "Path of property to select between the primary and secondary data paths");
3517
3518 prop = RNA_def_string(ot->srna,
3519 "rotation_path",
3520 nullptr,
3521 0,
3522 "Rotation Path",
3523 "Path of property used to rotate the texture display");
3525
3526 prop = RNA_def_string(ot->srna,
3527 "color_path",
3528 nullptr,
3529 0,
3530 "Color Path",
3531 "Path of property used to set the color of the control");
3533
3534 prop = RNA_def_string(ot->srna,
3535 "fill_color_path",
3536 nullptr,
3537 0,
3538 "Fill Color Path",
3539 "Path of property used to set the fill color of the control");
3541
3542 prop = RNA_def_string(
3543 ot->srna, "fill_color_override_path", nullptr, 0, "Fill Color Override Path", "");
3545 prop = RNA_def_string(
3546 ot->srna, "fill_color_override_test_path", nullptr, 0, "Fill Color Override Test", "");
3548
3549 prop = RNA_def_string(ot->srna,
3550 "zoom_path",
3551 nullptr,
3552 0,
3553 "Zoom Path",
3554 "Path of property used to set the zoom level for the control");
3556
3557 prop = RNA_def_string(ot->srna,
3558 "image_id",
3559 nullptr,
3560 0,
3561 "Image ID",
3562 "Path of ID that is used to generate an image for the control");
3564
3565 prop = RNA_def_boolean(
3566 ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
3568
3569 prop = RNA_def_boolean(
3570 ot->srna, "release_confirm", false, "Confirm On Release", "Finish operation on key release");
3572}
3573
3575
3576/* -------------------------------------------------------------------- */
3581
3582/* Uses no type defines, fully local testing function anyway. */
3583
3585{
3586 wmWindow *win = CTX_wm_window(C);
3587 bScreen *screen = CTX_wm_screen(C);
3588
3589 CTX_wm_region_popup_set(C, nullptr);
3590
3591 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3592 ED_area_tag_redraw(area);
3593 }
3595
3596 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3597}
3598
3599enum {
3607};
3608
3610 {eRTDrawRegion, "DRAW", 0, "Draw Region", "Draw region"},
3611 {eRTDrawRegionSwap, "DRAW_SWAP", 0, "Draw Region & Swap", "Draw region and swap"},
3612 {eRTDrawWindow, "DRAW_WIN", 0, "Draw Window", "Draw window"},
3613 {eRTDrawWindowSwap, "DRAW_WIN_SWAP", 0, "Draw Window & Swap", "Draw window and swap"},
3614 {eRTAnimationStep, "ANIM_STEP", 0, "Animation Step", "Animation steps"},
3615 {eRTAnimationPlay, "ANIM_PLAY", 0, "Animation Play", "Animation playback"},
3616 {eRTUndo, "UNDO", 0, "Undo/Redo", "Undo and redo"},
3617 {0, nullptr, 0, nullptr, nullptr},
3618};
3619
3621 Scene *scene,
3622 Depsgraph *depsgraph,
3623 wmWindow *win,
3624 ScrArea *area,
3625 ARegion *region,
3626 const int type,
3627 const int cfra,
3628 const int steps_done,
3629 const int steps_total)
3630{
3631 if (type == eRTDrawRegion) {
3632 if (region) {
3633 wm_draw_region_test(C, area, region);
3634 }
3635 }
3636 else if (type == eRTDrawRegionSwap) {
3637 CTX_wm_region_popup_set(C, nullptr);
3638
3639 ED_region_tag_redraw(region);
3641
3642 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3643 }
3644 else if (type == eRTDrawWindow) {
3645 bScreen *screen = WM_window_get_active_screen(win);
3646
3647 CTX_wm_region_popup_set(C, nullptr);
3648
3649 LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
3650 CTX_wm_area_set(C, area_iter);
3651 LISTBASE_FOREACH (ARegion *, region_iter, &area_iter->regionbase) {
3652 if (!region_iter->runtime->visible) {
3653 continue;
3654 }
3655 CTX_wm_region_set(C, region_iter);
3656 wm_draw_region_test(C, area_iter, region_iter);
3657 }
3658 }
3659
3660 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3661
3662 CTX_wm_area_set(C, area);
3663 CTX_wm_region_set(C, region);
3664 }
3665 else if (type == eRTDrawWindowSwap) {
3667 }
3668 else if (type == eRTAnimationStep) {
3669 scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1;
3671 }
3672 else if (type == eRTAnimationPlay) {
3673 /* Play anim, return on same frame as started with. */
3674 int tot = (scene->r.efra - scene->r.sfra) + 1;
3675 const int frames_total = tot * steps_total;
3676 int frames_done = tot * steps_done;
3677
3678 while (tot--) {
3679 WM_progress_set(win, float(frames_done) / float(frames_total));
3680 frames_done++;
3681
3682 /* TODO: ability to escape! */
3683 scene->r.cfra++;
3684 if (scene->r.cfra > scene->r.efra) {
3685 scene->r.cfra = scene->r.sfra;
3686 }
3687
3690 }
3691 }
3692 else { /* #eRTUndo. */
3693 /* Undo and redo, including depsgraph update since that can be a
3694 * significant part of the cost. */
3695 ED_undo_pop(C);
3697 ED_undo_redo(C);
3699 }
3700}
3701
3703{
3704 /* Check background mode as many of these actions use redrawing.
3705 * NOTE(@ideasman42): if it's useful to support undo or animation step this could
3706 * be allowed at the moment this seems like a corner case that isn't needed. */
3707 return !G.background && WM_operator_winactive(C);
3708}
3709
3711{
3712 Scene *scene = CTX_data_scene(C);
3713 wmWindow *win = CTX_wm_window(C);
3714 ScrArea *area = CTX_wm_area(C);
3715 ARegion *region = CTX_wm_region(C);
3717 const int type = RNA_enum_get(op->ptr, "type");
3718 const int iter = RNA_int_get(op->ptr, "iterations");
3719 const double time_limit = double(RNA_float_get(op->ptr, "time_limit"));
3720 const int cfra = scene->r.cfra;
3721 const char *infostr = "";
3722
3723 /* NOTE: Depsgraph is used to update scene for a new state, so no need to ensure evaluation
3724 * here.
3725 */
3727
3729
3730 WM_cursor_wait(true);
3731
3732 double time_start = BLI_time_now_seconds();
3733
3734 wm_window_make_drawable(wm, win);
3735
3736 int iter_steps = 0;
3737 for (int a = 0; a < iter; a++) {
3738
3739 if (type == eRTAnimationPlay) {
3740 WorkspaceStatus status(C);
3741 status.item(fmt::format("{} / {} {}", a + 1, iter, infostr), ICON_INFO);
3742 }
3743
3744 redraw_timer_step(C, scene, depsgraph, win, area, region, type, cfra, a, iter);
3745 iter_steps += 1;
3746
3747 if (time_limit != 0.0) {
3748 if ((BLI_time_now_seconds() - time_start) > time_limit) {
3749 break;
3750 }
3751 a = 0;
3752 }
3753 }
3754
3755 double time_delta = (BLI_time_now_seconds() - time_start) * 1000;
3756
3757 if (type == eRTAnimationPlay) {
3758 ED_workspace_status_text(C, nullptr);
3759 WM_progress_clear(win);
3760 }
3761
3762 WM_cursor_wait(false);
3763
3764 BKE_reportf(op->reports,
3766 "%d \u00D7 %s: %.4f ms, average: %.8f ms",
3767 iter_steps,
3768 infostr,
3769 time_delta,
3770 time_delta / iter_steps);
3771
3772 return OPERATOR_FINISHED;
3773}
3774
3776{
3777 ot->name = "Redraw Timer";
3778 ot->idname = "WM_OT_redraw_timer";
3779 ot->description = "Simple redraw timer to test the speed of updating the interface";
3780
3781 ot->invoke = WM_menu_invoke;
3782 ot->exec = redraw_timer_exec;
3783 ot->poll = redraw_timer_poll;
3784
3785 ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, eRTDrawRegion, "Type", "");
3787 ot->srna, "iterations", 10, 1, INT_MAX, "Iterations", "Number of times to redraw", 1, 1000);
3788 RNA_def_float(ot->srna,
3789 "time_limit",
3790 0.0,
3791 0.0,
3792 FLT_MAX,
3793 "Time Limit",
3794 "Seconds to run the test for (override iterations)",
3795 0.0,
3796 60.0);
3797}
3798
3800
3801/* -------------------------------------------------------------------- */
3806
3812
3814{
3815 ot->name = "Memory Statistics";
3816 ot->idname = "WM_OT_memory_statistics";
3817 ot->description = "Print memory statistics to the console";
3818
3819 ot->exec = memory_statistics_exec;
3820}
3821
3823
3824/* -------------------------------------------------------------------- */
3829
3834
3835static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
3836{
3838
3839 /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
3840 * Same goes for ID with no user. */
3841 if (ID_IS_EDITABLE(id) && (id->us != 0)) {
3842 UI_icon_render_id(C, scene, id, ICON_SIZE_ICON, false);
3843 UI_icon_render_id(C, scene, id, ICON_SIZE_PREVIEW, false);
3844 }
3845}
3846
3848{
3849 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
3850
3852 return IDWALK_RET_NOP;
3853 }
3854
3855 PreviewsIDEnsureData *data = static_cast<PreviewsIDEnsureData *>(cb_data->user_data);
3856 ID *id = *cb_data->id_pointer;
3857
3858 if (id && (id->tag & ID_TAG_DOIT)) {
3860 previews_id_ensure(data->C, data->scene, id);
3861 id->tag &= ~ID_TAG_DOIT;
3862 }
3863
3864 return IDWALK_RET_NOP;
3865}
3866
3868{
3869 Main *bmain = CTX_data_main(C);
3870 ListBase *lb[] = {&bmain->materials,
3871 &bmain->textures,
3872 &bmain->images,
3873 &bmain->worlds,
3874 &bmain->lights,
3875 nullptr};
3876 PreviewsIDEnsureData preview_id_data;
3877
3878 /* We use ID_TAG_DOIT to check whether we have already handled a given ID or not. */
3879 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3880 for (int i = 0; lb[i]; i++) {
3882 }
3883
3884 preview_id_data.C = C;
3885 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3886 preview_id_data.scene = scene;
3887 ID *id = (ID *)scene;
3888
3890 nullptr, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
3891 }
3892
3893 /* Check a last time for ID not used (fake users only, in theory), and
3894 * do our best for those, using current scene... */
3895 for (int i = 0; lb[i]; i++) {
3896 LISTBASE_FOREACH (ID *, id, lb[i]) {
3897 if (id->tag & ID_TAG_DOIT) {
3898 previews_id_ensure(C, nullptr, id);
3899 id->tag &= ~ID_TAG_DOIT;
3900 }
3901 }
3902 }
3903
3904 return OPERATOR_FINISHED;
3905}
3906
3908{
3909 ot->name = "Refresh Data-Block Previews";
3910 ot->idname = "WM_OT_previews_ensure";
3911 ot->description =
3912 "Ensure data-block previews are available and up-to-date "
3913 "(to be saved in .blend file, only for some types like materials, textures, etc.)";
3914
3915 ot->exec = previews_ensure_exec;
3916}
3917
3919
3920/* -------------------------------------------------------------------- */
3923
3937
3938/* Only types supporting previews currently. */
3940 {PREVIEW_FILTER_ALL, "ALL", 0, "All Types", ""},
3942 "GEOMETRY",
3943 0,
3944 "All Geometry Types",
3945 "Clear previews for scenes, collections and objects"},
3947 "SHADING",
3948 0,
3949 "All Shading Types",
3950 "Clear previews for materials, lights, worlds, textures and images"},
3951 {PREVIEW_FILTER_SCENE, "SCENE", 0, "Scenes", ""},
3952 {PREVIEW_FILTER_COLLECTION, "COLLECTION", 0, "Collections", ""},
3953 {PREVIEW_FILTER_OBJECT, "OBJECT", 0, "Objects", ""},
3954 {PREVIEW_FILTER_MATERIAL, "MATERIAL", 0, "Materials", ""},
3955 {PREVIEW_FILTER_LIGHT, "LIGHT", 0, "Lights", ""},
3956 {PREVIEW_FILTER_WORLD, "WORLD", 0, "Worlds", ""},
3957 {PREVIEW_FILTER_TEXTURE, "TEXTURE", 0, "Textures", ""},
3958 {PREVIEW_FILTER_IMAGE, "IMAGE", 0, "Images", ""},
3959#if 0 /* XXX: TODO. */
3960 {PREVIEW_FILTER_BRUSH, "BRUSH", 0, "Brushes", ""},
3961#endif
3962 {0, nullptr, 0, nullptr, nullptr},
3963};
3964
3966{
3967 switch (filter) {
3968 case PREVIEW_FILTER_ALL:
3976 return FILTER_ID_SCE;
3978 return FILTER_ID_GR;
3980 return FILTER_ID_OB;
3982 return FILTER_ID_MA;
3984 return FILTER_ID_LA;
3986 return FILTER_ID_WO;
3988 return FILTER_ID_TE;
3990 return FILTER_ID_IM;
3991 }
3992
3993 return 0;
3994}
3995
3997{
3998 Main *bmain = CTX_data_main(C);
3999 ListBase *lb[] = {
4000 &bmain->objects,
4001 &bmain->collections,
4002 &bmain->materials,
4003 &bmain->worlds,
4004 &bmain->lights,
4005 &bmain->textures,
4006 &bmain->images,
4007 nullptr,
4008 };
4009
4010 const int id_filters = preview_filter_to_idfilter(
4011 PreviewFilterID(RNA_enum_get(op->ptr, "id_type")));
4012
4013 for (int i = 0; lb[i]; i++) {
4014 ID *id = static_cast<ID *>(lb[i]->first);
4015 if (!id) {
4016 continue;
4017 }
4018
4019#if 0
4020 printf("%s: %d, %d, %d -> %d\n",
4021 id->name,
4022 GS(id->name),
4024 id_filters,
4025 BKE_idtype_idcode_to_idfilter(GS(id->name)) & id_filters);
4026#endif
4027
4028 if (!(BKE_idtype_idcode_to_idfilter(GS(id->name)) & id_filters)) {
4029 continue;
4030 }
4031
4032 for (; id; id = static_cast<ID *>(id->next)) {
4034
4035 BKE_previewimg_clear(prv_img);
4036 }
4037 }
4038
4039 return OPERATOR_FINISHED;
4040}
4041
4043{
4044 ot->name = "Clear Data-Block Previews";
4045 ot->idname = "WM_OT_previews_clear";
4046 ot->description =
4047 "Clear data-block previews (only for some types like objects, materials, textures, etc.)";
4048
4049 ot->exec = previews_clear_exec;
4050 ot->invoke = WM_menu_invoke;
4051
4052 ot->prop = RNA_def_enum_flag(ot->srna,
4053 "id_type",
4056 "Data-Block Type",
4057 "Which data-block previews to clear");
4058}
4059
4061
4062/* -------------------------------------------------------------------- */
4065
4067{
4068 PointerRNA ptr_props;
4070
4071 if (std::optional<std::string> manual_id = UI_but_online_manual_id_from_active(C)) {
4072 WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
4073 RNA_string_set(&ptr_props, "doc_id", manual_id.value().c_str());
4074
4076 WM_operatortype_find("WM_OT_doc_view_manual", false),
4078 &ptr_props,
4079 nullptr);
4080
4081 WM_operator_properties_free(&ptr_props);
4082 }
4083
4084 return retval;
4085}
4086
4088{
4089 /* Identifiers. */
4090 ot->name = "View Online Manual";
4091 ot->idname = "WM_OT_doc_view_manual_ui_context";
4092 ot->description = "View a context based online manual in a web browser";
4093
4094 /* Callbacks. */
4097}
4098
4100
4101/* -------------------------------------------------------------------- */
4106
4108{
4109 PropertyRNA *prop;
4110
4111 ot->name = "Set Stereo 3D";
4112 ot->idname = "WM_OT_set_stereo_3d";
4113 ot->description = "Toggle 3D stereo support for current window (or change the display mode)";
4114
4115 ot->exec = wm_stereo3d_set_exec;
4116 ot->invoke = wm_stereo3d_set_invoke;
4117 ot->poll = WM_operator_winactive;
4119 ot->check = wm_stereo3d_set_check;
4120 ot->cancel = wm_stereo3d_set_cancel;
4121
4122 prop = RNA_def_enum(ot->srna,
4123 "display_mode",
4126 "Display Mode",
4127 "");
4129 prop = RNA_def_enum(ot->srna,
4130 "anaglyph_type",
4133 "Anaglyph Type",
4134 "");
4136 prop = RNA_def_enum(ot->srna,
4137 "interlace_type",
4140 "Interlace Type",
4141 "");
4143 prop = RNA_def_boolean(ot->srna,
4144 "use_interlace_swap",
4145 false,
4146 "Swap Left/Right",
4147 "Swap left and right stereo channels");
4149 prop = RNA_def_boolean(ot->srna,
4150 "use_sidebyside_crosseyed",
4151 false,
4152 "Cross-Eyed",
4153 "Right eye should see left image and vice versa");
4155}
4156
4158
4159/* -------------------------------------------------------------------- */
4162
4164{
4204#if defined(WIN32)
4205 WM_operatortype_append(WM_OT_console_toggle);
4206#endif
4210
4211#ifdef WITH_XR_OPENXR
4213#endif
4214
4215 /* Gizmos. */
4218}
4219
4220/* Circle-select-like modal operators. */
4222{
4223 static const EnumPropertyItem modal_items[] = {
4224 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4225 {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
4226 {GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""},
4227 {GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""},
4228 {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""},
4229
4230 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4231 {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""},
4232 {GESTURE_MODAL_NOP, "NOP", 0, "No Operation", ""},
4233
4234 {0, nullptr, 0, nullptr, nullptr},
4235 };
4236
4237 /* WARNING: Name is incorrect, use for non-3d views. */
4238 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Gesture Circle");
4239
4240 /* This function is called for each space-type, only needs to add map once. */
4241 if (keymap && keymap->modal_items) {
4242 return;
4243 }
4244
4245 keymap = WM_modalkeymap_ensure(keyconf, "View3D Gesture Circle", modal_items);
4246
4247 /* Assign map to operators. */
4248 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle");
4249 WM_modalkeymap_assign(keymap, "UV_OT_select_circle");
4250 WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle");
4251 WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
4252 WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
4253 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
4254 WM_modalkeymap_assign(keymap, "ACTION_OT_select_circle");
4255}
4256
4257/* Straight line modal operators. */
4259{
4260 static const EnumPropertyItem modal_items[] = {
4261 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4262 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4263 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4264 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4265 {GESTURE_MODAL_SNAP, "SNAP", 0, "Snap", ""},
4266 {GESTURE_MODAL_FLIP, "FLIP", 0, "Flip", ""},
4267 {0, nullptr, 0, nullptr, nullptr},
4268 };
4269
4270 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Straight Line");
4271
4272 /* This function is called for each space-type, only needs to add map once. */
4273 if (keymap && keymap->modal_items) {
4274 return;
4275 }
4276
4277 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Straight Line", modal_items);
4278
4279 /* Assign map to operators. */
4280 WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line");
4281 WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
4282 WM_modalkeymap_assign(keymap, "MESH_OT_bisect");
4283 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_line_gesture");
4284 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_line_gesture");
4285 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_line_gesture");
4286 WM_modalkeymap_assign(keymap, "SCULPT_OT_project_line_gesture");
4287 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_line_gesture");
4288}
4289
4290/* Box_select-like modal operators. */
4292{
4293 static const EnumPropertyItem modal_items[] = {
4294 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4295 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4296 {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""},
4297 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4298 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4299 {0, nullptr, 0, nullptr, nullptr},
4300 };
4301
4302 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Box");
4303
4304 /* This function is called for each space-type, only needs to add map once. */
4305 if (keymap && keymap->modal_items) {
4306 return;
4307 }
4308
4309 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Box", modal_items);
4310
4311 /* Assign map to operators. */
4312 WM_modalkeymap_assign(keymap, "ACTION_OT_select_box");
4313 WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_box");
4314 WM_modalkeymap_assign(keymap, "ANIM_OT_previewrange_set");
4315 WM_modalkeymap_assign(keymap, "INFO_OT_select_box");
4316 WM_modalkeymap_assign(keymap, "FILE_OT_select_box");
4317 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_box");
4318 WM_modalkeymap_assign(keymap, "MARKER_OT_select_box");
4319 WM_modalkeymap_assign(keymap, "NLA_OT_select_box");
4320 WM_modalkeymap_assign(keymap, "NODE_OT_select_box");
4321 WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border");
4322 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show");
4323 WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_box");
4324#if 0 /* Template. */
4325 WM_modalkeymap_assign(keymap, "SCREEN_OT_box_select");
4326#endif
4327 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_box");
4328 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border");
4329 WM_modalkeymap_assign(keymap, "UV_OT_select_box");
4330 WM_modalkeymap_assign(keymap, "CLIP_OT_select_box");
4331 WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box");
4332 WM_modalkeymap_assign(keymap, "MASK_OT_select_box");
4333 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_box_gesture");
4334 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_box_gesture");
4335 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_box_gesture");
4336 WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
4337 WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border");
4338 WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border");
4339 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_box");
4340 /* XXX TODO: zoom border should perhaps map right-mouse to zoom out instead of in+cancel. */
4341 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border");
4342 WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border");
4343 WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
4344 WM_modalkeymap_assign(keymap, "GREASE_PENCIL_OT_erase_box");
4345}
4346
4347/* Lasso modal operators. */
4349{
4350 static const EnumPropertyItem modal_items[] = {
4351 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4352 {0, nullptr, 0, nullptr, nullptr},
4353 };
4354
4355 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Lasso");
4356
4357 /* This function is called for each space-type, only needs to add map once. */
4358 if (keymap && keymap->modal_items) {
4359 return;
4360 }
4361
4362 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Lasso", modal_items);
4363
4364 /* Assign map to operators. */
4365 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_lasso");
4366 WM_modalkeymap_assign(keymap, "MASK_OT_select_lasso");
4367 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_lasso_gesture");
4368 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_lasso_gesture");
4369 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_lasso_gesture");
4370 WM_modalkeymap_assign(keymap, "ACTION_OT_select_lasso");
4371 WM_modalkeymap_assign(keymap, "CLIP_OT_select_lasso");
4372 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_lasso");
4373 WM_modalkeymap_assign(keymap, "NODE_OT_select_lasso");
4374 WM_modalkeymap_assign(keymap, "UV_OT_select_lasso");
4375 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_lasso_gesture");
4376 WM_modalkeymap_assign(keymap, "GREASE_PENCIL_OT_erase_lasso");
4377}
4378
4379/* Polyline modal operators */
4381{
4382 static const EnumPropertyItem modal_items[] = {
4383 {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
4384 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4385 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4386 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4387 {0, nullptr, 0, nullptr, nullptr},
4388 };
4389
4390 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Polyline");
4391
4392 /* This function is called for each space-type, only needs to add map once. */
4393 if (keymap && keymap->modal_items) {
4394 return;
4395 }
4396
4397 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Polyline", modal_items);
4398
4399 /* assign map to operators */
4400 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_polyline_gesture");
4401 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_polyline_gesture");
4402 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_polyline_gesture");
4403 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_polyline_gesture");
4404}
4405
4406/* Zoom to border modal operators. */
4408{
4409 static const EnumPropertyItem modal_items[] = {
4410 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4411 {GESTURE_MODAL_IN, "IN", 0, "In", ""},
4412 {GESTURE_MODAL_OUT, "OUT", 0, "Out", ""},
4413 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4414 {0, nullptr, 0, nullptr, nullptr},
4415 };
4416
4417 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Zoom Border");
4418
4419 /* This function is called for each space-type, only needs to add map once. */
4420 if (keymap && keymap->modal_items) {
4421 return;
4422 }
4423
4424 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Zoom Border", modal_items);
4425
4426 /* Assign map to operators. */
4427 WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
4428 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border");
4429 WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
4430}
4431
4433{
4434 WM_keymap_ensure(keyconf, "Window", SPACE_EMPTY, RGN_TYPE_WINDOW);
4435
4436 wm_gizmos_keymap(keyconf);
4438 gesture_box_modal_keymap(keyconf);
4443
4445}
4446
4448
4449/* -------------------------------------------------------------------- */
4456
4457static bool rna_id_enum_filter_single(const ID *id, void *user_data)
4458{
4459 return (id != user_data);
4460}
4461
4462/* Generic itemf's for operators that take library args. */
4463static const EnumPropertyItem *rna_id_itemf(bool *r_free,
4464 ID *id,
4465 bool local,
4466 bool (*filter_ids)(const ID *id, void *user_data),
4467 void *user_data)
4468{
4469 EnumPropertyItem item_tmp = {0}, *item = nullptr;
4470 int totitem = 0;
4471 int i = 0;
4472
4473 if (id != nullptr) {
4474 const short id_type = GS(id->name);
4475 for (; id; id = static_cast<ID *>(id->next)) {
4476 if ((filter_ids != nullptr) && filter_ids(id, user_data) == false) {
4477 i++;
4478 continue;
4479 }
4480 if (local == false || !ID_IS_LINKED(id)) {
4481 item_tmp.identifier = item_tmp.name = id->name + 2;
4482 item_tmp.value = i++;
4483
4484 /* Show collection color tag icons in menus. */
4485 if (id_type == ID_GR) {
4487 }
4488
4489 RNA_enum_item_add(&item, &totitem, &item_tmp);
4490 }
4491 }
4492 }
4493
4494 RNA_enum_item_end(&item, &totitem);
4495 *r_free = true;
4496
4497 return item;
4498}
4499
4500/* Can add more ID types as needed. */
4501
4503 PointerRNA * /*ptr*/,
4504 PropertyRNA * /*prop*/,
4505 bool *r_free)
4506{
4507
4508 return rna_id_itemf(
4509 r_free, C ? (ID *)CTX_data_main(C)->actions.first : nullptr, false, nullptr, nullptr);
4510}
4511#if 0 /* UNUSED. */
4512const EnumPropertyItem *RNA_action_local_itemf(bContext *C,
4513 PointerRNA * /*ptr*/,
4514 PropertyRNA * /*prop*/,
4515 bool *r_free)
4516{
4517 return rna_id_itemf(r_free, C ? (ID *)CTX_data_main(C)->action.first : nullptr, true);
4518}
4519#endif
4520
4522 PointerRNA * /*ptr*/,
4523 PropertyRNA * /*prop*/,
4524 bool *r_free)
4525{
4526 return rna_id_itemf(
4527 r_free, C ? (ID *)CTX_data_main(C)->collections.first : nullptr, false, nullptr, nullptr);
4528}
4530 PointerRNA * /*ptr*/,
4531 PropertyRNA * /*prop*/,
4532 bool *r_free)
4533{
4534 return rna_id_itemf(
4535 r_free, C ? (ID *)CTX_data_main(C)->collections.first : nullptr, true, nullptr, nullptr);
4536}
4537
4539 PointerRNA * /*ptr*/,
4540 PropertyRNA * /*prop*/,
4541 bool *r_free)
4542{
4543 return rna_id_itemf(
4544 r_free, C ? (ID *)CTX_data_main(C)->images.first : nullptr, false, nullptr, nullptr);
4545}
4547 PointerRNA * /*ptr*/,
4548 PropertyRNA * /*prop*/,
4549 bool *r_free)
4550{
4551 return rna_id_itemf(
4552 r_free, C ? (ID *)CTX_data_main(C)->images.first : nullptr, true, nullptr, nullptr);
4553}
4554
4556 PointerRNA * /*ptr*/,
4557 PropertyRNA * /*prop*/,
4558 bool *r_free)
4559{
4560 return rna_id_itemf(
4561 r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, false, nullptr, nullptr);
4562}
4564 PointerRNA * /*ptr*/,
4565 PropertyRNA * /*prop*/,
4566 bool *r_free)
4567{
4568 return rna_id_itemf(
4569 r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, true, nullptr, nullptr);
4570}
4572 PointerRNA * /*ptr*/,
4573 PropertyRNA * /*prop*/,
4574 bool *r_free)
4575{
4576 Scene *scene_active = C ? CTX_data_scene(C) : nullptr;
4577 return rna_id_itemf(r_free,
4578 C ? (ID *)CTX_data_main(C)->scenes.first : nullptr,
4579 false,
4581 scene_active);
4582}
4584 PointerRNA * /*ptr*/,
4585 PropertyRNA * /*prop*/,
4586 bool *r_free)
4587{
4588 return rna_id_itemf(
4589 r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : nullptr, false, nullptr, nullptr);
4590}
4592 PointerRNA * /*ptr*/,
4593 PropertyRNA * /*prop*/,
4594 bool *r_free)
4595{
4596 return rna_id_itemf(
4597 r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : nullptr, true, nullptr, nullptr);
4598}
4599
4601 PointerRNA * /*ptr*/,
4602 PropertyRNA * /*prop*/,
4603 bool *r_free)
4604{
4605 return rna_id_itemf(
4606 r_free, C ? (ID *)CTX_data_main(C)->masks.first : nullptr, false, nullptr, nullptr);
4607}
4609 PointerRNA * /*ptr*/,
4610 PropertyRNA * /*prop*/,
4611 bool *r_free)
4612{
4613 return rna_id_itemf(
4614 r_free, C ? (ID *)CTX_data_main(C)->masks.first : nullptr, true, nullptr, nullptr);
4615}
4616
bool id_type_can_have_animdata(short id_type)
Definition anim_data.cc:63
ImBuf * BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
Definition brush.cc:1606
float BKE_brush_curve_strength_clamped(const Brush *br, float p, float len)
Definition brush.cc:1566
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, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:766
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1243
void IDP_ClearProperty(IDProperty *prop)
Definition idprop.cc:1249
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:725
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:873
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, bool do_overwrite) ATTR_NONNULL()
Definition idprop.cc:720
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:672
uint64_t BKE_idtype_idcode_to_idfilter(short idcode)
Definition idtype.cc:366
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:165
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:353
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1191
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1214
LibraryForeachIDCallbackFlag
@ 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, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
@ IDWALK_RET_NOP
@ IDWALK_RECURSE
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:877
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:126
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2697
#define BKE_ST_MAXNAME
Definition BKE_screen.hh:72
void BLF_size(int fontid, float size)
Definition blf.cc:440
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:792
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:502
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:468
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:582
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:805
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:385
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
void BLI_dial_free(Dial *dial)
Dial * BLI_dial_init(const float start_position[2], float threshold)
float BLI_dial_angle(Dial *dial, const float current_position[2])
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
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 DEG2RADF(_deg)
#define RAD2DEGF(_rad)
#define M_PI
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.cc:975
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
void BLI_str_tolower_ascii(char *str, size_t len) ATTR_NONNULL(1)
Definition string.cc:966
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.cc: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)
#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.
@ ID_TAG_DOIT
Definition DNA_ID.h:944
@ 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
@ S3D_ANAGLYPH_REDCYAN
@ USER_UNIT_NONE
@ 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
#define UI_SCALE_FAC
@ USER_SAVE_PROMPT
@ USER_GLOBALUNDO
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define OPERATOR_RETVAL_CHECK(ret)
#define OP_MAX_TYPENAME
FileSelectParams * ED_fileselect_get_active_params(const SpaceFile *sfile)
Definition filesel.cc:382
void initNumInput(NumInput *n)
Definition numinput.cc:69
#define NUM_STR_REP_LEN
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:311
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:189
void outputNumInput(NumInput *n, char *str, const UnitSettings &unit_settings)
Definition numinput.cc:87
@ NUM_NO_NEGATIVE
bool hasNumInput(const NumInput *n)
Definition numinput.cc:170
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:714
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:872
void ED_screen_refresh(bContext *C, wmWindowManager *wm, wmWindow *win)
bool ED_operator_regionactive(bContext *C)
Definition screen_ops.cc:98
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1040
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:99
bool ED_undo_is_legacy_compatible_for_property(bContext *C, ID *id, PointerRNA &ptr)
Definition ed_undo.cc:404
void ED_undo_push_op(bContext *C, wmOperator *op)
Definition ed_undo.cc:358
bool ED_undo_is_valid(const bContext *C, const char *undoname)
Definition ed_undo.cc:380
void ED_undo_redo(bContext *C)
Definition ed_undo.cc:353
bool ED_undo_operator_repeat(bContext *C, wmOperator *op)
Definition ed_undo.cc:630
void ED_undo_pop(bContext *C)
Definition ed_undo.cc:349
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:166
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 *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
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:208
@ PROP_STRING_SEARCH_SUGGESTION
Definition RNA_types.hh:701
@ PROP_STRING_SEARCH_SORT
Definition RNA_types.hh:694
PropertyType
Definition RNA_types.hh:149
@ PROP_FLOAT
Definition RNA_types.hh:152
@ PROP_BOOLEAN
Definition RNA_types.hh:150
@ PROP_ENUM
Definition RNA_types.hh:154
@ PROP_INT
Definition RNA_types.hh:151
@ PROP_POINTER
Definition RNA_types.hh:155
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:404
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_SKIP_PRESET
Definition RNA_types.hh:446
PropertySubType
Definition RNA_types.hh:220
@ PROP_DISTANCE
Definition RNA_types.hh:244
@ PROP_PIXEL
Definition RNA_types.hh:236
@ PROP_ANGLE
Definition RNA_types.hh:240
@ PROP_NONE
Definition RNA_types.hh:221
@ PROP_PERCENTAGE
Definition RNA_types.hh:238
@ PROP_FACTOR
Definition RNA_types.hh:239
#define C
Definition RandGen.cpp:29
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
#define UI_UNIT_Y
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)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
wmOperatorStatus UI_pie_menu_invoke(bContext *C, const char *idname, const wmEvent *event)
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
Definition interface.cc:641
@ UI_RETURN_CANCEL
@ UI_RETURN_OK
void UI_popup_dummy_panel_set(ARegion *region, uiBlock *block)
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, std::optional< blender::StringRef > tip)
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, std::optional< blender::StringRef > tip)
void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg, uiFreeArgFunc arg_free)
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)
uiBut * uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxncpy, int x, int y, short width, short height, std::optional< blender::StringRef > tip)
void UI_but_flag2_enable(uiBut *but, int flag)
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
wmOperatorStatus UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, ReportList *reports)
void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
@ UI_BUT2_ACTIVATE_ON_INIT_NO_SELECT
int UI_searchbox_size_x()
bool UI_block_has_active_default_button(const uiBlock *block)
@ UI_BLOCK_THEME_STYLE_REGULAR
@ UI_BLOCK_THEME_STYLE_POPUP
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)
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
#define UI_SEARCHBOX_BOUNDS
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
int UI_searchbox_size_y()
wmOperatorStatus UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) ATTR_NONNULL(1
void UI_block_bounds_set_centered(uiBlock *block, int addval)
Definition interface.cc:667
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
@ UI_BUT_ACTIVE_DEFAULT
@ UI_BUT_ACTIVATE_ON_INIT
@ UI_BLOCK_SEARCH_MENU
@ UI_BLOCK_NUMSELECT
@ UI_BLOCK_LOOP
@ UI_BLOCK_MOVEMOUSE_QUIT
@ UI_BLOCK_KEEP_OPEN
void UI_but_flag_enable(uiBut *but, int flag)
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)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
uiLayout * uiItemsAlertBox(uiBlock *block, const uiStyle *style, const int dialog_width, const eAlertIcon icon, const int icon_size)
void uiLayoutSetScaleY(uiLayout *layout, float scale)
@ UI_LAYOUT_VERTICAL
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)
@ UI_LAYOUT_PANEL
#define UI_ITEM_NONE
int uiLayoutGetWidth(uiLayout *layout)
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
uiBut * uiItemL_ex(uiLayout *layout, blender::StringRef name, int icon, bool highlight, bool redalert)
void uiItemsFullEnumO(uiLayout *layout, blender::StringRefNull opname, blender::StringRefNull propname, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, const int active=-1)
#define UI_MAX_DRAW_STR
@ TH_TEXT_HI
void UI_GetThemeColor4fv(int colorid, float col[4])
@ WM_JOB_TYPE_ANY
Definition WM_api.hh:1725
#define NC_WINDOW
Definition WM_types.hh:372
@ KM_CTRL
Definition WM_types.hh:276
CLG_LogRef * WM_LOG_OPERATORS
@ KM_PRESS
Definition WM_types.hh:308
@ KM_RELEASE
Definition WM_types.hh:309
bool do_update
Definition WM_types.hh:1008
ReportList * reports
Definition WM_types.hh:1025
wmPopupSize
Definition WM_types.hh:979
@ WM_POPUP_SIZE_LARGE
Definition WM_types.hh:981
@ WM_POPUP_SIZE_SMALL
Definition WM_types.hh:980
void(*)(bContext *C, const blender::int2 &xy, const blender::float2 &tilt, void *customdata) wmPaintCursorDraw
Definition WM_types.hh:1190
wmOperatorCallContext
Definition WM_types.hh:236
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:239
@ WM_OP_EXEC_DEFAULT
Definition WM_types.hh:245
wmPopupPosition
Definition WM_types.hh:984
@ WM_POPUP_POSITION_MOUSE
Definition WM_types.hh:985
@ WM_POPUP_POSITION_CENTER
Definition WM_types.hh:986
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define U
BMesh const char void * data
BPy_StructRNA * depsgraph
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:979
constexpr StringRef trim() const
int64_t size() const
void append(const T &value)
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define fabsf(x)
#define rot(x, k)
#define str(s)
uint pos
uint col
#define ceil
#define filter
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#define printf(...)
#define FILTER_ID_OB
#define FILTER_ID_MA
#define MEM_SAFE_FREE(v)
#define ID_IS_LINKED(_id)
#define MAX_ID_NAME
#define FILTER_ID_LA
#define FILTER_ID_GR
#define FILTER_ID_TE
#define ID_IS_EDITABLE(_id)
#define FILTER_ID_IM
#define FILTER_ID_SCE
#define GS(a)
#define FILTER_ID_WO
uint padding(uint offset, uint alignment)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void(* MEM_printmemlist_stats)(void)
Definition mallocn.cc:66
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 fmod(const float2 a, const float b)
#define G(x, y, z)
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRef 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)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
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_discrete(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:1014
std::optional< std::string > RNA_path_full_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
Definition rna_path.cc:1318
std::string RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
Definition rna_path.cc:1352
bool RNA_path_resolve(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:532
const EnumPropertyItem rna_enum_stereo3d_display_items[]
Definition rna_scene.cc:497
const EnumPropertyItem rna_enum_stereo3d_anaglyph_type_items[]
Definition rna_scene.cc:529
const EnumPropertyItem rna_enum_stereo3d_interlace_type_items[]
Definition rna_scene.cc:536
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
struct CurveMapping * curve
const char * identifier
Definition RNA_types.hh:623
const char * name
Definition RNA_types.hh:627
wmOperator * op
ListBase group
Definition DNA_ID.h:138
short flag
Definition DNA_ID.h:153
char name[64]
Definition DNA_ID.h:154
IDPropertyData data
Definition DNA_ID.h:159
Definition DNA_ID.h:404
int tag
Definition DNA_ID.h:424
int us
Definition DNA_ID.h:425
char name[66]
Definition DNA_ID.h:415
ImBufFloatBuffer float_buffer
LibraryForeachIDCallbackFlag cb_flag
void * data
struct LinkData * next
void * first
ListBase scenes
Definition BKE_main.hh:245
ListBase textures
Definition BKE_main.hh:252
ListBase lights
Definition BKE_main.hh:255
ListBase materials
Definition BKE_main.hh:251
ListBase worlds
Definition BKE_main.hh:260
ListBase collections
Definition BKE_main.hh:267
ListBase images
Definition BKE_main.hh:253
ListBase objects
Definition BKE_main.hh:247
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:51
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
PropertySubType subtype
GPUTexture * texture
PropertyRNA * prop
PropertyRNA * zoom_prop
PointerRNA fill_col_override_test_ptr
PointerRNA fill_col_ptr
ListBase orig_paintcursors
PropertyRNA * col_prop
PropertyRNA * rot_prop
PointerRNA rot_ptr
PropertyRNA * fill_col_override_prop
PointerRNA fill_col_override_ptr
PropertyRNA * fill_col_prop
PointerRNA col_ptr
PropertyType type
PointerRNA zoom_ptr
StructRNA * image_id_srna
PointerRNA image_id_ptr
PropertyRNA * fill_col_override_test_prop
struct RenderData r
struct UnitSettings unit
std::string single_menu_idname
struct bDopeSheet * ads
struct bDopeSheet * ads
View3DShading shading
struct EditBone * act_edbone
ListBase * edbo
ListBase areabase
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiFontStyle widget
short columnspace
wmEventType type
Definition WM_types.hh:754
short val
Definition WM_types.hh:756
int xy[2]
Definition WM_types.hh:758
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:1030
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1046
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1086
const char * idname
Definition WM_types.hh:1032
IDProperty * last_properties
Definition WM_types.hh:1127
PropertyRNA * prop
Definition WM_types.hh:1136
StructRNA * srna
Definition WM_types.hh:1124
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1078
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1070
struct ReportList * reports
IDProperty * properties
struct wmOperator * next
struct wmOperatorType * type
struct PointerRNA * ptr
void(* draw)(bContext *C, const blender::int2 &xy, const blender::float2 &tilt, void *customdata)
Definition wm.hh:29
bool(* poll)(bContext *C)
Definition wm.hh:28
void * customdata
Definition wm.hh:26
short region_type
Definition wm.hh:35
short space_type
Definition wm.hh:34
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len
#define N_(msgid)
void wm_operator_register(bContext *C, wmOperator *op)
Definition wm.cc:349
void WM_operator_free(wmOperator *op)
Definition wm.cc:275
void WM_cursor_wait(bool val)
void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:1648
void wm_draw_update(bContext *C)
Definition wm_draw.cc:1581
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)
wmOperatorStatus WM_operator_call_notest(bContext *C, wmOperator *op)
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)
wmOperatorStatus WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorStatus WM_operator_call_ex(bContext *C, wmOperator *op, const bool store)
wmOperatorStatus WM_operator_repeat(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ 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
#define ISMOUSE_MOTION(event_type)
@ 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:2818
void WM_OT_save_as_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3847
void WM_OT_open_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3363
PointerRNA * ptr
Definition wm_files.cc:4227
void WM_OT_recover_last_session(wmOperatorType *ot)
Definition wm_files.cc:3523
void WM_OT_read_userpref(wmOperatorType *ot)
Definition wm_files.cc:2752
void WM_OT_save_homefile(wmOperatorType *ot)
Definition wm_files.cc:2596
void WM_OT_read_factory_userpref(wmOperatorType *ot)
Definition wm_files.cc:2791
void WM_OT_save_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3938
void WM_OT_recover_auto_save(wmOperatorType *ot)
Definition wm_files.cc:3586
void WM_OT_read_factory_settings(wmOperatorType *ot)
Definition wm_files.cc:3057
wmOperatorType * ot
Definition wm_files.cc:4226
void WM_OT_read_homefile(wmOperatorType *ot)
Definition wm_files.cc:2981
void WM_OT_save_userpref(wmOperatorType *ot)
Definition wm_files.cc:2625
void WM_OT_clear_recent_files(wmOperatorType *ot)
Definition wm_files.cc:4030
void WM_OT_revert_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3446
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:224
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:929
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:956
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:893
void WM_keymap_fix_linking()
MenuType * WM_menutype_find(const StringRef idname, bool quiet)
void WM_menutype_idname_visit_for_search(const bContext *, PointerRNA *, PropertyRNA *, const char *, blender::FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
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)
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 radial_control_paint_cursor(bContext *, const blender::int2 &, const blender::float2 &, void *customdata)
static wmOperatorStatus wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_search_menu(wmOperatorType *ot)
static wmOperatorStatus previews_clear_exec(bContext *C, wmOperator *op)
#define ID_CAST_SCENEWORLD(id_pt)
const EnumPropertyItem * RNA_movieclip_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
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
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 wmOperatorStatus wm_exit_blender_exec(bContext *C, wmOperator *)
static wmOperatorStatus wm_debug_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void wm_block_redo_cancel_cb(bContext *C, void *arg_op)
static wmOperatorStatus 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 wmOperatorStatus memory_statistics_exec(bContext *, wmOperator *)
wmOperatorStatus WM_operator_redo_popup(bContext *C, wmOperator *op)
wmOperatorStatus 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 wmOperatorStatus radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
static void radial_control_set_tex(RadialControl *rc)
static wmOperatorStatus wm_call_panel_exec(bContext *C, wmOperator *op)
static void gesture_zoom_border_modal_keymap(wmKeyConfig *keyconf)
wmOperatorStatus WM_operator_confirm_message_ex(bContext *C, wmOperator *op, const char *title, const int icon, const char *message, const wmOperatorCallContext)
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)
wmOperatorStatus WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
wmOperatorStatus WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *)
static wmOperatorStatus wm_debug_menu_exec(bContext *C, wmOperator *op)
void wm_window_keymap(wmKeyConfig *keyconf)
static uiBlock * wm_enum_search_menu(bContext *C, ARegion *region, void *arg)
wmOperatorStatus WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *)
wmOperatorStatus WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *)
void WM_operator_last_properties_ensure(wmOperatorType *ot, PointerRNA *ptr)
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)
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)
static wmOperatorStatus previews_ensure_exec(bContext *C, wmOperator *)
#define CTX_TEST_PTR_ID(C, member, idptr)
static wmOperatorStatus wm_call_pie_menu_exec(bContext *C, wmOperator *op)
#define ID_CAST_OBDATA(id_pt)
@ eRTDrawWindowSwap
@ eRTAnimationStep
@ eRTDrawRegionSwap
@ eRTDrawWindow
@ eRTUndo
@ eRTDrawRegion
@ eRTAnimationPlay
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)
static wmOperatorStatus wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus 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)
void WM_operator_properties_reset(wmOperator *op)
static void WM_OT_debug_menu(wmOperatorType *ot)
#define ID_CAST_OBMATACT(id_pt)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void gesture_lasso_modal_keymap(wmKeyConfig *keyconf)
static void WM_OT_radial_control(wmOperatorType *ot)
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)
static void redraw_timer_step(bContext *C, Scene *scene, Depsgraph *depsgraph, wmWindow *win, ScrArea *area, ARegion *region, const int type, const int cfra, const int steps_done, const int steps_total)
#define OP_BL_SEP_LEN
#define WM_RADIAL_CONTROL_DISPLAY_WIDTH
static wmOperatorStatus redraw_timer_exec(bContext *C, wmOperator *op)
static int radial_control_get_properties(bContext *C, wmOperator *op)
const EnumPropertyItem * RNA_action_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void WM_operator_view3d_unit_defaults(bContext *C, wmOperator *op)
static bool redraw_timer_poll(bContext *C)
static void WM_OT_call_menu(wmOperatorType *ot)
wmOperatorStatus WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
#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)
void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void(*free)(void *))
static wmOperatorStatus radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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)
static void WM_OT_redraw_timer(wmOperatorType *ot)
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)
wmOperatorStatus WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *)
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 wmOperatorStatus doc_view_manual_ui_context_exec(bContext *C, wmOperator *)
wmOperatorStatus WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void WM_OT_previews_clear(wmOperatorType *ot)
wmOperator * WM_operator_last_redo(const bContext *C)
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)
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)
IDProperty * WM_operator_last_properties_ensure_idprops(wmOperatorType *ot)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)
static char g_search_text[256]
static std::string wm_call_menu_get_name(wmOperatorType *ot, PointerRNA *ptr)
wmOperatorStatus WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
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 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)
std::optional< std::string > WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
static void gesture_polyline_modal_keymap(wmKeyConfig *keyconf)
static void WM_OT_window_new(wmOperatorType *ot)
void WM_operator_properties_clear(PointerRNA *ptr)
RCPropFlags
@ RC_PROP_REQUIRE_FLOAT
@ RC_PROP_REQUIRE_BOOL
@ RC_PROP_ALLOW_MISSING
wmOperatorStatus WM_operator_ui_popup(bContext *C, wmOperator *op, int width)
#define TEST_PTR_DATA_TYPE(member, rna_type, rna_ptr, dataptr_cmp)
static void WM_OT_previews_ensure(wmOperatorType *ot)
static wmOperatorStatus wm_search_menu_exec(bContext *, wmOperator *)
static uint preview_filter_to_idfilter(enum PreviewFilterID filter)
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)
wmOperatorStatus WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallContext opcontext)
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 void WM_OT_window_close(wmOperatorType *ot)
static wmOperatorStatus wm_operator_defaults_exec(bContext *C, wmOperator *op)
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 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)
wmOperatorStatus WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *)
static wmOperatorStatus wm_call_menu_exec(bContext *C, wmOperator *op)
#define WM_RADIAL_CONTROL_DISPLAY_SIZE
const EnumPropertyItem * RNA_image_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static wmOperatorStatus wm_exit_blender_invoke(bContext *C, wmOperator *, const wmEvent *)
wmOperatorStatus WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *)
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 void WM_OT_operator_defaults(wmOperatorType *ot)
static wmOperatorStatus asset_shelf_popover_invoke(bContext *C, wmOperator *op, const wmEvent *)
const EnumPropertyItem * RNA_image_local_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void WM_paneltype_idname_visit_for_search(const bContext *, PointerRNA *, PropertyRNA *, const char *, blender::FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
PanelType * WM_paneltype_find(const StringRef idname, bool quiet)
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:400
wmOperatorStatus wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition wm_stereo.cc:344
wmOperatorStatus wm_stereo3d_set_exec(bContext *C, wmOperator *op)
Definition wm_stereo.cc:254
bool wm_stereo3d_set_check(bContext *, wmOperator *)
Definition wm_stereo.cc:392
void wm_stereo3d_set_draw(bContext *, wmOperator *op)
Definition wm_stereo.cc:354
wmOperatorStatus wm_window_new_exec(bContext *C, wmOperator *op)
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
Definition wm_window.cc:401
wmOperatorStatus wm_window_close_exec(bContext *C, wmOperator *)
wmOperatorStatus wm_window_new_main_exec(bContext *C, wmOperator *op)
void WM_progress_clear(wmWindow *win)
void WM_progress_set(wmWindow *win, float progress)
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
wmOperatorStatus wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *)
bScreen * WM_window_get_active_screen(const wmWindow *win)
void wm_xr_operatortypes_register()