changeset 1151:71c72e8d6755

Refactory cod eof TweenObject.updateTweenContent and MBScene.setCurrentScene(). - updateTweenContent() use frameline.get_frame_blocks(), instead of frameline._keys, to get information of tweens and key frames. - MBScene.setCurrentScene() use 'ns0:duplicate-src' attribute to map nodes from a start scene to a stop scene.
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 26 Dec 2010 23:40:09 +0800
parents 6586cd10c92f
children d333baa702a9
files pyink/MBScene.py pyink/tween.py
diffstat 2 files changed, 121 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/MBScene.py	Sun Dec 26 19:17:12 2010 +0800
+++ b/pyink/MBScene.py	Sun Dec 26 23:40:09 2010 +0800
@@ -141,10 +141,26 @@
         self.ui.updateUI()
 	pass
 
+def _travel_DOM(node):
+    nodes = [node]
+    while nodes:
+	node = nodes.pop(0)
+	child = node.firstChild()
+	while child:
+	    nodes.append(child)
+	    child = child.next()
+	    pass
+	yield node
+	pass
+    pass
+
 class MBScene():
-    _tween_types = (frameline.TWEEN_TYPE_NONE,
-		    frameline.TWEEN_TYPE_MOVE,
-		    frameline.TWEEN_TYPE_SHAPE)
+    _frameline_tween_types = (frameline.TWEEN_TYPE_NONE,
+			      frameline.TWEEN_TYPE_MOVE,
+			      frameline.TWEEN_TYPE_SHAPE)
+    _tween_obj_tween_types = (TweenObject.TWEEN_TYPE_NORMAL,
+			      TweenObject.TWEEN_TYPE_RELOCATE,
+			      TweenObject.TWEEN_TYPE_SCALE)
     _tween_type_names = ('normal', 'relocate', 'scale')
     
     def __init__(self, desktop, win, root=None):
