Blender V4.3
scene_edit.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdio>
10#include <cstring>
11
12#include "BLI_compiler_attrs.h"
13#include "BLI_listbase.h"
14#include "BLI_string.h"
15
16#include "DNA_sequence_types.h"
17
18#include "BKE_context.hh"
19#include "BKE_global.hh"
20#include "BKE_layer.hh"
21#include "BKE_lib_id.hh"
22#include "BKE_main.hh"
23#include "BKE_node.hh"
24#include "BKE_report.hh"
25#include "BKE_scene.hh"
26
27#include "DEG_depsgraph.hh"
29
30#include "BLT_translation.hh"
31
32#include "ED_render.hh"
33#include "ED_scene.hh"
34#include "ED_screen.hh"
35#include "ED_util.hh"
36
37#include "SEQ_relations.hh"
38#include "SEQ_select.hh"
39
40#include "RNA_access.hh"
41#include "RNA_define.hh"
42
43#include "WM_api.hh"
44#include "WM_types.hh"
45
46/* -------------------------------------------------------------------- */
50static Scene *scene_add(Main *bmain, Scene *scene_old, eSceneCopyMethod method)
51{
52 Scene *scene_new = nullptr;
53 if (method == SCE_COPY_NEW) {
54 scene_new = BKE_scene_add(bmain, DATA_("Scene"));
55 }
56 else { /* different kinds of copying */
57 /* We are going to deep-copy collections, objects and various object data, we need to have
58 * up-to-date obdata for that. */
59 if (method == SCE_COPY_FULL) {
61 }
62
63 scene_new = BKE_scene_duplicate(bmain, scene_old, method);
64 }
65
66 return scene_new;
67}
68
70 bContext *C,
71 eSceneCopyMethod method,
72 const bool assign_strip)
73{
74 Sequence *seq = nullptr;
75 Scene *scene_active = CTX_data_scene(C);
76 Scene *scene_strip = nullptr;
77 /* Sequencer need to use as base the scene defined in the strip, not the main scene. */
78 Editing *ed = scene_active->ed;
79 if (ed) {
80 seq = ed->act_seq;
81 if (seq && seq->scene) {
82 scene_strip = seq->scene;
83 }
84 }
85
86 /* If no scene assigned to the strip, only NEW scene mode is logic. */
87 if (scene_strip == nullptr) {
88 method = SCE_COPY_NEW;
89 }
90
91 Scene *scene_new = scene_add(bmain, scene_strip, method);
92
93 /* If don't need assign the scene to the strip, nothing else to do. */
94 if (!assign_strip) {
95 return scene_new;
96 }
97
98 /* As the scene is created in sequencer, do not set the new scene as active.
99 * This is useful for story-boarding where we want to keep actual scene active.
100 * The new scene is linked to the active strip and the viewport updated. */
101 if (scene_new && seq) {
102 seq->scene = scene_new;
103 /* Do a refresh of the sequencer data. */
104 SEQ_relations_invalidate_cache_raw(scene_active, seq);
107 }
108
109 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene_active);
111
112 return scene_new;
113}
114
116{
117 Scene *scene_old = WM_window_get_active_scene(win);
118 Scene *scene_new = scene_add(bmain, scene_old, method);
119
120 WM_window_set_active_scene(bmain, C, win, scene_new);
121
123
124 return scene_new;
125}
126
127bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene)
128{
129 Scene *scene_new;
130
131 /* kill running jobs */
132 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
134
135 if (scene->id.prev) {
136 scene_new = static_cast<Scene *>(scene->id.prev);
137 }
138 else if (scene->id.next) {
139 scene_new = static_cast<Scene *>(scene->id.next);
140 }
141 else {
142 return false;
143 }
144
145 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
146 if (win->parent != nullptr) { /* We only care about main windows here... */
147 continue;
148 }
149 if (win->scene == scene) {
150 WM_window_set_active_scene(bmain, C, win, scene_new);
151 }
152 }
153
154 BKE_id_delete(bmain, scene);
155
156 return true;
157}
158
159void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer)
160{
161 Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, layer);
162
163 BKE_scene_set_background(bmain, scene);
165 DEG_tag_on_visible_update(bmain, false);
166
167 ED_render_engine_changed(bmain, false);
169}
170
171static bool view_layer_remove_poll(const Scene *scene, const ViewLayer *layer)
172{
173 const int act = BLI_findindex(&scene->view_layers, layer);
174
175 if (act == -1) {
176 return false;
177 }
178 if ((scene->view_layers.first == scene->view_layers.last) && (scene->view_layers.first == layer))
179 {
180 /* ensure 1 layer is kept */
181 return false;
182 }
183
184 return true;
185}
186
187static void view_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, ViewLayer *layer)
188{
189 int act_layer_index = BLI_findindex(&scene->view_layers, layer);
190
191 for (Scene *sce = static_cast<Scene *>(bmain->scenes.first); sce;
192 sce = static_cast<Scene *>(sce->id.next))
193 {
194 if (sce->nodetree) {
195 blender::bke::node_tree_remove_layer_n(sce->nodetree, scene, act_layer_index);
196 }
197 }
198}
199
200bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports)
201{
202 if (view_layer_remove_poll(scene, layer) == false) {
203 if (reports) {
204 BKE_reportf(reports,
205 RPT_ERROR,
206 "View layer '%s' could not be removed from scene '%s'",
207 layer->name,
208 scene->id.name + 2);
209 }
210
211 return false;
212 }
213
214 /* We need to unset node-trees before removing the layer, otherwise its index will be -1. */
215 view_layer_remove_unset_nodetrees(bmain, scene, layer);
216
217 BLI_remlink(&scene->view_layers, layer);
218 BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
219
220 /* Remove from windows. */
221 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
222 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
223 if (win->scene == scene && STREQ(win->view_layer_name, layer->name)) {
224 ViewLayer *first_layer = BKE_view_layer_default_view(scene);
225 STRNCPY(win->view_layer_name, first_layer->name);
226 }
227 }
228
230
231 BKE_view_layer_free(layer);
232
236
237 return true;
238}
239
242/* -------------------------------------------------------------------- */
247{
248 Main *bmain = CTX_data_main(C);
249 wmWindow *win = CTX_wm_window(C);
250 int type = RNA_enum_get(op->ptr, "type");
251
252 ED_scene_add(bmain, C, win, eSceneCopyMethod(type));
253
254 return OPERATOR_FINISHED;
255}
256
258 {SCE_COPY_NEW, "NEW", 0, "New", "Add a new, empty scene with default settings"},
260 "EMPTY",
261 0,
262 "Copy Settings",
263 "Add a new, empty scene, and copy settings from the current scene"},
265 "LINK_COPY",
266 0,
267 "Linked Copy",
268 "Link in the collections from the current scene (shallow copy)"},
269 {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
270 {0, nullptr, 0, nullptr, nullptr},
271};
272
274{
275
276 /* identifiers */
277 ot->name = "New Scene";
278 ot->description = "Add new scene by type";
279 ot->idname = "SCENE_OT_new";
280
281 /* api callbacks */
284
285 /* flags */
287
288 /* properties */
289 ot->prop = RNA_def_enum(ot->srna, "type", scene_new_items, SCE_COPY_NEW, "Type", "");
291}
292
295/* -------------------------------------------------------------------- */
300{
301 Main *bmain = CTX_data_main(C);
302 int type = RNA_enum_get(op->ptr, "type");
303
304 if (ED_scene_sequencer_add(bmain, C, eSceneCopyMethod(type), true) == nullptr) {
305 return OPERATOR_CANCELLED;
306 }
307
308 return OPERATOR_FINISHED;
309}
310
312{
313 Scene *scene = CTX_data_scene(C);
314 const Sequence *seq = SEQ_select_active_get(scene);
315 return (seq && (seq->type == SEQ_TYPE_SCENE));
316}
317
319 PointerRNA * /*ptr*/,
320 PropertyRNA * /*prop*/,
321 bool *r_free)
322{
323 EnumPropertyItem *item = nullptr;
324 int totitem = 0;
325 uint item_index;
326
328 RNA_enum_item_add(&item, &totitem, &scene_new_items[item_index]);
329
330 bool has_scene_or_no_context = false;
331 if (C == nullptr) {
332 /* For documentation generation. */
333 has_scene_or_no_context = true;
334 }
335 else {
336 Scene *scene = CTX_data_scene(C);
337 Sequence *seq = SEQ_select_active_get(scene);
338 if (seq && (seq->type == SEQ_TYPE_SCENE) && (seq->scene != nullptr)) {
339 has_scene_or_no_context = true;
340 }
341 }
342
343 if (has_scene_or_no_context) {
345 for (int i = 0; i < ARRAY_SIZE(values); i++) {
346 item_index = RNA_enum_from_value(scene_new_items, values[i]);
347 RNA_enum_item_add(&item, &totitem, &scene_new_items[item_index]);
348 }
349 }
350
351 RNA_enum_item_end(&item, &totitem);
352 *r_free = true;
353 return item;
354}
355
357{
358
359 /* identifiers */
360 ot->name = "New Scene";
361 ot->description = "Add new scene by type in the sequence editor and assign to active strip";
362 ot->idname = "SCENE_OT_new_sequencer";
363
364 /* api callbacks */
368
369 /* flags */
371
372 /* properties */
373 ot->prop = RNA_def_enum(ot->srna, "type", scene_new_items, SCE_COPY_NEW, "Type", "");
376}
377
380/* -------------------------------------------------------------------- */
385{
386 Main *bmain = CTX_data_main(C);
387 Scene *scene = CTX_data_scene(C);
388 return BKE_scene_can_be_removed(bmain, scene);
389}
390
391static int scene_delete_exec(bContext *C, wmOperator * /*op*/)
392{
393 Scene *scene = CTX_data_scene(C);
394
395 if (ED_scene_delete(C, CTX_data_main(C), scene) == false) {
396 return OPERATOR_CANCELLED;
397 }
398
399 if (G.debug & G_DEBUG) {
400 printf("scene delete %p\n", scene);
401 }
402
404
405 return OPERATOR_FINISHED;
406}
407
409{
410 /* identifiers */
411 ot->name = "Delete Scene";
412 ot->description = "Delete active scene";
413 ot->idname = "SCENE_OT_delete";
414
415 /* api callbacks */
418
419 /* flags */
421}
422
425/* -------------------------------------------------------------------- */
435
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
@ G_DEBUG
ViewLayer * BKE_view_layer_default_view(const Scene *scene)
void BKE_view_layer_free(ViewLayer *view_layer)
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
eSceneCopyMethod
Definition BKE_scene.hh:29
@ SCE_COPY_EMPTY
Definition BKE_scene.hh:31
@ SCE_COPY_NEW
Definition BKE_scene.hh:30
@ SCE_COPY_FULL
Definition BKE_scene.hh:33
@ SCE_COPY_LINK_COLLECTION
Definition BKE_scene.hh:32
void BKE_scene_free_view_layer_depsgraph(Scene *scene, ViewLayer *view_layer)
Definition scene.cc:3281
Depsgraph * BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition scene.cc:3377
bool BKE_scene_can_be_removed(const Main *bmain, const Scene *scene)
Definition scene.cc:1939
Scene * BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
Definition scene.cc:1778
Scene * BKE_scene_add(Main *bmain, const char *name)
Definition scene.cc:1954
void BKE_scene_set_background(Main *bmain, Scene *sce)
Definition scene.cc:1987
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned int uint
#define ARRAY_SIZE(arr)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_SCENE
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_tag_on_visible_update(Main *bmain, bool do_time)
void DEG_relations_tag_update(Main *bmain)
void DEG_graph_relations_update(Depsgraph *graph)
@ ID_RECALC_AUDIO
Definition DNA_ID.h:1099
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1089
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1071
@ SEQ_TYPE_SCENE
void ED_render_engine_changed(Main *bmain, bool update_scene_data)
void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
bool ED_editors_flush_edits(Main *bmain)
Definition ed_util.cc:331
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:321
#define ND_SEQUENCER
Definition WM_types.hh:404
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_SCENE
Definition WM_types.hh:345
#define NA_REMOVED
Definition WM_types.hh:553
#define ND_LAYER
Definition WM_types.hh:417
#define ND_SCENEBROWSE
Definition WM_types.hh:399
#define printf
const Depsgraph * depsgraph
#define G(x, y, z)
void node_tree_remove_layer_n(bNodeTree *ntree, Scene *scene, int layer_index)
Definition node.cc:4764
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
static int scene_delete_exec(bContext *C, wmOperator *)
Scene * ED_scene_sequencer_add(Main *bmain, bContext *C, eSceneCopyMethod method, const bool assign_strip)
Definition scene_edit.cc:69
static const EnumPropertyItem * scene_new_sequencer_enum_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
Scene * ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method)
static void view_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, ViewLayer *layer)
bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene)
static void SCENE_OT_new(wmOperatorType *ot)
static void SCENE_OT_new_sequencer(wmOperatorType *ot)
static int scene_new_sequencer_exec(bContext *C, wmOperator *op)
static Scene * scene_add(Main *bmain, Scene *scene_old, eSceneCopyMethod method)
Definition scene_edit.cc:50
bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports)
static int scene_new_exec(bContext *C, wmOperator *op)
static bool scene_delete_poll(bContext *C)
void ED_operatortypes_scene()
static bool scene_new_sequencer_poll(bContext *C)
static bool view_layer_remove_poll(const Scene *scene, const ViewLayer *layer)
static void SCENE_OT_delete(wmOperatorType *ot)
void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer)
static EnumPropertyItem scene_new_items[]
void SEQ_relations_invalidate_cache_raw(Scene *scene, Sequence *seq)
Sequence * SEQ_select_active_get(const Scene *scene)
Sequence * act_seq
void * first
ListBase scenes
Definition BKE_main.hh:210
ListBase wm
Definition BKE_main.hh:239
struct Editing * ed
struct Scene * scene
char name[64]
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct PointerRNA * ptr
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_jobs_kill_all_from_owner(wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:612
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene)
Scene * WM_window_get_active_scene(const wmWindow *win)