1
$\begingroup$
>>> import inspect
>>> inspect.getclasstree(bpy_prop_array)
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
NameError: name 'bpy_prop_array' is not defined

I am still trying to extract a selected object as Python code (kind of a combined Python-learning and Blender-learning project for me). The concise version of the project: for each object property, find the default value. If the current value is different from the default value, then (eventually) spit out a line of Python code which will correctly set the current value. I could just skip this check against defaults, but then the output would be unreadably lengthy and would not highlight deliberate tweaks to the object's appearance etc.

Simple value attributes are not too difficult to extract and compare with defaults, but now I'm running into more complex types. It seems that some tuple or array values have only one default value, i.e. the actual property is a 4-int array, but the default value is a simple int 0. That's very proper and parsimonious, but means I have to do a bit more footwork to unpack all 4 ints and compare them to the default value. To do that I need to detect which properties are array-like and figure out how to extract their elements. Very few are simple tuples; others are Blender-defined types like the above. So I thought the next step would be to determine the inheritance tree of the Blender type, to see if I could identify it as the descendant of some base class such as a list, tuple, dict, etc.

My knowledge of Python is still quite shallow, and this is my first venture into OO coding (been procedural all my working life) so forgive me if this is a stupid question; I thought that the above code should reveal to me the inheritance of the type "bpy_prop_array" which I encountered when extracting object properties, but it appears there's some issue of scoping or definition that I don't yet understand.

My working code (very messy and experimental still):

import bpy
import string

context = bpy.context
obj = context.object

def fDump(obj,fname):
    f = open(fname,'w')
    dumpThing(f,obj,"object")
    matlen = len(obj.material_slots)
    indices = [i for i in range(matlen)]
    f.write("nn*********************** MATERIALS **********************nn")
    for i in range(matlen):
        matnam = C.object.material_slots[i].name
        f.write("*** Material %d, %sn" % (i, matnam))
        mat = D.materials[matnam]
        dumpThing(f,mat,"material")
        texlen = len(mat.texture_slots)
        for j in range(texlen):
            if mat.texture_slots[j]:
                f.write("******** %d is a valid texture slot for material %sn" % (j,matnam))
                tex = mat.texture_slots[j]
                texnam = tex.name
                dumpThing(f,tex,"texture")
    #lastly get vertices and polygons for obj
    vertlist = [vert.co for vert in obj.data.vertices]
    f.write("obj_verts = %sn" % (vertlist))
    facelist = [[vert for vert in f.vertices] for f in obj.data.polygons]
    f.write("obj_faces = %sn" % (facelist))

    f.close()

def dumpThing(f,thing,which):
    defvals = {}
    f.write("DEFAULT VALUESn")
    for prop in thing.bl_rna.properties:
        if hasattr(prop, "default"):
            slow = prop.name.lower()
            index = slow.replace(" ","_")
            if type(prop) is list or type(prop) is tuple:
                f.write("        BTW, %s is a list or tuple!n" % (slow))
            defvals[index] = prop.default
            f.write("%s : %sn" % (index, prop.default))
        else:
            f.write("%s : NO DEFAULTn" % (prop.name))
    f.write("ACTUAL VALUESn")
    name = thing.name
    for attr in dir(thing):
        attv = getattr(thing, attr)
        atype = type(attv)
        f.write("  %s TYPE is %sn" % (attr, atype))
        if type(attv) is list or type(attv) is tuple:
            f.write("        BTW, %s is a list or tuple!n" % (attr))
        if hasattr(thing, attr ):
            if attr in defvals:
                defv = defvals[attr]
                if attv != defv:
                    f.write("*** SET D.%ss["%s"].%s = %s (not default %s)n" % (which, name, attr, attv, defv))
                else:
                    f.write("    DEF D.%ss["%s"].%s = DEFAULT %sn" % (which, name, attr, attv))
            else:
                f.write( "    NODEF    D.%ss["%s"].%s = %sn" % (which, name, attr, attv))
$\endgroup$
  • 1
    $\begingroup$ Please include any relevant code in the answer body itself, not in an external link. $\endgroup$ – Ray Mairlot Jan 22 '17 at 20:11
  • 1
    $\begingroup$ answer body? you meant "question body"? OK... $\endgroup$ – Tazling Jan 22 '17 at 20:23
  • $\begingroup$ Updated answer here blender.stackexchange.com/a/71613/15543, might help a bit. $\endgroup$ – batFINGER Jan 23 '17 at 10:52
  • $\begingroup$ Thanks batFINGER, that snippet certainly will get me past the roadblock and keep my project moving along... though with the nagging question still unanswered: should inspect.getclasstree have worked? Why didn't it? I don't really need to know, since you have handed me another (looks like simpler) way to do what I had in mind, but I'm curious; so I think I'll leave this one Unanswered for a while. $\endgroup$ – Tazling Jan 23 '17 at 19:15

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.