diff --git a/examples/scene/scene.py b/examples/scene/scene.py index f404f6f4..733b2b43 100755 --- a/examples/scene/scene.py +++ b/examples/scene/scene.py @@ -1,4 +1,5 @@ #!/usr/bin/python +import math import pygtk pygtk.require('2.0') @@ -8,10 +9,24 @@ from sugar.scene.Stage import Stage from sugar.scene.Group import Group from sugar.scene.PixbufActor import PixbufActor from sugar.scene.CircleLayout import CircleLayout +from sugar.scene.Timeline import Timeline -def drawing_area_expose_cb(widget, event, stage): +def __drawing_area_expose_cb(widget, event, stage): stage.render(widget.window) +def __next_frame_cb(timeline, frame_num, group): + angle = math.pi * 2 / timeline.get_n_frames() * frame_num + group.get_layout().set_angle(angle) + group.do_layout() + + drawing_area.window.invalidate_rect(None, False) + +def __completed_cb(timeline, group): + group.get_layout().set_angle(0) + group.do_layout() + + drawing_area.window.invalidate_rect(None, False) + stage = Stage() pixbuf = gtk.gdk.pixbuf_new_from_file('background.png') @@ -26,7 +41,7 @@ while i <= 5: i += 1 layout = CircleLayout(100) -icons_group.set_layout_manager(layout) +icons_group.set_layout(layout) stage.add(icons_group) @@ -34,10 +49,15 @@ window = gtk.Window() window.set_default_size(640, 480) drawing_area = gtk.DrawingArea() -drawing_area.connect('expose_event', drawing_area_expose_cb, stage) +drawing_area.connect('expose_event', __drawing_area_expose_cb, stage) window.add(drawing_area) drawing_area.show() window.show() +timeline = Timeline(stage, 100) +timeline.connect('next-frame', __next_frame_cb, icons_group) +timeline.connect('completed', __completed_cb, icons_group) +timeline.start() + gtk.main() diff --git a/sugar/scene/CircleLayout.py b/sugar/scene/CircleLayout.py index eb36ee4f..706713e2 100644 --- a/sugar/scene/CircleLayout.py +++ b/sugar/scene/CircleLayout.py @@ -7,13 +7,17 @@ class CircleLayout(LayoutManager): LayoutManager.__init__(self) self._radium = radium + self._angle = 0 + + def set_angle(self, angle): + self._angle = angle def layout_group(self, group): step = 2 * math.pi / len(group.get_actors()) - angle = 2 * math.pi + angle = self._angle for actor in group.get_actors(): self._update_position(actor, angle) - angle -= step + angle += step def _update_position(self, actor, angle): x = math.cos(angle) * self._radium + self._radium diff --git a/sugar/scene/Group.py b/sugar/scene/Group.py index 1485d11c..8a2a5623 100644 --- a/sugar/scene/Group.py +++ b/sugar/scene/Group.py @@ -3,24 +3,29 @@ from sugar.scene.Actor import Actor class Group(Actor): def __init__(self): self._actors = [] - self._layout_manager = None + self._layout = None def add(self, actor): self._actors.append(actor) - if self._layout_manager: - self._layout_manager.layout_group(slef) + self.do_layout() def remove(self, actor): self._actors.remove(actor) - if self._layout_manager: - self._layout_manager.layout_group(self) + self.do_layout() def get_actors(self): return self._actors - def set_layout_manager(self, layout_manager): - self._layout_manager = layout_manager - self._layout_manager.layout_group(self) + def set_layout(self, layout): + self._layout = layout + self.do_layout() + + def get_layout(self): + return self._layout + + def do_layout(self): + if self._layout: + self._layout.layout_group(self) def render(self, drawable): for actor in self._actors: diff --git a/sugar/scene/Stage.py b/sugar/scene/Stage.py index f314db9c..1707f845 100644 --- a/sugar/scene/Stage.py +++ b/sugar/scene/Stage.py @@ -3,3 +3,7 @@ from sugar.scene.Group import Group class Stage(Group): def __init__(self): Group.__init__(self) + self._fps = 50 + + def get_fps(self): + return self._fps diff --git a/sugar/scene/Timeline.py b/sugar/scene/Timeline.py new file mode 100644 index 00000000..5f1ac5f8 --- /dev/null +++ b/sugar/scene/Timeline.py @@ -0,0 +1,33 @@ +import gobject + +class Timeline(gobject.GObject): + __gsignals__ = { + 'next-frame': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([int])), + 'completed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) + } + + def __init__(self, stage, n_frames): + gobject.GObject.__init__(self) + + self._stage = stage + self._fps = stage.get_fps() + self._n_frames = n_frames + self._current_frame = 0 + + def start(self): + gobject.timeout_add(1000 / self._fps, self.__timeout_cb) + + def get_n_frames(self): + return self._n_frames + + def __timeout_cb(self): + self.emit('next-frame', self._current_frame) + + # FIXME skip frames if necessary + self._current_frame += 1 + + if self._current_frame < self._n_frames: + return True + else: + self.emit('completed') + return False