Beispiel #1
0
 def _check_close_world(self) -> bool:
     """
     Check if it is safe to close the world and prompt the user if it is not.
     :return: True if the world can be closed, False otherwise
     """
     unsaved_changes = self._world.chunk_history_manager.unsaved_changes
     if unsaved_changes:
         msg = wx.MessageDialog(
             self,
             f"""There {
             'is' if unsaved_changes == 1 else 'are'
             } {unsaved_changes} unsaved change{
             's' if unsaved_changes >= 2 else ''
             } in {
             self._world.world_wrapper.world_name
             }. Would you like to save?""",
             style=wx.YES_NO | wx.CANCEL | wx.CANCEL_DEFAULT,
         )
         response = msg.ShowModal()
         if response == wx.ID_YES:
             self._canvas.save()
             return True
         elif response == wx.ID_NO:
             return True
         elif response == wx.ID_CANCEL:
             log.info(f"""Aborting closing world {
                 self._world.world_wrapper.world_name
                 } because the user pressed cancel.""")
             return False
     return True
Beispiel #2
0
    def __init__(self, parent, world_dirs, open_world_callback, sort=True):
        super(WorldList, self).__init__(parent)

        self.worlds = []

        world_formats = []
        for world_path in world_dirs:
            if os.path.isdir(world_path):
                try:
                    world_formats.append(
                        world_interface.load_format(world_path))
                except Exception as e:
                    log.info(f"Could not find loader for {world_path} {e}")
        if sort:
            world_formats = reversed(
                sorted(world_formats, key=lambda f: f.last_played))

        for world_format in world_formats:
            try:
                world_button = WorldUIButton(self, world_format,
                                             open_world_callback)
                self.add_object(world_button, 0, wx.ALL | wx.EXPAND)
                self.worlds.append(world_button)
            except Exception as e:
                log.info(
                    f"Failed to display world button for {world_format.world_path} {e}"
                )

        self.Layout()
    def run_operation(
        self,
        operation: Callable[[], OperationReturnType],
        title="Amulet",
        msg="Running Operation",
        throw_exceptions=False,
    ) -> Any:
        def operation_wrapper():
            yield 0, "Disabling Threads"
            self._disable_threads()
            yield 0, msg
            op = operation()
            if isinstance(op, GeneratorType):
                yield from op
            return op

        err = None
        out = None
        try:
            out = show_loading_dialog(
                operation_wrapper,
                title,
                msg,
                self,
            )
            self.world.create_undo_point()
            wx.PostEvent(self, CreateUndoEvent())
        except OperationError as e:
            msg = f"Error running operation: {e}"
            log.info(msg)
            self.world.restore_last_undo_point()
            wx.MessageDialog(self, msg, style=wx.OK).ShowModal()
            err = e
        except OperationSuccessful as e:
            msg = str(e)
            log.info(msg)
            self.world.restore_last_undo_point()
            wx.MessageDialog(self, msg, style=wx.OK).ShowModal()
            err = e
        except OperationSilentAbort as e:
            self.world.restore_last_undo_point()
            err = e
        except Exception as e:
            self.world.restore_last_undo_point()
            log.error(traceback.format_exc())
            wx.MessageDialog(
                self,
                f"Exception running operation: {e}\nSee the console for more details",
                style=wx.OK,
            ).ShowModal()
            err = e

        self._enable_threads()
        if err is not None and throw_exceptions:
            raise err
        return out
Beispiel #4
0
 def is_closeable(self) -> bool:
     """
     Check if it is safe to close the UI.
     :return: True if the program can be closed, False otherwise
     """
     if self._canvas is not None:
         if self._canvas.is_closeable():
             return self._check_close_world()
         log.info(
             f"The canvas in edit for world {self._world.world_wrapper.world_name} was not closeable for some reason."
         )
         return False
     return not bool(self._world.chunk_history_manager.unsaved_changes)
 def _convert_method(self):
     global work_count
     try:
         out_world = world_interface.load_format(self.out_world_path)
         log.info(
             f"Converting world {self.world.world_path} to {out_world.world_path}"
         )
         out_world: WorldFormatWrapper
         out_world.open()
         self.world.save(out_world, self._update_loading_bar)
         out_world.close()
         message = "World conversion completed"
         log.info(
             f"Finished converting world {self.world.world_path} to {out_world.world_path}"
         )
     except Exception as e:
         message = f"Error during conversion\n{e}"
         log.error(message, exc_info=True)
     self._update_loading_bar(0, 100)
     self.convert_button.Enable()
     wx.MessageBox(message)
     work_count -= 1
