Why are my (global) properties not editable?

addAnalyticCurves-20131226.zip (1.6 KB)

Hi all,

I’m trying to make an addon that makes it possible to create analytic curves, ie curves based on mathematical formulas for the x, y and z component. I’ve attached my (skeleton) code.

I prefer to group my addon properties into the same namespace (in this case: bpy.types.Scene.addcurve_addanalyticcurves). So I define a PropertyGroup-derived class that is used through a PointerProperty. This code is in init.py. This way of doing it has always worked very well for me.

To my surprise, however, it turns out that I cannot edit these (globally defined) properties (like testFloat) through the GUI. If I make the properties local to the operator (like testLocalFloat), everything works as expected.

So this works:

class OperatorBezier(bpy.types.Operator):
    bl_idname = "addcurve_addanalyticcurves.operator_bezier"
    bl_label = "Analytic Bezier"       
       
    testLocalFloat = FloatProperty(name="testLocalFloat", default=0.25, description="test-local-FloatProperty")
        
    def draw(self, context):
        
        self.layout.label(text = "Equations:")
        boxEquations = self.layout.box()
        
        row = boxEquations.row(align = True)
        row.prop(self, "testLocalFloat", text = "testLocalFloat")

This doesn’t work:

# in __init__.py
class AnalyticCurveProperties(bpy.types.PropertyGroup):
    testFloat = FloatProperty(name="testFloat", default=0.25, description="test-FloatProperty")
    
def register():
    bpy.utils.register_class(AnalyticCurveProperties)
    bpy.types.Scene.addcurve_addanalyticcurves = bpy.props.PointerProperty(type=AnalyticCurveProperties)

# in Operators.py
class OperatorBezier(bpy.types.Operator):
    bl_idname = "addcurve_addanalyticcurves.operator_bezier"
    bl_label = "Analytic Bezier"
        
    def draw(self, context):
        self.layout.label(text = "Equations:")
        boxEquations = self.layout.box()
        
        row = boxEquations.row(align = True)
        row.prop(context.scene.addcurve_addanalyticcurves, "testFloat", text = "testFloat")

What am I missing here? Could I get this to work using ‘global’ properties?

Cheers,
g

Hi guy,

Where are you drawing , ie is it in an invoked dialog box or is it an operator with options = {‘REGISTER’, ‘UNDO’} and drawn in the active operator tool panel?

Hi batFINGER,

it’s drawn in the active operator tool panel, ie the lower part of the tool panel. The operator is activated from a menu entry in the Add -> Curve menu (Add -> Curve -> Analytic -> Bezier).

Thanks,
g

Uggggh… asked because I think you’ll find that what you want to do just can’t be done in the registered operator panel… You will need to set up update methods or simply change other props with operator props
or make a Tool Panel for it and just add the primitive in the reg’d area.

I may be mistaken on this, but when I had a go at overriding the add speaker operator, to have the option to add or set a sound…as well as a few other things. Any change to an operator prop the sound I loaded or changed to disappears and everything would be lost except the operator props.

It’s like it is keeping the state from when it is first run, and re - starts from there. A good example is if you put in the scene.frame_start prop in your draw method you’ll see it change when you slide the time line. As soon as you change something in the op its values will revert back. Most likely something to do with undo and history for reg’d operators. Keeping every change you make to props that you can put in the draw method of an operator in an undo would be difficult to say the least.

Check out Truman’s add curve sapling addon. He uses the registered op area well, and may reveal some tricks on how to deal with working from that region. It normally drives me insane when I try and do something more intricate with a registered op.

Taking out ‘REGISTER’ option then this works fine, for changing the “global” in the draw method.


    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_popup(self, width=800)

If you have your heart set on using the reg’d area then good luck… and if you find the secrets to unlocking it please give me a hoy.

Thanks a lot, batFINGER, for elaborating on this. And for the warning regarding possible insanity – phew, that was a close one! :slight_smile:

I’ve got my heart set on getting this addon to work asap. It would have been nice to be able to do this from the active operator panel (where this GUI belongs, imho), while still using ‘global’ properties (ie, where they belong, imho). If this can’t be trivially done, then so be it; let’s try to find the quickest way to achieve our goal.

So for now, I plan to just make the variables local to my operator, as this seems like the fastest way to get some real work done. I definitely want the real-time-ness of the active operator panel, so as soon as you change some properties, I want the curve to update in the scene. That, after all, is the whole idea behind this panel, is it not?

I test-implemented your invoke() code example. It does popup the properties panel, but I couldn’t get it to (in real time) execute my curve-generating code. Maybe I’m missing something here, like a call to execute()? Btw, the cell-fracture addon does a similar thing, but it has an ok/apply button, so the real-time-ness is gone. In any case, I don’t really like the popup-approach anyway; I find it confusing and distracting.

I’m not sure what you’re saying about Truman’s add curve sapling addon code (which works great, btw). It uses properties local to the operator, doesn’t it?

Anyway, I’ll definitely let you know if any further progress is made!

You may create ‘local’ properties for the operator, initializing them with the values of the global properties in the invoke method and write the values of the local properties back to the global properties in the execute method.

You can pass callback functions to properties. Did you try this?