Fix crash when deleting active workspace render-layer

Also fixes some failing unit-tests for render-layers.
This commit is contained in:
Julian Eisel
2017-06-09 17:16:39 +02:00
parent f35df9a25a
commit 2bb004e03d
11 changed files with 101 additions and 55 deletions

View File

@@ -64,8 +64,6 @@ struct SceneLayer *BKE_scene_layer_context_active_ex(const struct Main *bmain, c
struct SceneLayer *BKE_scene_layer_context_active(const struct Scene *scene);
struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name);
bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl);
void BKE_scene_layer_free(struct SceneLayer *sl);
void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);

View File

@@ -128,39 +128,8 @@ SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name)
return sl;
}
bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl)
{
const int act = BLI_findindex(&scene->render_layers, sl);
if (act == -1) {
return false;
}
else if ( (scene->render_layers.first == scene->render_layers.last) &&
(scene->render_layers.first == sl))
{
/* ensure 1 layer is kept */
return false;
}
BLI_remlink(&scene->render_layers, sl);
BKE_scene_layer_free(sl);
MEM_freeN(sl);
scene->active_layer = 0;
/* TODO WORKSPACE: set active_layer to 0 */
for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
}
}
return true;
}
/**
* Free (or release) any data used by this SceneLayer (does not free the SceneLayer itself).
* Free (or release) any data used by this SceneLayer.
*/
void BKE_scene_layer_free(SceneLayer *sl)
{
@@ -200,6 +169,8 @@ void BKE_scene_layer_free(SceneLayer *sl)
BLI_freelistN(&sl->drawdata);
MEM_SAFE_FREE(sl->stats);
MEM_freeN(sl);
}
/**

View File

@@ -581,10 +581,12 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
curvemapping_free_data(&sce->r.mblur_shutter_curve);
for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
for (SceneLayer *sl = sce->render_layers.first, *sl_next; sl; sl = sl_next) {
sl_next = sl->next;
BLI_remlink(&sce->render_layers, sl);
BKE_scene_layer_free(sl);
}
BLI_freelistN(&sce->render_layers);
/* Master Collection */
BKE_collection_master_free(sce);

View File

@@ -79,6 +79,7 @@ static void do_version_workspaces_create_from_screens(Main *bmain)
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
const bScreen *screen_parent = screen_parent_find(screen);
WorkSpace *workspace;
SceneLayer *layer = BKE_scene_layer_render_active(screen->scene);
ListBase *transform_orientations;
if (screen_parent) {
@@ -91,7 +92,7 @@ static void do_version_workspaces_create_from_screens(Main *bmain)
workspace = BKE_workspace_add(bmain, screen->id.name + 2);
}
BKE_workspace_layout_add(workspace, screen, screen->id.name + 2);
BKE_workspace_render_layer_set(workspace, screen->scene->render_layers.first);
BKE_workspace_render_layer_set(workspace, layer);
transform_orientations = BKE_workspace_transform_orientations_get(workspace);
BLI_duplicatelist(transform_orientations, &screen->scene->transform_spaces);

View File

