[SOLVED] Material custom list [] property

Hi all,

I’m blocking on a script…here is my problem:
This script is for energetic calculation of walls roofs etc…
I want to add properties to the standard materials.
In those properties, I want to add a ‘layering’ system where layers are construction materials i.e. bricks, insulation…
To do that, I had in mind to create a list attached to every material, with this structure : [[ID int,‘Familly’,‘Type’,Lambda e boolean,Lambda float,Thickness float,Ri float],[ID int,‘Familly’,‘Type’,Lambda e boolean,Lambda float,Thickness float,Ri float],…]

It is almost working, with this code:


import bpy
from bpy.props import IntProperty

# Variables
mat = bpy.context.active_object.active_material
bpy.types.Material.Structure_checked = bpy.props.EnumProperty(
    items = [
        ("default", "Default Values", "Use default worst values"),
        ("owner", "Owner Information", "Use unconfirmed values"),
        ("verified", "Verified", "Use true verified values")
        ],
    name = "Structure certitude",
    description = "What is the certitude of structure composition",
    default = "default"
    )
bpy.types.Material.Structure_location = bpy.props.EnumProperty(
    items = [
        ("outside", "Outside", "Structure is in outside athmosphere"),
        ("unheated_not_frost_free", "Unheated not frost free", "Structure in unheated not frost free athmosphere"),
        ("unheated_frost_free", "Unheated frost free", "Structure in unheated frost free athmosphere"),
        ("inside", "Inside", "Structure in heated athmosphere"),
        ("ground", "Ground", "Structure is in the ground")
        ],
    name = "Structure location",
    description = "What is the athmoshere around the structure",
    default = "outside"
    )
    
bpy.types.Material.Structure_layers=[] #list of material layers ['ID','Familly','Type',Lambda e boolean,Lambda,Thickness,Ri]
mat.Structure_checked="default"
mat.Structure_location ="outside"
       
        



 
class EnergeticPerformancePanel(bpy.types.Panel):
    """Creates a Panel in the Material properties window"""
    bl_label = "Energetic Performance"
    bl_idname = "OBJECT_PT_energetic_performance"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "material"          # name of the new panel
 
    def draw(self, context):
        # display value of "foo", of the active object
        self.layout.prop(bpy.context.active_object.active_material, "Structure_checked",text="Structure certitude")
        self.layout.prop(bpy.context.active_object.active_material, "Structure_location",text="Structure location")
        self.layout.label("Structure layers", icon='SEQ_HISTOGRAM')
        
        row = self.layout.row()
        split = row.split(percentage=0.5)
        col=split.column()
        col.operator("material.addlayerinside", text="Add layer outside").mode=8
        split = row.split(percentage=1)
        col=split.column()
        col.alignment = 'RIGHT'
        col.label(" Outside ", icon='TRIA_UP')
        

        box = self.layout.box()
        row = box.row()
        split = row.split(percentage=0.2)
        col = split.column()
        col.label("Familly")
        split = split.split(percentage=0.25)
        col = split.column()
        col.label("Type")
        split = split.split(percentage=0.18)
        col = split.column()
        col.label("\u03BBe")
        split = split.split(percentage=0.2)
        col = split.column()
        col.label("\u03BB")
        split = split.split(percentage=0.25)
        col = split.column()
        col.label("Thickness")
        split = split.split(percentage=0.33)
        col = split.column()
        col.label("Ri")
        split = split.split(percentage=0.5)
        col = split.column()
        col.label("Ri")
        split = split.split(percentage=1)
        col = split.column()
        col.label("Ri")
        #row = box.row()
        #row.label(text=2000*"=")
        for i in range(len(mat.Structure_layers)):
            row = box.row()
            split = row.split(percentage=0.2)
            col = split.column()
            col.label(mat.Structure_layers[i][1])
            split = split.split(percentage=0.25)
            col = split.column()
            col.label(mat.Structure_layers[i][2])
            split = split.split(percentage=0.18)
            col = split.column()
            col.label(str(mat.Structure_layers[i][3]))
            split = split.split(percentage=0.2)
            col = split.column()
            col.label(str(mat.Structure_layers[i][4]))
            split = split.split(percentage=0.25)
            col = split.column()
            col.label(str(mat.Structure_layers[i][5]))
            split = split.split(percentage=0.33)
            col = split.column()
            col.label(str(mat.Structure_layers[i][6]))
            plit = split.split(percentage=0.5)
            col = split.column()
            col.label(str(mat.Structure_layers[i][6]))
            split = split.split(percentage=1)
            col = split.column()
            col.label(str(mat.Structure_layers[i][6]))
 
        
    
        row = self.layout.row()
        split = row.split(percentage=0.5)
        col=split.column()
        col.operator("material.addlayerinside", text="Add layer inside ").mode=8
        split = row.split(percentage=1)
        col=split.column()
        col.alignment = 'RIGHT'
        col.label(" Inside ", icon='TRIA_DOWN')
 
class OBJECT_OT_Button(bpy.types.Operator):
    bl_idname = "material.addlayerinside"
    bl_label = "Button"
    mode = IntProperty(name="mode",min =-100, max =20,soft_max=10,default =-99) 
    def execute(self, context):
        if len(mat.Structure_layers)>0:
            mat.Structure_layers.append([len(mat.Structure_layers),"massonery","bricks",True,0.02,0.5,3])
        else:
            mat.Structure_layers.append([0,"massonery","bricks",True,0.02,0.5,3])   
        return{'FINISHED'} 
    
    
class OBJECT_OT_Button(bpy.types.Operator):
    bl_idname = "material.deletelayer"
    bl_label = "Button"
    mode = IntProperty(name="mode",min =-100, max =20,soft_max=10,default =-99) 
    def execute(self, context):
        if len(mat.Structure_layers)>0:
            mat.Structure_layers.append([len(mat.Structure_layers),"massonery","bricks",True,0.02,0.5,3])
        else:
            mat.Structure_layers.append([0,"massonery","bricks",True,0.02,0.5,3])   
        return{'FINISHED'}    

def register():
    bpy.utils.register_module(__name__)
    pass

def unregister():
    bpy.utils.unregister_module(__name__)
    pass

if __name__ == "__main__":
    register()

But instead of changing layers only for one material,
it changes the list for every object material…
testfile (run the code and go to materials panel):
ennergetic.blend (1.83 MB)

Question: is this way a good way to deal with what I want to do?
How can I act on only 1 material I think the error is in the declaration:

bpy.types.Material.Structure_layers=[]

thanks in advance,


tmaes

bpy.props.CollectionProperty is probably what you’re after.

thank you, I’ll try it, I turned around in the API but I was too shy…

this was it!!! here is the sample code adapted to materials:


import bpy


# Assign a collection
class MaterialSettingItem(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty(name="Test Prop", default="Unknown")
    value = bpy.props.IntProperty(name="Test Prop", default=22)

bpy.utils.register_class(MaterialSettingItem)

bpy.types.Material.my_settings = \
    bpy.props.CollectionProperty(type=MaterialSettingItem)

# Assume an armature object selected
print("Adding 3 values!")

my_item = bpy.context.active_object.active_material.my_settings.add()
my_item.name = "Spam"
my_item.value = 1000

my_item = bpy.context.active_object.active_material.my_settings.add()
my_item.name = "Eggs"
my_item.value = 30

for my_item in bpy.context.active_object.active_material.my_settings:
    print(my_item.name, my_item.value)


thanks again


tmaes