1
1

Compare commits

...

13 Commits

Author SHA1 Message Date
a6896bda89 Port to new operator with instancing option from master 2022-04-07 16:08:40 +02:00
22e102efae Merge branch 'master' into temp-collection-assets 2022-04-07 15:03:42 +02:00
16ae0e7e0a Merge branch 'master' into temp-collection-assets 2022-01-18 14:42:54 +01:00
2aec6f88f0 Cleanup: Improve function names 2022-01-18 14:42:19 +01:00
2bc1dcdb1a Rename dimensions ID-property 2022-01-18 14:24:21 +01:00
4d5bb5e3de Cleanup: Avoid confusing function logic 2022-01-18 14:23:41 +01:00
143a7cf055 Cleanup: Improve comments 2022-01-18 11:58:06 +01:00
2f11352251 Merge branch 'master' into temp-collection-assets 2022-01-18 11:20:44 +01:00
3ef54e21cf Various cleanups (comments, API, naming, etc) 2022-01-11 21:29:08 +01:00
d64b07c3ae Merge branch 'master' into temp-collection-assets 2022-01-11 20:50:34 +01:00
46ae259390 Fix indirectly instanced objects being both instanced and linked
When appending a collection using instancing that contains another collection
instance, the object in the contained instance appear twice. Once from the
instanced collection (the one that was appended in the first place), and once
because they get linked to the active collection. Make sure they are not
linked.
2022-01-09 00:09:42 +01:00
fcdc3f00e1 Get bounding box snap placing on drop to work 2022-01-09 00:09:13 +01:00
d1e59b29c9 Initial bounding box based snapping for collection drag & drop 2022-01-08 15:21:37 +01:00
6 changed files with 356 additions and 49 deletions

View File

