111 lines
3.2 KiB
Python
111 lines
3.2 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]
|
|
|
|
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)
|
|
|
|
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():
|
|
bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
|
|
bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
|
|
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))
|
|
|
|
bgl.glLineWidth(4)
|
|
bgl.glEnable( bgl.GL_LINE_SMOOTH )
|
|
bgl.glEnable(bgl.GL_BLEND)
|
|
|
|
shader.bind()
|
|
shader.uniform_float("color", (0, 0, 0, 0.1))
|
|
batch.draw(shader)
|
|
|
|
bgl.glLineWidth(2)
|
|
shader.uniform_float("color", (0.85, 0.85, 0.85, 1))
|
|
batch.draw(shader)
|
|
|
|
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 = 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)
|
|
|
|
#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 = [v / 255 for v in buffer]
|
|
|
|
image.save_render(str(filepath))
|
|
|