1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup edscene
19  */
20 
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "BLI_compiler_attrs.h"
25 #include "BLI_listbase.h"
26 #include "BLI_string.h"
27 
28 #include "BKE_context.h"
29 #include "BKE_global.h"
30 #include "BKE_layer.h"
31 #include "BKE_lib_id.h"
32 #include "BKE_main.h"
33 #include "BKE_node.h"
34 #include "BKE_report.h"
35 #include "BKE_scene.h"
36 
37 #include "DEG_depsgraph.h"
38 #include "DEG_depsgraph_build.h"
39 
40 #include "BLT_translation.h"
41 
42 #include "ED_object.h"
43 #include "ED_render.h"
44 #include "ED_scene.h"
45 #include "ED_screen.h"
46 #include "ED_util.h"
47 
48 #include "RNA_access.h"
49 #include "RNA_define.h"
50 
51 #include "WM_api.h"
52 #include "WM_types.h"
53 
ED_scene_add(Main * bmain,bContext * C,wmWindow * win,eSceneCopyMethod method)54 Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method)
55 {
56   Scene *scene_new;
57 
58   if (method == SCE_COPY_NEW) {
59     scene_new = BKE_scene_add(bmain, DATA_("Scene"));
60   }
61   else { /* different kinds of copying */
62     Scene *scene_old = WM_window_get_active_scene(win);
63 
64     /* We are going to deep-copy collections, objects and various object data, we need to have
65      * up-to-date obdata for that. */
66     if (method == SCE_COPY_FULL) {
67       ED_editors_flush_edits(bmain);
68     }
69 
70     scene_new = BKE_scene_duplicate(bmain, scene_old, method);
71   }
72 
73   WM_window_set_active_scene(bmain, C, win, scene_new);
74 
75   WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new);
76 
77   return scene_new;
78 }
79 
80 /**
81  * \note Only call outside of area/region loops
82  * \return true if successful
83  */
ED_scene_delete(bContext * C,Main * bmain,Scene * scene)84 bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene)
85 {
86   Scene *scene_new;
87 
88   /* kill running jobs */
89   wmWindowManager *wm = bmain->wm.first;
90   WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_ANY);
91 
92   if (scene->id.prev) {
93     scene_new = scene->id.prev;
94   }
95   else if (scene->id.next) {
96     scene_new = scene->id.next;
97   }
98   else {
99     return false;
100   }
101 
102   LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
103     if (win->parent != NULL) { /* We only care about main windows here... */
104       continue;
105     }
106     if (win->scene == scene) {
107       WM_window_set_active_scene(bmain, C, win, scene_new);
108     }
109   }
110 
111   BKE_id_delete(bmain, scene);
112 
113   return true;
114 }
115 
116 /* Depsgraph updates after scene becomes active in a window. */
ED_scene_change_update(Main * bmain,Scene * scene,ViewLayer * layer)117 void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer)
118 {
119   Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, layer);
120 
121   BKE_scene_set_background(bmain, scene);
122   DEG_graph_relations_update(depsgraph);
123   DEG_on_visible_update(bmain, false);
124 
125   ED_render_engine_changed(bmain, false);
126   ED_update_for_newframe(bmain, depsgraph);
127 }
128 
view_layer_remove_poll(const Scene * scene,const ViewLayer * layer)129 static bool view_layer_remove_poll(const Scene *scene, const ViewLayer *layer)
130 {
131   const int act = BLI_findindex(&scene->view_layers, layer);
132 
133   if (act == -1) {
134     return false;
135   }
136   if ((scene->view_layers.first == scene->view_layers.last) &&
137       (scene->view_layers.first == layer)) {
138     /* ensure 1 layer is kept */
139     return false;
140   }
141 
142   return true;
143 }
144 
view_layer_remove_unset_nodetrees(const Main * bmain,Scene * scene,ViewLayer * layer)145 static void view_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, ViewLayer *layer)
146 {
147   int act_layer_index = BLI_findindex(&scene->view_layers, layer);
148 
149   for (Scene *sce = bmain->scenes.first; sce; sce = sce->id.next) {
150     if (sce->nodetree) {
151       BKE_nodetree_remove_layer_n(sce->nodetree, scene, act_layer_index);
152     }
153   }
154 }
155 
ED_scene_view_layer_delete(Main * bmain,Scene * scene,ViewLayer * layer,ReportList * reports)156 bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports)
157 {
158   if (view_layer_remove_poll(scene, layer) == false) {
159     if (reports) {
160       BKE_reportf(reports,
161                   RPT_ERROR,
162                   "View layer '%s' could not be removed from scene '%s'",
163                   layer->name,
164                   scene->id.name + 2);
165     }
166 
167     return false;
168   }
169 
170   /* We need to unset nodetrees before removing the layer, otherwise its index will be -1. */
171   view_layer_remove_unset_nodetrees(bmain, scene, layer);
172 
173   BLI_remlink(&scene->view_layers, layer);
174   BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
175 
176   /* Remove from windows. */
177   wmWindowManager *wm = bmain->wm.first;
178   LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
179     if (win->scene == scene && STREQ(win->view_layer_name, layer->name)) {
180       ViewLayer *first_layer = BKE_view_layer_default_view(scene);
181       STRNCPY(win->view_layer_name, first_layer->name);
182     }
183   }
184 
185   BKE_scene_free_view_layer_depsgraph(scene, layer);
186 
187   BKE_view_layer_free(layer);
188 
189   DEG_id_tag_update(&scene->id, 0);
190   DEG_relations_tag_update(bmain);
191   WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene);
192 
193   return true;
194 }
195 
scene_new_exec(bContext * C,wmOperator * op)196 static int scene_new_exec(bContext *C, wmOperator *op)
197 {
198   Main *bmain = CTX_data_main(C);
199   wmWindow *win = CTX_wm_window(C);
200   int type = RNA_enum_get(op->ptr, "type");
201 
202   ED_scene_add(bmain, C, win, type);
203 
204   return OPERATOR_FINISHED;
205 }
206 
SCENE_OT_new(wmOperatorType * ot)207 static void SCENE_OT_new(wmOperatorType *ot)
208 {
209   static EnumPropertyItem type_items[] = {
210       {SCE_COPY_NEW, "NEW", 0, "New", "Add a new, empty scene with default settings"},
211       {SCE_COPY_EMPTY,
212        "EMPTY",
213        0,
214        "Copy Settings",
215        "Add a new, empty scene, and copy settings from the current scene"},
216       {SCE_COPY_LINK_COLLECTION,
217        "LINK_COPY",
218        0,
219        "Linked Copy",
220        "Link in the collections from the current scene (shallow copy)"},
221       {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
222       {0, NULL, 0, NULL, NULL},
223   };
224 
225   /* identifiers */
226   ot->name = "New Scene";
227   ot->description = "Add new scene by type";
228   ot->idname = "SCENE_OT_new";
229 
230   /* api callbacks */
231   ot->exec = scene_new_exec;
232   ot->invoke = WM_menu_invoke;
233 
234   /* flags */
235   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
236 
237   /* properties */
238   ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
239 }
240 
scene_delete_poll(bContext * C)241 static bool scene_delete_poll(bContext *C)
242 {
243   Scene *scene = CTX_data_scene(C);
244   return (scene->id.prev || scene->id.next);
245 }
246 
scene_delete_exec(bContext * C,wmOperator * UNUSED (op))247 static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
248 {
249   Scene *scene = CTX_data_scene(C);
250 
251   if (ED_scene_delete(C, CTX_data_main(C), scene) == false) {
252     return OPERATOR_CANCELLED;
253   }
254 
255   if (G.debug & G_DEBUG) {
256     printf("scene delete %p\n", scene);
257   }
258 
259   WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
260 
261   return OPERATOR_FINISHED;
262 }
263 
SCENE_OT_delete(wmOperatorType * ot)264 static void SCENE_OT_delete(wmOperatorType *ot)
265 {
266   /* identifiers */
267   ot->name = "Delete Scene";
268   ot->description = "Delete active scene";
269   ot->idname = "SCENE_OT_delete";
270 
271   /* api callbacks */
272   ot->exec = scene_delete_exec;
273   ot->poll = scene_delete_poll;
274 
275   /* flags */
276   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
277 }
278 
ED_operatortypes_scene(void)279 void ED_operatortypes_scene(void)
280 {
281   WM_operatortype_append(SCENE_OT_new);
282   WM_operatortype_append(SCENE_OT_delete);
283 }
284