0
$\begingroup$

When adding in the parent code at the bottom the font objects create duplicates that are in a descending fashion:

Everything is in the correct place, without parent code: without parent code:

Extra duplicates in a descending fashion, with parent code: with parent code full code:

 import bpy, csv

#duplicat parent/children hiearchy
def copy_ob(ob, parent, collection=bpy.context.collection):
    # copy is the new object
    copy = ob.copy()
    if copy.type == 'MESH':
        copy.data = copy.data.copy()
    copy.parent = parent
    copy.matrix_parent_inverse = ob.matrix_parent_inverse.copy()
    collection.objects.link(copy)
    return copy
    

def tree_copy(ob, parent, levels=3):
    def recurse(ob, parent, depth):
        if depth > levels: 
            return
        copy = copy_ob(ob, parent)

        for child in ob.children:
            recurse(child, copy, depth + 1)

    recurse(ob, ob.parent, 0)


CSVname = '4names.csv'
with open('C:\\Users\Dyllan\Desktop\\' + CSVname, newline='') as f:
    #[1:] removes the first row of CSV file, change if you need to read top row!!!
    data = list(csv.reader(f))[1:]

flopCountDict = {'oFlop': 0, 'sFlop': 0, 'zFlop': 0, 'LFlop': 0, 'jFlop': 0, 'iFlop': 0, 'tFlop': 0}
typeList = ["oFlop", "sFlop", "zFlop", "LFlop", "jFlop", "iFlop", "tFlop", "Random"]

for i,rows in enumerate(data):
    xOffsetDict = {'oFlop': 0, 'sFlop': 1, 'zFlop': 2, 'LFlop': 3, 'jFlop': 4, 'iFlop': 5, 'tFlop': 6}
    zOffsetDict = {'oFlop': 5, 'sFlop': 7.5, 'zFlop': 2.5, 'LFlop': 2.5, 'jFlop': 2.5, 'iFlop': 2.5, 'tFlop': 2.5}
            
    #[11:] is to remove "your name: " from the string of each item in list
    nameData = rows[8][11:]
    typePull = rows[4]
    colorPull = rows[6]
    
    ###CUBE ADDITION
    #select handle of hiearchy to duplicate
    currentHandle = bpy.data.objects[typePull[0] + "JellyHandle." + str("{:03d}".format(flopCountDict[typePull]))]
    #duplicating the parent/child full tree
    tree_copy(currentHandle, None)
    #add that a copy was made of the current type
    
    ###NAMEOBJ
    nameCurve = bpy.data.curves.new(type="FONT", name="nameCurve.001")
    nameCurve.body = nameData
    nameObj = bpy.data.objects.new(name='textObj.' + typePull[0] + '.001', object_data=nameCurve)
    print(nameObj)
    #link to collection
    bpy.data.collections['names'].objects.link(nameObj) 
    bpy.context.view_layer.objects.active = nameObj
    nameObj.location.z = 16.25 * flopCountDict[typePull] + zOffsetDict[typePull]
    nameObj.location.x = 25 * xOffsetDict[typePull] + 5
    
    #update to the new duplicate structure
    flopCountDict[typePull] += 1
    currentHandle = bpy.data.objects[typePull[0] + "JellyHandle." + str("{:03d}".format(flopCountDict[typePull]))]
    currentHandle.location.z += 16.25


    ###PARENTING
    currentCloth = bpy.data.objects[typePull[0] + "JellyCloth." + str("{:03d}".format(flopCountDict[typePull]))]
#    nameObj.parent = currentCloth
 #   nameObj.matrix_parent_inverse = currentCloth.matrix_world.inverted()
$\endgroup$
3
  • $\begingroup$ A bit hard to follow. Could you define your goal a bit more? So you have a bunch of objects and want to generate some text parented to them if their names are in a CSV file? Could you edit the question and provide some screenshot or examples of the data and your object hierarchy structure? $\endgroup$ Dec 22, 2022 at 13:02
  • $\begingroup$ I’m using a CSV file to loop through a list of names, adding a basic cube and a font obj, then parenting that font obj to the cube. I’ll be happy to add screenshots if this explanation doesn’t help. $\endgroup$
    – Black Fox
    Dec 22, 2022 at 13:12
  • $\begingroup$ You are doing more in the script. Maybe that's the problem. I would suggest starting as simple as possible and after you see it works, add more stuff to it. $\endgroup$ Dec 22, 2022 at 14:10

