4
$\begingroup$

I have an object named Cubeä and when I try to select that object from the operator enum it gives an error.

enter image description here

import bpy
from bpy.types import Operator, Panel


class OBJECT_OT_object_add(Operator):
    '''Add an object'''

    bl_label = 'Add'
    bl_idname = 'object.object_add'
    bl_options = {'REGISTER', 'INTERNAL'}
    bl_property = 'object'

    def object_enum(self, context):
        return (
            (object.name, object.name, '', 'OBJECT_DATA', index)
            for index, object in enumerate(context.scene.objects)
            if object.type == 'MESH'
        )

    object : bpy.props.EnumProperty(items=object_enum)

    def invoke(self, context, event):
        context.window_manager.invoke_search_popup(self)
        return {'RUNNING_MODAL'}

    def execute(self, context):
        print(bpy.data.objects.get(self.object))

        return {'FINISHED'}


class HelloWorldPanel(Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Test"

    def draw(self, context):
        layout = self.layout

        layout.operator('object.object_add')


classes = (
    OBJECT_OT_object_add,
    HelloWorldPanel
)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)


def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)


if __name__ == "__main__":
    register()

Got this error:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 0: invalid start byte

$\endgroup$
4
  • 1
    $\begingroup$ Hello, most likely this blender.stackexchange.com/q/216230/86891 $\endgroup$
    – Gorgious
    Aug 28, 2023 at 6:14
  • $\begingroup$ @Gorgious in this case it's confusing because the list gets generated with context.window_manager.invoke_search_popup(self). I'm not able to fix it. Could you be so kind and present the solution here? in the mean time i have voted to close as bug. $\endgroup$ Aug 28, 2023 at 8:39
  • 1
    $\begingroup$ @HarryMcKenzie sure thing, please see my answer. However I would not close it as it is not a regular bug but a "known limitation" - as acknowledged by the devs and stated in the Blender documentation. I would however close it as a duplicate $\endgroup$
    – Gorgious
    Aug 28, 2023 at 9:12
  • $\begingroup$ Thank You @Gorgious! $\endgroup$ Aug 28, 2023 at 9:37

1 Answer 1

3
$\begingroup$

The dictionary solution should do it. Please see this Q&A for a more thorough explanation.

import bpy
from bpy.types import Operator, Panel

STRING_CACHE = {}
def intern_enum_items(items):
    def intern_string(s):
        if not isinstance(s, str):
            return s
        global STRING_CACHE
        if s not in STRING_CACHE:
            STRING_CACHE[s] = s
        return STRING_CACHE[s]
    return [tuple(intern_string(s) for s in item) for item in items]


def get_my_stuff(self, context):
    items = [
            (object.name, object.name, '', 'OBJECT_DATA', index)
            for index, object in enumerate(context.scene.objects)
            if object.type == 'MESH'
        ]
    return intern_enum_items(items)


class OBJECT_OT_object_add(Operator):
    '''Add an object'''

    bl_label = 'Add'
    bl_idname = 'object.object_add'
    bl_options = {'REGISTER', 'INTERNAL'}
    bl_property = 'object'

    object : bpy.props.EnumProperty(items=get_my_stuff)

    def invoke(self, context, event):
        context.window_manager.invoke_search_popup(self)
        return {'RUNNING_MODAL'}

    def execute(self, context):
        print(bpy.data.objects.get(self.object))

        return {'FINISHED'}


class HelloWorldPanel(Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Test"

    def draw(self, context):
        layout = self.layout

        layout.operator('object.object_add')


classes = (
    OBJECT_OT_object_add,
    HelloWorldPanel
)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)


def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)


if __name__ == "__main__":
    register()
$\endgroup$
3
  • 1
    $\begingroup$ Note: the shorter solution (with the function attribute) in the Q&A also works. One just needs to be careful to not use ((...)...) but [(...)...] or tuple((...)...) when filtering and caching the items. The first creates a generator object and not a tuple of tuples and caching the generator is pointless. $\endgroup$
    – taiyo
    Aug 28, 2023 at 9:49
  • $\begingroup$ @taiyo You are right and that totally makes sense ! I first tested with the function attribute and kept the generator and still had the error so I elected for the dictionary wich is a mouthful to say the least. If the first solution works then I would advise to use it, much simpler (IMO). I'll add the information to my answer there. Thanks for the advice ! $\endgroup$
    – Gorgious
    Aug 28, 2023 at 9:59
  • $\begingroup$ For this problem the global dictionary looks like overkill (still working though). In the Q&A, @scurest mentions in his answer there were still problems with bpy.types.Object. The dictionary solution may be necessary for such a scenario, where the objects can outlive the content of the function attribute. $\endgroup$
    – taiyo
    Aug 28, 2023 at 10:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .