Python API: Add link/append pre/post handlers. #128279
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Code Documentation
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#128279
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "mont29/blender:tmp-link-append-handlers"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The
pre
handler is called after blender internal code is done populatingthe link/append context with data to be processed, and before this data
starts being linked from library files.
The
post
handler is called after blender is done linking, andpotentailly appending and/or instantiating, the requested data and all
of their dependencies.
Both handlers are called with a single argument, the link/append
context.
An new RNA sets of wrappers have been added to expose relevant info from
these internal C++ structures.
NOTE: !113658 is very similar (but tied to asset drag & drop), whereas
this PR is more general (these could probably live hand-in-hand / side-
by-side).
Implements #122357
Some quick py example code:
@blender-bot package
Package build started. Download here when ready.
@blender-bot package darwin
Package build started. Download here when ready.
I tried testing this but I couldn't find my way unfortunately. I'm not too good at reading C++ code so I don't know how correctly I made my assumptions, maybe you or someone else can help me out.
Trying to implement functionalities that I laid out in original design issue:
I need to access custom properties registered on the ID. One of the most pressing issue was that it was impossible to assign objects unique identifiers, because when appended in other file it might not be unique anymore. I want to be able to access that custom property and change it. Right now it looks like I only have access to few read-only hard-coded props for each appended item, but ideally I should be able to just anything on object. How can I do that in post handler? My only idea was to get the names of items, then iterate over
bpy.data.objects
to find obj with that name(or UUID if possible) and access that usingbpy.context
. But I haven't tried this because even if it's possible it is very complicated and potentially expensive to do those iterations.I need a way to access embedded IDs that come with appended object. In my context objects/meshes that are stored as PointerProperties in custom props. For example: I append rig which has prop items such as hair styles registered as pointers, so that I can use custom property to switch between them with my script and only show one at a time. I need to access those objects and set some props on them, for example to set fake user. Is that possible? (It would be possible if above bullet point works correctly. Then I could access like
obj.rig_props.embedded_objects
and iterate over them to set properties, but maybe it's already possible now with other method)This is long shot, but would it be possible to override operator properties in pre handler? Namely "Instance Object Data" property, enabled by default is causing my add-on a lot of headaches if user forgot to disable it. And state of that property isn't remembered so you have to remember to untick it on every use. Way to override it and always disable in pre handler would be amazing.
I will test this on Tuesday, I don't know if that's too late, sorry! ;_; But I trust Nick's feedback ❤️
Generally looks good, notes inline.
In the RNA API using both names LinkAppend seems a bit odd at times, especially for names like
linked_appended_id
which in in fact means linked-or-appended-id.We could consider naming that calls this something less awkward.
Documentation can note that "append" is an option for linking which makes the data local after linking (which is what happens internally). Without having to include
LinkAppend
in all of the names relating to this API... we could even apply this naming to C++ API's although that's out of scope for this PR.@ -0,0 +30,4 @@
BlendfileLinkAppendContextLibrary *ctx_lib = static_cast<BlendfileLinkAppendContextLibrary *>(
ptr->data);
const size_t str_len = ctx_lib->path.length();
BLI_strncpy(value, ctx_lib->path.c_str(), str_len + 1);
picky can be
memcpy
, but |'m not that fussed.@ -0,0 +45,4 @@
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
ptr->data);
const size_t str_len = ctx_item->name.length();
BLI_strncpy(value, ctx_item->name.c_str(), str_len + 1);
picky can be
memcpy
, but |'m not that fussed.Would rather not, using
BLI_strncpy
has some added safety asserts, that actually helped me getting this 'str len arithmetic' right. ;)@ -0,0 +248,4 @@
RNA_define_verify_sdna(false); /* not in sdna */
prop = RNA_def_property(srna, "path", PROP_STRING, PROP_FILEPATH);
Prefer
filepath
for consistency, making it clear this isn't related to other kinds of paths.@ -0,0 +282,4 @@
RNA_define_verify_sdna(false); /* not in sdna */
prop = RNA_def_property(srna, "id_name", PROP_STRING, PROP_NONE);
Could call this
name
&type
? (theid_
prefix seems a bit redundant).Or it could be
name
&id_type
since theid_type
is a more specific value that doesn't have equivalents onbpy.types.ID
instances.name
andid_type
match theID
struct API, so think this is the best option.@ -0,0 +371,4 @@
prop, "Link Info", "Various status info about an item after it has been linked");
RNA_def_property_enum_funcs(prop, "rna_LinkAppendContextItem_link_info_get", nullptr, nullptr);
prop = RNA_def_property(srna, "linked_appended_id", PROP_POINTER, PROP_NONE);
The
linked_appended_*
prefix reads poorly to me. We could just call thisid
? (it looks to be the primary ID which would be referenced), other ID's can be clarified with longer names.@ -0,0 +438,4 @@
"only exposed as read-only data for the pre/post linking handlers");
RNA_define_verify_sdna(false); /* not in sdna */
Instead of exposing all of these in one collection, we could expose them by type, similar to Main & library linking/appending API's, e.g.
data.scenes
,data.objects
... etc.The advantages would be:
id_type
.Lookups by name on the collection would be possible, although I'm not sure if that's really useful in this context.
I don't think that that would be a good idea... It's moving too far away from internal data model to my liking.
Further more, there are cases were name lookup would still not be fully working (in case of missing IDs search and relocation, there can be several libraries processed at the same time, and therefore several ID of the same type and name in the context).
@ -0,0 +439,4 @@
RNA_define_verify_sdna(false); /* not in sdna */
prop = RNA_def_property(srna, "items_array", PROP_COLLECTION, PROP_NONE);
The name seems a bit off, it can't be
items
because of naming collisions with Python, but thearray
suffix is also a bit odd (as this is a collection).Suggestions:
datablocks
,datablocks_pending
...link_append_items
.Even though
datablocks
is arguably not correct in that these aren'tbpy.types.ID
instances, we could consider it close enough as they represent data-blocks being loaded.I would rather not differentiate too much naming between internal code and exposed API if it can be avoided. And
datablock
is not used much in our API currently I believe?link_append_items
is a bit redundant, but can go with that... Or we could also useelements
instead ofitems
?@ -0,0 +515,4 @@
"Instantiate collections as empties, instead of linking them into current view layer"},
{0, nullptr, 0, nullptr, nullptr},
};
prop = RNA_def_property(srna, "flags", PROP_ENUM, PROP_NONE);
In RNA we don't typically call these
flags
as that relates to bit-masks which don't make sense when called from Python, suggestoptions
as we have forbpy.types.Operator
&bpy.props.*
.@ -0,0 +538,4 @@
};
prop = RNA_def_property(srna, "process_stage", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, link_append_process_stage_items);
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
It looks like this shouldn't be treated as a flag based on it's use elsewhere.
Indeed, copy-paste error!
@ -99,6 +99,10 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{"_extension_repos_sync", "on creating or synchronizing the active repository"},
{"_extension_repos_files_clear",
"remove files from the repository directory (uses as a string argument)"},
{"link_append_pre",
It'd be interesting to know if script authors would find it useful to separate: link & append.
It seems plausible a developer might only want to add a handler for the "append" case - if they intend to modify appended data for e.g. which doesn't make sense for library data.
I would find that useful personally. But it would be lower on my priority list, so if it can take time I wouldnt mind if this lands in 4.3 without it.
It is fairly trivial to filter it by checking
'LINK' in link_append_context.flags
(in current build, again will be renamed soon), so don't really see the benefit of adding several handlers here. Not to mention that more 'modes' already exist (append or reuse), and more are likely to be added soon-ish (embedded linking).Thanks for giving it a try. This will be much easier once the RNA structs are in main, and the python API doc has them documented indeed.
This should be possible in the
post
handler? The relevant IDs are all accessible there (currently initems_array[123].linked_append_array
, but this will be renamed soon (see Campbells' review).All indirectly linked/appended data should also be listed in the
items_array
data in thepost
handler. There is no direct information about relations between these IDs though, this you'll have to rebuild yourself if needed.Not for 4.3 (too risky at this stage), but I think it should be possible to make some parts of the LinkAppendContext data (and the related options) editable later, yes.
I'd rather keep
LinkAppend
in struct names at least... I would not consider 'Append' as 'just an option' of linking, actual behavior is more complex than that (and is going to get even more complex in the future with things like embedded linking).Other option would be to find a better generic terminology covering that whole area, but 'Import' is already taken for external formats...
@blender-bot package
Package build started. Download here when ready.
@blender-bot package
Package build started. Download here when ready.
For more generic naming, including the term
blend
/blendfile
makes the functionality unambiguousBlendImport
for e.g.'BlendImport' looks and sounds nice actually!
@mont29 you're right I missed that I could use
linked_appended_id
(whick I think is renamed to justid
now, right?)I think it works fine for my purposes then. One thing I would like to clarify is that
item.id.type
would return type of that ID (like Mesh, Curve, Light for object, or ShaderTexImage for node) whileitem.id_type
would return which ID type it is (Object, Mesh, ShaderTree, etc) right?EDIT: One question I have is if it is possible to differentiate "main" ID being appended from rest that just come with it. For example if user chooses to append object, is it possible to get that object separately from its material, mesh, nodetrees and etc?
Correct
Yes, the (just renamed)
BlendImportContextItem.id_type
will have exactly the same meaning as existingID.id_type
property.Each
BlendImportContextItem
has aimport_info
enum property, inpost
handler, indirectly imported items will be tagged with'INDIRECT_USAGE'
.@blender-bot package
Package build started. Download here when ready.
rna_link_append.cc
torna_blendfile_import.cc
e2867550e3Everything works well for my purposes. I'm liking naming changes too. Thanks everyone who worked on this
@ -0,0 +440,4 @@
RNA_define_verify_sdna(false); /* not in sdna */
/* XXX Cannot use `items` here as this is a reserved Python dict method name. */
XXX
is more for warnings, this isn't something to resolve or fix, so it could beNOTE: cannot use ...
.elements
seems OK but also a bit odd,Possible alternatives:
import_items
data_items
link_items
datablock_items
I'm fine with either
elements
orimport_items
, both are somewhat weird but withing acceptable limits imho. No strong preference so will let you choose the one you prefer. ;)Slight preference for
import_items
matches (keymap_items
,enum_items
...filter_items_by_name
etc).@blender-bot build
@ -0,0 +421,4 @@
RNA_def_property_srna(cprop, "BlendImportContextItems");
srna = RNA_def_struct(brna, "BlendImportContextItems", nullptr);
RNA_def_struct_ui_text(
srna, "Link Append Context Items", "Collection of link/append context items");
Should "Link Append" be renamed to "Import" here? (description mentions link/append).
One other instance of "Link Append" exists here too.
@blender-bot build