Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPootle daemon <pootle@pootle.sugarlabs.org>2013-12-15 05:31:41 (GMT)
committer Pootle daemon <pootle@pootle.sugarlabs.org>2013-12-15 05:31:41 (GMT)
commita1388063aa061359fdc60ce575632de6b67de5e7 (patch)
treefb1907c7b93a13aecfd4ba5563d4343ac958772a
parentb4c27004f4ed8d9ee5b13a005bb96f5f47790154 (diff)
parentb6b17c0e7428e6e5a997f3e3e946659daa81b88a (diff)
Merge branch 'master' of git.sugarlabs.org:physics/mainline
-rw-r--r--NEWS4
-rw-r--r--activity.py26
-rwxr-xr-xactivity/activity.info2
-rw-r--r--elements/elements.py37
-rw-r--r--icons/clear-trace.svg32
-rw-r--r--physics.py82
-rw-r--r--tools.py56
7 files changed, 189 insertions, 50 deletions
diff --git a/NEWS b/NEWS
index 71e5711..fdc96b5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,9 @@
-11.9
+12
* Removed cjson dependency for elements
* Added option to joints to set collideConnected = False
* Added clear_all (svineet)
* Added tracking (svineet)
* Added tracing (svineet)
+* Added erase traces (svineet)
+* Added save/restore of pens and traces (svineet)
diff --git a/activity.py b/activity.py
index 79e32bd..2d34eee 100644
--- a/activity.py
+++ b/activity.py
@@ -130,6 +130,15 @@ class PhysicsActivity(activity.Activity):
toolbar_box.toolbar.insert(separator, -1)
separator.show()
+ clear_trace = ToolButton("clear-trace")
+ clear_trace.set_tooltip(_("Clear Trace Marks"))
+ clear_trace.set_accelerator(_("<ctrl>x"))
+ clear_trace.connect("clicked", self.clear_trace_cb)
+ clear_trace.set_sensitive(False)
+ toolbar_box.toolbar.insert(clear_trace, -1)
+ clear_trace.show()
+ self.clear_trace = clear_trace
+
self._insert_clear_all_button(toolbar_box.toolbar)
separator = gtk.SeparatorToolItem()
@@ -184,6 +193,7 @@ class PhysicsActivity(activity.Activity):
self.clear_all.set_accelerator(_('<ctrl>a'))
self.clear_all.connect('clicked', self.clear_all_cb)
toolbar.insert(self.clear_all, -1)
+ self.clear_all.set_sensitive(False)
self.clear_all.show()
def _insert_create_tools(self, create_toolbar):
@@ -212,12 +222,26 @@ class PhysicsActivity(activity.Activity):
separator.show()
button.set_tooltip(c.toolTip)
- # button.set_accelerator(c.toolAccelerator)
+ button.set_accelerator(c.toolAccelerator)
button.connect('clicked', self.radioClicked)
_insert_item(create_toolbar, button, -1)
button.show()
self.radioList[button] = c.name
+ def clear_trace_alert_cb(self, alert, response):
+ self.remove_alert(alert)
+ if response is gtk.RESPONSE_OK:
+ self.game.full_pos_list = [[] for _ in self.game.full_pos_list]
+ self.game.tracked_bodies = 0
+
+ def clear_trace_cb(self, button):
+ clear_trace_alert = ConfirmationAlert()
+ clear_trace_alert.props.title = _('Are You Sure?')
+ clear_trace_alert.props.msg = \
+ _('All trace points will be erased. This cannot be undone!')
+ clear_trace_alert.connect('response', self.clear_trace_alert_cb)
+ self.add_alert(clear_trace_alert)
+
def stop_play_cb(self, button):
pygame.event.post(pygame.event.Event(pygame.USEREVENT,
action="stop_start_toggle"))
diff --git a/activity/activity.info b/activity/activity.info
index a061772..01d19af 100755
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -4,6 +4,6 @@ summary = Prove Sir Issac Newton right! Create real life simulations using diffe
bundle_id = org.laptop.physics
exec = sugar-activity activity.PhysicsActivity
icon = activity-physics
-activity_version = 11
+activity_version = 12
show_launcher = yes
mime_types = application/x-physics-activity;
diff --git a/elements/elements.py b/elements/elements.py
index 2b6fb71..4d9a361 100644
--- a/elements/elements.py
+++ b/elements/elements.py
@@ -430,7 +430,7 @@ class Elements:
return variables
- def json_save(self, path, additional_vars = {}):
+ def json_save(self, path, additional_vars = {}, serialize=False):
import json
worldmodel = {}
@@ -501,8 +501,21 @@ class Elements:
controllerlist = []
worldmodel['controllerlist'] = controllerlist
- worldmodel['additional_vars'] = additional_vars
+ if serialize:
+ addvars = additional_vars
+ trackinfo = addvars['trackinfo']
+ backup = trackinfo
+ for key, info in backup.iteritems():
+ if not info[3]:
+ trackinfo[key][0] = info[0].userData['saveid']
+ trackinfo[key][1] = info[1].userData['saveid']
+ else:
+ addvars['trackinfo'][key][0] = None
+ addvars['trackinfo'][key][1] = None
+
+ additional_vars['trackinfo'] = trackinfo
+ worldmodel['additional_vars'] = additional_vars
f = open(path,'w')
f.write(json.dumps(worldmodel))
f.close()
@@ -510,7 +523,7 @@ class Elements:
for body in self.world.GetBodyList():
del body.userData['saveid'] #remove temporary data
- def json_load(self, path, additional_vars = {}):
+ def json_load(self, path, serialized=False):
import json
self.world.GetGroundBody().userData = {"saveid" : 0}
@@ -577,8 +590,24 @@ class Elements:
jointDef.maxMotorTorque = joint['maxMotorTorque']
self.world.CreateJoint(jointDef)
+ self.additional_vars = {}
+ addvars = {}
for (k,v) in worldmodel['additional_vars'].items():
- additional_vars[k] = v
+ addvars[k] = v
+
+ if serialized:
+ trackinfo = addvars['trackinfo']
+ for key, info in trackinfo.iteritems():
+ if not info[3]:
+ addvars['trackinfo'][key][0] = \
+ self.getBodyWithSaveId(info[0])
+ addvars['trackinfo'][key][1] = \
+ self.getBodyWithSaveId(info[1])
+ else:
+ addvars['trackinfo'][key][0] = None
+ addvars['trackinfo'][key][1] = None
+
+ self.additional_vars = addvars
for body in self.world.GetBodyList():
del body.userData['saveid'] #remove temporary data
diff --git a/icons/clear-trace.svg b/icons/clear-trace.svg
new file mode 100644
index 0000000..9d33e12
--- /dev/null
+++ b/icons/clear-trace.svg
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata17"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs15" /><g
+ transform="matrix(1.3576811,0,0,1.3576811,-8.8093315,-11.060859)"
+ id="Eraser"><g
+ id="g5"
+ style="display:inline"><path
+ d="m 15.621,33.853 c -1.1,0 -1.424,-0.691 -0.721,-1.536 L 29.149,15.208 c 0.704,-0.845 2.18,-1.537 3.28,-1.537 h 7.805 c 1.1,0 1.424,0.691 0.721,1.537 L 26.706,32.316 c -0.704,0.845 -2.18,1.536 -3.28,1.536 h -7.805 z"
+ id="path7"
+ style="fill:#ffffff" /><path
+ d="m 24.709,41.155 c -0.166,1.088 -1.2,1.978 -2.301,1.978 h -8.525 c -1.1,0 -1.865,-0.89 -1.7,-1.978 l 0.549,-3.62 c 0.165,-1.088 1.2,-1.978 2.3,-1.978 h 8.525 c 1.101,0 1.865,0.89 1.701,1.978 l -0.549,3.62 z"
+ id="path9"
+ style="fill:#ffffff" /><path
+ d="m 40.446,23.333 c -0.189,1.083 -0.921,2.662 -1.625,3.507 l -11.35,13.627 c -0.705,0.846 -1.125,0.65 -0.936,-0.434 l 0.646,-3.688 c 0.19,-1.083 0.921,-2.661 1.626,-3.506 l 11.35,-13.627 c 0.705,-0.845 1.125,-0.65 0.936,0.434 l -0.647,3.687 z"
+ id="path11"
+ style="fill:#ffffff" /></g></g></svg> \ No newline at end of file
diff --git a/physics.py b/physics.py
index b0cad5e..6ce600a 100644
--- a/physics.py
+++ b/physics.py
@@ -50,6 +50,7 @@ from helpers import *
class PhysicsGame:
def __init__(self, activity):
+ self.activity = activity
# Get everything set up
self.clock = pygame.time.Clock()
self.canvas = activity.canvas
@@ -69,8 +70,9 @@ class PhysicsGame:
self.pygame_started = False
self.full_pos_list = []
- self.tracked_bodies = []
- self.body_colors = []
+ self.tracked_bodies = 0
+
+ self.trackinfo = {}
def switch_off_fake_pygame_cursor_cb(self, panel, event):
self.show_fake_cursor = False
@@ -81,7 +83,11 @@ class PhysicsGame:
def write_file(self, path):
#Saving to journal
self.world.add.remove_mouseJoint()
- self.world.json_save(path)
+ additional_data = {
+ "trackinfo" : self.trackinfo,
+ "full_pos_list" : self.full_pos_list
+ }
+ self.world.json_save(path, additional_data, serialize=True)
def read_file(self, path):
#Loading from journal
@@ -115,7 +121,9 @@ class PhysicsGame:
if self.opening_queue:
path = self.opening_queue.encode('ascii', 'convert')
if os.path.exists(path):
- self.world.json_load(path)
+ self.world.json_load(path, serialized=True)
+ self.full_pos_list = self.world.additional_vars['full_pos_list']
+ self.trackinfo = self.world.additional_vars['trackinfo']
while self.loop:
while gtk.events_pending():
@@ -135,31 +143,51 @@ class PhysicsGame:
if self.in_focus:
# Drive motors
if self.world.run_physics:
+ bodies_present = len(self.world.world.GetBodyList())
+ clear_all_active = self.activity.clear_all.get_sensitive()
+ if (bodies_present > 1) and clear_all_active is False:
+ self.activity.clear_all.set_sensitive(True)
+ elif (bodies_present > 1) is False and \
+ clear_all_active is True:
+ self.activity.clear_all.set_sensitive(False)
+
+ poslist = self.full_pos_list
+ clear_trace_active = self.activity.clear_trace.get_sensitive()
+ if poslist:
+ if not poslist[0]:
+ if clear_trace_active:
+ self.activity.clear_trace.set_sensitive(False)
+ else:
+ if clear_trace_active is False:
+ self.activity.clear_trace.set_sensitive(True)
+
+
+ for key, info in self.trackinfo.iteritems():
+ body = info[1] # [host_body, tracker, color, destroyed?]
+ if info[3] is False: # Not destroyed the pen
+ trackdex = info[4]
+ def to_screen(pos):
+ px = self.world.meter_to_screen(
+ pos[0])
+ py = self.world.meter_to_screen(
+ pos[1])
+ py = self.world.renderer.get_surface() \
+ .get_height() - py
+ return (px, py)
+
+ x = body.position.x
+ y = body.position.y
+ tupled_pos = to_screen((x, y))
+ posx = tupled_pos[0]
+ posy = tupled_pos[1]
+ try:
+ self.full_pos_list[trackdex].append(posx)
+ self.full_pos_list[trackdex].append(posy)
+ except IndexError:
+ self.full_pos_list.append([posx, posy])
+
for body in self.world.world.GetBodyList():
if type(body.userData) == type({}):
- if body.userData.has_key('track_index'):
- trackdex = body.userData['track_index']
-
- def to_screen(pos):
- px = self.world.meter_to_screen(
- pos[0])
- py = self.world.meter_to_screen(
- pos[1])
- py = self.world.renderer.get_surface() \
- .get_height() - py
- return (px, py)
-
- x = body.position.x
- y = body.position.y
- tupled_pos = to_screen((x, y))
- posx = tupled_pos[0]
- posy = tupled_pos[1]
- try:
- self.full_pos_list[trackdex].append(posx)
- self.full_pos_list[trackdex].append(posy)
- except IndexError:
- self.full_pos_list.append([posx, posy])
-
if body.userData.has_key('rollMotor'):
diff = body.userData['rollMotor'] \
['targetVelocity'] \
diff --git a/tools.py b/tools.py
index af515b8..190b558 100644
--- a/tools.py
+++ b/tools.py
@@ -87,15 +87,17 @@ class Tool(object):
# Default drawing method is draw the pen points.
full_pos_list = self.game.full_pos_list
surface = self.game.world.renderer.get_surface()
- for i, pos_list in enumerate(full_pos_list):
- if len(self.game.body_colors) > i:
- color = self.game.body_colors[i]
- else:
- color = 0
- for i in range(0, len(pos_list), 2):
- posx = int(pos_list[i])
- posy = int(pos_list[i+1])
- pygame.draw.circle(surface, color, (posx, posy), 2)
+ for key, info in self.game.trackinfo.iteritems():
+ color = info[2]
+ trackdex = info[4]
+ try:
+ pos_list = self.game.full_pos_list[trackdex]
+ for i in range(0, len(pos_list), 2):
+ posx = int(pos_list[i])
+ posy = int(pos_list[i+1])
+ pygame.draw.circle(surface, color, (posx, posy), 2)
+ except IndexError:
+ pass
def cancel(self):
# Default cancel doesn't do anything
@@ -597,11 +599,22 @@ class DestroyTool(Tool):
tokill = self.game.world.get_bodies_at_pos(tuple_to_int(event.pos))
if tokill:
+ tracklist = self.game.trackinfo.items()
+ destroyed_body = False
+ for key, info in tracklist:
+ trackdex = info[4]
+ if trackdex in tokill[0].userData['track_indices'] and \
+ info[3] is False:
+ self.game.world.world.DestroyBody(info[1])
+ self.game.trackinfo[key][3] = True
+ destroyed_body = True
+ break
+
jointnode = tokill[0].GetJointList()
- if jointnode:
+ if jointnode and not destroyed_body:
joint = jointnode.joint
self.game.world.world.DestroyJoint(joint)
- else:
+ elif not destroyed_body:
self.game.world.world.DestroyBody(tokill[0])
elif event.type == MOUSEBUTTONUP and event.button == 1:
self.cancel()
@@ -690,13 +703,24 @@ class TrackTool(Tool):
track_circle = self.game.world.add.ball(
point_pos, self.radius, dynamic=True, density=0.001,
restitution=0.16, friction=0.1)
- track_circle.userData['track_index'] = \
- len(self.game.tracked_bodies)
-
+ trackdex = self.game.tracked_bodies
+ track_circle.userData['track_index'] = trackdex
+ dictkey = "pen{0}".format(trackdex)
self.game.world.add.joint(
track_circle, current_body, point_pos, point_pos, False)
- self.game.tracked_bodies.append(track_circle)
- self.game.body_colors.append(color)
+
+ if 'track_indices' in current_body.userData:
+ current_body.userData['track_indices'].append(trackdex)
+ else:
+ current_body.userData['track_indices'] = [trackdex]
+
+ self.game.trackinfo[dictkey] = [0, 1, 2, 4, 5]
+ self.game.trackinfo[dictkey][0] = current_body
+ self.game.trackinfo[dictkey][1] = track_circle
+ self.game.trackinfo[dictkey][2] = color
+ self.game.trackinfo[dictkey][3] = False # Pen destroyed or not.
+ self.game.trackinfo[dictkey][4] = trackdex # Tracking index.
+ self.game.tracked_bodies += 1 # counter of tracked bodies.
def getAllTools():