diff options
author | Pootle 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) |
commit | a1388063aa061359fdc60ce575632de6b67de5e7 (patch) | |
tree | fb1907c7b93a13aecfd4ba5563d4343ac958772a | |
parent | b4c27004f4ed8d9ee5b13a005bb96f5f47790154 (diff) | |
parent | b6b17c0e7428e6e5a997f3e3e946659daa81b88a (diff) |
Merge branch 'master' of git.sugarlabs.org:physics/mainline
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | activity.py | 26 | ||||
-rwxr-xr-x | activity/activity.info | 2 | ||||
-rw-r--r-- | elements/elements.py | 37 | ||||
-rw-r--r-- | icons/clear-trace.svg | 32 | ||||
-rw-r--r-- | physics.py | 82 | ||||
-rw-r--r-- | tools.py | 56 |
7 files changed, 189 insertions, 50 deletions
@@ -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 @@ -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'] \ @@ -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(): |