Python API: Add link/append pre/post handlers.
The `pre` handler is called after blender internal code is done populating the 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, and potentailly 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 Pull Request: https://projects.blender.org/blender/blender/pulls/128279 ----------------- Some quick py example code: ```python import bpy def my_handler_pre(lapp_context): print("About to {}:\n\t".format("link" if "LINK" in lapp_context.options else "append"), "\n\t".join("{} '{}', from libs ['{}']".format(item.id_type, item.name, "', '".join([l.filepath for l in item.source_libraries])) for item in lapp_context.import_items)) def my_handler_post(lapp_context): print("{}:\n\t".format("Linked" if "LINK" in lapp_context.options else "Appended"), "\n\t".join("{} '{}', from lib '{}'".format(item.id.id_type, item.id.name, item.source_library.filepath) for item in lapp_context.import_items)) bpy.app.handlers.link_append_pre.append(my_handler_pre) bpy.app.handlers.link_append_post.append(my_handler_post) ```
This commit is contained in:
committed by
Bastien Montagne
parent
b46e2e6300
commit
76e7770bc9
@@ -7,16 +7,169 @@
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "BLI_bit_vector.hh"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "BLO_readfile.hh"
|
||||
|
||||
struct BlendHandle;
|
||||
struct ID;
|
||||
struct Library;
|
||||
struct LibraryLink_Params;
|
||||
struct MainLibraryWeakReferenceMap;
|
||||
struct ReportList;
|
||||
|
||||
/* TODO: Rename file to `BKE_blendfile_import.hh`. */
|
||||
/* TODO: Replace `BlendfileLinkAppend` prefix by `blender::bke::blendfile::import` namespace. */
|
||||
/* TODO: Move these enums to scoped enum classes. */
|
||||
|
||||
/** Actions to apply to an item (i.e. linked ID). */
|
||||
enum {
|
||||
LINK_APPEND_ACT_UNSET = 0,
|
||||
LINK_APPEND_ACT_KEEP_LINKED,
|
||||
LINK_APPEND_ACT_REUSE_LOCAL,
|
||||
LINK_APPEND_ACT_MAKE_LOCAL,
|
||||
LINK_APPEND_ACT_COPY_LOCAL,
|
||||
};
|
||||
|
||||
/** Various status info about an item (i.e. linked ID). */
|
||||
enum {
|
||||
/** An indirectly linked ID. */
|
||||
LINK_APPEND_TAG_INDIRECT = 1 << 0,
|
||||
/**
|
||||
* An ID also used as liboverride dependency (either directly, as a liboverride reference, or
|
||||
* indirectly, as data used by a liboverride reference). It should never be directly made local.
|
||||
*
|
||||
* Mutually exclusive with #LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY_ONLY.
|
||||
*/
|
||||
LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY = 1 << 1,
|
||||
/**
|
||||
* An ID only used as liboverride dependency (either directly or indirectly, see
|
||||
* #LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY for precisions). It should not be considered during
|
||||
* the 'make local' process, and remain purely linked data.
|
||||
*
|
||||
* Mutually exclusive with #LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY.
|
||||
*/
|
||||
LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY_ONLY = 1 << 2,
|
||||
};
|
||||
|
||||
/* NOTE: These three structs are currently exposed in header to allow for their usage in RNA.
|
||||
* Regualr C++ code should not access their content directly.
|
||||
*
|
||||
* TODO: Refactor these three structs into classes, and integrated the whole API into them. */
|
||||
struct BlendfileLinkAppendContext;
|
||||
struct BlendfileLinkAppendContextItem;
|
||||
|
||||
/** A data-block (ID) entry in the `items` list from #BlendfileLinkAppendContext. */
|
||||
struct BlendfileLinkAppendContextItem {
|
||||
/**
|
||||
* Link/Append context owner of this item. Used in RNA API, could be removed once RNA paths are
|
||||
* functional.
|
||||
*/
|
||||
BlendfileLinkAppendContext *lapp_context;
|
||||
|
||||
/** Name of the ID (without the heading two-chars IDcode). */
|
||||
std::string name;
|
||||
/** All libraries (from #BlendfileLinkAppendContext.libraries) to try to load this ID from. */
|
||||
blender::BitVector<> libraries;
|
||||
/** ID type. */
|
||||
short idcode;
|
||||
|
||||
/** Type of action to perform on this item, and general status tag information.
|
||||
* NOTE: Mostly used by append post-linking processing. */
|
||||
char action;
|
||||
char tag;
|
||||
|
||||
/** Newly linked ID (nullptr until it has been successfully linked). */
|
||||
ID *new_id;
|
||||
/** Library ID from which the #new_id has been linked (nullptr until it has been successfully
|
||||
* linked). */
|
||||
Library *source_library;
|
||||
/** Liboverride of the linked ID (nullptr until it has been successfully created or an existing
|
||||
* one has been found). */
|
||||
ID *liboverride_id;
|
||||
/**
|
||||
* Whether the item has a matching local ID that was already appended from the same source
|
||||
* before, and has not been modified. In 'Append & Reuse' case, this local ID _may_ be reused
|
||||
* instead of making linked data local again.
|
||||
*/
|
||||
ID *reusable_local_id;
|
||||
|
||||
/** Opaque user data pointer. */
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
/** A blendfile library entry in the `libraries` vector from #BlendfileLinkAppendContext. */
|
||||
struct BlendfileLinkAppendContextLibrary {
|
||||
std::string path; /* Absolute .blend file path. */
|
||||
BlendHandle *blo_handle; /* Blend file handle, if any. */
|
||||
bool blo_handle_is_owned; /* Whether the blend file handle is owned, or borrowed. */
|
||||
/* The blendfile report associated with the `blo_handle`, if owned. */
|
||||
BlendFileReadReport bf_reports;
|
||||
};
|
||||
|
||||
/**
|
||||
* General container for all relevant data for a library/linked-data related operation (linking,
|
||||
* appending, library relocating, etc.).
|
||||
*/
|
||||
struct BlendfileLinkAppendContext {
|
||||
/** List of library paths to search IDs in. */
|
||||
blender::Vector<BlendfileLinkAppendContextLibrary> libraries;
|
||||
/**
|
||||
* List of all ID to try to link from #libraries. This is a linked list because iterators must
|
||||
* not be invalidated when adding more items.
|
||||
*/
|
||||
std::list<BlendfileLinkAppendContextItem> items;
|
||||
using items_iterator_t = std::list<BlendfileLinkAppendContextItem>::iterator;
|
||||
/** Linking/appending parameters. Including `bmain`, `scene`, `viewlayer` and `view3d`. */
|
||||
LibraryLink_Params *params = nullptr;
|
||||
|
||||
/**
|
||||
* What is the current stage of the link/append process. Used mainly by the RNA wrappers for the
|
||||
* pre/post handlers currently.
|
||||
*/
|
||||
enum class ProcessStage {
|
||||
/**
|
||||
* The context data is being filled with data (Libraries and IDs) to process. Nothing has been
|
||||
* linked yet.
|
||||
*/
|
||||
Init = 0,
|
||||
/** The context data is being used to linked IDs. */
|
||||
Linking,
|
||||
/**
|
||||
* The context data is being used to append IDs (i.e. make local linked ones, or re-use already
|
||||
* existing local ones).
|
||||
*/
|
||||
Appending,
|
||||
/**
|
||||
* The context data is being used to instantiate (loose) IDs (i.e. ensure that Collections,
|
||||
* Objects and/or ObjectData IDs are added to the current scene).
|
||||
*/
|
||||
Instantiating,
|
||||
/**
|
||||
* All data has been linked or appended. The context state represents the final result of the
|
||||
* process.
|
||||
*/
|
||||
Done,
|
||||
|
||||
/* NOTE: For the time being, liboverride step is not considered here (#BKE_blendfile_override).
|
||||
* Mainly because it is only available through the BPY API currently. */
|
||||
};
|
||||
ProcessStage process_stage;
|
||||
|
||||
/** Allows to easily find an existing items from an ID pointer. */
|
||||
blender::Map<ID *, BlendfileLinkAppendContextItem *> new_id_to_item;
|
||||
|
||||
/** Runtime info used by append code to manage re-use of already appended matching IDs. */
|
||||
MainLibraryWeakReferenceMap *library_weak_reference_mapping = nullptr;
|
||||
|
||||
/** Embedded blendfile and its size, if needed. */
|
||||
const void *blendfile_mem = nullptr;
|
||||
size_t blendfile_memsize = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate and initialize a new context to link/append data-blocks.
|
||||
@@ -158,6 +311,18 @@ void BKE_blendfile_link_append_context_item_foreach(
|
||||
BlendfileLinkAppendContextItem *item)> callback_function,
|
||||
eBlendfileLinkAppendForeachItemFlag flag);
|
||||
|
||||
/**
|
||||
* Called once the link/append process has been fully initialized (all of its data has been set).
|
||||
*
|
||||
* NOTE: Currently only used to call the matching handler.
|
||||
*/
|
||||
void BKE_blendfile_link_append_context_init_done(BlendfileLinkAppendContext *lapp_context);
|
||||
|
||||
/**
|
||||
* Perform linking operation on all items added to given `lapp_context`.
|
||||
*/
|
||||
void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports);
|
||||
|
||||
/**
|
||||
* Perform append operation, using modern ID usage looper to detect which ID should be kept
|
||||
* linked, made local, duplicated as local, re-used from local etc.
|
||||
@@ -166,10 +331,6 @@ void BKE_blendfile_link_append_context_item_foreach(
|
||||
* #BKE_blendfile_link on the same `lapp_context`.
|
||||
*/
|
||||
void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports);
|
||||
/**
|
||||
* Perform linking operation on all items added to given `lapp_context`.
|
||||
*/
|
||||
void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports);
|
||||
|
||||
/**
|
||||
* Instantiate loose data in the scene (e.g. add object to the active collection).
|
||||
@@ -177,6 +338,13 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re
|
||||
void BKE_blendfile_link_append_instantiate_loose(BlendfileLinkAppendContext *lapp_context,
|
||||
ReportList *reports);
|
||||
|
||||
/**
|
||||
* Finalize the link/append process.
|
||||
*
|
||||
* NOTE: Currently only used to call the matching handler..
|
||||
*/
|
||||
void BKE_blendfile_link_append_context_finalize(BlendfileLinkAppendContext *lapp_context);
|
||||
|
||||
/**
|
||||
* Options controlling the behavior of liboverrides creation.
|
||||
*/
|
||||
|
||||
@@ -110,6 +110,8 @@ enum eCbEvent {
|
||||
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST,
|
||||
BKE_CB_EVT_EXTENSION_REPOS_SYNC,
|
||||
BKE_CB_EVT_EXTENSION_REPOS_FILES_CLEAR,
|
||||
BKE_CB_EVT_BLENDIMPORT_PRE,
|
||||
BKE_CB_EVT_BLENDIMPORT_POST,
|
||||
BKE_CB_EVT_TOT,
|
||||
};
|
||||
|
||||
|
||||
@@ -61,8 +61,12 @@ static ID *asset_link_id(Main &global_main,
|
||||
lapp_context, asset_name, id_type, nullptr);
|
||||
BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, lapp_item, 0);
|
||||
|
||||
BKE_blendfile_link_append_context_init_done(lapp_context);
|
||||
|
||||
BKE_blendfile_link(lapp_context, nullptr);
|
||||
|
||||
BKE_blendfile_link_append_context_finalize(lapp_context);
|
||||
|
||||
ID *local_asset = BKE_blendfile_link_append_context_item_newid_get(lapp_context, lapp_item);
|
||||
|
||||
BKE_blendfile_link_append_context_free(lapp_context);
|
||||
|
||||
@@ -41,6 +41,8 @@ static void copybuffer_append(BlendfileLinkAppendContext *lapp_context,
|
||||
/* Tag existing IDs in given `bmain_dst` as already existing. */
|
||||
BKE_main_id_tag_all(bmain, ID_TAG_PRE_EXISTING, true);
|
||||
|
||||
BKE_blendfile_link_append_context_init_done(lapp_context);
|
||||
|
||||
BKE_blendfile_link(lapp_context, reports);
|
||||
|
||||
/* Mark all library linked objects to be updated. */
|
||||
@@ -53,6 +55,8 @@ static void copybuffer_append(BlendfileLinkAppendContext *lapp_context,
|
||||
/* Instantiate loose data in the scene (e.g. add object to the active collection). */
|
||||
BKE_blendfile_link_append_instantiate_loose(lapp_context, reports);
|
||||
|
||||
BKE_blendfile_link_append_context_finalize(lapp_context);
|
||||
|
||||
/* This must be unset, otherwise these object won't link into other scenes from this blend
|
||||
* file. */
|
||||
BKE_main_id_tag_all(bmain, ID_TAG_PRE_EXISTING, false);
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
@@ -28,11 +26,9 @@
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BLI_bit_vector.hh"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -40,6 +36,10 @@
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.hh"
|
||||
|
||||
#include "BKE_callbacks.hh"
|
||||
#include "BKE_grease_pencil_legacy_convert.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_key.hh"
|
||||
@@ -60,7 +60,6 @@
|
||||
|
||||
#include "BKE_blendfile_link_append.hh"
|
||||
|
||||
#include "BLO_readfile.hh"
|
||||
#include "BLO_writefile.hh"
|
||||
|
||||
static CLG_LogRef LOG = {"bke.blendfile_link_append"};
|
||||
@@ -69,69 +68,6 @@ static CLG_LogRef LOG = {"bke.blendfile_link_append"};
|
||||
/** \name Link/append context implementation and public management API.
|
||||
* \{ */
|
||||
|
||||
struct BlendfileLinkAppendContextItem {
|
||||
/** Name of the ID (without the heading two-chars IDcode). */
|
||||
std::string name;
|
||||
/** All libraries (from #BlendfileLinkAppendContext.libraries) to try to load this ID from. */
|
||||
blender::BitVector<> libraries;
|
||||
/** ID type. */
|
||||
short idcode;
|
||||
|
||||
/** Type of action to perform on this item, and general status tag information.
|
||||
* NOTE: Mostly used by append post-linking processing. */
|
||||
char action;
|
||||
char tag;
|
||||
|
||||
/** Newly linked ID (nullptr until it has been successfully linked). */
|
||||
ID *new_id;
|
||||
/** Library ID from which the #new_id has been linked (nullptr until it has been successfully
|
||||
* linked). */
|
||||
Library *source_library;
|
||||
/** Liboverride of the linked ID (nullptr until it has been successfully created or an existing
|
||||
* one has been found). */
|
||||
ID *liboverride_id;
|
||||
/**
|
||||
* Whether the item has a matching local ID that was already appended from the same source
|
||||
* before, and has not been modified. In 'Append & Reuse' case, this local ID _may_ be reused
|
||||
* instead of making linked data local again.
|
||||
*/
|
||||
ID *reusable_local_id;
|
||||
|
||||
/** Opaque user data pointer. */
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
/* A blendfile library entry in the `libraries` list of #BlendfileLinkAppendContext. */
|
||||
struct BlendfileLinkAppendContextLibrary {
|
||||
std::string path; /* Absolute .blend file path. */
|
||||
BlendHandle *blo_handle; /* Blend file handle, if any. */
|
||||
bool blo_handle_is_owned; /* Whether the blend file handle is owned, or borrowed. */
|
||||
/* The blendfile report associated with the `blo_handle`, if owned. */
|
||||
BlendFileReadReport bf_reports;
|
||||
};
|
||||
|
||||
struct BlendfileLinkAppendContext {
|
||||
/** List of library paths to search IDs in. */
|
||||
blender::Vector<BlendfileLinkAppendContextLibrary> libraries;
|
||||
/**
|
||||
* List of all ID to try to link from #libraries. This is a linked list because iterators must
|
||||
* not be invalidated when adding more items.
|
||||
*/
|
||||
std::list<BlendfileLinkAppendContextItem> items;
|
||||
/** Linking/appending parameters. Including `bmain`, `scene`, `viewlayer` and `view3d`. */
|
||||
LibraryLink_Params *params = nullptr;
|
||||
|
||||
/** Allows to easily find an existing items from an ID pointer. */
|
||||
blender::Map<ID *, BlendfileLinkAppendContextItem *> new_id_to_item;
|
||||
|
||||
/** Runtime info used by append code to manage re-use of already appended matching IDs. */
|
||||
MainLibraryWeakReferenceMap *library_weak_reference_mapping = nullptr;
|
||||
|
||||
/** Embedded blendfile and its size, if needed. */
|
||||
const void *blendfile_mem = nullptr;
|
||||
size_t blendfile_memsize = 0;
|
||||
};
|
||||
|
||||
struct BlendfileLinkAppendContextCallBack {
|
||||
BlendfileLinkAppendContext *lapp_context;
|
||||
BlendfileLinkAppendContextItem *item;
|
||||
@@ -155,36 +91,6 @@ struct BlendfileLinkAppendContextCallBack {
|
||||
bool is_liboverride_dependency_only;
|
||||
};
|
||||
|
||||
/** Actions to apply to an item (i.e. linked ID). */
|
||||
enum {
|
||||
LINK_APPEND_ACT_UNSET = 0,
|
||||
LINK_APPEND_ACT_KEEP_LINKED,
|
||||
LINK_APPEND_ACT_REUSE_LOCAL,
|
||||
LINK_APPEND_ACT_MAKE_LOCAL,
|
||||
LINK_APPEND_ACT_COPY_LOCAL,
|
||||
};
|
||||
|
||||
/** Various status info about an item (i.e. linked ID). */
|
||||
enum {
|
||||
/** An indirectly linked ID. */
|
||||
LINK_APPEND_TAG_INDIRECT = 1 << 0,
|
||||
/**
|
||||
* An ID also used as liboverride dependency (either directly, as a liboverride reference, or
|
||||
* indirectly, as data used by a liboverride reference). It should never be directly made local.
|
||||
*
|
||||
* Mutually exclusive with #LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY_ONLY.
|
||||
*/
|
||||
LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY = 1 << 1,
|
||||
/**
|
||||
* An ID only used as liboverride dependency (either directly or indirectly, see
|
||||
* #LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY for precisions). It should not be considered during
|
||||
* the 'make local' process, and remain purely linked data.
|
||||
*
|
||||
* Mutually exclusive with #LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY.
|
||||
*/
|
||||
LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY_ONLY = 1 << 2,
|
||||
};
|
||||
|
||||
static BlendHandle *link_append_context_library_blohandle_ensure(
|
||||
BlendfileLinkAppendContext &lapp_context,
|
||||
BlendfileLinkAppendContextLibrary &lib_context,
|
||||
@@ -225,6 +131,7 @@ BlendfileLinkAppendContext *BKE_blendfile_link_append_context_new(LibraryLink_Pa
|
||||
{
|
||||
BlendfileLinkAppendContext *lapp_context = MEM_new<BlendfileLinkAppendContext>(__func__);
|
||||
lapp_context->params = params;
|
||||
lapp_context->process_stage = BlendfileLinkAppendContext::ProcessStage::Init;
|
||||
return lapp_context;
|
||||
}
|
||||
|
||||
@@ -273,6 +180,7 @@ void BKE_blendfile_link_append_context_library_add(BlendfileLinkAppendContext *l
|
||||
BlendHandle *blo_handle)
|
||||
{
|
||||
BLI_assert(lapp_context->items.empty());
|
||||
BLI_assert(lapp_context->process_stage == BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
|
||||
BlendfileLinkAppendContextLibrary lib_context = {};
|
||||
|
||||
@@ -293,6 +201,8 @@ BlendfileLinkAppendContextItem *BKE_blendfile_link_append_context_item_add(
|
||||
{
|
||||
BlendfileLinkAppendContextItem item = {};
|
||||
|
||||
item.lapp_context = lapp_context;
|
||||
|
||||
item.name = idname;
|
||||
item.idcode = idcode;
|
||||
item.libraries = blender::BitVector<>(lapp_context->libraries.size(), false);
|
||||
@@ -312,6 +222,8 @@ int BKE_blendfile_link_append_context_item_idtypes_from_library_add(
|
||||
const uint64_t id_types_filter,
|
||||
const int library_index)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage == BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
|
||||
int id_num = 0;
|
||||
int id_code_iter = 0;
|
||||
short id_code;
|
||||
@@ -357,10 +269,12 @@ int BKE_blendfile_link_append_context_item_idtypes_from_library_add(
|
||||
}
|
||||
|
||||
void BKE_blendfile_link_append_context_item_library_index_enable(
|
||||
BlendfileLinkAppendContext * /*lapp_context*/,
|
||||
BlendfileLinkAppendContext *lapp_context,
|
||||
BlendfileLinkAppendContextItem *item,
|
||||
const int library_index)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage == BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
UNUSED_VARS_NDEBUG(lapp_context);
|
||||
item->libraries[library_index].set();
|
||||
}
|
||||
|
||||
@@ -375,9 +289,11 @@ void *BKE_blendfile_link_append_context_item_userdata_get(
|
||||
return item->userdata;
|
||||
}
|
||||
|
||||
ID *BKE_blendfile_link_append_context_item_newid_get(BlendfileLinkAppendContext * /*lapp_context*/,
|
||||
ID *BKE_blendfile_link_append_context_item_newid_get(BlendfileLinkAppendContext *lapp_context,
|
||||
BlendfileLinkAppendContextItem *item)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage != BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
UNUSED_VARS_NDEBUG(lapp_context);
|
||||
return item->new_id;
|
||||
}
|
||||
|
||||
@@ -385,6 +301,7 @@ void BKE_blendfile_link_append_context_item_newid_set(BlendfileLinkAppendContext
|
||||
BlendfileLinkAppendContextItem *item,
|
||||
ID *new_id)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage != BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
BLI_assert(item->new_id);
|
||||
BLI_assert(!item->liboverride_id);
|
||||
BLI_assert(new_id->lib == item->new_id->lib);
|
||||
@@ -396,8 +313,10 @@ void BKE_blendfile_link_append_context_item_newid_set(BlendfileLinkAppendContext
|
||||
}
|
||||
|
||||
ID *BKE_blendfile_link_append_context_item_liboverrideid_get(
|
||||
BlendfileLinkAppendContext * /*lapp_context*/, BlendfileLinkAppendContextItem *item)
|
||||
BlendfileLinkAppendContext *lapp_context, BlendfileLinkAppendContextItem *item)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage != BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
UNUSED_VARS_NDEBUG(lapp_context);
|
||||
return item->liboverride_id;
|
||||
}
|
||||
|
||||
@@ -431,6 +350,28 @@ void BKE_blendfile_link_append_context_item_foreach(
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_blendfile_link_append_context_init_done(BlendfileLinkAppendContext *lapp_context)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage == BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
|
||||
PointerRNA ctx_ptr = RNA_pointer_create(nullptr, &RNA_BlendImportContext, lapp_context);
|
||||
PointerRNA *pointers[1] = {&ctx_ptr};
|
||||
BKE_callback_exec(lapp_context->params->bmain, pointers, 1, BKE_CB_EVT_BLENDIMPORT_PRE);
|
||||
}
|
||||
|
||||
void BKE_blendfile_link_append_context_finalize(BlendfileLinkAppendContext *lapp_context)
|
||||
{
|
||||
BLI_assert(ELEM(lapp_context->process_stage,
|
||||
BlendfileLinkAppendContext::ProcessStage::Linking,
|
||||
BlendfileLinkAppendContext::ProcessStage::Appending,
|
||||
BlendfileLinkAppendContext::ProcessStage::Instantiating));
|
||||
lapp_context->process_stage = BlendfileLinkAppendContext::ProcessStage::Done;
|
||||
|
||||
PointerRNA ctx_ptr = RNA_pointer_create(nullptr, &RNA_BlendImportContext, lapp_context);
|
||||
PointerRNA *pointers[1] = {&ctx_ptr};
|
||||
BKE_callback_exec(lapp_context->params->bmain, pointers, 1, BKE_CB_EVT_BLENDIMPORT_POST);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -1334,6 +1275,9 @@ static void blendfile_append_define_actions(BlendfileLinkAppendContext &lapp_con
|
||||
|
||||
void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage == BlendfileLinkAppendContext::ProcessStage::Linking);
|
||||
lapp_context->process_stage = BlendfileLinkAppendContext::ProcessStage::Appending;
|
||||
|
||||
if (lapp_context->items.empty()) {
|
||||
/* Nothing to append. */
|
||||
return;
|
||||
@@ -1537,6 +1481,11 @@ static int foreach_libblock_link_finalize_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
void BKE_blendfile_link_append_instantiate_loose(BlendfileLinkAppendContext *lapp_context,
|
||||
ReportList *reports)
|
||||
{
|
||||
BLI_assert(ELEM(lapp_context->process_stage,
|
||||
BlendfileLinkAppendContext::ProcessStage::Linking,
|
||||
BlendfileLinkAppendContext::ProcessStage::Appending));
|
||||
lapp_context->process_stage = BlendfileLinkAppendContext::ProcessStage::Instantiating;
|
||||
|
||||
if (!lapp_context->params->context.scene) {
|
||||
return;
|
||||
}
|
||||
@@ -1574,6 +1523,9 @@ void BKE_blendfile_link_append_instantiate_loose(BlendfileLinkAppendContext *lap
|
||||
|
||||
void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
|
||||
{
|
||||
BLI_assert(lapp_context->process_stage == BlendfileLinkAppendContext::ProcessStage::Init);
|
||||
lapp_context->process_stage = BlendfileLinkAppendContext::ProcessStage::Linking;
|
||||
|
||||
if (lapp_context->items.empty()) {
|
||||
/* Nothing to be linked. */
|
||||
return;
|
||||
@@ -1869,6 +1821,8 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
|
||||
|
||||
BKE_main_id_tag_all(bmain, ID_TAG_PRE_EXISTING, true);
|
||||
|
||||
BKE_blendfile_link_append_context_init_done(lapp_context);
|
||||
|
||||
/* We do not want any instantiation here! */
|
||||
BKE_blendfile_link(lapp_context, reports);
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ set(DEFSRC
|
||||
rna_light.cc
|
||||
rna_lightprobe.cc
|
||||
rna_linestyle.cc
|
||||
rna_blendfile_import.cc
|
||||
rna_main.cc
|
||||
rna_mask.cc
|
||||
rna_material.cc
|
||||
|
||||
@@ -4827,6 +4827,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
||||
{"rna_lattice.cc", "rna_lattice_api.cc", RNA_def_lattice},
|
||||
{"rna_layer.cc", nullptr, RNA_def_view_layer},
|
||||
{"rna_linestyle.cc", nullptr, RNA_def_linestyle},
|
||||
{"rna_blendfile_import.cc", nullptr, RNA_def_blendfile_import},
|
||||
{"rna_main.cc", "rna_main_api.cc", RNA_def_main},
|
||||
{"rna_fluid.cc", nullptr, RNA_def_fluid},
|
||||
{"rna_material.cc", "rna_material_api.cc", RNA_def_material},
|
||||
|
||||
556
source/blender/makesrna/intern/rna_blendfile_import.cc
Normal file
556
source/blender/makesrna/intern/rna_blendfile_import.cc
Normal file
@@ -0,0 +1,556 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup RNA
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "BLO_readfile.hh"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_blendfile_link_append.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "BLI_bit_span.hh"
|
||||
# include "BLI_string_utils.hh"
|
||||
|
||||
void rna_BlendImportContextLibrary_filepath_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
int rna_BlendImportContextLibrary_filepath_len(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextLibrary *ctx_lib = static_cast<BlendfileLinkAppendContextLibrary *>(
|
||||
ptr->data);
|
||||
return int(ctx_lib->path.length());
|
||||
}
|
||||
|
||||
void rna_BlendImportContextItem_name_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
int rna_BlendImportContextItem_name_len(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return int(ctx_item->name.length());
|
||||
}
|
||||
|
||||
int rna_BlendImportContextItem_id_type_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return int(ctx_item->idcode);
|
||||
}
|
||||
|
||||
struct RNABlendImportContextItemLibrariesIterator {
|
||||
BlendfileLinkAppendContextItem *ctx_item;
|
||||
blender::bits::BitIterator iter;
|
||||
int iter_index;
|
||||
};
|
||||
|
||||
void rna_BlendImportContextItem_libraries_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
|
||||
const blender::BitVector<> &libraries = ctx_item->libraries;
|
||||
RNABlendImportContextItemLibrariesIterator *libs_iter =
|
||||
MEM_new<RNABlendImportContextItemLibrariesIterator>(
|
||||
__func__, RNABlendImportContextItemLibrariesIterator{ctx_item, libraries.begin(), 0});
|
||||
iter->internal.custom = libs_iter;
|
||||
while (!(*libs_iter->iter) && libs_iter->iter != libs_iter->ctx_item->libraries.end()) {
|
||||
libs_iter->iter.operator++();
|
||||
libs_iter->iter_index++;
|
||||
}
|
||||
iter->valid = (libs_iter->iter != libs_iter->ctx_item->libraries.end());
|
||||
}
|
||||
|
||||
void rna_BlendImportContextItem_libraries_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
RNABlendImportContextItemLibrariesIterator *libs_iter =
|
||||
static_cast<RNABlendImportContextItemLibrariesIterator *>(iter->internal.custom);
|
||||
do {
|
||||
libs_iter->iter.operator++();
|
||||
libs_iter->iter_index++;
|
||||
} while (!(*libs_iter->iter) && libs_iter->iter != libs_iter->ctx_item->libraries.end());
|
||||
iter->valid = (libs_iter->iter != libs_iter->ctx_item->libraries.end());
|
||||
}
|
||||
|
||||
void rna_BlendImportContextItem_libraries_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
RNABlendImportContextItemLibrariesIterator *libs_iter =
|
||||
static_cast<RNABlendImportContextItemLibrariesIterator *>(iter->internal.custom);
|
||||
|
||||
iter->valid = false;
|
||||
iter->internal.custom = nullptr;
|
||||
MEM_delete(libs_iter);
|
||||
}
|
||||
|
||||
PointerRNA rna_BlendImportContextItem_libraries_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
RNABlendImportContextItemLibrariesIterator *libs_iter =
|
||||
static_cast<RNABlendImportContextItemLibrariesIterator *>(iter->internal.custom);
|
||||
|
||||
BlendfileLinkAppendContextLibrary &ctx_lib =
|
||||
libs_iter->ctx_item->lapp_context->libraries[libs_iter->iter_index];
|
||||
return rna_pointer_inherit_refine(&iter->parent, &RNA_BlendImportContextLibrary, &ctx_lib);
|
||||
}
|
||||
|
||||
int rna_BlendImportContextItem_libraries_len(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
|
||||
/* Count amount of enabled libraries in the item's bitmask. */
|
||||
int count = 0;
|
||||
for (const blender::BitRef &bit : ctx_item->libraries) {
|
||||
if (bit) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int rna_BlendImportContextItem_append_action_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return int(ctx_item->action);
|
||||
}
|
||||
|
||||
int rna_BlendImportContextItem_import_info_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return int(ctx_item->tag);
|
||||
}
|
||||
|
||||
PointerRNA rna_BlendImportContextItem_id_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return rna_pointer_inherit_refine(&PointerRNA_NULL, &RNA_ID, ctx_item->new_id);
|
||||
}
|
||||
|
||||
PointerRNA rna_BlendImportContextItem_source_library_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return rna_pointer_inherit_refine(&PointerRNA_NULL, &RNA_Library, ctx_item->source_library);
|
||||
}
|
||||
|
||||
PointerRNA rna_BlendImportContextItem_library_override_id_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return rna_pointer_inherit_refine(&PointerRNA_NULL, &RNA_ID, ctx_item->liboverride_id);
|
||||
}
|
||||
|
||||
PointerRNA rna_BlendImportContextItem_reusable_local_id_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContextItem *ctx_item = static_cast<BlendfileLinkAppendContextItem *>(
|
||||
ptr->data);
|
||||
return rna_pointer_inherit_refine(&PointerRNA_NULL, &RNA_ID, ctx_item->reusable_local_id);
|
||||
}
|
||||
|
||||
struct RNABlendImportContextItemsIterator {
|
||||
BlendfileLinkAppendContext *ctx;
|
||||
BlendfileLinkAppendContext::items_iterator_t iter;
|
||||
};
|
||||
|
||||
void rna_BlendImportContext_import_items_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContext *ctx = static_cast<BlendfileLinkAppendContext *>(ptr->data);
|
||||
|
||||
RNABlendImportContextItemsIterator *items_iter = MEM_new<RNABlendImportContextItemsIterator>(
|
||||
__func__, RNABlendImportContextItemsIterator{ctx, ctx->items.begin()});
|
||||
iter->internal.custom = items_iter;
|
||||
iter->valid = (items_iter->iter != items_iter->ctx->items.end());
|
||||
}
|
||||
|
||||
void rna_BlendImportContext_import_items_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
RNABlendImportContextItemsIterator *items_iter =
|
||||
static_cast<RNABlendImportContextItemsIterator *>(iter->internal.custom);
|
||||
items_iter->iter++;
|
||||
iter->valid = (items_iter->iter != items_iter->ctx->items.end());
|
||||
}
|
||||
|
||||
void rna_BlendImportContext_import_items_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
RNABlendImportContextItemsIterator *items_iter =
|
||||
static_cast<RNABlendImportContextItemsIterator *>(iter->internal.custom);
|
||||
|
||||
iter->valid = false;
|
||||
iter->internal.custom = nullptr;
|
||||
MEM_delete(items_iter);
|
||||
}
|
||||
|
||||
PointerRNA rna_BlendImportContext_import_items_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
RNABlendImportContextItemsIterator *items_iter =
|
||||
static_cast<RNABlendImportContextItemsIterator *>(iter->internal.custom);
|
||||
|
||||
BlendfileLinkAppendContextItem &ctx_item = *items_iter->iter;
|
||||
return rna_pointer_inherit_refine(&iter->parent, &RNA_BlendImportContextItem, &ctx_item);
|
||||
}
|
||||
|
||||
int rna_BlendImportContext_import_items_len(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContext *ctx = static_cast<BlendfileLinkAppendContext *>(ptr->data);
|
||||
return int(ctx->items.size());
|
||||
}
|
||||
|
||||
int rna_BlendImportContext_options_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContext *ctx = static_cast<BlendfileLinkAppendContext *>(ptr->data);
|
||||
return int(ctx->params->flag);
|
||||
}
|
||||
|
||||
int rna_BlendImportContext_process_stage_get(PointerRNA *ptr)
|
||||
{
|
||||
BlendfileLinkAppendContext *ctx = static_cast<BlendfileLinkAppendContext *>(ptr->data);
|
||||
return int(ctx->process_stage);
|
||||
}
|
||||
|
||||
#else /* RNA_RUNTIME */
|
||||
|
||||
static void rna_def_blendfile_import_library(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "BlendImportContextLibrary", nullptr);
|
||||
RNA_def_struct_ui_text(
|
||||
srna,
|
||||
"Blendfile Import Context Library",
|
||||
"Library (blendfile) reference in a BlendImportContext data. Currently only "
|
||||
"exposed as read-only data for the pre/post blendimport handlers");
|
||||
|
||||
RNA_define_verify_sdna(false); /* not in sdna */
|
||||
|
||||
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_string_funcs(prop,
|
||||
"rna_BlendImportContextLibrary_filepath_get",
|
||||
"rna_BlendImportContextLibrary_filepath_len",
|
||||
nullptr);
|
||||
|
||||
RNA_define_verify_sdna(true); /* not in sdna */
|
||||
}
|
||||
|
||||
static void RNA_def_blendfile_import_libraries(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
RNA_def_property_srna(cprop, "BlendImportContextLibraries");
|
||||
srna = RNA_def_struct(brna, "BlendImportContextLibraries", nullptr);
|
||||
RNA_def_struct_ui_text(srna,
|
||||
"Blendfile Import Context Libraries",
|
||||
"Collection of source libraries, i.e. blendfile paths");
|
||||
}
|
||||
|
||||
static void rna_def_blendfile_import_item(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "BlendImportContextItem", nullptr);
|
||||
RNA_def_struct_ui_text(
|
||||
srna,
|
||||
"Blendfile Import Context Item",
|
||||
"An item (representing a data-block) in a BlendImportContext data. Currently only "
|
||||
"exposed as read-only data for the pre/post linking handlers");
|
||||
|
||||
RNA_define_verify_sdna(false); /* not in sdna */
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "ID Name", "ID name of the item");
|
||||
RNA_def_property_string_funcs(
|
||||
prop, "rna_BlendImportContextItem_name_get", "rna_BlendImportContextItem_name_len", nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_enum_id_type_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "ID Type", "ID type of the item");
|
||||
RNA_def_property_enum_funcs(prop, "rna_BlendImportContextItem_id_type_get", nullptr, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "source_libraries", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "BlendImportContextLibrary");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Source Libraries",
|
||||
"List of libraries to search and import that ID from. The ID will be "
|
||||
"imported from the first file in that list that contains it");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_BlendImportContextItem_libraries_begin",
|
||||
"rna_BlendImportContextItem_libraries_next",
|
||||
"rna_BlendImportContextItem_libraries_end",
|
||||
"rna_BlendImportContextItem_libraries_get",
|
||||
"rna_BlendImportContextItem_libraries_len",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
RNA_def_blendfile_import_libraries(brna, prop);
|
||||
|
||||
static const EnumPropertyItem blend_import_item_append_action_items[] = {
|
||||
{LINK_APPEND_ACT_UNSET, "UNSET", 0, "", "Not yet defined"},
|
||||
{LINK_APPEND_ACT_KEEP_LINKED, "KEEP_LINKED", 0, "", "ID has been kept linked"},
|
||||
{LINK_APPEND_ACT_REUSE_LOCAL,
|
||||
"REUSE_LOCAL",
|
||||
0,
|
||||
"",
|
||||
"An existing matching local ID has been re-used"},
|
||||
{LINK_APPEND_ACT_MAKE_LOCAL, "MAKE_LOCAL", 0, "", "The newly linked ID has been made local"},
|
||||
{LINK_APPEND_ACT_COPY_LOCAL,
|
||||
"COPY_LOCAL",
|
||||
0,
|
||||
"",
|
||||
"The linked ID had other unrelated usages, so it has been duplicated into a local copy"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
prop = RNA_def_property(srna, "append_action", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, blend_import_item_append_action_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Append Action",
|
||||
"How this item has been handled by the append operation. Only set if "
|
||||
"the data has been appended");
|
||||
RNA_def_property_enum_funcs(
|
||||
prop, "rna_BlendImportContextItem_append_action_get", nullptr, nullptr);
|
||||
|
||||
static const EnumPropertyItem blend_import_item_import_info_items[] = {
|
||||
{LINK_APPEND_TAG_INDIRECT,
|
||||
"INDIRECT_USAGE",
|
||||
0,
|
||||
"",
|
||||
"That item was added for an indirectly imported ID, as a dependency of another data-block"},
|
||||
{LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY,
|
||||
"LIBOVERRIDE_DEPENDENCY",
|
||||
0,
|
||||
"",
|
||||
"That item represents an ID also used as liboverride dependency (either directly, as a "
|
||||
"liboverride reference, or indirectly, as data used by a liboverride reference). It should "
|
||||
"never be directly made local. Mutually exclusive with `LIBOVERRIDE_DEPENDENCY_ONLY`"},
|
||||
{LINK_APPEND_TAG_LIBOVERRIDE_DEPENDENCY_ONLY,
|
||||
"LIBOVERRIDE_DEPENDENCY_ONLY",
|
||||
0,
|
||||
"",
|
||||
"That item represents an ID only used as liboverride dependency (either directly or "
|
||||
"indirectly, see `LIBOVERRIDE_DEPENDENCY` for precisions). It should not be considered "
|
||||
"during the 'make local' (append) process, and remain purely linked data. Mutually "
|
||||
"exclusive with `LIBOVERRIDE_DEPENDENCY`"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
prop = RNA_def_property(srna, "import_info", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, blend_import_item_import_info_items);
|
||||
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Import Info", "Various status info about an item after it has been imported");
|
||||
RNA_def_property_enum_funcs(
|
||||
prop, "rna_BlendImportContextItem_import_info_get", nullptr, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ID");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Imported ID",
|
||||
"The imported ID. None until it has been linked or appended. May be "
|
||||
"the same as `reusable_local_id` when appended");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, "rna_BlendImportContextItem_id_get", nullptr, nullptr, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "source_library", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Library");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Source Library",
|
||||
"Library ID representing the blendfile from which the ID was imported. "
|
||||
"None until the ID has been linked or appended");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, "rna_BlendImportContextItem_source_library_get", nullptr, nullptr, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "library_override_id", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ID");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Library Overridden ID",
|
||||
"The library override of the linked ID. None until it has been created");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, "rna_BlendImportContextItem_library_override_id_get", nullptr, nullptr, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "reusable_local_id", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ID");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Reusable Local ID",
|
||||
"The already existing local ID that may be reused in append & reuse "
|
||||
"case. None until it has been found");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, "rna_BlendImportContextItem_reusable_local_id_get", nullptr, nullptr, nullptr);
|
||||
|
||||
RNA_define_verify_sdna(true); /* not in sdna */
|
||||
}
|
||||
|
||||
static void rna_def_blendfile_import_items(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
RNA_def_property_srna(cprop, "BlendImportContextItems");
|
||||
srna = RNA_def_struct(brna, "BlendImportContextItems", nullptr);
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Blendfile Import Context Items", "Collection of blendfile import context items");
|
||||
|
||||
/* TODO: Add/Remove items _before_ doing link/append (i.e. for 'pre' handlers). */
|
||||
}
|
||||
|
||||
static void rna_def_blendfile_import_context(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "BlendImportContext", nullptr);
|
||||
RNA_def_struct_ui_text(
|
||||
srna,
|
||||
"Blendfile Import Context",
|
||||
"Contextual data for a blendfile library/linked-data related operation. Currently "
|
||||
"only exposed as read-only data for the pre/post blendimport handlers");
|
||||
|
||||
RNA_define_verify_sdna(false); /* not in sdna */
|
||||
|
||||
/* NOTE: Cannot use just `items` here as this is a reserved Python dict method name. */
|
||||
prop = RNA_def_property(srna, "import_items", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "BlendImportContextItem");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_BlendImportContext_import_items_begin",
|
||||
"rna_BlendImportContext_import_items_next",
|
||||
"rna_BlendImportContext_import_items_end",
|
||||
"rna_BlendImportContext_import_items_get",
|
||||
"rna_BlendImportContext_import_items_len",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
rna_def_blendfile_import_items(brna, prop);
|
||||
|
||||
static const EnumPropertyItem blend_import_options_items[] = {
|
||||
{FILE_LINK, "LINK", 0, "", "Only link data, instead of appending it"},
|
||||
{FILE_RELPATH,
|
||||
"MAKE_PATHS_RELATIVE",
|
||||
0,
|
||||
"",
|
||||
"Make paths of used library blendfiles relative to current blendfile"},
|
||||
{BLO_LIBLINK_USE_PLACEHOLDERS,
|
||||
"USE_PLACEHOLDERS",
|
||||
0,
|
||||
"",
|
||||
"Generate a placeholder (empty ID) if not found in any library files"},
|
||||
{BLO_LIBLINK_FORCE_INDIRECT,
|
||||
"FORCE_INDIRECT",
|
||||
0,
|
||||
"",
|
||||
"Force loaded ID to be tagged as indirectly linked (used in reload context only)"},
|
||||
{BLO_LIBLINK_APPEND_SET_FAKEUSER,
|
||||
"APPEND_SET_FAKEUSER",
|
||||
0,
|
||||
"",
|
||||
"Set fake user on appended IDs"},
|
||||
{BLO_LIBLINK_APPEND_RECURSIVE,
|
||||
"APPEND_RECURSIVE",
|
||||
0,
|
||||
"",
|
||||
"Append (make local) also indirect dependencies of appended IDs coming from other "
|
||||
"libraries. NOTE: All IDs (including indirectly linked ones) coming from the same initial "
|
||||
"library are always made local"},
|
||||
{BLO_LIBLINK_APPEND_LOCAL_ID_REUSE,
|
||||
"APPEND_LOCAL_ID_REUSE",
|
||||
0,
|
||||
"",
|
||||
"Try to re-use previously appended matching IDs when appending them again, instead of "
|
||||
"creating local duplicates"},
|
||||
{BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR,
|
||||
"APPEND_ASSET_DATA_CLEAR",
|
||||
0,
|
||||
"",
|
||||
"Clear the asset data on append (it is always kept for linked data)"},
|
||||
{FILE_AUTOSELECT, "SELECT_OBJECTS", 0, "", "Automatically select imported objects"},
|
||||
{FILE_ACTIVE_COLLECTION,
|
||||
"USE_ACTIVE_COLLECTION",
|
||||
0,
|
||||
"",
|
||||
"Use the active Collection of the current View Layer to instantiate imported "
|
||||
"collections and objects"},
|
||||
{BLO_LIBLINK_OBDATA_INSTANCE,
|
||||
"OBDATA_INSTANCE",
|
||||
0,
|
||||
"",
|
||||
"Instantiate object data IDs (i.e. create objects for them if needed)"},
|
||||
{BLO_LIBLINK_COLLECTION_INSTANCE,
|
||||
"COLLECTION_INSTANCE",
|
||||
0,
|
||||
"",
|
||||
"Instantiate collections as empties, instead of linking them into the current view layer"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
prop = RNA_def_property(srna, "options", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, blend_import_options_items);
|
||||
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "", "Options for this blendfile import operation");
|
||||
RNA_def_property_enum_funcs(prop, "rna_BlendImportContext_options_get", nullptr, nullptr);
|
||||
|
||||
/* NOTE: Only stages currently exposed to handlers are listed here. */
|
||||
static const EnumPropertyItem blend_import_process_stage_items[] = {
|
||||
{int(BlendfileLinkAppendContext::ProcessStage::Init),
|
||||
"INIT",
|
||||
0,
|
||||
"",
|
||||
"Blendfile import context has been initialized and filled with a list of items to import, "
|
||||
"no data has been linked or appended yet"},
|
||||
{int(BlendfileLinkAppendContext::ProcessStage::Done),
|
||||
"DONE",
|
||||
0,
|
||||
"",
|
||||
"All data has been imported and is available in the list of `import_items`"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
prop = RNA_def_property(srna, "process_stage", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, blend_import_process_stage_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "", "Current stage of the import process");
|
||||
RNA_def_property_enum_funcs(prop, "rna_BlendImportContext_process_stage_get", nullptr, nullptr);
|
||||
|
||||
RNA_define_verify_sdna(true); /* not in sdna */
|
||||
}
|
||||
|
||||
void RNA_def_blendfile_import(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_blendfile_import_library(brna);
|
||||
rna_def_blendfile_import_item(brna);
|
||||
rna_def_blendfile_import_context(brna);
|
||||
}
|
||||
|
||||
#endif /* RNA_RUNTIME */
|
||||
@@ -166,6 +166,7 @@ void RNA_def_key(BlenderRNA *brna);
|
||||
void RNA_def_light(BlenderRNA *brna);
|
||||
void RNA_def_lattice(BlenderRNA *brna);
|
||||
void RNA_def_linestyle(BlenderRNA *brna);
|
||||
void RNA_def_blendfile_import(BlenderRNA *brna);
|
||||
void RNA_def_main(BlenderRNA *brna);
|
||||
void RNA_def_material(BlenderRNA *brna);
|
||||
void RNA_def_mesh(BlenderRNA *brna);
|
||||
|
||||
@@ -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)"},
|
||||
{"blend_import_pre",
|
||||
"on linking or appending data (before), get a single `BlendImportContext` parameter"},
|
||||
{"blend_import_post",
|
||||
"on linking or appending data (after), get a single `BlendImportContext` parameter"},
|
||||
|
||||
/* sets the permanent tag */
|
||||
#define APP_CB_OTHER_FIELDS 1
|
||||
|
||||
@@ -527,6 +527,8 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject * /*args*/)
|
||||
}
|
||||
}
|
||||
|
||||
BKE_blendfile_link_append_context_init_done(lapp_context);
|
||||
|
||||
BKE_blendfile_link(lapp_context, nullptr);
|
||||
if (do_append) {
|
||||
BKE_blendfile_append(lapp_context, nullptr);
|
||||
@@ -535,6 +537,8 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject * /*args*/)
|
||||
BKE_blendfile_override(lapp_context, self->liboverride_flags, nullptr);
|
||||
}
|
||||
|
||||
BKE_blendfile_link_append_context_finalize(lapp_context);
|
||||
|
||||
/* If enabled, replace named items in given lists by the final matching new ID pointer. */
|
||||
#ifdef USE_RNA_DATABLOCKS
|
||||
idcode_step = 0;
|
||||
|
||||
@@ -350,6 +350,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_blendfile_link_append_context_init_done(lapp_context);
|
||||
|
||||
/* XXX We'd need re-entrant locking on Main for this to work... */
|
||||
// BKE_main_lock(bmain);
|
||||
|
||||
@@ -369,6 +371,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
|
||||
/* Instantiate loose data in the scene (e.g. add object to the active collection). */
|
||||
BKE_blendfile_link_append_instantiate_loose(lapp_context, op->reports);
|
||||
|
||||
BKE_blendfile_link_append_context_finalize(lapp_context);
|
||||
|
||||
BKE_blendfile_link_append_context_free(lapp_context);
|
||||
|
||||
/* Important we unset, otherwise these object won't
|
||||
@@ -543,6 +547,8 @@ static ID *wm_file_link_append_datablock_ex(Main *bmain,
|
||||
lapp_context, id_name, id_code, nullptr);
|
||||
BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, item, 0);
|
||||
|
||||
BKE_blendfile_link_append_context_init_done(lapp_context);
|
||||
|
||||
/* Link datablock. */
|
||||
BKE_blendfile_link(lapp_context, nullptr);
|
||||
|
||||
@@ -552,6 +558,8 @@ static ID *wm_file_link_append_datablock_ex(Main *bmain,
|
||||
|
||||
BKE_blendfile_link_append_instantiate_loose(lapp_context, nullptr);
|
||||
|
||||
BKE_blendfile_link_append_context_finalize(lapp_context);
|
||||
|
||||
/* Get linked datablock and free working data. */
|
||||
ID *id = BKE_blendfile_link_append_context_item_newid_get(lapp_context, item);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user