comparison pyink/MBScene.py @ 1205:1af64bcdfd7d

Move to MBScene._make_layers_integral() - Old MBScene.parseScene()/create_framelines()/update_framelines() is too fragile and inefficiently. - MBScene._make_layers_integral() is more robust that - separate logic into removing layer group nodes and adding layer group nodes - refactory code of create framelines and layers into methods - it make logic into layers - framelines and layers are incremental updated to avoid overhead of creating/destroying all framelines and layer objects.
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 03 Jan 2011 22:12:30 +0800
parents 78925515836f
children 1d476b35dc79
comparison
equal deleted inserted replaced
1204:78925515836f 1205:1af64bcdfd7d
297 # 297 #
298 class MBScene_dom(MBScene_dom_monitor): 298 class MBScene_dom(MBScene_dom_monitor):
299 # Declare variables, here, for keeping tracking 299 # Declare variables, here, for keeping tracking
300 _doc = None 300 _doc = None
301 _root = None 301 _root = None
302 _scenes_group = None
303 302
304 def __init__(self, *args, **kws): 303 def __init__(self, *args, **kws):
305 super(MBScene_dom, self).__init__() 304 super(MBScene_dom, self).__init__()
306 pass 305 pass
307 306
308 def handle_doc_root(self, doc, root): 307 def handle_doc_root(self, doc, root):
309 self._doc = doc 308 self._doc = doc
310 self._root = root 309 self._root = root
310 self._layers = []
311 311
312 self._start_monitor() # start MBScene_dom_monitor 312 self._start_monitor() # start MBScene_dom_monitor
313 self._init_metadata() 313 self._init_metadata()
314 self._parse_all_scenes() 314 self._parse_all_scenes()
315 self._parse_all_layers()
315 pass 316 pass
316 317
317 def dumpattr(self, n): 318 def dumpattr(self, n):
318 s = "" 319 s = ""
319 for a,v in n.attrib.items(): 320 for a,v in n.attrib.items():
470 pass 471 pass
471 472
472 ## \brief Create and add a svg:g for a scene under a group for a layer. 473 ## \brief Create and add a svg:g for a scene under a group for a layer.
473 # 474 #
474 def _add_scene_group(self, layer_idx): 475 def _add_scene_group(self, layer_idx):
475 layer = self.layers[layer_idx] 476 layer = self._layers[layer_idx]
476 doc = self._doc 477 doc = self._doc
477 478
478 scene_group = doc.createElement('svg:g') 479 scene_group = doc.createElement('svg:g')
479 gid = self.new_id() 480 gid = self.new_id()
480 scene_group.setAttribute("id", gid) 481 scene_group.setAttribute("id", gid)
499 scene_group = self._add_scene_group(layer_idx) 500 scene_group = self._add_scene_group(layer_idx)
500 scene_group_id = scene_group.getAttribute('id') 501 scene_group_id = scene_group.getAttribute('id')
501 scene_node = self._add_scene_node(frame, frame, ref=scene_group_id) 502 scene_node = self._add_scene_node(frame, frame, ref=scene_group_id)
502 line.add_keyframe(frame, scene_node) 503 line.add_keyframe(frame, scene_node)
503 504
504 for node in self.layers[layer_idx].group.childList(): 505 for node in self._layers[layer_idx].group.childList():
505 try: 506 try:
506 label = node.getAttribute('inkscape:label') 507 label = node.getAttribute('inkscape:label')
507 except: 508 except:
508 continue 509 continue
509 if label == 'dup': 510 if label == 'dup':
510 node.setAttribute('style', 'display: none') 511 node.setAttribute('style', 'display: none')
511 pass 512 pass
512 pass 513 pass
513 pass 514 pass
514 515
515 def add_scene_on_dom(self, frameline, scenes_node): 516 def parse_layer(self, layer_idx):
516 doc = self._doc 517 layer = self._layers[layer_idx]
517 for start_idx, stop_idx, tween_type in frameline.get_frame_blocks(): 518 layer_group = layer.group
518 scene_node = frameline.get_frame_data(start_idx) 519
519 tween_type_idx = self._frameline_tween_types.index(tween_type) 520 for child in layer_group.childList():
520 tween_type_name = self._tween_type_names[tween_type_idx] 521 if child.name() != 'svg:g':
522 continue
523 try:
524 child_id = child.getAttribute('id')
525 scene_node = self.get_scene(child_id)
526 except:
527 continue
521 528
522 scene_node = doc.createElement("ns0:scene") 529 layer.scenes.append(scene_node)
523 scenes_node.appendChild(scene_node) 530 pass
524 scene_node.setAttribute("start", str(start_idx + 1)) 531 pass
525 if start_idx != stop_idx: 532
526 scene_node.setAttribute("end", str(stop_idx + 1)) 533 def _parse_all_layers(self):
527 pass 534 root = self._root
528 scene_node.setAttribute("ref", scene_node.getAttribute("ref")) 535 layers = self._layers
529 scene_node.setAttribute("type", tween_type_name) 536
530 pass 537 for child in root.childList():
531 pass 538 if child.name() != 'svg:g':
532 539 continue
533 # TODO: this function should be removed. 540
534 def update_scenes_of_dom(self): 541 layer_group = child
535 doc = self._root 542 layer = Layer(layer_group)
536 rdoc = self._doc 543 layer.idx = len(layers)
537 for node in doc.childList(): 544 layers.append(layer)
538 if node.name() == 'svg:metadata': 545 self.parse_layer(layer.idx)
539 for t in node.childList(): 546 pass
540 if t.name() == "ns0:scenes": 547 pass
541 node.removeChild(t) 548
542 scenes_node = rdoc.createElement("ns0:scenes") 549 ## \brief Add/insert a layer at given position.
543 node.appendChild(scenes_node) 550 #
544 for layer in range(0, len(self._framelines)): 551 # \param layer_idx is the position in the layer list.
545 lobj = self._framelines[layer] 552 #
546 self.add_scene_on_dom(lobj, scenes_node) 553 def add_layer(self, layer_idx, layer_group):
547 pass 554 layers = self._layers
548 pass 555
549 pass 556 layer = Layer(layer_group)
550 pass 557 if layer_idx >= len(layers):
551 pass 558 layers.append(layer)
552 pass 559 else:
553 560 layers.insert(layer_idx, layer)
554 def parseScene(self): 561 for idx in range(layer_idx, len(layers)):
555 """ 562 layers[idx].idx = idx
556 In this function, we will collect all items for the current 563 pass
557 scene and then relocate them back to the appropriate scene 564 pass
558 object. 565 pass
559 """ 566
560 self.layers = [] 567 def rm_layer(self, layer_idx):
561 doc = self._root 568 layers = self._layers
562 569
563 # TODO: Remove following code sicne this function is for parsing. 570 del layers[layer_idx]
564 # Why do this here? 571
565 addEventListener(doc,'DOMNodeInserted',self.updateUI,None) 572 for idx in range(layer_idx, len(layers)):
566 addEventListener(doc,'DOMNodeRemoved',self.updateUI,None) 573 layers[idx].idx = idx
567
568 doc.childList()
569 try:
570 self.width = float(doc.getAttribute("width"))
571 self.height= float(doc.getAttribute("height"))
572 except:
573 self.width = 640
574 self.height=480
575 pass
576
577 for node in doc.childList():
578 if node.name() == 'svg:g':
579 oldscene = None
580 lyobj = Layer(node)
581 self.layers.append(lyobj)
582 for scene_group in node.childList():
583 if scene_group.name() != 'svg:g':
584 continue
585
586 try:
587 label = scene_group.getAttribute('inkscape:label')
588 if label == 'dup':
589 continue
590 except:
591 pass
592
593 try:
594 scene_group_id = scene_group.getAttribute('id')
595 scene_node = self.get_scene(scene_group_id)
596 start, stop, tween_type = \
597 self._parse_one_scene(scene_node)
598 except:
599 continue
600
601 lyobj.scenes.append(Scene(scene_node, start, stop,
602 tween_type))
603 pass
604 pass
605 pass 574 pass
606 pass 575 pass
607 pass 576 pass
608 577
609 class MBScene(MBScene_dom): 578 class MBScene(MBScene_dom):
618 def __init__(self, desktop, win, root=None): 587 def __init__(self, desktop, win, root=None):
619 super(MBScene, self).__init__() 588 super(MBScene, self).__init__()
620 589
621 self.desktop = desktop 590 self.desktop = desktop
622 self.window = win 591 self.window = win
623 self.layers = []
624 self.layers.append(Layer(None))
625 self.top = None 592 self.top = None
626 self.last_update = None 593 self.last_update = None
627 pybInkscape.inkscape.connect('change_selection', self.show_selection) 594 pybInkscape.inkscape.connect('change_selection', self.show_selection)
628 self.last_select = None 595 self.last_select = None
629 self._lockui=False 596 self._lockui=False
720 try: 687 try:
721 frameline.duplicateGroup.setAttribute("style","display:none") 688 frameline.duplicateGroup.setAttribute("style","display:none")
722 except: 689 except:
723 print "*" * 40 690 print "*" * 40
724 layer_idx = frameline.layer_idx 691 layer_idx = frameline.layer_idx
725 layer = self.layers[layer_idx] 692 layer = self._layers[layer_idx]
726 for child in layer.group.childList(): 693 for child in layer.group.childList():
727 label = child.getAttribute('inkscape:label') 694 label = child.getAttribute('inkscape:label')
728 if label == 'dup': 695 if label == 'dup':
729 frameline.duplicateGroup = child 696 frameline.duplicateGroup = child
730 break 697 break
797 pass 764 pass
798 pass 765 pass
799 pass 766 pass
800 767
801 def enterGroup(self, obj): 768 def enterGroup(self, obj):
802 for l in self.layers: 769 for l in self._layers:
803 for s in l.group.childList(): 770 for s in l.group.childList():
804 if s.getAttribute('id') == obj.getAttribute("id"): 771 if s.getAttribute('id') == obj.getAttribute("id"):
805 self.desktop.setCurrentLayer(s.spitem) 772 self.desktop.setCurrentLayer(s.spitem)
806 pass 773 pass
807 pass 774 pass
826 self._disable_tween_type_selector = True 793 self._disable_tween_type_selector = True
827 self.tweenTypeSelector.set_active(sel_type) 794 self.tweenTypeSelector.set_active(sel_type)
828 self._disable_tween_type_selector = False 795 self._disable_tween_type_selector = False
829 pass 796 pass
830 797
831 def newCell(self,file):
832 img = gtk.Image()
833 img.set_from_file(file)
834 btn = gtk.EventBox()
835 btn.add(img)
836 btn.connect("button_press_event", self.cellSelect)
837 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
838 return btn
839
840 def onCellClick(self, line, frame, but): 798 def onCellClick(self, line, frame, but):
841 self.last_line = line 799 self.last_line = line
842 self.last_frame = frame 800 self.last_frame = frame
843 self.last_line.active_frame(frame) 801 self.last_line.active_frame(frame)
844 self._lockui = True 802 self._lockui = True
862 # 820 #
863 def _add_frameline(self, layer_idx): 821 def _add_frameline(self, layer_idx):
864 if layer_idx > len(self._framelines): 822 if layer_idx > len(self._framelines):
865 raise ValueError, 'layer number should be a consequence' 823 raise ValueError, 'layer number should be a consequence'
866 824
867 vbox = self.scrollwin_vbox 825 vbox = self._frameline_vbox
868 826
869 line = frameline(self._num_frames_of_line) 827 line = frameline(self._num_frames_of_line)
870 line.set_size_request(self._num_frames_of_line * 10, 20) 828 line.set_size_request(self._num_frames_of_line * 10, 20)
871 829
872 hbox = gtk.HBox() 830 hbox = gtk.HBox()
889 pass 847 pass
890 848
891 ## \brief Remove the given frameline from the frameline box. 849 ## \brief Remove the given frameline from the frameline box.
892 # 850 #
893 def _remove_frameline(self, layer_idx): 851 def _remove_frameline(self, layer_idx):
894 vbox = self.scrollwin_vbox 852 vbox = self._frameline_vbox
895 line = self._framelines[layer_idx] 853 line = self._framelines[layer_idx]
896 854
897 hbox = line.parent 855 hbox = line.parent
898 vbox.remove(hbox) 856 vbox.remove(hbox)
899 del self._framelines[layer_idx] 857 del self._framelines[layer_idx]
900 pass 858 pass
901 859
860 ## \brief Remove the layer that lost the layer group.
861 #
862 # This function is called when a layer group being removed from the
863 # DOM-tree.
902 def _remove_lost_group_layer(self, layer_idx): 864 def _remove_lost_group_layer(self, layer_idx):
903 layer = self.layers[layer_idx] 865 layer = self._layers[layer_idx]
904 frameline = self._framelines[layer_idx] 866 frameline = self._framelines[layer_idx]
905 for start, end, tween_type in frameline.get_frame_blocks(): 867 for start, end, tween_type in frameline.get_frame_blocks():
906 scene_node = frameline.get_frame_data(start) 868 scene_node = frameline.get_frame_data(start)
907 self._rm_scene_node(scene_node) 869 self._rm_scene_node(scene_node)
908 pass 870 pass
909 871
910 self._remove_frameline(layer_idx) # TODO 872 self._remove_frameline(layer_idx) # TODO
911 del self.layers[layer_idx] 873 del self._layers[layer_idx]
912 pass 874 pass
913 875
876 ## \brief Make status of layers is updated when DOM is changed.
877 #
878 # When DOM-tree is changed, this function make sure layer information is up
879 # to date.
914 def _make_layers_integral(self): 880 def _make_layers_integral(self):
915 root = self._root 881 root = self._root
916 root_id = root.getAttribute('id') 882 root_id = root.getAttribute('id')
917 883
918 # Remove group of removed scenes 884 # Remove group of removed layers
919 layer_idx = 0 885 layer_idx = 0
920 while layer_idx < len(self.layers): 886 while layer_idx < len(self._layers):
921 layer = self.layers[layer_idx] 887 layer = self._layers[layer_idx]
922 888
923 if layer.group.name() != 'svg:g': 889 if layer.group.name() != 'svg:g':
924 self._remove_lost_group_layer(layer.layer_idx) # TODO 890 self._remove_lost_group_layer(layer_idx) # TODO
925 continue 891 continue
926 892
927 parent = layer.group.parent() 893 parent = layer.group.parent()
928 if parent.name() != 'svg:g': 894 if parent.name() != 'svg:svg':
929 self._remove_lost_group_layer(layer.layer_idx) 895 self._remove_lost_group_layer(layer_idx)
930 continue 896 continue
931 897
932 if parent.getAttribute('id') != root_id: 898 if parent.getAttribute('id') != root_id:
933 self._remove_lost_group_layer(layer.layer_idx) 899 self._remove_lost_group_layer(layer_idx)
934 continue 900 continue
935 901
936 layer_idx = layer_idx + 1 902 layer_idx = layer_idx + 1
937 pass 903 pass
938 904
939 # Add new scenes 905 # Add new layers
940 layer_idx = 0 906 layer_idx = 0
941 for child in root.childList(): 907 for child in root.childList():
942 if child.name() != 'svg:g': 908 if child.name() != 'svg:g':
943 continue 909 continue
944 910
945 layer = self.layers[layer_idx] 911 layer = self._layers[layer_idx]
946 layer_id = layer.group.getAttribute('id') 912 layer_group_id = layer.group.getAttribute('id')
947 child_id = child.getAttribute('id') 913 child_id = child.getAttribute('id')
948 if layer_id != child_id: 914 if layer_group_id != child_id:
949 self._add_frameline(layer_id) 915 self.add_layer(layer_idx, child)
916 self.parse_layer(layer_idx)
917 self._add_frameline(layer_idx)
950 pass 918 pass
951 919
952 layer_idx = layer_idx + 1 920 layer_idx = layer_idx + 1
953 pass 921 pass
954 pass 922 pass
955 923
956 def _create_framelines(self): 924 def _init_framelines(self):
957 if not hasattr(self, 'scrollwin'): 925 self._framelines = []
958 self.scrollwin = gtk.ScrolledWindow() 926
959 self.scrollwin.set_policy(gtk.POLICY_AUTOMATIC, 927 box = gtk.ScrolledWindow()
960 gtk.POLICY_AUTOMATIC) 928 self._frameline_box = box
961 self.scrollwin.set_size_request(-1,150) 929 box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
962 vbox = gtk.VBox() 930 box.set_size_request(-1, 150)
963 vbox.show() 931 vbox = gtk.VBox()
964 self.scrollwin.add_with_viewport(vbox) 932 self._frameline_vbox = vbox
965 self.scrollwin_vbox = vbox 933 box.add_with_viewport(vbox)
966 else: 934
967 for c in self.scrollwin_vbox.get_children(): 935 nframes = self._num_frames_of_line
968 self.scrollwin_vbox.remove(c)
969 vbox = self.scrollwin_vbox
970 pass
971
972 nframes = 100
973 936
974 # 937 #
975 # Set up a ruler 938 # Set up a ruler
976 # 939 #
977 ruler = frameruler(nframes) 940 ruler = frameruler(nframes)
981 label=gtk.Label('') 944 label=gtk.Label('')
982 label.set_size_request(100,0) 945 label.set_size_request(100,0)
983 hbox.pack_start(label,expand=False,fill=True) 946 hbox.pack_start(label,expand=False,fill=True)
984 hbox.pack_start(ruler) 947 hbox.pack_start(ruler)
985 vbox.pack_start(hbox, False) 948 vbox.pack_start(hbox, False)
986 949
987 #
988 # Add a frameline for each layer
989 #
990 self._framelines = []
991 for i in range(len(self.layers)):
992 self._add_frameline(i)
993 pass
994 vbox.show_all() 950 vbox.show_all()
995 pass 951 pass
996 952
997 ## \brief Update conetent of framelines according layers. 953 def _add_frameline_for_layers(self):
998 # 954 for layer_idx in range(len(self._layers)):
999 def _update_framelines(self): 955 self._add_frameline(layer_idx)
1000 for frameline in self._framelines: 956 pass
1001 layer_idx = frameline.layer_idx 957 pass
1002 layer = self.layers[layer_idx] 958
1003 if layer.group.getAttribute("inkscape:label")==None:
1004 frameline.label.set_text('???')
1005 else:
1006 frameline.label.set_text(layer.group.getAttribute("inkscape:label"))
1007 last_scene = None
1008 for scene in layer.scenes:
1009 if last_scene and last_scene.end == scene.start:
1010 frameline.setRightTween(last_scene.end)
1011 else:
1012 frameline.add_keyframe(scene.start, scene.node)
1013 last_scene = scene
1014 if scene.start != scene.end:
1015 frameline.add_keyframe(scene.end, scene.node)
1016 tween_type_idx = self._tween_type_names.index(scene.type)
1017 tween_type = self._frameline_tween_types[tween_type_idx]
1018 frameline.tween(scene.start, tween_type)
1019 pass
1020 pass
1021 pass
1022
1023 def cellSelect(self, cell, data): 959 def cellSelect(self, cell, data):
1024 if self.last_cell: 960 if self.last_cell:
1025 color = self.last_cell.get_colormap().alloc_color("gray") 961 color = self.last_cell.get_colormap().alloc_color("gray")
1026 self.last_cell.modify_bg(gtk.STATE_NORMAL, color) 962 self.last_cell.modify_bg(gtk.STATE_NORMAL, color)
1027 pass 963 pass
1083 old_node_id = old_node.getAttribute('id') 1019 old_node_id = old_node.getAttribute('id')
1084 new_node = new_nodes.next() 1020 new_node = new_nodes.next()
1085 new_node.setAttribute('ns0:duplicate-src', old_node_id) 1021 new_node.setAttribute('ns0:duplicate-src', old_node_id)
1086 pass 1022 pass
1087 1023
1088 layer = self.layers[self.last_line.layer_idx] 1024 layer = self._layers[self.last_line.layer_idx]
1089 gid = layer.group.getAttribute("inkscape:label")+self.new_id() 1025 gid = layer.group.getAttribute("inkscape:label")+self.new_id()
1090 scene_group.setAttribute("id",gid) 1026 scene_group.setAttribute("id",gid)
1091 scene_group.setAttribute("inkscape:groupmode","layer") 1027 scene_group.setAttribute("inkscape:groupmode","layer")
1092 layer.group.appendChild(scene_group) 1028 layer.group.appendChild(scene_group)
1093 return scene_group 1029 return scene_group
1240 1176
1241 pass 1177 pass
1242 1178
1243 def _updateUI(self,node=None,arg=None): 1179 def _updateUI(self,node=None,arg=None):
1244 self._lockui = True 1180 self._lockui = True
1245 self.parseScene() 1181 self._make_layers_integral()
1246 self._create_framelines()
1247 self._update_framelines()
1248 self._lockui = False 1182 self._lockui = False
1249 pass 1183 pass
1250 1184
1251 def show(self): 1185 def show(self):
1252 self.OK = True 1186 self.OK = True
1255 pass 1189 pass
1256 1190
1257 self.document = self.desktop.doc().rdoc 1191 self.document = self.desktop.doc().rdoc
1258 self.handle_doc_root(self.document, self.root) 1192 self.handle_doc_root(self.document, self.root)
1259 self.tween = TweenObject(self.document, self.root) 1193 self.tween = TweenObject(self.document, self.root)
1260 self._updateUI() 1194 self._init_framelines()
1195 self._add_frameline_for_layers()
1196 # self._updateUI()
1197
1261 if self.top == None: 1198 if self.top == None:
1262 self.top = gtk.VBox(False,0) 1199 self.top = gtk.VBox(False,0)
1263 self.desktop.getToplevel().child.child.pack_end(self.top,expand=False) 1200 self.desktop.getToplevel().child.child.pack_end(self.top,expand=False)
1264 else: 1201 else:
1265 self.top.remove(self.startWindow) 1202 self.top.remove(self.startWindow)
1266 pass 1203 pass
1267 1204
1268 vbox = gtk.VBox(False,0) 1205 vbox = gtk.VBox(False,0)
1269 self.startWindow = vbox 1206 self.startWindow = vbox
1270 self.top.pack_start(vbox,expand=False) 1207 self.top.pack_start(vbox,expand=False)
1271 vbox.pack_start(self.scrollwin,expand=False) 1208 vbox.pack_start(self._frameline_box,expand=False)
1272 hbox=gtk.HBox(False,0) 1209 hbox=gtk.HBox(False,0)
1273 self.addButtons(hbox) 1210 self.addButtons(hbox)
1274 vbox.pack_start(hbox,expand=False) 1211 vbox.pack_start(hbox,expand=False)
1275 1212
1276 self.top.show_all() 1213 self.top.show_all()