0
$\begingroup$

I'm working on an addon that reads stored scene data, but am having a bit if difficulty initializing them. The value on the sliders can only be read when you manually nudge them a value or two, or else the "default" values always return an error that says that the values can't be read. Here's the code:

bl_info = {
    "name": "Material ID Utilities",
    "author": "Ajlan (Jacobo) Altug",
    "version": (0, 1, 1),
    "blender": (2, 70, 0),
    "location": "N Panel",
    "description": "Offers a nifty way to visualize and arrange Material Pass ID's.",
    "category": "Material"}

import bpy
from bpy.props import *

### UI MENU ###
class AjMatidUIPanel(bpy.types.Panel):
    bl_label = "AJ_MATERIAL_ID_MANAGER"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"

    def draw(self, context):
        layout = self.layout
        scn = context.scene
        row = layout.row()
        row.prop(scn, 'MatInd', icon='BLENDER', toggle=True)
        row.operator("select.obj")      
        row = layout.row()
        row.prop(scn, 'StrtInd', icon='BLENDER', toggle=True)
        row.operator("assign.matid")
        box = layout.box()
        scnMat = bpy.data.materials
        box.label("MATERIAL ID LISTING: " + str(len(scnMat)) + " MATS IN THE SCENE.")          
        for mat in scnMat:
            matPassIndex = getattr(mat, 'pass_index')
            row = box.row()
            buf = mat.name
            buf = buf + " with ID: " + str(matPassIndex)
            row.label(buf, icon='MATERIAL_DATA')

### CLASS ###
class OBJECT_OT_SelectObjButton(bpy.types.Operator):
    bl_idname = "select.obj"
    bl_label = "Select Objects with ID"

    def execute(self, context):
        scn = context.scene
        scnMat = bpy.data.materials
        objList = []
        for obj in bpy.data.objects:
            if obj.type == "MESH":
                for slot in obj.material_slots:
                    mslot = slot.material
                    if mslot != None:
                        if mslot.pass_index == scn['MatInd']:
                            objList.append(obj)
                        else:
                            pass
                    else:
                        pass
            else:
                pass
        for ob in objList:
            ob.select = True           
        return{'FINISHED'} 


class OBJECT_OT_AssignMatIDButton(bpy.types.Operator):
    bl_idname = "assign.matid"
    bl_label = "ID to Mats"

    def execute(self, context):
        scn = context.scene
        scnMat = bpy.data.materials
        MatIndex = scn['MatInd']
        StrtIndex = scn['StrtInd']
        if len(scnMat) != 0:
            AssignMatID(scnMat, MatIndex, StrtIndex)
        else:
            pass
        return{'FINISHED'} 

### FUNCTIONS ###
def AssignMatID(scnMat, MatIndex, StrtIndex):
    i = StrtIndex
    for j in range(len(scnMat)):
        scnMat[j].pass_index = i
        i += 1

###  Registration  ###
def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.MatInd = IntProperty(
    name = "Material ID", 
    description = "Material Pass Index ID")
    default = 0

    bpy.types.Scene.StrtInd = IntProperty(
    name = "Start", 
    description = "Start Value")
    default = 0

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.MatInd
    del bpy.types.Scene.StrtInd

if __name__ == "__main__":
    register()

I referred to the Code Cookbook, and there the scene data is initialized in a format that seems unsuitable for a runtime addon, but it works. The scene data is initialized as such:

import bpy
from bpy.props import *

#
#    Store properties in the active scene
#
def initSceneProperties(scn):
    bpy.types.Scene.MyInt = IntProperty(
        name = "Integer", 
        description = "Enter an integer")
    scn['MyInt'] = 17

    bpy.types.Scene.MyFloat = FloatProperty(
        name = "Float", 
        description = "Enter a float",
        default = 33.33,
        min = -100,
        max = 100)

    bpy.types.Scene.MyBool = BoolProperty(
        name = "Boolean", 
        description = "True or False?")
    scn['MyBool'] = True

    bpy.types.Scene.MyEnum = EnumProperty(
        items = [('Eine', 'Un', 'One'), 
                 ('Zwei', 'Deux', 'Two'),
                 ('Drei', 'Trois', 'Three')],
        name = "Ziffer")
    scn['MyEnum'] = 2

    bpy.types.Scene.MyString = StringProperty(
        name = "String")
    scn['MyString'] = "Lorem ipsum dolor sit amet"
    return

initSceneProperties(bpy.context.scene)

How can I go about successfully initializing stored data in an addon?

$\endgroup$

1 Answer 1

2
$\begingroup$

The cookbook example doesn't work with recent Blender versions:

bpy.types.Scene.MyBool = BoolProperty(
    name = "Boolean", 
    description = "True or False?")
scn['MyBool'] = True

It will try to access bpy.context during initialization, which is now prohibited.

Your is syntactically correct, but you don't give any property a default value:

bpy.types.Scene.MatInd = IntProperty(
name = "Material ID", 
description = "Material Pass Index ID")
default = 0

default is supposed to be a parameter of the property initialization, but you place a random variable in the global scope.

It should be like this:

bpy.types.Scene.MatInd = IntProperty(
    name="Material ID", 
    description="Material Pass Index ID",
    default=0
)

Note that you can only supply static values, you can't do something like default=len(bpy.context.selected_objects) - no access to bpy.data and bpy.context is allowed, and therefore no dynamic default value (you could use random.random(), but that's not the point).

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .