577 lines
21 KiB
C++
577 lines
21 KiB
C++
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
#pragma once
|
|
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_sys_types.h"
|
|
|
|
/** \file
|
|
* \ingroup blenloader
|
|
* \brief external readfile function prototypes.
|
|
*/
|
|
|
|
struct AssetMetaData;
|
|
struct BHead;
|
|
struct BlendfileLinkAppendContext;
|
|
struct BlendHandle;
|
|
struct BlendThumbnail;
|
|
struct FileData;
|
|
struct ID;
|
|
struct Library;
|
|
struct LinkNode;
|
|
struct ListBase;
|
|
struct Main;
|
|
struct MemFile;
|
|
struct PreviewImage;
|
|
struct ReportList;
|
|
struct Scene;
|
|
struct UserDef;
|
|
struct View3D;
|
|
struct ViewLayer;
|
|
struct WorkSpace;
|
|
struct bScreen;
|
|
struct wmWindowManager;
|
|
|
|
struct WorkspaceConfigFileData {
|
|
Main *main; /* has to be freed when done reading file data */
|
|
|
|
ListBase workspaces;
|
|
};
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name BLO Read File API
|
|
*
|
|
* \see #BLO_write_file for file writing.
|
|
* \{ */
|
|
|
|
enum eBlenFileType {
|
|
BLENFILETYPE_BLEND = 1,
|
|
// BLENFILETYPE_PUB = 2, /* UNUSED */
|
|
// BLENFILETYPE_RUNTIME = 3, /* UNUSED */
|
|
};
|
|
|
|
struct BlendFileData {
|
|
Main *main;
|
|
UserDef *user;
|
|
|
|
int fileflags;
|
|
int globalf;
|
|
/** Typically the actual filepath of the read blend-file, except when recovering
|
|
* save-on-exit/autosave files. In the latter case, it will be the path of the file that
|
|
* generated the auto-saved one being recovered.
|
|
*
|
|
* NOTE: Currently expected to be the same path as #BlendFileData.filepath. */
|
|
char filepath[1024]; /* 1024 = FILE_MAX */
|
|
|
|
/** TODO: think this isn't needed anymore? */
|
|
bScreen *curscreen;
|
|
Scene *curscene;
|
|
/** Layer to activate in workspaces when reading without UI. */
|
|
ViewLayer *cur_view_layer;
|
|
|
|
eBlenFileType type;
|
|
};
|
|
|
|
/**
|
|
* Data used by WM readfile code and BKE's setup_app_data to handle the complex preservation logic
|
|
* of WindowManager and other UI data-blocks across blend-file reading process.
|
|
*/
|
|
struct BlendFileReadWMSetupData {
|
|
/** The existing WM when file-reading process is started. */
|
|
wmWindowManager *old_wm;
|
|
|
|
/** The startup file is being read. */
|
|
bool is_read_homefile;
|
|
/** The factory startup file is being read. */
|
|
bool is_factory_startup;
|
|
};
|
|
|
|
struct BlendFileReadParams {
|
|
uint skip_flags : 3; /* #eBLOReadSkip */
|
|
uint is_startup : 1;
|
|
uint is_factory_settings : 1;
|
|
|
|
/** Whether we are reading the memfile for an undo or a redo. */
|
|
int undo_direction; /* #eUndoStepDir */
|
|
};
|
|
|
|
struct BlendFileReadReport {
|
|
/** General reports handling. */
|
|
ReportList *reports;
|
|
|
|
/** Timing information. */
|
|
struct {
|
|
double whole;
|
|
double libraries;
|
|
double lib_overrides;
|
|
double lib_overrides_resync;
|
|
double lib_overrides_recursive_resync;
|
|
} duration;
|
|
|
|
/** Count information. */
|
|
struct {
|
|
/**
|
|
* Some numbers of IDs that ended up in a specific state, or required some specific process
|
|
* during this file read.
|
|
*/
|
|
int missing_libraries;
|
|
int missing_linked_id;
|
|
/** Some sub-categories of the above `missing_linked_id` counter. */
|
|
int missing_obdata;
|
|
int missing_obproxies;
|
|
|
|
/** Number of root override IDs that were resynced. */
|
|
int resynced_lib_overrides;
|
|
|
|
/** Number of proxies converted to library overrides. */
|
|
int proxies_to_lib_overrides_success;
|
|
/** Number of proxies that failed to convert to library overrides. */
|
|
int proxies_to_lib_overrides_failures;
|
|
/** Number of sequencer strips that were not read because were in non-supported channels. */
|
|
int sequence_strips_skipped;
|
|
} count;
|
|
|
|
/**
|
|
* Number of libraries which had overrides that needed to be resynced,
|
|
* and a single linked list of those.
|
|
*/
|
|
int resynced_lib_overrides_libraries_count;
|
|
bool do_resynced_lib_overrides_libraries_list;
|
|
LinkNode *resynced_lib_overrides_libraries;
|
|
};
|
|
|
|
/** Skip reading some data-block types (may want to skip screen data too). */
|
|
enum eBLOReadSkip {
|
|
BLO_READ_SKIP_NONE = 0,
|
|
/** Skip #BLO_CODE_USER blocks. */
|
|
BLO_READ_SKIP_USERDEF = (1 << 0),
|
|
/** Only read #BLO_CODE_USER (and associated data). */
|
|
BLO_READ_SKIP_DATA = (1 << 1),
|
|
/** Do not attempt to re-use IDs from old bmain for unchanged ones in case of undo. */
|
|
BLO_READ_SKIP_UNDO_OLD_MAIN = (1 << 2),
|
|
};
|
|
ENUM_OPERATORS(eBLOReadSkip, BLO_READ_SKIP_UNDO_OLD_MAIN)
|
|
#define BLO_READ_SKIP_ALL (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
|
|
|
|
/**
|
|
* Open a blender file from a `filepath`. The function returns NULL
|
|
* and sets a report in the list if it cannot open the file.
|
|
*
|
|
* \param filepath: The path of the file to open.
|
|
* \param reports: If the return value is NULL, errors indicating the cause of the failure.
|
|
* \return The data of the file.
|
|
*/
|
|
BlendFileData *BLO_read_from_file(const char *filepath,
|
|
eBLOReadSkip skip_flags,
|
|
BlendFileReadReport *reports);
|
|
/**
|
|
* Open a blender file from memory. The function returns NULL
|
|
* and sets a report in the list if it cannot open the file.
|
|
*
|
|
* \param mem: The file data.
|
|
* \param memsize: The length of \a mem.
|
|
* \param reports: If the return value is NULL, errors indicating the cause of the failure.
|
|
* \return The data of the file.
|
|
*/
|
|
BlendFileData *BLO_read_from_memory(const void *mem,
|
|
int memsize,
|
|
eBLOReadSkip skip_flags,
|
|
ReportList *reports);
|
|
/**
|
|
* Used for undo/redo, skips part of libraries reading
|
|
* (assuming their data are already loaded & valid).
|
|
*
|
|
* \param oldmain: old main,
|
|
* from which we will keep libraries and other data-blocks that should not have changed.
|
|
* \param filepath: current file, only for retrieving library data.
|
|
* Typically `BKE_main_blendfile_path(oldmain)`.
|
|
*/
|
|
BlendFileData *BLO_read_from_memfile(Main *oldmain,
|
|
const char *filepath,
|
|
MemFile *memfile,
|
|
const BlendFileReadParams *params,
|
|
ReportList *reports);
|
|
|
|
/**
|
|
* Frees a BlendFileData structure and *all* the data associated with it
|
|
* (the userdef data, and the main libblock data).
|
|
*
|
|
* \param bfd: The structure to free.
|
|
*/
|
|
void BLO_blendfiledata_free(BlendFileData *bfd);
|
|
|
|
/**
|
|
* Does versioning code that requires the Main data-base to be fully loaded and valid.
|
|
*
|
|
* readfile's `do_versions` does not allow to create (or delete) IDs, and only operates on a single
|
|
* library at a time.
|
|
*
|
|
* Called at the end of #setup_add_data from BKE's `blendfile.cc`.
|
|
*
|
|
* \param new_bmain: the newly read Main data-base.
|
|
*/
|
|
void BLO_read_do_version_after_setup(Main *new_bmain,
|
|
BlendfileLinkAppendContext *lapp_context,
|
|
BlendFileReadReport *reports);
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name BLO Blend File Handle API
|
|
* \{ */
|
|
|
|
struct BLODataBlockInfo {
|
|
char name[64]; /* MAX_NAME */
|
|
AssetMetaData *asset_data;
|
|
/** Ownership over #asset_data above can be "stolen out" of this struct, for more permanent
|
|
* storage. In that case, set this to false to avoid double freeing of the stolen data. */
|
|
bool free_asset_data;
|
|
/**
|
|
* Optimization: Tag data-blocks for which we know there is no preview.
|
|
* Knowing this can be used to skip the (potentially expensive) preview loading process. If this
|
|
* is set to true it means we looked for a preview and couldn't find one. False may mean that
|
|
* either no preview was found, or that it wasn't looked for in the first place.
|
|
*/
|
|
bool no_preview_found;
|
|
};
|
|
|
|
/**
|
|
* Frees contained data, not \a datablock_info itself.
|
|
*/
|
|
void BLO_datablock_info_free(BLODataBlockInfo *datablock_info);
|
|
/**
|
|
* Can be used to free the list returned by #BLO_blendhandle_get_datablock_info().
|
|
*/
|
|
void BLO_datablock_info_linklist_free(LinkNode * /*BLODataBlockInfo*/ datablock_infos);
|
|
|
|
/**
|
|
* Open a blendhandle from a file path.
|
|
*
|
|
* \param filepath: The file path to open.
|
|
* \param reports: Report errors in opening the file (can be NULL).
|
|
* \return A handle on success, or NULL on failure.
|
|
*/
|
|
BlendHandle *BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport *reports);
|
|
/**
|
|
* Open a blendhandle from memory.
|
|
*
|
|
* \param mem: The data to load from.
|
|
* \param memsize: The size of the data.
|
|
* \return A handle on success, or NULL on failure.
|
|
*/
|
|
BlendHandle *BLO_blendhandle_from_memory(const void *mem,
|
|
int memsize,
|
|
BlendFileReadReport *reports);
|
|
|
|
/**
|
|
* Gets the names of all the data-blocks in a file of a certain type
|
|
* (e.g. all the scene names in a file).
|
|
*
|
|
* \param bh: The blendhandle to access.
|
|
* \param ofblocktype: The type of names to get.
|
|
* \param use_assets_only: Only list IDs marked as assets.
|
|
* \param r_tot_names: The length of the returned list.
|
|
* \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN().
|
|
*/
|
|
LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
|
|
int ofblocktype,
|
|
|
|
bool use_assets_only,
|
|
int *r_tot_names);
|
|
/**
|
|
* Gets the names and asset-data (if ID is an asset) of data-blocks in a file of a certain type.
|
|
* The data-blocks can be limited to assets.
|
|
*
|
|
* \param bh: The blendhandle to access.
|
|
* \param ofblocktype: The type of names to get.
|
|
* \param use_assets_only: Limit the result to assets only.
|
|
* \param r_tot_info_items: The length of the returned list.
|
|
*
|
|
* \return A BLI_linklist of `BLODataBlockInfo *`.
|
|
*
|
|
* \note The links should be freed using #BLO_datablock_info_free() or the entire list using
|
|
* #BLO_datablock_info_linklist_free().
|
|
*/
|
|
LinkNode * /*BLODataBlockInfo*/ BLO_blendhandle_get_datablock_info(BlendHandle *bh,
|
|
int ofblocktype,
|
|
bool use_assets_only,
|
|
int *r_tot_info_items);
|
|
/**
|
|
* Get the PreviewImage of a single data block in a file.
|
|
* (e.g. all the scene previews in a file).
|
|
*
|
|
* \param bh: The blendhandle to access.
|
|
* \param ofblocktype: The type of names to get.
|
|
* \param name: Name of the block without the ID_ prefix, to read the preview image from.
|
|
* \return PreviewImage or NULL when no preview Images have been found. Caller owns the returned
|
|
*/
|
|
PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
|
|
int ofblocktype,
|
|
const char *name);
|
|
/**
|
|
* Gets the names of all the linkable data-block types available in a file.
|
|
* (e.g. "Scene", "Mesh", "Light", etc.).
|
|
*
|
|
* \param bh: The blendhandle to access.
|
|
* \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN().
|
|
*/
|
|
LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh);
|
|
|
|
/**
|
|
* Close and free a blendhandle. The handle becomes invalid after this call.
|
|
*
|
|
* \param bh: The handle to close.
|
|
*/
|
|
void BLO_blendhandle_close(BlendHandle *bh) ATTR_NONNULL(1);
|
|
|
|
/**
|
|
* Mark the given Main (and the 'root' local one in case of lib-split Mains) as invalid, and
|
|
* generate an error report containing given `message`.
|
|
*/
|
|
void BLO_read_invalidate_message(BlendHandle *bh, Main *bmain, const char *message);
|
|
|
|
/**
|
|
* BLI_assert-like macro to check a condition, and if `false`, fail the whole .blend reading
|
|
* process by marking the Main data-base as invalid, and returning provided `_ret_value`.
|
|
*
|
|
* NOTE: About usages:
|
|
* - #BLI_assert should be used when the error is considered as a bug, but there is some code to
|
|
* recover from it and produce a valid Main data-base.
|
|
* - #BLO_read_assert_message should be used when the error is not considered as recoverable.
|
|
*/
|
|
#define BLO_read_assert_message(_check_expr, _ret_value, _bh, _bmain, _message) \
|
|
if (_check_expr) { \
|
|
BLO_read_invalidate_message((_bh), (_bmain), (_message)); \
|
|
return _ret_value; \
|
|
} \
|
|
(void)0
|
|
|
|
/** \} */
|
|
|
|
#define BLO_GROUP_MAX 32
|
|
#define BLO_EMBEDDED_STARTUP_BLEND "<startup.blend>"
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name BLO Blend File Linking API
|
|
* \{ */
|
|
|
|
/**
|
|
* Options controlling behavior of append/link code.
|
|
* \note merged with 'user-level' options from operators etc. in 16 lower bits
|
|
* (see #eFileSel_Params_Flag in DNA_space_types.h).
|
|
*/
|
|
enum eBLOLibLinkFlags {
|
|
/** Generate a placeholder (empty ID) if not found in current lib file. */
|
|
BLO_LIBLINK_USE_PLACEHOLDERS = 1 << 16,
|
|
/** Force loaded ID to be tagged as #ID_TAG_INDIRECT (used in reload context only). */
|
|
BLO_LIBLINK_FORCE_INDIRECT = 1 << 17,
|
|
/** Set fake user on appended IDs. */
|
|
BLO_LIBLINK_APPEND_SET_FAKEUSER = 1 << 19,
|
|
/**
|
|
* 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_RECURSIVE = 1 << 20,
|
|
/** Try to re-use previously appended matching ID on new append. */
|
|
BLO_LIBLINK_APPEND_LOCAL_ID_REUSE = 1 << 21,
|
|
/** Clear the asset data. */
|
|
BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR = 1 << 22,
|
|
/** Instantiate object data IDs (i.e. create objects for them if needed). */
|
|
BLO_LIBLINK_OBDATA_INSTANCE = 1 << 24,
|
|
/** Instantiate collections as empties, instead of linking them into current view layer. */
|
|
BLO_LIBLINK_COLLECTION_INSTANCE = 1 << 25,
|
|
};
|
|
|
|
/**
|
|
* Struct for passing arguments to
|
|
* #BLO_library_link_begin, #BLO_library_link_named_part & #BLO_library_link_end.
|
|
* Wrap these in parameters since it's important both functions receive matching values.
|
|
*/
|
|
struct LibraryLink_Params {
|
|
/** The current main database, e.g. #G_MAIN or `CTX_data_main(C)`. */
|
|
Main *bmain;
|
|
/** Options for linking, used for instantiating. */
|
|
int flag;
|
|
/** Additional tag for #ID.tag. */
|
|
int id_tag_extra;
|
|
/** Context for instancing objects (optional, no instantiation will be performed when NULL). */
|
|
struct {
|
|
/** The scene in which to instantiate objects/collections. */
|
|
Scene *scene;
|
|
/** The scene layer in which to instantiate objects/collections. */
|
|
ViewLayer *view_layer;
|
|
/** The active 3D viewport (only used to define local-view). */
|
|
const View3D *v3d;
|
|
} context;
|
|
};
|
|
|
|
void BLO_library_link_params_init(LibraryLink_Params *params,
|
|
Main *bmain,
|
|
int flag,
|
|
int id_tag_extra);
|
|
void BLO_library_link_params_init_with_context(LibraryLink_Params *params,
|
|
Main *bmain,
|
|
int flag,
|
|
int id_tag_extra,
|
|
Scene *scene,
|
|
ViewLayer *view_layer,
|
|
const View3D *v3d);
|
|
|
|
/**
|
|
* Initialize the #BlendHandle for linking library data.
|
|
*
|
|
* \param bh: A blender file handle as returned by
|
|
* #BLO_blendhandle_from_file or #BLO_blendhandle_from_memory.
|
|
* \param filepath: Used for relative linking, copied to the `lib->filepath`.
|
|
* \param params: Settings for linking that don't change from beginning to end of linking.
|
|
* \return the library #Main, to be passed to #BLO_library_link_named_part as \a mainl.
|
|
*/
|
|
Main *BLO_library_link_begin(BlendHandle **bh,
|
|
const char *filepath,
|
|
const LibraryLink_Params *params);
|
|
/**
|
|
* Link a named data-block from an external blend file.
|
|
*
|
|
* \param mainl: The main database to link from (not the active one).
|
|
* \param bh: The blender file handle.
|
|
* \param idcode: The kind of data-block to link.
|
|
* \param name: The name of the data-block (without the 2 char ID prefix).
|
|
* \return the linked ID when found.
|
|
*/
|
|
ID *BLO_library_link_named_part(Main *mainl,
|
|
BlendHandle **bh,
|
|
short idcode,
|
|
const char *name,
|
|
const LibraryLink_Params *params);
|
|
/**
|
|
* Finalize linking from a given .blend file (library).
|
|
* Optionally instance the indirect object/collection in the scene when the flags are set.
|
|
* \note Do not use \a bh after calling this function, it may frees it.
|
|
*
|
|
* \param mainl: The main database to link from (not the active one).
|
|
* \param bh: The blender file handle (WARNING! may be freed by this function!).
|
|
* \param params: Settings for linking that don't change from beginning to end of linking.
|
|
*/
|
|
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const LibraryLink_Params *params);
|
|
|
|
/**
|
|
* Struct for temporarily loading datablocks from a blend file.
|
|
*/
|
|
struct TempLibraryContext {
|
|
/** Temporary main used for library data. */
|
|
Main *bmain_lib;
|
|
/** Temporary main used to load data into (currently initialized from `real_main`). */
|
|
Main *bmain_base;
|
|
BlendHandle *blendhandle;
|
|
BlendFileReadReport bf_reports;
|
|
LibraryLink_Params liblink_params;
|
|
Library *lib;
|
|
|
|
/** The ID datablock that was loaded. Is NULL if loading failed. */
|
|
ID *temp_id;
|
|
};
|
|
|
|
TempLibraryContext *BLO_library_temp_load_id(Main *real_main,
|
|
const char *blend_file_path,
|
|
short idcode,
|
|
const char *idname,
|
|
ReportList *reports);
|
|
void BLO_library_temp_free(TempLibraryContext *temp_lib_ctx);
|
|
|
|
/** \} */
|
|
|
|
void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname);
|
|
|
|
using BLOExpandDoitCallback = void (*)(void *fdhandle, Main *mainvar, void *idv);
|
|
|
|
/**
|
|
* Loop over all ID data in Main to mark relations.
|
|
* Set (id->tag & ID_TAG_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
|
|
*
|
|
* \param fdhandle: usually file-data, or own handle. May be nullptr.
|
|
* \param mainvar: the Main database to expand.
|
|
* \param calback: Called for each ID block it finds.
|
|
*/
|
|
void BLO_expand_main(void *fdhandle, Main *mainvar, BLOExpandDoitCallback callback);
|
|
|
|
/**
|
|
* Update defaults in startup.blend, without having to save and embed it.
|
|
* \note defaults for preferences are stored in `userdef_default.c` and can be updated there.
|
|
*/
|
|
/**
|
|
* Update defaults in startup.blend, without having to save and embed the file.
|
|
* This function can be emptied each time the startup.blend is updated.
|
|
*
|
|
* \note Screen data may be cleared at this point, this will happen in the case
|
|
* an app-template's data needs to be versioned when read-file is called with "Load UI" disabled.
|
|
* Versioning the screen data can be safely skipped without "Load UI" since the screen data
|
|
* will have been versioned when it was first loaded.
|
|
*/
|
|
void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template);
|
|
void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_template);
|
|
|
|
/** Disable unwanted experimental feature settings on startup. */
|
|
void BLO_sanitize_experimental_features_userpref_blend(UserDef *userdef);
|
|
|
|
/**
|
|
* Does a very light reading of given .blend file to extract its stored thumbnail.
|
|
*
|
|
* \param filepath: The path of the file to extract thumbnail from.
|
|
* \return The raw thumbnail
|
|
* (MEM-allocated, as stored in file, use #BKE_main_thumbnail_to_imbuf()
|
|
* to convert it to ImBuf image).
|
|
*/
|
|
BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
|
|
|
|
/**
|
|
* Does a very light reading of given .blend file to extract its version.
|
|
*
|
|
* \param filepath: The path of the blend file to extract version from.
|
|
* \return The file version
|
|
*/
|
|
short BLO_version_from_file(const char *filepath);
|
|
|
|
/**
|
|
* Runtime structure on `ID.runtime.readfile_data` that is available during the readfile process.
|
|
*
|
|
* This is intended for short-lived data, for example for things that are detected in an early
|
|
* phase of versioning that should be used in a later stage of versioning.
|
|
*
|
|
* \note This is NOT allocated when 'reading' an undo step, as that doesn't have to deal with
|
|
* versioning, linking, and the other stuff that this struct was meant for.
|
|
*/
|
|
struct ID_Readfile_Data {
|
|
struct Tags {
|
|
bool is_id_link_placeholder : 1;
|
|
|
|
/**
|
|
* Set when this ID used a legacy Action, in which case it also should pick
|
|
* an appropriate slot.
|
|
*
|
|
* \see ANIM_versioning.hh
|
|
*/
|
|
bool action_assignment_needs_slot : 1;
|
|
} tags;
|
|
};
|
|
|
|
/**
|
|
* Return `id->runtime.readfile_data->tags` if the `readfile_data` is allocated,
|
|
* otherwise return an all-zero set of tags.
|
|
*/
|
|
ID_Readfile_Data::Tags BLO_readfile_id_runtime_tags(ID &id);
|
|
|
|
/**
|
|
* Free the ID_Readfile_Data of all IDs in this bmain and all their embedded IDs.
|
|
*
|
|
* This is typically called at the end of the versioning process, as after that
|
|
* `ID.runtime.readfile_data` should no longer be needed.
|
|
*/
|
|
void BLO_readfile_id_runtime_data_free_all(Main &bmain);
|
|
|
|
/**
|
|
* Free the ID_Readfile_Data of this ID. Does _not_ deal with embedded IDs.
|
|
*/
|
|
void BLO_readfile_id_runtime_data_free(ID &id);
|