comparison inkscape/MB_Frame.py @ 233:ec62453bbb2b

Add frame support into the inkscape.
author wycc
date Mon, 22 Dec 2008 00:21:46 +0800
parents
children 889cdc5f23c5
comparison
equal deleted inserted replaced
232:527894c2ad39 233:ec62453bbb2b
1 #!/usr/bin/python
2 import inkex
3 import pygtk
4 import gtk
5 from copy import deepcopy
6 from lxml import etree
7 import random
8
9 # In the inkscape, the top layer group are treated as layer. The Mad butter fly add another structure under the layer as frame. It means that each layer can has multiple frame.
10 # Like the layer, the frames are represented by special groups. All groups directly under a layer will be treated as frames. However, a group may be spanned for more than one
11 # frame. For example
12 # <g id="layer1">
13 # <g id="g1234" scene="1">
14 # </g>
15 # <g id="g1235" scene="2-7">
16 # </g>
17 # <g id="g1236">
18 # </g>
19 # </g>
20 # This will stand for 7 scenes. Scene 1 and scene 2 are key scenes. 3,4,5,6,7 are filled scenes.In the above example, g1234 and g1236 are in the scene 1. g1235 and g1236 are in
21 # scene 2-7
22 #
23 # In the inkscape extention, we will provide an grid for users to select the current scene or change the scene structure. Users are allowed to
24 # Insert a new key scene
25 # Delete a key scene
26 # Insert a filled scene
27 # Delete a filled scene
28 # Select a scene for edit.
29 #
30 # When user select a scene to edit, we will hide all scenes which is not in the selected scene. For example, if we select scene 4, g1234 will be hidden and g1235 and g1236 will
31 # be displayed.
32
33
34
35 # Algorithm:
36 #
37 # We will parse the first two level of the SVG DOM. collect a table of layer and scene.
38 # 1. Collect the layer table which will be displayed as the first column of the grid.
39 # 2. Get the maximum scene number. This will decide the size of the grid.
40 # 3. When F6 is pressed, we will check if this scene has been defined. This can be done by scan all second level group and check if the current scene number is within the
41 # range specified by scene field. The function IsSceneDefined(scene) can be used for this purpose.
42 # 4. If this is a new scene, we will append a new group which duplication the content of the last scene in the same group. The scene field will contain the number from the
43 # last scene number of the last scene to the current scenen number. For example, if the last scene is from 4-7 and the new scene is 10, we will set the scene field as
44 # "8-10".
45 # 5. If this scene are filled screne, we will split the existing scene into two scenes with the same content.
46
47 class Layer:
48 def __init__(self,node):
49 self.scene = []
50 self.node = node
51 class Scene:
52 def __init__(self, node, start,end):
53 self.node = node
54 self.start = int(start)
55 self.end = int(end)
56
57
58 class MBScene(inkex.Effect):
59 def confirm(self,msg):
60 vbox = gtk.VBox()
61 vbox.pack_start(gtk.Label(msg))
62 self.button = gtk.Button('OK')
63 vbox.pack_start(self.button)
64 self.button.connect("clicked", self.onQuit)
65 self.window.add(vbox)
66 def dumpattr(self,n):
67 s = ""
68 for a,v in n.attrib.items():
69 s = s + ("%s=%s" % (a,v))
70 return s
71
72 def dump(self,node,l=0):
73 print " " * l*2,"<", node.tag, self.dumpattr(node),">"
74 for n in node:
75 self.dump(n,l+1)
76 print " " * l * 2,"/>"
77
78 def parseScene(self):
79 self.layer = []
80 for layer in self.document.getroot():
81 if layer.tag == '{http://www.w3.org/2000/svg}g':
82 #print layer.attrib.get("id")
83 lyobj = Layer(layer)
84 self.layer.append(lyobj)
85 for scene in layer:
86 if scene.tag == '{http://www.w3.org/2000/svg}g':
87 range = scene.attrib.get("scene").split('-')
88 if len(range) == 1:
89 #print " scene %d" % int(range[0])
90 lyobj.scene.append(Scene(scene,range[0],range[0]))
91 elif len(range) == 2:
92 #print " scene%d-%d" % (int(range[0]),int(range[1]))
93 lyobj.scene.append(Scene(scene,range[0],range[1]))
94 self.collectID()
95 #self.dumpID()
96 def collectID(self):
97 self.ID = {}
98 root = self.document.getroot()
99 for n in root:
100 self.collectID_recursive(n)
101 def collectID_recursive(self,node):
102 self.ID[node.get("id")] = 1
103 for n in node:
104 self.collectID_recursive(n)
105 def newID(self):
106 while True:
107 n = 's%d' % int(random.random()*10000)
108 #print "try %s" % n
109 if self.ID.has_key(n) == False:
110 return n
111 def dumpID(self):
112 for a,v in self.ID.items():
113 print a
114
115
116 def getLayer(self, layer):
117 for l in self.layer:
118 if l.node.attrib.get("id") == layer:
119 return l
120 return None
121
122
123 def insertKeyScene(self):
124 """
125 Insert a new key scene into the stage. If the nth is always a key scene, we will return without changing anything.
126 If the nth is a filled scene, we will break the original scene into two parts. If the nth is out of any scene, we will
127 append a new scene.
128
129 """
130 nth = self.last_cell.nScene
131 layer = self.getLayer(self.last_cell.layer)
132 x = self.last_cell.nScene
133 y = self.last_cell.nLayer
134 if layer == None: return
135 for i in range(0,len(layer.scene)):
136 s = layer.scene[i]
137 if nth >= s.start and nth <= s.end:
138 if nth == s.start: return
139 newscene = Scene(deepcopy(s.node),nth,s.end)
140 newscene.node.set("id", self.newID())
141 layer.scene.insert(i+1,newscene)
142 layer.scene[i].end = nth-1
143 btn = self.newCell('start.png')
144 btn.nScene = nth
145 btn.layer = layer
146 btn.nLayer = y
147 self.grid.remove(self.last_cell)
148 self.grid.attach(btn, x,x+1,y,y+1,0,0,0,0)
149 return
150 if len(layer.scene) > 0:
151 last = layer.scene[len(layer.scene)-1]
152 for x in range(last.end+1, nth):
153 btn = self.newCell('fill.png')
154 btn.nScene = x
155 btn.layer = layer
156 btn.nLayer = y
157 self.grid.attach(btn, x, x+1, y , y+1,0,0,0,0)
158 last.end = nth-1
159 newscene = Scene(deepcopy(s.node),nth,nth)
160 newscene.node.set("id",self.newID())
161 layer.scene.append(newscene)
162 btn = self.newCell('start.png')
163 x = self.last_cell.nScene
164 y = self.last_cell.nLayer
165 btn.nScene = nth
166 btn.layer = layer
167 btn.nLayer = y
168 self.grid.attach(btn, x, x+1, y, y+1,0,0,0,0)
169
170
171 def removeKeyScene(self):
172 nth = self.last_cell.nScene
173 layer = self.getLayer(self.last_cell.layer)
174 x = self.last_cell.nScene
175 y = self.last_cell.nLayer
176 # We can not remove the key scene at the first scene
177 if nth == 1: return
178 for i in range(0,len(layer.scene)):
179 s = layer.scene[i]
180 if nth == s.start:
181 layer.scene[i-1].end = s.end
182 layer.scene.remove(s)
183 btn = self.newCell('fill.png')
184 btn.nScene = nth
185 btn.layer = layer
186 btn.nLayer = y
187 self.grid.attach(btn, x,x+1,y,y+1,0,0,0,0)
188 return
189
190 def extendScene(self,layer,nth):
191 layer = self.getLayer(layer)
192 if layer == None: return
193 for i in range(0,len(layer.scene)-1):
194 s = layer.scene[i]
195 if nth >= layer.scene[i].start and nth < layer.scene[i+1].start:
196 layer.scene[i].end = nth
197 if len(layer.scene) > 0:
198 layer.scene[len(layer.scene)-1].end = nth
199 def setCurrentScene(self,nth):
200 for layer in self.layer:
201 for s in layer.scene:
202 if nth >= s.start and nth <= s.end:
203 s.node.set("style","")
204 else:
205 s.node.set("style","display:none")
206 def generate(self):
207 newdoc = deepcopy(self.document)
208 root = newdoc.getroot()
209 for n in root:
210 if n.tag == '{http://www.w3.org/2000/svg}g':
211 root.remove(n)
212
213 for l in self.layer:
214 # Duplicate all attribute of the layer
215 lnode = etree.Element("{http://www.w3.org/2000/svg}g")
216 for a,v in l.node.attrib.items():
217 lnode.set(a,v)
218 root.append(lnode)
219 for s in l.scene:
220 snode = etree.Element("{http://www.w3.org/2000/svg}g")
221 for a,v in s.node.attrib.items():
222 snode.set(a,v)
223 if s.start == s.end:
224 snode.set("scene", "%d" % s.start)
225 else:
226 snode.set("scene","%d-%d" % (s.start,s.end))
227 for n in s.node:
228 snode.append(deepcopy(n))
229 lnode.append(snode)
230 self.document = newdoc
231 def newCell(self,file):
232 img = gtk.Image()
233 img.set_from_file(file)
234 btn = gtk.EventBox()
235 btn.add(img)
236 btn.connect("button_press_event", self.cellSelect)
237 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
238 return btn
239 def showGrid(self):
240 max = 0
241 for layer in self.layer:
242 for s in layer.scene:
243 if s.end > max:
244 max = s.end
245 max = 50
246
247 self.grid = gtk.Table(len(self.layer)+1, 50)
248 self.scrollwin = gtk.ScrolledWindow()
249 self.scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
250 self.scrollwin.add_with_viewport(self.grid)
251 for i in range(1,max):
252 self.grid.attach(gtk.Label('%d'% i), i,i+1,0,1,0,0,0,0)
253 for i in range(1,len(self.layer)+1):
254 l = self.layer[i-1]
255 self.grid.attach(gtk.Label(l.node.get('id')), 0, 1, i, i+1,0,0,10,0)
256 for s in l.scene:
257 btn = self.newCell('start.png')
258 btn.nScene = s.start
259 btn.layer = l.node.get('id')
260 btn.nLayer = i
261
262 self.grid.attach(btn, s.start, s.start+1, i, i+1,0,0,0,0)
263 for j in range(s.start+1,s.end+1):
264 btn = self.newCell('fill.png')
265 self.grid.attach(btn, j, j+1, i , i+1,0,0,0,0)
266 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
267 btn.nScene = j
268 btn.layer = l.node.get('id')
269 btn.nLayer = i
270 if len(l.scene) == 0:
271 start = 0
272 else:
273 start = l.scene[len(l.scene)-1].end
274 for j in range(start,max):
275 btn = self.newCell('empty.png')
276 self.grid.attach(btn, j+1, j+2,i,i+1,0,0,0,0)
277 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
278 btn.nScene = j+1
279 btn.layer = l.node.get('id')
280 btn.nLayer = i
281 self.last_cell = None
282 def cellSelect(self, cell, data):
283 if self.last_cell:
284 self.last_cell.modify_bg(gtk.STATE_NORMAL, self.last_cell.get_colormap().alloc_color("gray"))
285
286 self.last_cell = cell
287 cell.modify_bg(gtk.STATE_NORMAL, cell.get_colormap().alloc_color("green"))
288
289 def doEditScene(self,w):
290 self.setCurrentScene(self.last_cell.nScene)
291 self.generate()
292 gtk.main_quit()
293 def doInsertKeyScene(self,w):
294 self.insertKeyScene()
295 self.grid.show_all()
296 self.generate()
297
298 def doRemoveScene(self,w):
299 self.removeKeyScene()
300 self.grid.show_all()
301 self.generate()
302 def addButtons(self,hbox):
303 btn = gtk.Button('Edit')
304 btn.connect('clicked', self.doEditScene)
305 hbox.pack_start(btn)
306 btn = gtk.Button('Insert Key')
307 btn.connect('clicked',self.doInsertKeyScene)
308 hbox.pack_start(btn)
309 btn=gtk.Button('Remove Key')
310 btn.connect('clicked', self.doRemoveScene)
311 hbox.pack_start(btn)
312 def effect(self):
313 self.parseScene()
314 self.showGrid()
315 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
316 self.window.connect("destroy", gtk.main_quit)
317 self.window.set_position(gtk.WIN_POS_MOUSE)
318 vbox = gtk.VBox()
319 self.window.add(vbox)
320 vbox.add(self.scrollwin)
321 self.vbox = vbox
322 hbox=gtk.HBox()
323 self.addButtons(hbox)
324 vbox.add(hbox)
325 self.window.set_size_request(600,200)
326 self.window.show_all()
327 gtk.main()
328
329
330
331
332
333 A = MBScene()
334 A.affect()
335
336