diff options
Diffstat (limited to 'atoidejouer/ui/screen/story.py')
-rw-r--r-- | atoidejouer/ui/screen/story.py | 412 |
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 |