I'm making a plugin for blender and I have some data types that contain drawing functions. However, when calling these functions on two specific classes, it throws an AttributeError
Traceback (most recent call last):
File "[REDACTED]/blender/4.2/scripts/addons/manifoldclothing/gen/GenPanel.py", line 17, in draw
context.active_object.manifoldHuman.maleBody.draw(layout, context)
File "[REDACTED]/blender/4.2/scripts/addons/manifoldclothing/data/FemaleBodyData.py", line 35, in draw
self.neck.draw(box, context)
^^^^^^^^^^^^^^
AttributeError: 'LongLimbData' object has no attribute 'draw'
LimbData:
import bpy
class LimbData(bpy.types.PropertyGroup):
length: bpy.props.FloatProperty(name="Length")
def draw(self, layout, context):
layout.prop(self, "length")
LongLimbData:
import bpy
from .LimbData import *
class LongLimbData(LimbData):
thickness: bpy.props.FloatProperty(name="Thickness")
def draw(self, layout, context):
super().draw(layout, context)
layout.prop(self, "thickness")
FemaleSpineData:
import bpy
from .LongLimbData import *
class FemaleSpineData(LongLimbData):
lowerWidth: bpy.props.FloatProperty(name="Lower Width")
upperWidth: bpy.props.FloatProperty(name="Upper Width")
def draw(self, layout, context):
super().draw(layout, context)
layout.prop(self, "lowerWidth")
layout.prop(self, "upperWidth")
FemaleBodyData:
import bpy
from .BodyData import *
from .FemaleChestData import *
from .FemaleHipData import *
from .FemaleThighData import *
class FemaleBodyData(BodyData):
hips: bpy.props.PointerProperty(type=FemaleHipData)
spine: bpy.props.PointerProperty(type=FemaleSpineData)
chest: bpy.props.PointerProperty(type=FemaleChestData)
neck: bpy.props.PointerProperty(type=LongLimbData)
head: bpy.props.PointerProperty(type=WideLimbData)
# OTHER FIELDS OMITTED
def draw(self, layout, context):
box = layout.box()
self.hips.draw(box, context)
self.spine.draw(box, context)
self.chest.draw(box, context)
self.neck.draw(box, context)
self.head.draw(box, context)
# OTHER DRAW CALLS OMITTED
But FemaleSpineData
(which extends LongLimbData
) can call super().draw(layout, context)
just fine. It shows the extra property that LongLimbData
defines.
I've made sure the indents are 4 spaces at least 5 times now. I also tried installing another version of blender to no avail.
Turns out this was an issue with blender. Blender does not play nice when subclassing existing property groups and such. The correct way to use subclassing in this case is to use mix-in classes.
Example:
import bpy
class AbstractLimb:
length: bpy.props.FloatProperty(name="Length", min=0.0)
def Draw(self, layout, context):
layout.prop(self, "length")
class LongLimb(AbstractLimb, bpy.types.PropertyGroup):
radius: bpy.props.FloatProperty(name="Radius", min=0.0)
def Draw(self, layout, context):
super().Draw(layout, context)
layout.prop(self, "radius")
class WideLimb(AbstractLimb, bpy.types.PropertyGroup):
width: bpy.props.FloatProperty(name="Width", min=0.0)
thickness: bpy.props.FloatProperty(name="Thickness", min=0.0)
def Draw(self, layout, context):
super().Draw(layout, context)
layout.prop(self, "width")
layout.prop(self, "thickness")
This threw no errors for me and was properly drawn by the UI.