# How do I reference a variable from an operator that's outside of a class?

Alright, this might be one of the more complicated questions I've asked on here. However, due to my lack of experience coding in Blender, it might be a more simple solution than I realize.

Summary:

I'm coding an addon that allows the user to select one camera from the scene, up to three light objects from the scene, and up to three mesh objects from the scene. At first, there is no option to add another light object or mesh object, but once an option has been selected the operator button pops up.

I want the operator button that pops up to increase the count of the associated pointer so that it will create another pointer for that category. I begin to run into issues when I try to reference the variable "num_lights" or "num_layers" from either operator in the "ADDON_PT_main_panel" class, though. I feel like it should be easy to do that but I can't get it to work nor can I find any helpful information on Google.

Question 1:

Question 1a:

Am I using the correct script to update the "ADDON_PT_main_panel" class once either of the operators has been executed?

I know this is kind of a loaded question but if anyone could help me figure this out I would really appreciate it!

My Code:

class ADDON_OT_add_light(bpy.types.Operator):

# Operator that increases "num_lights" by one every time
# that it's clicked as long as "num_lights" is less than 3,

bl_label = ''
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

num_lights = 1

# Increases count for number of light sources by 1 when clicked until it hits the limit.
# of 3 light sources.
def execute(self, context):
if num_lights < 3:
num_lights += 1
return num_lights

# Operator that increases "num_layers" by one every time
# that it's clicked as long as "num_layers" is less than 3,

bl_label = ''
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

num_layers = 1

# Increases count for number of base layers by 1 when clicked until it hits the limit.
# of 3 base layers.
def execute(self, context):
if num_layers < 3:
num_layers += 1
return num_layers

bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

def draw(self, context):
layout = self.layout
scene = context.scene
mytool = scene.my_tool

layout.label(text= "Camera:")
layout.prop(mytool, "camera_pointer")

layout.label(text= "Light Source(s):")
layout.prop(mytool, "lights_pointers")

# Determines whether or not an option has been selected for "lights_pointers".
light_pointer_status = str(bpy.context.scene.my_tool.lights_pointers)

# If number of light sources is updated to 2, then add another "lights_pointers".
if light_sources > 1:
layout.prop(mytool, "lights_pointers")

# If number of light sources is updated to 3, then add another "lights_pointers".
if light_sources > 2:
layout.prop(mytool, "lights_pointers")

# Only allows a new light source to be added if a first option has been chosen.
if light_pointer_status != 'None':
layout.operator("add_light.operator", text= "New Light", icon= "PLUS")

layout.label(text= "Base Layer Object(s):")
layout.prop(mytool, "objects_pointers")

# Determines whether or not an option has been selected for "layers_pointers".
object_pointer_status = str(bpy.context.scene.my_tool.objects_pointers)

# If number of base layers is updated to 2, then add another "objects_pointers".
if base_layers > 1:
layout.prop(mytool, "objects_pointers")

# If number of base layers is updated to 3, then add another "objects_pointers".
if base_layers > 2:
layout.prop(mytool, "objects_pointers")

# Only allows a new base layer to be added if a first option has been chosen.
if object_pointer_status != 'None':
layout.operator("add_layer.operator", text= "New Layer", icon= "PLUS")

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

def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
del bpy.types.Scene.my_tool

if __name__ == "__main__":
register()


First, you need to put all your state somewhere Blender can keep track of it. So you should handle the number of items just like the other properties, with an IntProperty. Here's an example with three object properties.


num_objects: bpy.props.IntProperty(
name= "Number of Objects",
description= "",
min=0,
max=3,
)

object0 : bpy.props.PointerProperty(
name= "Object",
description= "",
type= bpy.types.Object,
)

object1 : bpy.props.PointerProperty(
name= "Object",
description= "",
type= bpy.types.Object,
)

object2 : bpy.props.PointerProperty(
name= "Object",
description= "",
type= bpy.types.Object,
)


Let's add an operator to increase num_objects:


bl_label = ''
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

# poll returns True if the operator can be called now
@classmethod
def poll(cls, context):
scene = context.scene
if not scene: return False
mytool = scene.my_tool

if mytool.num_objects >= 3:
return False

# If the current slots are not all filled, can't add any more
objs = [mytool.object0, mytool.object1, mytool.object2]
objs = objs[:mytool.num_objects]
if not all(objs):
return False

return True

def execute(self, context):
context.scene.my_tool.num_objects += 1
return {'FINISHED'}


Now the panel

class ADDON_PT_main_panel(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

def draw(self, context):
layout = self.layout
scene = context.scene
mytool = scene.my_tool

for i in range(mytool.num_objects):
layout.prop(mytool, "object%d" % i)

# Skip drawing the button if it can't be clicked
layout.operator("my_tool.add_object", text= "New Object", icon= "PLUS")

• Thank you so much! It worked, and I even created a second operator that removes a pointer using the same code, except I converted it to subtract 1 rather than add. You've definitely made my night a lot easier! Nov 9, 2021 at 22:50

Here's another answer: get rid of the variable for the number of objects and the button for adding a new slot. Instead just show all the slots up the last filled one, plus one more (up to a max of 3).

Simpler code, simpler UI.

class ADDON_PT_main_panel(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

def draw(self, context):
layout = self.layout
scene = context.scene
mytool = scene.my_tool

if mytool.object2: num_objects = 3
elif mytool.object1: num_objects = 3
elif mytool.object0: num_objects = 2
else: num_objects = 1

for i in range(num_objects):
layout.prop(mytool, "object%d" % i)