changeset 1123:aad659b6b625

Add motion animation editor.
author wycc
date Thu, 09 Dec 2010 07:48:08 +0800
parents 3d438daea48c
children b5ff72dbc910
files pyink/MBScene.py pyink/mbtest.svg
diffstat 2 files changed, 296 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/MBScene.py	Thu Dec 09 07:47:14 2010 +0800
+++ b/pyink/MBScene.py	Thu Dec 09 07:48:08 2010 +0800
@@ -429,9 +429,35 @@
 
     
     def setCurrentScene(self,nth):
+	"""
+	    Update the scene group according to the curretn scene data. There are a couple of cases.
+	    1. If the type of the scene is normal, we display it when it contains the current 
+	       frame. Otherwise hide it.
+	    2. If the type of the scene is relocate or scale, we need to duplicate the scene group
+	       and then modify its transform matrix according to the definition of the scene. Then,
+	       hide the original scenr group and display the duplciate scene group. In addition,
+	       we may need to delete the old duplicated scene group as well.
+
+	    For each layer, we will always use the duplicated scene group whose name as dup.
+	    We will put the duplicated scene group inside it. We will create this group if it is not
+	    available.
+	"""
 	self.current = nth
 	for layer in self._framelines:
 	    i=0
+
+	    # Check the duplicated scene group and create it if it is not available
+	    try:
+	        if layer.duplicateGroup:
+		    layer.duplicateGroup.parent().removeChild(layer.duplicateGroup)
+		    layer.duplicateGroup = None
+	    except:
+	        traceback.print_exc()
+	        pass
+	    # Create a new group
+	    layer.duplicateGroup = None
+
+
 	    while i < len(layer._keys):
 	        s = layer._keys[i]
 		print s.ref.attribute("id"),s.idx,s.left_tween,s.right_tween
@@ -442,15 +468,131 @@
 		        s.ref.setAttribute("style","display:none",True)
 		    i = i + 1
 		    continue
-
-		if nth >= (s.idx+1) and nth <= (layer._keys[i+1].idx+1):
+		if nth == s.idx + 1:
 		    s.ref.setAttribute("style","",True)
 		else:
-		    s.ref.setAttribute("style","display:none",True)
+		    if nth > (s.idx+1) and nth <= (layer._keys[i+1].idx+1):
+			if i+2 < len(layer._keys):
+			    layer.duplicateGroup = self.desktop.doc().rdoc.createElement("svg:g")
+			    layer.duplicateGroup.setAttribute("inkscape:label","dup",True)
+			    s.ref.setAttribute("style","display:none",True)
+			    s.ref.parent().appendChild(layer.duplicateGroup)
+			    self.updateTweenContent(layer.duplicateGroup, layer.get_tween_type(s.idx),s, layer._keys[i+2], nth)
+		    else:
+		        s.ref.setAttribute("style","display:none",True)
 		i = i + 2
 		pass
 	    pass
 	pass