@@ -29,11 +29,14 @@
enum eSceneCopyMethod;
struct Scene *ED_scene_add(struct Main *bmain, bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL();
bool ED_scene_delete(bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL();
void ED_scene_exit(bContext *C) ATTR_NONNULL();
void ED_scene_changed_update(struct Main *bmain, bContext *C, struct Scene *scene_new,
struct Scene *ED_scene_add(struct Main *bmain, struct bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL();
bool ED_scene_delete(struct bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL();
void ED_scene_exit(struct bContext *C) ATTR_NONNULL();
void ED_scene_changed_update(struct Main *bmain, struct bContext *C, struct Scene *scene_new,
const struct bScreen *active_screen) ATTR_NONNULL();
bool ED_scene_render_layer_delete(
struct Main *bmain, struct Scene *scene, struct SceneLayer *layer,
struct ReportList *reports) ATTR_NONNULL(1, 2, 3);
void ED_operatortypes_scene(void);

View File

@@ -143,6 +143,8 @@ bool ED_workspace_delete(
struct wmWindowManager *wm, struct wmWindow *win) ATTR_NONNULL();
void ED_workspace_scene_data_sync(
struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
void ED_workspace_render_layer_unset(
const struct Main *bmain, const SceneLayer *layer_unset, SceneLayer *layer_new) ATTR_NONNULL(1, 2);
struct WorkSpaceLayout *ED_workspace_layout_add(
struct WorkSpace *workspace,
struct wmWindow *win,

View File

@@ -84,6 +84,7 @@
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_render.h"
#include "ED_scene.h"
#include "ED_screen.h"
#include "RNA_define.h"
@@ -653,17 +654,16 @@ void SCENE_OT_render_layer_add(wmOperatorType *ot)
static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = BKE_scene_layer_context_active(scene);
if (!BKE_scene_layer_remove(CTX_data_main(C), scene, sl)) {
if (!ED_scene_render_layer_delete(bmain, scene, sl, NULL)) {
return OPERATOR_CANCELLED;
}
DEG_id_tag_update(&scene->id, 0);
DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
return OPERATOR_FINISHED;
}

View File

@@ -26,18 +26,24 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "BLI_compiler_attrs.h"
#include "BLI_listbase.h"
#include "BLT_translation.h"
#include "DNA_workspace_types.h"
#include "ED_object.h"
#include "ED_render.h"
#include "ED_scene.h"
@@ -128,6 +134,64 @@ void ED_scene_changed_update(Main *bmain, bContext *C, Scene *scene_new, const b
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
static bool scene_render_layer_remove_poll(
const Scene *scene, const SceneLayer *layer)
{
const int act = BLI_findindex(&scene->render_layers, layer);
if (act == -1) {
return false;
}
else if ((scene->render_layers.first == scene->render_layers.last) &&
(scene->render_layers.first == layer))
{
/* ensure 1 layer is kept */
return false;
}
return true;
}
static void scene_render_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, SceneLayer *layer)
{
int act_layer_index = BLI_findindex(&scene->render_layers, layer);
for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
BKE_nodetree_remove_layer_n(sce->nodetree, scene, act_layer_index);
}
}
}
bool ED_scene_render_layer_delete(
Main *bmain, Scene *scene, SceneLayer *layer,
ReportList *reports)
{
if (scene_render_layer_remove_poll(scene, layer) == false) {
if (reports) {
BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'",
layer->name, scene->id.name + 2);
}
return false;
}
BLI_remlink(&scene->render_layers, layer);
BLI_assert(BLI_listbase_is_empty(&scene->render_layers) == false);
scene->active_layer = 0;
ED_workspace_render_layer_unset(bmain, layer, scene->render_layers.first);
scene_render_layer_remove_unset_nodetrees(bmain, scene, layer);
BKE_scene_layer_free(layer);
DEG_id_tag_update(&scene->id, 0);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene);
return true;
}
static int scene_new_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);

View File

@@ -269,6 +269,16 @@ void ED_workspace_scene_data_sync(
BKE_screen_view3d_scene_sync(screen, scene);
}
void ED_workspace_render_layer_unset(
const Main *bmain, const SceneLayer *layer_unset, SceneLayer *layer_new)
{
for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
if (BKE_workspace_render_layer_get(workspace) == layer_unset) {
BKE_workspace_render_layer_set(workspace, layer_new);
}
}
}
/** \} Workspace API */

View File

@@ -488,6 +488,7 @@ EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = {
#include "ED_mesh.h"
#include "ED_keyframing.h"
#include "ED_image.h"
#include "ED_scene.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -3092,17 +3093,9 @@ static void rna_SceneLayer_remove(
Scene *scene = (Scene *)id;
SceneLayer *sl = sl_ptr->data;
if (!BKE_scene_layer_remove(bmain, scene, sl)) {
BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'",
sl->name, scene->id.name + 2);
return;
if (ED_scene_render_layer_delete(bmain, scene, sl, reports)) {
RNA_POINTER_INVALIDATE(sl_ptr);
}
RNA_POINTER_INVALIDATE(sl_ptr);
DEG_id_tag_update(&scene->id, 0);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)

View File

@@ -168,6 +168,7 @@ struct wmWindowManager;
#include "../blender/editors/include/ED_object.h"
#include "../blender/editors/include/ED_particle.h"
#include "../blender/editors/include/ED_render.h"
#include "../blender/editors/include/ED_scene.h"
#include "../blender/editors/include/ED_screen.h"
#include "../blender/editors/include/ED_space_api.h"
#include "../blender/editors/include/ED_text.h"
@@ -507,6 +508,7 @@ void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE
struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL
struct Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm) RET_NULL
bool ED_scene_render_layer_delete(struct Main *bmain, Scene *scene, SceneLayer *layer, ReportList *reports) RET_ZERO
void ED_base_object_select(struct BaseLegacy *base, short mode) RET_NONE
void ED_object_base_select(struct Base *base, short mode) RET_NONE
bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, struct Object *ob, struct ModifierData *md) RET_ZERO