class TileSetWorkspace(QtGui.QWidget): ZOOM_VALUES = [1, 2, 2.5, 3, 4, 5, 8, 10] def __init__(self, parent, picture_path, queue): super(TileSetWorkspace, self).__init__(parent) self._parent = parent self.setGeometry(0, 48, 640, 432) self.config = Config() self._queue = queue rect = self.geometry() self._pos_label = QtGui.QLabel(self) self._pos_label.setGeometry( rect.right() - 100, rect.top() + 130, 100, 100 ) self._delete = IconButton(self, 'delete_tileset', 20, 20) self._delete.clicked.connect(self.remove) self._delete.setGeometry(rect.right() - 25, rect.top() + 5, 20, 20) self._zoom_in = IconButton(self, 'zoom_in', 50, 50) self._zoom_in.clicked.connect(self.on_zoom_in) self._zoom_in.setGeometry(rect.right() - 55, rect.top() + 35, 50, 50) self._zoom_out = IconButton(self, 'zoom_out', 50, 50) self._zoom_out.clicked.connect(self.on_zoom_out) self._zoom_out.setGeometry(rect.right() - 55, rect.top() + 90, 50, 50) self._scroll_area = QtGui.QScrollArea(self) self._scroll_area.setGeometry( 2, 2, rect.width() - 104, rect.height() - 4 ) self._scroll_area.setStyleSheet('QScrollArea {' 'background: black;' 'border: 3px solid #ccccff;' '}') self._tileset_picture = TileSetPicture( self, picture_path, self._queue ) self._scroll_area.setWidget(self._tileset_picture) self._zoom_index = 0 self.update_zoom() def read_tilesets_config(self): self._tileset_picture.read_tilesets_config() def base_name(self): return self._tileset_picture.base_name() def update_zoom(self): self._tileset_picture.set_height( self.ZOOM_VALUES[self._zoom_index] * 400 ) def on_zoom_in(self): if self._zoom_index + 1 < len(self.ZOOM_VALUES): self._zoom_index += 1 self.update_zoom() def on_zoom_out(self): if self._zoom_index - 1 >= 0: self._zoom_index -= 1 self.update_zoom() def on_picture_mouse_move(self, message): self._pos_label.setText('X : %d\nY : %d\nWidth : %d\nHeight : %d' % ( message['x'], message['y'], message['width'], message['height'] )) def remove(self): self._tileset_picture.remove() self._parent.remove_current()
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 FightEnvironmentWorkspace(QtGui.QFrame): LAYERS = ('screen', 'background3', 'background2', 'background1') def __init__(self, name): super(FightEnvironmentWorkspace, self).__init__() self._name = name self._height_ratio = 1.0 self.config = Config() self.setGeometry(0, 0, 320, 220) self._layers = {} self._buttons = [] self._current_conf = Config().current_file()['fightenv'][name] for layer_name in self.LAYERS: self._layers[layer_name] = self.new_layer() self._layers['screen'].setStyleSheet( 'QLabel {' 'background-color: black;' 'border: 3px solid #ccccff;' '}' ) self.new_button('Set background 1', 2, self.on_choose_background1, False) self.new_button('Set background 2', 104, self.on_choose_background2, False) self.new_button('Set background 3', 206, self.on_choose_background3) self._play_animation = IconButton(self, 'play_animation', 30, 30) self._play_animation.setGeometry(145, 182, 30, 30) self._play_animation.clicked.connect(self.on_play_animation) def on_play_animation(self): self._preview = FightEnvironmentPreview(self._name) self._preview.show() def name(self): return self._name def read_conf(self): for layer_name in self.LAYERS: if layer_name in self._current_conf: path = Config().current_file()['pathes'][self._current_conf[layer_name]] pixmap = QtGui.QPixmap(path) self.show_background(pixmap, layer_name) def show_background(self, pixmap, name): height = self._layers[name].height() width = (pixmap.width() * height) / pixmap.height() self._height_ratio = float(height) / pixmap.height() self._layers[name].setPixmap(pixmap.scaled(width, height)) for button in self._buttons: button.setEnabled(True) def on_choose_background3(self): pixmap = self.choose_and_save_image('background3') if pixmap: self.show_background(pixmap, 'background3') def on_choose_background2(self): pixmap = self.choose_and_save_image('background2') if pixmap: self.show_background(pixmap, 'background2') def on_choose_background1(self): pixmap = self.choose_and_save_image('background1') if pixmap: self.show_background(pixmap, 'background1') def choose_and_save_image(self, image_name): file_name = QtGui.QFileDialog.getOpenFileName( self, filter='Image (*.png)', directory=self.config.get( 'fightenv_image_dir', os.path.expanduser('~') ) ) if file_name: from mqme.mainwindow import MainWindow file_name = unicode(file_name) self.config.set('fightenv_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 self._current_conf[image_name] = image_id return QtGui.QPixmap(file_name) def new_button(self, name, x, callback, enabled=True): button = QtGui.QPushButton(name, self) button.setGeometry(x, 155, 100, 20) button.clicked.connect(callback) button.setEnabled(enabled) button.setStyleSheet( 'QPushButton {' 'font-size: 10px;' '}' ) button.show() self._buttons.append(button) def new_layer(self): layer = QtGui.QLabel(self) layer.setGeometry(7, 0, 300, 150) layer.show() return layer
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 )