changeset 41:ff3e395abf91

Renamed grease to bGrease (Basic Grease) to get rid of conflicts with an already installed grease.
author KarstenBock@gmx.net
date Mon, 05 Sep 2011 15:00:34 +0200
parents 2e3ab06a2f47
children 66a06de1bddc
files bGrease/__init__.py bGrease/collision.py bGrease/color.py bGrease/component/__init__.py bGrease/component/base.py bGrease/component/field.py bGrease/component/general.py bGrease/component/schema.py bGrease/controller/__init__.py bGrease/controller/integrator.py bGrease/entity.py bGrease/geometry.py bGrease/impl/__init__.py bGrease/impl/controls.py bGrease/impl/mode.py bGrease/impl/world.py bGrease/mode.py bGrease/renderer/__init__.py bGrease/renderer/camera.py bGrease/renderer/vector.py bGrease/world.py components/Behavior.py components/CharacterStatistics.py components/containable.py components/container.py components/description.py components/dialog.py components/fifeagent.py components/lockable.py components/usable.py entities/character.py gamemodel.py grease/__init__.py grease/collision.py grease/color.py grease/component/__init__.py grease/component/base.py grease/component/field.py grease/component/general.py grease/component/schema.py grease/controller/__init__.py grease/controller/integrator.py grease/entity.py grease/geometry.py grease/impl/__init__.py grease/impl/controls.py grease/impl/mode.py grease/impl/world.py grease/mode.py grease/renderer/__init__.py grease/renderer/camera.py grease/renderer/vector.py grease/world.py mode.py systems/gamerulessystem.py systems/scriptingsystem.py world.py
diffstat 57 files changed, 3705 insertions(+), 3705 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/__init__.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,75 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+
+__versioninfo__ = (0, 3, 0)
+__version__ = '.'.join(str(n) for n in __versioninfo__)
+
+__all__ = ('BaseWorld', 'Entity', 'System', 'Renderer')
+
+import component
+import geometry
+import collision
+from entity import Entity
+from world import BaseWorld
+
+import abc
+
+class System(object):
+	"""Grease system abstract base class. Systems define behaviorial aspects
+	of a |World|. All systems must define a :meth:`step`
+	method that is invoked by the world each timestep.  User-defined systems
+	are not required to subclass this class.
+	
+	See :ref:`an example system from the tutorial <tut-system-example>`.
+	"""
+	__metaclass__ = abc.ABCMeta
+
+	world = None
+	"""The |World| this system belongs to"""
+
+	def set_world(self, world):
+		"""Bind the system to a world"""
+		self.world = world
+	
+	@abc.abstractmethod
+	def step(self, dt):
+		"""Execute a time step for the system. Must be defined
+		by all system classes.
+
+		:param dt: Time since last step invocation
+		:type dt: float
+		"""
+
+class Renderer(object):
+	"""Grease renderer abstract base class. Renderers define the presentation
+	of a |World|. All renderers must define a :meth:`draw`
+	method that is invoked by the world when the display needs to be redrawn.
+	User-defined renderers are not required to subclass this class.
+
+	See :ref:`an example renderer from the tutorial <tut-renderer-example>`.
+	"""
+	__metaclass__ = abc.ABCMeta
+
+	world = None
+	"""The |World| this renderer belongs to"""
+
+	def set_world(self, world):
+		"""Bind the system to a world"""
+		self.world = world
+
+	@abc.abstractmethod
+	def draw(self):
+		"""Issue drawing commands for this renderer. Must be defined
+		for all renderer classes.
+		"""
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/collision.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,528 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""
+**Grease collision detection systems**
+
+Grease uses two-phase broad and narrow collision detection. *Broad-phase*
+collision systems are used to efficiently identify pairs that may be colliding
+without resorting to a brute-force check of all possible pairs. *Narrow-phase*
+collision systems use the pairs generated by the broad-phase and perform more
+precise collision tests to determine if a collision has actually occurred. The
+narrow-phase system also calculates more details about each collision,
+including collision point and normal vector for use in collision response.
+
+A typical collision detection system consists of a narrow-phase system that
+contains a broad-phased system. The narrow-phase system is usually the only
+
+one that the application directly interacts with, though the application is
+free to use the broad-phased system directly if desired. This could be
+useful in cases where speed, rather than precision is paramount.
+
+The narrow-phase system can be assigned handler objects to run after
+collision detection. These can perform tasks like handling collision response
+or dispatching collision events to application handlers.
+
+Note that broad-phase systems can return false positives, though they should
+never return false negatives. Do not assume that all pairs returned by a
+broad-phase system are actually in collision.
+"""
+
+__version__ = '$Id$'
+
+from bGrease.geometry import Vec2d
+from bisect import bisect_right
+
+
+class Pair(tuple):
+	"""Pair of entities in collision. This is an ordered sequence of two
+	entities, that compares and hashes unordered.
+	
+	Also stores additional collision point and normal vectors
+	for each entity.
+
+	Sets of ``Pair`` objects are exposed in the ``collision_pairs``
+	attribute of collision systems to indicate the entity pairs in
+	collision.
+	"""
+	info = None
+	"""A sequence of (entity, collision point, collision normal)
+	for each entity in the pair
+	"""
+
+	def __new__(cls, entity1, entity2, point=None, normal=None):
+		pair = tuple.__new__(cls, (entity1, entity2))
+		return pair
+	
+	def __hash__(self):
+		return hash(self[0]) ^ hash(self[1])
+	
+	def __eq__(self, other):
+		other = tuple(other)
+		return tuple(self) == other or (self[1], self[0]) == other
+	
+	def __repr__(self):
+		return '%s%r' % (self.__class__.__name__, tuple(self))
+	
+	def set_point_normal(self, point0, normal0, point1, normal1):
+		"""Set the collision point and normal for both entities"""
+		self.info = (
+			(self[0], point0, normal0),
+			(self[1], point1, normal1),
+		)
+
+
+class BroadSweepAndPrune(object):
+	"""2D Broad-phase sweep and prune bounding box collision detector
+
+	This algorithm is efficient for collision detection between many
+	moving bodies. It has linear algorithmic complexity and takes
+	advantage of temporal coherence between frames. It also does
+	not suffer from bad worst-case performance (like RDC can). 
+	Unlike spacial hashing, it does not need to be optimized for 
+	specific space and body sizes.
+
+	Other algorithms may be more efficient for collision detection with
+	stationary bodies, bodies that are always evenly distributed, or ad-hoc
+	queries.
+
+	:param collision_component: Name of the collision component used by this
+		system, defaults to 'collision'. This component supplies each
+		entities' aabb and collision masks.
+	:type collision_component: str
+	"""
+	world = None
+	"""|World| object this system belongs to"""
+
+	collision_component = None
+	"""Name of world's collision component used by this system"""
+
+	LEFT_ATTR = "left"
+	RIGHT_ATTR = "right"
+	TOP_ATTR = "top"
+	BOTTOM_ATTR = "bottom"
+
+	def __init__(self, collision_component='collision'):
+		self.collision_component = collision_component
+		self._by_x = None
+		self._by_y = None
+		self._collision_pairs = None
+	
+	def set_world(self, world):
+		"""Bind the system to a world"""
+		self.world = world
+	
+	def step(self, dt):
+		"""Update the system for this time step, updates and sorts the 
+		axis arrays.
+		"""
+		component = getattr(self.world.components, self.collision_component)
+		LEFT = self.LEFT_ATTR
+		RIGHT = self.RIGHT_ATTR
+		TOP = self.TOP_ATTR
+		BOTTOM = self.BOTTOM_ATTR
+		if self._by_x is None:
+			# Build axis lists from scratch
+			# Note we cache the box positions here
+			# so that we can perform hit tests efficiently
+			# it also isolates us from changes made to the 
+			# box positions after we run
+			by_x = self._by_x = []
+			append_x = by_x.append
+			by_y = self._by_y = []
+			append_y = by_y.append
+			for data in component.itervalues():
+				append_x([data.aabb.left, LEFT, data])
+				append_x([data.aabb.right, RIGHT, data])
+				append_y([data.aabb.bottom, BOTTOM, data])
+				append_y([data.aabb.top, TOP, data])
+		else:
+			by_x = self._by_x
+			by_y = self._by_y
+			removed = []
+			for entry in by_x:
+				entry[0] = getattr(entry[2].aabb, entry[1])
+			for entry in by_y:
+				entry[0] = getattr(entry[2].aabb, entry[1])
+			# Removing entities is inefficient, but expected to be rare
+			if component.deleted_entities:
+				deleted_entities = component.deleted_entities
+				deleted_x = []
+				deleted_y = []
+				for i, (_, _, data) in enumerate(by_x):
+					if data.entity in deleted_entities:
+						deleted_x.append(i)
+				deleted_x.reverse()
+				for i in deleted_x:
+					del by_x[i]
+				for i, (_, _, data) in enumerate(by_y):
+					if data.entity in deleted_entities:
+						deleted_y.append(i)
+				deleted_y.reverse()
+				for i in deleted_y:
+					del by_y[i]
+			# Tack on new entities
+			for entity in component.new_entities:
+				data = component[entity]
+				by_x.append([data.aabb.left, LEFT, data])
+				by_x.append([data.aabb.right, RIGHT, data])
+				by_y.append([data.aabb.bottom, BOTTOM, data])
+				by_y.append([data.aabb.top, TOP, data])
+				
+		# Tim-sort is highly efficient with mostly sorted lists.
+		# Because positions tend to change little each frame
+		# we take advantage of this here. Obviously things are
+		# less efficient with very fast moving, or teleporting entities
+		by_x.sort()
+		by_y.sort()
+		self._collision_pairs = None
+	
+	@property
+	def collision_pairs(self):
+		"""Set of candidate collision pairs for this timestep"""
+		if self._collision_pairs is None:
+			if self._by_x is None:
+				# Axis arrays not ready
+				return set()
+
+			LEFT = self.LEFT_ATTR
+			RIGHT = self.RIGHT_ATTR
+			TOP = self.TOP_ATTR
+			BOTTOM = self.BOTTOM_ATTR
+			# Build candidates overlapping along the x-axis
+			component = getattr(self.world.components, self.collision_component)
+			xoverlaps = set()
+			add_xoverlap = xoverlaps.add
+			discard_xoverlap = xoverlaps.discard
+			open = {}
+			for _, side, data in self._by_x:
+				if side is LEFT:
+					for open_entity, (from_mask, into_mask) in open.iteritems():
+						if data.from_mask & into_mask or from_mask & data.into_mask:
+							add_xoverlap(Pair(data.entity, open_entity))
+					open[data.entity] = (data.from_mask, data.into_mask)
+				elif side is RIGHT:
+					del open[data.entity]
+
+			if len(xoverlaps) <= 10 and len(xoverlaps)*4 < len(self._by_y):
+				# few candidates were found, so just scan the x overlap candidates
+				# along y. This requires an additional sort, but it should
+				# be cheaper than scanning everyone and its simpler
+				# than a separate brute-force check
+				entities = set([entity for entity, _ in xoverlaps] 
+					+ [entity for _, entity in xoverlaps])
+				by_y = []
+				for entity in entities:
+					data = component[entity]
+					# We can use tuples here, which are cheaper to create
+					by_y.append((data.aabb.bottom, BOTTOM, data))
+					by_y.append((data.aabb.top, TOP, data))
+				by_y.sort()
+			else:
+				by_y = self._by_y
+
+			# Now check the candidates along the y-axis
+			open = set()
+			add_open = open.add
+			discard_open = open.discard
+			self._collision_pairs = set()
+			add_pair = self._collision_pairs.add
+			for _, side, data in by_y:
+				if side is BOTTOM:
+					for open_entity in open:
+						pair = Pair(data.entity, open_entity)
+						if pair in xoverlaps:
+							discard_xoverlap(pair)
+							add_pair(pair)
+							if not xoverlaps:
+								# No more candidates, bail
+								return self._collision_pairs
+					add_open(data.entity)
+				elif side is TOP:
+					discard_open(data.entity)
+		return self._collision_pairs
+	
+	def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
+		"""Hit test at the point specified. 
+
+		:param x_or_point: x coordinate (float) or sequence of (x, y) floats.
+
+		:param y: y coordinate (float) if x is not a sequence
+
+		:param from_mask: Bit mask used to filter query results. This value
+			is bit ANDed with candidate entities' ``collision.into_mask``.
+			If the result is non-zero, then it is considered a hit. By
+			default all entities colliding with the input point are
+			returned.
+
+		:return: A set of entities where the point is inside their bounding
+			boxes as of the last time step.
+		"""
+		if self._by_x is None:
+			# Axis arrays not ready
+			return set()
+		if y is None:
+			x, y = x_or_point
+		else:
+			x = x_or_point
+		LEFT = self.LEFT_ATTR
+		RIGHT = self.RIGHT_ATTR
+		TOP = self.TOP_ATTR
+		BOTTOM = self.BOTTOM_ATTR
+		x_index = bisect_right(self._by_x, [x])
+		x_hits = set()
+		add_x_hit = x_hits.add
+		discard_x_hit = x_hits.discard
+		if x_index <= len(self._by_x) // 2:
+			# closer to the left, scan from left to right
+			while (x == self._by_x[x_index][0] 
+				and self._by_x[x_index][1] is LEFT 
+				and x_index < len(self._by_x)):
+				# Ensure we hit on exact left edge matches
+				x_index += 1
+			for _, side, data in self._by_x[:x_index]:
+				if side is LEFT and from_mask & data.into_mask:
+					add_x_hit(data.entity)
+				else:
+					discard_x_hit(data.entity)
+		else:
+			# closer to the right
+			for _, side, data in reversed(self._by_x[x_index:]):
+				if side is RIGHT and from_mask & data.into_mask:
+					add_x_hit(data.entity)
+				else:
+					discard_x_hit(data.entity)
+		if not x_hits:
+			return x_hits
+
+		y_index = bisect_right(self._by_y, [y])
+		y_hits = set()
+		add_y_hit = y_hits.add
+		discard_y_hit = y_hits.discard
+		if y_index <= len(self._by_y) // 2:
+			# closer to the bottom
+			while (y == self._by_y[y_index][0] 
+				and self._by_y[y_index][1] is BOTTOM 
+				and y_index < len(self._by_y)):
+				# Ensure we hit on exact bottom edge matches
+				y_index += 1
+			for _, side, data in self._by_y[:y_index]:
+				if side is BOTTOM:
+					add_y_hit(data.entity)
+				else:
+					discard_y_hit(data.entity)
+		else:
+			# closer to the top
+			for _, side, data in reversed(self._by_y[y_index:]):
+				if side is TOP:
+					add_y_hit(data.entity)
+				else:
+					discard_y_hit(data.entity)
+		if y_hits:
+			return x_hits & y_hits
+		else:
+			return y_hits
+
+
+class Circular(object):
+	"""Basic narrow-phase collision detector which treats all entities as
+	circles with their radius defined in the collision component.
+
+	:param handlers: A sequence of collision handler functions that are invoked
+		after collision detection.
+	:type handlers: sequence of functions
+	
+	:param collision_component: Name of collision component for this system,
+		defaults to 'collision'. This supplies each entity's collision
+		radius and masks.
+	:type collision_component: str
+
+	:param position_component: Name of position component for this system,
+		defaults to 'position'. This supplies each entity's position.
+	:type position_component: str
+
+	:param update_aabbs: If True (the default), then the entities'
+		`collision.aabb` fields will be updated using their position
+		and collision radius before invoking the broad phase system. 
+		Set this False if another system updates the aabbs.
+	:type update_aabbs: bool
+
+	:param broad_phase: A broad-phase collision system to use as a source
+		for collision pairs. If not specified, a :class:`BroadSweepAndPrune`
+		system will be created automatically.
+	"""
+	world = None
+	"""|World| object this system belongs to"""
+
+	position_component = None
+	"""Name of world's position component used by this system"""
+
+	collision_component = None
+	"""Name of world's collision component used by this system"""
+
+	update_aabbs = True
+	"""Flag to indicate whether the system updates the entities' `collision.aabb`
+	field before invoking the broad phase collision system
+	"""
+	
+	handlers = None
+	"""A sequence of collision handler functions invoke after collision
+	detection
+	"""
+
+	broad_phase = None
+	"""Broad phase collision system used as a source for collision pairs"""
+
+	def __init__(self, handlers=(), position_component='position', 
+		collision_component='collision', update_aabbs=True, broad_phase=None):
+		self.handlers = tuple(handlers)
+		if broad_phase is None:
+			broad_phase = BroadSweepAndPrune(collision_component)
+		self.collision_component = collision_component
+		self.position_component = position_component
+		self.update_aabbs = bool(update_aabbs)
+		self.broad_phase = broad_phase
+		self._collision_pairs = None
+	
+	def set_world(self, world):
+		"""Bind the system to a world"""
+		self.world = world
+		self.broad_phase.set_world(world)
+		for handler in self.handlers:
+			if hasattr(handler, 'set_world'):
+				handler.set_world(world)
+	
+	def step(self, dt):
+		"""Update the collision system for this time step and invoke
+		the handlers
+		"""
+		if self.update_aabbs:
+			for position, collision in self.world.components.join(
+				self.position_component, self.collision_component):
+				aabb = collision.aabb
+				x, y = position.position
+				radius = collision.radius
+				aabb.left = x - radius
+				aabb.right = x + radius
+				aabb.bottom = y - radius
+				aabb.top = y + radius
+		self.broad_phase.step(dt)
+		self._collision_pairs = None
+		for handler in self.handlers:
+			handler(self)
+	
+	@property
+	def collision_pairs(self):
+		"""The set of entity pairs in collision in this timestep"""
+		if self._collision_pairs is None:
+			position = getattr(self.world.components, self.position_component)
+			collision = getattr(self.world.components, self.collision_component)
+			pairs = self._collision_pairs = set()
+			for pair in self.broad_phase.collision_pairs:
+				entity1, entity2 = pair
+				position1 = position[entity1].position
+				position2 = position[entity2].position
+				radius1 = collision[entity1].radius
+				radius2 = collision[entity2].radius
+				separation = position2 - position1
+				if separation.get_length_sqrd() <= (radius1 + radius2)**2:
+					normal = separation.normalized()
+					pair.set_point_normal(
+						normal * radius1 + position1, normal,
+						normal * -radius2 + position2, -normal)
+					pairs.add(pair)
+		return self._collision_pairs
+	
+	def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
+		"""Hit test at the point specified. 
+
+		:param x_or_point: x coordinate (float) or sequence of (x, y) floats.
+
+		:param y: y coordinate (float) if x is not a sequence
+
+		:param from_mask: Bit mask used to filter query results. This value
+			is bit ANDed with candidate entities' ``collision.into_mask``.
+			If the result is non-zero, then it is considered a hit. By
+			default all entities colliding with the input point are
+			returned.
+
+		:return: A set of entities where the point is inside their collision
+			radii as of the last time step.
+
+		"""
+		if y is None:
+			point = Vec2d(x_or_point)
+		else:
+			point = Vec2d(x_or_point, y)
+		hits = set()
+		position = getattr(self.world.components, self.position_component)
+		collision = getattr(self.world.components, self.collision_component)
+		for entity in self.broad_phase.query_point(x_or_point, y, from_mask):
+			separation = point - position[entity].position
+			if separation.get_length_sqrd() <= collision[entity].radius**2:
+				hits.add(entity)
+		return hits
+
+
+def dispatch_events(collision_system):
+	"""Collision handler that dispatches `on_collide()` events to entities
+	marked for collision by the specified collision system. The `on_collide()`
+	event handler methods are defined by the application on the desired entity
+	classes. These methods should have the following signature::
+
+		def on_collide(self, other_entity, collision_point, collision_normal):
+			'''Handle A collision between this entity and `other_entity`
+
+			- other_entity (Entity): The other entity in collision with 
+			  `self`
+
+			- collision_point (Vec2d): The point on this entity (`self`)
+			  where the collision occurred. Note this may be `None` for 
+			  some collision systems that do not report it.
+
+			- collision_normal (Vec2d): The normal vector at the point of
+			  collision. As with `collision_point`, this may be None for
+			  some collision systems.
+			'''
+
+	Note the arguments to `on_collide()` are always passed positionally, so you
+	can use different argument names than above if desired.
+
+	If a pair of entities are in collision, then the event will be dispatched
+	to both objects in arbitrary order if all of their collision masks align.
+	"""
+	collision = getattr(collision_system.world.components, 
+		collision_system.collision_component)
+	for pair in collision_system.collision_pairs:
+		entity1, entity2 = pair
+		if pair.info is not None:
+			args1, args2 = pair.info
+		else:
+			args1 = entity1, None, None
+			args2 = entity2, None, None
+		try:
+			on_collide = entity1.on_collide
+			masks_align = collision[entity2].from_mask & collision[entity1].into_mask
+		except (AttributeError, KeyError):
+			pass
+		else:
+			if masks_align:
+				on_collide(*args2)
+		try:
+			on_collide = entity2.on_collide
+			masks_align = collision[entity1].from_mask & collision[entity2].into_mask
+		except (AttributeError, KeyError):
+			pass
+		else:
+			if masks_align:
+				on_collide(*args1)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/color.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,64 @@
+
+class RGBA(object):
+	"""Four channel color representation.
+
+	RGBA colors are floating point color representations with color channel
+	values between (0..1). Colors may be initialized from 3 or 4 floating
+	point numbers or a hex string::
+
+		RGBA(1.0, 1.0, 1.0) # Alpha defaults to 1.0
+		RGBA(1.0, 1.0, 0, 0.5)
+		RGBA("#333")
+		RGBA("#7F7F7F")
+	
+	Individual color channels can be accessed by attribute name, or the
+	color object can be treated as a sequence of 4 floats.
+	"""
+
+	def __init__(self, r_or_colorstr, g=None, b=None, a=None):
+		if isinstance(r_or_colorstr, str):
+			assert g is b is a is None, "Ambiguous color arguments" 
+			self.r, self.g, self.b, self.a = self._parse_colorstr(r_or_colorstr)
+		elif g is b is a is None:
+			try:
+				self.r, self.g, self.b, self.a = r_or_colorstr
+			except ValueError:
+				self.r, self.g, self.b = r_or_colorstr
+				self.a = 1.0
+		else:
+			self.r = r_or_colorstr
+			self.g = g
+			self.b = b
+			self.a = a
+		if self.a is None:
+			self.a = 1.0
+	
+	def _parse_colorstr(self, colorstr):
+		length = len(colorstr)
+		if not colorstr.startswith("#") or length not in (4, 5, 7, 9):
+			raise ValueError("Invalid color string: " + colorstr)
+		if length <= 5:
+			parsed = [int(c*2, 16) / 255.0 for c in colorstr[1:]]
+		else:
+			parsed = [int(colorstr[i:i+2], 16) / 255.0 for i in range(1, length, 2)]
+		if len(parsed) == 3:
+			parsed.append(1.0)
+		return parsed
+	
+	def __len__(self):
+		return 4
+	
+	def __getitem__(self, item):
+		return (self.r, self.g, self.b, self.a)[item]
+	
+	def __iter__(self):
+		return iter((self.r, self.g, self.b, self.a))
+	
+	def __eq__(self, other):
+		return tuple(self) == tuple(other)
+	
+	def __repr__(self):
+		return "%s(%.2f, %.2f, %.2f, %.2f)" % (self.__class__.__name__, 
+			self.r, self.g, self.b, self.a)
+			
+			
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/component/__init__.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,149 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""Components store all entity data in a given |World|. You can
+think of components as tables with entities as their primary keys. Like
+database tables, components are defined with a "schema" that specifies
+the data fields. Each field in a component has a name and a type.
+
+Component objects themselves have a dict-like interface with entities
+as keys and data records as values. An application will typically 
+interact with components via entity attributes, entity extents or
+by joining them. For more information see:
+
+- :class:`~grease.entity.Entity` class.
+- :class:`~grease.world.EntityExtent` class.
+- :meth:`~grease.world.ComponentParts.join` method of ComponentParts.
+
+See also :ref:`defining custom components in the tutorial <custom-component-example>`.
+"""
+
+__version__ = '$Id$'
+
+__all__ = ('Component', 'ComponentError', 'Position', 'Transform', 'Movement', 
+	'Shape', 'Renderable', 'Collision')
+
+from bGrease.component.general import Component
+from bGrease.geometry import Vec2d, Vec2dArray, Rect
+from bGrease import color
+
+
+class ComponentError(Exception):
+	"""General component error"""
+
+
+class Position(Component):
+	"""Predefined component that stores position and orientation info for 
+	entities.
+
+	Fields:
+
+	- **position** (Vec2d) -- Position vector
+	- **angle** (float) -- Angle, in degrees
+	"""
+
+	def __init__(self):
+		Component.__init__(self, position=Vec2d, angle=float)
+
+
+class Transform(Component):
+	"""Predefined component that stores offset, shear, 
+	rotation and scale info for entity shapes.
+	
+	Fields:
+
+	- **offset** (Vec2d)
+	- **shear** (Vec2d)
+	- **rotation** (float)
+	- **scale** (float, default 1.0)
+	"""
+
+	def __init__(self):
+		Component.__init__(self, offset=Vec2d, shear=Vec2d, rotation=float, scale=float)
+		self.fields['scale'].default = lambda: 1.0
+
+
+class Movement(Component):
+	"""Predefined component that stores velocity, 
+	acceleration and rotation info for entities.
+	
+	Fields:
+
+	- **velocity** (Vec2d) -- Rate of change of entity position
+	- **accel** (Vec2d) -- Rate of change of entity velocity
+	- **rotation** (Vec2d) -- Rate of change of entity angle, in degrees/time
+	"""
+
+	def __init__(self):
+		Component.__init__(self, velocity=Vec2d, accel=Vec2d, rotation=float)
+
+
+class Shape(Component):
+	"""Predefined component that stores shape vertices for entities
+	
+	- **closed** (bool) -- If the shapes is closed implying an edge between
+	  last and first vertices.
+	- **verts** (Vec2dArray) -- Array of vertex points
+	"""
+
+	def __init__(self):
+		Component.__init__(self, closed=int, verts=Vec2dArray)
+		self.fields['closed'].default = lambda: 1
+
+
+class Renderable(Component):
+	"""Predefined component that identifies entities to be 
+	rendered and provides their depth and color.
+	
+	- **depth** (float) -- Drawing depth, can be used to determine z-order
+		  while rendering.
+	- **color** (color.RGBA) -- Color used for entity. The effect of this
+		  field depends on the renderer.
+	"""
+
+	def __init__(self):
+		Component.__init__(self, depth=float, color=color.RGBA)
+		self.fields['color'].default = lambda: color.RGBA(1,1,1,1)
+
+
+class Collision(Component):
+	"""Predefined component that stores collision masks to determine 
+	which entities can collide.
+
+	Fields:
+
+	- **aabb** (Rect) -- The axis-aligned bounding box for the entity.
+		This is used for broad-phase collision detection.
+
+	- **radius** (float) -- The collision radius of the entity, used for narrow-phase
+		collision detection. The exact meaning of this value depends on the collision
+		system in use.
+	
+	- **from_mask** (int) -- A bitmask that determines what entities this object
+		can collide with.
+
+	- **into_mask** (int) -- A bitmask that determines what entities can collide
+		with this object.
+
+	When considering an entity A for collision with entity B, A's ``from_mask`` is
+	bit ANDed with B's ``into_mask``. If the result is nonzero (meaning 1 or more
+	bits is set the same for each) then the collision test is made. Otherwise,
+	the pair cannot collide. 
+
+	The default value for both of these masks is ``0xffffffff``, which means that
+	all entities will collide with each other by default.
+	"""
+	def __init__(self):
+		Component.__init__(self, aabb=Rect, radius=float, from_mask=int, into_mask=int)
+		self.fields['into_mask'].default = lambda: 0xffffffff
+		self.fields['from_mask'].default = lambda: 0xffffffff
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/component/base.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,74 @@
+class ComponentBase(object):
+	"""Component abstract base class
+
+	Strictly speaking you do not need to derive from this class to create your
+	own components, but it does serve to document the full interface that a
+	component implements and it provides some basic implementations for
+	certain methods
+	"""
+
+	## Optional attributes and methods ##
+
+	def set_manager(self, manager):
+		"""Set the manager of this component. If this method exists it will be
+		automatically called when the component is added to a manager.
+
+		This method stores the manager and allows the component to be added
+		only once to a single manager.
+		"""
+		assert getattr(self, 'manager', None) is None, 'Component cannot be added to multiple managers'
+		self.manager = manager
+
+	def __del__(self):
+		"""Break circrefs to allow faster collection"""
+		if hasattr(self, 'manager'):
+			del self.manager
+	
+	## Mandatory methods ##
+
+	def add(self, entity_id, data=None, **data_kw):
+		"""Add a data entry in the component for the given entity.  Additional
+		data (if any) for the entry can be provided in the data argument or as
+		keyword arguments. Additional data is optional and if omitted then
+		suitable defaults will be used. Return an entity data object
+		for the new entity entry.
+
+		The semantics of the data arguments is up to the component.
+
+		An entity_id is a unique key, thus multiple separate data entries for
+		a given entity are not allowed.  Components can indivdually decide
+		what to do if an entity_id is added multiple times to the component.
+		Potential options include, raising an exception, replacing the
+		existing data or coalescing it somehow.
+		"""
+	
+	def remove(self, entity_id):
+		"""Remove the entity data entry from the component. If the
+		entity is not in the component, raise KeyError
+		"""
+	
+	def __delitem_(self, entity_id):
+		"""Same as remove()"""
+
+	def __len__(self):
+		"""Return the number of entities in the component"""
+		raise NotImplementedError()
+	
+	def __iter__(self):
+		"""Return an iterator of entity data objects in this component
+
+		No order is defined for these data objects
+		"""
+		raise NotImplementedError()
+	
+	def __contains__(self, entity_id):
+		"""Return True if the entity is contained in the component"""
+		raise NotImplementedError()
+	
+	def __getitem__(self, entity_id):
+		"""Return the entity data object for the given entity. 
+		The entity data object returned may be mutable, immutable or a
+		mutable copy of the data at the discretion of the component
+		"""
+		raise NotImplementedError()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/component/field.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,303 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+
+__version__ = '$Id$'
+
+import operator
+from bGrease.geometry import Vec2d, Vec2dArray, Rect
+from bGrease import color
+
+# Allowed field types -> default values
+types = {int:lambda: 0, 
+         float:lambda: 0.0, 
+         bool:lambda: False,
+         str:lambda:"", 
+         object:lambda:None,
+         Vec2d:lambda: Vec2d(0,0), 
+         Vec2dArray:lambda: Vec2dArray(),
+         color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0),
+         Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0),
+         list: lambda: list(),
+         dict: lambda: dict(),
+         }
+
+class Schema(dict):
+        """Field schema definition for custom components"""
+
+        def __init__(self, **fields):
+                for ftype in fields.values():
+                        assert ftype in types, fname + " has an illegal field type"
+                self.update(fields)
+
+
+class FieldAccessor(object):
+        """Facade for manipulating a field for a set of entities"""
+
+        __field = None
+        __entities = None
+        __attrs = None
+        __getter = None
+        __parent_getters = ()
+
+        def __init__(self, field, entities, attrs=()):
+                self.__field = field
+                self.__entities = entities
+                field_getter = operator.attrgetter(field.name)
+                self.__attrs = attrs
+                if attrs:
+                        getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs]
+                        def get(entity):
+                                value = entity
+                                for getter in getters:
+                                        value = getter(value)
+                                return value
+                        self.__getter = get
+                        self.__parent_getters = getters[:-1]
+                else:
+                        self.__getter = field_getter
+
+        def __getattr__(self, name):
+                """Return a FieldAccessor for the child attribute"""
+                return self.__class__(self.__field, self.__entities, self.__attrs + (name,))
+
+        def __setattr__(self, name, value):
+                if value is self:
+                        return # returned by mutators
+                if hasattr(self.__class__, name):
+                        # Set local attr
+                        self.__dict__[name] = value
+                elif not name.startswith('_'):
+                        getattr(self, name).__set__(value)
+                else:
+                        raise AttributeError("Cannot set field attribute: %s" % name)
+
+        @property
+        def __setter(self):
+                """Return the proper setter function for setting the field value"""
+                if not self.__attrs:
+                        return setattr
+                else:
+                        parent_getters = self.__parent_getters
+                        def setter(data, name, value):
+                                for getter in parent_getters:
+                                        data = getter(data)
+                                setattr(data, name, value)
+                        self.__setter = setter
+                        return setter
+
+        def __set__(self, value):
+                """Set field values en masse"""
+                # Mass set field attr
+                setter = self.__setter
+                component = self.__field.component
+                if self.__attrs:
+                        name = self.__attrs[-1]
+                else:
+                        name = self.__field.name
+                if isinstance(value, FieldAccessor):
+                        # Join set between two entity sets
+                        if not self.__attrs:
+                                cast = self.__field.cast
+                        else: 
+                                cast = lambda x: x
+                        for entity in self.__entities:
+                                try:
+                                        setter(component[entity], name, cast(value[entity]))
+                                except KeyError:
+                                        pass
+                else:
+                        if not self.__attrs:
+                                value = self.__field.cast(value)
+                        for entity in self.__entities:
+                                try:
+                                        setter(component[entity], name, value)
+                                except KeyError:
+                                        pass
+
+        def __getitem__(self, entity):
+                """Return the field value for a single entity (used for joins)"""
+                if entity in self.__entities:
+                        return self.__getter(self.__field.component[entity])
+                raise KeyError(entity)
+
+        def __contains__(self, entity):
+                return entity in self.__entities
+
+        def __repr__(self):
+                return '<%s %s @ %x>' % (
+                        self.__class__.__name__, 
+                        '.'.join((self.__field.name,) + self.__attrs), id(self))
+
+        def __nonzero__(self):
+                return bool(self.__entities)
+
+        def __iter__(self):
+                """Return an iterator of all field values in the set"""
+                component = self.__field.component
+                getter = self.__getter
+                for entity in self.__entities:
+                        try:
+                                data = component[entity]
+                        except KeyError:
+                                continue
+                        yield getter(data)
+
+        ## batch comparison operators ##
+
+        def __match(self, value, op):
+                component = self.__field.component
+                getter = self.__getter
+                matches = set()
+                add = matches.add
+                if isinstance(value, FieldAccessor):
+                        # Join match between entity sets
+                        for entity in self.__entities:
+                                try:
+                                        data = component[entity]
+                                        other = value[entity]
+                                except KeyError:
+                                        continue
+                                if op(getter(data), other):
+                                        add(entity)
+                else:
+                        for entity in self.__entities:
+                                try:
+                                        data = component[entity]
+                                except KeyError:
+                                        continue
+                                if op(getter(data), value):
+                                        add(entity)
+                return matches
+
+        def __eq__(self, value):
+                """Return an entity set of all entities with a matching field value"""
+                return self.__match(value, operator.eq)
+
+        def __ne__(self, value):
+                """Return an entity set of all entities not matching field value"""
+                return self.__match(value, operator.ne)
+
+        def __gt__(self, value):
+                """Return an entity set of all entities with a greater field value"""
+                return self.__match(value, operator.gt)
+
+        def __ge__(self, value):
+                """Return an entity set of all entities with a greater or equal field value"""
+                return self.__match(value, operator.ge)
+
+        def __lt__(self, value):
+                """Return an entity set of all entities with a lesser field value"""
+                return self.__match(value, operator.lt)
+
+        def __le__(self, value):
+                """Return an entity set of all entities with a lesser or equal field value"""
+                return self.__match(value, operator.le)
+
+        def _contains(self, values):
+                """Return an entity set of all entities with a field value contained in values"""
+                return self.__match(values, operator.contains)
+
+        ## Batch in-place mutator methods
+
+        def __mutate(self, value, op):
+                component = self.__field.component
+                if self.__attrs:
+                        name = self.__attrs[-1]
+                else:
+                        name = self.__field.name
+                getter = self.__getter
+                setter = self.__setter
+                if isinstance(value, FieldAccessor):
+                        # Join between entity sets
+                        for entity in self.__entities:
+                                try:
+                                        data = component[entity]
+                                        other = value[entity]
+                                except KeyError:
+                                        continue
+                                setter(data, name, op(getter(data), other))
+                else:
+                        for entity in self.__entities:
+                                try:
+                                        data = component[entity]
+                                except KeyError:
+                                        continue
+                                setter(data, name, op(getter(data), value))
+                return self
+
+        def __iadd__(self, value):
+                return self.__mutate(value, operator.iadd)
+
+        def __isub__(self, value):
+                return self.__mutate(value, operator.isub)
+
+        def __imul__(self, value):
+                return self.__mutate(value, operator.imul)
+
+        def __idiv__(self, value):
+                return self.__mutate(value, operator.idiv)
+
+        def __itruediv__(self, value):
+                return self.__mutate(value, operator.itruediv)
+
+        def __ifloordiv__(self, value):
+                return self.__mutate(value, operator.ifloordiv)
+
+        def __imod__(self, value):
+                return self.__mutate(value, operator.imod)
+
+        def __ipow__(self, value):
+                return self.__mutate(value, operator.ipow)
+
+        def __ilshift__(self, value):
+                return self.__mutate(value, operator.ilshift)
+
+        def __irshift__(self, value):
+                return self.__mutate(value, operator.irshift)
+
+        def __iand__(self, value):
+                return self.__mutate(value, operator.iand)
+
+        def __ior__(self, value):
+                return self.__mutate(value, operator.ior)
+
+        def __ixor__(self, value):
+                return self.__mutate(value, operator.ixor)
+
+
+class Field(object):
+        """Component field metadata and accessor interface"""
+
+        def __init__(self, component, name, type, accessor_factory=FieldAccessor):
+                self.component = component
+                self.name = name
+                self.type = type
+                self.default = types.get(type)
+                self.accessor_factory = accessor_factory
+
+        def cast(self, value):
+                """Cast value to the appropriate type for thi field"""
+                if self.type is not object:
+                        return self.type(value)
+                else:
+                        return value
+
+        def accessor(self, entities=None):
+                """Return the field accessor for the entities in the component,
+                or all entities in the set specified that are also in the component
+                """
+                if entities is None or entities is self.component.entities:
+                        entities = self.component.entities
+                else:
+                        entities = entities & self.component.entities
+                return self.accessor_factory(self, entities)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/component/general.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,143 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+
+__version__ = '$Id$'
+
+from bGrease.component import base
+from bGrease.component import field
+from bGrease.entity import ComponentEntitySet
+
+
+class Component(dict):
+	"""General component with a configurable schema
+
+	The field schema is defined via keyword args where the 
+	arg name is the field name and the value is the type object.
+
+	The following types are supported for fields:
+
+	- :class:`int`
+	- :class:`float`
+	- :class:`bool`
+	- :class:`str`
+	- :class:`object`
+	- |Vec2d|
+	- |Vec2dArray|
+	- |RGBA|
+	- |Rect|
+	"""
+
+	deleted_entities = ()
+	"""List of entities deleted from the component since the last time step"""
+
+	new_entities = ()
+	"""List of entities added to the component since the last time step"""
+
+	def __init__(self, **fields):
+		self.fields = {}
+		for fname, ftype in fields.items():
+			assert ftype in field.types, fname + " has an illegal field type"
+			self.fields[fname] = field.Field(self, fname, ftype)
+		self.entities = ComponentEntitySet(self)
+		self._added = []
+		self._deleted = []
+	
+	def set_world(self, world):
+		self.world = world
+	
+	def step(self, dt):
+		"""Update the component for the next timestep"""
+		delitem = super(Component, self).__delitem__
+		for entity in self._deleted:
+			delitem(entity)
+		self.new_entities = self._added
+		self.deleted_entities = self._deleted
+		self._added = []
+		self._deleted = []
+	
+	def set(self, entity, data=None, **data_kw):
+		"""Set the component data for an entity, adding it to the
+		component if it is not already a member.
+
+		If data is specified, its data for the new entity's fields are
+		copied from its attributes, making it easy to copy another
+		entity's data. Keyword arguments are also matched to fields.
+		If both a data attribute and keyword argument are supplied for
+		a single field, the keyword arg is used.
+		"""
+		if data is not None:
+			for fname, field in self.fields.items():
+				if fname not in data_kw and hasattr(data, fname):
+					data_kw[fname] = getattr(data, fname)
+		data = self[entity] = Data(self.fields, entity, **data_kw)
+		return data
+	
+	def __setitem__(self, entity, data):
+		assert entity.world is self.world, "Entity not in component's world"
+		if entity not in self.entities:
+			self._added.append(entity)
+			self.entities.add(entity)
+		super(Component, self).__setitem__(entity, data)
+	
+	def remove(self, entity):
+		if entity in self.entities:
+			self._deleted.append(entity)
+			self.entities.remove(entity)
+			return True
+		return False
+	
+	__delitem__ = remove
+
+	def __repr__(self):
+		return '<%s %x of %r>' % (
+			self.__class__.__name__, id(self), getattr(self, 'world', None))
+
+
+class Singleton(Component):
+	"""Component that may contain only a single entity"""
+
+	def add(self, entity_id, data=None, **data_kw):
+		if entity_id not in self._data:
+			self.entity_id_set.clear()
+			self._data.clear()
+		Component.add(self, entity_id, data, **data_kw)
+	
+	@property
+	def entity(self):
+		"""Return the entity in the component, or None if empty"""
+		if self._data:
+			return self.manager[self._data.keys()[0]]
+	
+
+class Data(object):
+
+	def __init__(self, fields, entity, **data):
+		self.__dict__['_Data__fields'] = fields
+		self.__dict__['entity'] = entity
+		for field in fields.values():
+			if field.name in data:
+				setattr(self, field.name, data[field.name])
+			else:
+				setattr(self, field.name, field.default())
+	
+	def __setattr__(self, name, value):
+		if name in self.__fields:
+			self.__dict__[name] = self.__fields[name].cast(value)
+		else:
+			raise AttributeError("Invalid data field: " + name)
+	
+	def __repr__(self):
+		return '<%s(%r)>' % (self.__class__.__name__, self.__dict__)
+
+			
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/component/schema.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,1 @@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/controller/__init__.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,4 @@
+
+__all__ = ('EulerMovement',)
+
+from bGrease.controller.integrator import EulerMovement
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/controller/integrator.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,42 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+
+__version__ = '$Id$'
+
+
+class EulerMovement(object):
+	"""System that applies entity movement to position using Euler's method
+
+	:param position_component: Name of :class:`grease.component.Position` 
+		component to update.
+	:param movement_component: Name of :class:`grease.component.Movement` 
+		component used to update position.
+	"""
+
+	def __init__(self, position_component='position', movement_component='movement'):
+		self.position_component = position_component
+		self.movement_component = movement_component
+	
+	def set_world(self, world):
+		"""Bind the system to a world"""
+		self.world = world
+	
+	def step(self, dt):
+		"""Apply movement to position"""
+		assert self.world is not None, "Cannot run with no world set"
+		for position, movement in self.world.components.join(
+			self.position_component, self.movement_component):
+			movement.velocity += movement.accel * dt
+			position.position += movement.velocity * dt
+			position.angle += movement.rotation * dt
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/entity.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,212 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""Grease entities are useful as actionable, interactive
+game elements that are often visible to the player.
+
+You might use entities to represent:
+
+- Characters
+- Bullets
+- Particles
+- Pick-ups
+- Space Ships
+- Weapons
+- Trees
+- Planets
+- Explosions
+
+See :ref:`an example entity class in the tutorial <tut-entity-example>`.
+"""
+
+__version__ = '$Id$'
+
+__all__ = ('Entity', 'EntityComponentAccessor', 'ComponentEntitySet')
+
+
+class EntityMeta(type):
+	"""The entity metaclass enforces fixed slots of `entity_id` and `world`
+	for all subclasses. This prevents accidental use of other entity instance 
+	attributes, which may not be saved. 
+	
+	Class attributes are not affected by this restriction, but subclasses
+	should be careful not to cause name collisions with world components,
+	which are exposed as entity attributes. Using a naming convention for
+	class attributes, such as UPPER_CASE_WITH_UNDERSCORES is recommended to
+	avoid name clashes.
+
+	Note as a result of this, entity subclasses are not allowed to define
+	`__slots__`, and doing so will cause a `TypeError` to be raised.
+	"""
+
+	def __new__(cls, name, bases, clsdict):
+		if '__slots__' in clsdict:
+			raise TypeError('__slots__ may not be defined in Entity subclasses')
+		clsdict['__slots__'] = ('world', 'entity_id')
+		return type.__new__(cls, name, bases, clsdict)
+
+
+class Entity(object):
+	"""Base class for grease entities.
+	
+	Entity objects themselves are merely identifiers within a :class:`grease.world.World`.
+	They also provide a facade for convenient entity-wise access of component
+	data. However, they do not contain any data themselves other than an
+	entity id.
+
+	Entities must be instantiated in the context of a world. To instantiate an
+	entity, you must pass the world as the first argument to the constructor.
+	Subclasses that implement the :meth:`__init__()` method, must accept the world
+	as their first argument (after ``self``). Other constructor arguments can be
+	specified arbitarily by the subclass.
+	"""
+	__metaclass__ = EntityMeta
+
+	def __new__(cls, world, *args, **kw):
+		"""Create a new entity and add it to the world"""
+		entity = object.__new__(cls)
+		entity.world = world
+		entity.entity_id = world.new_entity_id()
+		world.entities.add(entity)
+		return entity
+	
+	def __getattr__(self, name):
+		"""Return an :class:`EntityComponentAccessor` for this entity
+		for the component named.
+
+		Example::
+
+			my_entity.movement
+		"""
+		component = getattr(self.world.components, name)
+		return EntityComponentAccessor(component, self)
+	
+	def __setattr__(self, name, value):
+		"""Set the entity data in the named component for this entity.
+		This sets the values of the component fields to the values of
+		the matching attributes of the value provided. This value must
+		have attributes for each of the component fields.
+
+		This allows you to easily copy component data from one entity
+		to another.
+
+		Example::
+
+			my_entity.position = other_entity.position
+		"""
+		if name in self.__class__.__slots__:
+			super(Entity, self).__setattr__(name, value)
+		else:
+			component = getattr(self.world.components, name)
+			component.set(self, value)
+	
+	def __delattr__(self, name):
+		"""Remove this entity and its data from the component.
+		
+		Example::
+		
+			del my_entity.renderable
+		"""
+		component = getattr(self.world.components, name)
+		del component[self]
+	
+	def __hash__(self):
+		return self.entity_id
+	
+	def __eq__(self, other):
+		return self.world is other.world and self.entity_id == other.entity_id
+
+	def __repr__(self):
+		return "<%s id: %s of %s %x>" % (
+			self.__class__.__name__, self.entity_id,
+			self.world.__class__.__name__, id(self.world))
+
+	def delete(self):
+		"""Delete the entity from its world. This removes all of its
+		component data. If then entity has already been deleted, 
+		this call does nothing.
+		"""
+		self.world.entities.discard(self)
+
+	@property
+	def exists(self):
+		"""True if the entity still exists in the world"""
+		return self in self.world.entities
+
+
+class EntityComponentAccessor(object):
+	"""A facade for accessing specific component data for a single entity.
+	The implementation is lazy and does not actually access the component
+	data until needed. If an attribute is set for a component that the 
+	entity is not yet a member of, it is automatically added to the
+	component first.
+
+	:param component: The :class:`grease.Component` being accessed
+	:param entity: The :class:`Entity` being accessed
+	"""
+	
+	# beware, name mangling ahead. We want to avoid clashing with any
+	# user-configured component field names
+	__data = None
+
+	def __init__(self, component, entity):
+		clsname = self.__class__.__name__
+		self.__dict__['_%s__component' % clsname] = component
+		self.__dict__['_%s__entity' % clsname] = entity
+	
+	def __nonzero__(self):
+		"""The accessor is True if the entity is in the component,
+		False if not, for convenient membership tests
+		"""
+		return self.__entity in self.__component
+	
+	def __getattr__(self, name):
+		"""Return the data for the specified field of the entity's component"""
+		if self.__data is None:
+			try:
+				data = self.__component[self.__entity]
+			except KeyError:
+				raise AttributeError(name)
+			clsname = self.__class__.__name__
+			self.__dict__['_%s__data' % clsname] = data
+		return getattr(self.__data, name)
+	
+	def __setattr__(self, name, value):
+		"""Set the data for the specified field of the entity's component"""
+		if self.__data is None:
+			clsname = self.__class__.__name__
+			if self.__entity in self.__component:
+				self.__dict__['_%s__data' % clsname] = self.__component[self.__entity]
+			else:
+				self.__dict__['_%s__data' % clsname] = self.__component.set(self.__entity)
+		setattr(self.__data, name, value)
+
+
+class ComponentEntitySet(set):
+	"""Set of entities in a component, can be queried by component fields"""
+
+	_component = None
+
+	def __init__(self, component, entities=()):
+		self.__dict__['_component'] = component
+		super(ComponentEntitySet, self).__init__(entities)
+	
+	def __getattr__(self, name):
+		if self._component is not None and name in self._component.fields:
+			return self._component.fields[name].accessor(self)
+		raise AttributeError(name)
+	
+	def __setattr__(self, name, value):
+		if self._component is not None and name in self._component.fields:
+			self._component.fields[name].accessor(self).__set__(value)
+		raise AttributeError(name)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/geometry.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,600 @@
+__version__ = "$Id$"
+__docformat__ = "reStructuredText"
+
+import operator
+import math
+import ctypes 
+
+class Vec2d(ctypes.Structure):
+    """2d vector class, supports vector and scalar operators,
+       and also provides a bunch of high level functions
+       """
+    __slots__ = ['x', 'y']
+    
+    @classmethod
+    def from_param(cls, arg):
+        return cls(arg)
+        
+    def __init__(self, x_or_pair, y = None):
+        
+        if y == None:
+            self.x = x_or_pair[0]
+            self.y = x_or_pair[1]
+        else:
+            self.x = x_or_pair
+            self.y = y
+ 
+    def __len__(self):
+        return 2
+ 
+    def __getitem__(self, key):
+        if key == 0:
+            return self.x
+        elif key == 1:
+            return self.y
+        else:
+            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")
+ 
+    def __setitem__(self, key, value):
+        if key == 0:
+            self.x = value
+        elif key == 1:
+            self.y = value
+        else:
+            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")
+ 
+    # String representaion (for debugging)
+    def __repr__(self):
+        return 'Vec2d(%s, %s)' % (self.x, self.y)
+    
+    # Comparison
+    def __eq__(self, other):
+        if hasattr(other, "__getitem__") and len(other) == 2:
+            return self.x == other[0] and self.y == other[1]
+        else:
+            return False
+    
+    def __ne__(self, other):
+        if hasattr(other, "__getitem__") and len(other) == 2:
+            return self.x != other[0] or self.y != other[1]
+        else:
+            return True
+ 
+    def __nonzero__(self):
+        return self.x or self.y
+ 
+    # Generic operator handlers
+    def _o2(self, other, f):
+        "Any two-operator operation where the left operand is a Vec2d"
+        if isinstance(other, Vec2d):
+            return Vec2d(f(self.x, other.x),
+                         f(self.y, other.y))
+        elif (hasattr(other, "__getitem__")):
+            return Vec2d(f(self.x, other[0]),
+                         f(self.y, other[1]))
+        else:
+            return Vec2d(f(self.x, other),
+                         f(self.y, other))
+ 
+    def _r_o2(self, other, f):
+        "Any two-operator operation where the right operand is a Vec2d"
+        if (hasattr(other, "__getitem__")):
+            return Vec2d(f(other[0], self.x),
+                         f(other[1], self.y))
+        else:
+            return Vec2d(f(other, self.x),
+                         f(other, self.y))
+ 
+    def _io(self, other, f):
+        "inplace operator"
+        if (hasattr(other, "__getitem__")):
+            self.x = f(self.x, other[0])
+            self.y = f(self.y, other[1])
+        else:
+            self.x = f(self.x, other)
+            self.y = f(self.y, other)
+        return self
+ 
+    # Addition
+    def __add__(self, other):
+        if isinstance(other, Vec2d):
+            return Vec2d(self.x + other.x, self.y + other.y)
+        elif hasattr(other, "__getitem__"):
+            return Vec2d(self.x + other[0], self.y + other[1])
+        else:
+            return Vec2d(self.x + other, self.y + other)
+    __radd__ = __add__
+    
+    def __iadd__(self, other):
+        if isinstance(other, Vec2d):
+            self.x += other.x
+            self.y += other.y
+        elif hasattr(other, "__getitem__"):
+            self.x += other[0]
+            self.y += other[1]
+        else:
+            self.x += other
+            self.y += other
+        return self
+ 
+    # Subtraction
+    def __sub__(self, other):
+        if isinstance(other, Vec2d):
+            return Vec2d(self.x - other.x, self.y - other.y)
+        elif (hasattr(other, "__getitem__")):
+            return Vec2d(self.x - other[0], self.y - other[1])
+        else:
+            return Vec2d(self.x - other, self.y - other)
+    def __rsub__(self, other):
+        if isinstance(other, Vec2d):
+            return Vec2d(other.x - self.x, other.y - self.y)
+        if (hasattr(other, "__getitem__")):
+            return Vec2d(other[0] - self.x, other[1] - self.y)
+        else:
+            return Vec2d(other - self.x, other - self.y)
+    def __isub__(self, other):
+        if isinstance(other, Vec2d):
+            self.x -= other.x
+            self.y -= other.y
+        elif (hasattr(other, "__getitem__")):
+            self.x -= other[0]
+            self.y -= other[1]
+        else:
+            self.x -= other
+            self.y -= other
+        return self
+ 
+    # Multiplication
+    def __mul__(self, other):
+        if isinstance(other, Vec2d):
+            return Vec2d(self.x*other.y, self.y*other.y)
+        if (hasattr(other, "__getitem__")):
+            return Vec2d(self.x*other[0], self.y*other[1])
+        else:
+            return Vec2d(self.x*other, self.y*other)
+    __rmul__ = __mul__
+    
+    def __imul__(self, other):
+        if isinstance(other, Vec2d):
+            self.x *= other.x
+            self.y *= other.y
+        elif (hasattr(other, "__getitem__")):
+            self.x *= other[0]
+            self.y *= other[1]
+        else:
+            self.x *= other
+            self.y *= other
+        return self
+ 
+    # Division
+    def __div__(self, other):
+        return self._o2(other, operator.div)
+    def __rdiv__(self, other):
+        return self._r_o2(other, operator.div)
+    def __idiv__(self, other):
+        return self._io(other, operator.div)
+ 
+    def __floordiv__(self, other):
+        return self._o2(other, operator.floordiv)
+    def __rfloordiv__(self, other):
+        return self._r_o2(other, operator.floordiv)
+    def __ifloordiv__(self, other):
+        return self._io(other, operator.floordiv)
+ 
+    def __truediv__(self, other):
+        return self._o2(other, operator.truediv)
+    def __rtruediv__(self, other):
+        return self._r_o2(other, operator.truediv)
+    def __itruediv__(self, other):
+        return self._io(other, operator.floordiv)
+ 
+    # Modulo
+    def __mod__(self, other):
+        return self._o2(other, operator.mod)
+    def __rmod__(self, other):
+        return self._r_o2(other, operator.mod)
+ 
+    def __divmod__(self, other):
+        return self._o2(other, divmod)
+    def __rdivmod__(self, other):
+        return self._r_o2(other, divmod)
+ 
+    # Exponentation
+    def __pow__(self, other):
+        return self._o2(other, operator.pow)
+    def __rpow__(self, other):
+        return self._r_o2(other, operator.pow)
+ 
+    # Bitwise operators
+    def __lshift__(self, other):
+        return self._o2(other, operator.lshift)
+    def __rlshift__(self, other):
+        return self._r_o2(other, operator.lshift)
+ 
+    def __rshift__(self, other):
+        return self._o2(other, operator.rshift)
+    def __rrshift__(self, other):
+        return self._r_o2(other, operator.rshift)
+ 
+    def __and__(self, other):
+        return self._o2(other, operator.and_)
+    __rand__ = __and__
+ 
+    def __or__(self, other):
+        return self._o2(other, operator.or_)
+    __ror__ = __or__
+ 
+    def __xor__(self, other):
+        return self._o2(other, operator.xor)
+    __rxor__ = __xor__
+ 
+    # Unary operations
+    def __neg__(self):
+        return Vec2d(operator.neg(self.x), operator.neg(self.y))
+ 
+    def __pos__(self):
+        return Vec2d(operator.pos(self.x), operator.pos(self.y))
+ 
+    def __abs__(self):
+        return Vec2d(abs(self.x), abs(self.y))
+ 
+    def __invert__(self):
+        return Vec2d(-self.x, -self.y)
+ 
+    # vectory functions
+    def get_length_sqrd(self): 
+        """Get the squared length of the vector.
+        It is more efficent to use this method instead of first call 
+        get_length() or access .length and then do a sqrt().
+        
+        :return: The squared length
+        """
+        return self.x**2 + self.y**2
+ 
+    def get_length(self):
+        """Get the length of the vector.
+        
+        :return: The length
+        """
+        return math.sqrt(self.x**2 + self.y**2)    
+    def __setlength(self, value):
+        length = self.get_length()
+        self.x *= value/length
+        self.y *= value/length
+    length = property(get_length, __setlength, doc = """Gets or sets the magnitude of the vector""")
+       
+    def rotate(self, angle_degrees):
+        """Rotate the vector by angle_degrees degrees clockwise."""
+        radians = -math.radians(angle_degrees)
+        cos = math.cos(radians)
+        sin = math.sin(radians)
+        x = self.x*cos - self.y*sin
+        y = self.x*sin + self.y*cos
+        self.x = x
+        self.y = y
+ 
+    def rotated(self, angle_degrees):
+        """Create and return a new vector by rotating this vector by 
+        angle_degrees degrees clockwise.
+        
+        :return: Rotated vector
+        """
+        radians = -math.radians(angle_degrees)
+        cos = math.cos(radians)
+        sin = math.sin(radians)
+        x = self.x*cos - self.y*sin
+        y = self.x*sin + self.y*cos
+        return Vec2d(x, y)
+    
+    def get_angle(self):
+        if (self.get_length_sqrd() == 0):
+            return 0
+        return math.degrees(math.atan2(self.y, self.x))
+    def __setangle(self, angle_degrees):
+        self.x = self.length
+        self.y = 0
+        self.rotate(angle_degrees)
+    angle = property(get_angle, __setangle, doc="""Gets or sets the angle of a vector""")
+ 
+    def get_angle_between(self, other):
+        """Get the angle between the vector and the other in degrees
+        
+        :return: The angle
+        """
+        cross = self.x*other[1] - self.y*other[0]
+        dot = self.x*other[0] + self.y*other[1]
+        return math.degrees(math.atan2(cross, dot))
+            
+    def normalized(self):
+        """Get a normalized copy of the vector
+        
+        :return: A normalized vector
+        """
+        length = self.length
+        if length != 0:
+            return self/length
+        return Vec2d(self)
+ 
+    def normalize_return_length(self):
+        """Normalize the vector and return its length before the normalization
+        
+        :return: The length before the normalization
+        """
+        length = self.length
+        if length != 0:
+            self.x /= length
+            self.y /= length
+        return length
+ 
+    def perpendicular(self):
+        return Vec2d(-self.y, self.x)
+    
+    def perpendicular_normal(self):
+        length = self.length
+        if length != 0:
+            return Vec2d(-self.y/length, self.x/length)
+        return Vec2d(self)
+        
+    def dot(self, other):
+        """The dot product between the vector and other vector
+            v1.dot(v2) -> v1.x*v2.x + v1.y*v2.y
+            
+        :return: The dot product
+        """
+        return float(self.x*other[0] + self.y*other[1])
+        
+    def get_distance(self, other):
+        """The distance between the vector and other vector
+        
+        :return: The distance
+        """
+        return math.sqrt((self.x - other[0])**2 + (self.y - other[1])**2)
+        
+    def get_dist_sqrd(self, other):
+        """The squared distance between the vector and other vector
+        It is more efficent to use this method than to call get_distance()
+        first and then do a sqrt() on the result.
+        
+        :return: The squared distance
+        """
+        return (self.x - other[0])**2 + (self.y - other[1])**2
+        
+    def projection(self, other):
+        other_length_sqrd = other[0]*other[0] + other[1]*other[1]
+        projected_length_times_other_length = self.dot(other)
+        return other*(projected_length_times_other_length/other_length_sqrd)
+    
+    def cross(self, other):
+        """The cross product between the vector and other vector
+            v1.cross(v2) -> v1.x*v2.y - v2.y-v1.x
+        
+        :return: The cross product
+        """
+        return self.x*other[1] - self.y*other[0]
+    
+    def interpolate_to(self, other, range):
+        return Vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)
+    
+    def convert_to_basis(self, x_vector, y_vector):
+        return Vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())
+ 
+    # Extra functions, mainly for chipmunk
+    def cpvrotate(self, other):
+        return Vec2d(self.x*other.x - self.y*other.y, self.x*other.y + self.y*other.x)
+    def cpvunrotate(self, other):
+        return Vec2d(self.x*other.x + self.y*other.y, self.y*other.x - self.x*other.y)
+    
+    # Pickle, does not work atm.
+    def __getstate__(self):
+        return [self.x, self.y]
+        
+    def __setstate__(self, dict):
+        self.x, self.y = dict
+    def __newobj__(cls, *args):
+        return cls.__new__(cls, *args)    
+Vec2d._fields_ = [
+            ('x', ctypes.c_double),
+            ('y', ctypes.c_double),
+        ]
+
+
+class Vec2dArray(list):
+
+	def __init__(self, iterable=()):
+		list.__init__(self, (Vec2d(i) for i in iterable))
+
+	def __setitem__(self, index, value):
+		list.__setitem__(self, index, Vec2d(value))
+	
+	def append(self, value):
+		"""Append a vector to the array"""
+		list.append(self, Vec2d(value))
+	
+	def insert(self, index, value):
+		"""Insert a vector into the array"""
+		list.insert(self, index, Vec2d(value))
+	
+	def transform(self, offset=Vec2d(0,0), angle=0, scale=1.0):
+		"""Return a new transformed Vec2dArray"""
+		offset = Vec2d(offset)
+		angle = math.radians(-angle)
+		rot_vec = Vec2d(math.cos(angle), math.sin(angle))
+		xformed = Vec2dArray()
+		for vec in self:
+			xformed.append(vec.cpvrotate(rot_vec) * scale + offset)
+		return xformed
+	
+	def segments(self, closed=True):
+		"""Generate arrays of line segments connecting adjacent vetices
+		in this array, exploding the shape into it's constituent segments
+		"""
+		if len(self) >= 2:
+			last = self[0]
+			for vert in self[1:]:
+				yield Vec2dArray((last, vert))
+				last = vert
+			if closed:
+				yield Vec2dArray((last, self[0]))
+		elif self and closed:
+			yield Vec2dArray((self[0], self[0]))
+
+
+
+class Rect(ctypes.Structure):
+	"""Simple rectangle. Will gain more functionality as needed"""
+	_fields_ = [
+		('left', ctypes.c_double),
+		('top', ctypes.c_double),
+		('right', ctypes.c_double),
+		('bottom', ctypes.c_double),
+	]
+
+	def __init__(self, rect_or_left, bottom=None, right=None, top=None):
+		if bottom is not None:
+			assert right is not None and top is not None, "No enough arguments to Rect"
+			self.left = rect_or_left
+			self.bottom = bottom
+			self.right = right
+			self.top = top
+		else:
+			self.left = rect_or_left.left
+			self.bottom = rect_or_left.bottom
+			self.right = rect_or_left.right
+			self.top = rect_or_left.top
+
+	@property
+	def width(self):
+		"""Rectangle width"""
+		return self.right - self.left
+	
+	@property
+	def height(self):
+		"""Rectangle height"""
+		return self.top - self.bottom
+
+
+########################################################################
+## Unit Testing                                                       ##
+########################################################################
+if __name__ == "__main__":
+ 
+    import unittest
+    import pickle
+ 
+    ####################################################################
+    class UnitTestVec2d(unittest.TestCase):
+    
+        def setUp(self):
+            pass
+        
+        def testCreationAndAccess(self):
+            v = Vec2d(111, 222)
+            self.assert_(v.x == 111 and v.y == 222)
+            v.x = 333
+            v[1] = 444
+            self.assert_(v[0] == 333 and v[1] == 444)
+ 
+        def testMath(self):
+            v = Vec2d(111,222)
+            self.assertEqual(v + 1, Vec2d(112, 223))
+            self.assert_(v - 2 == [109, 220])
+            self.assert_(v * 3 == (333, 666))
+            self.assert_(v / 2.0 == Vec2d(55.5, 111))
+            #self.assert_(v / 2 == (55, 111)) # Not supported since this is a c_float structure in the bottom
+            self.assert_(v ** Vec2d(2, 3) == [12321, 10941048])
+            self.assert_(v + [-11, 78] == Vec2d(100, 300))
+            #self.assert_(v / [11,2] == [10,111]) # Not supported since this is a c_float structure in the bottom
+ 
+        def testReverseMath(self):
+            v = Vec2d(111, 222)
+            self.assert_(1 + v == Vec2d(112, 223))
+            self.assert_(2 - v == [-109, -220])
+            self.assert_(3 * v == (333, 666))
+            #self.assert_([222,999] / v == [2,4]) # Not supported since this is a c_float structure in the bottom
+            self.assert_([111, 222] ** Vec2d(2, 3) == [12321, 10941048])
+            self.assert_([-11, 78] + v == Vec2d(100, 300))
+ 
+        def testUnary(self):
+            v = Vec2d(111, 222)
+            v = -v
+            self.assert_(v == [-111, -222])
+            v = abs(v)
+            self.assert_(v == [111, 222])
+ 
+        def testLength(self):
+            v = Vec2d(3,4)
+            self.assert_(v.length == 5)
+            self.assert_(v.get_length_sqrd() == 25)
+            self.assert_(v.normalize_return_length() == 5)
+            self.assertAlmostEquals(v.length, 1)
+            v.length = 5
+            self.assert_(v == Vec2d(3, 4))
+            v2 = Vec2d(10, -2)
+            self.assert_(v.get_distance(v2) == (v - v2).get_length())
+            
+        def testAngles(self):            
+            v = Vec2d(0, 3)
+            self.assertEquals(v.angle, 90)
+            v2 = Vec2d(v)
+            v.rotate(-90)
+            self.assertEqual(v.get_angle_between(v2), 90)
+            v2.angle -= 90
+            self.assertEqual(v.length, v2.length)
+            self.assertEquals(v2.angle, 0)
+            self.assertEqual(v2, [3, 0])
+            self.assert_((v - v2).length < .00001)
+            self.assertEqual(v.length, v2.length)
+            v2.rotate(300)
+            self.assertAlmostEquals(v.get_angle_between(v2), -60, 5) # Allow a little more error than usual (floats..)
+            v2.rotate(v2.get_angle_between(v))
+            angle = v.get_angle_between(v2)
+            self.assertAlmostEquals(v.get_angle_between(v2), 0)  
+ 
+        def testHighLevel(self):
+            basis0 = Vec2d(5.0, 0)
+            basis1 = Vec2d(0, .5)
+            v = Vec2d(10, 1)
+            self.assert_(v.convert_to_basis(basis0, basis1) == [2, 2])
+            self.assert_(v.projection(basis0) == (10, 0))
+            self.assert_(basis0.dot(basis1) == 0)
+            
+        def testCross(self):
+            lhs = Vec2d(1, .5)
+            rhs = Vec2d(4, 6)
+            self.assert_(lhs.cross(rhs) == 4)
+            
+        def testComparison(self):
+            int_vec = Vec2d(3, -2)
+            flt_vec = Vec2d(3.0, -2.0)
+            zero_vec = Vec2d(0, 0)
+            self.assert_(int_vec == flt_vec)
+            self.assert_(int_vec != zero_vec)
+            self.assert_((flt_vec == zero_vec) == False)
+            self.assert_((flt_vec != int_vec) == False)
+            self.assert_(int_vec == (3, -2))
+            self.assert_(int_vec != [0, 0])
+            self.assert_(int_vec != 5)
+            self.assert_(int_vec != [3, -2, -5])
+        
+        def testInplace(self):
+            inplace_vec = Vec2d(5, 13)
+            inplace_ref = inplace_vec
+            inplace_src = Vec2d(inplace_vec)    
+            inplace_vec *= .5
+            inplace_vec += .5
+            inplace_vec /= (3, 6)
+            inplace_vec += Vec2d(-1, -1)
+            alternate = (inplace_src*.5 + .5)/Vec2d(3, 6) + [-1, -1]
+            self.assertEquals(inplace_vec, inplace_ref)
+            self.assertEquals(inplace_vec, alternate)
+        
+        def testPickle(self):
+            return # pickling does not work atm
+            testvec = Vec2d(5, .3)
+            testvec_str = pickle.dumps(testvec)
+            loaded_vec = pickle.loads(testvec_str)
+            self.assertEquals(testvec, loaded_vec)
+    
+    ####################################################################
+    unittest.main()
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/impl/__init__.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,22 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+
+__versioninfo__ = (0, 3, 0)
+__version__ = '.'.join(str(n) for n in __versioninfo__)
+
+__all__ = ('Mode', 'World')
+
+from mode import Mode
+from world import World
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/impl/controls.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,216 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""Control systems for binding controls to game logic"""
+
+import bGrease
+from pyglet.window import key
+
+class KeyControls(grease.System):
+	"""System that maps subclass-defined action methods to keys. 
+
+	Keys may be mapped in the subclass definition using decorators
+	defined here as class methods or at runtime using the ``bind_key_*`` 
+	instance methods.
+
+	See :ref:`an example implementation in the tutorial <tut-controls-example>`.
+	"""
+	MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CAPSLOCK)
+	"""The MODIFIER_MASK allows you to filter out modifier keys that should be
+	ignored by the application. By default, capslock, numlock, and scrolllock 
+	are ignored.
+	"""
+
+	world = None
+	""":class:`grease.World` object this system is bound to"""
+
+	def __init__(self):
+		self._key_press_map = {}
+		self._key_release_map = {}
+		self._key_hold_map = {}
+		for name in self.__class__.__dict__:
+			member = getattr(self, name)
+			if hasattr(member, '_grease_hold_key_binding'):
+				for binding in member._grease_hold_key_binding:
+					self.bind_key_hold(member, *binding)
+			if hasattr(member, '_grease_press_key_binding'):
+				for binding in member._grease_press_key_binding:
+					self.bind_key_press(member, *binding)
+			if hasattr(member, '_grease_release_key_binding'):
+				for binding in member._grease_release_key_binding:
+					self.bind_key_release(member, *binding)
+		self.held_keys = set()
+
+	## decorator methods for binding methods to key input events ##
+
+	@classmethod
+	def key_hold(cls, symbol, modifiers=0):
+		"""Decorator to bind a method to be executed where a key is held down"""
+		def bind(f):
+			if not hasattr(f, '_grease_hold_key_binding'):
+				f._grease_hold_key_binding = []
+			f._grease_hold_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
+			return f
+		return bind
+
+	@classmethod
+	def key_press(cls, symbol, modifiers=0):
+		"""Decorator to bind a method to be executed where a key is initially depressed"""
+		def bind(f):
+			if not hasattr(f, '_grease_press_key_binding'):
+				f._grease_press_key_binding = []
+			f._grease_press_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
+			return f
+		return bind
+
+	@classmethod
+	def key_release(cls, symbol, modifiers=0):
+		"""Decorator to bind a method to be executed where a key is released"""
+		def bind(f):
+			if not hasattr(f, '_grease_release_key_binding'):
+				f._grease_release_key_binding = []
+			f._grease_release_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
+			return f
+		return bind
+	
+	## runtime binding methods ##
+	
+	def bind_key_hold(self, method, key, modifiers=0):
+		"""Bind a method to a key at runtime to be invoked when the key is
+		held down, this replaces any existing key hold binding for this key.
+		To unbind the key entirely, pass ``None`` for method.
+		"""
+		if method is not None:
+			self._key_hold_map[key, modifiers & self.MODIFIER_MASK] = method
+		else:
+			try:
+				del self._key_hold_map[key, modifiers & self.MODIFIER_MASK]
+			except KeyError:
+				pass
+
+	def bind_key_press(self, method, key, modifiers=0):
+		"""Bind a method to a key at runtime to be invoked when the key is initially
+		pressed, this replaces any existing key hold binding for this key. To unbind
+		the key entirely, pass ``None`` for method.
+		"""
+		if method is not None:
+			self._key_press_map[key, modifiers & self.MODIFIER_MASK] = method
+		else:
+			try:
+				del self._key_press_map[key, modifiers & self.MODIFIER_MASK]
+			except KeyError:
+				pass
+
+	def bind_key_release(self, method, key, modifiers=0):
+		"""Bind a method to a key at runtime to be invoked when the key is releaseed,
+		this replaces any existing key hold binding for this key. To unbind
+		the key entirely, pass ``None`` for method.
+		"""
+		if method is not None:
+			self._key_release_map[key, modifiers & self.MODIFIER_MASK] = method
+		else:
+			try:
+				del self._key_release_map[key, modifiers & self.MODIFIER_MASK]
+			except KeyError:
+				pass
+
+	def step(self, dt):
+		"""invoke held key functions"""
+		already_run = set()
+		for key in self.held_keys:
+			func = self._key_hold_map.get(key)
+			if func is not None and func not in already_run:
+				already_run.add(func)
+				func(dt)
+
+	def on_key_press(self, key, modifiers):
+		"""Handle pyglet key press. Invoke key press methods and
+		activate key hold functions
+		"""
+		key_mod = (key, modifiers & self.MODIFIER_MASK)
+		if key_mod in self._key_press_map:
+			self._key_press_map[key_mod]()
+		self.held_keys.add(key_mod)
+	
+	def on_key_release(self, key, modifiers):
+		"""Handle pyglet key release. Invoke key release methods and
+		deactivate key hold functions
+		"""
+		key_mod = (key, modifiers & self.MODIFIER_MASK)
+		if key_mod in self._key_release_map:
+			self._key_release_map[key_mod]()
+		self.held_keys.discard(key_mod)
+
+
+if __name__ == '__main__':
+	import pyglet
+
+	class TestKeyControls(KeyControls):
+		
+		MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CTRL)
+
+		remapped = False
+		
+		@KeyControls.key_hold(key.UP)
+		@KeyControls.key_hold(key.W)
+		def up(self, dt):
+			print 'UP!'
+		
+		@KeyControls.key_hold(key.LEFT)
+		@KeyControls.key_hold(key.A)
+		def left(self, dt):
+			print 'LEFT!'
+		
+		@KeyControls.key_hold(key.RIGHT)
+		@KeyControls.key_hold(key.D)
+		def right(self, dt):
+			print 'RIGHT!'
+		
+		@KeyControls.key_hold(key.DOWN)
+		@KeyControls.key_hold(key.S)
+		def down(self, dt):
+			print 'DOWN!'
+
+		@KeyControls.key_press(key.SPACE)
+		def fire(self):
+			print 'FIRE!'
+
+		@KeyControls.key_press(key.R)
+		def remap_keys(self):
+			if not self.remapped:
+				self.bind_key_hold(None, key.W)
+				self.bind_key_hold(None, key.A)
+				self.bind_key_hold(None, key.S)
+				self.bind_key_hold(None, key.D)
+				self.bind_key_hold(self.up, key.I)
+				self.bind_key_hold(self.left, key.J)
+				self.bind_key_hold(self.right, key.L)
+				self.bind_key_hold(self.down, key.K)
+			else:
+				self.bind_key_hold(None, key.I)
+				self.bind_key_hold(None, key.J)
+				self.bind_key_hold(None, key.K)
+				self.bind_key_hold(None, key.L)
+				self.bind_key_hold(self.up, key.W)
+				self.bind_key_hold(self.left, key.A)
+				self.bind_key_hold(self.right, key.D)
+				self.bind_key_hold(self.down, key.S)
+			self.remapped = not self.remapped
+			
+
+	window = pyglet.window.Window()
+	window.clear()
+	controls = TestKeyControls()
+	window.push_handlers(controls)
+	pyglet.clock.schedule_interval(controls.step, 0.5)
+	pyglet.app.run()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/impl/mode.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,203 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""
+Modes manage the state and transition between different application modes.
+Typically such modes are presented as different screens that the user can
+navigate between, similar to the way a browser navigates web pages. Individual
+modes may be things like:
+
+- Title screen
+- Options dialog
+- About screen
+- In-progress game
+- Inventory interface
+
+The modal framework provides a simple mechanism to ensure that modes are
+activated and deactivated properly. An activated mode is running and receives
+events. A deactivated mode is paused and does not receive events.
+
+Modes may be managed as a *last-in-first-out* stack, or as a list, or ring
+of modes in sequence, or some combination of all.
+
+For example usage see: :ref:`the mode section of the tutorial <tut-mode-section>`.
+"""
+
+__version__ = '$Id$'
+
+import abc
+import pyglet
+from bGrease.mode import *
+
+class PygletManager(BaseManager):
+	"""Mode manager abstract base class using pyglet.
+	
+	The mode manager keeps a stack of modes where a single mode
+	is active at one time. As modes are pushed on and popped from 
+	the stack, the mode at the top is always active. The current
+	active mode receives events from the manager's event dispatcher.
+	"""
+
+	event_dispatcher = None
+	""":class:`pyglet.event.EventDispatcher` object that the
+	active mode receive events from.
+	"""
+	
+	def activate_mode(self, mode):
+		"""Perform actions to activate a node
+		
+		:param mode: The :class: 'Mode' object to activate
+		"""
+		BaseManager.activate_mode(self, mode)
+		self.event_dispatcher.push_handlers(mode)
+		
+	def deactivate_mode(self, mode):
+		"""Perform actions to deactivate a node
+		
+		:param mode: The :class: 'Mode' object to deactivate
+		"""
+		BaseManager.deactivate_mode(self, mode)
+		self.event_dispatcher.remove_handlers(mode)
+
+class Manager(PygletManager):
+	"""A basic mode manager that wraps a single
+	:class:`pyglet.event.EventDispatcher` object for use by its modes.
+	"""
+
+	def __init__(self, event_dispatcher):
+		self.modes = []
+		self.event_dispatcher = event_dispatcher
+
+
+class ManagerWindow(PygletManager, pyglet.window.Window):
+	"""An integrated mode manager and pyglet window for convenience.
+	The window is the event dispatcher used by modes pushed to
+	this manager.
+
+	Constructor arguments are identical to :class:`pyglet.window.Window`
+	"""
+	
+	def __init__(self, *args, **kw):
+		super(ManagerWindow, self).__init__(*args, **kw)
+		self.modes = []
+		self.event_dispatcher = self
+
+	def on_key_press(self, symbol, modifiers):
+		"""Default :meth:`on_key_press handler`, pops the current mode on ``ESC``"""
+		if symbol == pyglet.window.key.ESCAPE:
+			self.pop_mode()
+
+	def on_last_mode_pop(self, mode):
+		"""Hook executed when the last mode is popped from the manager.
+		When the last mode is popped from a window, an :meth:`on_close` event
+		is dispatched.
+
+		:param mode: The :class:`Mode` object just popped from the manager
+		"""
+		self.dispatch_event('on_close')
+
+
+class Mode(BaseMode):
+	"""Application mode abstract base class using pyglet
+
+	Subclasses must implement the :meth:`step` method
+	
+	:param step_rate: The rate of :meth:`step()` calls per second. 
+
+	:param master_clock: The :class:`pyglet.clock.Clock` interface used
+		as the master clock that ticks the world's clock. This 
+		defaults to the main pyglet clock.
+	"""
+	clock = None
+	"""The :class:`pyglet.clock.Clock` instance used as this mode's clock.
+	You should use this clock to schedule tasks for this mode, so they
+	properly respect when the mode is active or inactive
+
+	Example::
+
+		my_mode.clock.schedule_once(my_cool_function, 4)
+	"""
+
+	def __init__(self, step_rate=60, master_clock=pyglet.clock, 
+		         clock_factory=pyglet.clock.Clock):
+		BaseMode.__init__(self)
+		self.step_rate = step_rate
+		self.time = 0.0
+		self.master_clock = master_clock
+		self.clock = clock_factory(time_function=lambda: self.time)
+		self.clock.schedule_interval(self.step, 1.0 / step_rate)
+	
+	def on_activate(self):
+		"""Being called when the Mode is activated"""
+		self.master_clock.schedule(self.tick)
+	
+	def on_deactivate(self):
+		"""Being called when the Mode is deactivated"""
+		self.master_clock.unschedule(self.tick)
+		
+	def tick(self, dt):
+		"""Tick the mode's clock.
+
+		:param dt: The time delta since the last tick
+		:type dt: float
+		"""
+		self.time += dt
+		self.clock.tick(poll=False)
+	
+	@abc.abstractmethod
+	def step(self, dt):
+		"""Execute a timestep for this mode. Must be defined by subclasses.
+		
+		:param dt: The time delta since the last time step
+		:type dt: float
+		"""
+
+class Multi(BaseMulti, Mode):
+	"""A mode with multiple submodes. One submode is active at one time.
+	Submodes can be switched to directly or switched in sequence. If
+	the Multi is active, then one submode is always active.
+
+	Multis are useful when modes can switch in an order other than
+	a LIFO stack, such as in "hotseat" multiplayer games, a
+	"wizard" style ui, or a sequence of slides.
+
+	Note unlike a normal :class:`Mode`, a :class:`Multi` doesn't have it's own
+	:attr:`clock` and :attr:`step_rate`. The active submode's are used
+	instead.
+	"""
+	
+	def __init__(self, submodes):
+		BaseMulti.__init__(self, submodes)
+		self.time = 0.0
+
+	
+	def _set_active_submode(self, submode):
+		BaseMulti._set_active_submode(self, submode)
+		self.master_clock = submode.master_clock
+		self.clock = submode.clock
+
+	def clear_subnode(self):
+		"""Clear any subnmode data"""
+		BaseMulti.clear_subnode(self)
+		self.master_clock = None
+		self.clock = None
+
+	def tick(self, dt):
+		"""Tick the active submode's clock.
+
+		:param dt: The time delta since the last tick
+		:type dt: float
+		"""
+		self.time += dt
+		if self.active_submode is not None:
+			self.active_submode.clock.tick(poll=False)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/impl/world.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,129 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""Worlds are environments described by a configuration of components, systems and 
+renderers. These parts describe the data, behavioral and presentation aspects
+of the world respectively.
+
+The world environment is the context within which entities exist. A typical
+application consists of one or more worlds containing entities that evolve
+over time and react to internal and external interaction.
+
+See :ref:`an example of world configuration in the tutorial <tut-world-example>`.
+"""
+
+__version__ = '$Id$'
+
+import itertools
+import pyglet
+from pyglet import gl
+from bGrease.world import *
+from bGrease.impl import Mode
+
+class World(Mode, BaseWorld):
+	"""A coordinated collection of components, systems and entities
+	
+	A world is also a mode that may be pushed onto a 
+	:class:`grease.mode.Manager`
+
+	:param step_rate: The rate of :meth:`step()` calls per second. 
+
+	:param master_clock: The :class:`pyglet.clock.Clock` interface used
+		as the master clock that ticks the world's clock. This 
+		defaults to the main pyglet clock.
+	"""
+
+	clock = None
+	""":class:`pyglet.clock` interface for use by constituents
+	of the world for scheduling
+	"""
+
+	time = None
+	"""Current clock time of the world, starts at 0 when the world
+	is instantiated
+	"""
+
+	running = True
+	"""Flag to indicate that the world clock is running, advancing time
+	and stepping the world. Set running to False to pause the world.
+	"""
+
+	def __init__(self, step_rate=60, master_clock=pyglet.clock,
+				 clock_factory=pyglet.clock.Clock):
+		Mode.__init__(self, step_rate, master_clock, clock_factory)
+		BaseWorld.__init__(self)
+	
+	def activate(self, manager):
+		"""Activate the world/mode for the given manager, if the world is already active, 
+		do nothing. This method is typically not used directly, it is called
+		automatically by the mode manager when the world becomes active.
+
+		The systems of the world are pushed onto `manager.event_dispatcher`
+		so they can receive system events.
+
+		:param manager: :class:`mode.BaseManager` instance
+		"""
+		if not self.active:
+			for system in self.systems:
+				manager.event_dispatcher.push_handlers(system)
+		super(World, self).activate(manager)
+	
+	def deactivate(self, manager):
+		"""Deactivate the world/mode, if the world is not active, do nothing.
+		This method is typically not used directly, it is called
+		automatically by the mode manager when the world becomes active.
+
+		Removes the system handlers from the `manager.event_dispatcher`
+
+		:param manager: :class:`mode.BaseManager` instance
+		"""
+		for system in self.systems:
+			manager.event_dispatcher.remove_handlers(system)
+		super(World, self).deactivate(manager)
+
+	def tick(self, dt):
+		"""Tick the mode's clock, but only if the world is currently running
+		
+		:param dt: The time delta since the last tick
+		:type dt: float
+		"""
+		if self.running:
+			super(World, self).tick(dt)
+	
+	def step(self, dt):
+		"""Execute a time step for the world. Updates the world `time`
+		and invokes the world's systems.
+		
+		Note that the specified time delta will be pinned to 10x the
+		configured step rate. For example if the step rate is 60,
+		then dt will be pinned at a maximum of 0.1666. This avoids 
+		pathological behavior when the time between steps goes
+		much longer than expected.
+
+		:param dt: The time delta since the last time step
+		:type dt: float
+		"""
+		dt = min(dt, 10.0 / self.step_rate)
+		for component in self.components:
+			if hasattr(component, "step"):
+				component.step(dt)
+		for system in self.systems:
+			if hasattr(system, "step"):
+				system.step(dt)
+
+	def on_draw(self, gl=pyglet.gl):
+		"""Clear the current OpenGL context, reset the model/view matrix and
+		invoke the `draw()` methods of the renderers in order
+		"""
+		gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
+		gl.glLoadIdentity()
+		BaseWorld.draw_renderers(self)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/mode.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,391 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""
+Modes manage the state and transition between different application modes.
+Typically such modes are presented as different screens that the user can
+navigate between, similar to the way a browser navigates web pages. Individual
+modes may be things like:
+
+- Title screen
+- Options dialog
+- About screen
+- In-progress game
+- Inventory interface
+
+The modal framework provides a simple mechanism to ensure that modes are
+activated and deactivated properly. An activated mode is running and receives
+events. A deactivated mode is paused and does not receive events.
+
+Modes may be managed as a *last-in-first-out* stack, or as a list, or ring
+of modes in sequence, or some combination of all.
+
+For example usage see: :ref:`the mode section of the tutorial <tut-mode-section>`.
+"""
+
+__version__ = '$Id$'
+
+import abc
+
+
+class BaseManager(object):
+	"""Mode manager abstract base class.
+	
+	The mode manager keeps a stack of modes where a single mode
+	is active at one time. As modes are pushed on and popped from 
+	the stack, the mode at the top is always active. The current
+	active mode receives events from the manager's event dispatcher.
+	"""
+
+	modes = ()
+	"""The mode stack sequence. The last mode in the stack is
+	the current active mode. Read-only.
+	"""
+
+	@property
+	def current_mode(self):
+		"""The current active mode or ``None``. Read-only"""
+		try:
+			return self.modes[-1]
+		except IndexError:
+			return None
+	
+	def on_last_mode_pop(self, mode):
+		"""Hook executed when the last mode is popped from the manager.
+		Implementing this method is optional for subclasses.
+
+		:param mode: The :class:`Mode` object just popped from the manager
+		"""
+	
+	def activate_mode(self, mode):
+		"""Perform actions to activate a node
+		
+		:param mode: The :class: 'Mode' object to activate
+		"""
+		mode.activate(self)
+
+	def deactivate_mode(self, mode):
+		"""Perform actions to deactivate a node
+		
+		:param mode: The :class: 'Mode' object to deactivate
+		"""
+		mode.deactivate(self)
+
+		
+	def push_mode(self, mode):
+		"""Push a mode to the top of the mode stack and make it active
+		
+		:param mode: The :class:`Mode` object to make active
+		"""
+		current = self.current_mode
+		if current is not None:
+			self.deactivate_mode(current)
+		self.modes.append(mode)
+		self.activate_mode(mode)
+	
+	def pop_mode(self):
+		"""Pop the current mode off the top of the stack and deactivate it.
+		The mode now at the top of the stack, if any is then activated.
+
+		:param mode: The :class:`Mode` object popped from the stack
+		"""
+		mode = self.modes.pop()
+		mode.deactivate(self)
+		current = self.current_mode
+		if current is not None:
+			self.activate_mode(current)
+		else:
+			self.on_last_mode_pop(mode)
+		return mode
+	
+	def swap_modes(self, mode):
+		"""Exchange the specified mode with the mode at the top of the stack.
+		This is similar to popping the current mode and pushing the specified
+		one, but without activating the previous mode on the stack or
+		executing :meth:`on_last_mode_pop()` if there is no previous mode.
+
+		:param mode: The :class:`Mode` object that was deactivated and replaced.
+		"""
+		old_mode = self.modes.pop()
+		self.deactivate_mode(old_mode)
+		self.modes.append(mode)
+		self.activate_mode(mode)
+		return old_mode
+	
+	def remove_mode(self, mode):
+		"""Remove the specified mode. If the mode is at the top of the stack,
+		this is equivilent to :meth:`pop_mode()`. If not, no other modes
+		are affected. If the mode is not in the manager, do nothing.
+
+		:param mode: The :class:`Mode` object to remove from the manager.
+		"""
+		if self.current_mode is mode:
+			self.pop_mode()
+		else:
+			try:
+				self.modes.remove(mode)
+			except ValueError:
+				pass
+
+class BaseMode(object):
+	"""Application mode very abstract base class
+	"""
+	__metaclass__ = abc.ABCMeta
+
+	manager = None
+	"""The :class:`BaseManager` that manages this mode"""
+
+	def __init__(self):
+		self.active = False
+		
+	def on_activate(self):
+		"""Being called when the Mode is activated"""
+		pass
+	
+	def activate(self, mode_manager):
+		"""Activate the mode for the given mode manager, if the mode is already active, 
+		do nothing
+
+		The default implementation schedules time steps at :attr:`step_rate` per
+		second, sets the :attr:`manager` and sets the :attr:`active` flag to True.
+		"""
+		if not self.active:
+			self.on_activate()
+			self.manager = mode_manager
+			self.active = True
+
+	def on_deactivate(self):
+		"""Being called when the Mode is deactivated"""
+		pass
+
+	def deactivate(self, mode_manager):
+		"""Deactivate the mode, if the mode is not active, do nothing
+
+		The default implementation unschedules time steps for the mode and
+		sets the :attr:`active` flag to False.
+		"""
+		self.on_deactivate()
+		self.active = False
+
+
+class BaseMulti(BaseMode):
+	"""A mode with multiple submodes. One submode is active at one time.
+	Submodes can be switched to directly or switched in sequence. If
+	the Multi is active, then one submode is always active.
+
+	Multis are useful when modes can switch in an order other than
+	a LIFO stack, such as in "hotseat" multiplayer games, a
+	"wizard" style ui, or a sequence of slides.
+
+	Note unlike a normal :class:`Mode`, a :class:`Multi` doesn't have it's own
+	:attr:`clock` and :attr:`step_rate`. The active submode's are used
+	instead.
+	"""
+	active_submode = None
+	"""The currently active submode"""
+
+	def __init__(self, *submodes):
+		# We do not invoke the superclass __init__ intentionally
+		self.active = False
+		self.submodes = list(submodes)
+	
+	def add_submode(self, mode, before=None, index=None):
+		"""Add the submode, but do not make it active.
+
+		:param mode: The :class:`Mode` object to add.
+
+		:param before: The existing mode to insert the mode before. 
+			If the mode specified is not a submode, raise
+			ValueError.
+
+		:param index: The place to insert the mode in the mode list.
+			Only one of ``before`` or ``index`` may be specified.
+
+			If neither ``before`` or ``index`` are specified, the
+			mode is appended to the end of the list.
+		"""
+		assert before is None or index is None, (
+			"Cannot specify both 'before' and 'index' arguments")
+		if before is not None:
+			index = self.submodes.index(mode)
+		if index is not None:
+			self.submodes.insert(index, mode)
+		else:
+			self.submodes.append(mode)
+	
+	def remove_submode(self, mode=None):
+		"""Remove the submode.
+
+		:param mode: The submode to remove, if omitted the active submode
+			is removed. If the mode is not present, do nothing.  If the
+			mode is active, it is deactivated, and the next mode, if any
+			is activated. If the last mode is removed, the :class:`Multi`
+			is removed from its manager. 
+		"""
+		# TODO handle multiple instances of the same subnode
+		if mode is None:
+			mode = self.active_submode
+		elif mode not in self.submodes:
+			return
+		next_mode = self.activate_next()
+		self.submodes.remove(mode)
+		if next_mode is mode:
+			if self.manager is not None:
+				self.manager.remove_mode(self)
+			self._deactivate_submode()
+				
+	def activate_subnode(self, mode, before=None, index=None):
+		"""Activate the specified mode, adding it as a subnode
+		if it is not already. If the mode is already the active
+		submode, do nothing.
+
+		:param mode: The mode to activate, and add as necesary.
+
+		:param before: The existing mode to insert the mode before
+			if it is not already a submode.  If the mode specified is not
+			a submode, raise ValueError.
+
+		:param index: The place to insert the mode in the mode list
+			if it is not already a submode.  Only one of ``before`` or
+			``index`` may be specified.
+
+			If the mode is already a submode, the ``before`` and ``index``
+			arguments are ignored.
+		"""
+		if mode not in self.submodes:
+			self.add_submode(mode, before, index)
+		if self.active_submode is not mode:
+			self._activate_submode(mode)
+	
+	def activate_next(self, loop=True):
+		"""Activate the submode after the current submode in order.  If there
+		is no current submode, the first submode is activated.
+
+		Note if there is only one submode, it's active, and `loop` is True
+		(the default), then this method does nothing and the subnode remains
+		active.
+
+		:param loop: When :meth:`activate_next` is called 
+			when the last submode is active, a True value for ``loop`` will
+			cause the first submode to be activated.  Otherwise the
+			:class:`Multi` is removed from its manager.
+		:type loop: bool
+
+		:return:
+			The submode that was activated or None if there is no
+			other submode to activate.
+		"""
+		assert self.submodes, "No submode to activate"
+		next_mode = None
+		if self.active_submode is None:
+			next_mode = self.submodes[0]
+		else:
+			last_mode = self.active_submode
+			index = self.submodes.index(last_mode) + 1
+			if index < len(self.submodes):
+				next_mode = self.submodes[index]
+			elif loop:
+				next_mode = self.submodes[0]
+		self._activate_submode(next_mode)
+		return next_mode
+
+	def activate_previous(self, loop=True):
+		"""Activate the submode before the current submode in order.  If there
+		is no current submode, the last submode is activated.
+
+		Note if there is only one submode, it's active, and `loop` is True
+		(the default), then this method does nothing and the subnode remains
+		active.
+		
+		:param loop: When :meth:`activate_previous` is called 
+			when the first submode is active, a True value for ``loop`` will
+			cause the last submode to be activated.  Otherwise the
+			:class:`Multi` is removed from its manager.
+		:type loop: bool
+
+		:return:
+			The submode that was activated or None if there is no
+			other submode to activate.
+		"""
+		assert self.submodes, "No submode to activate"
+		prev_mode = None
+		if self.active_submode is None:
+			prev_mode = self.submodes[-1]
+		else:
+			last_mode = self.active_submode
+			index = self.submodes.index(last_mode) - 1
+			if loop or index >= 0:
+				prev_mode = self.submodes[index]
+		self._activate_submode(prev_mode)
+		return prev_mode
+	
+	def _set_active_submode(self, submode):
+		self.active_submode = submode
+		self.step_rate = submode.step_rate
+
+	def _activate_submode(self, submode):
+		"""Activate a submode deactivating any current submode. If the Multi
+		itself is active, this happens immediately, otherwise the actual
+		activation is deferred until the Multi is activated. If the submode
+		is None, the Mulitmode is removed from its manager.
+
+		If submode is already the active submode, do nothing.
+		"""
+		if self.active_submode is submode:
+			return
+		assert submode in self.submodes, "Unknown submode"
+		self._deactivate_submode()
+		self._set_active_submode(submode)
+		if submode is not None:
+			if self.active:
+				self.manager.activate_mode(submode)
+		else:
+			if self.manager is not None:
+				self.manager.remove_mode(self)
+	
+	def clear_subnode(self):
+		"""Clear any subnmode data"""
+		self.active_submode = None
+		self.step_rate = None
+				
+	def _deactivate_submode(self, clear_subnode=True):
+		"""Deactivate the current submode, if any. if `clear_subnode` is
+		True, `active_submode` is always None when this method returns
+		"""
+		if self.active_submode is not None:
+			if self.active:
+				self.manager.deactivate_mode(self.active_submode)
+			if clear_subnode:
+				self.clear_subnode()
+	
+	def activate(self, mode_manager):
+		"""Activate the :class:`Multi` for the specified manager. The
+		previously active submode of the :class:`Multi` is activated. If there
+		is no previously active submode, then the first submode is made active. 
+		A :class:`Multi` with no submodes cannot be activated
+		"""
+		assert self.submodes, "No submode to activate"
+		self.manager = mode_manager
+		if self.active_submode is None:
+			self._set_active_submode(self.submodes[0])
+		else:
+			self._set_active_submode(self.active_submode)
+		self.manager.activate_mode(self.active_submode)
+		super(BaseMulti, self).activate(mode_manager)
+	
+	def deactivate(self, mode_manager):
+		"""Deactivate the :class:`Multi` for the specified manager.
+		The `active_submode`, if any, is deactivated.
+		"""
+		self._deactivate_submode(clear_subnode=False)
+		super(BaseMulti, self).deactivate(mode_manager)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/renderer/__init__.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,25 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""Renderers define world presentation. This module contains the
+built-in renderer classes.
+
+See also:
+
+- :class:`~grease.Renderer` abstract base class.
+- :ref:`Example renderer class in the tutorial <tut-renderer-example>`
+"""
+
+__all__ = ('Vector', 'Camera')
+
+from bGrease.renderer.vector import Vector
+from bGrease.renderer.camera import Camera
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/renderer/camera.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,39 @@
+import pyglet
+
+class Camera(object):
+	"""Sets the point of view for further renderers by altering the
+	model/view matrix when it is drawn. It does not actually perform
+	any drawing itself.
+
+	:param position: The position vector for the camera. Sets the center of the view.
+	:type position: Vec2d
+	:param angle: Camera rotation in degrees about the z-axis.
+	:type angle: float
+	:param zoom: Scaling vector for the coordinate axis.
+	:type zoom: Vec2d
+	:param relative: Flag to indicate if the camera settings are relative 
+		to the previous view state. If ``False`` the view state is reset before 
+		setting the camera view by loading the identity model/view matrix.
+	
+	At runtime the camera may be manipulated via attributes with the 
+	same names and functions as the parameters above.
+	"""
+
+	def __init__(self, position=None, angle=None, zoom=None, relative=False):
+		self.position = position
+		self.angle = angle
+		self.zoom = zoom
+		self.relative = relative
+	
+	def draw(self, gl=pyglet.gl):
+		if not self.relative:
+			gl.glLoadIdentity()
+		if self.position is not None:
+			px, py = self.position
+			gl.glTranslatef(px, py, 0)
+		if self.angle is not None:
+			gl.glRotatef(self.angle, 0, 0, 1)
+		if self.zoom is not None:
+			sx, sy = self.zoom
+			gl.glScalef(sx, sy ,0)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/renderer/vector.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,166 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+
+__version__ = '$Id$'
+
+__all__ = ('Vector',)
+
+from bGrease.geometry import Vec2d
+import ctypes
+from math import sin, cos, radians
+import pyglet
+
+
+class Vector(object):
+	"""Renders shapes in a classic vector graphics style
+	
+	:param scale: Scaling factor applied to shape vertices when rendered.
+	
+	:param line_width: The line width provided to ``glLineWidth`` before rendering.
+		If not specified or None, ``glLineWidth`` is not called, and the line
+		width used is determined by the OpenGL state at the time of rendering.
+
+	:param anti_alias: If ``True``, OpenGL blending and line smoothing is enabled.
+		This allows for fractional line widths as well. If ``False``, the blending
+		and line smoothing modes are unchanged.
+
+	:param corner_fill: If true (the default), the shape corners will be filled
+		with round points when the ``line_width`` exceeds 2.0. This improves
+		the visual quality of the rendering at larger line widths at some
+		cost to performance. Has no effect if ``line_width`` is not specified.
+
+	:param position_component: Name of :class:`grease.component.Position` 
+		component to use. Shapes rendered are offset by the entity positions.
+
+	:param renderable_component: Name of :class:`grease.component.Renderable` 
+		component to use. This component specifies the entities to be 
+		rendered and their base color.
+
+	:param shape_component: Name of :class:`grease.component.Shape` 
+		component to use. Source of the shape vertices for each entity.
+
+	The entities rendered are taken from the intersection of he position,
+	renderable and shape components each time :meth:`draw` is called.
+	"""
+
+	CORNER_FILL_SCALE = 0.6
+	CORNER_FILL_THRESHOLD = 2.0
+
+	def __init__(self, scale=1.0, line_width=None, anti_alias=True, corner_fill=True,
+		position_component='position', 
+		renderable_component='renderable', 
+		shape_component='shape'):
+		self.scale = float(scale)
+		self.corner_fill = corner_fill
+		self.line_width = line_width
+		self.anti_alias = anti_alias
+		self._max_line_width = None
+		self.position_component = position_component
+		self.renderable_component = renderable_component
+		self.shape_component = shape_component
+	
+	def set_world(self, world):
+		self.world = world
+
+	def _generate_verts(self):
+		"""Generate vertex and index arrays for rendering"""
+		vert_count = sum(len(shape.verts) + 1
+			for shape, ignored, ignored in self.world.components.join(
+				self.shape_component, self.position_component, self.renderable_component))
+		v_array = (CVertColor * vert_count)()
+		if vert_count > 65536:
+			i_array = (ctypes.c_uint * 2 * vert_count)()
+			i_size = pyglet.gl.GL_UNSIGNED_INT
+		else:
+			i_array = (ctypes.c_ushort * (2 * vert_count))()
+			i_size = pyglet.gl.GL_UNSIGNED_SHORT
+		v_index = 0
+		i_index = 0
+		scale = self.scale
+		rot_vec = Vec2d(0, 0)
+		for shape, position, renderable in self.world.components.join(
+			self.shape_component, self.position_component, self.renderable_component):
+			shape_start = v_index
+			angle = radians(-position.angle)
+			rot_vec.x = cos(angle)
+			rot_vec.y = sin(angle)
+			r = int(renderable.color.r * 255)
+			g = int(renderable.color.g * 255)
+			b = int(renderable.color.b * 255)
+			a = int(renderable.color.a * 255)
+			for vert in shape.verts:
+				vert = vert.cpvrotate(rot_vec) * scale + position.position
+				v_array[v_index].vert.x = vert.x
+				v_array[v_index].vert.y = vert.y
+				v_array[v_index].color.r = r
+				v_array[v_index].color.g = g
+				v_array[v_index].color.b = b
+				v_array[v_index].color.a = a
+				if v_index > shape_start:
+					i_array[i_index] = v_index - 1
+					i_index += 1
+					i_array[i_index] = v_index
+					i_index += 1
+				v_index += 1
+			if shape.closed and v_index - shape_start > 2:
+				i_array[i_index] = v_index - 1
+				i_index += 1
+				i_array[i_index] = shape_start
+				i_index += 1
+		return v_array, i_size, i_array, i_index
+
+	def draw(self, gl=pyglet.gl):
+		vertices, index_size, indices, index_count = self._generate_verts()
+		if index_count:
+			if self.anti_alias:
+				gl.glEnable(gl.GL_LINE_SMOOTH)
+				gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
+				gl.glEnable(gl.GL_BLEND)
+				gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
+			gl.glPushClientAttrib(gl.GL_CLIENT_VERTEX_ARRAY_BIT)
+			gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
+			gl.glEnableClientState(gl.GL_COLOR_ARRAY)
+			gl.glVertexPointer(
+				2, gl.GL_FLOAT, ctypes.sizeof(CVertColor), ctypes.pointer(vertices))
+			gl.glColorPointer(
+				4, gl.GL_UNSIGNED_BYTE, ctypes.sizeof(CVertColor), 
+				ctypes.pointer(vertices[0].color))
+			if self.line_width is not None:
+				gl.glLineWidth(self.line_width)
+				if self._max_line_width is None:
+					range_out = (ctypes.c_float * 2)()
+					gl.glGetFloatv(gl.GL_ALIASED_LINE_WIDTH_RANGE, range_out)
+					self._max_line_width = float(range_out[1]) * self.CORNER_FILL_SCALE
+				if self.corner_fill and self.line_width > self.CORNER_FILL_THRESHOLD:
+					gl.glEnable(gl.GL_POINT_SMOOTH)
+					gl.glPointSize(
+						min(self.line_width * self.CORNER_FILL_SCALE, self._max_line_width))
+					gl.glDrawArrays(gl.GL_POINTS, 0, index_count)
+			gl.glDrawElements(gl.GL_LINES, index_count, index_size, ctypes.pointer(indices))
+			gl.glPopClientAttrib()
+
+
+class CVert(ctypes.Structure):
+	_fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)]
+
+class CColor(ctypes.Structure):
+	_fields_ = [
+		("r", ctypes.c_ubyte), 
+		("g", ctypes.c_ubyte), 
+		("b", ctypes.c_ubyte), 
+		("a", ctypes.c_ubyte),
+	]
+
+class CVertColor(ctypes.Structure):
+	_fields_ = [("vert", CVert), ("color", CColor)]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bGrease/world.py	Mon Sep 05 15:00:34 2011 +0200
@@ -0,0 +1,302 @@
+#############################################################################
+#
+# Copyright (c) 2010 by Casey Duncan and contributors
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the MIT License
+# A copy of the license should accompany this distribution.
+# 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.
+#
+#############################################################################
+"""Worlds are environments described by a configuration of components, systems and 
+renderers. These parts describe the data, behavioral and presentation aspects
+of the world respectively.
+
+The world environment is the context within which entities exist. A typical
+application consists of one or more worlds containing entities that evolve
+over time and react to internal and external interaction.
+
+See :ref:`an example of world configuration in the tutorial <tut-world-example>`.
+"""
+
+__version__ = '$Id$'
+
+import itertools
+from bGrease import mode
+from bGrease.component import ComponentError
+from bGrease.entity import Entity, ComponentEntitySet
+
+
+class BaseWorld(object):
+	"""A coordinated collection of components, systems and entities
+	
+	A world is also a mode that may be pushed onto a 
+	:class:`grease.mode.Manager`
+	"""
+
+	components = None
+	""":class:`ComponentParts` object containing all world components.
+	:class:`grease.component.Component` objects define and contain all entity data
+	"""
+
+	systems = None
+	""":class:`Parts` object containing all world systems. 
+	:class:`grease.System` objects define world and entity behavior
+	"""
+
+	renderers = None
+	""":class:`Parts` object containing all world renderers. 
+	:class:`grease.Renderer` objects define world presentation
+	"""
+
+	entities = None
+	"""Set of all entities that exist in the world"""
+
+	def __init__(self):
+		self.components = ComponentParts(self)
+		self.systems = Parts(self)
+		self.renderers = Parts(self)
+		self.new_entity_id = itertools.count().next
+		self.new_entity_id() # skip id 0
+		self.entities = WorldEntitySet(self)
+		self._full_extent = EntityExtent(self, self.entities)
+		self._extents = {}
+		self.configure()
+
+	def configure(self):
+		"""Hook to configure the world after construction. This method
+		is called immediately after the world is initialized. Override
+		in a subclass to configure the world's components, systems,
+		and renderers.
+
+		The default implementation does nothing.
+		"""
+	
+	def __getitem__(self, entity_class):
+		"""Return an :class:`EntityExtent` for the given entity class. This extent
+		can be used to access the set of entities of that class in the world
+		or to query these entities via their components. 
+
+		Examples::
+
+			world[MyEntity]
+			world[...]
+
+		:param entity_class: The entity class for the extent.
+
+			May also be a tuple of entity classes, in which case
+			the extent returned contains union of all entities of the classes
+			in the world.
+
+			May also be the special value ellipsis (``...``), which
+			returns an extent containing all entities in the world.  This allows
+			you to conveniently query all entities using ``world[...]``.
+		"""
+		if isinstance(entity_class, tuple):
+			entities = set()
+			for cls in entity_class:
+				if cls in self._extents:
+					entities |= self._extents[cls].entities
+			return EntityExtent(self, entities)
+		elif entity_class is Ellipsis:
+			return self._full_extent
+		try:
+			return self._extents[entity_class]
+		except KeyError:
+			extent = self._extents[entity_class] = EntityExtent(self, set())
+			return extent
+	
+	def draw_renderers(self):
+		"""Draw all renderers"""
+		for renderer in self.renderers:
+			renderer.draw()
+
+class WorldEntitySet(set):
+	"""Entity set for a :class:`World`"""
+
+	def __init__(self, world):
+		self.world = world
+	
+	def add(self, entity):
+		"""Add the entity to the set and all necessary class sets
+		Return the unique entity id for the entity, creating one
+		as needed.
+		"""
+		super(WorldEntitySet, self).add(entity)
+		for cls in entity.__class__.__mro__:
+			if issubclass(cls, Entity):
+				self.world[cls].entities.add(entity)
+
+	def remove(self, entity):
+		"""Remove the entity from the set and, world components,
+		and all necessary class sets
+		"""
+		super(WorldEntitySet, self).remove(entity)
+		for component in self.world.components:
+			try:
+				del component[entity]
+			except KeyError:
+				pass
+		for cls in entity.__class__.__mro__:
+			if issubclass(cls, Entity):
+				self.world[cls].entities.discard(entity)
+	
+	def discard(self, entity):
+		"""Remove the entity from the set if it exists, if not,
+		do nothing
+		"""
+		try:
+			self.remove(entity)
+		except KeyError:
+			pass
+
+
+class EntityExtent(object):
+	"""Encapsulates a set of entities queriable by component. Extents
+	are accessed by using an entity class as a key on the :class:`World`::
+
+		extent = world[MyEntity]
+	"""
+
+	entities = None
+	"""The full set of entities in the extent""" 
+
+	def __init__(self, world, entities):
+		self.__world = world
+		self.entities = entities
+
+	def __getattr__(self, name):
+		"""Return a queriable :class:`ComponentEntitySet` for the named component 
+
+		Example::
+
+			world[MyEntity].movement.velocity > (0, 0)
+
+		Returns a set of entities where the value of the :attr:`velocity` field
+		of the :attr:`movement` component is greater than ``(0, 0)``.
+		"""
+		component = getattr(self.__world.components, name)
+		return ComponentEntitySet(component, self.entities & component.entities)
+
+
+class Parts(object):
+	"""Maps world parts to attributes. The parts are kept in the
+	order they are set. Parts may also be inserted out of order.
+	
+	Used for:
+	
+	- :attr:`World.systems`
+	- :attr:`World.renderers`
+	"""
+
+	_world = None
+	_parts = None
+	_reserved_names = ('entities', 'entity_id', 'world')
+
+	def __init__(self, world):
+		self._world = world
+		self._parts = []
+	
+	def _validate_name(self, name):
+		if (name in self._reserved_names or name.startswith('_') 
+			or hasattr(self.__class__, name)):
+			raise ComponentError('illegal part name: %s' % name)
+		return name
+
+	def __setattr__(self, name, part):
+		if not hasattr(self.__class__, name):
+			self._validate_name(name)
+			if not hasattr(self, name):
+				self._parts.append(part)
+			else:
+				old_part = getattr(self, name)
+				self._parts[self._parts.index(old_part)] = part
+			super(Parts, self).__setattr__(name, part)
+			if hasattr(part, 'set_world'):
+				part.set_world(self._world)
+		elif name.startswith("_"):
+			super(Parts, self).__setattr__(name, part)
+		else:
+			raise AttributeError("%s attribute is read only" % name)
+	
+	def __delattr__(self, name):
+		self._validate_name(name)
+		part = getattr(self, name)
+		self._parts.remove(part)
+		super(Parts, self).__delattr__(name)
+
+	def insert(self, name, part, before=None, index=None):
+		"""Add a part with a particular name at a particular index.
+		If a part by that name already exists, it is replaced.
+			
+		:arg name: The name of the part.
+		:type name: str
+
+		:arg part: The component, system, or renderer part to insert
+	
+		:arg before: A part object or name. If specified, the part is
+			inserted before the specified part in order.
+
+		:arg index: If specified, the part is inserted in the position
+			specified. You cannot specify both before and index.
+		:type index: int
+		"""
+		assert before is not None or index is not None, (
+			"Must specify a value for 'before' or 'index'")
+		assert before is None or index is None, (
+			"Cannot specify both 'before' and 'index' arguments when inserting")
+		self._validate_name(name)
+		if before is not None:
+			if isinstance(before, str):
+				before = getattr(self, before)
+			index = self._parts.index(before)
+		if hasattr(self, name):
+			old_part = getattr(self, name)
+			self._parts.remove(old_part)
+		self._parts.insert(index, part)
+		super(Parts, self).__setattr__(name, part)
+		if hasattr(part, 'set_world'):
+			part.set_world(self._world)
+
+	def __iter__(self):
+		"""Iterate the parts in order"""
+		return iter(tuple(self._parts))
+	
+	def __len__(self):
+		return len(self._parts)
+
+
+class ComponentParts(Parts):
+	"""Maps world components to attributes. The components are kept in the
+	order they are set. Components may also be inserted out of order.
+
+	Used for: :attr:`World.components`
+	"""
+
+	def join(self, *component_names):
+		"""Join and iterate entity data from multiple components together.
+
+		For each entity in all of the components named, yield a tuple containing
+		the entity data from each component specified.
+
+		This is useful in systems that pull data from multiple components.
+		
+		Typical Usage::
+
+			for position, movement in world.components.join("position", "movement"):
+				# Do something with each entity's position and movement data
+		"""
+		if component_names:
+			components = [getattr(self, self._validate_name(name)) 
+				for name in component_names]
+			if len(components) > 1:
+				entities = components[0].entities & components[1].entities
+				for comp in components[2:]:
+					entities &= comp.entities
+			else:
+				entities = components[0].entities
+			for entity in entities:
+				yield tuple(comp[entity] for comp in components)
+
--- a/components/Behavior.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/Behavior.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Behavior(Component):
     """
