Blender V5.0
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_interface_layout.hh"
101#include "UI_resources.hh"
102
103#include "WM_api.hh"
104#include "WM_keymap.hh"
105#include "WM_types.hh"
106
107#include "wm.hh"
108#include "wm_draw.hh"
109#include "wm_event_system.hh"
110#include "wm_event_types.hh"
111#include "wm_files.hh"
112#include "wm_window.hh"
113#ifdef WITH_XR_OPENXR
114# include "wm_xr.hh"
115#endif
116
117#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
118
119/* -------------------------------------------------------------------- */
122
123#define OP_BL_SEP_STRING "_OT_"
124#define OP_BL_SEP_LEN 4
125
126#define OP_PY_SEP_CHAR '.'
127#define OP_PY_SEP_LEN 1
128
129/* Difference between python 'identifier' and BL/C code one ("." separator replaced by "_OT_"),
130 * and final `\0` char. */
131#define OP_MAX_PY_IDNAME (OP_MAX_TYPENAME - OP_BL_SEP_LEN + OP_PY_SEP_LEN - 1)
132
133size_t WM_operator_py_idname(char *dst, const char *src)
134{
135 const char *sep = strstr(src, OP_BL_SEP_STRING);
136 if (sep) {
137 const size_t sep_offset = size_t(sep - src);
138
139 /* NOTE: we use ASCII `tolower` instead of system `tolower`, because the
140 * latter depends on the locale, and can lead to `idname` mismatch. */
141 memcpy(dst, src, sep_offset);
142 BLI_str_tolower_ascii(dst, sep_offset);
143
144 dst[sep_offset] = OP_PY_SEP_CHAR;
145 return BLI_strncpy_rlen(dst + (sep_offset + OP_PY_SEP_LEN),
146 sep + OP_BL_SEP_LEN,
147 OP_MAX_TYPENAME - sep_offset - OP_PY_SEP_LEN) +
148 (sep_offset + OP_PY_SEP_LEN);
149 }
150 /* Should not happen but support just in case. */
151 return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
152}
153
154size_t WM_operator_bl_idname(char *dst, const char *src)
155{
156 const size_t from_len = strlen(src);
157
158 const char *sep = strchr(src, OP_PY_SEP_CHAR);
159 if (sep && (from_len <= OP_MAX_PY_IDNAME)) {
160 const size_t sep_offset = size_t(sep - src);
161 memcpy(dst, src, sep_offset);
162 BLI_str_toupper_ascii(dst, sep_offset);
163
164 memcpy(dst + sep_offset, OP_BL_SEP_STRING, OP_BL_SEP_LEN);
165 BLI_strncpy(dst + sep_offset + OP_BL_SEP_LEN,
166 sep + OP_PY_SEP_LEN,
167 from_len - sep_offset - OP_PY_SEP_LEN + 1);
168 return from_len + OP_BL_SEP_LEN - OP_PY_SEP_LEN;
169 }
170 /* Should not happen but support just in case. */
171 return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
172}
173
174bool WM_operator_bl_idname_is_valid(const char *idname)
175{
176 const char *sep = strstr(idname, OP_BL_SEP_STRING);
177 /* Separator missing or at string beginning/end. */
178 if ((sep == nullptr) || (sep == idname) || (sep[OP_BL_SEP_LEN] == '\0')) {
179 return false;
180 }
181
182 for (const char *ch = idname; ch < sep; ch++) {
183 if ((*ch >= 'A' && *ch <= 'Z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
184 continue;
185 }
186 return false;
187 }
188
189 for (const char *ch = sep + OP_BL_SEP_LEN; *ch; ch++) {
190 if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
191 continue;
192 }
193 return false;
194 }
195 return true;
196}
197
199 const char *classname,
200 const char *idname)
201{
202 const char *ch = idname;
203 int dot = 0;
204 int i;
205 for (i = 0; *ch; i++, ch++) {
206 if ((*ch >= 'a' && *ch <= 'z') || (*ch >= '0' && *ch <= '9') || *ch == '_') {
207 /* Pass. */
208 }
209 else if (*ch == '.') {
210 if (ch == idname || (*(ch + 1) == '\0')) {
211 BKE_reportf(reports,
212 RPT_ERROR,
213 "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
214 classname,
215 idname,
216 i);
217 return false;
218 }
219 dot++;
220 }
221 else {
222 BKE_reportf(reports,
223 RPT_ERROR,
224 "Registering operator class: '%s', invalid bl_idname '%s', at position %d",
225 classname,
226 idname,
227 i);
228 return false;
229 }
230 }
231
232 if (i > OP_MAX_PY_IDNAME) {
233 BKE_reportf(reports,
234 RPT_ERROR,
235 "Registering operator class: '%s', invalid bl_idname '%s', "
236 "is too long, maximum length is %d",
237 classname,
238 idname,
240 return false;
241 }
242
243 if (dot != 1) {
245 reports,
246 RPT_ERROR,
247 "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
248 classname,
249 idname);
250 return false;
251 }
252 return true;
253}
254
256 wmOperator *op,
257 const bool all_args,
258 const bool macro_args,
260 PointerRNA *opptr)
261{
262 char idname_py[OP_MAX_TYPENAME];
263
264 /* For building the string. */
265 std::stringstream ss;
266
267 /* Arbitrary, but can get huge string with stroke painting otherwise. */
268 int max_prop_length = 10;
269
270 WM_operator_py_idname(idname_py, ot->idname);
271 ss << "bpy.ops." << idname_py << "(";
272
273 if (op && op->macro.first) {
274 /* Special handling for macros, else we only get default values in this case... */
275 wmOperator *opm;
276 bool first_op = true;
277
278 opm = static_cast<wmOperator *>(macro_args ? op->macro.first : nullptr);
279
280 for (; opm; opm = opm->next) {
281 PointerRNA *opmptr = opm->ptr;
282 PointerRNA opmptr_default;
283 if (opmptr == nullptr) {
284 WM_operator_properties_create_ptr(&opmptr_default, opm->type);
285 opmptr = &opmptr_default;
286 }
287
288 std::string string_args = RNA_pointer_as_string_id(C, opmptr);
289 if (first_op) {
290 ss << opm->type->idname << '=' << string_args;
291 first_op = false;
292 }
293 else {
294 ss << ", " << opm->type->idname << '=' << string_args;
295 }
296
297 if (opmptr == &opmptr_default) {
298 WM_operator_properties_free(&opmptr_default);
299 }
300 }
301 }
302 else {
303 /* Only to get the original props for comparisons. */
304 PointerRNA opptr_default;
305 const bool macro_args_test = ot->macro.first ? macro_args : true;
306
307 if (opptr == nullptr) {
308 WM_operator_properties_create_ptr(&opptr_default, ot);
309 opptr = &opptr_default;
310 }
311
313 C, opptr, false, all_args, macro_args_test, max_prop_length);
314
315 if (opptr == &opptr_default) {
316 WM_operator_properties_free(&opptr_default);
317 }
318 }
319
320 ss << ')';
321
322 return ss.str();
323}
324
326 wmOperator *op,
327 const bool all_args,
328 const bool macro_args)
329{
330 return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr);
331}
332
333std::string WM_operator_pystring_abbreviate(std::string str, int str_len_max)
334{
335 const int str_len = str.size();
336 const size_t parens_start = str.find('(');
337 if (parens_start == std::string::npos) {
338 return str;
339 }
340
341 const size_t parens_end = str.find(parens_start + 1, ')');
342 if (parens_end == std::string::npos) {
343 return str;
344 }
345
346 const int parens_len = parens_end - parens_start;
347 if (parens_len <= str_len_max) {
348 return str;
349 }
350
351 /* Truncate after the first comma. */
352 const size_t comma_first = str.find(parens_start, ',');
353 if (comma_first == std::string::npos) {
354 return str;
355 }
356 const char end_str[] = " ... )";
357 const int end_str_len = sizeof(end_str) - 1;
358
359 /* Leave a place for the first argument. */
360 const int new_str_len = (comma_first - parens_start) + 1;
361
362 if (str_len < new_str_len + parens_start + end_str_len + 1) {
363 return str;
364 }
365
366 return str.substr(0, comma_first) + end_str;
367}
368
369/* Return nullptr if no match is found. */
370#if 0
371static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr, bool *r_is_id)
372{
373 /* Loop over all context items and do 2 checks
374 *
375 * - See if the pointer is in the context.
376 * - See if the pointers ID is in the context.
377 */
378
379 /* Don't get from the context store since this is normally
380 * set only for the UI and not usable elsewhere. */
381 ListBase lb = CTX_data_dir_get_ex(C, false, true, true);
382 LinkData *link;
383
384 const char *member_found = nullptr;
385 const char *member_id = nullptr;
386 bool member_found_is_id = false;
387
388 for (link = lb.first; link; link = link->next) {
389 const char *identifier = link->data;
390 PointerRNA ctx_item_ptr = {};
391 // CTX_data_pointer_get(C, identifier); /* XXX, this isn't working. */
392
393 if (ctx_item_ptr.type == nullptr) {
394 continue;
395 }
396
397 if (ptr->owner_id == ctx_item_ptr.owner_id) {
398 const bool is_id = RNA_struct_is_ID(ctx_item_ptr.type);
399 if ((ptr->data == ctx_item_ptr.data) && (ptr->type == ctx_item_ptr.type)) {
400 /* Found! */
401 member_found = identifier;
402 member_found_is_id = is_id;
403 break;
404 }
405 if (is_id) {
406 /* Found a reference to this ID, so fall back to it if there is no direct reference. */
407 member_id = identifier;
408 }
409 }
410 }
411 BLI_freelistN(&lb);
412
413 if (member_found) {
414 *r_is_id = member_found_is_id;
415 return member_found;
416 }
417 else if (member_id) {
418 *r_is_id = true;
419 return member_id;
420 }
421 else {
422 return nullptr;
423 }
424}
425
426#else
427
428/* Use hard coded checks for now. */
429
444static const char *wm_context_member_from_ptr(const bContext *C,
445 const PointerRNA *ptr,
446 bool *r_is_id)
447{
448 const char *member_id = nullptr;
449 bool is_id = false;
450
451# define CTX_TEST_PTR_ID(C, member, idptr) \
452 { \
453 const char *ctx_member = member; \
454 PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
455 if (ctx_item_ptr.owner_id == idptr) { \
456 member_id = ctx_member; \
457 is_id = true; \
458 break; \
459 } \
460 } \
461 (void)0
462
463# define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \
464 { \
465 const char *ctx_member = member; \
466 const char *ctx_member_full = member_full; \
467 PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
468 if (ctx_item_ptr.owner_id && (ID *)cast(ctx_item_ptr.owner_id) == idptr) { \
469 member_id = ctx_member_full; \
470 is_id = true; \
471 break; \
472 } \
473 } \
474 (void)0
475
476# define TEST_PTR_DATA_TYPE(member, rna_type, rna_ptr, dataptr_cmp) \
477 { \
478 const char *ctx_member = member; \
479 if (RNA_struct_is_a((rna_ptr)->type, &(rna_type)) && (rna_ptr)->data == (dataptr_cmp)) { \
480 member_id = ctx_member; \
481 break; \
482 } \
483 } \
484 (void)0
485
486/* A version of #TEST_PTR_DATA_TYPE that calls `CTX_data_pointer_get_type(C, member)`. */
487# define TEST_PTR_DATA_TYPE_FROM_CONTEXT(member, rna_type, rna_ptr) \
488 { \
489 const char *ctx_member = member; \
490 if (RNA_struct_is_a((rna_ptr)->type, &(rna_type)) && \
491 (rna_ptr)->data == (CTX_data_pointer_get_type(C, ctx_member, &(rna_type)).data)) \
492 { \
493 member_id = ctx_member; \
494 break; \
495 } \
496 } \
497 (void)0
498
499 /* General checks (multiple ID types). */
500 if (ptr->owner_id) {
501 const ID_Type ptr_id_type = GS(ptr->owner_id->name);
502
503 /* Support break in the macros for an early exit. */
504 do {
505 /* Animation Data. */
506 if (id_type_can_have_animdata(ptr_id_type)) {
507 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_nla_track", RNA_NlaTrack, ptr);
508 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_nla_strip", RNA_NlaStrip, ptr);
509 }
510 } while (false);
511 }
512
513 /* Specific ID type checks. */
514 if (ptr->owner_id && (member_id == nullptr)) {
515
516 const ID_Type ptr_id_type = GS(ptr->owner_id->name);
517 switch (ptr_id_type) {
518 case ID_SCE: {
519 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_strip", RNA_Strip, ptr);
520
521 CTX_TEST_PTR_ID(C, "scene", ptr->owner_id);
522 break;
523 }
524 case ID_OB: {
525 TEST_PTR_DATA_TYPE_FROM_CONTEXT("active_pose_bone", RNA_PoseBone, ptr);
526
527 CTX_TEST_PTR_ID(C, "object", ptr->owner_id);
528 break;
529 }
530 /* From #rna_Main_objects_new. */
532
533 if (ptr_id_type == ID_AR) {
534 const bArmature *arm = (bArmature *)ptr->owner_id;
535 if (arm->edbo != nullptr) {
536 TEST_PTR_DATA_TYPE("active_bone", RNA_EditBone, ptr, arm->act_edbone);
537 }
538 else {
539 TEST_PTR_DATA_TYPE("active_bone", RNA_Bone, ptr, arm->act_bone);
540 }
541 }
542
543# define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data)
544 CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->owner_id);
545 break;
546# undef ID_CAST_OBDATA
547 }
548 case ID_MA: {
549# define ID_CAST_OBMATACT(id_pt) \
550 BKE_object_material_get(((Object *)id_pt), ((Object *)id_pt)->actcol)
552 C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->owner_id);
553 break;
554# undef ID_CAST_OBMATACT
555 }
556 case ID_WO: {
557# define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world)
558 CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->owner_id);
559 break;
560# undef ID_CAST_SCENEWORLD
561 }
562 case ID_SCR: {
563 CTX_TEST_PTR_ID(C, "screen", ptr->owner_id);
564
565 TEST_PTR_DATA_TYPE("area", RNA_Area, ptr, CTX_wm_area(C));
566 TEST_PTR_DATA_TYPE("region", RNA_Region, ptr, CTX_wm_region(C));
567
568 SpaceLink *space_data = CTX_wm_space_data(C);
569 if (space_data != nullptr) {
570 TEST_PTR_DATA_TYPE("space_data", RNA_Space, ptr, space_data);
571
572 switch (space_data->spacetype) {
573 case SPACE_VIEW3D: {
574 const View3D *v3d = (View3D *)space_data;
575 const View3DShading *shading = &v3d->shading;
576
577 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_View3DOverlay, ptr, v3d);
578 TEST_PTR_DATA_TYPE("space_data.shading", RNA_View3DShading, ptr, shading);
579 break;
580 }
581 case SPACE_GRAPH: {
582 const SpaceGraph *sipo = (SpaceGraph *)space_data;
583 const bDopeSheet *ads = sipo->ads;
584 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
585 break;
586 }
587 case SPACE_FILE: {
588 const SpaceFile *sfile = (SpaceFile *)space_data;
590 TEST_PTR_DATA_TYPE("space_data.params", RNA_FileSelectParams, ptr, params);
591 break;
592 }
593 case SPACE_IMAGE: {
594 const SpaceImage *sima = (SpaceImage *)space_data;
595 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceImageOverlay, ptr, sima);
596 TEST_PTR_DATA_TYPE("space_data.uv_editor", RNA_SpaceUVEditor, ptr, sima);
597 break;
598 }
599 case SPACE_NLA: {
600 const SpaceNla *snla = (SpaceNla *)space_data;
601 const bDopeSheet *ads = snla->ads;
602 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
603 break;
604 }
605 case SPACE_ACTION: {
606 const SpaceAction *sact = (SpaceAction *)space_data;
607 const bDopeSheet *ads = &sact->ads;
608 TEST_PTR_DATA_TYPE("space_data.dopesheet", RNA_DopeSheet, ptr, ads);
609 break;
610 }
611 case SPACE_NODE: {
612 const SpaceNode *snode = (SpaceNode *)space_data;
613 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceNodeOverlay, ptr, snode);
614 break;
615 }
616 case SPACE_CLIP: {
617 const SpaceClip *sclip = (SpaceClip *)space_data;
618 TEST_PTR_DATA_TYPE("space_data.overlay", RNA_SpaceClipOverlay, ptr, sclip);
619 break;
620 }
621 case SPACE_SEQ: {
622 const SpaceSeq *sseq = (SpaceSeq *)space_data;
624 "space_data.preview_overlay", RNA_SequencerPreviewOverlay, ptr, sseq);
626 "space_data.timeline_overlay", RNA_SequencerTimelineOverlay, ptr, sseq);
627 TEST_PTR_DATA_TYPE("space_data.cache_overlay", RNA_SequencerCacheOverlay, ptr, sseq);
628 break;
629 }
630 }
631 }
632
633 break;
634 }
635 default:
636 break;
637 }
638# undef CTX_TEST_PTR_ID
639# undef CTX_TEST_PTR_ID_CAST
640# undef TEST_PTR_DATA_TYPE
641 }
642
643 *r_is_id = is_id;
644
645 return member_id;
646}
647#endif
648
649std::optional<std::string> WM_context_path_resolve_property_full(const bContext *C,
650 const PointerRNA *ptr,
651 PropertyRNA *prop,
652 int index)
653{
654 bool is_id;
655 const char *member_id = wm_context_member_from_ptr(C, ptr, &is_id);
656 if (!member_id) {
657 return std::nullopt;
658 }
659 std::string member_id_data_path;
660 if (is_id && !RNA_struct_is_ID(ptr->type)) {
661 std::optional<std::string> data_path = RNA_path_from_ID_to_struct(ptr);
662 if (data_path) {
663 if (prop != nullptr) {
664 std::string prop_str = RNA_path_property_py(ptr, prop, index);
665 if (prop_str[0] == '[') {
666 member_id_data_path = fmt::format("{}.{}{}", member_id, *data_path, prop_str);
667 }
668 else {
669 member_id_data_path = fmt::format("{}.{}.{}", member_id, *data_path, prop_str);
670 }
671 }
672 else {
673 member_id_data_path = fmt::format("{}.{}", member_id, *data_path);
674 }
675 }
676 }
677 else {
678 if (prop != nullptr) {
679 std::string prop_str = RNA_path_property_py(ptr, prop, index);
680 if (prop_str[0] == '[') {
681 member_id_data_path = fmt::format("{}{}", member_id, prop_str);
682 }
683 else {
684 member_id_data_path = fmt::format("{}.{}", member_id, prop_str);
685 }
686 }
687 else {
688 member_id_data_path = member_id;
689 }
690 }
691
692 return member_id_data_path;
693}
694
695std::optional<std::string> WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr)
696{
697 return WM_context_path_resolve_property_full(C, ptr, nullptr, -1);
698}
699
700static std::optional<std::string> wm_prop_pystring_from_context(bContext *C,
702 PropertyRNA *prop,
703 int index)
704{
705 std::optional<std::string> member_id_data_path = WM_context_path_resolve_property_full(
706 C, ptr, prop, index);
707 if (!member_id_data_path.has_value()) {
708 return std::nullopt;
709 }
710 return "bpy.context." + member_id_data_path.value();
711}
712
713std::optional<std::string> WM_prop_pystring_assign(bContext *C,
715 PropertyRNA *prop,
716 int index)
717{
718 std::optional<std::string> lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) :
719 std::nullopt;
720
721 if (!lhs.has_value()) {
722 /* Fall back to `bpy.data.foo[id]` if we don't find in the context. */
723 if (std::optional<std::string> lhs_str = RNA_path_full_property_py(ptr, prop, index)) {
724 lhs = lhs_str;
725 }
726 else {
727 return std::nullopt;
728 }
729 }
730
731 std::string rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX);
732
733 std::string ret = fmt::format("{} = {}", lhs.value(), rhs);
734 return ret;
735}
736
738{
739 /* Set the ID so the context can be accessed: see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
740 *ptr = RNA_pointer_create_discrete(static_cast<ID *>(G_MAIN->wm.first), ot->srna, nullptr);
741}
742
743void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
744{
745 wmOperatorType *ot = WM_operatortype_find(opstring, false);
746
747 if (ot) {
749 }
750 else {
751 /* Set the ID so the context can be accessed: see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
753 static_cast<ID *>(G_MAIN->wm.first), &RNA_OperatorProperties, nullptr);
754 }
755}
756
757void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
758{
759 IDProperty *tmp_properties = nullptr;
760 /* Allow passing nullptr for properties, just create the properties here then. */
761 if (properties == nullptr) {
762 properties = &tmp_properties;
763 }
764
765 if (*properties == nullptr) {
766 *properties = blender::bke::idprop::create_group("wmOpItemProp").release();
767 }
768
769 if (*ptr == nullptr) {
770 *ptr = MEM_new<PointerRNA>("wmOpItemPtr");
772 }
773
774 (*ptr)->data = *properties;
775}
776
777void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
778{
779 RNA_STRUCT_BEGIN (ptr, prop) {
780 switch (RNA_property_type(prop)) {
781 case PROP_ENUM:
782 if (no_context) {
784 }
785 else {
787 }
788 break;
789 case PROP_POINTER: {
791
792 /* Recurse into operator properties. */
793 if (RNA_struct_is_a(ptype, &RNA_OperatorProperties)) {
795 WM_operator_properties_sanitize(&opptr, no_context);
796 }
797 break;
798 }
799 default:
800 break;
801 }
802 }
804}
805
807{
808 bool changed = false;
809 RNA_STRUCT_BEGIN (ptr, prop) {
810 switch (RNA_property_type(prop)) {
811 case PROP_POINTER: {
813 if (ptype != &RNA_Struct) {
815 changed |= WM_operator_properties_default(&opptr, do_update);
816 }
817 break;
818 }
819 default:
820 if ((do_update == false) || (RNA_property_is_set(ptr, prop) == false)) {
821 if (RNA_property_reset(ptr, prop, -1)) {
822 changed = true;
823 }
824 }
825 break;
826 }
827 }
829
830 return changed;
831}
832
834{
835 if (op->ptr->data) {
837
838 RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
839 PropertyRNA *prop = static_cast<PropertyRNA *>(itemptr.data);
840
841 if ((RNA_property_flag(prop) & (PROP_SKIP_SAVE | PROP_SKIP_PRESET)) == 0) {
842 const char *identifier = RNA_property_identifier(prop);
843 RNA_struct_system_idprops_unset(op->ptr, identifier);
844 }
845 }
847 }
848}
849
851{
852 IDProperty *properties = static_cast<IDProperty *>(ptr->data);
853
854 if (properties) {
855 IDP_ClearProperty(properties);
856 }
857}
858
860{
861 IDProperty *properties = static_cast<IDProperty *>(ptr->data);
862
863 if (properties) {
864 IDP_FreeProperty(properties);
865 ptr->data = nullptr; /* Just in case. */
866 }
867}
868
870
871/* -------------------------------------------------------------------- */
874
875#if 1 /* May want to disable operator remembering previous state for testing. */
876
878{
879 bool changed = false;
880 IDProperty *replaceprops = blender::bke::idprop::create_group("wmOperatorProperties").release();
881
883
884 RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
885 PropertyRNA *prop = static_cast<PropertyRNA *>(itemptr.data);
886 if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
887 if (!RNA_property_is_set(op->ptr, prop)) { /* Don't override a setting already set. */
888 const char *identifier = RNA_property_identifier(prop);
889 IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, identifier);
890 if (idp_src) {
891 IDProperty *idp_dst = IDP_CopyProperty(idp_src);
892
893 /* NOTE: in the future this may need to be done recursively,
894 * but for now RNA doesn't access nested operators. */
895 idp_dst->flag |= IDP_FLAG_GHOST;
896
897 /* Add to temporary group instead of immediate replace,
898 * because we are iterating over this group. */
899 IDP_AddToGroup(replaceprops, idp_dst);
900 changed = true;
901 }
902 }
903 }
904 }
906
907 if (changed) {
908 CLOG_DEBUG(WM_LOG_OPERATORS, "Loading previous properties for '%s'", op->type->idname);
909 }
910 IDP_MergeGroup(op->properties, replaceprops, true);
911 IDP_FreeProperty(replaceprops);
912 return changed;
913}
914
916{
917 bool changed = false;
918 if (op->type->last_properties) {
920 LISTBASE_FOREACH (wmOperator *, opm, &op->macro) {
921 IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname);
922 if (idp_src) {
923 changed |= operator_last_properties_init_impl(opm, idp_src);
924 }
925 }
926 }
927 return changed;
928}
929
931{
932 if (op->type->last_properties) {
934 op->type->last_properties = nullptr;
935 }
936
937 if (op->properties) {
939 CLOG_DEBUG(WM_LOG_OPERATORS, "Storing properties for '%s'", op->type->idname);
940 }
942 }
943
944 if (op->macro.first != nullptr) {
945 LISTBASE_FOREACH (wmOperator *, opm, &op->macro) {
946 if (opm->properties) {
947 if (op->type->last_properties == nullptr) {
948 op->type->last_properties =
949 blender::bke::idprop::create_group("wmOperatorProperties").release();
950 }
951 IDProperty *idp_macro = IDP_CopyProperty(opm->properties);
952 STRNCPY(idp_macro->name, opm->type->idname);
953 IDP_ReplaceInGroup(op->type->last_properties, idp_macro);
954 }
955 }
956 }
957
958 return (op->type->last_properties != nullptr);
959}
960
961#else
962
964{
965 return false;
966}
967
969{
970 return false;
971}
972
973#endif
974
976
977/* -------------------------------------------------------------------- */
980
982{
983 PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
984 "wait_to_deselect_others");
985 const bool use_select_on_click = RNA_struct_property_is_set(op->ptr, "use_select_on_click");
986 const short init_event_type = short(POINTER_AS_INT(op->customdata));
987
988 /* Get settings from RNA properties for operator. */
989 const int mval[2] = {RNA_int_get(op->ptr, "mouse_x"), RNA_int_get(op->ptr, "mouse_y")};
990
991 if (init_event_type == 0) {
992 op->customdata = POINTER_FROM_INT(int(event->type));
993
994 if (use_select_on_click) {
995 /* Don't do any selection yet. Wait to see if there's a drag or click (release) event. */
998 }
999
1000 if (event->val == KM_PRESS) {
1001 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, true);
1002
1003 wmOperatorStatus retval = op->type->exec(C, op);
1004 OPERATOR_RETVAL_CHECK(retval);
1005
1006 if (retval & OPERATOR_RUNNING_MODAL) {
1008 }
1009 return retval | OPERATOR_PASS_THROUGH;
1010 }
1011 /* If we are in init phase, and cannot validate init of modal operations,
1012 * just fall back to basic exec.
1013 */
1014 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
1015
1016 wmOperatorStatus retval = op->type->exec(C, op);
1017 OPERATOR_RETVAL_CHECK(retval);
1018
1019 return retval | OPERATOR_PASS_THROUGH;
1020 }
1021 if (event->type == init_event_type && event->val == KM_RELEASE) {
1022 RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
1023
1024 wmOperatorStatus retval = op->type->exec(C, op);
1025 OPERATOR_RETVAL_CHECK(retval);
1026
1027 return retval | OPERATOR_PASS_THROUGH;
1028 }
1029 if (ISMOUSE_MOTION(event->type)) {
1030 const int drag_delta[2] = {
1031 mval[0] - event->mval[0],
1032 mval[1] - event->mval[1],
1033 };
1034 /* If user moves mouse more than defined threshold, we consider select operator as
1035 * finished. Otherwise, it is still running until we get an 'release' event. In any
1036 * case, we pass through event, but select op is not finished yet. */
1037 if (WM_event_drag_test_with_delta(event, drag_delta)) {
1039 }
1040 /* Important not to return anything other than PASS_THROUGH here,
1041 * otherwise it prevents underlying drag detection code to work properly. */
1042 return OPERATOR_PASS_THROUGH;
1043 }
1044
1046}
1047
1049{
1050 ARegion *region = CTX_wm_region(C);
1051
1052 int mval[2];
1053 WM_event_drag_start_mval(event, region, mval);
1054
1055 RNA_int_set(op->ptr, "mouse_x", mval[0]);
1056 RNA_int_set(op->ptr, "mouse_y", mval[1]);
1057
1059
1060 wmOperatorStatus retval = op->type->modal(C, op, event);
1061 OPERATOR_RETVAL_CHECK(retval);
1062 return retval;
1063}
1064
1066{
1067 if (op->flag & OP_IS_INVOKE) {
1068 Scene *scene = CTX_data_scene(C);
1069 View3D *v3d = CTX_wm_view3d(C);
1070
1071 const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
1072 ED_scene_grid_scale(scene, nullptr);
1073
1074 /* Always run, so the values are initialized,
1075 * otherwise we may get differ behavior when `dia != 1.0`. */
1076 RNA_STRUCT_BEGIN (op->ptr, prop) {
1077 if (RNA_property_type(prop) == PROP_FLOAT) {
1079 if (pstype == PROP_DISTANCE) {
1080 /* We don't support arrays yet. */
1081 BLI_assert(RNA_property_array_check(prop) == false);
1082 /* Initialize. */
1083 if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
1084 const float value = RNA_property_float_get_default(op->ptr, prop) * dia;
1085 RNA_property_float_set(op->ptr, prop, value);
1086 }
1087 }
1088 }
1089 }
1091 }
1092}
1093
1095{
1096 return (op->flag & OP_IS_INVOKE && !(U.uiflag & USER_REDUCE_MOTION)) ? U.smooth_viewtx : 0;
1097}
1098
1100 wmOperator *op,
1102{
1103 PropertyRNA *prop = op->type->prop;
1104
1105 if (prop == nullptr) {
1106 CLOG_ERROR(WM_LOG_OPERATORS, "'%s' has no enum property set", op->type->idname);
1107 }
1108 else if (RNA_property_type(prop) != PROP_ENUM) {
1110 "'%s', '%s' is not an enum property",
1111 op->type->idname,
1113 }
1114 else if (RNA_property_is_set(op->ptr, prop)) {
1115 const wmOperatorStatus retval = op->type->exec(C, op);
1116 OPERATOR_RETVAL_CHECK(retval);
1117 return retval;
1118 }
1119 else {
1121 C, WM_operatortype_name(op->type, op->ptr).c_str(), ICON_NONE);
1122 uiLayout *layout = UI_popup_menu_layout(pup);
1123 /* Set this so the default execution context is the same as submenus. */
1124 layout->operator_context_set(opcontext);
1125 layout->op_enum(op->type->idname,
1127 static_cast<IDProperty *>(op->ptr->data),
1128 opcontext,
1129 UI_ITEM_NONE);
1130 UI_popup_menu_end(C, pup);
1131 return OPERATOR_INTERFACE;
1132 }
1133
1134 return OPERATOR_CANCELLED;
1135}
1136
1141
1143 wmOperator *op; /* The operator that will be executed when selecting an item. */
1144};
1145
1147static uiBlock *wm_enum_search_menu(bContext *C, ARegion *region, void *arg)
1148{
1149 EnumSearchMenu *search_menu = static_cast<EnumSearchMenu *>(arg);
1150 wmWindow *win = CTX_wm_window(C);
1151 wmOperator *op = search_menu->op;
1152 /* `template_ID` uses `4 * widget_unit` for width,
1153 * we use a bit more, some items may have a suffix to show. */
1154 const int width = UI_searchbox_size_x();
1155 const int height = UI_searchbox_size_y();
1156 static char search[256] = "";
1157
1158 uiBlock *block = UI_block_begin(C, region, "_popup", blender::ui::EmbossType::Emboss);
1161
1162 search[0] = '\0';
1163#if 0 /* Ok, this isn't so easy. */
1164 uiDefBut(block,
1166 0,
1167 WM_operatortype_name(op->type, op->ptr),
1168 0,
1169 0,
1171 UI_UNIT_Y,
1172 nullptr,
1173 0.0,
1174 0.0,
1175 "");
1176#endif
1177 uiBut *but = uiDefSearchButO_ptr(block,
1178 op->type,
1179 static_cast<IDProperty *>(op->ptr->data),
1180 search,
1181 0,
1182 ICON_VIEWZOOM,
1183 sizeof(search),
1184 0,
1185 0,
1186 width,
1187 UI_UNIT_Y,
1188 "");
1189
1190 /* Fake button, it holds space for search items. */
1191 uiDefBut(block, ButType::Label, 0, "", 0, -height, width, height, nullptr, 0, 0, std::nullopt);
1192
1193 /* Move it downwards, mouse over button. */
1195
1197
1198 return block;
1199}
1200
1202{
1203 static EnumSearchMenu search_menu;
1204 search_menu.op = op;
1205 /* Refreshing not supported, because operator might get freed. */
1206 const bool can_refresh = false;
1207 UI_popup_block_invoke_ex(C, wm_enum_search_menu, &search_menu, nullptr, can_refresh);
1208 return OPERATOR_INTERFACE;
1209}
1210
1212 wmOperator *op,
1213 const char *title,
1214 const int icon,
1215 const char *message,
1216 const blender::wm::OpCallContext /*opcontext*/)
1217{
1218 int alert_icon = ALERT_ICON_QUESTION;
1219 switch (icon) {
1220 case ICON_NONE:
1221 alert_icon = ALERT_ICON_NONE;
1222 break;
1223 case ICON_ERROR:
1224 alert_icon = ALERT_ICON_WARNING;
1225 break;
1226 case ICON_QUESTION:
1227 alert_icon = ALERT_ICON_QUESTION;
1228 break;
1229 case ICON_CANCEL:
1230 alert_icon = ALERT_ICON_ERROR;
1231 break;
1232 case ICON_INFO:
1233 alert_icon = ALERT_ICON_INFO;
1234 break;
1235 }
1236 return WM_operator_confirm_ex(C, op, IFACE_(title), nullptr, IFACE_(message), alert_icon, false);
1237}
1238
1240{
1242 C, op, IFACE_(message), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1243}
1244
1246{
1248 C, op, IFACE_(op->type->name), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1249}
1250
1252 wmOperator *op,
1253 const wmEvent * /*event*/)
1254{
1255 const bool confirm = RNA_boolean_get(op->ptr, "confirm");
1256 if (confirm) {
1258 C, op, IFACE_(op->type->name), nullptr, IFACE_("OK"), ALERT_ICON_NONE, false);
1259 }
1260 return op->type->exec(C, op);
1261}
1262
1264{
1265 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
1266 return WM_operator_call_notest(C, op); /* Call exec direct. */
1267 }
1270}
1271
1273{
1274 char filepath[FILE_MAX];
1275 /* Don't nullptr check prop, this can only run on ops with a 'filepath'. */
1276 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
1277 RNA_property_string_get(op->ptr, prop, filepath);
1278 if (BKE_image_path_ext_from_imformat_ensure(filepath, sizeof(filepath), im_format)) {
1279 RNA_property_string_set(op->ptr, prop, filepath);
1280 /* NOTE: we could check for and update 'filename' here,
1281 * but so far nothing needs this. */
1282 return true;
1283 }
1284 return false;
1285}
1286
1288{
1289 if (CTX_wm_window(C) == nullptr) {
1290 return false;
1291 }
1292 return true;
1293}
1294
1295bool WM_operator_check_ui_enabled(const bContext *C, const char *idname)
1296{
1298 Scene *scene = CTX_data_scene(C);
1299
1300 return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY));
1301}
1302
1304{
1306
1307 /* Only for operators that are registered and did an undo push. */
1308 LISTBASE_FOREACH_BACKWARD (wmOperator *, op, &wm->runtime->operators) {
1309 if ((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO)) {
1310 return op;
1311 }
1312 }
1313
1314 return nullptr;
1315}
1316
1318{
1319 if (ot->last_properties == nullptr) {
1320 ot->last_properties = blender::bke::idprop::create_group("wmOperatorProperties").release();
1321 }
1322 return ot->last_properties;
1323}
1324
1330
1332{
1333 Main *bmain = CTX_data_main(C);
1334 ID *id = nullptr;
1335
1336 /* Check input variables. */
1337 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
1338 const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
1339 char filepath[FILE_MAX];
1340 bool exists = false;
1341
1342 RNA_string_get(op->ptr, "filepath", filepath);
1343
1344 errno = 0;
1345
1346 if (idcode == ID_IM) {
1347 id = reinterpret_cast<ID *>(BKE_image_load_exists(bmain, filepath, &exists));
1348 }
1349 else {
1351 }
1352
1353 if (!id) {
1354 BKE_reportf(op->reports,
1355 RPT_ERROR,
1356 "Cannot read %s '%s': %s",
1358 filepath,
1359 errno ? strerror(errno) : RPT_("unsupported format"));
1360 return nullptr;
1361 }
1362
1363 if (is_relative_path) {
1364 if (exists == false) {
1365 if (idcode == ID_IM) {
1366 BLI_path_rel(((Image *)id)->filepath, BKE_main_blendfile_path(bmain));
1367 }
1368 else {
1370 }
1371 }
1372 }
1373
1374 return id;
1375 }
1376
1378 return nullptr;
1379 }
1380
1381 /* Lookup an already existing ID. */
1383
1384 if (!id) {
1385 /* Print error with the name if the name is available. */
1386
1387 if (RNA_struct_property_is_set(op->ptr, "name")) {
1388 char name[MAX_ID_NAME - 2];
1389 RNA_string_get(op->ptr, "name", name);
1391 op->reports, RPT_ERROR, "%s '%s' not found", BKE_idtype_idcode_to_name(idcode), name);
1392 return nullptr;
1393 }
1394
1395 BKE_reportf(op->reports, RPT_ERROR, "%s not found", BKE_idtype_idcode_to_name(idcode));
1396 return nullptr;
1397 }
1398
1399 id_us_plus(id);
1400 return id;
1401}
1402
1403static void wm_block_redo_cb(bContext *C, void *arg_op, int /*arg_event*/)
1404{
1405 wmOperator *op = static_cast<wmOperator *>(arg_op);
1406
1407 if (op == WM_operator_last_redo(C)) {
1408 /* Operator was already executed once? undo & repeat. */
1410 }
1411 else {
1412 /* Operator not executed yet, call it. */
1413 ED_undo_push_op(C, op);
1415
1416 WM_operator_repeat(C, op);
1417 }
1418}
1419
1420static void wm_block_redo_cancel_cb(bContext *C, void *arg_op)
1421{
1422 wmOperator *op = static_cast<wmOperator *>(arg_op);
1423
1424 /* If operator never got executed, free it. */
1425 if (op != WM_operator_last_redo(C)) {
1426 WM_operator_free(op);
1427 }
1428}
1429
1430static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
1431{
1432 wmOperator *op = static_cast<wmOperator *>(arg_op);
1433 const uiStyle *style = UI_style_get_dpi();
1434 int width = 15 * UI_UNIT_X;
1435
1436 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1439
1440 /* #UI_BLOCK_NUMSELECT for layer buttons. */
1442
1443 /* If register is not enabled, the operator gets freed on #OPERATOR_FINISHED
1444 * ui_apply_but_funcs_after calls #ED_undo_operator_repeate_cb and crashes. */
1446
1448 UI_popup_dummy_panel_set(region, block);
1449 uiLayout &layout = blender::ui::block_layout(block,
1452 0,
1453 0,
1454 width,
1455 UI_UNIT_Y,
1456 0,
1457 style);
1458
1459 if (op == WM_operator_last_redo(C)) {
1461 layout.enabled_set(false);
1462 }
1463 }
1464
1465 uiItemL_ex(&layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE, true, false);
1467 layout.separator(0.5f);
1468
1469 uiLayout *col = &layout.column(false);
1471
1472 UI_block_bounds_set_popup(block, 7 * UI_SCALE_FAC, nullptr);
1473
1474 return block;
1475}
1476
1491
1492/* Only invoked by OK button in popups created with #wm_block_dialog_create(). */
1493static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
1494{
1495 wmOperator *op;
1496 {
1497 /* Execute will free the operator.
1498 * In this case, wm_operator_ui_popup_cancel won't run. */
1499 wmOpPopUp *data = static_cast<wmOpPopUp *>(arg1);
1500 op = data->op;
1501 MEM_delete(data);
1502 }
1503
1504 uiBlock *block = static_cast<uiBlock *>(arg2);
1505 /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled
1506 * in case WM_operator_call_ex exits/reloads the current file (#49199). */
1507
1509
1510 /* Get context data *after* WM_operator_call_ex
1511 * which might have closed the current file and changed context. */
1512 wmWindow *win = CTX_wm_window(C);
1513 UI_popup_block_close(C, win, block);
1514
1515 WM_operator_call_ex(C, op, true);
1516}
1517
1518static void wm_operator_ui_popup_cancel(bContext *C, void *user_data);
1519
1520/* Only invoked by Cancel button in popups created with #wm_block_dialog_create(). */
1521static void dialog_cancel_cb(bContext *C, void *arg1, void *arg2)
1522{
1524 uiBlock *block = static_cast<uiBlock *>(arg2);
1526 wmWindow *win = CTX_wm_window(C);
1527 UI_popup_block_close(C, win, block);
1528}
1529
1533static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_data)
1534{
1535 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1536 wmOperator *op = data->op;
1537 const uiStyle *style = UI_style_get_dpi();
1538 const bool small = data->size == WM_POPUP_SIZE_SMALL;
1539 const short icon_size = (small ? 32 : 40) * UI_SCALE_FAC;
1540
1541 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1544 UI_popup_dummy_panel_set(region, block);
1545
1546 if (data->mouse_move_quit) {
1548 }
1549 if (data->icon < ALERT_ICON_NONE || data->icon >= ALERT_ICON_MAX) {
1550 data->icon = ALERT_ICON_QUESTION;
1551 }
1552
1554
1555 UI_fontstyle_set(&style->widget);
1556 /* Width based on the text lengths. */
1557 int text_width = std::max(
1558 120 * UI_SCALE_FAC,
1559 BLF_width(style->widget.uifont_id, data->title.c_str(), BLF_DRAW_STR_DUMMY_MAX));
1560
1561 /* Break Message into multiple lines. */
1562 blender::Vector<std::string> message_lines;
1563 blender::StringRef messaged_trimmed = blender::StringRef(data->message).trim();
1564 std::istringstream message_stream(messaged_trimmed);
1565 std::string line;
1566 while (std::getline(message_stream, line)) {
1567 message_lines.append(line);
1568 text_width = std::max(
1569 text_width, int(BLF_width(style->widget.uifont_id, line.c_str(), BLF_DRAW_STR_DUMMY_MAX)));
1570 }
1571
1572 int dialog_width = std::max(text_width + int(style->columnspace * 2.5), data->width);
1573
1574 /* Adjust width if the button text is long. */
1575 const int longest_button_text = std::max(
1576 BLF_width(style->widget.uifont_id, data->confirm_text.c_str(), BLF_DRAW_STR_DUMMY_MAX),
1578 dialog_width = std::max(dialog_width, 3 * longest_button_text);
1579
1580 uiLayout *layout;
1581 if (data->icon != ALERT_ICON_NONE) {
1582 layout = uiItemsAlertBox(
1583 block, style, dialog_width + icon_size, eAlertIcon(data->icon), icon_size);
1584 }
1585 else {
1586 layout = &blender::ui::block_layout(block,
1589 0,
1590 0,
1591 dialog_width,
1592 0,
1593 0,
1594 style);
1595 }
1596
1597 /* Title. */
1598 if (!data->title.empty()) {
1599 uiItemL_ex(layout, data->title, ICON_NONE, true, false);
1600
1601 /* Line under the title if there are properties but no message body. */
1602 if (data->include_properties && message_lines.size() == 0) {
1603 layout->separator(0.2f, LayoutSeparatorType::Line);
1604 };
1605 }
1606
1607 /* Message lines. */
1608 if (message_lines.size() > 0) {
1609 uiLayout *lines = &layout->column(false);
1610 lines->scale_y_set(0.65f);
1611 lines->separator(0.1f);
1612 for (auto &st : message_lines) {
1613 lines->label(st, ICON_NONE);
1614 }
1615 }
1616
1617 if (data->include_properties) {
1618 layout->separator(0.5f);
1620 }
1621
1622 layout->separator(small ? 0.1f : 1.8f);
1623
1624 /* Clear so the OK button is left alone. */
1625 UI_block_func_set(block, nullptr, nullptr, nullptr);
1626
1627#ifdef _WIN32
1628 const bool windows_layout = true;
1629#else
1630 const bool windows_layout = false;
1631#endif
1632
1633 /* Check there are no active default buttons, allowing a dialog to define its own
1634 * confirmation buttons which are shown instead of these, see: #124098. */
1635 if (!UI_block_has_active_default_button(layout->block())) {
1636 /* New column so as not to interfere with custom layouts, see: #26436. */
1637 uiLayout *col = &layout->column(false);
1638 uiBlock *col_block = col->block();
1639 uiBut *confirm_but;
1640 uiBut *cancel_but;
1641
1642 col = &col->split(0.0f, true);
1643 col->scale_y_set(small ? 1.0f : 1.2f);
1644
1645 if (windows_layout) {
1646 confirm_but = uiDefBut(col_block,
1648 0,
1649 data->confirm_text.c_str(),
1650 0,
1651 0,
1652 0,
1653 UI_UNIT_Y,
1654 nullptr,
1655 0,
1656 0,
1657 "");
1658 col->column(false);
1659 }
1660
1661 cancel_but = uiDefBut(
1662 col_block, ButType::But, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, nullptr, 0, 0, "");
1663
1664 if (!windows_layout) {
1665 col->column(false);
1666 confirm_but = uiDefBut(col_block,
1668 0,
1669 data->confirm_text.c_str(),
1670 0,
1671 0,
1672 0,
1673 UI_UNIT_Y,
1674 nullptr,
1675 0,
1676 0,
1677 "");
1678 }
1679
1680 UI_but_func_set(confirm_but, dialog_exec_cb, data, col_block);
1681 UI_but_func_set(cancel_but, dialog_cancel_cb, data, col_block);
1682 UI_but_flag_enable((data->cancel_default) ? cancel_but : confirm_but, UI_BUT_ACTIVE_DEFAULT);
1683 }
1684
1685 const int padding = (small ? 7 : 14) * UI_SCALE_FAC;
1686
1687 if (data->position == WM_POPUP_POSITION_MOUSE) {
1688 const float button_center_x = windows_layout ? -0.4f : -0.90f;
1689 const float button_center_y = small ? 2.0f : 3.1f;
1690 const int bounds_offset[2] = {int(button_center_x * layout->width()),
1691 int(button_center_y * UI_UNIT_X)};
1692 UI_block_bounds_set_popup(block, padding, bounds_offset);
1693 }
1694 else if (data->position == WM_POPUP_POSITION_CENTER) {
1696 }
1697
1698 return block;
1699}
1700
1701static uiBlock *wm_operator_ui_create(bContext *C, ARegion *region, void *user_data)
1702{
1703 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1704 wmOperator *op = data->op;
1705 const uiStyle *style = UI_style_get_dpi();
1706
1707 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1711
1712 UI_popup_dummy_panel_set(region, block);
1713
1714 uiLayout &layout = blender::ui::block_layout(block,
1717 0,
1718 0,
1719 data->width,
1720 0,
1721 0,
1722 style);
1723
1724 /* Since UI is defined the auto-layout args are not used. */
1726
1727 UI_block_func_set(block, nullptr, nullptr, nullptr);
1728
1729 UI_block_bounds_set_popup(block, 6 * UI_SCALE_FAC, nullptr);
1730
1731 return block;
1732}
1733
1734static void wm_operator_ui_popup_cancel(bContext *C, void *user_data)
1735{
1736 wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
1737 wmOperator *op = data->op;
1738
1739 if (op) {
1740 if (op->type->cancel) {
1741 op->type->cancel(C, op);
1742 }
1743
1744 if (data->free_op) {
1745 WM_operator_free(op);
1746 }
1747 }
1748
1749 MEM_delete(data);
1750}
1751
1752static void wm_operator_ui_popup_ok(bContext *C, void *arg, int retval)
1753{
1754 wmOpPopUp *data = static_cast<wmOpPopUp *>(arg);
1755 wmOperator *op = data->op;
1756
1757 if (op && retval > 0) {
1758 WM_operator_call_ex(C, op, true);
1759 }
1760
1761 MEM_delete(data);
1762}
1763
1765 wmOperator *op,
1766 const char *title,
1767 const char *message,
1768 const char *confirm_text,
1769 int icon,
1770 bool cancel_default)
1771{
1772 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1773 data->op = op;
1774
1775 /* Larger dialog needs a wider minimum width to balance with the big icon. */
1776 const float min_width = (message == nullptr) ? 180.0f : 230.0f;
1777 data->width = int(min_width * UI_SCALE_FAC * UI_style_get()->widget.points /
1779
1780 data->free_op = true;
1781 data->title = (title == nullptr) ? WM_operatortype_name(op->type, op->ptr) : title;
1782 data->message = (message == nullptr) ? std::string() : message;
1783 data->confirm_text = (confirm_text == nullptr) ? IFACE_("OK") : confirm_text;
1784 data->icon = eAlertIcon(icon);
1785 data->size = (message == nullptr) ? WM_POPUP_SIZE_SMALL : WM_POPUP_SIZE_LARGE;
1786 data->position = (message == nullptr) ? WM_POPUP_POSITION_MOUSE : WM_POPUP_POSITION_CENTER;
1787 data->cancel_default = cancel_default;
1788 data->mouse_move_quit = (message == nullptr) ? true : false;
1789 data->include_properties = false;
1790
1793
1795}
1796
1798{
1799 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1800 data->op = op;
1801 data->width = width * UI_SCALE_FAC;
1802 data->free_op = true; /* If this runs and gets registered we may want not to free it. */
1805}
1806
1813 bContext *C,
1814 wmOperator *op,
1815 const bool do_call,
1816 const bool do_redo,
1817 std::optional<std::string> title = std::nullopt,
1818 std::optional<std::string> confirm_text = std::nullopt,
1819 const bool cancel_default = false,
1820 std::optional<std::string> message = std::nullopt)
1821{
1822 if ((op->type->flag & OPTYPE_REGISTER) == 0) {
1823 BKE_reportf(op->reports,
1824 RPT_ERROR,
1825 "Operator '%s' does not have register enabled, incorrect invoke function",
1826 op->type->idname);
1827 return OPERATOR_CANCELLED;
1828 }
1829
1830 if (do_redo) {
1831 if ((op->type->flag & OPTYPE_UNDO) == 0) {
1832 BKE_reportf(op->reports,
1833 RPT_ERROR,
1834 "Operator '%s' does not have undo enabled, incorrect invoke function",
1835 op->type->idname);
1836 return OPERATOR_CANCELLED;
1837 }
1838 }
1839
1840 /* If we don't have global undo, we can't do undo push for automatic redo,
1841 * so we require manual OK clicking in this popup. */
1842 if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) {
1844 C, op, 300, title, confirm_text, cancel_default, message);
1845 }
1846
1848
1849 if (do_call) {
1850 wm_block_redo_cb(C, op, 0);
1851 }
1852
1854}
1855
1857 wmOperator *op,
1858 const wmEvent * /*event*/,
1859 std::optional<std::string> title,
1860 std::optional<std::string> confirm_text,
1861 const bool cancel_default,
1862 std::optional<std::string> message)
1863{
1865 C, op, false, false, title, confirm_text, cancel_default, message);
1866}
1867
1869 wmOperator *op,
1870 const wmEvent * /*event*/)
1871{
1872 return wm_operator_props_popup_ex(C, op, false, false, {}, {});
1873}
1874
1876 wmOperator *op,
1877 const wmEvent * /*event*/)
1878{
1879 return wm_operator_props_popup_ex(C, op, true, true);
1880}
1881
1883{
1884 return wm_operator_props_popup_ex(C, op, false, true);
1885}
1886
1888 wmOperator *op,
1889 int width,
1890 std::optional<std::string> title,
1891 std::optional<std::string> confirm_text,
1892 const bool cancel_default,
1893 std::optional<std::string> message)
1894{
1895 wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
1896 data->op = op;
1897 data->width = int(float(width) * UI_SCALE_FAC * UI_style_get()->widget.points /
1899 data->free_op = true; /* If this runs and gets registered we may want not to free it. */
1900 data->title = title ? std::move(*title) : WM_operatortype_name(op->type, op->ptr);
1901 data->confirm_text = confirm_text ? std::move(*confirm_text) : IFACE_("OK");
1902 data->message = message ? std::move(*message) : std::string();
1903 data->icon = ALERT_ICON_NONE;
1904 data->size = WM_POPUP_SIZE_SMALL;
1905 data->position = (message) ? WM_POPUP_POSITION_CENTER : WM_POPUP_POSITION_MOUSE;
1906 data->cancel_default = cancel_default;
1907 data->mouse_move_quit = false;
1908 data->include_properties = true;
1909
1910 /* The operator is not executed until popup OK button is clicked. */
1913
1915}
1916
1918{
1919 /* `CTX_wm_reports(C)` because operator is on stack, not active in event system. */
1920 if ((op->type->flag & OPTYPE_REGISTER) == 0) {
1922 RPT_ERROR,
1923 "Operator redo '%s' does not have register enabled, incorrect invoke function",
1924 op->type->idname);
1925 return OPERATOR_CANCELLED;
1926 }
1927 if (op->type->poll && op->type->poll(C) == 0) {
1929 CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context", op->type->idname);
1930 return OPERATOR_CANCELLED;
1931 }
1932
1933 /* Operator is stored and kept alive in the window manager. So passing a pointer to the UI is
1934 * fine, it will remain valid. */
1936
1937 return OPERATOR_CANCELLED;
1938}
1939
1941
1942/* -------------------------------------------------------------------- */
1947
1949{
1950 G.debug_value = RNA_int_get(op->ptr, "debug_value");
1953
1954 return OPERATOR_FINISHED;
1955}
1956
1958 wmOperator *op,
1959 const wmEvent * /*event*/)
1960{
1961 RNA_int_set(op->ptr, "debug_value", G.debug_value);
1962 return WM_operator_props_dialog_popup(C, op, 250, IFACE_("Set Debug Value"), IFACE_("Set"));
1963}
1964
1966{
1967 ot->name = "Debug Menu";
1968 ot->idname = "WM_OT_debug_menu";
1969 ot->description = "Open a popup to set the debug level";
1970
1971 ot->invoke = wm_debug_menu_invoke;
1972 ot->exec = wm_debug_menu_exec;
1973 ot->poll = WM_operator_winactive;
1974
1975 ot->prop = RNA_def_int(
1976 ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000);
1977}
1978
1980
1981/* -------------------------------------------------------------------- */
1984
1986{
1987 PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator);
1988
1989 if (!ptr.data) {
1990 BKE_report(op->reports, RPT_ERROR, "No operator in context");
1991 return OPERATOR_CANCELLED;
1992 }
1993
1995 return OPERATOR_FINISHED;
1996}
1997
1998/* Used by operator preset menu. pre-2.65 this was a 'Reset' button. */
2000{
2001 ot->name = "Restore Operator Defaults";
2002 ot->idname = "WM_OT_operator_defaults";
2003 ot->description = "Set the active operator to its default values";
2004
2006
2007 ot->flag = OPTYPE_INTERNAL;
2008}
2009
2011
2012/* -------------------------------------------------------------------- */
2015
2021
2027
2028static char g_search_text[256] = "";
2029
2030static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdata)
2031{
2032 const SearchPopupInit_Data *init_data = static_cast<const SearchPopupInit_Data *>(userdata);
2033
2034 uiBlock *block = UI_block_begin(C, region, "_popup", blender::ui::EmbossType::Emboss);
2037
2038 uiBut *but = uiDefSearchBut(block,
2040 0,
2041 ICON_VIEWZOOM,
2042 sizeof(g_search_text),
2043 0,
2044 0,
2045 init_data->size[0],
2046 UI_UNIT_Y,
2047 "");
2048
2049 if (init_data->search_type == SEARCH_TYPE_OPERATOR) {
2051 }
2052 else if (init_data->search_type == SEARCH_TYPE_MENU) {
2054 }
2055 else if (init_data->search_type == SEARCH_TYPE_SINGLE_MENU) {
2056 UI_but_func_menu_search(but, init_data->single_menu_idname.c_str());
2058 }
2059 else {
2061 }
2062
2064
2065 /* Fake button, it holds space for search items. */
2066 const int height = init_data->size[1] - UI_SEARCHBOX_BOUNDS;
2067 uiDefBut(block,
2069 0,
2070 "",
2071 0,
2072 -height,
2073 init_data->size[0],
2074 height,
2075 nullptr,
2076 0,
2077 0,
2078 std::nullopt);
2079
2080 /* Move it downwards, mouse over button. */
2082
2083 return block;
2084}
2085
2087{
2088 return OPERATOR_FINISHED;
2089}
2090
2092{
2093 /* Exception for launching via space-bar. */
2094 if (event->type == EVT_SPACEKEY) {
2095 bool ok = true;
2096 ScrArea *area = CTX_wm_area(C);
2097 if (area) {
2098 if (area->spacetype == SPACE_CONSOLE) {
2099 /* So we can use the shortcut in the console. */
2100 ok = false;
2101 }
2102 else if (area->spacetype == SPACE_TEXT) {
2103 /* So we can use the space-bar in the text editor. */
2104 ok = false;
2105 }
2106 }
2107 else {
2108 Object *editob = CTX_data_edit_object(C);
2109 if (editob && editob->type == OB_FONT) {
2110 /* So we can use the space-bar for entering text. */
2111 ok = false;
2112 }
2113 }
2114 if (!ok) {
2115 return OPERATOR_PASS_THROUGH;
2116 }
2117 }
2118
2119 SearchType search_type;
2120 if (STREQ(op->type->idname, "WM_OT_search_menu")) {
2121 search_type = SEARCH_TYPE_MENU;
2122 }
2123 else if (STREQ(op->type->idname, "WM_OT_search_single_menu")) {
2124 search_type = SEARCH_TYPE_SINGLE_MENU;
2125 }
2126 else {
2127 search_type = SEARCH_TYPE_OPERATOR;
2128 }
2129
2130 static SearchPopupInit_Data data{};
2131
2132 if (search_type == SEARCH_TYPE_SINGLE_MENU) {
2133 data.single_menu_idname = RNA_string_get(op->ptr, "menu_idname");
2134
2135 std::string buffer = RNA_string_get(op->ptr, "initial_query");
2136 STRNCPY(g_search_text, buffer.c_str());
2137 }
2138 else {
2139 g_search_text[0] = '\0';
2140 }
2141
2142 data.search_type = search_type;
2143 data.size[0] = UI_searchbox_size_x() * 2;
2144 data.size[1] = UI_searchbox_size_y();
2145
2147
2148 return OPERATOR_INTERFACE;
2149}
2150
2152{
2153 ot->name = "Search Menu";
2154 ot->idname = "WM_OT_search_menu";
2155 ot->description = "Pop-up a search over all menus in the current context";
2156
2157 ot->invoke = wm_search_menu_invoke;
2158 ot->exec = wm_search_menu_exec;
2159 ot->poll = WM_operator_winactive;
2160}
2161
2163{
2164 ot->name = "Search Operator";
2165 ot->idname = "WM_OT_search_operator";
2166 ot->description = "Pop-up a search over all available operators in current context";
2167
2168 ot->invoke = wm_search_menu_invoke;
2169 ot->exec = wm_search_menu_exec;
2170 ot->poll = WM_operator_winactive;
2171}
2172
2174{
2175 ot->name = "Search Single Menu";
2176 ot->idname = "WM_OT_search_single_menu";
2177 ot->description = "Pop-up a search for a menu in current context";
2178
2179 ot->invoke = wm_search_menu_invoke;
2180 ot->exec = wm_search_menu_exec;
2181 ot->poll = WM_operator_winactive;
2182
2183 RNA_def_string(ot->srna, "menu_idname", nullptr, 0, "Menu Name", "Menu to search in");
2184 RNA_def_string(ot->srna,
2185 "initial_query",
2186 nullptr,
2187 0,
2188 "Initial Query",
2189 "Query to insert into the search box");
2190}
2191
2193{
2194 char idname[BKE_ST_MAXNAME];
2195 RNA_string_get(op->ptr, "name", idname);
2196
2197 return UI_popup_menu_invoke(C, idname, op->reports);
2198}
2199
2201{
2202 char idname[BKE_ST_MAXNAME];
2203 RNA_string_get(ptr, "name", idname);
2204 MenuType *mt = WM_menutype_find(idname, true);
2205 return (mt) ? CTX_IFACE_(mt->translation_context, mt->label) :
2206 CTX_IFACE_(ot->translation_context, ot->name);
2207}
2208
2210{
2211 ot->name = "Call Menu";
2212 ot->idname = "WM_OT_call_menu";
2213 ot->description = "Open a predefined menu";
2214
2215 ot->exec = wm_call_menu_exec;
2216 ot->poll = WM_operator_winactive;
2217 ot->get_name = wm_call_menu_get_name;
2218
2219 ot->flag = OPTYPE_INTERNAL;
2220
2221 PropertyRNA *prop;
2222
2223 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the menu");
2225 prop,
2227 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2229}
2230
2232{
2233 char idname[BKE_ST_MAXNAME];
2234 RNA_string_get(op->ptr, "name", idname);
2235
2236 return UI_pie_menu_invoke(C, idname, event);
2237}
2238
2240{
2241 char idname[BKE_ST_MAXNAME];
2242 RNA_string_get(op->ptr, "name", idname);
2243
2244 return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate);
2245}
2246
2248{
2249 ot->name = "Call Pie Menu";
2250 ot->idname = "WM_OT_call_menu_pie";
2251 ot->description = "Open a predefined pie menu";
2252
2253 ot->invoke = wm_call_pie_menu_invoke;
2254 ot->exec = wm_call_pie_menu_exec;
2255 ot->poll = WM_operator_winactive;
2256 ot->get_name = wm_call_menu_get_name;
2257
2258 ot->flag = OPTYPE_INTERNAL;
2259
2260 PropertyRNA *prop;
2261
2262 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the pie menu");
2264 prop,
2266 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2268}
2269
2271{
2272 char idname[BKE_ST_MAXNAME];
2273 RNA_string_get(op->ptr, "name", idname);
2274 const bool keep_open = RNA_boolean_get(op->ptr, "keep_open");
2275
2276 return UI_popover_panel_invoke(C, idname, keep_open, op->reports);
2277}
2278
2280{
2281 char idname[BKE_ST_MAXNAME];
2282 RNA_string_get(ptr, "name", idname);
2283 PanelType *pt = WM_paneltype_find(idname, true);
2284 return (pt) ? CTX_IFACE_(pt->translation_context, pt->label) :
2285 CTX_IFACE_(ot->translation_context, ot->name);
2286}
2287
2289{
2290 ot->name = "Call Panel";
2291 ot->idname = "WM_OT_call_panel";
2292 ot->description = "Open a predefined panel";
2293
2294 ot->exec = wm_call_panel_exec;
2295 ot->poll = WM_operator_winactive;
2296 ot->get_name = wm_call_panel_get_name;
2297
2298 ot->flag = OPTYPE_INTERNAL;
2299
2300 PropertyRNA *prop;
2301
2302 prop = RNA_def_string(ot->srna, "name", nullptr, BKE_ST_MAXNAME, "Name", "Name of the menu");
2304 prop,
2306 /* Only a suggestion as menu items may be referenced from add-ons that have been disabled. */
2309 prop = RNA_def_boolean(ot->srna, "keep_open", true, "Keep Open", "");
2311}
2312
2314 wmOperator *op,
2315 const wmEvent * /*event*/)
2316{
2317 std::string asset_shelf_id = RNA_string_get(op->ptr, "name");
2318
2319 if (!blender::ui::asset_shelf_popover_invoke(*C, asset_shelf_id, *op->reports)) {
2321 }
2322
2323 return OPERATOR_INTERFACE;
2324}
2325
2326/* Needs to be defined at WM level to be globally accessible. */
2328{
2329 /* identifiers */
2330 ot->name = "Call Asset Shelf Popover";
2331 ot->idname = "WM_OT_call_asset_shelf_popover";
2332 ot->description = "Open a predefined asset shelf in a popup";
2333
2334 /* API callbacks. */
2336
2337 ot->flag = OPTYPE_INTERNAL;
2338
2339 RNA_def_string(ot->srna,
2340 "name",
2341 nullptr,
2342 0,
2343 "Asset Shelf Name",
2344 "Identifier of the asset shelf to display");
2345}
2346
2348
2349/* -------------------------------------------------------------------- */
2352
2358{
2359 wmWindow *win = CTX_wm_window(C);
2360 bScreen *screen;
2361
2362 if (win == nullptr) {
2363 return false;
2364 }
2365 if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL))) {
2366 return false;
2367 }
2368 if (G.background) {
2369 return false;
2370 }
2371
2372 return true;
2373}
2374
2376{
2377 wmWindow *win = CTX_wm_window(C);
2378 bScreen *screen;
2379
2380 if (win == nullptr) {
2381 return false;
2382 }
2383 if (!((screen = WM_window_get_active_screen(win)) && (screen->state != SCREENFULL))) {
2384 return false;
2385 }
2386 if (G.background) {
2387 return false;
2388 }
2389
2390 return true;
2391}
2392
2393/* Included for script-access. */
2395{
2396 ot->name = "Close Window";
2397 ot->idname = "WM_OT_window_close";
2398 ot->description = "Close the current window";
2399
2400 ot->exec = wm_window_close_exec;
2401 ot->poll = WM_operator_winactive;
2402}
2403
2405{
2406 ot->name = "New Window";
2407 ot->idname = "WM_OT_window_new";
2408 ot->description = "Create a new window";
2409
2410 ot->exec = wm_window_new_exec;
2412}
2413
2415{
2416 ot->name = "New Main Window";
2417 ot->idname = "WM_OT_window_new_main";
2418 ot->description = "Create a new main window with its own workspace and scene selection";
2419
2422}
2423
2425{
2426 ot->name = "Toggle Window Fullscreen";
2427 ot->idname = "WM_OT_window_fullscreen_toggle";
2428 ot->description = "Toggle the current window full-screen";
2429
2431 ot->poll = WM_operator_winactive;
2432}
2433
2439
2441 wmOperator * /*op*/,
2442 const wmEvent * /*event*/)
2443{
2444 if (U.uiflag & USER_SAVE_PROMPT) {
2446 }
2447 else {
2449 }
2450 return OPERATOR_FINISHED;
2451}
2452
2454{
2455 ot->name = "Quit Blender";
2456 ot->idname = "WM_OT_quit_blender";
2457 ot->description = "Quit Blender";
2458
2459 ot->invoke = wm_exit_blender_invoke;
2460 ot->exec = wm_exit_blender_exec;
2461}
2462
2464
2465/* -------------------------------------------------------------------- */
2468
2469#if defined(WIN32)
2470
2471static wmOperatorStatus wm_console_toggle_exec(bContext * /*C*/, wmOperator * /*op*/)
2472{
2474 return OPERATOR_FINISHED;
2475}
2476
2477static void WM_OT_console_toggle(wmOperatorType *ot)
2478{
2479 /* XXX Have to mark these for xgettext, as under linux they do not exists... */
2480 ot->name = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Toggle System Console");
2481 ot->idname = "WM_OT_console_toggle";
2482 ot->description = N_("Toggle System Console");
2483
2484 ot->exec = wm_console_toggle_exec;
2485 ot->poll = WM_operator_winactive;
2486}
2487
2488#endif
2489
2491
2492/* -------------------------------------------------------------------- */
2500
2502 short region_type,
2503 bool (*poll)(bContext *C),
2504 wmPaintCursorDraw draw,
2505 void *customdata)
2506{
2507 wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
2508
2509 wmPaintCursor *pc = MEM_callocN<wmPaintCursor>("paint cursor");
2510
2511 BLI_addtail(&wm->runtime->paintcursors, pc);
2512
2513 pc->customdata = customdata;
2514 pc->poll = poll;
2515 pc->draw = draw;
2516
2517 pc->space_type = space_type;
2518 pc->region_type = region_type;
2519
2520 return pc;
2521}
2522
2524{
2525 wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
2526 LISTBASE_FOREACH (wmPaintCursor *, pc, &wm->runtime->paintcursors) {
2527 if (pc == handle) {
2528 BLI_remlink(&wm->runtime->paintcursors, pc);
2529 MEM_freeN(pc);
2530 return true;
2531 }
2532 }
2533 return false;
2534}
2535
2536void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void (*free)(void *))
2537{
2538 LISTBASE_FOREACH_MUTABLE (wmPaintCursor *, pc, &wm->runtime->paintcursors) {
2539 if (pc->draw == draw_fn) {
2540 if (free) {
2541 free(pc->customdata);
2542 }
2543 BLI_remlink(&wm->runtime->paintcursors, pc);
2544 MEM_freeN(pc);
2545 }
2546 }
2547}
2548
2550
2551/* -------------------------------------------------------------------- */
2554
2555#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_SCALE_FAC)
2556#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * UI_SCALE_FAC)
2557#define WM_RADIAL_CONTROL_DISPLAY_WIDTH \
2558 (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE)
2559#define WM_RADIAL_MAX_STR 10
2560
2566 PropertyRNA *prop = nullptr;
2574 float initial_value = 0.0f;
2575 float current_value = 0.0f;
2576 float min_value = 0.0f;
2577 float max_value = 0.0f;
2578 /* Original screen space coordinates that the operator started on. */
2579 int initial_co[2] = {};
2580 /* Modified value of #initial_co to simplify calculating new values. */
2582 int slow_mouse[2] = {};
2583 bool slow_mode = false;
2584 Dial *dial = nullptr;
2587 bool use_secondary_tex = false;
2588 void *cursor = nullptr;
2590 int init_event = 0;
2591};
2592
2594{
2595 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
2596 char msg[UI_MAX_DRAW_STR];
2597 ScrArea *area = CTX_wm_area(C);
2598 Scene *scene = CTX_data_scene(C);
2599
2600 if (hasNumInput(&rc->num_input)) {
2601 char num_str[NUM_STR_REP_LEN];
2602 outputNumInput(&rc->num_input, num_str, scene->unit);
2603 SNPRINTF(msg, "%s: %s", RNA_property_ui_name(rc->prop), num_str);
2604 }
2605 else {
2606 const char *ui_name = RNA_property_ui_name(rc->prop);
2607 switch (rc->subtype) {
2608 case PROP_NONE:
2609 case PROP_DISTANCE:
2611 SNPRINTF(msg, "%s: %0.4f", ui_name, rc->current_value);
2612 break;
2613 case PROP_PIXEL:
2615 SNPRINTF(msg, "%s: %d", ui_name, int(rc->current_value)); /* XXX: round to nearest? */
2616 break;
2617 case PROP_PERCENTAGE:
2618 SNPRINTF(msg, "%s: %3.1f%%", ui_name, rc->current_value);
2619 break;
2620 case PROP_FACTOR:
2621 SNPRINTF(msg, "%s: %1.3f", ui_name, rc->current_value);
2622 break;
2623 case PROP_ANGLE:
2624 SNPRINTF(msg, "%s: %3.2f", ui_name, RAD2DEGF(rc->current_value));
2625 break;
2626 default:
2627 STRNCPY(msg, ui_name); /* XXX: No value? */
2628 break;
2629 }
2630 }
2631
2632 ED_area_status_text(area, msg);
2633}
2634
2636{
2637 float d[2] = {0, 0};
2638 float zoom[2] = {1, 1};
2639
2641 copy_v2_v2_int(rc->initial_co, event->xy);
2642
2643 switch (rc->subtype) {
2644 case PROP_NONE:
2645 case PROP_DISTANCE:
2647 case PROP_PIXEL:
2649 d[0] = rc->initial_value;
2650 break;
2651 case PROP_PERCENTAGE:
2652 d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH +
2654 break;
2655 case PROP_FACTOR:
2658 break;
2659 case PROP_ANGLE:
2662 break;
2663 default:
2664 return;
2665 }
2666
2667 if (rc->zoom_prop) {
2669 d[0] *= zoom[0];
2670 d[1] *= zoom[1];
2671 }
2672
2673 rc->initial_radial_center[0] -= d[0];
2674 rc->initial_radial_center[1] -= d[1];
2675}
2676
2678{
2679 ImBuf *ibuf;
2680
2681 switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) {
2682 case ID_BR:
2683 if ((ibuf = BKE_brush_gen_radial_control_imbuf(static_cast<Brush *>(rc->image_id_ptr.data),
2685 !ELEM(rc->subtype,
2686 PROP_NONE,
2687 PROP_PIXEL,
2691 {
2692
2693 rc->texture = GPU_texture_create_2d("radial_control",
2694 ibuf->x,
2695 ibuf->y,
2696 1,
2697 blender::gpu::TextureFormat::UNORM_8,
2699 ibuf->float_buffer.data);
2700
2702 GPU_texture_swizzle_set(rc->texture, "111r");
2703
2705 MEM_freeN(ibuf);
2706 }
2707 break;
2708 default:
2709 break;
2710 }
2711}
2712
2713static void radial_control_paint_tex(RadialControl *rc, float radius, float alpha)
2714{
2715
2716 /* Set fill color. */
2717 float col[3] = {0, 0, 0};
2718 if (rc->fill_col_prop) {
2719 PointerRNA *fill_ptr;
2720 PropertyRNA *fill_prop;
2721
2722 if (rc->fill_col_override_prop &&
2724 {
2725 fill_ptr = &rc->fill_col_override_ptr;
2726 fill_prop = rc->fill_col_override_prop;
2727 }
2728 else {
2729 fill_ptr = &rc->fill_col_ptr;
2730 fill_prop = rc->fill_col_prop;
2731 }
2732
2733 RNA_property_float_get_array(fill_ptr, fill_prop, col);
2734 }
2735
2737 uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
2738
2739 if (rc->texture) {
2740 uint texCoord = GPU_vertformat_attr_add(
2741 format, "texCoord", blender::gpu::VertAttrType::SFLOAT_32_32);
2742
2743 /* Set up rotation if available. */
2744 if (rc->rot_prop) {
2745 float rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop);
2748 }
2749
2751
2753 immBindTexture("image", rc->texture);
2754
2755 /* Draw textured quad. */
2757
2758 immAttr2f(texCoord, 0, 0);
2759 immVertex2f(pos, -radius, -radius);
2760
2761 immAttr2f(texCoord, 1, 0);
2762 immVertex2f(pos, radius, -radius);
2763
2764 immAttr2f(texCoord, 1, 1);
2765 immVertex2f(pos, radius, radius);
2766
2767 immAttr2f(texCoord, 0, 1);
2768 immVertex2f(pos, -radius, radius);
2769
2770 immEnd();
2771
2773
2774 /* Undo rotation. */
2775 if (rc->rot_prop) {
2777 }
2778 }
2779 else {
2780 /* Flat color if no texture available. */
2783 imm_draw_circle_fill_2d(pos, 0.0f, 0.0f, radius, 40);
2784 }
2785
2787}
2788
2789static void radial_control_paint_curve(uint pos, Brush *br, float radius, int line_segments)
2790{
2791 GPU_line_width(2.0f);
2792 immUniformColor4f(0.8f, 0.8f, 0.8f, 0.85f);
2793 float step = (radius * 2.0f) / float(line_segments);
2795 immBegin(GPU_PRIM_LINES, line_segments * 2);
2796 for (int i = 0; i < line_segments; i++) {
2797 float h1 = BKE_brush_curve_strength_clamped(br, fabsf((i * step) - radius), radius);
2798 immVertex2f(pos, -radius + (i * step), h1 * radius);
2799 float h2 = BKE_brush_curve_strength_clamped(br, fabsf(((i + 1) * step) - radius), radius);
2800 immVertex2f(pos, -radius + ((i + 1) * step), h2 * radius);
2801 }
2802 immEnd();
2803}
2804
2806 const blender::int2 & /*xy*/,
2807 const blender::float2 & /*tilt*/,
2808 void *customdata)
2809{
2810 RadialControl *rc = static_cast<RadialControl *>(customdata);
2811 const uiStyle *style = UI_style_get();
2812 const uiFontStyle *fstyle = &style->widget;
2813 const int fontid = fstyle->uifont_id;
2814 short fstyle_points = fstyle->points;
2815 char str[WM_RADIAL_MAX_STR];
2816 short strdrawlen = 0;
2817 float strwidth, strheight;
2818 float r1 = 0.0f, r2 = 0.0f, rmin = 0.0, tex_radius, alpha;
2819 float zoom[2], col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2820 float text_color[4];
2821
2822 switch (rc->subtype) {
2823 case PROP_NONE:
2824 case PROP_DISTANCE:
2825 case PROP_PIXEL:
2826 r1 = rc->current_value;
2827 r2 = rc->initial_value;
2828 tex_radius = r1;
2829 alpha = 0.75;
2830 break;
2833 r1 = rc->current_value / 2.0f;
2834 r2 = rc->initial_value / 2.0f;
2835 tex_radius = r1;
2836 alpha = 0.75;
2837 break;
2838 case PROP_PERCENTAGE:
2841 r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2843 SNPRINTF(str, "%3.1f%%", rc->current_value);
2844 strdrawlen = BLI_strlen_utf8(str);
2845 tex_radius = r1;
2846 alpha = 0.75;
2847 break;
2848 case PROP_FACTOR:
2851 r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2853 alpha = rc->current_value / 2.0f + 0.5f;
2854 SNPRINTF(str, "%1.3f", rc->current_value);
2855 strdrawlen = BLI_strlen_utf8(str);
2856 break;
2857 case PROP_ANGLE:
2858 r1 = r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE;
2859 alpha = 0.75;
2861 SNPRINTF(str, "%3.2f", RAD2DEGF(rc->current_value));
2862 strdrawlen = BLI_strlen_utf8(str);
2863 break;
2864 default:
2865 tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* NOTE: this is a dummy value. */
2866 alpha = 0.75;
2867 break;
2868 }
2869
2870 int x, y;
2871 if (rc->subtype == PROP_ANGLE) {
2872 /* Use the initial mouse position to draw the rotation preview. This avoids starting the
2873 * rotation in a random direction. */
2874 x = rc->initial_radial_center[0];
2875 y = rc->initial_radial_center[1];
2876 }
2877 else {
2878 /* Keep cursor in the original place. */
2879 x = rc->initial_co[0];
2880 y = rc->initial_co[1];
2881 }
2882 GPU_matrix_translate_2f(float(x), float(y));
2883
2885 GPU_line_smooth(true);
2886
2887 /* Apply zoom if available. */
2888 if (rc->zoom_prop) {
2891 }
2892
2893 /* Draw rotated texture. */
2894 radial_control_paint_tex(rc, tex_radius, alpha);
2895
2896 /* Set line color. */
2897 if (rc->col_prop) {
2899 }
2900
2902 uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
2903
2905
2906 if (rc->subtype == PROP_ANGLE) {
2908
2909 /* Draw original angle line. */
2910 GPU_matrix_rotate_3f(RAD2DEGF(rc->initial_value), 0.0f, 0.0f, 1.0f);
2914 immEnd();
2915
2916 /* Draw new angle line. */
2917 GPU_matrix_rotate_3f(RAD2DEGF(rc->current_value - rc->initial_value), 0.0f, 0.0f, 1.0f);
2921 immEnd();
2922
2924 }
2925
2926 /* Draw circles on top. */
2927 GPU_line_width(2.0f);
2929 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 80);
2930
2931 GPU_line_width(1.0f);
2933 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 80);
2934 if (rmin > 0.0f) {
2935 /* Inner fill circle to increase the contrast of the value. */
2936 const float black[3] = {0.0f};
2937 immUniformColor3fvAlpha(black, 0.2f);
2938 imm_draw_circle_fill_2d(pos, 0.0, 0.0f, rmin, 80);
2939
2941 imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 80);
2942 }
2943
2944 /* Draw curve falloff preview. */
2946 Brush *br = static_cast<Brush *>(rc->image_id_ptr.data);
2947 if (br) {
2948 radial_control_paint_curve(pos, br, r2, 120);
2949 }
2950 }
2951
2953
2954 BLF_size(fontid, 1.75f * fstyle_points * UI_SCALE_FAC);
2955 UI_GetThemeColor4fv(TH_TEXT_HI, text_color);
2956 BLF_color4fv(fontid, text_color);
2957
2958 /* Draw value. */
2959 BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight);
2960 BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
2961 BLF_draw(fontid, str, strdrawlen);
2962
2964 GPU_line_smooth(false);
2965}
2966
2972
2979 wmOperator *op,
2980 const char *name,
2981 PointerRNA *r_ptr,
2982 PropertyRNA **r_prop,
2983 int req_length,
2984 RCPropFlags flags)
2985{
2986 PropertyRNA *unused_prop;
2987
2988 /* Check flags. */
2989 if ((flags & RC_PROP_REQUIRE_BOOL) && (flags & RC_PROP_REQUIRE_FLOAT)) {
2990 BKE_report(op->reports, RPT_ERROR, "Property cannot be both boolean and float");
2991 return 0;
2992 }
2993
2994 /* Get an rna string path from the operator's properties. */
2995 std::string str = RNA_string_get(op->ptr, name);
2996 if (str.empty()) {
2997 if (r_prop) {
2998 *r_prop = nullptr;
2999 }
3000 return 1;
3001 }
3002
3003 if (!r_prop) {
3004 r_prop = &unused_prop;
3005 }
3006
3007 /* Get rna from path. */
3008 if (!RNA_path_resolve(ctx_ptr, str.c_str(), r_ptr, r_prop)) {
3009 if (flags & RC_PROP_ALLOW_MISSING) {
3010 return 1;
3011 }
3012 BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name);
3013 return 0;
3014 }
3015
3016 /* Check property type. */
3018 PropertyType prop_type = RNA_property_type(*r_prop);
3019
3020 if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) ||
3021 ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT)))
3022 {
3023 BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name);
3024 return 0;
3025 }
3026 }
3027
3028 /* Check property's array length. */
3029 int len;
3030 if (*r_prop && (len = RNA_property_array_length(r_ptr, *r_prop)) != req_length) {
3031 BKE_reportf(op->reports,
3032 RPT_ERROR,
3033 "Property from path '%s' has length %d instead of %d",
3034 name,
3035 len,
3036 req_length);
3037 return 0;
3038 }
3039
3040 /* Success. */
3041 return 1;
3042}
3043
3044/* Initialize the rna pointers and properties using rna paths. */
3046{
3047 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3048
3049 PointerRNA ctx_ptr = RNA_pointer_create_discrete(nullptr, &RNA_Context, C);
3050
3051 /* Check if we use primary or secondary path. */
3052 PointerRNA use_secondary_ptr;
3053 PropertyRNA *use_secondary_prop = nullptr;
3054 if (!radial_control_get_path(&ctx_ptr,
3055 op,
3056 "use_secondary",
3057 &use_secondary_ptr,
3058 &use_secondary_prop,
3059 0,
3061 {
3062 return 0;
3063 }
3064
3065 const char *data_path;
3066 if (use_secondary_prop && RNA_property_boolean_get(&use_secondary_ptr, use_secondary_prop)) {
3067 data_path = "data_path_secondary";
3068 }
3069 else {
3070 data_path = "data_path_primary";
3071 }
3072
3073 if (!radial_control_get_path(&ctx_ptr, op, data_path, &rc->ptr, &rc->prop, 0, RCPropFlags(0))) {
3074 return 0;
3075 }
3076
3077 /* Data path is required. */
3078 if (!rc->prop) {
3079 return 0;
3080 }
3081
3083 &ctx_ptr, op, "rotation_path", &rc->rot_ptr, &rc->rot_prop, 0, RC_PROP_REQUIRE_FLOAT))
3084 {
3085 return 0;
3086 }
3087
3089 &ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 4, RC_PROP_REQUIRE_FLOAT))
3090 {
3091 return 0;
3092 }
3093
3094 if (!radial_control_get_path(&ctx_ptr,
3095 op,
3096 "fill_color_path",
3097 &rc->fill_col_ptr,
3098 &rc->fill_col_prop,
3099 3,
3101 {
3102 return 0;
3103 }
3104
3105 if (!radial_control_get_path(&ctx_ptr,
3106 op,
3107 "fill_color_override_path",
3110 3,
3112 {
3113 return 0;
3114 }
3115 if (!radial_control_get_path(&ctx_ptr,
3116 op,
3117 "fill_color_override_test_path",
3120 0,
3122 {
3123 return 0;
3124 }
3125
3126 /* Slightly ugly; allow this property to not resolve correctly.
3127 * Needed because 3d texture paint shares the same key-map as 2d image paint. */
3128 if (!radial_control_get_path(&ctx_ptr,
3129 op,
3130 "zoom_path",
3131 &rc->zoom_ptr,
3132 &rc->zoom_prop,
3133 2,
3135 {
3136 return 0;
3137 }
3138
3140 &ctx_ptr, op, "image_id", &rc->image_id_ptr, nullptr, 0, RCPropFlags(0)))
3141 {
3142 return 0;
3143 }
3144 if (rc->image_id_ptr.data) {
3145 /* Extra check, pointer must be to an ID. */
3147 BKE_report(op->reports, RPT_ERROR, "Pointer from path image_id is not an ID");
3148 return 0;
3149 }
3150 }
3151
3152 rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex");
3153
3154 return 1;
3155}
3156
3158{
3159 op->customdata = MEM_new<RadialControl>(__func__);
3160 if (!op->customdata) {
3161 return OPERATOR_CANCELLED;
3162 }
3163 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3164
3165 if (!radial_control_get_properties(C, op)) {
3166 MEM_delete(rc);
3167 return OPERATOR_CANCELLED;
3168 }
3169
3170 /* Get type, initial, min, and max values of the property. */
3171 switch (rc->type = RNA_property_type(rc->prop)) {
3172 case PROP_INT: {
3173 int value, min, max, step;
3174
3175 value = RNA_property_int_get(&rc->ptr, rc->prop);
3176 RNA_property_int_ui_range(&rc->ptr, rc->prop, &min, &max, &step);
3177
3178 rc->initial_value = value;
3179 rc->min_value = min_ii(value, min);
3180 rc->max_value = max_ii(value, max);
3181 break;
3182 }
3183 case PROP_FLOAT: {
3184 float value, min, max, step, precision;
3185
3186 value = RNA_property_float_get(&rc->ptr, rc->prop);
3187 RNA_property_float_ui_range(&rc->ptr, rc->prop, &min, &max, &step, &precision);
3188
3189 rc->initial_value = value;
3190 rc->min_value = min_ff(value, min);
3191 rc->max_value = max_ff(value, max);
3192 break;
3193 }
3194 default:
3195 BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float");
3196 MEM_delete(rc);
3197 return OPERATOR_CANCELLED;
3198 }
3199
3200 /* Initialize numerical input. */
3201 initNumInput(&rc->num_input);
3202 rc->num_input.idx_max = 0;
3206
3207 /* Get subtype of property. */
3209 if (!ELEM(rc->subtype,
3210 PROP_NONE,
3215 PROP_ANGLE,
3216 PROP_PIXEL,
3218 {
3219 BKE_report(op->reports,
3220 RPT_ERROR,
3221 "Property must be a none, distance, factor, percentage, angle, or pixel");
3222 MEM_delete(rc);
3223 return OPERATOR_CANCELLED;
3224 }
3225
3226 rc->current_value = rc->initial_value;
3229
3231
3232 /* Temporarily disable other paint cursors. */
3234 rc->orig_paintcursors = wm->runtime->paintcursors;
3235 BLI_listbase_clear(&wm->runtime->paintcursors);
3236
3237 /* Add radial control paint cursor. */
3240
3242
3244}
3245
3246static void radial_control_set_value(RadialControl *rc, float val)
3247{
3248 switch (rc->type) {
3249 case PROP_INT:
3250 RNA_property_int_set(&rc->ptr, rc->prop, val);
3251 break;
3252 case PROP_FLOAT:
3253 RNA_property_float_set(&rc->ptr, rc->prop, val);
3254 break;
3255 default:
3256 break;
3257 }
3258}
3259
3261{
3262 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3264 ScrArea *area = CTX_wm_area(C);
3265
3266 if (rc->dial) {
3267 BLI_dial_free(rc->dial);
3268 rc->dial = nullptr;
3269 }
3270
3271 ED_area_status_text(area, nullptr);
3272
3273 WM_paint_cursor_end(static_cast<wmPaintCursor *>(rc->cursor));
3274
3275 /* Restore original paint cursors. */
3276 wm->runtime->paintcursors = rc->orig_paintcursors;
3277
3278 /* Not sure if this is a good notifier to use;
3279 * intended purpose is to update the UI so that the
3280 * new value is displayed in sliders/number-fields. */
3282
3283 if (rc->texture != nullptr) {
3285 }
3286
3287 MEM_delete(rc);
3288}
3289
3291{
3292 RadialControl *rc = static_cast<RadialControl *>(op->customdata);
3293 float new_value, dist = 0.0f, zoom[2];
3294 float delta[2];
3296 float angle_precision = 0.0f;
3297 const bool has_numInput = hasNumInput(&rc->num_input);
3298 bool handled = false;
3299 float numValue;
3300 /* TODO: fix hard-coded events. */
3301
3302 bool snap = (event->modifier & KM_CTRL) != 0;
3303
3304 /* Modal numinput active, try to handle numeric inputs first... */
3305 if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) {
3306 handled = true;
3307 applyNumInput(&rc->num_input, &numValue);
3308
3309 if (rc->subtype == PROP_ANGLE) {
3310 numValue = fmod(numValue, 2.0f * float(M_PI));
3311 if (numValue < 0.0f) {
3312 numValue += 2.0f * float(M_PI);
3313 }
3314 }
3315
3316 CLAMP(numValue, rc->min_value, rc->max_value);
3317 new_value = numValue;
3318
3319 radial_control_set_value(rc, new_value);
3320 rc->current_value = new_value;
3323 }
3324
3325 handled = false;
3326 switch (event->type) {
3327 case EVT_ESCKEY:
3328 case RIGHTMOUSE:
3329 /* Canceled; restore original value. */
3330 if (rc->init_event != RIGHTMOUSE) {
3333 }
3334 break;
3335
3336 case LEFTMOUSE:
3337 case EVT_PADENTER:
3338 case EVT_RETKEY:
3339 /* Done; value already set. */
3340 /* Keep the RNA update separate from setting the value, for some properties this could lead
3341 * to a continues flickering due to invalidating the overlay texture. */
3342 RNA_property_update(C, &rc->ptr, rc->prop);
3344 break;
3345
3346 case MOUSEMOVE:
3347 if (!has_numInput) {
3348 if (rc->slow_mode) {
3349 if (rc->subtype == PROP_ANGLE) {
3350 /* Calculate the initial angle here first. */
3351 delta[0] = rc->initial_radial_center[0] - rc->slow_mouse[0];
3352 delta[1] = rc->initial_radial_center[1] - rc->slow_mouse[1];
3353
3354 /* Precision angle gets calculated from dial and gets added later. */
3355 angle_precision = -0.1f * BLI_dial_angle(rc->dial,
3356 blender::float2{float(event->xy[0]),
3357 float(event->xy[1])});
3358 }
3359 else {
3360 delta[0] = rc->initial_radial_center[0] - rc->slow_mouse[0];
3361 delta[1] = 0.0f;
3362
3363 if (rc->zoom_prop) {
3365 delta[0] /= zoom[0];
3366 }
3367
3368 dist = len_v2(delta);
3369
3370 delta[0] = event->xy[0] - rc->slow_mouse[0];
3371
3372 if (rc->zoom_prop) {
3373 delta[0] /= zoom[0];
3374 }
3375
3376 dist = dist + 0.1f * (delta[0]);
3377 }
3378 }
3379 else {
3380 delta[0] = float(rc->initial_radial_center[0] - event->xy[0]);
3381 delta[1] = float(rc->initial_radial_center[1] - event->xy[1]);
3382 if (rc->zoom_prop) {
3384 delta[0] /= zoom[0];
3385 delta[1] /= zoom[1];
3386 }
3387 if (rc->subtype == PROP_ANGLE) {
3388 dist = len_v2(delta);
3389 }
3390 else {
3391 dist = clamp_f(-delta[0], 0.0f, FLT_MAX);
3392 }
3393 }
3394
3395 /* Calculate new value and apply snapping. */
3396 switch (rc->subtype) {
3397 case PROP_NONE:
3398 case PROP_DISTANCE:
3400 case PROP_PIXEL:
3402 new_value = dist;
3403 if (snap) {
3404 new_value = (int(new_value) + 5) / 10 * 10;
3405 }
3406 break;
3407 case PROP_PERCENTAGE:
3408 new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) /
3410 100.0f;
3411 if (snap) {
3412 new_value = int(new_value + 2.5f) / 5 * 5;
3413 }
3414 break;
3415 case PROP_FACTOR:
3417 if (snap) {
3418 new_value = (int(ceil(new_value * 10.0f)) * 10.0f) / 100.0f;
3419 }
3420 /* Invert new value to increase the factor moving the mouse to the right. */
3421 new_value = 1 - new_value;
3422 break;
3423 case PROP_ANGLE:
3424 new_value = atan2f(delta[1], delta[0]) + float(M_PI) + angle_precision;
3425 new_value = fmod(new_value, 2.0f * float(M_PI));
3426 if (new_value < 0.0f) {
3427 new_value += 2.0f * float(M_PI);
3428 }
3429 if (snap) {
3430 new_value = DEG2RADF((int(RAD2DEGF(new_value)) + 5) / 10 * 10);
3431 }
3432 break;
3433 default:
3434 new_value = dist; /* NOTE(@ideasman42): Dummy value, should this ever happen? */
3435 break;
3436 }
3437
3438 /* Clamp and update. */
3439 CLAMP(new_value, rc->min_value, rc->max_value);
3440 radial_control_set_value(rc, new_value);
3441 rc->current_value = new_value;
3442 handled = true;
3443 break;
3444 }
3445 break;
3446
3447 case EVT_LEFTSHIFTKEY:
3448 case EVT_RIGHTSHIFTKEY: {
3449 if (event->val == KM_PRESS) {
3450 rc->slow_mouse[0] = event->xy[0];
3451 rc->slow_mouse[1] = event->xy[1];
3452 rc->slow_mode = true;
3453 if (rc->subtype == PROP_ANGLE) {
3454 const float initial_position[2] = {float(rc->initial_radial_center[0]),
3456 const float current_position[2] = {float(rc->slow_mouse[0]), float(rc->slow_mouse[1])};
3457 rc->dial = BLI_dial_init(initial_position, 0.0f);
3458 /* Immediately set the position to get a an initial direction. */
3459 BLI_dial_angle(rc->dial, current_position);
3460 }
3461 handled = true;
3462 }
3463 if (event->val == KM_RELEASE) {
3464 rc->slow_mode = false;
3465 handled = true;
3466 if (rc->dial) {
3467 BLI_dial_free(rc->dial);
3468 rc->dial = nullptr;
3469 }
3470 }
3471 break;
3472 }
3473 default: {
3474 break;
3475 }
3476 }
3477
3478 /* Modal numinput inactive, try to handle numeric inputs last... */
3479 if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) {
3480 applyNumInput(&rc->num_input, &numValue);
3481
3482 if (rc->subtype == PROP_ANGLE) {
3483 numValue = fmod(numValue, 2.0f * float(M_PI));
3484 if (numValue < 0.0f) {
3485 numValue += 2.0f * float(M_PI);
3486 }
3487 }
3488
3489 CLAMP(numValue, rc->min_value, rc->max_value);
3490 new_value = numValue;
3491
3492 radial_control_set_value(rc, new_value);
3493
3494 rc->current_value = new_value;
3497 }
3498
3499 if (!handled && (event->val == KM_RELEASE) && (rc->init_event == event->type) &&
3500 RNA_boolean_get(op->ptr, "release_confirm"))
3501 {
3502 /* Keep the RNA update separate from setting the value, for some properties this could lead to
3503 * a continues flickering due to invalidating the overlay texture. */
3504 RNA_property_update(C, &rc->ptr, rc->prop);
3506 }
3507
3510
3511 if (ret & OPERATOR_FINISHED) {
3513 if (wm->op_undo_depth == 0) {
3514 ID *id = rc->ptr.owner_id;
3516 ED_undo_push(C, op->type->name);
3517 }
3518 }
3519 }
3520
3521 if (ret != OPERATOR_RUNNING_MODAL) {
3523 }
3524
3525 return ret;
3526}
3527
3529{
3530 ot->name = "Radial Control";
3531 ot->idname = "WM_OT_radial_control";
3532 ot->description = "Set some size property (e.g. brush size) with mouse wheel";
3533
3534 ot->invoke = radial_control_invoke;
3535 ot->modal = radial_control_modal;
3536 ot->cancel = radial_control_cancel;
3537
3539
3540 /* All paths relative to the context. */
3541 PropertyRNA *prop;
3542 prop = RNA_def_string(ot->srna,
3543 "data_path_primary",
3544 nullptr,
3545 0,
3546 "Primary Data Path",
3547 "Primary path of property to be set by the radial control");
3549
3550 prop = RNA_def_string(ot->srna,
3551 "data_path_secondary",
3552 nullptr,
3553 0,
3554 "Secondary Data Path",
3555 "Secondary path of property to be set by the radial control");
3557
3558 prop = RNA_def_string(ot->srna,
3559 "use_secondary",
3560 nullptr,
3561 0,
3562 "Use Secondary",
3563 "Path of property to select between the primary and secondary data paths");
3565
3566 prop = RNA_def_string(ot->srna,
3567 "rotation_path",
3568 nullptr,
3569 0,
3570 "Rotation Path",
3571 "Path of property used to rotate the texture display");
3573
3574 prop = RNA_def_string(ot->srna,
3575 "color_path",
3576 nullptr,
3577 0,
3578 "Color Path",
3579 "Path of property used to set the color of the control");
3581
3582 prop = RNA_def_string(ot->srna,
3583 "fill_color_path",
3584 nullptr,
3585 0,
3586 "Fill Color Path",
3587 "Path of property used to set the fill color of the control");
3589
3590 prop = RNA_def_string(
3591 ot->srna, "fill_color_override_path", nullptr, 0, "Fill Color Override Path", "");
3593 prop = RNA_def_string(
3594 ot->srna, "fill_color_override_test_path", nullptr, 0, "Fill Color Override Test", "");
3596
3597 prop = RNA_def_string(ot->srna,
3598 "zoom_path",
3599 nullptr,
3600 0,
3601 "Zoom Path",
3602 "Path of property used to set the zoom level for the control");
3604
3605 prop = RNA_def_string(ot->srna,
3606 "image_id",
3607 nullptr,
3608 0,
3609 "Image ID",
3610 "Path of ID that is used to generate an image for the control");
3612
3613 prop = RNA_def_boolean(
3614 ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
3616
3617 prop = RNA_def_boolean(
3618 ot->srna, "release_confirm", false, "Confirm On Release", "Finish operation on key release");
3620}
3621
3623
3624/* -------------------------------------------------------------------- */
3629
3630/* Uses no type defines, fully local testing function anyway. */
3631
3633{
3634 wmWindow *win = CTX_wm_window(C);
3635 bScreen *screen = CTX_wm_screen(C);
3636
3637 CTX_wm_region_popup_set(C, nullptr);
3638
3639 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
3640 ED_area_tag_redraw(area);
3641 }
3643
3644 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3645}
3646
3647enum {
3655};
3656
3658 {eRTDrawRegion, "DRAW", 0, "Draw Region", "Draw region"},
3659 {eRTDrawRegionSwap, "DRAW_SWAP", 0, "Draw Region & Swap", "Draw region and swap"},
3660 {eRTDrawWindow, "DRAW_WIN", 0, "Draw Window", "Draw window"},
3661 {eRTDrawWindowSwap, "DRAW_WIN_SWAP", 0, "Draw Window & Swap", "Draw window and swap"},
3662 {eRTAnimationStep, "ANIM_STEP", 0, "Animation Step", "Animation steps"},
3663 {eRTAnimationPlay, "ANIM_PLAY", 0, "Animation Play", "Animation playback"},
3664 {eRTUndo, "UNDO", 0, "Undo/Redo", "Undo and redo"},
3665 {0, nullptr, 0, nullptr, nullptr},
3666};
3667
3669 Scene *scene,
3670 Depsgraph *depsgraph,
3671 wmWindow *win,
3672 ScrArea *area,
3673 ARegion *region,
3674 const int type,
3675 const int cfra,
3676 const int steps_done,
3677 const int steps_total)
3678{
3679 if (type == eRTDrawRegion) {
3680 if (region) {
3681 wm_draw_region_test(C, area, region);
3682 }
3683 }
3684 else if (type == eRTDrawRegionSwap) {
3685 CTX_wm_region_popup_set(C, nullptr);
3686
3687 ED_region_tag_redraw(region);
3689
3690 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3691 }
3692 else if (type == eRTDrawWindow) {
3693 bScreen *screen = WM_window_get_active_screen(win);
3694
3695 CTX_wm_region_popup_set(C, nullptr);
3696
3697 LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
3698 CTX_wm_area_set(C, area_iter);
3699 LISTBASE_FOREACH (ARegion *, region_iter, &area_iter->regionbase) {
3700 if (!region_iter->runtime->visible) {
3701 continue;
3702 }
3703 CTX_wm_region_set(C, region_iter);
3704 wm_draw_region_test(C, area_iter, region_iter);
3705 }
3706 }
3707
3708 CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
3709
3710 CTX_wm_area_set(C, area);
3711 CTX_wm_region_set(C, region);
3712 }
3713 else if (type == eRTDrawWindowSwap) {
3715 }
3716 else if (type == eRTAnimationStep) {
3717 scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1;
3719 }
3720 else if (type == eRTAnimationPlay) {
3721 /* Play anim, return on same frame as started with. */
3722 int tot = (scene->r.efra - scene->r.sfra) + 1;
3723 const int frames_total = tot * steps_total;
3724 int frames_done = tot * steps_done;
3725
3726 while (tot--) {
3727 WM_progress_set(win, float(frames_done) / float(frames_total));
3728 frames_done++;
3729
3730 /* TODO: ability to escape! */
3731 scene->r.cfra++;
3732 if (scene->r.cfra > scene->r.efra) {
3733 scene->r.cfra = scene->r.sfra;
3734 }
3735
3738 }
3739 }
3740 else { /* #eRTUndo. */
3741 /* Undo and redo, including depsgraph update since that can be a
3742 * significant part of the cost. */
3743 ED_undo_pop(C);
3745 ED_undo_redo(C);
3747 }
3748}
3749
3751{
3752 /* Check background mode as many of these actions use redrawing.
3753 * NOTE(@ideasman42): if it's useful to support undo or animation step this could
3754 * be allowed at the moment this seems like a corner case that isn't needed. */
3755 return !G.background && WM_operator_winactive(C);
3756}
3757
3759{
3760 Scene *scene = CTX_data_scene(C);
3761 wmWindow *win = CTX_wm_window(C);
3762 ScrArea *area = CTX_wm_area(C);
3763 ARegion *region = CTX_wm_region(C);
3765 const int type = RNA_enum_get(op->ptr, "type");
3766 const int iter = RNA_int_get(op->ptr, "iterations");
3767 const double time_limit = double(RNA_float_get(op->ptr, "time_limit"));
3768 const int cfra = scene->r.cfra;
3769 const char *infostr = "";
3770
3771 /* NOTE: Depsgraph is used to update scene for a new state, so no need to ensure evaluation
3772 * here.
3773 */
3775
3777
3778 WM_cursor_wait(true);
3779
3780 double time_start = BLI_time_now_seconds();
3781
3782 wm_window_make_drawable(wm, win);
3783
3784 int iter_steps = 0;
3785 for (int a = 0; a < iter; a++) {
3786
3787 if (type == eRTAnimationPlay) {
3789 status.item(fmt::format("{} / {} {}", a + 1, iter, infostr), ICON_INFO);
3790 }
3791
3792 redraw_timer_step(C, scene, depsgraph, win, area, region, type, cfra, a, iter);
3793 iter_steps += 1;
3794
3795 if (time_limit != 0.0) {
3796 if ((BLI_time_now_seconds() - time_start) > time_limit) {
3797 break;
3798 }
3799 a = 0;
3800 }
3801 }
3802
3803 double time_delta = (BLI_time_now_seconds() - time_start) * 1000;
3804
3805 if (type == eRTAnimationPlay) {
3806 ED_workspace_status_text(C, nullptr);
3807 WM_progress_clear(win);
3808 }
3809
3810 WM_cursor_wait(false);
3811
3812 BKE_reportf(op->reports,
3814 "%d \u00D7 %s: %.4f ms, average: %.8f ms",
3815 iter_steps,
3816 infostr,
3817 time_delta,
3818 time_delta / iter_steps);
3819
3820 return OPERATOR_FINISHED;
3821}
3822
3824{
3825 ot->name = "Redraw Timer";
3826 ot->idname = "WM_OT_redraw_timer";
3827 ot->description = "Simple redraw timer to test the speed of updating the interface";
3828
3829 ot->invoke = WM_menu_invoke;
3830 ot->exec = redraw_timer_exec;
3831 ot->poll = redraw_timer_poll;
3832
3833 ot->prop = RNA_def_enum(ot->srna, "type", redraw_timer_type_items, eRTDrawRegion, "Type", "");
3835 ot->srna, "iterations", 10, 1, INT_MAX, "Iterations", "Number of times to redraw", 1, 1000);
3836 RNA_def_float(ot->srna,
3837 "time_limit",
3838 0.0,
3839 0.0,
3840 FLT_MAX,
3841 "Time Limit",
3842 "Seconds to run the test for (override iterations)",
3843 0.0,
3844 60.0);
3845}
3846
3848
3849/* -------------------------------------------------------------------- */
3854
3860
3862{
3863 ot->name = "Memory Statistics";
3864 ot->idname = "WM_OT_memory_statistics";
3865 ot->description = "Print memory statistics to the console";
3866
3867 ot->exec = memory_statistics_exec;
3868}
3869
3871
3872/* -------------------------------------------------------------------- */
3877
3882
3883static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
3884{
3886
3887 /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
3888 * Same goes for ID with no user. */
3889 if (ID_IS_EDITABLE(id) && (id->us != 0)) {
3890 UI_icon_render_id(C, scene, id, ICON_SIZE_ICON, false);
3891 UI_icon_render_id(C, scene, id, ICON_SIZE_PREVIEW, false);
3892 }
3893}
3894
3896{
3897 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
3898
3900 return IDWALK_RET_NOP;
3901 }
3902
3903 PreviewsIDEnsureData *data = static_cast<PreviewsIDEnsureData *>(cb_data->user_data);
3904 ID *id = *cb_data->id_pointer;
3905
3906 if (id && (id->tag & ID_TAG_DOIT)) {
3908 previews_id_ensure(data->C, data->scene, id);
3909 id->tag &= ~ID_TAG_DOIT;
3910 }
3911
3912 return IDWALK_RET_NOP;
3913}
3914
3916{
3917 Main *bmain = CTX_data_main(C);
3918 ListBase *lb[] = {&bmain->materials,
3919 &bmain->textures,
3920 &bmain->images,
3921 &bmain->worlds,
3922 &bmain->lights,
3923 nullptr};
3924 PreviewsIDEnsureData preview_id_data;
3925
3926 /* We use ID_TAG_DOIT to check whether we have already handled a given ID or not. */
3927 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3928 for (int i = 0; lb[i]; i++) {
3930 }
3931
3932 preview_id_data.C = C;
3933 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
3934 preview_id_data.scene = scene;
3935 ID *id = (ID *)scene;
3936
3938 nullptr, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
3939 }
3940
3941 /* Check a last time for ID not used (fake users only, in theory), and
3942 * do our best for those, using current scene... */
3943 for (int i = 0; lb[i]; i++) {
3944 LISTBASE_FOREACH (ID *, id, lb[i]) {
3945 if (id->tag & ID_TAG_DOIT) {
3946 previews_id_ensure(C, nullptr, id);
3947 id->tag &= ~ID_TAG_DOIT;
3948 }
3949 }
3950 }
3951
3952 return OPERATOR_FINISHED;
3953}
3954
3956{
3957 ot->name = "Refresh Data-Block Previews";
3958 ot->idname = "WM_OT_previews_ensure";
3959 ot->description =
3960 "Ensure data-block previews are available and up-to-date "
3961 "(to be saved in .blend file, only for some types like materials, textures, etc.)";
3962
3963 ot->exec = previews_ensure_exec;
3964}
3965
3967
3968/* -------------------------------------------------------------------- */
3971
3985
3986/* Only types supporting previews currently. */
3988 {PREVIEW_FILTER_ALL, "ALL", 0, "All Types", ""},
3990 "GEOMETRY",
3991 0,
3992 "All Geometry Types",
3993 "Clear previews for scenes, collections and objects"},
3995 "SHADING",
3996 0,
3997 "All Shading Types",
3998 "Clear previews for materials, lights, worlds, textures and images"},
3999 {PREVIEW_FILTER_SCENE, "SCENE", 0, "Scenes", ""},
4000 {PREVIEW_FILTER_COLLECTION, "COLLECTION", 0, "Collections", ""},
4001 {PREVIEW_FILTER_OBJECT, "OBJECT", 0, "Objects", ""},
4002 {PREVIEW_FILTER_MATERIAL, "MATERIAL", 0, "Materials", ""},
4003 {PREVIEW_FILTER_LIGHT, "LIGHT", 0, "Lights", ""},
4004 {PREVIEW_FILTER_WORLD, "WORLD", 0, "Worlds", ""},
4005 {PREVIEW_FILTER_TEXTURE, "TEXTURE", 0, "Textures", ""},
4006 {PREVIEW_FILTER_IMAGE, "IMAGE", 0, "Images", ""},
4007#if 0 /* XXX: TODO. */
4008 {PREVIEW_FILTER_BRUSH, "BRUSH", 0, "Brushes", ""},
4009#endif
4010 {0, nullptr, 0, nullptr, nullptr},
4011};
4012
4014{
4015 switch (filter) {
4016 case PREVIEW_FILTER_ALL:
4024 return FILTER_ID_SCE;
4026 return FILTER_ID_GR;
4028 return FILTER_ID_OB;
4030 return FILTER_ID_MA;
4032 return FILTER_ID_LA;
4034 return FILTER_ID_WO;
4036 return FILTER_ID_TE;
4038 return FILTER_ID_IM;
4039 }
4040
4041 return 0;
4042}
4043
4045{
4046 Main *bmain = CTX_data_main(C);
4047 ListBase *lb[] = {
4048 &bmain->objects,
4049 &bmain->collections,
4050 &bmain->materials,
4051 &bmain->worlds,
4052 &bmain->lights,
4053 &bmain->textures,
4054 &bmain->images,
4055 nullptr,
4056 };
4057
4058 const int id_filters = preview_filter_to_idfilter(
4059 PreviewFilterID(RNA_enum_get(op->ptr, "id_type")));
4060
4061 for (int i = 0; lb[i]; i++) {
4062 ID *id = static_cast<ID *>(lb[i]->first);
4063 if (!id) {
4064 continue;
4065 }
4066
4067#if 0
4068 printf("%s: %d, %d, %d -> %d\n",
4069 id->name,
4070 GS(id->name),
4072 id_filters,
4073 BKE_idtype_idcode_to_idfilter(GS(id->name)) & id_filters);
4074#endif
4075
4076 if (!(BKE_idtype_idcode_to_idfilter(GS(id->name)) & id_filters)) {
4077 continue;
4078 }
4079
4080 for (; id; id = static_cast<ID *>(id->next)) {
4082
4083 BKE_previewimg_clear(prv_img);
4084 }
4085 }
4086
4087 return OPERATOR_FINISHED;
4088}
4089
4091{
4092 ot->name = "Clear Data-Block Previews";
4093 ot->idname = "WM_OT_previews_clear";
4094 ot->description =
4095 "Clear data-block previews (only for some types like objects, materials, textures, etc.)";
4096
4097 ot->exec = previews_clear_exec;
4098 ot->invoke = WM_menu_invoke;
4099
4100 ot->prop = RNA_def_enum_flag(ot->srna,
4101 "id_type",
4104 "Data-Block Type",
4105 "Which data-block previews to clear");
4106}
4107
4109
4110/* -------------------------------------------------------------------- */
4113
4115{
4116 PointerRNA ptr_props;
4118
4119 if (std::optional<std::string> manual_id = UI_but_online_manual_id_from_active(C)) {
4120 WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
4121 RNA_string_set(&ptr_props, "doc_id", manual_id.value().c_str());
4122
4124 WM_operatortype_find("WM_OT_doc_view_manual", false),
4126 &ptr_props,
4127 nullptr);
4128
4129 WM_operator_properties_free(&ptr_props);
4130 }
4131
4132 return retval;
4133}
4134
4136{
4137 /* Identifiers. */
4138 ot->name = "View Online Manual";
4139 ot->idname = "WM_OT_doc_view_manual_ui_context";
4140 ot->description = "View a context based online manual in a web browser";
4141
4142 /* Callbacks. */
4145}
4146
4148
4149/* -------------------------------------------------------------------- */
4154
4156{
4157 PropertyRNA *prop;
4158
4159 ot->name = "Set Stereo 3D";
4160 ot->idname = "WM_OT_set_stereo_3d";
4161 ot->description = "Toggle 3D stereo support for current window (or change the display mode)";
4162
4163 ot->exec = wm_stereo3d_set_exec;
4164 ot->invoke = wm_stereo3d_set_invoke;
4165 ot->poll = WM_operator_winactive;
4167 ot->check = wm_stereo3d_set_check;
4168 ot->cancel = wm_stereo3d_set_cancel;
4169
4170 prop = RNA_def_enum(ot->srna,
4171 "display_mode",
4174 "Display Mode",
4175 "");
4177 prop = RNA_def_enum(ot->srna,
4178 "anaglyph_type",
4181 "Anaglyph Type",
4182 "");
4184 prop = RNA_def_enum(ot->srna,
4185 "interlace_type",
4188 "Interlace Type",
4189 "");
4191 prop = RNA_def_boolean(ot->srna,
4192 "use_interlace_swap",
4193 false,
4194 "Swap Left/Right",
4195 "Swap left and right stereo channels");
4197 prop = RNA_def_boolean(ot->srna,
4198 "use_sidebyside_crosseyed",
4199 false,
4200 "Cross-Eyed",
4201 "Right eye should see left image and vice versa");
4203}
4204
4206
4207/* -------------------------------------------------------------------- */
4210
4212{
4252#if defined(WIN32)
4253 WM_operatortype_append(WM_OT_console_toggle);
4254#endif
4259
4260#ifdef WITH_XR_OPENXR
4262#endif
4263
4264 /* Gizmos. */
4267}
4268
4269/* Circle-select-like modal operators. */
4271{
4272 static const EnumPropertyItem modal_items[] = {
4273 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4274 {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
4275 {GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""},
4276 {GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""},
4277 {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""},
4278
4279 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4280 {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""},
4281 {GESTURE_MODAL_NOP, "NOP", 0, "No Operation", ""},
4282
4283 {0, nullptr, 0, nullptr, nullptr},
4284 };
4285
4286 /* WARNING: Name is incorrect, use for non-3d views. */
4287 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Gesture Circle");
4288
4289 /* This function is called for each space-type, only needs to add map once. */
4290 if (keymap && keymap->modal_items) {
4291 return;
4292 }
4293
4294 keymap = WM_modalkeymap_ensure(keyconf, "View3D Gesture Circle", modal_items);
4295
4296 /* Assign map to operators. */
4297 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle");
4298 WM_modalkeymap_assign(keymap, "UV_OT_select_circle");
4299 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_circle");
4300 WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle");
4301 WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
4302 WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
4303 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
4304 WM_modalkeymap_assign(keymap, "ACTION_OT_select_circle");
4305}
4306
4307/* Straight line modal operators. */
4309{
4310 static const EnumPropertyItem modal_items[] = {
4311 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4312 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4313 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4314 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4315 {GESTURE_MODAL_SNAP, "SNAP", 0, "Snap", ""},
4316 {GESTURE_MODAL_FLIP, "FLIP", 0, "Flip", ""},
4317 {0, nullptr, 0, nullptr, nullptr},
4318 };
4319
4320 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Straight Line");
4321
4322 /* This function is called for each space-type, only needs to add map once. */
4323 if (keymap && keymap->modal_items) {
4324 return;
4325 }
4326
4327 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Straight Line", modal_items);
4328
4329 /* Assign map to operators. */
4330 WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line");
4331 WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
4332 WM_modalkeymap_assign(keymap, "MESH_OT_bisect");
4333 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_line_gesture");
4334 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_line_gesture");
4335 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_line_gesture");
4336 WM_modalkeymap_assign(keymap, "SCULPT_OT_project_line_gesture");
4337 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_line_gesture");
4338}
4339
4340/* Box_select-like modal operators. */
4342{
4343 static const EnumPropertyItem modal_items[] = {
4344 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4345 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4346 {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""},
4347 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4348 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4349 {0, nullptr, 0, nullptr, nullptr},
4350 };
4351
4352 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Box");
4353
4354 /* This function is called for each space-type, only needs to add map once. */
4355 if (keymap && keymap->modal_items) {
4356 return;
4357 }
4358
4359 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Box", modal_items);
4360
4361 /* Assign map to operators. */
4362 WM_modalkeymap_assign(keymap, "ACTION_OT_select_box");
4363 WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_box");
4364 WM_modalkeymap_assign(keymap, "ANIM_OT_previewrange_set");
4365 WM_modalkeymap_assign(keymap, "INFO_OT_select_box");
4366 WM_modalkeymap_assign(keymap, "FILE_OT_select_box");
4367 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_box");
4368 WM_modalkeymap_assign(keymap, "MARKER_OT_select_box");
4369 WM_modalkeymap_assign(keymap, "NLA_OT_select_box");
4370 WM_modalkeymap_assign(keymap, "NODE_OT_select_box");
4371 WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border");
4372 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show");
4373 WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_box");
4374#if 0 /* Template. */
4375 WM_modalkeymap_assign(keymap, "SCREEN_OT_box_select");
4376#endif
4377 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_box");
4378 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border");
4379 WM_modalkeymap_assign(keymap, "UV_OT_select_box");
4380 WM_modalkeymap_assign(keymap, "UV_OT_custom_region_set");
4381 WM_modalkeymap_assign(keymap, "CLIP_OT_select_box");
4382 WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box");
4383 WM_modalkeymap_assign(keymap, "MASK_OT_select_box");
4384 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_box_gesture");
4385 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_box_gesture");
4386 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_box_gesture");
4387 WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
4388 WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border");
4389 WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border");
4390 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_box");
4391 /* XXX TODO: zoom border should perhaps map right-mouse to zoom out instead of in+cancel. */
4392 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border");
4393 WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border");
4394 WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
4395 WM_modalkeymap_assign(keymap, "GREASE_PENCIL_OT_erase_box");
4396}
4397
4398/* Lasso modal operators. */
4400{
4401 static const EnumPropertyItem modal_items[] = {
4402 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4403 {0, nullptr, 0, nullptr, nullptr},
4404 };
4405
4406 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Lasso");
4407
4408 /* This function is called for each space-type, only needs to add map once. */
4409 if (keymap && keymap->modal_items) {
4410 return;
4411 }
4412
4413 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Lasso", modal_items);
4414
4415 /* Assign map to operators. */
4416 WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_lasso");
4417 WM_modalkeymap_assign(keymap, "MASK_OT_select_lasso");
4418 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_lasso_gesture");
4419 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_lasso_gesture");
4420 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_lasso_gesture");
4421 WM_modalkeymap_assign(keymap, "ACTION_OT_select_lasso");
4422 WM_modalkeymap_assign(keymap, "CLIP_OT_select_lasso");
4423 WM_modalkeymap_assign(keymap, "GRAPH_OT_select_lasso");
4424 WM_modalkeymap_assign(keymap, "NODE_OT_select_lasso");
4425 WM_modalkeymap_assign(keymap, "UV_OT_select_lasso");
4426 WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_lasso");
4427 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_lasso_gesture");
4428 WM_modalkeymap_assign(keymap, "GREASE_PENCIL_OT_erase_lasso");
4429}
4430
4431/* Polyline modal operators */
4433{
4434 static const EnumPropertyItem modal_items[] = {
4435 {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
4436 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4437 {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
4438 {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
4439 {0, nullptr, 0, nullptr, nullptr},
4440 };
4441
4442 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Polyline");
4443
4444 /* This function is called for each space-type, only needs to add map once. */
4445 if (keymap && keymap->modal_items) {
4446 return;
4447 }
4448
4449 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Polyline", modal_items);
4450
4451 /* assign map to operators */
4452 WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_polyline_gesture");
4453 WM_modalkeymap_assign(keymap, "PAINT_OT_mask_polyline_gesture");
4454 WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_polyline_gesture");
4455 WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_polyline_gesture");
4456}
4457
4458/* Zoom to border modal operators. */
4460{
4461 static const EnumPropertyItem modal_items[] = {
4462 {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
4463 {GESTURE_MODAL_IN, "IN", 0, "In", ""},
4464 {GESTURE_MODAL_OUT, "OUT", 0, "Out", ""},
4465 {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
4466 {0, nullptr, 0, nullptr, nullptr},
4467 };
4468
4469 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Zoom Border");
4470
4471 /* This function is called for each space-type, only needs to add map once. */
4472 if (keymap && keymap->modal_items) {
4473 return;
4474 }
4475
4476 keymap = WM_modalkeymap_ensure(keyconf, "Gesture Zoom Border", modal_items);
4477
4478 /* Assign map to operators. */
4479 WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border");
4480 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border");
4481 WM_modalkeymap_assign(keymap, "IMAGE_OT_view_zoom_border");
4482}
4483
4485{
4486 WM_keymap_ensure(keyconf, "Window", SPACE_EMPTY, RGN_TYPE_WINDOW);
4487
4488 wm_gizmos_keymap(keyconf);
4490 gesture_box_modal_keymap(keyconf);
4495
4497}
4498
4500
4501/* -------------------------------------------------------------------- */
4508
4509static bool rna_id_enum_filter_single(const ID *id, void *user_data)
4510{
4511 return (id != user_data);
4512}
4513
4514static bool rna_id_enum_filter_single_and_assets(const ID *id, void *user_data)
4515{
4516 if (!rna_id_enum_filter_single(id, user_data)) {
4517 return false;
4518 }
4519 if (id->asset_data != nullptr) {
4520 return false;
4521 }
4522 return true;
4523}
4524
4525/* Generic itemf's for operators that take library args. */
4526static const EnumPropertyItem *rna_id_itemf(bool *r_free,
4527 ID *id,
4528 bool local,
4529 bool (*filter_ids)(const ID *id, void *user_data),
4530 void *user_data)
4531{
4532 EnumPropertyItem item_tmp = {0}, *item = nullptr;
4533 int totitem = 0;
4534 int i = 0;
4535
4536 if (id != nullptr) {
4537 const short id_type = GS(id->name);
4538 for (; id; id = static_cast<ID *>(id->next)) {
4539 if ((filter_ids != nullptr) && filter_ids(id, user_data) == false) {
4540 i++;
4541 continue;
4542 }
4543 if (local == false || !ID_IS_LINKED(id)) {
4544 item_tmp.identifier = item_tmp.name = id->name + 2;
4545 item_tmp.value = i++;
4546
4547 /* Show collection color tag icons in menus. */
4548 if (id_type == ID_GR) {
4550 }
4551
4552 RNA_enum_item_add(&item, &totitem, &item_tmp);
4553 }
4554 }
4555 }
4556
4557 RNA_enum_item_end(&item, &totitem);
4558 *r_free = true;
4559
4560 return item;
4561}
4562
4563/* Can add more ID types as needed. */
4564
4566 PointerRNA * /*ptr*/,
4567 PropertyRNA * /*prop*/,
4568 bool *r_free)
4569{
4570
4571 return rna_id_itemf(
4572 r_free, C ? (ID *)CTX_data_main(C)->actions.first : nullptr, false, nullptr, nullptr);
4573}
4574#if 0 /* UNUSED. */
4575const EnumPropertyItem *RNA_action_local_itemf(bContext *C,
4576 PointerRNA * /*ptr*/,
4577 PropertyRNA * /*prop*/,
4578 bool *r_free)
4579{
4580 return rna_id_itemf(r_free, C ? (ID *)CTX_data_main(C)->action.first : nullptr, true);
4581}
4582#endif
4583
4585 PointerRNA * /*ptr*/,
4586 PropertyRNA * /*prop*/,
4587 bool *r_free)
4588{
4589 return rna_id_itemf(
4590 r_free, C ? (ID *)CTX_data_main(C)->collections.first : nullptr, false, nullptr, nullptr);
4591}
4593 PointerRNA * /*ptr*/,
4594 PropertyRNA * /*prop*/,
4595 bool *r_free)
4596{
4597 return rna_id_itemf(
4598 r_free, C ? (ID *)CTX_data_main(C)->collections.first : nullptr, true, nullptr, nullptr);
4599}
4600
4602 PointerRNA * /*ptr*/,
4603 PropertyRNA * /*prop*/,
4604 bool *r_free)
4605{
4606 return rna_id_itemf(
4607 r_free, C ? (ID *)CTX_data_main(C)->images.first : nullptr, false, nullptr, nullptr);
4608}
4610 PointerRNA * /*ptr*/,
4611 PropertyRNA * /*prop*/,
4612 bool *r_free)
4613{
4614 return rna_id_itemf(
4615 r_free, C ? (ID *)CTX_data_main(C)->images.first : nullptr, true, nullptr, nullptr);
4616}
4617
4619 PointerRNA * /*ptr*/,
4620 PropertyRNA * /*prop*/,
4621 bool *r_free)
4622{
4623 return rna_id_itemf(
4624 r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, false, nullptr, nullptr);
4625}
4627 PointerRNA * /*ptr*/,
4628 PropertyRNA * /*prop*/,
4629 bool *r_free)
4630{
4631 return rna_id_itemf(
4632 r_free, C ? (ID *)CTX_data_main(C)->scenes.first : nullptr, true, nullptr, nullptr);
4633}
4635 PointerRNA * /*ptr*/,
4636 PropertyRNA * /*prop*/,
4637 bool *r_free)
4638{
4639 Scene *sequencer_scene = C ? CTX_data_sequencer_scene(C) : nullptr;
4640 return rna_id_itemf(r_free,
4641 C ? (ID *)CTX_data_main(C)->scenes.first : nullptr,
4642 false,
4644 sequencer_scene);
4645}
4647 PointerRNA * /*ptr*/,
4648 PropertyRNA * /*prop*/,
4649 bool *r_free)
4650{
4651 return rna_id_itemf(
4652 r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : nullptr, false, nullptr, nullptr);
4653}
4655 PointerRNA * /*ptr*/,
4656 PropertyRNA * /*prop*/,
4657 bool *r_free)
4658{
4659 return rna_id_itemf(
4660 r_free, C ? (ID *)CTX_data_main(C)->movieclips.first : nullptr, true, nullptr, nullptr);
4661}
4662
4664 PointerRNA * /*ptr*/,
4665 PropertyRNA * /*prop*/,
4666 bool *r_free)
4667{
4668 return rna_id_itemf(
4669 r_free, C ? (ID *)CTX_data_main(C)->masks.first : nullptr, false, nullptr, nullptr);
4670}
4672 PointerRNA * /*ptr*/,
4673 PropertyRNA * /*prop*/,
4674 bool *r_free)
4675{
4676 return rna_id_itemf(
4677 r_free, C ? (ID *)CTX_data_main(C)->masks.first : nullptr, true, nullptr, nullptr);
4678}
4679
bool id_type_can_have_animdata(short id_type)
Definition anim_data.cc:64
ImBuf * BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
Definition brush.cc:1677
float BKE_brush_curve_strength_clamped(const Brush *br, float p, float len)
Definition brush.cc:1637
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)
Scene * CTX_data_sequencer_scene(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:747
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1251
void IDP_ClearProperty(IDProperty *prop)
Definition idprop.cc:1257
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:717
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:863
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, bool do_overwrite) ATTR_NONNULL()
Definition idprop.cc:712
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:666
uint64_t BKE_idtype_idcode_to_idfilter(short idcode)
Definition idtype.cc:363
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:164
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:358
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1201
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1224
@ IDWALK_RET_NOP
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_RECURSE
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
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
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2700
#define BKE_ST_MAXNAME
Definition BKE_screen.hh:72
void BLF_size(int fontid, float size)
Definition blf.cc:443
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:789
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:505
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:440
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:585
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:802
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:388
#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 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:965
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:604
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
void BLI_str_tolower_ascii(char *str, size_t len) ATTR_NONNULL(1)
Definition string.cc:956
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:113
#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:188
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
ID and Library types, which are fundamental for SDNA.
#define FILTER_ID_OB
Definition DNA_ID.h:1214
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
#define FILTER_ID_MA
Definition DNA_ID.h:1208
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define FILTER_ID_LA
Definition DNA_ID.h:1205
#define FILTER_ID_GR
Definition DNA_ID.h:1203
#define FILTER_ID_TE
Definition DNA_ID.h:1220
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define FILTER_ID_IM
Definition DNA_ID.h:1204
#define FILTER_ID_SCE
Definition DNA_ID.h:1217
#define FILTER_ID_WO
Definition DNA_ID.h:1223
@ 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
@ S3D_DISPLAY_ANAGLYPH
@ S3D_INTERLACE_ROW
@ USER_UNIT_NONE
@ SCREENFULL
@ SCREENNORMAL
@ RGN_TYPE_WINDOW
#define RGN_TYPE_ANY
@ SPACE_TEXT
@ SPACE_CLIP
@ 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
@ USER_REDUCE_MOTION
@ 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:379
void initNumInput(NumInput *n)
Definition numinput.cc:70
#define NUM_STR_REP_LEN
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:312
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:190
@ NUM_NO_NEGATIVE
void outputNumInput(NumInput *n, char *str, const UnitSettings &unit_settings)
Definition numinput.cc:88
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:693
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:851
void ED_screen_refresh(bContext *C, wmWindowManager *wm, wmWindow *win)
bool ED_operator_regionactive(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1024
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:98
bool ED_undo_is_legacy_compatible_for_property(bContext *C, ID *id, PointerRNA &ptr)
Definition ed_undo.cc:405
void ED_undo_push_op(bContext *C, wmOperator *op)
Definition ed_undo.cc:359
bool ED_undo_is_valid(const bContext *C, const char *undoname)
Definition ed_undo.cc:381
void ED_undo_redo(bContext *C)
Definition ed_undo.cc:354
bool ED_undo_operator_repeat(bContext *C, wmOperator *op)
Definition ed_undo.cc:631
void ED_undo_pop(bContext *C)
Definition ed_undo.cc:350
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 immBindTexture(const char *name, blender::gpu::Texture *tex)
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
void immUniformColor4f(float r, float g, float b, float a)
void immVertex2f(uint attr_id, float x, float y)
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
void GPU_line_width(float width)
Definition gpu_state.cc:166
void GPU_line_smooth(bool enable)
Definition gpu_state.cc:78
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(GPUBlend blend)
Definition gpu_state.cc:42
void GPU_texture_swizzle_set(blender::gpu::Texture *texture, const char swizzle[4])
void GPU_texture_unbind(blender::gpu::Texture *texture)
@ GPU_TEXTURE_USAGE_SHADER_READ
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
void GPU_texture_free(blender::gpu::Texture *texture)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
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:220
@ PROP_STRING_SEARCH_SUGGESTION
Definition RNA_types.hh:792
@ PROP_STRING_SEARCH_SORT
Definition RNA_types.hh:785
PropertyType
Definition RNA_types.hh:161
@ PROP_FLOAT
Definition RNA_types.hh:164
@ PROP_BOOLEAN
Definition RNA_types.hh:162
@ PROP_ENUM
Definition RNA_types.hh:166
@ PROP_INT
Definition RNA_types.hh:163
@ PROP_POINTER
Definition RNA_types.hh:167
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:430
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_SKIP_PRESET
Definition RNA_types.hh:473
PropertySubType
Definition RNA_types.hh:232
@ PROP_DISTANCE
Definition RNA_types.hh:256
@ PROP_PIXEL
Definition RNA_types.hh:248
@ PROP_ANGLE
Definition RNA_types.hh:252
@ PROP_PIXEL_DIAMETER
Definition RNA_types.hh:293
@ PROP_NONE
Definition RNA_types.hh:233
@ PROP_PERCENTAGE
Definition RNA_types.hh:250
@ PROP_FACTOR
Definition RNA_types.hh:251
@ PROP_DISTANCE_DIAMETER
Definition RNA_types.hh:294
#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)
@ UI_BLOCK_SEARCH_MENU
@ UI_BLOCK_NUMSELECT
@ UI_BLOCK_LOOP
@ UI_BLOCK_MOVEMOUSE_QUIT
@ UI_BLOCK_KEEP_OPEN
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)
@ UI_BUT_ACTIVE_DEFAULT
@ UI_BUT_ACTIVATE_ON_INIT
void UI_block_bounds_set_popup(uiBlock *block, int addval, const int bounds_offset[2])
Definition interface.cc:653
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)
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)
@ UI_BUT2_ACTIVATE_ON_INIT_NO_SELECT
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)
int UI_searchbox_size_x()
bool UI_block_has_active_default_button(const uiBlock *block)
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)
@ UI_RETURN_CANCEL
@ UI_RETURN_OK
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:679
void UI_but_func_menu_search(uiBut *but, const char *single_menu_idname=nullptr)
@ UI_BLOCK_THEME_STYLE_REGULAR
@ UI_BLOCK_THEME_STYLE_POPUP
#define UI_DEFAULT_TEXT_POINTS
#define UI_UNIT_X
void UI_block_flag_enable(uiBlock *block, int flag)
uiBut * uiDefBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_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_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)
uiLayout * uiItemsAlertBox(uiBlock *block, const uiStyle *style, const int dialog_width, const eAlertIcon icon, const int icon_size)
#define UI_ITEM_NONE
uiBut * uiItemL_ex(uiLayout *layout, blender::StringRef name, int icon, bool highlight, bool redalert)
#define UI_MAX_DRAW_STR
@ TH_TEXT_HI
void UI_GetThemeColor4fv(int colorid, float col[4])
@ WM_JOB_TYPE_ANY
Definition WM_api.hh:1775
#define NC_WINDOW
Definition WM_types.hh:375
@ KM_CTRL
Definition WM_types.hh:279
CLG_LogRef * WM_LOG_OPERATORS
@ KM_PRESS
Definition WM_types.hh:311
@ KM_RELEASE
Definition WM_types.hh:312
@ 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
wmPopupSize
Definition WM_types.hh:982
@ WM_POPUP_SIZE_LARGE
Definition WM_types.hh:984
@ WM_POPUP_SIZE_SMALL
Definition WM_types.hh:983
void(*)(bContext *C, const blender::int2 &xy, const blender::float2 &tilt, void *customdata) wmPaintCursorDraw
Definition WM_types.hh:1193
wmPopupPosition
Definition WM_types.hh:987
@ WM_POPUP_POSITION_MOUSE
Definition WM_types.hh:988
@ WM_POPUP_POSITION_CENTER
Definition WM_types.hh:989
#define U
BMesh const char void * data
BPy_StructRNA * depsgraph
constexpr StringRef trim() const
int64_t size() const
void append(const T &value)
nullptr float
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define rot(x, k)
#define str(s)
#define GS(x)
uint pos
uint col
#define filter
#define printf(...)
#define ceil
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
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)
uiLayout & block_layout(uiBlock *block, LayoutDirection direction, LayoutType type, int x, int y, int size, int em, int padding, const uiStyle *style)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
vector snap(vector a, vector b)
Definition node_math.h:97
const char * name
const int status
return ret
#define fabsf
#define sinf
#define cosf
#define atan2f
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_system_idprops_unset(PointerRNA *ptr, const char *identifier)
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)
const char * RNA_property_ui_name(const PropertyRNA *prop, const PointerRNA *ptr)
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)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
std::string RNA_string_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)
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_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:515
const EnumPropertyItem rna_enum_stereo3d_anaglyph_type_items[]
Definition rna_scene.cc:547
const EnumPropertyItem rna_enum_stereo3d_interlace_type_items[]
Definition rna_scene.cc:554
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
struct CurveMapping * curve_distance_falloff
const char * identifier
Definition RNA_types.hh:657
const char * name
Definition RNA_types.hh:661
wmOperator * op
ListBase group
Definition DNA_ID.h:143
short flag
Definition DNA_ID.h:163
char name[64]
Definition DNA_ID.h:164
IDPropertyData data
Definition DNA_ID.h:169
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
struct AssetMetaData * asset_data
Definition DNA_ID.h:423
char name[258]
Definition DNA_ID.h:432
int us
Definition DNA_ID.h:443
ImBufFloatBuffer float_buffer
LibraryForeachIDCallbackFlag cb_flag
void * data
struct LinkData * next
void * first
ListBase scenes
Definition BKE_main.hh:278
ListBase textures
Definition BKE_main.hh:285
ListBase lights
Definition BKE_main.hh:288
ListBase materials
Definition BKE_main.hh:284
ListBase worlds
Definition BKE_main.hh:291
ListBase collections
Definition BKE_main.hh:298
ListBase images
Definition BKE_main.hh:286
ListBase objects
Definition BKE_main.hh:280
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
PropertyRNA * prop
PropertyRNA * zoom_prop
PointerRNA fill_col_override_test_ptr
PointerRNA fill_col_ptr
ListBase orig_paintcursors
PropertyRNA * col_prop
blender::gpu::Texture * texture
PropertyRNA * rot_prop
PointerRNA rot_ptr
int initial_radial_center[2]
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 scale_y_set(float scale)
void op_enum(blender::StringRefNull opname, blender::StringRefNull propname, IDProperty *properties, blender::wm::OpCallContext context, eUI_Item_Flag flag, const int active=-1)
uiBlock * block() const
void operator_context_set(blender::wm::OpCallContext opcontext)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void enabled_set(bool enabled)
int width() const
uiFontStyle widget
short columnspace
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int xy[2]
Definition WM_types.hh:761
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:1033
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1049
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1089
const char * idname
Definition WM_types.hh:1035
IDProperty * last_properties
Definition WM_types.hh:1130
PropertyRNA * prop
Definition WM_types.hh:1139
StructRNA * srna
Definition WM_types.hh:1127
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1081
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1073
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
WindowManagerRuntimeHandle * runtime
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:333
void WM_operator_free(wmOperator *op)
Definition wm.cc:259
void WM_cursor_wait(bool val)
void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:1682
void wm_draw_update(bContext *C)
Definition wm_draw.cc:1614
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)
wmOperatorStatus WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, blender::wm::OpCallContext context, PointerRNA *properties, const wmEvent *event)
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_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)
#define ISMOUSE_MOTION(event_type)
@ RIGHTMOUSE
@ EVT_PADENTER
@ EVT_SPACEKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
@ EVT_RETKEY
@ 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
void WM_OT_read_history(wmOperatorType *ot)
Definition wm_files.cc:2822
void WM_OT_save_as_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3862
void WM_OT_open_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3373
PointerRNA * ptr
Definition wm_files.cc:4238
void WM_OT_recover_last_session(wmOperatorType *ot)
Definition wm_files.cc:3536
void WM_OT_read_userpref(wmOperatorType *ot)
Definition wm_files.cc:2756
void WM_OT_save_homefile(wmOperatorType *ot)
Definition wm_files.cc:2600
void WM_OT_read_factory_userpref(wmOperatorType *ot)
Definition wm_files.cc:2795
void WM_OT_save_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3953
void WM_OT_recover_auto_save(wmOperatorType *ot)
Definition wm_files.cc:3599
void WM_OT_read_factory_settings(wmOperatorType *ot)
Definition wm_files.cc:3064
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_OT_read_homefile(wmOperatorType *ot)
Definition wm_files.cc:2988
void WM_OT_save_userpref(wmOperatorType *ot)
Definition wm_files.cc:2629
void WM_OT_clear_recent_files(wmOperatorType *ot)
Definition wm_files.cc:4045
void WM_OT_revert_mainfile(wmOperatorType *ot)
Definition wm_files.cc:3456
void WM_OT_set_working_color_space(wmOperatorType *ot)
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:247
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:932
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:959
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:895
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 memory_statistics_exec(bContext *, wmOperator *)
wmOperatorStatus WM_operator_redo_popup(bContext *C, wmOperator *op)
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)
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 *)
wmOperatorStatus WM_menu_invoke_ex(bContext *C, wmOperator *op, blender::wm::OpCallContext opcontext)
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)
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, std::optional< std::string > message)
static wmOperatorStatus wm_call_pie_menu_exec(bContext *C, wmOperator *op)
#define ID_CAST_OBDATA(id_pt)
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)
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 bool rna_id_enum_filter_single_and_assets(const ID *id, void *user_data)
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)
wmOperatorStatus WM_operator_confirm_message_ex(bContext *C, wmOperator *op, const char *title, const int icon, const char *message, const blender::wm::OpCallContext)
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 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, std::optional< std::string > message=std::nullopt)
static bool wm_operator_winactive_normal(bContext *C)
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 *)
const EnumPropertyItem * RNA_scene_without_sequencer_scene_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
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)
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)
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, std::optional< std::string > message)
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)
@ eRTDrawWindowSwap
@ eRTAnimationStep
@ eRTDrawRegionSwap
@ eRTDrawWindow
@ eRTUndo
@ eRTDrawRegion
@ eRTAnimationPlay
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:402
wmOperatorStatus wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition wm_stereo.cc:346
wmOperatorStatus wm_stereo3d_set_exec(bContext *C, wmOperator *op)
Definition wm_stereo.cc:256
bool wm_stereo3d_set_check(bContext *, wmOperator *)
Definition wm_stereo.cc:394
void wm_stereo3d_set_draw(bContext *, wmOperator *op)
Definition wm_stereo.cc:356
wmOperatorStatus wm_window_new_exec(bContext *C, wmOperator *op)
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
Definition wm_window.cc:407
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()