+    def updateTweenContent(self,obj, typ, source,dest,cur):
+	"""
+	    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.
+	"""
+	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 all objects
+	while d:
+	    try:
+		label = d.attribute("inkscape:label")
+	    except:
+		d = d.next()
+		continue
+	    dests[label.value()] = 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
+	    try:
+		label = s.attribute("inkscape:label")
+		# Use i8nkscape:label to identidy the equipvalent objects
+		if label:
+		    if dests.hasattr(label.value()):
+			self.updateTweenObject(obj,typ,s,dests[label.value()],percent)
+			s = s.next()
+			continue
+	    except:
+		pass
+	    # Search obejcts in the destination
+	    while d:
+		try:
+		    d.attribute("inkscape:label")
+		    d = d.next()
+		    continue
+		except:
+		    pass
+		if s.name() == d.name():
+		    self.updateTweenObject(obj,typ,s,d,percent)
+		    d = d.next()
+		    break
+		d = d.next()
+	    s = s.next()
+    def parseTransform(self,obj):
+	"""
+	    Return the transform matrix of an object
+	"""
+	try:
+	    t = obj.attribute("transform")
+	    print t
+	    if t[0:9] == 'translate':
+		print "translate"
+		fields = t[10:].split(',')
+		x = float(fields[0])
+		fields = fields[1].split(')')
+		y = float(fields[0])
+		return [1,0,x,0,1,y]
+	    elif t[0:6] == 'matrix':
+		print "matrix"
+		fields=t[7:].split(')')
+		fields = fields[0].split(',')
+		return [float(fields[0]),float(fields[1]),float(fields[2]),float(fields[3]),float(fields[4]),float(fields[5])]
+	except:
+	    traceback.print_exc()
+	    return [1,0,0,0,1,0]
+
+	    
+    def updateTweenObject(self,obj,typ,s,d,p):
+	"""
+	    Generate tweened object in the @obj by using s and d in the @p percent
+	"""
+	print 'compare',s,d
+	if typ == 'relocate':
+	    print "percent",p
+	    newobj = s.duplicate(self.desktop.doc().rdoc)
+	    top = self.desktop.doc().rdoc.createElement("svg:g")
+	    top.appendChild(newobj)
+	    obj.appendChild(top)
+	    print s.name()
+	    if s.name() == 'svg:g':
+		# Parse the translate or matrix
+		sm = self.parseTransform(s)
+		dm = self.parseTransform(d)
+		print "g", (dm[2]-sm[2])*p,(dm[5]-sm[5])*p
+		top.setAttribute("transform","translate(%g,%g)" % ((dm[2]-sm[2])*p,(dm[5]-sm[5])*p),True)
+	    else:
+		try:
+		    sx = float(s.attribute("x"))
+		    sy = float(s.attribute("y"))
+		    dx = float(d.attribute("x"))
+		    dy = float(d.attribute("y"))
+		    tx = (dx-sx)*p
+		    ty = (dy-sy)*p
+		    print tx,ty
+		    top.setAttribute("transform","translate(%g,%g)" % (tx,ty),True)
+		except:
+		    traceback.print_exc()
+		    pass
+	    pass
+	pass
     def enterGroup(self,obj):
         for l in self.layers:
 	    for s in l.node.childList():
--- a/pyink/mbtest.svg	Thu Dec 09 07:47:14 2010 +0800
+++ b/pyink/mbtest.svg	Thu Dec 09 07:48:08 2010 +0800
@@ -29,7 +29,7 @@
      inkscape:zoom="1.6029106"
      inkscape:cx="238.58561"
      inkscape:cy="290.40921"
-     inkscape:current-layer="g3189"
+     inkscape:current-layer="layer2"
      inkscape:document-units="px"
      showgrid="false"
      inkscape:window-width="1400"
@@ -180,6 +180,45 @@
        y1="28.009714"
        x2="104.68548"
        y2="28.009714" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3211-0-5-5"
+       id="linearGradient3316-4-8-2"
+       gradientUnits="userSpaceOnUse"
+       x1="31.940987"
+       y1="28.009714"
+       x2="104.68548"
+       y2="28.009714" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3211-0-5-5">
+      <stop
+         style="stop-color:#001dff;stop-opacity:1;"
+         offset="0"
+         id="stop3213-3-8-8" />
+      <stop
+         style="stop-color:#001dff;stop-opacity:0;"
+         offset="1"
+         id="stop3215-9-4-6" />
+    </linearGradient>
+    <filter
+       color-interpolation-filters="sRGB"
+       inkscape:collect="always"
+       id="filter3295-1-3-2">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.67110109"
+         id="feGaussianBlur3297-9-7-8" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3211-0-5-5"
+       id="linearGradient3909"
+       gradientUnits="userSpaceOnUse"
+       x1="31.940987"
+       y1="28.009714"
+       x2="104.68548"
+       y2="28.009714" />
   </defs>
   <metadata
      id="metadata2388">
@@ -211,9 +250,13 @@
          type="normal" />
       <ns0:scene
          start="1"
-         ref="g3189"
+         ref="g3303"
          end="15"
          type="relocate" />
+      <ns0:scene
+         start="16"
+         ref="Backgrounds4326"
+         type="normal" />
     </ns0:scenes>
   </metadata>
   <g
@@ -222,59 +265,58 @@
      inkscape:label="Background"
      style="display:inline">
     <g
