1
$\begingroup$

I was trying to go along with a 2.80 scripting tutorial.. But property names cannot be defined.

Invoke works as intended but no idea why this is failing.

import bpy
from bpy.types import (
    Operator,
    Panel,
    PropertyGroup,
)
from bpy.props import (
    BoolProperty,
    IntProperty,
    )


class Subdivide_operator(bpy.types.Operator):
    """Subdivide"""
    bl_idname = "object.subdivide_operator"
    bl_label = "Subdivide"
    bl_options = {'REGISTER', 'UNDO'}

    sub_visible: bpy.props.BoolProperty()
    sub_levels: bpy.props.IntProperty()

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

    def execute(self, context):
        subdivide = bpy.context.object.modifiers.new(type="SUBSURF",name="Qsubd_subdv")
        subdivide.show_viewport = sub_visible
        subdivide.levels = sub_levels
        bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Qsubd_subdv")

        return {'FINISHED'}   


class A_Panel(bpy.types.Panel):
    bl_label = "Layout Demo"
    bl_space_type = 'PROPERTIES'
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"


    def draw(self, context):
        layout = self.layout
        layout.operator("object.subdivide_operator")


def register():
    bpy.utils.register_class(A_Panel)    
    bpy.utils.register_class(Subdivide_operator)    

def unregister():
    bpy.utils.unregister_class(A_Panel)
    bpy.utils.unregister_class(Subdivide_operator)    

if __name__ == "__main__":
    register()

Invoked Popup menu

Error

$\endgroup$
0
2
$\begingroup$

Annotations are properties of the class instance

Bold question title, for what in the end is a python syntax error.

The error is because the property annotations of the operator need to be referenced from the instance (self)

subdivide.show_viewport = self.sub_visible

Without, the script is looking for a local variable sub_visible that is not defined. Error message in question

Recommend looking at the templates that come with blender Text Editor > Templates > Python and reading the documentation.

A clean up... spot the difference between this and question code. I use the nvim editor. It does a lot of clean up for me, or flags unused imports etc.

  • If imported, use the imported types and props.
  • Use the recommended naming convention for operator and panel types. See Docs.
  • When context is passed, use it. Don't get into the habit of bpy. everything.

Added min and max for subdivision property value. 0 and below will produce an error, trying to set to 12 could produce a meltdown.

A poll method as it requires an object and object mode and a mesh context.object.type == 'MESH'

import bpy
from bpy.types import (
    Operator,
    Panel,
)
from bpy.props import (
    BoolProperty,
    IntProperty,
)


class OBJECT_OT_subdivide(Operator):
    """Subdivide"""
    bl_idname = "object.subdivide"
    bl_label = "Subdivide"
    bl_options = {'REGISTER', 'UNDO'}

    sub_visible: BoolProperty()
    sub_levels: IntProperty(
        min=1,
        soft_max=6)

    @classmethod
    def poll(self, context):
        ob = context.object
        return ob and ob.mode == 'OBJECT' and ob.type == 'MESH'

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

    def execute(self, context):
        subdivide = context.object.modifiers.new(
            type='SUBSURF',
            name="Qsubd_subdv")
        subdivide.show_viewport = self.sub_visible
        subdivide.levels = self.sub_levels
        bpy.ops.object.modifier_apply(
            apply_as='DATA',
            modifier=subdivide.name)

        return {'FINISHED'}


class OBJECT_PT_subdivide(Panel):
    bl_label = "Layout Demo"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout
        layout.operator("object.subdivide")


classes = (OBJECT_PT_subdivide,
           OBJECT_OT_subdivide,
           )


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()
$\endgroup$
1
  • $\begingroup$ Thank you for the detailed response! I can't believe I forgot self lol. $\endgroup$ Feb 23 '20 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.