class TilesEditor(ChildWindow): def __init__(self): super(TilesEditor, self).__init__() self.config = Config() self.setWindowTitle('Tiles Editor') self.setFixedSize(640, 480) self._tab_widget = QtGui.QTabWidget(self) self._tab_widget.setGeometry(0, 0, 640, 480) self.subscribe('menu.trigger.import_tileset', self.on_import_tileset) self.subscribe('picture.mousemove', self.on_picture_mouse_move) self.subscribe('new_project', self.on_new_file) self.subscribe('open_project', self.on_open_file) self._workspaces = [] def on_new_file(self, message): self._workspaces = [] self._tab_widget.clear() def on_open_file(self, message): self.current_file = self.config.current_file() for tileset in self.current_file.get('tilesets', []): workspace = TileSetWorkspace( self, self.current_file['pathes'][tileset], self._queue ) workspace.show() self._tab_widget.addTab(workspace, workspace.base_name()) self._workspaces.append(workspace) self.send('tileset_editor.new_tileset', { 'tileset': workspace.base_name() }) self.send('tileset.update', { 'tileset': workspace.base_name() }) workspace.read_tilesets_config() self.send('open_maps') def on_import_tileset(self, message): file_name = QtGui.QFileDialog.getOpenFileName( self, filter='Tilesets (*.png)', directory=self.config.get( 'tilesets_images_dir', os.path.expanduser('~') ) ) if file_name: self.config.set( 'tilesets_images_dir', os.path.dirname(str(file_name)) ) self.send('config.save') workspace = TileSetWorkspace( self, str(file_name), self._queue ) workspace.show() self._tab_widget.addTab(workspace, workspace.base_name()) self._workspaces.append(workspace) self.send('tileset_editor.new_tileset', { 'tileset': workspace.base_name() }) def on_picture_mouse_move(self, message): for workspace in self._workspaces: workspace.on_picture_mouse_move(message) def remove_current(self): self._workspaces.pop(self._tab_widget.currentIndex()) self._tab_widget.removeTab(self._tab_widget.currentIndex())
class MainWindow(QtGui.QMainWindow): resources_directories = ( 'fightenv', 'images', 'maps', 'sprites', 'tiles' ) queue = Queue.Queue() CHILDREN = ( TilesEditor, MapEditor, LayersDialog, SpritesEditor, FightEnvironmentEditor ) def __init__(self, resolution, title): super(MainWindow, self).__init__() self.config = Config() self.config.init_from_file(settings.CONFIG_FILE_PATH) self._timer = QtCore.QTimer(self) self.setWindowIcon(QtGui.QIcon(os.path.join( settings.IMAGES_PATH, 'mqme.png' ))) MainWindow._subscriptions = { 'config.save': self.on_save_config_request, 'menu.trigger.save_project': self.on_save_project_request, 'menu.trigger.new_project': self.on_new_project_request, 'menu.trigger.open_project': self.on_open_project_request, 'menu.trigger.export_to_resources': self.on_export_request } self.connect(self._timer, QtCore.SIGNAL("timeout()"), self.update) self.workspace = QtGui.QWorkspace() width, height = resolution self.resize(width, height) self.setWindowTitle(title) self.setCentralWidget(self.workspace) self.setMenuBar(MenuBar(self, self.on_menu_triggered)) self._children = [] for child_type in self.CHILDREN: child = child_type() self.workspace.addWindow(child) child.set_queue(MainWindow.queue) self._children.append(child) self._timer.start(settings.QUEUE_READ_LOOP_DELAY) def keyPressEvent(self, event): super(MainWindow, self).keyPressEvent(event) self.send('key_press', {'key': event.key()}) def keyReleaseEvent(self, event): super(MainWindow, self).keyReleaseEvent(event) self.send('key_release', {'key': event.key()}) def send(self, name, body=None): message = {'name': name} if body is not None: message.update(body) MainWindow.queue.put(message) @staticmethod def subscribe(message_name, callback): MainWindow._subscriptions[message_name] = callback def receive(self, message): name = message.get('name') if name in MainWindow._subscriptions: MainWindow._subscriptions[name](message) def on_menu_triggered(self, menu_name): self.send('menu.trigger.%s' % menu_name) def update(self): try: index = 0 while index < settings.QUEUE_READ_LOOP_DELAY: message = MainWindow.queue.get_nowait() self.receive(message) for child in self._children: child.receive(message) index += 1 except Queue.Empty: pass def on_save_config_request(self, message): self.config.save(settings.CONFIG_FILE_PATH) def on_save_project_request(self, message): file_name = QtGui.QFileDialog.getSaveFileName( self, filter='MQME Projects (*.mqp)', directory=self.config.get( 'project_dir', os.path.expanduser('~') ) ) if file_name: file_name = unicode(file_name) self.config.set( 'project_dir', os.path.dirname(file_name) ) self.config.save(settings.CONFIG_FILE_PATH) self.config.save_current_file(file_name) def on_open_project_request(self, message): file_name = QtGui.QFileDialog.getOpenFileName( self, filter='MQME Projects (*.mqp)', directory=self.config.get( 'project_dir', os.path.expanduser('~') ) ) if file_name: self.send('new_project') file_name = unicode(file_name) self.config.set( 'project_dir', os.path.dirname(file_name) ) self.config.save(settings.CONFIG_FILE_PATH) self.config.read_current_file(file_name) self.send('open_project') def on_new_project_request(self, message): self.config.reset_current_file() self.send('new_project') def on_export_request(self, message): if self.config.has_changed(): msg_box = QtGui.QMessageBox(self) msg_box.setWindowTitle('Config has changed') msg_box.setText( 'You need to save the project before exporting' ) msg_box.setDefaultButton(QtGui.QMessageBox.Cancel) msg_box.exec_() return current_file = self.config.current_file() directory = None if 'pathes' in current_file: directory = current_file['pathes'].get('resources_dir', None) if directory is None: directory = QtGui.QFileDialog.getExistingDirectory( self, directory=self.config.get( 'resources_dir', os.path.expanduser('~') ) ) if directory is not None: directory = str(directory) if not 'pathes' in current_file: current_file['pathes'] = {} current_file['pathes']['resources_dir'] = directory self.config.set('resources_dir', directory) self.config.save(settings.CONFIG_FILE_PATH) for sub_directory in self.resources_directories: subpath = os.path.join(directory, sub_directory) if not os.path.exists(subpath): os.makedirs(subpath) self.export_maps(directory) self.export_tilesets(directory) self.export_sprites(directory) self.export_fight_environments(directory) msg_box = QtGui.QMessageBox(self) msg_box.setWindowTitle('Export') msg_box.setText( 'Project exported successfully !' ) msg_box.setDefaultButton(QtGui.QMessageBox.Cancel) msg_box.exec_() def export_physics(self, sps_obj, id, directory): svg_path = os.path.join(directory, id + '.svg') if os.path.exists(svg_path): with open(svg_path) as raw_file: dom = parse(raw_file) root = dom.getElementsByTagName('svg')[0] image = root.getElementsByTagName('image')[0] width = float(image.getAttribute('width')) height = float(image.getAttribute('height')) x = float(image.getAttribute('x')) y = float(image.getAttribute('y')) for rect in root.getElementsByTagName('rect'): physics_type = rect.getAttribute('id').split('_')[0] if physics_type != 'platform': physics_type = 'ground' sps_obj['physics'][id].append({ 'x': (float(rect.getAttribute('x')) - x) / width, 'y': (float(rect.getAttribute('y')) - y) / height, 'width': float(rect.getAttribute('width')) / width, 'height': float(rect.getAttribute('height')) / height, 'type': physics_type }) for circle in root.getElementsByTagName('path'): sodipodi_type = circle.getAttribute('sodipodi:type') if sodipodi_type == 'arc': cx = float(circle.getAttribute('sodipodi:cx')) transform_raw = circle.getAttribute('transform') transform_raw = transform_raw.replace('translate(', '').replace(')', '') foe_x = float(transform_raw.split(',')[0]) + cx sps_obj['foes'][id].append({ 'x': (foe_x - x) / width }) if id.find('town_d') > -1: print cx, transform_raw, foe_x, x, (foe_x - x) / width def export_fight_environments(self, directory): fightenv_directory = os.path.join(directory, 'fightenv') environments = self.config.current_file().get('fightenv', {}) layers = ('background3', 'background2') for name, fight_env in environments.items(): sps_obj = {'backgrounds': [], 'physics': {}, 'foes': {}} max_width = 0 max_height = 0 images = {} bg1_path = self.config.current_file()['pathes'][ fight_env['background1'] ] bg1_key = os.path.basename(bg1_path).split('_')[0] bg1_directory = os.path.dirname(bg1_path) for image_name in os.listdir(bg1_directory): if image_name.startswith(bg1_key) and image_name.endswith('.png'): image_id = image_name.split('_', 1)[1].split('.')[0] image_path = os.path.join(bg1_directory, image_name) sps_obj['physics'][name + '_' + image_id] = [] sps_obj['foes'][name + '_' + image_id] = [] self.export_physics( sps_obj, name + '_' + image_id, os.path.dirname(image_path) ) image = utils.get_resized_image(image_path) output_path = os.path.join( fightenv_directory, name + '_' + image_id + '.png' ) image.save(output_path) sps_obj['backgrounds'].append('fightenv/' + name + '_' + image_id) for layer_index in (2, 3): image = utils.get_resized_image( self.config.current_file()['pathes'][ fight_env['background' + str(layer_index)] ] ) output_path = os.path.join( fightenv_directory, name + '_bg' + str(layer_index) + '.png' ) image.save(output_path) sps_obj['backgrounds'].append( 'fightenv/' + name + '_bg' + str(layer_index) ) base_path = os.path.join(fightenv_directory, name) with open(base_path + '.sps', 'w') as sps: sps.write(json.dumps(sps_obj)) def export_sprites(self, directory): sprites_directory = os.path.join(directory, 'sprites') actors = self.config.current_file().get('actors', {}) for actor_name in actors: SpritesGenerator(actor_name).save(sprites_directory) def export_maps(self, directory): maps = self.config.current_file().get('maps', {}) for map_name, map_obj in maps.items(): path = os.path.join(directory, 'maps', map_name + '.map') map_obj['camera'] = [ map_obj['camera_width'], map_obj['camera_height'] ] map_obj['size'] = [ map_obj['width'], map_obj['height'] ] x = 0 for matrix_line in map_obj['specials']: y = 0 for special_conf in matrix_line: if special_conf['class_name'] == 'start_pos': map_obj['start_pos'] = [x, y] y += 1 x += 1 with open(path, 'w') as map_file: map_file.write(json.dumps(map_obj, sort_keys=True, indent=4)) def export_tilesets(self, directory): tilesets = self.config.current_file().get('tilesets', {}) for tileset_name, tileset_obj in tilesets.items(): path = os.path.join(directory, 'tiles', tileset_name + '.sps') with open(path, 'w') as tileset_file: tileset_file.write(json.dumps( tileset_obj, sort_keys=True, indent=4 ))
class MapEditor(ChildWindow): LAYERS = [ MapBackgroundLayer, MapBlockMatrixLayer, MapForegroundLayer, MapSpecialsLayer ] def __init__(self): super(MapEditor, self).__init__() self.config = Config() self.setFixedSize(900, 600) self.setWindowTitle('Map Editor') self.subscribe('menu.trigger.new_map', self.on_new_map) self.subscribe('tileset_editor.new_tileset', self.on_new_tileset) self.subscribe('tileset.update', self.on_tileset_update) self.subscribe('open_maps', self.on_open_maps) self.subscribe('hide_map_layer', self.on_hide_layer) self.subscribe('show_map_layer', self.on_show_layer) self._toolbox = QtGui.QToolBar(self) self._toolbox.setGeometry(0, 0, 100, 600) self._actions = {} for tool in MapSpecialsLayer.TOOLS: ref, name = tool action = MenuAction(self._toolbox, ref, self.on_action_checked) action.setIcon(QtGui.QIcon(os.path.join( settings.IMAGES_PATH, '%s.png' % ref ))) action.setText(name) action.setCheckable(True) self._toolbox.addAction(action) self._actions[ref] = action self._tab_widget = QtGui.QTabWidget(self) self._tab_widget.setTabsClosable(True) self._tab_widget.tabCloseRequested.connect(self.on_map_delete) self._tab_widget.setGeometry(100, 0, 550, 550) self._zoom_in = IconButton(self, 'zoom_in', 30, 30) self._zoom_in.setGeometry(150, 560, 30, 30) self._zoom_in.clicked.connect(self.on_zoom_in) self._zoom_out = IconButton(self, 'zoom_out', 30, 30) self._zoom_out.setGeometry(110, 560, 30, 30) self._zoom_out.clicked.connect(self.on_zoom_out) self._tileset_cb = QtGui.QComboBox(self) self._tileset_cb.setGeometry(665, 5, 220, 20) self._tileset_cb.currentIndexChanged.connect(self.update) self._tiles_widgets = {} self._current_tool = None def on_map_delete(self, index): map_name = self._tab_widget.widget(index).map_name() msg_box = QtGui.QMessageBox(self) msg_box.setWindowTitle('Delete Map') msg_box.setText('Do you want to delete "%s" ?' % map_name) msg_box.setStandardButtons( QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel ) msg_box.setDefaultButton(QtGui.QMessageBox.Cancel) status = msg_box.exec_() if status == QtGui.QMessageBox.Ok: self._tab_widget.widget(index).remove_map() self._tab_widget.removeTab(index) def on_hide_layer(self, message): index = 0 while index < self._tab_widget.count(): self._tab_widget.widget(index).hide_layer(message['layer_type']) index += 1 def on_show_layer(self, message): index = 0 while index < self._tab_widget.count(): self._tab_widget.widget(index).show_layer(message['layer_type']) index += 1 def on_action_checked(self, action_ref): for ref, action in self._actions.items(): if ref != action_ref: action.setChecked(False) if self._actions[action_ref].isChecked(): self._current_tool = action_ref else: self._current_tool = None self._tab_widget.currentWidget().set_current_tool(self._current_tool) def on_open_maps(self, message): current_file = self.config.current_file() for map_name, map_obj in current_file.get('maps', {}).items(): map_grid = MapGrid(self, map_obj, self.LAYERS) map_grid.read_map_conf() map_grid.show_layer(MapBackgroundLayer) self._tab_widget.addTab(map_grid, map_name) def on_new_project(self, message): self._current_tool = None for widget in self._tiles_widgets.values(): widget.hide() self._tileset_cb.clear() self._tiles_widgets = {} self._tab_widget.clear() def on_select_tile(self, tile): for selector in self._tiles_widgets.values(): selector.unselect_all() self._current_tool = tile self._tab_widget.currentWidget().set_current_tool(tile) def on_new_tileset(self, message): self._tileset_cb.addItem(message['tileset']) self._tiles_widgets[message['tileset']] = TilesSelector( self, self.on_select_tile, message['tileset'] ) self._tiles_widgets[message['tileset']].setGeometry(665, 30, 220, 560) self.update() def update(self, index=None): for name in self._tiles_widgets.keys(): self._tiles_widgets[name].hide() current_tileset = str(self._tileset_cb.currentText()) if current_tileset in self._tiles_widgets: self._tiles_widgets[current_tileset].show() def on_tileset_update(self, message): if message['tileset'] in self._tiles_widgets: self._tiles_widgets[message['tileset']].update() def on_new_map(self, message): map_obj = NewMapDialog.get_new_map(self) if map_obj is not None: self._tab_widget.addTab(MapGrid( self, map_obj, self.LAYERS), map_obj['name'] ) def on_zoom_in(self): self._tab_widget.currentWidget().on_zoom_in() def on_zoom_out(self): self._tab_widget.currentWidget().on_zoom_out()
class TileSetPicture(QtGui.QLabel): def __init__(self, parent, picture_path, queue): super(TileSetPicture, self).__init__(parent) self._parent = parent self._queue = queue self._items = [] self._base_pixmap = QtGui.QPixmap(picture_path) self.config = Config() self.current_file = self.config.current_file() path_elements = os.path.split(picture_path) self._base_name = os.path.splitext( path_elements[len(path_elements) - 1] )[0] if not 'tilesets' in self.current_file: self.current_file['tilesets'] = {} if not 'pathes' in self.current_file: self.current_file['pathes'] = {} self.current_file['pathes'][self._base_name] = picture_path if not self._base_name in self.current_file['tilesets']: self.current_file['tilesets'][self._base_name] = {} self._current_item = None def base_name(self): return self._base_name def pixmap(self): return self._base_pixmap def read_tilesets_config(self): self.current_file = self.config.current_file() tileset_dict = self.current_file['tilesets'][self._base_name] for tile_name, tile in tileset_dict.items(): item = TileItem(self, self._queue, tile['crop_x'], tile['crop_y'], tile['crop_width'], tile['crop_height'] ) item.set_name(tile_name) item.show() self._items.append(item) def set_height(self, height): pixmap = self._base_pixmap.scaledToHeight(height) self.setGeometry(0, 0, pixmap.width(), pixmap.height()) self.setPixmap(pixmap) for item in self._items: item.update_geometry() def mousePressEvent(self, event): self._current_item = TileItem(self, self._queue, event.x(), event.y()) self._current_item.show() def mouseReleaseEvent(self, event): if self._current_item is not None: if self._current_item.real_width() == 1: self._current_item.hide() else: status = False while not status: name, status = QtGui.QInputDialog.getText( self._parent, 'Tile name', 'Name :' ) name = str(name) self._current_item.set_name(name) self.current_file['tilesets'][ self._base_name ][name] = self._current_item.to_dict() self.current_file['tilesets'] self._items.append(self._current_item) self._queue.put({'name': 'config.save'}) self._queue.put({ 'name': 'tileset.update', 'tileset': self._base_name }) self._current_item = None def mouseMoveEvent(self, event): if self._current_item is not None: rect = self._current_item.geometry() width = event.x() - rect.x() if width < 3: width = 3 height = event.y() - rect.y() if height < 3: height = 3 self._current_item.set_size(width, height) def remove_item(self, item): self._items.pop(self._items.index(item)) item.hide() del self.current_file[ 'tilesets' ][self._base_name][item.to_dict()['name']] def remove(self): del self.current_file['tilesets'][self._base_name]
class AnimationArea(QtGui.QFrame): FPS_VALUES = [40, 35, 30, 25, 20, 15, 10, 5, 2, 1] NB_MULTIPLIERS = 100 def __init__(self, parent, actor_name, animation_name): super(AnimationArea, self).__init__(parent) self._parent = parent self.config = Config() self.current_conf = Config().current_file()[ 'actors' ][actor_name]['animations'][animation_name] self._current_frame = 0 self._actor_name = actor_name self._animation_name = animation_name self.setGeometry(0, 0, 480, 450) self._frames_list = QtGui.QComboBox(self) self._frames_list.setGeometry(5, 420, 100, 20) self._frames_list.currentIndexChanged.connect(self.on_change_frame) self._add_frame_button = IconButton(self, 'add_frame', 50, 50) self._add_frame_button.setGeometry(110, 420, 20, 20) self._add_frame_button.clicked.connect(self.on_add_frame) self._remove_frame_button = IconButton(self, 'remove_frame', 50, 50) self._remove_frame_button.setGeometry(135, 420, 20, 20) self._remove_frame_button.clicked.connect(self.on_remove_frame) self._scroll_areas = {} self._add_picture_button = IconButton(self, 'add_picture', 50, 50) self._add_picture_button.setGeometry(402, 2, 50, 50) self._add_picture_button.clicked.connect(self.on_new_picture) self._remove_animation_button = IconButton( self, 'remove_animation', 50, 50 ) self._remove_animation_button.setGeometry(402, 54, 50, 50) self._remove_animation_button.clicked.connect(self.on_remove_animation) self._resize_button = QtGui.QRadioButton('Resize', self) self._resize_button.setGeometry(170, 420, 70, 20) self._move_button = QtGui.QRadioButton('Move', self) self._move_button.setGeometry(240, 420, 70, 20) self._move_button.setChecked(True) self._multiplier = QtGui.QComboBox(self) self._multiplier.setGeometry(402, 380, 50, 20) for multiplier in range(1, self.NB_MULTIPLIERS + 1): self._multiplier.addItem('x' + str(multiplier)) self._pos_label = QtGui.QLabel(self) self._pos_label.setGeometry(402, 100, 50, 100) self._play_animation = IconButton(self, 'play_animation', 50, 50) self._play_animation.setGeometry(402, 210, 50, 50) self._play_animation.clicked.connect(self.on_play_animation) self._fps_choice = QtGui.QComboBox(self) self._fps_choice.setGeometry(310, 420, 150, 20) if not len(self.current_conf): self._scroll_areas[0] = QtGui.QScrollArea(self) self._scroll_areas[0].setGeometry(0, 0, 400, 400) self._scroll_areas[0].setWidget(SpriteGridWidget(self)) self._frames_list.addItem('Frame 0') self.current_conf['fps'] = 40 for value in self.FPS_VALUES: period = 1000 / value self._fps_choice.addItem('%d FPS - %d ms' % (value, period)) self._fps_choice.setCurrentIndex(self.FPS_VALUES.index( self.current_conf['fps'] )) self._fps_choice.currentIndexChanged.connect(self.on_change_fps) self._multiplier.currentIndexChanged.connect(self.on_change_multiplier) def on_change_multiplier(self): frame_key = 'frame_%d' % self._current_frame conf = None for elem in self.current_conf[frame_key]: if elem.get('type', None) == 'conf': conf = elem break if conf is None: conf = {'type': 'conf'} self.current_conf[frame_key].append(conf) multiplier = self._multiplier.currentIndex() + 1 conf['multiplier'] = multiplier def on_play_animation(self): preview = AnimationPreview( self, self._actor_name, self._animation_name ) preview.show() def read_conf(self): for index in range(len(self.current_conf) - 1): frame_key = 'frame_%d' % index self._scroll_areas[index] = QtGui.QScrollArea(self) self._scroll_areas[index].setGeometry(0, 0, 400, 400) self._scroll_areas[index].setWidget(SpriteGridWidget(self)) for obj in self.current_conf[frame_key]: if obj.get('type', None) != 'conf': frame_image = FrameImage( self._scroll_areas[index].widget(), self.config.current_file()['pathes'][obj['id']], obj['id'], frame_key ) frame_image.setGeometry( 200 + obj['x'] * 100, 200 + obj['y'] * 100, obj['width'] * 100, obj['height'] * 100, ) frame_image.show() self._frames_list.addItem('Frame %d' % index) self._scroll_areas[index].hide() self._current_frame = 0 self._scroll_areas[0].show() self._frames_list.setCurrentIndex(0) frame_key = 'frame_%d' % self._current_frame conf = None for elem in self.current_conf[frame_key]: if elem.get('type', None) == 'conf': conf = elem break if conf is None: conf = {'type': 'conf'} self.current_conf[frame_key].append(conf) multiplier = conf.get('multiplier', 1) self._multiplier.setCurrentIndex(multiplier - 1) def remove_animation(self): animations = Config().current_file()[ 'actors'][self._actor_name]['animations'] del animations[self._animation_name] def on_remove_animation(self): self._parent.remove_animation(self._animation_name) def on_change_fps(self): self.current_conf['fps'] = self.FPS_VALUES[ self._fps_choice.currentIndex() ] def on_remove_frame(self): if len(self._scroll_areas) > 1: if self._current_frame == len(self._scroll_areas) - 1: frame_key = self.get_frame_key() if frame_key in self.current_conf: del self.current_conf[frame_key] self._scroll_areas[self._current_frame].hide() del self._scroll_areas[self._current_frame] self._current_frame -= 1 self._frames_list.setCurrentIndex(self._current_frame) self._frames_list.removeItem(len(self._scroll_areas)) def move_image(self, image, gap): gap_x, gap_y = gap obj = None rect = image.geometry() for image_obj in self.current_conf[image.frame_key()]: if image_obj.get('type', None) != 'conf': if image_obj['id'] == image.image_id(): obj = image_obj if self._move_button.isChecked(): x, y = rect.x() + gap_x, rect.y() + gap_y image.setGeometry(x, y, rect.width(), rect.height()) obj['x'] = (x - 200.0) / 100.0 obj['y'] = (y - 200.0) / 100.0 else: width = rect.width() + gap_x height = width * rect.height() / rect.width() image.setGeometry(rect.x(), rect.y(), width, height) obj['width'] = width / 100.0 obj['height'] = height / 100.0 self.update_label(obj) def update_label(self, image_obj): self._pos_label.setText( 'X : %s\nY : %s\nW : %s\nH : %s' % ( str(image_obj['x']), str(image_obj['y']), str(image_obj['width']), str(image_obj['height']) ) ) def on_change_frame(self): self._scroll_areas[self._current_frame].hide() self._current_frame = self._frames_list.currentIndex() frame_key = 'frame_%d' % self._current_frame if frame_key in self.current_conf: conf = None for elem in self.current_conf.get(frame_key, []): if elem.get('type', None) == 'conf': conf = elem break if conf is None: conf = {'type': 'conf'} self.current_conf[frame_key].append(conf) multiplier = conf.get('multiplier', 1) else: multiplier = 1 self._multiplier.setCurrentIndex(multiplier - 1) self._scroll_areas[self._current_frame].show() def on_add_frame(self): if self._current_frame == len(self._scroll_areas) - 1: self._scroll_areas[self._current_frame].hide() self._current_frame += 1 frame_label = 'Frame %d' % self._current_frame self._scroll_areas[self._current_frame] = QtGui.QScrollArea(self) self._scroll_areas[self._current_frame].setGeometry(0, 0, 400, 400) self._scroll_areas[self._current_frame].setWidget( SpriteGridWidget(self) ) self._frames_list.addItem(frame_label) self._frames_list.setCurrentIndex(self._current_frame) frame_key = self.get_frame_key() if not frame_key in self.current_conf: self.current_conf[frame_key] = [] def get_frame_key(self): return 'frame_%d' % self._current_frame def remove_image(self, frame_image): frame_image.hide() index = 0 for image_obj in self.current_conf[frame_image.frame_key()]: if not 'type' in image_obj or image_obj['type'] != 'conf': if image_obj['id'] == frame_image.image_id(): self.current_conf[frame_image.frame_key()].pop(index) index += 1 def on_new_picture(self): file_name = QtGui.QFileDialog.getOpenFileName( self, filter='Image (*.png)', directory=self.config.get( 'frame_image_dir', os.path.expanduser('~') ) ) if file_name: from mqme.mainwindow import MainWindow file_name = unicode(file_name) self.config.set('frame_image_dir', os.path.dirname(file_name)) MainWindow.queue.put({'name': 'config.save'}) if not 'pathes' in Config().current_file(): Config().current_file()['pathes'] = {} image_id = str(uuid.uuid1()) Config().current_file()['pathes'][image_id] = file_name frame_key = self.get_frame_key() if not frame_key in self.current_conf: self.current_conf[frame_key] = [] frame_image = FrameImage( self._scroll_areas[self._current_frame].widget(), file_name, image_id, frame_key ) frame_image.show() width, height = frame_image.ratio() x = 0.5 - (width / 2.0) y = 1.0 - height self.current_conf[frame_key].append({ 'id': image_id, 'width': width, 'height': height, 'x': x, 'y': y }) frame_image.setGeometry( 200 + x * 100, 200 + y * 100, width * 100, height * 100 )