0
$\begingroup$

I have button in my panel, that button switch emitter/hair in particle system it works, but the problem is i have many object, and if i change object selected, button not update.I'm looking for a correct method. This sctipt is simplified for explain:

import bpy
from bpy.props import  BoolProperty
from bpy.types import PropertyGroup, Panel, Scene

def UpdateMitter(self,context):

    toogle = bpy.context.scene.my_prop_grp.emitter_hair
    obj = bpy.context.active_object
    part = obj.particle_systems[0]  
    settings = part.settings

    if toogle is True:
        settings.type = 'EMITTER'   
    else:
        settings.type = 'HAIR'  

class PropGroup(bpy.types.PropertyGroup):
    emitter_hair: BoolProperty(update = UpdateMitter)

class MyPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "test_toogle"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "View"

    def draw(self, context):
        layout = self.layout
        layout.label(text="My problem:")
        scene = bpy.context.scene
        layout.prop(scene.my_prop_grp, 'emitter_hair',  text="Toggle")


classes = (PropGroup, Panel)  

def register():

    bpy.utils.register_class(PropGroup)
    bpy.utils.register_class(MyPanel)

    Scene.my_prop_grp = bpy.props.PointerProperty(type=PropGroup)


def unregister():

    bpy.utils.register_class(PropGroup)
    bpy.utils.register_class(MyPanel)

if __name__ == "__main__":
    register()
$\endgroup$

1 Answer 1

2
$\begingroup$

An Object property?

Make it an object property then it is set on a per object basis.

Since the property is defined on an Object class, then self in an update method is an object of type bpy.types.Object of which context.object is an instance . If it was registered as a scene property, self would be a scene.

If it were a scene property, I would set the PS type for all objects with it.

def emitter_update(self, context):
    toogle = self.my_prop_grp.emitter_hair
    pobs = [o for o in self.objects if len(o.particle_systems)]
    for ob in pobs:
        part = ob.particle_systems[0]  
        settings = part.settings
        settings.type = 'EMITTER' if toogle else 'HAIR'

Consult blender docs re naming conventions for classes, methods.

One of my pet hates: when context is passed as a function argument .. use it. Get out of the habit of bpy.context.foo.blah.bar...

Added a poll method in panel so it doesn't show when context object has no particle system.

import bpy
from bpy.props import  BoolProperty, PointerProperty
from bpy.types import PropertyGroup, Panel, Object

def emitter_update(self, context):
    toogle = self.my_prop_grp.emitter_hair
    part = self.particle_systems[0]  
    settings = part.settings
    settings.type = 'EMITTER' if toogle else 'HAIR'

class MyParticleSettings(bpy.types.PropertyGroup):       
    emitter_hair: BoolProperty(update = emitter_update)

class VIEW3D_PT_toggle_ps(Panel):
    """Test"""

    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "View"

    @classmethod
    def poll(self, context):
        ob = context.object
        return ob and len(ob.particle_systems)

    def draw(self, context):
        ob = context.object
        layout = self.layout
        layout.label(text="My problem:")
        layout.prop(ob.my_particle_settings, 'emitter_hair',  text="Toggle")


classes = (MyParticleSettings,
        VIEW3D_PT_toggle_ps)  


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

    Object.my_particle_settings = PointerProperty(type=MyParticleSettings)


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

if __name__ == "__main__":
    register()

I imagine this will be extended, otherwise could simply put the enum in layout

row.prop(part, "type", expand=True)

or a window manager context toggle operator.

TIP.

In version 2.7x could reload scripts using the F8 key. It is AFAIK not mapped to a key in default 2.8.

Either map it to a key, run in python console.

bpy.ops.script.reload()

Pre(ap)ending a simple operator button draw method to headers of both text editor and python console provides a couple of handy and often used buttons

For example when testing above, posted with ob.my_prop_group in the draw method after it had been renamed to ob.my_particle_settings. As I hadn't reloaded scripts it was still registered from a previous test run, and worked as expected.

Running after reloading scripts will throw errors for such unregistered props.

$\endgroup$
3
  • $\begingroup$ ty , but now i not understand why if i select object with particle system ok panel appears, but not the toggle $\endgroup$
    – Noob Cat
    Commented Mar 2, 2019 at 13:14
  • $\begingroup$ ok my_prop_grp in layout.prop it becomes my_particle_settings $\endgroup$
    – Noob Cat
    Commented Mar 2, 2019 at 13:27
  • 1
    $\begingroup$ Cheers. Edited. $\endgroup$
    – batFINGER
    Commented Mar 2, 2019 at 13:46

You must log in to answer this question.

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