I am trying to Draw Dynamic Enum property and I started using a one of the templates provided with the blender.
What I am trying to do: I have a Folder Test 2 in which I have 2 Folders -
- Blends
- Icons
and a __ init __.py in which I am drawing Enum.
I want to import icons from the Icons folder and for each icon, the object should be appended from the Objects.blend file present in the Blends folder.
my icons are cube, sphere, plane, Suzanne...., A cube should be appended when I select cube icon and hit add button, and similarly, the sphere should be appended when clicked on sphere icon (I have used cube, sphere, etc objects as an example, in future I will be replacing these object with the actual object I want to import).The object to be imported and icon for it has exactly the same name
If anyone wants to try complete file here is the link - To get files, Click here
So, this is my__ init __.py file -
bl_info = {
"name": "Add Object",
"author": "Rakesh",
"version": (1, 0),
"blender": (2, 83, 0),
"location": "View3D > Add > Mesh > New Object",
"description": "Adds a new Mesh Object",
"warning": "",
"category": "Add Mesh",
}
import bpy
import os
from bpy.types import (
Operator,
Panel,
PropertyGroup,
)
from bpy.props import *
import bpy.utils.previews
from bpy.types import WindowManager
class Object_OT_AddButton(Operator):
bl_idname = "add.object"
bl_label = "Add Object"
def execute(self, context):
selected_preview = bpy.data.window_managers["WinMan"].my_previews
category = context.scene.my_tool.cat
bpy.ops.wm.append(directory=os.path.join(os.path.dirname(__file__), "Blends" + os.sep + category +
".blend" + os.sep + "Object"), filepath=category + ".blend", filename=selected_preview)
return{'FINISHED'}
def update_category(self, context):
enum_previews_from_directory_items(self, context)
class Categories(PropertyGroup):
mesh_options = [
("Objects", "Objects", '', 0),
]
cat = bpy.props.EnumProperty(
items=mesh_options,
description="Select a Category",
default="Objects",
update=update_category
)
def enum_previews_from_directory_items(self, context):
category = context.scene.my_tool.cat
# Icons Directory
directory = os.path.join(os.path.dirname(
__file__), "Icons" + os.sep + category)
enum_items = []
if context is None:
return enum_items
wm = context.window_manager
directory = wm.my_previews_dir
# Get the preview collection (defined in register func).
pcoll = preview_collections["main"]
if directory == pcoll.my_previews_dir:
return pcoll.my_previews
print("Scanning directory: %s" % directory)
if directory and os.path.exists(directory):
# Scan the directory for png files
image_paths = []
for fn in os.listdir(directory):
if fn.lower().endswith(""):
image_paths.append(fn)
for i, name in enumerate(image_paths):
# generates a thumbnail preview for a file.
filepath = os.path.join(directory, name)
icon = pcoll.get(name)
if filepath in pcoll:
enum_items.append((name, name, "", pcoll[filepath].icon_id, i))
else:
thumb = pcoll.load(filepath, filepath, 'IMAGE')
enum_items.append((name, name, "", thumb.icon_id, i))
pcoll.my_previews = enum_items
pcoll.my_previews_dir = directory
return pcoll.my_previews
class PreviewsExamplePanel(Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Add object Panel"
bl_idname = "OBJECT_PT_previews"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
wm = context.window_manager
scene = context.scene
mytool = scene.my_tool
col = layout.column()
col.prop(context.scene.my_tool, "cat", text="Category")
row = layout.row()
row.template_icon_view(wm, "my_previews", show_labels=True)
row = layout.row()
row.operator("add.object", icon="RESTRICT_RENDER_OFF", text="Add")
# We can store multiple preview collections here,
# however in this example we only store "main"
preview_collections = {}
def register():
from bpy.types import WindowManager
from bpy.props import (
StringProperty,
EnumProperty,
)
WindowManager.my_previews_dir = StringProperty(
name="Folder Path",
subtype='DIR_PATH',
default=""
)
WindowManager.my_previews = EnumProperty(
items=enum_previews_from_directory_items,
)
import bpy.utils.previews
pcoll = bpy.utils.previews.new()
pcoll.my_previews_dir = ""
pcoll.my_previews = ()
preview_collections["main"] = pcoll
bpy.utils.register_class(Object_OT_AddButton)
bpy.utils.register_class(Categories)
bpy.types.Scene.my_tool = PointerProperty(type=Categories)
bpy.utils.register_class(PreviewsExamplePanel)
def unregister():
from bpy.types import WindowManager
del WindowManager.my_previews
for pcoll in preview_collections.values():
bpy.utils.previews.remove(pcoll)
preview_collections.clear()
bpy.utils.unregister_class(Object_OT_AddButton)
bpy.utils.unregister_class(Categories)
del bpy.types.Scene.my_tool
bpy.utils.unregister_class(PreviewsExamplePanel)
if __name__ == "__main__":
register()
Issues I am facing -
- Error: Traceback (most recent call last): File "C:\Users\ADMIN\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\test2_init_.py", line 31, in execute ".blend" + os.sep + "Object"), filepath=category + ".blend", filename=selected_preview) File "C:\Program Files\Blender Foundation\Blender 2.83\2.83\scripts\modules\bpy\ops.py", line 201, in call ret = op_call(self.idname_py(), None, kw)
RuntimeError: Error: 'C:\Users\ADMIN\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\test2\Blends\Objects.blend\Object': nothing indicated
location: < unknown location >:-1
- The issue shown above is not reported normally, I mean by this is when I press the button this error is shown, otherwise no errors are shown.
This is what my panel looks like -
when I click that add button I get that error, the reason of the error what I believe is some thing is wrong in importing icons as icons are not imported and without selecting any icon i am clicking add and that gives the error -
RuntimeError: Error: 'C:\Users\ADMIN\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\test2\Blends\Objects.blend\Object': nothing indicated
I am trying to achieve this type of Panel, In this panel, a particle system is added but I don't want any particle system I just want the object to be appended to the scene when the icon from the dynamic enum is clicked.
Reference Image -
category = context.scene.object.cat
suggests some pointer propertyobject
is set onScene
type to propertygroup above. But It isn't. $\endgroup$Categories
class hasn't been registered? Please make some effort to debug code, or look for answers, before posting each error message. $\endgroup$bpy.types.Scene.object = PointerProperty(...
Then the scene will havescene.object.cat
consult the documentation Was an absolute beginner at one stage too. May sound counter-intuitive but consider disconnecting from net for an hour or so and nut these things out. Coding is logic. eg Scene has no object property, when you think about it you don't really need someone telling you what this means. $\endgroup$