2
$\begingroup$

What's the best practice for polymorthic properties? I want to associate a type with an object; Cylinder, Thread, Cube etc. For each type I want properties associated, but as the object can only be one type at it only need one set of properties.

What I was hoping to be able to do was define a class from PropertyGroup then subclass that, and set the custom type on the object. Something like this

class ObjectParameters(bpy.types.PropertyGroup):
    type: bpy.props.StringProperty()

class CylinderParameters(ObjectParameters):
    height: bpy.props.FloatProperty()
    radius: bpy.props.FloatProperty()
    
    
class ThreadParameters(ObjectParameters):
    height: bpy.props.FloatProperty()
    pitch: bpy.props.FloatProperty()
    radius: bpy.props.FloatProperty()


bpy.utils.register_class(ObjectParameters)
bpy.utils.register_class(CylinderParameters)
bpy.utils.register_class(ThreadParameters)


bpy.types.Object.object_parameters = bpy.props.PointerProperty(type=ObjectParameters)

cube = bpy.data.objects['Cube']
print(cube.object_parameters)
cube.object_parameters = CylinderParameters()
print(cube.object_parameters)

That fails as you can't create an instance of CylinderParameters; and even if you could cylinder_parameters is read-only so you wouldn't be able to change it.

The best option I've come up with so far is this; creating properties for each type on bpy.types.Object then having another one select between them.

import bpy


class CylinderParameters(bpy.types.PropertyGroup):
    height: bpy.props.FloatProperty()
    radius: bpy.props.FloatProperty()
    
    
class ThreadParameters(bpy.types.PropertyGroup):
    height: bpy.props.FloatProperty()
    pitch: bpy.props.FloatProperty()
    radius: bpy.props.FloatProperty()


bpy.utils.register_class(CylinderParameters)
bpy.utils.register_class(ThreadParameters)


bpy.types.Object.object_type = bpy.props.EnumProperty(items=[
    ('NONE', 'None', '', 1),
    ('cylinder_parameters', 'Cylinder', '', 2),
    ('thread_parameters', 'Thread', '', 3),
], default='NONE')
bpy.types.Object.cylinder_parameters = bpy.props.PointerProperty(type=CylinderParameters)
bpy.types.Object.thread_parameters = bpy.props.PointerProperty(type=ThreadParameters)


cube = bpy.data.objects['Cube']
print('init type', cube.object_type)
cube.object_type = 'cylinder_parameters'
print(cube.object_type)
print(getattr(cube, cube.object_type))

The other way is to just update a custom property on the object with a dictionary e.g.

cube = bpy.data.objects['Cube']
cube['parameters'] = {'type': 'cylinder', 'height': 56, 'radius': 1}
print(cube['parameters'])

Whats the best way to do this?

$\endgroup$
1
  • $\begingroup$ The other thing you can do it to add a property function to bpy.types.Object which returns the relevant properties $\endgroup$ – mountainstorm Sep 6 '20 at 20:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.