4
$\begingroup$

I have a large animation (over 200 objects) that I have been working on for a while. In the animation I use a great number of tubes, made simply by defining Bezier Circles as bevel objects for Bezier Curves.

Some of the Curves share Circles as bevel objects, and I'm now starting to realise that this is a problem, since I would very much like to parent each Circle to its belonging Curve and hide it, for the sake of order.

Rather than having to manually inspect every Curve and take note of which Circle it uses, I would like to do the reverse operation, i.e. go through every Circle and take note of which Curves that uses it as bevel object. This is nice because it would allow me to duplicate Circles used multiple times and parent each new version to a Curve. Can this be done? If not in the GUI, then possibly programmatically?

TL:DR I want to go through each Bezier Circle and see which objects that uses it as bevel object, so that I can duplicate a Circle if it is used by multiple objects, and parent each new Circle to its belonging object, such that no two objects share the same Circle as bevel object.

$\endgroup$
  • $\begingroup$ you do it the reverse way loop through curves, find their bevel object and duplicate it $\endgroup$ – Chebhou Apr 24 '15 at 10:47
  • $\begingroup$ This doesn't really solve the problem, cause it provides no way of knowing whether a bevel object is shared among different curves. So duplication would just create an unwanted large amount of bezier circles wouldn't it? Or am I missing the point? $\endgroup$ – Ulf Aslak Apr 24 '15 at 10:56
  • $\begingroup$ AFAIK you can't tell if the circle is used or not, but you can count the number of curves using it then decide if to duplicate or not , or simply duplicate all then remove original $\endgroup$ – Chebhou Apr 24 '15 at 11:02
4
$\begingroup$

in this script :

  • loop through curves
  • duplicate their bevel object and assign it to
  • then remove original bevel objects
  • parent each bevel object to its respective curve, then hide it (OP Edit)

import bpy

originals = []
for obj in bpy.data.objects :
    if obj.type == 'CURVE':
        b_obj = obj.data.bevel_object
        if  b_obj:
            originals.append(b_obj)
            bpy.ops.object.select_all(action='DESELECT')
            b_obj.select = True
            bpy.ops.object.duplicate()
            new_b_obj = bpy.context.selected_objects[0]
            new_b_obj.name = obj.name +"_bevel"
            obj.data.bevel_object = new_b_obj

print(originals)
#cleaning
for obj in set(originals):
    bpy.context.scene.objects.unlink(obj)
    bpy.data.objects.remove(obj)

#parent each bevel object to its curve and hide it (OP Edit)
for obj in bpy.data.objects:
if obj.type == 'CURVE':
    bevel_obj = obj.data.bevel_object
    if bevel_obj != None:
        bevel_obj.parent = obj
        bevel_obj.hide = True

You wont have extra objects, and each bevel object will be named after its user.

$\endgroup$
  • $\begingroup$ Yes, now I understand what you were trying to say :). Code worked nicely, except in the second for loop, originals should be set(originals) since some of the circles were in the list twice. Thanks! $\endgroup$ – Ulf Aslak Apr 24 '15 at 14:10
  • $\begingroup$ @UlfAslak you are welcome! , i didn't think of that , you can edit my post to correct it $\endgroup$ – Chebhou Apr 24 '15 at 14:13
  • $\begingroup$ made the edit to the loop, and also added a third loop to parent each bevel object to its corresponding curve, and hide it. This is pretty much exactly like i wanted it! $\endgroup$ – Ulf Aslak Apr 24 '15 at 14:25
4
$\begingroup$

I think something like this might work, but for your own sanity run this only a copy of your scene, or a small representative version of your scene.

Just in case:

  • This finds the bevel_object
  • if the bevel Object is used by another BezierCurve it duplicates the bevel Object and associated Curve data,
  • then uses the duplicate as the replacement bevel Object.

In code form:

import bpy

scene = bpy.context.scene

bevel_names = set()
for obj in bpy.data.objects:

    if obj.type == 'CURVE':
        name = obj.name
        b_obj = obj.data.bevel_object
        print(' {0} -> {1} '.format(name, str(b_obj)))

        if b_obj:
            if b_obj.name in bevel_names:
                dup = b_obj.copy()
                dup.data = b_obj.data.copy()
                scene.objects.link(dup)
                obj.data.bevel_object = dup
                bevel_names.add(dup.name)
                # dup.parent = obj
            else:
                bevel_names.add(b_obj.name)
                #_obj.parent = obj

For the bezierCurves, it doesn't appear possible to parent the bevel object to them. A solution would be to make an empty for every BezierCurve and parent both BezierCurve and bevel Object to the empty.

$\endgroup$
  • $\begingroup$ I made it work by adding a second loop that went through each curve and just set its bevel object as a child, while hiding it too. Thanks for the nice response! $\endgroup$ – Ulf Aslak Apr 24 '15 at 14:11
  • $\begingroup$ excellent. It's nice to see the variations we come up with. $\endgroup$ – zeffii Apr 24 '15 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.