NodeBox source

Expand NodeBox with your own code or make custom builds

root/nodebox/trunk/src/nodebox/console.py

Revision 287, 5.4 kB (checked in by fdb, 8 months ago)

Console now runs main

Line 
1 from AppKit import NSApplication
2
3 from nodebox import graphics
4 from nodebox import util
5
6 class NodeBoxRunner(object):
7    
8     def __init__(self):
9         # Force NSApp initialisation.
10         NSApplication.sharedApplication().activateIgnoringOtherApps_(0)
11         self.namespace = {}
12         self.canvas = graphics.Canvas()
13         self.context = graphics.Context(self.canvas, self.namespace)
14         self.__doc__ = {}
15         self._pageNumber = 1
16         self.frame = 1
17        
18     def _check_animation(self):
19         """Returns False if this is not an animation, True otherwise.
20         Throws an expection if the animation is not correct (missing a draw method)."""
21         if self.canvas.speed is not None:
22             if not self.namespace.has_key('draw'):
23                 raise graphics.NodeBoxError('Not a correct animation: No draw() method.')
24             return True
25         return False
26
27     def run(self, source_or_code):
28         self._initNamespace()
29         if isinstance(source_or_code, basestring):
30             source_or_code = compile(source_or_code + "\n\n", "<Untitled>", "exec")
31         exec source_or_code in self.namespace
32         if self._check_animation():
33             if self.namespace.has_key('setup'):
34                 self.namespace['setup']()
35             self.namespace['draw']()
36        
37     def run_multiple(self, source_or_code, frames):
38         if isinstance(source_or_code, basestring):
39             source_or_code = compile(source_or_code + "\n\n", "<Untitled>", "exec")
40            
41         # First frame is special:
42         self.run(source_or_code)
43         yield 1
44         animation = self._check_animation()
45            
46         for i in range(frames-1):
47             self.canvas.clear()
48             self.frame = i + 2
49             self.namespace["PAGENUM"] = self.namespace["FRAME"] = self.frame
50             if animation:
51                 self.namespace['draw']()
52             else:
53                 exec source_or_code in self.namespace
54             yield self.frame
55    
56     def _initNamespace(self, frame=1):
57         self.canvas.clear()
58         self.namespace.clear()
59         # Add everything from the namespace
60         for name in graphics.__all__:
61             self.namespace[name] = getattr(graphics, name)
62         for name in util.__all__:
63             self.namespace[name] = getattr(util, name)
64         # Add everything from the context object
65         self.namespace["_ctx"] = self.context
66         for attrName in dir(self.context):
67             self.namespace[attrName] = getattr(self.context, attrName)
68         # Add the document global
69         self.namespace["__doc__"] = self.__doc__
70         # Add the frame
71         self.frame = frame
72         self.namespace["PAGENUM"] = self.namespace["FRAME"] = self.frame
73        
74 def make_image(source_or_code, outputfile):
75    
76     """Given a source string or code object, executes the scripts and saves the result as an image.
77     Supported image extensions: pdf, tiff, png, jpg, gif"""
78    
79     runner = NodeBoxRunner()
80     runner.run(source_or_code)
81     runner.canvas.save(outputfile)
82    
83 def make_movie(source_or_code, outputfile, frames, fps=30):
84
85     """Given a source string or code object, executes the scripts and saves the result as a movie.
86     You also have to specify the number of frames to render.
87     Supported movie extension: mov"""
88
89     from nodebox.util import QTSupport
90     runner = NodeBoxRunner()
91     movie = QTSupport.Movie(outputfile, fps)
92     for frame in runner.run_multiple(source_or_code, frames):
93         movie.add(runner.canvas)
94     movie.save()
95
96 def usage(err=""):
97     if len(err) > 0:
98         err = '\n\nError: ' + str(err)
99     print """NodeBox console runner
100 Usage: console.py sourcefile imagefile
101    or: console.py sourcefile moviefile number_of_frames [fps]
102 Supported image extensions: pdf, tiff, png, jpg, gif
103 Supported movie extension:  mov""" + err
104
105 def main():
106     import sys, os
107     if len(sys.argv) < 2:
108         usage()
109     elif len(sys.argv) == 3: # Should be an image
110         basename, ext = os.path.splitext(sys.argv[2])
111         if ext not in ('.pdf', '.gif', '.jpg', '.jpeg', '.png', '.tiff'):
112             return usage('This is not a supported image format.')
113         make_image(open(sys.argv[1]).read(), sys.argv[2])
114     elif len(sys.argv) == 4 or len(sys.argv) == 5: # Should be a movie
115         basename, ext = os.path.splitext(sys.argv[2])
116         if ext != '.mov':
117             return usage('This is not a supported movie format.')
118         if len(sys.argv) == 5:
119             try:
120                 fps = int(sys.argv[4])
121             except ValueError:
122                 return usage()
123         else:
124             fps = 30
125         make_movie(open(sys.argv[1]).read(), sys.argv[2], int(sys.argv[3]), fps)
126
127 def test():
128     # Creating the NodeBoxRunner class directly:
129     runner = NodeBoxRunner()
130     runner.run('size(500,500)\nfor i in range(400):\n  oval(random(WIDTH),random(HEIGHT),50,50, fill=(random(), 0,0,random()))')
131     runner.canvas.save('console-test.pdf')
132     runner.canvas.save('console-test.png')
133    
134     # Using the runner for animations:
135     runner = NodeBoxRunner()
136     for frame in runner.run_multiple('size(300, 300)\ntext(FRAME, 100, 100)', 10):
137         runner.canvas.save('console-test-frame%02i.png' % frame)
138
139     # Using the shortcut functions:
140     make_image('size(200,200)\ntext(FRAME, 100, 100)', 'console-test.gif')
141     make_movie('size(200,200)\ntext(FRAME, 100, 100)', 'console-test.mov', 10)
142
143 if __name__=='__main__':
144     main()
Note: See TracBrowser for help on using the browser.