comparison pyink/MBScene.py @ 1189:9cf183faf89f

Maintaining scene group ID to scene node mapping in MBScene_dom_monitor
author Thinker K.F. Li <thinker@codemud.net>
date Sat, 01 Jan 2011 19:52:28 +0800
parents 45e3a9273af2
children a4df892fb4e5
comparison
equal deleted inserted replaced
1188:45e3a9273af2 1189:9cf183faf89f
159 class MBScene_dom_monitor(object): 159 class MBScene_dom_monitor(object):
160 def __init__(self, *args, **kws): 160 def __init__(self, *args, **kws):
161 super(MBScene_dom_monitor, self).__init__() 161 super(MBScene_dom_monitor, self).__init__()
162 162
163 self._id2node = {} # map ID to the node in the DOM tree. 163 self._id2node = {} # map ID to the node in the DOM tree.
164 self._group2scene = {} # map ID of a group to associated scene node.
164 pass 165 pass
165 166
166 def _start_monitor(self): 167 def _start_monitor(self):
167 self._collect_node_ids() 168 self._collect_node_ids()
168 169
174 175
175 def _on_insert_node(self, node): 176 def _on_insert_node(self, node):
176 try: 177 try:
177 node_id = node.getAttribute('id') 178 node_id = node.getAttribute('id')
178 except: 179 except:
179 return 180 pass
180 self._id2node[node_id] = node 181 else:
182 if node_id not in self._id2node:
183 self._id2node[node_id] = node
184 pass
185 pass
186
187 if node.name() == 'ns0:scene':
188 try:
189 ref = node.getAttribute('ref')
190 except:
191 pass
192 else:
193 print 'scene %s' % (ref)
194 if ref not in self._group2scene:
195 self._group2scene[ref] = node
196 pass
197 pass
198 pass
181 pass 199 pass
182 200
183 def _on_remove_node(self, node): 201 def _on_remove_node(self, node):
184 try: 202 try:
185 node_id = node.getAttribute('id') 203 node_id = node.getAttribute('id')
186 except: 204 except:
205 pass
206 else:
207 if node_id not in self._id2node:
208 raise ValueError, \
209 'remove a node that is never known (%s)' % (node_id)
210 del self._id2node[node_id]
211 pass
212
213 if node.name() == 'ns0:scene':
214 try:
215 ref = node.getAttribute('ref')
216 except:
217 pass
218 else:
219 del self._group2scene[ref]
220 pass
221 pass
222 pass
223
224 def _on_attr_modified(self, node, name, old_value, new_value):
225 print 'chg attr %s' % (name)
226 if name == 'id' and old_value != new_value:
227 if old_value and (old_value not in self._id2node):
228 raise ValueError, \
229 'old ID value of passed node is valid one (%s)' % \
230 (old_value)
231 if (new_value in self._id2node):
232 raise ValueError, \
233 'new ID value of passed node is valid one (%s)' % \
234 (new_value)
235
236 if old_value:
237 del self._id2node[old_value]
238 pass
239 self._id2node[new_value] = node
240 pass
241 elif name == 'ref' and node.name() == 'ns0:scene':
242 print 'change ref %s' % (new_value)
243 if old_value == new_value:
244 return
245 if old_value:
246 node = self._group2scene[old_value] # use old node. Binding
247 # may generate a new
248 # wrapper.
249 del self._group2scene[old_value]
250 pass
251 if new_value:
252 self._group2scene[new_value] = node
253 pass
187 return 254 return
188 if node_id not in self._id2node:
189 raise ValueError, \
190 'remove a node that is never known (%s)' % (node_id)
191 del self._id2node[node_id]
192 pass
193
194 def _on_attr_modified(self, node, name, old_value, new_value):
195 if name != 'id' or old_value == new_value:
196 return
197
198 if old_value and (old_value not in self._id2node):
199 raise ValueError, \
200 'old ID value of passed node is valid one (%s)' % (old_value)
201 if (new_value in self._id2node):
202 raise ValueError, \
203 'new ID value of passed node is valid one (%s)' % (new_value)
204
205 if old_value:
206 del self._id2node[old_value]
207 pass
208 self._id2node[new_value] = node
209 pass 255 pass
210 256
211 def _collect_node_ids(self): 257 def _collect_node_ids(self):
212 self._id2node = {} 258 self._id2node = {}
213 root = self._root 259 root = self._root
229 pass 275 pass
230 276
231 def get_node(self, node_id): 277 def get_node(self, node_id):
232 return self._id2node[node_id] 278 return self._id2node[node_id]
233 279
280 def get_scene(self, group_id):
281 print 'get_scene %s' % (group_id)
282 return self._group2scene[group_id]
283
234 def new_id(self): 284 def new_id(self):
235 while True: 285 while True:
236 candidate = 's%d' % int(random.random()*100000) 286 candidate = 's%d' % int(random.random()*100000)
237 if candidate not in self._id2node: 287 if candidate not in self._id2node:
238 return candidate 288 return candidate
251 def handle_doc_root(self, doc, root): 301 def handle_doc_root(self, doc, root):
252 self._doc = doc 302 self._doc = doc
253 self._root = root 303 self._root = root
254 304
255 self._start_monitor() # start MBScene_dom_monitor 305 self._start_monitor() # start MBScene_dom_monitor
306 self._init_metadata()
256 pass 307 pass
257 308
258 def dumpattr(self, n): 309 def dumpattr(self, n):
259 s = "" 310 s = ""
260 for a,v in n.attrib.items(): 311 for a,v in n.attrib.items():
267 for n in node: 318 for n in node:
268 self.dump(n, l+1) 319 self.dump(n, l+1)
269 pass 320 pass
270 print " " * l * 2,"/>" 321 print " " * l * 2,"/>"
271 pass 322 pass
323
324 def _parse_one_scene(self, scene):
325 assert scene.name() == 'ns0:scene'
326
327 start = int(scene.getAttribute("start"))
328 try:
329 end = int(scene.getAttribute("end"))
330 except:
331 end = start
332 pass
333
334 try:
335 scene_type = scene.getAttribute('type')
336 if scene_type == None:
337 scene_type = 'normal'
338 pass
339 except:
340 scene_type = 'normal'
341 pass
342
343 return start, end, scene_type
272 344
273 def _parse_one_scenes(self, scenes): 345 def _parse_one_scenes(self, scenes):
274 self.scenemap = {} 346 self.scenemap = {}
275 try: 347 try:
276 cur = int(n.getAttribute("current")) 348 cur = int(n.getAttribute("current"))
280 self.current = cur 352 self.current = cur
281 353
282 for scene in scenes.childList(): 354 for scene in scenes.childList():
283 if scene.name() != 'ns0:scene': 355 if scene.name() != 'ns0:scene':
284 continue 356 continue
285 357
286 try: 358 try:
287 start = int(scene.getAttribute("start")) 359 start, end, scene_type = self._parse_one_scene(scene)
288 except: 360 except:
289 traceback.print_exc()
290 continue 361 continue
291 try:
292 end = int(scene.getAttribute("end"))
293 except:
294 end = start
295 pass
296 362
297 if end > self.maxframe: 363 if end > self.maxframe:
298 self.maxframe = end 364 self.maxframe = end
299 pass 365 pass
300 try: 366
301 scene_type = scene.getAttribute('type')
302 if scene_type == None:
303 scene_type = 'normal'
304 pass
305 except:
306 traceback.print_exc()
307 scene_type = 'normal'
308 pass
309 link = scene.getAttribute("ref") 367 link = scene.getAttribute("ref")
310 self.scenemap[link] = (int(start), int(end), scene_type) 368 self.scenemap[link] = (start, end, scene_type)
311 if cur >= start and cur <= end: 369 if cur >= start and cur <= end:
312 self.currentscene = link 370 self.currentscene = link
313 pass 371 pass
314 pass 372 pass
315 pass 373 pass
316 374
317 def parseMetadata(self, node): 375 def _init_metadata(self):
376 for node in self._root.childList():
377 if node.name() == 'svg:metadata':
378 break
379 pass
380 else:
381 raise RuntimeError, \
382 'can not find <svg:metadata> node in the document'
383
318 for n in node.childList(): 384 for n in node.childList():
319 if n.name() == 'ns0:scenes': 385 if n.name() == 'ns0:scenes':
320 self._parse_one_scenes(n)
321 break 386 break
322 pass 387 pass
323 else: 388 else:
324 ns = "http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd" 389 ns = "http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd"
325 self._root.setAttribute("xmlns:ns0", ns) 390 self._root.setAttribute("xmlns:ns0", ns)
326 scenes = self._doc.createElement("ns0:scenes") 391 scenes = self._doc.createElement("ns0:scenes")
327 node.appendChild(scenes) 392 node.appendChild(scenes)
328 pass 393 pass
329 pass 394 pass
330 395
331 def insertKeyScene(self, line, frame): 396 def insertKeyScene(self, line, frame):
332 """ 397 """
333 Insert a new key scene into the stage. If the nth is always a 398 Insert a new key scene into the stage. If the nth is always a
334 key scene, we will return without changing anything. If the 399 key scene, we will return without changing anything. If the
335 nth is a filled scene, we will break the original scene into 400 nth is a filled scene, we will break the original scene into
336 two parts. If the nth is out of any scene, we will append a 401 two parts. If the nth is out of any scene, we will append a
337 new scene. 402 new scene.
338 403
339 """ 404 """
340 rdoc = self._doc 405 rdoc = self._doc
341 ns = rdoc.createElement("svg:g") 406 scene_group = rdoc.createElement("svg:g")
342 found = False 407 found = False
343 for node in line.node.childList(): 408 for node in line.node.childList():
344 try: 409 try:
345 label = node.getAttribute("inkscape:label") 410 label = node.getAttribute("inkscape:label")
346 except: 411 except:
348 if label == "dup": 413 if label == "dup":
349 #FIXME: The duplication here is not perfect. We should 414 #FIXME: The duplication here is not perfect. We should
350 # get the element inside the group and apply the 415 # get the element inside the group and apply the
351 # transformation matrix to it directly. 416 # transformation matrix to it directly.
352 for n in node.childList(): 417 for n in node.childList():
353 ns.appendChild(n.duplicate(self._doc)) 418 scene_group.appendChild(n.duplicate(self._doc))
354 found = True 419 found = True
355 node.setAttribute("style","display:none") 420 node.setAttribute("style","display:none")
356 break 421 break
357 pass 422 pass
358 pass 423 pass
362 txt.setAttribute("x","0") 427 txt.setAttribute("x","0")
363 txt.setAttribute("y","0") 428 txt.setAttribute("y","0")
364 txt.setAttribute("width","100") 429 txt.setAttribute("width","100")
365 txt.setAttribute("height","100") 430 txt.setAttribute("height","100")
366 txt.setAttribute("style","fill:#ff00") 431 txt.setAttribute("style","fill:#ff00")
367 ns.appendChild(txt) 432 scene_group.appendChild(txt)
368 433
369 gid = line.node.getAttribute('inkscape:label')+self.new_id() 434 gid = line.node.getAttribute('inkscape:label')+self.new_id()
370 ns.setAttribute("id",gid) 435 scene_group.setAttribute("id",gid)
371 ns.setAttribute("inkscape:groupmode","layer") 436 scene_group.setAttribute("inkscape:groupmode","layer")
372 line.node.appendChild(ns) 437 line.node.appendChild(scene_group)
373 line.add_keyframe(frame, ns) 438 line.add_keyframe(frame, scene_group)
374 self.update_scenes_of_dom() 439 self.update_scenes_of_dom()
375 pass 440 pass
376 441
377 def add_scene_on_dom(self, frameline, scenes_node): 442 def add_scene_on_dom(self, frameline, scenes_node):
378 doc = self._doc 443 doc = self._doc
385 scenes_node.appendChild(scene_node) 450 scenes_node.appendChild(scene_node)
386 scene_node.setAttribute("start", str(start_idx + 1)) 451 scene_node.setAttribute("start", str(start_idx + 1))
387 if start_idx != stop_idx: 452 if start_idx != stop_idx:
388 scene_node.setAttribute("end", str(stop_idx + 1)) 453 scene_node.setAttribute("end", str(stop_idx + 1))
389 pass 454 pass
390 scene_node.setAttribute("ref", ref.attribute("id")) 455 scene_node.setAttribute("ref", ref.getAttribute("id"))
391 scene_node.setAttribute("type", tween_type_name) 456 scene_node.setAttribute("type", tween_type_name)
392 pass 457 pass
393 pass 458 pass
394 459
395 def update_scenes_of_dom(self): 460 def update_scenes_of_dom(self):
417 In this function, we will collect all items for the current 482 In this function, we will collect all items for the current
418 scene and then relocate them back to the appropriate scene 483 scene and then relocate them back to the appropriate scene
419 object. 484 object.
420 """ 485 """
421 self.layers = [] 486 self.layers = []
422 self.scenemap = None
423 doc = self._root 487 doc = self._root
424 488
425 # TODO: Remove following code sicne this function is for parsing. 489 # TODO: Remove following code sicne this function is for parsing.
426 # Why do this here? 490 # Why do this here?
427 addEventListener(doc,'DOMNodeInserted',self.updateUI,None) 491 addEventListener(doc,'DOMNodeInserted',self.updateUI,None)
435 self.width = 640 499 self.width = 640
436 self.height=480 500 self.height=480
437 pass 501 pass
438 502
439 for node in doc.childList(): 503 for node in doc.childList():
440 print node.name() 504 if node.name() == 'svg:g':
441 if node.name() == 'svg:metadata':
442 self.parseMetadata(node)
443 pass
444 elif node.name() == 'svg:g':
445 oldscene = None 505 oldscene = None
446 lyobj = Layer(node) 506 lyobj = Layer(node)
447 self.layers.append(lyobj) 507 self.layers.append(lyobj)
448 lyobj.current_scene = [] 508 lyobj.current_scene = []
449 for scene in node.childList(): 509 for scene in node.childList():
458 except: 518 except:
459 pass 519 pass
460 520
461 try: 521 try:
462 scene_id = scene.getAttribute('id') 522 scene_id = scene.getAttribute('id')
463 start, stop, tween_type = self.scenemap[scene_id] 523 scene = self.get_scene(scene_id)
524 start, stop, tween_type = \
525 self._parse_one_scene(scene)
464 except: 526 except:
465 lyobj.current_scene.append(scene) 527 lyobj.current_scene.append(scene)
466 continue 528 continue
467 529
468 lyobj.scenes.append(Scene(scene, start, stop, 530 lyobj.scenes.append(Scene(scene, start, stop,
496 558
497 self.desktop = desktop 559 self.desktop = desktop
498 self.window = win 560 self.window = win
499 self.layers = [] 561 self.layers = []
500 self.layers.append(Layer(None)) 562 self.layers.append(Layer(None))
501 self.scenemap = None
502 self.top = None 563 self.top = None
503 self.last_update = None 564 self.last_update = None
504 pybInkscape.inkscape.connect('change_selection', self.show_selection) 565 pybInkscape.inkscape.connect('change_selection', self.show_selection)
505 self.last_select = None 566 self.last_select = None
506 self.lockui=False 567 self._lockui=False
507 self.tween=None 568 self.tween=None
508 self.document = None 569 self.document = None
509 self.root = root 570 self.root = root
510 self.framerate=12 571 self.framerate=12
511 self.maxframe=0 572 self.maxframe=0
769 830
770 def onCellClick(self, line, frame, but): 831 def onCellClick(self, line, frame, but):
771 self.last_line = line 832 self.last_line = line
772 self.last_frame = frame 833 self.last_frame = frame
773 self.last_line.active_frame(frame) 834 self.last_line.active_frame(frame)
774 self.lockui = True 835 self._lockui = True
775 self.doEditScene(None) 836 self.doEditScene(None)
776 self.lockui = False 837 self._lockui = False
777 pass 838 pass
778 839
779 def _remove_active_frame(self,widget,event): 840 def _remove_active_frame(self,widget,event):
780 """ 841 """
781 Hide all hover frames. This is a hack. We should use the lost focus event 842 Hide all hover frames. This is a hack. We should use the lost focus event
937 self.setCurrentScene(self.last_frame+1) 998 self.setCurrentScene(self.last_frame+1)
938 self.selectSceneObject(self.last_line, self.last_frame) 999 self.selectSceneObject(self.last_line, self.last_frame)
939 pass 1000 pass
940 1001
941 def doInsertKeyScene(self,w): 1002 def doInsertKeyScene(self,w):
942 self.lockui=True 1003 self._lockui=True
943 self.insertKeyScene(self.last_line, self.last_frame) 1004 self.insertKeyScene(self.last_line, self.last_frame)
944 self.selectSceneObject(self.last_line, self.last_frame) 1005 self.selectSceneObject(self.last_line, self.last_frame)
945 self.lockui=False 1006 self._lockui=False
946 # self.grid.show_all() 1007 # self.grid.show_all()
947 return 1008 return
948 1009
949 def doDuplicateKeyScene(self,w): 1010 def doDuplicateKeyScene(self,w):
950 self.lockui = True 1011 self._lockui = True
951 self.duplicateKeyScene() 1012 self.duplicateKeyScene()
952 self.lockui = False 1013 self._lockui = False
953 1014
954 def doRemoveScene(self,w): 1015 def doRemoveScene(self,w):
955 self.lockui = True 1016 self._lockui = True
956 self.removeKeyScene() 1017 self.removeKeyScene()
957 self.lockui = False 1018 self._lockui = False
958 return 1019 return
959 1020
960 1021
961 def doExtendScene(self,w): 1022 def doExtendScene(self,w):
962 self.lockui = True 1023 self._lockui = True
963 self.extendScene() 1024 self.extendScene()
964 self.lockui = False 1025 self._lockui = False
965 #self.grid.show_all() 1026 #self.grid.show_all()
966 pass 1027 pass
967 1028
968 def changeObjectLabel(self,w): 1029 def changeObjectLabel(self,w):
969 o = self.desktop.selection.list()[0] 1030 o = self.desktop.selection.list()[0]
982 """ 1043 """
983 Execute the current animation till the last frame. 1044 Execute the current animation till the last frame.
984 """ 1045 """
985 if self.btnRun.get_label() == "Run": 1046 if self.btnRun.get_label() == "Run":
986 self.btnRun.set_label("Stop") 1047 self.btnRun.set_label("Stop")
987 self.lockui = True 1048 self._lockui = True
988 self.last_update = glib.timeout_add(1000/self.framerate,self.doRunNext) 1049 self.last_update = glib.timeout_add(1000/self.framerate,self.doRunNext)
989 else: 1050 else:
990 self.btnRun.set_label("Run") 1051 self.btnRun.set_label("Run")
991 glib.source_remove(self.last_update) 1052 glib.source_remove(self.last_update)
992 self.lockui = False 1053 self._lockui = False
993 pass 1054 pass
994 1055
995 def doRunNext(self): 1056 def doRunNext(self):
996 if self.current >= self.maxframe: 1057 if self.current >= self.maxframe:
997 self.current = 0 1058 self.current = 0
1001 traceback.print_exc() 1062 traceback.print_exc()
1002 raise 1063 raise
1003 self.last_update = glib.timeout_add(1000/self.framerate,self.doRunNext) 1064 self.last_update = glib.timeout_add(1000/self.framerate,self.doRunNext)
1004 1065
1005 def doInsertScene(self,w): 1066 def doInsertScene(self,w):
1006 self.lockui=True 1067 self._lockui=True
1007 self.last_line.insert_frame(self.last_frame) 1068 self.last_line.insert_frame(self.last_frame)
1008 self.update_scenes_of_dom() 1069 self.update_scenes_of_dom()
1009 self.lockui=False 1070 self._lockui=False
1010 1071
1011 def doRemoveScene(self,w): 1072 def doRemoveScene(self,w):
1012 self.lockui=True 1073 self._lockui=True
1013 self.last_line.remove_frame(self.last_frame) 1074 self.last_line.remove_frame(self.last_frame)
1014 self.update_scenes_of_dom() 1075 self.update_scenes_of_dom()
1015 self.lockui=False 1076 self._lockui=False
1016 1077
1017 def addButtons(self,hbox): 1078 def addButtons(self,hbox):
1018 btn = gtk.Button('Insert Key') 1079 btn = gtk.Button('Insert Key')
1019 btn.connect('clicked',self.doInsertKeyScene) 1080 btn.connect('clicked',self.doInsertKeyScene)
1020 hbox.pack_start(btn,expand=False,fill=False) 1081 hbox.pack_start(btn,expand=False,fill=False)
1096 self.OK = True 1157 self.OK = True
1097 gtk.main_quit() 1158 gtk.main_quit()
1098 pass 1159 pass
1099 1160
1100 def updateUI(self,node=None,arg=None): 1161 def updateUI(self,node=None,arg=None):
1101 if self.lockui: return 1162 if self._lockui: return
1102 1163
1103 if self.last_update!= None: 1164 if self.last_update!= None:
1104 glib.source_remove(self.last_update) 1165 glib.source_remove(self.last_update)
1105 self.last_update = glib.timeout_add(300,self._updateUI) 1166 self.last_update = glib.timeout_add(300,self._updateUI)
1106 1167
1107 pass 1168 pass
1108 1169
1109 def _updateUI(self,node=None,arg=None): 1170 def _updateUI(self,node=None,arg=None):
1171 self._lockui = True
1110 self.parseScene() 1172 self.parseScene()
1111 self._create_framelines() 1173 self._create_framelines()
1112 self._update_framelines() 1174 self._update_framelines()
1175 self._lockui = False
1113 pass 1176 pass
1114 1177
1115 def show(self): 1178 def show(self):
1116 self.OK = True 1179 self.OK = True
1117 if not self.root: 1180 if not self.root: