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()
Exemple #2
0
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
            )