Beispiel #6
0
 def _create_atlas(self) -> Generator[float, None, None]:
     """Create and bind the atlas texture."""
     atlas_iter = textureatlas.create_atlas(self._resource_pack.textures)
     try:
         while True:
             yield next(atlas_iter)
     except StopIteration as e:
         texture_atlas, self._texture_bounds, width, height = e.value
     glBindTexture(GL_TEXTURE_2D, self._gl_texture_atlas)
     glTexImage2D(
         GL_TEXTURE_2D,
         0,
         GL_RGBA,
         width,
         height,
         0,
         GL_RGBA,
         GL_UNSIGNED_BYTE,
         texture_atlas,
     )
     glBindTexture(GL_TEXTURE_2D, 0)
     log.info("Finished setting up texture atlas in OpenGL")
    def _setup_texture(self, context_id: str):
        """Set up the texture for a given context"""
        gl_texture = self._gl_textures[context_id] = glGenTextures(
            1)  # Create the texture location
        glBindTexture(GL_TEXTURE_2D, gl_texture)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)

        glBindTexture(GL_TEXTURE_2D, gl_texture)
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RGBA,
            self._image_width,
            self._image_height,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            self._image,
        )
        glBindTexture(GL_TEXTURE_2D, 0)
        log.info("Finished setting up texture atlas in OpenGL")
 def is_closeable(self):
     if work_count:
         log.info(
             f"World {self.world.world_path} is still being converted. Please let it finish before closing"
         )
     return work_count == 0
def create_atlas_iter(
    texture_tuple: Tuple[str, ...]
) -> Generator[
    float,
    None,
    Tuple[numpy.ndarray, Dict[Any, Tuple[float, float, float, float]], int, int],
]:
    log.info("Creating texture atlas")
    # Parse texture names
    textures = []
    for texture_index, texture in enumerate(texture_tuple):
        if not texture_index % 100:
            yield texture_index / (len(texture_tuple) * 2)
        # Look for a texture name
        name, frames = texture, [texture]

        # Build frame objects
        frames = [Frame(f) for f in frames]

        # Add frames to texture object list
        textures.append(Texture(name, frames))

    # Sort textures by perimeter size in non-increasing order
    textures = sorted(textures, key=lambda i: i.frames[0].perimeter, reverse=True)

    height = 0
    width = 0
    pixels = 0
    for t in textures:
        for f in t.frames:
            height = max(f.height, height)
            width = max(f.width, width)
            pixels += f.height * f.width

    size = max(height, width, 1 << (math.ceil(pixels ** 0.5) - 1).bit_length())

    atlas_created = False
    atlas = None
    while not atlas_created:
        try:
            # Create the atlas and pack textures in
            log.info(f"Trying to pack textures into image of size {size}x{size}")
            atlas = TextureAtlas(size, size)

            for texture_index, texture in enumerate(textures):
                if not texture_index % 30:
                    yield 0.5 + texture_index / (len(textures) / 2)
                atlas.pack(texture)
            atlas_created = True
        except AtlasTooSmall:
            log.info(f"Image was too small. Trying with a larger area")
            size *= 2

    log.info(f"Successfully packed textures into an image of size {size}x{size}")

    texture_atlas = numpy.array(atlas.generate("RGBA"), numpy.uint8).ravel()

    texture_bounds = atlas.to_dict()
    texture_bounds = {
        texture_path: texture_bounds[texture_path] for texture_path in texture_tuple
    }

    log.info("Finished creating texture atlas")
    return texture_atlas, texture_bounds, atlas.width, atlas.height