@@ -550,6 +566,7 @@
 	"""
 	self.current = nth
 	self.tween.updateMapping()
+	idx = nth - 1
 	for layer in self._framelines:
 	    i=0
 
@@ -565,37 +582,38 @@
 	        layer.layer.node.appendChild(layer.duplicateGroup)
 	        pass
 	    # Create a new group
-#layer.duplicateGroup = None
-	    while i < len(layer._keys):
-	        s = layer._keys[i]
-		print s.ref.getAttribute("id"),s.idx,s.left_tween,s.right_tween
-		if s.right_tween is False:
-		    if nth == s.idx+1:
-		        s.ref.setAttribute("style","")
+	    for start_idx, stop_idx, tween_type in layer.get_frame_blocks():
+		if start_idx == stop_idx:
+		    scene_group = layer.get_frame_data(start_idx)
+		    if idx == start_idx:
+			scene_group.setAttribute('style', '')
 		    else:
-		        s.ref.setAttribute("style","display:none")
-		    i = i + 1
-		    continue
-		
-		if nth == s.idx + 1:
-		    s.ref.setAttribute("style","")
+			scene_group.setAttribute('style', 'display: none')
+			pass
+		elif start_idx <= idx and stop_idx >= idx:
+		    scene_group = layer.get_frame_data(start_idx)
+		    scene_group.setAttribute("style","display:none")
+		    layer.duplicateGroup.setAttribute("style","")
+		    tween_type_idx = \
+			self._frameline_tween_types.index(tween_type)
+		    tween_obj_tween_type = \
+			self._tween_obj_tween_types[tween_type_idx]
+		    
+		    next_idx, next_stop_idx, next_tween_type = \
+			layer.get_frame_block(stop_idx + 1)
+		    next_scene_group = layer.get_frame_data(next_idx)
+		    
+		    nframes = next_idx - start_idx + 1
+		    percent = float(idx - start_idx) / nframes
+		    self.tween.updateTweenContent(layer.duplicateGroup,
+						  tween_obj_tween_type,
+						  scene_group,
+						  next_scene_group,
+						  percent)
 		else:
-		    if nth > (s.idx+1) and nth <= (layer._keys[i+1].idx+1):
-			if i+2 < len(layer._keys):
-			    s.ref.setAttribute("style","display:none")
-	                    layer.duplicateGroup.setAttribute("style","")
-			    d = layer._keys[i + 2]
-			    self.tween.\
-				updateTweenContent(layer.duplicateGroup,
-						   layer.get_tween_type(s.idx),
-						   s, d, nth)
-			else:
-	                    layer.duplicateGroup.setAttribute("style","")
-			    s.ref.setAttribute("style","display:none")
-			    pass
-		    else:
-		        s.ref.setAttribute("style","display:none")
-		i = i + 2
+		    scene_group = layer.get_frame_data(start_idx)
+		    scene_group.setAttribute("style","display:none")
+		    pass
 		pass
 	    pass
 	pass
@@ -635,7 +653,7 @@
         pass
 
     def setTweenType(self, tween_type):
-	sel_type = MBScene._tween_types.index(tween_type)
+	sel_type = MBScene._frameline_tween_types.index(tween_type)
 	self._disable_tween_type_selector = True
 	self.tweenTypeSelector.set_active(sel_type)
 	self._disable_tween_type_selector = False
@@ -729,7 +747,7 @@
 		if scene.start != scene.end:
 		    frameline.add_keyframe(scene.end-1,scene.node)
 		    tween_type_idx = self._tween_type_names.index(scene.type)
-		    tween_type = self._tween_types[tween_type_idx]
+		    tween_type = self._frameline_tween_types[tween_type_idx]
 		    frameline.tween(scene.start-1, tween_type)
 		pass
 	    pass
@@ -787,6 +805,15 @@
 	if orig == None:
 	    return None
 	ns = orig.duplicate(rdoc)
+
+	old_nodes = _travel_DOM(orig)
+	new_nodes = _travel_DOM(ns)
+	for old_node in old_nodes:
+	    old_node_id = old_node.getAttribute('id')
+	    new_node = new_nodes.next()
+	    new_node.setAttribute('ns0:duplicate-src', old_node_id)
+	    pass
+
 	gid = self.last_line.node.getAttribute("inkscape:label")+self.newID()
 	self.ID[gid]=1
 	ns.setAttribute("id",gid)
@@ -893,7 +920,7 @@
 	for start_idx, stop_idx, tween_type in frameline.get_frame_blocks():
 	    if start_idx < stop_idx:
 		n = self.tweenTypeSelector.get_active()
-		new_tween_type = MBScene._tween_types[n]
+		new_tween_type = MBScene._frameline_tween_types[n]
 		self.last_line.set_tween_type(start_idx, new_tween_type)
 		self.update()
 		break
@@ -929,7 +956,7 @@
 	doc = self.document
 	for start_idx, stop_idx, tween_type in frameline.get_frame_blocks():
 	    ref = frameline.get_frame_data(start_idx)
-	    tween_type_idx = self._tween_types.index(tween_type)
+	    tween_type_idx = self._frameline_tween_types.index(tween_type)
 	    tween_type_name = self._tween_type_names[tween_type_idx]
 	    
 	    scene_node = doc.createElement("ns0:scene")
--- a/pyink/tween.py	Sun Dec 26 19:17:12 2010 +0800
+++ b/pyink/tween.py	Sun Dec 26 23:40:09 2010 +0800
@@ -2,7 +2,12 @@
 # vim: sw=4:ts=8:sts=4
 import traceback
 import math
+
 class TweenObject:
+    TWEEN_TYPE_NORMAL = 0
+    TWEEN_TYPE_RELOCATE = 1
+    TWEEN_TYPE_SCALE = 2
+    
     def __init__(self,doc,dom):
         self.document = doc
 	self.dom = dom
@@ -24,81 +29,66 @@
 	        self.nodeToItem[c.getAttribute("id")] = c
 	    except:
 	        pass
-    def updateTweenContent(self,obj, typ, source,dest,cur):
+    def updateTweenContent(self, duplicate_group, tween_type,
+			   start_scene_group, stop_scene_group, percent):
 	"""