2 Answers 2

0
$\begingroup$

I would recommend keeping things as simple as possible. Once it works, add more stuff. So everything seems to work:

import bpy, csv

#with open('C:\\Test\\CSV.csv') as f:
#    data = list(csv.reader(f))

data = [['A', 'a'], ['B', 'b'], ['C', 'c'], ['D', 'd']] #Same as what I have in csv

for i,every_row in enumerate(data):
    #Cube
    bpy.ops.mesh.primitive_cube_add(location=(2.1 * i, 0, 0))
    new_cube = bpy.context.object
    new_cube.name = every_row[0]
    #Text
    bpy.ops.object.text_add(location=new_cube.location.copy())
    text = bpy.context.object
    text.location.z += 1.5
    text.name = text.data.body = every_row[1]
    #Parenting
    text.parent = new_cube
    text.matrix_parent_inverse = new_cube.matrix_world.inverted()
$\endgroup$
1
  • $\begingroup$ Updated post: I used your code and it functions when using a new cube obj. I am using a set of pre-built objects and duplicating them to be my parent objs. Parent code makes duplicate objects in a very specific fashion: the new cube on the bottom has 4 duplicate names attached, cube above has 3, then 2, then 1. I can't figure out what aspect of my code is causing it to do that. The top two funcs are there to duplicate an obj and it's children hiearchy tree, I think they may be causing the problem but I didn't write them so it's hard to understand. Thank you for all of your help! $\endgroup$
    – Black Fox
    Dec 23, 2022 at 23:53
0
$\begingroup$

The issue was that my depth was set too deep on the tree search. After the text object was parented, it was being searched in the recurse function and duplicating. This solution is only a band-aid as I know there should be a better way of selecting the object tree as I am not sure why the same tree is being searched twice.

import bpy, csv

#duplicat parent/children hiearchy
def copy_ob(ob, parent, collection=bpy.context.collection):
    # copy is the new object
    copy = ob.copy()
    if copy.type == 'MESH':
        copy.data = copy.data.copy()
    copy.parent = parent
    copy.matrix_parent_inverse = ob.matrix_parent_inverse.copy()
    collection.objects.link(copy)
    bpy.context.view_layer.objects.active = copy
    print(copy)
    return copy
    

def tree_copy(ob, parent, levels=2):
    def recurse(ob, parent, depth):
        if depth > levels: 
            return
        copy = copy_ob(ob, parent)

        for child in ob.children:
            recurse(child, copy, depth + 1)

    recurse(ob, ob.parent, 0)


CSVname = '4names.csv'
with open('C:\\Users\Dyllan\Desktop\\' + CSVname, newline='') as f:
    #[1:] removes the first row of CSV file, change if you need to read top row!!!
    data = list(csv.reader(f))[1:]

flopCountDict = {'oFlop': 0, 'sFlop': 0, 'zFlop': 0, 'LFlop': 0, 'jFlop': 0, 'iFlop': 0, 'tFlop': 0}
typeList = ["oFlop", "sFlop", "zFlop", "LFlop", "jFlop", "iFlop", "tFlop", "Random"]


for i,rows in enumerate(data):
    xOffsetDict = {'oFlop': 0, 'sFlop': 1, 'zFlop': 2, 'LFlop': 3, 'jFlop': 4, 'iFlop': 5, 'tFlop': 6}
    zOffsetDict = {'oFlop': 5, 'sFlop': 7.5, 'zFlop': 2.5, 'LFlop': 2.5, 'jFlop': 2.5, 'iFlop': 2.5, 'tFlop': 2.5}
            
    nameData = rows[8][11:]
    typePull = rows[4]
    colorPull = rows[6]
    
    currentHandle = bpy.data.objects[typePull[0] + "JellyHandle." + str("{:03d}".format(flopCountDict[typePull]))]

    ###Obj Duplication
    tree_copy(currentHandle, None)
    flopCountDict[typePull] += 1
    
    clothObj = bpy.context.object
    #update to the new duplicate structure
    currentHandle = bpy.context.object.parent.parent
    currentHandle.location.z += 16.25
    bpy.ops.object.text_add(location=bpy.context.object.parent.parent.location)
    newText = bpy.context.object
    newText.name = newText.data.body = nameData
    
    #print(str(newText) + str(clothObj))
    newText.parent = clothObj
    newText.matrix_parent_inverse = clothObj.matrix_world.inverted()
$\endgroup$

You must log in to answer this question.

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