0
$\begingroup$

In this script, I am taking two names, and printing them. The first name should be chosen from the menu or written manually (a new one).

import bpy

class NAME_MT_menu(bpy.types.Menu):
    bl_label = "List of existing names to choose"

    def draw(self, context):
        layout = self.layout
        for name in ('Peter', 'Patrick', 'John', 'Colom', 'Jerry'):
            layout.operator(NAME_OT_names_from_menu.bl_idname, text=name).name = name


class NAME_OT_names_from_menu(bpy.types.Operator):
    bl_idname = "name.names_from_menu"
    bl_label = "Add existing name to menu"
    name = bpy.props.StringProperty()

    def execute(self, context):
        # how to alter operator property while it's invoking
        return {"FINISHED"}


class NAME_OT_get(bpy.types.Operator):
    bl_idname = "name.get"
    bl_label = "Get names"
    first_name = bpy.props.StringProperty()
    second_name = bpy.props.StringProperty()

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def execute(self, context):

        print("Hi {} {}".format(self.first_name, self.second_name))

        return {"FINISHED"}
        # return {"CANCELLED"}

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.prop(self, 'first_name', text='')
        row.menu('NAME_MT_menu', text='')
        row = layout.row()
        row.prop(self, 'second_name', text='')


class NAME_PT_panel(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_label = 'My Panel'
    bl_context = 'objectmode'
    bl_category = 'Test'

    # drawing menu
    def draw(self, context):
        self.layout.operator(NAME_OT_get.bl_idname)


classes = (NAME_PT_panel, NAME_OT_get, NAME_OT_names_from_menu, NAME_MT_menu)

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

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

if __name__ == "__main__":
    register()

I know it can work if I will register first_name like this :

bpy.types.Scene.first_name = bpy.props.StringProperty()

and use context.scene.first_name instead of self.first_name, but it is like creating global variables, and I want to avoid this. Another issue with this solution is: when the name is chosen, the text field will not update until the user will hoover the mouse over it.

$\endgroup$

1 Answer 1

0
$\begingroup$

Since no one helped I changed approach. Instead of using a menu, I used enum property, with the update function.

import bpy

def update_names():
    def func(self, context):
        self.first_name = self.names
    return func

def get_items():
    def func(self, context):
        items = [(name, name, "") for name in sorted(('Peter', 'Patrick', 'John', 'Colom', 'Jerry'))]
        return items
    return func

class NAME_OT_get(bpy.types.Operator):
    bl_idname = "name.get"
    bl_label = "Get names"
    first_name = bpy.props.StringProperty()
    second_name = bpy.props.StringProperty()
    names = bpy.props.EnumProperty(items=get_items(), update=update_names())

    def check(self, context):
        return True

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def execute(self, context):

        print("Hi {} {}".format(self.first_name, self.second_name))

        return {"FINISHED"}
        # return {"CANCELLED"}

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.prop(self, 'first_name', text='')
        row.prop(self, 'names',text='')
        row = layout.row()
        row.prop(self, 'second_name', text='')


class NAME_PT_panel(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_label = 'My Panel'
    bl_context = 'objectmode'
    bl_category = 'Test'

    # drawing menu
    def draw(self, context):
        self.layout.operator(NAME_OT_get.bl_idname)


classes = (NAME_PT_panel, NAME_OT_get)

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

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

if __name__ == "__main__":
    register()

check() function is solving my problem with refreshing of first_name prop.

So I did not want to have global property, I have a global update() function instead. At least it is not registered as blender property. Is someone know how to make update function as a method in NAME_OT_get class?

$\endgroup$

You must log in to answer this question.

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