list items by type

Hello all,
I was wondering if there is an easy way to list items by type.

For example if I want to get all items of type bpy.types.FCurve
I have tried weak refs and garbageCollect but no luck
Basically I just want something faster than looping over every object, data, node, etc to get what I need.

Any help appreciated
Thank you
-Alex

Something like :

objects = [elem for elem in bpy.context.scene.objects if elem.type == "CURVE"]

Do you want the objects of a certain type or the object data (e.g. meshes)?

Thanks DoubleZ_, that is what I am running currently, but as you can imagine with 10,000 objects with 10 animation curves each, grabbing data in this way is very slow.

CoDEmanX, I want to get the data, basically every instance of that type

bpy.data.curves gives you all the curves (but note that there are subtypes, CURVE, SURFACE and FONT)

bpy.data.meshes all the mesh datablocks and so on

bpy.data = entire .blend, regardless of scenes!

@CoDEmanX
Yes that is correct, but I cannot do something like:
drivers = [item for item in bpy.data if type(item) == bpy.types.FCurve]

Which is what is desired here.
Looping through every type (bpy.data.meshes, bpy.data.objects, etc) is far too slow for my needs

I’d be interested to see the faster code you come up with. There is no SQLesque interface to bpy.data AFAIK. I am currently working on a an AddOn that generates and manages thousands and thousands of objects. The real slowdown, of course, is the viewport and the outliner.

There is no way to determine the type of an object without fetching it. You could make a list that associates a name with any other information you need to reference, such as type. But you still would have to run through all the objects at least once to populate the associations.

Another approach might be to simply name your objects with their type. Then you could reference all objects that are MESHES with a prefix or postfix. That might be the fastest way and in a code managed system I would find this acceptable. The end-user would have to know, however, that renaming objects manually might break the system.

i got a question.
i dont know much about this but, have you tried creating some kind of portal?

i mean create a gate to the items you want in-which you can instantly bring them through.

Thanks Atom, I’ll have another look through the source and see if i can find something.
I’d really like to avoid recompiling for this one though.

MidnightCpu, i have no idea what you are talking about sorry

@Atom

There is no way to determine the type of an object without fetching it.

Couldn’t you just add an override function to object that sought of auto registers an object in a pseudo database with the info you need.

Sorry I’m just getting my head around the override thingy so this could be completely bogus.

sorry thought i would give it a shot but, i think i know what your saying i started reading a little on scripting.
your wanting to augment you file types

The issue of registering items in a database or stuct of some form is that this script is designed to be run after blender is open.
This is not an addon, basically I am porting the maya.cmds module to blender which lets me do things like:
cmds.connectAttr(‘Cube.001.customProperty’, ‘Cube.002.tx’)
Which will add drivers and stuff.
I’m most of the way complete, but having difficulty finding an efficient way to grab destination connections from an attribute for my listConnections function, especially in scenes with tens of thousands of objects.

It might still work as blender runs scripts again again again

Hang on that would then just be the same as the slow way

Sorry That’s me! out of ideas

but having difficulty finding an efficient way to grab destination connections from an attribute for my listConnections function,

What about using self modifying code?


# Construct a string that will set the value directly when executed.
s = "da_target." + fcurve.data_path + " = " + str(v)
name_space = {}
code = compile(s, '<string>', 'exec')
try:
    exec (code) in name_space
except:
    print ("Code fails to execute.")

You could construct a DNA string that performs the connections directly…? Just brainstorming here.

Hi Atom, not sure what you mean,
I can get all the source objects just fine,
For example say Cube locationX is driven by Sphere locationX

If I ask Sphere locationX for all the objects it is is driving, I will have to get the driver for Cube locationX and check if it is being driven by sphere.
Does this make sense?

So are you still trying to create a solution or do you have a solution and it is just slow?

It is still slow, my current solution takes 0.05 seconds to get 30,000 drivers from 10,000 objects (including materials and node trees)
This is fine for small scenes, but when I need to run these queries 50 times during a single script you can see how the performance hit stacks up.

Not a big thing though, I have plenty of other things to work on :slight_smile:

2.5 seconds is a concern?

I don’t get what this is supposed to do:

drivers = [item for item in bpy.data if type(item) == bpy.types.FCurve]

And what about caching?

Yes, when working with realtime applications.
I have optimized it down to 0.035 seconds, It will have to do for now.
drivers = [item for item in bpy.data if type(item) == bpy.types.FCurve]
This was simply an example of something I would like to do

Caching will not work in this example as drivers can change at any time.
I’ll close this as I won’t be investigating further at this time, but thank you everyone for your input.