@@ -25,6 +25,7 @@ struct BlendDataReader;
struct BlendExpander;
struct BlendLibReader;
struct BlendWriter;
struct BoundBox;
struct Collection;
struct Library;
struct Main;
@@ -38,6 +39,19 @@ typedef struct CollectionParent {
struct Collection *collection;
} CollectionParent;
/**
* Options to control how object visibility flags should affect operations. Used for bounding-box
* calculations, for example.
*/
typedef enum CollectionObjectVisibility {
/** Include all objects linked to the scene, regardless of visibility flags. */
COLLECTION_VISIBILITY_ALL_OBJECTS,
/** Exclude objects hidden with the render visibility flag. */
COLLECTION_VISIBILITY_RENDER,
/** Exclude objects hidden with the viewport visibility flag. */
COLLECTION_VISIBILITY_VIEWPORT
} CollectionObjectVisibility;
/* Collections */
/**
@@ -206,6 +220,39 @@ void BKE_collection_object_cache_free(struct Collection *collection);
struct Base *BKE_collection_or_layer_objects(const struct ViewLayer *view_layer,
struct Collection *collection);
/* Dimensions. */
/**
* Calculate an axis-aligned bounding box (in global space) of all objects in this collection,
* excluding empties (but including lamps, cameras, curves, etc.). Nested collections and
* collection instances are included.
*
* \warning This is not a reliable bounding box for things like collision detection. For example,
* it doesn't consider particle instances or grease pencil stroke width.
* Take it as approximation, e.g. for visual feedback.
*
* \param object_visibility: Define the required object visibility is (e.g. decide between viewport
* vs. render visibility).
*/
void BKE_collection_boundbox_hint_calc(const struct Collection *collection,
CollectionObjectVisibility object_visibility,
struct BoundBox *r_boundbox);
/**
* Calculate axis-aligned dimensions of all objects in this collection, excluding empties (but
* including lamps, cameras, curves, etc.). Nested collections and collection instances are
* included.
*
* \warning This is not a reliable bounding box for things like collision detection. For example,
* it doesn't consider particle instances or grease pencil stroke width.
* Take it as approximation, e.g. for visual feedback.
*
* \param object_visibility: Define the required object visibility is (e.g. decide between viewport
* vs. render visibility).
*/
void BKE_collection_dimensions_hint_calc(const struct Collection *collection,
CollectionObjectVisibility object_visibility,
float r_vec[3]);
/* Editing. */
/**

View File

@@ -12,11 +12,13 @@
#include "BLI_blenlib.h"
#include "BLI_iterator.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_base.h"
#include "BLI_threads.h"
#include "BLT_translation.h"
#include "BKE_anim_data.h"
#include "BKE_asset.h"
#include "BKE_collection.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
@@ -352,6 +354,43 @@ static void collection_blend_read_expand(BlendExpander *expander, ID *id)
BKE_collection_blend_read_expand(expander, collection);
}
static IDProperty *collection_asset_dimensions_property(Collection *collection)
{
float dimensions[3];
/* Use the bounding-box for what the user sees, i.e. use viewport visibility. */
BKE_collection_dimensions_hint_calc(collection, COLLECTION_VISIBILITY_VIEWPORT, dimensions);
if (is_zero_v3(dimensions)) {
return NULL;
}
IDPropertyTemplate idprop = {0};
idprop.array.len = ARRAY_SIZE(dimensions);
idprop.array.type = IDP_FLOAT;
/* Note that since the dimensions are more of an approximation (e.g. excluding instances), this
* is really just a hint for visual feedback! */
IDProperty *property = IDP_New(IDP_ARRAY, &idprop, "dimensions_hint");
memcpy(IDP_Array(property), dimensions, sizeof(dimensions));
return property;
}
static void collection_asset_pre_save(void *asset_ptr, struct AssetMetaData *asset_data)
{
Collection *collection = (Collection *)asset_ptr;
BLI_assert(GS(collection->id.name) == ID_GR);
/* Update dimensions hint for the asset. */
IDProperty *dimensions_prop = collection_asset_dimensions_property(collection);
if (dimensions_prop) {
BKE_asset_metadata_idprop_ensure(asset_data, dimensions_prop);
}
}
AssetTypeInfo AssetType_GR = {
/* pre_save_fn */ collection_asset_pre_save,
};
IDTypeInfo IDType_ID_GR = {
.id_code = ID_GR,
.id_filter = FILTER_ID_GR,
@@ -361,7 +400,7 @@ IDTypeInfo IDType_ID_GR = {
.name_plural = "collections",
.translation_context = BLT_I18NCONTEXT_ID_COLLECTION,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
.asset_type_info = NULL,
.asset_type_info = &AssetType_GR,
.init_data = collection_init_data,
.copy_data = collection_copy_data,
@@ -839,6 +878,105 @@ Base *BKE_collection_or_layer_objects(const ViewLayer *view_layer, Collection *c
/** \} */
/* -------------------------------------------------------------------- */
/** \name Collection Dimensions
* \{ */
/**
* \param with_empties: Include the location of empties in the bounding box.
* \param instance_mat: The transform matrix of the object instancing this collection. Pass the
* unit matrix if the collection is not an instance.
*/
static void collection_minmax_calc_recursive(const Collection *parent_collection,
const CollectionObjectVisibility object_visibility,
const bool with_empties,
float parent_instance_mat[4][4],
float r_min[3],
float r_max[3])
{
LISTBASE_FOREACH (const CollectionObject *, cob, &parent_collection->gobject) {
Object *ob = cob->ob;
if (ob->instance_collection) {
float child_collection_mat[4][4];
unit_m4(child_collection_mat);
sub_v3_v3(child_collection_mat[3], ob->instance_collection->instance_offset);
mul_m4_m4m4(child_collection_mat, ob->obmat, parent_instance_mat);
collection_minmax_calc_recursive(ob->instance_collection,
object_visibility,
with_empties,
child_collection_mat,
r_min,
r_max);
}
if ((object_visibility == COLLECTION_VISIBILITY_RENDER) &&
(ob->visibility_flag & OB_HIDE_RENDER)) {
continue;
}
if ((object_visibility == COLLECTION_VISIBILITY_VIEWPORT) &&
(ob->visibility_flag & OB_HIDE_VIEWPORT)) {
continue;
}
/* Empties don't contribute to the dimensions. */
if (!with_empties && (ob->type == OB_EMPTY)) {
continue;
}
BoundBox *bb_object = BKE_object_boundbox_get(ob);
if (bb_object) {
float obmat[4][4];
mul_m4_m4m4(obmat, ob->obmat, parent_instance_mat);
BKE_boundbox_minmax(bb_object, obmat, r_min, r_max);
}
else {
minmax_v3v3_v3(r_min, r_max, ob->obmat[3]);
}
}
LISTBASE_FOREACH (CollectionChild *, child, &parent_collection->children) {
collection_minmax_calc_recursive(
child->collection, object_visibility, with_empties, parent_instance_mat, r_min, r_max);
}
}
static void collection_minmax(const Collection *collection,
const CollectionObjectVisibility object_visibility,
float r_min[3],
float r_max[3])
{
INIT_MINMAX(r_min, r_max);
/* The matrix of the */
float instance_collection_mat[4][4];
unit_m4(instance_collection_mat);
collection_minmax_calc_recursive(
collection, object_visibility, false, instance_collection_mat, r_min, r_max);
}
void BKE_collection_boundbox_hint_calc(const Collection *collection,
const CollectionObjectVisibility object_visibility,
BoundBox *r_boundbox)
{
float min[3], max[3];
collection_minmax(collection, object_visibility, min, max);
BKE_boundbox_init_from_minmax(r_boundbox, min, max);
}
void BKE_collection_dimensions_hint_calc(const Collection *collection,
const CollectionObjectVisibility object_visibility,
float r_vec[3])
{
float min[3], max[3];
collection_minmax(collection, object_visibility, min, max);
sub_v3_v3v3(r_vec, max, min);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Scene Master Collection
* \{ */

View File

@@ -3888,7 +3888,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op)
void OBJECT_OT_transform_to_mouse(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Place Object Under Mouse";
ot->name = "Place Object or Collection Under Mouse";
ot->description = "Snap selected item(s) to the mouse location";
ot->idname = "OBJECT_OT_transform_to_mouse";

View File

@@ -490,7 +490,9 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C,
return WM_drag_is_ID_type(drag, id_type);
}
static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
static void view3d_boundbox_drop_draw_activate(struct wmDropBox *drop,
wmDrag *drag,
const float dimensions[3])
{
V3DSnapCursorState *state = drop->draw_data;
if (state) {
@@ -503,22 +505,14 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
return;
}
const int drag_id_type = WM_drag_get_ID_type(drag);
if (!ELEM(drag_id_type, ID_OB, ID_GR)) {
return;
}
state = drop->draw_data = ED_view3d_cursor_snap_active();
state->draw_plane = true;
float dimensions[3] = {0.0f};
if (drag->type == WM_DRAG_ID) {
Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB);
BKE_object_dimensions_get(ob, dimensions);
}
else {
struct AssetMetaData *meta_data = WM_drag_get_asset_meta_data(drag, ID_OB);
IDProperty *dimensions_prop = BKE_asset_metadata_idprop_find(meta_data, "dimensions");
if (dimensions_prop) {
copy_v3_v3(dimensions, IDP_Array(dimensions_prop));
}
}
if (!is_zero_v3(dimensions)) {
mul_v3_v3fl(state->box_dimensions, dimensions, 0.5f);
UI_GetThemeColor4ubv(TH_GIZMO_PRIMARY, state->color_box);
@@ -526,7 +520,51 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
}
}
static void view3d_ob_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
static void view3d_boundbox_drop_draw_activate_object(struct wmDropBox *drop, wmDrag *drag)
{
const int drag_id_type = WM_drag_get_ID_type(drag);
BLI_assert(drag_id_type == ID_OB);
float dimensions[3] = {0.0f};
if (drag->type == WM_DRAG_ID) {
Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB);
BKE_object_dimensions_get(ob, dimensions);
}
else {
struct AssetMetaData *meta_data = WM_drag_get_asset_meta_data(drag, drag_id_type);
IDProperty *dimensions_prop = BKE_asset_metadata_idprop_find(meta_data, "dimensions");
if (dimensions_prop) {
copy_v3_v3(dimensions, IDP_Array(dimensions_prop));
}
}
view3d_boundbox_drop_draw_activate(drop, drag, dimensions);
}
static void view3d_boundbox_drop_draw_activate_collection(struct wmDropBox *drop, wmDrag *drag)
{
const int drag_id_type = WM_drag_get_ID_type(drag);
BLI_assert(drag_id_type == ID_GR);
float dimensions[3] = {0.0f};
if (drag->type == WM_DRAG_ID) {
Collection *collection = (Collection *)WM_drag_get_local_ID(drag, ID_GR);
BKE_collection_dimensions_hint_calc(collection, COLLECTION_VISIBILITY_VIEWPORT, dimensions);
}
else {
struct AssetMetaData *meta_data = WM_drag_get_asset_meta_data(drag, drag_id_type);
IDProperty *dimensions_prop = BKE_asset_metadata_idprop_find(meta_data, "dimensions_hint");
if (dimensions_prop) {
copy_v3_v3(dimensions, IDP_Array(dimensions_prop));
}
}
view3d_boundbox_drop_draw_activate(drop, drag, dimensions);
}
static void view3d_boundbox_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
{
V3DSnapCursorState *state = drop->draw_data;
if (state) {
@@ -564,6 +602,10 @@ static bool view3d_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent
return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR);
}
/**
* \note the term local here refers to not being an external asset,
* poll will succeed for linked library objects.
*/
static bool view3d_collection_drop_poll_local_id(bContext *C, wmDrag *drag, const wmEvent *event)
{
if (!view3d_collection_drop_poll(C, drag, event) || (drag->type != WM_DRAG_ID)) {
@@ -688,30 +730,37 @@ static bool view3d_volume_drop_poll(bContext *UNUSED(C),
return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME);
}
static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
Object *ob,
float obmat_final[4][4])
static void view3d_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
const BoundBox *bb,
const float base_mat[4][4],
float r_mat_final[4][4])
{
V3DSnapCursorData *snap_data;
snap_data = ED_view3d_cursor_snap_data_get(snap_state, NULL, 0, 0);
BLI_assert(snap_state->draw_box || snap_state->draw_plane);
copy_m4_m3(obmat_final, snap_data->plane_omat);
copy_v3_v3(obmat_final[3], snap_data->loc);
copy_m4_m3(r_mat_final, snap_data->plane_omat);
copy_v3_v3(r_mat_final[3], snap_data->loc);
float scale[3];
mat4_to_size(scale, ob->obmat);
rescale_m4(obmat_final, scale);
mat4_to_size(scale, base_mat);
rescale_m4(r_mat_final, scale);
const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
float offset[3];
BKE_boundbox_calc_center_aabb(bb, offset);
offset[2] = bb->vec[0][2];
mul_mat3_m4_v3(obmat_final, offset);
sub_v3_v3(obmat_final[3], offset);
mul_mat3_m4_v3(r_mat_final, offset);
sub_v3_v3(r_mat_final[3], offset);
}
}
static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
Object *ob,
float r_obmat_final[4][4])
{
view3d_drop_matrix_from_snap(snap_state, BKE_object_boundbox_get(ob), ob->obmat, r_obmat_final);
}
static void view3d_ob_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID(drag, ID_OB);
@@ -771,10 +820,18 @@ static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
}
}
static void view3d_collection_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
static void view3d_collection_drop_matrix_get(const Collection *collection,
float r_mat_final[4][4])
{
ID *id = WM_drag_get_local_ID(drag, ID_GR);
RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
const float unit_mat[4][4];
unit_m4((float(*)[])unit_mat);
BoundBox boundbox;
/* Use the bounding-box for what the user will see, i.e. use viewport visibility. */
const CollectionObjectVisibility visibility = COLLECTION_VISIBILITY_VIEWPORT;
BKE_collection_boundbox_hint_calc(collection, visibility, &boundbox);
view3d_drop_matrix_from_snap(snap_state, &boundbox, unit_mat, r_mat_final);
}
/* Mostly the same logic as #view3d_ob_drop_copy_external_asset(), just different enough to make
@@ -810,11 +867,39 @@ static void view3d_collection_drop_copy_external_asset(wmDrag *drag, wmDropBox *
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
ED_outliner_select_sync_from_object_tag(C);
float mat[4][4];
view3d_collection_drop_matrix_get(collection, mat);
float loc[3], rot_quat[4], rot_eul[3], scale[3];
mat4_decompose(loc, rot_quat, scale, mat);
add_v3_v3(loc, collection->instance_offset);
quat_to_eul(rot_eul, rot_quat);
RNA_float_set_array(drop->ptr, "location", loc);
RNA_float_set_array(drop->ptr, "rotation", rot_eul);
RNA_float_set_array(drop->ptr, "scale", scale);
/* XXX Without an undo push here, there will be a crash when the user modifies operator
* properties. The stuff we do in these drop callbacks just isn't safe over undo/redo. */
ED_undo_push(C, "Collection_Drop");
}
static void view3d_collection_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR);
float mat[4][4];
view3d_collection_drop_matrix_get((Collection *)id, mat);
float loc[3], rot_quat[4], rot_eul[3], scale[3];
mat4_decompose(loc, rot_quat, scale, mat);
quat_to_eul(rot_eul, rot_quat);
RNA_float_set_array(drop->ptr, "location", loc);
RNA_float_set_array(drop->ptr, "rotation", rot_eul);
RNA_float_set_array(drop->ptr, "scale", scale);
RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
}
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
@@ -871,40 +956,48 @@ static void view3d_dropboxes(void)
ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
struct wmDropBox *drop;
/* Local object. */
drop = WM_dropbox_add(lb,
"OBJECT_OT_add_named",
view3d_ob_drop_poll_local_id,
view3d_ob_drop_copy_local_id,
WM_drag_free_imported_drag_ID,
NULL);
drop->draw = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_ob_drop_draw_activate;
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
drop->draw_activate = view3d_boundbox_drop_draw_activate_object;
drop->draw_deactivate = view3d_boundbox_drop_draw_deactivate;
/* Object asset from external file. */
drop = WM_dropbox_add(lb,
"OBJECT_OT_transform_to_mouse",
view3d_ob_drop_poll_external_asset,
view3d_ob_drop_copy_external_asset,
WM_drag_free_imported_drag_ID,
NULL);
drop->draw = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_ob_drop_draw_activate;
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
drop->draw_activate = view3d_boundbox_drop_draw_activate_object;
drop->draw_deactivate = view3d_boundbox_drop_draw_deactivate;
WM_dropbox_add(lb,
"OBJECT_OT_collection_external_asset_drop",
view3d_collection_drop_poll_external_asset,
view3d_collection_drop_copy_external_asset,
WM_drag_free_imported_drag_ID,
NULL);
WM_dropbox_add(lb,
"OBJECT_OT_collection_instance_add",
view3d_collection_drop_poll_local_id,
view3d_collection_drop_copy_local_id,
WM_drag_free_imported_drag_ID,
NULL);
/* Local collection (adds collection instance). */
drop = WM_dropbox_add(lb,
"OBJECT_OT_collection_instance_add",
view3d_collection_drop_poll_local_id,
view3d_collection_drop_copy_local_id,
WM_drag_free_imported_drag_ID,
NULL);
drop->draw = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_boundbox_drop_draw_activate_collection;
drop->draw_deactivate = view3d_boundbox_drop_draw_deactivate;
drop = WM_dropbox_add(lb,
"OBJECT_OT_collection_external_asset_drop",
view3d_collection_drop_poll_external_asset,
view3d_collection_drop_copy_external_asset,
WM_drag_free_imported_drag_ID,
NULL);
drop->draw = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_boundbox_drop_draw_activate_collection;
drop->draw_deactivate = view3d_boundbox_drop_draw_deactivate;
WM_dropbox_add(lb,
"OBJECT_OT_drop_named_material",

View File

@@ -1182,6 +1182,9 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
/* ID drag and drop */
ID *WM_drag_asset_id_import_ex(wmDragAsset *asset_drag,
const int flag_extra,
const bool collection_instance);
/**
* \param flag_extra: Additional linking flags (from #eFileSel_Params_Flag).
*/
@@ -1194,6 +1197,7 @@ struct ID *WM_drag_get_local_ID_from_event(const struct wmEvent *event, short id
* Check if the drag data is either a local ID or an external ID asset of type \a idcode.
*/
bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode);
int WM_drag_get_ID_type(const struct wmDrag *drag);
/**
* \note: Does not store \a asset in any way, so it's fine to pass a temporary.

View File

@@ -507,6 +507,21 @@ bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
}
int WM_drag_get_ID_type(const wmDrag *drag)
{
const ID *local_id = WM_drag_get_local_ID(drag, 0);
if (local_id) {
return GS(local_id->name);
}
const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
if (asset_drag) {
return asset_drag->id_type;
}
return 0;
}
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset,
AssetMetaData *metadata,
const char *path,
@@ -554,11 +569,16 @@ struct AssetMetaData *WM_drag_get_asset_meta_data(const wmDrag *drag, int idcode
return NULL;
}
ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
ID *WM_drag_asset_id_import_ex(wmDragAsset *asset_drag,
const int flag_extra,
const bool collection_instance)
{
/* Only support passing in limited flags. */
BLI_assert(flag_extra == (flag_extra & FILE_AUTOSELECT));
eFileSel_Params_Flag flag = flag_extra | FILE_ACTIVE_COLLECTION;
if (collection_instance) {
flag |= BLO_LIBLINK_COLLECTION_INSTANCE;
}
const char *name = asset_drag->name;
ID_Type idtype = asset_drag->id_type;
@@ -602,6 +622,11 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
return NULL;
}
ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
{
return WM_drag_asset_id_import_ex(asset_drag, flag_extra, false);
}
bool WM_drag_asset_will_import_linked(const wmDrag *drag)
{
if (drag->type != WM_DRAG_ASSET) {