forked from blender/blender
main sync #3
@ -21,6 +21,8 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
|
|||||||
ATTR_WARN_UNUSED_RESULT;
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
|
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
|
||||||
ATTR_WARN_UNUSED_RESULT;
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
|
struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset)
|
||||||
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT;
|
bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT;
|
||||||
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
|
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
|
||||||
ATTR_WARN_UNUSED_RESULT;
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
|
@ -82,6 +82,9 @@ class AssetRepresentation {
|
|||||||
* #get_import_method(). Also returns true if there is no predefined import method
|
* #get_import_method(). Also returns true if there is no predefined import method
|
||||||
* (when #get_import_method() returns no value). */
|
* (when #get_import_method() returns no value). */
|
||||||
bool may_override_import_method() const;
|
bool may_override_import_method() const;
|
||||||
|
/** If this asset is stored inside this current file (#is_local_id() is true), this returns the
|
||||||
|
* ID's pointer, otherwise null. */
|
||||||
|
ID *local_id() const;
|
||||||
/** Returns if this asset is stored inside this current file, and as such fully editable. */
|
/** Returns if this asset is stored inside this current file, and as such fully editable. */
|
||||||
bool is_local_id() const;
|
bool is_local_id() const;
|
||||||
const AssetLibrary &owner_asset_library() const;
|
const AssetLibrary &owner_asset_library() const;
|
||||||
|
@ -97,6 +97,11 @@ bool AssetRepresentation::may_override_import_method() const
|
|||||||
return owner_asset_library_->may_override_import_method_;
|
return owner_asset_library_->may_override_import_method_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID *AssetRepresentation::local_id() const
|
||||||
|
{
|
||||||
|
return is_local_id_ ? local_asset_id_ : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool AssetRepresentation::is_local_id() const
|
bool AssetRepresentation::is_local_id() const
|
||||||
{
|
{
|
||||||
return is_local_id_;
|
return is_local_id_;
|
||||||
@ -159,6 +164,13 @@ AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *a
|
|||||||
return &asset->get_metadata();
|
return &asset->get_metadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset_handle)
|
||||||
|
{
|
||||||
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
|
||||||
|
return asset->local_id();
|
||||||
|
}
|
||||||
|
|
||||||
bool AS_asset_representation_is_local_id(const AssetRepresentation *asset_handle)
|
bool AS_asset_representation_is_local_id(const AssetRepresentation *asset_handle)
|
||||||
{
|
{
|
||||||
const asset_system::AssetRepresentation *asset =
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
@ -381,6 +381,8 @@ bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
|
|||||||
const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
|
const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
|
||||||
struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid);
|
struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid);
|
||||||
|
|
||||||
|
struct AssetRepresentation *CTX_wm_asset(const bContext *C);
|
||||||
|
|
||||||
bool CTX_wm_interface_locked(const bContext *C);
|
bool CTX_wm_interface_locked(const bContext *C);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1493,6 +1493,11 @@ AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
|
|||||||
return AssetHandle{nullptr};
|
return AssetHandle{nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetRepresentation *CTX_wm_asset(const bContext *C)
|
||||||
|
{
|
||||||
|
return static_cast<AssetRepresentation *>(ctx_data_pointer_get(C, "asset"));
|
||||||
|
}
|
||||||
|
|
||||||
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)
|
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)
|
||||||
{
|
{
|
||||||
Main *bmain = CTX_data_main(C);
|
Main *bmain = CTX_data_main(C);
|
||||||
|
@ -24,6 +24,7 @@ set(SRC
|
|||||||
intern/asset_catalog.cc
|
intern/asset_catalog.cc
|
||||||
intern/asset_filter.cc
|
intern/asset_filter.cc
|
||||||
intern/asset_handle.cc
|
intern/asset_handle.cc
|
||||||
|
intern/asset_import.cc
|
||||||
intern/asset_indexer.cc
|
intern/asset_indexer.cc
|
||||||
intern/asset_library_reference.cc
|
intern/asset_library_reference.cc
|
||||||
intern/asset_library_reference_enum.cc
|
intern/asset_library_reference_enum.cc
|
||||||
@ -37,6 +38,7 @@ set(SRC
|
|||||||
ED_asset_catalog.hh
|
ED_asset_catalog.hh
|
||||||
ED_asset_filter.h
|
ED_asset_filter.h
|
||||||
ED_asset_handle.h
|
ED_asset_handle.h
|
||||||
|
ED_asset_import.h
|
||||||
ED_asset_indexer.h
|
ED_asset_indexer.h
|
||||||
ED_asset_library.h
|
ED_asset_library.h
|
||||||
ED_asset_list.h
|
ED_asset_list.h
|
||||||
|
@ -21,6 +21,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct AssetHandle;
|
struct AssetHandle;
|
||||||
|
|
||||||
|
struct AssetRepresentation *ED_asset_handle_get_representation(const struct AssetHandle *asset);
|
||||||
const char *ED_asset_handle_get_name(const struct AssetHandle *asset);
|
const char *ED_asset_handle_get_name(const struct AssetHandle *asset);
|
||||||
struct AssetMetaData *ED_asset_handle_get_metadata(const struct AssetHandle *asset);
|
struct AssetMetaData *ED_asset_handle_get_metadata(const struct AssetHandle *asset);
|
||||||
struct ID *ED_asset_handle_get_local_id(const struct AssetHandle *asset);
|
struct ID *ED_asset_handle_get_local_id(const struct AssetHandle *asset);
|
||||||
@ -45,11 +46,4 @@ void ED_asset_handle_get_full_library_path(
|
|||||||
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
|
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
|
||||||
const struct AssetHandle *asset);
|
const struct AssetHandle *asset);
|
||||||
|
|
||||||
namespace blender::ed::asset {
|
|
||||||
|
|
||||||
/** If the ID already exists in the database, return it, otherwise add it. */
|
|
||||||
ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, AssetHandle asset);
|
|
||||||
|
|
||||||
} // namespace blender::ed::asset
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
23
source/blender/editors/asset/ED_asset_import.h
Normal file
23
source/blender/editors/asset/ED_asset_import.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup edasset
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DNA_ID_enums.h"
|
||||||
|
|
||||||
|
struct AssetRepresentation;
|
||||||
|
struct Main;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(
|
||||||
|
struct Main *bmain, const struct AssetRepresentation *asset_c_ptr, ID_Type idtype);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "DNA_asset_types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct AssetHandle;
|
|
||||||
struct AssetLibraryReference;
|
struct AssetLibraryReference;
|
||||||
struct ID;
|
struct ID;
|
||||||
struct bContext;
|
struct bContext;
|
||||||
@ -49,6 +50,9 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
|
|||||||
*/
|
*/
|
||||||
void ED_assetlist_storage_exit(void);
|
void ED_assetlist_storage_exit(void);
|
||||||
|
|
||||||
|
AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference,
|
||||||
|
int asset_index);
|
||||||
|
|
||||||
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,4 +30,8 @@ blender::asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
|
|||||||
|
|
||||||
/* Can return false to stop iterating. */
|
/* Can return false to stop iterating. */
|
||||||
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
||||||
|
/**
|
||||||
|
* \warning Never keep the asset handle passed to \a fn outside of \a fn's scope. While iterating,
|
||||||
|
* the file data wrapped by the asset handle can be freed, since the file cache has a maximum size.
|
||||||
|
*/
|
||||||
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
|
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
|
||||||
|
@ -11,13 +11,18 @@
|
|||||||
|
|
||||||
#include "BKE_blendfile.h"
|
#include "BKE_blendfile.h"
|
||||||
|
|
||||||
#include "BLO_readfile.h"
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
#include "ED_asset_handle.h"
|
#include "ED_asset_handle.h"
|
||||||
|
|
||||||
#include "WM_api.h"
|
AssetRepresentation *ED_asset_handle_get_representation(const AssetHandle *asset)
|
||||||
|
{
|
||||||
|
return asset->file_data->asset;
|
||||||
|
}
|
||||||
|
|
||||||
const char *ED_asset_handle_get_name(const AssetHandle *asset)
|
const char *ED_asset_handle_get_name(const AssetHandle *asset)
|
||||||
{
|
{
|
||||||
@ -55,36 +60,11 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
|||||||
{
|
{
|
||||||
*r_full_lib_path = '\0';
|
*r_full_lib_path = '\0';
|
||||||
|
|
||||||
std::string asset_path = AS_asset_representation_full_path_get(asset_handle->file_data->asset);
|
std::string library_path = AS_asset_representation_full_library_path_get(
|
||||||
if (asset_path.empty()) {
|
asset_handle->file_data->asset);
|
||||||
|
if (library_path.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BKE_library_path_explode(asset_path.c_str(), r_full_lib_path, nullptr, nullptr);
|
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace blender::ed::asset {
|
|
||||||
|
|
||||||
ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, const AssetHandle asset)
|
|
||||||
{
|
|
||||||
if (ID *local_id = ED_asset_handle_get_local_id(&asset)) {
|
|
||||||
return local_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
char blend_path[FILE_MAX_LIBEXTRA];
|
|
||||||
ED_asset_handle_get_full_library_path(&asset, blend_path);
|
|
||||||
const char *id_name = ED_asset_handle_get_name(&asset);
|
|
||||||
|
|
||||||
return WM_file_append_datablock(&bmain,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
blend_path,
|
|
||||||
ED_asset_handle_get_id_type(&asset),
|
|
||||||
id_name,
|
|
||||||
BLO_LIBLINK_APPEND_RECURSIVE |
|
|
||||||
BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR |
|
|
||||||
BLO_LIBLINK_APPEND_LOCAL_ID_REUSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::ed::asset
|
|
||||||
|
44
source/blender/editors/asset/intern/asset_import.cc
Normal file
44
source/blender/editors/asset/intern/asset_import.cc
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup edasset
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AS_asset_representation.h"
|
||||||
|
#include "AS_asset_representation.hh"
|
||||||
|
|
||||||
|
#include "BLO_readfile.h"
|
||||||
|
|
||||||
|
#include "WM_api.h"
|
||||||
|
|
||||||
|
#include "ED_asset_import.h"
|
||||||
|
|
||||||
|
using namespace blender;
|
||||||
|
|
||||||
|
ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(Main *bmain,
|
||||||
|
const AssetRepresentation *asset_c_ptr,
|
||||||
|
ID_Type idtype)
|
||||||
|
{
|
||||||
|
const asset_system::AssetRepresentation &asset =
|
||||||
|
*reinterpret_cast<const asset_system::AssetRepresentation *>(asset_c_ptr);
|
||||||
|
|
||||||
|
if (ID *local_id = asset.local_id()) {
|
||||||
|
return local_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string blend_path = asset.get_identifier().full_library_path();
|
||||||
|
if (blend_path.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WM_file_append_datablock(bmain,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
blend_path.c_str(),
|
||||||
|
idtype,
|
||||||
|
asset.get_name().c_str(),
|
||||||
|
BLO_LIBLINK_APPEND_RECURSIVE |
|
||||||
|
BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR |
|
||||||
|
BLO_LIBLINK_APPEND_LOCAL_ID_REUSE);
|
||||||
|
}
|
@ -112,6 +112,8 @@ class AssetList : NonCopyable {
|
|||||||
void ensurePreviewsJob(const bContext *C);
|
void ensurePreviewsJob(const bContext *C);
|
||||||
void clear(bContext *C);
|
void clear(bContext *C);
|
||||||
|
|
||||||
|
AssetHandle asset_get_by_index(int index) const;
|
||||||
|
|
||||||
bool needsRefetch() const;
|
bool needsRefetch() const;
|
||||||
bool isLoaded() const;
|
bool isLoaded() const;
|
||||||
asset_system::AssetLibrary *asset_library() const;
|
asset_system::AssetLibrary *asset_library() const;
|
||||||
@ -139,7 +141,7 @@ void AssetList::setup()
|
|||||||
filelist_setlibrary(files, &library_ref_);
|
filelist_setlibrary(files, &library_ref_);
|
||||||
filelist_setfilter_options(
|
filelist_setfilter_options(
|
||||||
files,
|
files,
|
||||||
false,
|
true,
|
||||||
true,
|
true,
|
||||||
true, /* Just always hide parent, prefer to not add an extra user option for this. */
|
true, /* Just always hide parent, prefer to not add an extra user option for this. */
|
||||||
FILE_TYPE_BLENDERLIB,
|
FILE_TYPE_BLENDERLIB,
|
||||||
@ -246,6 +248,11 @@ void AssetList::clear(bContext *C)
|
|||||||
WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr);
|
WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetHandle AssetList::asset_get_by_index(int index) const
|
||||||
|
{
|
||||||
|
return {filelist_file(filelist_, index)};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return True if the asset-list needs a UI redraw.
|
* \return True if the asset-list needs a UI redraw.
|
||||||
*/
|
*/
|
||||||
@ -472,6 +479,13 @@ asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
|
|||||||
return list->asset_library();
|
return list->asset_library();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference,
|
||||||
|
int asset_index)
|
||||||
|
{
|
||||||
|
const AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||||
|
return list->asset_get_by_index(asset_index);
|
||||||
|
}
|
||||||
|
|
||||||
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||||
{
|
{
|
||||||
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
||||||
|
@ -8,9 +8,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AS_asset_representation.h"
|
||||||
|
#include "AS_asset_representation.hh"
|
||||||
|
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
|
#include "ED_asset.h"
|
||||||
|
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
|
|
||||||
#include "BLI_utility_mixins.hh"
|
#include "BLI_utility_mixins.hh"
|
||||||
@ -19,17 +25,16 @@
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "ED_asset_handle.h"
|
|
||||||
#include "ED_asset_temp_id_consumer.h"
|
#include "ED_asset_temp_id_consumer.h"
|
||||||
|
|
||||||
using namespace blender;
|
using namespace blender;
|
||||||
|
|
||||||
class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
|
class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
|
||||||
const AssetHandle &handle_;
|
const AssetRepresentation *asset_;
|
||||||
TempLibraryContext *temp_lib_context_ = nullptr;
|
TempLibraryContext *temp_lib_context_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AssetTemporaryIDConsumer(const AssetHandle &handle) : handle_(handle)
|
AssetTemporaryIDConsumer(const AssetRepresentation *asset) : asset_(asset)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~AssetTemporaryIDConsumer()
|
~AssetTemporaryIDConsumer()
|
||||||
@ -41,20 +46,20 @@ class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
|
|||||||
|
|
||||||
ID *get_local_id()
|
ID *get_local_id()
|
||||||
{
|
{
|
||||||
return ED_asset_handle_get_local_id(&handle_);
|
return AS_asset_representation_local_id_get(asset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ID *import_id(ID_Type id_type, Main &bmain, ReportList &reports)
|
ID *import_id(ID_Type id_type, Main &bmain, ReportList &reports)
|
||||||
{
|
{
|
||||||
const char *asset_name = ED_asset_handle_get_name(&handle_);
|
const char *asset_name = AS_asset_representation_name_get(asset_);
|
||||||
char blend_file_path[FILE_MAX_LIBEXTRA];
|
std::string blend_file_path = AS_asset_representation_full_library_path_get(asset_);
|
||||||
ED_asset_handle_get_full_library_path(&handle_, blend_file_path);
|
|
||||||
|
|
||||||
temp_lib_context_ = BLO_library_temp_load_id(
|
temp_lib_context_ = BLO_library_temp_load_id(
|
||||||
&bmain, blend_file_path, id_type, asset_name, &reports);
|
&bmain, blend_file_path.c_str(), id_type, asset_name, &reports);
|
||||||
|
|
||||||
if (temp_lib_context_ == nullptr || temp_lib_context_->temp_id == nullptr) {
|
if (temp_lib_context_ == nullptr || temp_lib_context_->temp_id == nullptr) {
|
||||||
BKE_reportf(&reports, RPT_ERROR, "Unable to load %s from %s", asset_name, blend_file_path);
|
BKE_reportf(
|
||||||
|
&reports, RPT_ERROR, "Unable to load %s from %s", asset_name, blend_file_path.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +75,7 @@ AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle)
|
|||||||
}
|
}
|
||||||
BLI_assert(handle->file_data->asset != nullptr);
|
BLI_assert(handle->file_data->asset != nullptr);
|
||||||
return reinterpret_cast<AssetTempIDConsumer *>(
|
return reinterpret_cast<AssetTempIDConsumer *>(
|
||||||
MEM_new<AssetTemporaryIDConsumer>(__func__, *handle));
|
MEM_new<AssetTemporaryIDConsumer>(__func__, ED_asset_handle_get_representation(handle)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer)
|
void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer)
|
||||||
|
@ -25,6 +25,7 @@ void ED_operatortypes_asset(void);
|
|||||||
#include "../asset/ED_asset_catalog.h"
|
#include "../asset/ED_asset_catalog.h"
|
||||||
#include "../asset/ED_asset_filter.h"
|
#include "../asset/ED_asset_filter.h"
|
||||||
#include "../asset/ED_asset_handle.h"
|
#include "../asset/ED_asset_handle.h"
|
||||||
|
#include "../asset/ED_asset_import.h"
|
||||||
#include "../asset/ED_asset_library.h"
|
#include "../asset/ED_asset_library.h"
|
||||||
#include "../asset/ED_asset_list.h"
|
#include "../asset/ED_asset_list.h"
|
||||||
#include "../asset/ED_asset_mark_clear.h"
|
#include "../asset/ED_asset_mark_clear.h"
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "BLI_function_ref.hh"
|
||||||
#include "BLI_string_ref.hh"
|
#include "BLI_string_ref.hh"
|
||||||
#include "BLI_vector.hh"
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
@ -17,8 +18,10 @@ namespace blender::nodes::geo_eval_log {
|
|||||||
struct GeometryAttributeInfo;
|
struct GeometryAttributeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PointerRNA;
|
||||||
struct StructRNA;
|
struct StructRNA;
|
||||||
struct uiBlock;
|
struct uiBlock;
|
||||||
|
struct uiList;
|
||||||
struct uiSearchItems;
|
struct uiSearchItems;
|
||||||
|
|
||||||
namespace blender::ui {
|
namespace blender::ui {
|
||||||
@ -53,6 +56,60 @@ void attribute_search_add_items(StringRefNull str,
|
|||||||
|
|
||||||
} // namespace blender::ui
|
} // namespace blender::ui
|
||||||
|
|
||||||
|
enum eUIListFilterResult {
|
||||||
|
/** Never show this item, even when filter results are inverted (#UILST_FLT_EXCLUDE). */
|
||||||
|
UI_LIST_ITEM_NEVER_SHOW,
|
||||||
|
/** Show this item, unless filter results are inverted (#UILST_FLT_EXCLUDE). */
|
||||||
|
UI_LIST_ITEM_FILTER_MATCHES,
|
||||||
|
/** Don't show this item, unless filter results are inverted (#UILST_FLT_EXCLUDE). */
|
||||||
|
UI_LIST_ITEM_FILTER_MISMATCHES,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function object for UI list item filtering that does the default name comparison with '*'
|
||||||
|
* wildcards. Create an instance of this once and pass it to #UI_list_filter_and_sort_items(), do
|
||||||
|
* NOT create an instance for every item, this would be costly.
|
||||||
|
*/
|
||||||
|
class uiListNameFilter {
|
||||||
|
/* Storage with an inline buffer for smaller strings (small buffer optimization). */
|
||||||
|
struct {
|
||||||
|
char filter_buff[32];
|
||||||
|
char *filter_dyn = nullptr;
|
||||||
|
} storage_;
|
||||||
|
char *filter_ = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uiListNameFilter(uiList &list);
|
||||||
|
~uiListNameFilter();
|
||||||
|
|
||||||
|
eUIListFilterResult operator()(const PointerRNA &itemptr,
|
||||||
|
blender::StringRefNull name,
|
||||||
|
int index);
|
||||||
|
};
|
||||||
|
|
||||||
|
using uiListItemFilterFn = blender::FunctionRef<eUIListFilterResult(
|
||||||
|
const PointerRNA &itemptr, blender::StringRefNull name, int index)>;
|
||||||
|
using uiListItemGetNameFn =
|
||||||
|
blender::FunctionRef<std::string(const PointerRNA &itemptr, int index)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter list items using \a item_filter_fn and sort the result. This respects the normal UI list
|
||||||
|
* filter settings like alphabetical sorting (#UILST_FLT_SORT_ALPHA), and result inverting
|
||||||
|
* (#UILST_FLT_EXCLUDE).
|
||||||
|
*
|
||||||
|
* Call this from a #uiListType::filter_items callback with any #item_filter_fn. #uiListNameFilter
|
||||||
|
* can be used to apply the default name based filtering.
|
||||||
|
*
|
||||||
|
* \param get_name_fn: In some cases the name cannot be retrieved via RNA. This function can be set
|
||||||
|
* to provide the name still.
|
||||||
|
*/
|
||||||
|
void UI_list_filter_and_sort_items(uiList *ui_list,
|
||||||
|
const struct bContext *C,
|
||||||
|
uiListItemFilterFn item_filter_fn,
|
||||||
|
PointerRNA *dataptr,
|
||||||
|
const char *propname,
|
||||||
|
uiListItemGetNameFn get_name_fn = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this for all available view types.
|
* Override this for all available view types.
|
||||||
*/
|
*/
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "RNA_prototypes.h"
|
#include "RNA_prototypes.h"
|
||||||
|
|
||||||
#include "UI_interface.h"
|
#include "UI_interface.h"
|
||||||
|
#include "UI_interface.hh"
|
||||||
|
|
||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
#include "WM_types.h"
|
#include "WM_types.h"
|
||||||
@ -32,6 +33,7 @@
|
|||||||
|
|
||||||
struct AssetViewListData {
|
struct AssetViewListData {
|
||||||
AssetLibraryReference asset_library_ref;
|
AssetLibraryReference asset_library_ref;
|
||||||
|
AssetFilterSettings filter_settings;
|
||||||
bScreen *screen;
|
bScreen *screen;
|
||||||
bool show_names;
|
bool show_names;
|
||||||
};
|
};
|
||||||
@ -45,8 +47,6 @@ static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char blend_path[FILE_MAX_LIBEXTRA];
|
char blend_path[FILE_MAX_LIBEXTRA];
|
||||||
/* Context can be null here, it's only needed for a File Browser specific hack that should go
|
|
||||||
* away before too long. */
|
|
||||||
ED_asset_handle_get_full_library_path(asset_handle, blend_path);
|
ED_asset_handle_get_full_library_path(asset_handle, blend_path);
|
||||||
|
|
||||||
const eAssetImportMethod import_method =
|
const eAssetImportMethod import_method =
|
||||||
@ -68,19 +68,23 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||||||
const bContext * /*C*/,
|
const bContext * /*C*/,
|
||||||
uiLayout *layout,
|
uiLayout *layout,
|
||||||
PointerRNA * /*dataptr*/,
|
PointerRNA * /*dataptr*/,
|
||||||
PointerRNA *itemptr,
|
PointerRNA * /*itemptr*/,
|
||||||
int /*icon*/,
|
int /*icon*/,
|
||||||
PointerRNA * /*active_dataptr*/,
|
PointerRNA * /*active_dataptr*/,
|
||||||
const char * /*active_propname*/,
|
const char * /*active_propname*/,
|
||||||
int /*index*/,
|
int index,
|
||||||
int /*flt_flag*/)
|
int /*flt_flag*/)
|
||||||
{
|
{
|
||||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||||
|
|
||||||
BLI_assert(RNA_struct_is_a(itemptr->type, &RNA_AssetHandle));
|
AssetHandle asset_handle = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
|
||||||
AssetHandle *asset_handle = (AssetHandle *)itemptr->data;
|
|
||||||
|
|
||||||
uiLayoutSetContextPointer(layout, "asset_handle", itemptr);
|
PointerRNA file_ptr;
|
||||||
|
RNA_pointer_create(&list_data->screen->id,
|
||||||
|
&RNA_FileSelectEntry,
|
||||||
|
const_cast<FileDirEntry *>(asset_handle.file_data),
|
||||||
|
&file_ptr);
|
||||||
|
uiLayoutSetContextPointer(layout, "active_file", &file_ptr);
|
||||||
|
|
||||||
uiBlock *block = uiLayoutGetBlock(layout);
|
uiBlock *block = uiLayoutGetBlock(layout);
|
||||||
const bool show_names = list_data->show_names;
|
const bool show_names = list_data->show_names;
|
||||||
@ -90,8 +94,8 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||||||
uiBut *but = uiDefIconTextBut(block,
|
uiBut *but = uiDefIconTextBut(block,
|
||||||
UI_BTYPE_PREVIEW_TILE,
|
UI_BTYPE_PREVIEW_TILE,
|
||||||
0,
|
0,
|
||||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
ED_asset_handle_get_preview_icon_id(&asset_handle),
|
||||||
show_names ? ED_asset_handle_get_name(asset_handle) : "",
|
show_names ? ED_asset_handle_get_name(&asset_handle) : "",
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
size_x,
|
size_x,
|
||||||
@ -103,14 +107,43 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||||||
0,
|
0,
|
||||||
"");
|
"");
|
||||||
ui_def_but_icon(but,
|
ui_def_but_icon(but,
|
||||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
ED_asset_handle_get_preview_icon_id(&asset_handle),
|
||||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||||
if (!ui_list->dyn_data->custom_drag_optype) {
|
if (!ui_list->dyn_data->custom_drag_optype) {
|
||||||
asset_view_item_but_drag_set(but, asset_handle);
|
asset_view_item_but_drag_set(but, &asset_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void asset_view_filter_items(uiList *ui_list,
|
||||||
|
const bContext *C,
|
||||||
|
PointerRNA *dataptr,
|
||||||
|
const char *propname)
|
||||||
|
{
|
||||||
|
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||||
|
AssetFilterSettings &filter_settings = list_data->filter_settings;
|
||||||
|
|
||||||
|
uiListNameFilter name_filter(*ui_list);
|
||||||
|
|
||||||
|
UI_list_filter_and_sort_items(
|
||||||
|
ui_list,
|
||||||
|
C,
|
||||||
|
[&name_filter, list_data, &filter_settings](
|
||||||
|
const PointerRNA &itemptr, blender::StringRefNull name, int index) {
|
||||||
|
AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
|
||||||
|
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
|
||||||
|
return UI_LIST_ITEM_NEVER_SHOW;
|
||||||
|
}
|
||||||
|
return name_filter(itemptr, name, index);
|
||||||
|
},
|
||||||
|
dataptr,
|
||||||
|
propname,
|
||||||
|
[list_data](const PointerRNA & /*itemptr*/, int index) -> std::string {
|
||||||
|
AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
|
||||||
|
return ED_asset_handle_get_name(&asset);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
|
static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
|
||||||
{
|
{
|
||||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||||
@ -136,14 +169,13 @@ uiListType *UI_UL_asset_view()
|
|||||||
|
|
||||||
BLI_strncpy(list_type->idname, "UI_UL_asset_view", sizeof(list_type->idname));
|
BLI_strncpy(list_type->idname, "UI_UL_asset_view", sizeof(list_type->idname));
|
||||||
list_type->draw_item = asset_view_draw_item;
|
list_type->draw_item = asset_view_draw_item;
|
||||||
|
list_type->filter_items = asset_view_filter_items;
|
||||||
list_type->listener = asset_view_listener;
|
list_type->listener = asset_view_listener;
|
||||||
|
|
||||||
return list_type;
|
return list_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asset_view_template_refresh_asset_collection(
|
static void populate_asset_collection(const AssetLibraryReference &asset_library_ref,
|
||||||
const AssetLibraryReference &asset_library_ref,
|
|
||||||
const AssetFilterSettings &filter_settings,
|
|
||||||
PointerRNA &assets_dataptr,
|
PointerRNA &assets_dataptr,
|
||||||
const char *assets_propname)
|
const char *assets_propname)
|
||||||
{
|
{
|
||||||
@ -164,17 +196,15 @@ static void asset_view_template_refresh_asset_collection(
|
|||||||
|
|
||||||
RNA_property_collection_clear(&assets_dataptr, assets_prop);
|
RNA_property_collection_clear(&assets_dataptr, assets_prop);
|
||||||
|
|
||||||
ED_assetlist_iterate(asset_library_ref, [&](AssetHandle asset) {
|
ED_assetlist_iterate(asset_library_ref, [&](AssetHandle /*asset*/) {
|
||||||
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
|
/* XXX creating a dummy #RNA_AssetHandle collection item. It's #file_data will be null. This is
|
||||||
/* Don't do anything else, but return true to continue iterating. */
|
* because the #FileDirEntry may be freed while iterating, there's a cache for them with a
|
||||||
return true;
|
* maximum size. Further code will query as needed it using the collection index. */
|
||||||
}
|
|
||||||
|
|
||||||
PointerRNA itemptr, fileptr;
|
PointerRNA itemptr, fileptr;
|
||||||
RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr);
|
RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr);
|
||||||
|
|
||||||
RNA_pointer_create(
|
RNA_pointer_create(nullptr, &RNA_FileSelectEntry, nullptr, &fileptr);
|
||||||
nullptr, &RNA_FileSelectEntry, const_cast<FileDirEntry *>(asset.file_data), &fileptr);
|
|
||||||
RNA_pointer_set(&itemptr, "file_data", fileptr);
|
RNA_pointer_set(&itemptr, "file_data", fileptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -221,12 +251,12 @@ void uiTemplateAssetView(uiLayout *layout,
|
|||||||
ED_assetlist_ensure_previews_job(&asset_library_ref, C);
|
ED_assetlist_ensure_previews_job(&asset_library_ref, C);
|
||||||
const int tot_items = ED_assetlist_size(&asset_library_ref);
|
const int tot_items = ED_assetlist_size(&asset_library_ref);
|
||||||
|
|
||||||
asset_view_template_refresh_asset_collection(
|
populate_asset_collection(asset_library_ref, *assets_dataptr, assets_propname);
|
||||||
asset_library_ref, *filter_settings, *assets_dataptr, assets_propname);
|
|
||||||
|
|
||||||
AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data),
|
AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data),
|
||||||
"AssetViewListData");
|
"AssetViewListData");
|
||||||
list_data->asset_library_ref = asset_library_ref;
|
list_data->asset_library_ref = asset_library_ref;
|
||||||
|
list_data->filter_settings = *filter_settings;
|
||||||
list_data->screen = CTX_wm_screen(C);
|
list_data->screen = CTX_wm_screen(C);
|
||||||
list_data->show_names = (display_flags & UI_TEMPLATE_ASSET_DRAW_NO_NAMES) == 0;
|
list_data->show_names = (display_flags & UI_TEMPLATE_ASSET_DRAW_NO_NAMES) == 0;
|
||||||
|
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "BLI_fnmatch.h"
|
#include "BLI_fnmatch.h"
|
||||||
|
#include "BLI_function_ref.hh"
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_math_base.h"
|
#include "BLI_math_base.h"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
|
#include "BLI_string_ref.hh"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_screen.h"
|
#include "BKE_screen.h"
|
||||||
@ -26,12 +28,15 @@
|
|||||||
#include "RNA_prototypes.h"
|
#include "RNA_prototypes.h"
|
||||||
|
|
||||||
#include "UI_interface.h"
|
#include "UI_interface.h"
|
||||||
|
#include "UI_interface.hh"
|
||||||
#include "UI_view2d.h"
|
#include "UI_view2d.h"
|
||||||
|
|
||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
|
|
||||||
#include "interface_intern.hh"
|
#include "interface_intern.hh"
|
||||||
|
|
||||||
|
using namespace blender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The validated data that was passed to #uiTemplateList (typically through Python).
|
* The validated data that was passed to #uiTemplateList (typically through Python).
|
||||||
* Populated through #ui_template_list_data_retrieve().
|
* Populated through #ui_template_list_data_retrieve().
|
||||||
@ -148,6 +153,45 @@ static void uilist_draw_filter_default(struct uiList *ui_list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uiListNameFilter::uiListNameFilter(uiList &list)
|
||||||
|
{
|
||||||
|
const char *filter_raw = list.filter_byname;
|
||||||
|
|
||||||
|
if (filter_raw[0]) {
|
||||||
|
const size_t slen = strlen(filter_raw);
|
||||||
|
|
||||||
|
/* Implicitly add heading/trailing wildcards if needed. */
|
||||||
|
if (slen + 3 <= sizeof(storage_.filter_buff)) {
|
||||||
|
filter_ = storage_.filter_buff;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filter_ = storage_.filter_dyn = static_cast<char *>(
|
||||||
|
MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn"));
|
||||||
|
}
|
||||||
|
BLI_strncpy_ensure_pad(filter_, filter_raw, '*', slen + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uiListNameFilter::~uiListNameFilter()
|
||||||
|
{
|
||||||
|
MEM_SAFE_FREE(storage_.filter_dyn);
|
||||||
|
}
|
||||||
|
|
||||||
|
eUIListFilterResult uiListNameFilter::operator()(const PointerRNA & /* itemptr */,
|
||||||
|
StringRefNull name,
|
||||||
|
int /* index */)
|
||||||
|
{
|
||||||
|
if (!filter_) {
|
||||||
|
return UI_LIST_ITEM_FILTER_MATCHES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case-insensitive! */
|
||||||
|
if (fnmatch(filter_, name.c_str(), FNM_CASEFOLD) == 0) {
|
||||||
|
return UI_LIST_ITEM_FILTER_MATCHES;
|
||||||
|
}
|
||||||
|
return UI_LIST_ITEM_FILTER_MISMATCHES;
|
||||||
|
}
|
||||||
|
|
||||||
struct StringCmp {
|
struct StringCmp {
|
||||||
char name[MAX_IDPROP_NAME];
|
char name[MAX_IDPROP_NAME];
|
||||||
int org_idx;
|
int org_idx;
|
||||||
@ -159,16 +203,16 @@ static int cmpstringp(const void *p1, const void *p2)
|
|||||||
return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
|
return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uilist_filter_items_default(struct uiList *ui_list,
|
void UI_list_filter_and_sort_items(uiList *ui_list,
|
||||||
const struct bContext * /*C*/,
|
const bContext * /*C*/,
|
||||||
struct PointerRNA *dataptr,
|
uiListItemFilterFn item_filter_fn,
|
||||||
const char *propname)
|
PointerRNA *dataptr,
|
||||||
|
const char *propname,
|
||||||
|
uiListItemGetNameFn get_name_fn)
|
||||||
{
|
{
|
||||||
uiListDyn *dyn_data = ui_list->dyn_data;
|
uiListDyn *dyn_data = ui_list->dyn_data;
|
||||||
PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
|
PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
|
||||||
|
|
||||||
const char *filter_raw = ui_list->filter_byname;
|
|
||||||
char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = nullptr;
|
|
||||||
const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
|
const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
|
||||||
const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
|
const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
|
||||||
UILST_FLT_SORT_ALPHA;
|
UILST_FLT_SORT_ALPHA;
|
||||||
@ -176,41 +220,26 @@ static void uilist_filter_items_default(struct uiList *ui_list,
|
|||||||
|
|
||||||
dyn_data->items_shown = dyn_data->items_len = len;
|
dyn_data->items_shown = dyn_data->items_len = len;
|
||||||
|
|
||||||
if (len && (order_by_name || filter_raw[0])) {
|
if (len && (order_by_name || item_filter_fn)) {
|
||||||
StringCmp *names = nullptr;
|
StringCmp *names = nullptr;
|
||||||
int order_idx = 0, i = 0;
|
int order_idx = 0, i = 0;
|
||||||
|
|
||||||
if (order_by_name) {
|
if (order_by_name) {
|
||||||
names = static_cast<StringCmp *>(MEM_callocN(sizeof(StringCmp) * len, "StringCmp"));
|
names = static_cast<StringCmp *>(MEM_callocN(sizeof(StringCmp) * len, "StringCmp"));
|
||||||
}
|
}
|
||||||
if (filter_raw[0]) {
|
|
||||||
const size_t slen = strlen(filter_raw);
|
|
||||||
|
|
||||||
|
if (item_filter_fn) {
|
||||||
dyn_data->items_filter_flags = static_cast<int *>(
|
dyn_data->items_filter_flags = static_cast<int *>(
|
||||||
MEM_callocN(sizeof(int) * len, "items_filter_flags"));
|
MEM_callocN(sizeof(int) * len, "items_filter_flags"));
|
||||||
dyn_data->items_shown = 0;
|
dyn_data->items_shown = 0;
|
||||||
|
|
||||||
/* Implicitly add heading/trailing wildcards if needed. */
|
|
||||||
if (slen + 3 <= sizeof(filter_buff)) {
|
|
||||||
filter = filter_buff;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filter = filter_dyn = static_cast<char *>(
|
|
||||||
MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn"));
|
|
||||||
}
|
|
||||||
BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RNA_PROP_BEGIN (dataptr, itemptr, prop) {
|
RNA_PROP_BEGIN (dataptr, itemptr, prop) {
|
||||||
bool do_order = false;
|
bool do_order = false;
|
||||||
|
|
||||||
char *namebuf;
|
char *namebuf;
|
||||||
if (RNA_struct_is_a(itemptr.type, &RNA_AssetHandle)) {
|
if (get_name_fn) {
|
||||||
/* XXX The AssetHandle design is hacky and meant to be temporary. It can't have a proper
|
namebuf = BLI_strdup(get_name_fn(itemptr, i).c_str());
|
||||||
* name property, so for now this hardcoded exception is needed. */
|
|
||||||
AssetHandle *asset_handle = (AssetHandle *)itemptr.data;
|
|
||||||
const char *asset_name = ED_asset_handle_get_name(asset_handle);
|
|
||||||
namebuf = BLI_strdup(asset_name);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
namebuf = RNA_struct_name_get_alloc(&itemptr, nullptr, 0, nullptr);
|
namebuf = RNA_struct_name_get_alloc(&itemptr, nullptr, 0, nullptr);
|
||||||
@ -218,9 +247,13 @@ static void uilist_filter_items_default(struct uiList *ui_list,
|
|||||||
|
|
||||||
const char *name = namebuf ? namebuf : "";
|
const char *name = namebuf ? namebuf : "";
|
||||||
|
|
||||||
if (filter[0]) {
|
if (item_filter_fn) {
|
||||||
/* Case-insensitive! */
|
const eUIListFilterResult filter_result = item_filter_fn(itemptr, name, i);
|
||||||
if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
|
|
||||||
|
if (filter_result == UI_LIST_ITEM_NEVER_SHOW) {
|
||||||
|
/* Pass. */
|
||||||
|
}
|
||||||
|
else if (filter_result == UI_LIST_ITEM_FILTER_MATCHES) {
|
||||||
dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
|
dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
|
||||||
if (!filter_exclude) {
|
if (!filter_exclude) {
|
||||||
dyn_data->items_shown++;
|
dyn_data->items_shown++;
|
||||||
@ -266,15 +299,30 @@ static void uilist_filter_items_default(struct uiList *ui_list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter_dyn) {
|
|
||||||
MEM_freeN(filter_dyn);
|
|
||||||
}
|
|
||||||
if (names) {
|
if (names) {
|
||||||
MEM_freeN(names);
|
MEM_freeN(names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default UI List filtering: Filter by name.
|
||||||
|
*/
|
||||||
|
static void uilist_filter_items_default(struct uiList *ui_list,
|
||||||
|
const struct bContext *C,
|
||||||
|
struct PointerRNA *dataptr,
|
||||||
|
const char *propname)
|
||||||
|
{
|
||||||
|
if (ui_list->filter_byname[0]) {
|
||||||
|
uiListNameFilter name_filter(*ui_list);
|
||||||
|
UI_list_filter_and_sort_items(ui_list, C, name_filter, dataptr, propname);
|
||||||
|
}
|
||||||
|
/* Optimization: Skip filtering entirely when there is no filter string set. */
|
||||||
|
else {
|
||||||
|
UI_list_filter_and_sort_items(ui_list, C, nullptr, dataptr, propname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void uilist_free_dyn_data(uiList *ui_list)
|
static void uilist_free_dyn_data(uiList *ui_list)
|
||||||
{
|
{
|
||||||
uiListDyn *dyn_data = ui_list->dyn_data;
|
uiListDyn *dyn_data = ui_list->dyn_data;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "AS_asset_catalog.hh"
|
#include "AS_asset_catalog.hh"
|
||||||
#include "AS_asset_catalog_tree.hh"
|
#include "AS_asset_catalog_tree.hh"
|
||||||
#include "AS_asset_library.hh"
|
#include "AS_asset_library.hh"
|
||||||
|
#include "AS_asset_representation.h"
|
||||||
|
|
||||||
#include "BLI_multi_value_map.hh"
|
#include "BLI_multi_value_map.hh"
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params)
|
|||||||
|
|
||||||
struct LibraryAsset {
|
struct LibraryAsset {
|
||||||
AssetLibraryReference library_ref;
|
AssetLibraryReference library_ref;
|
||||||
AssetHandle handle;
|
AssetRepresentation &asset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AssetItemTree {
|
struct AssetItemTree {
|
||||||
@ -93,11 +94,11 @@ static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ED_assetlist_iterate(all_library_ref, [&](AssetHandle asset) {
|
ED_assetlist_iterate(all_library_ref, [&](AssetHandle asset_handle) {
|
||||||
if (!ED_asset_filter_matches_asset(&type_filter, &asset)) {
|
if (!ED_asset_filter_matches_asset(&type_filter, &asset_handle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset);
|
const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset_handle);
|
||||||
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
|
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
|
||||||
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) {
|
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) {
|
||||||
return true;
|
return true;
|
||||||
@ -111,7 +112,8 @@ static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node
|
|||||||
if (catalog == nullptr) {
|
if (catalog == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
assets_per_path.add(catalog->path, LibraryAsset{all_library_ref, asset});
|
AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle);
|
||||||
|
assets_per_path.add(catalog->path, LibraryAsset{all_library_ref, *asset});
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -178,16 +180,17 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
|||||||
|
|
||||||
for (const LibraryAsset &item : asset_items) {
|
for (const LibraryAsset &item : asset_items) {
|
||||||
uiLayout *col = uiLayoutColumn(layout, false);
|
uiLayout *col = uiLayoutColumn(layout, false);
|
||||||
PointerRNA file{
|
|
||||||
&screen.id, &RNA_FileSelectEntry, const_cast<FileDirEntry *>(item.handle.file_data)};
|
PointerRNA asset_ptr{NULL, &RNA_AssetRepresentation, &item.asset};
|
||||||
uiLayoutSetContextPointer(col, "active_file", &file);
|
uiLayoutSetContextPointer(col, "asset", &asset_ptr);
|
||||||
|
|
||||||
PointerRNA library_ptr{&screen.id,
|
PointerRNA library_ptr{&screen.id,
|
||||||
&RNA_AssetLibraryReference,
|
&RNA_AssetLibraryReference,
|
||||||
const_cast<AssetLibraryReference *>(&item.library_ref)};
|
const_cast<AssetLibraryReference *>(&item.library_ref)};
|
||||||
uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr);
|
uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr);
|
||||||
|
|
||||||
uiItemO(col, ED_asset_handle_get_name(&item.handle), ICON_NONE, "NODE_OT_add_group_asset");
|
uiItemO(
|
||||||
|
col, AS_asset_representation_name_get(&item.asset), ICON_NONE, "NODE_OT_add_group_asset");
|
||||||
}
|
}
|
||||||
|
|
||||||
catalog_item->foreach_child([&](asset_system::AssetCatalogTreeItem &child_item) {
|
catalog_item->foreach_child([&](asset_system::AssetCatalogTreeItem &child_item) {
|
||||||
|
@ -40,7 +40,7 @@ namespace blender::ed::space_node {
|
|||||||
struct AddNodeItem {
|
struct AddNodeItem {
|
||||||
nodes::AddNodeInfo info;
|
nodes::AddNodeInfo info;
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
std::optional<AssetHandle> asset;
|
const AssetRepresentation *asset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AddNodeSearchStorage {
|
struct AddNodeSearchStorage {
|
||||||
@ -66,24 +66,25 @@ static void add_node_search_listen_fn(const wmRegionListenerParams *params, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void search_items_for_asset_metadata(const bNodeTree &node_tree,
|
static void search_items_for_asset_metadata(const bNodeTree &node_tree,
|
||||||
const AssetHandle asset,
|
const AssetHandle asset_handle,
|
||||||
Vector<AddNodeItem> &search_items)
|
Vector<AddNodeItem> &search_items)
|
||||||
{
|
{
|
||||||
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset);
|
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset_handle);
|
||||||
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
|
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
|
||||||
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
|
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle);
|
||||||
AddNodeItem item{};
|
AddNodeItem item{};
|
||||||
item.info.ui_name = ED_asset_handle_get_name(&asset);
|
item.info.ui_name = ED_asset_handle_get_name(&asset_handle);
|
||||||
item.identifier = node_tree.typeinfo->group_idname;
|
item.identifier = node_tree.typeinfo->group_idname;
|
||||||
item.info.description = asset_data.description == nullptr ? "" : asset_data.description;
|
item.info.description = asset_data.description == nullptr ? "" : asset_data.description;
|
||||||
item.asset = asset;
|
item.asset = asset;
|
||||||
item.info.after_add_fn = [asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
|
item.info.after_add_fn = [asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
|
||||||
Main &bmain = *CTX_data_main(&C);
|
Main &bmain = *CTX_data_main(&C);
|
||||||
node.flag &= ~NODE_OPTIONS;
|
node.flag &= ~NODE_OPTIONS;
|
||||||
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset);
|
node.id = ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT);
|
||||||
id_us_plus(node.id);
|
id_us_plus(node.id);
|
||||||
BKE_ntree_update_tag_node_property(&node_tree, &node);
|
BKE_ntree_update_tag_node_property(&node_tree, &node);
|
||||||
DEG_relations_tag_update(&bmain);
|
DEG_relations_tag_update(&bmain);
|
||||||
|
@ -143,10 +143,10 @@ static void add_existing_group_input_fn(nodes::LinkSearchOpParams ¶ms,
|
|||||||
*/
|
*/
|
||||||
static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
|
static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
|
||||||
const bNodeSocket &socket,
|
const bNodeSocket &socket,
|
||||||
const AssetHandle asset,
|
const AssetHandle asset_handle,
|
||||||
Vector<SocketLinkOperation> &search_link_ops)
|
Vector<SocketLinkOperation> &search_link_ops)
|
||||||
{
|
{
|
||||||
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset);
|
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset_handle);
|
||||||
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
|
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
|
||||||
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
|
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
|
||||||
return;
|
return;
|
||||||
@ -182,7 +182,8 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StringRef asset_name = ED_asset_handle_get_name(&asset);
|
AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle);
|
||||||
|
const StringRef asset_name = ED_asset_handle_get_name(&asset_handle);
|
||||||
const StringRef socket_name = socket_property->name;
|
const StringRef socket_name = socket_property->name;
|
||||||
|
|
||||||
search_link_ops.append(
|
search_link_ops.append(
|
||||||
@ -193,7 +194,7 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
|
|||||||
bNode &node = params.add_node(params.node_tree.typeinfo->group_idname);
|
bNode &node = params.add_node(params.node_tree.typeinfo->group_idname);
|
||||||
node.flag &= ~NODE_OPTIONS;
|
node.flag &= ~NODE_OPTIONS;
|
||||||
|
|
||||||
node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset);
|
node.id = ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT);
|
||||||
id_us_plus(node.id);
|
id_us_plus(node.id);
|
||||||
BKE_ntree_update_tag_node_property(¶ms.node_tree, &node);
|
BKE_ntree_update_tag_node_property(¶ms.node_tree, &node);
|
||||||
DEG_relations_tag_update(&bmain);
|
DEG_relations_tag_update(&bmain);
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
#include "AS_asset_representation.h"
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "DNA_collection_types.h"
|
#include "DNA_collection_types.h"
|
||||||
@ -378,14 +380,16 @@ void NODE_OT_add_group(wmOperatorType *ot)
|
|||||||
/** \name Add Node Group Asset Operator
|
/** \name Add Node Group Asset Operator
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static bool add_node_group_asset(const bContext &C, const AssetHandle asset, ReportList &reports)
|
static bool add_node_group_asset(const bContext &C,
|
||||||
|
const AssetRepresentation *asset,
|
||||||
|
ReportList &reports)
|
||||||
{
|
{
|
||||||
Main &bmain = *CTX_data_main(&C);
|
Main &bmain = *CTX_data_main(&C);
|
||||||
SpaceNode &snode = *CTX_wm_space_node(&C);
|
SpaceNode &snode = *CTX_wm_space_node(&C);
|
||||||
bNodeTree &edit_tree = *snode.edittree;
|
bNodeTree &edit_tree = *snode.edittree;
|
||||||
|
|
||||||
bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
|
bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
|
||||||
asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset));
|
ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT));
|
||||||
if (!node_group) {
|
if (!node_group) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -427,9 +431,8 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven
|
|||||||
if (!library_ref) {
|
if (!library_ref) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
bool is_valid;
|
const AssetRepresentation *asset = CTX_wm_asset(C);
|
||||||
const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid);
|
if (!asset) {
|
||||||
if (!is_valid) {
|
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +445,7 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven
|
|||||||
|
|
||||||
snode.runtime->cursor /= UI_DPI_FAC;
|
snode.runtime->cursor /= UI_DPI_FAC;
|
||||||
|
|
||||||
if (!add_node_group_asset(*C, handle, *op->reports)) {
|
if (!add_node_group_asset(*C, asset, *op->reports)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,12 +463,11 @@ static char *node_add_group_asset_get_description(struct bContext *C,
|
|||||||
struct wmOperatorType * /*op*/,
|
struct wmOperatorType * /*op*/,
|
||||||
struct PointerRNA * /*values*/)
|
struct PointerRNA * /*values*/)
|
||||||
{
|
{
|
||||||
bool is_valid;
|
const AssetRepresentation *asset = CTX_wm_asset(C);
|
||||||
const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid);
|
if (!asset) {
|
||||||
if (!is_valid) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&handle);
|
const AssetMetaData &asset_data = *AS_asset_representation_metadata_get(asset);
|
||||||
if (!asset_data.description) {
|
if (!asset_data.description) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,10 @@ typedef struct AssetLibraryReference {
|
|||||||
* Not part of the core design, we should try to get rid of it. Only needed to wrap FileDirEntry
|
* Not part of the core design, we should try to get rid of it. Only needed to wrap FileDirEntry
|
||||||
* into a type with PropertyGroup as base, so we can have an RNA collection of #AssetHandle's to
|
* into a type with PropertyGroup as base, so we can have an RNA collection of #AssetHandle's to
|
||||||
* pass to the UI.
|
* pass to the UI.
|
||||||
|
*
|
||||||
|
* \warning Never store this! When using #ED_assetlist_iterate(), only access it within the
|
||||||
|
* iterator function. The contained file data can be freed since the file cache has a
|
||||||
|
* maximum number of items.
|
||||||
*/
|
*/
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -578,6 +578,17 @@ static void rna_def_asset_handle(BlenderRNA *brna)
|
|||||||
rna_def_asset_handle_api(srna);
|
rna_def_asset_handle_api(srna);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_def_asset_representation(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
StructRNA *srna;
|
||||||
|
|
||||||
|
srna = RNA_def_struct(brna, "AssetRepresentation", NULL);
|
||||||
|
RNA_def_struct_ui_text(srna,
|
||||||
|
"Asset Representation",
|
||||||
|
"Information about an entity that makes it possible for the asset system "
|
||||||
|
"to deal with the entity as asset");
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_def_asset_catalog_path(BlenderRNA *brna)
|
static void rna_def_asset_catalog_path(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
StructRNA *srna = RNA_def_struct(brna, "AssetCatalogPath", NULL);
|
StructRNA *srna = RNA_def_struct(brna, "AssetCatalogPath", NULL);
|
||||||
@ -610,6 +621,7 @@ void RNA_def_asset(BlenderRNA *brna)
|
|||||||
rna_def_asset_data(brna);
|
rna_def_asset_data(brna);
|
||||||
rna_def_asset_library_reference(brna);
|
rna_def_asset_library_reference(brna);
|
||||||
rna_def_asset_handle(brna);
|
rna_def_asset_handle(brna);
|
||||||
|
rna_def_asset_representation(brna);
|
||||||
rna_def_asset_catalog_path(brna);
|
rna_def_asset_catalog_path(brna);
|
||||||
|
|
||||||
RNA_define_animate_sdna(true);
|
RNA_define_animate_sdna(true);
|
||||||
|
Loading…
Reference in New Issue
Block a user