diff options
Diffstat (limited to 'atoidejouerbeta/story/keys.py')
-rw-r--r-- | atoidejouerbeta/story/keys.py | 692 |
1 files changed, 692 insertions, 0 deletions
diff --git a/atoidejouerbeta/story/keys.py b/atoidejouerbeta/story/keys.py new file mode 100644 index 0000000..90f03bb --- /dev/null +++ b/atoidejouerbeta/story/keys.py @@ -0,0 +1,692 @@ + +# python import +import json, logging, os +# .. +from functools import partial +from gettext import gettext as _ + +# gtk import +import gobject, gtk, glib + +# sugar import +from sugar.activity import activity + +# atoidejouerbeta import +from atoidejouerbeta.tools import image, sound, storage, ui + +# get application logger +logger = logging.getLogger('atoidejouerbeta') + + +class StoryKeys(object): + + def __init__(self, type_, activity_): + # keep type + self._type = type_ + # .. + self._activity = activity_ + # .. + self.clear() + + def clear(self): + # .. + self._names = list() + self.__codes = { + 'graphics': dict(), + 'sounds': dict(), + 'story': dict(), + } + self.__clear = { + 'graphics': False, + 'sounds': False, + 'story': False, + } + # + self._keys = dict() + + def loads(self, data, clear=True): + # parse json data + _data_dict = json.loads(data) + # .. + if self._type == 'graphics': + # .. + _tmp_names = _data_dict['graphic_names'] + _tmp_keys = _data_dict['graphic_keys'] + # .. + elif self._type == 'sounds': + # .. + _tmp_names = _data_dict['sound_names'] + _tmp_keys = _data_dict['sound_keys'] + # ?? + else: + return + # reset keys + if clear is True: + self.clear() + else: + pass + # set names + _exist_list = list() + for _n in _tmp_names: + if _n in self._names: + _exist_list.append(_n) + else: + self._names.append(_n) + # ensure keys + for _seq_name, _seq_dict in _tmp_keys.items(): + # get seq_path for check + _seq_path = storage.get_sequence_path(self._type, _seq_name) + # little check + if _seq_name in self._keys: + continue + # check path + elif os.path.exists(_seq_path): + # init seq dict copy + _tmp_seq_dict = dict() + # work on seq dict copy + for _frame_name, _frame_dict in _seq_dict.items(): + # seq dict copy update + _tmp_seq_dict[float(_frame_name)] = _frame_dict + # update main dict + self._keys[_seq_name] = _tmp_seq_dict + # sequence does not exist + else: + if _seq_name in self._names: + self._names.remove(_seq_name) + else: + pass + # .. + return _exist_list + + def add_sequence(self, sequence_name, filenames): + # TODO ensure valid name + if sequence_name in self._names: + return False + else: + # add name to the registry + self._names.append(sequence_name) + # init seq dict + _seq_dict = dict() + # update dict + for _i, _f in enumerate(filenames): + _seq_dict[_f] = { + '__align': [0, 0], + '__duration': 0, + '__loop': False, + '__file_type': None, + '__key_type': None + } + # udpate main dict + self._keys[sequence_name] = { + 0: _seq_dict + } + # ok + return True + + def remove_sequence(self, sequence_name): + # little check + if sequence_name in self._names: + self._names.remove(sequence_name) + del self._keys[sequence_name] + # ?? + else: + pass + + def ask_clear(self): + # ... + self.__clear = { + 'graphics': True, + 'sounds': True, + 'story': True, + } + + def get_clear(self, screen): + return self.__clear[screen] + + def set_clear(self, screen, flag): + self.__clear[screen] = flag + + def set_layout(self, sequence_name, layout): + # little check + if sequence_name in self._names: + _current = self._names.index(sequence_name) + # little check + if _current == layout: + # do nothing + pass + else: + # ... + self._names.remove(sequence_name) + # ... + self._names.insert(layout, sequence_name) + # nothing to do + else: + pass + + def get_layout(self, sequence_name): + if sequence_name in self._names: + return self._names.index(sequence_name) + else: + return -1 + + def get_max_layout(self): + return len(self._names) - 1 + + def set_code(self, screen, sequence_name, filename, _code): + # .. + if sequence_name in self.__codes[screen]: + pass + else: + self.__codes[screen][sequence_name] = dict() + # .. + self.__codes[screen][sequence_name][filename] = _code + + def get_code(self, screen, sequence_name, filename): + # .. + if sequence_name in self.__codes[screen]: + # .. + if filename in self.__codes[screen][sequence_name]: + return self.__codes[screen][sequence_name][filename] + # ?? + else: + return None + # ?? + else: + return None + + def get_sequence_codes(self, screen, sequence_name): + # .. + if sequence_name in self.__codes[screen]: + return self.__codes[screen][sequence_name] + else: + return dict() + + def get_names(self, mask=False): + # .. add mask + if mask is True: + yield 'background_default' + else: + pass + for _n in self._names: + yield _n + # .. add mask + if mask is True: + yield 'mask_default' + else: + pass + + def get_frame_dict(self, sequence_name, frame): + # little check + if sequence_name in self._names: + # .. + _seq_dict = self._keys[sequence_name] + # little check + if frame in _seq_dict: + # get frame dict + return _seq_dict[frame] + else: + return None + else: + return None + + def set_frame(self, sequence_name, previous_frame, new_frame): + # little check + if sequence_name in self._names: + # .. + _seq_dict = self._keys[sequence_name] + # little check + if previous_frame in _seq_dict: + # set frame dict from previous + _seq_dict[new_frame] = _seq_dict[previous_frame] + # clear main dict + del _seq_dict[previous_frame] + else: + pass + else: + pass + + def get_max_frame(self): + # ... + _tmp_set = set() + # ... + for _seq_dict in self._keys.values(): + # udpate set + _tmp_set = _tmp_set.union(_seq_dict.keys()) + # order list + _tmp_list = list(_tmp_set) + _tmp_list.sort() + # return max + if len(_tmp_list) == 0: + return 0 + else: + return _tmp_list[-1] + + def set_filename_dict(self, sequence_name, frame, filename, dict_=None): + # ensure default dict + if dict_ is None: + dict_ = { + '__align': [0, 0], + '__duration': 0, + '__loop': False, + '__file_type': None, + '__key_type': None + } + else: + pass + # ensure frame dict + _frame_dict = self.get_frame_dict(sequence_name, frame) + if _frame_dict is None: + self._keys[sequence_name][frame] = dict() + else: + pass + # update the main dict + self._keys[sequence_name][frame][filename] = dict_ + + def get_filename_dict(self, sequence_name, frame, filename): + # little check + if sequence_name in self._names: + # .. + _seq_dict = self._keys[sequence_name] + # little check + if frame in _seq_dict: + # get frame dict + _frame_dict = _seq_dict[frame] + # little check + if filename in _frame_dict: + # return filename dict + return _frame_dict[filename] + else: + return None + else: + return None + else: + return None + + def remove_filename(self, sequence_name, frame, filename): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return + # do remove + else: + del self._keys[sequence_name][frame][filename] + + def remove_filename_from_all(self, sequence_name, filename): + # little check + if sequence_name in self._names: + for _frame in range(self.get_max_frame()): + self.remove_filename(sequence_name, _frame, filename) + # .. + else: + pass + + def set_align(self, sequence_name, frame, filename, align): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return + else: + self._keys[sequence_name][frame][filename]['__align'] = align + + def get_previous_align(self, sequence_name, frame): + # prepare inversed range + _range = range(frame) + _range.reverse() + # try one by one + for _f in _range: + # get frame dict + _frame_dict = self.get_frame_dict(sequence_name, _f) + # get frame values + _frame_values = [] if _frame_dict is None else _frame_dict.values() + # find first valid key + for _f_dict in _frame_values: + # little check + if _f_dict['__key_type'] != 'key': + continue + elif '__align' in _f_dict: + return _f_dict['__align'] + else: + return [0, 0] + # default + return [0, 0] + + def get_align(self, sequence_name, frame, filename): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return [0, 0] + else: + # ensure default + if '__align' in _f_dict: + return _f_dict['__align'] + else: + # set default + _f_dict['__align'] = [0, 0] + # return default + return [0, 0] + + def get_next_align(self, sequence_name, frame, filename, + use_transition=False): + # prepare inversed range + _range = range(frame + 1, self.get_max_frame() + 1) + # try one by one + for _f in _range: + # get frame dict + _frame_dict = self.get_frame_dict(sequence_name, _f) + # get frame values + _frame_values = [] if _frame_dict is None else _frame_dict.values() + if _frame_dict is None: + continue + else: + # find first valid key + for _f_name, _f_dict in _frame_dict.items(): + # little check + if use_transition is False\ + and _f_dict['__key_type'] != 'key': + continue + elif '__align' in _f_dict\ + and _f_dict['__key_type'] in ['key', 'transition']: + # works on the same file only + if _f_name == filename: + return _f_dict['__align'] + else: + return None, None + else: + continue + # default + return None, None + + def inc_position(self, sequence_name, frame, filename, move, value): + # get align first + _x, _y = self.get_align(sequence_name, frame, filename) + # inc + if move == 'x': + _x += value + elif move == 'y': + _y += value + else: + # ?? + return + # update + self.set_align(sequence_name, frame, filename, (_x, _y)) + # return current pos + return _x, _y + + def set_duration(self, sequence_name, frame, filename, duration): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return + else: + self._keys[sequence_name][frame][filename]['__duration'] = duration + + def get_duration(self, sequence_name, frame, filename): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return 0 + else: + # ensure default + if '__duration' in _f_dict: + return _f_dict['__duration'] + else: + # set default + _f_dict['__duration'] = 0 + # return default + return 0 + + def inc_duration(self, sequence_name, frame, filename, value): + # get duration first + _d = self.get_duration(sequence_name, frame, filename) + # inc + _d += value + # TODO max is max_ or next key + # get max frame + _max_frame = self._activity._number_of_keys - frame + # ensure value + if _d < 0: + _d = 0 + elif _d >= _max_frame: + _d = _max_frame - 1 + else: + pass + # update + self.set_duration(sequence_name, frame, filename, _d) + # return current pos + return _d + + def set_loop(self, sequence_name, frame, filename, loop): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return + else: + self._keys[sequence_name][frame][filename]['__loop'] = loop + + def get_loop(self, sequence_name, frame, filename): + # .. get the dict + _f_dict = self.get_filename_dict(sequence_name, frame, filename) + # little check + if _f_dict is None: + return False + # ensure default + else: + if '__loop' in _f_dict: + return _f_dict['__loop'] + else: + # set default + _f_dict['__loop'] = False + # return default + return False + + def set_current(self, sequence_name, frame, filename, file_type='lib', + key_type='key'): + """ + file_type lib or jnl + key_type key or transition + """ + # get the dict + _filename_dict = self.get_filename_dict(sequence_name, frame, filename) + # ensure filename dict + if _filename_dict is None: + self.set_filename_dict(sequence_name, frame, filename) + else: + pass + # get the dict + _frame_dict = self.get_frame_dict(sequence_name, frame) + # little check + if _frame_dict is None: + pass + else: + # set current + for _f, _d in _frame_dict.items(): + # key type or none + _ft = key_type if _f == filename else None + # update + self._keys[sequence_name][frame][_f]['__file_type'] = _ft + # key type or none + _kt = key_type if _f == filename else None + # update + self._keys[sequence_name][frame][_f]['__key_type'] = _kt + + def get_current(self, sequence_name, frame): + # get the dict + _f_dict = self.get_frame_dict(sequence_name, frame) + # little check + if _f_dict is None: + return None, None, None + else: + for _f, _d in _f_dict.items(): + if _d['__key_type'] is None: + continue + else: + return _f, _d['__file_type'], _d['__key_type'] + # default + return None, None, None + + def _refresh_graphic_keys(self, sequence_name): + # little check + if sequence_name in self._keys: + # next dict for transition check + _next_list = list() + _range = list() + _filenames = list() + # update next dict + for _frame, _filename_dict in self._keys[sequence_name].items(): + for _filename, _dict in _filename_dict.items(): + if _filename is None or _dict['__key_type'] != 'key': + # invalidate previous + self._keys[sequence_name][_frame][_filename] = { + '__align': [0, 0], + '__duration': 0, + '__loop': False, + '__file_type': None, + '__key_type': None + } + else: + # small update for transition management + _tr_frame = (_frame + 1) if len(_range) == 0 else _frame + # update current range + _range.append(_tr_frame) + _filenames.append((_filename, _dict['__file_type'])) + # .. + if len(_range) == 2: + _next_list.append((_range, _filenames)) + _range = list() + _filenames = list() + else: + continue + # set transition + for _range, _filenames in _next_list: + # get first align + _first_filename, _first_filetype = _filenames[0] + _first_x, _first_y = self.get_align(sequence_name, _range[0]-1, + _first_filename) + # get last align + _last_filename, _last_filetype = _filenames[1] + _last_x, _last_y = self.get_align(sequence_name, _range[1], + _last_filename) + # compute steps + _inc_x = float(_last_x - _first_x) + _inc_x /= (_range[1] - _range[0] + 1) + _inc_y = float(_last_y - _first_y) + _inc_y /= (_range[1] - _range[0] + 1) + # init new position values + _new_x = _first_x + _new_y = _first_y + for _i in range(*_range): + # compute filename and file type + if _i < ((_range[1] - _range[0]) / 2): + _f = _first_filename + _t = _first_filetype + else: + #_f = _last_filename + #_t = _last_filetype + _f = _first_filename + _t = _first_filename + # set transition + self.set_current(sequence_name, _i, _f, file_type=_t, + key_type='transition') + # compute align + _new_x += _inc_x + _new_y += _inc_y + # update align + self.set_align(sequence_name, _i, _f, (_new_x, _new_y)) + else: + pass + + def _refresh_sound_keys(self, sequence_name): + # shortcut + _max = self._activity._number_of_keys + # little check + if sequence_name in self._keys: + # next dict for transition check + _durations = list() + _loops = list() + # update next dict + for _frame, _filename_dict in self._keys[sequence_name].items(): + for _filename, _dict in _filename_dict.items(): + if _filename is None or _dict['__key_type'] != 'key': + # invalidate previous + self._keys[sequence_name][_frame][_filename] = { + '__align': [0, 0], + '__duration': 0, + '__loop': False, + '__file_type': None, + '__key_type': None + } + else: + if _dict['__loop'] is True: + _loops.append((_frame, _filename, _dict['__file_type'])) + elif _dict['__duration'] != None: + _durations.append((_frame, _filename, + _dict['__file_type'], _dict['__duration'])) + else: + continue + # set transition for loop keys + for _frame, _f, _f_type in _loops: + # little check + _t_start = _frame + 1 + # .. + if _t_start >= _max: + continue + else: + pass + # .. + for _i in range(_t_start, _max+1): + # set transition + self.set_current(sequence_name, _i, _f, + file_type=_f_type, key_type='transition') + # set transition for loop keys + for _frame, _f, _f_type, _d in _durations: + # little check + _t_start = _frame + 1 + _t_end = _t_start + _d + # .. + if _t_start >= _max: + continue + elif _t_end > _max: + _t_end = _max+1 + else: + pass + # .. + if _t_start > _t_end: + continue + else: + pass + # .. + for _i in range(_t_start, _t_end): + _f_dict = self.get_filename_dict(sequence_name, _i, _f) + # update + _kt = None if _f_dict is None else _f_dict['__key_type'] + # .. + if _kt is None: + # set transition + self.set_current(sequence_name, _i, _f, + file_type=_f_type, key_type='transition') + + def check_sequences(self): + # sequence check + _s_to_remove = list() + for _s_name in self._names: + _path = storage.get_sequence_path(self._type, _s_name) + if os.path.exists(_path): + continue + else: + _s_to_remove.append(_s_name) + # .. + for _s_name in _s_to_remove: + self.remove_sequence(_s_name) + + def refresh(self, sequence_name): + # .. + if self._type == 'graphics': + self._refresh_graphic_keys(sequence_name) + else: + self._refresh_sound_keys(sequence_name) |