--- a/components/CharacterStatistics.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/CharacterStatistics.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class CharacterStatistics(Component):
     """Component that defines character statistics."""
--- a/components/containable.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/containable.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Containable(Component):
     """Component that allows an entity to be contained by Container entity."""
--- a/components/container.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/container.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Container(Component):
     """
--- a/components/description.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/description.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Description(Component):
     """Component that stores the description of an object"""
--- a/components/dialog.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/dialog.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Dialog(Component):
     """Component that stores the dialogue"""
--- a/components/fifeagent.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/fifeagent.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,8 +11,8 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
-from grease.geometry import Vec2d
+from bGrease.component import Component
+from bGrease.geometry import Vec2d
 
 class FifeAgent(Component):
     """Component that stores the values for a fife agent"""
--- a/components/lockable.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/lockable.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Lockable(Component):
     """Component that stores the data of a lock"""
--- a/components/usable.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/components/usable.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease.component import Component
+from bGrease.component import Component
 
 class Usable(Component):
     """
--- a/entities/character.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/entities/character.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,8 +11,8 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease import Entity
-from parpg.grease.geometry import Vec2d
+from bGrease import Entity
+from bGrease.geometry import Vec2d
 
 class Character(Entity):
     def __init__(self, world, view_name, real_name, desc, statistics, max_bulk,
--- a/gamemodel.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/gamemodel.py	Mon Sep 05 15:00:34 2011 +0200
@@ -21,7 +21,7 @@
 
 from fife import fife
 from fife.extensions.serializers.xmlobject import XMLObjectLoader 
-from parpg.grease.geometry import Vec2d
+from bGrease.geometry import Vec2d
 
 from parpg import vfs
 from gamestate import GameState
--- a/grease/__init__.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-
-__versioninfo__ = (0, 3, 0)
-__version__ = '.'.join(str(n) for n in __versioninfo__)
-
-__all__ = ('BaseWorld', 'Entity', 'System', 'Renderer')
-
-import component
-import geometry
-import collision
-from entity import Entity
-from world import BaseWorld
-
-import abc
-
-class System(object):
-	"""Grease system abstract base class. Systems define behaviorial aspects
-	of a |World|. All systems must define a :meth:`step`
-	method that is invoked by the world each timestep.  User-defined systems
-	are not required to subclass this class.
-	
-	See :ref:`an example system from the tutorial <tut-system-example>`.
-	"""
-	__metaclass__ = abc.ABCMeta
-
-	world = None
-	"""The |World| this system belongs to"""
-
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-	
-	@abc.abstractmethod
-	def step(self, dt):
-		"""Execute a time step for the system. Must be defined
-		by all system classes.
-
-		:param dt: Time since last step invocation
-		:type dt: float
-		"""
-
-class Renderer(object):
-	"""Grease renderer abstract base class. Renderers define the presentation
-	of a |World|. All renderers must define a :meth:`draw`
-	method that is invoked by the world when the display needs to be redrawn.
-	User-defined renderers are not required to subclass this class.
-
-	See :ref:`an example renderer from the tutorial <tut-renderer-example>`.
-	"""
-	__metaclass__ = abc.ABCMeta
-
-	world = None
-	"""The |World| this renderer belongs to"""
-
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-
-	@abc.abstractmethod
-	def draw(self):
-		"""Issue drawing commands for this renderer. Must be defined
-		for all renderer classes.
-		"""
-
--- a/grease/collision.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,528 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""
-**Grease collision detection systems**
-
-Grease uses two-phase broad and narrow collision detection. *Broad-phase*
-collision systems are used to efficiently identify pairs that may be colliding
-without resorting to a brute-force check of all possible pairs. *Narrow-phase*
-collision systems use the pairs generated by the broad-phase and perform more
-precise collision tests to determine if a collision has actually occurred. The
-narrow-phase system also calculates more details about each collision,
-including collision point and normal vector for use in collision response.
-
-A typical collision detection system consists of a narrow-phase system that
-contains a broad-phased system. The narrow-phase system is usually the only
-
-one that the application directly interacts with, though the application is
-free to use the broad-phased system directly if desired. This could be
-useful in cases where speed, rather than precision is paramount.
-
-The narrow-phase system can be assigned handler objects to run after
-collision detection. These can perform tasks like handling collision response
-or dispatching collision events to application handlers.
-
-Note that broad-phase systems can return false positives, though they should
-never return false negatives. Do not assume that all pairs returned by a
-broad-phase system are actually in collision.
-"""
-
-__version__ = '$Id$'
-
-from grease.geometry import Vec2d
-from bisect import bisect_right
-
-
-class Pair(tuple):
-	"""Pair of entities in collision. This is an ordered sequence of two
-	entities, that compares and hashes unordered.
-	
-	Also stores additional collision point and normal vectors
-	for each entity.
-
-	Sets of ``Pair`` objects are exposed in the ``collision_pairs``
-	attribute of collision systems to indicate the entity pairs in
-	collision.
-	"""
-	info = None
-	"""A sequence of (entity, collision point, collision normal)
-	for each entity in the pair
-	"""
-
-	def __new__(cls, entity1, entity2, point=None, normal=None):
-		pair = tuple.__new__(cls, (entity1, entity2))
-		return pair
-	
-	def __hash__(self):
-		return hash(self[0]) ^ hash(self[1])
-	
-	def __eq__(self, other):
-		other = tuple(other)
-		return tuple(self) == other or (self[1], self[0]) == other
-	
-	def __repr__(self):
-		return '%s%r' % (self.__class__.__name__, tuple(self))
-	
-	def set_point_normal(self, point0, normal0, point1, normal1):
-		"""Set the collision point and normal for both entities"""
-		self.info = (
-			(self[0], point0, normal0),
-			(self[1], point1, normal1),
-		)
-
-
-class BroadSweepAndPrune(object):
-	"""2D Broad-phase sweep and prune bounding box collision detector
-
-	This algorithm is efficient for collision detection between many
-	moving bodies. It has linear algorithmic complexity and takes
-	advantage of temporal coherence between frames. It also does
-	not suffer from bad worst-case performance (like RDC can). 
-	Unlike spacial hashing, it does not need to be optimized for 
-	specific space and body sizes.
-
-	Other algorithms may be more efficient for collision detection with
-	stationary bodies, bodies that are always evenly distributed, or ad-hoc
-	queries.
-
-	:param collision_component: Name of the collision component used by this
-		system, defaults to 'collision'. This component supplies each
-		entities' aabb and collision masks.
-	:type collision_component: str
-	"""
-	world = None
-	"""|World| object this system belongs to"""
-
-	collision_component = None
-	"""Name of world's collision component used by this system"""
-
-	LEFT_ATTR = "left"
-	RIGHT_ATTR = "right"
-	TOP_ATTR = "top"
-	BOTTOM_ATTR = "bottom"
-
-	def __init__(self, collision_component='collision'):
-		self.collision_component = collision_component
-		self._by_x = None
-		self._by_y = None
-		self._collision_pairs = None
-	
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-	
-	def step(self, dt):
-		"""Update the system for this time step, updates and sorts the 
-		axis arrays.
-		"""
-		component = getattr(self.world.components, self.collision_component)
-		LEFT = self.LEFT_ATTR
-		RIGHT = self.RIGHT_ATTR
-		TOP = self.TOP_ATTR
-		BOTTOM = self.BOTTOM_ATTR
-		if self._by_x is None:
-			# Build axis lists from scratch
-			# Note we cache the box positions here
-			# so that we can perform hit tests efficiently
-			# it also isolates us from changes made to the 
-			# box positions after we run
-			by_x = self._by_x = []
-			append_x = by_x.append
-			by_y = self._by_y = []
-			append_y = by_y.append
-			for data in component.itervalues():
-				append_x([data.aabb.left, LEFT, data])
-				append_x([data.aabb.right, RIGHT, data])
-				append_y([data.aabb.bottom, BOTTOM, data])
-				append_y([data.aabb.top, TOP, data])
-		else:
-			by_x = self._by_x
-			by_y = self._by_y
-			removed = []
-			for entry in by_x:
-				entry[0] = getattr(entry[2].aabb, entry[1])
-			for entry in by_y:
-				entry[0] = getattr(entry[2].aabb, entry[1])
-			# Removing entities is inefficient, but expected to be rare
-			if component.deleted_entities:
-				deleted_entities = component.deleted_entities
-				deleted_x = []
-				deleted_y = []
-				for i, (_, _, data) in enumerate(by_x):
-					if data.entity in deleted_entities:
-						deleted_x.append(i)
-				deleted_x.reverse()
-				for i in deleted_x:
-					del by_x[i]
-				for i, (_, _, data) in enumerate(by_y):
-					if data.entity in deleted_entities:
-						deleted_y.append(i)
-				deleted_y.reverse()
-				for i in deleted_y:
-					del by_y[i]
-			# Tack on new entities
-			for entity in component.new_entities:
-				data = component[entity]
-				by_x.append([data.aabb.left, LEFT, data])
-				by_x.append([data.aabb.right, RIGHT, data])
-				by_y.append([data.aabb.bottom, BOTTOM, data])
-				by_y.append([data.aabb.top, TOP, data])
-				
-		# Tim-sort is highly efficient with mostly sorted lists.
-		# Because positions tend to change little each frame
-		# we take advantage of this here. Obviously things are
-		# less efficient with very fast moving, or teleporting entities
-		by_x.sort()
-		by_y.sort()
-		self._collision_pairs = None
-	
-	@property
-	def collision_pairs(self):
-		"""Set of candidate collision pairs for this timestep"""
-		if self._collision_pairs is None:
-			if self._by_x is None:
-				# Axis arrays not ready
-				return set()
-
-			LEFT = self.LEFT_ATTR
-			RIGHT = self.RIGHT_ATTR
-			TOP = self.TOP_ATTR
-			BOTTOM = self.BOTTOM_ATTR
-			# Build candidates overlapping along the x-axis
-			component = getattr(self.world.components, self.collision_component)
-			xoverlaps = set()
-			add_xoverlap = xoverlaps.add
-			discard_xoverlap = xoverlaps.discard
-			open = {}
-			for _, side, data in self._by_x:
-				if side is LEFT:
-					for open_entity, (from_mask, into_mask) in open.iteritems():
-						if data.from_mask & into_mask or from_mask & data.into_mask:
-							add_xoverlap(Pair(data.entity, open_entity))
-					open[data.entity] = (data.from_mask, data.into_mask)
-				elif side is RIGHT:
-					del open[data.entity]
-
-			if len(xoverlaps) <= 10 and len(xoverlaps)*4 < len(self._by_y):
-				# few candidates were found, so just scan the x overlap candidates
-				# along y. This requires an additional sort, but it should
-				# be cheaper than scanning everyone and its simpler
-				# than a separate brute-force check
-				entities = set([entity for entity, _ in xoverlaps] 
-					+ [entity for _, entity in xoverlaps])
-				by_y = []
-				for entity in entities:
-					data = component[entity]
-					# We can use tuples here, which are cheaper to create
-					by_y.append((data.aabb.bottom, BOTTOM, data))
-					by_y.append((data.aabb.top, TOP, data))
-				by_y.sort()
-			else:
-				by_y = self._by_y
-
-			# Now check the candidates along the y-axis
-			open = set()
-			add_open = open.add
-			discard_open = open.discard
-			self._collision_pairs = set()
-			add_pair = self._collision_pairs.add
-			for _, side, data in by_y:
-				if side is BOTTOM:
-					for open_entity in open:
-						pair = Pair(data.entity, open_entity)
-						if pair in xoverlaps:
-							discard_xoverlap(pair)
-							add_pair(pair)
-							if not xoverlaps:
-								# No more candidates, bail
-								return self._collision_pairs
-					add_open(data.entity)
-				elif side is TOP:
-					discard_open(data.entity)
-		return self._collision_pairs
-	
-	def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
-		"""Hit test at the point specified. 
-
-		:param x_or_point: x coordinate (float) or sequence of (x, y) floats.
-
-		:param y: y coordinate (float) if x is not a sequence
-
-		:param from_mask: Bit mask used to filter query results. This value
-			is bit ANDed with candidate entities' ``collision.into_mask``.
-			If the result is non-zero, then it is considered a hit. By
-			default all entities colliding with the input point are
-			returned.
-
-		:return: A set of entities where the point is inside their bounding
-			boxes as of the last time step.
-		"""
-		if self._by_x is None:
-			# Axis arrays not ready
-			return set()
-		if y is None:
-			x, y = x_or_point
-		else:
-			x = x_or_point
-		LEFT = self.LEFT_ATTR
-		RIGHT = self.RIGHT_ATTR
-		TOP = self.TOP_ATTR
-		BOTTOM = self.BOTTOM_ATTR
-		x_index = bisect_right(self._by_x, [x])
-		x_hits = set()
-		add_x_hit = x_hits.add
-		discard_x_hit = x_hits.discard
-		if x_index <= len(self._by_x) // 2:
-			# closer to the left, scan from left to right
-			while (x == self._by_x[x_index][0] 
-				and self._by_x[x_index][1] is LEFT 
-				and x_index < len(self._by_x)):
-				# Ensure we hit on exact left edge matches
-				x_index += 1
-			for _, side, data in self._by_x[:x_index]:
-				if side is LEFT and from_mask & data.into_mask:
-					add_x_hit(data.entity)
-				else:
-					discard_x_hit(data.entity)
-		else:
-			# closer to the right
-			for _, side, data in reversed(self._by_x[x_index:]):
-				if side is RIGHT and from_mask & data.into_mask:
-					add_x_hit(data.entity)
-				else:
-					discard_x_hit(data.entity)
-		if not x_hits:
-			return x_hits
-
-		y_index = bisect_right(self._by_y, [y])
-		y_hits = set()
-		add_y_hit = y_hits.add
-		discard_y_hit = y_hits.discard
-		if y_index <= len(self._by_y) // 2:
-			# closer to the bottom
-			while (y == self._by_y[y_index][0] 
-				and self._by_y[y_index][1] is BOTTOM 
-				and y_index < len(self._by_y)):
-				# Ensure we hit on exact bottom edge matches
-				y_index += 1
-			for _, side, data in self._by_y[:y_index]:
-				if side is BOTTOM:
-					add_y_hit(data.entity)
-				else:
-					discard_y_hit(data.entity)
-		else:
-			# closer to the top
-			for _, side, data in reversed(self._by_y[y_index:]):
-				if side is TOP:
-					add_y_hit(data.entity)
-				else:
-					discard_y_hit(data.entity)
-		if y_hits:
-			return x_hits & y_hits
-		else:
-			return y_hits
-
-
-class Circular(object):
-	"""Basic narrow-phase collision detector which treats all entities as
-	circles with their radius defined in the collision component.
-
-	:param handlers: A sequence of collision handler functions that are invoked
-		after collision detection.
-	:type handlers: sequence of functions
-	
-	:param collision_component: Name of collision component for this system,
-		defaults to 'collision'. This supplies each entity's collision
-		radius and masks.
-	:type collision_component: str
-
-	:param position_component: Name of position component for this system,
-		defaults to 'position'. This supplies each entity's position.
-	:type position_component: str
-
-	:param update_aabbs: If True (the default), then the entities'
-		`collision.aabb` fields will be updated using their position
-		and collision radius before invoking the broad phase system. 
-		Set this False if another system updates the aabbs.
-	:type update_aabbs: bool
-
-	:param broad_phase: A broad-phase collision system to use as a source
-		for collision pairs. If not specified, a :class:`BroadSweepAndPrune`
-		system will be created automatically.
-	"""
-	world = None
-	"""|World| object this system belongs to"""
-
-	position_component = None
-	"""Name of world's position component used by this system"""
-
-	collision_component = None
-	"""Name of world's collision component used by this system"""
-
-	update_aabbs = True
-	"""Flag to indicate whether the system updates the entities' `collision.aabb`
-	field before invoking the broad phase collision system
-	"""
-	
-	handlers = None
-	"""A sequence of collision handler functions invoke after collision
-	detection
-	"""
-
-	broad_phase = None
-	"""Broad phase collision system used as a source for collision pairs"""
-
-	def __init__(self, handlers=(), position_component='position', 
-		collision_component='collision', update_aabbs=True, broad_phase=None):
-		self.handlers = tuple(handlers)
-		if broad_phase is None:
-			broad_phase = BroadSweepAndPrune(collision_component)
-		self.collision_component = collision_component
-		self.position_component = position_component
-		self.update_aabbs = bool(update_aabbs)
-		self.broad_phase = broad_phase
-		self._collision_pairs = None
-	
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-		self.broad_phase.set_world(world)
-		for handler in self.handlers:
-			if hasattr(handler, 'set_world'):
-				handler.set_world(world)
-	
-	def step(self, dt):
-		"""Update the collision system for this time step and invoke
-		the handlers
-		"""
-		if self.update_aabbs:
-			for position, collision in self.world.components.join(
-				self.position_component, self.collision_component):
-				aabb = collision.aabb
-				x, y = position.position
-				radius = collision.radius
-				aabb.left = x - radius
-				aabb.right = x + radius
-				aabb.bottom = y - radius
-				aabb.top = y + radius
-		self.broad_phase.step(dt)
-		self._collision_pairs = None
-		for handler in self.handlers:
-			handler(self)
-	
-	@property
-	def collision_pairs(self):
-		"""The set of entity pairs in collision in this timestep"""
-		if self._collision_pairs is None:
-			position = getattr(self.world.components, self.position_component)
-			collision = getattr(self.world.components, self.collision_component)
-			pairs = self._collision_pairs = set()
-			for pair in self.broad_phase.collision_pairs:
-				entity1, entity2 = pair
-				position1 = position[entity1].position
-				position2 = position[entity2].position
-				radius1 = collision[entity1].radius
-				radius2 = collision[entity2].radius
-				separation = position2 - position1
-				if separation.get_length_sqrd() <= (radius1 + radius2)**2:
-					normal = separation.normalized()
-					pair.set_point_normal(
-						normal * radius1 + position1, normal,
-						normal * -radius2 + position2, -normal)
-					pairs.add(pair)
-		return self._collision_pairs
-	
-	def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
-		"""Hit test at the point specified. 
-
-		:param x_or_point: x coordinate (float) or sequence of (x, y) floats.
-
-		:param y: y coordinate (float) if x is not a sequence
-
-		:param from_mask: Bit mask used to filter query results. This value
-			is bit ANDed with candidate entities' ``collision.into_mask``.
-			If the result is non-zero, then it is considered a hit. By
-			default all entities colliding with the input point are
-			returned.
-
-		:return: A set of entities where the point is inside their collision
-			radii as of the last time step.
-
-		"""
-		if y is None:
-			point = Vec2d(x_or_point)
-		else:
-			point = Vec2d(x_or_point, y)
-		hits = set()
-		position = getattr(self.world.components, self.position_component)
-		collision = getattr(self.world.components, self.collision_component)
-		for entity in self.broad_phase.query_point(x_or_point, y, from_mask):
-			separation = point - position[entity].position
-			if separation.get_length_sqrd() <= collision[entity].radius**2:
-				hits.add(entity)
-		return hits
-
-
-def dispatch_events(collision_system):
-	"""Collision handler that dispatches `on_collide()` events to entities
-	marked for collision by the specified collision system. The `on_collide()`
-	event handler methods are defined by the application on the desired entity
-	classes. These methods should have the following signature::
-
-		def on_collide(self, other_entity, collision_point, collision_normal):
-			'''Handle A collision between this entity and `other_entity`
-
-			- other_entity (Entity): The other entity in collision with 
-			  `self`
-
-			- collision_point (Vec2d): The point on this entity (`self`)
-			  where the collision occurred. Note this may be `None` for 
-			  some collision systems that do not report it.
-
-			- collision_normal (Vec2d): The normal vector at the point of
-			  collision. As with `collision_point`, this may be None for
-			  some collision systems.
-			'''
-
-	Note the arguments to `on_collide()` are always passed positionally, so you
-	can use different argument names than above if desired.
-
-	If a pair of entities are in collision, then the event will be dispatched
-	to both objects in arbitrary order if all of their collision masks align.
-	"""
-	collision = getattr(collision_system.world.components, 
-		collision_system.collision_component)
-	for pair in collision_system.collision_pairs:
-		entity1, entity2 = pair
-		if pair.info is not None:
-			args1, args2 = pair.info
-		else:
-			args1 = entity1, None, None
-			args2 = entity2, None, None
-		try:
-			on_collide = entity1.on_collide
-			masks_align = collision[entity2].from_mask & collision[entity1].into_mask
-		except (AttributeError, KeyError):
-			pass
-		else:
-			if masks_align:
-				on_collide(*args2)
-		try:
-			on_collide = entity2.on_collide
-			masks_align = collision[entity1].from_mask & collision[entity2].into_mask
-		except (AttributeError, KeyError):
-			pass
-		else:
-			if masks_align:
-				on_collide(*args1)
-
--- a/grease/color.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-
-class RGBA(object):
-	"""Four channel color representation.
-
-	RGBA colors are floating point color representations with color channel
-	values between (0..1). Colors may be initialized from 3 or 4 floating
-	point numbers or a hex string::
-
-		RGBA(1.0, 1.0, 1.0) # Alpha defaults to 1.0
-		RGBA(1.0, 1.0, 0, 0.5)
-		RGBA("#333")
-		RGBA("#7F7F7F")
-	
-	Individual color channels can be accessed by attribute name, or the
-	color object can be treated as a sequence of 4 floats.
-	"""
-
-	def __init__(self, r_or_colorstr, g=None, b=None, a=None):
-		if isinstance(r_or_colorstr, str):
-			assert g is b is a is None, "Ambiguous color arguments" 
-			self.r, self.g, self.b, self.a = self._parse_colorstr(r_or_colorstr)
-		elif g is b is a is None:
-			try:
-				self.r, self.g, self.b, self.a = r_or_colorstr
-			except ValueError:
-				self.r, self.g, self.b = r_or_colorstr
-				self.a = 1.0
-		else:
-			self.r = r_or_colorstr
-			self.g = g
-			self.b = b
-			self.a = a
-		if self.a is None:
-			self.a = 1.0
-	
-	def _parse_colorstr(self, colorstr):
-		length = len(colorstr)
-		if not colorstr.startswith("#") or length not in (4, 5, 7, 9):
-			raise ValueError("Invalid color string: " + colorstr)
-		if length <= 5:
-			parsed = [int(c*2, 16) / 255.0 for c in colorstr[1:]]
-		else:
-			parsed = [int(colorstr[i:i+2], 16) / 255.0 for i in range(1, length, 2)]
-		if len(parsed) == 3:
-			parsed.append(1.0)
-		return parsed
-	
-	def __len__(self):
-		return 4
-	
-	def __getitem__(self, item):
-		return (self.r, self.g, self.b, self.a)[item]
-	
-	def __iter__(self):
-		return iter((self.r, self.g, self.b, self.a))
-	
-	def __eq__(self, other):
-		return tuple(self) == tuple(other)
-	
-	def __repr__(self):
-		return "%s(%.2f, %.2f, %.2f, %.2f)" % (self.__class__.__name__, 
-			self.r, self.g, self.b, self.a)
-			
-			
--- a/grease/component/__init__.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""Components store all entity data in a given |World|. You can
-think of components as tables with entities as their primary keys. Like
-database tables, components are defined with a "schema" that specifies
-the data fields. Each field in a component has a name and a type.
-
-Component objects themselves have a dict-like interface with entities
-as keys and data records as values. An application will typically 
-interact with components via entity attributes, entity extents or
-by joining them. For more information see:
-
-- :class:`~grease.entity.Entity` class.
-- :class:`~grease.world.EntityExtent` class.
-- :meth:`~grease.world.ComponentParts.join` method of ComponentParts.
-
-See also :ref:`defining custom components in the tutorial <custom-component-example>`.
-"""
-
-__version__ = '$Id$'
-
-__all__ = ('Component', 'ComponentError', 'Position', 'Transform', 'Movement', 
-	'Shape', 'Renderable', 'Collision')
-
-from grease.component.general import Component
-from grease.geometry import Vec2d, Vec2dArray, Rect
-from grease import color
-
-
-class ComponentError(Exception):
-	"""General component error"""
-
-
-class Position(Component):
-	"""Predefined component that stores position and orientation info for 
-	entities.
-
-	Fields:
-
-	- **position** (Vec2d) -- Position vector
-	- **angle** (float) -- Angle, in degrees
-	"""
-
-	def __init__(self):
-		Component.__init__(self, position=Vec2d, angle=float)
-
-
-class Transform(Component):
-	"""Predefined component that stores offset, shear, 
-	rotation and scale info for entity shapes.
-	
-	Fields:
-
-	- **offset** (Vec2d)
-	- **shear** (Vec2d)
-	- **rotation** (float)
-	- **scale** (float, default 1.0)
-	"""
-
-	def __init__(self):
-		Component.__init__(self, offset=Vec2d, shear=Vec2d, rotation=float, scale=float)
-		self.fields['scale'].default = lambda: 1.0
-
-
-class Movement(Component):
-	"""Predefined component that stores velocity, 
-	acceleration and rotation info for entities.
-	
-	Fields:
-
-	- **velocity** (Vec2d) -- Rate of change of entity position
-	- **accel** (Vec2d) -- Rate of change of entity velocity
-	- **rotation** (Vec2d) -- Rate of change of entity angle, in degrees/time
-	"""
-
-	def __init__(self):
-		Component.__init__(self, velocity=Vec2d, accel=Vec2d, rotation=float)
-
-
-class Shape(Component):
-	"""Predefined component that stores shape vertices for entities
-	
-	- **closed** (bool) -- If the shapes is closed implying an edge between
-	  last and first vertices.
-	- **verts** (Vec2dArray) -- Array of vertex points
-	"""
-
-	def __init__(self):
-		Component.__init__(self, closed=int, verts=Vec2dArray)
-		self.fields['closed'].default = lambda: 1
-
-
-class Renderable(Component):
-	"""Predefined component that identifies entities to be 
-	rendered and provides their depth and color.
-	
-	- **depth** (float) -- Drawing depth, can be used to determine z-order
-		  while rendering.
-	- **color** (color.RGBA) -- Color used for entity. The effect of this
-		  field depends on the renderer.
-	"""
-
-	def __init__(self):
-		Component.__init__(self, depth=float, color=color.RGBA)
-		self.fields['color'].default = lambda: color.RGBA(1,1,1,1)
-
-
-class Collision(Component):
-	"""Predefined component that stores collision masks to determine 
-	which entities can collide.
-
-	Fields:
-
-	- **aabb** (Rect) -- The axis-aligned bounding box for the entity.
-		This is used for broad-phase collision detection.
-
-	- **radius** (float) -- The collision radius of the entity, used for narrow-phase
-		collision detection. The exact meaning of this value depends on the collision
-		system in use.
-	
-	- **from_mask** (int) -- A bitmask that determines what entities this object
-		can collide with.
-
-	- **into_mask** (int) -- A bitmask that determines what entities can collide
-		with this object.
-
-	When considering an entity A for collision with entity B, A's ``from_mask`` is
-	bit ANDed with B's ``into_mask``. If the result is nonzero (meaning 1 or more
-	bits is set the same for each) then the collision test is made. Otherwise,
-	the pair cannot collide. 
-
-	The default value for both of these masks is ``0xffffffff``, which means that
-	all entities will collide with each other by default.
-	"""
-	def __init__(self):
-		Component.__init__(self, aabb=Rect, radius=float, from_mask=int, into_mask=int)
-		self.fields['into_mask'].default = lambda: 0xffffffff
-		self.fields['from_mask'].default = lambda: 0xffffffff
-
--- a/grease/component/base.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-class ComponentBase(object):
-	"""Component abstract base class
-
-	Strictly speaking you do not need to derive from this class to create your
-	own components, but it does serve to document the full interface that a
-	component implements and it provides some basic implementations for
-	certain methods
-	"""
-
-	## Optional attributes and methods ##
-
-	def set_manager(self, manager):
-		"""Set the manager of this component. If this method exists it will be
-		automatically called when the component is added to a manager.
-
-		This method stores the manager and allows the component to be added
-		only once to a single manager.
-		"""
-		assert getattr(self, 'manager', None) is None, 'Component cannot be added to multiple managers'
-		self.manager = manager
-
-	def __del__(self):
-		"""Break circrefs to allow faster collection"""
-		if hasattr(self, 'manager'):
-			del self.manager
-	
-	## Mandatory methods ##
-
-	def add(self, entity_id, data=None, **data_kw):
-		"""Add a data entry in the component for the given entity.  Additional
-		data (if any) for the entry can be provided in the data argument or as
-		keyword arguments. Additional data is optional and if omitted then
-		suitable defaults will be used. Return an entity data object
-		for the new entity entry.
-
-		The semantics of the data arguments is up to the component.
-
-		An entity_id is a unique key, thus multiple separate data entries for
-		a given entity are not allowed.  Components can indivdually decide
-		what to do if an entity_id is added multiple times to the component.
-		Potential options include, raising an exception, replacing the
-		existing data or coalescing it somehow.
-		"""
-	
-	def remove(self, entity_id):
-		"""Remove the entity data entry from the component. If the
-		entity is not in the component, raise KeyError
-		"""
-	
-	def __delitem_(self, entity_id):
-		"""Same as remove()"""
-
-	def __len__(self):
-		"""Return the number of entities in the component"""
-		raise NotImplementedError()
-	
-	def __iter__(self):
-		"""Return an iterator of entity data objects in this component
-
-		No order is defined for these data objects
-		"""
-		raise NotImplementedError()
-	
-	def __contains__(self, entity_id):
-		"""Return True if the entity is contained in the component"""
-		raise NotImplementedError()
-	
-	def __getitem__(self, entity_id):
-		"""Return the entity data object for the given entity. 
-		The entity data object returned may be mutable, immutable or a
-		mutable copy of the data at the discretion of the component
-		"""
-		raise NotImplementedError()
-
--- a/grease/component/field.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,303 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-import operator
-from grease.geometry import Vec2d, Vec2dArray, Rect
-from grease import color
-
-# Allowed field types -> default values
-types = {int:lambda: 0, 
-         float:lambda: 0.0, 
-         bool:lambda: False,
-         str:lambda:"", 
-         object:lambda:None,
-         Vec2d:lambda: Vec2d(0,0), 
-         Vec2dArray:lambda: Vec2dArray(),
-         color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0),
-         Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0),
-         list: lambda: list(),
-         dict: lambda: dict(),
-         }
-
-class Schema(dict):
-        """Field schema definition for custom components"""
-
-        def __init__(self, **fields):
-                for ftype in fields.values():
-                        assert ftype in types, fname + " has an illegal field type"
-                self.update(fields)
-
-
-class FieldAccessor(object):
-        """Facade for manipulating a field for a set of entities"""
-
-        __field = None
-        __entities = None
-        __attrs = None
-        __getter = None
-        __parent_getters = ()
-
-        def __init__(self, field, entities, attrs=()):
-                self.__field = field
-                self.__entities = entities
-                field_getter = operator.attrgetter(field.name)
-                self.__attrs = attrs
-                if attrs:
-                        getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs]
-                        def get(entity):
-                                value = entity
-                                for getter in getters:
-                                        value = getter(value)
-                                return value
-                        self.__getter = get
-                        self.__parent_getters = getters[:-1]
-                else:
-                        self.__getter = field_getter
-
-        def __getattr__(self, name):
-                """Return a FieldAccessor for the child attribute"""
-                return self.__class__(self.__field, self.__entities, self.__attrs + (name,))
-
-        def __setattr__(self, name, value):
-                if value is self:
-                        return # returned by mutators
-                if hasattr(self.__class__, name):
-                        # Set local attr
-                        self.__dict__[name] = value
-                elif not name.startswith('_'):
-                        getattr(self, name).__set__(value)
-                else:
-                        raise AttributeError("Cannot set field attribute: %s" % name)
-
-        @property
-        def __setter(self):
-                """Return the proper setter function for setting the field value"""
-                if not self.__attrs:
-                        return setattr
-                else:
-                        parent_getters = self.__parent_getters
-                        def setter(data, name, value):
-                                for getter in parent_getters:
-                                        data = getter(data)
-                                setattr(data, name, value)
-                        self.__setter = setter
-                        return setter
-
-        def __set__(self, value):
-                """Set field values en masse"""
-                # Mass set field attr
-                setter = self.__setter
-                component = self.__field.component
-                if self.__attrs:
-                        name = self.__attrs[-1]
-                else:
-                        name = self.__field.name
-                if isinstance(value, FieldAccessor):
-                        # Join set between two entity sets
-                        if not self.__attrs:
-                                cast = self.__field.cast
-                        else: 
-                                cast = lambda x: x
-                        for entity in self.__entities:
-                                try:
-                                        setter(component[entity], name, cast(value[entity]))
-                                except KeyError:
-                                        pass
-                else:
-                        if not self.__attrs:
-                                value = self.__field.cast(value)
-                        for entity in self.__entities:
-                                try:
-                                        setter(component[entity], name, value)
-                                except KeyError:
-                                        pass
-
-        def __getitem__(self, entity):
-                """Return the field value for a single entity (used for joins)"""
-                if entity in self.__entities:
-                        return self.__getter(self.__field.component[entity])
-                raise KeyError(entity)
-
-        def __contains__(self, entity):
-                return entity in self.__entities
-
-        def __repr__(self):
-                return '<%s %s @ %x>' % (
-                        self.__class__.__name__, 
-                        '.'.join((self.__field.name,) + self.__attrs), id(self))
-
-        def __nonzero__(self):
-                return bool(self.__entities)
-
-        def __iter__(self):
-                """Return an iterator of all field values in the set"""
-                component = self.__field.component
-                getter = self.__getter
-                for entity in self.__entities:
-                        try:
-                                data = component[entity]
-                        except KeyError:
-                                continue
-                        yield getter(data)
-
-        ## batch comparison operators ##
-
-        def __match(self, value, op):
-                component = self.__field.component
-                getter = self.__getter
-                matches = set()
-                add = matches.add
-                if isinstance(value, FieldAccessor):
-                        # Join match between entity sets
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                        other = value[entity]
-                                except KeyError:
-                                        continue
-                                if op(getter(data), other):
-                                        add(entity)
-                else:
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                except KeyError:
-                                        continue
-                                if op(getter(data), value):
-                                        add(entity)
-                return matches
-
-        def __eq__(self, value):
-                """Return an entity set of all entities with a matching field value"""
-                return self.__match(value, operator.eq)
-
-        def __ne__(self, value):
-                """Return an entity set of all entities not matching field value"""
-                return self.__match(value, operator.ne)
-
-        def __gt__(self, value):
-                """Return an entity set of all entities with a greater field value"""
-                return self.__match(value, operator.gt)
-
-        def __ge__(self, value):
-                """Return an entity set of all entities with a greater or equal field value"""
-                return self.__match(value, operator.ge)
-
-        def __lt__(self, value):
-                """Return an entity set of all entities with a lesser field value"""
-                return self.__match(value, operator.lt)
-
-        def __le__(self, value):
-                """Return an entity set of all entities with a lesser or equal field value"""
-                return self.__match(value, operator.le)
-
-        def _contains(self, values):
-                """Return an entity set of all entities with a field value contained in values"""
-                return self.__match(values, operator.contains)
-
-        ## Batch in-place mutator methods
-
-        def __mutate(self, value, op):
-                component = self.__field.component
-                if self.__attrs:
-                        name = self.__attrs[-1]
-                else:
-                        name = self.__field.name
-                getter = self.__getter
-                setter = self.__setter
-                if isinstance(value, FieldAccessor):
-                        # Join between entity sets
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                        other = value[entity]
-                                except KeyError:
-                                        continue
-                                setter(data, name, op(getter(data), other))
-                else:
-                        for entity in self.__entities:
-                                try:
-                                        data = component[entity]
-                                except KeyError:
-                                        continue
-                                setter(data, name, op(getter(data), value))
-                return self
-
-        def __iadd__(self, value):
-                return self.__mutate(value, operator.iadd)
-
-        def __isub__(self, value):
-                return self.__mutate(value, operator.isub)
-
-        def __imul__(self, value):
-                return self.__mutate(value, operator.imul)
-
-        def __idiv__(self, value):
-                return self.__mutate(value, operator.idiv)
-
-        def __itruediv__(self, value):
-                return self.__mutate(value, operator.itruediv)
-
-        def __ifloordiv__(self, value):
-                return self.__mutate(value, operator.ifloordiv)
-
-        def __imod__(self, value):
-                return self.__mutate(value, operator.imod)
-
-        def __ipow__(self, value):
-                return self.__mutate(value, operator.ipow)
-
-        def __ilshift__(self, value):
-                return self.__mutate(value, operator.ilshift)
-
-        def __irshift__(self, value):
-                return self.__mutate(value, operator.irshift)
-
-        def __iand__(self, value):
-                return self.__mutate(value, operator.iand)
-
-        def __ior__(self, value):
-                return self.__mutate(value, operator.ior)
-
-        def __ixor__(self, value):
-                return self.__mutate(value, operator.ixor)
-
-
-class Field(object):
-        """Component field metadata and accessor interface"""
-
-        def __init__(self, component, name, type, accessor_factory=FieldAccessor):
-                self.component = component
-                self.name = name
-                self.type = type
-                self.default = types.get(type)
-                self.accessor_factory = accessor_factory
-
-        def cast(self, value):
-                """Cast value to the appropriate type for thi field"""
-                if self.type is not object:
-                        return self.type(value)
-                else:
-                        return value
-
-        def accessor(self, entities=None):
-                """Return the field accessor for the entities in the component,
-                or all entities in the set specified that are also in the component
-                """
-                if entities is None or entities is self.component.entities:
-                        entities = self.component.entities
-                else:
-                        entities = entities & self.component.entities
-                return self.accessor_factory(self, entities)
--- a/grease/component/general.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-from grease.component import base
-from grease.component import field
-from grease.entity import ComponentEntitySet
-
-
-class Component(dict):
-	"""General component with a configurable schema
-
-	The field schema is defined via keyword args where the 
-	arg name is the field name and the value is the type object.
-
-	The following types are supported for fields:
-
-	- :class:`int`
-	- :class:`float`
-	- :class:`bool`
-	- :class:`str`
-	- :class:`object`
-	- |Vec2d|
-	- |Vec2dArray|
-	- |RGBA|
-	- |Rect|
-	"""
-
-	deleted_entities = ()
-	"""List of entities deleted from the component since the last time step"""
-
-	new_entities = ()
-	"""List of entities added to the component since the last time step"""
-
-	def __init__(self, **fields):
-		self.fields = {}
-		for fname, ftype in fields.items():
-			assert ftype in field.types, fname + " has an illegal field type"
-			self.fields[fname] = field.Field(self, fname, ftype)
-		self.entities = ComponentEntitySet(self)
-		self._added = []
-		self._deleted = []
-	
-	def set_world(self, world):
-		self.world = world
-	
-	def step(self, dt):
-		"""Update the component for the next timestep"""
-		delitem = super(Component, self).__delitem__
-		for entity in self._deleted:
-			delitem(entity)
-		self.new_entities = self._added
-		self.deleted_entities = self._deleted
-		self._added = []
-		self._deleted = []
-	
-	def set(self, entity, data=None, **data_kw):
-		"""Set the component data for an entity, adding it to the
-		component if it is not already a member.
-
-		If data is specified, its data for the new entity's fields are
-		copied from its attributes, making it easy to copy another
-		entity's data. Keyword arguments are also matched to fields.
-		If both a data attribute and keyword argument are supplied for
-		a single field, the keyword arg is used.
-		"""
-		if data is not None:
-			for fname, field in self.fields.items():
-				if fname not in data_kw and hasattr(data, fname):
-					data_kw[fname] = getattr(data, fname)
-		data = self[entity] = Data(self.fields, entity, **data_kw)
-		return data
-	
-	def __setitem__(self, entity, data):
-		assert entity.world is self.world, "Entity not in component's world"
-		if entity not in self.entities:
-			self._added.append(entity)
-			self.entities.add(entity)
-		super(Component, self).__setitem__(entity, data)
-	
-	def remove(self, entity):
-		if entity in self.entities:
-			self._deleted.append(entity)
-			self.entities.remove(entity)
-			return True
-		return False
-	
-	__delitem__ = remove
-
-	def __repr__(self):
-		return '<%s %x of %r>' % (
-			self.__class__.__name__, id(self), getattr(self, 'world', None))
-
-
-class Singleton(Component):
-	"""Component that may contain only a single entity"""
-
-	def add(self, entity_id, data=None, **data_kw):
-		if entity_id not in self._data:
-			self.entity_id_set.clear()
-			self._data.clear()
-		Component.add(self, entity_id, data, **data_kw)
-	
-	@property
-	def entity(self):
-		"""Return the entity in the component, or None if empty"""
-		if self._data:
-			return self.manager[self._data.keys()[0]]
-	
-
-class Data(object):
-
-	def __init__(self, fields, entity, **data):
-		self.__dict__['_Data__fields'] = fields
-		self.__dict__['entity'] = entity
-		for field in fields.values():
-			if field.name in data:
-				setattr(self, field.name, data[field.name])
-			else:
-				setattr(self, field.name, field.default())
-	
-	def __setattr__(self, name, value):
-		if name in self.__fields:
-			self.__dict__[name] = self.__fields[name].cast(value)
-		else:
-			raise AttributeError("Invalid data field: " + name)
-	
-	def __repr__(self):
-		return '<%s(%r)>' % (self.__class__.__name__, self.__dict__)
-
-			
-
--- a/grease/component/schema.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/grease/controller/__init__.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-__all__ = ('EulerMovement',)
-
-from grease.controller.integrator import EulerMovement
--- a/grease/controller/integrator.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-
-class EulerMovement(object):
-	"""System that applies entity movement to position using Euler's method
-
-	:param position_component: Name of :class:`grease.component.Position` 
-		component to update.
-	:param movement_component: Name of :class:`grease.component.Movement` 
-		component used to update position.
-	"""
-
-	def __init__(self, position_component='position', movement_component='movement'):
-		self.position_component = position_component
-		self.movement_component = movement_component
-	
-	def set_world(self, world):
-		"""Bind the system to a world"""
-		self.world = world
-	
-	def step(self, dt):
-		"""Apply movement to position"""
-		assert self.world is not None, "Cannot run with no world set"
-		for position, movement in self.world.components.join(
-			self.position_component, self.movement_component):
-			movement.velocity += movement.accel * dt
-			position.position += movement.velocity * dt
-			position.angle += movement.rotation * dt
-
--- a/grease/entity.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""Grease entities are useful as actionable, interactive
-game elements that are often visible to the player.
-
-You might use entities to represent:
-
-- Characters
-- Bullets
-- Particles
-- Pick-ups
-- Space Ships
-- Weapons
-- Trees
-- Planets
-- Explosions
-
-See :ref:`an example entity class in the tutorial <tut-entity-example>`.
-"""
-
-__version__ = '$Id$'
-
-__all__ = ('Entity', 'EntityComponentAccessor', 'ComponentEntitySet')
-
-
-class EntityMeta(type):
-	"""The entity metaclass enforces fixed slots of `entity_id` and `world`
-	for all subclasses. This prevents accidental use of other entity instance 
-	attributes, which may not be saved. 
-	
-	Class attributes are not affected by this restriction, but subclasses
-	should be careful not to cause name collisions with world components,
-	which are exposed as entity attributes. Using a naming convention for
-	class attributes, such as UPPER_CASE_WITH_UNDERSCORES is recommended to
-	avoid name clashes.
-
-	Note as a result of this, entity subclasses are not allowed to define
-	`__slots__`, and doing so will cause a `TypeError` to be raised.
-	"""
-
-	def __new__(cls, name, bases, clsdict):
-		if '__slots__' in clsdict:
-			raise TypeError('__slots__ may not be defined in Entity subclasses')
-		clsdict['__slots__'] = ('world', 'entity_id')
-		return type.__new__(cls, name, bases, clsdict)
-
-
-class Entity(object):
-	"""Base class for grease entities.
-	
-	Entity objects themselves are merely identifiers within a :class:`grease.world.World`.
-	They also provide a facade for convenient entity-wise access of component
-	data. However, they do not contain any data themselves other than an
-	entity id.
-
-	Entities must be instantiated in the context of a world. To instantiate an
-	entity, you must pass the world as the first argument to the constructor.
-	Subclasses that implement the :meth:`__init__()` method, must accept the world
-	as their first argument (after ``self``). Other constructor arguments can be
-	specified arbitarily by the subclass.
-	"""
-	__metaclass__ = EntityMeta
-
-	def __new__(cls, world, *args, **kw):
-		"""Create a new entity and add it to the world"""
-		entity = object.__new__(cls)
-		entity.world = world
-		entity.entity_id = world.new_entity_id()
-		world.entities.add(entity)
-		return entity
-	
-	def __getattr__(self, name):
-		"""Return an :class:`EntityComponentAccessor` for this entity
-		for the component named.
-
-		Example::
-
-			my_entity.movement
-		"""
-		component = getattr(self.world.components, name)
-		return EntityComponentAccessor(component, self)
-	
-	def __setattr__(self, name, value):
-		"""Set the entity data in the named component for this entity.
-		This sets the values of the component fields to the values of
-		the matching attributes of the value provided. This value must
-		have attributes for each of the component fields.
-
-		This allows you to easily copy component data from one entity
-		to another.
-
-		Example::
-
-			my_entity.position = other_entity.position
-		"""
-		if name in self.__class__.__slots__:
-			super(Entity, self).__setattr__(name, value)
-		else:
-			component = getattr(self.world.components, name)
-			component.set(self, value)
-	
-	def __delattr__(self, name):
-		"""Remove this entity and its data from the component.
-		
-		Example::
-		
-			del my_entity.renderable
-		"""
-		component = getattr(self.world.components, name)
-		del component[self]
-	
-	def __hash__(self):
-		return self.entity_id
-	
-	def __eq__(self, other):
-		return self.world is other.world and self.entity_id == other.entity_id
-
-	def __repr__(self):
-		return "<%s id: %s of %s %x>" % (
-			self.__class__.__name__, self.entity_id,
-			self.world.__class__.__name__, id(self.world))
-
-	def delete(self):
-		"""Delete the entity from its world. This removes all of its
-		component data. If then entity has already been deleted, 
-		this call does nothing.
-		"""
-		self.world.entities.discard(self)
-
-	@property
-	def exists(self):
-		"""True if the entity still exists in the world"""
-		return self in self.world.entities
-
-
-class EntityComponentAccessor(object):
-	"""A facade for accessing specific component data for a single entity.
-	The implementation is lazy and does not actually access the component
-	data until needed. If an attribute is set for a component that the 
-	entity is not yet a member of, it is automatically added to the
-	component first.
-
-	:param component: The :class:`grease.Component` being accessed
-	:param entity: The :class:`Entity` being accessed
-	"""
-	
-	# beware, name mangling ahead. We want to avoid clashing with any
-	# user-configured component field names
-	__data = None
-
-	def __init__(self, component, entity):
-		clsname = self.__class__.__name__
-		self.__dict__['_%s__component' % clsname] = component
-		self.__dict__['_%s__entity' % clsname] = entity
-	
-	def __nonzero__(self):
-		"""The accessor is True if the entity is in the component,
-		False if not, for convenient membership tests
-		"""
-		return self.__entity in self.__component
-	
-	def __getattr__(self, name):
-		"""Return the data for the specified field of the entity's component"""
-		if self.__data is None:
-			try:
-				data = self.__component[self.__entity]
-			except KeyError:
-				raise AttributeError(name)
-			clsname = self.__class__.__name__
-			self.__dict__['_%s__data' % clsname] = data
-		return getattr(self.__data, name)
-	
-	def __setattr__(self, name, value):
-		"""Set the data for the specified field of the entity's component"""
-		if self.__data is None:
-			clsname = self.__class__.__name__
-			if self.__entity in self.__component:
-				self.__dict__['_%s__data' % clsname] = self.__component[self.__entity]
-			else:
-				self.__dict__['_%s__data' % clsname] = self.__component.set(self.__entity)
-		setattr(self.__data, name, value)
-
-
-class ComponentEntitySet(set):
-	"""Set of entities in a component, can be queried by component fields"""
-
-	_component = None
-
-	def __init__(self, component, entities=()):
-		self.__dict__['_component'] = component
-		super(ComponentEntitySet, self).__init__(entities)
-	
-	def __getattr__(self, name):
-		if self._component is not None and name in self._component.fields:
-			return self._component.fields[name].accessor(self)
-		raise AttributeError(name)
-	
-	def __setattr__(self, name, value):
-		if self._component is not None and name in self._component.fields:
-			self._component.fields[name].accessor(self).__set__(value)
-		raise AttributeError(name)
-
--- a/grease/geometry.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,600 +0,0 @@
-__version__ = "$Id$"
-__docformat__ = "reStructuredText"
-
-import operator
-import math
-import ctypes 
-
-class Vec2d(ctypes.Structure):
-    """2d vector class, supports vector and scalar operators,
-       and also provides a bunch of high level functions
-       """
-    __slots__ = ['x', 'y']
-    
-    @classmethod
-    def from_param(cls, arg):
-        return cls(arg)
-        
-    def __init__(self, x_or_pair, y = None):
-        
-        if y == None:
-            self.x = x_or_pair[0]
-            self.y = x_or_pair[1]
-        else:
-            self.x = x_or_pair
-            self.y = y
- 
-    def __len__(self):
-        return 2
- 
-    def __getitem__(self, key):
-        if key == 0:
-            return self.x
-        elif key == 1:
-            return self.y
-        else:
-            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")
- 
-    def __setitem__(self, key, value):
-        if key == 0:
-            self.x = value
-        elif key == 1:
-            self.y = value
-        else:
-            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")
- 
-    # String representaion (for debugging)
-    def __repr__(self):
-        return 'Vec2d(%s, %s)' % (self.x, self.y)
-    
-    # Comparison
-    def __eq__(self, other):
-        if hasattr(other, "__getitem__") and len(other) == 2:
-            return self.x == other[0] and self.y == other[1]
-        else:
-            return False
-    
-    def __ne__(self, other):
-        if hasattr(other, "__getitem__") and len(other) == 2:
-            return self.x != other[0] or self.y != other[1]
-        else:
-            return True
- 
-    def __nonzero__(self):
-        return self.x or self.y
- 
-    # Generic operator handlers
-    def _o2(self, other, f):
-        "Any two-operator operation where the left operand is a Vec2d"
-        if isinstance(other, Vec2d):
-            return Vec2d(f(self.x, other.x),
-                         f(self.y, other.y))
-        elif (hasattr(other, "__getitem__")):
-            return Vec2d(f(self.x, other[0]),
-                         f(self.y, other[1]))
-        else:
-            return Vec2d(f(self.x, other),
-                         f(self.y, other))
- 
-    def _r_o2(self, other, f):
-        "Any two-operator operation where the right operand is a Vec2d"
-        if (hasattr(other, "__getitem__")):
-            return Vec2d(f(other[0], self.x),
-                         f(other[1], self.y))
-        else:
-            return Vec2d(f(other, self.x),
-                         f(other, self.y))
- 
-    def _io(self, other, f):
-        "inplace operator"
-        if (hasattr(other, "__getitem__")):
-            self.x = f(self.x, other[0])
-            self.y = f(self.y, other[1])
-        else:
-            self.x = f(self.x, other)
-            self.y = f(self.y, other)
-        return self
- 
-    # Addition
-    def __add__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(self.x + other.x, self.y + other.y)
-        elif hasattr(other, "__getitem__"):
-            return Vec2d(self.x + other[0], self.y + other[1])
-        else:
-            return Vec2d(self.x + other, self.y + other)
-    __radd__ = __add__
-    
-    def __iadd__(self, other):
-        if isinstance(other, Vec2d):
-            self.x += other.x
-            self.y += other.y
-        elif hasattr(other, "__getitem__"):
-            self.x += other[0]
-            self.y += other[1]
-        else:
-            self.x += other
-            self.y += other
-        return self
- 
-    # Subtraction
-    def __sub__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(self.x - other.x, self.y - other.y)
-        elif (hasattr(other, "__getitem__")):
-            return Vec2d(self.x - other[0], self.y - other[1])
-        else:
-            return Vec2d(self.x - other, self.y - other)
-    def __rsub__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(other.x - self.x, other.y - self.y)
-        if (hasattr(other, "__getitem__")):
-            return Vec2d(other[0] - self.x, other[1] - self.y)
-        else:
-            return Vec2d(other - self.x, other - self.y)
-    def __isub__(self, other):
-        if isinstance(other, Vec2d):
-            self.x -= other.x
-            self.y -= other.y
-        elif (hasattr(other, "__getitem__")):
-            self.x -= other[0]
-            self.y -= other[1]
-        else:
-            self.x -= other
-            self.y -= other
-        return self
- 
-    # Multiplication
-    def __mul__(self, other):
-        if isinstance(other, Vec2d):
-            return Vec2d(self.x*other.y, self.y*other.y)
-        if (hasattr(other, "__getitem__")):
-            return Vec2d(self.x*other[0], self.y*other[1])
-        else:
-            return Vec2d(self.x*other, self.y*other)
-    __rmul__ = __mul__
-    
-    def __imul__(self, other):
-        if isinstance(other, Vec2d):
-            self.x *= other.x
-            self.y *= other.y
-        elif (hasattr(other, "__getitem__")):
-            self.x *= other[0]
-            self.y *= other[1]
-        else:
-            self.x *= other
-            self.y *= other
-        return self
- 
-    # Division
-    def __div__(self, other):
-        return self._o2(other, operator.div)
-    def __rdiv__(self, other):
-        return self._r_o2(other, operator.div)
-    def __idiv__(self, other):
-        return self._io(other, operator.div)
- 
-    def __floordiv__(self, other):
-        return self._o2(other, operator.floordiv)
-    def __rfloordiv__(self, other):
-        return self._r_o2(other, operator.floordiv)
-    def __ifloordiv__(self, other):
-        return self._io(other, operator.floordiv)
- 
-    def __truediv__(self, other):
-        return self._o2(other, operator.truediv)
-    def __rtruediv__(self, other):
-        return self._r_o2(other, operator.truediv)
-    def __itruediv__(self, other):
-        return self._io(other, operator.floordiv)
- 
-    # Modulo
-    def __mod__(self, other):
-        return self._o2(other, operator.mod)
-    def __rmod__(self, other):
-        return self._r_o2(other, operator.mod)
- 
-    def __divmod__(self, other):
-        return self._o2(other, divmod)
-    def __rdivmod__(self, other):
-        return self._r_o2(other, divmod)
- 
-    # Exponentation
-    def __pow__(self, other):
-        return self._o2(other, operator.pow)
-    def __rpow__(self, other):
-        return self._r_o2(other, operator.pow)
- 
-    # Bitwise operators
-    def __lshift__(self, other):
-        return self._o2(other, operator.lshift)
-    def __rlshift__(self, other):
-        return self._r_o2(other, operator.lshift)
- 
-    def __rshift__(self, other):
-        return self._o2(other, operator.rshift)
-    def __rrshift__(self, other):
-        return self._r_o2(other, operator.rshift)
- 
-    def __and__(self, other):
-        return self._o2(other, operator.and_)
-    __rand__ = __and__
- 
-    def __or__(self, other):
-        return self._o2(other, operator.or_)
-    __ror__ = __or__
- 
-    def __xor__(self, other):
-        return self._o2(other, operator.xor)
-    __rxor__ = __xor__
- 
-    # Unary operations
-    def __neg__(self):
-        return Vec2d(operator.neg(self.x), operator.neg(self.y))
- 
-    def __pos__(self):
-        return Vec2d(operator.pos(self.x), operator.pos(self.y))
- 
-    def __abs__(self):
-        return Vec2d(abs(self.x), abs(self.y))
- 
-    def __invert__(self):
-        return Vec2d(-self.x, -self.y)
- 
-    # vectory functions
-    def get_length_sqrd(self): 
-        """Get the squared length of the vector.
-        It is more efficent to use this method instead of first call 
-        get_length() or access .length and then do a sqrt().
-        
-        :return: The squared length
-        """
-        return self.x**2 + self.y**2
- 
-    def get_length(self):
-        """Get the length of the vector.
-        
-        :return: The length
-        """
-        return math.sqrt(self.x**2 + self.y**2)    
-    def __setlength(self, value):
-        length = self.get_length()
-        self.x *= value/length
-        self.y *= value/length
-    length = property(get_length, __setlength, doc = """Gets or sets the magnitude of the vector""")
-       
-    def rotate(self, angle_degrees):
-        """Rotate the vector by angle_degrees degrees clockwise."""
-        radians = -math.radians(angle_degrees)
-        cos = math.cos(radians)
-        sin = math.sin(radians)
-        x = self.x*cos - self.y*sin
-        y = self.x*sin + self.y*cos
-        self.x = x
-        self.y = y
- 
-    def rotated(self, angle_degrees):
-        """Create and return a new vector by rotating this vector by 
-        angle_degrees degrees clockwise.
-        
-        :return: Rotated vector
-        """
-        radians = -math.radians(angle_degrees)
-        cos = math.cos(radians)
-        sin = math.sin(radians)
-        x = self.x*cos - self.y*sin
-        y = self.x*sin + self.y*cos
-        return Vec2d(x, y)
-    
-    def get_angle(self):
-        if (self.get_length_sqrd() == 0):
-            return 0
-        return math.degrees(math.atan2(self.y, self.x))
-    def __setangle(self, angle_degrees):
-        self.x = self.length
-        self.y = 0
-        self.rotate(angle_degrees)
-    angle = property(get_angle, __setangle, doc="""Gets or sets the angle of a vector""")
- 
-    def get_angle_between(self, other):
-        """Get the angle between the vector and the other in degrees
-        
-        :return: The angle
-        """
-        cross = self.x*other[1] - self.y*other[0]
-        dot = self.x*other[0] + self.y*other[1]
-        return math.degrees(math.atan2(cross, dot))
-            
-    def normalized(self):
-        """Get a normalized copy of the vector
-        
-        :return: A normalized vector
-        """
-        length = self.length
-        if length != 0:
-            return self/length
-        return Vec2d(self)
- 
-    def normalize_return_length(self):
-        """Normalize the vector and return its length before the normalization
-        
-        :return: The length before the normalization
-        """
-        length = self.length
-        if length != 0:
-            self.x /= length
-            self.y /= length
-        return length
- 
-    def perpendicular(self):
-        return Vec2d(-self.y, self.x)
-    
-    def perpendicular_normal(self):
-        length = self.length
-        if length != 0:
-            return Vec2d(-self.y/length, self.x/length)
-        return Vec2d(self)
-        
-    def dot(self, other):
-        """The dot product between the vector and other vector
-            v1.dot(v2) -> v1.x*v2.x + v1.y*v2.y
-            
-        :return: The dot product
-        """
-        return float(self.x*other[0] + self.y*other[1])
-        
-    def get_distance(self, other):
-        """The distance between the vector and other vector
-        
-        :return: The distance
-        """
-        return math.sqrt((self.x - other[0])**2 + (self.y - other[1])**2)
-        
-    def get_dist_sqrd(self, other):
-        """The squared distance between the vector and other vector
-        It is more efficent to use this method than to call get_distance()
-        first and then do a sqrt() on the result.
-        
-        :return: The squared distance
-        """
-        return (self.x - other[0])**2 + (self.y - other[1])**2
-        
-    def projection(self, other):
-        other_length_sqrd = other[0]*other[0] + other[1]*other[1]
-        projected_length_times_other_length = self.dot(other)
-        return other*(projected_length_times_other_length/other_length_sqrd)
-    
-    def cross(self, other):
-        """The cross product between the vector and other vector
-            v1.cross(v2) -> v1.x*v2.y - v2.y-v1.x
-        
-        :return: The cross product
-        """
-        return self.x*other[1] - self.y*other[0]
-    
-    def interpolate_to(self, other, range):
-        return Vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)
-    
-    def convert_to_basis(self, x_vector, y_vector):
-        return Vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())
- 
-    # Extra functions, mainly for chipmunk
-    def cpvrotate(self, other):
-        return Vec2d(self.x*other.x - self.y*other.y, self.x*other.y + self.y*other.x)
-    def cpvunrotate(self, other):
-        return Vec2d(self.x*other.x + self.y*other.y, self.y*other.x - self.x*other.y)
-    
-    # Pickle, does not work atm.
-    def __getstate__(self):
-        return [self.x, self.y]
-        
-    def __setstate__(self, dict):
-        self.x, self.y = dict
-    def __newobj__(cls, *args):
-        return cls.__new__(cls, *args)    
-Vec2d._fields_ = [
-            ('x', ctypes.c_double),
-            ('y', ctypes.c_double),
-        ]
-
-
-class Vec2dArray(list):
-
-	def __init__(self, iterable=()):
-		list.__init__(self, (Vec2d(i) for i in iterable))
-
-	def __setitem__(self, index, value):
-		list.__setitem__(self, index, Vec2d(value))
-	
-	def append(self, value):
-		"""Append a vector to the array"""
-		list.append(self, Vec2d(value))
-	
-	def insert(self, index, value):
-		"""Insert a vector into the array"""
-		list.insert(self, index, Vec2d(value))
-	
-	def transform(self, offset=Vec2d(0,0), angle=0, scale=1.0):
-		"""Return a new transformed Vec2dArray"""
-		offset = Vec2d(offset)
-		angle = math.radians(-angle)
-		rot_vec = Vec2d(math.cos(angle), math.sin(angle))
-		xformed = Vec2dArray()
-		for vec in self:
-			xformed.append(vec.cpvrotate(rot_vec) * scale + offset)
-		return xformed
-	
-	def segments(self, closed=True):
-		"""Generate arrays of line segments connecting adjacent vetices
-		in this array, exploding the shape into it's constituent segments
-		"""
-		if len(self) >= 2:
-			last = self[0]
-			for vert in self[1:]:
-				yield Vec2dArray((last, vert))
-				last = vert
-			if closed:
-				yield Vec2dArray((last, self[0]))
-		elif self and closed:
-			yield Vec2dArray((self[0], self[0]))
-
-
-
-class Rect(ctypes.Structure):
-	"""Simple rectangle. Will gain more functionality as needed"""
-	_fields_ = [
-		('left', ctypes.c_double),
-		('top', ctypes.c_double),
-		('right', ctypes.c_double),
-		('bottom', ctypes.c_double),
-	]
-
-	def __init__(self, rect_or_left, bottom=None, right=None, top=None):
-		if bottom is not None:
-			assert right is not None and top is not None, "No enough arguments to Rect"
-			self.left = rect_or_left
-			self.bottom = bottom
-			self.right = right
-			self.top = top
-		else:
-			self.left = rect_or_left.left
-			self.bottom = rect_or_left.bottom
-			self.right = rect_or_left.right
-			self.top = rect_or_left.top
-
-	@property
-	def width(self):
-		"""Rectangle width"""
-		return self.right - self.left
-	
-	@property
-	def height(self):
-		"""Rectangle height"""
-		return self.top - self.bottom
-
-
-########################################################################
-## Unit Testing                                                       ##
-########################################################################
-if __name__ == "__main__":
- 
-    import unittest
-    import pickle
- 
-    ####################################################################
-    class UnitTestVec2d(unittest.TestCase):
-    
-        def setUp(self):
-            pass
-        
-        def testCreationAndAccess(self):
-            v = Vec2d(111, 222)
-            self.assert_(v.x == 111 and v.y == 222)
-            v.x = 333
-            v[1] = 444
-            self.assert_(v[0] == 333 and v[1] == 444)
- 
-        def testMath(self):
-            v = Vec2d(111,222)
-            self.assertEqual(v + 1, Vec2d(112, 223))
-            self.assert_(v - 2 == [109, 220])
-            self.assert_(v * 3 == (333, 666))
-            self.assert_(v / 2.0 == Vec2d(55.5, 111))
-            #self.assert_(v / 2 == (55, 111)) # Not supported since this is a c_float structure in the bottom
-            self.assert_(v ** Vec2d(2, 3) == [12321, 10941048])
-            self.assert_(v + [-11, 78] == Vec2d(100, 300))
-            #self.assert_(v / [11,2] == [10,111]) # Not supported since this is a c_float structure in the bottom
- 
-        def testReverseMath(self):
-            v = Vec2d(111, 222)
-            self.assert_(1 + v == Vec2d(112, 223))
-            self.assert_(2 - v == [-109, -220])
-            self.assert_(3 * v == (333, 666))
-            #self.assert_([222,999] / v == [2,4]) # Not supported since this is a c_float structure in the bottom
-            self.assert_([111, 222] ** Vec2d(2, 3) == [12321, 10941048])
-            self.assert_([-11, 78] + v == Vec2d(100, 300))
- 
-        def testUnary(self):
-            v = Vec2d(111, 222)
-            v = -v
-            self.assert_(v == [-111, -222])
-            v = abs(v)
-            self.assert_(v == [111, 222])
- 
-        def testLength(self):
-            v = Vec2d(3,4)
-            self.assert_(v.length == 5)
-            self.assert_(v.get_length_sqrd() == 25)
-            self.assert_(v.normalize_return_length() == 5)
-            self.assertAlmostEquals(v.length, 1)
-            v.length = 5
-            self.assert_(v == Vec2d(3, 4))
-            v2 = Vec2d(10, -2)
-            self.assert_(v.get_distance(v2) == (v - v2).get_length())
-            
-        def testAngles(self):            
-            v = Vec2d(0, 3)
-            self.assertEquals(v.angle, 90)
-            v2 = Vec2d(v)
-            v.rotate(-90)
-            self.assertEqual(v.get_angle_between(v2), 90)
-            v2.angle -= 90
-            self.assertEqual(v.length, v2.length)
-            self.assertEquals(v2.angle, 0)
-            self.assertEqual(v2, [3, 0])
-            self.assert_((v - v2).length < .00001)
-            self.assertEqual(v.length, v2.length)
-            v2.rotate(300)
-            self.assertAlmostEquals(v.get_angle_between(v2), -60, 5) # Allow a little more error than usual (floats..)
-            v2.rotate(v2.get_angle_between(v))
-            angle = v.get_angle_between(v2)
-            self.assertAlmostEquals(v.get_angle_between(v2), 0)  
- 
-        def testHighLevel(self):
-            basis0 = Vec2d(5.0, 0)
-            basis1 = Vec2d(0, .5)
-            v = Vec2d(10, 1)
-            self.assert_(v.convert_to_basis(basis0, basis1) == [2, 2])
-            self.assert_(v.projection(basis0) == (10, 0))
-            self.assert_(basis0.dot(basis1) == 0)
-            
-        def testCross(self):
-            lhs = Vec2d(1, .5)
-            rhs = Vec2d(4, 6)
-            self.assert_(lhs.cross(rhs) == 4)
-            
-        def testComparison(self):
-            int_vec = Vec2d(3, -2)
-            flt_vec = Vec2d(3.0, -2.0)
-            zero_vec = Vec2d(0, 0)
-            self.assert_(int_vec == flt_vec)
-            self.assert_(int_vec != zero_vec)
-            self.assert_((flt_vec == zero_vec) == False)
-            self.assert_((flt_vec != int_vec) == False)
-            self.assert_(int_vec == (3, -2))
-            self.assert_(int_vec != [0, 0])
-            self.assert_(int_vec != 5)
-            self.assert_(int_vec != [3, -2, -5])
-        
-        def testInplace(self):
-            inplace_vec = Vec2d(5, 13)
-            inplace_ref = inplace_vec
-            inplace_src = Vec2d(inplace_vec)    
-            inplace_vec *= .5
-            inplace_vec += .5
-            inplace_vec /= (3, 6)
-            inplace_vec += Vec2d(-1, -1)
-            alternate = (inplace_src*.5 + .5)/Vec2d(3, 6) + [-1, -1]
-            self.assertEquals(inplace_vec, inplace_ref)
-            self.assertEquals(inplace_vec, alternate)
-        
-        def testPickle(self):
-            return # pickling does not work atm
-            testvec = Vec2d(5, .3)
-            testvec_str = pickle.dumps(testvec)
-            loaded_vec = pickle.loads(testvec_str)
-            self.assertEquals(testvec, loaded_vec)
-    
-    ####################################################################
-    unittest.main()
- 
--- a/grease/impl/__init__.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-
-__versioninfo__ = (0, 3, 0)
-__version__ = '.'.join(str(n) for n in __versioninfo__)
-
-__all__ = ('Mode', 'World')
-
-from mode import Mode
-from world import World
-
-
--- a/grease/impl/controls.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""Control systems for binding controls to game logic"""
-
-import grease
-from pyglet.window import key
-
-class KeyControls(grease.System):
-	"""System that maps subclass-defined action methods to keys. 
-
-	Keys may be mapped in the subclass definition using decorators
-	defined here as class methods or at runtime using the ``bind_key_*`` 
-	instance methods.
-
-	See :ref:`an example implementation in the tutorial <tut-controls-example>`.
-	"""
-	MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CAPSLOCK)
-	"""The MODIFIER_MASK allows you to filter out modifier keys that should be
-	ignored by the application. By default, capslock, numlock, and scrolllock 
-	are ignored.
-	"""
-
-	world = None
-	""":class:`grease.World` object this system is bound to"""
-
-	def __init__(self):
-		self._key_press_map = {}
-		self._key_release_map = {}
-		self._key_hold_map = {}
-		for name in self.__class__.__dict__:
-			member = getattr(self, name)
-			if hasattr(member, '_grease_hold_key_binding'):
-				for binding in member._grease_hold_key_binding:
-					self.bind_key_hold(member, *binding)
-			if hasattr(member, '_grease_press_key_binding'):
-				for binding in member._grease_press_key_binding:
-					self.bind_key_press(member, *binding)
-			if hasattr(member, '_grease_release_key_binding'):
-				for binding in member._grease_release_key_binding:
-					self.bind_key_release(member, *binding)
-		self.held_keys = set()
-
-	## decorator methods for binding methods to key input events ##
-
-	@classmethod
-	def key_hold(cls, symbol, modifiers=0):
-		"""Decorator to bind a method to be executed where a key is held down"""
-		def bind(f):
-			if not hasattr(f, '_grease_hold_key_binding'):
-				f._grease_hold_key_binding = []
-			f._grease_hold_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
-			return f
-		return bind
-
-	@classmethod
-	def key_press(cls, symbol, modifiers=0):
-		"""Decorator to bind a method to be executed where a key is initially depressed"""
-		def bind(f):
-			if not hasattr(f, '_grease_press_key_binding'):
-				f._grease_press_key_binding = []
-			f._grease_press_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
-			return f
-		return bind
-
-	@classmethod
-	def key_release(cls, symbol, modifiers=0):
-		"""Decorator to bind a method to be executed where a key is released"""
-		def bind(f):
-			if not hasattr(f, '_grease_release_key_binding'):
-				f._grease_release_key_binding = []
-			f._grease_release_key_binding.append((symbol, modifiers & cls.MODIFIER_MASK))
-			return f
-		return bind
-	
-	## runtime binding methods ##
-	
-	def bind_key_hold(self, method, key, modifiers=0):
-		"""Bind a method to a key at runtime to be invoked when the key is
-		held down, this replaces any existing key hold binding for this key.
-		To unbind the key entirely, pass ``None`` for method.
-		"""
-		if method is not None:
-			self._key_hold_map[key, modifiers & self.MODIFIER_MASK] = method
-		else:
-			try:
-				del self._key_hold_map[key, modifiers & self.MODIFIER_MASK]
-			except KeyError:
-				pass
-
-	def bind_key_press(self, method, key, modifiers=0):
-		"""Bind a method to a key at runtime to be invoked when the key is initially
-		pressed, this replaces any existing key hold binding for this key. To unbind
-		the key entirely, pass ``None`` for method.
-		"""
-		if method is not None:
-			self._key_press_map[key, modifiers & self.MODIFIER_MASK] = method
-		else:
-			try:
-				del self._key_press_map[key, modifiers & self.MODIFIER_MASK]
-			except KeyError:
-				pass
-
-	def bind_key_release(self, method, key, modifiers=0):
-		"""Bind a method to a key at runtime to be invoked when the key is releaseed,
-		this replaces any existing key hold binding for this key. To unbind
-		the key entirely, pass ``None`` for method.
-		"""
-		if method is not None:
-			self._key_release_map[key, modifiers & self.MODIFIER_MASK] = method
-		else:
-			try:
-				del self._key_release_map[key, modifiers & self.MODIFIER_MASK]
-			except KeyError:
-				pass
-
-	def step(self, dt):
-		"""invoke held key functions"""
-		already_run = set()
-		for key in self.held_keys:
-			func = self._key_hold_map.get(key)
-			if func is not None and func not in already_run:
-				already_run.add(func)
-				func(dt)
-
-	def on_key_press(self, key, modifiers):
-		"""Handle pyglet key press. Invoke key press methods and
-		activate key hold functions
-		"""
-		key_mod = (key, modifiers & self.MODIFIER_MASK)
-		if key_mod in self._key_press_map:
-			self._key_press_map[key_mod]()
-		self.held_keys.add(key_mod)
-	
-	def on_key_release(self, key, modifiers):
-		"""Handle pyglet key release. Invoke key release methods and
-		deactivate key hold functions
-		"""
-		key_mod = (key, modifiers & self.MODIFIER_MASK)
-		if key_mod in self._key_release_map:
-			self._key_release_map[key_mod]()
-		self.held_keys.discard(key_mod)
-
-
-if __name__ == '__main__':
-	import pyglet
-
-	class TestKeyControls(KeyControls):
-		
-		MODIFIER_MASK = ~(key.MOD_NUMLOCK | key.MOD_SCROLLLOCK | key.MOD_CTRL)
-
-		remapped = False
-		
-		@KeyControls.key_hold(key.UP)
-		@KeyControls.key_hold(key.W)
-		def up(self, dt):
-			print 'UP!'
-		
-		@KeyControls.key_hold(key.LEFT)
-		@KeyControls.key_hold(key.A)
-		def left(self, dt):
-			print 'LEFT!'
-		
-		@KeyControls.key_hold(key.RIGHT)
-		@KeyControls.key_hold(key.D)
-		def right(self, dt):
-			print 'RIGHT!'
-		
-		@KeyControls.key_hold(key.DOWN)
-		@KeyControls.key_hold(key.S)
-		def down(self, dt):
-			print 'DOWN!'
-
-		@KeyControls.key_press(key.SPACE)
-		def fire(self):
-			print 'FIRE!'
-
-		@KeyControls.key_press(key.R)
-		def remap_keys(self):
-			if not self.remapped:
-				self.bind_key_hold(None, key.W)
-				self.bind_key_hold(None, key.A)
-				self.bind_key_hold(None, key.S)
-				self.bind_key_hold(None, key.D)
-				self.bind_key_hold(self.up, key.I)
-				self.bind_key_hold(self.left, key.J)
-				self.bind_key_hold(self.right, key.L)
-				self.bind_key_hold(self.down, key.K)
-			else:
-				self.bind_key_hold(None, key.I)
-				self.bind_key_hold(None, key.J)
-				self.bind_key_hold(None, key.K)
-				self.bind_key_hold(None, key.L)
-				self.bind_key_hold(self.up, key.W)
-				self.bind_key_hold(self.left, key.A)
-				self.bind_key_hold(self.right, key.D)
-				self.bind_key_hold(self.down, key.S)
-			self.remapped = not self.remapped
-			
-
-	window = pyglet.window.Window()
-	window.clear()
-	controls = TestKeyControls()
-	window.push_handlers(controls)
-	pyglet.clock.schedule_interval(controls.step, 0.5)
-	pyglet.app.run()
-
--- a/grease/impl/mode.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""
-Modes manage the state and transition between different application modes.
-Typically such modes are presented as different screens that the user can
-navigate between, similar to the way a browser navigates web pages. Individual
-modes may be things like:
-
-- Title screen
-- Options dialog
-- About screen
-- In-progress game
-- Inventory interface
-
-The modal framework provides a simple mechanism to ensure that modes are
-activated and deactivated properly. An activated mode is running and receives
-events. A deactivated mode is paused and does not receive events.
-
-Modes may be managed as a *last-in-first-out* stack, or as a list, or ring
-of modes in sequence, or some combination of all.
-
-For example usage see: :ref:`the mode section of the tutorial <tut-mode-section>`.
-"""
-
-__version__ = '$Id$'
-
-import abc
-import pyglet
-from grease.mode import *
-
-class PygletManager(BaseManager):
-	"""Mode manager abstract base class using pyglet.
-	
-	The mode manager keeps a stack of modes where a single mode
-	is active at one time. As modes are pushed on and popped from 
-	the stack, the mode at the top is always active. The current
-	active mode receives events from the manager's event dispatcher.
-	"""
-
-	event_dispatcher = None
-	""":class:`pyglet.event.EventDispatcher` object that the
-	active mode receive events from.
-	"""
-	
-	def activate_mode(self, mode):
-		"""Perform actions to activate a node
-		
-		:param mode: The :class: 'Mode' object to activate
-		"""
-		BaseManager.activate_mode(self, mode)
-		self.event_dispatcher.push_handlers(mode)
-		
-	def deactivate_mode(self, mode):
-		"""Perform actions to deactivate a node
-		
-		:param mode: The :class: 'Mode' object to deactivate
-		"""
-		BaseManager.deactivate_mode(self, mode)
-		self.event_dispatcher.remove_handlers(mode)
-
-class Manager(PygletManager):
-	"""A basic mode manager that wraps a single
-	:class:`pyglet.event.EventDispatcher` object for use by its modes.
-	"""
-
-	def __init__(self, event_dispatcher):
-		self.modes = []
-		self.event_dispatcher = event_dispatcher
-
-
-class ManagerWindow(PygletManager, pyglet.window.Window):
-	"""An integrated mode manager and pyglet window for convenience.
-	The window is the event dispatcher used by modes pushed to
-	this manager.
-
-	Constructor arguments are identical to :class:`pyglet.window.Window`
-	"""
-	
-	def __init__(self, *args, **kw):
-		super(ManagerWindow, self).__init__(*args, **kw)
-		self.modes = []
-		self.event_dispatcher = self
-
-	def on_key_press(self, symbol, modifiers):
-		"""Default :meth:`on_key_press handler`, pops the current mode on ``ESC``"""
-		if symbol == pyglet.window.key.ESCAPE:
-			self.pop_mode()
-
-	def on_last_mode_pop(self, mode):
-		"""Hook executed when the last mode is popped from the manager.
-		When the last mode is popped from a window, an :meth:`on_close` event
-		is dispatched.
-
-		:param mode: The :class:`Mode` object just popped from the manager
-		"""
-		self.dispatch_event('on_close')
-
-
-class Mode(BaseMode):
-	"""Application mode abstract base class using pyglet
-
-	Subclasses must implement the :meth:`step` method
-	
-	:param step_rate: The rate of :meth:`step()` calls per second. 
-
-	:param master_clock: The :class:`pyglet.clock.Clock` interface used
-		as the master clock that ticks the world's clock. This 
-		defaults to the main pyglet clock.
-	"""
-	clock = None
-	"""The :class:`pyglet.clock.Clock` instance used as this mode's clock.
-	You should use this clock to schedule tasks for this mode, so they
-	properly respect when the mode is active or inactive
-
-	Example::
-
-		my_mode.clock.schedule_once(my_cool_function, 4)
-	"""
-
-	def __init__(self, step_rate=60, master_clock=pyglet.clock, 
-		         clock_factory=pyglet.clock.Clock):
-		BaseMode.__init__(self)
-		self.step_rate = step_rate
-		self.time = 0.0
-		self.master_clock = master_clock
-		self.clock = clock_factory(time_function=lambda: self.time)
-		self.clock.schedule_interval(self.step, 1.0 / step_rate)
-	
-	def on_activate(self):
-		"""Being called when the Mode is activated"""
-		self.master_clock.schedule(self.tick)
-	
-	def on_deactivate(self):
-		"""Being called when the Mode is deactivated"""
-		self.master_clock.unschedule(self.tick)
-		
-	def tick(self, dt):
-		"""Tick the mode's clock.
-
-		:param dt: The time delta since the last tick
-		:type dt: float
-		"""
-		self.time += dt
-		self.clock.tick(poll=False)
-	
-	@abc.abstractmethod
-	def step(self, dt):
-		"""Execute a timestep for this mode. Must be defined by subclasses.
-		
-		:param dt: The time delta since the last time step
-		:type dt: float
-		"""
-
-class Multi(BaseMulti, Mode):
-	"""A mode with multiple submodes. One submode is active at one time.
-	Submodes can be switched to directly or switched in sequence. If
-	the Multi is active, then one submode is always active.
-
-	Multis are useful when modes can switch in an order other than
-	a LIFO stack, such as in "hotseat" multiplayer games, a
-	"wizard" style ui, or a sequence of slides.
-
-	Note unlike a normal :class:`Mode`, a :class:`Multi` doesn't have it's own
-	:attr:`clock` and :attr:`step_rate`. The active submode's are used
-	instead.
-	"""
-	
-	def __init__(self, submodes):
-		BaseMulti.__init__(self, submodes)
-		self.time = 0.0
-
-	
-	def _set_active_submode(self, submode):
-		BaseMulti._set_active_submode(self, submode)
-		self.master_clock = submode.master_clock
-		self.clock = submode.clock
-
-	def clear_subnode(self):
-		"""Clear any subnmode data"""
-		BaseMulti.clear_subnode(self)
-		self.master_clock = None
-		self.clock = None
-
-	def tick(self, dt):
-		"""Tick the active submode's clock.
-
-		:param dt: The time delta since the last tick
-		:type dt: float
-		"""
-		self.time += dt
-		if self.active_submode is not None:
-			self.active_submode.clock.tick(poll=False)
-
--- a/grease/impl/world.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""Worlds are environments described by a configuration of components, systems and 
-renderers. These parts describe the data, behavioral and presentation aspects
-of the world respectively.
-
-The world environment is the context within which entities exist. A typical
-application consists of one or more worlds containing entities that evolve
-over time and react to internal and external interaction.
-
-See :ref:`an example of world configuration in the tutorial <tut-world-example>`.
-"""
-
-__version__ = '$Id$'
-
-import itertools
-import pyglet
-from pyglet import gl
-from grease.world import *
-from grease.impl import Mode
-
-class World(Mode, BaseWorld):
-	"""A coordinated collection of components, systems and entities
-	
-	A world is also a mode that may be pushed onto a 
-	:class:`grease.mode.Manager`
-
-	:param step_rate: The rate of :meth:`step()` calls per second. 
-
-	:param master_clock: The :class:`pyglet.clock.Clock` interface used
-		as the master clock that ticks the world's clock. This 
-		defaults to the main pyglet clock.
-	"""
-
-	clock = None
-	""":class:`pyglet.clock` interface for use by constituents
-	of the world for scheduling
-	"""
-
-	time = None
-	"""Current clock time of the world, starts at 0 when the world
-	is instantiated
-	"""
-
-	running = True
-	"""Flag to indicate that the world clock is running, advancing time
-	and stepping the world. Set running to False to pause the world.
-	"""
-
-	def __init__(self, step_rate=60, master_clock=pyglet.clock,
-				 clock_factory=pyglet.clock.Clock):
-		Mode.__init__(self, step_rate, master_clock, clock_factory)
-		BaseWorld.__init__(self)
-	
-	def activate(self, manager):
-		"""Activate the world/mode for the given manager, if the world is already active, 
-		do nothing. This method is typically not used directly, it is called
-		automatically by the mode manager when the world becomes active.
-
-		The systems of the world are pushed onto `manager.event_dispatcher`
-		so they can receive system events.
-
-		:param manager: :class:`mode.BaseManager` instance
-		"""
-		if not self.active:
-			for system in self.systems:
-				manager.event_dispatcher.push_handlers(system)
-		super(World, self).activate(manager)
-	
-	def deactivate(self, manager):
-		"""Deactivate the world/mode, if the world is not active, do nothing.
-		This method is typically not used directly, it is called
-		automatically by the mode manager when the world becomes active.
-
-		Removes the system handlers from the `manager.event_dispatcher`
-
-		:param manager: :class:`mode.BaseManager` instance
-		"""
-		for system in self.systems:
-			manager.event_dispatcher.remove_handlers(system)
-		super(World, self).deactivate(manager)
-
-	def tick(self, dt):
-		"""Tick the mode's clock, but only if the world is currently running
-		
-		:param dt: The time delta since the last tick
-		:type dt: float
-		"""
-		if self.running:
-			super(World, self).tick(dt)
-	
-	def step(self, dt):
-		"""Execute a time step for the world. Updates the world `time`
-		and invokes the world's systems.
-		
-		Note that the specified time delta will be pinned to 10x the
-		configured step rate. For example if the step rate is 60,
-		then dt will be pinned at a maximum of 0.1666. This avoids 
-		pathological behavior when the time between steps goes
-		much longer than expected.
-
-		:param dt: The time delta since the last time step
-		:type dt: float
-		"""
-		dt = min(dt, 10.0 / self.step_rate)
-		for component in self.components:
-			if hasattr(component, "step"):
-				component.step(dt)
-		for system in self.systems:
-			if hasattr(system, "step"):
-				system.step(dt)
-
-	def on_draw(self, gl=pyglet.gl):
-		"""Clear the current OpenGL context, reset the model/view matrix and
-		invoke the `draw()` methods of the renderers in order
-		"""
-		gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
-		gl.glLoadIdentity()
-		BaseWorld.draw_renderers(self)
\ No newline at end of file
--- a/grease/mode.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,391 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""
-Modes manage the state and transition between different application modes.
-Typically such modes are presented as different screens that the user can
-navigate between, similar to the way a browser navigates web pages. Individual
-modes may be things like:
-
-- Title screen
-- Options dialog
-- About screen
-- In-progress game
-- Inventory interface
-
-The modal framework provides a simple mechanism to ensure that modes are
-activated and deactivated properly. An activated mode is running and receives
-events. A deactivated mode is paused and does not receive events.
-
-Modes may be managed as a *last-in-first-out* stack, or as a list, or ring
-of modes in sequence, or some combination of all.
-
-For example usage see: :ref:`the mode section of the tutorial <tut-mode-section>`.
-"""
-
-__version__ = '$Id$'
-
-import abc
-
-
-class BaseManager(object):
-	"""Mode manager abstract base class.
-	
-	The mode manager keeps a stack of modes where a single mode
-	is active at one time. As modes are pushed on and popped from 
-	the stack, the mode at the top is always active. The current
-	active mode receives events from the manager's event dispatcher.
-	"""
-
-	modes = ()
-	"""The mode stack sequence. The last mode in the stack is
-	the current active mode. Read-only.
-	"""
-
-	@property
-	def current_mode(self):
-		"""The current active mode or ``None``. Read-only"""
-		try:
-			return self.modes[-1]
-		except IndexError:
-			return None
-	
-	def on_last_mode_pop(self, mode):
-		"""Hook executed when the last mode is popped from the manager.
-		Implementing this method is optional for subclasses.
-
-		:param mode: The :class:`Mode` object just popped from the manager
-		"""
-	
-	def activate_mode(self, mode):
-		"""Perform actions to activate a node
-		
-		:param mode: The :class: 'Mode' object to activate
-		"""
-		mode.activate(self)
-
-	def deactivate_mode(self, mode):
-		"""Perform actions to deactivate a node
-		
-		:param mode: The :class: 'Mode' object to deactivate
-		"""
-		mode.deactivate(self)
-
-		
-	def push_mode(self, mode):
-		"""Push a mode to the top of the mode stack and make it active
-		
-		:param mode: The :class:`Mode` object to make active
-		"""
-		current = self.current_mode
-		if current is not None:
-			self.deactivate_mode(current)
-		self.modes.append(mode)
-		self.activate_mode(mode)
-	
-	def pop_mode(self):
-		"""Pop the current mode off the top of the stack and deactivate it.
-		The mode now at the top of the stack, if any is then activated.
-
-		:param mode: The :class:`Mode` object popped from the stack
-		"""
-		mode = self.modes.pop()
-		mode.deactivate(self)
-		current = self.current_mode
-		if current is not None:
-			self.activate_mode(current)
-		else:
-			self.on_last_mode_pop(mode)
-		return mode
-	
-	def swap_modes(self, mode):
-		"""Exchange the specified mode with the mode at the top of the stack.
-		This is similar to popping the current mode and pushing the specified
-		one, but without activating the previous mode on the stack or
-		executing :meth:`on_last_mode_pop()` if there is no previous mode.
-
-		:param mode: The :class:`Mode` object that was deactivated and replaced.
-		"""
-		old_mode = self.modes.pop()
-		self.deactivate_mode(old_mode)
-		self.modes.append(mode)
-		self.activate_mode(mode)
-		return old_mode
-	
-	def remove_mode(self, mode):
-		"""Remove the specified mode. If the mode is at the top of the stack,
-		this is equivilent to :meth:`pop_mode()`. If not, no other modes
-		are affected. If the mode is not in the manager, do nothing.
-
-		:param mode: The :class:`Mode` object to remove from the manager.
-		"""
-		if self.current_mode is mode:
-			self.pop_mode()
-		else:
-			try:
-				self.modes.remove(mode)
-			except ValueError:
-				pass
-
-class BaseMode(object):
-	"""Application mode very abstract base class
-	"""
-	__metaclass__ = abc.ABCMeta
-
-	manager = None
-	"""The :class:`BaseManager` that manages this mode"""
-
-	def __init__(self):
-		self.active = False
-		
-	def on_activate(self):
-		"""Being called when the Mode is activated"""
-		pass
-	
-	def activate(self, mode_manager):
-		"""Activate the mode for the given mode manager, if the mode is already active, 
-		do nothing
-
-		The default implementation schedules time steps at :attr:`step_rate` per
-		second, sets the :attr:`manager` and sets the :attr:`active` flag to True.
-		"""
-		if not self.active:
-			self.on_activate()
-			self.manager = mode_manager
-			self.active = True
-
-	def on_deactivate(self):
-		"""Being called when the Mode is deactivated"""
-		pass
-
-	def deactivate(self, mode_manager):
-		"""Deactivate the mode, if the mode is not active, do nothing
-
-		The default implementation unschedules time steps for the mode and
-		sets the :attr:`active` flag to False.
-		"""
-		self.on_deactivate()
-		self.active = False
-
-
-class BaseMulti(BaseMode):
-	"""A mode with multiple submodes. One submode is active at one time.
-	Submodes can be switched to directly or switched in sequence. If
-	the Multi is active, then one submode is always active.
-
-	Multis are useful when modes can switch in an order other than
-	a LIFO stack, such as in "hotseat" multiplayer games, a
-	"wizard" style ui, or a sequence of slides.
-
-	Note unlike a normal :class:`Mode`, a :class:`Multi` doesn't have it's own
-	:attr:`clock` and :attr:`step_rate`. The active submode's are used
-	instead.
-	"""
-	active_submode = None
-	"""The currently active submode"""
-
-	def __init__(self, *submodes):
-		# We do not invoke the superclass __init__ intentionally
-		self.active = False
-		self.submodes = list(submodes)
-	
-	def add_submode(self, mode, before=None, index=None):
-		"""Add the submode, but do not make it active.
-
-		:param mode: The :class:`Mode` object to add.
-
-		:param before: The existing mode to insert the mode before. 
-			If the mode specified is not a submode, raise
-			ValueError.
-
-		:param index: The place to insert the mode in the mode list.
-			Only one of ``before`` or ``index`` may be specified.
-
-			If neither ``before`` or ``index`` are specified, the
-			mode is appended to the end of the list.
-		"""
-		assert before is None or index is None, (
-			"Cannot specify both 'before' and 'index' arguments")
-		if before is not None:
-			index = self.submodes.index(mode)
-		if index is not None:
-			self.submodes.insert(index, mode)
-		else:
-			self.submodes.append(mode)
-	
-	def remove_submode(self, mode=None):
-		"""Remove the submode.
-
-		:param mode: The submode to remove, if omitted the active submode
-			is removed. If the mode is not present, do nothing.  If the
-			mode is active, it is deactivated, and the next mode, if any
-			is activated. If the last mode is removed, the :class:`Multi`
-			is removed from its manager. 
-		"""
-		# TODO handle multiple instances of the same subnode
-		if mode is None:
-			mode = self.active_submode
-		elif mode not in self.submodes:
-			return
-		next_mode = self.activate_next()
-		self.submodes.remove(mode)
-		if next_mode is mode:
-			if self.manager is not None:
-				self.manager.remove_mode(self)
-			self._deactivate_submode()
-				
-	def activate_subnode(self, mode, before=None, index=None):
-		"""Activate the specified mode, adding it as a subnode
-		if it is not already. If the mode is already the active
-		submode, do nothing.
-
-		:param mode: The mode to activate, and add as necesary.
-
-		:param before: The existing mode to insert the mode before
-			if it is not already a submode.  If the mode specified is not
-			a submode, raise ValueError.
-
-		:param index: The place to insert the mode in the mode list
-			if it is not already a submode.  Only one of ``before`` or
-			``index`` may be specified.
-
-			If the mode is already a submode, the ``before`` and ``index``
-			arguments are ignored.
-		"""
-		if mode not in self.submodes:
-			self.add_submode(mode, before, index)
-		if self.active_submode is not mode:
-			self._activate_submode(mode)
-	
-	def activate_next(self, loop=True):
-		"""Activate the submode after the current submode in order.  If there
-		is no current submode, the first submode is activated.
-
-		Note if there is only one submode, it's active, and `loop` is True
-		(the default), then this method does nothing and the subnode remains
-		active.
-
-		:param loop: When :meth:`activate_next` is called 
-			when the last submode is active, a True value for ``loop`` will
-			cause the first submode to be activated.  Otherwise the
-			:class:`Multi` is removed from its manager.
-		:type loop: bool
-
-		:return:
-			The submode that was activated or None if there is no
-			other submode to activate.
-		"""
-		assert self.submodes, "No submode to activate"
-		next_mode = None
-		if self.active_submode is None:
-			next_mode = self.submodes[0]
-		else:
-			last_mode = self.active_submode
-			index = self.submodes.index(last_mode) + 1
-			if index < len(self.submodes):
-				next_mode = self.submodes[index]
-			elif loop:
-				next_mode = self.submodes[0]
-		self._activate_submode(next_mode)
-		return next_mode
-
-	def activate_previous(self, loop=True):
-		"""Activate the submode before the current submode in order.  If there
-		is no current submode, the last submode is activated.
-
-		Note if there is only one submode, it's active, and `loop` is True
-		(the default), then this method does nothing and the subnode remains
-		active.
-		
-		:param loop: When :meth:`activate_previous` is called 
-			when the first submode is active, a True value for ``loop`` will
-			cause the last submode to be activated.  Otherwise the
-			:class:`Multi` is removed from its manager.
-		:type loop: bool
-
-		:return:
-			The submode that was activated or None if there is no
-			other submode to activate.
-		"""
-		assert self.submodes, "No submode to activate"
-		prev_mode = None
-		if self.active_submode is None:
-			prev_mode = self.submodes[-1]
-		else:
-			last_mode = self.active_submode
-			index = self.submodes.index(last_mode) - 1
-			if loop or index >= 0:
-				prev_mode = self.submodes[index]
-		self._activate_submode(prev_mode)
-		return prev_mode
-	
-	def _set_active_submode(self, submode):
-		self.active_submode = submode
-		self.step_rate = submode.step_rate
-
-	def _activate_submode(self, submode):
-		"""Activate a submode deactivating any current submode. If the Multi
-		itself is active, this happens immediately, otherwise the actual
-		activation is deferred until the Multi is activated. If the submode
-		is None, the Mulitmode is removed from its manager.
-
-		If submode is already the active submode, do nothing.
-		"""
-		if self.active_submode is submode:
-			return
-		assert submode in self.submodes, "Unknown submode"
-		self._deactivate_submode()
-		self._set_active_submode(submode)
-		if submode is not None:
-			if self.active:
-				self.manager.activate_mode(submode)
-		else:
-			if self.manager is not None:
-				self.manager.remove_mode(self)
-	
-	def clear_subnode(self):
-		"""Clear any subnmode data"""
-		self.active_submode = None
-		self.step_rate = None
-				
-	def _deactivate_submode(self, clear_subnode=True):
-		"""Deactivate the current submode, if any. if `clear_subnode` is
-		True, `active_submode` is always None when this method returns
-		"""
-		if self.active_submode is not None:
-			if self.active:
-				self.manager.deactivate_mode(self.active_submode)
-			if clear_subnode:
-				self.clear_subnode()
-	
-	def activate(self, mode_manager):
-		"""Activate the :class:`Multi` for the specified manager. The
-		previously active submode of the :class:`Multi` is activated. If there
-		is no previously active submode, then the first submode is made active. 
-		A :class:`Multi` with no submodes cannot be activated
-		"""
-		assert self.submodes, "No submode to activate"
-		self.manager = mode_manager
-		if self.active_submode is None:
-			self._set_active_submode(self.submodes[0])
-		else:
-			self._set_active_submode(self.active_submode)
-		self.manager.activate_mode(self.active_submode)
-		super(BaseMulti, self).activate(mode_manager)
-	
-	def deactivate(self, mode_manager):
-		"""Deactivate the :class:`Multi` for the specified manager.
-		The `active_submode`, if any, is deactivated.
-		"""
-		self._deactivate_submode(clear_subnode=False)
-		super(BaseMulti, self).deactivate(mode_manager)
-
--- a/grease/renderer/__init__.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""Renderers define world presentation. This module contains the
-built-in renderer classes.
-
-See also:
-
-- :class:`~grease.Renderer` abstract base class.
-- :ref:`Example renderer class in the tutorial <tut-renderer-example>`
-"""
-
-__all__ = ('Vector', 'Camera')
-
-from grease.renderer.vector import Vector
-from grease.renderer.camera import Camera
--- a/grease/renderer/camera.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-import pyglet
-
-class Camera(object):
-	"""Sets the point of view for further renderers by altering the
-	model/view matrix when it is drawn. It does not actually perform
-	any drawing itself.
-
-	:param position: The position vector for the camera. Sets the center of the view.
-	:type position: Vec2d
-	:param angle: Camera rotation in degrees about the z-axis.
-	:type angle: float
-	:param zoom: Scaling vector for the coordinate axis.
-	:type zoom: Vec2d
-	:param relative: Flag to indicate if the camera settings are relative 
-		to the previous view state. If ``False`` the view state is reset before 
-		setting the camera view by loading the identity model/view matrix.
-	
-	At runtime the camera may be manipulated via attributes with the 
-	same names and functions as the parameters above.
-	"""
-
-	def __init__(self, position=None, angle=None, zoom=None, relative=False):
-		self.position = position
-		self.angle = angle
-		self.zoom = zoom
-		self.relative = relative
-	
-	def draw(self, gl=pyglet.gl):
-		if not self.relative:
-			gl.glLoadIdentity()
-		if self.position is not None:
-			px, py = self.position
-			gl.glTranslatef(px, py, 0)
-		if self.angle is not None:
-			gl.glRotatef(self.angle, 0, 0, 1)
-		if self.zoom is not None:
-			sx, sy = self.zoom
-			gl.glScalef(sx, sy ,0)
-
--- a/grease/renderer/vector.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-
-__version__ = '$Id$'
-
-__all__ = ('Vector',)
-
-from grease.geometry import Vec2d
-import ctypes
-from math import sin, cos, radians
-import pyglet
-
-
-class Vector(object):
-	"""Renders shapes in a classic vector graphics style
-	
-	:param scale: Scaling factor applied to shape vertices when rendered.
-	
-	:param line_width: The line width provided to ``glLineWidth`` before rendering.
-		If not specified or None, ``glLineWidth`` is not called, and the line
-		width used is determined by the OpenGL state at the time of rendering.
-
-	:param anti_alias: If ``True``, OpenGL blending and line smoothing is enabled.
-		This allows for fractional line widths as well. If ``False``, the blending
-		and line smoothing modes are unchanged.
-
-	:param corner_fill: If true (the default), the shape corners will be filled
-		with round points when the ``line_width`` exceeds 2.0. This improves
-		the visual quality of the rendering at larger line widths at some
-		cost to performance. Has no effect if ``line_width`` is not specified.
-
-	:param position_component: Name of :class:`grease.component.Position` 
-		component to use. Shapes rendered are offset by the entity positions.
-
-	:param renderable_component: Name of :class:`grease.component.Renderable` 
-		component to use. This component specifies the entities to be 
-		rendered and their base color.
-
-	:param shape_component: Name of :class:`grease.component.Shape` 
-		component to use. Source of the shape vertices for each entity.
-
-	The entities rendered are taken from the intersection of he position,
-	renderable and shape components each time :meth:`draw` is called.
-	"""
-
-	CORNER_FILL_SCALE = 0.6
-	CORNER_FILL_THRESHOLD = 2.0
-
-	def __init__(self, scale=1.0, line_width=None, anti_alias=True, corner_fill=True,
-		position_component='position', 
-		renderable_component='renderable', 
-		shape_component='shape'):
-		self.scale = float(scale)
-		self.corner_fill = corner_fill
-		self.line_width = line_width
-		self.anti_alias = anti_alias
-		self._max_line_width = None
-		self.position_component = position_component
-		self.renderable_component = renderable_component
-		self.shape_component = shape_component
-	
-	def set_world(self, world):
-		self.world = world
-
-	def _generate_verts(self):
-		"""Generate vertex and index arrays for rendering"""
-		vert_count = sum(len(shape.verts) + 1
-			for shape, ignored, ignored in self.world.components.join(
-				self.shape_component, self.position_component, self.renderable_component))
-		v_array = (CVertColor * vert_count)()
-		if vert_count > 65536:
-			i_array = (ctypes.c_uint * 2 * vert_count)()
-			i_size = pyglet.gl.GL_UNSIGNED_INT
-		else:
-			i_array = (ctypes.c_ushort * (2 * vert_count))()
-			i_size = pyglet.gl.GL_UNSIGNED_SHORT
-		v_index = 0
-		i_index = 0
-		scale = self.scale
-		rot_vec = Vec2d(0, 0)
-		for shape, position, renderable in self.world.components.join(
-			self.shape_component, self.position_component, self.renderable_component):
-			shape_start = v_index
-			angle = radians(-position.angle)
-			rot_vec.x = cos(angle)
-			rot_vec.y = sin(angle)
-			r = int(renderable.color.r * 255)
-			g = int(renderable.color.g * 255)
-			b = int(renderable.color.b * 255)
-			a = int(renderable.color.a * 255)
-			for vert in shape.verts:
-				vert = vert.cpvrotate(rot_vec) * scale + position.position
-				v_array[v_index].vert.x = vert.x
-				v_array[v_index].vert.y = vert.y
-				v_array[v_index].color.r = r
-				v_array[v_index].color.g = g
-				v_array[v_index].color.b = b
-				v_array[v_index].color.a = a
-				if v_index > shape_start:
-					i_array[i_index] = v_index - 1
-					i_index += 1
-					i_array[i_index] = v_index
-					i_index += 1
-				v_index += 1
-			if shape.closed and v_index - shape_start > 2:
-				i_array[i_index] = v_index - 1
-				i_index += 1
-				i_array[i_index] = shape_start
-				i_index += 1
-		return v_array, i_size, i_array, i_index
-
-	def draw(self, gl=pyglet.gl):
-		vertices, index_size, indices, index_count = self._generate_verts()
-		if index_count:
-			if self.anti_alias:
-				gl.glEnable(gl.GL_LINE_SMOOTH)
-				gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
-				gl.glEnable(gl.GL_BLEND)
-				gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
-			gl.glPushClientAttrib(gl.GL_CLIENT_VERTEX_ARRAY_BIT)
-			gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
-			gl.glEnableClientState(gl.GL_COLOR_ARRAY)
-			gl.glVertexPointer(
-				2, gl.GL_FLOAT, ctypes.sizeof(CVertColor), ctypes.pointer(vertices))
-			gl.glColorPointer(
-				4, gl.GL_UNSIGNED_BYTE, ctypes.sizeof(CVertColor), 
-				ctypes.pointer(vertices[0].color))
-			if self.line_width is not None:
-				gl.glLineWidth(self.line_width)
-				if self._max_line_width is None:
-					range_out = (ctypes.c_float * 2)()
-					gl.glGetFloatv(gl.GL_ALIASED_LINE_WIDTH_RANGE, range_out)
-					self._max_line_width = float(range_out[1]) * self.CORNER_FILL_SCALE
-				if self.corner_fill and self.line_width > self.CORNER_FILL_THRESHOLD:
-					gl.glEnable(gl.GL_POINT_SMOOTH)
-					gl.glPointSize(
-						min(self.line_width * self.CORNER_FILL_SCALE, self._max_line_width))
-					gl.glDrawArrays(gl.GL_POINTS, 0, index_count)
-			gl.glDrawElements(gl.GL_LINES, index_count, index_size, ctypes.pointer(indices))
-			gl.glPopClientAttrib()
-
-
-class CVert(ctypes.Structure):
-	_fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)]
-
-class CColor(ctypes.Structure):
-	_fields_ = [
-		("r", ctypes.c_ubyte), 
-		("g", ctypes.c_ubyte), 
-		("b", ctypes.c_ubyte), 
-		("a", ctypes.c_ubyte),
-	]
-
-class CVertColor(ctypes.Structure):
-	_fields_ = [("vert", CVert), ("color", CColor)]
-
--- a/grease/world.py	Mon Sep 05 14:49:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2010 by Casey Duncan and contributors
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the MIT License
-# A copy of the license should accompany this distribution.
-# 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.
-#
-#############################################################################
-"""Worlds are environments described by a configuration of components, systems and 
-renderers. These parts describe the data, behavioral and presentation aspects
-of the world respectively.
-
-The world environment is the context within which entities exist. A typical
-application consists of one or more worlds containing entities that evolve
-over time and react to internal and external interaction.
-
-See :ref:`an example of world configuration in the tutorial <tut-world-example>`.
-"""
-
-__version__ = '$Id$'
-
-import itertools
-from grease import mode
-from grease.component import ComponentError
-from grease.entity import Entity, ComponentEntitySet
-
-
-class BaseWorld(object):
-	"""A coordinated collection of components, systems and entities
-	
-	A world is also a mode that may be pushed onto a 
-	:class:`grease.mode.Manager`
-	"""
-
-	components = None
-	""":class:`ComponentParts` object containing all world components.
-	:class:`grease.component.Component` objects define and contain all entity data
-	"""
-
-	systems = None
-	""":class:`Parts` object containing all world systems. 
-	:class:`grease.System` objects define world and entity behavior
-	"""
-
-	renderers = None
-	""":class:`Parts` object containing all world renderers. 
-	:class:`grease.Renderer` objects define world presentation
-	"""
-
-	entities = None
-	"""Set of all entities that exist in the world"""
-
-	def __init__(self):
-		self.components = ComponentParts(self)
-		self.systems = Parts(self)
-		self.renderers = Parts(self)
-		self.new_entity_id = itertools.count().next
-		self.new_entity_id() # skip id 0
-		self.entities = WorldEntitySet(self)
-		self._full_extent = EntityExtent(self, self.entities)
-		self._extents = {}
-		self.configure()
-
-	def configure(self):
-		"""Hook to configure the world after construction. This method
-		is called immediately after the world is initialized. Override
-		in a subclass to configure the world's components, systems,
-		and renderers.
-
-		The default implementation does nothing.
-		"""
-	
-	def __getitem__(self, entity_class):
-		"""Return an :class:`EntityExtent` for the given entity class. This extent
-		can be used to access the set of entities of that class in the world
-		or to query these entities via their components. 
-
-		Examples::
-
-			world[MyEntity]
-			world[...]
-
-		:param entity_class: The entity class for the extent.
-
-			May also be a tuple of entity classes, in which case
-			the extent returned contains union of all entities of the classes
-			in the world.
-
-			May also be the special value ellipsis (``...``), which
-			returns an extent containing all entities in the world.  This allows
-			you to conveniently query all entities using ``world[...]``.
-		"""
-		if isinstance(entity_class, tuple):
-			entities = set()
-			for cls in entity_class:
-				if cls in self._extents:
-					entities |= self._extents[cls].entities
-			return EntityExtent(self, entities)
-		elif entity_class is Ellipsis:
-			return self._full_extent
-		try:
-			return self._extents[entity_class]
-		except KeyError:
-			extent = self._extents[entity_class] = EntityExtent(self, set())
-			return extent
-	
-	def draw_renderers(self):
-		"""Draw all renderers"""
-		for renderer in self.renderers:
-			renderer.draw()
-
-class WorldEntitySet(set):
-	"""Entity set for a :class:`World`"""
-
-	def __init__(self, world):
-		self.world = world
-	
-	def add(self, entity):
-		"""Add the entity to the set and all necessary class sets
-		Return the unique entity id for the entity, creating one
-		as needed.
-		"""
-		super(WorldEntitySet, self).add(entity)
-		for cls in entity.__class__.__mro__:
-			if issubclass(cls, Entity):
-				self.world[cls].entities.add(entity)
-
-	def remove(self, entity):
-		"""Remove the entity from the set and, world components,
-		and all necessary class sets
-		"""
-		super(WorldEntitySet, self).remove(entity)
-		for component in self.world.components:
-			try:
-				del component[entity]
-			except KeyError:
-				pass
-		for cls in entity.__class__.__mro__:
-			if issubclass(cls, Entity):
-				self.world[cls].entities.discard(entity)
-	
-	def discard(self, entity):
-		"""Remove the entity from the set if it exists, if not,
-		do nothing
-		"""
-		try:
-			self.remove(entity)
-		except KeyError:
-			pass
-
-
-class EntityExtent(object):
-	"""Encapsulates a set of entities queriable by component. Extents
-	are accessed by using an entity class as a key on the :class:`World`::
-
-		extent = world[MyEntity]
-	"""
-
-	entities = None
-	"""The full set of entities in the extent""" 
-
-	def __init__(self, world, entities):
-		self.__world = world
-		self.entities = entities
-
-	def __getattr__(self, name):
-		"""Return a queriable :class:`ComponentEntitySet` for the named component 
-
-		Example::
-
-			world[MyEntity].movement.velocity > (0, 0)
-
-		Returns a set of entities where the value of the :attr:`velocity` field
-		of the :attr:`movement` component is greater than ``(0, 0)``.
-		"""
-		component = getattr(self.__world.components, name)
-		return ComponentEntitySet(component, self.entities & component.entities)
-
-
-class Parts(object):
-	"""Maps world parts to attributes. The parts are kept in the
-	order they are set. Parts may also be inserted out of order.
-	
-	Used for:
-	
-	- :attr:`World.systems`
-	- :attr:`World.renderers`
-	"""
-
-	_world = None
-	_parts = None
-	_reserved_names = ('entities', 'entity_id', 'world')
-
-	def __init__(self, world):
-		self._world = world
-		self._parts = []
-	
-	def _validate_name(self, name):
-		if (name in self._reserved_names or name.startswith('_') 
-			or hasattr(self.__class__, name)):
-			raise ComponentError('illegal part name: %s' % name)
-		return name
-
-	def __setattr__(self, name, part):
-		if not hasattr(self.__class__, name):
-			self._validate_name(name)
-			if not hasattr(self, name):
-				self._parts.append(part)
-			else:
-				old_part = getattr(self, name)
-				self._parts[self._parts.index(old_part)] = part
-			super(Parts, self).__setattr__(name, part)
-			if hasattr(part, 'set_world'):
-				part.set_world(self._world)
-		elif name.startswith("_"):
-			super(Parts, self).__setattr__(name, part)
-		else:
-			raise AttributeError("%s attribute is read only" % name)
-	
-	def __delattr__(self, name):
-		self._validate_name(name)
-		part = getattr(self, name)
-		self._parts.remove(part)
-		super(Parts, self).__delattr__(name)
-
-	def insert(self, name, part, before=None, index=None):
-		"""Add a part with a particular name at a particular index.
-		If a part by that name already exists, it is replaced.
-			
-		:arg name: The name of the part.
-		:type name: str
-
-		:arg part: The component, system, or renderer part to insert
-	
-		:arg before: A part object or name. If specified, the part is
-			inserted before the specified part in order.
-
-		:arg index: If specified, the part is inserted in the position
-			specified. You cannot specify both before and index.
-		:type index: int
-		"""
-		assert before is not None or index is not None, (
-			"Must specify a value for 'before' or 'index'")
-		assert before is None or index is None, (
-			"Cannot specify both 'before' and 'index' arguments when inserting")
-		self._validate_name(name)
-		if before is not None:
-			if isinstance(before, str):
-				before = getattr(self, before)
-			index = self._parts.index(before)
-		if hasattr(self, name):
-			old_part = getattr(self, name)
-			self._parts.remove(old_part)
-		self._parts.insert(index, part)
-		super(Parts, self).__setattr__(name, part)
-		if hasattr(part, 'set_world'):
-			part.set_world(self._world)
-
-	def __iter__(self):
-		"""Iterate the parts in order"""
-		return iter(tuple(self._parts))
-	
-	def __len__(self):
-		return len(self._parts)
-
-
-class ComponentParts(Parts):
-	"""Maps world components to attributes. The components are kept in the
-	order they are set. Components may also be inserted out of order.
-
-	Used for: :attr:`World.components`
-	"""
-
-	def join(self, *component_names):
-		"""Join and iterate entity data from multiple components together.
-
-		For each entity in all of the components named, yield a tuple containing
-		the entity data from each component specified.
-
-		This is useful in systems that pull data from multiple components.
-		
-		Typical Usage::
-
-			for position, movement in world.components.join("position", "movement"):
-				# Do something with each entity's position and movement data
-		"""
-		if component_names:
-			components = [getattr(self, self._validate_name(name)) 
-				for name in component_names]
-			if len(components) > 1:
-				entities = components[0].entities & components[1].entities
-				for comp in components[2:]:
-					entities &= comp.entities
-			else:
-				entities = components[0].entities
-			for entity in entities:
-				yield tuple(comp[entity] for comp in components)
-
--- a/mode.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/mode.py	Mon Sep 05 15:00:34 2011 +0200
@@ -1,5 +1,5 @@
 
-from parpg.grease.mode import *
+from bGrease.mode import *
 import abc
 
 class FifeManager(BaseManager):
--- a/systems/gamerulessystem.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/systems/gamerulessystem.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease import System
+from bGrease import System
 
 class GameRulesSystem(System):
     """
--- a/systems/scriptingsystem.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/systems/scriptingsystem.py	Mon Sep 05 15:00:34 2011 +0200
@@ -11,7 +11,7 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from parpg.grease import System
+from bGrease import System
 
 class ScriptingSystem(System):
     """
--- a/world.py	Mon Sep 05 14:49:45 2011 +0200
+++ b/world.py	Mon Sep 05 15:00:34 2011 +0200
@@ -1,4 +1,4 @@
-from parpg.grease.world import *
+from bGrease.world import *
 
 from parpg.mode import FifeMode
 from parpg import components