3
$\begingroup$

I'm using Custom Properties (/ID properties) to store a dynamic list of properties I expose in a panel (cf dynamic PropertyGroup / Panel).

I can easily handle all of the property types I'm interested in. All except boolean properties. For some reason, Blender does not support ID properties of type bool.

I would like to emulate bool properties using an integer (for example).

My question is: how can I render a panel with a checkbox that will somehow change the value of that integer?

Thank you,

$\endgroup$
3
$\begingroup$

ID properties can't be displayed as checkboxes:

import bpy

def draw_func(self, context):
    layout = self.layout
    ob = context.object

    try:
        ob["myBool"]
    except (AttributeError, KeyError):
        layout.label('No ["myBool"] property.')
    else:
        layout.prop(ob, '["myBool"]', toggle=True, slider=False)

def register():
    bpy.types.OBJECT_PT_custom_props.prepend(draw_func)

def unregister():
    bpy.types.OBJECT_PT_custom_props.remove(draw_func)

if __name__ == "__main__":
    register()

They will always display as integer or floating point numbers, and also stored this way.

You need to use bpy.props.BoolProperty() for checkboxes.

$\endgroup$
  • $\begingroup$ I know that ID properties cannot be bool. That's why I want to emulate bool ID properties. But I need bool ID properties because only ID properties are exported in FBX and I need boolean values. $\endgroup$ – Jean-Marc Le Roux Aug 18 '15 at 6:33
  • $\begingroup$ I guess you could simply change the FBX script to use a bpy.props property. Cast the value as needed. There's no difference between ID properties and bpy.props properties internally anyway. $\endgroup$ – CoDEmanX Aug 18 '15 at 6:58
  • $\begingroup$ AFAIK it's a much more complicated process/implementation than just using the proxy method I describe in my answer. $\endgroup$ – Jean-Marc Le Roux Aug 18 '15 at 7:15
  • $\begingroup$ Perhaps, but also a smaller overhead (because it would only cast on export). $\endgroup$ – CoDEmanX Aug 18 '15 at 13:39
3
$\begingroup$

It's actually pretty easy to do:

1 - Create a proxy PropertyGroup that will represent your bool properties: that proxy should have just a "value" field of type BoolProperty. Also make sure the update function of that property will actually change the ID property:

class BoolPropertyProxy(bpy.types.PropertyGroup):
    value = BoolProperty(name="Value", update=bool_property_update)

def minko_script_bool_property_update(self, context):
    context.active_object[self.name] = self.value

bpy.utils.register_class(BoolPropertyProxy)
bpy.types.Object.bool_properties = bpy.props.CollectionProperty(type=BoolPropertyProxy)

2 - When creating your ID properties, if the property is a bool then create and store an additional BoolPropertyProxy:

obj['properties'] = props
for key, key_type in props.items():
    obj[key] = get_property_default_value(key)
    if key_type == 'bool':
        bool_prop = obj.bool_properties.add()
        bool_prop.name = key
        bool_prop.value = get_property_default_value(key)

3 - In the UI, if the property is typed as a bool, use the corresponding proxy instead:

for key, key_type in obj['properties']:
    if key_type == 'bool':
        for bool_prop in obj.bool_properties:
            if bool_prop.name == key:
                col.prop(bool_prop, 'value', text=key)
                break
    else:
        col.prop(obj, '["' + key + '"]', text=key)

The value is stilled stored as an integer, but it's displayed as a checkbox which is much more convenient. I guess the same "proxy" idea can be used for pretty much any type.

$\endgroup$

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.