I’m trying to use custom icon - rendered in offscreen - for EnumProperty
but icons does not show up. But if i use template_icon_view()
icons shows up fine.
Check icon shown in template_icon_view but not in below.
If I use regular blender icons like ‘CUBE’, ‘ADD’ , icons shows up everywhere fine.
I can’t seem to figure out the what causes this. Any help would be appreciated. I’m attaching script - when executed you can access operator in sidebar-view3d.
import bpy
import gpu
import bgl
from mathutils import Matrix
import bpy.utils.previews
WIDTH = 128
HEIGHT = 128
preview_collections = None
def main(context):
for ob in context.scene.objects:
print(ob)
def draw_solid_color(color,width,height):
from gpu.types import (
GPUBatch,
GPUVertBuf,
GPUVertFormat,
)
coords = ((-1, -1), (1, -1), (1, 1), (-1, 1))
indices = ((0, 1, 2), (0, 2, 3))
with gpu.matrix.push_pop():
# gpu.matrix.translate(position)
gpu.matrix.scale((width, height))
verts = list(coords)
fmt = GPUVertFormat()
pos_id = fmt.attr_add(id="pos", comp_type='F32', len=2, fetch_mode='FLOAT')
vbo = GPUVertBuf(len=len(verts), format=fmt)
vbo.attr_fill(id=pos_id, data=verts)
ibo = gpu.types.GPUIndexBuf(type='TRIS', seq=indices)
batch = GPUBatch(type='TRIS', buf=vbo, elem = ibo)
shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
batch.program_set(shader)
shader.uniform_float("color", color)
batch.draw()
def offscreen_render(color=(1.0,1.0,1.0,1.0)):
COLOR = color
offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)
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))
# Need some code to write solid color to buffer
draw_solid_color(COLOR,WIDTH,HEIGHT)
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()
return buffer
def create_icon(buffer,icon_name):
global preview_collections
if(not preview_collections):
preview_collections = bpy.utils.previews.new()
try:
iprev = preview_collections.new(icon_name)
except:
iprev = preview_collections[icon_name]
iprev.image_size = (WIDTH,HEIGHT)
iprev.image_pixels_float = [v / 255 for v in buffer]
class SimpleOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.simple_operator"
bl_label = "---- Click This ----"
def get_items(self,context):
# using custom icons
# items = [(icon_name,icon_name,'',preview_collections[icon_name].icon_id,i)
# for i,icon_name in enumerate(['col1','col2','col3','col4','col5'])]
# using default icons
items = [(icon_name,icon_name,'','CUBE',i)
for i,icon_name in enumerate(['col1','col2','col3','col4','col5'])]
return items
enum : bpy.props.EnumProperty(
name="Color",
items=get_items,
options = {'HIDDEN'}
)
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
print(self.enum)
main(context)
context.scene.target = self.enum
return {'FINISHED'}
def invoke(self,context,event):
buffer = offscreen_render(context.scene.icon_color)
create_icon(buffer,'col1')
buffer = offscreen_render(context.scene.icon_color)
create_icon(buffer,'col2')
buffer = offscreen_render(context.scene.icon_color)
create_icon(buffer,'col3')
buffer = offscreen_render(context.scene.icon_color)
create_icon(buffer,'col4')
buffer = offscreen_render(context.scene.icon_color)
create_icon(buffer,'col5')
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
layout = self.layout
row = layout.row()
row.template_icon_view(self,"enum",scale = 5)
row = layout.row()
row.prop_tabs_enum(self,"enum",icon_only= True)
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "World Panel"
bl_idname = "OBJECT_PT_World"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(context.scene,"icon_color")
row = layout.row()
row.prop(context.scene,"target")
row = layout.row()
row.operator("object.simple_operator")
def register():
bpy.utils.register_class(SimpleOperator)
bpy.utils.register_class(HelloWorldPanel)
import sys
bpy.types.Scene.icon_color = bpy.props.FloatVectorProperty(name="icon_color",
description="icon_color",
default=(0.0, 0.0, 0.0, 1.0),
soft_min=0,
soft_max=1,
min=sys.float_info.min,
max=sys.float_info.max,
subtype='COLOR_GAMMA',
size=4,
)
bpy.types.Scene.target = bpy.props.StringProperty()
def unregister():
for pcoll in preview_collections.values():
bpy.utils.previews.remove(pcoll)
preview_collections.clear()
bpy.utils.unregister_class(HelloWorldPanel)
bpy.utils.unregister_class(SimpleOperator)
del bpy.types.Scene.icon_color
del bpy.types.Scene.target
if __name__ == "__main__":
register()