-	    Update the content of the duplicate scene group. We will
-	    use the (start,end) and cur to calculate the percentage of
-	    the tween motion effect and then use it to update the
-	    transform matrix of the duplicated scene group.
+	    Update the content of the duplicate scene group.  We will
+	    use precent, start_scene_group, stop_scene_group to
+	    compute transform matrix and update duplicate scene group
+	    specified.
 	"""
-
-	start = source.idx
-	end = dest.idx
-	print cur,start,end
-	percent = (cur-start)*1.0/(end-start)
-	i = 0
-	s = source.ref.firstChild()
-	d = dest.ref.firstChild()
-	sources={}
-	dests={}
 	# Collect ref from the obj
-	o = obj.firstChild()
-	maps={}
-	while o:
-	    print "--->",o
+	node = duplicate_group.firstChild()
+	dup_nodes = {}
+	while node:
 	    try:
-	        ref = o.getAttribute("ref")
+	        ref = node.getAttribute("ref")
+		dup_nodes[ref] = node
 	    except:
-	        print o
 		ref = None
+		pass
+	    node = node.next()
+	    pass
 
-	    if ref:
-	        maps[ref] = o
-	    o = o.next()
-	# Collect all objects
-	while d:
+	# Collect all nodes in stop scene
+	stop_nodes = {}
+	node = stop_scene_group.firstChild()
+	while node:
 	    try:
-		label = d.getAttribute("inkscape:label")
-	    except:
-		d = d.next()
-		continue
-	    dests[label] = d
-	    d = d.next()
-	# Check if the object in the source exists in the destination
-	s = source.ref.firstChild()
-	d = dest.ref.firstChild()
-	while s:
-	    print s,d
-	    sid = s.getAttribute("id")
-	    if maps.has_key(sid):
-	        o = maps[sid]
-	    else:
-	        o = None
-	    try:
-		label = s.getAttribute("inkscape:label")
-		# Use i8nkscape:label to identidy the equipvalent objects
-		if label:
-		    if dests.has_key(label):
-			self.updateTweenObject(obj, typ, s,
-					       dests[label], percent, o)
-			s = s.next()
-			continue
+		node_label = node.getAttribute("ns0:duplicate-src")
+		stop_nodes[node_label] = node
 	    except:
 		pass
-	    # Search obejcts in the destination
-	    while d:
-		try:
-		    d.getAttribute("inkscape:label")
-		    d = d.next()
-		    continue
-		except:
-		    pass
-		if s.name() == d.name():
-		    self.updateTweenObject(obj,typ,s,d,percent,o)
-		    d = d.next()
-		    break
-		d = d.next()
-	    s = s.next()
+	    node = node.next()
+	    pass
+
+	#
+	# Node ID of a node of start scene must be mapped to
+	# 'ns0:duplicate-src' attribute of a node of stop scene.  The
+	# nodes which can not be mapped to a node of stop scene are
+	# not manipulated by the tween.
+	#
+	# When a scene is duplicated, 'ns0:duplicate-src' attribute of
+	# nodes, in the new scene, must be setted to ID of respective
+	# one in the duplicated scene.
+	#
+	start_node = start_scene_group.firstChild()
+	while start_node:
+	    start_node_id = start_node.getAttribute('id')
+	    try:
+		stop_node = stop_nodes[start_node_id]
+	    except KeyError:
+		start_node = start_node.next()
+		continue
+	    
+	    dup_node = dup_nodes.setdefault(start_node_id, None)
+	    
+	    self.updateTweenObject(duplicate_group, tween_type,
+				   start_node, stop_node,
+				   percent, dup_node)
+	    start_node = start_node.next()
+	    pass
+	pass
 
     def parseTransform(self,obj):
 	"""
@@ -171,7 +161,7 @@
 	    Generate tweened object in the @obj by using s and d in the @p percent
 	    http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
 	"""
-	if typ == 1:
+	if typ == self.TWEEN_TYPE_RELOCATE:
 	    if s.name() == 'svg:g':
 		if not newobj:
 		    newobj = s.duplicate(self.document)
@@ -207,10 +197,10 @@
 		    traceback.print_exc()
 		    pass
 	    pass
-	elif typ == 2:
+	elif typ == self.TWEEN_TYPE_SCALE:
 	    self.updateTweenObjectScale(obj,s,d,p,newobj)
 	    pass
-	elif typ == 0:
+	elif typ == self.TWEEN_TYPE_NORMAL:
 	    newobj = s.duplicate(self.document)
 	    newobj.setAttribute("ref", s.getAttribute("id"))
 	    top = self.document.createElement("svg:g")