old bug in python api, Blender.Scene.Unlink() did not check if screens were using this scene or if it was used as a set elsewhere.

In both cases this resulted in invalid pointers and crashes.
Also was not freeing nodes or sequence data.
This commit is contained in:
Campbell Barton 2007-12-24 10:25:35 +00:00
parent 2b49858b02
commit df46987ba3
2 changed files with 31 additions and 10 deletions

@ -1,6 +1,6 @@
/*
*
* $Id: Scene.c 12513 2007-11-07 18:52:23Z joeedh $
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
@ -51,12 +51,15 @@ struct View3D;
#include "BLI_blenlib.h" /* only for SceneObSeq_new */
#include "BSE_drawview.h" /* for play_anim */
#include "BSE_headerbuttons.h" /* for copy_scene */
#include "BSE_sequence.h" /* to clear_scene_in_allseqs */
#include "BSE_node.h" /* to clear_scene_in_nodes */
#include "BIF_drawscene.h" /* for set_scene */
#include "BIF_space.h" /* for copy_view3d_lock() */
#include "BIF_screen.h" /* curarea */
#include "BDR_editobject.h" /* free_and_unlink_base() */
#include "mydevice.h" /* for #define REDRAW */
#include "DNA_view3d_types.h"
/* python types */
#include "Object.h"
#include "Camera.h"
@ -718,8 +721,9 @@ static PyObject *M_Scene_Unlink( PyObject * self, PyObject * args )
{
PyObject *pyobj;
BPy_Scene *pyscn;
Scene *scene;
Scene *scene, *sce;
bScreen *sc;
if( !PyArg_ParseTuple( args, "O!", &Scene_Type, &pyobj ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected Scene PyType object" );
@ -733,6 +737,23 @@ static PyObject *M_Scene_Unlink( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError( PyExc_SystemError,
"current Scene cannot be removed!" );
/* Copied from header_info.c */
/* check all sets */
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
if(sce->set == scene) sce->set= 0;
}
/* check all sequences */
clear_scene_in_allseqs(scene);
/* check render layer nodes in other scenes */
clear_scene_in_nodes(scene);
for (sc= G.main->screen.first; sc; sc= sc->id.next ) {
if(sc->scene == scene) sc->scene= G.scene;
}
free_libblock( &G.main->scene, scene );
pyscn->scene= NULL;

@ -484,18 +484,19 @@ void do_info_buttons(unsigned short event)
else if(G.scene->id.next) sce= G.scene->id.next;
else return;
if(okee("Delete current scene")) {
/* Note, anything besides free_libblock needs to be added in
* Python Scene.c for Blender.Scene.Unlink() */
/* exit modes... could become single call once */
exit_editmode(EM_FREEDATA|EM_WAITCURSOR);
exit_paint_modes();
/* check all sets */
sce1= G.main->scene.first;
while(sce1) {
for (sce1= G.main->scene.first; sce1; sce1= sce1->id.next) {
if(sce1->set == G.scene) sce1->set= 0;
sce1= sce1->id.next;
}
/* check all sequences */
clear_scene_in_allseqs(G.scene);
@ -503,10 +504,9 @@ void do_info_buttons(unsigned short event)
clear_scene_in_nodes(G.scene);
/* al screens */
sc= G.main->screen.first;
while(sc) {
for (sc= G.main->screen.first; sc; sc= sc->id.next ) {
if(sc->scene == G.scene) sc->scene= sce;
sc= sc->id.next;
}
free_libblock(&G.main->scene, G.scene);
set_scene(sce);