Blender V5.0
render_shading.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "DNA_ID.h"
15#include "DNA_curve_types.h"
16#include "DNA_light_types.h"
18#include "DNA_material_types.h"
19#include "DNA_node_types.h"
20#include "DNA_object_types.h"
21#include "DNA_particle_types.h"
22#include "DNA_scene_types.h"
23#include "DNA_space_types.h"
24#include "DNA_world_types.h"
25
26#include "BLI_listbase.h"
27#include "BLI_math_vector.h"
28#include "BLI_path_utils.hh"
29#include "BLI_string.h"
30#include "BLI_string_utils.hh"
31#include "BLI_utildefines.h"
32
33#include "BLT_translation.hh"
34
35#include "BKE_anim_data.hh"
36#include "BKE_animsys.h"
37#include "BKE_appdir.hh"
39#include "BKE_blendfile.hh"
40#include "BKE_brush.hh"
41#include "BKE_context.hh"
42#include "BKE_curve.hh"
43#include "BKE_editmesh.hh"
44#include "BKE_global.hh"
45#include "BKE_image.hh"
46#include "BKE_layer.hh"
47#include "BKE_lib_id.hh"
48#include "BKE_lib_query.hh"
49#include "BKE_lib_remap.hh"
50#include "BKE_library.hh"
51#include "BKE_lightprobe.h"
52#include "BKE_linestyle.h"
53#include "BKE_main.hh"
55#include "BKE_material.hh"
56#include "BKE_node.hh"
57#include "BKE_node_runtime.hh"
59#include "BKE_object.hh"
60#include "BKE_report.hh"
61#include "BKE_scene.hh"
62#include "BKE_texture.h"
63#include "BKE_vfont.hh"
64#include "BKE_workspace.hh"
65#include "BKE_world.h"
66
67#include "NOD_composite.hh"
68
69#include "DEG_depsgraph.hh"
72
73#ifdef WITH_FREESTYLE
74# include "BKE_freestyle.h"
75# include "FRS_freestyle.h"
76# include "RNA_enum_types.hh"
77#endif
78
79#include "RNA_access.hh"
80
81#include "WM_api.hh"
82#include "WM_types.hh"
83
84#include "ED_curve.hh"
85#include "ED_mesh.hh"
86#include "ED_node.hh"
87#include "ED_object.hh"
88#include "ED_paint.hh"
89#include "ED_render.hh"
90#include "ED_scene.hh"
91#include "ED_screen.hh"
92#include "ED_undo.hh"
93
94#include "RNA_define.hh"
95#include "RNA_prototypes.hh"
96
97#include "UI_interface.hh"
98
99#include "RE_engine.h"
100#include "RE_pipeline.h"
101
103
104#include "render_intern.hh" /* own include */
105
106using blender::Vector;
107
108static bool object_materials_supported_poll_ex(bContext *C, const Object *ob);
109
110/* -------------------------------------------------------------------- */
113
114static void material_copybuffer_filepath_get(char filepath[FILE_MAX], size_t filepath_maxncpy)
115{
116 BLI_path_join(filepath, filepath_maxncpy, BKE_tempdir_base(), "copybuffer_material.blend");
117}
118
119static bool object_array_for_shading_edit_mode_enabled_filter(const Object *ob, void *user_data)
120{
121 bContext *C = static_cast<bContext *>(user_data);
123 if (BKE_object_is_in_editmode(ob) == true) {
124 return true;
125 }
126 }
127 return false;
128}
129
135
136static bool object_array_for_shading_edit_mode_disabled_filter(const Object *ob, void *user_data)
137{
138 bContext *C = static_cast<bContext *>(user_data);
140 if (BKE_object_is_in_editmode(ob) == false) {
141 return true;
142 }
143 }
144 return false;
145}
146
152
154
155/* -------------------------------------------------------------------- */
158
160{
162 return false;
163 }
164 if (!OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
165 return false;
166 }
167
168 /* Material linked to object. */
169 if (ob->matbits && ob->actcol && ob->matbits[ob->actcol - 1]) {
170 return true;
171 }
172
173 /* Material linked to obdata. */
174 const ID *data = static_cast<ID *>(ob->data);
176}
177
183
185{
186 const Object *ob_active = CTX_data_active_object(C);
187 if (ob_active == nullptr) {
188 return false;
189 }
190 return ob_active->actcol > 0;
191}
192
193
194/* -------------------------------------------------------------------- */
197
199{
200 Main *bmain = CTX_data_main(C);
202
203 if (!ob) {
204 return OPERATOR_CANCELLED;
205 }
206
208
209 if (ob->mode & OB_MODE_TEXTURE_PAINT) {
210 Scene *scene = CTX_data_scene(C);
211 ED_paint_proj_mesh_data_check(*scene, *ob, nullptr, nullptr, nullptr, nullptr);
213 }
214
218
219 return OPERATOR_FINISHED;
220}
221
223{
224 /* identifiers */
225 ot->name = "Add Material Slot";
226 ot->idname = "OBJECT_OT_material_slot_add";
227 ot->description = "Add a new material slot";
228
229 /* API callbacks. */
232
233 /* flags */
235}
236
238
239/* -------------------------------------------------------------------- */
242
244{
246
248 return false;
249 }
250
251 /* Removing material slots in edit mode screws things up, see bug #21822. */
253 CTX_wm_operator_poll_msg_set(C, "Unable to remove material slot in edit mode");
254 return false;
255 }
257 return false;
258 }
259
260 return true;
261}
262
286
288{
289 /* identifiers */
290 ot->name = "Remove Material Slot";
291 ot->idname = "OBJECT_OT_material_slot_remove";
292 ot->description = "Remove the selected material slot";
293
294 /* API callbacks. */
297
298 /* flags */
300}
301
303
304/* -------------------------------------------------------------------- */
307
309{
310 View3D *v3d = CTX_wm_view3d(C);
311 bool changed_multi = false;
312
314 const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : nullptr;
315
317 for (Object *ob : objects) {
318 short mat_nr_active = -1;
319
320 if (ob->totcol == 0) {
321 continue;
322 }
323 if (obact && (mat_active == BKE_object_material_get(ob, obact->actcol))) {
324 /* Avoid searching since there may be multiple slots with the same material.
325 * For the active object or duplicates: match the material slot index first. */
326 mat_nr_active = obact->actcol - 1;
327 }
328 else {
329 /* Find the first matching material.
330 * NOTE: there may be multiple but that's not a common use case. */
331 for (int i = 0; i < ob->totcol; i++) {
332 const Material *mat = BKE_object_material_get(ob, i + 1);
333 if (mat_active == mat) {
334 mat_nr_active = i;
335 break;
336 }
337 }
338 if (mat_nr_active == -1) {
339 continue;
340 }
341 }
342
343 bool changed = false;
344 if (ob->type == OB_MESH) {
346 BMFace *efa;
347 BMIter iter;
348
349 if (em) {
350 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
352 changed = true;
353 efa->mat_nr = mat_nr_active;
354 }
355 }
356 }
357 }
358 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
359 ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
360
361 if (nurbs) {
362 LISTBASE_FOREACH (Nurb *, nu, nurbs) {
363 if (ED_curve_nurb_select_check(v3d, nu)) {
364 changed = true;
365 nu->mat_nr = mat_nr_active;
366 }
367 }
368 }
369 }
370 else if (ob->type == OB_FONT) {
371 const Curve *cu = static_cast<const Curve *>(ob->data);
372 EditFont *ef = cu->editfont;
373 int i, selstart, selend;
374
375 if (ef && BKE_vfont_select_get(cu, &selstart, &selend)) {
376 for (i = selstart; i <= selend; i++) {
377 changed = true;
378 ef->textbufinfo[i].mat_nr = mat_nr_active;
379 }
380 }
381 }
382
383 if (changed) {
384 changed_multi = true;
387 }
388 }
389
390 return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
391}
392
394{
395 /* identifiers */
396 ot->name = "Assign Material Slot";
397 ot->idname = "OBJECT_OT_material_slot_assign";
398 ot->description = "Assign active material slot to selection";
399
400 /* API callbacks. */
403
404 /* flags */
406}
407
409
410/* -------------------------------------------------------------------- */
413
415{
416 bool changed_multi = false;
418 const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : nullptr;
419
421 for (Object *ob : objects) {
422 if (ob->totcol == 0) {
423 continue;
424 }
425
426 const short mat_nr_active = BKE_object_material_index_get_with_hint(
427 ob, mat_active, obact ? obact->actcol - 1 : -1);
428
429 if (mat_nr_active == -1) {
430 continue;
431 }
432
433 bool changed = false;
434
435 if (ob->type == OB_MESH) {
437
438 if (em) {
439 changed = EDBM_deselect_by_material(em, mat_nr_active, select);
440 }
441 }
442 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
443 ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
444 BPoint *bp;
445 BezTriple *bezt;
446 int a;
447
448 if (nurbs) {
449 LISTBASE_FOREACH (Nurb *, nu, nurbs) {
450 if (nu->mat_nr == mat_nr_active) {
451 if (nu->bezt) {
452 a = nu->pntsu;
453 bezt = nu->bezt;
454 while (a--) {
455 if (bezt->hide == 0) {
456 changed = true;
457 if (select) {
458 bezt->f1 |= SELECT;
459 bezt->f2 |= SELECT;
460 bezt->f3 |= SELECT;
461 }
462 else {
463 bezt->f1 &= ~SELECT;
464 bezt->f2 &= ~SELECT;
465 bezt->f3 &= ~SELECT;
466 }
467 }
468 bezt++;
469 }
470 }
471 else if (nu->bp) {
472 a = nu->pntsu * nu->pntsv;
473 bp = nu->bp;
474 while (a--) {
475 if (bp->hide == 0) {
476 changed = true;
477 if (select) {
478 bp->f1 |= SELECT;
479 }
480 else {
481 bp->f1 &= ~SELECT;
482 }
483 }
484 bp++;
485 }
486 }
487 }
488 }
489 }
490 }
491
492 if (changed) {
493 changed_multi = true;
494 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SELECT);
496 }
497 }
498
499 return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
500}
501
506
508{
509 /* identifiers */
510 ot->name = "Select Material Slot";
511 ot->idname = "OBJECT_OT_material_slot_select";
512 ot->description = "Select by active material slot";
513
514 /* API callbacks. */
516
517 /* flags */
519}
520
525
527{
528 /* identifiers */
529 ot->name = "Deselect Material Slot";
530 ot->idname = "OBJECT_OT_material_slot_deselect";
531 ot->description = "Deselect by active material slot";
532
533 /* API callbacks. */
535
536 /* flags */
538}
539
541
542/* -------------------------------------------------------------------- */
545
547{
548 Main *bmain = CTX_data_main(C);
550 Material ***matar_obdata;
551
552 if (!ob || !(matar_obdata = BKE_object_material_array_p(ob))) {
553 return OPERATOR_CANCELLED;
554 }
555
557
558 Material ***matar_object = &ob->mat;
559
560 Material **matar = static_cast<Material **>(
561 MEM_callocN(sizeof(*matar) * size_t(ob->totcol), __func__));
562 for (int i = ob->totcol; i--;) {
563 matar[i] = ob->matbits[i] ? (*matar_object)[i] : (*matar_obdata)[i];
564 }
565
566 CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
567 if (ob != ob_iter && BKE_object_material_array_p(ob_iter)) {
568 /* If we are using the same obdata, we only assign slots in ob_iter that are using object
569 * materials, and not obdata ones. */
570 const bool is_same_obdata = ob->data == ob_iter->data;
571
572 /* If we are using the same obdata, make the target object inherit the matbits of the active
573 * object. Without this, object material slots are not copied unless the target object
574 * already had its material slot link set to object. */
575 if (is_same_obdata) {
576 for (int i = ob->totcol; i--;) {
577 if (ob->matbits[i]) {
578 ob_iter->matbits[i] = ob->matbits[i];
579 }
580 }
581 }
582
583 BKE_object_material_array_assign(bmain, ob_iter, &matar, ob->totcol, is_same_obdata);
584
585 if (ob_iter->totcol == ob->totcol) {
586 ob_iter->actcol = ob->actcol;
589 }
590 }
591 }
593
594 MEM_freeN(matar);
595
596 return OPERATOR_FINISHED;
597}
598
600{
601 /* identifiers */
602 ot->name = "Copy Material to Selected";
603 ot->idname = "OBJECT_OT_material_slot_copy";
604 ot->description = "Copy material to selected objects";
605
606 /* API callbacks. */
609
610 /* flags */
612}
613
615
616/* -------------------------------------------------------------------- */
619
621{
623
624 uint *slot_remap;
625 int index_pair[2];
626
627 int dir = RNA_enum_get(op->ptr, "direction");
628
629 if (!ob || ob->totcol < 2) {
630 return OPERATOR_CANCELLED;
631 }
632
633 /* up */
634 if (dir == 1 && ob->actcol > 1) {
635 index_pair[0] = ob->actcol - 2;
636 index_pair[1] = ob->actcol - 1;
637 ob->actcol--;
638 }
639 /* down */
640 else if (dir == -1 && ob->actcol < ob->totcol) {
641 index_pair[0] = ob->actcol - 1;
642 index_pair[1] = ob->actcol - 0;
643 ob->actcol++;
644 }
645 else {
646 return OPERATOR_CANCELLED;
647 }
648
649 slot_remap = MEM_malloc_arrayN<uint>(ob->totcol, __func__);
650
651 range_vn_u(slot_remap, ob->totcol, 0);
652
653 slot_remap[index_pair[0]] = index_pair[1];
654 slot_remap[index_pair[1]] = index_pair[0];
655
656 BKE_object_material_remap(ob, slot_remap);
657
658 MEM_freeN(slot_remap);
659
663
664 return OPERATOR_FINISHED;
665}
666
668{
669 static const EnumPropertyItem material_slot_move[] = {
670 {1, "UP", 0, "Up", ""},
671 {-1, "DOWN", 0, "Down", ""},
672 {0, nullptr, 0, nullptr, nullptr},
673 };
674
675 /* identifiers */
676 ot->name = "Move Material";
677 ot->idname = "OBJECT_OT_material_slot_move";
678 ot->description = "Move the active material up/down in the list";
679
680 /* API callbacks. */
683
684 /* flags */
686
687 RNA_def_enum(ot->srna,
688 "direction",
689 material_slot_move,
690 0,
691 "Direction",
692 "Direction to move the active material towards");
693}
694
696
697/* -------------------------------------------------------------------- */
700
702{
703 Main *bmain = CTX_data_main(C);
704 int removed = 0;
705
707 for (Object *ob : objects) {
708 int actcol = ob->actcol;
709 for (int slot = 1; slot <= ob->totcol; slot++) {
710 while (slot <= ob->totcol && !BKE_object_material_slot_used(ob, slot)) {
711 ob->actcol = slot;
713
714 if (actcol >= slot) {
715 actcol--;
716 }
717
718 removed++;
719 }
720 }
721 ob->actcol = actcol;
722
724 }
725
726 if (!removed) {
727 return OPERATOR_CANCELLED;
728 }
729
730 BKE_reportf(op->reports, RPT_INFO, "Removed %d slots", removed);
731
732 Object *ob_active = CTX_data_active_object(C);
733 if (ob_active->mode & OB_MODE_TEXTURE_PAINT) {
734 Scene *scene = CTX_data_scene(C);
735 ED_paint_proj_mesh_data_check(*scene, *ob_active, nullptr, nullptr, nullptr, nullptr);
737 }
738
742
743 return OPERATOR_FINISHED;
744}
745
747{
748 /* identifiers */
749 ot->name = "Remove Unused Slots";
750 ot->idname = "OBJECT_OT_material_slot_remove_unused";
751 ot->description = "Remove unused material slots";
752
753 /* API callbacks. */
756
757 /* flags */
759}
760
762{
763 /* Removing material slots in edit mode screws things up, see bug #21822. */
764 Object *ob_active = CTX_data_active_object(C);
765 Main *bmain = CTX_data_main(C);
766 int removed = 0;
767
769 for (Object *ob : objects) {
770 int actcol = ob->actcol;
771 for (int slot = 1; slot <= ob->totcol; slot++) {
772 while (slot <= ob->totcol) {
773 ob->actcol = slot;
775
776 if (actcol >= slot) {
777 actcol--;
778 }
779
780 removed++;
781 }
782 }
783 ob->actcol = actcol;
784
786 }
787
788 if (!removed) {
789 return OPERATOR_CANCELLED;
790 }
791
792 BKE_reportf(op->reports, RPT_INFO, "Removed %d materials", removed);
793
794 if (ob_active->mode == OB_MODE_TEXTURE_PAINT) {
795 Scene *scene = CTX_data_scene(C);
796 ED_paint_proj_mesh_data_check(*scene, *ob_active, nullptr, nullptr, nullptr, nullptr);
798 }
799
803
804 return OPERATOR_FINISHED;
805}
806
808{
809 /* identifiers */
810 ot->name = "Remove All Materials";
811 ot->idname = "OBJECT_OT_material_slot_remove_all";
812 ot->description = "Remove all materials";
813
814 /* API callbacks. */
817
818 /* flags */
820}
821
823
824/* -------------------------------------------------------------------- */
827
829{
830 Material *ma = static_cast<Material *>(
831 CTX_data_pointer_get_type(C, "material", &RNA_Material).data);
832 Main *bmain = CTX_data_main(C);
834 PropertyRNA *prop;
835
836 /* hook into UI */
838
839 Object *ob = static_cast<Object *>((prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data :
840 nullptr);
841
842 /* add or copy material */
843 if (ma) {
844 Material *new_ma = (Material *)BKE_id_copy_ex(
845 bmain, &ma->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
846 ma = new_ma;
847 }
848 else {
849 const char *name = DATA_("Material");
850 if (!(ob != nullptr && ob->type == OB_GREASE_PENCIL)) {
851 ma = BKE_material_add(bmain, name);
852 }
853 else {
854 ma = BKE_gpencil_material_add(bmain, name);
855 }
856 ED_node_shader_default(C, bmain, &ma->id);
857 }
858
859 if (prop) {
860 if (ob != nullptr) {
861 /* Add slot follows user-preferences for creating new slots,
862 * RNA pointer assignment doesn't, see: #60014. */
863 if (BKE_object_material_get_p(ob, ob->actcol) == nullptr) {
865 }
866 }
867
868 /* when creating new ID blocks, use is already 1, but RNA
869 * pointer use also increases user, so this compensates it */
870 id_us_min(&ma->id);
871
872 if (ptr.owner_id) {
873 BKE_id_move_to_same_lib(*bmain, ma->id, *ptr.owner_id);
874 }
875
876 PointerRNA idptr = RNA_id_pointer_create(&ma->id);
877 RNA_property_pointer_set(&ptr, prop, idptr, nullptr);
878 RNA_property_update(C, &ptr, prop);
879 }
880
882
883 return OPERATOR_FINISHED;
884}
885
887{
888 /* identifiers */
889 ot->name = "New Material";
890 ot->idname = "MATERIAL_OT_new";
891 ot->description = "Add a new material";
892
893 /* API callbacks. */
894 ot->exec = new_material_exec;
896
897 /* flags */
899}
900
902
903/* -------------------------------------------------------------------- */
906
908{
909 Tex *tex = static_cast<Tex *>(CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data);
910 Main *bmain = CTX_data_main(C);
912 PropertyRNA *prop;
913
914 /* add or copy texture */
915 if (tex) {
916 tex = (Tex *)BKE_id_copy(bmain, &tex->id);
917 }
918 else {
919 tex = BKE_texture_add(bmain, DATA_("Texture"));
920 }
921
922 /* hook into UI */
924
925 bool linked_id_created = false;
926 if (prop) {
927 /* when creating new ID blocks, use is already 1, but RNA
928 * pointer use also increases user, so this compensates it */
929 id_us_min(&tex->id);
930
931 if (ptr.owner_id) {
932 BKE_id_move_to_same_lib(*bmain, tex->id, *ptr.owner_id);
933 linked_id_created = ID_IS_LINKED(&tex->id);
934 }
935
936 PointerRNA idptr = RNA_id_pointer_create(&tex->id);
937 RNA_property_pointer_set(&ptr, prop, idptr, nullptr);
938 RNA_property_update(C, &ptr, prop);
939 }
940
941 if (!linked_id_created) {
942 ED_undo_push_op(C, op);
943 }
944
946
947 return OPERATOR_FINISHED;
948}
949
951{
952 /* identifiers */
953 ot->name = "New Texture";
954 ot->idname = "TEXTURE_OT_new";
955 ot->description = "Add a new texture";
956
957 /* API callbacks. */
958 ot->exec = new_texture_exec;
959
960 /* flags */
962}
963
965
966/* -------------------------------------------------------------------- */
969
971{
972 World *wo = static_cast<World *>(CTX_data_pointer_get_type(C, "world", &RNA_World).data);
973 Main *bmain = CTX_data_main(C);
975 PropertyRNA *prop;
976
977 /* add or copy world */
978 if (wo) {
979 World *new_wo = (World *)BKE_id_copy_ex(
980 bmain, &wo->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
981 wo = new_wo;
982 }
983 else {
984 wo = BKE_world_add(bmain, CTX_DATA_(BLT_I18NCONTEXT_ID_WORLD, "World"));
985 ED_node_shader_default(C, bmain, &wo->id);
986 }
987
988 /* hook into UI */
990
991 if (prop) {
992 /* when creating new ID blocks, use is already 1, but RNA
993 * pointer use also increases user, so this compensates it */
994 id_us_min(&wo->id);
995
996 if (ptr.owner_id) {
997 BKE_id_move_to_same_lib(*bmain, wo->id, *ptr.owner_id);
998 }
999
1000 PointerRNA idptr = RNA_id_pointer_create(&wo->id);
1001 RNA_property_pointer_set(&ptr, prop, idptr, nullptr);
1002 RNA_property_update(C, &ptr, prop);
1003 }
1004
1006
1007 return OPERATOR_FINISHED;
1008}
1009
1011{
1012 /* identifiers */
1013 ot->name = "New World";
1014 ot->idname = "WORLD_OT_new";
1015 ot->description = "Create a new world Data-Block";
1016
1017 /* API callbacks. */
1018 ot->exec = new_world_exec;
1019
1020 /* flags */
1022}
1023
1025
1026/* -------------------------------------------------------------------- */
1029
1031{
1032 wmWindow *win = CTX_wm_window(C);
1033 Scene *scene = CTX_data_scene(C);
1034
1035 ViewLayer *view_layer_current = win ? WM_window_get_active_view_layer(win) : nullptr;
1036 int type = RNA_enum_get(op->ptr, "type");
1037 /* Copy requires a source. */
1038 if (type == VIEWLAYER_ADD_COPY) {
1039 if (view_layer_current == nullptr) {
1040 type = VIEWLAYER_ADD_NEW;
1041 }
1042 }
1043 ViewLayer *view_layer_new = BKE_view_layer_add(
1044 scene, view_layer_current ? view_layer_current->name : nullptr, view_layer_current, type);
1045
1046 if (win) {
1047 WM_window_set_active_view_layer(win, view_layer_new);
1048 }
1049
1053
1054 return OPERATOR_FINISHED;
1055}
1056
1058{
1059 static EnumPropertyItem type_items[] = {
1060 {VIEWLAYER_ADD_NEW, "NEW", 0, "New", "Add a new view layer"},
1061 {VIEWLAYER_ADD_COPY, "COPY", 0, "Copy Settings", "Copy settings of current view layer"},
1063 "EMPTY",
1064 0,
1065 "Blank",
1066 "Add a new view layer with all collections disabled"},
1067 {0, nullptr, 0, nullptr, nullptr},
1068 };
1069
1070 /* identifiers */
1071 ot->name = "Add View Layer";
1072 ot->idname = "SCENE_OT_view_layer_add";
1073 ot->description = "Add a view layer";
1074
1075 /* API callbacks. */
1076 ot->exec = view_layer_add_exec;
1077 ot->invoke = WM_menu_invoke;
1078
1079 /* flags */
1081
1082 /* properties */
1083 ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
1084}
1085
1087
1088/* -------------------------------------------------------------------- */
1091
1093{
1094 Scene *scene = CTX_data_scene(C);
1095 return (scene->view_layers.first != scene->view_layers.last);
1096}
1097
1099{
1100 Main *bmain = CTX_data_main(C);
1101 Scene *scene = CTX_data_scene(C);
1102 ViewLayer *view_layer = CTX_data_view_layer(C);
1103
1104 if (!ED_scene_view_layer_delete(bmain, scene, view_layer, nullptr)) {
1105 return OPERATOR_CANCELLED;
1106 }
1107
1109
1110 return OPERATOR_FINISHED;
1111}
1112
1114{
1115 /* identifiers */
1116 ot->name = "Remove View Layer";
1117 ot->idname = "SCENE_OT_view_layer_remove";
1118 ot->description = "Remove the selected view layer";
1119
1120 /* API callbacks. */
1121 ot->exec = view_layer_remove_exec;
1122 ot->poll = view_layer_remove_poll;
1123
1124 /* flags */
1126}
1127
1129
1130/* -------------------------------------------------------------------- */
1133
1135{
1136 Scene *scene = CTX_data_scene(C);
1137 ViewLayer *view_layer = CTX_data_view_layer(C);
1138
1139 BKE_view_layer_add_aov(view_layer);
1140
1141 RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
1142 if (engine_type->update_render_passes) {
1143 RenderEngine *engine = RE_engine_create(engine_type);
1144 if (engine) {
1145 BKE_view_layer_verify_aov(engine, scene, view_layer);
1146 }
1147 RE_engine_free(engine);
1148 engine = nullptr;
1149 }
1150
1151 if (scene->compositing_node_group) {
1153 }
1154
1158
1159 return OPERATOR_FINISHED;
1160}
1161
1163{
1164 /* identifiers */
1165 ot->name = "Add AOV";
1166 ot->idname = "SCENE_OT_view_layer_add_aov";
1167 ot->description = "Add a Shader AOV";
1168
1169 /* API callbacks. */
1171
1172 /* flags */
1174}
1175
1177
1178/* -------------------------------------------------------------------- */
1181
1183{
1184 Scene *scene = CTX_data_scene(C);
1185 ViewLayer *view_layer = CTX_data_view_layer(C);
1186
1187 if (view_layer->active_aov == nullptr) {
1188 return OPERATOR_FINISHED;
1189 }
1190
1191 BKE_view_layer_remove_aov(view_layer, view_layer->active_aov);
1192
1193 RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
1194 if (engine_type->update_render_passes) {
1195 RenderEngine *engine = RE_engine_create(engine_type);
1196 if (engine) {
1197 BKE_view_layer_verify_aov(engine, scene, view_layer);
1198 }
1199 RE_engine_free(engine);
1200 engine = nullptr;
1201 }
1202
1203 if (scene->compositing_node_group) {
1205 }
1206
1210
1211 return OPERATOR_FINISHED;
1212}
1213
1215{
1216 /* identifiers */
1217 ot->name = "Remove AOV";
1218 ot->idname = "SCENE_OT_view_layer_remove_aov";
1219 ot->description = "Remove Active AOV";
1220
1221 /* API callbacks. */
1223
1224 /* flags */
1226}
1227
1229
1230/* -------------------------------------------------------------------- */
1233
1235{
1236 Scene *scene = CTX_data_scene(C);
1237 ViewLayer *view_layer = CTX_data_view_layer(C);
1238
1239 char name[MAX_NAME];
1240 name[0] = '\0';
1241 /* If a name is provided, ensure that it is unique. */
1242 if (RNA_struct_property_is_set(op->ptr, "name")) {
1243 RNA_string_get(op->ptr, "name", name);
1244 /* Ensure that there are no dots in the name. */
1245 BLI_string_replace_char(name, '.', '_');
1246 LISTBASE_FOREACH (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) {
1247 if (STREQ(lightgroup->name, name)) {
1248 return OPERATOR_CANCELLED;
1249 }
1250 }
1251 }
1252
1254
1255 if (scene->compositing_node_group) {
1257 }
1258
1262
1263 return OPERATOR_FINISHED;
1264}
1265
1267{
1268 /* identifiers */
1269 ot->name = "Add Lightgroup";
1270 ot->idname = "SCENE_OT_view_layer_add_lightgroup";
1271 ot->description = "Add a Light Group";
1272
1273 /* API callbacks. */
1275
1276 /* flags */
1278
1279 /* properties */
1280 ot->prop = RNA_def_string(ot->srna,
1281 "name",
1282 nullptr,
1284 "Name",
1285 "Name of newly created lightgroup");
1286}
1287
1289
1290/* -------------------------------------------------------------------- */
1293
1295{
1296 Scene *scene = CTX_data_scene(C);
1297 ViewLayer *view_layer = CTX_data_view_layer(C);
1298
1299 if (view_layer->active_lightgroup == nullptr) {
1300 return OPERATOR_FINISHED;
1301 }
1302
1303 BKE_view_layer_remove_lightgroup(view_layer, view_layer->active_lightgroup);
1304
1305 if (scene->compositing_node_group) {
1307 }
1308
1312
1313 return OPERATOR_FINISHED;
1314}
1315
1317{
1318 /* identifiers */
1319 ot->name = "Remove Lightgroup";
1320 ot->idname = "SCENE_OT_view_layer_remove_lightgroup";
1321 ot->description = "Remove Active Lightgroup";
1322
1323 /* API callbacks. */
1325
1326 /* flags */
1328}
1329
1331
1332/* -------------------------------------------------------------------- */
1335
1337{
1338 blender::Set<blender::StringRefNull> used_lightgroups;
1339
1340 FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
1341 if (ob->lightgroup && ob->lightgroup->name[0]) {
1342 used_lightgroups.add_as(ob->lightgroup->name);
1343 }
1344 }
1346
1347 if (scene->world && scene->world->lightgroup && scene->world->lightgroup->name[0]) {
1348 used_lightgroups.add_as(scene->world->lightgroup->name);
1349 }
1350
1351 return used_lightgroups;
1352}
1353
1355{
1356 Scene *scene = CTX_data_scene(C);
1357 ViewLayer *view_layer = CTX_data_view_layer(C);
1358
1360 for (const blender::StringRefNull used_lightgroup : used_lightgroups) {
1361 if (!BLI_findstring(&view_layer->lightgroups,
1362 used_lightgroup.c_str(),
1364 {
1365 BKE_view_layer_add_lightgroup(view_layer, used_lightgroup.c_str());
1366 }
1367 }
1368
1369 if (scene->compositing_node_group) {
1371 }
1372
1376
1377 return OPERATOR_FINISHED;
1378}
1379
1381{
1382 /* identifiers */
1383 ot->name = "Add Used Lightgroups";
1384 ot->idname = "SCENE_OT_view_layer_add_used_lightgroups";
1385 ot->description = "Add all used Light Groups";
1386
1387 /* API callbacks. */
1389
1390 /* flags */
1392}
1393
1395
1396/* -------------------------------------------------------------------- */
1399
1401{
1402 Scene *scene = CTX_data_scene(C);
1403 ViewLayer *view_layer = CTX_data_view_layer(C);
1404
1406 LISTBASE_FOREACH_MUTABLE (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) {
1407 if (!used_lightgroups.contains_as(lightgroup->name)) {
1408 BKE_view_layer_remove_lightgroup(view_layer, lightgroup);
1409 }
1410 }
1411
1412 if (scene->compositing_node_group) {
1414 }
1415
1419
1420 return OPERATOR_FINISHED;
1421}
1422
1424{
1425 /* identifiers */
1426 ot->name = "Remove Unused Lightgroups";
1427 ot->idname = "SCENE_OT_view_layer_remove_unused_lightgroups";
1428 ot->description = "Remove all unused Light Groups";
1429
1430 /* API callbacks. */
1432
1433 /* flags */
1435}
1436
1438
1439/* -------------------------------------------------------------------- */
1442
1443enum {
1447};
1448
1450 wmOperator *op)
1451{
1452 ViewLayer *view_layer = CTX_data_view_layer(C);
1453 Scene *scene = CTX_data_scene(C);
1454
1455 auto is_irradiance_volume = [](Object *ob) -> bool {
1456 return ob->type == OB_LIGHTPROBE &&
1457 static_cast<LightProbe *>(ob->data)->type == LIGHTPROBE_TYPE_VOLUME;
1458 };
1459
1461
1462 auto irradiance_volume_setup = [&](Object *ob) {
1466 probes.append(ob);
1467 };
1468
1469 int subset = RNA_enum_get(op->ptr, "subset");
1470 switch (subset) {
1471 case LIGHTCACHE_SUBSET_ALL: {
1472 FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
1473 if (is_irradiance_volume(ob)) {
1474 irradiance_volume_setup(ob);
1475 }
1476 }
1478 break;
1479 }
1481 ObjectsInViewLayerParams parameters;
1482 parameters.filter_fn = nullptr;
1483 parameters.no_dup_data = true;
1485 view_layer, nullptr, &parameters);
1486 for (Object *ob : objects) {
1487 if (is_irradiance_volume(ob)) {
1488 irradiance_volume_setup(ob);
1489 }
1490 }
1491 break;
1492 }
1494 Object *active_ob = CTX_data_active_object(C);
1495 if (is_irradiance_volume(active_ob)) {
1496 irradiance_volume_setup(active_ob);
1497 }
1498 break;
1499 }
1500 default:
1502 break;
1503 }
1504
1505 return probes;
1506}
1507
1509 /* Store actual owner of job, so modal operator could check for it,
1510 * the reason of this is that active scene could change when rendering
1511 * several layers from compositor #31800. */
1513
1514 std::string report;
1515};
1516
1518 wmOperator *op,
1519 const wmEvent * /*event*/)
1520{
1522 wmWindow *win = CTX_wm_window(C);
1523 ViewLayer *view_layer = CTX_data_view_layer(C);
1524 Main *bmain = CTX_data_main(C);
1525 Scene *scene = CTX_data_scene(C);
1526
1528
1529 if (probes.is_empty()) {
1530 return OPERATOR_CANCELLED;
1531 }
1532
1533 BakeOperatorData *data = MEM_new<BakeOperatorData>(__func__);
1534 data->scene = scene;
1535 data->report = "";
1536
1538 wm, win, bmain, view_layer, scene, probes, data->report, scene->r.cfra, 0);
1539 if (wm_job == nullptr) {
1540 MEM_delete(data);
1541 BKE_report(op->reports, RPT_WARNING, "Cannot bake light probe while rendering");
1542 return OPERATOR_CANCELLED;
1543 }
1544
1546
1547 op->customdata = static_cast<void *>(data);
1548
1549 WM_jobs_start(wm, wm_job);
1550
1551 WM_cursor_wait(false);
1552
1554}
1555
1557 wmOperator *op,
1558 const wmEvent *event)
1559{
1560 BakeOperatorData *data = static_cast<BakeOperatorData *>(op->customdata);
1561 Scene *scene = data->scene;
1562
1563 /* No running bake, remove handler and pass through. */
1565 std::string report = data->report;
1566
1567 MEM_delete(data);
1568 op->customdata = nullptr;
1569
1570 if (!report.empty()) {
1571 BKE_report(op->reports, RPT_ERROR, report.c_str());
1572 return OPERATOR_CANCELLED;
1573 }
1575 }
1576
1577 /* Running bake. */
1578 switch (event->type) {
1579 case EVT_ESCKEY:
1581 default: {
1582 break;
1583 }
1584 }
1585 return OPERATOR_PASS_THROUGH;
1586}
1587
1589{
1591 Scene *scene = static_cast<BakeOperatorData *>(op->customdata)->scene;
1592
1593 /* Kill on cancel, because job is using op->reports. */
1595}
1596
1597/* Executes blocking bake. */
1599{
1600 ViewLayer *view_layer = CTX_data_view_layer(C);
1601 Main *bmain = CTX_data_main(C);
1602 Scene *scene = CTX_data_scene(C);
1603
1604 G.is_break = false;
1605
1607
1608 std::string report;
1610 bmain, view_layer, scene, probes, report, scene->r.cfra);
1611 /* Do the job. */
1612 wmJobWorkerStatus worker_status = {};
1613 EEVEE_lightbake_job(rj, &worker_status);
1614 /* Move baking data to original object and then free it. */
1617
1618 if (!report.empty()) {
1619 BKE_report(op->reports, RPT_ERROR, report.c_str());
1620 return OPERATOR_CANCELLED;
1621 }
1622
1623 return OPERATOR_FINISHED;
1624}
1625
1627{
1628 static const EnumPropertyItem light_cache_subset_items[] = {
1629 {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All Volumes", "Bake all light probe volumes"},
1631 "SELECTED",
1632 0,
1633 "Selected Only",
1634 "Only bake selected light probe volumes"},
1636 "ACTIVE",
1637 0,
1638 "Active Only",
1639 "Only bake the active light probe volume"},
1640 {0, nullptr, 0, nullptr, nullptr},
1641 };
1642
1643 /* identifiers */
1644 ot->name = "Bake Light Cache";
1645 ot->idname = "OBJECT_OT_lightprobe_cache_bake";
1646 ot->description = "Bake irradiance volume light cache";
1647
1648 /* API callbacks. */
1653
1654 ot->prop = RNA_def_enum(
1655 ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
1657}
1658
1660
1661/* -------------------------------------------------------------------- */
1664
1666{
1667 Scene *scene = CTX_data_scene(C);
1668
1669 /* Kill potential bake job first (see #57011). */
1672
1674
1675 for (Object *object : probes) {
1676 if (object->lightprobe_cache == nullptr) {
1677 continue;
1678 }
1681 }
1682
1684
1685 return OPERATOR_FINISHED;
1686}
1687
1689{
1690 static const EnumPropertyItem lightprobe_subset_items[] = {
1692 "ALL",
1693 0,
1694 "All Light Probes",
1695 "Delete all light probes' baked lighting data"},
1697 "SELECTED",
1698 0,
1699 "Selected Only",
1700 "Only delete selected light probes' baked lighting data"},
1702 "ACTIVE",
1703 0,
1704 "Active Only",
1705 "Only delete the active light probe's baked lighting data"},
1706 {0, nullptr, 0, nullptr, nullptr},
1707 };
1708
1709 /* identifiers */
1710 ot->name = "Delete Light Cache";
1711 ot->idname = "OBJECT_OT_lightprobe_cache_free";
1712 ot->description = "Delete cached indirect lighting";
1713 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1714
1715 /* API callbacks. */
1717
1718 ot->prop = RNA_def_enum(ot->srna,
1719 "subset",
1720 lightprobe_subset_items,
1722 "Subset",
1723 "Subset of probes to update");
1724}
1725
1727
1728/* -------------------------------------------------------------------- */
1731
1733{
1734 Scene *scene = CTX_data_scene(C);
1735
1736 /* don't allow user to remove "left" and "right" views */
1737 return scene->r.actview > 1;
1738}
1739
1741{
1742 Main *bmain = CTX_data_main(C);
1743 Scene *scene = CTX_data_scene(C);
1744
1745 BKE_scene_add_render_view(scene, nullptr);
1746 scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
1747
1749
1750 BKE_ntree_update_tag_id_changed(bmain, &scene->id);
1752
1753 return OPERATOR_FINISHED;
1754}
1755
1757{
1758 /* identifiers */
1759 ot->name = "Add Render View";
1760 ot->idname = "SCENE_OT_render_view_add";
1761 ot->description = "Add a render view";
1762
1763 /* API callbacks. */
1764 ot->exec = render_view_add_exec;
1765
1766 /* flags */
1767 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1768}
1769
1771
1772/* -------------------------------------------------------------------- */
1775
1777{
1778 Main *bmain = CTX_data_main(C);
1779 Scene *scene = CTX_data_scene(C);
1780 SceneRenderView *rv = static_cast<SceneRenderView *>(
1781 BLI_findlink(&scene->r.views, scene->r.actview));
1782
1783 if (!BKE_scene_remove_render_view(scene, rv)) {
1784 return OPERATOR_CANCELLED;
1785 }
1786
1788
1789 BKE_ntree_update_tag_id_changed(bmain, &scene->id);
1791
1792 return OPERATOR_FINISHED;
1793}
1794
1796{
1797 /* identifiers */
1798 ot->name = "Remove Render View";
1799 ot->idname = "SCENE_OT_render_view_remove";
1800 ot->description = "Remove the selected render view";
1801
1802 /* API callbacks. */
1805
1806 /* flags */
1807 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1808}
1809
1811
1812#ifdef WITH_FREESTYLE
1813
1814/* -------------------------------------------------------------------- */
1817
1818static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
1819{
1820 if (!lineset) {
1821 BKE_report(reports,
1822 RPT_ERROR,
1823 "No active lineset and associated line style to manipulate the modifier");
1824 return false;
1825 }
1826 if (!lineset->linestyle) {
1827 BKE_report(reports,
1828 RPT_ERROR,
1829 "The active lineset does not have a line style (indicating data corruption)");
1830 return false;
1831 }
1832
1833 return true;
1834}
1835
1836static bool freestyle_active_module_poll(bContext *C)
1837{
1838 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1839 FreestyleModuleConfig *module = static_cast<FreestyleModuleConfig *>(ptr.data);
1840
1841 return module != nullptr;
1842}
1843
1844static wmOperatorStatus freestyle_module_add_exec(bContext *C, wmOperator * /*op*/)
1845{
1846 Scene *scene = CTX_data_scene(C);
1847 ViewLayer *view_layer = CTX_data_view_layer(C);
1848
1850
1852
1853 return OPERATOR_FINISHED;
1854}
1855
1856void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
1857{
1858 /* identifiers */
1859 ot->name = "Add Freestyle Module";
1860 ot->idname = "SCENE_OT_freestyle_module_add";
1861 ot->description = "Add a style module into the list of modules";
1862
1863 /* API callbacks. */
1864 ot->exec = freestyle_module_add_exec;
1865
1866 /* flags */
1868}
1869
1871
1872/* -------------------------------------------------------------------- */
1875
1876static wmOperatorStatus freestyle_module_remove_exec(bContext *C, wmOperator * /*op*/)
1877{
1878 Scene *scene = CTX_data_scene(C);
1879 ViewLayer *view_layer = CTX_data_view_layer(C);
1880 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1881 FreestyleModuleConfig *module = static_cast<FreestyleModuleConfig *>(ptr.data);
1882
1884
1887
1888 return OPERATOR_FINISHED;
1889}
1890
1891void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
1892{
1893 /* identifiers */
1894 ot->name = "Remove Freestyle Module";
1895 ot->idname = "SCENE_OT_freestyle_module_remove";
1896 ot->description = "Remove the style module from the stack";
1897
1898 /* API callbacks. */
1899 ot->poll = freestyle_active_module_poll;
1900 ot->exec = freestyle_module_remove_exec;
1901
1902 /* flags */
1904}
1905
1906static wmOperatorStatus freestyle_module_move_exec(bContext *C, wmOperator *op)
1907{
1908 Scene *scene = CTX_data_scene(C);
1909 ViewLayer *view_layer = CTX_data_view_layer(C);
1910 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1911 FreestyleModuleConfig *module = static_cast<FreestyleModuleConfig *>(ptr.data);
1912 int dir = RNA_enum_get(op->ptr, "direction");
1913
1914 if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
1917 }
1918
1919 return OPERATOR_FINISHED;
1920}
1921
1923
1924/* -------------------------------------------------------------------- */
1927
1928void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
1929{
1930 static const EnumPropertyItem direction_items[] = {
1931 {-1, "UP", 0, "Up", ""},
1932 {1, "DOWN", 0, "Down", ""},
1933 {0, nullptr, 0, nullptr, nullptr},
1934 };
1935
1936 /* identifiers */
1937 ot->name = "Move Freestyle Module";
1938 ot->idname = "SCENE_OT_freestyle_module_move";
1939 ot->description = "Change the position of the style module within in the list of style modules";
1940
1941 /* API callbacks. */
1942 ot->poll = freestyle_active_module_poll;
1943 ot->exec = freestyle_module_move_exec;
1944
1945 /* flags */
1947
1948 /* props */
1949 RNA_def_enum(ot->srna,
1950 "direction",
1951 direction_items,
1952 0,
1953 "Direction",
1954 "Direction to move the chosen style module towards");
1955}
1956
1958
1959/* -------------------------------------------------------------------- */
1962
1963static wmOperatorStatus freestyle_lineset_add_exec(bContext *C, wmOperator * /*op*/)
1964{
1965 Main *bmain = CTX_data_main(C);
1966 Scene *scene = CTX_data_scene(C);
1967 ViewLayer *view_layer = CTX_data_view_layer(C);
1968
1969 BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, nullptr);
1970
1973
1974 return OPERATOR_FINISHED;
1975}
1976
1977void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
1978{
1979 /* identifiers */
1980 ot->name = "Add Line Set";
1981 ot->idname = "SCENE_OT_freestyle_lineset_add";
1982 ot->description = "Add a line set into the list of line sets";
1983
1984 /* API callbacks. */
1985 ot->exec = freestyle_lineset_add_exec;
1986
1987 /* flags */
1989}
1990
1992
1993/* -------------------------------------------------------------------- */
1996
1997static bool freestyle_active_lineset_poll(bContext *C)
1998{
1999 ViewLayer *view_layer = CTX_data_view_layer(C);
2000
2001 if (!view_layer) {
2002 return false;
2003 }
2004
2005 return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != nullptr;
2006}
2007
2008static wmOperatorStatus freestyle_lineset_copy_exec(bContext *C, wmOperator * /*op*/)
2009{
2010 ViewLayer *view_layer = CTX_data_view_layer(C);
2011
2013
2014 return OPERATOR_FINISHED;
2015}
2016
2017void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
2018{
2019 /* identifiers */
2020 ot->name = "Copy Line Set";
2021 ot->idname = "SCENE_OT_freestyle_lineset_copy";
2022 ot->description = "Copy the active line set to the internal clipboard";
2023
2024 /* API callbacks. */
2025 ot->exec = freestyle_lineset_copy_exec;
2026 ot->poll = freestyle_active_lineset_poll;
2027
2028 /* flags */
2030}
2031
2033
2034/* -------------------------------------------------------------------- */
2037
2038static wmOperatorStatus freestyle_lineset_paste_exec(bContext *C, wmOperator * /*op*/)
2039{
2040 Scene *scene = CTX_data_scene(C);
2041 ViewLayer *view_layer = CTX_data_view_layer(C);
2042
2044
2047
2048 return OPERATOR_FINISHED;
2049}
2050
2051void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
2052{
2053 /* identifiers */
2054 ot->name = "Paste Line Set";
2055 ot->idname = "SCENE_OT_freestyle_lineset_paste";
2056 ot->description = "Paste the internal clipboard content to the active line set";
2057
2058 /* API callbacks. */
2059 ot->exec = freestyle_lineset_paste_exec;
2060 ot->poll = freestyle_active_lineset_poll;
2061
2062 /* flags */
2064}
2065
2067
2068/* -------------------------------------------------------------------- */
2071
2072static wmOperatorStatus freestyle_lineset_remove_exec(bContext *C, wmOperator * /*op*/)
2073{
2074 Scene *scene = CTX_data_scene(C);
2075 ViewLayer *view_layer = CTX_data_view_layer(C);
2076
2078
2081
2082 return OPERATOR_FINISHED;
2083}
2084
2085void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
2086{
2087 /* identifiers */
2088 ot->name = "Remove Line Set";
2089 ot->idname = "SCENE_OT_freestyle_lineset_remove";
2090 ot->description = "Remove the active line set from the list of line sets";
2091
2092 /* API callbacks. */
2093 ot->exec = freestyle_lineset_remove_exec;
2094 ot->poll = freestyle_active_lineset_poll;
2095
2096 /* flags */
2098}
2099
2101
2102/* -------------------------------------------------------------------- */
2105
2106static wmOperatorStatus freestyle_lineset_move_exec(bContext *C, wmOperator *op)
2107{
2108 Scene *scene = CTX_data_scene(C);
2109 ViewLayer *view_layer = CTX_data_view_layer(C);
2110 int dir = RNA_enum_get(op->ptr, "direction");
2111
2112 if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
2115 }
2116
2117 return OPERATOR_FINISHED;
2118}
2119
2120void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
2121{
2122 static const EnumPropertyItem direction_items[] = {
2123 {-1, "UP", 0, "Up", ""},
2124 {1, "DOWN", 0, "Down", ""},
2125 {0, nullptr, 0, nullptr, nullptr},
2126 };
2127
2128 /* identifiers */
2129 ot->name = "Move Line Set";
2130 ot->idname = "SCENE_OT_freestyle_lineset_move";
2131 ot->description = "Change the position of the active line set within the list of line sets";
2132
2133 /* API callbacks. */
2134 ot->exec = freestyle_lineset_move_exec;
2135 ot->poll = freestyle_active_lineset_poll;
2136
2137 /* flags */
2139
2140 /* props */
2141 RNA_def_enum(ot->srna,
2142 "direction",
2143 direction_items,
2144 0,
2145 "Direction",
2146 "Direction to move the active line set towards");
2147}
2148
2150
2151/* -------------------------------------------------------------------- */
2154
2155static wmOperatorStatus freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
2156{
2157 Main *bmain = CTX_data_main(C);
2158 ViewLayer *view_layer = CTX_data_view_layer(C);
2160
2161 if (!lineset) {
2162 BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
2163 return OPERATOR_CANCELLED;
2164 }
2165 if (lineset->linestyle) {
2166 id_us_min(&lineset->linestyle->id);
2167 lineset->linestyle = (FreestyleLineStyle *)BKE_id_copy(bmain, &lineset->linestyle->id);
2168 }
2169 else {
2170 lineset->linestyle = BKE_linestyle_new(bmain, DATA_("LineStyle"));
2171 }
2172 DEG_id_tag_update(&lineset->linestyle->id, 0);
2174
2175 return OPERATOR_FINISHED;
2176}
2177
2178void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
2179{
2180 /* identifiers */
2181 ot->name = "New Line Style";
2182 ot->idname = "SCENE_OT_freestyle_linestyle_new";
2183 ot->description = "Create a new line style, reusable by multiple line sets";
2184
2185 /* API callbacks. */
2186 ot->exec = freestyle_linestyle_new_exec;
2187 ot->poll = freestyle_active_lineset_poll;
2188
2189 /* flags */
2191}
2192
2194
2195/* -------------------------------------------------------------------- */
2198
2199static wmOperatorStatus freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
2200{
2201 ViewLayer *view_layer = CTX_data_view_layer(C);
2203 int type = RNA_enum_get(op->ptr, "type");
2204
2205 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2206 return OPERATOR_CANCELLED;
2207 }
2208
2209 if (BKE_linestyle_color_modifier_add(lineset->linestyle, nullptr, type) == nullptr) {
2210 BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
2211 return OPERATOR_CANCELLED;
2212 }
2213 DEG_id_tag_update(&lineset->linestyle->id, 0);
2215
2216 return OPERATOR_FINISHED;
2217}
2218
2219void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
2220{
2221 /* identifiers */
2222 ot->name = "Add Line Color Modifier";
2223 ot->idname = "SCENE_OT_freestyle_color_modifier_add";
2224 ot->description =
2225 "Add a line color modifier to the line style associated with the active lineset";
2226
2227 /* API callbacks. */
2228 ot->invoke = WM_menu_invoke;
2229 ot->exec = freestyle_color_modifier_add_exec;
2230 ot->poll = freestyle_active_lineset_poll;
2231
2232 /* flags */
2234
2235 /* properties */
2236 ot->prop = RNA_def_enum(
2237 ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
2238}
2239
2241
2242/* -------------------------------------------------------------------- */
2245
2246static wmOperatorStatus freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
2247{
2248 ViewLayer *view_layer = CTX_data_view_layer(C);
2250 int type = RNA_enum_get(op->ptr, "type");
2251
2252 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2253 return OPERATOR_CANCELLED;
2254 }
2255
2256 if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, nullptr, type) == nullptr) {
2257 BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
2258 return OPERATOR_CANCELLED;
2259 }
2260 DEG_id_tag_update(&lineset->linestyle->id, 0);
2262
2263 return OPERATOR_FINISHED;
2264}
2265
2266void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
2267{
2268 /* identifiers */
2269 ot->name = "Add Alpha Transparency Modifier";
2270 ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
2271 ot->description =
2272 "Add an alpha transparency modifier to the line style associated with the active lineset";
2273
2274 /* API callbacks. */
2275 ot->invoke = WM_menu_invoke;
2276 ot->exec = freestyle_alpha_modifier_add_exec;
2277 ot->poll = freestyle_active_lineset_poll;
2278
2279 /* flags */
2281
2282 /* properties */
2283 ot->prop = RNA_def_enum(
2284 ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
2285}
2286
2288
2289/* -------------------------------------------------------------------- */
2292
2293static wmOperatorStatus freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
2294{
2295 ViewLayer *view_layer = CTX_data_view_layer(C);
2297 int type = RNA_enum_get(op->ptr, "type");
2298
2299 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2300 return OPERATOR_CANCELLED;
2301 }
2302
2303 if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, nullptr, type) == nullptr) {
2304 BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
2305 return OPERATOR_CANCELLED;
2306 }
2307 DEG_id_tag_update(&lineset->linestyle->id, 0);
2309
2310 return OPERATOR_FINISHED;
2311}
2312
2313void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
2314{
2315 /* identifiers */
2316 ot->name = "Add Line Thickness Modifier";
2317 ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
2318 ot->description =
2319 "Add a line thickness modifier to the line style associated with the active lineset";
2320
2321 /* API callbacks. */
2322 ot->invoke = WM_menu_invoke;
2323 ot->exec = freestyle_thickness_modifier_add_exec;
2324 ot->poll = freestyle_active_lineset_poll;
2325
2326 /* flags */
2328
2329 /* properties */
2330 ot->prop = RNA_def_enum(
2331 ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
2332}
2333
2335
2336/* -------------------------------------------------------------------- */
2339
2340static wmOperatorStatus freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
2341{
2342 ViewLayer *view_layer = CTX_data_view_layer(C);
2344 int type = RNA_enum_get(op->ptr, "type");
2345
2346 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2347 return OPERATOR_CANCELLED;
2348 }
2349
2350 if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, nullptr, type) == nullptr) {
2351 BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
2352 return OPERATOR_CANCELLED;
2353 }
2354 DEG_id_tag_update(&lineset->linestyle->id, 0);
2356
2357 return OPERATOR_FINISHED;
2358}
2359
2360void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
2361{
2362 /* identifiers */
2363 ot->name = "Add Stroke Geometry Modifier";
2364 ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
2365 ot->description =
2366 "Add a stroke geometry modifier to the line style associated with the active lineset";
2367
2368 /* API callbacks. */
2369 ot->invoke = WM_menu_invoke;
2370 ot->exec = freestyle_geometry_modifier_add_exec;
2371 ot->poll = freestyle_active_lineset_poll;
2372
2373 /* flags */
2375
2376 /* properties */
2377 ot->prop = RNA_def_enum(
2378 ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
2379}
2380
2382
2383/* -------------------------------------------------------------------- */
2386
2387static int freestyle_get_modifier_type(PointerRNA *ptr)
2388{
2389 if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier)) {
2391 }
2392 if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier)) {
2394 }
2395 if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier)) {
2397 }
2398 if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier)) {
2400 }
2401 return -1;
2402}
2403
2404static wmOperatorStatus freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
2405{
2406 ViewLayer *view_layer = CTX_data_view_layer(C);
2408 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
2409 LineStyleModifier *modifier = static_cast<LineStyleModifier *>(ptr.data);
2410
2411 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2412 return OPERATOR_CANCELLED;
2413 }
2414
2415 switch (freestyle_get_modifier_type(&ptr)) {
2418 break;
2421 break;
2424 break;
2427 break;
2428 default:
2429 BKE_report(
2430 op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
2431 return OPERATOR_CANCELLED;
2432 }
2433 DEG_id_tag_update(&lineset->linestyle->id, 0);
2435
2436 return OPERATOR_FINISHED;
2437}
2438
2439void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
2440{
2441 /* identifiers */
2442 ot->name = "Remove Modifier";
2443 ot->idname = "SCENE_OT_freestyle_modifier_remove";
2444 ot->description = "Remove the modifier from the list of modifiers";
2445
2446 /* API callbacks. */
2447 ot->exec = freestyle_modifier_remove_exec;
2448 ot->poll = freestyle_active_lineset_poll;
2449
2450 /* flags */
2452}
2453
2455
2456/* -------------------------------------------------------------------- */
2459
2460static wmOperatorStatus freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
2461{
2462 ViewLayer *view_layer = CTX_data_view_layer(C);
2464 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
2465 LineStyleModifier *modifier = static_cast<LineStyleModifier *>(ptr.data);
2466
2467 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2468 return OPERATOR_CANCELLED;
2469 }
2470
2471 switch (freestyle_get_modifier_type(&ptr)) {
2473 BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
2474 break;
2476 BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
2477 break;
2479 BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
2480 break;
2482 BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
2483 break;
2484 default:
2485 BKE_report(
2486 op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
2487 return OPERATOR_CANCELLED;
2488 }
2489 DEG_id_tag_update(&lineset->linestyle->id, 0);
2491
2492 return OPERATOR_FINISHED;
2493}
2494
2495void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
2496{
2497 /* identifiers */
2498 ot->name = "Copy Modifier";
2499 ot->idname = "SCENE_OT_freestyle_modifier_copy";
2500 ot->description = "Duplicate the modifier within the list of modifiers";
2501
2502 /* API callbacks. */
2503 ot->exec = freestyle_modifier_copy_exec;
2504 ot->poll = freestyle_active_lineset_poll;
2505
2506 /* flags */
2508}
2509
2511
2512/* -------------------------------------------------------------------- */
2515
2516static wmOperatorStatus freestyle_modifier_move_exec(bContext *C, wmOperator *op)
2517{
2518 ViewLayer *view_layer = CTX_data_view_layer(C);
2520 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
2521 LineStyleModifier *modifier = static_cast<LineStyleModifier *>(ptr.data);
2522 int dir = RNA_enum_get(op->ptr, "direction");
2523 bool changed = false;
2524
2525 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
2526 return OPERATOR_CANCELLED;
2527 }
2528
2529 switch (freestyle_get_modifier_type(&ptr)) {
2531 changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
2532 break;
2534 changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
2535 break;
2537 changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
2538 break;
2540 changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
2541 break;
2542 default:
2543 BKE_report(
2544 op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
2545 return OPERATOR_CANCELLED;
2546 }
2547
2548 if (changed) {
2549 DEG_id_tag_update(&lineset->linestyle->id, 0);
2551 }
2552
2553 return OPERATOR_FINISHED;
2554}
2555
2556void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
2557{
2558 static const EnumPropertyItem direction_items[] = {
2559 {-1, "UP", 0, "Up", ""},
2560 {1, "DOWN", 0, "Down", ""},
2561 {0, nullptr, 0, nullptr, nullptr},
2562 };
2563
2564 /* identifiers */
2565 ot->name = "Move Modifier";
2566 ot->idname = "SCENE_OT_freestyle_modifier_move";
2567 ot->description = "Move the modifier within the list of modifiers";
2568
2569 /* API callbacks. */
2570 ot->exec = freestyle_modifier_move_exec;
2571 ot->poll = freestyle_active_lineset_poll;
2572
2573 /* flags */
2575
2576 /* props */
2577 RNA_def_enum(ot->srna,
2578 "direction",
2579 direction_items,
2580 0,
2581 "Direction",
2582 "Direction to move the chosen modifier towards");
2583}
2584
2586
2587/* -------------------------------------------------------------------- */
2590
2591static wmOperatorStatus freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
2592{
2593 Main *bmain = CTX_data_main(C);
2594 ViewLayer *view_layer = CTX_data_view_layer(C);
2596
2597 if (!linestyle) {
2598 BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
2599 return OPERATOR_CANCELLED;
2600 }
2601
2602 FRS_create_stroke_material(bmain, linestyle);
2603
2604 return OPERATOR_FINISHED;
2605}
2606
2607void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
2608{
2609 /* identifiers */
2610 ot->name = "Create Freestyle Stroke Material";
2611 ot->idname = "SCENE_OT_freestyle_stroke_material_create";
2612 ot->description = "Create Freestyle stroke material for testing";
2613
2614 /* API callbacks. */
2615 ot->exec = freestyle_stroke_material_create_exec;
2616
2617 /* flags */
2618 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2619}
2620
2622
2623#endif /* WITH_FREESTYLE */
2624
2625/* -------------------------------------------------------------------- */
2628
2630{
2631 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
2632
2633 if (id) {
2634 MTex **mtex_ar, *mtexswap;
2635 short act;
2636 int type = RNA_enum_get(op->ptr, "type");
2637 AnimData *adt = BKE_animdata_from_id(id);
2638
2639 give_active_mtex(id, &mtex_ar, &act);
2640
2641 if (type == -1) { /* Up */
2642 if (act > 0) {
2643 mtexswap = mtex_ar[act];
2644 mtex_ar[act] = mtex_ar[act - 1];
2645 mtex_ar[act - 1] = mtexswap;
2646
2648 id, adt, nullptr, "texture_slots", nullptr, nullptr, act - 1, -1, false);
2650 id, adt, nullptr, "texture_slots", nullptr, nullptr, act, act - 1, false);
2652 id, adt, nullptr, "texture_slots", nullptr, nullptr, -1, act, false);
2653
2654 set_active_mtex(id, act - 1);
2655 }
2656 }
2657 else { /* Down */
2658 if (act < MAX_MTEX - 1) {
2659 mtexswap = mtex_ar[act];
2660 mtex_ar[act] = mtex_ar[act + 1];
2661 mtex_ar[act + 1] = mtexswap;
2662
2664 id, adt, nullptr, "texture_slots", nullptr, nullptr, act + 1, -1, false);
2666 id, adt, nullptr, "texture_slots", nullptr, nullptr, act, act + 1, false);
2668 id, adt, nullptr, "texture_slots", nullptr, nullptr, -1, act, false);
2669
2670 set_active_mtex(id, act + 1);
2671 }
2672 }
2673
2674 DEG_id_tag_update(id, 0);
2676 }
2677
2678 return OPERATOR_FINISHED;
2679}
2680
2682{
2683 static const EnumPropertyItem slot_move[] = {
2684 {-1, "UP", 0, "Up", ""},
2685 {1, "DOWN", 0, "Down", ""},
2686 {0, nullptr, 0, nullptr, nullptr},
2687 };
2688
2689 /* identifiers */
2690 ot->name = "Move Texture Slot";
2691 ot->idname = "TEXTURE_OT_slot_move";
2692 ot->description = "Move texture slots up and down";
2693
2694 /* API callbacks. */
2695 ot->exec = texture_slot_move_exec;
2696
2697 /* flags */
2699
2700 RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
2701}
2702
2704
2705/* -------------------------------------------------------------------- */
2708
2710{
2711 using namespace blender::bke::blendfile;
2712
2713 Material *ma = static_cast<Material *>(
2714 CTX_data_pointer_get_type(C, "material", &RNA_Material).data);
2715
2716 if (ma == nullptr) {
2717 return OPERATOR_CANCELLED;
2718 }
2719 if (ID_IS_PACKED(&ma->id)) {
2720 /* Direct link/append of packed IDs is not supported currently, so neither is their
2721 * copy/pasting. */
2722 return OPERATOR_CANCELLED;
2723 }
2724
2725 Main *bmain = CTX_data_main(C);
2726 PartialWriteContext copybuffer{*bmain};
2727
2728 /* Add the material to the copybuffer (and all of its dependencies). */
2729 copybuffer.id_add(
2730 &ma->id,
2731 PartialWriteContext::IDAddOptions{(PartialWriteContext::IDAddOperations::SET_FAKE_USER |
2732 PartialWriteContext::IDAddOperations::SET_CLIPBOARD_MARK |
2733 PartialWriteContext::IDAddOperations::ADD_DEPENDENCIES)},
2734 nullptr);
2735
2736 char filepath[FILE_MAX];
2737 material_copybuffer_filepath_get(filepath, sizeof(filepath));
2738 copybuffer.write(filepath, *op->reports);
2739
2740 /* We are all done! */
2741 BKE_report(op->reports, RPT_INFO, "Copied material to internal clipboard");
2742
2743 return OPERATOR_FINISHED;
2744}
2745
2747{
2748 /* identifiers */
2749 ot->name = "Copy Material";
2750 ot->idname = "MATERIAL_OT_copy";
2751 ot->description = "Copy the material settings and nodes";
2752
2753 /* API callbacks. */
2754 ot->exec = copy_material_exec;
2756
2757 /* flags */
2758 /* no undo needed since no changes are made to the material */
2760}
2761
2763
2764/* -------------------------------------------------------------------- */
2767
2772{
2773 if (cb_data->cb_flag & IDWALK_CB_USER) {
2774 id_us_min(*cb_data->id_pointer);
2775 }
2776 *cb_data->id_pointer = nullptr;
2777 return IDWALK_RET_NOP;
2778}
2779
2784{
2785 Main *bmain = static_cast<Main *>(cb_data->user_data);
2786 ID **id_p = cb_data->id_pointer;
2787 if (*id_p) {
2788 if (cb_data->cb_flag & IDWALK_CB_USER) {
2789 id_us_min(*id_p);
2790 }
2791 ListBase *lb = which_libbase(bmain, GS((*id_p)->name));
2792 ID *id_local = static_cast<ID *>(
2793 BLI_findstring(lb, (*id_p)->name + 2, offsetof(ID, name) + 2));
2794 *id_p = id_local;
2795 if (cb_data->cb_flag & IDWALK_CB_USER) {
2796 id_us_plus(id_local);
2797 }
2798 else if (cb_data->cb_flag & IDWALK_CB_USER_ONE) {
2799 id_us_ensure_real(id_local);
2800 }
2801 id_lib_extern(id_local);
2802 }
2803 return IDWALK_RET_NOP;
2804}
2805
2807{
2808 Main *bmain = CTX_data_main(C);
2809 Material *ma = static_cast<Material *>(
2810 CTX_data_pointer_get_type(C, "material", &RNA_Material).data);
2811
2812 if (ma == nullptr) {
2813 BKE_report(op->reports, RPT_WARNING, "Cannot paste without a material");
2814 return OPERATOR_CANCELLED;
2815 }
2816
2817 /* Read copy buffer .blend file. */
2818 char filepath[FILE_MAX];
2819 Main *temp_bmain = BKE_main_new();
2820
2822
2823 material_copybuffer_filepath_get(filepath, sizeof(filepath));
2824
2825 /* NOTE(@ideasman42) The node tree might reference different kinds of ID types.
2826 * It's not clear-cut which ID types should be included, although it's unlikely
2827 * users would want an entire scene & it's objects to be included.
2828 * Filter a subset of ID types with some reasons for including them. */
2829 const uint64_t ntree_filter = (
2830 /* Material is necessary for reading the clipboard. */
2831 FILTER_ID_MA |
2832 /* Node-groups. */
2833 FILTER_ID_NT |
2834 /* Image textures. */
2835 FILTER_ID_IM |
2836 /* Internal text (scripts). */
2838 /* Texture coordinates may reference objects.
2839 * Note that object data is *not* included. */
2840 FILTER_ID_OB);
2841
2842 if (!BKE_copybuffer_read(temp_bmain, filepath, op->reports, ntree_filter)) {
2843 BKE_report(op->reports, RPT_ERROR, "Internal clipboard is empty");
2844 BKE_main_free(temp_bmain);
2845 return OPERATOR_CANCELLED;
2846 }
2847
2848 /* There may be multiple materials,
2849 * check for a property that marks this as the active material. */
2850 Material *ma_from = nullptr;
2851 LISTBASE_FOREACH (Material *, ma_iter, &temp_bmain->materials) {
2852 if (ma_iter->id.flag & ID_FLAG_CLIPBOARD_MARK) {
2853 ma_from = ma_iter;
2854 break;
2855 }
2856 }
2857
2858 /* Make sure data from this file is usable for material paste. */
2859 if (ma_from == nullptr) {
2860 BKE_report(op->reports, RPT_ERROR, "Internal clipboard is not from a material");
2861 BKE_main_free(temp_bmain);
2862 return OPERATOR_CANCELLED;
2863 }
2864
2865 /* Keep animation by moving local animation to the paste node-tree. */
2866 if (ma->nodetree && ma_from->nodetree) {
2867 BLI_assert(ma_from->nodetree->adt == nullptr);
2868 std::swap(ma->nodetree->adt, ma_from->nodetree->adt);
2869 }
2870
2871 /* Needed to update #SpaceNode::nodetree else a stale pointer is used. */
2872 if (ma->nodetree) {
2873 bNodeTree *nodetree = ma->nodetree;
2875
2876 /* Free & clear data here, so user counts are handled, otherwise it's
2877 * freed as part of #BKE_main_free which doesn't handle user-counts. */
2878 /* Walk over all the embedded nodes ID's (non-recursively). */
2880 bmain, &nodetree->id, paste_material_nodetree_ids_decref, nullptr, IDWALK_NOP);
2881
2883 MEM_freeN(nodetree);
2884 ma->nodetree = nullptr;
2885 }
2886
2887/* Swap data-block content, while swapping isn't always needed,
2888 * it means memory is properly freed in the case of allocations.. */
2889#define SWAP_MEMBER(member) std::swap(ma->member, ma_from->member)
2890
2891 /* Intentionally skip:
2892 * - Texture painting slots.
2893 * - Preview render.
2894 * - Grease pencil styles (we could although they reference many ID's themselves).
2895 */
2897 SWAP_MEMBER(r);
2898 SWAP_MEMBER(g);
2899 SWAP_MEMBER(b);
2900 SWAP_MEMBER(a);
2901 SWAP_MEMBER(specr);
2902 SWAP_MEMBER(specg);
2903 SWAP_MEMBER(specb);
2904 SWAP_MEMBER(spec);
2905 SWAP_MEMBER(roughness);
2906 SWAP_MEMBER(metallic);
2907 SWAP_MEMBER(index);
2908 SWAP_MEMBER(nodetree);
2909 SWAP_MEMBER(line_col);
2910 SWAP_MEMBER(line_priority);
2911 SWAP_MEMBER(vcol_alpha);
2912
2913 SWAP_MEMBER(alpha_threshold);
2914 SWAP_MEMBER(refract_depth);
2915 SWAP_MEMBER(blend_method);
2916 SWAP_MEMBER(blend_shadow);
2917 SWAP_MEMBER(blend_flag);
2918
2919 SWAP_MEMBER(lineart);
2920
2921#undef SWAP_MEMBER
2922
2923 /* The node-tree from the clipboard is now assigned to the local material,
2924 * however the ID's it references are still part of `temp_bmain`.
2925 * These data-blocks references must be cleared or replaces with references to `bmain`.
2926 * TODO(@ideasman42): support merging indirectly referenced data-blocks besides the material,
2927 * this would be useful for pasting materials with node-groups between files. */
2928 if (ma->nodetree) {
2929 /* This implicitly points to local data, assign after remapping. */
2930 ma->nodetree->owner_id = nullptr;
2931
2932 /* Map remote ID's to local ones. */
2935
2936 ma->nodetree->owner_id = &ma->id;
2937 }
2938 BKE_main_free(temp_bmain);
2939
2940 /* Important to run this when the embedded tree if freed,
2941 * otherwise the depsgraph holds a reference to the (now freed) `ma->nodetree`.
2942 * Also run this when a new node-tree is set to ensure it's accounted for.
2943 * This also applies to animation data which is likely to be stored in the depsgraph.
2944 * Always call instead of checking when it *might* be needed. */
2946
2947 /* There are some custom updates to the node tree above, better do a full update pass. */
2950
2953
2954 return OPERATOR_FINISHED;
2955}
2956
2958{
2959 /* identifiers */
2960 ot->name = "Paste Material";
2961 ot->idname = "MATERIAL_OT_paste";
2962 ot->description = "Paste the material settings and nodes";
2963
2964 /* API callbacks. */
2965 ot->exec = paste_material_exec;
2967
2968 /* flags */
2970}
2971
2973
2974/* -------------------------------------------------------------------- */
2977
2978static short mtexcopied = 0; /* must be reset on file load */
2980
2982{ /* use for file reload */
2983 mtexcopied = 0;
2984}
2985
2986static void copy_mtex_copybuf(ID *id)
2987{
2988 MTex **mtex = nullptr;
2989
2990 switch (GS(id->name)) {
2991 case ID_PA:
2992 mtex = &(((ParticleSettings *)id)->mtex[int(((ParticleSettings *)id)->texact)]);
2993 break;
2994 case ID_LS:
2995 mtex = &(((FreestyleLineStyle *)id)->mtex[int(((FreestyleLineStyle *)id)->texact)]);
2996 break;
2997 default:
2998 break;
2999 }
3000
3001 if (mtex && *mtex) {
3002 mtexcopybuf = blender::dna::shallow_copy(**mtex);
3003 mtexcopied = 1;
3004 }
3005 else {
3006 mtexcopied = 0;
3007 }
3008}
3009
3010static void paste_mtex_copybuf(ID *id)
3011{
3012 MTex **mtex = nullptr;
3013
3014 if (mtexcopied == 0 || mtexcopybuf.tex == nullptr) {
3015 return;
3016 }
3017
3018 switch (GS(id->name)) {
3019 case ID_PA:
3020 mtex = &(((ParticleSettings *)id)->mtex[int(((ParticleSettings *)id)->texact)]);
3021 break;
3022 case ID_LS:
3023 mtex = &(((FreestyleLineStyle *)id)->mtex[int(((FreestyleLineStyle *)id)->texact)]);
3024 break;
3025 default:
3026 BLI_assert_msg(0, "invalid id type");
3027 return;
3028 }
3029
3030 if (mtex) {
3031 if (*mtex == nullptr) {
3032 *mtex = MEM_callocN<MTex>("mtex copy");
3033 }
3034 else if ((*mtex)->tex) {
3035 id_us_min(&(*mtex)->tex->id);
3036 }
3037
3038 **mtex = blender::dna::shallow_copy(mtexcopybuf);
3039
3040 /* NOTE(@ideasman42): the simple memory copy has no special handling for ID data-blocks.
3041 * Ideally this would use `BKE_copybuffer_*` API's, however for common using
3042 * copy-pasting between slots, the case a users expects to copy between files
3043 * seems quite niche. So, do primitive ID validation. */
3044
3045 /* WARNING: This isn't a fool-proof solution as it's possible memory locations are reused,
3046 * or that the ID was relocated in memory since it was copied.
3047 * it does however guard against references to dangling pointers. */
3048 if ((*mtex)->tex && (BLI_findindex(&G_MAIN->textures, (*mtex)->tex) == -1)) {
3049 (*mtex)->tex = nullptr;
3050 }
3051 if ((*mtex)->object && (BLI_findindex(&G_MAIN->objects, (*mtex)->object) == -1)) {
3052 (*mtex)->object = nullptr;
3053 }
3054 id_us_plus((ID *)(*mtex)->tex);
3055 id_lib_extern((ID *)(*mtex)->object);
3056 }
3057}
3058
3060
3061/* -------------------------------------------------------------------- */
3064
3066{
3067 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
3068
3069 if (id == nullptr) {
3070 /* copying empty slot */
3072 return OPERATOR_CANCELLED;
3073 }
3074
3076
3077 return OPERATOR_FINISHED;
3078}
3079
3081{
3082 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
3083
3084 return (id != nullptr);
3085}
3086
3088{
3089 /* identifiers */
3090 ot->name = "Copy Texture Slot Settings";
3091 ot->idname = "TEXTURE_OT_slot_copy";
3092 ot->description = "Copy the material texture settings and nodes";
3093
3094 /* API callbacks. */
3095 ot->exec = copy_mtex_exec;
3096 ot->poll = copy_mtex_poll;
3097
3098 /* flags */
3099 /* no undo needed since no changes are made to the mtex */
3101}
3102
3104
3105/* -------------------------------------------------------------------- */
3108
3110{
3111 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
3112
3113 if (id == nullptr) {
3114 Material *ma = static_cast<Material *>(
3115 CTX_data_pointer_get_type(C, "material", &RNA_Material).data);
3116 Light *la = static_cast<Light *>(CTX_data_pointer_get_type(C, "light", &RNA_Light).data);
3117 World *wo = static_cast<World *>(CTX_data_pointer_get_type(C, "world", &RNA_World).data);
3118 ParticleSystem *psys = static_cast<ParticleSystem *>(
3119 CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data);
3120 FreestyleLineStyle *linestyle = static_cast<FreestyleLineStyle *>(
3121 CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data);
3122
3123 if (ma) {
3124 id = &ma->id;
3125 }
3126 else if (la) {
3127 id = &la->id;
3128 }
3129 else if (wo) {
3130 id = &wo->id;
3131 }
3132 else if (psys) {
3133 id = &psys->part->id;
3134 }
3135 else if (linestyle) {
3136 id = &linestyle->id;
3137 }
3138
3139 if (id == nullptr) {
3140 return OPERATOR_CANCELLED;
3141 }
3142 }
3143
3145
3147
3148 return OPERATOR_FINISHED;
3149}
3150
3152{
3153 /* identifiers */
3154 ot->name = "Paste Texture Slot Settings";
3155 ot->idname = "TEXTURE_OT_slot_paste";
3156 ot->description = "Copy the texture settings and nodes";
3157
3158 /* API callbacks. */
3159 ot->exec = paste_mtex_exec;
3160
3161 /* flags */
3163}
3164
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, struct ID *ref_id, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
const char * BKE_tempdir_base() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:1243
bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *reports, uint64_t id_types_mask)
#define FOREACH_SCENE_OBJECT_END
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
#define CTX_DATA_BEGIN(C, Type, instance, member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define CTX_DATA_END
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
ListBase * BKE_curve_editNurbs_get(Curve *cu)
Definition curve.cc:419
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
struct FreestyleModuleConfig * BKE_freestyle_module_add(struct FreestyleConfig *config)
Definition freestyle.cc:116
struct FreestyleLineSet * BKE_freestyle_lineset_add(struct Main *bmain, struct FreestyleConfig *config, const char *name)
Definition freestyle.cc:163
struct FreestyleLineSet * BKE_freestyle_lineset_get_active(struct FreestyleConfig *config)
Definition freestyle.cc:212
bool BKE_freestyle_module_move(struct FreestyleConfig *config, struct FreestyleModuleConfig *module_conf, int direction)
Definition freestyle.cc:140
bool BKE_freestyle_module_delete(struct FreestyleConfig *config, struct FreestyleModuleConfig *module_conf)
Definition freestyle.cc:131
#define G_MAIN
ViewLayerLightgroup * BKE_view_layer_add_lightgroup(ViewLayer *view_layer, const char *name)
void BKE_view_layer_remove_aov(ViewLayer *view_layer, ViewLayerAOV *aov)
void BKE_view_layer_remove_lightgroup(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup)
#define FOREACH_OBJECT_END
Definition BKE_layer.hh:432
#define FOREACH_OBJECT_BEGIN(scene, view_layer, _instance)
Definition BKE_layer.hh:422
@ VIEWLAYER_ADD_NEW
Definition BKE_layer.hh:34
@ VIEWLAYER_ADD_EMPTY
Definition BKE_layer.hh:35
@ VIEWLAYER_ADD_COPY
Definition BKE_layer.hh:36
void BKE_view_layer_verify_aov(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
blender::Vector< Object * > BKE_view_layer_array_selected_objects_params(ViewLayer *view_layer, const View3D *v3d, const ObjectsInViewLayerParams *params)
ViewLayer * BKE_view_layer_add(Scene *scene, const char *name, ViewLayer *view_layer_source, int type)
ViewLayerAOV * BKE_view_layer_add_aov(ViewLayer *view_layer)
void id_lib_extern(ID *id)
Definition lib_id.cc:290
void id_us_plus(ID *id)
Definition lib_id.cc:358
void BKE_id_move_to_same_lib(Main &bmain, ID &id, const ID &owner_id)
Definition lib_id.cc:879
void id_us_ensure_real(ID *id)
Definition lib_id.cc:313
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:782
@ LIB_ID_COPY_ACTIONS
@ LIB_ID_COPY_DEFAULT
void id_us_min(ID *id)
Definition lib_id.cc:366
@ IDWALK_RET_NOP
@ IDWALK_CB_USER_ONE
@ IDWALK_CB_USER
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_NOP
void void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(1
@ ID_REMAP_FORCE_UI_POINTERS
General operations for probes.
void BKE_lightprobe_cache_free(struct Object *object)
void BKE_lightprobe_cache_create(struct Object *object)
Blender kernel freestyle line style functionality.
FreestyleLineStyle * BKE_linestyle_new(struct Main *bmain, const char *name)
Definition linestyle.cc:703
int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier)
int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier)
Definition linestyle.cc:930
LineStyleModifier * BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m, int flag)
LineStyleModifier * BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m, int flag)
bool BKE_linestyle_thickness_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
LineStyleModifier * BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
#define LS_MODIFIER_TYPE_COLOR
#define LS_MODIFIER_TYPE_ALPHA
bool BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
LineStyleModifier * BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
FreestyleLineStyle * BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer)
Definition linestyle.cc:714
LineStyleModifier * BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
Definition linestyle.cc:780
int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier)
#define LS_MODIFIER_TYPE_GEOMETRY
bool BKE_linestyle_alpha_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
bool BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
LineStyleModifier * BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m, int flag)
Definition linestyle.cc:838
#define LS_MODIFIER_TYPE_THICKNESS
LineStyleModifier * BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
LineStyleModifier * BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m, int flag)
int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier)
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:902
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_free(Main *bmain)
Definition main.cc:192
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:892
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
General operations, lookup, etc. for materials.
short * BKE_object_material_len_p(Object *ob)
Material ** BKE_object_material_get_p(Object *ob, short act)
void BKE_object_material_remap(Object *ob, const unsigned int *remap)
Material * BKE_gpencil_material_add(Main *bmain, const char *name)
bool BKE_object_material_slot_add(Main *bmain, Object *ob, bool set_active=true)
void BKE_object_material_array_assign(Main *bmain, Object *ob, Material ***matar, int totcol, bool to_object_only)
Material * BKE_material_add(Main *bmain, const char *name)
bool BKE_object_material_slot_used(Object *object, short actcol)
Material * BKE_object_material_get(Object *ob, short act)
int BKE_object_material_index_get_with_hint(Object *ob, const Material *ma, int hint_index)
Material *** BKE_object_material_array_p(Object *ob)
bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
void BKE_ntree_update_tag_all(bNodeTree *ntree)
void BKE_ntree_update_tag_id_changed(Main *bmain, ID *id)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_INFO
Definition BKE_report.hh:35
@ 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
bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv)
Definition scene.cc:2731
SceneRenderView * BKE_scene_add_render_view(Scene *sce, const char *name)
Definition scene.cc:2712
bool give_active_mtex(struct ID *id, struct MTex ***mtex_ar, short *act)
Definition texture.cc:480
void set_active_mtex(struct ID *id, short act)
Definition texture.cc:506
struct Tex * BKE_texture_add(struct Main *bmain, const char *name)
Definition texture.cc:370
int BKE_vfont_select_get(const Curve *cu, int *r_start, int *r_end)
Definition vfont.cc:408
struct World * BKE_world_add(struct Main *bmain, const char *name)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void range_vn_u(unsigned int *array_tar, int size, unsigned int start)
#define FILE_MAX
#define BLI_path_join(...)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
void BLI_string_replace_char(char *str, char src, char dst) ATTR_NONNULL(1)
unsigned int uint
#define ELEM(...)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_WORLD
#define CTX_DATA_(context, msgid)
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
ID and Library types, which are fundamental for SDNA.
#define ID_IS_PACKED(_id)
Definition DNA_ID.h:700
#define FILTER_ID_OB
Definition DNA_ID.h:1214
@ ID_RECALC_SHADING
Definition DNA_ID.h:1094
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1104
#define FILTER_ID_MA
Definition DNA_ID.h:1208
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define FILTER_ID_IM
Definition DNA_ID.h:1204
@ ID_FLAG_CLIPBOARD_MARK
Definition DNA_ID.h:799
#define FILTER_ID_NT
Definition DNA_ID.h:1213
#define FILTER_ID_TXT
Definition DNA_ID.h:1221
@ ID_LS
@ ID_PA
#define MAX_NAME
Definition DNA_defs.h:50
@ LIGHTPROBE_TYPE_VOLUME
@ OB_MODE_TEXTURE_PAINT
Object is a sort of wrapper for general info.
@ OB_SURF
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_LIGHTPROBE
#define OB_TYPE_SUPPORT_MATERIAL(_type)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
bool EDBM_deselect_by_material(BMEditMesh *em, short index, bool select)
void ED_node_shader_default(const bContext *C, Main *bmain, ID *id)
Definition node_edit.cc:513
bool ED_paint_proj_mesh_data_check(Scene &scene, Object &ob, bool *r_has_uvs, bool *r_has_mat, bool *r_has_tex, bool *r_has_stencil)
bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports) ATTR_NONNULL(1
bool ED_operator_object_active_local_editable_ex(bContext *C, const Object *ob)
void ED_undo_push_op(bContext *C, wmOperator *op)
Definition ed_undo.cc:359
bool FRS_move_active_lineset(struct FreestyleConfig *config, int direction)
void FRS_paste_active_lineset(struct FreestyleConfig *config)
struct Material * FRS_create_stroke_material(struct Main *bmain, struct FreestyleLineStyle *linestyle)
void FRS_copy_active_lineset(struct FreestyleConfig *config)
void FRS_delete_active_lineset(struct FreestyleConfig *config)
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
#define MAX_MTEX
Definition Stroke.h:31
void UI_context_active_but_prop_get_templateID(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop)
@ WM_JOB_TYPE_LIGHT_BAKE
Definition WM_api.hh:1802
#define NC_WORLD
Definition WM_types.hh:387
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DRAW
Definition WM_types.hh:461
#define ND_DATA
Definition WM_types.hh:509
#define NC_LINESTYLE
Definition WM_types.hh:400
#define ND_RENDER_OPTIONS
Definition WM_types.hh:435
#define ND_SHADING_PREVIEW
Definition WM_types.hh:480
#define NC_SCENE
Definition WM_types.hh:378
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_TOOLSETTINGS
Definition WM_types.hh:449
#define NC_MATERIAL
Definition WM_types.hh:380
#define ND_SELECT
Definition WM_types.hh:508
#define NC_TEXTURE
Definition WM_types.hh:381
#define ND_LAYER
Definition WM_types.hh:450
#define ND_OB_SHADING
Definition WM_types.hh:457
#define NC_OBJECT
Definition WM_types.hh:379
#define ND_SHADING_LINKS
Definition WM_types.hh:479
@ BM_ELEM_SELECT
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
BMesh const char void * data
unsigned long long int uint64_t
bool add_as(ForwardKey &&key)
Definition BLI_set.hh:256
bool contains_as(const ForwardKey &key) const
Definition BLI_set.hh:314
void append(const T &value)
bool is_empty() const
ID * id_add(const ID *id, IDAddOptions options, blender::FunctionRef< IDAddOperations(LibraryIDLinkCallbackData *cb_data, IDAddOptions options)> dependencies_filter_cb=nullptr)
bool write(const char *write_filepath, int write_flags, int remap_mode, ReportList &reports)
#define SELECT
#define offsetof(t, d)
bool ED_curve_nurb_select_check(const View3D *v3d, const Nurb *nu)
void * EEVEE_lightbake_job_data_alloc(Main *bmain, ViewLayer *view_layer, Scene *scene, blender::Vector< Object * > original_probes, std::string &report, int frame)
void EEVEE_lightbake_job(void *job_data, wmJobWorkerStatus *worker_status)
void EEVEE_lightbake_job_data_free(void *job_data)
wmJob * EEVEE_lightbake_job_create(wmWindowManager *wm, wmWindow *win, Main *bmain, ViewLayer *view_layer, Scene *scene, blender::Vector< Object * > original_probes, std::string &report, int delay_ms, int frame)
void EEVEE_lightbake_update(void *job_data)
#define GS(x)
#define select(A, B, C)
RenderEngineType * RE_engines_find(const char *idname)
RenderEngine * RE_engine_create(RenderEngineType *type)
void RE_engine_free(RenderEngine *engine)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
void node_tree_free_embedded_tree(bNodeTree *ntree)
Definition node.cc:4462
Object * context_object(const bContext *C)
blender::Vector< Object * > objects_in_mode_or_selected(bContext *C, bool(*filter_fn)(const Object *ob, void *user_data), void *filter_user_data)
void ntreeCompositUpdateRLayers(bNodeTree *ntree)
static struct PyModuleDef module
Definition python.cpp:796
const char * name
void ED_render_clear_mtex_copybuf()
static wmOperatorStatus material_slot_assign_exec(bContext *C, wmOperator *)
void OBJECT_OT_material_slot_remove_all(wmOperatorType *ot)
@ LIGHTCACHE_SUBSET_ACTIVE
@ LIGHTCACHE_SUBSET_SELECTED
@ LIGHTCACHE_SUBSET_ALL
static wmOperatorStatus render_view_remove_exec(bContext *C, wmOperator *)
void OBJECT_OT_material_slot_add(wmOperatorType *ot)
static wmOperatorStatus paste_mtex_exec(bContext *C, wmOperator *)
void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
static bool material_slot_remove_poll(bContext *C)
static wmOperatorStatus copy_material_exec(bContext *C, wmOperator *op)
static wmOperatorStatus material_slot_remove_all_exec(bContext *C, wmOperator *op)
static wmOperatorStatus lightprobe_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *)
static blender::Vector< Object * > lightprobe_cache_irradiance_volume_subset_get(bContext *C, wmOperator *op)
static wmOperatorStatus view_layer_remove_unused_lightgroups_exec(bContext *C, wmOperator *)
static wmOperatorStatus lightprobe_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_lightprobe_cache_free(wmOperatorType *ot)
void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
static bool object_array_for_shading_edit_mode_enabled_filter(const Object *ob, void *user_data)
static wmOperatorStatus new_material_exec(bContext *C, wmOperator *)
static MTex mtexcopybuf
void SCENE_OT_view_layer_remove_unused_lightgroups(wmOperatorType *ot)
static bool view_layer_remove_poll(bContext *C)
static void paste_mtex_copybuf(ID *id)
static wmOperatorStatus material_slot_remove_unused_exec(bContext *C, wmOperator *op)
static wmOperatorStatus material_slot_copy_exec(bContext *C, wmOperator *)
static void copy_mtex_copybuf(ID *id)
void OBJECT_OT_lightprobe_cache_bake(wmOperatorType *ot)
static wmOperatorStatus material_slot_select_exec(bContext *C, wmOperator *)
static wmOperatorStatus lightprobe_cache_free_exec(bContext *C, wmOperator *op)
static wmOperatorStatus new_world_exec(bContext *C, wmOperator *)
void OBJECT_OT_material_slot_select(wmOperatorType *ot)
void WORLD_OT_new(wmOperatorType *ot)
void OBJECT_OT_material_slot_remove_unused(wmOperatorType *ot)
void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
static bool object_array_for_shading_edit_mode_disabled_filter(const Object *ob, void *user_data)
static wmOperatorStatus lightprobe_cache_bake_exec(bContext *C, wmOperator *op)
static wmOperatorStatus material_slot_remove_exec(bContext *C, wmOperator *)
void MATERIAL_OT_paste(wmOperatorType *ot)
static wmOperatorStatus material_slot_deselect_exec(bContext *C, wmOperator *)
static wmOperatorStatus view_layer_add_exec(bContext *C, wmOperator *op)
void MATERIAL_OT_new(wmOperatorType *ot)
void SCENE_OT_view_layer_add(wmOperatorType *ot)
static wmOperatorStatus view_layer_add_lightgroup_exec(bContext *C, wmOperator *op)
void OBJECT_OT_material_slot_move(wmOperatorType *ot)
static wmOperatorStatus view_layer_add_aov_exec(bContext *C, wmOperator *)
void SCENE_OT_view_layer_add_used_lightgroups(wmOperatorType *ot)
void TEXTURE_OT_new(wmOperatorType *ot)
static bool render_view_remove_poll(bContext *C)
static bool object_materials_supported_poll(bContext *C)
void MATERIAL_OT_copy(wmOperatorType *ot)
static wmOperatorStatus material_slot_move_exec(bContext *C, wmOperator *op)
static wmOperatorStatus new_texture_exec(bContext *C, wmOperator *op)
void SCENE_OT_view_layer_remove_lightgroup(wmOperatorType *ot)
static int paste_material_nodetree_ids_decref(LibraryIDLinkCallbackData *cb_data)
static wmOperatorStatus render_view_add_exec(bContext *C, wmOperator *)
void TEXTURE_OT_slot_paste(wmOperatorType *ot)
static Vector< Object * > object_array_for_shading_edit_mode_enabled(bContext *C)
static wmOperatorStatus view_layer_remove_lightgroup_exec(bContext *C, wmOperator *)
void SCENE_OT_view_layer_add_aov(wmOperatorType *ot)
static wmOperatorStatus view_layer_remove_exec(bContext *C, wmOperator *)
void TEXTURE_OT_slot_copy(wmOperatorType *ot)
static int paste_material_nodetree_ids_relink_or_clear(LibraryIDLinkCallbackData *cb_data)
static wmOperatorStatus view_layer_remove_aov_exec(bContext *C, wmOperator *)
void SCENE_OT_render_view_add(wmOperatorType *ot)
void SCENE_OT_view_layer_remove_aov(wmOperatorType *ot)
void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
void TEXTURE_OT_slot_move(wmOperatorType *ot)
void SCENE_OT_view_layer_remove(wmOperatorType *ot)
static wmOperatorStatus paste_material_exec(bContext *C, wmOperator *op)
static bool material_slot_populated_poll(bContext *C)
void SCENE_OT_view_layer_add_lightgroup(wmOperatorType *ot)
static wmOperatorStatus copy_mtex_exec(bContext *C, wmOperator *)
static wmOperatorStatus material_slot_add_exec(bContext *C, wmOperator *)
static blender::Set< blender::StringRefNull > get_used_lightgroups(Scene *scene)
static void material_copybuffer_filepath_get(char filepath[FILE_MAX], size_t filepath_maxncpy)
static wmOperatorStatus material_slot_de_select(bContext *C, bool select)
static void lightprobe_cache_bake_cancel(bContext *C, wmOperator *op)
void SCENE_OT_render_view_remove(wmOperatorType *ot)
#define SWAP_MEMBER(member)
static wmOperatorStatus view_layer_add_used_lightgroups_exec(bContext *C, wmOperator *)
static bool object_materials_supported_poll_ex(bContext *C, const Object *ob)
static bool copy_mtex_poll(bContext *C)
static wmOperatorStatus texture_slot_move_exec(bContext *C, wmOperator *op)
static short mtexcopied
static Vector< Object * > object_array_for_shading_edit_mode_disabled(bContext *C)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
const EnumPropertyItem rna_enum_linestyle_thickness_modifier_type_items[]
const EnumPropertyItem rna_enum_linestyle_geometry_modifier_type_items[]
const EnumPropertyItem rna_enum_linestyle_color_modifier_type_items[]
const EnumPropertyItem rna_enum_linestyle_alpha_modifier_type_items[]
short mat_nr
uint8_t f1
struct EditFont * editfont
CharInfo * textbufinfo
Definition BKE_vfont.hh:43
struct FreestyleLineStyle * linestyle
Definition DNA_ID.h:414
LibraryForeachIDCallbackFlag cb_flag
void * last
void * first
char filepath[1024]
Definition BKE_main.hh:179
ListBase materials
Definition BKE_main.hh:284
struct bNodeTree * nodetree
struct Material ** mat
char * matbits
bool(* filter_fn)(const Object *ob, void *user_data)
Definition BKE_layer.hh:487
ParticleSettings * part
ID * owner_id
Definition RNA_types.hh:51
void * data
Definition RNA_types.hh:53
char engine[32]
void(* update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer)
Definition RE_engine.h:110
struct bNodeTree * compositing_node_group
struct RenderData r
ListBase view_layers
struct World * world
struct FreestyleConfig freestyle_config
ListBase lightgroups
ViewLayerLightgroup * active_lightgroup
ViewLayerAOV * active_aov
char name[64]
struct LightgroupMembership * lightgroup
struct AnimData * adt
wmEventType type
Definition WM_types.hh:757
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_cursor_wait(bool val)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_ESCKEY
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
void WM_jobs_kill_type(wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:623
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:247
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer)
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
uint8_t flag
Definition wm_window.cc:145