2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * The Original Code is Copyright (C) 2009 Blender Foundation.
18 * All rights reserved.
20 * Contributor(s): Blender Foundation
22 * ***** END GPL LICENSE BLOCK *****
25 /** \file blender/editors/render/render_shading.c
32 #include "MEM_guardedalloc.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_lamp_types.h"
36 #include "DNA_lightprobe_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_particle_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_world_types.h"
45 #include "BLI_utildefines.h"
46 #include "BLI_listbase.h"
47 #include "BLI_math_vector.h"
49 #include "BLT_translation.h"
51 #include "BKE_animsys.h"
52 #include "BKE_context.h"
53 #include "BKE_curve.h"
54 #include "BKE_editmesh.h"
56 #include "BKE_global.h"
57 #include "BKE_image.h"
58 #include "BKE_layer.h"
59 #include "BKE_library.h"
60 #include "BKE_linestyle.h"
62 #include "BKE_material.h"
63 #include "BKE_paint.h"
64 #include "BKE_report.h"
65 #include "BKE_scene.h"
66 #include "BKE_texture.h"
67 #include "BKE_workspace.h"
68 #include "BKE_world.h"
70 #include "DEG_depsgraph.h"
71 #include "DEG_depsgraph_build.h"
74 # include "BKE_freestyle.h"
75 # include "FRS_freestyle.h"
76 # include "RNA_enum_types.h"
79 #include "RNA_access.h"
84 #include "ED_object.h"
88 #include "ED_render.h"
90 #include "ED_screen.h"
92 #include "RNA_define.h"
94 #include "UI_interface.h"
96 #include "RE_pipeline.h"
98 #include "engines/eevee/eevee_lightcache.h"
100 #include "render_intern.h" // own include
103 * Object list for material operations.
104 * has exception for pinned object.
106 static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
108 ScrArea *sa = CTX_wm_area(C);
109 SpaceButs *sbuts = NULL;
111 if (sa->spacetype == SPACE_BUTS) {
112 sbuts = sa->spacedata.first;
114 else if (sa->spacetype == SPACE_VIEW3D) {
115 v3d = sa->spacedata.first;
119 if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
120 objects = MEM_mallocN(sizeof(*objects), __func__);
121 objects[0] = (Object *)sbuts->pinid;
125 ViewLayer *view_layer = CTX_data_view_layer(C);
126 objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_objects_len);
131 /********************** material slot operators *********************/
133 static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
135 Main *bmain = CTX_data_main(C);
136 Object *ob = ED_object_context(C);
139 return OPERATOR_CANCELLED;
141 BKE_object_material_slot_add(bmain, ob);
143 if (ob->mode & OB_MODE_TEXTURE_PAINT) {
144 Scene *scene = CTX_data_scene(C);
145 BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
146 WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
149 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
150 WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
151 WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
153 return OPERATOR_FINISHED;
156 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
159 ot->name = "Add Material Slot";
160 ot->idname = "OBJECT_OT_material_slot_add";
161 ot->description = "Add a new material slot";
164 ot->exec = material_slot_add_exec;
165 ot->poll = ED_operator_object_active_editable;
168 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
171 static int material_slot_remove_exec(bContext *C, wmOperator *op)
173 Object *ob = ED_object_context(C);
176 return OPERATOR_CANCELLED;
178 /* Removing material slots in edit mode screws things up, see bug #21822.*/
179 if (ob == CTX_data_edit_object(C)) {
180 BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
181 return OPERATOR_CANCELLED;
184 BKE_object_material_slot_remove(CTX_data_main(C), ob);
186 if (ob->mode & OB_MODE_TEXTURE_PAINT) {
187 Scene *scene = CTX_data_scene(C);
188 BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
189 WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
192 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
193 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
194 WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
195 WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
197 return OPERATOR_FINISHED;
200 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
203 ot->name = "Remove Material Slot";
204 ot->idname = "OBJECT_OT_material_slot_remove";
205 ot->description = "Remove the selected material slot";
208 ot->exec = material_slot_remove_exec;
209 ot->poll = ED_operator_object_active_editable;
212 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
215 static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
217 View3D *v3d = CTX_wm_view3d(C);
218 bool changed_multi = false;
220 uint objects_len = 0;
221 Object **objects = object_array_for_shading(C, &objects_len);
222 for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
223 Object *ob = objects[ob_index];
224 if (ob->actcol <= 0) {
227 bool changed = false;
228 if (ob->type == OB_MESH) {
229 BMEditMesh *em = BKE_editmesh_from_object(ob);
234 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
235 if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
237 efa->mat_nr = ob->actcol - 1;
242 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
244 ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
247 for (nu = nurbs->first; nu; nu = nu->next) {
248 if (ED_curve_nurb_select_check(v3d, nu)) {
250 nu->mat_nr = ob->actcol - 1;
255 else if (ob->type == OB_FONT) {
256 EditFont *ef = ((Curve *)ob->data)->editfont;
257 int i, selstart, selend;
259 if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) {
260 for (i = selstart; i <= selend; i++) {
262 ef->textbufinfo[i].mat_nr = ob->actcol;
268 changed_multi = true;
269 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
270 WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
275 return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
278 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
281 ot->name = "Assign Material Slot";
282 ot->idname = "OBJECT_OT_material_slot_assign";
283 ot->description = "Assign active material slot to selection";
286 ot->exec = material_slot_assign_exec;
287 ot->poll = ED_operator_object_active_editable;
290 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
293 static int material_slot_de_select(bContext *C, bool select)
295 bool changed_multi = false;
297 uint objects_len = 0;
298 Object **objects = object_array_for_shading(C, &objects_len);
299 for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
300 Object *ob = objects[ob_index];
301 bool changed = false;
303 if (ob->type == OB_MESH) {
304 BMEditMesh *em = BKE_editmesh_from_object(ob);
307 changed = EDBM_deselect_by_material(em, ob->actcol - 1, select);
310 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
311 ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
318 for (nu = nurbs->first; nu; nu = nu->next) {
319 if (nu->mat_nr == ob->actcol - 1) {
324 if (bezt->hide == 0) {
341 a = nu->pntsu * nu->pntsv;
346 if (select) bp->f1 |= SELECT;
347 else bp->f1 &= ~SELECT;
358 changed_multi = true;
359 DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
360 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
366 return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
369 static int material_slot_select_exec(bContext *C, wmOperator *UNUSED(op))
371 return material_slot_de_select(C, true);
374 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
377 ot->name = "Select Material Slot";
378 ot->idname = "OBJECT_OT_material_slot_select";
379 ot->description = "Select by active material slot";
382 ot->exec = material_slot_select_exec;
385 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
388 static int material_slot_deselect_exec(bContext *C, wmOperator *UNUSED(op))
390 return material_slot_de_select(C, false);
393 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
396 ot->name = "Deselect Material Slot";
397 ot->idname = "OBJECT_OT_material_slot_deselect";
398 ot->description = "Deselect by active material slot";
401 ot->exec = material_slot_deselect_exec;
404 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
408 static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op))
410 Main *bmain = CTX_data_main(C);
411 Object *ob = ED_object_context(C);
414 if (!ob || !(matar = give_matarar(ob)))
415 return OPERATOR_CANCELLED;
417 CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
419 if (ob != ob_iter && give_matarar(ob_iter)) {
420 if (ob->data != ob_iter->data)
421 assign_matarar(bmain, ob_iter, matar, ob->totcol);
423 if (ob_iter->totcol == ob->totcol) {
424 ob_iter->actcol = ob->actcol;
425 DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
426 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
432 return OPERATOR_FINISHED;
436 void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
439 ot->name = "Copy Material to Selected";
440 ot->idname = "OBJECT_OT_material_slot_copy";
441 ot->description = "Copy material to selected objects";
444 ot->exec = material_slot_copy_exec;
447 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
450 static int material_slot_move_exec(bContext *C, wmOperator *op)
452 Object *ob = ED_object_context(C);
454 unsigned int *slot_remap;
457 int dir = RNA_enum_get(op->ptr, "direction");
459 if (!ob || ob->totcol < 2) {
460 return OPERATOR_CANCELLED;
464 if (dir == 1 && ob->actcol > 1) {
465 index_pair[0] = ob->actcol - 2;
466 index_pair[1] = ob->actcol - 1;
470 else if (dir == -1 && ob->actcol < ob->totcol) {
471 index_pair[0] = ob->actcol - 1;
472 index_pair[1] = ob->actcol - 0;
476 return OPERATOR_CANCELLED;
479 slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
481 range_vn_u(slot_remap, ob->totcol, 0);
483 slot_remap[index_pair[0]] = index_pair[1];
484 slot_remap[index_pair[1]] = index_pair[0];
486 BKE_material_remap_object(ob, slot_remap);
488 MEM_freeN(slot_remap);
490 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
491 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
492 WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
494 return OPERATOR_FINISHED;
497 void OBJECT_OT_material_slot_move(wmOperatorType *ot)
499 static const EnumPropertyItem material_slot_move[] = {
500 {1, "UP", 0, "Up", ""},
501 {-1, "DOWN", 0, "Down", ""},
502 {0, NULL, 0, NULL, NULL}
506 ot->name = "Move Material";
507 ot->idname = "OBJECT_OT_material_slot_move";
508 ot->description = "Move the active material up/down in the list";
511 ot->exec = material_slot_move_exec;
514 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
516 RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction",
517 "Direction to move the active material towards");
520 /********************** new material operator *********************/
522 static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
524 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
525 Main *bmain = CTX_data_main(C);
526 Object *ob = CTX_data_active_object(C);
527 PointerRNA ptr, idptr;
530 /* add or copy material */
532 ma = BKE_material_copy(bmain, ma);
535 if ((!ob) || (ob->type != OB_GPENCIL)) {
536 ma = BKE_material_add(bmain, DATA_("Material"));
539 ma = BKE_material_add_gpencil(bmain, DATA_("Material"));
541 ED_node_shader_default(C, &ma->id);
542 ma->use_nodes = true;
546 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
549 /* when creating new ID blocks, use is already 1, but RNA
550 * pointer use also increases user, so this compensates it */
553 RNA_id_pointer_create(&ma->id, &idptr);
554 RNA_property_pointer_set(&ptr, prop, idptr);
555 RNA_property_update(C, &ptr, prop);
558 WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
560 return OPERATOR_FINISHED;
563 void MATERIAL_OT_new(wmOperatorType *ot)
566 ot->name = "New Material";
567 ot->idname = "MATERIAL_OT_new";
568 ot->description = "Add a new material";
571 ot->exec = new_material_exec;
574 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
577 /********************** new texture operator *********************/
579 static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
581 Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
582 Main *bmain = CTX_data_main(C);
583 PointerRNA ptr, idptr;
586 /* add or copy texture */
588 tex = BKE_texture_copy(bmain, tex);
591 tex = BKE_texture_add(bmain, DATA_("Texture"));
595 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
598 /* when creating new ID blocks, use is already 1, but RNA
599 * pointer use also increases user, so this compensates it */
602 RNA_id_pointer_create(&tex->id, &idptr);
603 RNA_property_pointer_set(&ptr, prop, idptr);
604 RNA_property_update(C, &ptr, prop);
607 WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
609 return OPERATOR_FINISHED;
612 void TEXTURE_OT_new(wmOperatorType *ot)
615 ot->name = "New Texture";
616 ot->idname = "TEXTURE_OT_new";
617 ot->description = "Add a new texture";
620 ot->exec = new_texture_exec;
623 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
626 /********************** new world operator *********************/
628 static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
630 World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
631 Main *bmain = CTX_data_main(C);
632 PointerRNA ptr, idptr;
635 /* add or copy world */
637 wo = BKE_world_copy(bmain, wo);
640 wo = BKE_world_add(bmain, DATA_("World"));
641 ED_node_shader_default(C, &wo->id);
642 wo->use_nodes = true;
646 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
649 /* when creating new ID blocks, use is already 1, but RNA
650 * pointer use also increases user, so this compensates it */
653 RNA_id_pointer_create(&wo->id, &idptr);
654 RNA_property_pointer_set(&ptr, prop, idptr);
655 RNA_property_update(C, &ptr, prop);
658 WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
660 return OPERATOR_FINISHED;
663 void WORLD_OT_new(wmOperatorType *ot)
666 ot->name = "New World";
667 ot->idname = "WORLD_OT_new";
668 ot->description = "Create a new world Data-Block";
671 ot->exec = new_world_exec;
674 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
677 /********************** render layer operators *********************/
679 static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
681 wmWindow *win = CTX_wm_window(C);
682 Scene *scene = CTX_data_scene(C);
683 ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
686 WM_window_set_active_view_layer(win, view_layer);
689 DEG_id_tag_update(&scene->id, 0);
690 DEG_relations_tag_update(CTX_data_main(C));
691 WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
693 return OPERATOR_FINISHED;
696 void SCENE_OT_view_layer_add(wmOperatorType *ot)
699 ot->name = "Add View Layer";
700 ot->idname = "SCENE_OT_view_layer_add";
701 ot->description = "Add a view layer";
704 ot->exec = view_layer_add_exec;
707 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
710 static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
712 Main *bmain = CTX_data_main(C);
713 Scene *scene = CTX_data_scene(C);
714 ViewLayer *view_layer = CTX_data_view_layer(C);
716 if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
717 return OPERATOR_CANCELLED;
720 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
722 return OPERATOR_FINISHED;
725 void SCENE_OT_view_layer_remove(wmOperatorType *ot)
728 ot->name = "Remove View Layer";
729 ot->idname = "SCENE_OT_view_layer_remove";
730 ot->description = "Remove the selected view layer";
733 ot->exec = view_layer_remove_exec;
736 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
739 /********************** light cache operators *********************/
741 LIGHTCACHE_SUBSET_ALL = 0,
742 LIGHTCACHE_SUBSET_DIRTY,
743 LIGHTCACHE_SUBSET_CUBE,
746 static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
748 if (scene->eevee.light_cache != NULL) {
749 int subset = RNA_enum_get(op->ptr, "subset");
751 case LIGHTCACHE_SUBSET_ALL:
752 scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
754 case LIGHTCACHE_SUBSET_CUBE:
755 scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
757 case LIGHTCACHE_SUBSET_DIRTY:
758 /* Leave tag untouched. */
765 static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
767 Scene *scene = (Scene *) op->customdata;
769 /* no running blender, remove handler and pass through */
770 if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
771 return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
775 switch (event->type) {
777 return OPERATOR_RUNNING_MODAL;
779 return OPERATOR_PASS_THROUGH;
782 static void light_cache_bake_cancel(bContext *C, wmOperator *op)
784 wmWindowManager *wm = CTX_wm_manager(C);
785 Scene *scene = (Scene *) op->customdata;
787 /* kill on cancel, because job is using op->reports */
788 WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
791 /* executes blocking render */
792 static int light_cache_bake_exec(bContext *C, wmOperator *op)
794 ViewLayer *view_layer = CTX_data_view_layer(C);
795 Main *bmain = CTX_data_main(C);
796 Scene *scene = CTX_data_scene(C);
800 /* TODO abort if selected engine is not eevee. */
801 void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false);
803 light_cache_bake_tag_cache(scene, op);
805 short stop = 0, do_update; float progress; /* Not actually used. */
806 EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
807 EEVEE_lightbake_job_data_free(rj);
809 // no redraw needed, we leave state as we entered it
810 ED_update_for_newframe(bmain, CTX_data_depsgraph(C));
812 WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
814 return OPERATOR_FINISHED;
817 static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
819 wmWindowManager *wm = CTX_wm_manager(C);
820 wmWindow *win = CTX_wm_window(C);
821 ViewLayer *view_layer = CTX_data_view_layer(C);
822 Main *bmain = CTX_data_main(C);
823 Scene *scene = CTX_data_scene(C);
824 int delay = RNA_int_get(op->ptr, "delay");
826 wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay);
829 return OPERATOR_CANCELLED;
832 /* add modal handler for ESC */
833 WM_event_add_modal_handler(C, op);
835 light_cache_bake_tag_cache(scene, op);
837 /* store actual owner of job, so modal operator could check for it,
838 * the reason of this is that active scene could change when rendering
839 * several layers from compositor [#31800]
841 op->customdata = scene;
843 WM_jobs_start(wm, wm_job);
847 return OPERATOR_RUNNING_MODAL;
850 void SCENE_OT_light_cache_bake(wmOperatorType *ot)
852 static const EnumPropertyItem light_cache_subset_items[] = {
853 {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All LightProbes", "Bake both irradiance grids and reflection cubemaps"},
854 {LIGHTCACHE_SUBSET_DIRTY, "DIRTY", 0, "Dirty Only", "Only bake lightprobes that are marked as dirty"},
855 {LIGHTCACHE_SUBSET_CUBE, "CUBEMAPS", 0, "Cubemaps Only", "Try to only bake reflection cubemaps if irradiance "
856 "grids are up to date"},
857 {0, NULL, 0, NULL, NULL}
861 ot->name = "Bake Light Cache";
862 ot->idname = "SCENE_OT_light_cache_bake";
863 ot->description = "Bake the active view layer lighting";
866 ot->invoke = light_cache_bake_invoke;
867 ot->modal = light_cache_bake_modal;
868 ot->cancel = light_cache_bake_cancel;
869 ot->exec = light_cache_bake_exec;
871 ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking starts", 0, 2000);
872 RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
874 ot->prop = RNA_def_enum(ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
875 RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
878 static bool light_cache_free_poll(bContext *C)
880 Scene *scene = CTX_data_scene(C);
882 return scene->eevee.light_cache;
885 static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
887 Scene *scene = CTX_data_scene(C);
889 /* kill potential bake job first (see T57011) */
890 wmWindowManager *wm = CTX_wm_manager(C);
891 WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
893 if (!scene->eevee.light_cache) {
894 return OPERATOR_CANCELLED;
897 EEVEE_lightcache_free(scene->eevee.light_cache);
898 scene->eevee.light_cache = NULL;
900 EEVEE_lightcache_info_update(&scene->eevee);
902 DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
904 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
906 return OPERATOR_FINISHED;
909 void SCENE_OT_light_cache_free(wmOperatorType *ot)
912 ot->name = "Free Light Cache";
913 ot->idname = "SCENE_OT_light_cache_free";
914 ot->description = "Free cached indirect lighting";
917 ot->exec = light_cache_free_exec;
918 ot->poll = light_cache_free_poll;
921 /********************** render view operators *********************/
923 static bool render_view_remove_poll(bContext *C)
925 Scene *scene = CTX_data_scene(C);
927 /* don't allow user to remove "left" and "right" views */
928 return scene->r.actview > 1;
931 static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
933 Scene *scene = CTX_data_scene(C);
935 BKE_scene_add_render_view(scene, NULL);
936 scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
938 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
940 return OPERATOR_FINISHED;
943 void SCENE_OT_render_view_add(wmOperatorType *ot)
946 ot->name = "Add Render View";
947 ot->idname = "SCENE_OT_render_view_add";
948 ot->description = "Add a render view";
951 ot->exec = render_view_add_exec;
954 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
957 static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
959 Scene *scene = CTX_data_scene(C);
960 SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
962 if (!BKE_scene_remove_render_view(scene, rv))
963 return OPERATOR_CANCELLED;
965 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
967 return OPERATOR_FINISHED;
970 void SCENE_OT_render_view_remove(wmOperatorType *ot)
973 ot->name = "Remove Render View";
974 ot->idname = "SCENE_OT_render_view_remove";
975 ot->description = "Remove the selected render view";
978 ot->exec = render_view_remove_exec;
979 ot->poll = render_view_remove_poll;
982 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
985 #ifdef WITH_FREESTYLE
987 static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
990 BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to manipulate the modifier");
993 if (!lineset->linestyle) {
994 BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)");
1001 static bool freestyle_active_module_poll(bContext *C)
1003 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1004 FreestyleModuleConfig *module = ptr.data;
1006 return module != NULL;
1009 static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
1011 Scene *scene = CTX_data_scene(C);
1012 ViewLayer *view_layer = CTX_data_view_layer(C);
1014 BKE_freestyle_module_add(&view_layer->freestyle_config);
1016 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1018 return OPERATOR_FINISHED;
1021 void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
1024 ot->name = "Add Freestyle Module";
1025 ot->idname = "SCENE_OT_freestyle_module_add";
1026 ot->description = "Add a style module into the list of modules";
1029 ot->exec = freestyle_module_add_exec;
1032 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1035 static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
1037 Scene *scene = CTX_data_scene(C);
1038 ViewLayer *view_layer = CTX_data_view_layer(C);
1039 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1040 FreestyleModuleConfig *module = ptr.data;
1042 BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
1044 DEG_id_tag_update(&scene->id, 0);
1045 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1047 return OPERATOR_FINISHED;
1050 void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
1053 ot->name = "Remove Freestyle Module";
1054 ot->idname = "SCENE_OT_freestyle_module_remove";
1055 ot->description = "Remove the style module from the stack";
1058 ot->poll = freestyle_active_module_poll;
1059 ot->exec = freestyle_module_remove_exec;
1062 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1065 static int freestyle_module_move_exec(bContext *C, wmOperator *op)
1067 Scene *scene = CTX_data_scene(C);
1068 ViewLayer *view_layer = CTX_data_view_layer(C);
1069 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1070 FreestyleModuleConfig *module = ptr.data;
1071 int dir = RNA_enum_get(op->ptr, "direction");
1073 if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
1074 DEG_id_tag_update(&scene->id, 0);
1075 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1078 return OPERATOR_FINISHED;
1081 void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
1083 static const EnumPropertyItem direction_items[] = {
1084 {-1, "UP", 0, "Up", ""},
1085 {1, "DOWN", 0, "Down", ""},
1086 {0, NULL, 0, NULL, NULL}
1090 ot->name = "Move Freestyle Module";
1091 ot->idname = "SCENE_OT_freestyle_module_move";
1092 ot->description = "Change the position of the style module within in the list of style modules";
1095 ot->poll = freestyle_active_module_poll;
1096 ot->exec = freestyle_module_move_exec;
1099 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1102 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1103 "Direction to move the chosen style module towards");
1106 static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
1108 Main *bmain = CTX_data_main(C);
1109 Scene *scene = CTX_data_scene(C);
1110 ViewLayer *view_layer = CTX_data_view_layer(C);
1112 BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
1114 DEG_id_tag_update(&scene->id, 0);
1115 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1117 return OPERATOR_FINISHED;
1120 void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
1123 ot->name = "Add Line Set";
1124 ot->idname = "SCENE_OT_freestyle_lineset_add";
1125 ot->description = "Add a line set into the list of line sets";
1128 ot->exec = freestyle_lineset_add_exec;
1131 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1134 static bool freestyle_active_lineset_poll(bContext *C)
1136 ViewLayer *view_layer = CTX_data_view_layer(C);
1142 return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
1145 static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
1147 ViewLayer *view_layer = CTX_data_view_layer(C);
1149 FRS_copy_active_lineset(&view_layer->freestyle_config);
1151 return OPERATOR_FINISHED;
1154 void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
1157 ot->name = "Copy Line Set";
1158 ot->idname = "SCENE_OT_freestyle_lineset_copy";
1159 ot->description = "Copy the active line set to a buffer";
1162 ot->exec = freestyle_lineset_copy_exec;
1163 ot->poll = freestyle_active_lineset_poll;
1166 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1169 static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
1171 Scene *scene = CTX_data_scene(C);
1172 ViewLayer *view_layer = CTX_data_view_layer(C);
1174 FRS_paste_active_lineset(&view_layer->freestyle_config);
1176 DEG_id_tag_update(&scene->id, 0);
1177 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1179 return OPERATOR_FINISHED;
1182 void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
1185 ot->name = "Paste Line Set";
1186 ot->idname = "SCENE_OT_freestyle_lineset_paste";
1187 ot->description = "Paste the buffer content to the active line set";
1190 ot->exec = freestyle_lineset_paste_exec;
1191 ot->poll = freestyle_active_lineset_poll;
1194 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1197 static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
1199 Scene *scene = CTX_data_scene(C);
1200 ViewLayer *view_layer = CTX_data_view_layer(C);
1202 FRS_delete_active_lineset(&view_layer->freestyle_config);
1204 DEG_id_tag_update(&scene->id, 0);
1205 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1207 return OPERATOR_FINISHED;
1210 void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
1213 ot->name = "Remove Line Set";
1214 ot->idname = "SCENE_OT_freestyle_lineset_remove";
1215 ot->description = "Remove the active line set from the list of line sets";
1218 ot->exec = freestyle_lineset_remove_exec;
1219 ot->poll = freestyle_active_lineset_poll;
1222 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1225 static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
1227 Scene *scene = CTX_data_scene(C);
1228 ViewLayer *view_layer = CTX_data_view_layer(C);
1229 int dir = RNA_enum_get(op->ptr, "direction");
1231 if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
1232 DEG_id_tag_update(&scene->id, 0);
1233 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1236 return OPERATOR_FINISHED;
1239 void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
1241 static const EnumPropertyItem direction_items[] = {
1242 {-1, "UP", 0, "Up", ""},
1243 {1, "DOWN", 0, "Down", ""},
1244 {0, NULL, 0, NULL, NULL}
1248 ot->name = "Move Line Set";
1249 ot->idname = "SCENE_OT_freestyle_lineset_move";
1250 ot->description = "Change the position of the active line set within the list of line sets";
1253 ot->exec = freestyle_lineset_move_exec;
1254 ot->poll = freestyle_active_lineset_poll;
1257 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1260 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1261 "Direction to move the active line set towards");
1264 static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
1266 Main *bmain = CTX_data_main(C);
1267 ViewLayer *view_layer = CTX_data_view_layer(C);
1268 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1271 BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
1272 return OPERATOR_CANCELLED;
1274 if (lineset->linestyle) {
1275 id_us_min(&lineset->linestyle->id);
1276 lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
1279 lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
1281 DEG_id_tag_update(&lineset->linestyle->id, 0);
1282 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1284 return OPERATOR_FINISHED;
1287 void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
1290 ot->name = "New Line Style";
1291 ot->idname = "SCENE_OT_freestyle_linestyle_new";
1292 ot->description = "Create a new line style, reusable by multiple line sets";
1295 ot->exec = freestyle_linestyle_new_exec;
1296 ot->poll = freestyle_active_lineset_poll;
1299 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1302 static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
1304 ViewLayer *view_layer = CTX_data_view_layer(C);
1305 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1306 int type = RNA_enum_get(op->ptr, "type");
1308 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1309 return OPERATOR_CANCELLED;
1312 if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1313 BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
1314 return OPERATOR_CANCELLED;
1316 DEG_id_tag_update(&lineset->linestyle->id, 0);
1317 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1319 return OPERATOR_FINISHED;
1322 void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
1325 ot->name = "Add Line Color Modifier";
1326 ot->idname = "SCENE_OT_freestyle_color_modifier_add";
1327 ot->description = "Add a line color modifier to the line style associated with the active lineset";
1330 ot->invoke = WM_menu_invoke;
1331 ot->exec = freestyle_color_modifier_add_exec;
1332 ot->poll = freestyle_active_lineset_poll;
1335 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1338 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
1341 static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
1343 ViewLayer *view_layer = CTX_data_view_layer(C);
1344 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1345 int type = RNA_enum_get(op->ptr, "type");
1347 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1348 return OPERATOR_CANCELLED;
1351 if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1352 BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
1353 return OPERATOR_CANCELLED;
1355 DEG_id_tag_update(&lineset->linestyle->id, 0);
1356 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1358 return OPERATOR_FINISHED;
1361 void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
1364 ot->name = "Add Alpha Transparency Modifier";
1365 ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
1366 ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset";
1369 ot->invoke = WM_menu_invoke;
1370 ot->exec = freestyle_alpha_modifier_add_exec;
1371 ot->poll = freestyle_active_lineset_poll;
1374 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1377 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
1380 static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
1382 ViewLayer *view_layer = CTX_data_view_layer(C);
1383 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1384 int type = RNA_enum_get(op->ptr, "type");
1386 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1387 return OPERATOR_CANCELLED;
1390 if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1391 BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
1392 return OPERATOR_CANCELLED;
1394 DEG_id_tag_update(&lineset->linestyle->id, 0);
1395 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1397 return OPERATOR_FINISHED;
1400 void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
1403 ot->name = "Add Line Thickness Modifier";
1404 ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
1405 ot->description = "Add a line thickness modifier to the line style associated with the active lineset";
1408 ot->invoke = WM_menu_invoke;
1409 ot->exec = freestyle_thickness_modifier_add_exec;
1410 ot->poll = freestyle_active_lineset_poll;
1413 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1416 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
1419 static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
1421 ViewLayer *view_layer = CTX_data_view_layer(C);
1422 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1423 int type = RNA_enum_get(op->ptr, "type");
1425 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1426 return OPERATOR_CANCELLED;
1429 if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1430 BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
1431 return OPERATOR_CANCELLED;
1433 DEG_id_tag_update(&lineset->linestyle->id, 0);
1434 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1436 return OPERATOR_FINISHED;
1439 void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
1442 ot->name = "Add Stroke Geometry Modifier";
1443 ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
1444 ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset";
1447 ot->invoke = WM_menu_invoke;
1448 ot->exec = freestyle_geometry_modifier_add_exec;
1449 ot->poll = freestyle_active_lineset_poll;
1452 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1455 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
1458 static int freestyle_get_modifier_type(PointerRNA *ptr)
1460 if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
1461 return LS_MODIFIER_TYPE_COLOR;
1462 else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
1463 return LS_MODIFIER_TYPE_ALPHA;
1464 else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
1465 return LS_MODIFIER_TYPE_THICKNESS;
1466 else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
1467 return LS_MODIFIER_TYPE_GEOMETRY;
1471 static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
1473 ViewLayer *view_layer = CTX_data_view_layer(C);
1474 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1475 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1476 LineStyleModifier *modifier = ptr.data;
1478 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1479 return OPERATOR_CANCELLED;
1482 switch (freestyle_get_modifier_type(&ptr)) {
1483 case LS_MODIFIER_TYPE_COLOR:
1484 BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
1486 case LS_MODIFIER_TYPE_ALPHA:
1487 BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
1489 case LS_MODIFIER_TYPE_THICKNESS:
1490 BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
1492 case LS_MODIFIER_TYPE_GEOMETRY:
1493 BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
1496 BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1497 return OPERATOR_CANCELLED;
1499 DEG_id_tag_update(&lineset->linestyle->id, 0);
1500 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1502 return OPERATOR_FINISHED;
1505 void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
1508 ot->name = "Remove Modifier";
1509 ot->idname = "SCENE_OT_freestyle_modifier_remove";
1510 ot->description = "Remove the modifier from the list of modifiers";
1513 ot->exec = freestyle_modifier_remove_exec;
1514 ot->poll = freestyle_active_lineset_poll;
1517 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1520 static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
1522 ViewLayer *view_layer = CTX_data_view_layer(C);
1523 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1524 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1525 LineStyleModifier *modifier = ptr.data;
1527 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1528 return OPERATOR_CANCELLED;
1531 switch (freestyle_get_modifier_type(&ptr)) {
1532 case LS_MODIFIER_TYPE_COLOR:
1533 BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
1535 case LS_MODIFIER_TYPE_ALPHA:
1536 BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
1538 case LS_MODIFIER_TYPE_THICKNESS:
1539 BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
1541 case LS_MODIFIER_TYPE_GEOMETRY:
1542 BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
1545 BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1546 return OPERATOR_CANCELLED;
1548 DEG_id_tag_update(&lineset->linestyle->id, 0);
1549 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1551 return OPERATOR_FINISHED;
1554 void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
1557 ot->name = "Copy Modifier";
1558 ot->idname = "SCENE_OT_freestyle_modifier_copy";
1559 ot->description = "Duplicate the modifier within the list of modifiers";
1562 ot->exec = freestyle_modifier_copy_exec;
1563 ot->poll = freestyle_active_lineset_poll;
1566 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1569 static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
1571 ViewLayer *view_layer = CTX_data_view_layer(C);
1572 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1573 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1574 LineStyleModifier *modifier = ptr.data;
1575 int dir = RNA_enum_get(op->ptr, "direction");
1576 bool changed = false;
1578 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1579 return OPERATOR_CANCELLED;
1582 switch (freestyle_get_modifier_type(&ptr)) {
1583 case LS_MODIFIER_TYPE_COLOR:
1584 changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
1586 case LS_MODIFIER_TYPE_ALPHA:
1587 changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
1589 case LS_MODIFIER_TYPE_THICKNESS:
1590 changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
1592 case LS_MODIFIER_TYPE_GEOMETRY:
1593 changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
1596 BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1597 return OPERATOR_CANCELLED;
1601 DEG_id_tag_update(&lineset->linestyle->id, 0);
1602 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1605 return OPERATOR_FINISHED;
1608 void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
1610 static const EnumPropertyItem direction_items[] = {
1611 {-1, "UP", 0, "Up", ""},
1612 {1, "DOWN", 0, "Down", ""},
1613 {0, NULL, 0, NULL, NULL}
1617 ot->name = "Move Modifier";
1618 ot->idname = "SCENE_OT_freestyle_modifier_move";
1619 ot->description = "Move the modifier within the list of modifiers";
1622 ot->exec = freestyle_modifier_move_exec;
1623 ot->poll = freestyle_active_lineset_poll;
1626 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1629 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1630 "Direction to move the chosen modifier towards");
1633 static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
1635 Main *bmain = CTX_data_main(C);
1636 ViewLayer *view_layer = CTX_data_view_layer(C);
1637 FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
1640 BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
1641 return OPERATOR_CANCELLED;
1644 FRS_create_stroke_material(bmain, linestyle);
1646 return OPERATOR_FINISHED;
1649 void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
1652 ot->name = "Create Freestyle Stroke Material";
1653 ot->idname = "SCENE_OT_freestyle_stroke_material_create";
1654 ot->description = "Create Freestyle stroke material for testing";
1657 ot->exec = freestyle_stroke_material_create_exec;
1660 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1663 #endif /* WITH_FREESTYLE */
1665 static int texture_slot_move_exec(bContext *C, wmOperator *op)
1667 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1670 MTex **mtex_ar, *mtexswap;
1672 int type = RNA_enum_get(op->ptr, "type");
1673 struct AnimData *adt = BKE_animdata_from_id(id);
1675 give_active_mtex(id, &mtex_ar, &act);
1677 if (type == -1) { /* Up */
1679 mtexswap = mtex_ar[act];
1680 mtex_ar[act] = mtex_ar[act - 1];
1681 mtex_ar[act - 1] = mtexswap;
1683 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0);
1684 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
1685 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1687 set_active_mtex(id, act - 1);
1691 if (act < MAX_MTEX - 1) {
1692 mtexswap = mtex_ar[act];
1693 mtex_ar[act] = mtex_ar[act + 1];
1694 mtex_ar[act + 1] = mtexswap;
1696 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0);
1697 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
1698 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1700 set_active_mtex(id, act + 1);
1704 DEG_id_tag_update(id, 0);
1705 WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
1708 return OPERATOR_FINISHED;
1711 void TEXTURE_OT_slot_move(wmOperatorType *ot)
1713 static const EnumPropertyItem slot_move[] = {
1714 {-1, "UP", 0, "Up", ""},
1715 {1, "DOWN", 0, "Down", ""},
1716 {0, NULL, 0, NULL, NULL}
1720 ot->name = "Move Texture Slot";
1721 ot->idname = "TEXTURE_OT_slot_move";
1722 ot->description = "Move texture slots up and down";
1725 ot->exec = texture_slot_move_exec;
1728 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1730 RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
1735 /********************** material operators *********************/
1737 /* material copy/paste */
1738 static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
1740 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1743 return OPERATOR_CANCELLED;
1745 copy_matcopybuf(CTX_data_main(C), ma);
1747 return OPERATOR_FINISHED;
1750 void MATERIAL_OT_copy(wmOperatorType *ot)
1753 ot->name = "Copy Material";
1754 ot->idname = "MATERIAL_OT_copy";
1755 ot->description = "Copy the material settings and nodes";
1758 ot->exec = copy_material_exec;
1761 ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the material */
1764 static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
1766 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1769 return OPERATOR_CANCELLED;
1771 paste_matcopybuf(CTX_data_main(C), ma);
1773 WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
1775 return OPERATOR_FINISHED;
1778 void MATERIAL_OT_paste(wmOperatorType *ot)
1781 ot->name = "Paste Material";
1782 ot->idname = "MATERIAL_OT_paste";
1783 ot->description = "Paste the material settings and nodes";
1786 ot->exec = paste_material_exec;
1789 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1793 static short mtexcopied = 0; /* must be reset on file load */
1794 static MTex mtexcopybuf;
1796 void ED_render_clear_mtex_copybuf(void)
1797 { /* use for file reload */
1801 static void copy_mtex_copybuf(ID *id)
1805 switch (GS(id->name)) {
1807 mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1810 mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1816 if (mtex && *mtex) {
1817 memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
1825 static void paste_mtex_copybuf(ID *id)
1829 if (mtexcopied == 0 || mtexcopybuf.tex == NULL)
1832 switch (GS(id->name)) {
1834 mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1837 mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1840 BLI_assert(!"invalid id type");
1845 if (*mtex == NULL) {
1846 *mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
1848 else if ((*mtex)->tex) {
1849 id_us_min(&(*mtex)->tex->id);
1852 memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
1854 id_us_plus((ID *)mtexcopybuf.tex);
1859 static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
1861 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1864 /* copying empty slot */
1865 ED_render_clear_mtex_copybuf();
1866 return OPERATOR_CANCELLED;
1869 copy_mtex_copybuf(id);
1871 return OPERATOR_FINISHED;
1874 static bool copy_mtex_poll(bContext *C)
1876 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1878 return (id != NULL);
1881 void TEXTURE_OT_slot_copy(wmOperatorType *ot)
1884 ot->name = "Copy Texture Slot Settings";
1885 ot->idname = "TEXTURE_OT_slot_copy";
1886 ot->description = "Copy the material texture settings and nodes";
1889 ot->exec = copy_mtex_exec;
1890 ot->poll = copy_mtex_poll;
1893 ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the mtex */
1896 static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
1898 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1901 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1902 Lamp *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
1903 World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
1904 ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
1905 FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
1914 id = &psys->part->id;
1916 id = &linestyle->id;
1919 return OPERATOR_CANCELLED;
1922 paste_mtex_copybuf(id);
1924 WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL);
1926 return OPERATOR_FINISHED;
1929 void TEXTURE_OT_slot_paste(wmOperatorType *ot)
1932 ot->name = "Paste Texture Slot Settings";
1933 ot->idname = "TEXTURE_OT_slot_paste";
1934 ot->description = "Copy the texture settings and nodes";
1937 ot->exec = paste_mtex_exec;
1940 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;