Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activity.py31
-rw-r--r--icons/track.svg18
-rw-r--r--physics.py21
-rw-r--r--tools.py31
4 files changed, 99 insertions, 2 deletions
diff --git a/activity.py b/activity.py
index 9994dea..eef0e36 100644
--- a/activity.py
+++ b/activity.py
@@ -22,6 +22,8 @@ import os
import gtk
from gettext import gettext as _
import logging
+import csv
+import tempfile
import pygame
import sugargame
@@ -36,6 +38,7 @@ from sugar.graphics.alert import ConfirmationAlert
from sugar.graphics.toolbarbox import ToolbarBox
from sugar.graphics.toolbarbox import ToolbarButton
from sugar.graphics.style import GRID_CELL_SIZE
+from sugar.datastore import datastore
import tools
import physics
@@ -120,6 +123,12 @@ class PhysicsActivity(activity.Activity):
self._insert_stop_play_button(toolbar_box.toolbar)
+ export_csv = ToolButton("document-save")
+ export_csv.set_tooltip(_("Export tracked objects to journal"))
+ export_csv.connect('clicked', self._export_csv_cb)
+ toolbar_box.toolbar.insert(export_csv, -1)
+ export_csv.show()
+
separator = gtk.SeparatorToolItem()
toolbar_box.toolbar.insert(separator, -1)
separator.show()
@@ -203,8 +212,9 @@ class PhysicsActivity(activity.Activity):
def clear_all_cb(self, button):
clear_all_alert = ConfirmationAlert()
- clear_all_alert.props.title=_('Are You Sure?')
- clear_all_alert.props.msg = _('All you work will be discarded. This cannot be undone!')
+ clear_all_alert.props.title = _('Are You Sure?')
+ clear_all_alert.props.msg = \
+ _('All you work will be discarded. This cannot be undone!')
clear_all_alert.connect('response', self.clear_all_alert_cb)
self.add_alert(clear_all_alert)
@@ -216,6 +226,23 @@ class PhysicsActivity(activity.Activity):
else:
pass
+ def _export_csv_cb(self, button):
+ jobject = datastore.create()
+ jobject.metadata['title'] = _("Physics export")
+ jobject.metadata['mime_type'] = "text/csv"
+
+ tmp_dir = os.path.join(self.get_activity_root(), 'instance')
+ fd, file_path = tempfile.mkstemp(dir=tmp_dir)
+ os.close(fd)
+
+ data = self.game.full_pos_list
+ csvfile = open(file_path, "wb")
+ writer = csv.writer(csvfile)
+ writer.writerows(data)
+ jobject.set_file_path(os.path.abspath(csvfile.name))
+ csvfile.close()
+ datastore.write(jobject)
+
def radioClicked(self, button):
pygame.event.post(pygame.event.Event(pygame.USEREVENT,
action=self.radioList[button]))
diff --git a/icons/track.svg b/icons/track.svg
new file mode 100644
index 0000000..16b2afc
--- /dev/null
+++ b/icons/track.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="55px"
+ height="55px" viewBox="0 0 55 55" enable-background="new 0 0 55 55" xml:space="preserve">
+
+<g id="Freeform_Marquee" >
+ <path display="inline" fill="none" stroke="#FFFFFF" stroke-width="2.25" stroke-dasharray="6" d="M4.434,48
+ c0,0,3.453-38.583,19-41.833s28.334,18.5,28.334,18.5L34.434,33"/>
+ <g display="inline">
+ <path fill="#FFFFFF" d="M45.368,43.971l-5.382-5.383h3.642c0.458,0,0.918-0.174,1.267-0.524c0.701-0.7,0.7-1.836,0-2.535
+ c-0.351-0.351-0.811-0.525-1.267-0.526h-9.766l0.001,9.765c0,0.458,0.176,0.916,0.525,1.267c0.7,0.701,1.836,0.701,2.535,0
+ c0.351-0.35,0.524-0.809,0.524-1.267v-3.644l5.385,5.384c0.324,0.323,0.772,0.524,1.268,0.525
+ c0.99-0.001,1.793-0.804,1.793-1.794C45.894,44.742,45.691,44.296,45.368,43.971z"/>
+ </g>
+</g>
+
+</svg>
diff --git a/physics.py b/physics.py
index 253ff1b..64e4ae1 100644
--- a/physics.py
+++ b/physics.py
@@ -66,6 +66,9 @@ class PhysicsGame:
self.loop = True
self.pygame_started = False
+ self.full_pos_list = []
+ self.tracked_bodies = []
+
def switch_off_fake_pygame_cursor_cb(self, panel, event):
self.show_fake_cursor = False
@@ -131,6 +134,24 @@ class PhysicsGame:
if self.world.run_physics:
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 round_to_3(n):
+ return math.ceil(n * 1000) / 1000.0
+
+ roundx = round_to_3(body.position.x)
+ roundy = round_to_3(body.position.y)
+ tupled_pos = (roundx, roundy)
+ posx = tupled_pos[0]
+ posy = tupled_pos[1]
+ try:
+ self.full_pos_list[trackdex].append(posx)
+ self.full_pos_list[trackdex].append(posy)
+ except:
+ self.full_pos_list.append([posx, posy])
+
+ if type(body.userData) == type({}):
if body.userData.has_key('rollMotor'):
diff = body.userData['rollMotor'] \
['targetVelocity'] \
diff --git a/tools.py b/tools.py
index 62aba05..d1af693 100644
--- a/tools.py
+++ b/tools.py
@@ -595,6 +595,36 @@ class DestroyTool(Tool):
self.vertices = None
+# Track tool
+class TrackTool(Tool):
+ name = 'Track'
+ icon = 'track'
+ toolTip = _('Track Object')
+ toolAccelerator = _("<ctrl>r")
+
+ def __init__(self, game):
+ Tool.__init__(self, game)
+ self.radius = 1
+
+ def handleToolEvent(self, event):
+ Tool.handleToolEvent(self, event)
+
+ if pygame.mouse.get_pressed()[0]:
+ current_body = self.game.world.get_bodies_at_pos(
+ tuple_to_int(event.pos))[0]
+ if current_body:
+ point_pos = tuple_to_int(event.pos)
+ 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)
+
+ self.game.world.add.joint(
+ track_circle, current_body, point_pos, point_pos)
+ self.game.tracked_bodies.append(track_circle)
+
+
def getAllTools():
return [MagicPenTool,
CircleTool,
@@ -605,6 +635,7 @@ def getAllTools():
MotorTool,
PinTool,
JointTool,
+ TrackTool,
DestroyTool]
allTools = getAllTools()