Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activity.py197
-rw-r--r--physics.py71
-rw-r--r--sugargame/event.py5
3 files changed, 150 insertions, 123 deletions
diff --git a/activity.py b/activity.py
index 3a97890..f3d6b4b 100644
--- a/activity.py
+++ b/activity.py
@@ -1,42 +1,42 @@
-"""
- Physics, a 2D Physics Playground for Kids
- Copyright (C) 2008 Alex Levenson and Brian Jordan
+# Physics, a 2D Physics Playground for Kids
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+# Copyright (C) 2008 Alex Levenson and Brian Jordan
+# Copyright (C) 2012 Daniel Francis
+# Copyright (C) 2013 Sugar Labs
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-"""
-import tools
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import gtk
+from gettext import gettext as _
+import logging
+
+import pygame
import sugargame
import sugargame.canvas
-import pygame
+
+from sugar.activity import activity
+from sugar.activity.widgets import ActivityToolbarButton
+from sugar.activity.widgets import StopButton
from sugar.graphics.radiotoolbutton import RadioToolButton
from sugar.graphics.toolbutton import ToolButton
-from sugar.activity import activity
-from gettext import gettext as _
-import gtk
+from sugar.graphics.toolbarbox import ToolbarBox
+from sugar.graphics.toolbarbox import ToolbarButton
+from sugar.graphics.style import GRID_CELL_SIZE
+import tools
import physics
-try:
- # >= 0.86 toolbars
- from sugar.graphics.toolbarbox import ToolbarBox
- from sugar.activity.widgets import ActivityToolbarButton
- from sugar.activity.widgets import StopButton
-except ImportError:
- # <= 0.84 toolbars
- pass
-
class PhysicsActivity(activity.Activity):
def __init__(self, handle):
@@ -44,19 +44,29 @@ class PhysicsActivity(activity.Activity):
self.metadata['mime_type'] = 'application/x-physics-activity'
self.add_events(gtk.gdk.ALL_EVENTS_MASK |
gtk.gdk.VISIBILITY_NOTIFY_MASK)
+
self.connect('visibility-notify-event', self._focus_event)
self.connect('window-state-event', self._window_event)
- # Build the Pygame canvas.
+
self._canvas = sugargame.canvas.PygameCanvas(self)
self.game = physics.main(self)
self.build_toolbar()
- # Note that set_canvas implicitly calls read_file when resuming from the Journal.
self.set_canvas(self._canvas)
+ gtk.gdk.screen_get_default().connect('size-changed',
+ self.__configure_cb)
- # Start the game running.
self._canvas.run_pygame(self.game.run)
+ def __configure_cb(self, event):
+ ''' Screen size has changed '''
+ if self.game.opening_queue is not None:
+ self.write_file(self.game.opening_queue)
+ pygame.display.set_mode((gtk.gdk.screen_width(),
+ gtk.gdk.screen_height() - 2 * GRID_CELL_SIZE),
+ pygame.RESIZABLE)
+ self.game.run(True)
+
def read_file(self, file_path):
self.game.read_file(file_path)
@@ -64,8 +74,7 @@ class PhysicsActivity(activity.Activity):
self.game.write_file(file_path)
def get_preview(self):
- """Custom preview code to get image from pygame.
- """
+ """ Custom preview code to get image from pygame. """
surface = pygame.display.get_surface()
width, height = surface.get_width(), surface.get_height()
pixbuf = gtk.gdk.pixbuf_new_from_data(pygame.image.tostring(surface,
@@ -76,6 +85,7 @@ class PhysicsActivity(activity.Activity):
pixbuf = pixbuf.scale_simple(300, 225, gtk.gdk.INTERP_BILINEAR)
preview_data = []
+
def save_func(buf, data):
data.append(buf)
@@ -84,67 +94,59 @@ class PhysicsActivity(activity.Activity):
return preview_data
- # Setup the toolbar
def build_toolbar(self):
- try:
- # Use new >= 0.86 toolbar
- self.max_participants = 1
- toolbar_box = ToolbarBox()
- activity_button = ActivityToolbarButton(self)
- toolbar_box.toolbar.insert(activity_button, 0)
- activity_button.show()
-
- separator = gtk.SeparatorToolItem()
- toolbar_box.toolbar.insert(separator, -1)
- separator.show()
-
- self._insert_create_tools(toolbar_box.toolbar)
-
- separator = gtk.SeparatorToolItem()
- separator.props.draw = False
- separator.set_size_request(0, -1)
- separator.set_expand(True)
- toolbar_box.toolbar.insert(separator, -1)
- separator.show()
-
- stop_button = StopButton(self)
- toolbar_box.toolbar.insert(stop_button, -1)
- stop_button.show()
-
- self.set_toolbar_box(toolbar_box)
- toolbar_box.show()
- return toolbar_box
-
- except NameError:
- # Use old <= 0.84 toolbar design
- toolbox = activity.ActivityToolbox(self)
- activity_toolbar = toolbox.get_activity_toolbar()
- activity_toolbar.share.props.visible = False
-
- create_toolbar = gtk.Toolbar()
- self._insert_create_tools(create_toolbar)
-
- toolbox.add_toolbar(_("Create"), create_toolbar)
- create_toolbar.show()
- toolbox.set_current_toolbar(1)
-
- toolbox.show()
- self.set_toolbox(toolbox)
- return activity_toolbar
+ self.max_participants = 1
+ toolbar_box = ToolbarBox()
+ activity_button = ActivityToolbarButton(self)
+ toolbar_box.toolbar.insert(activity_button, 0)
+ activity_button.show()
- def _insert_create_tools(self, create_toolbar):
- # Stop/play button
+ create_toolbar = ToolbarButton()
+ create_toolbar.props.page = gtk.Toolbar()
+ create_toolbar.props.icon_name = 'magicpen'
+ create_toolbar.props.label = _('Create')
+ toolbar_box.toolbar.insert(create_toolbar, -1)
+ self._insert_create_tools(create_toolbar)
+
+ self._insert_stop_play_button(toolbar_box.toolbar)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(0, -1)
+ separator.set_expand(True)
+ toolbar_box.toolbar.insert(separator, -1)
+ separator.show()
+
+ stop = StopButton(self)
+ toolbar_box.toolbar.insert(stop, -1)
+ stop.show()
+
+ self.set_toolbar_box(toolbar_box)
+ toolbar_box.show_all()
+ create_toolbar.set_expanded(True)
+ return toolbar_box
+
+ def can_close(self):
+ self.preview = self.get_preview()
+ self.game.loop = False
+ return True
+
+ def _insert_stop_play_button(self, toolbar):
self.stop_play_state = True
self.stop_play = ToolButton('media-playback-stop')
self.stop_play.set_tooltip(_("Stop"))
self.stop_play.set_accelerator(_('<ctrl>space'))
self.stop_play.connect('clicked', self.stop_play_cb)
- create_toolbar.insert(self.stop_play, -1)
+ toolbar.insert(self.stop_play, -1)
self.stop_play.show()
- separator = gtk.SeparatorToolItem()
- create_toolbar.insert(separator, -1)
- separator.show()
+ def _insert_create_tools(self, create_toolbar):
+
+ def _insert_item(toolbar, item, pos=-1):
+ if hasattr(toolbar, 'insert'):
+ toolbar.insert(item, pos)
+ else:
+ toolbar.props.page.insert(item, pos)
# Make + add the component buttons
self.radioList = {}
@@ -157,17 +159,17 @@ class PhysicsActivity(activity.Activity):
button.set_group(None)
firstButton = button
button.set_tooltip(c.toolTip)
- button.set_accelerator(c.toolAccelerator)
+ # button.set_accelerator(c.toolAccelerator)
button.connect('clicked', self.radioClicked)
- create_toolbar.insert(button, -1)
+ _insert_item(create_toolbar, button, -1)
button.show()
self.radioList[button] = c.name
def stop_play_cb(self, button):
pygame.event.post(pygame.event.Event(pygame.USEREVENT,
- action="stop_start_toggle"))
+ action="stop_start_toggle"))
self.stop_play_state = not self.stop_play_state
- # Update button
+
if self.stop_play_state:
self.stop_play.set_icon('media-playback-stop')
self.stop_play.set_tooltip(_("Stop"))
@@ -180,19 +182,22 @@ class PhysicsActivity(activity.Activity):
action=self.radioList[button]))
def _focus_event(self, event, data=None):
- """Send focus events to pygame to allow it to idle when in background.
- """
+ """ Send focus events to pygame to allow it to idle when in
+ background. """
+ if not self.game.pygame_started:
+ logging.debug('focus_event: pygame not yet initialized')
+ return
if data.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:
pygame.event.post(pygame.event.Event(pygame.USEREVENT,
- action="focus_out"))
+ action="focus_out"))
else:
self.game.show_fake_cursor = True
pygame.event.post(pygame.event.Event(pygame.USEREVENT,
- action="focus_in"))
+ action="focus_in"))
def _window_event(self, window, event):
- """Send focus out event to pygame when switching to a desktop view.
- """
+ """ Send focus out event to pygame when switching to a desktop
+ view. """
if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
pygame.event.post(pygame.event.Event(pygame.USEREVENT,
- action="focus_out"))
+ action="focus_out"))
diff --git a/physics.py b/physics.py
index 5f80527..253ff1b 100644
--- a/physics.py
+++ b/physics.py
@@ -25,22 +25,29 @@ Code: git://git.sugarlabs.org/physics/mainline.git
"""
+import os
import sys
import math
+import gtk
+import logging
+
import pygame
from pygame.locals import *
from pygame.color import *
import sugargame
+
sys.path.append("lib/")
import pkg_resources
-# If your architecture is different, comment these lines and install the modules in your system.
+# If your architecture is different, comment these lines and install
+# the modules in your system.
sys.path.append("lib/Elements-0.13-py2.5.egg")
sys.path.append("lib/Box2D-2.0.2b1-py2.5-linux-i686.egg")
import Box2D as box2d
import elements
+
import tools
from helpers import *
-import gtk
+
class PhysicsGame:
def __init__(self, activity):
@@ -56,6 +63,8 @@ class PhysicsGame:
# Set up the world (instance of Elements)
self.box2d = box2d
self.opening_queue = None
+ self.loop = True
+ self.pygame_started = False
def switch_off_fake_pygame_cursor_cb(self, panel, event):
self.show_fake_cursor = False
@@ -72,34 +81,44 @@ class PhysicsGame:
#Loading from journal
self.opening_queue = path
- def run(self):
+ def run(self, restart=False):
self.screen = pygame.display.get_surface()
- pygame.display.init()
+ if not restart:
+ pygame.init()
+ pygame.display.init()
+ # pygame.mixer.quit()
+ self.pygame_started = True
+
+ # Fake a Sugar cursor for the pyGame canvas area
+ self.show_fake_cursor = True
+ pygame.mouse.set_cursor((8, 8), (0, 0), (0, 0, 0, 0, 0, 0, 0, 0),
+ (0, 0, 0, 0, 0, 0, 0, 0))
+ self.cursor_picture = pygame.image.load('standardcursor.png')
+ self.cursor_picture.convert_alpha()
+ self.canvas.connect("enter_notify_event",
+ self.switch_on_fake_pygame_cursor_cb)
+ self.canvas.connect("leave_notify_event",
+ self.switch_off_fake_pygame_cursor_cb)
+ self.canvas.add_events(gtk.gdk.ENTER_NOTIFY_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK)
+
self.world = elements.Elements(self.screen.get_size())
self.world.renderer.set_surface(self.screen)
-
- # Set up static environment
self.world.add.ground()
- # Fake a Sugar cursor for the pyGame canvas area
- self.show_fake_cursor = True
- pygame.mouse.set_cursor((8, 8), (0, 0), (0, 0, 0, 0, 0, 0, 0, 0),
- (0, 0, 0, 0, 0, 0, 0, 0))
- self.cursor_picture = pygame.image.load('standardcursor.png')
- self.cursor_picture.convert_alpha()
- self.canvas.connect("enter_notify_event",
- self.switch_on_fake_pygame_cursor_cb)
- self.canvas.connect("leave_notify_event",
- self.switch_off_fake_pygame_cursor_cb)
- self.canvas.add_events(gtk.gdk.ENTER_NOTIFY_MASK
- | gtk.gdk.LEAVE_NOTIFY_MASK)
-
- while True:
+ if self.opening_queue:
+ path = self.opening_queue.encode('ascii', 'convert')
+ if os.path.exists(path):
+ self.world.json_load(path)
+
+ while self.loop:
while gtk.events_pending():
gtk.main_iteration()
- if self.opening_queue:
- self.world.json_load(self.opening_queue)
+ if not self.loop:
+ pygame.quit()
+ self.pygame_started = False
+ break
for event in pygame.event.get():
self.currentTool.handleEvents(event)
@@ -114,11 +133,11 @@ class PhysicsGame:
if type(body.userData) == type({}):
if body.userData.has_key('rollMotor'):
diff = body.userData['rollMotor'] \
- ['targetVelocity'] \
- - body.GetAngularVelocity()
+ ['targetVelocity'] \
+ - body.GetAngularVelocity()
body.ApplyTorque(body.userData['rollMotor'] \
- ['strength'] * diff \
- * body.getMassData().I)
+ ['strength'] * diff \
+ * body.getMassData().I)
# Update & Draw World
self.world.update()
diff --git a/sugargame/event.py b/sugargame/event.py
index 4cc3be8..2ee2bed 100644
--- a/sugargame/event.py
+++ b/sugargame/event.py
@@ -101,7 +101,10 @@ class Translator(object):
def _quit_cb(self, data=None):
self.__stopped = True
- pygame.event.post(pygame.event.Event(pygame.QUIT))
+ try:
+ pygame.event.post(pygame.event.Event(pygame.QUIT))
+ except pygame.error, e:
+ logging.error('pygame already stopped? %s' % (e))
def _keydown_cb(self, widget, event):
key = event.keyval