Exemplo n.º 1
0
class Canvas:
    image: Image.Image
    draw: ImageDraw.ImageDraw

    vao: int
    program: ShaderProgram

    texture: int

    width: int
    height: int

    font: ImageFont.ImageFont

    def __init__(self, width, height):
        self._createGlSurface()

        self.texture = 0

        self.resize(width, height)

        self._createGlTexture()

        self.width = width
        self.height = height

        self.program = ShaderProgram('shaders/guiShader.vert',
                                     'shaders/guiShader.frag')

        self.font = ImageFont.truetype('assets/minecraft_font.ttf', 16)

    def resize(self, width, height):
        self.width = width
        self.height = height

        self.image = Image.new("RGB", (width, height), color=ALPHA_COLOR)
        self.draw = typing.cast(ImageDraw.ImageDraw,
                                ImageDraw.Draw(self.image, "RGBA"))

        if self.texture == 0:
            self._createGlTexture()

    def create_oval(self, x0, y0, x1, y1, **kwargs):
        if 'fill' in kwargs:
            assert (kwargs['fill'] not in ['#000', '#000000', 'black'])

        fill = kwargs.pop('fill', '#0000')
        outline = kwargs.pop('outline', '#111F')
        width = kwargs.pop('width', 1)
        assert (len(kwargs) == 0)
        self.draw.ellipse([x0, y0, x1, y1],
                          fill=fill,
                          outline=outline,
                          width=width)

    def create_rectangle(self, x0, y0, x1, y1, **kwargs):
        if 'fill' in kwargs:
            assert (kwargs['fill'] not in ['#000', '#000000', 'black'])

        fill = kwargs.pop('fill', '#0000')
        outline = kwargs.pop('outline', '#111F')
        width = kwargs.pop('width', 1)

        assert (len(kwargs) == 0)

        self.draw.rectangle([x0, y0, x1, y1],
                            fill=fill,
                            outline=outline,
                            width=width)

    def create_text(self, x, y, **kwargs):
        text = kwargs.pop('text')
        fill = kwargs.pop('fill', '#FFF')
        anchor = convertAnchor(kwargs.pop('anchor', 'center'))
        font = kwargs.pop('font', ())

        if len(kwargs) != 0:
            print(kwargs)
            assert (False)

        self.draw.text((int(x), int(y)),
                       text=text,
                       fill=fill,
                       font=self.font,
                       anchor=anchor)

    def create_image(self, x, y, **kwargs):
        image = kwargs.pop('image')
        anchor = kwargs.pop('anchor', 'center')

        if len(kwargs) != 0:
            print(kwargs)
            assert (False)

        if anchor == 'center':
            x -= image.width // 2
            y -= image.height // 2
        else:
            print(anchor)
            assert (False)

        mask = getCachedMask(image)

        self.image.paste(image, box=(int(x), int(y)), mask=mask)

    def _createGlSurface(self):
        vertices = numpy.array(
            [
                1.0,
                1.0,
                1.0,
                0.0,  # top right
                1.0,
                -1.0,
                1.0,
                1.0,  # bottom right
                -1.0,
                -1.0,
                0.0,
                1.0,  # bottom left
                -1.0,
                1.0,
                0.0,
                0.0,  # top left 
            ],
            dtype='float32')

        indices = numpy.array([
            0,
            1,
            3,
            1,
            2,
            3,
        ], dtype='uint32')

        vao: int = glGenVertexArrays(1)  #type:ignore
        vbo: int = glGenBuffers(1)  #type:ignore
        ebo: int = glGenBuffers(1)  #type:ignore

        glBindVertexArray(vao)

        glBindBuffer(GL_ARRAY_BUFFER, vbo)
        glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices,
                     GL_STATIC_DRAW)

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices,
                     GL_STATIC_DRAW)

        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * 4,
                              ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)

        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * 4,
                              ctypes.c_void_p(2 * 4))
        glEnableVertexAttribArray(1)

        glBindBuffer(GL_ARRAY_BUFFER, 0)

        glBindVertexArray(0)

        self.vao = vao

    def _createGlTexture(self):
        self.texture = glGenTextures(1)  #type:ignore
        glBindTexture(GL_TEXTURE_2D, self.texture)

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)

        glBindTexture(GL_TEXTURE_2D, 0)

    def redraw(self):
        arr = numpy.asarray(self.image.convert('RGBA'), dtype=numpy.uint8)

        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_2D, self.texture)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.image.width,
                     self.image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     arr)  #type:ignore

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        self.program.useProgram()
        glUniform3f(self.program.getUniformLocation("alphaColor"),
                    ALPHA_COLOR[0] / 255.0, ALPHA_COLOR[1] / 255.0,
                    ALPHA_COLOR[2] / 255.0)

        glBindVertexArray(self.vao)
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
                       ctypes.c_void_p(0))  #type:ignore

        #glBlendFunc(GL_SRC_ALPHA, GL_ZERO)

        self.image = Image.new("RGB", (self.width, self.height),
                               color=ALPHA_COLOR)
        self.draw = typing.cast(ImageDraw.ImageDraw,
                                ImageDraw.Draw(self.image, "RGBA"))