-       id="g3189"
-       style="">
-      <rect
-         style="fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;display:inline"
-         id="rect2437"
-         width="641.95721"
-         height="481.62387"
-         x="0.93578684"
-         y="-10.98185" />
+       style="display:none"
+       transform="translate(-15.128732,2.0275737)"
+       id="g3303"
+       inkscape:label="action1">
+      <g
+         id="g3189">
+        <rect
+           style="fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;display:inline"
+           id="rect2437"
+           width="641.95721"
+           height="481.62387"
+           x="0.93578684"
+           y="-10.98185" />
+        <rect
+           style="fill:#ffcc1d;fill-opacity:1;stroke:none"
+           id="rect3698"
+           width="624.48901"
+           height="46.789886"
+           x="6.8625164"
+           y="5.8625031"
+           rx="10"
+           ry="10" />
+      </g>
       <rect
-         style="fill:#ffcc1d;fill-opacity:1;stroke:none"
-         id="rect3698"
-         width="624.48901"
-         height="46.789886"
-         x="6.8625164"
-         y="5.8625031"
-         rx="10"
-         ry="10" />
-      <g
-         style="display:inline"
-         transform="translate(-15.128732,2.0275737)"
-         id="g3303"
-         inkscape:label="action1">
-        <rect
-           y="15.22048"
-           x="32.440987"
-           height="25.57847"
-           width="71.744492"
-           id="rect2439"
-           style="fill:url(#linearGradient3237);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" />
-        <text
-           id="text3299"
+         y="15.22048"
+         x="32.440987"
+         height="25.57847"
+         width="71.744492"
+         id="rect2439"
+         style="fill:url(#linearGradient3237);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" />
+      <text
+         id="text3299"
+         y="33.312569"
+         x="39.927368"
+         style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           style="font-size:16px"
            y="33.312569"
            x="39.927368"
-           style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
-           xml:space="preserve"><tspan
-             style="font-size:16px"
-             y="33.312569"
-             x="39.927368"
-             id="tspan3301"
-             sodipodi:role="line">Action</tspan></text>
-      </g>
+           id="tspan3301"
+           sodipodi:role="line">Action</tspan></text>
       <g
          style="display:inline"
          id="g3308"
-         transform="translate(76.891374,2.9633707)">
+         transform="translate(75.331712,-0.46789912)">
         <rect
            y="15.22048"
            x="32.440987"
            height="25.57847"
            width="71.744492"
            id="rect3310"
-           style="fill:url(#linearGradient3316-4-8);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)" />
+           style="fill:url(#linearGradient3316-4-8-2);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3-2)" />
         <text
            id="text3312"
            y="33.312569"
@@ -289,7 +331,72 @@
       </g>
     </g>
     <g
-       id="s4393" />
+       inkscape:label="action1"
+       id="Backgrounds4326"
+       transform="translate(-15.128732,2.0275737)"
+       style=""
+       inkscape:groupmode="layer">
+      <g
+         id="g3889">
+        <rect
+           y="-10.98185"
+           x="0.93578684"
+           height="481.62387"
+           width="641.95721"
+           id="rect3891"
+           style="fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;display:inline" />
+        <rect
+           ry="10"
+           rx="10"
+           y="5.8625031"
+           x="6.8625164"
+           height="46.789886"
+           width="624.48901"
+           id="rect3893"
+           style="fill:#ffcc1d;fill-opacity:1;stroke:none" />
+      </g>
+      <rect
+         style="fill:url(#linearGradient3237);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3)"
+         id="rect3895"
+         width="71.744492"
+         height="25.57847"
+         x="32.440987"
+         y="15.22048" />
+      <text
+         xml:space="preserve"
+         style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+         x="39.927368"
+         y="33.312569"
+         id="text3897"><tspan
+           sodipodi:role="line"
+           id="tspan3899"
+           x="39.927368"
+           y="33.312569"
+           style="font-size:16px">Action</tspan></text>
+      <g
+         transform="translate(170.78307,-0.46789912)"
+         id="g3901"
+         style="display:inline">
+        <rect
+           style="fill:url(#linearGradient3909);fill-opacity:1;stroke:none;filter:url(#filter3295-1-3-2)"
+           id="rect3903"
+           width="71.744492"
+           height="25.57847"
+           x="32.440987"
+           y="15.22048" />
+        <text
+           xml:space="preserve"
+           style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+           x="39.927368"
+           y="33.312569"
+           id="text3905"><tspan
+             sodipodi:role="line"
+             id="tspan3907"
+             x="39.927368"
+             y="33.312569"
+             style="font-size:16px">Select</tspan></text>
+      </g>
+    </g>
   </g>
   <g
      inkscape:groupmode="layer"