Value Troubles / object dimensions

Hello fellow blenderhood!

I am working on an AddOn which synchronizes arrays through space (children objects, with parent objects). It already works fine for FIXED COUNT-fit-type, but I don’t find a way, to…

…either cache a value which I read from an object and which stays the same, although the object is modified a few steps later. (the objects “dimensions” - Its values change with the modifikation of the object, which changes my value also)

…or get the objects “true” dimensions (the dimensions of the single object, without the array-modifikation. I guess, the data must be there anywhere, cause Blender has it. (Maybe something like “mesh_dimension”…? )

So is there a way to call something like the dimensions of the mesh instead of the dimensions of the object, or an uncomplicated way to save Float-Values of an objects value, without them beeing influenced by further modifikations of the object? Many Thanks for your help!

Here are two possibilities:

  1. Store the data in the object using blender python properties:
    http://www.blender.org/documentation/blender_python_api_2_72_release/bpy.props.html

  2. If you know your modifier’s name:
    Deactivate modifier
    Read dimensions
    Reactivate modifier

import bpy
obj = bpy.context.object
obj.modifiers['Array'].show_viewport=False
dimensions = obj.dimensions
obj.modifiers['Array'].show_viewport=True

Thank you for your reply!

I tried the second way already but nevertheless I couldn’t find a way to work with the correct dimensions.

Atm I first store the Fit-Type and associated Value of the Modifier, reset the modifier to fit_type ‘FIXED_COUNT’ and a count of “1” (I also tried deleting it), then get the dimensions, then calculate the children-offset with that dimension-values, than set the children offset, then restore the Type from the first step and then set the corresponding children fit_type and value.

My previous attempts to fix this were more a digging into quicksand. :spin: I tried to dump the dimension values by pickle and as textfile too, to see their values and have them stored uninfluenced by further manipulations, but it always uses and writes the “original” dimension-values. If I leave the Restorement-Part at the end out, it fails too. It correctly resets the modifier (but the written dimensions are still the ones from before the reset). I don’t get it and I suspect myself to make a fundamental mistake, which will turn out to be pretty dull in the end.

Maybe it helps to see the Code - Beforehand: I am a beginner in Python (but getting more and more excited about it), so I am sure there are much more elegant and cleaner ways to write this (and without writing extrafiles). But what I first want to fix is the problem with my class calling the wrong values. So here is the corresponding part of my code:

(Fun-Fact: When I delete the children arrays and then use Fit-Type “Fit_Length”, the first synch works (cause I deleted the part for reseting the children-dimensions for better overview it is only the first) for a certain offset-realm, although the written txt-File contains the wrong dimensions, but for FIXED_COUNT and counts > 1, it always calculates wrong offsets.)

def invoke(self, context, event) :
        #
        a = bpy.context.scene.objects.active
        asynch = a.modifiers["ArraySynch"]
        #   test fit_type
        if asynch.fit_type == 'FIXED_COUNT':
            atest = "1 0 0"
            acount = asynch.count
            #
            a_sval = open("E:/a_sval.pkl","wb")
            pickle.dump(acount, a_sval, -1)
            a_sval.close()
            #
        elif asynch.fit_type == 'FIT_LENGTH':
            atest = "0 1 0"
        else:
            atest = "0 0 1"
        #Store atest in file
        atester = open("E:/atest.pkl", "wb")
        pickle.dump(atest, atester, -1)
        atester.close()
        #
                #
        if asynch.fit_type != 'FIXED_COUNT':
            asynch.fit_type = 'FIXED_COUNT'
        else:
            pass
        asynch.count = 1
        # 
        #Dimensions               
        ax = str(a.dimensions[0]) +"
"
        ay = str(a.dimensions[1]) +"
"
        az = str(a.dimensions[2]) +"
"
                #
                # store a dimensions in adims.pkl
        adimdat = open("E:/adims.txt","w")
        adimdat.write(ax)
        adimdat.write(ay)
        adimdat.write(az) 
        #pickle.dump(adim, adimdat, -1)
        adimdat.close()
        #
        #
        childlist = a.children
        for ob in childlist:      
            # test for ArraySynch-Array
            rtest = False
            for mod in ob.modifiers:
                if mod.name == "ArraySynch" and mod.type == 'ARRAY':
                    rtest = True
                else:
                    pass
            #new ArraySynch if rtest=false
            if rtest == False:
                ob.modifiers.new("ArraySynch", type='ARRAY')
                ob.modifiers["ArraySynch"].relative_offset_displace = (1,0,0)
            else:
                pass   
            #
            #reset rsynch.count
            rsynch = ob.modifiers["ArraySynch"]
            rsynch.fit_type = 'FIXED_COUNT'
            rsynch.count = 1
            #
            # load adims from Store_adim
            adimdat = open("E:/adims.txt","r")
            pckld_adimx = adimdat.readline(1)
            pckld_adimy = adimdat.readline(2)
            pckld_adimz = adimdat.readline(3)
            #pckld_adim = pickle.load(adimdat)
            adimdat.close()
            #
            adx = float(pckld_adimx)
            ady = float(pckld_adimy)
            adz = float(pckld_adimz) 
            # 
            # get r.dimensions
            rxyz = ob.dimensions
            rx = rxyz[0]
            ry = rxyz[1]
            rz = rxyz[2]
            #
            #
            aoffsx = asynch.relative_offset_displace[0]
            aoffsy = asynch.relative_offset_displace[1]
            aoffsz = asynch.relative_offset_displace[2]
            ##
            roffsx = (adx*aoffsx)/rx
            roffsy = (ady*aoffsy)/ry
            roffsz = (adz*aoffsz)/rz
            #
            rsynch.relative_offset_displace[0] = roffsx
            rsynch.relative_offset_displace[1] = roffsy
            rsynch.relative_offset_displace[2] = roffsz
            # 
            #
            # 
        #
#        atester = open("E:/atest.pkl","rb")
#        pckld_atest = pickle.load(atester)
#        atester.close()
        #
#        a_sval = open("E:/a_sval.pkl","rb")
#        pckld_count = pickle.load(a_sval)
#        a_sval.close()
        #
        #        
#        if pckld_atest == "1 0 0":
#            asynch.fit_type = 'FIXED_COUNT'
#            asynch.count = pckld_count
#        elif pckld_atest == "0 1 0":
#            asynch.fit_type = 'FIT_LENGTH'
#            alength = asynch.fit_length
#        else:
#            asynch.fit_type = 'FIT_CURVE'
#            acurve = asynch.curve
        #
        #
        #
        #childlist = a.children
#        for ob in childlist:
#            rtest = False
#            for mod in ob.modifiers:                
#                if mod.name == "ArraySynch" and mod.type =='ARRAY':
#                    rtest = True
#                else:
#                    rtest = False
#            if rtest == True:
#                pass
#            else:
#                ob.modifiers.new("ArraySynch", type='ARRAY')
#                ob.modifiers["ArraySynch"].relative_offset_displace = (1,0,0)
            #
#            rsynch = ob.modifiers["ArraySynch"]
#            rsynch.fit_type = asynch.fit_type
#            if asynch.fit_type == 'FIXED_COUNT':
#                rsynch.count = asynch.count
#            elif asynch.fit_type == 'FIT_LENGTH':
#                rsynch.fit_length = asynch.fit_length
#            else:
#                rsynch.curve = asynch.curve
        return{'FINISHED'}

Sorry - I did not read your post correct. Deactivating is a quite more elegant way! I’ll try that and give you an update.

@mods - my previois post can be deleted for now. If it doesn’t work I will cry for help again anyway. :wink:

Same same. It seems as if Python gets the objects dimensions when the class is called, not when I call the objects dimensions within this class.

class Synch_Offs(bpy.types.Operator) :
    """"""
    bl_idname = "atype.store"
    bl_label = "Store atype"
    bl_options = {"REGISTER", "UNDO"}
    def execute(self, context) :
        #
        a = bpy.context.scene.objects.active
        asynch = a.modifiers["ArraySynch"]
        #
        asynch.show_viewport = False
        #
        axyz = a.dimensions              
        ax = axyz[0] 
        ay = axyz[1]
        az = axyz[2]
        #
        childlist = a.children
        for ob in childlist:      
            # test for ArraySynch-Array
            rtest = False
            for mod in ob.modifiers:
                if mod.name == "ArraySynch" and mod.type == 'ARRAY':
                    rtest = True
                else:
                    pass
            #new ArraySynch if rtest=false
            if rtest == False:
                ob.modifiers.new("ArraySynch", type='ARRAY')
                ob.modifiers["ArraySynch"].relative_offset_displace = (1,0,0)
            else:
                pass   
            #
            #
            rsynch = ob.modifiers["ArraySynch"]
            rsynch.show_viewport = False
            #
            # 
            rxyz = ob.dimensions
            rx = rxyz[0]
            ry = rxyz[1]
            rz = rxyz[2]
            #
            aoffsx = asynch.relative_offset_displace[0]
            aoffsy = asynch.relative_offset_displace[1]
            aoffsz = asynch.relative_offset_displace[2]
            #
            roffsx = (ax*aoffsx)/rx
            roffsy = (ay*aoffsy)/ry
            roffsz = (az*aoffsz)/rz
            #
            rsynch.relative_offset_displace[0] = roffsx
            rsynch.relative_offset_displace[1] = roffsy
            rsynch.relative_offset_displace[2] = roffsz
            # 
            #
            # 
        asynch.show_viewport = True       
        for ob in childlist:
            rsynch = ob.modifiers["ArraySynch"]
            rsynch.show_viewport = True
            rsynch.fit_type = asynch.fit_type            #
            if asynch.fit_type == 'FIXED_COUNT':
                rsynch.count = asynch.count
            elif asynch.fit_type == 'FIT_LENGTH':
                rsynch.fit_length = asynch.fit_length
            else:
                rsynch.curve = asynch.curve
        return{'FINISHED'}

Got it! B)

I simply had to refresh the 3D-View (after resetting, deleting or deactivating the array) to get the correct dimensions. For those, who are faced with similiar troubles: I did that with “py.ops.view3d.move()”.

Many thanks to Little-me for your support!

Await the mighty Array-Synch-AddOn! (yeah!)

ahah great !!
Just a few extra tips to make your code a bit cleaner :wink:

  • You should rather use context.scene.update() than using the move operator to update the scene
  • You have a lot of repetition like

axyz = a.dimensions
ax = axyz[0]
ay = axyz[1]
az = axyz[2]

you could code all this on one line to save space in your code and make it easier to read


ax, ay, az = a.dimensions
asynch.relative_offset_displace = [aoffsx, aoffsy, aoffsz]
...

Merci little-me! I will do so.

And: Sorry for my late reply! I only just noticed your post.