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, ID_RECALC_GEOMETRY);
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, ID_RECALC_GEOMETRY);
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, ID_RECALC_SELECT);
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, ID_RECALC_GEOMETRY);
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, ID_RECALC_GEOMETRY);
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 PointerRNA ptr, idptr;
530 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
532 Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL;
534 /* add or copy material */
536 ma = BKE_material_copy(bmain, ma);
539 const char *name = DATA_("Material");
540 if (!(ob != NULL && ob->type == OB_GPENCIL)) {
541 ma = BKE_material_add(bmain, name);
544 ma = BKE_material_add_gpencil(bmain, name);
546 ED_node_shader_default(C, &ma->id);
547 ma->use_nodes = true;
553 /* Add slot follows user-preferences for creating new slots,
554 * RNA pointer assignment doesn't, see: T60014. */
555 if (give_current_material_p(ob, ob->actcol) == NULL) {
556 BKE_object_material_slot_add(bmain, ob);
560 /* when creating new ID blocks, use is already 1, but RNA
561 * pointer use also increases user, so this compensates it */
564 RNA_id_pointer_create(&ma->id, &idptr);
565 RNA_property_pointer_set(&ptr, prop, idptr);
566 RNA_property_update(C, &ptr, prop);
569 WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma);
571 return OPERATOR_FINISHED;
574 void MATERIAL_OT_new(wmOperatorType *ot)
577 ot->name = "New Material";
578 ot->idname = "MATERIAL_OT_new";
579 ot->description = "Add a new material";
582 ot->exec = new_material_exec;
585 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
588 /********************** new texture operator *********************/
590 static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
592 Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
593 Main *bmain = CTX_data_main(C);
594 PointerRNA ptr, idptr;
597 /* add or copy texture */
599 tex = BKE_texture_copy(bmain, tex);
602 tex = BKE_texture_add(bmain, DATA_("Texture"));
606 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
609 /* when creating new ID blocks, use is already 1, but RNA
610 * pointer use also increases user, so this compensates it */
613 RNA_id_pointer_create(&tex->id, &idptr);
614 RNA_property_pointer_set(&ptr, prop, idptr);
615 RNA_property_update(C, &ptr, prop);
618 WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex);
620 return OPERATOR_FINISHED;
623 void TEXTURE_OT_new(wmOperatorType *ot)
626 ot->name = "New Texture";
627 ot->idname = "TEXTURE_OT_new";
628 ot->description = "Add a new texture";
631 ot->exec = new_texture_exec;
634 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
637 /********************** new world operator *********************/
639 static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
641 World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
642 Main *bmain = CTX_data_main(C);
643 PointerRNA ptr, idptr;
646 /* add or copy world */
648 wo = BKE_world_copy(bmain, wo);
651 wo = BKE_world_add(bmain, DATA_("World"));
652 ED_node_shader_default(C, &wo->id);
653 wo->use_nodes = true;
657 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
660 /* when creating new ID blocks, use is already 1, but RNA
661 * pointer use also increases user, so this compensates it */
664 RNA_id_pointer_create(&wo->id, &idptr);
665 RNA_property_pointer_set(&ptr, prop, idptr);
666 RNA_property_update(C, &ptr, prop);
669 WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo);
671 return OPERATOR_FINISHED;
674 void WORLD_OT_new(wmOperatorType *ot)
677 ot->name = "New World";
678 ot->idname = "WORLD_OT_new";
679 ot->description = "Create a new world Data-Block";
682 ot->exec = new_world_exec;
685 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
688 /********************** render layer operators *********************/
690 static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
692 wmWindow *win = CTX_wm_window(C);
693 Scene *scene = CTX_data_scene(C);
694 ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
697 WM_window_set_active_view_layer(win, view_layer);
700 DEG_id_tag_update(&scene->id, 0);
701 DEG_relations_tag_update(CTX_data_main(C));
702 WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
704 return OPERATOR_FINISHED;
707 void SCENE_OT_view_layer_add(wmOperatorType *ot)
710 ot->name = "Add View Layer";
711 ot->idname = "SCENE_OT_view_layer_add";
712 ot->description = "Add a view layer";
715 ot->exec = view_layer_add_exec;
718 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
721 static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
723 Main *bmain = CTX_data_main(C);
724 Scene *scene = CTX_data_scene(C);
725 ViewLayer *view_layer = CTX_data_view_layer(C);
727 if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
728 return OPERATOR_CANCELLED;
731 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
733 return OPERATOR_FINISHED;
736 void SCENE_OT_view_layer_remove(wmOperatorType *ot)
739 ot->name = "Remove View Layer";
740 ot->idname = "SCENE_OT_view_layer_remove";
741 ot->description = "Remove the selected view layer";
744 ot->exec = view_layer_remove_exec;
747 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
750 /********************** light cache operators *********************/
752 LIGHTCACHE_SUBSET_ALL = 0,
753 LIGHTCACHE_SUBSET_DIRTY,
754 LIGHTCACHE_SUBSET_CUBE,
757 static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
759 if (scene->eevee.light_cache != NULL) {
760 int subset = RNA_enum_get(op->ptr, "subset");
762 case LIGHTCACHE_SUBSET_ALL:
763 scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
765 case LIGHTCACHE_SUBSET_CUBE:
766 scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
768 case LIGHTCACHE_SUBSET_DIRTY:
769 /* Leave tag untouched. */
776 static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
778 Scene *scene = (Scene *) op->customdata;
780 /* no running blender, remove handler and pass through */
781 if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
782 return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
786 switch (event->type) {
788 return OPERATOR_RUNNING_MODAL;
790 return OPERATOR_PASS_THROUGH;
793 static void light_cache_bake_cancel(bContext *C, wmOperator *op)
795 wmWindowManager *wm = CTX_wm_manager(C);
796 Scene *scene = (Scene *) op->customdata;
798 /* kill on cancel, because job is using op->reports */
799 WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
802 /* executes blocking render */
803 static int light_cache_bake_exec(bContext *C, wmOperator *op)
805 ViewLayer *view_layer = CTX_data_view_layer(C);
806 Main *bmain = CTX_data_main(C);
807 Scene *scene = CTX_data_scene(C);
811 /* TODO abort if selected engine is not eevee. */
812 void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false);
814 light_cache_bake_tag_cache(scene, op);
816 short stop = 0, do_update; float progress; /* Not actually used. */
817 EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
818 EEVEE_lightbake_job_data_free(rj);
820 // no redraw needed, we leave state as we entered it
821 ED_update_for_newframe(bmain, CTX_data_depsgraph(C));
823 WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
825 return OPERATOR_FINISHED;
828 static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
830 wmWindowManager *wm = CTX_wm_manager(C);
831 wmWindow *win = CTX_wm_window(C);
832 ViewLayer *view_layer = CTX_data_view_layer(C);
833 Main *bmain = CTX_data_main(C);
834 Scene *scene = CTX_data_scene(C);
835 int delay = RNA_int_get(op->ptr, "delay");
837 wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay);
840 return OPERATOR_CANCELLED;
843 /* add modal handler for ESC */
844 WM_event_add_modal_handler(C, op);
846 light_cache_bake_tag_cache(scene, op);
848 /* store actual owner of job, so modal operator could check for it,
849 * the reason of this is that active scene could change when rendering
850 * several layers from compositor [#31800]
852 op->customdata = scene;
854 WM_jobs_start(wm, wm_job);
858 return OPERATOR_RUNNING_MODAL;
861 void SCENE_OT_light_cache_bake(wmOperatorType *ot)
863 static const EnumPropertyItem light_cache_subset_items[] = {
864 {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All LightProbes", "Bake both irradiance grids and reflection cubemaps"},
865 {LIGHTCACHE_SUBSET_DIRTY, "DIRTY", 0, "Dirty Only", "Only bake lightprobes that are marked as dirty"},
866 {LIGHTCACHE_SUBSET_CUBE, "CUBEMAPS", 0, "Cubemaps Only", "Try to only bake reflection cubemaps if irradiance "
867 "grids are up to date"},
868 {0, NULL, 0, NULL, NULL}
872 ot->name = "Bake Light Cache";
873 ot->idname = "SCENE_OT_light_cache_bake";
874 ot->description = "Bake the active view layer lighting";
877 ot->invoke = light_cache_bake_invoke;
878 ot->modal = light_cache_bake_modal;
879 ot->cancel = light_cache_bake_cancel;
880 ot->exec = light_cache_bake_exec;
882 ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking starts", 0, 2000);
883 RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
885 ot->prop = RNA_def_enum(ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
886 RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
889 static bool light_cache_free_poll(bContext *C)
891 Scene *scene = CTX_data_scene(C);
893 return scene->eevee.light_cache;
896 static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
898 Scene *scene = CTX_data_scene(C);
900 /* kill potential bake job first (see T57011) */
901 wmWindowManager *wm = CTX_wm_manager(C);
902 WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
904 if (!scene->eevee.light_cache) {
905 return OPERATOR_CANCELLED;
908 EEVEE_lightcache_free(scene->eevee.light_cache);
909 scene->eevee.light_cache = NULL;
911 EEVEE_lightcache_info_update(&scene->eevee);
913 DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
915 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
917 return OPERATOR_FINISHED;
920 void SCENE_OT_light_cache_free(wmOperatorType *ot)
923 ot->name = "Free Light Cache";
924 ot->idname = "SCENE_OT_light_cache_free";
925 ot->description = "Free cached indirect lighting";
928 ot->exec = light_cache_free_exec;
929 ot->poll = light_cache_free_poll;
932 /********************** render view operators *********************/
934 static bool render_view_remove_poll(bContext *C)
936 Scene *scene = CTX_data_scene(C);
938 /* don't allow user to remove "left" and "right" views */
939 return scene->r.actview > 1;
942 static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op))
944 Scene *scene = CTX_data_scene(C);
946 BKE_scene_add_render_view(scene, NULL);
947 scene->r.actview = BLI_listbase_count(&scene->r.views) - 1;
949 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
951 return OPERATOR_FINISHED;
954 void SCENE_OT_render_view_add(wmOperatorType *ot)
957 ot->name = "Add Render View";
958 ot->idname = "SCENE_OT_render_view_add";
959 ot->description = "Add a render view";
962 ot->exec = render_view_add_exec;
965 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
968 static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op))
970 Scene *scene = CTX_data_scene(C);
971 SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview);
973 if (!BKE_scene_remove_render_view(scene, rv))
974 return OPERATOR_CANCELLED;
976 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
978 return OPERATOR_FINISHED;
981 void SCENE_OT_render_view_remove(wmOperatorType *ot)
984 ot->name = "Remove Render View";
985 ot->idname = "SCENE_OT_render_view_remove";
986 ot->description = "Remove the selected render view";
989 ot->exec = render_view_remove_exec;
990 ot->poll = render_view_remove_poll;
993 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
996 #ifdef WITH_FREESTYLE
998 static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
1001 BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to manipulate the modifier");
1004 if (!lineset->linestyle) {
1005 BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)");
1012 static bool freestyle_active_module_poll(bContext *C)
1014 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1015 FreestyleModuleConfig *module = ptr.data;
1017 return module != NULL;
1020 static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
1022 Scene *scene = CTX_data_scene(C);
1023 ViewLayer *view_layer = CTX_data_view_layer(C);
1025 BKE_freestyle_module_add(&view_layer->freestyle_config);
1027 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1029 return OPERATOR_FINISHED;
1032 void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
1035 ot->name = "Add Freestyle Module";
1036 ot->idname = "SCENE_OT_freestyle_module_add";
1037 ot->description = "Add a style module into the list of modules";
1040 ot->exec = freestyle_module_add_exec;
1043 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1046 static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
1048 Scene *scene = CTX_data_scene(C);
1049 ViewLayer *view_layer = CTX_data_view_layer(C);
1050 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1051 FreestyleModuleConfig *module = ptr.data;
1053 BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
1055 DEG_id_tag_update(&scene->id, 0);
1056 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1058 return OPERATOR_FINISHED;
1061 void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
1064 ot->name = "Remove Freestyle Module";
1065 ot->idname = "SCENE_OT_freestyle_module_remove";
1066 ot->description = "Remove the style module from the stack";
1069 ot->poll = freestyle_active_module_poll;
1070 ot->exec = freestyle_module_remove_exec;
1073 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1076 static int freestyle_module_move_exec(bContext *C, wmOperator *op)
1078 Scene *scene = CTX_data_scene(C);
1079 ViewLayer *view_layer = CTX_data_view_layer(C);
1080 PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
1081 FreestyleModuleConfig *module = ptr.data;
1082 int dir = RNA_enum_get(op->ptr, "direction");
1084 if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
1085 DEG_id_tag_update(&scene->id, 0);
1086 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1089 return OPERATOR_FINISHED;
1092 void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
1094 static const EnumPropertyItem direction_items[] = {
1095 {-1, "UP", 0, "Up", ""},
1096 {1, "DOWN", 0, "Down", ""},
1097 {0, NULL, 0, NULL, NULL}
1101 ot->name = "Move Freestyle Module";
1102 ot->idname = "SCENE_OT_freestyle_module_move";
1103 ot->description = "Change the position of the style module within in the list of style modules";
1106 ot->poll = freestyle_active_module_poll;
1107 ot->exec = freestyle_module_move_exec;
1110 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1113 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1114 "Direction to move the chosen style module towards");
1117 static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
1119 Main *bmain = CTX_data_main(C);
1120 Scene *scene = CTX_data_scene(C);
1121 ViewLayer *view_layer = CTX_data_view_layer(C);
1123 BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
1125 DEG_id_tag_update(&scene->id, 0);
1126 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1128 return OPERATOR_FINISHED;
1131 void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
1134 ot->name = "Add Line Set";
1135 ot->idname = "SCENE_OT_freestyle_lineset_add";
1136 ot->description = "Add a line set into the list of line sets";
1139 ot->exec = freestyle_lineset_add_exec;
1142 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1145 static bool freestyle_active_lineset_poll(bContext *C)
1147 ViewLayer *view_layer = CTX_data_view_layer(C);
1153 return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
1156 static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
1158 ViewLayer *view_layer = CTX_data_view_layer(C);
1160 FRS_copy_active_lineset(&view_layer->freestyle_config);
1162 return OPERATOR_FINISHED;
1165 void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
1168 ot->name = "Copy Line Set";
1169 ot->idname = "SCENE_OT_freestyle_lineset_copy";
1170 ot->description = "Copy the active line set to a buffer";
1173 ot->exec = freestyle_lineset_copy_exec;
1174 ot->poll = freestyle_active_lineset_poll;
1177 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1180 static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
1182 Scene *scene = CTX_data_scene(C);
1183 ViewLayer *view_layer = CTX_data_view_layer(C);
1185 FRS_paste_active_lineset(&view_layer->freestyle_config);
1187 DEG_id_tag_update(&scene->id, 0);
1188 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1190 return OPERATOR_FINISHED;
1193 void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
1196 ot->name = "Paste Line Set";
1197 ot->idname = "SCENE_OT_freestyle_lineset_paste";
1198 ot->description = "Paste the buffer content to the active line set";
1201 ot->exec = freestyle_lineset_paste_exec;
1202 ot->poll = freestyle_active_lineset_poll;
1205 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1208 static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
1210 Scene *scene = CTX_data_scene(C);
1211 ViewLayer *view_layer = CTX_data_view_layer(C);
1213 FRS_delete_active_lineset(&view_layer->freestyle_config);
1215 DEG_id_tag_update(&scene->id, 0);
1216 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1218 return OPERATOR_FINISHED;
1221 void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
1224 ot->name = "Remove Line Set";
1225 ot->idname = "SCENE_OT_freestyle_lineset_remove";
1226 ot->description = "Remove the active line set from the list of line sets";
1229 ot->exec = freestyle_lineset_remove_exec;
1230 ot->poll = freestyle_active_lineset_poll;
1233 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1236 static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
1238 Scene *scene = CTX_data_scene(C);
1239 ViewLayer *view_layer = CTX_data_view_layer(C);
1240 int dir = RNA_enum_get(op->ptr, "direction");
1242 if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
1243 DEG_id_tag_update(&scene->id, 0);
1244 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
1247 return OPERATOR_FINISHED;
1250 void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
1252 static const EnumPropertyItem direction_items[] = {
1253 {-1, "UP", 0, "Up", ""},
1254 {1, "DOWN", 0, "Down", ""},
1255 {0, NULL, 0, NULL, NULL}
1259 ot->name = "Move Line Set";
1260 ot->idname = "SCENE_OT_freestyle_lineset_move";
1261 ot->description = "Change the position of the active line set within the list of line sets";
1264 ot->exec = freestyle_lineset_move_exec;
1265 ot->poll = freestyle_active_lineset_poll;
1268 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1271 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1272 "Direction to move the active line set towards");
1275 static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
1277 Main *bmain = CTX_data_main(C);
1278 ViewLayer *view_layer = CTX_data_view_layer(C);
1279 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1282 BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
1283 return OPERATOR_CANCELLED;
1285 if (lineset->linestyle) {
1286 id_us_min(&lineset->linestyle->id);
1287 lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
1290 lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
1292 DEG_id_tag_update(&lineset->linestyle->id, 0);
1293 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1295 return OPERATOR_FINISHED;
1298 void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
1301 ot->name = "New Line Style";
1302 ot->idname = "SCENE_OT_freestyle_linestyle_new";
1303 ot->description = "Create a new line style, reusable by multiple line sets";
1306 ot->exec = freestyle_linestyle_new_exec;
1307 ot->poll = freestyle_active_lineset_poll;
1310 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1313 static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
1315 ViewLayer *view_layer = CTX_data_view_layer(C);
1316 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1317 int type = RNA_enum_get(op->ptr, "type");
1319 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1320 return OPERATOR_CANCELLED;
1323 if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1324 BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
1325 return OPERATOR_CANCELLED;
1327 DEG_id_tag_update(&lineset->linestyle->id, 0);
1328 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1330 return OPERATOR_FINISHED;
1333 void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
1336 ot->name = "Add Line Color Modifier";
1337 ot->idname = "SCENE_OT_freestyle_color_modifier_add";
1338 ot->description = "Add a line color modifier to the line style associated with the active lineset";
1341 ot->invoke = WM_menu_invoke;
1342 ot->exec = freestyle_color_modifier_add_exec;
1343 ot->poll = freestyle_active_lineset_poll;
1346 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1349 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", "");
1352 static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
1354 ViewLayer *view_layer = CTX_data_view_layer(C);
1355 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1356 int type = RNA_enum_get(op->ptr, "type");
1358 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1359 return OPERATOR_CANCELLED;
1362 if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1363 BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
1364 return OPERATOR_CANCELLED;
1366 DEG_id_tag_update(&lineset->linestyle->id, 0);
1367 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1369 return OPERATOR_FINISHED;
1372 void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
1375 ot->name = "Add Alpha Transparency Modifier";
1376 ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
1377 ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset";
1380 ot->invoke = WM_menu_invoke;
1381 ot->exec = freestyle_alpha_modifier_add_exec;
1382 ot->poll = freestyle_active_lineset_poll;
1385 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1388 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", "");
1391 static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
1393 ViewLayer *view_layer = CTX_data_view_layer(C);
1394 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1395 int type = RNA_enum_get(op->ptr, "type");
1397 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1398 return OPERATOR_CANCELLED;
1401 if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1402 BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
1403 return OPERATOR_CANCELLED;
1405 DEG_id_tag_update(&lineset->linestyle->id, 0);
1406 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1408 return OPERATOR_FINISHED;
1411 void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
1414 ot->name = "Add Line Thickness Modifier";
1415 ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
1416 ot->description = "Add a line thickness modifier to the line style associated with the active lineset";
1419 ot->invoke = WM_menu_invoke;
1420 ot->exec = freestyle_thickness_modifier_add_exec;
1421 ot->poll = freestyle_active_lineset_poll;
1424 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1427 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", "");
1430 static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
1432 ViewLayer *view_layer = CTX_data_view_layer(C);
1433 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1434 int type = RNA_enum_get(op->ptr, "type");
1436 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1437 return OPERATOR_CANCELLED;
1440 if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) {
1441 BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
1442 return OPERATOR_CANCELLED;
1444 DEG_id_tag_update(&lineset->linestyle->id, 0);
1445 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1447 return OPERATOR_FINISHED;
1450 void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
1453 ot->name = "Add Stroke Geometry Modifier";
1454 ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
1455 ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset";
1458 ot->invoke = WM_menu_invoke;
1459 ot->exec = freestyle_geometry_modifier_add_exec;
1460 ot->poll = freestyle_active_lineset_poll;
1463 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1466 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", "");
1469 static int freestyle_get_modifier_type(PointerRNA *ptr)
1471 if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
1472 return LS_MODIFIER_TYPE_COLOR;
1473 else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
1474 return LS_MODIFIER_TYPE_ALPHA;
1475 else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
1476 return LS_MODIFIER_TYPE_THICKNESS;
1477 else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
1478 return LS_MODIFIER_TYPE_GEOMETRY;
1482 static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
1484 ViewLayer *view_layer = CTX_data_view_layer(C);
1485 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1486 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1487 LineStyleModifier *modifier = ptr.data;
1489 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1490 return OPERATOR_CANCELLED;
1493 switch (freestyle_get_modifier_type(&ptr)) {
1494 case LS_MODIFIER_TYPE_COLOR:
1495 BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier);
1497 case LS_MODIFIER_TYPE_ALPHA:
1498 BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier);
1500 case LS_MODIFIER_TYPE_THICKNESS:
1501 BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier);
1503 case LS_MODIFIER_TYPE_GEOMETRY:
1504 BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier);
1507 BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1508 return OPERATOR_CANCELLED;
1510 DEG_id_tag_update(&lineset->linestyle->id, 0);
1511 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1513 return OPERATOR_FINISHED;
1516 void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
1519 ot->name = "Remove Modifier";
1520 ot->idname = "SCENE_OT_freestyle_modifier_remove";
1521 ot->description = "Remove the modifier from the list of modifiers";
1524 ot->exec = freestyle_modifier_remove_exec;
1525 ot->poll = freestyle_active_lineset_poll;
1528 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1531 static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
1533 ViewLayer *view_layer = CTX_data_view_layer(C);
1534 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1535 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1536 LineStyleModifier *modifier = ptr.data;
1538 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1539 return OPERATOR_CANCELLED;
1542 switch (freestyle_get_modifier_type(&ptr)) {
1543 case LS_MODIFIER_TYPE_COLOR:
1544 BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0);
1546 case LS_MODIFIER_TYPE_ALPHA:
1547 BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0);
1549 case LS_MODIFIER_TYPE_THICKNESS:
1550 BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0);
1552 case LS_MODIFIER_TYPE_GEOMETRY:
1553 BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0);
1556 BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1557 return OPERATOR_CANCELLED;
1559 DEG_id_tag_update(&lineset->linestyle->id, 0);
1560 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1562 return OPERATOR_FINISHED;
1565 void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
1568 ot->name = "Copy Modifier";
1569 ot->idname = "SCENE_OT_freestyle_modifier_copy";
1570 ot->description = "Duplicate the modifier within the list of modifiers";
1573 ot->exec = freestyle_modifier_copy_exec;
1574 ot->poll = freestyle_active_lineset_poll;
1577 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1580 static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
1582 ViewLayer *view_layer = CTX_data_view_layer(C);
1583 FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
1584 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
1585 LineStyleModifier *modifier = ptr.data;
1586 int dir = RNA_enum_get(op->ptr, "direction");
1587 bool changed = false;
1589 if (!freestyle_linestyle_check_report(lineset, op->reports)) {
1590 return OPERATOR_CANCELLED;
1593 switch (freestyle_get_modifier_type(&ptr)) {
1594 case LS_MODIFIER_TYPE_COLOR:
1595 changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir);
1597 case LS_MODIFIER_TYPE_ALPHA:
1598 changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir);
1600 case LS_MODIFIER_TYPE_THICKNESS:
1601 changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir);
1603 case LS_MODIFIER_TYPE_GEOMETRY:
1604 changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir);
1607 BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
1608 return OPERATOR_CANCELLED;
1612 DEG_id_tag_update(&lineset->linestyle->id, 0);
1613 WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
1616 return OPERATOR_FINISHED;
1619 void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
1621 static const EnumPropertyItem direction_items[] = {
1622 {-1, "UP", 0, "Up", ""},
1623 {1, "DOWN", 0, "Down", ""},
1624 {0, NULL, 0, NULL, NULL}
1628 ot->name = "Move Modifier";
1629 ot->idname = "SCENE_OT_freestyle_modifier_move";
1630 ot->description = "Move the modifier within the list of modifiers";
1633 ot->exec = freestyle_modifier_move_exec;
1634 ot->poll = freestyle_active_lineset_poll;
1637 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1640 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction",
1641 "Direction to move the chosen modifier towards");
1644 static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
1646 Main *bmain = CTX_data_main(C);
1647 ViewLayer *view_layer = CTX_data_view_layer(C);
1648 FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
1651 BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
1652 return OPERATOR_CANCELLED;
1655 FRS_create_stroke_material(bmain, linestyle);
1657 return OPERATOR_FINISHED;
1660 void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
1663 ot->name = "Create Freestyle Stroke Material";
1664 ot->idname = "SCENE_OT_freestyle_stroke_material_create";
1665 ot->description = "Create Freestyle stroke material for testing";
1668 ot->exec = freestyle_stroke_material_create_exec;
1671 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1674 #endif /* WITH_FREESTYLE */
1676 static int texture_slot_move_exec(bContext *C, wmOperator *op)
1678 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1681 MTex **mtex_ar, *mtexswap;
1683 int type = RNA_enum_get(op->ptr, "type");
1684 struct AnimData *adt = BKE_animdata_from_id(id);
1686 give_active_mtex(id, &mtex_ar, &act);
1688 if (type == -1) { /* Up */
1690 mtexswap = mtex_ar[act];
1691 mtex_ar[act] = mtex_ar[act - 1];
1692 mtex_ar[act - 1] = mtexswap;
1694 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0);
1695 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
1696 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1698 set_active_mtex(id, act - 1);
1702 if (act < MAX_MTEX - 1) {
1703 mtexswap = mtex_ar[act];
1704 mtex_ar[act] = mtex_ar[act + 1];
1705 mtex_ar[act + 1] = mtexswap;
1707 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0);
1708 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
1709 BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
1711 set_active_mtex(id, act + 1);
1715 DEG_id_tag_update(id, 0);
1716 WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
1719 return OPERATOR_FINISHED;
1722 void TEXTURE_OT_slot_move(wmOperatorType *ot)
1724 static const EnumPropertyItem slot_move[] = {
1725 {-1, "UP", 0, "Up", ""},
1726 {1, "DOWN", 0, "Down", ""},
1727 {0, NULL, 0, NULL, NULL}
1731 ot->name = "Move Texture Slot";
1732 ot->idname = "TEXTURE_OT_slot_move";
1733 ot->description = "Move texture slots up and down";
1736 ot->exec = texture_slot_move_exec;
1739 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1741 RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
1746 /********************** material operators *********************/
1748 /* material copy/paste */
1749 static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
1751 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1754 return OPERATOR_CANCELLED;
1756 copy_matcopybuf(CTX_data_main(C), ma);
1758 return OPERATOR_FINISHED;
1761 void MATERIAL_OT_copy(wmOperatorType *ot)
1764 ot->name = "Copy Material";
1765 ot->idname = "MATERIAL_OT_copy";
1766 ot->description = "Copy the material settings and nodes";
1769 ot->exec = copy_material_exec;
1772 ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the material */
1775 static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
1777 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1780 return OPERATOR_CANCELLED;
1782 paste_matcopybuf(CTX_data_main(C), ma);
1784 WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
1786 return OPERATOR_FINISHED;
1789 void MATERIAL_OT_paste(wmOperatorType *ot)
1792 ot->name = "Paste Material";
1793 ot->idname = "MATERIAL_OT_paste";
1794 ot->description = "Paste the material settings and nodes";
1797 ot->exec = paste_material_exec;
1800 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1804 static short mtexcopied = 0; /* must be reset on file load */
1805 static MTex mtexcopybuf;
1807 void ED_render_clear_mtex_copybuf(void)
1808 { /* use for file reload */
1812 static void copy_mtex_copybuf(ID *id)
1816 switch (GS(id->name)) {
1818 mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1821 mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1827 if (mtex && *mtex) {
1828 memcpy(&mtexcopybuf, *mtex, sizeof(MTex));
1836 static void paste_mtex_copybuf(ID *id)
1840 if (mtexcopied == 0 || mtexcopybuf.tex == NULL)
1843 switch (GS(id->name)) {
1845 mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
1848 mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
1851 BLI_assert(!"invalid id type");
1856 if (*mtex == NULL) {
1857 *mtex = MEM_mallocN(sizeof(MTex), "mtex copy");
1859 else if ((*mtex)->tex) {
1860 id_us_min(&(*mtex)->tex->id);
1863 memcpy(*mtex, &mtexcopybuf, sizeof(MTex));
1865 id_us_plus((ID *)mtexcopybuf.tex);
1870 static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
1872 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1875 /* copying empty slot */
1876 ED_render_clear_mtex_copybuf();
1877 return OPERATOR_CANCELLED;
1880 copy_mtex_copybuf(id);
1882 return OPERATOR_FINISHED;
1885 static bool copy_mtex_poll(bContext *C)
1887 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1889 return (id != NULL);
1892 void TEXTURE_OT_slot_copy(wmOperatorType *ot)
1895 ot->name = "Copy Texture Slot Settings";
1896 ot->idname = "TEXTURE_OT_slot_copy";
1897 ot->description = "Copy the material texture settings and nodes";
1900 ot->exec = copy_mtex_exec;
1901 ot->poll = copy_mtex_poll;
1904 ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo needed since no changes are made to the mtex */
1907 static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
1909 ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
1912 Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
1913 Lamp *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
1914 World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
1915 ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
1916 FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
1925 id = &psys->part->id;
1927 id = &linestyle->id;
1930 return OPERATOR_CANCELLED;
1933 paste_mtex_copybuf(id);
1935 WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL);
1937 return OPERATOR_FINISHED;
1940 void TEXTURE_OT_slot_paste(wmOperatorType *ot)
1943 ot->name = "Paste Texture Slot Settings";
1944 ot->idname = "TEXTURE_OT_slot_paste";
1945 ot->description = "Copy the texture settings and nodes";
1948 ot->exec = paste_mtex_exec;
1951 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;