Support Blender 4.0
This commit is contained in:
parent
91cb6a9356
commit
9913ae8c35
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,8 @@
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Image Editor Plus",
|
"name": "Image Editor Plus",
|
||||||
"author": "akaneyu",
|
"author": "akaneyu",
|
||||||
"version": (1, 7, 3),
|
"version": (1, 8, 0),
|
||||||
"blender": (2, 93, 0),
|
"blender": (3, 3, 0),
|
||||||
"location": "Image",
|
"location": "Image",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
|
|
21
addon/app.py
21
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
|
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
|
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_rotating \
|
||||||
or area_session.layer_scaling:
|
or area_session.layer_scaling:
|
||||||
|
|
||||||
info_text = "LMB: Perform\n" \
|
info_text = "LMB: Perform " \
|
||||||
+ "RMB: Cancel"
|
+ "RMB: Cancel"
|
||||||
|
|
||||||
area_height = context.area.height
|
area_width = context.area.width
|
||||||
|
|
||||||
# info text
|
# info text
|
||||||
if info_text:
|
if info_text:
|
||||||
blf.enable(0, blf.WORD_WRAP)
|
ui_scale = context.preferences.system.ui_scale
|
||||||
blf.word_wrap(0, 100)
|
|
||||||
|
|
||||||
blf.position(0, 30, area_height - 70, 0)
|
session.ui_renderer.render_info_box((0, 0), (area_width, 20 * ui_scale))
|
||||||
blf.size(0, 14, 72)
|
|
||||||
|
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.draw(0, info_text)
|
||||||
|
|
||||||
blf.disable(0, blf.WORD_WRAP)
|
|
||||||
|
|
||||||
def get_curve_node():
|
def get_curve_node():
|
||||||
node_group = bpy.data.node_groups.get('imageeditorplus')
|
node_group = bpy.data.node_groups.get('imageeditorplus')
|
||||||
if not node_group:
|
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)
|
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
|
# gamma correction
|
||||||
utils.convert_colorspace(pixels, 'Linear',
|
utils.convert_colorspace(pixels, 'Linear',
|
||||||
|
|
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,10 +17,6 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import math
|
import math
|
||||||
import time
|
|
||||||
import bpy
|
|
||||||
import bgl
|
|
||||||
import blf
|
|
||||||
import gpu
|
import gpu
|
||||||
from gpu_extras.batch import batch_for_shader
|
from gpu_extras.batch import batch_for_shader
|
||||||
from mathutils import Matrix, Vector
|
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)):
|
def render_selection_frame(self, pos, size, rot=0, scale=(1.0, 1.0)):
|
||||||
width, height = size[0], size[1]
|
width, height = size[0], size[1]
|
||||||
|
|
||||||
bgl.glEnable(bgl.GL_BLEND)
|
prev_blend = gpu.state.blend_get()
|
||||||
bgl.glLineWidth(2.0)
|
gpu.state.blend_set('ALPHA')
|
||||||
|
|
||||||
|
gpu.state.line_width_set(2.0)
|
||||||
|
|
||||||
with gpu.matrix.push_pop():
|
with gpu.matrix.push_pop():
|
||||||
verts = [[0, 0], [0, height], [width, height], [width, 0], [0, 0]]
|
verts = [[0, 0], [0, height], [width, height], [width, 0], [0, 0]]
|
||||||
|
@ -172,20 +170,12 @@ class UIRenderer:
|
||||||
|
|
||||||
batch.draw(self.dotted_line_shader)
|
batch.draw(self.dotted_line_shader)
|
||||||
|
|
||||||
err = bgl.glGetError()
|
gpu.state.blend_set(prev_blend)
|
||||||
if err != bgl.GL_NO_ERROR:
|
|
||||||
print('render_selection_frame')
|
|
||||||
print('OpenGL error:', err)
|
|
||||||
|
|
||||||
def render_image_sub(self, img, pos, size, rot, scale):
|
def render_image_sub(self, img, pos, size, rot, scale):
|
||||||
width, height = size[0], size[1]
|
width, height = size[0], size[1]
|
||||||
|
|
||||||
img.gl_load()
|
texture = gpu.texture.from_image(img)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
with gpu.matrix.push_pop():
|
with gpu.matrix.push_pop():
|
||||||
gpu.matrix.translate([pos[0] + width / 2.0, pos[1] + height / 2.0])
|
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.bind()
|
||||||
|
|
||||||
self.image_shader.uniform_int('image', 0)
|
self.image_shader.uniform_sampler('image', texture)
|
||||||
|
|
||||||
batch.draw(self.image_shader)
|
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)):
|
def render_image(self, img, pos, size, rot=0, scale=(1.0, 1.0)):
|
||||||
bgl.glEnable(bgl.GL_BLEND)
|
prev_blend = gpu.state.blend_get()
|
||||||
# FIXME: glBlendFuncSeparate does not seem to be implemented,
|
gpu.state.blend_set('ALPHA')
|
||||||
# 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);
|
|
||||||
|
|
||||||
self.render_image_sub(img, pos, size, rot, scale)
|
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)):
|
def render_image_offscreen(self, img, rot=0, scale=(1.0, 1.0)):
|
||||||
width, height = img.size[0], img.size[1]
|
width, height = img.size[0], img.size[1]
|
||||||
|
|
||||||
|
@ -248,10 +232,8 @@ class UIRenderer:
|
||||||
|
|
||||||
ofs = gpu.types.GPUOffScreen(ofs_width, ofs_height)
|
ofs = gpu.types.GPUOffScreen(ofs_width, ofs_height)
|
||||||
with ofs.bind():
|
with ofs.bind():
|
||||||
bgl.glDisable(bgl.GL_BLEND)
|
fb = gpu.state.active_framebuffer_get()
|
||||||
|
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||||
bgl.glClearColor(0, 0, 0, 0)
|
|
||||||
bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
with gpu.matrix.push_pop():
|
with gpu.matrix.push_pop():
|
||||||
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
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)
|
self.render_image_sub(img, [0, 0], [width, height], rot, scale)
|
||||||
|
|
||||||
buff = bgl.Buffer(bgl.GL_BYTE, ofs_width * ofs_height * 4)
|
buff = fb.read_color(0, 0, ofs_width, ofs_height, 4, 0, 'UBYTE')
|
||||||
bgl.glReadBuffer(bgl.GL_BACK)
|
|
||||||
bgl.glReadPixels(0, 0, ofs_width, ofs_height, bgl.GL_RGBA,
|
|
||||||
bgl.GL_UNSIGNED_BYTE, buff)
|
|
||||||
|
|
||||||
ofs.free()
|
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
|
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)
|
||||||
|
|
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,24 +15,17 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import bpy
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
def read_pixels_from_image(img):
|
def read_pixels_from_image(img):
|
||||||
width, height = img.size[0], img.size[1]
|
width, height = img.size[0], img.size[1]
|
||||||
|
|
||||||
if bpy.app.version >= (2, 83, 0):
|
|
||||||
pixels = np.empty(len(img.pixels), dtype=np.float32);
|
pixels = np.empty(len(img.pixels), dtype=np.float32);
|
||||||
img.pixels.foreach_get(pixels)
|
img.pixels.foreach_get(pixels)
|
||||||
return np.reshape(pixels, (height, width, 4))
|
return np.reshape(pixels, (height, width, 4))
|
||||||
else:
|
|
||||||
return np.reshape(img.pixels[:], (height, width, 4))
|
|
||||||
|
|
||||||
def write_pixels_to_image(img, pixels):
|
def write_pixels_to_image(img, pixels):
|
||||||
if bpy.app.version >= (2, 83, 0):
|
|
||||||
img.pixels.foreach_set(np.reshape(pixels, -1))
|
img.pixels.foreach_set(np.reshape(pixels, -1))
|
||||||
else:
|
|
||||||
img.pixels = np.reshape(pixels, -1)
|
|
||||||
|
|
||||||
if img.preview:
|
if img.preview:
|
||||||
img.preview.reload()
|
img.preview.reload()
|
||||||
|
|
Loading…
Reference in New Issue