Keyframing what collection is being instanced by an object.
Sorry for this being long, its just a very important thing to me.
For a while now I've been looking into using Blender as an alternative or straight replacement to Adobe Flash/Animate, and it is very close to being one. However, there are some things I can't do in Blender that are absolute deal breakers, and an equivalent to the flexibility that symbols provide is one. This is a change that would alleviate that.
Take for instance, this doll person.
I animate each part of them frame by frame. While their pieces are made of grease pencil stuff, the animation is not. The process in flash is to make "Sprites" using symbols, and animate those.
In Blender, I
would
do the same with collections, however, as there is no way to swap out collections at will (short of keeping them all off screen and manually swapping their positions) there is no good way to animate these puppet people.
(in this short test animation, I had to keep all the different body angles and hand poses off-screen and swap them in when needed, which was an absolute pain.)
The use cases for collection instance keyframing (or even mesh data keyframing?) are not just limited to this niche-ish 2d use case (although it applies for any other grease pencil animations too)...
Say for instance, you have someone shoot someone else with a shotgun and need them to explode into a shower of giblets! You have the normal victim collection being animated, and then when you need to, you swap it out for the gibbed version.
This also brings up the issue of having per-frame objects rather than per-scene, but that is another issue entirely. Being able to keyframe what is being instanced at any given time by an empty or other object would be an absolutely irreplaceable tool to have for any Blender animator, be it 2d or 3d.
2 Comments
hey, just for fun, i did a proof of concept of what you're looking for in a python script. basically it allows you to keyframe an integer value which then corresponds to the collection index you want on that frame (which is then applied via a frame change handler).
obviously needs lots of refinement. searching for collections by their index isn't user friendly, but you can't keyframe strings. i'm sure there's a clever way around that though.
edit: i suck at understanding how to format inline code, sorry!
import bpy
def update_standin(self,context): if (len(bpy.data.collections) > self.standin_collection) and (self.standin_collection > 0): self.instance_collection = bpy.data.collections[self.standin_collection] else: self.instance_collection = None
def swap(self): for ob in bpy.context.scene.objects: if ob.instance_type == 'COLLECTION': if (len(bpy.data.collections) > ob.standin_collection) and (ob.standin_collection > 0): ob.instance_collection = bpy.data.collections[ob.standin_collection] else: ob.instance_collection = None
class StandinPanel(bpy.types.Panel): """Creates a Panel in the Object properties window""" bl_label = "Instance Standin" bl_idname = "OBJECT_PT_hello" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "object"
def register(): bpy.app.handlers.frame_change_post.clear() bpy.app.handlers.frame_change_post.append(swap) bpy.types.Object.standin_collection = bpy.props.IntProperty(name = "Lighting Standin Collection", update=update_standin) bpy.utils.register_class(StandinPanel)
def unregister(): bpy.app.handlers.frame_change_post.append(swap) bpy.utils.unregister_class(StandinPanel)
if name == " main ": register()
the only remaining issue is the animated value is still the index of the collection, which can change as you add or remove collections, so your animation can break if your set of collections change.