Dynamically accessing variables from UI panel

TLDR: once I import my parameters file, I’m never getting the updated parameter
I built a multi-file particle simulator for blender. The relevant files are params.py (which globally holds basic parameters), Particle_System.py (which holds the Class ParticleSystem that I want to access), and Blender_UI (which builds the UI).

in params.py:

particle_system = None

in main.py:

import params
from Particle_System import ParticleSystem
print("Original particle system is ", params.particle_system)
params.particle_system = ParticleSystem(...)
print("New particle system is ", params.particle_system)

in Blender_UI:

import params
# this function runs when the "activate" button is clicked
class LIST_OT_ActivateItem(Operator):
    bl_idname = "my_list.activate_item"
    bl_label = "Activates an item"

    @classmethod
    def poll(cls, context):
        return context.scene.my_list

    def execute(self, context):
        my_list = context.scene.my_list
        index = context.scene.list_index
        print("Current particle system is ", params.particle_system)

This prints out…
Original particle system is None
New particle system is <Particle_System.ParticleSystem object at 0x133244190>

and when I click activate, prints out
Current particle system is None

I want this to print out <Particle_System.ParticleSystem object at 0x133244190>, but am having a really hard time accessing this object from the UI panel.

Welcome to BA :slight_smile:

What happens when you do click the activate button? What’s the console output? I have some guesses about things you might need to change in your code but it’s hard to say for sure without more details :slight_smile:

1 Like

sorry- just updated! I accidentally posted mid-writing…

I’m also not attached to this specific way of doing things, but I do need to access the instance of the class I’m creating in main from the UI

Ok cool exactly what I thought, you need persistent data. There’s two ways to do this, with a Globals class or using PropertyGroups. Globals is simpler, here’s how that works: How to change a label text dynamically? - #2 by josephhansen

I am using a property group, I just had trouble finding a property that would support a custom class. I couldn’t get the PointerProperty to work…

class ListItem(PropertyGroup):
    """Group of properties representing an item in the list."""

    particle_num: IntProperty(
           name="Particle Number",
           description="Index of the particle to edit",
           default=0,
           min = 0,
           max = 100,
           subtype='UNSIGNED')

    action_str: EnumProperty(
            name="Action",
            description="Choose an action for display with the associated particle",
            items=[
            ('Show displacement vectors', 'Show displacement vectors', 'Shows the displacement occured by each neighbor at every step'),
            ('Show neighbors', 'Show neighbors', 'Shows the particle current neighbors'),
            ('Show follicle path', 'Show follicle path', 'Shows the path the particle has taken'),
            ('Choose Action', 'Choose Action', 'Default choice')],
            default='Choose Action'
    )
    is_active: BoolProperty(
            name="Is Active",
            description="Determines whether the action is being taken",
            default=False)

I’ll try this! Thanks!!

I’m still getting the issue- if I put the Globals class in the Blender_UI.py, it’s still copying the variable from params.py before it is changed in main.py, and not updating. Maybe I need to set the variable in this class from another function in main.py?

class Globals(): 
    particle_system = params.particle_system

That’s not a bad idea… that execution order is a tricky one, but I think that solution might work

If you want to dynamically fetch the variable you can try defining in Particle_System (btw module names should be snake_case by convention) something like :

def get():
    return particle_systems

But Blender’s serialization system is finicky, it behaves erratically if not used strictly within the context of it’s own UI system. eg the address of objects might change if you undo / redo, or save your file, and new objects are generated on the fly constantly so storing a pointer to a Blender prop outside a Blender prop is bound to bring in errors.

So you’d better store this property on bpy.types.Scene for instance. It has its shortcomings but at least if you always use the same scene you know you’ll find your object at all times.

Using bpy.types.Scene did it- thank you!