Resolving a definite type for an asset is difficult. Instead, the following proposes a way to define type related characteristics (traits) of an asset, which can then be mapped to precise behavior.
The type of an asset is a vague concept. Some considerations:
So the proposal is to avoid the concept of a single static type. Instead, differentiate assets using type related characteristics, so called traits.
Asset traits are keywords that specify certain type characteristics of an asset. They are loose (in the sense of having no knowledge about each other) but well defined.
With every trait added, the asset's type characteristics get defined more precisely. So traits are additive and increase specificity. Or put differently: Each trait removes ambiguity.
Traits look a lot like the already supported asset tags. And they are similar, but traits are more focused on type-relevant characteristics of the asset, have well-defined meaning, and are managed by software. Tags are managed by the user (more specifically, an asset creator) to help browsing assets, and can contain arbitrary bits of information with or without well-defined meaning.
Design Choices
Redundancy allowed: There may be some redundancy in the traits of an asset. For example Stencil
pretty much implies that it's also an image and a texture. This makes it easy for code to check high-level characteristics, while keeping the flexibility to do more granular checks as needed.
Implicit hierarchy: There's also often a semantic hierarchy between the traits. For example the traits of a mesh-object could also be specified in a path-like manner: "ID/Object/Mesh"
. There doesn't seem to be a need for making the hierarchy explicit though, so it doesn't seem worth the overhead of defining a sensible path system. A loose set of strings seems simple and flexible. Plus, assets may have multiple independent traits, so just a single path-like trait wouldn't be sufficient anyway.
Style conventions: Traits are written using capitalized words and spaces as needed. This way they can be nicely exposed to the user if wanted, without additional "translation" from a coder-y style like ObjectData
. For example, we may choose to display some traits as read-only tags to the user, since this information is useful for their browsing experience too.
Since traits are supposed to be well-defined, we should keep a glossary of the traits Blender uses natively. Here are some example definitions:
ID
Object
Object
- and the ID
-trait set.Modifier
Node Tree
, Geometry Nodes
, and Mesh Modifier
would together indicate a geometry node-group that can not only be used as regular node group, but also be dropped into the modifier stack of a mesh object.Traits don't have to be defined by Blender natively. An add-on may introduce new traits (which it would have to manage itself). For example an add-on adding USD asset support, or support for using Inkscape brushes in Blender. The add-ons can provide own traits to indicate these assets.
Well-defined just means there is a reasonably clear definition, which is not necessarily provided by Blender itself.
The stork brings them
ID
and Brush
traits.IDTypeInfo::refine_asset_traits()
could add further traits, like Sculpt Mode
, to indicate a sculpt brush.TODO
How do we keep traits updated? E.g. a texture may switch from being a stencil to a regular texture and vice versa. Updating traits on save may be a good start, but since traits drive operations like preview rendering, they also need to be updated before any such operation. Could be just a call to IDTypeInfo::refine_asset_traits()
?
While this is a forward compatible system in itself, there is the issue that we can't possibly predict all the possible traits that might be useful in future. For example, will we need image format details as traits in the future? Versioning code could of course add new traits as needed, but then that code may need the fully loaded asset data, not just the lightweight representation of an asset we load for the asset browser/system.
Note that this is a general problem with assets, even if we store type information differently. You just don't know what information you'll need from a the representation of an asset in future.
OpenAssetIO also uses the concept of traits. It's similar to what is proposed here, although it goes a bit further to support communicating more general metadata this way too (which Blender handles differently). Point is, we can easily map Blender's asset traits to the one of OpenAssetIO. There may have to be a small translation layer though, since our trait terminology would be quite Blender-focused. An ID
trait could be translated to a blender-ID
OpenAssetIO trait. In general prefixing Blender specific traits with blender-
seems like a good idea. Further OpenAssetIO traits can be added as needed then. E.g. the Blender Image
trait may be expanded into a image
and raster
trait for OpenAssetIO (indicating an image stored in a pixel format).
TL;DR: Operations like importing, preview rendering, drag & drop or managing asset metadata should behave differently depending on the type of an asset. How can this be supported reliably?
Dragging an object into the scene should trigger a different operation than activating a brush. Rendering an object preview may want to use a different preview-scene setup than a material preview. How can we make sure Blender behaves correctly (or at least predictably) for each asset?
These operations fall into two categories:
Taking the operations displayed in the picture above, they can be categorized as follows:
Produce | Consume |
---|---|
Mark as Asset, Preview Rendering, Manage Asset Metadata, Assign to Default Catalog |
Drag & Drop, Import/Apply, Query Type Icon, Query Default Preview |
The mentioned operations can be implemented in some kind of callback (for example a "naked" callback or an operator). What's needed is a way to map the traits of an asset to these callbacks.
Code could request the asset system to resolve a set of traits to a set of callbacks. For example (dummy code):
This so far is only a vague & early idea.
Is this predictable enough? What if multiple callbacks fight for the same set of traits? Should the specificity of traits be used as tie breaker? And/or some concept of asset "owner" (e.g. so asset market X can add their own preview rendering for materials in its library).
TODO How can code register callbacks for a given set of traits? C++ or Python.