├── .gitignore ├── LICENSE.txt ├── README.txt ├── examples ├── 01-basics │ ├── 01-rect.py │ ├── 02-color.py │ ├── 03-frame.py │ └── 04-mouse.py ├── 02-transform │ ├── 01-spiral.py │ └── 02-push.py ├── 03-image │ ├── 01-image.py │ ├── 02-color.py │ ├── 03-filter.py │ ├── 04-quad.py │ ├── 05-pixels.py │ ├── 06-noise.py │ └── creature.png ├── 04-text │ ├── 01-text.py │ └── 02-style.py ├── 05-path │ ├── 01-curve.py │ ├── 02-clip.py │ ├── 03-tangent.py │ ├── 04-text.py │ ├── 05-spider.py │ ├── 06-handle.py │ ├── 07-fit.py │ └── 08-drag.py ├── 06-math │ └── 01-attractor.py ├── 07-filter │ ├── 01-shadow.py │ ├── 02-bump.py │ ├── 03-mirror.py │ ├── 04-twirl.py │ ├── 05-render.py │ ├── 06-mask.py │ ├── 07-blend.py │ ├── 08-bloom.py │ ├── 09-buffer.py │ ├── cell.png │ ├── creature.png │ └── dendrite.png ├── 08-physics │ ├── 01-flock.py │ ├── 02-spring.py │ ├── 03-force.py │ ├── 04-animation.py │ ├── 05-emitter.py │ ├── 06-pack.py │ ├── 07-graph.py │ └── cells │ │ ├── blue-block.png │ │ ├── blue-circle.png │ │ ├── blue-empty1.png │ │ ├── blue-empty2.png │ │ ├── blue-star.png │ │ ├── green-block1.png │ │ ├── green-block2.png │ │ ├── green-circle1.png │ │ ├── green-circle2.png │ │ ├── green-empty1.png │ │ ├── green-empty2.png │ │ ├── green-empty3.png │ │ ├── green-star1.png │ │ └── green-star2.png ├── 09-layer │ ├── 01-drag.py │ ├── 02-polygon.py │ ├── 03-tween.py │ └── creature.png ├── 10-gui │ ├── 01-slider.py │ ├── 02-panel.py │ ├── 03-button.py │ ├── 04-knob.py │ └── 05-layout.py ├── 11-sound │ ├── 01-fft.pd │ ├── 01-fft.py │ ├── 02-in-out.pd │ ├── 02-in-out.py │ ├── 03-sequencer.pd │ ├── 03-sequencer.py │ ├── 04-audiosnails.pd │ └── 04-audiosnails.py ├── 12-experimental │ ├── 01-isight.py │ ├── 02-blend.py │ ├── 03-movie.py │ ├── 04-live1.py │ └── 04-live2.py ├── README.txt ├── template.py └── test.py ├── icon.png ├── nodebox ├── __init__.py ├── ext │ ├── __init__.py │ ├── bezier.c │ ├── geometry.c │ ├── noise.c │ ├── psyco │ │ ├── __init__.py │ │ ├── classes.py │ │ ├── core.py │ │ ├── kdictproxy.py │ │ ├── logger.py │ │ ├── profiler.py │ │ ├── src │ │ │ ├── COPYING.txt │ │ │ ├── MANIFEST │ │ │ ├── README.txt │ │ │ ├── c │ │ │ │ ├── Makefile │ │ │ │ ├── Modules │ │ │ │ │ ├── parray.c │ │ │ │ │ ├── pmath.c │ │ │ │ │ └── ppsyco.c │ │ │ │ ├── Objects │ │ │ │ │ ├── compactobject.c │ │ │ │ │ ├── compactobject.h │ │ │ │ │ ├── pabstract.c │ │ │ │ │ ├── pabstract.h │ │ │ │ │ ├── pboolobject.c │ │ │ │ │ ├── pboolobject.h │ │ │ │ │ ├── pclassobject.c │ │ │ │ │ ├── pclassobject.h │ │ │ │ │ ├── pcompactobject.c │ │ │ │ │ ├── pcompactobject.h │ │ │ │ │ ├── pdescrobject.c │ │ │ │ │ ├── pdescrobject.h │ │ │ │ │ ├── pdictobject.c │ │ │ │ │ ├── pdictobject.h │ │ │ │ │ ├── pfloatobject.c │ │ │ │ │ ├── pfloatobject.h │ │ │ │ │ ├── pfuncobject.c │ │ │ │ │ ├── pfuncobject.h │ │ │ │ │ ├── pintobject.c │ │ │ │ │ ├── pintobject.h │ │ │ │ │ ├── piterobject.c │ │ │ │ │ ├── piterobject.h │ │ │ │ │ ├── plistobject.c │ │ │ │ │ ├── plistobject.h │ │ │ │ │ ├── plongobject.c │ │ │ │ │ ├── plongobject.h │ │ │ │ │ ├── pmethodobject.c │ │ │ │ │ ├── pmethodobject.h │ │ │ │ │ ├── pobject.c │ │ │ │ │ ├── pobject.h │ │ │ │ │ ├── prangeobject.c │ │ │ │ │ ├── prangeobject.h │ │ │ │ │ ├── pstringobject.c │ │ │ │ │ ├── pstringobject.h │ │ │ │ │ ├── pstructmember.c │ │ │ │ │ ├── pstructmember.h │ │ │ │ │ ├── ptupleobject.c │ │ │ │ │ ├── ptupleobject.h │ │ │ │ │ ├── ptypeobject.c │ │ │ │ │ └── ptypeobject.h │ │ │ │ ├── Python │ │ │ │ │ ├── frames.c │ │ │ │ │ ├── frames.h │ │ │ │ │ ├── pbltinmodule.c │ │ │ │ │ ├── pbltinmodule.h │ │ │ │ │ ├── pycheader.h │ │ │ │ │ ├── pycinternal.h │ │ │ │ │ ├── pycompiler.c │ │ │ │ │ ├── pycompiler.h │ │ │ │ │ └── pyver.h │ │ │ │ ├── alarm.c │ │ │ │ ├── alarm.h │ │ │ │ ├── blockalloc.h │ │ │ │ ├── codegen.c │ │ │ │ ├── codegen.h │ │ │ │ ├── codemanager.c │ │ │ │ ├── codemanager.h │ │ │ │ ├── cstruct.c │ │ │ │ ├── cstruct.h │ │ │ │ ├── depend.py │ │ │ │ ├── dispatcher.c │ │ │ │ ├── dispatcher.h │ │ │ │ ├── files.py │ │ │ │ ├── i386 │ │ │ │ │ ├── idispatcher.c │ │ │ │ │ ├── idispatcher.h │ │ │ │ │ ├── iencoding.c │ │ │ │ │ ├── iencoding.h │ │ │ │ │ ├── iinitialize.h │ │ │ │ │ ├── iprocessor.c │ │ │ │ │ ├── ipyencoding.c │ │ │ │ │ └── ipyencoding.h │ │ │ │ ├── initialize.h │ │ │ │ ├── ivm │ │ │ │ │ ├── idispatcher.c │ │ │ │ │ ├── idispatcher.h │ │ │ │ │ ├── iencoding.c │ │ │ │ │ ├── iencoding.h │ │ │ │ │ ├── iinitialize.h │ │ │ │ │ ├── iprocessor.c │ │ │ │ │ ├── ipyencoding.c │ │ │ │ │ ├── ipyencoding.h │ │ │ │ │ ├── ivm-insns.c │ │ │ │ │ ├── ivm-insns.h │ │ │ │ │ ├── localsetup.py │ │ │ │ │ └── prolog │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ ├── ccode.pl │ │ │ │ │ │ ├── detcheck.pl │ │ │ │ │ │ ├── insns-igen-h.i.default │ │ │ │ │ │ ├── insns-igen.i.default │ │ │ │ │ │ ├── insns-switch.i.default │ │ │ │ │ │ ├── insns-table.py.default │ │ │ │ │ │ ├── insns-threaded.i.default │ │ │ │ │ │ ├── insns.pl │ │ │ │ │ │ ├── insns.py │ │ │ │ │ │ ├── insnset.py │ │ │ │ │ │ ├── mode_combine.pl.default │ │ │ │ │ │ ├── optimize.pl │ │ │ │ │ │ ├── samelines.py │ │ │ │ │ │ ├── utils.pl │ │ │ │ │ │ ├── vm.pl │ │ │ │ │ │ └── vmwriter.pl │ │ │ │ ├── linuxmemchk.c │ │ │ │ ├── linuxmemchk.h │ │ │ │ ├── mergepoints.c │ │ │ │ ├── mergepoints.h │ │ │ │ ├── mkincl.py │ │ │ │ ├── mychecker.py │ │ │ │ ├── platform.c │ │ │ │ ├── platform.h │ │ │ │ ├── processor.h │ │ │ │ ├── profile.c │ │ │ │ ├── profile.h │ │ │ │ ├── psyco.c │ │ │ │ ├── psyco.h │ │ │ │ ├── psyfunc.c │ │ │ │ ├── psyfunc.h │ │ │ │ ├── pycodegen.h │ │ │ │ ├── stats.c │ │ │ │ ├── stats.h │ │ │ │ ├── timing.h │ │ │ │ ├── vcompiler.c │ │ │ │ ├── vcompiler.h │ │ │ │ ├── versionchecker.py │ │ │ │ └── win32 │ │ │ │ │ └── psyco.vcproj │ │ │ ├── doc │ │ │ │ ├── Makefile │ │ │ │ ├── README.txt │ │ │ │ └── psycoguide.tex │ │ │ ├── psyco-mactel.diff │ │ │ ├── py-support │ │ │ │ ├── __init__.py │ │ │ │ ├── classes.py │ │ │ │ ├── core.py │ │ │ │ ├── kdictproxy.py │ │ │ │ ├── logger.py │ │ │ │ ├── profiler.py │ │ │ │ └── support.py │ │ │ ├── py-utils │ │ │ │ ├── cvs.py │ │ │ │ ├── httpxam.py │ │ │ │ ├── ivmdump.py │ │ │ │ ├── ivmextract.py │ │ │ │ ├── ivmoptimize.py │ │ │ │ ├── manifest.py │ │ │ │ ├── symbols.py │ │ │ │ ├── vinfo_dump.py │ │ │ │ ├── win32 │ │ │ │ │ └── README.TXT │ │ │ │ ├── xam.py │ │ │ │ └── xamsupport.c │ │ │ ├── setup.py │ │ │ └── test │ │ │ │ ├── bpnn.py │ │ │ │ ├── btrun.py │ │ │ │ ├── classicregrtest.py │ │ │ │ ├── file1-basetests │ │ │ │ ├── file2-basetests.uu │ │ │ │ ├── fulltester.py │ │ │ │ ├── life-psyco.py │ │ │ │ ├── life.py │ │ │ │ ├── pystone-jit.py │ │ │ │ ├── pystone.py │ │ │ │ ├── regrtester.py │ │ │ │ ├── regrtester2.py │ │ │ │ ├── test1.py │ │ │ │ ├── test3.py │ │ │ │ ├── test5.py │ │ │ │ ├── test_base.py │ │ │ │ ├── test_compactobject.py │ │ │ │ └── test_misc.py │ │ └── support.py │ └── setup.py ├── font │ ├── Droid Sans Mono.ttf │ ├── Droid Sans-Bold.ttf │ ├── Droid Sans.ttf │ ├── Droid Serif-Bold.ttf │ ├── Droid Serif-BoldItalic.ttf │ ├── Droid Serif-Italic.ttf │ ├── Droid Serif-Regular.ttf │ ├── glyph.p │ └── glyph.py ├── graphics │ ├── __init__.py │ ├── bezier.py │ ├── context.py │ ├── geometry.py │ ├── noise.py │ ├── physics.py │ └── shader.py ├── gui │ ├── __init__.py │ ├── controls.py │ └── theme │ │ ├── Droid Sans-Bold.ttf │ │ ├── Droid Sans.ttf │ │ ├── action-close.png │ │ ├── action.png │ │ ├── button.png │ │ ├── field.png │ │ ├── flag-checked.png │ │ ├── flag.png │ │ ├── flag.psd │ │ ├── knob-socket.png │ │ ├── knob.png │ │ ├── panel.png │ │ ├── slider-handle.png │ │ └── slider.png └── sound │ ├── __init__.py │ ├── osc.py │ └── process.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directories 2 | build 3 | dist 4 | *.egg-info 5 | 6 | # Mac OS X custom attribute files 7 | .DS_Store 8 | 9 | # Windows thumbnails 10 | Thumbs.db 11 | 12 | # Python 13 | *.pyc 14 | *.pyo 15 | 16 | # Temporary editor files 17 | *.swp 18 | .idea 19 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2012, City In A Bottle 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in 11 | the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of "NodeBox for OpenGL" nor the names of its 14 | contributors may be used to endorse or promote products 15 | derived from this software without specific prior written 16 | permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /examples/01-basics/01-rect.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | # Import the drawing commands from the NodeBox module. 5 | from nodebox.graphics import * 6 | # This includes: 7 | # - drawing primitives such as line(), rect(), ellipse(), triangle(), 8 | # - color commands such as fill(), stroke(), strokewidth(), 9 | # - transform commands such as translate(), rotate(), scale(), push() and pop(), 10 | # - bezier commands such as beginpath(), endpath(), moveto(), lineto(), curveto(), drawpath(), 11 | # - image commands such as image() and crop(), 12 | # - image filters such as blur(), colorize(), 13 | # - text commands such as text(), font(), fontsize(), 14 | # - foundation classes such as Color, BezierPath, Image, Text, Layer and Canvas. 15 | 16 | # The canvas will update several times per second. 17 | # The idea is to write a draw() function that contains a combination of drawing commands. 18 | # The draw() function is attached to the canvas so that its output is shown every frame. 19 | # The canvas has a timer for the current frame and logs the position of the mouse, 20 | # these can be used to create different animations for each frame. 21 | def draw(canvas): 22 | 23 | # Clear the previous frame. 24 | # This does not happen by default, because interesting effects can be achieved 25 | # by not clearing the background (for example, see math/1-attractor.py). 26 | canvas.clear() 27 | 28 | # Draw a rectangle. 29 | # The x parameter defines the horizontal offset from the left edge of the canvas. 30 | # The y parameter defines the vertical offset from the bottom edge of the canvas. 31 | # The rectangle's height is 100 minimum, and grows when you move the mouse up. 32 | # Change some numbers to observe their impact. 33 | rect(x=100, y=10, width=300, height=max(100, canvas.mouse.y)) 34 | 35 | canvas.size = 500, 500 # Set the size of the canvas. 36 | canvas.run(draw) # Register the draw function and start the application. -------------------------------------------------------------------------------- /examples/01-basics/02-color.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # When you run a script, NodeBox reads the code from top to bottom, like a recipe. 7 | # When it encounters coloring or transformation commands, it changes the current state. 8 | # All subsequent elements (primitives, paths, text and images) 9 | # you draw then adhere to the current state. 10 | 11 | def draw(canvas): 12 | 13 | canvas.clear() 14 | 15 | # The fill() command sets the current fill color. 16 | # This color is used for all subsequent shapes. 17 | # It takes four parameters: red, green, blue and opacity, ranging between 0.0 and 1.0. 18 | # So an opacity of 0.5 means 50% transparent. 19 | fill(0.0, 0.5, 0.75, 0.5) # 50 % transparent cyan (=cold greenish blue). 20 | 21 | # Some things to note: 22 | # 1) Both the rectangle and ellipse are drawn in the current fill color. 23 | # 2) The current fill is transparent, so their colors blend where they overlap. 24 | # 3) The rectangle is positioned from its bottom-left corner, the ellipse from the center. 25 | rect(50, 200, 100, 100) 26 | ellipse(150, 200, 100, 100) 27 | 28 | # The stroke() command sets the current outline color. 29 | # The strokewidth() command defines the thickness of the outline. 30 | # If less than four parameters are given for fill() and stroke(), 31 | # they are assumed to be R,G,B values (3 parameters) or grayscale + opacity (2 parameters). 32 | nofill() 33 | stroke(0.0, 0.25) # 75% transparent black. 34 | strokewidth(1) 35 | triangle(200, 200, 250, 300, 300, 200) 36 | 37 | # While rect() and ellipse() expect x, y, width, height parameters, 38 | # triangle() expects the coordinates of three points, 39 | # which are connected into a triangle. 40 | 41 | # Clear the current stroke, 42 | # otherwise it is still active in the next frame 43 | # when we start drawing the rectangle and the ellipse. 44 | nostroke() 45 | 46 | # You can also pass Color objects to fill() and stroke(). 47 | # A Color object can be created with the color command. 48 | # It has clr.r, clr.g, clr.b, clr.a properties. 49 | clr = color(0.25, 0.15, 0.75, 0.5) # 50% transparent purple/blue. 50 | fill(clr) 51 | ellipse(200, 400, 300, 300) 52 | 53 | # Display the coordinates, 54 | # so we can compare them with the values in the source code. 55 | fill(0) 56 | x, y = canvas.mouse.xy 57 | text("%s,%s"%(x,y), x, y) 58 | 59 | canvas.size = 500, 500 60 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/01-basics/03-frame.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Here is the "Hypnoval", a classic example in NodeBox for Mac OS X. 7 | # It uses the canvas.frame counter to create variation in each frame. 8 | # Math functions sin() and cos() are used to create fluid motion. 9 | # Sine and cosine describe smooth repetitive oscillation between -1 and 1: 10 | # sin(0)=0, sin(pi/2)=1, sin(-pi/2)=-1 11 | # cos(0)=1, cos(pi/2)=0, cos(pi)=-1 12 | # Values near 0 occur more frequently than those near 1 (i.e. "faster" near 1). 13 | 14 | def draw(canvas): 15 | 16 | canvas.clear() 17 | 18 | # A counter based on the current frame: 19 | i = canvas.frame * 0.1 20 | 21 | # We also use an internal counter that modifies individual ellipses. 22 | step = 0.0 23 | 24 | # The grid() function yields (x,y)-coordinates in a grid. 25 | # In this case the grid is 10 by 10 with 45 pixels spacing. 26 | for x, y in grid(10, 10, 45, 45): 27 | x += 50 # Displace a little bit from the left edge. 28 | y += 50 # Displace a little bit from the bottom edge. 29 | 30 | # Draw the ellipse: 31 | fill(0.15, 0.25 - 0.2*sin(i+step), 0.75, 0.5) 32 | ellipse( 33 | x + sin(i+step) * 10.0, # Play around with the numbers! 34 | y + cos(i+step) * 20.0, width=50, height=50) 35 | 36 | # Increase the step so that each ellipse looks different. 37 | step += 0.05 38 | 39 | 40 | canvas.size = 500, 500 41 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/01-basics/04-mouse.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # A freehand drawing application! 7 | 8 | # The canvas, which is passed to every draw() call, 9 | # has a "mouse" property that logs the current mouse state. 10 | # Ideally, you'd use event handlers such as canvas.on_mouse_press() 11 | # but we can already play around with the mouse here: 12 | # - canvas.mouse.x: horizontal postion of the mouse, 0 means left canvas edge, 13 | # - canvas.mouse.y: vertical postion of the mouse, 0 means bottom canvas edge, 14 | # - canvas.mouse.dx: horizontal offset from the previous mouse position, 15 | # - canvas.mouse.dy: vertical offset from the previous mouse position, 16 | # - canvas.mouse.button: mouse button pressed (LEFT | MIDDLE | RIGHT | None), 17 | # - canvas.mouse.modifiers: a list of keyboard modifiers (CTRL | SHIFT | ALT), 18 | # - canvas.mouse.pressed: True when a button is pressed, 19 | # - canvas.mouse.dragged: True when the mouse is dragged. 20 | 21 | def draw(canvas): 22 | 23 | #canvas.clear() 24 | if canvas.frame == 1: 25 | background(1) 26 | 27 | m = canvas.mouse 28 | 29 | strokewidth(1) 30 | stroke(0, 0.4) 31 | if CTRL in m.modifiers: 32 | # If the CTRL key is held down, draw thinner lines. 33 | stroke(0, 0.2) 34 | 35 | if m.pressed: 36 | # If the mouse is pressed, draw lines. 37 | # This is a better way than simply drawing a dot at the current mouse position 38 | # (i.e. ellipse(m.x, m.y, 2, 2)), because the mouse can move faster 39 | # than the application can track. 40 | # So each frame we draw a little line to the previous mouse position. 41 | line(m.x, m.y, m.x - m.dx, m.y - m.dy) 42 | 43 | canvas.size = 500, 500 44 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/02-transform/01-spiral.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | def draw(canvas): 7 | 8 | canvas.clear() 9 | 10 | # The origin point of the canvas is in the bottom-left corner. 11 | # That means if you draw a shape or image at x=0 and y=0, 12 | # it appears in the bottom-left corner. 13 | # The origin point can be moved around with the translate() command. 14 | # For example, here it is placed in the center of the canvas: 15 | translate(250, 250) 16 | 17 | # Like colors, NodeBox keeps a current transform "state". 18 | # All subsequent drawing commands will originate from the center. 19 | 20 | stroke(0, 0.2) 21 | strokewidth(1) 22 | 23 | n = 350 24 | for i in range(n): 25 | t = float(i) / n # A counter between 0.0 and 1.0. 26 | fill(0.25-t, 0.15+t, 0.75, 0.15) 27 | 28 | # The transform state logs the current scale. 29 | # Thus, the first time when we call scale(0.99), the current scale is 99%. 30 | # The second time the current scale becomes 99% of 99 = 98%, and so on. 31 | # That is why each subsequent ellipse is a bit smaller than the previous one. 32 | scale(0.99) 33 | 34 | # In the same way, rotate() calls are cumulative. 35 | # The first rotate(5) sets the current angle to 5, the second 10, 15, 20, ... 36 | # That is why each subsequent ellipse appears at a different angle. 37 | rotate(5) 38 | 39 | # However, instead of drawing a lot of ellipses on top of each other, 40 | # each rotated at a different angle, each ellipse is instead rotating 41 | # around the origin point (which we placed in the center). 42 | # This is because we draw each ellipse at x=200, so 200 pixels to the right 43 | # of the origin, only "to the right" is relative to the current rotation. 44 | # In the same way, "200 pixels" is relative to the current scale, 45 | # so the ellipses spiral to the center. 46 | ellipse(x=200, y=0, width=120, height=60) 47 | 48 | # The order in which transformations occur is important: 49 | # translating first and scaling / rotating afterwards 50 | # has a different effect than scaling / rotating first. 51 | 52 | canvas.size = 500, 500 53 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/02-transform/02-push.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Often, you may need groups of shapes that you can transform as a whole. 7 | # For example: a planet that has moons rotating around it. 8 | # The planet+moons is a group that as a whole rotates around a sun. 9 | 10 | txt = Text("moon") 11 | 12 | def draw(canvas): 13 | 14 | canvas.clear() 15 | 16 | stroke(0, 0.2) 17 | 18 | # Put the origin point in the center of the canvas. 19 | translate(canvas.width/2, canvas.height/2) 20 | ellipse(0, 0, 10, 10) 21 | text("sun", 10, 0) 22 | 23 | n = 3 24 | for i in range(n): 25 | 26 | # The push() and pop() commands can be used to create a branch in the transform state. 27 | # Once push() is called, transformations are in effect until pop() is called, 28 | # at which point the transformation state resets to the way it was before push(). 29 | # Each planet acts as a local origin for its orbitting moon. 30 | push() 31 | rotate(canvas.frame + i*360.0/n) # Rotate around sun. 32 | line(0, 0, 120, 0) # Draw a (rotated) line with length 120. 33 | translate(120, 0) # Move the origin to the end of the (rotated) line. 34 | ellipse(0, 0, 5, 5) # Draw the planet at the end of the (rotated) line. 35 | text("planet", 10, 0) 36 | rotate(canvas.frame * 6) # Increase rotation. 37 | line(0, 0, 30, 0) # Draw a line with length 30 from the planet. 38 | text("moon", 32, 0) 39 | pop() # Move the origin back to the sun. Undo rotation. 40 | 41 | canvas.size = 500, 500 42 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/01-image.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # The main purpose of NodeBox for OpenGL is drawing images to the canvas. 7 | # Typically, an image can be a JPEG or TIFF file, or a PNG if it uses transparency. 8 | # Image filenames can be passed to the image() command directly, 9 | # but it is faster to load them before the animation starts: 10 | img = Image("creature.png") 11 | 12 | def draw(canvas): 13 | 14 | canvas.clear() 15 | 16 | # Just like line(), rect(), ellipse() etc. images can be transformed 17 | # with translate(), scale() and rotate(). 18 | translate(250, 250) 19 | scale(1.0 + 0.5 * cos(canvas.frame*0.01)) 20 | rotate(canvas.frame) 21 | 22 | # An image is drawn from its bottom-left corner. 23 | # So if you draw an image at (0,0), its bottom-left corner is at the canvas origin. 24 | # By the default the canvas origin is at the bottom-left of the window, 25 | # but we translated it to the center of the canvas. 26 | # Then, the image is rotated from the bottom-left corner of the image. 27 | # We draw it at an offset (minus half the image width and half the image height) 28 | # so it appears to be rotating from its center. 29 | image(img, x=-img.width/2, y=-img.height/2) 30 | 31 | canvas.size = 500, 500 32 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/02-color.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.geometry import smoothstep 6 | 7 | img = Image("creature.png") 8 | 9 | def draw(canvas): 10 | 11 | canvas.clear() 12 | 13 | translate(250, 250) 14 | scale(0.5) 15 | 16 | t = canvas.frame % 100 * 0.01 # A number between 0.0 and 1.0. 17 | t = smoothstep(0.0, 1.0, t) # Slow down ("ease") when nearing 0.0 or 1.0. 18 | rotate(t * 360) 19 | 20 | m = 1.0 - 2 * abs(0.5-t) # A number that goes from 0.0 to 1.0 and then back to 0.0. 21 | scale(0.5+m) 22 | 23 | # The image command has an optional "color" and an optional "alpha" parameter. 24 | # The alpha sets the overall opacity of the image (alpha=0.25 means 75% transparent). 25 | # The color adjusts the fill color of the image. By default it is (1,1,1,1), 26 | # which means that the image pixels are mixed with white and remain unaffected. 27 | # In this case, we lower the green component, 28 | # so the creature gets more pink when it flies. 29 | image(img, x=0, y=-img.height, color=color(1, 1-m, 1, 1), alpha=1.0) 30 | 31 | # You can pass a Color object (i.e. returned from color()), 32 | # or simply a (R,G,B)-tuple, which is faster because no Color needs to be constructed. 33 | 34 | canvas.size = 500, 500 35 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/03-filter.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # This example will make more sense after you've seen the examples in /07-filter 7 | 8 | # NodeBox for OpenGL has a range of commands for filtering images. 9 | # For example, blur(img) returns a new Image that is a blurred version of the given image. 10 | # By chaining filters, e.g. twirl(bump(blur(img))), interesting effects can be achieved 11 | 12 | # Some filters can be used directly with the image() command. 13 | # For the filters invert(), colorize(), blur(), desaturate(), mask(), blend() and distort(), 14 | # there are variants inverted(), colorized(), blurred(), desaturated(), masked(), 15 | # blended() and distorted() that can be passed to the "filter" parameter of the image() command. 16 | # The advantage is that the effect doesn't need to be rendered offscreen, which is faster. 17 | # The disadvantage is that: 18 | # - image() parameters "color" and "alpha" won't work (they are overridden by the filter), 19 | # - the effect can not be chained, 20 | # - the effect must be relatively simple, e.g. blurred() is a 3x3 Gaussian kernel 21 | # vs. blur() which uses a 9x9 Gaussian kernel. 22 | 23 | # In short, these variants are usually meant for testing purposes, 24 | # but it's useful to note their existence nonetheless. 25 | 26 | img = Image("creature.png") 27 | 28 | def draw(canvas): 29 | 30 | canvas.clear() 31 | 32 | image(img, 50, 50, filter=distorted(STRETCH, dx=canvas.mouse.relative_x, 33 | dy=canvas.mouse.relative_y)) 34 | 35 | canvas.size = 500, 500 36 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/04-quad.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | img = Image("creature.png") 7 | 8 | # The image.quad property describes the four-sided polygon 9 | # on which an image texture is "mounted". 10 | # This is not necessarily a rectangle, the corners can be distorted: 11 | img.quad.dx1 = 200 12 | img.quad.dy1 = 100 13 | img.quad.dx2 = 100 14 | img.quad.dy2 = -100 15 | 16 | # This flushes the image cache, so it is a costly operation. 17 | 18 | def draw(canvas): 19 | canvas.clear() 20 | image(img) 21 | 22 | canvas.size = 500, 500 23 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/05-pixels.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # The pixels() command yields a list of pixels from a given image. 7 | # Since this is a relatively slow operation, this is not useful for dynamic image processing, 8 | # but there a various other ways in which pixels can be useful. In short: 9 | # - len(Pixels): the number of pixels in the image. 10 | # - Pixels.width: the width of the image. 11 | # - Pixels.height: the height of the image. 12 | # - Pixels[i]: a list of [R,G,B,A] values between 0-255 that can be modified. 13 | # - Pixels.get(x, y): returns a Color from the pixel at row x and column y. 14 | # - Pixels.set(x, y, clr): sets the color of the pixel at (x,y). 15 | # - Pixels.update() commits all the changes. You can then pass Pixels to the image() command. 16 | 17 | img = Image("creature.png") 18 | p = Pixels(img) 19 | 20 | def draw(canvas): 21 | 22 | # Since the background is a bit transparent, 23 | # it takes some time for the previous frame to fade away. 24 | background(1,0.03) 25 | 26 | # Here we simply use pixels from the image as a color palette. 27 | for i in range(15): 28 | x = random(p.width) 29 | y = random(p.height) 30 | clr = p.get(x, y) 31 | clr.alpha *= 0.5 32 | fill(clr) 33 | stroke(clr) 34 | strokewidth(random(5)) 35 | r = random(5, 100) 36 | ellipse(random(canvas.width), random(canvas.height), r*2, r*2) 37 | 38 | canvas.size = 500, 500 39 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/06-noise.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Create a pixels array from a solid white image: 7 | p = Pixels(solid(200, 200, Color(1))) 8 | 9 | # Colorize pixels with the Perlin noise() generator. 10 | # Noise is smoother than random(), comparable to a random gradient. 11 | # This is often used to generate terrain surface maps. 12 | 13 | # The noise() command returns a smooth value between -1.0 and 1.0. 14 | # The x, y, z parameters determine the coordinates in the noise landscape. 15 | # Since the landscape is infinite, the actual value of a coordinate doesn't matter, 16 | # only the distance between successive steps. 17 | # The smaller the difference between steps, the smoother the noise sequence. 18 | # Steps between 0.005 and 0.1 usually work best. 19 | zoom = 4 20 | for i in range(p.width): 21 | for j in range(p.height): 22 | t = noise( 23 | zoom * float(i) / p.width, 24 | zoom * float(j) / p.height 25 | ) 26 | t = 0.5 + 0.5 * t # Map values from -1.0-1.0 to 0.0-1.0. 27 | t = int(255*t) # Map values to 0-255. 28 | p[i+j*p.width] = (t,t,t,255) 29 | 30 | p.update() 31 | 32 | def draw(canvas): 33 | image(p, 150, 150) 34 | 35 | canvas.size = 500, 500 36 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/03-image/creature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/03-image/creature.png -------------------------------------------------------------------------------- /examples/04-text/01-text.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # In the classic NodeBox for Mac OS X, text can easily be drawn with text(), font(), fontsize(). 7 | # This is possible here as well, but it is much faster to prepare the text beforehand: 8 | txt = Text("hello, world", font="Droid Serif", fontsize=20, fontweight=BOLD) 9 | 10 | # The less changes you make to the text, the faster it is drawn. 11 | 12 | # A Text object has many different typographical parameters: 13 | # - font: the name of the font to use (e.g. "Droid Sans", "Helvetica", ...), 14 | # - fontsize: the fontsize in points, 15 | # - fontweight: NORMAL, BOLD, ITALIC or a (BOLD, ITALIC)-tuple, 16 | # - lineheight: line spacing, 1.0 by default, 17 | # - align: LEFT, RIGHT or CENTER, 18 | # - fill: a Color object that sets the color of the text. 19 | 20 | def draw(canvas): 21 | 22 | canvas.clear() 23 | 24 | # Center the text horizontally. 25 | # Vertically, the y position is the baseline of the text. 26 | x = (canvas.width - textwidth(txt)) / 2 27 | y = 250 28 | text(txt, x, y) 29 | 30 | canvas.size = 500, 500 31 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/04-text/02-style.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | txt = Text("So long!\nThanks for all the fish.", 7 | font = "Droid Serif", 8 | fontsize = 20, 9 | fontweight = BOLD, 10 | lineheight = 1.2, 11 | fill = color(0.25)) 12 | 13 | # Text.style() can be used to style individual characters in the text. 14 | # It takes a start index, a stop index, and optional styling parameters: 15 | txt.style(9, len(txt), fontsize=txt.fontsize/2, fontweight=NORMAL) 16 | 17 | def draw(canvas): 18 | 19 | canvas.clear() 20 | 21 | x = (canvas.width - textwidth(txt)) / 2 22 | y = 250 23 | text(txt, x, y) 24 | 25 | canvas.size = 500, 500 26 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/05-path/01-curve.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # The BezierPath object handles complex vector shapes made up of curves and lines. 7 | # As with images and text, it is a good idea to create the path once, outside the draw loop. 8 | # OpenGL has to perform an operation called "tessellation" (dividing the shape into triangles) 9 | # before it can be drawn. Furthermore, curves have to be divided into a group 10 | # of small straight lines before they can be drawn. These operations take time. 11 | # BezierPath will perform them once and then cache the results, 12 | # therefore creating a new path each frame slows down your app. 13 | 14 | # Create a leaf shape. 15 | # BezierPath has moveto(x,y), lineto(x,y), curveto(x1, y1, x2, y2, x3, y3) and close() methods. 16 | # For curveto(), (x1,y1) describes the direction in which the curve from this point starts, 17 | # and (x2,y2) describes the direction in which it ends in point (x,y). 18 | # In this case, moveto() positions the current point at origin (0,0). 19 | # Then we draw a curve upwards, bulging out to the right and ending in a spike. 20 | # Then we draw a curve back to the origin, starting in a spike and bulging out to the left. 21 | leaf = BezierPath() 22 | leaf.moveto(0, 0) 23 | leaf.curveto(50, 50, 0, 150, 0, 200) 24 | leaf.curveto(0, 150, -50, 50, 0, 0) 25 | 26 | # The resulting path can be passed to drawpath() to render it to the canvas. 27 | # Note: just as in the classic NodeBox for Mac OS X, paths can also be constructed 28 | # with beginpath(). The commands below create exactly the same leaf shape as above: 29 | # beginpath(0, 0) 30 | # curveto(50, 50, 0, 150, 0, 200) 31 | # curveto(0, 150, -50, 50, 0, 0) 32 | # p = endpath(draw=False) 33 | 34 | def draw(canvas): 35 | 36 | canvas.clear() 37 | 38 | fill(0.25, 0.15, 0.75, 0.25) # Transparent purple/blue. 39 | stroke(0, 0.25) # High transparency makes the stroke look thinner. 40 | strokewidth(1) 41 | 42 | translate(250, 250) # Origin in the center of the canvas. 43 | for i in range(40): 44 | rotate(9) 45 | drawpath(leaf) 46 | 47 | canvas.size = 500, 500 48 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/05-path/02-clip.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Here, the leaf shape from the previous example is reused, 7 | # but instead of simply coloring it with blue, we give it a nice gradient touch. 8 | # Such effects - if your application has room to pull it off, add depth and realism. 9 | # We'll use a clipping mask to achieve this. 10 | 11 | # Create a leaf shape. 12 | leaf = BezierPath() 13 | leaf.moveto(0, 0) 14 | leaf.curveto(50, 50, 0, 150, 0, 200) 15 | leaf.curveto(0, 150, -50, 50, 0, 0) 16 | 17 | def draw(canvas): 18 | 19 | canvas.clear() 20 | 21 | translate(250, 250) 22 | for i in range(12): 23 | rotate(30) 24 | # Instead of drawing the path directly, we use it as a clipping mask. 25 | # All shapes drawn between beginclip() and endclip() that fall 26 | # outside the clipping path are hidden. 27 | # Inside we use a colorplane to draw a gradient; 28 | # comment out beginclip() and endclip() to observe what happens. 29 | beginclip(leaf) 30 | colorplane(-75, 0, 150, 200, 31 | color(0.25, 0.15, 0.75, 0.65), # Gradient top color. 32 | color(0.15, 0.45, 0.95, 0.15) # Gradient bottom color. 33 | ) 34 | endclip() 35 | 36 | # For a sublte finishing touch, 37 | # we could also add the leaf stroke back on top: 38 | drawpath(leaf, stroke=(0,0,0,0.25), strokewidth=1, fill=None) 39 | 40 | canvas.size = 500, 500 41 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/05-path/03-tangent.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # The classic NodeBox for Mac OS X has interesting path mathematics functionality. 7 | # This functionality is also present in NodeBox for OpenGL. 8 | # For example: we can calculate arbitrary points on a path, 9 | # insert new points, construct a smooth BezierPath from a list of points, etc. 10 | 11 | # What we want to do in this example, 12 | # is place copies of a leaf (see the previous example) along a path (or stem). 13 | # This is achieved by calculating points along a curve and retrieving their "direction". 14 | 15 | # Create a leaf shape. 16 | leaf = BezierPath() 17 | leaf.moveto(0, 0) 18 | leaf.curveto(50, 50, 0, 150, 0, 200) 19 | leaf.curveto(0, 150, -50, 50, 0, 0) 20 | 21 | # Create the stem. 22 | stem = BezierPath() 23 | stem.moveto(150, 100) 24 | stem.curveto(50, 400, 450, 400, 350, 100) 25 | 26 | def draw(canvas): 27 | 28 | canvas.clear() 29 | 30 | nofill() 31 | stroke(0, 0.25) 32 | strokewidth(1) 33 | 34 | drawpath(stem) 35 | 36 | fill(0.25, 0.15, 0.75, 0.25) 37 | 38 | # The BezierPath.points() method yields points evenly distributed along the path. 39 | # The directed() iterator yields (angle, point)-tuples 40 | # for each point in a BezierPath(), BezierPath.points() list, or list of Point objects. 41 | # - The angle represents the direction into which the curve is bending. 42 | # - The line drawn in this direction is known as the curve's tangent. 43 | # This is useful in many ways, for example: to fit text to a path, 44 | # or to place elements (e.g. leaves, moving creatures) along a curved trajectory. 45 | for angle, pt in directed(stem.points(50)): 46 | push() 47 | translate(pt.x, pt.y) # Position the origin point at the current point. 48 | scale(0.5) # Scale it down. 49 | rotate(angle) # Rotate in the point's direction (you may need to add 90, 180, ...) 50 | drawpath(leaf) # Draw the leaf. 51 | rotate(90) # Indicate the normal (i.e. the line perpendicular to the tangent) 52 | line(0, 0, 300, 0, strokestyle=DASHED) 53 | pop() # Reset origin point, scale and rotation. 54 | 55 | canvas.size = 500, 500 56 | canvas.run(draw) 57 | 58 | -------------------------------------------------------------------------------- /examples/05-path/04-text.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # The classic NodeBox for Mac OS X has an interesting textpath() function 7 | # that transforms a string into a BezierPath. 8 | # This function is partly emulated in NodeBox for OpenGL, as long as 9 | # you stick with the default fonts (Droid Sans, Droid Sans Mono, Droid Serif). 10 | # Note: there is a way to make more fonts available - see nodebox/font/glyph.py, 11 | # relying on the classic NodeBox to do the calculations. 12 | path = textpath("GROW", x=40, y=200, fontname="Arial", fontsize=100, bold=True) 13 | 14 | # Now that we have a BezierPath from the text we can use all sorts of math on it. 15 | # Calculate a list of points (PathElement objects), evenly distributed along the path: 16 | points = list(path.points(1000)) 17 | 18 | def draw(canvas): 19 | 20 | fill(0.2, 0.2, 0, max(0.1, 1-canvas.frame*0.05)) # Less opacity over time. 21 | 22 | for pt in points: 23 | ellipse(pt.x, pt.y, 1, 1) 24 | 25 | # Each frame, adjust the position of the point a little bit. 26 | # Since we are not clearing the background, 27 | # it will appear as if something is growing from the text. 28 | pt.x += random(-1.0, 1.0) 29 | pt.y += random(-1.0, 1.0) 30 | 31 | canvas.fps = 20 32 | canvas.size = 500, 500 33 | canvas.run(draw) 34 | 35 | -------------------------------------------------------------------------------- /examples/05-path/05-spider.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.geometry import distance 6 | from math import sqrt 7 | 8 | def spider(string, x=0, y=0, radius=25, **kwargs): 9 | """ A path filter that creates web threading along the characters of the given string. 10 | Its output can be drawn directly to the canvas or used in a render() function. 11 | Adapted from: http://nodebox.net/code/index.php/Path_Filters 12 | """ 13 | # **kwargs represents any additional optional parameters. 14 | # For example: spider("hello", 100, 100, font="Helvetica") => 15 | # kwargs = {"font": "Helvetica"} 16 | # We pass these on to the textpath() call in the function; 17 | # so the spider() function takes the same parameters as textpath: 18 | # x, y, font, fontsize, fontweight, ... 19 | font( 20 | kwargs.get("font", "Droid Sans"), 21 | kwargs.get("fontsize", 100)) 22 | p = textpath(string, x, y, **kwargs) 23 | n = int(p.length) 24 | m = 2.0 25 | radius = max(radius, 0.1 * fontsize()) 26 | points = list(p.points(n)) 27 | for i in range(n): 28 | pt1 = choice(points) 29 | pt2 = choice(points) 30 | while distance(pt1.x, pt1.y, pt2.x, pt2.y) > radius: 31 | pt2 = choice(points) 32 | line(pt1.x + random(-m, m), 33 | pt1.y + random(-m, m), 34 | pt2.x + random(-m, m), 35 | pt2.y + random(-m, m)) 36 | 37 | # Render the function's output to an image. 38 | # Rendering the image beforehand is much faster than calling spider() every frame. 39 | stroke(0.1, 0.1, 0, 0.5) 40 | strokewidth(1) 41 | img = render(spider, 500, 150, 42 | string = "SPIDER", 43 | font = "Droid Sans", 44 | fontsize = 100, 45 | bold = True, 46 | x = 25, 47 | y = 25, 48 | radius = 30) 49 | 50 | def draw(canvas): 51 | canvas.clear() 52 | translate(0, 200) 53 | image(img) 54 | 55 | canvas.size = 500, 500 56 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/05-path/06-handle.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # I always seem to forget how Bezier handles work. 7 | # This example clarifies which handles control what part of a curve. 8 | 9 | fontsize(9) 10 | 11 | p = BezierPath() 12 | p.moveto(50, 100) 13 | p.curveto(100, 400, 200, 50, 450, 100) 14 | 15 | def draw(canvas): 16 | 17 | canvas.clear() 18 | 19 | nofill() 20 | stroke(0, 0.25) 21 | strokewidth(1) 22 | drawpath(p) 23 | fill(0) 24 | 25 | # BezierPath is essentially a list of PathElement objects. 26 | # Each PathElement has a "cmd" property (MOVETO, LINETO, CURVETO or CLOSE), 27 | # an x and y position and two control handles ctrl1 and ctrl2. 28 | # These control handles determine how a curve bends. 29 | for i, pt in enumerate(p): 30 | if i > 0: 31 | # ctrl1 describes how the curve from the previous point started. 32 | line(p[i-1].x, p[i-1].y, pt.ctrl1.x, pt.ctrl1.y, strokestyle=DASHED) 33 | text("pt%s.ctrl1 (%s,%s)" % (i, pt.ctrl1.x, pt.ctrl1.y), 34 | x = pt.ctrl1.x, 35 | y = pt.ctrl1.y+5) 36 | if pt.ctrl2.x != pt.x \ 37 | or pt.ctrl2.y != pt.y: 38 | # ctrl2 describes how the curve from the previous point arrives in this point. 39 | line(pt.x, pt.y, pt.ctrl2.x, pt.ctrl2.y, strokestyle=DASHED) 40 | t = text("pt%s.ctrl2 (%s,%s)" % (i, pt.ctrl2.x, pt.ctrl2.y), 41 | x = pt.ctrl2.x, 42 | y = pt.ctrl2.y+5) 43 | ellipse(pt.x, pt.y, 4, 4) 44 | text("pt%s"%i, x=pt.x+5, y=pt.y+5) 45 | 46 | # If you use BezierPath.points() to generate intermediary points, 47 | # you get DynamicPathElements whose handles need to be interpreted differently: 48 | # - ctrl1 describes how the curve from the previous point arrives, 49 | # - ctrl2 describes how the curve continues. 50 | t = canvas.frame % 500 * 0.002 51 | pt = p.point(t) 52 | ellipse(pt.x, pt.y, 4, 4) 53 | line(pt.x, pt.y, pt.ctrl1.x, pt.ctrl1.y, strokestyle=DASHED) 54 | line(pt.x, pt.y, pt.ctrl2.x, pt.ctrl2.y, strokestyle=DASHED) 55 | text("ptx", x=pt.x+5, y=pt.y+5) 56 | text("ptx.ctrtl1", x=pt.ctrl1.x, y=pt.ctrl1.y+5) 57 | text("ptx.ctrtl2", x=pt.ctrl2.x, y=pt.ctrl2.y+5) 58 | 59 | canvas.size = 500, 500 60 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/05-path/07-fit.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0,os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # This example demonstrated how to fit text to a path using the directed() command 7 | # (thanks to Karsten Wolf). 8 | 9 | # Create a Text object for each character. 10 | txt = "NodeBox for OpenGL" 11 | glyphs = [Text(ch, fontname="Droid Sans Mono") for ch in txt] 12 | 13 | def draw(canvas): 14 | 15 | background(1) 16 | 17 | # Create a path where the mouse position controls the curve. 18 | dx = canvas.mouse.x 19 | dy = canvas.mouse.y 20 | path = BezierPath() 21 | path.moveto(100, 250) 22 | path.curveto(200, 250, dx, dy, 400, 250) 23 | 24 | # Calculate points on the path and draw a character at each points. 25 | # The directed() command yields (angle, point)-tuples. 26 | # The angle can be used to rotate each character along the path curvature. 27 | points = path.points(amount=len(glyphs), start=0.05, end=0.95) 28 | for i, (angle, pt) in enumerate(directed(points)): 29 | push() 30 | translate(pt.x, pt.y) 31 | rotate(angle) 32 | text(glyphs[i], x=-textwidth(glyphs[i])/2) 33 | pop() 34 | 35 | drawpath(path, fill=None, stroke=(0,0,0,0.5)) 36 | line(path[-1].x, path[-1].y, dx, dy, stroke=(0,0,0,0.1)) 37 | 38 | canvas.fps = 30 39 | canvas.size = 500, 500 40 | canvas.run(draw) 41 | -------------------------------------------------------------------------------- /examples/05-path/08-drag.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys;sys.path.insert(0,os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # A classic NodeBox example (http://nodebox.net/code/index.php/Dendrite). 7 | # It registers the dragged mouse movements, 8 | # and use those to draw wavering lines. 9 | # Thanks to Karsten Wolf. 10 | 11 | from random import seed 12 | from math import sin 13 | 14 | lines = [] 15 | 16 | def draw(canvas): 17 | background(0.1, 0.0, 0.1, 0.25) 18 | nofill() 19 | stroke(1, 1, 1, 0.2) 20 | strokewidth(0.5) 21 | 22 | # Register mouse movement. 23 | if canvas.mouse.dragged: 24 | lines.append((LINETO, canvas.mouse.x, canvas.mouse.y, canvas.frame)) 25 | elif canvas.mouse.pressed: 26 | lines.append((MOVETO, canvas.mouse.x, canvas.mouse.y, canvas.frame)) 27 | 28 | if len(lines) > 0: 29 | for i in range(5): 30 | seed(i) # Lock the seed for smooth animation. 31 | p = BezierPath() 32 | for cmd, x, y, t in lines: 33 | d = sin((canvas.frame - t) / 10.0) * 10.0 # Play with the numbers. 34 | x += random(-d, d) 35 | y += random(-d, d) 36 | if cmd == MOVETO: 37 | p.moveto(x, y) 38 | else: 39 | p.lineto(x, y) 40 | drawpath(p) 41 | 42 | canvas.fps = 60 43 | canvas.size = 600, 400 44 | #canvas.fullscreen = True 45 | canvas.run(draw) 46 | -------------------------------------------------------------------------------- /examples/06-math/01-attractor.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from math import sin, cos 6 | 7 | # The Peter De Jong attractor feeds its previous value back into the equation, 8 | # creating a scatter of points that generates strange, attractive patterns. 9 | # The function's return value is a Python iterator - an implicit list of (x,y)-values. 10 | # All of the iterator's values can be retrieved one by one in a loop, 11 | # or you can move to the next value with iterator.next(). 12 | def peter_de_jong_attractor(a, b, c, d, n=100000, scale=100): 13 | x0, y0 = 0.0, 0.0 14 | for i in range(n): 15 | x1 = sin(a*y0) - cos(b*x0) 16 | y1 = sin(c*x0) - cos(d*y0) 17 | x0 = x1 18 | y0 = y1 19 | yield (x1*scale, y1*scale) 20 | 21 | # Classic example from http://local.wasp.uwa.edu.au/~pbourke/fractals/peterdejong/ 22 | # Play around with the numbers to produce different patterns. 23 | a = peter_de_jong_attractor(1.4, -2.3, 2.4, -2.1, n=5000000, scale=150) 24 | 25 | def draw(canvas): 26 | 27 | # The trick is not to clear the canvas each frame. 28 | # Instead, we only draw a background in the first frame, 29 | # and then gradually build up the composition with the next points each frame. 30 | if canvas.frame == 1: 31 | background(1) 32 | 33 | # Translate the canvas origin point to the center. 34 | # The attractor can yield negative (x,y)-values, 35 | # so if we leave the origin point in the bottom left, 36 | # part of the pattern will fall outside the drawing area. 37 | translate(canvas.width/2, canvas.height/2) 38 | 39 | # Note how the fill color has a very low alpha (i.e. high transparency). 40 | # This makes the pattern more fine-grained, 41 | # as many transparent points will need to overlap to form a thicker line. 42 | fill(0, 0.1) 43 | 44 | try: 45 | for i in range(1000): 46 | # Get the next x and y coordinates in the attractor. 47 | # Draw a pixel at the current x and y coordinates. 48 | x, y = a.next() 49 | rect(x, y, 1, 1) 50 | except StopIteration: 51 | pass 52 | 53 | canvas.size = 700, 700 54 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/01-shadow.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Load an image from file. 7 | # For performance, it's a good idea to create images once, outside the draw() loop. 8 | # NodeBox can then keep the image in graphics card memory so it displays faster. 9 | img = Image("creature.png") 10 | 11 | # A simple image effect is a drop shadow. 12 | # We create a grayscale version of the image with the colorize() filter, 13 | # by reducing the image's R,G,B channels to zero but keeping the alpha channel. 14 | # Then we diffuse it with the blur() filter. 15 | # We create the shadow outside the draw() loop for performance: 16 | shadow = colorize(img, color=(0,0,0,1)) 17 | shadow = blur(shadow, amount=3, kernel=5) 18 | 19 | def draw(canvas): 20 | 21 | canvas.clear() 22 | 23 | # Some simple mouse interaction to make it more interesting. 24 | # Moving the mouse up will move the creature up from the ground. 25 | dy = canvas.mouse.y 26 | 27 | # The origin point (0,0) of the canvas is in the lower left corner. 28 | # Transformations such as rotate() and scale() originate from (0,0). 29 | # We move (or "translate") the origin point to the center of the canvas, 30 | # and then draw the image a bit to the left and to the bottom of it. 31 | # This way, transformations will originate from the center. 32 | translate(canvas.width/2, canvas.height/2) 33 | scale(0.75 + dy*0.001) 34 | image(img, x=-300, y=-200 + dy*0.1) 35 | image(shadow, x=-300, y=-240, alpha=0.5 - dy*0.0005) 36 | 37 | # Start the application: 38 | canvas.fps = 60 39 | canvas.size = 500, 500 40 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/02-bump.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | img = Image("creature.png") 7 | 8 | def draw(canvas): 9 | 10 | canvas.clear() 11 | 12 | # The mouse position controls the origin of the bulge. 13 | # The bump() filter takes two parameters: dx and dy (as do most distortion filters). 14 | # These control the origin of the bulge, as relative values between 0.0 and 1.0. 15 | # For example: dx=0.0 means left edge, dx=0.5 means center of image. 16 | # We divide the absolute mouse position by the image width to get relative values. 17 | dx = canvas.mouse.x / float(img.width) 18 | dy = canvas.mouse.y / float(img.height) 19 | 20 | # Since the effect is interactive, we can't render it beforehand. 21 | # We need to reapply it to the source image each frame, 22 | # based on the current mouse position in this frame. 23 | image(bump(img, dx, dy, radius=0.5, zoom=0.75)) 24 | 25 | # The opposite of bump() is dent(): 26 | #image(dent(img, dx, dy, radius=0.5, zoom=0.75)) 27 | 28 | # Start the application: 29 | canvas.fps = 60 30 | canvas.size = 500, 500 31 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/03-mirror.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | img = Image("dendrite.png") 7 | 8 | def draw(canvas): 9 | 10 | #canvas.clear() 11 | 12 | dx = canvas.mouse.x / float(img.width) 13 | dy = canvas.mouse.y / float(img.height) 14 | 15 | # The idea is that the output of each filter can be passed to another filter, 16 | # creating a "rendering pipeline". 17 | # For example, the "mirror" effect is a very easy way to show off. 18 | # It reflects the image along a given horizontal (and/or vertical) axis. 19 | # In this case, we use the mouse position as axes. 20 | # By piping together many mirrors, we get an interesting kaleidoscopic effect. 21 | kaleidoscope = mirror(mirror(img, dx, dy), dy, dx) 22 | 23 | # You may have noticed the fluid, blurry transitions between patterns. 24 | # This is because we are not clearing the canvas background (we are "painting"). 25 | # Since the image gets drawn with an alpha=0.5 (50% opacity), 26 | # the new version is constantly pasted on top of the previous version. 27 | image(kaleidoscope, alpha=0.5) 28 | 29 | # Start the application. 30 | # Open a window that is as big as the image. 31 | canvas.fps = 60 32 | canvas.size = img.width, img.height 33 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/04-twirl.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | img = Image("creature.png") 7 | 8 | def draw(canvas): 9 | 10 | # This basically does the same as the previous example (bump), 11 | # except that we use a twirl distortion filter. 12 | # Furthermore, the filter is permanently applied when the mouse is pressed. 13 | # To do this, we replace the source image with the twirled version. 14 | # Hence we declare img as global, so we can modify the variable's contents. 15 | global img 16 | 17 | canvas.clear() 18 | 19 | dx = canvas.mouse.x / float(img.width) 20 | dy = canvas.mouse.y / float(img.height) 21 | image(twirl(img, dx, dy, angle=180, radius=0.5)) 22 | 23 | if canvas.mouse.pressed: 24 | # When the mouse is pressed, render a twirled version of the image, 25 | # and set it as the new source image. 26 | img = twirl(img, dx, dy, angle=180, radius=0.25) 27 | 28 | # Start the application: 29 | canvas.fps = 60 30 | canvas.size = 500, 500 31 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/05-render.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # The render() command executes a function with drawing commands 7 | # in an offscreen (i.e. hidden) canvas and returns an Image object. 8 | # This is useful if you want to apply filters to text, ellipses, etc. 9 | def hello(): 10 | fill(1, 0, 0, 0.5) # Transparent red. 11 | ellipse(120, 120, 200, 200) 12 | fill(0, 1, 0, 0.5) # Transparent green. 13 | ellipse(170, 120, 200, 200) 14 | fill(0, 0, 1, 0.5) # Transparent blue. 15 | ellipse(145, 160, 200, 200) 16 | fill(0) 17 | font("Droid Serif") 18 | text("hello", x=0, y=90, fontsize=70, width=300, align=CENTER) 19 | 20 | # We call this a "procedural" image, because it is entirely created in code. 21 | # Procedural images can be useful in many ways: 22 | # - applying effects to text, 23 | # - caching a complex composition that is not frequently updated (for speed), 24 | # - creating on-the-fly textures or shapes that are different every time, 25 | # - using NodeBox from the command line without opening an application window. 26 | img = render(function=hello, width=300, height=300) 27 | 28 | # Note that we make the width and height of the offscreen canvas 29 | # a little bit larger than the actual composition. 30 | # This creates a transparent border, so effects don't get cut off 31 | # at the edge of the rendered image. 32 | 33 | # Images can be saved to file, even without starting canvas.run(). 34 | # To try it out, uncomment the following line: 35 | #img.save("hello.png") 36 | 37 | def draw(canvas): 38 | 39 | canvas.clear() 40 | 41 | # Apply a blur filter to the procedural image and draw it. 42 | image(blur(img, scale=canvas.mouse.relative_x), 20, 100) 43 | 44 | # Compare to the same shapes drawn directly to the canvas. 45 | # You may notice that the rendered image has jagged edges... 46 | # For now, there is nothing to be done about that - a soft blur can help. 47 | translate(300,100) 48 | fill(1, 0, 0, 0.5) 49 | ellipse(120, 120, 200, 200) 50 | fill(0, 1, 0, 0.5) 51 | ellipse(170, 120, 200, 200) 52 | fill(0, 0, 1, 0.5) 53 | ellipse(145, 160, 200, 200) 54 | 55 | # Start the application: 56 | canvas.fps = 60 57 | canvas.size = 600, 500 58 | canvas.run(draw) 59 | -------------------------------------------------------------------------------- /examples/07-filter/06-mask.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Render a radial gradient image. 7 | # Without additional parameters, the gradient will be grayscale. 8 | g = gradient(350, 350, type=RADIAL) 9 | 10 | # The mask() filter covers one image with another (grayscale) image. 11 | # You can use the grayscale() filter to make image black & white. 12 | # The mask will hide the source image where the mask is black. 13 | # We use the radial gradient as a mask. 14 | # The radial gradient is white at the edges and black at the center. 15 | # We invert it so we get black edges. 16 | # The result is that the source image will gradually fade away at the edges. 17 | img = Image("dendrite.png") 18 | img = mask(img, invert(g)) 19 | 20 | # Crop the source image to the size of the mask. 21 | # Our mask is smaller than the source image, so beyond it is still pixel data 22 | # but we no longer need it. 23 | img = crop(img, x=0, y=0, width=350, height=350) 24 | 25 | def draw(canvas): 26 | 27 | #canvas.clear() 28 | 29 | # Each frame, paint a new image to the canvas. 30 | # Since its edges are transparent, all images blend into each other. 31 | # This is a useful technique if you want to create random, 32 | # procedural textures (e.g. tree back, rust & dirt, clouded sky, ...) 33 | translate(random(450), random(450)) 34 | rotate(random(360)) 35 | translate(-img.width/2, -img.height/2) # Rotate from image center. 36 | image(img) 37 | 38 | # Start the application: 39 | canvas.fps = 5 # Slow framerate so we can observe what is happening. 40 | canvas.size = 500, 500 # This is a bad idea since keyboard events 41 | canvas.run(draw) # are now logged very slowly. -------------------------------------------------------------------------------- /examples/07-filter/07-blend.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # Blend modes are used to combine the pixels of two images, 7 | # in different ways than standard transparency. 8 | # NodeBox supports the most common blend modes as filters: 9 | # add(), subtract(), darken(), lighten(), multiply(), screen(), overlay(), hue(). 10 | # These can be used to adjust the lighting in an image 11 | # (by blending it with a copy of itself), 12 | # or to obtain many creative texturing effects. 13 | 14 | img1 = Image("creature.png") 15 | img2 = Image("creature.png") 16 | 17 | def draw(canvas): 18 | 19 | canvas.clear() 20 | 21 | # Press the mouse to compare the blend to normal ("source over") mode: 22 | if not canvas.mouse.pressed: 23 | image( 24 | # Try changing this to another blend filter: 25 | multiply(img1, img2, 26 | # All blend modes (and mask()) have optional dx and dy parameters 27 | # that define the offset of the blend layer. 28 | dx = canvas.mouse.x - img1.width/2, 29 | dy = canvas.mouse.y - img1.height/2)) 30 | else: 31 | image(img1) 32 | image(img2, 33 | x = canvas.mouse.x - img1.width/2, 34 | y = canvas.mouse.y - img1.height/2) 35 | 36 | # Start the application: 37 | canvas.fps = 30 38 | canvas.size = 500, 500 39 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/08-bloom.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | img = Image("dendrite.png") 7 | 8 | def draw(canvas): 9 | canvas.clear() 10 | 11 | # The bloom() and glow() filters can be used for a "magic light" effect. 12 | # They work as a combination of brightpass(), blur() and add() filters. 13 | image(bloom(img, 14 | intensity = 1.0, 15 | threshold = 0.6 - 0.3*canvas.mouse.relative_x)) 16 | 17 | # Start the application: 18 | canvas.fps = 30 19 | canvas.size = 700, 350 20 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/07-filter/cell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/07-filter/cell.png -------------------------------------------------------------------------------- /examples/07-filter/creature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/07-filter/creature.png -------------------------------------------------------------------------------- /examples/07-filter/dendrite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/07-filter/dendrite.png -------------------------------------------------------------------------------- /examples/08-physics/02-spring.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.physics import Particle, Spring, System 6 | 7 | # A "particle system" is used to simulate effects such as explosions, smoke, water, ... 8 | # It consists of object with a mass (particles) that are subjected to forces 9 | # (attractive, repulsive, spring-based). 10 | 11 | # In this case, 12 | # the system is a grid (net/tissue) of particles arranged in rows and columns. 13 | s = System() 14 | x = 65 # Horizontal offset. 15 | y = 65 # Vertical offset. 16 | d = 40 # Distance between each particle. 17 | m = 10 # Number of rows. 18 | n = 10 # Number of columns. 19 | for i in range(n): 20 | for j in range(m): 21 | s.append( 22 | Particle( 23 | x = x + i*d, 24 | y = y + j*d, radius=5)) 25 | 26 | # Spring forces operate on all particles, 27 | # so that when we drag one particle all others are indirectly dragged as well. 28 | # The strength of each spring defines the flexibilty of the resulting fabric. 29 | for i in range(n): 30 | for j in range(m): 31 | p1 = s.particles[i*m + j] 32 | if i < (n-1): 33 | p2 = s.particles[(i+1)*m + j+0] # Particle to the right. 34 | s.springs.append( Spring(p1, p2, length=d, strength=2.0)) 35 | if j < (m-1): 36 | p2 = s.particles[(i+0)*m + j+1] # Particle below. 37 | s.springs.append( Spring(p1, p2, length=d, strength=2.0)) 38 | 39 | # An interesting effect is to add a global repulsive force between all particles. 40 | # The fabric will now bulge outward - a little bit like a balloon. 41 | # When manipulated, it will resume its old shape. 42 | #s.force(strength=1) 43 | 44 | dragged = None 45 | def draw(canvas): 46 | 47 | canvas.clear() 48 | background(1) 49 | 50 | stroke(0, 0.2) 51 | fill(0) 52 | s.update() # Calculate forces in the system. 53 | s.draw() # Draw particles and springs. 54 | # This is a very simple representation. 55 | # If you need fancier drawing, subclass Particle and Spring. 56 | 57 | # Particles can be dragged... I hate making the bed. 58 | global dragged 59 | if dragged: 60 | # Uncomment the code below to make the fabric break on random occasions. 61 | # If this happens, find all the springs connected 62 | # to the particle being dragged and snap them: 63 | #if random() > 0.995: 64 | # for f in s.dynamics(dragged, type=Spring): 65 | # f.snap() 66 | dragged.x = canvas.mouse.x 67 | dragged.y = canvas.mouse.y 68 | if not canvas.mouse.pressed: 69 | dragged = None 70 | elif not dragged: 71 | for p in s.particles: 72 | if abs(canvas.mouse.x-p.x) < p.radius and \ 73 | abs(canvas.mouse.y-p.y) < p.radius: 74 | dragged = p 75 | 76 | canvas.size = 500, 500 77 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/08-physics/03-force.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.physics import Particle, Force, System 6 | 7 | # BANG! 8 | 9 | # Here is a short example of how the Particle class 10 | # can be subclassed with a custom draw() method: 11 | class Spark(Particle): 12 | def draw(self): 13 | r = self.radius * (1-self.age) 14 | ellipse(self.x, self.y, r*2, r*2) 15 | 16 | s = System(gravity=(0, 2.5)) # Pull the particles to the bottom edge. 17 | for i in range(80): 18 | s.append( 19 | Spark( 20 | x = 300, 21 | y = 400, 22 | mass = random(5.0,10.0), # Heavier particles are repulsed harder. 23 | radius = 5, # But doesn't mean they appear bigger. 24 | life = 200 # Particles whither away after 200 frames. 25 | )) 26 | 27 | # A repulsive force between all particles. 28 | # When particles are very close to each other, forces can be very strong, 29 | # causing particles to move offscreen before anything can be observed. 30 | # This can be tweaked with the threshold ( 31 | # which is the minimum distance at which the force operates). 32 | # We can also lower the strength of the force, 33 | # but this weakens the effect in general. 34 | # What also helps is not creating all particles at the same position. 35 | s.force(strength=8.5, threshold=70) 36 | 37 | def draw(canvas): 38 | 39 | background(1, 0.1) # Trailing effect. 40 | 41 | s.update(limit=20) 42 | s.draw() 43 | canvas.size = 600, 600 44 | canvas.run(draw) 45 | 46 | # Running physics in real-time takes a lot of processing power. 47 | # If you are using physics for game effects (e.g. explosions, spells), 48 | # it is a good idea to render them offscreen, store them as an Animation, 49 | # and replay the animation when necessary. -------------------------------------------------------------------------------- /examples/08-physics/04-animation.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.physics import Particle, Force, System 6 | 7 | # This example demonstrates the Animation object, 8 | # which can be used to store and replay a sequence of image frames. 9 | # This is useful for caching pre-rendered effects, like a spell or an explosion. 10 | 11 | # This is just the explosion system from the previous example in a more condensed form. 12 | s = System(gravity=(0, 1.0)) 13 | for i in range(80): 14 | s.append(Particle(x=200, y=250, mass=random(5.0,10.0), radius=5, life=30)) 15 | s.force(strength=4.5, threshold=70) 16 | 17 | # Instead of drawing the system directly to the canvas, 18 | # we render each step offscreen as an image, 19 | # and then gather the images in an animation loop. 20 | explosion = Animation(duration=0.75, loop=False) 21 | for i in range(30): 22 | s.update(limit=20) 23 | img = render(s.draw, 400, 400) 24 | explosion.append(img) 25 | 26 | # This can take several seconds: 27 | # - calculating forces in the system is costly (if possible, load Psyco to speed them up), 28 | # - rendering each image takes time (specifically, initialising a new empty image). 29 | # If possible, reduce the image frames in size (smaller images = faster rendering). 30 | 31 | # When the user clicks on the canvas, the explosion animation is played. 32 | # We keep a list of explosions currently playing: 33 | explosions = [] 34 | 35 | def on_mouse_press(canvas, mouse): 36 | # When the mouse is clicked, start a new explosion at the mouse position. 37 | explosions.append((mouse.x, mouse.y, explosion.copy())) 38 | 39 | def draw(canvas): 40 | 41 | canvas.clear() 42 | 43 | global explosions 44 | for x, y, e in explosions: 45 | push() 46 | translate(x-200, y-250) # Draw from the origin of the explosion. 47 | e.update() # Move to the next frame in the animation. 48 | image(e.frame) # Draw the current frame. 49 | pop() 50 | 51 | # Remove explosions that are done playing. 52 | explosions = [(x, y, e) for x, y, e in explosions if not e.done] 53 | 54 | canvas.size = 700, 700 55 | canvas.on_mouse_press = on_mouse_press # Register mouse event handler. 56 | canvas.run(draw) 57 | -------------------------------------------------------------------------------- /examples/08-physics/05-emitter.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.physics import System, Emitter, Particle, MASS 6 | 7 | # 1) An emitter will be firing particles with a constant velocity. 8 | # 2) Drag in the system slows down the particles. 9 | # 3) Gravity then becomes greater than the particles' velocity and they are pulled down. 10 | s = System(gravity=(0, 1.0), drag=0.01) 11 | 12 | # The emitter is positioned centrally at the bottom, 13 | # and fires particles upwards in a 30-degrees angle range. 14 | e = Emitter(x=200, y=0, angle=90, strength=10.0, spread=30) 15 | for i in range(100): 16 | # Particles have random mass and lifespan to make it more interesting and diverse. 17 | # The MASS constant means that we want the radius of the visual particle 18 | # to be initialized with the same value as its mass (it's a convenience trick). 19 | # This way we can observe how heavier particles respond. 20 | e.append(Particle(0, 0, mass=random(10,50), radius=MASS, life=random(50,250))) 21 | 22 | s.append(e) # Install the emitter in the system. 23 | 24 | # Add an obstacle that other particles want to stay away from. 25 | 26 | class Obstacle(Particle): 27 | def draw(self): 28 | # The only way to style individual particles is to redefine draw() in a subclass. 29 | # Set the fill color directly for this ellipse, i.e. don't use fill(), 30 | # because this sets the state and then other particles might use this color too. 31 | ellipse(self.x, self.y, self.radius*2, self.radius*2, fill=(0,0,0.3,0.1)) 32 | 33 | obstacle = Obstacle(0, 0, mass=70, radius=70, fixed=True) 34 | s.append(obstacle) 35 | s.force(6, source=obstacle) # Repulsive force from this particle to all others. 36 | 37 | def draw(canvas): 38 | 39 | background(1) 40 | 41 | fill(0,0.5,1,0.1) 42 | stroke(0,0.3) 43 | strokewidth(1) 44 | s.update() 45 | s.draw() 46 | 47 | # Put the obstacle at the mouse position. 48 | # This way we can play around with the fountain spray. 49 | obstacle.x = canvas.mouse.x 50 | obstacle.y = canvas.mouse.y 51 | 52 | canvas.size = 400, 700 53 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/08-physics/07-graph.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.graphics.physics import Node, Edge, Graph 6 | 7 | # Create a graph with randomly connected nodes. 8 | # Nodes and edges can be styled with fill, stroke, strokewidth parameters. 9 | # Each node displays its id as a text label, stored as a Text object in Node.text. 10 | # To hide the node label, set the text parameter to None. 11 | g = Graph() 12 | # Random nodes. 13 | for i in range(50): 14 | g.add_node(id=str(i+1), 15 | radius = 5, 16 | stroke = color(0), 17 | text = color(0)) 18 | # Random edges. 19 | for i in range(75): 20 | node1 = choice(g.nodes) 21 | node2 = choice(g.nodes) 22 | g.add_edge(node1, node2, 23 | length = 1.0, 24 | weight = random(), 25 | stroke = color(0)) 26 | 27 | # Two handy tricks to prettify the layout: 28 | # 1) Nodes with a higher weight (i.e. incoming traffic) appear bigger. 29 | for node in g.nodes: 30 | node.radius = node.radius + node.radius*node.weight 31 | # 2) Nodes with only one connection ("leaf" nodes) have a shorter connection. 32 | for node in g.nodes: 33 | if len(node.edges) == 1: 34 | node.edges[0].length *= 0.1 35 | 36 | g.prune(depth=0) # Remove orphaned nodes with no connections. 37 | g.distance = 10 # Overall spacing between nodes. 38 | g.layout.force = 0.01 # Strength of the attractive & repulsive force. 39 | g.layout.repulsion = 15 # Repulsion radius. 40 | 41 | dragged = None 42 | def draw(canvas): 43 | 44 | canvas.clear() 45 | background(1) 46 | translate(250, 250) 47 | 48 | # With directed=True, edges have an arrowhead indicating the direction of the connection. 49 | # With weighted=True, Node.centrality is indicated by a shadow under high-traffic nodes. 50 | # With weighted=0.0-1.0, indicates nodes whose centrality > the given threshold. 51 | # This requires some extra calculations. 52 | g.draw(weighted=0.5, directed=True) 53 | g.update(iterations=10) 54 | 55 | # Make it interactive! 56 | # When the mouse is pressed, remember on which node. 57 | # Drag this node around when the mouse is moved. 58 | dx = canvas.mouse.x - 250 # Undo translate(). 59 | dy = canvas.mouse.y - 250 60 | global dragged 61 | if canvas.mouse.pressed and not dragged: 62 | dragged = g.node_at(dx, dy) 63 | if not canvas.mouse.pressed: 64 | dragged = None 65 | if dragged: 66 | dragged.x = dx 67 | dragged.y = dy 68 | 69 | canvas.size = 500, 500 70 | canvas.run(draw) 71 | -------------------------------------------------------------------------------- /examples/08-physics/cells/blue-block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/blue-block.png -------------------------------------------------------------------------------- /examples/08-physics/cells/blue-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/blue-circle.png -------------------------------------------------------------------------------- /examples/08-physics/cells/blue-empty1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/blue-empty1.png -------------------------------------------------------------------------------- /examples/08-physics/cells/blue-empty2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/blue-empty2.png -------------------------------------------------------------------------------- /examples/08-physics/cells/blue-star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/blue-star.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-block1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-block1.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-block2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-block2.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-circle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-circle1.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-circle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-circle2.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-empty1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-empty1.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-empty2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-empty2.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-empty3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-empty3.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-star1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-star1.png -------------------------------------------------------------------------------- /examples/08-physics/cells/green-star2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/08-physics/cells/green-star2.png -------------------------------------------------------------------------------- /examples/09-layer/03-tween.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | # This example demonstrates motion tweening and prototype-based inheritance on layers. 7 | 8 | # Motion tweening is easy: set the Layer.duration parameter to the amount of seconds 9 | # it should take for transformations to take effect. 10 | 11 | # Prototype-based inheritance is used because we were lazy. 12 | # Normally, you create a subclass of layer, give it extra properties (image, color, ...) 13 | # and override its draw() method. The only problem (aside from the repetitive work) 14 | # is Layer.copy(). This creates a copy of the layer with all of its properties, 15 | # but NOT the custom properties we added in a subclass. So we'd have to implement 16 | # our own copy() method for each custom layer that we want to reuse. 17 | 18 | # Layers can also use dynamic, prototype-based inheritance, where layers are "inherited" 19 | # instead of subclassed. Custom properties and methods can be set with Layer.set_property() 20 | # and Layer.set_method(). This ensures that they will be copied correctly. 21 | 22 | # Create a layer that draws an image, and has the same dimensions as the image. 23 | # It transforms from the center, and it will take one second for transformations to complete. 24 | creature = Layer.from_image("creature.png", x=250, y=250, origin=CENTER, duration=1.0) 25 | 26 | # Add a new on_mouse_press handler to the prototype: 27 | def whirl(layer, mouse): 28 | layer.x += random(-100, 100) 29 | layer.y += random(-100, 100) 30 | layer.scaling += random(-0.2, 0.2) 31 | layer.rotation += random(-360, 360) 32 | layer.opacity = random(0.5, 1.0) 33 | 34 | creature.set_method(whirl, "on_mouse_press") 35 | 36 | # Add a number of copies to the canvas. 37 | for i in range(4): 38 | canvas.append(creature.copy()) 39 | 40 | canvas.size = 500, 500 41 | canvas.run() 42 | -------------------------------------------------------------------------------- /examples/09-layer/creature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/examples/09-layer/creature.png -------------------------------------------------------------------------------- /examples/10-gui/02-panel.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.gui import * 6 | 7 | # A panel is a container for other GUI controls. 8 | # Controls can be added to the panel, 9 | # and organized by setting the controls' x and y properties 10 | # (since all controls inherit from Layer, they all have the same properties as a layer). 11 | panel = Panel("Example", width=200, height=200, fixed=False, modal=False) 12 | 13 | # Alternatively, a layout manager can be added to a panel. 14 | # A layout manager is itself a group of controls. 15 | # By calling Layout.apply(), the manager will take care of arranging its controls. 16 | # A simple layout manager is "Rows" layout, in which each control is drawn on a new row. 17 | # A caption can be defined for each control in the Rows layout, 18 | # it will be placed to the left of each control. 19 | layout = Rows() 20 | layout.extend([ 21 | Field(value="hello world", hint="text", id="text"), 22 | ("size", Slider(default=1.0, min=0.0, max=2.0, steps=100, id="size")), 23 | ("alpha", Slider(default=1.0, min=0.0, max=1.0, steps=100, id="alpha")), 24 | ("show?", Flag(default=True, id="show")) 25 | ]) 26 | 27 | # The panel will automatically call Layout.apply() when the layout is added. 28 | panel.append(layout) 29 | 30 | # With Panel.pack(), the size of the panel is condensed as much as possible. 31 | panel.pack() 32 | 33 | # Panel inherits from Layer, 34 | # so we append it to the canvas just as we do with a layer: 35 | canvas.append(panel) 36 | 37 | def draw(canvas): 38 | 39 | canvas.clear() 40 | 41 | # In this simple example, 42 | # we link the values from the controls in the panel to a displayed text. 43 | # Controls with an id are available as properties of the panel 44 | # (e.g. a control with id "slider" can be retrieved as Panel.slider). 45 | # Most controls have a Control.value property that retrieves the current value: 46 | if panel.show.value == True: 47 | font("Droid Serif") 48 | fontsize(50 * panel.size.value) 49 | fill(0, panel.alpha.value) 50 | text(panel.text.value, 50, 250) 51 | 52 | canvas.size = 500, 500 53 | canvas.run(draw) 54 | 55 | # Note: 56 | # We named one of the sliders "alpha" instead of "opacity", 57 | # which would be a more comprehensible id, but which is already taken 58 | # because there is a Panel.opacity property (inherited from Layer). 59 | # In reality, it is much better to choose less ambiguous id's, 60 | # such as "field1_text" or "slider2_opacity". 61 | -------------------------------------------------------------------------------- /examples/10-gui/03-button.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.gui import * 6 | 7 | # This is the same example as the previous, but with a button added to the panel. 8 | # All controls have a Control.on_action() event that fires when the user 9 | # interacts with the control (for a slider: dragging the slider, for a flag: 10 | # toggling the flag, for a field: hitting enter, for a button: clicking it). 11 | 12 | def reset_panel(button): 13 | # A simple action which we will link to the button. 14 | # It fires when the button is pressed. 15 | panel = button.parent.parent # First parent is the Rows layout, parent of the layout is the panel. 16 | panel.field_text.reset() 17 | panel.slider_size.reset() 18 | panel.slider_opacity.reset() 19 | panel.show.reset() 20 | 21 | panel = Panel("Example", width=200, height=200, fixed=False, modal=False) 22 | panel.append(Rows( 23 | [Field(value="hello world", hint="text", id="field_text"), 24 | ( "size", Slider(default=1.0, min=0.0, max=2.0, steps=100, id="slider_size")), 25 | ( "opacity", Slider(default=1.0, min=0.0, max=1.0, steps=100, id="slider_opacity")), 26 | ( "show?", Flag(default=True, id="show")), 27 | Button("Reset", action=reset_panel), # Register our function as the button's action. 28 | ])) 29 | panel.pack() 30 | canvas.append(panel) 31 | 32 | def draw(canvas): 33 | 34 | canvas.clear() 35 | 36 | if panel.show.value == True: 37 | font("Droid Serif") 38 | fontsize(50 * panel.slider_size.value) 39 | fill(0, panel.slider_opacity.value) 40 | text(panel.field_text.value, 50, 250) 41 | 42 | canvas.size = 500, 500 43 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/10-gui/04-knob.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.gui import * 6 | 7 | # This example demonstrates the knob GUI control, 8 | # and how different layout managers can be nested. 9 | # Knobs look nice when placed next to each other. 10 | # The "Row" layout can be used to achieve this. 11 | # It arranges all of its controls horizontally, with their captions on top. 12 | # The Row layout can then be nested in a Rows layout (or vice versa). 13 | # This allows you to build many different interface grids. 14 | panel = Panel("Example", width=300, height=200, fixed=False, modal=False) 15 | panel.append(Rows( 16 | [("text",Field(value="hello world", hint="text", id="field_text")), 17 | ( "size", Slider(default=1.0, min=0.0, max=2.0, steps=100, id="slider_size")), 18 | ( "opacity", Slider(default=1.0, min=0.0, max=1.0, steps=100, id="slider_opacity")), 19 | ( "color", Row([("R", Knob(id="knob_r")), 20 | ("G", Knob(id="knob_g")), 21 | ("B", Knob(id="knob_b")) 22 | ]))])) 23 | panel.pack() 24 | canvas.append(panel) 25 | 26 | def draw(canvas): 27 | 28 | canvas.clear() 29 | 30 | font("Droid Serif") 31 | fontsize(50 * panel.slider_size.value) 32 | fill(panel.knob_r.relative, # Knob.value is between 0-360. 33 | panel.knob_g.relative, # Knob.relative between 0.0-1.0. 34 | panel.knob_b.relative, 35 | panel.slider_opacity.value) 36 | text(panel.field_text.value, 20, 200) 37 | 38 | canvas.size = 500, 500 39 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/11-sound/01-fft.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.sound import PD, LOCALHOST 6 | 7 | # PureData is a free, real-time graphical programming environment for audio processing. 8 | # You can connect building blocks to manipulate audio input, or generate audio output. 9 | # A network of building blocks is called a "patch" in Pd-terms. 10 | 11 | # FFT (Fast Fourier Transform) is (among other things) an algorithm to measure tone frequency. 12 | # The 01-fft.pd patch calculates FFT on the microphone input and broadcasts 13 | # a list of 8 frequency bands (from low tones to high tones) on the "/equalizer" path. 14 | # You can observe this by opening the PD patch. 15 | # We can retrieve the data with PD.get("/equalizer"). 16 | 17 | # This is useful for an interactive VJ application, for example. 18 | 19 | # The nodebox.sound.PD class is useful for loading a patch silently in the background. 20 | # The buffer is the number of bytes of audio to transfer between NodeBox and Pd during each request. 21 | # FFT requires a lot of computation, so small buffers are best. 22 | # With start=True to patch will load automatically. Be patient while it loads. 23 | pd = PD("01-fft.pd", buffer=16, start=True) 24 | 25 | def draw(canvas): 26 | canvas.clear() 27 | # Retrieve new audio frequencies each frame of animation. 28 | # The server host and port correspond to the host and port in the patch. 29 | data = pd.get("/equalizer", host=LOCALHOST, port=44000) 30 | if data: 31 | w = float(canvas.width) / len(data) 32 | for i, frequency in enumerate(data): 33 | rect(w*i, 0, w, frequency * 2) 34 | 35 | # We can register a stop() event with the canvas, 36 | # which will be executed when the application window closes. 37 | # It is important to quit PD here, otherwise it will continue to run in the background! 38 | def stop(canvas): 39 | pd.stop() 40 | 41 | canvas.run(draw, stop=stop) 42 | 43 | -------------------------------------------------------------------------------- /examples/11-sound/02-in-out.pd: -------------------------------------------------------------------------------- 1 | #N canvas 564 68 542 392 10; 2 | #X obj 24 339 sendOSC; 3 | #X obj 20 32 loadbang; 4 | #X obj 128 187 bng 15 250 50 0 empty empty empty 0 -6 0 10 -262144 5 | -1 -1; 6 | #X floatatom 157 149 5 0 0 0 - - -; 7 | #X obj 179 187 bng 15 250 50 0 empty empty empty 0 -6 0 10 -262144 8 | -1 -1; 9 | #X obj 282 277 print; 10 | #X floatatom 360 211 5 0 0 0 - - -; 11 | #X floatatom 319 211 5 0 0 0 - - -; 12 | #X obj 299 176 unpack s f f; 13 | #X obj 55 254 pack f f f; 14 | #X msg 327 318 set \$1; 15 | #X obj 40 149 nbx 5 14 40 1e+37 0 0 empty empty empty 0 -6 0 10 -262144 16 | -1 -1 270 256; 17 | #X obj 98 149 nbx 5 14 40 1e+37 0 0 empty empty empty 0 -6 0 10 -262144 18 | -1 -1 113 256; 19 | #X text 20 10 loadbang fires when the patch is loaded; 20 | #X msg 20 56 connect localhost 44000; 21 | #X msg 55 278 send /output \$1 \$2 \$3; 22 | #X text 280 125 receive mouse position from NodeBox; 23 | #X msg 342 344 /input; 24 | #X obj 280 147 dumpOSC 44001; 25 | #X text 31 79 broadcasts 3 numbers on port 44000 we use these numbers 26 | in NodeBox to control size/color/rotation of a shape; 27 | #X connect 1 0 14 0; 28 | #X connect 1 0 11 0; 29 | #X connect 1 0 12 0; 30 | #X connect 2 0 9 0; 31 | #X connect 3 0 4 0; 32 | #X connect 3 0 9 2; 33 | #X connect 4 0 9 0; 34 | #X connect 8 0 10 0; 35 | #X connect 8 1 7 0; 36 | #X connect 8 2 6 0; 37 | #X connect 9 0 15 0; 38 | #X connect 10 0 17 0; 39 | #X connect 11 0 9 0; 40 | #X connect 12 0 9 1; 41 | #X connect 12 0 2 0; 42 | #X connect 14 0 0 0; 43 | #X connect 15 0 0 0; 44 | #X connect 18 0 8 0; 45 | #X connect 18 0 5 0; 46 | -------------------------------------------------------------------------------- /examples/11-sound/02-in-out.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..","..")) 3 | 4 | from nodebox.graphics import * 5 | from nodebox.sound import PD, LOCALHOST, IN, OUT 6 | 7 | # This script demonstrates how to simultaneously receive from and send to Pd. 8 | # We need two communication ports. By default, NodeBox receives on port 44000 (IN), 9 | # so Pd should send from port 44000. NodeBox sends on port 44001 (OUT), 10 | # so Pd should receive om port 44001. 11 | 12 | # With start=False, the patch will not be loaded automatically in the background. 13 | # This means that you must open Pd manually and load the patch. 14 | # This is necessary, because we'll use the Pd GUI to control the NodeBox animation. 15 | pd = PD("02-in-out.pd", start=False) 16 | 17 | def draw(canvas): 18 | canvas.clear() 19 | # As you can see in the Pd patch, it broadcasts three values, 20 | # which we use to control the size, color and rotation of a rectangle. 21 | # You may have to drag the numbers up or down in Pd in order for the rectangle to appear. 22 | data = pd.get("/output", host=LOCALHOST, port=IN) 23 | if data: 24 | size, color, angle = data 25 | translate(250, 250) 26 | rotate(angle) 27 | fill(0, color/255.0, 0) 28 | rect(-size/2, -size/2, size, size) 29 | # As a test, send the mouse position to Pd. 30 | # If you click the NodeBox application window and move the mouse around, 31 | # you'll see the (x,y) position printed in the main Pd window. 32 | pd.send((canvas.mouse.x, canvas.mouse.y), "/input", host=LOCALHOST, port=OUT) 33 | 34 | # We can send data to Pd to generate sound interactively. 35 | # We can receive data from Pd to create an animation that responds to sound. 36 | 37 | def stop(canvas): 38 | pd.stop() 39 | 40 | canvas.size = 500, 500 41 | canvas.run(draw, stop=stop) 42 | 43 | -------------------------------------------------------------------------------- /examples/11-sound/04-audiosnails.pd: -------------------------------------------------------------------------------- 1 | #N canvas 697 101 664 651 10; 2 | #X floatatom 100 173 5 0 0 0 - - -; 3 | #X msg 81 192 set \$1; 4 | #X obj 23 173 print; 5 | #N canvas 0 22 450 300 (subpatch) 0; 6 | #X array am 1000 float 0; 7 | #X coords 0 1 999 -1 200 100 1; 8 | #X restore 301 126 graph; 9 | #X obj 268 305 tgl 15 1 empty empty empty 0 -6 0 10 -262144 -1 -1 1 10 | 1; 11 | #X obj 189 391 dac~; 12 | #X text 279 217 -1; 13 | #X text 285 172 0; 14 | #X text 285 125 1; 15 | #X obj 231 358 tabwrite~ am; 16 | #X obj 189 228 *~; 17 | #X obj 268 330 metro 100; 18 | #X obj 204 158 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10 19 | -262144 -1 -1 0 256; 20 | #X obj 52 305 expr~ $v1 > $v2; 21 | #X obj -4 245 nbx 5 14 0 100 0 1 empty empty pulse_width_(0-100) 60 22 | 6 0 10 -262144 -1 -1 22 256; 23 | #X obj 135 272 / 100; 24 | #X obj 204 192 osc~ 0.9; 25 | #X obj 80 135 unpack s f f; 26 | #X floatatom 152 180 5 0 0 0 - - -; 27 | #X obj 241 76 / 10; 28 | #X obj 169 37 * 44; 29 | #X obj 330 60 mtof; 30 | #X obj 189 117 phasor~; 31 | #X obj 288 25 loadbang; 32 | #X msg 381 25 \; pd dsp 1; 33 | #X msg 453 25 \; pd dsp 0; 34 | #X text 402 0 sound on/off; 35 | #X obj 228 29 % 3000; 36 | #X obj 61 76 dumpOSC 44001; 37 | #X msg 96 218 /input; 38 | #X connect 1 0 29 0; 39 | #X connect 4 0 11 0; 40 | #X connect 10 0 13 0; 41 | #X connect 11 0 9 0; 42 | #X connect 12 0 16 0; 43 | #X connect 13 0 5 0; 44 | #X connect 13 0 5 1; 45 | #X connect 13 0 9 0; 46 | #X connect 14 0 15 0; 47 | #X connect 15 0 13 1; 48 | #X connect 16 0 10 1; 49 | #X connect 17 0 1 0; 50 | #X connect 17 0 2 0; 51 | #X connect 17 1 0 0; 52 | #X connect 17 1 27 0; 53 | #X connect 17 2 18 0; 54 | #X connect 17 2 20 0; 55 | #X connect 18 0 20 0; 56 | #X connect 20 0 22 0; 57 | #X connect 21 0 22 0; 58 | #X connect 22 0 10 0; 59 | #X connect 23 0 24 0; 60 | #X connect 27 0 12 0; 61 | #X connect 28 0 17 0; 62 | -------------------------------------------------------------------------------- /examples/12-experimental/02-blend.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..", "..")) 3 | 4 | from nodebox.graphics import * 5 | from pyglet.gl import * 6 | from random import seed 7 | 8 | # A question that regularly pops up is: 9 | # "How can I draw shapes to the canvas with a blending mode? (e.g. multiply)" 10 | # OpenGL has different blend modes with the glBlendFunc() command. 11 | # You can either enable alpha transparency (for images with holes) 12 | # OR a different blend mode, but you cannot combine both. 13 | # This is a limitation in OpenGL. 14 | # You could use image filters (e.g. multiply(), render()) but this can be slow / a lot of work: 15 | # if you also want your image to appear rotated on the canvas, 16 | # you'd first need to transform (rotate, scale) the image into another image, 17 | # and then use this rendered image with multiply() or screen(). 18 | 19 | # Here is an example of additive and subtractive blending, directly to the canvas. 20 | # You can use these to simulate screen and multiply blend. 21 | # Additive: glBlendFunc(GL_SRC_ALPHA, GL_ONE) 22 | # Subtractive: glBlendFunc(GL_DST_COLOR, GL_ONE) 23 | 24 | # Additive blending works OK with alpha transparency, 25 | # subtractive doesn't, so it's only useful in specific situations. 26 | 27 | def draw(canvas): 28 | 29 | seed(1) 30 | canvas.clear() 31 | background(0) 32 | 33 | if not canvas.mouse.pressed: 34 | # Press the mouse to see the difference with normal blending. 35 | # Additive mode adds a nice glow effect to overlapping shapes. 36 | glBlendFunc(GL_SRC_ALPHA, GL_ONE) 37 | #glBlendFunc(GL_DST_COLOR, GL_ZERO) # For subtractive blending, set background(1). 38 | # background(0) + subtractive shape = black. 39 | 40 | fill(0.8, 0.2, 0, random()) 41 | for i in range(100): 42 | r = 50 + random(100) 43 | oval(random(500), random(500), r, r) 44 | 45 | # When you're done, reset to the default NodeBox blend mode, 46 | # which enables alpha transparency for images. 47 | glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 48 | 49 | 50 | canvas.size = 500, 500 51 | canvas.run(draw) 52 | -------------------------------------------------------------------------------- /examples/12-experimental/04-live1.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..", "..")) 3 | import warnings 4 | 5 | from nodebox.graphics import * 6 | 7 | # Live coding example. 8 | # The actual drawing code is in 04-live2.py. 9 | # This script starts the canvas and executes the commands from 04-live2.py. 10 | # You can then edit and save the code there, 11 | # changes will be reflected automatically while the canvas keeps running. 12 | 13 | SCRIPT = "04-live2.py" 14 | source = open(SCRIPT).read() 15 | modified = os.path.getmtime(SCRIPT) 16 | 17 | def draw(canvas): 18 | global source 19 | global modified 20 | try: 21 | exec(source) 22 | except Exception, e: 23 | warnings.warn(str(e), Warning) 24 | if os.path.getmtime(SCRIPT) > modified: 25 | source = open(SCRIPT).read() 26 | modified = os.path.getmtime(SCRIPT) 27 | 28 | canvas.size = 500, 500 29 | canvas.fps = 30 30 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/12-experimental/04-live2.py: -------------------------------------------------------------------------------- 1 | # Live coding example. 2 | # See 04-live1.py. 3 | # The commands below are read and executed in a canvas there. 4 | # If you edit and save this file, changes are automatically reflected, 5 | # while the canvas started in 04-live1.py keeps on running. 6 | 7 | #canvas.clear() 8 | for i in range(10): 9 | x = random(canvas.width) 10 | y = random(canvas.height) 11 | r = random(20) + 50 12 | fill(random(), 0.0, random(0.25), random(0.25)) 13 | stroke(0, 0.2) 14 | ellipse(x, y, r, r) 15 | -------------------------------------------------------------------------------- /examples/README.txt: -------------------------------------------------------------------------------- 1 | NodeBox for OpenGL 2 | ================== 3 | 4 | NodeBox for OpenGL is a Python module for creating 2D interactive visuals using OpenGL. It is based on the command set of the classic NodeBox for Mac OS X (http://nodebox.net). It has support for Bezier paths, text, image filters (blur, bloom, ...), offscreen rendering, animation & motion tweening, and simple 2D physics. 5 | 6 | REQUIREMENTS 7 | ============ 8 | 9 | This set of examples requires that you have NodeBox for OpenGL: 10 | http://cityinabottle.org/nodebox 11 | 12 | NodeBox is expected to be located on the same path as the examples folder. 13 | 14 | Your video hardware needs support for OpenGL 2.0. 15 | NodeBox may not (fully) work on older hardware. Telltale signs are: 16 | - Using image filters only works with non-transparent images. 17 | - Using image filters produces no visible effect, and nodebox.graphics.shader.SUPPORTED is False. 18 | - Using the render() or filter() command throws an OffscreenBufferError. 19 | 20 | Older hardware may produce garbled output in the following examples (that rely on image filters): 21 | - 05-path/05-spider.py 22 | - 07-filter/* 23 | - 08-physics/04-animation.py -------------------------------------------------------------------------------- /examples/template.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | def draw(canvas): 7 | canvas.clear() 8 | 9 | canvas.size = 500, 500 10 | canvas.run(draw) -------------------------------------------------------------------------------- /examples/test.py: -------------------------------------------------------------------------------- 1 | # Add the upper directory (where the nodebox module is) to the search path. 2 | import os, sys; sys.path.insert(0, os.path.join("..")) 3 | 4 | from nodebox.graphics import * 5 | 6 | def draw(canvas): 7 | background(1) 8 | translate(250, 250) 9 | rotate(canvas.frame) 10 | rect(-100, -100, 200, 200) 11 | 12 | canvas.size = 500, 500 13 | canvas.run(draw) 14 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/icon.png -------------------------------------------------------------------------------- /nodebox/__init__.py: -------------------------------------------------------------------------------- 1 | #=== NODEBOX FOR OPENGL ============================================================================== 2 | 3 | # NodeBox for OpenGL is a Python module for creating 2D interactive visuals using OpenGL. 4 | # It is based on the command set of the classic NodeBox for Mac OS X (http://nodebox.net). 5 | # It has support for Bezier paths, text, image filters (blur, bloom, ...), offscreen rendering, 6 | # animation & motion tweening, and simple 2D physics. 7 | 8 | __author__ = "Tom De Smedt, Frederik De Bleser" 9 | __version__ = "1.7" 10 | __copyright__ = "Copyright (c) 2008-2012 City In A Bottle (cityinabottle.org)" 11 | __license__ = "BSD" 12 | 13 | import sys 14 | if sys.version_info < (2,7): 15 | try: import psyco; psyco.profile() 16 | except: 17 | try: from ext import psyco; psyco.profile() 18 | except: 19 | pass 20 | 21 | import nodebox -------------------------------------------------------------------------------- /nodebox/ext/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/ext/__init__.py -------------------------------------------------------------------------------- /nodebox/ext/noise.c: -------------------------------------------------------------------------------- 1 | // --- PERLIN NOISE -------------------------------------------------------------------- 2 | // Based on: Malcolm Kesson, http://www.fundza.com/c4serious/noise/perlin/perlin.html 3 | // © 2002-4 Malcolm Kesson. All rights reserved. 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | static int p[512]; 11 | 12 | double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); } 13 | double lerp(double t, double a, double b) { return a + t * (b - a); } 14 | double grad(int hash, double x, double y, double z) { 15 | int h = hash & 15; 16 | double u = h < 8 ? x : y, 17 | v = h < 4 ? y : h==12 || h==14 ? x : z; 18 | return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); 19 | } 20 | 21 | double _generate(double x, double y, double z) { 22 | // Find unit cuve that contains point. 23 | int X = (int)floor(x) & 255, 24 | Y = (int)floor(y) & 255, 25 | Z = (int)floor(z) & 255; 26 | // Find relative x, y, z of point in cube. 27 | x -= floor(x); 28 | y -= floor(y); 29 | z -= floor(z); 30 | // Compute fade curves for each of x, y, z. 31 | double u=fade(x), v=fade(y), w=fade(z); 32 | // Hash coordinates of the 8 cube corners. 33 | int A = p[X ] + Y, 34 | AA = p[A ] + Z, 35 | AB = p[A+1] + Z, 36 | B = p[X+1] + Y, 37 | BA = p[B ] + Z, 38 | BB = p[B+1] + Z; 39 | // Add blended results from 8 corners of cube. 40 | return lerp(w, 41 | lerp(v, lerp(u, grad(p[AA ], x , y , z ), 42 | grad(p[BA ], x-1, y , z )), 43 | lerp(u, grad(p[AB ], x , y-1, z ), 44 | grad(p[BB ], x-1, y-1, z ))), 45 | lerp(v, lerp(u, grad(p[AA+1], x , y , z-1), 46 | grad(p[BA+1], x-1, y , z-1)), 47 | lerp(u, grad(p[AB+1], x , y-1, z-1), 48 | grad(p[BB+1], x-1, y-1, z-1)))); 49 | } 50 | 51 | // ------------------------------------------------------------------------------------- 52 | 53 | static PyObject * 54 | generate(PyObject *self, PyObject *args) { 55 | double x, y, z, d; 56 | if (!PyArg_ParseTuple(args, "ddd", &x, &y, &z)) return NULL; 57 | d = _generate(x, y, z); 58 | return Py_BuildValue("d", d); 59 | } 60 | 61 | static PyObject * 62 | init(PyObject *self, PyObject *args) { 63 | PyObject * a; 64 | if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &a)) return NULL; 65 | int i; 66 | for(i=0; i<512; i++) 67 | p[i] = (int)PyInt_AsLong(PyList_GetItem(a, i)); 68 | return Py_BuildValue(""); 69 | } 70 | 71 | static PyMethodDef methods[]={ 72 | { "generate", generate, METH_VARARGS }, 73 | { "init", init, METH_VARARGS }, 74 | { NULL, NULL } 75 | }; 76 | 77 | PyMODINIT_FUNC initnoise(void) { 78 | PyObject *m; 79 | m = Py_InitModule("noise", methods); 80 | } 81 | 82 | int main(int argc, char *argv[]) { 83 | Py_SetProgramName(argv[0]); 84 | Py_Initialize(); 85 | initnoise(); 86 | return 0; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/__init__.py: -------------------------------------------------------------------------------- 1 | ########################################################################### 2 | # 3 | # Psyco top-level file of the Psyco package. 4 | # Copyright (C) 2001-2002 Armin Rigo et.al. 5 | 6 | """Psyco -- the Python Specializing Compiler. 7 | 8 | Typical usage: add the following lines to your application's main module, 9 | preferably after the other imports: 10 | 11 | try: 12 | import psyco 13 | psyco.full() 14 | except ImportError: 15 | print 'Psyco not installed, the program will just run slower' 16 | """ 17 | ########################################################################### 18 | 19 | 20 | # 21 | # This module is present to make 'psyco' a package and to 22 | # publish the main functions and variables. 23 | # 24 | # More documentation can be found in core.py. 25 | # 26 | 27 | 28 | # Try to import the dynamic-loading _psyco and report errors 29 | try: 30 | import _psyco 31 | except ImportError, e: 32 | extramsg = '' 33 | import sys, imp 34 | try: 35 | file, filename, (suffix, mode, type) = imp.find_module('_psyco', __path__) 36 | except ImportError: 37 | ext = [suffix for suffix, mode, type in imp.get_suffixes() 38 | if type == imp.C_EXTENSION] 39 | if ext: 40 | extramsg = (" (cannot locate the compiled extension '_psyco%s' " 41 | "in the package path '%s')" % (ext[0], '; '.join(__path__))) 42 | else: 43 | extramsg = (" (check that the compiled extension '%s' is for " 44 | "the correct Python version; this is Python %s)" % 45 | (filename, sys.version.split()[0])) 46 | raise ImportError, str(e) + extramsg 47 | 48 | # Publish important data by importing them in the package 49 | from support import __version__, error, warning, _getrealframe, _getemulframe 50 | from support import version_info, __version__ as hexversion 51 | from core import full, profile, background, runonly, stop, cannotcompile 52 | from core import log, bind, unbind, proxy, unproxy, dumpcodebuf 53 | from _psyco import setfilter 54 | from _psyco import compact, compacttype 55 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/classes.py: -------------------------------------------------------------------------------- 1 | ########################################################################### 2 | # 3 | # Psyco class support module. 4 | # Copyright (C) 2001-2002 Armin Rigo et.al. 5 | 6 | """Psyco class support module. 7 | 8 | 'psyco.classes.psyobj' is an alternate Psyco-optimized root for classes. 9 | Any class inheriting from it or using the metaclass '__metaclass__' might 10 | get optimized specifically for Psyco. It is equivalent to call 11 | psyco.bind() on the class object after its creation. 12 | 13 | Importing everything from psyco.classes in a module will import the 14 | '__metaclass__' name, so all classes defined after a 15 | 16 | from psyco.classes import * 17 | 18 | will automatically use the Psyco-optimized metaclass. 19 | """ 20 | ########################################################################### 21 | 22 | __all__ = ['psyobj', 'psymetaclass', '__metaclass__'] 23 | 24 | 25 | from _psyco import compacttype 26 | import core 27 | from types import FunctionType 28 | 29 | class psymetaclass(compacttype): 30 | "Psyco-optimized meta-class. Turns all methods into Psyco proxies." 31 | 32 | def __new__(cls, name, bases, dict): 33 | bindlist = dict.get('__psyco__bind__') 34 | if bindlist is None: 35 | bindlist = [key for key, value in dict.items() 36 | if isinstance(value, FunctionType)] 37 | for attr in bindlist: 38 | dict[attr] = core.proxy(dict[attr]) 39 | return super(psymetaclass, cls).__new__(cls, name, bases, dict) 40 | 41 | psyobj = psymetaclass("psyobj", (), {}) 42 | __metaclass__ = psymetaclass 43 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/logger.py: -------------------------------------------------------------------------------- 1 | ########################################################################### 2 | # 3 | # Psyco logger. 4 | # Copyright (C) 2001-2002 Armin Rigo et.al. 5 | 6 | """Psyco logger. 7 | 8 | See log() in core.py. 9 | """ 10 | ########################################################################### 11 | 12 | 13 | import _psyco 14 | from time import time, localtime, strftime 15 | 16 | 17 | current = None 18 | print_charges = 10 19 | dump_delay = 0.2 20 | dump_last = 0.0 21 | 22 | def write(s, level): 23 | t = time() 24 | f = t-int(t) 25 | try: 26 | current.write("%s.%02d %-*s%s\n" % ( 27 | strftime("%X", localtime(int(t))), 28 | int(f*100.0), 63-level, s, 29 | "%"*level)) 30 | current.flush() 31 | except (OSError, IOError): 32 | pass 33 | 34 | def psycowrite(s): 35 | t = time() 36 | f = t-int(t) 37 | try: 38 | current.write("%s.%02d %-*s%s\n" % ( 39 | strftime("%X", localtime(int(t))), 40 | int(f*100.0), 60, s.strip(), 41 | "% %")) 42 | current.flush() 43 | except (OSError, IOError): 44 | pass 45 | 46 | ##def writelines(lines, level=0): 47 | ## if lines: 48 | ## t = time() 49 | ## f = t-int(t) 50 | ## timedesc = strftime("%x %X", localtime(int(t))) 51 | ## print >> current, "%s.%03d %-*s %s" % ( 52 | ## timedesc, int(f*1000), 53 | ## 50-level, lines[0], 54 | ## "+"*level) 55 | ## timedesc = " " * (len(timedesc)+5) 56 | ## for line in lines[1:]: 57 | ## print >> current, timedesc, line 58 | 59 | def writememory(): 60 | write("memory usage: %d+ kb" % _psyco.memory(), 1) 61 | 62 | def dumpcharges(): 63 | global dump_last 64 | if print_charges: 65 | t = time() 66 | if not (dump_last <= t < dump_last+dump_delay): 67 | if t <= dump_last+1.5*dump_delay: 68 | dump_last += dump_delay 69 | else: 70 | dump_last = t 71 | #write("%s: charges:" % who, 0) 72 | lst = _psyco.stattop(print_charges) 73 | if lst: 74 | f = t-int(t) 75 | lines = ["%s.%02d ______\n" % ( 76 | strftime("%X", localtime(int(t))), 77 | int(f*100.0))] 78 | i = 1 79 | for co, charge in lst: 80 | detail = co.co_filename 81 | if len(detail) > 19: 82 | detail = '...' + detail[-17:] 83 | lines.append(" #%-3d |%4.1f %%| %-26s%20s:%d\n" % 84 | (i, charge*100.0, co.co_name, detail, 85 | co.co_firstlineno)) 86 | i += 1 87 | current.writelines(lines) 88 | current.flush() 89 | 90 | def writefinalstats(): 91 | dumpcharges() 92 | writememory() 93 | writedate("program exit") 94 | 95 | def writedate(msg): 96 | write('%s, %s' % (msg, strftime("%x")), 20) 97 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/COPYING.txt: -------------------------------------------------------------------------------- 1 | Psyco is distributed under the MIT License. 2 | 3 | Copyright (c) 2001-2003 Armin Rigo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/README.txt: -------------------------------------------------------------------------------- 1 | ====================================================================== 2 | Psyco, the Python Specializing Compiler 3 | ====================================================================== 4 | 5 | 6 | VERSION 1.5.2+SVN 7 | ----------------- 8 | 9 | Psyco is a Python extension module which can massively speed up the 10 | execution of any Python code. 11 | 12 | 13 | REQUIREMENTS 14 | ------------ 15 | 16 | Psyco works on almost any version of Python (currently 2.2.2 17 | to 2.5). At present it *requires* a *32-bit* *PC* (i.e. a 18 | 386-compatible processor), but it is OS-independant. 19 | 20 | This program is still and will always be incomplete, but it 21 | has been stable for a long time and can give good results. 22 | 23 | There are no plans to port Psyco to 64-bit architectures. 24 | This would be rather involved. Psyco is only being 25 | maintained, not further developed. The development efforts of 26 | the author are now focused on PyPy, which will include 27 | Psyco-like techniques. (http://codespeak.net/pypy) 28 | 29 | Psyco requires Python >= 2.2.2. Support for older versions 30 | has been dropped after Psyco 1.5.2. 31 | 32 | 33 | QUICK INTRODUCTION 34 | ------------------ 35 | 36 | To install Psyco, do the usual 37 | 38 | python setup.py install 39 | 40 | Manually, you can also put the 'psyco' package in your Python search 41 | path, e.g. by copying the subdirectory 'psyco' into the directory 42 | '/usr/lib/python2.x/site-packages' (default path on Linux). 43 | 44 | Basic usage is very simple: add 45 | 46 | import psyco 47 | psyco.full() 48 | 49 | to the beginning of your main script. For basic introduction see: 50 | 51 | import psyco 52 | help(psyco) 53 | 54 | 55 | DOCUMENTATION AND LATEST VERSIONS 56 | --------------------------------- 57 | 58 | Home page: 59 | 60 | * http://psyco.sourceforge.net 61 | 62 | The current up-to-date documentation is the Ultimate Psyco Guide. 63 | If it was not included in this distribution ("psycoguide.ps" or 64 | "psycoguide/index.html"), see the doc page: 65 | 66 | * http://psyco.sourceforge.net/doc.html 67 | 68 | 69 | DEBUG BUILD 70 | ----------- 71 | 72 | To build a version of Psyco that includes debugging checks and/or 73 | debugging output, see comments in setup.py. 74 | 75 | 76 | ---------- 77 | Armin Rigo. 78 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/compactobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** A "regular" PyObject type with Psyco-optimized attributes ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _COMPACTOBJECT_H 6 | #define _COMPACTOBJECT_H 7 | 8 | 9 | #include "../psyco.h" 10 | #include "../Python/pyver.h" 11 | #include "../vcompiler.h" 12 | 13 | 14 | typedef struct compact_impl_s compact_impl_t; /* private structure */ 15 | 16 | typedef struct { 17 | PyObject_HEAD 18 | char* k_data; /* heap-allocated memory for the attributes */ 19 | compact_impl_t* k_impl; /* description of how the data is encoded */ 20 | } PyCompactObject; 21 | 22 | 23 | EXTERNVAR PyTypeObject PyCompact_Type; 24 | EXTERNVAR compact_impl_t* PyCompact_EmptyImpl; 25 | 26 | #define PyCompact_Check(op) PyObject_TypeCheck(op, &PyCompact_Type) 27 | 28 | 29 | /* EXTERNFN PyObject* PyCompact_New(void); */ 30 | /* EXTERNFN PyObject* PyCompact_GetSlot(PyObject* ko, PyObject* key); */ 31 | /* EXTERNFN PyObject* PyCompact_SetSlot(PyObject* ko, PyObject* key, */ 32 | /* PyObject* value); */ 33 | /* EXTERNFN int PyCompact_Extend(PyObject* ko, compact_impl_t* nimpl); */ 34 | /* EXTERNFN compact_impl_t* PyCompact_ExtendImpl(compact_impl_t* oldimpl, */ 35 | /* PyObject* attr, */ 36 | /* vinfo_t* v_descr); */ 37 | 38 | /*****************************************************************/ 39 | /* Private structures and routines exported for pcompactobject.c */ 40 | 41 | struct compact_impl_s { 42 | PyObject* attrname; /* name of the last attr */ 43 | vinfo_t* vattr; /* storage format of the last attr */ 44 | int datasize; /* total size of the k_data buffer */ 45 | compact_impl_t* extensions; /* chained list of extensions */ 46 | compact_impl_t* next; /* next in chained list */ 47 | compact_impl_t* parent; /* of which this one is an extension */ 48 | }; 49 | 50 | #define K_ROUNDUP(sz) (((sz) + 7) & ~7) 51 | 52 | #define K_INTERN(attr) do { \ 53 | PyString_InternInPlace(&attr); \ 54 | if (attr->ob_type != &PyString_Type || !PyString_CHECK_INTERNED(attr)) \ 55 | Py_FatalError("Psyco failed to intern an attribute name"); \ 56 | } while (0) 57 | 58 | EXTERNFN vinfo_t* vinfo_copy_no_share(vinfo_t* vi); 59 | EXTERNFN bool k_match_vinfo(vinfo_t* vnew, vinfo_t* vexisting); 60 | EXTERNFN compact_impl_t* k_extend_impl(compact_impl_t* oldimpl, PyObject* attr, 61 | vinfo_t* v); 62 | EXTERNFN void k_attribute_range(vinfo_t* v, int* smin, int* smax); 63 | EXTERNFN compact_impl_t* k_duplicate_impl(compact_impl_t* base, 64 | compact_impl_t* first_excluded, 65 | compact_impl_t* last, 66 | int shift_delta); 67 | 68 | #endif /* _COMPACTOBJECT_H */ 69 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pboolobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of boolobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_BOOLOBJECT_H 6 | #define _PSY_BOOLOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | #if BOOLEAN_TYPE /* Booleans were introduced in Python 2.3 */ 13 | 14 | 15 | #define BOOL_ob_ival DEF_FIELD(PyBoolObject, long, ob_ival, OB_type) 16 | #define iBOOL_OB_IVAL FIELD_INDEX(BOOL_ob_ival) 17 | #define BOOL_TOTAL FIELDS_TOTAL(BOOL_ob_ival) 18 | 19 | 20 | #define PsycoBool_Check(tp) PyType_TypeCheck(tp, &PyBool_Type) 21 | 22 | 23 | /***************************************************************/ 24 | /*** Virtual-time object builder ***/ 25 | 26 | /* not-yet-computed booleans */ 27 | EXTERNVAR source_virtual_t psyco_computed_bool; 28 | 29 | /* !! consumes a reference to vlong. PsycoBool_FromLong() does not. */ 30 | PSY_INLINE vinfo_t* PsycoBool_FROM_LONG(vinfo_t* vlong) 31 | { 32 | vinfo_t* result = vinfo_new(VirtualTime_New(&psyco_computed_bool)); 33 | result->array = array_new(BOOL_TOTAL); 34 | result->array->items[iOB_TYPE] = 35 | vinfo_new(CompileTime_New((long)(&PyBool_Type))); 36 | result->array->items[iBOOL_OB_IVAL] = vlong; assert_nonneg(vlong); 37 | return result; 38 | } 39 | PSY_INLINE vinfo_t* PsycoBool_FromLong(vinfo_t* vlong) 40 | { 41 | vinfo_incref(vlong); 42 | return PsycoBool_FROM_LONG(vlong); 43 | } 44 | 45 | 46 | #else /* !BOOLEAN_TYPE */ 47 | /* define the booleans as synonims for integers */ 48 | # define PsycoBool_FROM_LONG(v) PsycoInt_FROM_LONG(v) 49 | # define PsycoBool_FromLong(v) PsycoInt_FromLong(v) 50 | #endif /* BOOLEAN_TYPE */ 51 | 52 | /* utility */ 53 | #define PsycoBool_FromCondition(po, cc) \ 54 | PsycoBool_FROM_LONG(psyco_vinfo_condition(po, cc)) 55 | 56 | #endif /* _PSY_INTOBJECT_H */ 57 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pclassobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of classobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_CLASSOBJECT_H 6 | #define _PSY_CLASSOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | /* Instance methods */ 14 | #define METHOD_im_func DEF_FIELD(PyMethodObject, PyObject*, im_func, OB_type) 15 | #define METHOD_im_self DEF_FIELD(PyMethodObject, PyObject*, im_self, \ 16 | METHOD_im_func) 17 | #define METHOD_im_class DEF_FIELD(PyMethodObject, PyObject*, im_class, \ 18 | METHOD_im_self) 19 | #define iMETHOD_IM_FUNC FIELD_INDEX(METHOD_im_func) 20 | #define iMETHOD_IM_SELF FIELD_INDEX(METHOD_im_self) 21 | #define iMETHOD_IM_CLASS FIELD_INDEX(METHOD_im_class) 22 | #define METHOD_TOTAL FIELDS_TOTAL(METHOD_im_class) 23 | 24 | 25 | EXTERNFN vinfo_t* pinstancemethod_call(PsycoObject* po, vinfo_t* methobj, 26 | vinfo_t* arg, vinfo_t* kw); 27 | 28 | 29 | /***************************************************************/ 30 | /*** Virtual-time object builder ***/ 31 | 32 | /* not-yet-computed instance method objects. Usually not computed at all, 33 | but if it needs be, will call PyMethod_New(). */ 34 | EXTERNVAR source_virtual_t psyco_computed_method; 35 | 36 | EXTERNFN 37 | vinfo_t* PsycoMethod_New(PyObject* func, vinfo_t* self, PyObject* cls); 38 | 39 | 40 | #endif /* _PSY_CLASSOBJECT_H */ 41 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pcompactobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Meta-version of compactobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_COMPACTOBJECT_H 6 | #define _PSY_COMPACTOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | /***************************************************************/ 14 | /* virtual compact objects. */ 15 | /*EXTERNFN vinfo_t* PsycoCompact_New(PsycoObject* po); 16 | XXX to do */ 17 | 18 | #endif /* _PSY_COMPACTOBJECT_H */ 19 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pdescrobject.c: -------------------------------------------------------------------------------- 1 | #include "../psyfunc.h" 2 | #include "pdescrobject.h" 3 | #include "pstructmember.h" 4 | #include "pmethodobject.h" 5 | 6 | 7 | static vinfo_t* pmember_get(PsycoObject* po, PyMemberDescrObject* descr, 8 | vinfo_t* obj, PyTypeObject *type) 9 | { 10 | /* a meta-implementation for member_get() of descrobject.c. 11 | Note that not all parameters are 'vinfo_t*'; only 'obj' 12 | is. This is because PsycoObject_GenericGetAttr() gives 13 | immediate values for the other two arguments. */ 14 | 15 | /* XXX We assume that 'obj' is a valid instance of 'type'. */ 16 | return PsycoMember_GetOne(po, obj, descr->d_member); 17 | } 18 | 19 | static vinfo_t* pmethod_get(PsycoObject* po, PyMethodDescrObject* descr, 20 | vinfo_t* obj, PyTypeObject *type) 21 | { 22 | /* a meta-implementation for method_get() of descrobject.c. 23 | Same remarks as for pmember_get(). */ 24 | return PsycoCFunction_New(po, descr->d_method, obj); 25 | } 26 | 27 | 28 | INITIALIZATIONFN 29 | void psy_descrobject_init(void) 30 | { 31 | PyObject* dummy; 32 | PyTypeObject* PyMemberDescr_Type; 33 | PyTypeObject* PyMethodDescr_Type; 34 | PyMemberDef dummydef; 35 | PyMethodDef dummydef2; 36 | 37 | /* Member descriptors */ 38 | /* any better way to get a pointer to PyMemberDescr_Type? */ 39 | memset(&dummydef, 0, sizeof(dummydef)); 40 | dummydef.name = "dummy"; 41 | dummy = PyDescr_NewMember(&PsycoFunction_Type, &dummydef); 42 | PyMemberDescr_Type = dummy->ob_type; 43 | Py_DECREF(dummy); 44 | 45 | Psyco_DefineMeta(PyMemberDescr_Type->tp_descr_get, 46 | pmember_get); 47 | 48 | /* C Method descriptors */ 49 | /* any better way to get a pointer to PyMethodDescr_Type? */ 50 | memset(&dummydef2, 0, sizeof(dummydef2)); 51 | dummydef2.ml_name = "dummy"; 52 | dummy = PyDescr_NewMethod(&PsycoFunction_Type, &dummydef2); 53 | PyMethodDescr_Type = dummy->ob_type; 54 | Py_DECREF(dummy); 55 | 56 | Psyco_DefineMeta(PyMethodDescr_Type->tp_descr_get, 57 | pmethod_get); 58 | } 59 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pdescrobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of descrobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_DESCROBJECT_H 6 | #define _PSY_DESCROBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | #endif /* _PSY_DESCROBJECT_H */ 14 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pdictobject.c: -------------------------------------------------------------------------------- 1 | #include "pdictobject.h" 2 | 3 | 4 | #define DICT_ma_used FMUT(DEF_FIELD(PyDictObject, int, ma_used, OB_type)) 5 | #define iDICT_MA_USED FIELD_INDEX(DICT_ma_used) 6 | 7 | DEFINEFN 8 | vinfo_t* PsycoDict_New(PsycoObject* po) 9 | { 10 | /* XXX no virtual dicts yet */ 11 | vinfo_t* v = psyco_generic_call(po, PyDict_New, 12 | CfReturnRef|CfPyErrIfNull, ""); 13 | if (v == NULL) 14 | return NULL; 15 | 16 | /* the result is a dict */ 17 | Psyco_AssertType(po, v, &PyDict_Type); 18 | return v; 19 | } 20 | 21 | DEFINEFN 22 | vinfo_t* PsycoDict_Copy(PsycoObject* po, vinfo_t* orig) 23 | { 24 | vinfo_t* v = psyco_generic_call(po, PyDict_Copy, 25 | CfReturnRef|CfPyErrIfNull, 26 | "v", orig); 27 | if (v == NULL) 28 | return NULL; 29 | 30 | /* the result is a dict */ 31 | Psyco_AssertType(po, v, &PyDict_Type); 32 | return v; 33 | } 34 | 35 | DEFINEFN 36 | bool PsycoDict_SetItem(PsycoObject* po, vinfo_t* vdict, 37 | PyObject* key, vinfo_t* vvalue) 38 | { 39 | return psyco_generic_call(po, PyDict_SetItem, 40 | CfNoReturnValue|CfPyErrIfNeg, 41 | "vlv", vdict, (long) key, vvalue) != NULL; 42 | } 43 | 44 | static vinfo_t* psyco_dict_length(PsycoObject* po, vinfo_t* vi) 45 | { 46 | return psyco_get_field(po, vi, DICT_ma_used); 47 | } 48 | 49 | 50 | INITIALIZATIONFN 51 | void psy_dictobject_init(void) 52 | { 53 | PyMappingMethods *m = PyDict_Type.tp_as_mapping; 54 | Psyco_DefineMeta(m->mp_length, psyco_dict_length); 55 | } 56 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pdictobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of dictobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_DICTOBJECT_H 6 | #define _PSY_DICTOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | EXTERNFN vinfo_t* PsycoDict_New(PsycoObject* po); 14 | EXTERNFN vinfo_t* PsycoDict_Copy(PsycoObject* po, vinfo_t* orig); 15 | EXTERNFN bool PsycoDict_SetItem(PsycoObject* po, vinfo_t* vdict, 16 | PyObject* key, vinfo_t* vvalue); 17 | 18 | 19 | #endif /* _PSY_LISTOBJECT_H */ 20 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pfuncobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of funcobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_FUNCOBJECT_H 6 | #define _PSY_FUNCOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | #define FUNC_code DEF_FIELD(PyFunctionObject, PyObject*, func_code, OB_type) 14 | #define FUNC_globals DEF_FIELD(PyFunctionObject, PyObject*, func_globals, \ 15 | FUNC_code) 16 | #define FUNC_defaults DEF_FIELD(PyFunctionObject, PyObject*, func_defaults, \ 17 | FUNC_globals) 18 | #define iFUNC_CODE FIELD_INDEX(FUNC_code) 19 | #define iFUNC_GLOBALS FIELD_INDEX(FUNC_globals) 20 | #define iFUNC_DEFAULTS FIELD_INDEX(FUNC_defaults) 21 | #define FUNC_TOTAL FIELDS_TOTAL(FUNC_defaults) 22 | 23 | 24 | EXTERNFN vinfo_t* pfunction_call(PsycoObject* po, vinfo_t* func, 25 | vinfo_t* arg, vinfo_t* kw); 26 | EXTERNFN vinfo_t* pfunction_simple_call(PsycoObject* po, PyObject* f, 27 | vinfo_t* arg, bool allow_inline); 28 | 29 | 30 | /***************************************************************/ 31 | /* virtual functions. */ 32 | /* 'fdefaults' may be NULL. */ 33 | EXTERNFN vinfo_t* PsycoFunction_New(PsycoObject* po, vinfo_t* fcode, 34 | vinfo_t* fglobals, vinfo_t* fdefaults); 35 | 36 | 37 | #endif /* _PSY_FUNCOBJECT_H */ 38 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pintobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of intobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_INTOBJECT_H 6 | #define _PSY_INTOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | #include "pboolobject.h" 12 | 13 | 14 | #define INT_ob_ival DEF_FIELD(PyIntObject, long, ob_ival, OB_type) 15 | #define iINT_OB_IVAL FIELD_INDEX(INT_ob_ival) 16 | #define INT_TOTAL FIELDS_TOTAL(INT_ob_ival) 17 | 18 | 19 | #define PsycoInt_Check(tp) PyType_TypeCheck(tp, &PyInt_Type) 20 | 21 | 22 | /***************************************************************/ 23 | /*** Virtual-time object builder ***/ 24 | 25 | /* not-yet-computed integers; it will call PyInt_FromLong */ 26 | EXTERNVAR source_virtual_t psyco_computed_int; 27 | 28 | /* !! consumes a reference to vlong. PsycoInt_FromLong() does not. */ 29 | PSY_INLINE vinfo_t* PsycoInt_FROM_LONG(vinfo_t* vlong) 30 | { 31 | vinfo_t* result = vinfo_new(VirtualTime_New(&psyco_computed_int)); 32 | result->array = array_new(INT_TOTAL); 33 | result->array->items[iOB_TYPE] = 34 | vinfo_new(CompileTime_New((long)(&PyInt_Type))); 35 | result->array->items[iINT_OB_IVAL] = vlong; 36 | return result; 37 | } 38 | PSY_INLINE vinfo_t* PsycoInt_FromLong(vinfo_t* vlong) 39 | { 40 | vinfo_incref(vlong); 41 | return PsycoInt_FROM_LONG(vlong); 42 | } 43 | 44 | PSY_INLINE vinfo_t* PsycoInt_AS_LONG(PsycoObject* po, vinfo_t* v) 45 | { /* no type check; does not return a new reference. */ 46 | return psyco_get_const(po, v, INT_ob_ival); 47 | } 48 | 49 | /* return a new ref */ 50 | EXTERNFN vinfo_t* PsycoInt_AsLong(PsycoObject* po, vinfo_t* v); 51 | 52 | 53 | PSY_INLINE vinfo_t* PsycoIntInt_RichCompare(PsycoObject* po, vinfo_t* v, 54 | vinfo_t* w, int op) 55 | { /* only for two integer objects */ 56 | vinfo_t* a; 57 | vinfo_t* b; 58 | condition_code_t cc; 59 | a = PsycoInt_AS_LONG(po, v); 60 | if (a == NULL) return NULL; 61 | b = PsycoInt_AS_LONG(po, w); 62 | if (b == NULL) return NULL; 63 | cc = integer_cmp(po, a, b, op); 64 | if (cc == CC_ERROR) return NULL; 65 | return PsycoBool_FromCondition(po, cc); 66 | } 67 | 68 | 69 | EXTERNFN /* internal, for pboolobject.c */ 70 | vinfo_t* pint_base2op(PsycoObject* po, vinfo_t* v, vinfo_t* w, 71 | vinfo_t*(*op)(PsycoObject*,vinfo_t*,vinfo_t*)); 72 | 73 | 74 | #endif /* _PSY_INTOBJECT_H */ 75 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/piterobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of iterobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_ITEROBJECT_H 6 | #define _PSY_ITEROBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | /* this structure not exported by iterobject.h */ 14 | typedef struct { 15 | PyObject_HEAD 16 | long it_index; 17 | PyObject *it_seq; 18 | } seqiterobject; 19 | 20 | #define SEQITER_it_index FMUT(DEF_FIELD(seqiterobject, long, it_index, OB_type)) 21 | #define SEQITER_it_seq DEF_FIELD(seqiterobject, PyObject*, it_seq, \ 22 | SEQITER_it_index) 23 | #define iSEQITER_IT_INDEX FIELD_INDEX(SEQITER_it_index) 24 | #define iSEQITER_IT_SEQ FIELD_INDEX(SEQITER_it_seq) 25 | #define SEQITER_TOTAL FIELDS_TOTAL(SEQITER_it_seq) 26 | 27 | 28 | /*********************************************************************/ 29 | /* Virtual sequence iterators. Created if needed by PySeqIter_New(). */ 30 | EXTERNVAR source_virtual_t psyco_computed_seqiter; 31 | 32 | /* !! consumes a ref on 'seq' */ 33 | EXTERNFN vinfo_t* PsycoSeqIter_NEW(PsycoObject* po, vinfo_t* seq); 34 | 35 | PSY_INLINE vinfo_t* PsycoSeqIter_New(PsycoObject* po, vinfo_t* seq) 36 | { 37 | vinfo_incref(seq); 38 | return PsycoSeqIter_NEW(po, seq); 39 | } 40 | 41 | #endif /* _PSY_ITEROBJECT_H */ 42 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/plistobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of listobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_LISTOBJECT_H 6 | #define _PSY_LISTOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | #define LIST_ob_item FMUT(DEF_FIELD(PyListObject, PyObject**, ob_item, \ 14 | VAR_size)) 15 | #define LIST_TOTAL FIELDS_TOTAL(LIST_ob_item) 16 | #define VLIST_ITEMS LIST_TOTAL 17 | #define LIST_itemsarray FMUT(DEF_ARRAY(PyObject*, 0)) 18 | 19 | 20 | /* Warning: only for very short lists! Each new length could 21 | force a new copy of the whole code to be emitted... */ 22 | #define VLIST_LENGTH_MAX 3 23 | 24 | 25 | EXTERNFN vinfo_t* PsycoList_New(PsycoObject* po, int size, vinfo_t** source); 26 | EXTERNFN vinfo_t* PsycoList_SingletonNew(vinfo_t* vitem); 27 | EXTERNFN bool PsycoList_Append(PsycoObject* po, vinfo_t* v, vinfo_t* vitem); 28 | /*EXTERNVAR vinfo_t* psyco_empty_list;*/ 29 | 30 | /* get the virtual array of items in the list, 31 | returning the length of the list or -1 if it fails (items not known). 32 | The items are then found in list->array->items[VLIST+i]. 33 | Never sets a PycException. */ 34 | EXTERNFN int PsycoList_Load(vinfo_t* list); 35 | 36 | 37 | /* for pstringobject.c */ 38 | EXTERNFN vinfo_t* psyco_plist_concat(PsycoObject* po, vinfo_t* a, vinfo_t* b); 39 | 40 | /* for piterobject.c */ 41 | EXTERNFN vinfo_t* plist_item(PsycoObject* po, vinfo_t* a, vinfo_t* i); 42 | 43 | 44 | #endif /* _PSY_LISTOBJECT_H */ 45 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/plongobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of longobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_LONGOBJECT_H 6 | #define _PSY_LONGOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | #define PsycoLong_Check(tp) PyType_TypeCheck(tp, &PyLong_Type) 14 | 15 | 16 | EXTERNFN vinfo_t* PsycoLong_AsLong(PsycoObject* po, vinfo_t* v); 17 | EXTERNFN bool PsycoLong_AsDouble(PsycoObject* po, vinfo_t* v, vinfo_t** vd1, vinfo_t** vd2); 18 | 19 | #endif /* _PSY_LONGOBJECT_H */ 20 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pmethodobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of methodobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_METHODOBJECT_H 6 | #define _PSY_METHODOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | #define CFUNC_m_ml DEF_FIELD(PyCFunctionObject, PyMethodDef*, m_ml, OB_type) 14 | #define CFUNC_m_self DEF_FIELD(PyCFunctionObject, PyObject*, m_self, CFUNC_m_ml) 15 | #define iCFUNC_M_ML FIELD_INDEX(CFUNC_m_ml) 16 | #define iCFUNC_M_SELF FIELD_INDEX(CFUNC_m_self) 17 | #define CFUNC_TOTAL FIELDS_TOTAL(CFUNC_m_self) 18 | 19 | 20 | EXTERNFN vinfo_t* PsycoCFunction_Call(PsycoObject* po, vinfo_t* func, 21 | vinfo_t* tuple, vinfo_t* kw); 22 | 23 | 24 | /***************************************************************/ 25 | /*** Virtual-time object builder ***/ 26 | 27 | /* not-yet-computed C method objects, with a m_ml and m_self field. 28 | Usually not computed at all, but if it needs be, will call 29 | PyCFunction_New(). */ 30 | EXTERNVAR source_virtual_t psyco_computed_cfunction; 31 | 32 | PSY_INLINE vinfo_t* PsycoCFunction_New(PsycoObject* po, PyMethodDef* ml, 33 | vinfo_t* self) 34 | { 35 | vinfo_t* result = vinfo_new(VirtualTime_New(&psyco_computed_cfunction)); 36 | result->array = array_new(CFUNC_TOTAL); 37 | result->array->items[iOB_TYPE] = 38 | vinfo_new(CompileTime_New((long)(&PyCFunction_Type))); 39 | result->array->items[iCFUNC_M_ML] = 40 | vinfo_new(CompileTime_New((long) ml)); 41 | vinfo_incref(self); 42 | result->array->items[iCFUNC_M_SELF] = self; 43 | return result; 44 | } 45 | 46 | 47 | #endif /* _PSY_METHODOBJECT_H */ 48 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/prangeobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of rangeobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_RANGEOBJECT_H 6 | #define _PSY_RANGEOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | #include "plistobject.h" 12 | 13 | 14 | /* currently step == 1 only */ 15 | /* The following functions *consume* a reference to start and len ! */ 16 | 17 | /* for xrange() */ 18 | EXTERNFN vinfo_t* PsycoXRange_NEW(PsycoObject* po, vinfo_t* start, vinfo_t* len); 19 | /* for range() */ 20 | EXTERNFN vinfo_t* PsycoListRange_NEW(PsycoObject* po, vinfo_t* start, vinfo_t* len); 21 | 22 | 23 | /***************************************************************/ 24 | /*** Virtual list range objects (not for xrange) ***/ 25 | 26 | #define RANGE_LEN iVAR_SIZE /* for virtual range() only */ 27 | #define RANGE_START LIST_TOTAL /* " */ 28 | /*#define RANGE_STEP (RANGE_START+1) * " */ 29 | #define RANGE_TOTAL /*(RANGE_STEP+1)*/ (RANGE_START+1) 30 | /* XXX no support for steps currently. Needs implementation of division to 31 | figure out the length. */ 32 | 33 | EXTERNVAR source_virtual_t psyco_computed_listrange; 34 | 35 | 36 | #endif /* _PSY_RANGEOBJECT_H */ 37 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pstringobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of stringobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_STRINGOBJECT_H 6 | #define _PSY_STRINGOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | #define USE_CATSTR 0 /*trying to use only bufstring virtual strings instead*/ 13 | #define USE_BUFSTR 1 14 | 15 | 16 | /* various ways to access the actual character data */ 17 | #define STR_sval UNSIGNED_ARRAY(char, offsetof(PyStringObject, ob_sval)) 18 | #define STR_sval2 UNSIGNED_ARRAY(short, offsetof(PyStringObject, ob_sval)) 19 | #define STR_sval4 UNSIGNED_ARRAY(long, offsetof(PyStringObject, ob_sval)) 20 | 21 | 22 | /* all flavors of virtual strings */ 23 | #define VIRTUALSTR_FIRST FIELDS_TOTAL(FIX_size) 24 | 25 | /* virtual one-character strings */ 26 | #define CHARACTER_CHAR VIRTUALSTR_FIRST 27 | #define CHARACTER_TOTAL (CHARACTER_CHAR+1) 28 | 29 | /* virtual string slices */ 30 | #define STRSLICE_SOURCE VIRTUALSTR_FIRST 31 | #define STRSLICE_START (STRSLICE_SOURCE+1) 32 | #define STRSLICE_TOTAL (STRSLICE_START+1) 33 | 34 | #if USE_CATSTR 35 | /* virtual string concatenations */ 36 | #define CATSTR_LIST VIRTUALSTR_FIRST 37 | #define CATSTR_TOTAL (CATSTR_LIST+1) 38 | #endif 39 | 40 | #if USE_BUFSTR 41 | /* virtual overallocated-buffer concatenations */ 42 | #define BUFSTR_BUFOBJ VIRTUALSTR_FIRST 43 | #define BUFSTR_TOTAL (BUFSTR_BUFOBJ+1) 44 | #endif 45 | 46 | 47 | #define PsycoString_Check(tp) PyType_TypeCheck(tp, &PyString_Type) 48 | #ifdef Py_USING_UNICODE 49 | # define PsycoUnicode_Check(tp) PyType_TypeCheck(tp, &PyUnicode_Type) 50 | #else 51 | # define PsycoUnicode_Check(tp) 0 52 | #endif 53 | 54 | 55 | PSY_INLINE vinfo_t* PsycoString_AS_STRING(PsycoObject* po, vinfo_t* v) 56 | { /* no type check */ 57 | return integer_add_i(po, v, offsetof(PyStringObject, ob_sval), false); 58 | } 59 | PSY_INLINE vinfo_t* PsycoString_GET_SIZE(PsycoObject* po, vinfo_t* v) 60 | { /* no type check */ 61 | return psyco_get_const(po, v, FIX_size); 62 | } 63 | 64 | 65 | EXTERNFN vinfo_t* PsycoCharacter_New(vinfo_t* chrval); 66 | EXTERNFN bool PsycoCharacter_Ord(PsycoObject* po, vinfo_t* v, vinfo_t** vord); 67 | 68 | 69 | #endif /* _PSY_STRINGOBJECT_H */ 70 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/pstructmember.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of structmember.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_STRUCTMEMBER_H 6 | #define _PSY_STRUCTMEMBER_H 7 | 8 | #include "../Python/pycompiler.h" 9 | #include "pobject.h" 10 | 11 | 12 | EXTERNFN 13 | vinfo_t* PsycoMember_GetOne(PsycoObject* po, vinfo_t* addr, PyMemberDef* l); 14 | 15 | 16 | #endif /* _PSY_STRUCTMEMBER_H */ 17 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/ptupleobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of tupleobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_TUPLEOBJECT_H 6 | #define _PSY_TUPLEOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | #define TUPLE_ob_item FARRAY(DEF_FIELD(PyTupleObject, PyObject*, ob_item, \ 14 | FIX_size)) 15 | #define iTUPLE_OB_ITEM FIELD_INDEX(TUPLE_ob_item) 16 | 17 | /* The following macro reads an item from a Psyco tuple without any 18 | checks. Be sure the item has already been loaded in the array of 19 | the vinfo_t. This should only be used after a successful call to 20 | PsycoTuple_Load(). */ 21 | #define PsycoTuple_GET_ITEM(vtuple, index) \ 22 | ((vtuple)->array->items[iTUPLE_OB_ITEM + (index)]) 23 | 24 | 25 | /***************************************************************/ 26 | /* virtual tuples. 27 | If 'source' is not NULL it gives the content of the tuple. 28 | If 'source' is NULL you have to initialize it yourself. */ 29 | EXTERNFN vinfo_t* PsycoTuple_New(int count, vinfo_t** source); 30 | 31 | /* get the (possibly virtual) array of items in the tuple, 32 | returning the length of the tuple or -1 if it fails (items not known). 33 | The items are then found in PsycoTuple_GET_ITEM(tuple, i). 34 | Never sets a PycException. */ 35 | EXTERNFN int PsycoTuple_Load(vinfo_t* tuple); 36 | 37 | EXTERNFN vinfo_t* PsycoTuple_Concat(PsycoObject* po, vinfo_t* v1, vinfo_t* v2); 38 | 39 | 40 | #endif /* _PSY_TUPLEOBJECT_H */ 41 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Objects/ptypeobject.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco equivalent of typeobject.h ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_TYPEOBJECT_H 6 | #define _PSY_TYPEOBJECT_H 7 | 8 | 9 | #include "pobject.h" 10 | #include "pabstract.h" 11 | 12 | 13 | EXTERNFN vinfo_t* psyco_pobject_new(PsycoObject* po, PyTypeObject* type, 14 | vinfo_t* varg, vinfo_t* vkw); 15 | 16 | 17 | #endif /* _PSY_TYPEOBJECT_H */ 18 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Python/pbltinmodule.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** interface to bltinmodule.c ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSY_BLTINMODULE_H 6 | #define _PSY_BLTINMODULE_H 7 | 8 | /* empty */ 9 | 10 | #endif /* _PSY_BLTINMODULE_H */ 11 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/Python/pycinternal.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Includes Python internal headers ***/ 3 | /***************************************************************/ 4 | 5 | 6 | #ifndef _PYCINTERNAL_H 7 | #define _PYCINTERNAL_H 8 | 9 | #include 10 | 11 | 12 | /* Post-2.2 versions of Python introduced the following more explicit names. 13 | XXX We should map the new names to the old ones if the new names do not 14 | XXX exist but how can we detect if this is needed? 15 | XXX Hacked by completely overriding the enum values with #defines. */ 16 | 17 | #define PyCmp_IN 6 18 | #define PyCmp_NOT_IN 7 19 | #define PyCmp_IS 8 20 | #define PyCmp_IS_NOT 9 21 | #define PyCmp_EXC_MATCH 10 22 | 23 | 24 | #endif /* _PYCINTERNAL_H */ 25 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/alarm.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** General-purpose alarm module ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _ALARM_H 6 | #define _ALARM_H 7 | 8 | 9 | #include "psyco.h" 10 | 11 | 12 | #define ALARM_FUNCTIONS {"alarm", psyco_new_alarm, METH_VARARGS} 13 | 14 | EXTERNFN PyObject* psyco_new_alarm(PyObject* dummy, PyObject* args); 15 | 16 | 17 | #endif /* _ALARM_H */ 18 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/cstruct.c: -------------------------------------------------------------------------------- 1 | #include "cstruct.h" 2 | 3 | 4 | DEFINEFN 5 | PyObject* PyCStruct_New(size_t size, destructor d) 6 | { 7 | cstruct_header_t* cs; 8 | cs = (cstruct_header_t*) PyObject_Malloc(size); 9 | if (cs == NULL) 10 | OUT_OF_MEMORY(); 11 | PyObject_INIT(cs, &PyCStruct_Type); 12 | cs->cs_destructor = d; 13 | cs->cs_key = NULL; 14 | return (PyObject*) cs; 15 | } 16 | 17 | static void cstruct_dealloc(cstruct_header_t* cs) 18 | { 19 | if (cs->cs_destructor != NULL) 20 | cs->cs_destructor((PyObject*) cs); 21 | Py_XDECREF(cs->cs_key); 22 | PyObject_Del((PyObject*) cs); 23 | } 24 | 25 | static long cstruct_hash(cstruct_header_t* cs) 26 | { 27 | /* loosing high bits is fine. This can't be -1 */ 28 | if (cs->cs_key == NULL) 29 | return (long)cs; 30 | else 31 | return (long)cs->cs_key; 32 | } 33 | 34 | static PyObject* cstruct_richcmp(cstruct_header_t* o1, cstruct_header_t* o2, 35 | int op) 36 | { 37 | int c; 38 | PyObject* result; 39 | char* k1 = o1->cs_key ? (char*) o1->cs_key : (char*) o1; 40 | char* k2 = o2->cs_key ? (char*) o2->cs_key : (char*) o2; 41 | switch (op) { 42 | case Py_EQ: c = k1 == k2; break; 43 | case Py_NE: c = k1 != k2; break; 44 | case Py_LT: c = k1 < k2; break; 45 | case Py_LE: c = k1 <= k2; break; 46 | case Py_GT: c = k1 > k2; break; 47 | case Py_GE: c = k1 >= k2; break; 48 | default: 49 | Py_INCREF(Py_NotImplemented); 50 | return Py_NotImplemented; 51 | } 52 | result = c ? Py_True : Py_False; 53 | Py_INCREF(result); 54 | return result; 55 | } 56 | 57 | 58 | DEFINEVAR 59 | PyTypeObject PyCStruct_Type = { 60 | PyObject_HEAD_INIT(NULL) 61 | 0, /*ob_size*/ 62 | "CStruct", /*tp_name*/ 63 | sizeof(cstruct_header_t) /* + ??? */, /*tp_basicsize*/ 64 | 0, /*tp_itemsize*/ 65 | /* methods */ 66 | (destructor)cstruct_dealloc, /*tp_dealloc*/ 67 | 0, /*tp_print*/ 68 | 0, /*tp_getattr*/ 69 | 0, /*tp_setattr*/ 70 | 0, /*tp_compare*/ 71 | 0, /*tp_repr*/ 72 | 0, /*tp_as_number*/ 73 | 0, /*tp_as_sequence*/ 74 | 0, /*tp_as_mapping*/ 75 | (hashfunc)cstruct_hash, /*tp_hash*/ 76 | 0, /*tp_call*/ 77 | 0, /*tp_str*/ 78 | 0, /*tp_getattro*/ 79 | 0, /*tp_setattro*/ 80 | 0, /*tp_as_buffer*/ 81 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ 82 | 0, /*tp_doc*/ 83 | 0, /*tp_traverse*/ 84 | 0, /*tp_clear*/ 85 | (richcmpfunc)cstruct_richcmp, /*tp_richcompare*/ 86 | }; 87 | 88 | 89 | INITIALIZATIONFN 90 | void psyco_cstruct_init(void) 91 | { 92 | PyCStruct_Type.ob_type = &PyType_Type; 93 | } 94 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/cstruct.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Turning general-purpose C structures into Python objects ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _CSTRUCT_H 6 | #define _CSTRUCT_H 7 | 8 | 9 | #include "psyco.h" 10 | 11 | 12 | #define PyCStruct_HEAD \ 13 | PyObject_HEAD \ 14 | destructor cs_destructor; \ 15 | PyObject* cs_key; 16 | 17 | typedef struct { /* internal */ 18 | PyCStruct_HEAD 19 | } cstruct_header_t; 20 | 21 | 22 | EXTERNVAR PyTypeObject PyCStruct_Type; 23 | 24 | #define PyCStruct_Check(op) PyObject_TypeCheck(op, &PyCStruct_Type) 25 | 26 | EXTERNFN PyObject* PyCStruct_New(size_t size, destructor d); 27 | #define PyCStruct_NEW(TYPE, d) \ 28 | ((TYPE*) PyCStruct_New(sizeof(TYPE), (destructor)(d))) 29 | 30 | /* lookup in the given dict for the item whose key is a CStruct with 31 | the given key as cs_key */ 32 | PSY_INLINE PyObject* PyCStruct_DictGet(PyObject* dict, PyObject* key) 33 | { 34 | cstruct_header_t sample; 35 | sample.ob_type = &PyCStruct_Type; 36 | sample.ob_refcnt = 1; 37 | sample.cs_key = key; 38 | return PyDict_GetItem(dict, (PyObject*) &sample); 39 | } 40 | 41 | 42 | #endif /* _CSTRUCT_H */ 43 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/depend.py: -------------------------------------------------------------------------------- 1 | import os, sys, files 2 | from mkincl import * 3 | 4 | GCC = '/usr/bin/gcc' 5 | 6 | processor = sys.argv[1] 7 | 8 | 9 | g = open('dyn-Makefile', 'w') 10 | print >> g, "# automatically generated by depend.py" 11 | print >> g 12 | print >> g, "O_FILES =", 13 | 14 | basenames = [] 15 | for f in files.SRC: 16 | assert f.filename.endswith('.c') 17 | basenames.append(f.filename[:-2]) 18 | for f in files.PROCESSOR_SRC[processor]: 19 | assert f.filename.endswith('.c') 20 | basenames.append(processor + '/' + f.filename[:-2]) 21 | 22 | for fn in basenames: 23 | print >> g, fn+'.o', 24 | print >> g 25 | print >> g 26 | 27 | for fn in basenames: 28 | print fn 29 | h = os.popen("%s -I%s %s -M -Wundef %s.c" % (GCC, processor, 30 | INCLUDE_STR, fn), 'r') 31 | data = h.read() 32 | h.close() 33 | data = data.replace('\\\n', ' ') 34 | data = data[data.index(':')+1:] 35 | data = data.strip().split() 36 | data = map(os.path.normpath, data) 37 | found = {} 38 | print >> g, '%s.o:' % fn, 39 | for f1 in data: 40 | if f1 not in found and not f1.startswith('/'): 41 | print >> g, f1, 42 | found[f1] = 1 43 | print >> g 44 | print >> g 45 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/i386/iinitialize.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Automatically generated support file ***/ 3 | /***************************************************************/ 4 | 5 | /* This file is automatically generated by 'files.py'. 6 | DO NOT MODIFY. Changes will be overwritten ! */ 7 | 8 | 9 | /* internal part for psyco.c */ 10 | #if ALL_STATIC 11 | # include "iprocessor.c" 12 | # include "idispatcher.c" 13 | # include "iencoding.c" 14 | # include "ipyencoding.c" 15 | #else /* if !ALL_STATIC */ 16 | EXTERNFN void psyco_processor_init(void); /* iprocessor.c */ 17 | #endif /* !ALL_STATIC */ 18 | 19 | PSY_INLINE void initialize_processor_files(void) { 20 | psyco_processor_init(); /* iprocessor.c */ 21 | } 22 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/iinitialize.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Automatically generated support file ***/ 3 | /***************************************************************/ 4 | 5 | /* This file is automatically generated by 'files.py'. 6 | DO NOT MODIFY. Changes will be overwritten ! */ 7 | 8 | 9 | /* internal part for psyco.c */ 10 | #if ALL_STATIC 11 | # include "iprocessor.c" 12 | # include "idispatcher.c" 13 | # include "iencoding.c" 14 | # include "ipyencoding.c" 15 | # include "ivm-insns.c" 16 | #else /* if !ALL_STATIC */ 17 | #endif /* !ALL_STATIC */ 18 | 19 | PSY_INLINE void initialize_processor_files(void) { 20 | } 21 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/ipyencoding.c: -------------------------------------------------------------------------------- 1 | #include "ipyencoding.h" 2 | #include "../pycodegen.h" 3 | 4 | 5 | DEFINEFN 6 | void decref_create_new_ref(PsycoObject* po, vinfo_t* w) 7 | { 8 | psyco_incref_nv(po, w); 9 | } 10 | 11 | DEFINEFN 12 | bool decref_create_new_lastref(PsycoObject* po, vinfo_t* w) 13 | { 14 | bool could_eat = eat_reference(w); 15 | if (!could_eat) { 16 | /* in this case we must Py_INCREF() the object */ 17 | psyco_incref_nv(po, w); 18 | } 19 | return could_eat; 20 | } 21 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/ivm-insns.c: -------------------------------------------------------------------------------- 1 | #include "ivm-insns.h" 2 | 3 | 4 | #define setlatestopcode(opcode) (*code = (opcode)) 5 | #define INSN_EMIT_opcode(opcode) (*code++ = (opcode)) 6 | #define INSN_EMIT_modified_opcode(opcode, totalargs) \ 7 | (code[-((int)(totalargs))-1] = (opcode)) 8 | 9 | #define bytecode_size(T) sizeof(T) 10 | #define INSN_EMIT_void(arg) do { /*nothing*/ } while (0) 11 | #define INSN_EMIT_byte(arg) (*code++ = (code_t)(arg)) 12 | #define INSN_EMIT_char(arg) (*code++ = (code_t)(arg)) 13 | #define INSN_EMIT_int(arg) (*(int*)code = (int)(arg), code += sizeof(int)) 14 | #define INSN_EMIT_word_t(arg) (*(word_t*)code=(word_t)(arg),code+=sizeof(word_t)) 15 | #define INSN_EMIT_placeholder_byte(ppbyte) (*(ppbyte)=code++) 16 | #define INSN_EMIT_placeholder_long(ppword) (*(ppword)=(word_t*)code, \ 17 | code+=sizeof(word_t)) 18 | 19 | 20 | #include "prolog/insns-igen.i" 21 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/localsetup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | dir = os.path.join(os.path.dirname(__file__), 'prolog') 4 | for filename in os.listdir(dir): 5 | if filename.lower().endswith('.default'): 6 | basename = os.path.join(dir, filename[:-8]) 7 | filename = os.path.join(dir, filename) 8 | if not os.path.exists(basename): 9 | copy = 2 10 | else: 11 | try: 12 | copy = os.stat(filename).st_mtime > os.stat(basename).st_mtime 13 | except OSError: 14 | copy = 0 15 | if copy: 16 | print 'Copying', filename, '->', basename 17 | if copy != 2: 18 | print '(OVERRIDING the older file)' 19 | import shutil 20 | shutil.copy(filename, basename) 21 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/prolog/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | ## ## 3 | ## SWI-Prolog Virtual Machine Generator ## 4 | ## ## 5 | #################################################################### 6 | 7 | # 8 | # To run this you will need SWI-Prolog. 9 | # http://www.swi-prolog.org/ 10 | # 11 | 12 | VMWRITER = vm.pl vmwriter.pl utils.pl ccode.pl detcheck.pl mode_combine.pl 13 | GENERATED = insns-switch.i insns-threaded.i insns-igen.i insns-igen-h.i \ 14 | insns-table.py 15 | # insns-threaded-rel.i 16 | TEMP = optimize.tmp 17 | 18 | 19 | all: $(GENERATED) 20 | 21 | clean: 22 | rm -f $(GENERATED) $(TEMP) 23 | 24 | default: $(addsuffix .default,$(GENERATED) mode_combine.pl) 25 | 26 | minimal: empty_mode_combine all 27 | 28 | empty_mode_combine: 29 | echo > mode_combine.pl 30 | 31 | 32 | $(GENERATED): insns.pl $(VMWRITER) 33 | pl -f insns.pl -g main_emit -t halt 34 | 35 | %.default: % 36 | cp $< $@ 37 | 38 | #%-switch.i: %.pl $(VMWRITER) 39 | # pl -f $< -g "main_emit(modes, switch)" -t halt > $@ 40 | # 41 | #%-threaded-rel.i: %.pl $(VMWRITER) 42 | # pl -f $< -g "main_emit(modes, threaded(relative))" -t halt > $@ 43 | # 44 | #%-threaded.i: %.pl $(VMWRITER) 45 | # pl -f $< -g "main_emit(modes, threaded(absolute))" -t halt > $@ 46 | # 47 | #%-immed.i: %.pl $(VMWRITER) 48 | # pl -f $< -g "main_emit(modes, single([immed(int)]))" -t halt > $@ 49 | # 50 | #%-igen.i: %.pl $(VMWRITER) 51 | # pl -f $< -g "main_emit(insns, functions('DEFINEFN '))" -t halt > $@ 52 | # 53 | #%-igen-h.i: %.pl $(VMWRITER) 54 | # pl -f $< -g "main_emit(insns, headers('EXTERNFN '))" -t halt > $@ 55 | # 56 | #%-table.py: %.pl $(VMWRITER) 57 | # pl -f $< -g "main_emit(pytable)" -t halt > $@ 58 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/prolog/detcheck.pl: -------------------------------------------------------------------------------- 1 | :- dynamic detchecked/1, detdebug/0. 2 | 3 | det(Functor/Arity) :- 4 | ignore(retract(detchecked(Functor/Arity))), 5 | assert(detchecked(Functor/Arity)), 6 | length(Args, Arity), 7 | Head =.. [Functor | Args], 8 | atom_concat('__detcheck$', Functor, MangledFunctor), 9 | MangledHead =.. [MangledFunctor | Args], 10 | ignore(retract(Head :- _)), 11 | assert(Head :- ((detdebug -> writeq(Head), nl ; true), MangledHead, ! ; 12 | deterror(Head))). 13 | 14 | deterror(Head) :- 15 | user_error('*** Predicate call should not have failed:', Head). 16 | 17 | user_error(Msg, Object) :- 18 | tell(user_error), 19 | nl, 20 | write(Msg), 21 | nl, 22 | write_term(Object, [quoted(true), max_depth(8)]), 23 | nl, 24 | throw(user_error). 25 | 26 | 27 | term_expansion(Head :- Body, MangledHead :- Body) :- 28 | !, 29 | term_expansion(Head, MangledHead). 30 | 31 | term_expansion(Head, MangledHead) :- 32 | Head =.. [Functor | Args], 33 | length(Args, Arity), 34 | detchecked(Functor/Arity), 35 | !, 36 | atom_concat('__detcheck$', Functor, MangledFunctor), 37 | MangledHead =.. [MangledFunctor | Args]. 38 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/prolog/insns.py: -------------------------------------------------------------------------------- 1 | from insnset import InstructionSet 2 | 3 | 4 | --- IN-PROGRESS --- 5 | 6 | 7 | class Immed: 8 | def __init__(self, *commonvalues): 9 | self.commonvalues = commonvalues 10 | 11 | def modes(self, ivm): 12 | for n in self.commonvalues: 13 | if ivm.nextarg('void', min=n, max=n) is not None: 14 | return str(n) 15 | return ivm.nextarg('word_t') 16 | 17 | class Address: 18 | def modes(self, ivm): 19 | return ivm.nextarg('word_t') 20 | 21 | class Stack: 22 | def modes(self, ivm): 23 | for i in range(len(ivm.stack)): 24 | if ivm.nextarg('void', min=i, max=i) is not None: 25 | return ivm.stack[i] 26 | n = ivm.nextarg('code_t', min=len(stack), max=255) 27 | if n is None: 28 | n = ivm.nextarg('word_t') 29 | return ivm.compute('stack_nth(%s-%d)' % (n, len(stack))) 30 | 31 | class StackRef: 32 | def modes(self, ivm): 33 | ... 34 | 35 | 36 | class IVM(InstructionSet): 37 | 38 | def insn_inv(self): 39 | x = self.pop(); self.push('~%s' % x) 40 | 41 | def insn_neg_o(self): 42 | x = self.pop(); self.push('-%s' % x) 43 | self.setflag('%s == LONG_MIN' % x) 44 | 45 | def insn_abs_o(self): 46 | x = self.pop(); self.push('%s<0 ? -%s : %s' % (x,x,x)) 47 | self.setflag('%s == LONG_MIN' % x) 48 | 49 | def insn_add(self): 50 | y = self.pop(); x = self.pop(); self.push('%s+%s' % (x,y)) 51 | 52 | def insn_add_o(self): 53 | y = self.pop(); x = self.pop(); self.push('%s+%s' % (x,y)) 54 | self.setflag('((%s+%s)^%s) < 0 && (%s^%s) >= 0' % (x,y,x,x,y)) 55 | 56 | def insn_immed(self, x=Immed(0,1)): 57 | self.push(x) 58 | 59 | def insn_s_push(self, s=Stack()): 60 | self.push(s) 61 | 62 | def insn_s_pop(self, s=StackRef()): 63 | s.write(self.pop()) 64 | 65 | def insn_flag_push(self): 66 | self.push(self.consumeflag()) 67 | 68 | def insn_cmpz(self): 69 | self.pop('x'); self.setflag('x == 0') 70 | 71 | def insn_jumpfar(self, target=Address()): 72 | self.do('nextip = (code_t*) %s;' % target) 73 | insn_jumpfar.chainable = False 74 | 75 | def insn_load1(self): 76 | self.pop('addr'); self.push('*(char*) addr') 77 | 78 | def insn_store1(self): 79 | self.pop('value'); self.pop('addr') 80 | self.do('*(char*) addr = value;') 81 | 82 | 83 | ivm = IVM(['accum']) 84 | ivm.insn_add_o() 85 | ivm.insn_add() 86 | ivm.insn_flag_push() 87 | ivm.normalize(['accum']) 88 | ivm.write() 89 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/prolog/insnset.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class InstructionSet: 4 | 5 | def __init__(self, stack): 6 | self.locals = {} 7 | self.stack = stack 8 | self.popped = 0 9 | self.flag = 'flag' 10 | self.codelines = [] 11 | 12 | def do(self, code): 13 | self.codelines.append(code) 14 | 15 | def push(self, expr): 16 | self.stack.append(expr) 17 | 18 | def compute(self, expr): 19 | if expr in self.locals: 20 | return expr 21 | name = 'l%d' % len(self.locals) 22 | self.locals[name] = expr 23 | self.do('%s = %s;' % (name, expr)) 24 | return name 25 | 26 | def pop(self): 27 | if self.stack: 28 | name = self.compute(self.stack.pop()) 29 | else: 30 | name = self.compute('stack_nth(%d);' % self.popped) 31 | self.popped += 1 32 | return name 33 | 34 | def setflag(self, expr): 35 | self.flag = expr 36 | 37 | def forgetflag(self): 38 | self.flag = None 39 | 40 | def consumeflag(self): 41 | result = self.flag 42 | self.forgetflag() 43 | return result 44 | 45 | def normalize(self, stack): 46 | rstack = list(stack) 47 | rstack.reverse() 48 | code = ['%s = %s;' % (target, self.pop()) for target in rstack] 49 | shift = self.popped-len(self.stack) 50 | code += ['stack_nth(%d) = %s;' % (i, self.pop()) 51 | for i in range(len(self.stack))] 52 | if self.flag is not None and self.flag != 'flag': 53 | self.do('flag = %s;' % self.flag) 54 | if shift != 0: 55 | if shift > 0: 56 | self.do('stack_shift_pos(%d);' % shift) 57 | else: 58 | self.do('stack_shift(%d);' % shift) 59 | for line in code: 60 | self.do(line) 61 | self.stack = list(stack) 62 | self.popped = 0 63 | 64 | def write(self): 65 | print '{' 66 | if self.locals: 67 | locals = self.locals.keys() 68 | locals.sort() 69 | print '\tword_t %s;' % (', '.join(locals),) 70 | for line in self.codelines: 71 | print '\t' + line 72 | print '}' 73 | 74 | 75 | class InstructionSetWriter: 76 | 77 | def __init__(self, InsnSet, nbaccum=1): 78 | self.InsnSet = InsnSet 79 | self.nbaccum = nbaccum 80 | 81 | 82 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/prolog/mode_combine.pl.default: -------------------------------------------------------------------------------- 1 | % This file defines combination of instructions, or more precisely instruction 2 | % modes, that should be produced as a single larger instruction with its 3 | % own bytecode. There are about 73 basic instruction modes, so this leaves 4 | % room for 182 extra combined instructions. For example: 5 | 6 | %% mode_combine([s_push(0), immed(char)]). 7 | %% mode_combine([s_push(0), immed(char), cmplt]). 8 | %% mode_combine([s_push(0), immed(char), cmplt, jcondfar(long)]). 9 | 10 | % See py-utils/ivmoptimize.py for a way to generate automatically the 182 best 11 | % combinations for your own program. Optimizing Psyco/IVM in this way for a 12 | % specific program can make it run quite faster. 13 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/ivm/prolog/samelines.py: -------------------------------------------------------------------------------- 1 | # 2 | # Search for identical lines in stdin. Line starting with "*" 3 | # are assumed to be repeated that number of times. 4 | # stdout report is formatted according to sys.argv[1]. 5 | # 6 | import sys, re 7 | 8 | re1 = re.compile(r"([0-9]+)[*](.*)") 9 | 10 | def samelines(infile, outfile, format, verbose=1, minimum=2): 11 | lines = {} 12 | total = 0 13 | try: 14 | for line in infile: 15 | verbose -= 1 16 | if not verbose: 17 | if total: 18 | print >> sys.stderr, '%d lines, %d without duplicates...' % ( 19 | total, len(lines)) 20 | total += 5000 21 | verbose = 5000 22 | if line.endswith('\n'): 23 | line = line[:-1] 24 | match = re1.match(line) 25 | if match: 26 | count = int(match.group(1)) 27 | line = match.group(2) 28 | else: 29 | count = 1 30 | lines[line] = lines.get(line, 0) + count 31 | finally: 32 | for line, count in lines.iteritems(): 33 | if count >= minimum: 34 | print >> outfile, format % (line, count) 35 | 36 | if __name__ == '__main__': 37 | format = sys.argv[1] 38 | samelines(sys.stdin, sys.stdout, format) 39 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/linuxmemchk.c: -------------------------------------------------------------------------------- 1 | /* custom checking allocators a la Electric Fence */ 2 | #include "linuxmemchk.h" 3 | #if HEAVY_MEM_CHECK 4 | #undef NDEBUG 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #define PAGESIZE 4096 13 | #ifndef MALLOC_BIGBUFFER 14 | # define MALLOC_BIGBUFFER PAGESIZE*16384 15 | #endif 16 | 17 | 18 | struct _alloc_s { 19 | void* ptr; 20 | int npages; 21 | }; 22 | static void* _na_start = NULL; 23 | static char* _na_cur; 24 | 25 | static struct _alloc_s* _na_find(void* data) 26 | { 27 | int err; 28 | long data1; 29 | struct _alloc_s* s; 30 | assert(_na_start+PAGESIZE <= data && 31 | data < _na_start+MALLOC_BIGBUFFER-PAGESIZE); 32 | data1 = (long) data; 33 | data1 &= ~(PAGESIZE-1); 34 | data1 -= PAGESIZE; 35 | err = mprotect((void*) data1, PAGESIZE, PROT_READ|PROT_WRITE); 36 | assert(!err); 37 | s = (struct _alloc_s*) data1; 38 | assert(s->npages > 0); 39 | return s; 40 | } 41 | 42 | DEFINEFN 43 | void* memchk_ef_malloc(int size) 44 | { 45 | int err, npages = (size + PAGESIZE-1) / PAGESIZE + 1; 46 | struct _alloc_s* s; 47 | char* data; 48 | if (_na_start == NULL) 49 | { 50 | _na_start = mmap(NULL, MALLOC_BIGBUFFER, PROT_NONE, 51 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 52 | assert(_na_start != MAP_FAILED); 53 | _na_cur = (char*) _na_start; 54 | } 55 | s = (struct _alloc_s*) _na_cur; 56 | _na_cur += npages * PAGESIZE; 57 | if (_na_cur >= ((char*) _na_start) + MALLOC_BIGBUFFER) 58 | { 59 | fprintf(stderr, "Nothing wrong so far, but MALLOC_CHECK is running out\n of mmap'ed memory. Increase MALLOC_BIGBUFFER.\n"); 60 | assert(0); 61 | } 62 | err = mprotect(s, npages * PAGESIZE, PROT_READ|PROT_WRITE|PROT_EXEC); 63 | assert(!err); 64 | s->ptr = data = _na_cur - /*((size+3)&~3)*/ size; 65 | s->npages = npages; 66 | err = mprotect(s, PAGESIZE, PROT_NONE); 67 | assert(!err); 68 | return data; 69 | } 70 | 71 | DEFINEFN 72 | void memchk_ef_free(void* data) 73 | { 74 | int err, npages; 75 | struct _alloc_s* s; 76 | if (data == NULL) 77 | return; 78 | s = _na_find(data); 79 | assert(s->ptr == data); 80 | npages = s->npages; 81 | s->npages = 0; 82 | err = mprotect(s, npages * PAGESIZE, PROT_NONE); 83 | assert(!err); 84 | //fprintf(stderr, "PyMem_FREE(%p): mprotect %p %x\n", data, s, npages*PAGESIZE); 85 | } 86 | 87 | DEFINEFN 88 | void* memchk_ef_realloc(void* data, int nsize) 89 | { 90 | int size; 91 | struct _alloc_s* s = _na_find(data); 92 | void* ndata = PyMem_MALLOC(nsize); 93 | 94 | assert(s->ptr == data); 95 | size = ((char*)s) + s->npages * PAGESIZE - (char*)data; 96 | memcpy(ndata, data, size 5 | #undef PyMem_MALLOC 6 | #undef PyMem_REALLOC 7 | #undef PyMem_FREE 8 | 9 | EXTERNFN void* memchk_ef_malloc(int size); 10 | EXTERNFN void memchk_ef_free(void* data); 11 | EXTERNFN void* memchk_ef_realloc(void* data, int nsize); 12 | 13 | #define PyMem_MALLOC memchk_ef_malloc 14 | #define PyMem_REALLOC memchk_ef_realloc 15 | #define PyMem_FREE memchk_ef_free 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/mkincl.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | 3 | def getincl(): 4 | PY_VER = sys.version[:3] 5 | for p in (sys.prefix, sys.exec_prefix): 6 | if sys.executable.startswith(p): 7 | return [os.path.join(sys.prefix, 'include', 'python'+PY_VER)] 8 | base = os.path.dirname(sys.executable) 9 | if os.path.exists(os.path.join(base, 'Include')): 10 | return [os.path.join(base, 'Include'), base, os.path.join(base, 'Stackless')] 11 | raise IOError, 'cannot find the include directories for %s' % sys.executable 12 | 13 | INCLUDE_STR = ' '.join(['-I%s' % s for s in getincl()]) 14 | 15 | if __name__ == '__main__': 16 | print INCLUDE_STR 17 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/mychecker.py: -------------------------------------------------------------------------------- 1 | import re, dis 2 | recase = re.compile(r'case\s+([A-Z_][A-Z_+0-9]*)\s*[:]') 3 | rebin = re.compile(r'BINARY_OPCODE[(]([A-Z_][A-Z_+0-9]*),') 4 | remiss = re.compile(r'[/*]*MISSING_OPCODE[(]([A-Z_][A-Z_+0-9]*)[)]') 5 | 6 | if dis.opname[86] == 'YIELD_STMT': 7 | dis.opname[86] = 'YIELD_VALUE' 8 | 9 | inswitch = 0 10 | lst = [] 11 | miss = [] 12 | warn = 0 13 | 14 | def register(op): 15 | global warn 16 | print "%29s" % op, 17 | if op not in lst: 18 | lst.append(op) 19 | if op not in dis.opname: 20 | print "%29s" % "<--- unknown opcode", 21 | #warn += 1 22 | print 23 | 24 | print "+++ Found +++" 25 | print 26 | 27 | for line in open('Python/pycompiler.c').readlines(): 28 | line = line.strip() 29 | if line.startswith('switch (opcode)'): 30 | inswitch = 1 31 | elif line.endswith('/* switch (opcode) */'): 32 | inswitch = 0 33 | elif inswitch: 34 | m = recase.match(line) or rebin.match(line) 35 | if m: 36 | register(m.group(1)) 37 | else: 38 | m = remiss.match(line) 39 | if m: 40 | miss.append(m.group(1)) 41 | print 42 | print 43 | 44 | assert not inswitch 45 | 46 | print '+++ Not implemented +++' 47 | print 48 | for i, opname in zip(range(1,256), dis.opname[1:]): 49 | if not opname.startswith('<') and opname not in lst: 50 | print "%4d %29s" % (i, opname), 51 | if opname not in miss: 52 | print "%29s" % "<--- forgotten ?", 53 | warn += 1 54 | else: 55 | miss.remove(opname) 56 | print 57 | print 58 | 59 | for opname in miss: 60 | print "%29s" % opname, "%29s" % "<--- marked as missing, don't know why" 61 | 62 | print 63 | 64 | for line in open('mergepoints.c').readlines(): 65 | for word in lst: 66 | if line.find(word) >= 0: 67 | lst.remove(word) 68 | break 69 | 70 | for word in lst: 71 | print '!!! Not found in mergepoints.c !!!' 72 | print 73 | print word 74 | print 75 | warn += 1 76 | 77 | if warn: 78 | print ' !!! %d warning(s) !!!' % warn 79 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OS-specific utilities. 3 | * 4 | * The rationale is that #include cannot be put anywhere else 5 | * because it messes up things like default alignments; if included in the 6 | * body of Psyco, we get crashes at run-time. 7 | * 8 | * This file is compiled separated. 9 | */ 10 | 11 | /************************************************************/ 12 | #ifdef _WIN32 13 | /************************************************************/ 14 | 15 | #include 16 | 17 | long psyco_allocate_executable_buffer(long basicsize, char **result) 18 | { 19 | DWORD old; 20 | char *p = (char*) VirtualAlloc(NULL, basicsize, MEM_COMMIT|MEM_RESERVE, 21 | PAGE_EXECUTE_READWRITE); 22 | if (p == NULL) 23 | return 0; 24 | VirtualProtect(p, basicsize, PAGE_EXECUTE_READWRITE, &old); 25 | /* ignore errors, just try */ 26 | *result = p; 27 | return basicsize; 28 | } 29 | 30 | /************************************************************/ 31 | #else /* Assume UNIX */ 32 | /************************************************************/ 33 | 34 | #include 35 | #include 36 | #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 37 | # define MAP_ANONYMOUS MAP_ANON 38 | #endif 39 | 40 | long psyco_allocate_executable_buffer(long basicsize, char **result) 41 | { 42 | #if defined(MAP_ANONYMOUS) && defined(MAP_PRIVATE) 43 | /* note that some platforms *require* the allocation to be performed 44 | by mmap, because PyMem_MALLOC() doesn't set the PROT_EXEC flag. 45 | On these platforms we just hope that the first allocation is 46 | successful, so that when another allocation fails, Psyco correctly 47 | signals the OUT_OF_MEMORY. */ 48 | long bigsize = basicsize * 32; /* allocate 32 blocks at a time */ 49 | char *p = (char*) mmap(NULL, bigsize, 50 | PROT_EXEC|PROT_READ|PROT_WRITE, 51 | MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 52 | if (p == MAP_FAILED || p == NULL) 53 | return 0; 54 | *result = p; 55 | return bigsize; 56 | 57 | #else 58 | 59 | return 0; 60 | 61 | #endif 62 | } 63 | 64 | /************************************************************/ 65 | #endif /* !MS_WINDOWS */ 66 | /************************************************************/ 67 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OS-specific utilities. 3 | */ 4 | 5 | /* allocate 'basicsize' bytes, or possibly a multiple of it if allocating 6 | large blocks of memory is better. The allocated address is stored 7 | in '*result'. The total allocated size is returned, or 0 to try some 8 | other allocation method. */ 9 | extern long psyco_allocate_executable_buffer(long basicsize, char **result); 10 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/processor.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Processor-specific execution ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PROCESSOR_H 6 | #define _PROCESSOR_H 7 | 8 | #include "psyco.h" 9 | 10 | 11 | /***************************************************************/ 12 | /*** Execution ***/ 13 | 14 | /* executes a block of code. A new stack frame is created and 15 | the 'initial_stack' values are PUSHed into it. The number 16 | of values pushed are determined by the saved arguments_count of 17 | the 'codebuf'. 18 | */ 19 | struct stack_frame_info_s; 20 | EXTERNFN PyObject* psyco_processor_run(CodeBufferObject* codebuf, 21 | long initial_stack[], 22 | struct stack_frame_info_s*** finfo, 23 | PyObject* tdict); 24 | 25 | #define RUN_ARGC(codebuf) \ 26 | (extra_assert(CodeBuffer_Check((codebuf))), \ 27 | (int)((get_stack_depth(&((CodeBufferObject*)(codebuf))->snapshot) \ 28 | - INITIAL_STACK_DEPTH - sizeof(long)) / sizeof(long))) 29 | 30 | /* call a C function with a variable number of arguments 31 | (implemented as a pointer to assembler code) */ 32 | EXTERNVAR long (*psyco_call_var) (void* c_func, int argcount, long arguments[]); 33 | 34 | /* check for signed integer multiplication overflow */ 35 | EXTERNVAR char (*psyco_int_mul_ovf) (long a, long b); 36 | 37 | /* find the next stack frame 38 | ("next" = more recent in time = towards innermost frames) */ 39 | EXTERNFN struct stack_frame_info_s** 40 | psyco_next_stack_frame(struct stack_frame_info_s** finfo); 41 | 42 | 43 | #endif /* _PROCESSOR_H */ 44 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/profile.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Profilers to collect statistics ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PROFILE_H 6 | #define _PROFILE_H 7 | 8 | 9 | #include "psyco.h" 10 | #include "Python/frames.h" 11 | #include 12 | #include 13 | 14 | 15 | /* enable profiling, see comments in profile.c for the various methods */ 16 | EXTERNFN bool psyco_set_profiler(void (*rs)(void*, int)); 17 | /* where 'rs' may be: */ 18 | EXTERNFN void psyco_rs_profile(void*, int); 19 | EXTERNFN void psyco_rs_fullcompile(void*, int); 20 | EXTERNFN void psyco_rs_nocompile(void*, int); 21 | 22 | /* enable the same profiling feature on all threads */ 23 | EXTERNFN void psyco_profile_threads(int start); 24 | 25 | /* call this when it is detected to be worthwhile to give a frame a 26 | little Psyco help */ 27 | EXTERNFN bool psyco_turbo_frame(PyFrameObject* frame); 28 | 29 | /* call this to mark the code object as being worthwhile to 30 | systematically accelerate */ 31 | EXTERNFN void psyco_turbo_code(PyCodeObject* code, int recursion); 32 | 33 | /* call this to accelerate all frames currently executing the given code */ 34 | EXTERNFN void psyco_turbo_frames(PyCodeObject* code); 35 | 36 | 37 | #endif /* _PROFILE_H */ 38 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/psyfunc.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Psyco Function objects (a.k.a. proxies) ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PSYFUNC_H 6 | #define _PSYFUNC_H 7 | 8 | 9 | #include "psyco.h" 10 | #include /* for PyCodeObject */ 11 | 12 | 13 | /* Encode a call to the given Python function, compiling it as needed. */ 14 | EXTERNFN vinfo_t* psyco_call_pyfunc(PsycoObject* po, PyCodeObject* co, 15 | vinfo_t* vglobals, vinfo_t* vdefaults, 16 | vinfo_t* arg_tuple, int recursion); 17 | 18 | /* for pycompiler.c */ 19 | EXTERNFN vinfo_t* psyco_save_inline_po(PsycoObject* po); 20 | EXTERNFN PsycoObject* psyco_restore_inline_po(PsycoObject* po,vinfo_array_t** a); 21 | 22 | 23 | /* Psyco proxies for Python functions. Calling a proxy has the same effect 24 | as calling the function it has been built from, except that the function 25 | is compiled first. As proxies are real Python objects, calling them is 26 | the only way to go from Python's base level to Psyco's meta-level. 27 | Note that (unlike in previous versions of Psyco) proxies should not be 28 | seen by user Python code. Use _psyco.proxycode() to build a proxy and 29 | emcompass it in a code object. */ 30 | typedef struct { 31 | PyObject_HEAD 32 | PyCodeObject* psy_code; /* */ 33 | PyObject* psy_globals; /* same as in Python function object */ 34 | PyObject* psy_defaults; /* */ 35 | int psy_recursion; /* # levels to automatically compile called functions */ 36 | PyObject* psy_fastcall; /* cache mapping arg count to code bufs */ 37 | } PsycoFunctionObject; 38 | 39 | EXTERNVAR PyTypeObject PsycoFunction_Type; 40 | 41 | #define PsycoFunction_Check(op) PyObject_TypeCheck(op, &PsycoFunction_Type) 42 | 43 | 44 | #if 0 /* unneeded */ 45 | EXTERNFN PyObject* psyco_PsycoFunction_New(PyFunctionObject* func, int rec); 46 | #endif 47 | EXTERNFN PsycoFunctionObject* psyco_PsycoFunction_NewEx(PyCodeObject* code, 48 | PyObject* globals, 49 | PyObject* defaults, /* or NULL */ 50 | int rec); 51 | EXTERNFN PyObject* psyco_proxycode(PyFunctionObject* func, int rec); 52 | 53 | PSY_INLINE bool is_proxycode(PyCodeObject* code) { 54 | return PyTuple_Size(code->co_consts) > 1 && 55 | PsycoFunction_Check(PyTuple_GET_ITEM(code->co_consts, 1)); 56 | } 57 | 58 | 59 | #endif /* _PSYFUNC_H */ 60 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/pycodegen.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Generic support code for Python-specific code generation ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _PYCODEGEN_H 6 | #define _PYCODEGEN_H 7 | 8 | #include "vcompiler.h" 9 | #include 10 | 11 | 12 | /* emit Py_INCREF(v) */ 13 | PSY_INLINE bool psyco_incref_v(PsycoObject* po, vinfo_t* v) 14 | { 15 | if (!compute_vinfo(v, po)) return false; 16 | psyco_incref_nv(po, v); 17 | return true; 18 | } 19 | 20 | /* emit Py_DECREF(v) */ 21 | PSY_INLINE void psyco_decref_v(PsycoObject* po, vinfo_t* v) 22 | { 23 | switch (gettime(v->source)) { 24 | 25 | case RunTime: 26 | psyco_decref_rt(po, v); 27 | break; 28 | 29 | case CompileTime: 30 | psyco_decref_c(po, (PyObject*) CompileTime_Get(v->source)->value); 31 | break; 32 | } 33 | } 34 | 35 | 36 | /* can eat a reference if we had one in the first place, and 37 | if no one else will require it (i.e. there is only one reference 38 | left to 'vi') */ 39 | PSY_INLINE bool eat_reference(vinfo_t* vi) 40 | { 41 | if (has_rtref(vi->source) && vi->refcount == 1) 42 | { 43 | vi->source = remove_rtref(vi->source); 44 | return true; 45 | } 46 | else 47 | return false; 48 | } 49 | 50 | /* force a reference to be consumed */ 51 | PSY_INLINE void consume_reference(PsycoObject* po, vinfo_t* vi) 52 | { 53 | if (!eat_reference(vi)) 54 | psyco_incref_v(po, vi); 55 | } 56 | 57 | /* make sure we have a reference on 'vi' */ 58 | PSY_INLINE void need_reference(PsycoObject* po, vinfo_t* vi) 59 | { 60 | if ((vi->source & (TimeMask | RunTime_NoRef)) == (RunTime | RunTime_NoRef)) 61 | { 62 | vi->source = add_rtref(vi->source); 63 | psyco_incref_rt(po, vi); 64 | } 65 | } 66 | 67 | 68 | #endif /* _PYCODEGEN_H */ 69 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/stats.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Statistics management and usage about code objects ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _STATS_H 6 | #define _STATS_H 7 | 8 | /* NB.: the real-time profilers are in profile.c */ 9 | 10 | #include "psyco.h" 11 | #include "cstruct.h" 12 | #include "mergepoints.h" 13 | #include "timing.h" 14 | #include "Python/frames.h" 15 | #include 16 | #include 17 | 18 | 19 | #if VERBOSE_STATS 20 | # define stats_printf(args) debug_printf(1, args) 21 | #else 22 | # define stats_printf(args) do { } while (0) /* nothing */ 23 | #endif 24 | 25 | 26 | /* extra data attached to code objects */ 27 | typedef struct { 28 | PyCStruct_HEAD /* cs_key is the code object */ 29 | float st_charge; /* usage statistics */ 30 | PyObject* st_mergepoints; 31 | PyObject* st_codebuf; /* as compiled from PsycoCode_CompileCode() */ 32 | PyObject* st_globals; /* globals used in st_codebuf */ 33 | } PyCodeStats; 34 | 35 | 36 | /* return the PyCodeStats for 'co' */ 37 | EXTERNFN PyCodeStats* PyCodeStats_Get(PyCodeObject* co); 38 | EXTERNFN PyCodeStats* PyCodeStats_MaybeGet(PyCodeObject* co); 39 | 40 | /* compute and return a Borrowed reference to st_mergepoints */ 41 | PSY_INLINE PyObject* PyCodeStats_MergePoints(PyCodeStats* cs, int module) { 42 | PyObject* mp = cs->st_mergepoints; 43 | if (mp == NULL) { 44 | mp = psyco_build_merge_points((PyCodeObject*) cs->cs_key, 45 | module); 46 | cs->st_mergepoints = mp; 47 | } 48 | else if (!module && mp != Py_None && 49 | (psyco_mp_flags(mp) & MP_FLAGS_MODULE)) 50 | mp = Py_None; /* can only run as top-level module code */ 51 | return mp; 52 | } 53 | 54 | 55 | EXTERNFN void psyco_stats_reset(void); 56 | EXTERNFN void psyco_stats_append(PyThreadState* tstate, PyFrameObject* f); 57 | EXTERNFN void psyco_stats_collect(void); 58 | EXTERNFN PyObject* psyco_stats_top(int n); 59 | /* set tunable parameters */ 60 | EXTERNFN bool psyco_stats_write(PyObject* args, PyObject* kwds); 61 | EXTERNFN PyObject* psyco_stats_read(char* name); 62 | EXTERNFN PyObject* psyco_stats_dump(void); 63 | 64 | 65 | /* private timing data, based on timing.h */ 66 | #if MEASURE_ALL_THREADS 67 | # define measuring_state(ts) 1 68 | #else 69 | # define measuring_state(ts) ((ts) == psyco_main_threadstate) 70 | EXTERNVAR PyThreadState* psyco_main_threadstate; 71 | #endif 72 | 73 | 74 | #endif /* _STATS_H */ 75 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/timing.h: -------------------------------------------------------------------------------- 1 | /***************************************************************/ 2 | /*** Measuring processor time ***/ 3 | /***************************************************************/ 4 | 5 | #ifndef _TIMING_H 6 | #define _TIMING_H 7 | 8 | #include "psyco.h" 9 | #include "Python/pyver.h" 10 | 11 | 12 | #define measure_is_zero(m) ((m) == (time_measure_t) 0) 13 | 14 | 15 | /***************************************************************/ 16 | /* Use the tick_counter field of the PyThreadState for timing */ 17 | 18 | #define MEASURE_ALL_THREADS 1 19 | 20 | typedef int time_measure_t; 21 | 22 | PSY_INLINE time_measure_t get_measure(PyThreadState* tstate) 23 | { 24 | int result = tstate->tick_counter; 25 | tstate->tick_counter = 0; 26 | return result; 27 | } 28 | 29 | /***************************************************************/ 30 | 31 | 32 | #endif /* _TIMING_H */ 33 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/c/versionchecker.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | explicitnumber = { 5 | '0x010100f0': '1.1.1', # bugfix release, no change in hex version 6 | '0x010200f0': '1.2', 7 | '0x010300f0': '1.3', 8 | '0x010400f0': '1.4', 9 | '0x010500f0': '1.5', 10 | '0x010501f0': '1.5.1', 11 | '0x010502f0': '1.5.2', 12 | } 13 | 14 | FILES = { 15 | 'Python/pyver.h': re.compile(r'PSYCO_VERSION_HEX\s+(0x[0-9a-fA-F]+)'), 16 | '../py-support/support.py': re.compile(r'__version__\s*=\s*(0x[0-9a-fA-F]+)'), 17 | '../doc/psycoguide.tex': re.compile(r'\\release\{([0-9.]+)\}'), 18 | '../setup.py': re.compile(r'version\s*=\s*\"([0-9.]+)\"'), 19 | '../../www/dist/Makefile': re.compile(r'version\s*=\s*([0-9.]+)'), 20 | '../../www/content/index.rst': re.compile(r'`Psyco ([0-9.]+)@'), 21 | '../../www/content/download.rst': re.compile(r'Current version is ([0-9.]+)'), 22 | '../../www/content/./download.rst': re.compile(r'[dD]ownload Release ([0-9.]+)'), 23 | '../../www/content/doc.rst': re.compile(r'Psyco release ([0-9.]+)'), 24 | '../README.txt': re.compile(r'VERSION ([0-9.]+)'), 25 | } 26 | 27 | versions = {} 28 | for filename, regexp in FILES.items(): 29 | for line in open(filename, 'r'): 30 | match = regexp.search(line) 31 | if match: 32 | break 33 | else: 34 | raise Exception, "No version number found in " + filename 35 | ver = match.group(1) 36 | print '%20s %s' % (ver, filename) 37 | if ver.startswith('0x'): 38 | ver = explicitnumber[ver] 39 | versions[ver] = filename 40 | 41 | if len(versions) != 1: 42 | raise Exception, versions 43 | else: 44 | print "versionchecker: ok" 45 | 46 | import files; files.main() 47 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/doc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile.local should define MKHOWTO to point to the Python 3 | # distribution's Doc/tools/mkhowto, e.g. 4 | # MKHOWTO = ${HOME}/cvs/python/dist/src/Doc/tools/mkhowto 5 | include Makefile.local 6 | 7 | PAPER=a4 8 | DVIPS=dvips -N0 -t $(PAPER) 9 | 10 | html = psycoguide 11 | dvi = psycoguide.dvi 12 | ps = psycoguide.ps 13 | ps-gz= psycoguide.ps.gz 14 | all = $(html) $(dvi) $(ps) $(ps-gz) 15 | 16 | html : $(html) 17 | dvi : $(dvi) 18 | ps : $(ps) 19 | ps-gz: $(ps-gz) 20 | all : $(all) 21 | 22 | %: %.tex 23 | -rm -fr $@ 24 | ${MKHOWTO} $< 25 | 26 | %.dvi: %.tex 27 | ${MKHOWTO} --paper=$(PAPER) --dvi $< 28 | 29 | %.ps.gz: %.ps 30 | gzip -c < $< > $@ 31 | 32 | %.ps: %.dvi 33 | $(DVIPS) -o $@ $< 34 | 35 | %.pdf: %.tex 36 | rm -f $*.log $*.out $*.aux 37 | pdflatex $< 38 | pdflatex $< 39 | rm -f $*.log $*.out $*.aux 40 | 41 | clean: 42 | rm -fr $(all) 43 | rm -f *.log *.aux *.ind *.idx *.l2h *.toc *.syn 44 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/doc/README.txt: -------------------------------------------------------------------------------- 1 | To compile psycoguide.tex, see instructions at the top of the Makefile. 2 | 3 | See also: 4 | 5 | - Psyco presentations: 6 | 7 | http://codespeak.net/svn/user/arigo/talks/accu2004-psyco 8 | http://codespeak.net/svn/user/arigo/talks/pepm04-psyco 9 | 10 | The two presentations are very similar, but introduce concepts in a 11 | different order. The second one is best suited for people with an 12 | academic background. 13 | 14 | - Papers about Psyco: 15 | 16 | Representation-Based Just-In-Time Specialization 17 | and the Psyco Prototype for Python 18 | PEPM'04 19 | http://codespeak.net/svn/user/arigo/papers/psyco/compiled/theory_psyco.ps.gz 20 | http://codespeak.net/svn/user/arigo/papers/psyco/compiled/theory_psyco.pdf 21 | 22 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-support/__init__.py: -------------------------------------------------------------------------------- 1 | ########################################################################### 2 | # 3 | # Psyco top-level file of the Psyco package. 4 | # Copyright (C) 2001-2002 Armin Rigo et.al. 5 | 6 | """Psyco -- the Python Specializing Compiler. 7 | 8 | Typical usage: add the following lines to your application's main module, 9 | preferably after the other imports: 10 | 11 | try: 12 | import psyco 13 | psyco.full() 14 | except ImportError: 15 | print 'Psyco not installed, the program will just run slower' 16 | """ 17 | ########################################################################### 18 | 19 | 20 | # 21 | # This module is present to make 'psyco' a package and to 22 | # publish the main functions and variables. 23 | # 24 | # More documentation can be found in core.py. 25 | # 26 | 27 | 28 | # Try to import the dynamic-loading _psyco and report errors 29 | try: 30 | import _psyco 31 | except ImportError, e: 32 | extramsg = '' 33 | import sys, imp 34 | try: 35 | file, filename, (suffix, mode, type) = imp.find_module('_psyco', __path__) 36 | except ImportError: 37 | ext = [suffix for suffix, mode, type in imp.get_suffixes() 38 | if type == imp.C_EXTENSION] 39 | if ext: 40 | extramsg = (" (cannot locate the compiled extension '_psyco%s' " 41 | "in the package path '%s')" % (ext[0], '; '.join(__path__))) 42 | else: 43 | extramsg = (" (check that the compiled extension '%s' is for " 44 | "the correct Python version; this is Python %s)" % 45 | (filename, sys.version.split()[0])) 46 | raise ImportError, str(e) + extramsg 47 | 48 | # Publish important data by importing them in the package 49 | from support import __version__, error, warning, _getrealframe, _getemulframe 50 | from support import version_info, __version__ as hexversion 51 | from core import full, profile, background, runonly, stop, cannotcompile 52 | from core import log, bind, unbind, proxy, unproxy, dumpcodebuf 53 | from _psyco import setfilter 54 | from _psyco import compact, compacttype 55 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-support/classes.py: -------------------------------------------------------------------------------- 1 | ########################################################################### 2 | # 3 | # Psyco class support module. 4 | # Copyright (C) 2001-2002 Armin Rigo et.al. 5 | 6 | """Psyco class support module. 7 | 8 | 'psyco.classes.psyobj' is an alternate Psyco-optimized root for classes. 9 | Any class inheriting from it or using the metaclass '__metaclass__' might 10 | get optimized specifically for Psyco. It is equivalent to call 11 | psyco.bind() on the class object after its creation. 12 | 13 | Importing everything from psyco.classes in a module will import the 14 | '__metaclass__' name, so all classes defined after a 15 | 16 | from psyco.classes import * 17 | 18 | will automatically use the Psyco-optimized metaclass. 19 | """ 20 | ########################################################################### 21 | 22 | __all__ = ['psyobj', 'psymetaclass', '__metaclass__'] 23 | 24 | 25 | from _psyco import compacttype 26 | import core 27 | from types import FunctionType 28 | 29 | class psymetaclass(compacttype): 30 | "Psyco-optimized meta-class. Turns all methods into Psyco proxies." 31 | 32 | def __new__(cls, name, bases, dict): 33 | bindlist = dict.get('__psyco__bind__') 34 | if bindlist is None: 35 | bindlist = [key for key, value in dict.items() 36 | if isinstance(value, FunctionType)] 37 | for attr in bindlist: 38 | dict[attr] = core.proxy(dict[attr]) 39 | return super(psymetaclass, cls).__new__(cls, name, bases, dict) 40 | 41 | psyobj = psymetaclass("psyobj", (), {}) 42 | __metaclass__ = psymetaclass 43 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/ivmextract.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | import xam 3 | from ivmdump import insnlist, insntable, stackpushes, chainable 4 | from struct import unpack 5 | 6 | 7 | IGNORE_INSNS = ('assertdepth', 'dynamicfreq') 8 | 9 | def dump(data): 10 | l = len(data) 11 | p = 0 12 | results = [] 13 | result = [] 14 | freq = 1 15 | while p < l: 16 | mode = insnlist[ord(data[p])] 17 | if mode.opcode not in insntable: 18 | break 19 | p += mode.unpacksize + 1 20 | if p > l: 21 | break 22 | args = mode.getargs(data, p-mode.unpacksize) 23 | for insn in mode.insns: 24 | if insn[0] in IGNORE_INSNS: 25 | if insn[0] == 'dynamicfreq': 26 | freq = args[0] 27 | continue 28 | a = len(insn)-1 29 | if a: 30 | txt = '%s(%s)' % (insn[0], ','.join(map(str,args[:a]))) 31 | del args[:a] 32 | else: 33 | txt = insn[0] 34 | result.append(txt) 35 | if mode.opcode not in chainable: 36 | results.append((freq, result)) 37 | result = [] 38 | results.append((freq, result)) 39 | return results 40 | 41 | 42 | def main(DIRECTORY): 43 | filename = os.path.join(DIRECTORY, 'psyco.dump') 44 | if not os.path.isfile(filename) and os.path.isfile(DIRECTORY): 45 | filename = DIRECTORY 46 | DIRECTORY = os.path.dirname(DIRECTORY) 47 | outfilename = filename + '.ivm' 48 | if os.path.isfile(filename): 49 | codebufs = xam.readdump(filename) 50 | f = open(outfilename, 'w') 51 | for codebuf in codebufs: 52 | if codebuf.data: 53 | data, addr, next, key = codebuf.splitheader() 54 | for freq, lst in dump(data): 55 | if len(lst) > 1: 56 | print >> f, 'psycodump(%d, [%s]).' % (freq, 57 | ', '.join(lst)) 58 | f.close() 59 | elif not os.path.isfile(outfilename): 60 | print >> sys.stderr, filename, "not found." 61 | sys.exit(1) 62 | else: 63 | print >> sys.stderr, "reusing text dump from", outfilename 64 | return outfilename 65 | 66 | 67 | if __name__ == '__main__': 68 | if len(sys.argv) <= 1: 69 | print "Usage: python ivmextract.py " 70 | print " psyco.dump is loaded from the ." 71 | sys.exit(2) 72 | for dir in sys.argv[1:]: 73 | print "'%s'." % main(dir) 74 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/ivmoptimize.py: -------------------------------------------------------------------------------- 1 | """ 2 | python ivmoptimize.py path [ path ... ] 3 | 4 | This script optimizes and regenerates the 'ivm' virtual machine 5 | used by Psyco on non-i386 platforms. You need to compile Psyco 6 | in debugging mode (see below) and use 'psyco.dumpcodebuf()' to 7 | generate one or more dump files called 'psyco.dump'. Run then 8 | the present script with the path(s) to the 'psyco.dump' file(s). 9 | Finally, you have to recompile Psyco in normal (optimized) mode. 10 | 11 | You need SWI Prolog to do that. http://www.swi-prolog.org/ 12 | 13 | To compile Psyco in debugging mode, create a file 'preferences.py' 14 | in the same directory as 'setup.py' with the following content: 15 | 16 | PROCESSOR = 'ivm' 17 | PSYCO_DEBUG = 1 18 | VERBOSE_LEVEL = 1 19 | CODE_DUMP = 1 20 | 21 | and re-run 'python setup.py build -f install'. 22 | """ 23 | import sys, os 24 | import ivmextract 25 | 26 | try: 27 | LOCALDIR = __file__ 28 | except NameError: 29 | LOCALDIR = sys.argv[0] 30 | LOCALDIR = os.path.dirname(LOCALDIR) 31 | 32 | 33 | def main(paths, maxlength=8, optmode='optimize.pl'): 34 | outfilenames = [os.path.abspath(ivmextract.main(dir)) for dir in paths] 35 | os.chdir(os.path.join(LOCALDIR, os.pardir, 'c', 'ivm', 'prolog')) 36 | g = open("mode_combine.pl", "w") 37 | g.close() # empty file 38 | g = os.popen('pl -f %s -g remotecontrol -t halt' % optmode, 'w') 39 | for fn in outfilenames: 40 | print >> g, "loaddumpfile('%s')." % fn 41 | print >> g, "measure(%d)." % maxlength 42 | print >> g, "emitmodes(255)." 43 | g.close() 44 | g = open("mode_combine.pl", "r") 45 | if not g.readline(): 46 | print >> sys.stderr, "*** the Prolog program %s failed" % optmode 47 | sys.exit(1) 48 | g.close() 49 | err = os.system('pl -f insns.pl -g main_emit -t halt') 50 | if err == 0: 51 | print 52 | print 'Done. If you compile Psyco, its ivm virtual machine will now' 53 | print 'be optimized for the usage patterns found in the dump files.' 54 | 55 | 56 | if __name__ == '__main__': 57 | if len(sys.argv) <= 1: 58 | print >> sys.stderr, __doc__ 59 | sys.exit(2) 60 | else: 61 | main(sys.argv[1:]) 62 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/manifest.py: -------------------------------------------------------------------------------- 1 | from __future__ import generators 2 | import os 3 | import py # the py lib, see http://codespeak.net/py 4 | 5 | def psycofiles(): 6 | path = py.path.svnwc(os.pardir) 7 | for p in path.visit(lambda x: x.check(versioned=1)): 8 | if p.check(dir=1): 9 | print p 10 | else: 11 | yield p.relto(path) 12 | 13 | def generate(): 14 | filename = os.path.join('..', 'MANIFEST') 15 | print 'Rebuilding %s...' % filename 16 | lst = list(psycofiles()) 17 | lst.sort() 18 | f = open(filename, 'w') 19 | for filename in lst: 20 | print >> f, filename 21 | f.close() 22 | 23 | if __name__ == '__main__': 24 | generate() 25 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/symbols.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | import xam 3 | 4 | """ 5 | This script loads a psyco.dump file (like httpxam.py) and 6 | reads on its standard input a list of addresses. For each 7 | address that it recognizes it prints the name of the 8 | corresponding symbol or the address of the code buffer 9 | that contains the address. Use this on debugger memory 10 | dumps. 11 | 12 | This could be enhanced by detecting the addresses of 13 | vinfo_t's as well. 14 | """ 15 | 16 | 17 | def main(codebufs, f): 18 | while 1: 19 | line = f.readline() 20 | if not line: 21 | break 22 | for addr in xam.lineaddresses(line): 23 | sym = xam.symbols.get(addr) 24 | if sym: 25 | print '0x%x\tis\t' % addr, xam.symtext(sym, addr) 26 | break 27 | 28 | 29 | if __name__ == '__main__': 30 | if len(sys.argv) <= 1: 31 | print "Usage: python symbols.py " 32 | print " psyco.dump is loaded from the ." 33 | sys.exit(1) 34 | DIRECTORY = sys.argv[1] 35 | del sys.argv[1] 36 | codebufs = xam.readdump(os.path.join(DIRECTORY, 'psyco.dump')) 37 | print >> sys.stderr, "Reading for addresses from stdin..." 38 | main(codebufs, sys.stdin) 39 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/vinfo_dump.py: -------------------------------------------------------------------------------- 1 | from xam import * 2 | import httpxam 3 | 4 | 5 | def load_vi_array(dumpfile, d): 6 | match = re_int.match(dumpfile.readline()) 7 | assert match 8 | count = int(match.group(1)) 9 | a = [] 10 | for i in range(count): 11 | line = dumpfile.readline() 12 | match = re_int.match(line) 13 | assert match 14 | addr = long(match.group(1)) 15 | if d.has_key(addr): 16 | vi = d[addr] 17 | else: 18 | line = dumpfile.readline() 19 | match = re_ctvinfo.match(line) 20 | if match: 21 | vi = CompileTimeVInfo(int(match.group(1)), 22 | long(match.group(2))) 23 | else: 24 | match = re_rtvinfo.match(line) 25 | if match: 26 | vi = RunTimeVInfo(long(match.group(1))) 27 | else: 28 | match = re_vtvinfo.match(line) 29 | assert match 30 | vi = VirtualTimeVInfo(long(match.group(1), 16)) 31 | d[addr] = vi 32 | vi.addr = addr 33 | vi.array = load_vi_array(dumpfile, d) 34 | a.append(vi) 35 | a.reverse() 36 | return a 37 | 38 | def main(dumpfile): 39 | import os, tempfile 40 | array = load_vi_array(dumpfile, {0: None}) 41 | text = httpxam.show_vinfos(array, {}) 42 | if os.fork() == 0: 43 | TMP = tempfile.mktemp('.html') 44 | g = open(TMP, 'w') 45 | g.write('\n') 46 | g.write(text) 47 | g.write('\n') 48 | g.close() 49 | try: 50 | os.system('xterm -e lynx -force_html %s' % TMP) 51 | finally: 52 | os.unlink(TMP) 53 | 54 | if __name__ == '__main__': 55 | import sys 56 | main(sys.stdin) 57 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/win32/README.TXT: -------------------------------------------------------------------------------- 1 | Windows users who want to explore the generated machine code need to download 2 | the following files and put them in this directory: 3 | 4 | objdump.exe: 5 | 6 | http://cvs.sourceforge.net/viewcvs.py/psyco/psyco/py-utils/win32/objdump.exe?rev=1.1&view=auto 7 | 8 | cygwin1.dll: 9 | 10 | http://cvs.sourceforge.net/viewcvs.py/psyco/psyco/py-utils/win32/cygwin1.dll?rev=1.1&view=auto 11 | 12 | 13 | Both are GPL software distributed (with source) in Red Hat's Cygwin 14 | (http://www.redhat.com/software/cygwin/). 15 | 16 | For more information on exploring the machine code see the top-level README.TXT file. 17 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/py-utils/xamsupport.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static PyObject* any_pointer(PyObject* self, PyObject* args) 4 | { 5 | char* from; 6 | int fromlen, i; 7 | long addr0, start, end, intervallen; 8 | if (!PyArg_ParseTuple(args, "ls#ll", &addr0, &from, &fromlen, &start, &end)) 9 | return NULL; 10 | 11 | intervallen = end-start; 12 | for (i=0; i<=fromlen-4; i++) 13 | { 14 | long offset = *(long*) (from+i); 15 | offset -= start; 16 | if (((unsigned long)(addr0+i+offset)) < intervallen || 17 | ((unsigned long) offset) < intervallen) 18 | return PyInt_FromLong(1); 19 | } 20 | return PyInt_FromLong(0); 21 | } 22 | 23 | static PyMethodDef XamMethods[] = { 24 | {"any_pointer", any_pointer, METH_VARARGS}, 25 | {NULL, NULL} /* Sentinel */ 26 | }; 27 | 28 | void initxamsupport() 29 | { 30 | Py_InitModule("xamsupport", XamMethods); 31 | } 32 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/test/regrtester2.py: -------------------------------------------------------------------------------- 1 | # 2 | # A less memory-exploding version of regrtester.py. 3 | # It runs only a fraction of the tests. 4 | # 5 | 6 | import sys, re, psyco 7 | 8 | 9 | assert len(sys.argv) >= 2 10 | match = re.match(r"(\d+)[/](\d+)", sys.argv[1]) 11 | assert match, "syntax: regrtester2.py n/m [-nodump] [seed]" 12 | n = int(match.group(1)) 13 | m = int(match.group(2)) 14 | assert 0 <= n < m 15 | 16 | 17 | import test.regrtest 18 | import regrtester 19 | 20 | def confirm_still_in_psyco(): 21 | return __in_psyco__ 22 | 23 | tests = [s for s in test.regrtest.findtests() 24 | if hash(s) % m == n and s not in test.regrtest.NOTTESTS] 25 | if __name__ == '__main__': 26 | if len(sys.argv) > 2 and sys.argv[2] == '-nodump': 27 | dump = 0 28 | del sys.argv[2] 29 | else: 30 | dump = 1 31 | 32 | import random, time 33 | seed = time.ctime() 34 | if len(sys.argv) > 2: 35 | seed = sys.argv[2] 36 | del sys.argv[2] 37 | print 'Random seed is %r' % seed 38 | random.seed(seed) 39 | random.shuffle(tests) 40 | 41 | fully_in_psyco = confirm_still_in_psyco() 42 | try: 43 | test.regrtest.main(tests) #, verbose=1) 44 | finally: 45 | if dump: 46 | psyco.dumpcodebuf() 47 | if fully_in_psyco: 48 | assert confirm_still_in_psyco() 49 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/test/test_base.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | """ Run base Psyco tests. 4 | """ 5 | 6 | import sys, os, random, doctest, cStringIO 7 | True,False = 1==1,1==0 8 | 9 | 10 | SEPARATOR = """ 11 | ========== %r ========== 12 | """ 13 | LASTLINE = "Tests completed." 14 | BUFFERFILE = "buffer-basetests.txt" 15 | EXPECTEDFILE = "expected-basetests.txt" 16 | INPUTSCRIPT = "input-basetexts.py" 17 | 18 | TESTS = open('btrun.py', 'r').read() 19 | 20 | 21 | if hasattr(doctest, '_extract_examples'): 22 | tests = doctest._extract_examples(TESTS) 23 | else: 24 | examples = doctest.DocTestParser().get_examples(TESTS) 25 | tests = [(example.source, example.want, example.lineno) 26 | for example in examples] 27 | 28 | # --- 29 | 30 | def main(quiet=False): 31 | PRELUDE = '' 32 | for inp, outp, line in tests[:]: 33 | if not outp: 34 | PRELUDE += inp + '\n' 35 | tests.remove((inp, outp, line)) 36 | random.shuffle(tests) # first run all tests in any order 37 | tests_again = tests[:] 38 | random.shuffle(tests_again) 39 | all_tests = tests + tests_again # then run them all again in any other order 40 | 41 | childin = open(INPUTSCRIPT, 'w') 42 | expected = open(EXPECTEDFILE, 'w') 43 | 44 | print >> childin, 'import sys' 45 | print >> childin, PRELUDE 46 | 47 | def filterline(line): 48 | if line.startswith('${') and line.endswith('}'): 49 | line = str(eval(line[2:-1])) 50 | return line 51 | 52 | for inp, outp, line in all_tests: 53 | sep = SEPARATOR % inp 54 | print >> childin, 'print %r' % sep 55 | if not quiet: 56 | print >> childin, 'print >> sys.stderr, %r' % inp.strip() 57 | print >> expected, sep 58 | print >> childin, inp 59 | outplines = [filterline(line) for line in outp.split('\n')] 60 | expected.write('\n'.join(outplines)) 61 | 62 | print >> childin, 'print %r' % LASTLINE 63 | print >> expected, LASTLINE 64 | expected.close() 65 | childin.close() 66 | 67 | # run in a child process 68 | err = os.system('"%s" %s > %s' % (sys.executable, INPUTSCRIPT, BUFFERFILE)) 69 | print >> sys.stderr 70 | if err: 71 | print >> sys.stderr, 'FAIL: child process returned %d, %d' % (err>>8, err&255) 72 | sys.exit(1) 73 | else: 74 | data1 = open(EXPECTEDFILE, 'r').read() 75 | data2 = open(BUFFERFILE, 'r').read() 76 | if data1 != data2: 77 | print >> sys.stderr, 'FAIL: different output' 78 | if sys.argv[1:2] != ['-q']: 79 | cmd = 'diff -c %s %s' % (EXPECTEDFILE, BUFFERFILE) 80 | os.system(cmd) 81 | return False 82 | else: 83 | print >> sys.stderr, 'Passed.' 84 | return True 85 | 86 | def test_main(): 87 | ok = main(quiet=True) 88 | assert ok 89 | 90 | if __name__ == '__main__': 91 | if not main(): 92 | sys.exit(1) 93 | -------------------------------------------------------------------------------- /nodebox/ext/psyco/src/test/test_misc.py: -------------------------------------------------------------------------------- 1 | import py, sys, psyco 2 | 3 | 4 | def test_index(): 5 | if sys.version_info < (2, 5): 6 | py.test.skip("for Python 2.5") 7 | 8 | class X(object): 9 | def __index__(self): 10 | return -3 11 | 12 | def f(x): 13 | return (12, 23, 34, 45)[x] 14 | 15 | res = psyco.proxy(f)(X()) 16 | assert res == 23 17 | 18 | 19 | def test_index_slice(): 20 | if sys.version_info < (2, 5): 21 | py.test.skip("for Python 2.5") 22 | 23 | class Observer(object): 24 | def __getslice__(self, i, j): 25 | return "slice", i, j 26 | def __getitem__(self, x): 27 | raise Exception("in __getitem__") 28 | class X(object): 29 | def __index__(self): 30 | return 5 31 | class Y(object): 32 | def __index__(self): 33 | return -2 34 | 35 | def f(o, x, y): 36 | return o[x:y] 37 | 38 | res = psyco.proxy(f)(Observer(), X(), Y()) 39 | assert res == ("slice", 5, -2) 40 | 41 | def test_index_repeat(): 42 | if sys.version_info < (2, 5): 43 | py.test.skip("for Python 2.5") 44 | 45 | class X(object): 46 | def __index__(self): 47 | return 3 48 | 49 | def f(x): 50 | return (12, 23) * x 51 | 52 | res = psyco.proxy(f)(X()) 53 | assert res == (12, 23, 12, 23, 12, 23) 54 | 55 | def test_slice_overflow(): 56 | class X(object): 57 | def __len__(self): 58 | return sys.maxint 59 | def __getslice__(self, i, j): 60 | return i, j 61 | def f(X): 62 | return X()[-(2**100):2**100] 63 | 64 | res = psyco.proxy(f)(X) 65 | assert res == f(X) 66 | 67 | def test_id(): 68 | def f(x): 69 | return id(x) 70 | obj = [] 71 | res = psyco.proxy(f)(obj) 72 | assert res == id(obj) 73 | 74 | def test_math_module(): 75 | import math 76 | global _operation 77 | for name in ["acos", "asin", "atan", "ceil", "cos", "cosh", "exp", 78 | "fabs", "floor", "sin", "sinh", "sqrt", "tan", "tanh"]: 79 | _operation = getattr(math, name) 80 | 81 | def tester(a): 82 | return _operation(a) 83 | res = psyco.proxy(tester)(0.17) 84 | assert abs(res - _operation(0.17)) < 1e6 85 | 86 | def tester(a): 87 | return _operation(*a) 88 | res = psyco.proxy(tester)((0.71,)) 89 | assert abs(res - _operation(0.71)) < 1e6 90 | 91 | for name in ["atan2", "fmod", "hypot", "pow"]: 92 | _operation = getattr(math, name) 93 | 94 | def tester(a, b): 95 | return _operation(a, b) 96 | res = psyco.proxy(tester)(0.17, 0.081) 97 | assert abs(res - _operation(0.17, 0.081)) < 1e6 98 | 99 | def tester(a): 100 | return _operation(*a) 101 | res = psyco.proxy(tester)((0.71, 0.2643)) 102 | assert abs(res - _operation(0.71, 0.2643)) < 1e6 103 | -------------------------------------------------------------------------------- /nodebox/ext/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | 3 | bezier = Extension("bezier", sources=["bezier.c"]) 4 | geometry = Extension("geometry", sources=["geometry.c"]) 5 | noise = Extension("noise", sources=["noise.c"]) 6 | 7 | setup( 8 | name = "extensions", 9 | version = "1.0", 10 | author = "Tom De Smedt, Frederik De Bleser", 11 | description = "Fast C Bezier, geometry and noise math.", 12 | ext_modules = [bezier, geometry, noise] 13 | ) -------------------------------------------------------------------------------- /nodebox/font/Droid Sans Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Sans Mono.ttf -------------------------------------------------------------------------------- /nodebox/font/Droid Sans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Sans-Bold.ttf -------------------------------------------------------------------------------- /nodebox/font/Droid Sans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Sans.ttf -------------------------------------------------------------------------------- /nodebox/font/Droid Serif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Serif-Bold.ttf -------------------------------------------------------------------------------- /nodebox/font/Droid Serif-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Serif-BoldItalic.ttf -------------------------------------------------------------------------------- /nodebox/font/Droid Serif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Serif-Italic.ttf -------------------------------------------------------------------------------- /nodebox/font/Droid Serif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/font/Droid Serif-Regular.ttf -------------------------------------------------------------------------------- /nodebox/graphics/__init__.py: -------------------------------------------------------------------------------- 1 | import bezier 2 | import context 3 | import geometry 4 | import physics 5 | import shader 6 | 7 | from noise import noise 8 | from context import * 9 | 10 | physics.line = context.line 11 | physics.ellipse = context.ellipse 12 | physics.Text = context.Text 13 | 14 | #----------------------------------------------------------------------------------------------------- 15 | # Expose the canvas and some common canvas properties on global level. 16 | # Some magic constants from NodeBox are commands here: 17 | # - WIDTH => width() 18 | # - HEIGHT => height() 19 | # - FRAME => frame() 20 | 21 | canvas = Canvas() 22 | 23 | def size(width=None, height=None): 24 | if width is not None: 25 | canvas.width = width 26 | if height is not None: 27 | canvas.height = height 28 | return canvas.size 29 | 30 | def speed(fps=None): 31 | if fps is not None: 32 | canvas.fps = fps 33 | return canvas.fps 34 | 35 | def frame(): 36 | return canvas.frame 37 | 38 | def clear(): 39 | canvas.clear() -------------------------------------------------------------------------------- /nodebox/graphics/noise.py: -------------------------------------------------------------------------------- 1 | from random import random 2 | from math import floor 3 | 4 | class PerlinNoise: 5 | 6 | def __init__(self, permutation=None): 7 | """ Initializes a Perlin noise generator with the given permutation pattern, 8 | which is a list of 256 integers between 0-255. 9 | """ 10 | if not permutation: 11 | permutation = [random()*256 for i in range(256)] 12 | self._init([int(x) for x in permutation] * 2) 13 | 14 | def _init(self, p): 15 | self._p = p 16 | def _fade(self, t): 17 | return t * t * t * (t * (t * 6 - 15) + 10) 18 | def _lerp(self, t, a, b): 19 | return a + t * (b - a) 20 | def _grad(self, hash, x, y, z): 21 | u, v, h = x, y, hash & 15 22 | if h >= 8: u = y 23 | if h >= 4: 24 | v = x 25 | if h != 12 and h != 14: v = z 26 | if (h&1) != 0: u = -u 27 | if (h&2) != 0: v = -v 28 | return u + v 29 | 30 | def generate(self, x, y=0, z=0): 31 | """ Returns a smooth value between -1.0 and 1.0. 32 | The x, y, z parameters determine the coordinates in the noise landscape. 33 | Since the landscape is infinite, the actual value of a coordinate doesn't matter, 34 | only the distance between successive steps. 35 | The smaller the difference between steps, the smoother the noise sequence. 36 | Steps between 0.005 and 0.1 usually work best. 37 | """ 38 | lerp, grad, fade, p = self._lerp, self._grad, self._fade, self._p 39 | # Find unit cuve that contains point (x,y,z). 40 | X = int(floor(x)) & 255 41 | Y = int(floor(y)) & 255 42 | Z = int(floor(z)) & 255 43 | # Find relative (x,y,z) of point in cube. 44 | # Compute fade curves. 45 | x, y, z = x-floor(x), y-floor(y), z-floor(z) 46 | u, v, w = fade(x), fade(y), fade(z) 47 | # Hash coordinates of the cube corners. 48 | A = Y + p[X] 49 | B = Y + p[X+1] 50 | AA, AB, BA, BB = Z+p[A], Z+p[A+1], Z+p[B], Z+p[B+1] 51 | # Add blended results from the cube corners. 52 | return lerp(w, 53 | lerp(v, lerp(u, grad(p[AA ], x , y , z ), 54 | grad(p[BA ], x-1, y , z )), 55 | lerp(u, grad(p[AB ], x , y-1, z ), 56 | grad(p[BB ], x-1, y-1, z ))), 57 | lerp(v, lerp(u, grad(p[AA+1], x , y , z-1), 58 | grad(p[BA+1], x-1, y , z-1)), 59 | lerp(u, grad(p[AB+1], x , y-1, z-1), 60 | grad(p[BB+1], x-1, y-1, z-1)))) 61 | 62 | try: 63 | # Fast C implementations: 64 | from nodebox.ext.noise import init, generate 65 | PerlinNoise._init = init 66 | PerlinNoise.generate = generate 67 | except: 68 | pass 69 | 70 | _generator = PerlinNoise() 71 | def noise(x, y=0, z=0): 72 | return _generator.generate(x, y, z) 73 | -------------------------------------------------------------------------------- /nodebox/gui/__init__.py: -------------------------------------------------------------------------------- 1 | from controls import * -------------------------------------------------------------------------------- /nodebox/gui/theme/Droid Sans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/Droid Sans-Bold.ttf -------------------------------------------------------------------------------- /nodebox/gui/theme/Droid Sans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/Droid Sans.ttf -------------------------------------------------------------------------------- /nodebox/gui/theme/action-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/action-close.png -------------------------------------------------------------------------------- /nodebox/gui/theme/action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/action.png -------------------------------------------------------------------------------- /nodebox/gui/theme/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/button.png -------------------------------------------------------------------------------- /nodebox/gui/theme/field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/field.png -------------------------------------------------------------------------------- /nodebox/gui/theme/flag-checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/flag-checked.png -------------------------------------------------------------------------------- /nodebox/gui/theme/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/flag.png -------------------------------------------------------------------------------- /nodebox/gui/theme/flag.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/flag.psd -------------------------------------------------------------------------------- /nodebox/gui/theme/knob-socket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/knob-socket.png -------------------------------------------------------------------------------- /nodebox/gui/theme/knob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/knob.png -------------------------------------------------------------------------------- /nodebox/gui/theme/panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/panel.png -------------------------------------------------------------------------------- /nodebox/gui/theme/slider-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/slider-handle.png -------------------------------------------------------------------------------- /nodebox/gui/theme/slider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nodebox/nodebox-opengl/2c50526ef14dea5bc3802b7fda08871919d62ac4/nodebox/gui/theme/slider.png -------------------------------------------------------------------------------- /nodebox/sound/__init__.py: -------------------------------------------------------------------------------- 1 | from process import * -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup 3 | from setuptools import find_packages 4 | 5 | # Utility function to read the README file. 6 | # From http://packages.python.org/an_example_pypi_project/setuptools.html. 7 | def read(fname): 8 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 9 | 10 | setup( name = "NodeBox for OpenGL", 11 | version = "1.7", 12 | description = "NodeBox for OpenGL (NOGL) is a free, cross-platform library " 13 | "for generating 2D animations with Python programming code.", 14 | long_description = read("README.txt"), 15 | keywords = "2d graphics sound physics games multimedia", 16 | license = "BSD", 17 | author = "Tom De Smedt", 18 | url = "http://www.cityinabottle.org/nodebox/", 19 | packages = find_packages(), 20 | package_data = {"nodebox.gui": ["theme/*"]}, 21 | install_requires = ["pyglet",], 22 | classifiers = [ 23 | "Development Status :: 4 - Beta", 24 | "Environment :: MacOS X", 25 | "Environment :: Win32 (MS Windows)", 26 | "Environment :: X11 Applications", 27 | "Intended Audience :: Developers", 28 | "Intended Audience :: Education", 29 | "License :: OSI Approved :: BSD License", 30 | "Operating System :: MacOS :: MacOS X", 31 | "Operating System :: Microsoft :: Windows", 32 | "Operating System :: POSIX :: Linux", 33 | "Programming Language :: Python", 34 | "Topic :: Artistic Software", 35 | "Topic :: Games/Entertainment", 36 | "Topic :: Multimedia :: Graphics", 37 | "Topic :: Scientific/Engineering :: Visualization", 38 | "Topic :: Software Development :: Libraries :: Python Modules", 39 | ], 40 | ) 41 | --------------------------------------------------------------------------------