Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/elements/add_objects.py
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2014-03-07 19:44:11 (GMT)
committer Walter Bender <walter@sugarlabs.org>2014-03-07 19:44:11 (GMT)
commit8ba9d4ae100be129b255230790149f488032fa3c (patch)
tree791c00f957b6a04c8fd32e1c8059ce1e690b8ee7 /elements/add_objects.py
parent3d36a1c34a7c49f4265bb669aefcacededc94e55 (diff)
elements cleanupgtk3
Diffstat (limited to 'elements/add_objects.py')
-rw-r--r--elements/add_objects.py350
1 files changed, 195 insertions, 155 deletions
diff --git a/elements/add_objects.py b/elements/add_objects.py
index bfb7e0b..cec8212 100644
--- a/elements/add_objects.py
+++ b/elements/add_objects.py
@@ -8,7 +8,7 @@ Home: http://elements.linuxuser.at
IRC: #elements on irc.freenode.org
Code: http://www.assembla.com/wiki/show/elements
- svn co http://svn2.assembla.com/svn/elements
+ svn co http://svn2.assembla.com/svn/elements
License: GPLv3 | See LICENSE for the full text
This program is free software: you can redistribute it and/or modify
@@ -22,7 +22,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
+along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from locals import *
from elements import box2d
@@ -34,64 +34,75 @@ from math import asin
import tools_poly
+
class Add:
element_count = 0
-
+
def __init__(self, parent):
self.parent = parent
-
+
def ground(self):
""" Add a static ground to the scene
-
+
Return: box2d.b2Body
"""
return self._rect((-10.0, 0.0), 50.0, 0.1, dynamic=False)
-
- def triangle(self, pos, sidelength, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a triangle | pos & a in the current input unit system (meters or pixels)
-
+
+ def triangle(self, pos, sidelength, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a triangle | pos & a in the current input unit system
+ (meters or pixels)
+
Parameters:
pos .... position (x,y)
sidelength ...... sidelength
other .. see [physics parameters]
-
+
Return: box2d.b2Body
"""
- vertices = [(-sidelength, 0.0), (sidelength, 0.0), (0.0, 2*sidelength)]
- return self.poly(pos, vertices, dynamic, density, restitution, friction, screenCoord)
+ vertices = [(-sidelength, 0.0), (sidelength, 0.0),
+ (0.0, 2 * sidelength)]
+ return self.poly(pos, vertices, dynamic, density, restitution,
+ friction, screenCoord)
+
+ def ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16,
+ friction=0.5, screenCoord=True):
+ """ Add a dynamic ball at pos after correcting the positions and
+ lengths to the internal meter system if neccessary
+ (if INPUT_PIXELS), then call self._add_ball(...)
- def ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic ball at pos after correcting the positions and legths to the internal
- meter system if neccessary (if INPUT_PIXELS), then call self._add_ball(...)
-
Parameters:
pos ..... position (x,y)
radius .. circle radius
other ... see [physics parameters]
-
+
Return: box2d.b2Body
"""
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
+ # Bring coordinates into the world coordinate system (flip,
+ # camera offset, ...)
+ if screenCoord:
+ x, y = self.parent.to_world(pos)
+ else:
+ x, y = pos
- if self.parent.input == INPUT_PIXELS:
+ if self.parent.input_unit == INPUT_PIXELS:
x /= self.parent.ppm
y /= self.parent.ppm
radius /= self.parent.ppm
-
- return self._ball((x,y), radius, dynamic, density, restitution, friction)
- def _ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ return self._ball((x, y), radius, dynamic, density, restitution,
+ friction)
+
+ def _ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16,
+ friction=0.5):
# Add a ball without correcting any settings
# meaning, pos and vertices are in meters
# Define the body
x, y = pos
bodyDef = box2d.b2BodyDef()
- bodyDef.position=(x, y)
+ bodyDef.position = (x, y)
- userData = { 'color' : self.parent.get_color() }
+ userData = {'color': self.parent.get_color()}
bodyDef.userData = userData
# Create the Body
@@ -99,7 +110,7 @@ class Add:
density = 0
body = self.parent.world.CreateBody(bodyDef)
-
+
self.parent.element_count += 1
# Add a shape to the Body
@@ -110,12 +121,14 @@ class Add:
circleDef.friction = friction
body.CreateShape(circleDef)
- body.SetMassFromShapes()
-
- return body
+ body.SetMassFromShapes()
+
+ return body
- def rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic rectangle with input unit according to self.input (INPUT_PIXELS or INPUT_METERS)
+ def rect(self, pos, width, height, angle=0, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a dynamic rectangle with input unit according to self.input
+ (INPUT_PIXELS or INPUT_METERS)
Correcting the positions to meters and calling self._add_rect()
Parameters:
@@ -127,69 +140,78 @@ class Add:
Return: box2d.b2Body
"""
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
+ # Bring coordinates into the world coordinate system (flip,
+ # camera offset, ...)
+ if screenCoord:
+ x, y = self.parent.to_world(pos)
+ else:
+ x, y = pos
# If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
+ if self.parent.input_unit == INPUT_PIXELS:
x /= self.parent.ppm
y /= self.parent.ppm
width /= self.parent.ppm
height /= self.parent.ppm
-
+
# grad -> radians
angle = (angle * pi) / 180
-
- return self._rect((x,y), width, height, angle, dynamic, density, restitution, friction)
+ return self._rect((x, y), width, height, angle, dynamic, density,
+ restitution, friction)
- def wall(self, pos1, pos2, width=5, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a static rectangle between two arbitrary points with input unit according to self.input
- (INPUT_PIXELS or INPUT_METERS) Correcting the positions to meters and calling self._add_rect()
+ def wall(self, pos1, pos2, width=5, density=1.0, restitution=0.16,
+ friction=0.5, screenCoord=True):
+ """ Add a static rectangle between two arbitrary points with input
+ unit according to self.input_unit (INPUT_PIXELS or INPUT_METERS)
+ Correcting the positions to meters and calling self._add_rect()
Return: box2d.b2Body
"""
- if width < 5: width = 5
-
- if (pos1[0] < pos2[0]):
+ if width < 5:
+ width = 5
+
+ if (pos1[0] < pos2[0]):
x1, y1 = pos1
x2, y2 = pos2
else:
x1, y1 = pos2
- x2, y2 = pos1
+ x2, y2 = pos1
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord:
- x1, y1 = self.parent.to_world((x1, y1))
- x2, y2 = self.parent.to_world((x2, y2))
+ # Bring coordinates into the world coordinate system (flip,
+ # camera offset, ...)
+ if screenCoord:
+ x1, y1 = self.parent.to_world((x1, y1))
+ x2, y2 = self.parent.to_world((x2, y2))
# If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
+ if self.parent.input_unit == INPUT_PIXELS:
x1 /= self.parent.ppm
y1 /= self.parent.ppm
x2 /= self.parent.ppm
y2 /= self.parent.ppm
width /= self.parent.ppm
-
- length = sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )*0.5
+
+ length = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) * 0.5
if width > 0:
- halfX = x1 + (x2-x1)*0.5
- halfY = y1 + (y2-y1)*0.5
+ halfX = x1 + (x2 - x1) * 0.5
+ halfY = y1 + (y2 - y1) * 0.5
+
+ angle = asin((y2 - halfY) / length)
+ return self._rect((halfX, halfY), length, width, angle, False,
+ density, restitution, friction)
- angle = asin( (y2-halfY)/length )
- return self._rect((halfX, halfY), length, width, angle, False, density, restitution, friction)
-
- def _rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ def _rect(self, pos, width, height, angle=0, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5):
# Add a rect without correcting any settings
# meaning, pos and vertices are in meters
# angle is now in radians ((degrees * pi) / 180))
x, y = pos
bodyDef = box2d.b2BodyDef()
- bodyDef.position=(x, y)
+ bodyDef.position = (x, y)
- userData = { 'color' : self.parent.get_color() }
+ userData = {'color': self.parent.get_color()}
bodyDef.userData = userData
# Create the Body
@@ -197,25 +219,28 @@ class Add:
density = 0
body = self.parent.world.CreateBody(bodyDef)
-
+
self.parent.element_count += 1
# Add a shape to the Body
boxDef = box2d.b2PolygonDef()
-
- boxDef.SetAsBox(width, height, (0,0), angle)
+
+ boxDef.SetAsBox(width, height, (0, 0), angle)
boxDef.density = density
boxDef.restitution = restitution
boxDef.friction = friction
body.CreateShape(boxDef)
-
+
body.SetMassFromShapes()
-
+
return body
- def poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic polygon, which has the vertices arranged around the poly's center at pos
- Correcting the positions to meters if INPUT_PIXELS, and calling self._add_poly()
+ def poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16,
+ friction=0.5, screenCoord=True):
+ """ Add a dynamic polygon, which has the vertices arranged around
+ the poly's center at pos
+ Correcting the positions to meters if INPUT_PIXELS, and calling
+ self._add_poly()
Parameters:
pos ....... position (x,y)
@@ -223,34 +248,39 @@ class Add:
other ... see [physics parameters]
Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
+ """
+ # Bring coordinates into the world coordinate system (flip,
+ # camera offset, ...)
+ if screenCoord:
+ x, y = self.parent.to_world(pos)
+ else:
+ x, y = pos
+
# If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
+ if self.parent.input_unit == INPUT_PIXELS:
# translate pixel -> meters
x /= self.parent.ppm
y /= self.parent.ppm
-
+
# Translate vertices from pixels to meters
v_new = []
for v in vertices:
vx, vy = v
- v_new.append((vx/self.parent.ppm, vy/self.parent.ppm))
+ v_new.append((vx / self.parent.ppm, vy / self.parent.ppm))
vertices = v_new
-
- return self._poly((x,y), vertices, dynamic, density, restitution, friction)
- def _poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ return self._poly((x, y), vertices, dynamic, density, restitution,
+ friction)
+
+ def _poly(self, pos, vertices, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5):
# add a centered poly at pos without correcting any settings
# meaning, pos and vertices are in meters
x, y = pos
bodyDef = box2d.b2BodyDef()
- bodyDef.position=(x, y)
-
- userData = { 'color' : self.parent.get_color() }
+ bodyDef.position = (x, y)
+
+ userData = {'color': self.parent.get_color()}
bodyDef.userData = userData
# Create the Body
@@ -258,7 +288,7 @@ class Add:
density = 0
body = self.parent.world.CreateBody(bodyDef)
-
+
self.parent.element_count += 1
# Add a shape to the Body
@@ -271,36 +301,40 @@ class Add:
body.CreateShape(polyDef)
body.SetMassFromShapes()
-
+
return body
-
- def concavePoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- # 1. Step: Reduce
+
+ def concavePoly(self, vertices, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5, screenCoord=True):
+ # 1. Step: Reduce
# Detect if the polygon is closed or open
- if vertices[0] != vertices[-1]:
+ if vertices[0] != vertices[-1]:
is_closed = False
else:
is_closed = True
-
+
# Continue reducing the vertecs
x, y = c = tools_poly.calc_center(vertices)
vertices = tools_poly.poly_center_vertices(vertices)
-
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(c)
- else: x, y = c
+
+ # Bring coordinates into the world coordinate system (flip,
+ # camera offset, ...)
+ if screenCoord:
+ x, y = self.parent.to_world(c)
+ else:
+ x, y = c
# If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
+ if self.parent.input_unit == INPUT_PIXELS:
# translate pixel -> meters
x /= self.parent.ppm
y /= self.parent.ppm
-
+
# Let's add the body
bodyDef = box2d.b2BodyDef()
- bodyDef.position=(x, y)
+ bodyDef.position = (x, y)
- userData = { 'color' : self.parent.get_color() }
+ userData = {'color': self.parent.get_color()}
bodyDef.userData = userData
# Create the Body
@@ -308,12 +342,12 @@ class Add:
density = 0
body = self.parent.world.CreateBody(bodyDef)
-
+
self.parent.element_count += 1
# Create the reusable Box2D polygon and circle definitions
polyDef = box2d.b2PolygonDef()
- polyDef.vertexCount = 4 # rectangle
+ polyDef.vertexCount = 4 # rectangle
polyDef.density = density
polyDef.restitution = restitution
polyDef.friction = friction
@@ -324,25 +358,25 @@ class Add:
circleDef.restitution = restitution
circleDef.friction = friction
- # Set the scale factor
+ # Set the scale factor
factor = 8.0
v2 = box2d.b2Vec2(*vertices[0])
for v in vertices[1:]:
- v1 = v2.copy()
- v2 = box2d.b2Vec2(*v)
-
- vdir = v2-v1 # (v2x-v1x, v2y-v1y)
+ v1 = v2.copy()
+ v2 = box2d.b2Vec2(*v)
+
+ vdir = v2 - v1 # (v2x-v1x, v2y-v1y)
vdir.Normalize()
-
+
# we need a little size for the end part
- vn = box2d.b2Vec2(-vdir.y*factor, vdir.x*factor)
+ vn = box2d.b2Vec2(-vdir.y * factor, vdir.x * factor)
- v = [ v1+vn, v1-vn, v2-vn, v2+vn ]
+ v = [v1 + vn, v1 - vn, v2 - vn, v2 + vn]
- # Create a line (rect) for each part of the polygon,
- # and attach it to the body
- polyDef.setVertices( [vi / self.parent.ppm for vi in v] )
+ # Create a line (rect) for each part of the polygon,
+ # and attach it to the body
+ polyDef.setVertices([vi / self.parent.ppm for vi in v])
try:
polyDef.checkValues()
@@ -359,20 +393,21 @@ class Add:
break
circleDef.localPosition = v2 / self.parent.ppm
- body.CreateShape(circleDef)
-
+ body.CreateShape(circleDef)
+
# Now, all shapes have been attached
- body.SetMassFromShapes()
-
+ body.SetMassFromShapes()
+
# Return hard and soft reduced vertices
return body
- def complexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ def complexPoly(self, vertices, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5):
# 1. Step: Reduce
# 2. Step: See if start and end are close, if so then close the polygon
# 3. Step: Detect if convex or concave
# 4. Step: Start self.convexPoly or self.concavePoly
- vertices, is_convex = tools_poly.reduce_poly_by_angle(vertices)
+ vertices, is_convex = tools_poly.reduce_poly_by_angle(vertices)
#print "->", is_convex
# If start and endpoints are close to each other, close polygon
@@ -380,7 +415,7 @@ class Add:
x2, y2 = vertices[-1]
dx = x2 - x1
dy = y2 - y1
- l = sqrt((dx*dx)+(dy*dy))
+ l = sqrt((dx * dx) + (dy * dy))
if l < 50:
vertices[-1] = vertices[0]
@@ -392,19 +427,22 @@ class Add:
# Lines shall be drawn by self.concavePoly(...)
# print "is line"
is_convex = False
-
+
if is_convex:
# print "convex"
- return self.convexPoly(vertices, dynamic, density, restitution, friction), vertices
+ return self.convexPoly(vertices, dynamic, density, restitution,
+ friction), vertices
else:
# print "concave"
- return self.concavePoly(vertices, dynamic, density, restitution, friction), vertices
-
+ return self.concavePoly(vertices, dynamic, density, restitution,
+ friction), vertices
- def convexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- """ Add a complex polygon with vertices in absolute positions (meters or pixels, according
- to INPUT_PIXELS or INPUT_METERS). This function does the reduction and convec hulling
- of the poly, and calls add_poly(...)
+ def convexPoly(self, vertices, dynamic=True, density=1.0,
+ restitution=0.16, friction=0.5):
+ """ Add a complex polygon with vertices in absolute positions
+ (meters or pixels, according to INPUT_PIXELS or INPUT_METERS).
+ This function does the reduction and convec hulling
+ of the poly, and calls add_poly(...)
Parameters:
vertices .. absolute vertices positions
@@ -412,31 +450,34 @@ class Add:
Return: box2d.b2Body
"""
- # NOTE: Box2D has a maximum poly vertex count, defined in Common/box2d.b2Settings.h (box2d.b2_maxPolygonVertices)
- # We need to make sure, that we reach that by reducing the poly with increased tolerance
- # Reduce Polygon
- tolerance = 10 #5
+ # NOTE: Box2D has a maximum poly vertex count, defined in
+ # Common/box2d.b2Settings.h (box2d.b2_maxPolygonVertices) We
+ # need to make sure, that we reach that by reducing the poly
+ # with increased tolerance Reduce Polygon
+ tolerance = 10 # 5
v_new = vertices
while len(v_new) > box2d.b2_maxPolygonVertices:
- tolerance += 1
+ tolerance += 1
v_new = tools_poly.reduce_poly(vertices, tolerance)
-
- # print "convexPoly: Polygon reduced from %i to %i vertices | tolerance: %i" % (len(vertices), len(v_new), tolerance)
+
+ # print "convexPoly: Polygon reduced from %i to %i vertices |
+ # tolerance: %i" % (len(vertices), len(v_new), tolerance)
vertices = v_new
-
+
# So poly should be alright now
# Continue reducing the vertecs
- vertices_orig_reduced = vertices
+ vertices_orig_reduced = vertices
vertices = tools_poly.poly_center_vertices(vertices)
vertices = tools_poly.convex_hull(vertices)
- if len(vertices) < 3:
- return
-
+ if len(vertices) < 3:
+ return
+
# Define the body
- x, y = c = tools_poly.calc_center(vertices_orig_reduced)
- return self.poly((x,y), vertices, dynamic, density, restitution, friction)
+ x, y = tools_poly.calc_center(vertices_orig_reduced)
+ return self.poly((x, y), vertices, dynamic, density, restitution,
+ friction)
def to_b2vec(self, pt):
# Convert vector to a b2vect
@@ -454,33 +495,33 @@ class Add:
b1, b2, p1, p2, flag = args
p1 = self.to_b2vec(p1)
- p2 = self.to_b2vec(p2)
-
+ p2 = self.to_b2vec(p2)
+
jointDef = box2d.b2DistanceJointDef()
jointDef.Initialize(b1, b2, p1, p2)
jointDef.collideConnected = flag
-
- self.parent.world.CreateJoint(jointDef)
+
+ self.parent.world.CreateJoint(jointDef)
elif len(args) == 4:
# Distance Joint
b1, b2, p1, p2 = args
p1 = self.to_b2vec(p1)
- p2 = self.to_b2vec(p2)
-
+ p2 = self.to_b2vec(p2)
+
jointDef = box2d.b2DistanceJointDef()
jointDef.Initialize(b1, b2, p1, p2)
jointDef.collideConnected = True
-
- self.parent.world.CreateJoint(jointDef)
-
+
+ self.parent.world.CreateJoint(jointDef)
+
elif len(args) == 3:
# Revolute Joint between two bodies (unimplemented)
pass
elif len(args) == 2:
- # Revolute Joint to the Background, at point
+ # Revolute Joint to the Background, at point
b1 = self.parent.world.GetGroundBody()
b2 = args[0]
p1 = self.to_b2vec(args[1])
@@ -494,10 +535,10 @@ class Add:
b1 = self.parent.world.GetGroundBody()
b2 = args[0]
p1 = b2.GetWorldCenter()
-
+
jointDef = box2d.b2RevoluteJointDef()
jointDef.Initialize(b1, b2, p1)
-
+
self.parent.world.CreateJoint(jointDef)
def motor(self, body, pt, torque=900, speed=-10):
@@ -530,9 +571,8 @@ class Add:
else:
self.parent.mouseJoint = self.parent.world.CreateJoint(mj)
body.WakeUp()
-
+
def remove_mouseJoint(self):
if self.parent.mouseJoint:
self.parent.world.DestroyJoint(self.parent.mouseJoint)
self.parent.mouseJoint = None
-