From 1f8b84304e8978ada495be019eac50768bf49da5 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Fri, 24 May 2013 15:03:30 +0000 Subject: changes in support of rotation --- 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 . +# 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 . + +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(_('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 -- cgit v0.9.1