99from .context import before_draw
1010from .context import clear
1111from .context import detect_current_context
12- from .group import Group
1312from .sceneobject import SceneObject
1413from .sceneobject import SceneObjectFactory
1514
@@ -47,32 +46,33 @@ def __data__(self):
4746 # type: () -> dict
4847 return {
4948 "name" : self .name ,
50- "items" : list (self .items .values ()),
51- "objects" : list (self .objects .values ()),
49+ "attributes" : self .attributes ,
50+ "datastore" : self .datastore ,
51+ "objects" : self .objects ,
5252 "tree" : self .tree ,
5353 }
5454
55- def __init__ (self , name = "Scene" , context = None ):
56- # type: (str, str | None) -> None
57- super (Scene , self ).__init__ (name = name )
55+ def __init__ (self , context = None , datastore = None , objects = None , tree = None , ** kwargs ):
56+ # type: (str | None, dict | None, dict | None, Tree | None, **kwargs ) -> None
57+ super (Scene , self ).__init__ (** kwargs )
5858
59- # TODO: deal with context
6059 self .context = context or detect_current_context ()
61-
62- self .tree = Tree ()
63- self .tree . add ( TreeNode ( name = "ROOT" ) )
64- self .items = {}
65- self .objects = {}
60+ self . datastore = datastore or {}
61+ self .objects = objects or {}
62+ self .tree = tree or Tree ( )
63+ if self .tree . root is None :
64+ self .tree . add ( TreeNode ( name = self . name ))
6665
6766 def __repr__ (self ):
6867 # type: () -> str
6968
7069 def node_repr (node ):
71- if node .name == "ROOT" :
72- return self .name
73-
74- sceneobject = self .objects [node .name ]
75- return str (sceneobject )
70+ # type: (TreeNode) -> str
71+ if node .is_root :
72+ return node .name
73+ else :
74+ sceneobject = self .objects [node .name ]
75+ return str (sceneobject )
7676
7777 return self .tree .get_hierarchy_string (node_repr = node_repr )
7878
@@ -108,19 +108,39 @@ def add(self, item, parent=None, **kwargs):
108108
109109 # Add the scene object and item to the data store
110110 self .objects [str (sceneobject .guid )] = sceneobject
111- self .items [str (item .guid )] = item
111+ self .datastore [str (item .guid )] = item
112112
113113 # Add the scene object to the hierarchical tree
114114 if parent is None :
115115 parent_node = self .tree .root
116116 else :
117- print (parent .guid )
117+ if not isinstance (parent , SceneObject ):
118+ raise ValueError ("Parent is not a SceneObject." , parent )
118119 parent_node = self .tree .get_node_by_name (parent .guid )
120+ if parent_node is None :
121+ raise ValueError ("Parent is not part of the scene." , parent )
119122
120123 self .tree .add (TreeNode (name = str (sceneobject .guid )), parent = parent_node )
121124
122125 return sceneobject
123126
127+ def remove (self , sceneobject ):
128+ """Remove a scene object along with all its descendants from the scene.
129+
130+ Parameters
131+ ----------
132+ sceneobject : :class:`compas.scene.SceneObject`
133+ The scene object to remove.
134+ """
135+ # type: (SceneObject) -> None
136+ guid = str (sceneobject .guid )
137+ self .objects .pop (guid , None )
138+ node = self .tree .get_node_by_name (guid )
139+ if node :
140+ for descendant in node .descendants :
141+ self .objects .pop (descendant .name , None )
142+ self .tree .remove (node )
143+
124144 def clear_context (self , guids = None ):
125145 # type: (list | None) -> None
126146 """Clear the visualisation context.
@@ -173,7 +193,7 @@ def clear(self, clear_scene=True, clear_context=True):
173193 """
174194 guids = []
175195
176- for sceneobject in self .objects :
196+ for sceneobject in list ( self .objects . values ()) :
177197 guids += sceneobject .guids
178198 sceneobject ._guids = None
179199
@@ -233,7 +253,7 @@ def find_by_name(self, name):
233253 return self .get_node_by_name (name = name )
234254
235255 def find_by_itemtype (self , itemtype ):
236- # type: (... ) -> SceneObject | None
256+ # type: (type ) -> SceneObject | None
237257 """Find the first scene object with a data item of the given type.
238258
239259 Parameters
@@ -246,12 +266,12 @@ def find_by_itemtype(self, itemtype):
246266 :class:`SceneObject` or None
247267
248268 """
249- for obj in self .objects :
269+ for obj in self .objects . values () :
250270 if isinstance (obj .item , itemtype ):
251271 return obj
252272
253273 def find_all_by_itemtype (self , itemtype ):
254- # type: (... ) -> list[SceneObject]
274+ # type: (type ) -> list[SceneObject]
255275 """Find all scene objects with a data item of the given type.
256276
257277 Parameters
@@ -265,7 +285,7 @@ def find_all_by_itemtype(self, itemtype):
265285
266286 """
267287 sceneobjects = []
268- for obj in self .objects :
288+ for obj in self .objects . values () :
269289 if isinstance (obj .item , itemtype ):
270290 sceneobjects .append (obj )
271291 return sceneobjects
0 commit comments