Exemplo n.º 1
0
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
                ))