Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Boisture <jboisture@jboisture-laptop.(none)>2009-07-24 22:00:00 (GMT)
committer Jamie Boisture <jboisture@jboisture-laptop.(none)>2009-07-24 22:00:00 (GMT)
commitca210cf65d417c9d6710cde14560233f4d847c77 (patch)
tree8e15d5a4586d8957eac55c91268b8fa87331b3d0
parent0d622e6c2fe08c9d06ac03aa6d28e49b2f66da21 (diff)
added the gasp library to /library/pippy
-rw-r--r--library/pippy/gasp/__init__.py2
-rw-r--r--library/pippy/gasp/api.py534
-rw-r--r--library/pippy/gasp/backend.py619
-rw-r--r--library/pippy/gasp/color.py145
4 files changed, 1300 insertions, 0 deletions
diff --git a/library/pippy/gasp/__init__.py b/library/pippy/gasp/__init__.py
new file mode 100644
index 0000000..15651e6
--- /dev/null
+++ b/library/pippy/gasp/__init__.py
@@ -0,0 +1,2 @@
+from api import *
+import color
diff --git a/library/pippy/gasp/api.py b/library/pippy/gasp/api.py
new file mode 100644
index 0000000..9a88ce7
--- /dev/null
+++ b/library/pippy/gasp/api.py
@@ -0,0 +1,534 @@
+import backend
+import math
+import random
+import time
+
+# diffrent update_when values
+NOTHING = "Nothing"
+MOUSE_PRESSED = "Mouse_Pressed"
+KEY_PRESSED = "Key_Pressed"
+
+#============================ SCREEN FUNCTIONS ==============================
+
+class Screen:
+ """
+ Defines the graphics window in which objects can be created
+ """
+ def __init__(self, width, height,
+ title="Gasp", background=(255,255,255), back_end=None):
+ global backend
+ backend = back_end
+ self.width = width
+ self.height = height
+ self.title = title
+ self.background = backend.color_convert(background)
+
+ # backend.check_screen_atts(self) # checks the variables
+ backend.create_screen(self)
+
+
+
+def begin_graphics(width=-1, height=-1, title="Gasp",
+ background=(255,255,255), back_end=backend):
+ """
+ Initialize a graphics window in GASP
+ """
+ global screen
+ screen = Screen(width, height, title, background, back_end)
+
+def end_graphics():
+ """
+ Close the graphics window
+ """
+ backend.end()
+
+def clear_screen():
+ """
+ Removes all objects from the graphics window
+ """
+ backend.clear_screen()
+
+
+def remove_from_screen(obj):
+ """
+ Removes a specified object from the graphics window
+ """
+ backend.remove(obj)
+
+#================================ Point =====================================
+
+class Point:
+ """
+ Creates a point object with an x and y attribute
+ """
+ def __init__(self, *args):
+ if len(args) == 1:
+ self.x, self.y = args[0]
+ else:
+ self.x, self.y = args
+
+ def __str__(self):
+ return "A Point instance at (%i, %i) \n" %(self.x, self.y)
+
+ def distance(self, other):
+ ''' The distance between two points '''
+ return math.sqrt(float((other.x - self.x))**2 +
+ (float(other.y - self.y))**2)
+
+
+def make_it_a_point(point):
+ """
+ Takes something and makes it into a point if it isn't one already
+ """
+ if isinstance(point, Point):
+ return point
+ else:
+ return Point(point)
+
+
+
+class Shape:
+ def __init__(self, center, filled=False, color=(0,0,0), thickness=1):
+ self.center = make_it_a_point(center)
+ self.filled = filled
+ self.color = backend.color_convert(color)
+ self.thickness = thickness
+ self.rot = 0
+ self.key = time.time()*random.random()
+
+ def move_by(self,x,y):
+ if self.on_screen:
+ self.topleft = (self.topleft[0]+x,self.topleft[1]+y)
+ self.center = Point(self.center.x+x,self.center.y+y)
+ else: move_by(self,x,y)
+
+ def move_to(self,pos):
+ if self.on_screen:
+ x,y = pos[0]-self.center.x,pos[1]-self.center.y
+ self.topleft = (self.topleft[0]+x,self.topleft[1]+y)
+ self.center = Point(self.center.x+x,self.center.y+y)
+ else: move_to(self,pos)
+
+ def draw(self,context):
+ context.save()
+ x,y = backend.flip_coords(self.topleft)
+ context.translate(x,y-self.surface.get_height())
+ if self.rot != 0:
+ context.translate(self.surface.get_width()/2,self.surface.get_height()/2)
+ context.rotate(self.rot)
+ context.translate(-1*self.surface.get_width()/2,-1*self.surface.get_height()/2)
+ context.set_source_surface(self.surface)
+ context.paint()
+ context.restore()
+
+class Plot(Shape):
+ """
+ Allows screen objects to be placed in the graphics window
+ """
+ def __init__(self, pos, color=(0,0,0), size=1):
+ self.center = make_it_a_point(pos)
+ self.color = color
+ self.size = size
+ self.key = time.time()*random.random()
+ self.on_screen = False
+ screen.action_objects.put([["plot",self],"new object"])
+
+
+class Line(Shape):
+ """
+ Allows the creation of lines in the graphics window
+ """
+ def __init__(self, start, end, color=(0,0,0),thickness=1):
+ self.start = make_it_a_point(start)
+ self.end = make_it_a_point(end)
+ self.center = make_it_a_point(((start[0]+end[0])/2,(start[1]+end[1])/2))
+ self.color = backend.color_convert(color)
+ self.thickness=thickness
+ self.key = time.time()*random.random()
+ self.on_screen = False
+ screen.action_objects.put([["line",self],"new object"])
+
+ def move_by(self,x,y):
+ if self.on_screen:
+ self.topleft = (self.topleft[0]+x,self.topleft[1]+y)
+ self.center = Point(self.center.x+x,self.center.y+y)
+ else: move_by(self,x,y)
+
+ def move_to(self,pos):
+ if self.on_screen:
+ x,y = pos[0]-self.center.x,pos[1]-self.center.y
+ self.topleft = (self.topleft[0]+x,self.topleft[1]+y)
+ self.center = Point(self.center.x+x,self.center.y+y)
+ else: move_to(self,pos)
+
+ def __repr__(self):
+ return "A Line instance from (%d, %d) to (%d, %d)" % \
+ (self.start.x, self.start.y, self.end.x, self.end.y)
+
+class Box(Shape):
+ """
+ Allows the creation of squares and rectangles in the graphics window
+ """
+ def __init__(self, lower_left_corner, width, height,
+ filled=False, color=(0,0,0), thickness=1):
+ self.center = Point((int(lower_left_corner[0] + width/2.0),
+ int(lower_left_corner[1] + height/2.0)))
+ self.height = height
+ self.width = width
+ self.on_screen = False
+ Shape.__init__(self, self.center, filled, color, thickness)
+ screen.action_objects.put([["box",self],"new object"])
+
+ def move_to(self,pos):
+ if self.on_screen:
+ x,y = pos[0]-self.topleft[0],pos[1]-self.topleft[1]
+ self.topleft = (self.topleft[0]+x,self.topleft[1]+y)
+ self.center = Point(self.center.x+x,self.center.y+y)
+ else:
+ move_to(self,pos)
+
+ def __repr__(self):
+ return "Box instance at (%d, %d) with width %d and height %d" % \
+ (self.center.x, self.center.y, self.width, self.height)
+
+class Polygon(Shape):
+ """
+ Allows the creation of polygons in the graphics window
+ """
+ def __init__(self, points, filled=False, color=(0,0,0),thickness=1):
+ self.thickness = thickness
+ self.points = points
+ x_values = []
+ y_values = []
+ for point in self.points:
+ x_values.append(point[0])
+ y_values.append(point[1])
+ self.height = (max(y_values) - min(y_values))+self.thickness*2
+ self.width = (max(x_values) - min(x_values))+self.thickness*2
+ self.topleft = (min(x_values)-self.thickness, min(y_values)-self.thickness)
+ self.center = Point(self.width/2 + min(x_values), self.height/2 +
+ min(y_values))
+ self.on_screen = False
+ Shape.__init__(self, self.center, filled, color)
+ screen.action_objects.put([["polygon",self],"new object"])
+
+ def __repr__(self):
+ return "Polygon instance at (%i, %i) with the points:\n %t" % \
+ (self.center.x , self.center.y, self.points)
+
+class Circle(Shape):
+ """
+ Allows the creation of circles in the graphics window
+ """
+ def __init__(self, center, radius,
+ filled=False, color=(0,0,0), thickness=1):
+ Shape.__init__(self, center, filled, color, thickness)
+ self.radius = radius
+ self.on_screen = False
+ screen.action_objects.put([["circle",self],"new object"])
+ #backend.create_circle(self)
+
+ def __repr__(self):
+ return "Circle instance at (%d, %d) with radius %d" % \
+ (self.center.x, self.center.y, self.radius)
+
+class Arc(Shape):
+ """
+ Allows the creation of arcs in the graphics window
+ """
+ def __init__(self, center, radius, start_angle, end_angle,
+ filled=False, color=(0,0,0), thickness=1):
+ Shape.__init__(self, center, filled, color, thickness)
+ self.radius = radius
+ self.start_angle = 360-start_angle
+ self.end_angle = 360-end_angle
+ self.on_screen = False
+ screen.action_objects.put([["arc",self],"new object"])
+
+ def __repr__(self):
+ return "Arc instance at (%d, %d) with start angle %d and end angle %d" \
+ % (self.center.x, self.center.y, self.start_angle, self.end_angle)
+
+
+
+class Oval(Shape):
+ """
+ Allows the creation of circles in the graphics window
+ """
+ def __init__(self, center, width, height,
+ filled=False, color=(0,0,0), thickness=1):
+ Shape.__init__(self, center, filled, color, thickness)
+ self.width = width
+ self.height = height
+ self.on_screen = False
+ screen.action_objects.put([["oval",self],"new object"])
+
+ def __repr__(self):
+ return "Oval instance at (%d, %d) with width %d and height %d" % \
+ (self.center.x, self.center.y, self.width, self.height)
+
+class Image(Shape):
+ """
+ Allows the placing of images in the graphics window
+ """
+ def __init__(self, file_path, center, width=0, height=0):
+ self.path_name = file_path
+ self.center = Point(backend.flip_coords(center))
+ self.width = width
+ self.height = height
+ self.key = time.time()*random.random()
+ self.on_screen = False
+ screen.action_objects.put([["image",self],"new object"])
+
+ def draw(self,context):
+ context.save()
+ context.translate(*self.topleft)
+ context.translate(self.width/2,self.height/2)
+ context.rotate(self.rot)
+ context.translate(-1*self.width/2,-1*self.height/2)
+ context.save()
+ context.scale(self.scale[0],self.scale[1])
+ context.set_source_pixbuf(self.pixbuf,0,0)
+ context.paint()
+ context.restore()
+ context.restore()
+
+ def move_by(self,x,y):
+ if self.on_screen:
+ self.topleft = (self.topleft[0]+x,self.topleft[1]-y)
+ self.center = Point(self.center.x+x,self.center.y-y)
+ else:
+ move_by(self,x,y)
+
+ def move_to(self,pos):
+ if self.on_screen:
+ x,y = pos[0]-self.center.x,pos[1]-self.center.y
+ self.topleft = (self.topleft[0]+x,self.topleft[1]-y)
+ self.center = Point(self.center.x+x,self.center.y-y)
+ else:
+ move_to(self,pos)
+
+ def __repr__(self):
+ return "Image instance at (%i, %i) from the file %s" % \
+ (self.center.x, self.center.y, self.path_name)
+
+
+def move_to(obj, pos):
+ """
+ Moves a screen object to a specified location
+ """
+ screen.action_objects.put([obj,"move_to",pos])
+
+
+def move_by(obj, dx, dy):
+ """
+ Moves a screen object by specified X and Y amounts
+ """
+ screen.action_objects.put([obj,"move_by",(dx,dy)])
+
+def get_text_length(text):
+ return backend.get_text_length(text)
+
+
+def rotate_to(obj, angle):
+ """
+ Rotates a screen object to a specified angle
+ """
+ screen.action_objects.put([obj,"rotate_to",math.radians(angle)])
+
+
+def rotate_by(obj, angle):
+ """
+ Rotates a screen object by a specified angle
+ """
+ screen.action_objects.put([obj,"rotate_by",math.radians(angle)])
+
+
+# =============================== Text ======================================
+
+class Text(Shape):
+ """
+ Allows the creation of text in the graphics window
+ """
+ def __init__(self, text, pos, color=(0,0,0), size=12):
+ self.text = text
+ self.color = backend.color_convert(color)
+ self.size = size
+ self.pos = backend.flip_coords(pos)
+ self.key = time.time()*random.random()
+ self.on_screen = False
+ screen.action_objects.put([["text",self],"new object"])
+ #screen.action_objects.put(obj)
+ #screen.objects.append(obj)
+
+ def draw(self, context):
+ context.save()
+ context.move_to(*self.pos)
+ if self.rot != 0:
+ context.rotate(self.rot)
+ context.set_source_rgb(*self.color)
+ context.set_font_size(self.size)
+ context.show_text(self.text)
+ context.restore()
+
+
+ def move_to(self,pos):
+ self.pos = backend.flip_coords(pos)
+ move_to(self,pos)
+
+ def move_by(self,dx,dy):
+ self.pos = (self.pos[0]+dx,self.pos[1]-dy)
+ move_by(self,dx,dy)
+
+# ============================ Text Entry ==================================
+
+def Text_Entry(message="Enter Text:", pos=(0,0), color=(0,0,0), size=12):
+ entry = backend.Entry(message,pos,color,size)
+ return entry.entry
+
+
+"""# =============================== Sound =====================================
+
+class Sound:
+ ""
+ Allows the creation and playback of sounds
+ ""
+ def __init__(self, file_path):
+ self.path = file_path
+ self.filename = ''.join(file_path.split('.')[:-1]).split('/')[-1]
+
+ def play(self):
+ backend.play_sound(self)
+
+ def stop(self):
+ backend.stop_sound(self)
+
+
+def create_sound(file_path):
+ ""
+ Creates a sound object from a file
+ ""
+ return Sound(file_path)
+
+
+def play_sound(sound):
+ ""
+ Starts to play a specified sound object
+ ""
+ sound.play()
+
+
+def stop_sound(sound):
+ ""
+ Stops the playback of a specified sound object
+ ""
+ sound.stop()"""
+
+# =========================== Event Functions ==============================
+
+def mouse_position():
+ """
+ Returns a Point() at the mouse's current position
+ """
+ pos = backend.mouse_pos()
+ return backend.flip_coords((int(pos[0]),int(pos[1])))
+
+
+def mouse_buttons():
+ """
+ Returns a dictionary of the current state of the mouse buttons
+ """
+ return backend.mouse_state()
+
+
+def keys_pressed():
+ """
+ Returns a list of all of the keys being pressed
+ """
+ return backend.keys()
+
+def key_pressed(key):
+ return key in backend.keys()
+
+def screen_size():
+ return backend.get_screen_size()
+
+# ============================= GASP TOOLS ==================================
+
+def screen_shot(filename="screen_shot"):
+ """
+ Saves a screenshot to a specified file name
+ """
+ backend.screen_picture(filename)
+
+def random_between(num1, num2):
+ if (num1 == num2):
+ return num1
+ elif (num1 > num2):
+ return random.randint(num2, num1)
+ else:
+ return random.randint(num1, num2)
+
+read_string = raw_input
+
+
+def read_number(prompt='Please enter a number: '):
+ """
+ Prompts the user to enter a number
+ """
+ while True:
+ try:
+ result = eval(raw_input(prompt))
+ if isinstance(result, (float, int)):
+ return result
+ print "But that wasn't a number!"
+ except:
+ print "But that wasn't a number!"
+
+
+def read_yesorno(prompt='Yes or no? '):
+ """
+ Asks the user to enter yes or no
+ """
+ while True:
+ result = raw_input(prompt)
+ result = result.lower()
+ if result=='yes' or result=='y': return True
+ if result=='no' or result=='n': return False
+ print "Please answer yes or no."
+
+# =============================== Time =====================================
+
+def set_speed(speed):
+ """
+ Sets program frame rate in frames per second
+ """
+ backend.set_frame_rate(speed)
+
+
+def update_when(event_type):
+ """
+ Event Types include
+ 'key_pressed'
+ 'mouse_clicked'
+ 'next_tick'
+ """
+ if event_type == "key_pressed":
+ return backend.update_when(event_type)
+ else: backend.update_when(event_type)
+
+def sleep(duration):
+ """
+ Sleeps for a length of time
+ """
+ backend.sleep(duration)
+
+
+# ============================== main =====================================
+
+if __name__ == "__main__":
+ """
+ If api.py is run independently, this runs the test suite
+ """
+ import doctest
+ doctest.testmod()
diff --git a/library/pippy/gasp/backend.py b/library/pippy/gasp/backend.py
new file mode 100644
index 0000000..1118bbf
--- /dev/null
+++ b/library/pippy/gasp/backend.py
@@ -0,0 +1,619 @@
+import os
+import sys
+import math
+import multiprocessing
+import gobject
+import time
+import gtk
+import cairo
+
+
+# diffrent update_when values
+NOTHING = "Nothing"
+MOUSE_PRESSED = "Mouse_Pressed"
+KEY_PRESSED = "Key_Pressed"
+screen = None
+
+#============================= SCREEN FUNCTIONS ================================
+
+def check_screen_atts(screen_obj):
+
+ try: # checks width attribute
+ width = int(screen_obj.width)
+ self.width = width
+ except:
+ raise GaspException("Width is not a viable type. Width = %d " % screen_obj.width)
+
+ try: # checks height attribute
+ height = int(height)
+ self.height = height
+ except:
+ raise GaspException("Height is not a vaiable type. Height = %d" % screen_obj.height)
+
+
+def shutdown(type, value, traceback):
+ end()
+ sys.__excepthook__(type, value, traceback)
+
+
+def create_screen(screen_obj): # takes a Screen() objects.
+ global screen
+ #create the screen obj
+ screen = screen_obj
+
+ #create the window and set its size and title
+ screen.window = gtk.Window()
+ screen.window.set_title(screen.title)
+ if screen.width < 0 or screen.height < 0:
+ screen.window.maximize()
+ screen.width = screen.window.get_screen().get_width()
+ screen.height = screen.window.get_screen().get_height()
+ screen.window.set_default_size(screen.width, screen.height)
+ screen.window.set_resizable(False)
+
+ #create the drawing area
+ screen.drawing_area = gtk.DrawingArea()
+ screen.window.add(screen.drawing_area)
+ screen.drawing_area.set_size_request(screen.width,screen.height)
+ screen.drawing_area.show()
+
+ screen.frame_rate = 40
+ screen.last_tick = time.time()
+
+ #set up the event handling
+ screen.drawing_area.set_events( gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.BUTTON1_MOTION_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+ screen.drawing_area.connect("motion_notify_event", mouse_move)
+ screen.drawing_area.connect('button-press-event', mouse_press)
+ screen.drawing_area.connect('button-release-event', mouse_release)
+ screen.window.connect("key-press-event",key_pressed)
+ screen.window.connect("key-release-event",key_released)
+ screen.window.connect('delete-event', quit)
+ screen.keys_pressed = []
+ screen.mouse_pos = (-1,-1)
+ screen.mouse_state = {"left":0,"middle":0,"right":0}
+ screen.mouse_buttons = ["left","middle","right"]
+
+ #set the window icon and show the window
+ screen.window.show()
+
+ #create the buffer to draw to
+ screen.buffer = gtk.gdk.Pixmap(screen.drawing_area.window, screen.width, screen.height)
+ screen.gc = gtk.gdk.GC(screen.buffer)
+ screen.objects = []
+ screen.action_objects = multiprocessing.Queue()
+ screen.keys = multiprocessing.Queue()
+ screen.process = multiprocessing.current_process()
+ screen.mouse = multiprocessing.Queue()
+
+ #start the thread that will update the gui by calling main_iteration
+ screen.updater = Updater(screen)
+
+ screen.screenshot = False
+ screen.filename = ""
+ screen.update_when = NOTHING
+ screen.update1 = multiprocessing.Queue()
+ screen.update2 = multiprocessing.Queue()
+ #if this is called to often key and mouse events will be slow
+ screen.sprites = 0
+
+ screen.text_entry = None
+ screen.entry_done = multiprocessing.Queue()
+ screen.updater.daemon = True
+ screen.updater.start()
+
+def quit(widget=None, event=None):
+ screen.updater.running = False
+ for queue in [screen.action_objects, screen.keys, screen.mouse, screen.update1, screen.update2, screen.entry_done]:
+ while not queue.empty():
+ queue.get()
+ os.popen("kill " +str(os.getppid()))
+ #screen.process.terminate()
+
+class Updater( multiprocessing.Process ):
+ """thread that handles the updateing of the GUI
+ This thread does not update the graphics"""
+ def __init__(self,screen):
+ self.screen = screen
+ multiprocessing.Process.__init__(self)
+ self.objects = []
+ self.sprites = 0
+
+ def create_obj(self,obj):
+ if obj[0] == "circle":
+ create_circle(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "box":
+ create_box(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "plot":
+ plot(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "line":
+ create_line(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "polygon":
+ create_polygon(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "arc":
+ create_arc(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "oval":
+ create_oval(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "image":
+ create_image(obj[1])
+ self.objects.append(obj[1])
+ elif obj[0] == "text":
+ create_text(obj[1])
+ self.objects.append(obj[1])
+
+ def update(self,widget=None, event=None):
+ self.check_queues()
+ if not self.running: return False
+ context = self.screen.buffer.cairo_create() #create a cairo context the draw to buffer
+ #draw background
+ context.set_source_rgb(*self.screen.background)
+ context.rectangle(0, 0, *self.screen.drawing_area.window.get_size())
+ context.fill()
+ #draw all of the objects on screen
+ if screen.text_entry:
+ screen.text_entry.draw(context)
+ else:
+ for i in self.objects:
+ i.draw(context)
+ #take a screenshot it must be hear because it requires an active cairo context
+ if self.screen.screenshot:
+ print "taking screen shot"
+ self.screen.screenshot = False
+ surf = context.get_target()
+ surf.write_to_png(self.screen.filename)
+ #draw the buffer onto the actual drawing area
+ self.screen.drawing_area.window.draw_drawable(self.screen.gc,self.screen.buffer,0,0,0,0,-1,-1,)
+ #return True
+ #make sure that the number of sprites on screen hasn't changed
+ if self.sprites == len(self.objects):
+ return True
+ #if the number of sprites has changed it will end this time out
+ #and begin a new one with more or less time difference depending
+ #on the number of sprites on screen
+ #this makes sure it is not updated to often
+ if self.sprites != len(self.objects):
+ gobject.timeout_add(40+len(self.objects)/10,self.update)
+ self.sprites = len(self.objects)
+ return False
+
+ def check_queues(self):
+ while not self.screen.update1.empty():
+ self.screen.update_when = self.screen.update1.get()
+ while not self.screen.action_objects.empty():
+ obj=screen.action_objects.get()
+ if obj[1] =="end_graphics":
+ self.running = False
+ elif obj[1] == "text entry":
+ self.screen.text_entry = obj[0]
+ elif obj[1] =="remove_all":
+ self.objects = []
+ elif obj[1] == "screen shot":
+ self.screen.screenshot = True
+ self.screen.filename = obj[0]
+ elif obj[1] == "new object":
+ self.create_obj(obj[0])
+ else:
+ for i in self.objects:
+ if i.key == obj[0].key:
+ if obj[1] == "remove":
+ self.objects.remove(i)
+ if obj[1] == "move_to":
+ i.move_to(obj[2])
+ if obj[1] == "move_by":
+ i.move_by(obj[2][0],obj[2][1])
+ if obj[1] == "rotate_by":
+ i.rot += obj[2]
+ if obj[1] == "rotate_to":
+ i.rot = obj[2]
+
+ def run(self):
+ gobject.timeout_add(40, self.update) #this will call update periodically
+ self.running = True
+ #while threading.enumerate()[0].isAlive() and self.running:
+ #if threading.activeCount() < 2: self.killPID()
+ while self.running:
+ sleep(1.0/100.0)
+ gtk.main_iteration(False)
+
+
+#============================== EVENT HANDLER FUNCTIONS ===============================
+
+def key_pressed(widget, event):
+ if event.keyval == 65307: quit()
+ if screen.text_entry:
+ if event.keyval == 65293:
+ screen.entry_done.put(screen.text_entry.entry)
+ screen.text_entry = None
+ elif event.keyval == 65288:
+ screen.text_entry.entry = screen.text_entry.entry[:-1]
+ else:
+ screen.text_entry.entry += event.string
+ else:
+ string = ""
+ if event.keyval == 65364:string = "down"
+ elif event.keyval == 65362:string = "up"
+ elif event.keyval == 65361:string = "left"
+ elif event.keyval == 65363:string = "right"
+ elif event.keyval == 65293:string = "enter"
+ elif event.keyval == 65506:string = "shift"
+ elif event.keyval == 65289:string = "tab"
+ else:string = event.string
+ if not string in screen.keys_pressed: screen.keys.put([string,"pressed"])
+ if screen.update_when == KEY_PRESSED: screen.update2.put(NOTHING)
+
+def key_released(widget, event):
+ string = ""
+ if event.keyval == 65364:string = "down"
+ elif event.keyval == 65362:string = "up"
+ elif event.keyval == 65361:string = "left"
+ elif event.keyval == 65363:string = "right"
+ elif event.keyval == 65293:string = "enter"
+ elif event.keyval == 65506:string = "shift"
+ elif event.keyval == 65289:string = "tab"
+ else:string = event.string
+ screen.keys.put([string,"released"])
+
+def mouse_press(widget, event):
+ screen.mouse.put(["press",screen.mouse_buttons[event.button-1],1])
+ if screen.update_when == MOUSE_PRESSED:
+ screen.update_when = NOTHING
+
+
+def mouse_release(widget, event):
+ screen.mouse.put(["press",screen.mouse_buttons[event.button-1],0])
+
+def mouse_move(widget, event):
+ screen.mouse.put(["position",(event.x,event.y)])
+
+
+
+def require_screen(func):
+ def wrapper(*args):
+ if not screen:
+ raise GaspException("No graphics window initialized. Please call begin_graphics().")
+ return func(*args)
+
+ return wrapper
+
+
+#============================== SHAPE FUNCTIONS ===============================
+@require_screen
+def plot(obj): # must be passed a Plot()
+ obj.rot = 0
+ obj.topleft = (obj.center.x-obj.size,obj.center.y-obj.size)
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,int(obj.size*2),int(obj.size*2))
+ context = cairo.Context(obj.surface)
+ context.set_source_rgb(*obj.color)
+ context.rectangle(0,0,obj.size*2,obj.size*2)
+ context.fill_preserve()
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+@require_screen
+def create_line(obj): # Must take a line object
+ thickness = obj.thickness
+ obj.topleft = (min(obj.start.x,obj.end.x)-thickness,min(obj.start.y,obj.end.y)-thickness)
+ obj.width = abs(obj.start.x-obj.end.x)+thickness*2
+ obj.height = abs(obj.start.y-obj.end.y)+thickness*2
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(obj.width),int(obj.height))
+ context = cairo.Context(obj.surface)
+ context.set_source_rgb(*obj.color)
+ context.set_line_width(thickness)
+ context.move_to(obj.start.x-obj.topleft[0],obj.height - (obj.start.y-obj.topleft[1]))
+ context.line_to(obj.end.x-obj.topleft[0],obj.height - (obj.end.y-obj.topleft[1]))
+ context.stroke()
+ context.arc(obj.start.x-obj.topleft[0],obj.height - (obj.start.y-obj.topleft[1]),thickness/2, 0, 2.0 * math.pi)
+ context.fill()
+ context.arc(obj.end.x-obj.topleft[0],obj.height - (obj.end.y-obj.topleft[1]),thickness/2, 0, 2.0 * math.pi)
+ context.fill()
+ obj.thickness = 1
+ obj.rot = 0
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+@require_screen
+def create_box(obj): # Must take a box object
+ obj.topleft = (obj.center.x-obj.width/2,obj.center.y-obj.height/2)
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,int(obj.width+obj.thickness*2),int(obj.height+obj.thickness*2))
+ context = cairo.Context(obj.surface)
+ context.set_source_rgb(*obj.color)
+ context.set_line_width(obj.thickness)
+ context.rectangle(obj.thickness,obj.thickness,obj.width,obj.height)
+ if obj.filled: context.fill_preserve()
+ else: context.stroke()
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+@require_screen
+def create_polygon(obj): # Must take a polygon object
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(obj.width),int(obj.height))
+ context = cairo.Context(obj.surface)
+ context.set_source_rgb(*obj.color)
+ context.set_line_width(obj.thickness)
+ context.move_to(obj.points[0][0]-obj.topleft[0],obj.height - (obj.points[0][1]-obj.topleft[1]))
+ i = 1
+ while i < len(obj.points):
+ context.line_to(obj.points[i][0]-obj.topleft[0],obj.height-(obj.points[i][1]-obj.topleft[1]))
+ i+=1
+ context.line_to(obj.points[0][0]-obj.topleft[0],obj.height - (obj.points[0][1]-obj.topleft[1]))
+ if obj.filled: context.fill_preserve()
+ else: context.stroke()
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+@require_screen
+def create_circle(obj): # Must take a circle objects
+ obj.width = obj.radius*2+2*obj.thickness
+ obj.height = obj.width
+ obj.topleft = (obj.center.x-obj.width/2,obj.center.y-obj.height/2)
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,int(obj.width),int(obj.height))
+ context = cairo.Context(obj.surface)
+ context.set_source_rgb(*obj.color)
+ context.set_line_width(obj.thickness)
+ context.arc(obj.width/2,obj.height/2, obj.radius, 0, 2.0 * math.pi)
+ if obj.filled: context.fill_preserve()
+ else: context.stroke()
+ obj.on_screen = True
+ #screen.updater.add(obj)
+ #screen.new_objects.put(obj)
+ #screen.objects.append(obj)
+
+@require_screen
+def create_arc(obj):
+ obj.width = obj.radius*2+2*obj.thickness
+ obj.height = obj.width
+ obj.topleft = (obj.center.x-obj.width/2,obj.center.y-obj.height/2)
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,int(obj.width),int(obj.height))
+ context = cairo.Context(obj.surface)
+ context.set_source_rgb(*obj.color)
+ context.set_line_width(obj.thickness)
+ context.arc(obj.width/2,obj.height/2, obj.radius, math.radians(obj.end_angle), math.radians(obj.start_angle))
+ context.stroke()
+ if obj.filled:
+ angle = obj.end_angle
+ context.set_line_width(3.5)
+ context.move_to(obj.width/2,obj.height/2)
+ while angle < obj.start_angle:
+ context.line_to(obj.width/2+math.cos(math.radians(angle))*obj.radius,obj.height/2+math.sin(math.radians(angle))*obj.radius)
+ angle+=4
+ angle = obj.start_angle
+ context.line_to(obj.width/2+math.cos(math.radians(angle))*obj.radius,obj.height/2+math.sin(math.radians(angle))*obj.radius)
+ context.line_to(obj.width/2,obj.height/2)
+ context.fill_preserve()
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+@require_screen
+def create_oval(obj): # Must take an oval object
+ radius = obj.width
+ obj.topleft = (obj.center.x-(2*obj.width+obj.thickness)/2,obj.center.y-(2*obj.height+obj.thickness)/2)
+ obj.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,int(2*obj.width+obj.thickness),int(2*obj.height+obj.thickness))
+ context = cairo.Context(obj.surface)
+ scale = (1,1.0*obj.height/obj.width)
+ context.set_source_rgb(*obj.color)
+ context.set_line_width(obj.thickness)
+ context.save()
+ context.scale(scale[0],scale[1])
+ context.arc((2*obj.width+obj.thickness)/(2*scale[0]), (2*obj.height+obj.thickness)/(2*scale[1]), radius, 0, 2 * math.pi)
+ context.restore()
+ if obj.filled: context.fill()
+ else: context.stroke()
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+@require_screen
+def create_image(obj): # must take an image object
+ obj.rot = 0
+ obj.pixbuf = gtk.gdk.pixbuf_new_from_file(obj.path_name)
+ width = obj.pixbuf.get_width()
+ height = obj.pixbuf.get_height()
+ if obj.width != 0 and obj.height != 0:
+ obj.scale = (float(obj.width)/width, float(obj.height)/height)
+ else:
+ obj.scale = (1,1)
+ obj.width = width
+ obj.height = height
+ obj.topleft = (obj.center.x-obj.width/2,obj.center.y-obj.height/2)
+ obj.on_screen = True
+ #screen.objects.append(obj)
+
+def create_text(obj):
+ temp_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,1,1)
+ context = cairo.Context(temp_surface)
+ context.set_font_size(obj.size)
+ x,y,obj.length,obj.height = context.text_extents(obj.text)[:4]
+ obj.topleft = (int(obj.pos[0]),int(obj.pos[1]))
+ obj.rot = 0
+ obj.on_screen = True
+
+def get_text_length(text):
+ temp_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,1,1)
+ context = cairo.Context(temp_surface)
+ context.set_font_size(text.size)
+ x,y,length,height = context.text_extents(text.text)[:4]
+ return length
+
+class Entry:
+ """
+ Allows the creation of text in the graphics window
+ """
+ def __init__(self, message, pos, color, size):
+ self.message = message
+ self.color = color_convert(color)
+ self.size = size
+ self.pos = flip_coords(pos)
+ self.entry = ""
+ screen.text_entry = self
+ screen.action_objects.put([self,"text entry"])
+ self.done = False
+ while not self.done:
+ if not screen.entry_done.empty():
+ self.entry = screen.entry_done.get()
+ self.done = True
+ pass
+
+ def draw(self, context):
+ context.save()
+ context.move_to(*self.pos)
+ context.set_source_rgb(*self.color)
+ context.set_font_size(self.size)
+ context.show_text(self.message+" "+self.entry)
+ context.restore()
+
+
+
+"""#================================== Sound =====================================
+
+def create_sound(obj): # needs to be a sound object.
+ try:
+ pygame.mixer.init()
+ except:
+ print "sound is all ready init"
+ pass
+ obj.sound = pygame.mixer.Sound(obj.path)
+
+
+def play_sound(obj):
+ obj.sound.play()
+
+
+def stop_sound(obj):
+ obj.sound.stop()"""
+
+
+# ============================== Event Functions ==============================
+
+
+@require_screen
+def keys(): #returns all the keys currently being pressed
+ while not screen.keys.empty():
+ key = screen.keys.get()
+ if key[1] == "pressed":
+ screen.keys_pressed.append(key[0])
+ if key[1] == "released" and key[0] in screen.keys_pressed:
+ screen.keys_pressed.remove(key[0])
+ return screen.keys_pressed
+
+def mouse_pos():
+ while not screen.mouse.empty():
+ event = screen.mouse.get()
+ if event[0] == "press":
+ screen.mouse_state[event[1]]=event[2]
+ if event[0] == "position":
+ screen.mouse_pos = event[1]
+ return screen.mouse_pos
+
+def mouse_state():
+ while not screen.mouse.empty():
+ event = screen.mouse.get()
+ if event[0] == "press":
+ screen.mouse_state[event[1]]=event[2]
+ if event[0] == "position":
+ screen.mouse_pos = event[1]
+ return screen.mouse_state
+
+def get_screen_size():
+ return (screen.width,screen.height)
+
+
+
+# ============================ Exception Handling ============================
+
+class GaspException(Exception):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return repr(self.value)
+
+
+# =============================== BACKEND TOOLS ===============================
+@require_screen
+def screen_picture(file_name):
+ screen.action_objects.put([file_name,"screen shot"])
+
+@require_screen
+def flip_coords(point):
+ """
+ Changes (0, 0) from topleft bottomleft.
+ """
+ try:
+ return (point[0],screen.height-point[1])
+ except: return (point.x,screen.height-point.y)
+
+
+def color_convert(color):
+ """
+ convert the colors to the formate the cairo takes
+ """
+ return (color[0]/255.0,color[1]/255.0,color[2]/255.0)
+
+
+
+@require_screen
+def end():
+ screen.action_objects.put([None, "end_graphics"])
+ for queue in [screen.action_objects, screen.keys, screen.mouse, screen.update1, screen.update2, screen.entry_done]:
+ while not queue.empty():
+ queue.get()
+ sys.exit()
+
+@require_screen
+def remove(obj):
+ screen.action_objects.put([obj,"remove"])
+
+@require_screen
+def clear_screen():
+ screen.action_objects.put([None,"remove_all"])
+
+
+# ============================== Time ========================================
+@require_screen
+def update_when(event_type):
+
+ if event_type == "key_pressed":
+ screen.update_when = KEY_PRESSED
+ screen.update1.put(KEY_PRESSED)
+
+ elif event_type == "mouse_pressed":
+ screen.update_when = MOUSE_PRESSED
+
+ elif event_type == "next_tick":
+ while time.time() < screen.last_tick+1.0/screen.frame_rate:
+ pass
+ screen.last_tick = time.time()
+
+ if screen.update_when == KEY_PRESSED:
+ while True:
+ while not screen.update2.empty():
+ screen.update_when = screen.update2.get()
+ keys_p = keys()
+ if len(keys_p) != 0 and screen.update_when == NOTHING:
+ screen.update_when = NOTHING
+ return keys_p[0]
+ old_state = mouse_state()
+ while screen.update_when == MOUSE_PRESSED:
+ state = mouse_state()
+ for key in state.get_keys():
+ if state[key] != old_state[key] and state[key] == 1:
+ screen.update_when = NOTHING
+
+
+@require_screen
+def set_frame_rate(fps):
+ screen.frame_rate = fps
+
+
+def sleep(duration):
+ time.sleep(duration)
diff --git a/library/pippy/gasp/color.py b/library/pippy/gasp/color.py
new file mode 100644
index 0000000..dfd3928
--- /dev/null
+++ b/library/pippy/gasp/color.py
@@ -0,0 +1,145 @@
+"""
+color.py : Constants for colors (RBG values)
+
+copyright: James Hancock, 2008
+"""
+
+ALICEBLUE = (240, 248, 255)
+ANTIQUEWHITE = (250, 235, 215)
+AQUA = (0, 255, 255)
+AZURE = (240, 255, 212)
+BEIGE = (245, 245, 220)
+BISQUE = (245, 245, 220)
+BLACK = (0, 0, 0)
+BLANCHEDALMOND = (255, 255, 205)
+BLUE = (0, 0, 255)
+BLUEVIOLET = (138, 43, 226)
+BROWN = (165, 42, 42)
+BURLYWOOD = (222, 184, 135)
+CADETBLUE = (95, 158, 160)
+CHARTREUSE = (127, 255, 0)
+CHOCOLATE = (210, 105, 30)
+CORAL = (255, 127, 80)
+CORNFLOWERBLUE = (100, 149, 237)
+CORNSILK = (255, 248, 220)
+CRIMSON = (220, 20, 60)
+CYAN = (0, 255, 255)
+DARKBLUE = (0, 0, 139)
+DARKCYAN = (0, 139, 139)
+DARKGOLDENROD = (184, 134, 11)
+DARKGRAY = (169, 169, 169)
+DARKGREEN = (0, 100, 0)
+DARKKHAKI = (189, 183, 107)
+DARKMAGENTA = (139, 0, 139)
+DARKOLIVEGREEN = (85, 107, 47)
+DARKORANGE = (255, 140, 0)
+DARKORCHID = (155, 50, 204)
+DARKRED = (139, 0, 0)
+DARKSALMON = (233, 150, 122)
+DARKSEAGREEN = (143, 188, 143)
+DARKSLATEBLUE = (72, 61, 139)
+DARKSLATEGRAY = (47, 79, 79)
+DARKTURQUOISE = (0, 206, 209)
+DARKVIOLET = (148, 0, 211)
+DEEPPINK = (255, 20, 147)
+DEEPSKYBLUE = (0, 191, 255)
+DIMGRAY = (105, 105, 105)
+DODGERBLUE = (30, 144, 255)
+FIREBRICK = (178, 34, 34)
+FLORALWHITE = (255, 250, 240)
+FORESTGREEN = (34, 139, 34)
+FUCHSIA = (255, 0, 255)
+GAINSBORO = (220, 220, 220)
+GHOSTWHITE = (248, 248, 255)
+GOLD = (255, 215, 0)
+GOLDENROD = (218, 165, 32)
+GRAY = (218, 165, 32)
+GREEN = (0, 128, 0)
+GREENYELLOW = (173, 255, 47)
+HONEYDEW = (240, 255, 240)
+HOTPINK = (255, 105, 180)
+INDIANRED = (205, 92, 92)
+INDIGO = (75, 0, 130)
+IVORY = (255, 240, 240)
+KHAKI = (240, 230, 140)
+LAVENDER = (230, 230, 250)
+LAVENDERBLUSH = (255, 240, 245)
+LAWNGREEN = (124, 252, 245)
+LEMONCHIFFON = (255, 250, 205)
+LIGHTBLUE = (173, 216, 230)
+LIGHTCORAL = (240, 128, 128)
+LIGHTCYAN = (224, 255, 255)
+LIGHTGOLDENRODYELLOW = (250, 250, 210)
+LIGHTGREEN = (144, 238, 144)
+LIGHTGRAY = (211, 211, 211)
+LIGHTPINK = (255, 182, 193)
+LIGHTSALMON = (255, 160, 122)
+LIGHTSEAGREEN = (32, 178, 170)
+LIGHTSKYBLUE = (135, 206, 250)
+LIGHTSLATEGRAY = (119, 136, 153)
+LIGHTSTEELBLUE = (176, 196, 222)
+LIGHTYELLOW = (255, 255, 224)
+LIME = (0, 255, 0)
+LIMEGREEN = (50, 205, 50)
+LINEN = (250, 240, 230)
+MAGENTA = (255, 0, 255)
+MAROON = (128, 0, 0)
+MEDIUMAQUAMARINE = (102, 205, 170)
+MEDIUMBLUE = (0, 0, 205)
+MEDIUMORCHID = (186, 85, 211)
+MEDIUMPURPLE = (147, 112, 219)
+MEDIUMSEAGREEN = (60, 179, 113)
+MEDIUMSLATEBLUE = (123, 104, 238)
+MEDIUMSPRINGGREEN = (0, 250, 154)
+MEDIUMTURQOISE = (72, 209, 204)
+MEDIUMVIOLETRED = (199, 21, 133)
+MIDNIGHTBLUE = (25, 25, 112)
+MINTCREAM = (245, 255, 250)
+MISTYROSE = (255, 228, 225)
+MOCCASIN = (255, 225, 181)
+NAVAJOWHITE = (255, 222, 173)
+NAVY = (0, 0, 128)
+OLDLACE = (253, 245, 230)
+OLIVE = (128, 128, 0)
+OLIVEDRAB = (107, 142, 35)
+ORANGE = (255, 165, 0)
+ORANGERED = (255, 69, 0)
+ORCHID = (218, 122, 214)
+PALEGOLDENROD = (238, 232, 170)
+PALEGREEN = (152, 251, 152)
+PALETURQOISE = (175, 238, 238)
+PALEVIOLETRED = (219, 112, 147)
+PAPAYAWHIP = (255, 239, 213)
+PEACHPUFF = (255, 239, 213)
+PERU = (205, 133, 63)
+PINK = (255, 192, 203)
+PLUM = (211, 160, 221)
+POWDERBLUE = (176, 224, 230)
+PURPLE = (128, 0, 128)
+RED = (255, 0, 0)
+ROSYBROWN = (188, 143, 143)
+ROYALBLUE = (65, 105, 225)
+SADDLEBROWN = (139, 69, 19)
+SALMON = (250, 128, 114)
+SANDYBROWN = (244, 164, 96)
+SEAGREEN = (46, 139, 87)
+SEASHELL = (255, 245, 238)
+SIENNA = (160, 82, 45)
+SILVER = (192, 192, 192)
+SKYBLUE = (135, 206, 235)
+SLATEBLUE = (106, 90, 205)
+SLATEGRAY = (112, 128, 144)
+SNOW = (255, 250, 250)
+SPRINGGREEN = (0, 255, 127)
+STEELBLUE = (70, 130, 180)
+TAN = (210, 180, 140)
+TEAL = (0, 128, 128)
+THISTLE = (216, 191, 216)
+TOMATO = (253, 99, 71)
+TURQUOISE = (64, 224, 208)
+VIOLET = (238, 130, 238)
+WHEAT = (245, 222, 170)
+WHITE = (255, 255, 255)
+WHITESMOKE = (245, 245, 245)
+YELLOW = (255, 255, 0)
+YELLOWGREEN = (154, 205, 50)