Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/atoidejouer/ui/screen/story.py
diff options
context:
space:
mode:
Diffstat (limited to 'atoidejouer/ui/screen/story.py')
-rw-r--r--atoidejouer/ui/screen/story.py412
1 files changed, 412 insertions, 0 deletions
diff --git a/atoidejouer/ui/screen/story.py b/atoidejouer/ui/screen/story.py
new file mode 100644
index 0000000..ef53f60
--- /dev/null
+++ b/atoidejouer/ui/screen/story.py
@@ -0,0 +1,412 @@
+# python import
+import logging
+# ..
+from gettext import gettext as _
+
+# gtk import
+import gtk
+
+# graphics import
+from lib import graphics
+
+# atoidejouer import
+from atoidejouer.db import story
+from atoidejouer.tools import config, image, sound, storage
+
+# get application logger
+logger = logging.getLogger('atoidejouer')
+
+
+def _on_drag_finish(image, event, scene, key, image_size):
+ # get align values
+ key.x, key.y = scene._reverse_x_y(image_size, (image.x, image.y))
+ # do update
+ rowcount = story.DB().update(key)
+ # DEBUG
+ # logger.debug('[ui.screen.story] _on_drag_finish - key: %s' % key)
+ # logger.debug('[ui.screen.story] _on_drag_finish - rowcount: %s' % rowcount)
+ # DEBUG
+ # refresh
+ scene.toolbar.activity.get_current_screen().refresh(key=key)
+
+
+def _on_click(image, event, scene, key):
+ # remove image on right click
+ if event.button == 3:
+ story.DB()._del(key)
+ # invalidate key
+ key = None
+ # refresh
+ scene.toolbar.activity.get_current_screen().refresh(key=key)
+
+
+class ScreenStory(graphics.Scene):
+
+ def __init__(self, toolbar, height_offset=0, width_offset=0,
+ set_canvas=False, clear=False):
+ # ..
+ graphics.Scene.__init__(self)
+ self.background_color = "#ffffff"
+ # keep toolbar
+ self.toolbar = toolbar
+ # ..
+ self._set_canvas = set_canvas
+ self._clear = False
+ # init image dicts
+ self.__sizes = dict()
+ self.__graphics = dict()
+ self.__sounds = dict()
+ self.__dd_signals = dict()
+ # init fullscreen flag
+ self.fullscreen = False
+ self._fullscreen_changed = True
+ # screen size first
+ self._height_offset = height_offset
+ self._width_offset = width_offset
+ # ..
+ self._screen_height = None
+ self._screen_width = None
+ # ...
+ self._refresh_screen_size()
+ # and show
+ self._show()
+
+ def set_fullscreen(self, fullscreen):
+ # update fullscreen flag
+ self.fullscreen = fullscreen
+ # has changed
+ self._fullscreen_changed = True
+ # refresh
+ self.refresh()
+
+ def _refresh_screen_size(self):
+ # keep some info
+ self._screen_height = gtk.gdk.screen_height() - self._height_offset
+ self._screen_width = gtk.gdk.screen_width() - self._width_offset
+
+ def set_clear(self, clear):
+ self._clear = clear
+
+ def _check_clear(self):
+ # need clear
+ if self._clear is True:
+ # hide previous
+ for _image in self.__graphics.values():
+ _image.visible = False
+ del _image
+ # ..
+ self.__graphics = dict()
+ # ..
+ self.__sizes = dict()
+ # done
+ self._clear = False
+ return True
+ else:
+ return False
+
+ def refresh(self, **kargs):
+ # clear?
+ self._check_clear()
+ # ensure valid screen size
+ self._refresh_screen_size()
+ # get the current frame
+ _time = 0.0 if self.toolbar.activity._thread is None\
+ else self.toolbar.activity._thread._time
+ # get the current rate
+ _rate = config.Config().get_rate_value()
+ # using DB
+ _currents = list()
+ for _k in story.DB().get(story.Key(mime_type='image/png', time=_time)):
+ self.__refresh_image(_k, _rate)
+ _currents.append(_k.id)
+ # draw mask
+ _currents.append(self.__refresh_default('mask'))
+ # hide previous
+ for _id, _image in self.__graphics.items():
+ if _id not in _currents:
+ _image.visible = False
+ self.queue_draw()
+ # show first
+ if self._fullscreen_changed is True:
+ # disable changed flag
+ self._fullscreen_changed = False
+ else:
+ pass
+ # refresh sounds if playing
+ if self.toolbar.activity._thread is None:
+ pass
+ elif self.toolbar.activity._thread._pause is False:
+ """
+ # for each sound
+ for _n in self._get_keys('sounds').get_names():
+ if sequence_name is None\
+ or sequence_name == _n:
+ # do move
+ self.__refresh_sound(_n, _time)
+ else:
+ # just get code
+ _currents.append(self._get_current_code('sounds', _n,
+ _time))
+ # using DB
+ for key in story.DB().get(story.Key(mime_type='audio/ogg', time=_time)):
+ self.__refresh_sound(key)
+ """
+ else:
+ # stop all
+ for _id, _sound in self.__sounds.items():
+ if self.toolbar.activity._thread._time == 0:
+ _sound.stop()
+ else:
+ _sound.pause()
+
+ def _update_w_h(self, key):
+ if key.id in self.__sizes:
+ pass
+ else:
+ # get file size
+ _c, _w, _h = image.get_image_info(key.get_path())
+ # ..
+ if (self.fullscreen is True\
+ or self._screen_width < 1024)\
+ and _w != 0:
+ _new_w = _w * self._screen_width / 1024
+ _new_h = _h * _new_w / _w
+ else:
+ _new_w = _w
+ _new_h = _h
+ # update size
+ self.__sizes[key.id] = _new_w, _new_h, _w, _h
+ # return new values
+ return self.__sizes[key.id]
+
+ def _reverse_x_y(self, size, position):
+ # ..
+ _w, _h = size
+ _x, _y = position
+ # ..
+ if self.fullscreen is True\
+ or self._screen_width < 1024:
+ _scene_with = self._screen_width
+ _scene_height = 516 * _scene_with / 1024.0
+ else:
+ _scene_with = 1024
+ _scene_height = 516
+ # update x
+ _a_x = _x - (self._screen_width - _w) / 2
+ _a_x = int(_a_x * 100.0 / _scene_with)
+ # update y
+ _a_y = _y - (self._screen_height - _h - 88) / 2
+ _a_y = int(_a_y * 100.0 / _scene_height)
+ # return it
+ return _a_x, _a_y
+
+ def _update_x_y(self, size, align):
+ _new_w, _new_h, _w, _h = size
+ _x, _y = align
+ if self.fullscreen is True\
+ or self._screen_width < 1024:
+ _scene_with = self._screen_width
+ _scene_height = 516 * _scene_with / 1024.0
+ else:
+ _scene_with = 1024
+ _scene_height = 516
+ # update x
+ _new_x = ((self._screen_width - _new_w) / 2)
+ _new_x += int(_x * _scene_with / 100.0)
+ # update y
+ _new_y = ((self._screen_height - _new_h - 88) / 2)
+ _new_y += int(_y * _scene_height / 100.0)
+ # return it
+ return _new_x, _new_y
+
+ def __get_scene_size(self):
+ #
+ if self.fullscreen is True\
+ or self._screen_width < 1024:
+ _scene_with = self._screen_width
+ _scene_height = 516 * _scene_with / 1024.0
+ else:
+ _scene_with = 1024
+ _scene_height = 516
+ # ..
+ return _scene_with, _scene_height
+
+ def __refresh_default(self, default_name):
+ _code = '__%s' % default_name
+ # ensure current image
+ if _code in self.__graphics:
+ # ..
+ self.__graphics[_code].visible = True
+ else:
+ _filename = '%s_default' % default_name
+ _path = storage.get_image_path(_filename)
+ _key = story.Key(id=_code, path=_path, layer=0)
+ # ..
+ _align = (0, 0)
+ # get/update width and height
+ _size = self._update_w_h(_key)
+ # ..
+ self.__graphics[_key.id] =\
+ self.__update_drawing_area(_key, _size, _align)
+ # and return displayed code
+ return _code
+
+ def __get_transition_align(self, key, rate):
+ # get align
+ _x, _y = key.x, key.y
+ # get the current frame
+ _time = 0.0 if self.toolbar.activity._thread is None\
+ else self.toolbar.activity._thread._time
+ # get transition ratio
+ _ratio = _time - int(_time)
+ if _ratio < rate:
+ return _x, _y
+ else:
+ _next_key = story.Key(title=key.title, mime_type="image/png",
+ time=(key.time+1), layer=key.layer)
+ _next_key = story.DB().get(_next_key)
+ _next_x, _next_y = _next_key.x, _next_key.y
+ _next_x = _x if _next_x is None else _x + (_next_x - _x) * _ratio
+ _next_y = _y if _next_y is None else _y + (_next_y - _y) * _ratio
+ return _next_x, _next_y
+
+ def __refresh_image(self, key, rate):
+ # get/update width and height
+ _size = self._update_w_h(key)
+ # get align
+ _align = self.__get_transition_align(key, rate)
+ # ensure current image
+ if key.id in self.__graphics:
+ # DEBUG
+ # logger.debug('[ui.screen.story] __refresh_image - key: %s' % key)
+ # DEBUG
+ _image = self.__graphics[key.id]
+ # update x, y
+ _image.x, _image.y = self._update_x_y(_size, _align)
+ # get z_order
+ _image.z_order = key.layer
+ # scale
+ _new_w, _new_h, _w, _h = _size
+ # set visibility
+ _image.visible = True
+ # refresh signals
+ self.__update_image_signals(key, _image, (_new_w, _new_h))
+ else:
+ # draggable for edit only
+ _draggable = self._set_canvas is False\
+ and config.Config().use_dnd() is True
+ _image = self.__update_drawing_area(key, _size, _align,
+ draggable=_draggable)
+ self.__graphics[key.id] = _image
+
+ def __update_image_signals(self, key, image, size):
+ # remove existing handlers
+ if key.id in self.__dd_signals:
+ _h_id_drag, _h_id_click = self.__dd_signals[key.id]
+ image.disconnect(_h_id_drag)
+ image.disconnect(_h_id_click)
+ # connect
+ _h_id_drag = image.connect('on-drag-finish', _on_drag_finish, self,
+ key, size)
+ _h_id_click = image.connect('on-click', _on_click, self, key)
+ # update signal dict
+ self.__dd_signals[key.id] = (_h_id_drag, _h_id_click)
+
+ def __update_drawing_area(self, key, size, align, draggable=False):
+ # update x, y
+ _x, _y = self._update_x_y(size, align)
+ _new_w, _new_h, _w, _h = size
+ if _w is None or _w == 0:
+ _scale = 1
+ else:
+ _scale = float(_new_w)/_w
+ # DEBUG
+ # logger.debug('[ui.screen.story] __update_drawing_area - key: %s' % key)
+ # DEBUG
+ # image
+ _image = graphics.Image(key.get_path(), x=_x, y=_y, scale_x=_scale,
+ scale_y=_scale, z_order=key.layer, draggable=draggable)
+ # refresh signals
+ self.__update_image_signals(key, _image, (_new_w, _new_h))
+ # do add
+ self.add_child(_image)
+ return _image
+
+ """
+ def __stop_unused_sounds(self, key):
+ sounds = story.DB().get(story.Key(name=key.name, mime_type='audio/ogg'))
+ # hide previous
+ for _k in keys:
+ if _k.id != current\
+ and _k.id in self.__sounds:
+ self.__sounds[_k.id].pause()
+ else:
+ continue
+
+ def __refresh_sound(self, sequence_name, frame):
+ # get sequence file codes
+ _seq_codes = self._get_keys('sounds').get_sequence_codes(
+ self.toolbar.name, sequence_name)
+ # get sequence filename
+ _current, _f_type, _k_type = self._get_keys('sounds').get_current(
+ sequence_name, frame)
+ # need current
+ if _current is None:
+ return self.__stop_unused_sounds(_seq_codes, None)
+ else:
+ pass
+ # current file code
+ _code = _seq_codes[_current] if _current in _seq_codes else None
+ # ensure current image
+ if _code in self.__sounds:
+ _s = self.__sounds[_code]
+ if _k_type is None:
+ _s.pause()
+ elif _k_type == 'key':
+ # reset
+ _s.seek(0)
+ # play
+ _s.play()
+ else:
+ _s.seek(frame)
+ _s.play()
+ else:
+ # create new
+ if _k_type is None:
+ pass
+ else:
+ # ... TODO manage start time
+ _code, _sound = self._prepare_sound(sequence_name, _current)
+ _sound.play()
+ # ..
+ self.__stop_unused_sounds(_seq_codes, _code)
+
+ def _prepare_sound(self, sequence_name, current):
+ # get graphics path
+ _path = storage.get_sound_path(current)
+ # ensure/generate code
+ _filecode = key.random_str()
+ # update story key object
+ self._get_keys('sounds').set_code(self.toolbar.name, sequence_name,
+ current, _filecode)
+ # ...
+ _sound = sound.Player()
+ _sound.load(_path)
+ # update graphic dict
+ self.__sounds[_filecode] = _sound
+ # return image for futher use
+ return _filecode, _sound
+ """
+
+ def _show(self):
+ # first refresh
+ self.refresh()
+ # ..
+ self.show()
+ # update size request
+ self.set_size_request(self._screen_width, self._screen_height)
+ # update canvas
+ if self._set_canvas is True:
+ self.toolbar.activity.set_canvas(self)
+ else:
+ pass