124 lines
3.5 KiB
Python
124 lines
3.5 KiB
Python
|
|
import bpy
|
|
import bmesh
|
|
import numpy as np
|
|
import bgl
|
|
from mathutils import Vector, Matrix
|
|
import gpu
|
|
from gpu_extras.batch import batch_for_shader
|
|
|
|
|
|
def bounds_2d_co(coords, width, height):
|
|
from bpy_extras.view3d_utils import location_3d_to_region_2d as space_2d
|
|
|
|
region = bpy.context.region
|
|
rv3d = bpy.context.space_data.region_3d
|
|
|
|
co_2d = [space_2d(region, rv3d, co) for co in coords]
|
|
|
|
print("co_2d", co_2d)
|
|
|
|
x_value = sorted(co_2d, key=lambda x:x[0])
|
|
y_value = sorted(co_2d, key=lambda x:x[1])
|
|
|
|
min_x = x_value[0][0]
|
|
min_y = y_value[0][1]
|
|
|
|
box_width = x_value[-1][0] - min_x
|
|
box_height = y_value[-1][1] - min_y
|
|
|
|
x_margin = 1 / width # one pixel margin
|
|
y_margin = 1 / height
|
|
|
|
scale_fac = 2 / max(box_width, box_height)
|
|
|
|
if box_width < box_height :
|
|
center_offset = (box_height - box_width) /2
|
|
min_x -= center_offset
|
|
else :
|
|
center_offset = (box_width - box_height) /2
|
|
min_y -= center_offset
|
|
|
|
co_2d_bounds = []
|
|
for co in co_2d:
|
|
x = (co[0] - min_x) *scale_fac * (1 - 2*x_margin) -1 + x_margin#+ x_offset
|
|
y = (co[1] - min_y) *scale_fac * (1 - 2*y_margin) -1 + y_margin#-height/2 #* (1-y_offset) #+ y_offset
|
|
|
|
co_2d_bounds.append(Vector((x, y)))
|
|
|
|
|
|
return co_2d_bounds
|
|
|
|
|
|
def render_widget(shape, filepath, width=32, height=32) :
|
|
dg = bpy.context.evaluated_depsgraph_get()
|
|
|
|
bm = bmesh.new()
|
|
bm.from_object(shape, dg)
|
|
|
|
width *= 2
|
|
height *= 2
|
|
|
|
coords = [shape.matrix_world @ v.co for v in bm.verts]
|
|
coords = bounds_2d_co(coords, width, height)
|
|
|
|
indices = [(e.verts[0].index, e.verts[1].index) for e in bm.edges]
|
|
|
|
bm.free()
|
|
|
|
offscreen = gpu.types.GPUOffScreen(width, height)
|
|
shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
|
|
batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)
|
|
|
|
with offscreen.bind():
|
|
fb = gpu.state.active_framebuffer_get()
|
|
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
|
with gpu.matrix.push_pop():
|
|
# reset matrices -> use normalized device coordinates [-1, 1]
|
|
gpu.matrix.load_matrix(Matrix.Identity(4))
|
|
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
|
|
|
|
|
shader.bind()
|
|
gpu.state.line_width_set(4*2)
|
|
#bgl.glEnable(bgl.GL_BLEND)
|
|
#bgl.glEnable( bgl.GL_LINE_SMOOTH )
|
|
shader.uniform_float("color", (0, 0, 0, 0.2))
|
|
batch.draw(shader)
|
|
|
|
gpu.state.line_width_set(2*2)
|
|
shader.uniform_float("color", (0.85, 0.85, 0.85, 1))
|
|
batch.draw(shader)
|
|
|
|
buffer = fb.read_color(0, 0, width, height, 4, 0, 'FLOAT')
|
|
buffer.dimensions = width * height * 4
|
|
#buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4)
|
|
#bgl.glReadBuffer(bgl.GL_BACK)
|
|
#bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
|
|
|
|
offscreen.free()
|
|
|
|
#icon_name = '.' + shape.name + '_icon.png'
|
|
icon_name = f'.{shape.name}_icon.png'
|
|
image = bpy.data.images.get(icon_name)
|
|
|
|
if image:
|
|
bpy.data.images.remove(image)
|
|
|
|
image = bpy.data.images.new(icon_name, width, height, alpha=True, float_buffer=True)
|
|
|
|
#image_data = np.asarray(buffer, dtype=np.uint8)
|
|
#image.pixels.foreach_set(image_data.flatten()/255)
|
|
|
|
#image_data = np.asarray(buffer, dtype=np.uint8)
|
|
image.pixels.foreach_set(buffer)
|
|
|
|
image.scale(int(width/2), int(height/2))
|
|
|
|
image.filepath_raw = str(filepath)
|
|
|
|
image.save()
|
|
|
|
bpy.data.images.remove(image)
|
|
|