Add option to link assets on drag & drop
Note: Linking in this case as in link vs. append. Easily confused with linking a data-block to multiple usages (e.g. single material used by multiple objects). Adds a drop-down to the Asset Browser header to choose between Link and Append. This is probably gonna be a temporary place, T54642 shows where this could be placed eventually. Linking support is crucial for usage of the asset browser in production environments. It just wasn't enabled yet because a) the asset project currently focuses on single user, not production assets, and b) because there were many unkowns still for the workflow that have big impact on production use as well. With the recently held asset workshop I'm more confident with enabling linking, as design ideas relevant to production use were confirmed. Differential Revision: https://developer.blender.org/D11536 Reviewed by: Bastien Montagne
This commit is contained in:
@@ -44,6 +44,10 @@ class FILEBROWSER_HT_header(Header):
|
|||||||
|
|
||||||
layout.separator_spacer()
|
layout.separator_spacer()
|
||||||
|
|
||||||
|
layout.prop(params, "import_type", text="")
|
||||||
|
|
||||||
|
layout.separator_spacer()
|
||||||
|
|
||||||
# Uses prop_with_popover() as popover() only adds the triangle icon in headers.
|
# Uses prop_with_popover() as popover() only adds the triangle icon in headers.
|
||||||
layout.prop_with_popover(
|
layout.prop_with_popover(
|
||||||
params,
|
params,
|
||||||
|
@@ -244,5 +244,20 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FOREACH_NODETREE_END;
|
FOREACH_NODETREE_END;
|
||||||
|
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "FileAssetSelectParams", "int", "import_type")) {
|
||||||
|
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||||
|
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||||
|
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||||
|
if (sl->spacetype == SPACE_FILE) {
|
||||||
|
SpaceFile *sfile = (SpaceFile *)sl;
|
||||||
|
if (sfile->asset_params) {
|
||||||
|
sfile->asset_params->import_type = FILE_ASSET_IMPORT_APPEND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -723,6 +723,7 @@ void UI_but_drag_set_asset(uiBut *but,
|
|||||||
const char *name,
|
const char *name,
|
||||||
const char *path,
|
const char *path,
|
||||||
int id_type,
|
int id_type,
|
||||||
|
int import_type, /* eFileAssetImportType */
|
||||||
int icon,
|
int icon,
|
||||||
struct ImBuf *imb,
|
struct ImBuf *imb,
|
||||||
float scale);
|
float scale);
|
||||||
|
@@ -6144,6 +6144,7 @@ void UI_but_drag_set_asset(uiBut *but,
|
|||||||
const char *name,
|
const char *name,
|
||||||
const char *path,
|
const char *path,
|
||||||
int id_type,
|
int id_type,
|
||||||
|
int import_type,
|
||||||
int icon,
|
int icon,
|
||||||
struct ImBuf *imb,
|
struct ImBuf *imb,
|
||||||
float scale)
|
float scale)
|
||||||
@@ -6153,6 +6154,7 @@ void UI_but_drag_set_asset(uiBut *but,
|
|||||||
BLI_strncpy(asset_drag->name, name, sizeof(asset_drag->name));
|
BLI_strncpy(asset_drag->name, name, sizeof(asset_drag->name));
|
||||||
asset_drag->path = path;
|
asset_drag->path = path;
|
||||||
asset_drag->id_type = id_type;
|
asset_drag->id_type = id_type;
|
||||||
|
asset_drag->import_type = import_type;
|
||||||
|
|
||||||
but->dragtype = WM_DRAG_ASSET;
|
but->dragtype = WM_DRAG_ASSET;
|
||||||
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
|
ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */
|
||||||
|
@@ -142,7 +142,8 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh
|
|||||||
color);
|
color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_draw_icon(uiBlock *block,
|
static void file_draw_icon(const SpaceFile *sfile,
|
||||||
|
uiBlock *block,
|
||||||
const FileDirEntry *file,
|
const FileDirEntry *file,
|
||||||
const char *path,
|
const char *path,
|
||||||
int sx,
|
int sx,
|
||||||
@@ -177,10 +178,14 @@ static void file_draw_icon(uiBlock *block,
|
|||||||
ImBuf *preview_image = filelist_file_getimage(file);
|
ImBuf *preview_image = filelist_file_getimage(file);
|
||||||
char blend_path[FILE_MAX_LIBEXTRA];
|
char blend_path[FILE_MAX_LIBEXTRA];
|
||||||
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
|
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
|
||||||
|
const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
|
||||||
|
BLI_assert(asset_params != NULL);
|
||||||
|
|
||||||
UI_but_drag_set_asset(but,
|
UI_but_drag_set_asset(but,
|
||||||
file->name,
|
file->name,
|
||||||
BLI_strdup(blend_path),
|
BLI_strdup(blend_path),
|
||||||
file->blentype,
|
file->blentype,
|
||||||
|
asset_params->import_type,
|
||||||
icon,
|
icon,
|
||||||
preview_image,
|
preview_image,
|
||||||
UI_DPI_FAC);
|
UI_DPI_FAC);
|
||||||
@@ -299,7 +304,8 @@ void file_calc_previews(const bContext *C, ARegion *region)
|
|||||||
UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
|
UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_draw_preview(uiBlock *block,
|
static void file_draw_preview(const SpaceFile *sfile,
|
||||||
|
uiBlock *block,
|
||||||
const FileDirEntry *file,
|
const FileDirEntry *file,
|
||||||
const char *path,
|
const char *path,
|
||||||
int sx,
|
int sx,
|
||||||
@@ -484,9 +490,19 @@ static void file_draw_preview(uiBlock *block,
|
|||||||
/* path is no more static, cannot give it directly to but... */
|
/* path is no more static, cannot give it directly to but... */
|
||||||
else if (file->typeflag & FILE_TYPE_ASSET) {
|
else if (file->typeflag & FILE_TYPE_ASSET) {
|
||||||
char blend_path[FILE_MAX_LIBEXTRA];
|
char blend_path[FILE_MAX_LIBEXTRA];
|
||||||
|
|
||||||
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
|
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
|
||||||
UI_but_drag_set_asset(
|
const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
|
||||||
but, file->name, BLI_strdup(blend_path), file->blentype, icon, imb, scale);
|
BLI_assert(asset_params != NULL);
|
||||||
|
|
||||||
|
UI_but_drag_set_asset(but,
|
||||||
|
file->name,
|
||||||
|
BLI_strdup(blend_path),
|
||||||
|
file->blentype,
|
||||||
|
asset_params->import_type,
|
||||||
|
icon,
|
||||||
|
imb,
|
||||||
|
scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -925,7 +941,8 @@ void file_draw_list(const bContext *C, ARegion *region)
|
|||||||
is_icon = 1;
|
is_icon = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_draw_preview(block,
|
file_draw_preview(sfile,
|
||||||
|
block,
|
||||||
file,
|
file,
|
||||||
path,
|
path,
|
||||||
sx,
|
sx,
|
||||||
@@ -940,7 +957,8 @@ void file_draw_list(const bContext *C, ARegion *region)
|
|||||||
is_link);
|
is_link);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
file_draw_icon(block,
|
file_draw_icon(sfile,
|
||||||
|
block,
|
||||||
file,
|
file,
|
||||||
path,
|
path,
|
||||||
sx,
|
sx,
|
||||||
|
@@ -120,6 +120,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
|
|||||||
asset_params->base_params.details_flags = U_default.file_space_data.details_flags;
|
asset_params->base_params.details_flags = U_default.file_space_data.details_flags;
|
||||||
asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL;
|
asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL;
|
||||||
asset_params->asset_library.custom_library_index = -1;
|
asset_params->asset_library.custom_library_index = -1;
|
||||||
|
asset_params->import_type = FILE_ASSET_IMPORT_APPEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSelectParams *base_params = &asset_params->base_params;
|
FileSelectParams *base_params = &asset_params->base_params;
|
||||||
|
@@ -780,8 +780,16 @@ typedef struct FileAssetSelectParams {
|
|||||||
FileSelectParams base_params;
|
FileSelectParams base_params;
|
||||||
|
|
||||||
FileSelectAssetLibraryUID asset_library;
|
FileSelectAssetLibraryUID asset_library;
|
||||||
|
|
||||||
|
short import_type; /* eFileAssetImportType */
|
||||||
|
char _pad[6];
|
||||||
} FileAssetSelectParams;
|
} FileAssetSelectParams;
|
||||||
|
|
||||||
|
typedef enum eFileAssetImportType {
|
||||||
|
FILE_ASSET_IMPORT_LINK = 0,
|
||||||
|
FILE_ASSET_IMPORT_APPEND = 1,
|
||||||
|
} eFileAssetImportType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper to store previous and next folder lists (#FolderList) for a specific browse mode
|
* A wrapper to store previous and next folder lists (#FolderList) for a specific browse mode
|
||||||
* (#eFileBrowse_Mode).
|
* (#eFileBrowse_Mode).
|
||||||
|
@@ -6569,6 +6569,16 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna)
|
|||||||
{0, NULL, 0, NULL, NULL},
|
{0, NULL, 0, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const EnumPropertyItem asset_import_type_items[] = {
|
||||||
|
{FILE_ASSET_IMPORT_LINK, "LINK", 0, "Link", "Import the assets as linked data-block"},
|
||||||
|
{FILE_ASSET_IMPORT_APPEND,
|
||||||
|
"APPEND",
|
||||||
|
0,
|
||||||
|
"Append",
|
||||||
|
"Import the assets as copied data-block, with no link to the original asset data-block"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "FileAssetSelectParams", "FileSelectParams");
|
srna = RNA_def_struct(brna, "FileAssetSelectParams", "FileSelectParams");
|
||||||
RNA_def_struct_ui_text(
|
RNA_def_struct_ui_text(
|
||||||
srna, "Asset Select Parameters", "Settings for the file selection in Asset Browser mode");
|
srna, "Asset Select Parameters", "Settings for the file selection in Asset Browser mode");
|
||||||
@@ -6590,6 +6600,13 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna)
|
|||||||
NULL);
|
NULL);
|
||||||
RNA_def_property_ui_text(prop, "Asset Category", "Determine which kind of assets to display");
|
RNA_def_property_ui_text(prop, "Asset Category", "Determine which kind of assets to display");
|
||||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
|
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "import_type", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, asset_import_type_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Import Type", "Determine how the asset will be imported");
|
||||||
|
/* Asset drag info saved by buttons stores the import type, so the space must redraw when import
|
||||||
|
* type changes. */
|
||||||
|
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_filemenu_entry(BlenderRNA *brna)
|
static void rna_def_filemenu_entry(BlenderRNA *brna)
|
||||||
|
@@ -205,6 +205,13 @@ void WM_autosave_init(struct wmWindowManager *wm);
|
|||||||
bool WM_recover_last_session(struct bContext *C, struct ReportList *reports);
|
bool WM_recover_last_session(struct bContext *C, struct ReportList *reports);
|
||||||
void WM_file_tag_modified(void);
|
void WM_file_tag_modified(void);
|
||||||
|
|
||||||
|
struct ID *WM_file_link_datablock(struct Main *bmain,
|
||||||
|
struct Scene *scene,
|
||||||
|
struct ViewLayer *view_layer,
|
||||||
|
struct View3D *v3d,
|
||||||
|
const char *filepath,
|
||||||
|
const short id_code,
|
||||||
|
const char *id_name);
|
||||||
struct ID *WM_file_append_datablock(struct Main *bmain,
|
struct ID *WM_file_append_datablock(struct Main *bmain,
|
||||||
struct Scene *scene,
|
struct Scene *scene,
|
||||||
struct ViewLayer *view_layer,
|
struct ViewLayer *view_layer,
|
||||||
|
@@ -920,6 +920,7 @@ typedef struct wmDragAsset {
|
|||||||
/* Always freed. */
|
/* Always freed. */
|
||||||
const char *path;
|
const char *path;
|
||||||
int id_type;
|
int id_type;
|
||||||
|
int import_type; /* eFileAssetImportType */
|
||||||
} wmDragAsset;
|
} wmDragAsset;
|
||||||
|
|
||||||
typedef struct wmDrag {
|
typedef struct wmDrag {
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "DNA_screen_types.h"
|
#include "DNA_screen_types.h"
|
||||||
|
#include "DNA_space_types.h"
|
||||||
#include "DNA_windowmanager_types.h"
|
#include "DNA_windowmanager_types.h"
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
@@ -377,9 +378,17 @@ wmDragAsset *WM_drag_get_asset_data(const wmDrag *drag, int idcode)
|
|||||||
|
|
||||||
static ID *wm_drag_asset_id_import(wmDragAsset *asset_drag)
|
static ID *wm_drag_asset_id_import(wmDragAsset *asset_drag)
|
||||||
{
|
{
|
||||||
/* Append only for now, wmDragAsset could have a `link` bool. */
|
switch ((eFileAssetImportType)asset_drag->import_type) {
|
||||||
return WM_file_append_datablock(
|
case FILE_ASSET_IMPORT_LINK:
|
||||||
G_MAIN, NULL, NULL, NULL, asset_drag->path, asset_drag->id_type, asset_drag->name);
|
return WM_file_link_datablock(
|
||||||
|
G_MAIN, NULL, NULL, NULL, asset_drag->path, asset_drag->id_type, asset_drag->name);
|
||||||
|
case FILE_ASSET_IMPORT_APPEND:
|
||||||
|
return WM_file_append_datablock(
|
||||||
|
G_MAIN, NULL, NULL, NULL, asset_drag->path, asset_drag->id_type, asset_drag->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -642,23 +642,23 @@ void WM_OT_append(wmOperatorType *ot)
|
|||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Append Single Data-Block & Return it
|
/** \name Link/Append Single Data-Block & Return it
|
||||||
*
|
*
|
||||||
* Used for appending workspace from startup files.
|
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
ID *WM_file_append_datablock(Main *bmain,
|
static ID *wm_file_link_datablock_ex(Main *bmain,
|
||||||
Scene *scene,
|
Scene *scene,
|
||||||
ViewLayer *view_layer,
|
ViewLayer *view_layer,
|
||||||
View3D *v3d,
|
View3D *v3d,
|
||||||
const char *filepath,
|
const char *filepath,
|
||||||
const short id_code,
|
const short id_code,
|
||||||
const char *id_name)
|
const char *id_name,
|
||||||
|
bool clear_pre_existing_flag)
|
||||||
{
|
{
|
||||||
/* Tag everything so we can make local only the new datablock. */
|
/* Tag everything so we can make local only the new datablock. */
|
||||||
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
|
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
|
||||||
|
|
||||||
/* Define working data, with just the one item we want to append. */
|
/* Define working data, with just the one item we want to link. */
|
||||||
WMLinkAppendData *lapp_data = wm_link_append_data_new(0);
|
WMLinkAppendData *lapp_data = wm_link_append_data_new(0);
|
||||||
|
|
||||||
wm_link_append_data_library_add(lapp_data, filepath);
|
wm_link_append_data_library_add(lapp_data, filepath);
|
||||||
@@ -672,6 +672,36 @@ ID *WM_file_append_datablock(Main *bmain,
|
|||||||
ID *id = item->new_id;
|
ID *id = item->new_id;
|
||||||
wm_link_append_data_free(lapp_data);
|
wm_link_append_data_free(lapp_data);
|
||||||
|
|
||||||
|
if (clear_pre_existing_flag) {
|
||||||
|
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID *WM_file_link_datablock(Main *bmain,
|
||||||
|
Scene *scene,
|
||||||
|
ViewLayer *view_layer,
|
||||||
|
View3D *v3d,
|
||||||
|
const char *filepath,
|
||||||
|
const short id_code,
|
||||||
|
const char *id_name)
|
||||||
|
{
|
||||||
|
return wm_file_link_datablock_ex(
|
||||||
|
bmain, scene, view_layer, v3d, filepath, id_code, id_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ID *WM_file_append_datablock(Main *bmain,
|
||||||
|
Scene *scene,
|
||||||
|
ViewLayer *view_layer,
|
||||||
|
View3D *v3d,
|
||||||
|
const char *filepath,
|
||||||
|
const short id_code,
|
||||||
|
const char *id_name)
|
||||||
|
{
|
||||||
|
ID *id = wm_file_link_datablock_ex(
|
||||||
|
bmain, scene, view_layer, v3d, filepath, id_code, id_name, false);
|
||||||
|
|
||||||
/* Make datablock local. */
|
/* Make datablock local. */
|
||||||
BKE_library_make_local(bmain, NULL, NULL, true, false);
|
BKE_library_make_local(bmain, NULL, NULL, true, false);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user