diff --git a/addon/__init__.py b/addon/__init__.py index 5d27d34..4c39775 100644 --- a/addon/__init__.py +++ b/addon/__init__.py @@ -1,5 +1,5 @@ ''' - Copyright (C) 2021 - 2023 Akaneyu + Copyright (C) 2021 - 2024 Akaneyu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,8 +18,8 @@ bl_info = { "name": "Image Editor Plus", "author": "akaneyu", - "version": (1, 7, 3), - "blender": (2, 93, 0), + "version": (1, 8, 0), + "blender": (3, 3, 0), "location": "Image", "warning": "", "description": "", diff --git a/addon/app.py b/addon/app.py index bf95a54..e1212a8 100644 --- a/addon/app.py +++ b/addon/app.py @@ -1,5 +1,5 @@ ''' - Copyright (C) 2021 - 2023 Akaneyu + Copyright (C) 2021 - 2024 Akaneyu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -152,22 +152,23 @@ def draw_handler(): or area_session.layer_rotating \ or area_session.layer_scaling: - info_text = "LMB: Perform\n" \ + info_text = "LMB: Perform " \ + "RMB: Cancel" - area_height = context.area.height + area_width = context.area.width # info text if info_text: - blf.enable(0, blf.WORD_WRAP) - blf.word_wrap(0, 100) + ui_scale = context.preferences.system.ui_scale - blf.position(0, 30, area_height - 70, 0) - blf.size(0, 14, 72) + session.ui_renderer.render_info_box((0, 0), (area_width, 20 * ui_scale)) + + blf.position(0, 8 * ui_scale, 6 * ui_scale, 0) + blf.size(0, 11 * ui_scale) if bpy.app.version >= (3, 6) \ + else blf.size(0, 11 * ui_scale, 72) + blf.color(0, 0.7, 0.7, 0.7, 1.0) blf.draw(0, info_text) - blf.disable(0, blf.WORD_WRAP) - def get_curve_node(): node_group = bpy.data.node_groups.get('imageeditorplus') if not node_group: @@ -392,7 +393,7 @@ def apply_layer_transform(img, rot, scale): buff, width, height = session.ui_renderer.render_image_offscreen(img, rot, scale) - pixels = np.reshape(buff, (height, width, 4)).astype(np.float32) / 255.0 + pixels = np.array([[pixel for pixel in row] for row in buff], np.float32) / 255.0 # gamma correction utils.convert_colorspace(pixels, 'Linear', diff --git a/addon/ui_renderer.py b/addon/ui_renderer.py index 14286bf..d02d254 100644 --- a/addon/ui_renderer.py +++ b/addon/ui_renderer.py @@ -1,5 +1,5 @@ ''' - Copyright (C) 2020 Akaneyu + Copyright (C) 2020 - 2024 Akaneyu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,10 +17,6 @@ import sys import math -import time -import bpy -import bgl -import blf import gpu from gpu_extras.batch import batch_for_shader from mathutils import Matrix, Vector @@ -138,8 +134,10 @@ class UIRenderer: def render_selection_frame(self, pos, size, rot=0, scale=(1.0, 1.0)): width, height = size[0], size[1] - bgl.glEnable(bgl.GL_BLEND) - bgl.glLineWidth(2.0) + prev_blend = gpu.state.blend_get() + gpu.state.blend_set('ALPHA') + + gpu.state.line_width_set(2.0) with gpu.matrix.push_pop(): verts = [[0, 0], [0, height], [width, height], [width, 0], [0, 0]] @@ -172,20 +170,12 @@ class UIRenderer: batch.draw(self.dotted_line_shader) - err = bgl.glGetError() - if err != bgl.GL_NO_ERROR: - print('render_selection_frame') - print('OpenGL error:', err) + gpu.state.blend_set(prev_blend) def render_image_sub(self, img, pos, size, rot, scale): width, height = size[0], size[1] - img.gl_load() - - bgl.glActiveTexture(bgl.GL_TEXTURE0) - bgl.glBindTexture(bgl.GL_TEXTURE_2D, img.bindcode) - bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_NEAREST) - bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_NEAREST) + texture = gpu.texture.from_image(img) with gpu.matrix.push_pop(): gpu.matrix.translate([pos[0] + width / 2.0, pos[1] + height / 2.0]) @@ -207,24 +197,18 @@ class UIRenderer: self.image_shader.bind() - self.image_shader.uniform_int('image', 0) + self.image_shader.uniform_sampler('image', texture) batch.draw(self.image_shader) - err = bgl.glGetError() - if err != bgl.GL_NO_ERROR: - print('render_image') - print('OpenGL error:', err) - def render_image(self, img, pos, size, rot=0, scale=(1.0, 1.0)): - bgl.glEnable(bgl.GL_BLEND) - # FIXME: glBlendFuncSeparate does not seem to be implemented, - # but we believe this blend mode was already applied - #bgl.glBlendFuncSeparate(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA, - # bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA); + prev_blend = gpu.state.blend_get() + gpu.state.blend_set('ALPHA') self.render_image_sub(img, pos, size, rot, scale) + gpu.state.blend_set(prev_blend) + def render_image_offscreen(self, img, rot=0, scale=(1.0, 1.0)): width, height = img.size[0], img.size[1] @@ -248,10 +232,8 @@ class UIRenderer: ofs = gpu.types.GPUOffScreen(ofs_width, ofs_height) with ofs.bind(): - bgl.glDisable(bgl.GL_BLEND) - - bgl.glClearColor(0, 0, 0, 0) - bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) + fb = gpu.state.active_framebuffer_get() + fb.clear(color=(0.0, 0.0, 0.0, 0.0)) with gpu.matrix.push_pop(): gpu.matrix.load_projection_matrix(Matrix.Identity(4)) @@ -262,16 +244,36 @@ class UIRenderer: self.render_image_sub(img, [0, 0], [width, height], rot, scale) - buff = bgl.Buffer(bgl.GL_BYTE, ofs_width * ofs_height * 4) - bgl.glReadBuffer(bgl.GL_BACK) - bgl.glReadPixels(0, 0, ofs_width, ofs_height, bgl.GL_RGBA, - bgl.GL_UNSIGNED_BYTE, buff) + buff = fb.read_color(0, 0, ofs_width, ofs_height, 4, 0, 'UBYTE') ofs.free() - err = bgl.glGetError() - if err != bgl.GL_NO_ERROR: - print('render_image_offscreen') - print('OpenGL error:', err) - return buff, ofs_width, ofs_height + + def render_info_box(self, pos1, pos2): + prev_blend = gpu.state.blend_get() + gpu.state.blend_set('ALPHA') + + verts = [ + pos1, + (pos2[0], pos1[1]), + (pos1[0], pos2[1]), + pos2 + ] + + indices = [ + (0, 1, 2), + (2, 1, 3) + ] + + batch = batch_for_shader(self.default_shader, 'TRIS', + {"pos": verts}, indices=indices) + + self.default_shader.bind() + + self.default_shader.uniform_vector_float(self.default_shader_u_color, + np.array([0, 0, 0, 0.7], 'f'), 4) + + batch.draw(self.default_shader) + + gpu.state.blend_set(prev_blend) diff --git a/addon/utils.py b/addon/utils.py index 79ab5b8..d41b28b 100644 --- a/addon/utils.py +++ b/addon/utils.py @@ -1,5 +1,5 @@ ''' - Copyright (C) 2021 Akaneyu + Copyright (C) 2021 - 2024 Akaneyu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,24 +15,17 @@ along with this program. If not, see . ''' -import bpy import numpy as np def read_pixels_from_image(img): width, height = img.size[0], img.size[1] - if bpy.app.version >= (2, 83, 0): - pixels = np.empty(len(img.pixels), dtype=np.float32); - img.pixels.foreach_get(pixels) - return np.reshape(pixels, (height, width, 4)) - else: - return np.reshape(img.pixels[:], (height, width, 4)) + pixels = np.empty(len(img.pixels), dtype=np.float32); + img.pixels.foreach_get(pixels) + return np.reshape(pixels, (height, width, 4)) def write_pixels_to_image(img, pixels): - if bpy.app.version >= (2, 83, 0): - img.pixels.foreach_set(np.reshape(pixels, -1)) - else: - img.pixels = np.reshape(pixels, -1) + img.pixels.foreach_set(np.reshape(pixels, -1)) if img.preview: img.preview.reload()