Compare commits
101 Commits
temp_test_
...
ui-asset-v
Author | SHA1 | Date | |
---|---|---|---|
c7904d2398 | |||
91b87d8d7f | |||
e7462cfa44 | |||
2c65710c9a | |||
01a5d3fa28 | |||
10383566b8 | |||
c6182a91c3 | |||
5a94ab9ac2 | |||
fd6015f9fd | |||
12d7b71294 | |||
552fec44da | |||
269dc0bbc6 | |||
c81ac61e58 | |||
eecaca8b2a | |||
c56e8ae919 | |||
![]() |
c8b925cafb | ||
064a379205 | |||
545bbcc7f3 | |||
84060a0eb1 | |||
59f7044134 | |||
fac59931c7 | |||
aae7ea2874 | |||
![]() |
1bd3645deb | ||
![]() |
a4a6c2a1a4 | ||
2199796694 | |||
a9613b2947 | |||
392a1d8a9f | |||
3b28a68d97 | |||
c0cf72a6fd | |||
bb95895b19 | |||
412d760efa | |||
c8cb79e309 | |||
afb2974c34 | |||
dfaf420e93 | |||
c026bb2961 | |||
063c248cb7 | |||
40ed613609 | |||
d78754ff18 | |||
02ccd5931a | |||
b485710a25 | |||
9b2661a8e0 | |||
19e1ae866f | |||
96543946b2 | |||
0e071e015e | |||
2fad30ba1e | |||
3d706bb0f3 | |||
d71b7ff3ff | |||
048a5e5f56 | |||
622ca567eb | |||
7be8055a07 | |||
2f658677c6 | |||
5ccb47a97e | |||
9a6c22a764 | |||
317e78a792 | |||
![]() |
2606f57bec | ||
b9451c4841 | |||
1c76b5aff0 | |||
23d705aacc | |||
ffd518617c | |||
c02ff5222e | |||
ef832a5a42 | |||
148a3095ca | |||
049c34b86e | |||
4f8f541e02 | |||
700824f247 | |||
a0084630b9 | |||
418fdab1bc | |||
caaa9b40ec | |||
6045464c75 | |||
3522532cb2 | |||
3bf8074d83 | |||
![]() |
a7dc752f26 | ||
5d42e77bb2 | |||
89fa44440c | |||
a371a0e0e0 | |||
![]() |
356d624f21 | ||
f5ede4ed8c | |||
3f8edc5da1 | |||
8e126c3fa2 | |||
bf3288e71a | |||
cd240d87ed | |||
8457a235a2 | |||
4ed86e0a11 | |||
5726029b86 | |||
d59ac439a1 | |||
4ecdc400b5 | |||
d194b038d5 | |||
5bc7acbdec | |||
ca69a303e1 | |||
6c0c809524 | |||
5dcf164932 | |||
1a2ab21a2c | |||
b88c7f7d13 | |||
c8a7e3a572 | |||
9d08f2d69a | |||
19e6db3d53 | |||
eef2a348a7 | |||
378b7eb2af | |||
3ce680f434 | |||
bc9eac28ba | |||
796c599194 |
@@ -117,13 +117,19 @@ def register():
|
||||
for cls in mod.classes:
|
||||
register_class(cls)
|
||||
|
||||
# space_userprefs.py
|
||||
from bpy.props import (
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
IntProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.types import WindowManager
|
||||
from bpy.types import (
|
||||
AssetHandle,
|
||||
WindowManager,
|
||||
WorkSpace,
|
||||
)
|
||||
|
||||
# space_userprefs.py
|
||||
def addon_filter_items(_self, _context):
|
||||
import addon_utils
|
||||
|
||||
@@ -165,6 +171,19 @@ def register():
|
||||
)
|
||||
# done...
|
||||
|
||||
# space_view3d.py
|
||||
WorkSpace.active_pose_asset_index = IntProperty(
|
||||
name="Active Pose Asset",
|
||||
# TODO explain which list the index belongs to, or how it can be used to get the pose.
|
||||
description="Per workspace index of the active pose asset"
|
||||
)
|
||||
# Register for window-manager. This is a global property that shouldn't be
|
||||
# written to files.
|
||||
WindowManager.pose_assets = CollectionProperty(
|
||||
type=AssetHandle
|
||||
)
|
||||
# done...
|
||||
|
||||
|
||||
def unregister():
|
||||
from bpy.utils import unregister_class
|
||||
|
@@ -7000,6 +7000,29 @@ class VIEW3D_PT_context_properties(Panel):
|
||||
rna_prop_ui.draw(self.layout, context, member, object, False)
|
||||
|
||||
|
||||
class VIEW3D_PT_asset_testing(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Asset Testing"
|
||||
bl_category = "Assets"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
wm = context.window_manager
|
||||
workspace = context.workspace
|
||||
|
||||
layout.template_asset_view(
|
||||
"pose_assets",
|
||||
workspace,
|
||||
"active_asset_library",
|
||||
wm,
|
||||
"pose_assets",
|
||||
workspace,
|
||||
"active_pose_asset_index"
|
||||
)
|
||||
|
||||
|
||||
# Grease Pencil Object - Multiframe falloff tools
|
||||
class VIEW3D_PT_gpencil_multi_frame(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@@ -7713,6 +7736,7 @@ classes = (
|
||||
VIEW3D_PT_transform_orientations,
|
||||
VIEW3D_PT_overlay_gpencil_options,
|
||||
VIEW3D_PT_context_properties,
|
||||
VIEW3D_PT_asset_testing,
|
||||
VIEW3D_PT_paint_vertex_context_menu,
|
||||
VIEW3D_PT_paint_texture_context_menu,
|
||||
VIEW3D_PT_paint_weight_context_menu,
|
||||
|
@@ -26,6 +26,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AssetLibraryReference;
|
||||
struct BlendDataReader;
|
||||
struct BlendWriter;
|
||||
struct ID;
|
||||
@@ -45,6 +46,8 @@ struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(struct AssetMetaData *
|
||||
const char *name);
|
||||
void BKE_asset_metadata_tag_remove(struct AssetMetaData *asset_data, struct AssetTag *tag);
|
||||
|
||||
void BKE_asset_library_reference_init_default(struct AssetLibraryReference *library_ref);
|
||||
|
||||
struct PreviewImage *BKE_asset_metadata_preview_get_from_id(const struct AssetMetaData *asset_data,
|
||||
const struct ID *owner_id);
|
||||
|
||||
|
@@ -340,6 +340,8 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
|
||||
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
|
||||
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
|
||||
|
||||
const struct AssetLibraryReference *CTX_wm_asset_library(const bContext *C);
|
||||
|
||||
bool CTX_wm_interface_locked(const bContext *C);
|
||||
|
||||
/* Gets pointer to the dependency graph.
|
||||
|
@@ -332,6 +332,9 @@ typedef void (*uiListFilterItemsFunc)(struct uiList *ui_list,
|
||||
struct PointerRNA *,
|
||||
const char *propname);
|
||||
|
||||
/* Listen to notifiers. Only for lists defined in C. */
|
||||
typedef void (*uiListListener)(struct uiList *ui_list, wmRegionListenerParams *params);
|
||||
|
||||
typedef struct uiListType {
|
||||
struct uiListType *next, *prev;
|
||||
|
||||
@@ -341,6 +344,9 @@ typedef struct uiListType {
|
||||
uiListDrawFilterFunc draw_filter;
|
||||
uiListFilterItemsFunc filter_items;
|
||||
|
||||
/* For lists defined in C only. */
|
||||
uiListListener listener;
|
||||
|
||||
/* RNA integration */
|
||||
ExtensionRNA rna_ext;
|
||||
} uiListType;
|
||||
|
@@ -110,6 +110,11 @@ void BKE_asset_metadata_tag_remove(AssetMetaData *asset_data, AssetTag *tag)
|
||||
BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags);
|
||||
}
|
||||
|
||||
void BKE_asset_library_reference_init_default(AssetLibraryReference *library_ref)
|
||||
{
|
||||
memcpy(library_ref, DNA_struct_default_get(AssetLibraryReference), sizeof(*library_ref));
|
||||
}
|
||||
|
||||
/* Queries -------------------------------------------- */
|
||||
|
||||
PreviewImage *BKE_asset_metadata_preview_get_from_id(const AssetMetaData *UNUSED(asset_data),
|
||||
|
@@ -1398,6 +1398,11 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
|
||||
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
|
||||
}
|
||||
|
||||
const AssetLibraryReference *CTX_wm_asset_library(const bContext *C)
|
||||
{
|
||||
return ctx_data_pointer_get(C, "asset_library");
|
||||
}
|
||||
|
||||
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
@@ -233,22 +233,30 @@ bool BKE_cryptomatte_find_name(const CryptomatteSession *session,
|
||||
|
||||
char *BKE_cryptomatte_entries_to_matte_id(NodeCryptomatte *node_storage)
|
||||
{
|
||||
DynStr *matte_id = BLI_dynstr_new();
|
||||
std::stringstream ss;
|
||||
ss.precision(9);
|
||||
|
||||
bool first = true;
|
||||
LISTBASE_FOREACH (CryptomatteEntry *, entry, &node_storage->entries) {
|
||||
if (!first) {
|
||||
BLI_dynstr_append(matte_id, ",");
|
||||
ss << ',';
|
||||
}
|
||||
if (BLI_strnlen(entry->name, sizeof(entry->name)) != 0) {
|
||||
BLI_dynstr_nappend(matte_id, entry->name, sizeof(entry->name));
|
||||
blender::StringRef entry_name(entry->name, BLI_strnlen(entry->name, sizeof(entry->name)));
|
||||
if (!entry_name.is_empty()) {
|
||||
ss << entry_name;
|
||||
}
|
||||
else {
|
||||
BLI_dynstr_appendf(matte_id, "<%.9g>", entry->encoded_hash);
|
||||
ss << '<' << std::scientific << entry->encoded_hash << '>';
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
char *result = BLI_dynstr_get_cstring(matte_id);
|
||||
BLI_dynstr_free(matte_id);
|
||||
|
||||
/* Convert result to C string. */
|
||||
const std::string result_string = ss.str();
|
||||
const char *c_str = result_string.c_str();
|
||||
size_t result_len = result_string.size() + 1;
|
||||
char *result = static_cast<char *>(MEM_mallocN(sizeof(char) * result_len, __func__));
|
||||
memcpy(result, c_str, result_len);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,8 @@
|
||||
#include "BKE_cryptomatte.hh"
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
@@ -663,6 +663,7 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(attribute));
|
||||
default:
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -676,6 +677,7 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(attribute));
|
||||
default:
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -702,11 +704,13 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(attribute));
|
||||
default:
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -683,6 +683,9 @@ void BKE_area_region_free(SpaceType *st, ARegion *region)
|
||||
if (dyn_data->items_filter_neworder) {
|
||||
MEM_freeN(dyn_data->items_filter_neworder);
|
||||
}
|
||||
if (dyn_data->customdata) {
|
||||
MEM_freeN(dyn_data->customdata);
|
||||
}
|
||||
MEM_freeN(dyn_data);
|
||||
}
|
||||
if (uilst->properties) {
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idtype.h"
|
||||
@@ -53,6 +54,13 @@
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void workspace_init_data(ID *id)
|
||||
{
|
||||
WorkSpace *workspace = (WorkSpace *)id;
|
||||
|
||||
BKE_asset_library_reference_init_default(&workspace->active_asset_library);
|
||||
}
|
||||
|
||||
static void workspace_free_data(ID *id)
|
||||
{
|
||||
WorkSpace *workspace = (WorkSpace *)id;
|
||||
@@ -180,7 +188,7 @@ IDTypeInfo IDType_ID_WS = {
|
||||
.translation_context = BLT_I18NCONTEXT_ID_WORKSPACE,
|
||||
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_MAKELOCAL | IDTYPE_FLAGS_NO_ANIMDATA,
|
||||
|
||||
.init_data = NULL,
|
||||
.init_data = workspace_init_data,
|
||||
.copy_data = NULL,
|
||||
.free_data = workspace_free_data,
|
||||
.make_local = NULL,
|
||||
|
@@ -53,6 +53,7 @@
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_colortools.h"
|
||||
@@ -1964,4 +1965,13 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "WorkSpace", "AssetLibraryReference", "active_asset_library")) {
|
||||
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
|
||||
BKE_asset_library_reference_init_default(&workspace->active_asset_library);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ set(INC
|
||||
../include
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../blenloader
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
@@ -30,6 +31,7 @@ set(INC_SYS
|
||||
|
||||
set(SRC
|
||||
asset_edit.cc
|
||||
asset_list.cc
|
||||
asset_ops.cc
|
||||
)
|
||||
|
||||
|
@@ -18,11 +18,23 @@
|
||||
* \ingroup edasset
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "UI_interface_icons.h"
|
||||
|
||||
@@ -30,6 +42,8 @@
|
||||
|
||||
#include "ED_asset.h"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
bool ED_asset_mark_id(const bContext *C, ID *id)
|
||||
{
|
||||
if (id->asset_data) {
|
||||
@@ -45,6 +59,9 @@ bool ED_asset_mark_id(const bContext *C, ID *id)
|
||||
|
||||
UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true);
|
||||
|
||||
/* Important for asset storage to update properly! */
|
||||
ED_assetlist_storage_tag_main_data_dirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,6 +74,9 @@ bool ED_asset_clear_id(ID *id)
|
||||
/* Don't clear fake user here, there's no guarantee that it was actually set by
|
||||
* #ED_asset_mark_id(), it might have been something/someone else. */
|
||||
|
||||
/* Important for asset storage to update properly! */
|
||||
ED_assetlist_storage_tag_main_data_dirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -65,3 +85,135 @@ bool ED_asset_can_make_single_from_context(const bContext *C)
|
||||
/* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */
|
||||
return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != nullptr;
|
||||
}
|
||||
|
||||
/* TODO better place? */
|
||||
/* TODO What about the setter and the itemf? */
|
||||
#include "BKE_preferences.h"
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library)
|
||||
{
|
||||
/* Simple case: Predefined repo, just set the value. */
|
||||
if (library->type < ASSET_LIBRARY_CUSTOM) {
|
||||
return library->type;
|
||||
}
|
||||
|
||||
/* Note that the path isn't checked for validity here. If an invalid library path is used, the
|
||||
* Asset Browser can give a nice hint on what's wrong. */
|
||||
const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
|
||||
&U, library->custom_library_index);
|
||||
if (user_library) {
|
||||
return ASSET_LIBRARY_CUSTOM + library->custom_library_index;
|
||||
}
|
||||
|
||||
BLI_assert(0);
|
||||
return ASSET_LIBRARY_LOCAL;
|
||||
}
|
||||
|
||||
AssetLibraryReference ED_asset_library_reference_from_enum_value(int value)
|
||||
{
|
||||
AssetLibraryReference library;
|
||||
|
||||
/* Simple case: Predefined repo, just set the value. */
|
||||
if (value < ASSET_LIBRARY_CUSTOM) {
|
||||
library.type = value;
|
||||
library.custom_library_index = -1;
|
||||
BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL));
|
||||
return library;
|
||||
}
|
||||
|
||||
const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
|
||||
&U, value - ASSET_LIBRARY_CUSTOM);
|
||||
|
||||
/* Note that the path isn't checked for validity here. If an invalid library path is used, the
|
||||
* Asset Browser can give a nice hint on what's wrong. */
|
||||
const bool is_valid = (user_library->name[0] && user_library->path[0]);
|
||||
if (!user_library) {
|
||||
library.type = ASSET_LIBRARY_LOCAL;
|
||||
library.custom_library_index = -1;
|
||||
}
|
||||
else if (user_library && is_valid) {
|
||||
library.custom_library_index = value - ASSET_LIBRARY_CUSTOM;
|
||||
library.type = ASSET_LIBRARY_CUSTOM;
|
||||
}
|
||||
return library;
|
||||
}
|
||||
|
||||
class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
|
||||
const AssetHandle &handle_;
|
||||
TempLibraryContext *temp_lib_context_ = nullptr;
|
||||
|
||||
public:
|
||||
AssetTemporaryIDConsumer(const AssetHandle &handle) : handle_(handle)
|
||||
{
|
||||
}
|
||||
~AssetTemporaryIDConsumer()
|
||||
{
|
||||
if (temp_lib_context_) {
|
||||
BLO_library_temp_free(temp_lib_context_);
|
||||
}
|
||||
}
|
||||
|
||||
ID *get_local_id()
|
||||
{
|
||||
return ED_assetlist_asset_local_id_get(&handle_);
|
||||
}
|
||||
|
||||
ID *import_id(const AssetLibraryReference &asset_library,
|
||||
ID_Type id_type,
|
||||
Main &bmain,
|
||||
ReportList &reports)
|
||||
{
|
||||
std::string asset_path = ED_assetlist_asset_filepath_get(asset_library, handle_);
|
||||
if (asset_path.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char blend_file_path[FILE_MAX_LIBEXTRA];
|
||||
char *group = NULL;
|
||||
char *asset_name = NULL;
|
||||
BLO_library_path_explode(asset_path.c_str(), blend_file_path, &group, &asset_name);
|
||||
|
||||
temp_lib_context_ = BLO_library_temp_load_id(
|
||||
&bmain, blend_file_path, id_type, asset_name, &reports);
|
||||
|
||||
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);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BLI_assert(GS(temp_lib_context_->temp_id->name) == id_type);
|
||||
return temp_lib_context_->temp_id;
|
||||
}
|
||||
};
|
||||
|
||||
AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<AssetTempIDConsumer *>(
|
||||
OBJECT_GUARDED_NEW(AssetTemporaryIDConsumer, *handle));
|
||||
}
|
||||
|
||||
void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer)
|
||||
{
|
||||
OBJECT_GUARDED_SAFE_DELETE(*consumer, AssetTemporaryIDConsumer);
|
||||
}
|
||||
|
||||
ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_,
|
||||
const AssetLibraryReference *asset_library,
|
||||
ID_Type id_type,
|
||||
Main *bmain,
|
||||
ReportList *reports)
|
||||
{
|
||||
if (!(consumer_ && asset_library && bmain && reports)) {
|
||||
return nullptr;
|
||||
}
|
||||
AssetTemporaryIDConsumer *consumer = reinterpret_cast<AssetTemporaryIDConsumer *>(consumer_);
|
||||
|
||||
if (ID *local_id = consumer->get_local_id()) {
|
||||
return local_id;
|
||||
}
|
||||
return consumer->import_id(*asset_library, id_type, *bmain, *reports);
|
||||
}
|
||||
|
563
source/blender/editors/asset/asset_list.cc
Normal file
563
source/blender/editors/asset/asset_list.cc
Normal file
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup edasset
|
||||
*
|
||||
* Abstractions to manage runtime asset lists with a global cache for multiple UI elements to
|
||||
* access.
|
||||
* Internally this uses the #FileList API and structures from `filelist.c`. This is just because it
|
||||
* contains most necessary logic already and there's not much time for a more long-term solution.
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_fileselect.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* XXX uses private header of file-space. */
|
||||
#include "../space_file/filelist.h"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
/**
|
||||
* Wrapper to add logic to the AssetLibraryReference DNA struct.
|
||||
*/
|
||||
class AssetLibraryReferenceWrapper {
|
||||
const AssetLibraryReference &reference_;
|
||||
|
||||
public:
|
||||
/* Intentionally not `explicit`, allow implicit conversion for convienience. Might have to be
|
||||
* NOLINT */
|
||||
AssetLibraryReferenceWrapper(const AssetLibraryReference &reference);
|
||||
~AssetLibraryReferenceWrapper() = default;
|
||||
|
||||
friend bool operator==(const AssetLibraryReferenceWrapper &a,
|
||||
const AssetLibraryReferenceWrapper &b);
|
||||
uint64_t hash() const;
|
||||
};
|
||||
|
||||
AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryReference &reference)
|
||||
: reference_(reference)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b)
|
||||
{
|
||||
return (a.reference_.type == b.reference_.type) && (a.reference_.type == ASSET_LIBRARY_CUSTOM) ?
|
||||
(a.reference_.custom_library_index == b.reference_.custom_library_index) :
|
||||
true;
|
||||
}
|
||||
|
||||
uint64_t AssetLibraryReferenceWrapper::hash() const
|
||||
{
|
||||
uint64_t hash1 = DefaultHash<decltype(reference_.type)>{}(reference_.type);
|
||||
if (reference_.type != ASSET_LIBRARY_CUSTOM) {
|
||||
return hash1;
|
||||
}
|
||||
|
||||
uint64_t hash2 = DefaultHash<decltype(reference_.custom_library_index)>{}(
|
||||
reference_.custom_library_index);
|
||||
return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Asset list API
|
||||
*
|
||||
* Internally re-uses #FileList from the File Browser. It does all the heavy lifting already.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* RAII wrapper for `FileList`
|
||||
*/
|
||||
class FileListWrapper : NonCopyable {
|
||||
static void filelist_free_fn(FileList *list)
|
||||
{
|
||||
filelist_free(list);
|
||||
MEM_freeN(list);
|
||||
}
|
||||
|
||||
std::unique_ptr<FileList, decltype(&filelist_free_fn)> file_list_;
|
||||
|
||||
public:
|
||||
explicit FileListWrapper(eFileSelectType filesel_type)
|
||||
: file_list_(filelist_new(filesel_type), filelist_free_fn)
|
||||
{
|
||||
}
|
||||
FileListWrapper(FileListWrapper &&other) = default;
|
||||
FileListWrapper &operator=(FileListWrapper &&other) = default;
|
||||
~FileListWrapper()
|
||||
{
|
||||
/* Destructs the owned pointer. */
|
||||
file_list_ = nullptr;
|
||||
}
|
||||
|
||||
operator FileList *() const
|
||||
{
|
||||
return file_list_.get();
|
||||
}
|
||||
};
|
||||
|
||||
class PreviewTimer : NonCopyable {
|
||||
/* Non-owning! The Window-Manager registers and owns this. */
|
||||
wmTimer *timer_ = nullptr;
|
||||
|
||||
public:
|
||||
void ensureRunning(const bContext *C)
|
||||
{
|
||||
if (!timer_) {
|
||||
timer_ = WM_event_add_timer_notifier(
|
||||
CTX_wm_manager(C), CTX_wm_window(C), NC_ASSET | ND_ASSET_LIST_PREVIEW, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
void stop(const bContext *C)
|
||||
{
|
||||
if (timer_) {
|
||||
WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), timer_);
|
||||
timer_ = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class AssetList : NonCopyable {
|
||||
FileListWrapper filelist_;
|
||||
AssetLibraryReference library_ref_;
|
||||
PreviewTimer previews_timer_;
|
||||
|
||||
public:
|
||||
AssetList() = delete;
|
||||
AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref);
|
||||
AssetList(AssetList &&other) = default;
|
||||
~AssetList() = default;
|
||||
|
||||
void setup(const AssetFilterSettings *filter_settings = nullptr);
|
||||
void fetch(const bContext &C);
|
||||
void ensurePreviewsJob(bContext *C);
|
||||
|
||||
bool needsRefetch() const;
|
||||
void iterate(AssetListIterFn fn) const;
|
||||
bool listen(const wmNotifier ¬ifier) const;
|
||||
void tagMainDataDirty() const;
|
||||
void remapID(ID *id_old, ID *id_new) const;
|
||||
StringRef filepath() const;
|
||||
};
|
||||
|
||||
AssetList::AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref)
|
||||
: filelist_(filesel_type), library_ref_(asset_library_ref)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetList::setup(const AssetFilterSettings *filter_settings)
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
|
||||
/* TODO there should only be one (FileSelectAssetLibraryUID vs. AssetLibraryReference). */
|
||||
FileSelectAssetLibraryUID file_asset_lib_ref;
|
||||
file_asset_lib_ref.type = library_ref_.type;
|
||||
file_asset_lib_ref.custom_library_index = library_ref_.custom_library_index;
|
||||
|
||||
bUserAssetLibrary *user_library = nullptr;
|
||||
|
||||
/* Ensure valid repository, or fall-back to local one. */
|
||||
if (library_ref_.type == ASSET_LIBRARY_CUSTOM) {
|
||||
BLI_assert(library_ref_.custom_library_index >= 0);
|
||||
|
||||
user_library = BKE_preferences_asset_library_find_from_index(
|
||||
&U, library_ref_.custom_library_index);
|
||||
}
|
||||
|
||||
/* Relevant bits from file_refresh(). */
|
||||
/* TODO pass options properly. */
|
||||
filelist_setrecursion(files, 1);
|
||||
filelist_setsorting(files, FILE_SORT_ALPHA, false);
|
||||
filelist_setlibrary(files, &file_asset_lib_ref);
|
||||
/* TODO different filtering settings require the list to be reread. That's a no-go for when we
|
||||
* want to allow showing the same asset library with different filter settings (as in,
|
||||
* different ID types). The filelist needs to be made smarter somehow, maybe goes together with
|
||||
* the plan to separate the view (preview caching, filtering, etc. ) from the data. */
|
||||
filelist_setfilter_options(
|
||||
files,
|
||||
filter_settings != nullptr,
|
||||
true,
|
||||
true, /* Just always hide parent, prefer to not add an extra user option for this. */
|
||||
FILE_TYPE_BLENDERLIB,
|
||||
filter_settings ? filter_settings->id_types : FILTER_ID_ALL,
|
||||
true,
|
||||
"",
|
||||
"");
|
||||
|
||||
char path[FILE_MAXDIR] = "";
|
||||
if (user_library) {
|
||||
BLI_strncpy(path, user_library->path, sizeof(path));
|
||||
filelist_setdir(files, path);
|
||||
}
|
||||
else {
|
||||
filelist_setdir(files, path);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetList::fetch(const bContext &C)
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
|
||||
if (filelist_needs_force_reset(files)) {
|
||||
filelist_readjob_stop(files, CTX_wm_manager(&C));
|
||||
filelist_clear(files);
|
||||
}
|
||||
|
||||
if (filelist_needs_reading(files)) {
|
||||
if (!filelist_pending(files)) {
|
||||
filelist_readjob_start(files, NC_ASSET | ND_ASSET_LIST_READING, &C);
|
||||
}
|
||||
}
|
||||
filelist_sort(files);
|
||||
filelist_filter(files);
|
||||
}
|
||||
|
||||
bool AssetList::needsRefetch() const
|
||||
{
|
||||
return filelist_needs_force_reset(filelist_);
|
||||
}
|
||||
|
||||
void AssetList::iterate(AssetListIterFn fn) const
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
int numfiles = filelist_files_ensure(files);
|
||||
|
||||
for (int i = 0; i < numfiles; i++) {
|
||||
FileDirEntry *file = filelist_file(files, i);
|
||||
if (!fn(*file)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetList::ensurePreviewsJob(bContext *C)
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
int numfiles = filelist_files_ensure(files);
|
||||
|
||||
filelist_cache_previews_set(files, true);
|
||||
filelist_file_cache_slidingwindow_set(files, 256);
|
||||
/* TODO fetch all previews for now. */
|
||||
filelist_file_cache_block(files, numfiles / 2);
|
||||
filelist_cache_previews_update(files);
|
||||
|
||||
{
|
||||
const bool previews_running = filelist_cache_previews_running(files);
|
||||
if (previews_running) {
|
||||
previews_timer_.ensureRunning(C);
|
||||
}
|
||||
else {
|
||||
/* Preview is not running, no need to keep generating update events! */
|
||||
previews_timer_.stop(C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \return True if the asset-list needs a UI redraw.
|
||||
*/
|
||||
bool AssetList::listen(const wmNotifier ¬ifier) const
|
||||
{
|
||||
switch (notifier.category) {
|
||||
case NC_ASSET:
|
||||
if (ELEM(notifier.data, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
|
||||
return true;
|
||||
}
|
||||
if (ELEM(notifier.action, NA_ADDED, NA_REMOVED)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AssetList::tagMainDataDirty() const
|
||||
{
|
||||
if (filelist_needs_reset_on_main_changes(filelist_)) {
|
||||
/* Full refresh of the file list if local asset data was changed. Refreshing this view
|
||||
* is cheap and users expect this to be updated immediately. */
|
||||
filelist_tag_force_reset(filelist_);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetList::remapID(ID * /*id_old*/, ID * /*id_new*/) const
|
||||
{
|
||||
/* Trigger full refetch of the file list if main data was changed, don't even attempt remap
|
||||
* pointers. We could give file list types a id-remap callback, but it's probably not worth it.
|
||||
* Refreshing local file lists is relatively cheap. */
|
||||
tagMainDataDirty();
|
||||
}
|
||||
|
||||
StringRef AssetList::filepath() const
|
||||
{
|
||||
return filelist_dir(filelist_);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Runtime asset list cache
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Class managing a global asset list map, each entry being a list for a specific asset library.
|
||||
*/
|
||||
class AssetListStorage {
|
||||
using AssetListMap = Map<AssetLibraryReferenceWrapper, AssetList>;
|
||||
|
||||
public:
|
||||
/* Purely static class, can't instantiate this. */
|
||||
AssetListStorage() = delete;
|
||||
|
||||
static void fetch_library(const AssetLibraryReference &library_reference,
|
||||
const bContext &C,
|
||||
const AssetFilterSettings *filter_settings = nullptr);
|
||||
static void destruct();
|
||||
static AssetList *lookup_list(const AssetLibraryReference &library_ref);
|
||||
static void tagMainDataDirty();
|
||||
static void remapID(ID *id_new, ID *id_old);
|
||||
|
||||
private:
|
||||
static std::optional<eFileSelectType> asset_library_reference_to_fileselect_type(
|
||||
const AssetLibraryReference &library_reference);
|
||||
|
||||
using is_new_t = bool;
|
||||
static std::tuple<AssetList &, is_new_t> ensure_list_storage(
|
||||
const AssetLibraryReference &library_reference, eFileSelectType filesel_type);
|
||||
|
||||
static AssetListMap &global_storage();
|
||||
};
|
||||
|
||||
void AssetListStorage::fetch_library(const AssetLibraryReference &library_reference,
|
||||
const bContext &C,
|
||||
const AssetFilterSettings *filter_settings)
|
||||
{
|
||||
std::optional filesel_type = asset_library_reference_to_fileselect_type(library_reference);
|
||||
if (!filesel_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::tuple list_create_info = ensure_list_storage(library_reference, *filesel_type);
|
||||
AssetList &list = std::get<0>(list_create_info);
|
||||
const bool is_new = std::get<1>(list_create_info);
|
||||
if (is_new || list.needsRefetch()) {
|
||||
list.setup(filter_settings);
|
||||
list.fetch(C);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetListStorage::destruct()
|
||||
{
|
||||
global_storage().~AssetListMap();
|
||||
}
|
||||
|
||||
AssetList *AssetListStorage::lookup_list(const AssetLibraryReference &library_ref)
|
||||
{
|
||||
return global_storage().lookup_ptr(library_ref);
|
||||
}
|
||||
|
||||
void AssetListStorage::tagMainDataDirty()
|
||||
{
|
||||
for (AssetList &list : global_storage().values()) {
|
||||
list.tagMainDataDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetListStorage::remapID(ID *id_new, ID *id_old)
|
||||
{
|
||||
for (AssetList &list : global_storage().values()) {
|
||||
list.remapID(id_new, id_old);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<eFileSelectType> AssetListStorage::asset_library_reference_to_fileselect_type(
|
||||
const AssetLibraryReference &library_reference)
|
||||
{
|
||||
switch (library_reference.type) {
|
||||
case ASSET_LIBRARY_CUSTOM:
|
||||
return FILE_LOADLIB;
|
||||
case ASSET_LIBRARY_LOCAL:
|
||||
return FILE_MAIN_ASSET;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::tuple<AssetList &, AssetListStorage::is_new_t> AssetListStorage::ensure_list_storage(
|
||||
const AssetLibraryReference &library_reference, eFileSelectType filesel_type)
|
||||
{
|
||||
AssetListMap &storage = global_storage();
|
||||
|
||||
if (AssetList *list = storage.lookup_ptr(library_reference)) {
|
||||
return {*list, false};
|
||||
}
|
||||
storage.add(library_reference, AssetList(filesel_type, library_reference));
|
||||
return {storage.lookup(library_reference), true};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for Construct on First Use idiom, to avoid the Static Initialization Fiasco.
|
||||
*/
|
||||
AssetListStorage::AssetListMap &AssetListStorage::global_storage()
|
||||
{
|
||||
static AssetListMap global_storage_;
|
||||
return global_storage_;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name C-API
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Invoke asset list reading, potentially in a parallel job. Won't wait until the job is done,
|
||||
* and may return earlier.
|
||||
*/
|
||||
void ED_assetlist_storage_fetch(const AssetLibraryReference *library_reference,
|
||||
const AssetFilterSettings *filter_settings,
|
||||
const bContext *C)
|
||||
{
|
||||
AssetListStorage::fetch_library(*library_reference, *C, filter_settings);
|
||||
}
|
||||
|
||||
void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference, bContext *C)
|
||||
{
|
||||
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
list->ensurePreviewsJob(C);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO expose AssetList with an iterator? */
|
||||
void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
list->iterate(fn);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ED_assetlist_asset_filepath_get(const AssetLibraryReference &library_reference,
|
||||
const AssetHandle &asset_handle)
|
||||
{
|
||||
if (asset_handle.file_data->id || !asset_handle.file_data->asset_data) {
|
||||
return nullptr;
|
||||
}
|
||||
const char *library_path = ED_assetlist_library_path(&library_reference);
|
||||
if (!library_path) {
|
||||
return nullptr;
|
||||
}
|
||||
const char *asset_relpath = asset_handle.file_data->relpath;
|
||||
|
||||
char path[FILE_MAX_LIBEXTRA];
|
||||
BLI_join_dirfile(path, sizeof(path), library_path, asset_relpath);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
ID *ED_assetlist_asset_local_id_get(const AssetHandle *asset_handle)
|
||||
{
|
||||
return asset_handle->file_data->asset_data ? asset_handle->file_data->id : nullptr;
|
||||
}
|
||||
|
||||
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||
{
|
||||
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
||||
if (imbuf) {
|
||||
return imbuf;
|
||||
}
|
||||
|
||||
return filelist_geticon_image_ex(asset_handle->file_data);
|
||||
}
|
||||
|
||||
const char *ED_assetlist_library_path(const AssetLibraryReference *library_reference)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
return list->filepath().data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return True if the region needs a UI redraw.
|
||||
*/
|
||||
bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
|
||||
const wmNotifier *notifier)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
return list->listen(*notifier);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag all asset lists in the storage that show main data as needing an update (refetch).
|
||||
*
|
||||
* This only tags the data. If the asset list is visible on screen, the space is still responsible
|
||||
* for ensuring the necessary redraw. It can use #ED_assetlist_listen() to check if the asset-list
|
||||
* needs a redraw for a given notifier.
|
||||
*/
|
||||
void ED_assetlist_storage_tag_main_data_dirty()
|
||||
{
|
||||
AssetListStorage::tagMainDataDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remapping of ID pointers within the asset lists. Typically called when an ID is deleted to clear
|
||||
* all references to it (\a id_new is null then).
|
||||
*/
|
||||
void ED_assetlist_storage_id_remap(ID *id_old, ID *id_new)
|
||||
{
|
||||
AssetListStorage::remapID(id_old, id_new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can't wait for static deallocation to run. There's nested data allocated with our guarded
|
||||
* allocator, it will complain about unfreed memory on exit.
|
||||
*/
|
||||
void ED_assetlist_storage_exit()
|
||||
{
|
||||
AssetListStorage::destruct();
|
||||
}
|
||||
|
||||
/** \} */
|
@@ -20,17 +20,67 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_ID_enums.h"
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AssetFilterSettings;
|
||||
struct AssetLibraryReference;
|
||||
struct bContext;
|
||||
struct Main;
|
||||
struct ReportList;
|
||||
struct wmNotifier;
|
||||
|
||||
typedef struct AssetTempIDConsumer AssetTempIDConsumer;
|
||||
|
||||
bool ED_asset_mark_id(const struct bContext *C, struct ID *id);
|
||||
bool ED_asset_clear_id(struct ID *id);
|
||||
|
||||
bool ED_asset_can_make_single_from_context(const struct bContext *C);
|
||||
|
||||
int ED_asset_library_reference_to_enum_value(const struct AssetLibraryReference *library);
|
||||
struct AssetLibraryReference ED_asset_library_reference_from_enum_value(int value);
|
||||
|
||||
AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle);
|
||||
void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer);
|
||||
struct ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer,
|
||||
const AssetLibraryReference *asset_library,
|
||||
ID_Type id_type,
|
||||
struct Main *bmain,
|
||||
struct ReportList *reports);
|
||||
|
||||
void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference,
|
||||
const struct AssetFilterSettings *filter_settings,
|
||||
const struct bContext *C);
|
||||
void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference,
|
||||
struct bContext *C);
|
||||
void ED_assetlist_storage_tag_main_data_dirty(void);
|
||||
void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
|
||||
void ED_assetlist_storage_exit(void);
|
||||
|
||||
ID *ED_assetlist_asset_local_id_get(const AssetHandle *asset_handle);
|
||||
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
||||
const char *ED_assetlist_library_path(const struct AssetLibraryReference *library_reference);
|
||||
|
||||
bool ED_assetlist_listen(const struct AssetLibraryReference *library_reference,
|
||||
const struct wmNotifier *notifier);
|
||||
|
||||
void ED_operatortypes_asset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO move to C++ asset-list header? */
|
||||
#ifdef __cplusplus
|
||||
std::string ED_assetlist_asset_filepath_get(const AssetLibraryReference &library_reference,
|
||||
const AssetHandle &asset_handle);
|
||||
|
||||
# include "BLI_function_ref.hh"
|
||||
/* Can return false to stop iterating. */
|
||||
using AssetListIterFn = blender::FunctionRef<bool(FileDirEntry &)>;
|
||||
void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn);
|
||||
#endif
|
||||
|
@@ -136,13 +136,9 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
|
||||
|
||||
void ED_operatormacros_file(void);
|
||||
|
||||
void ED_fileselect_clear(struct wmWindowManager *wm,
|
||||
struct Scene *owner_scene,
|
||||
struct SpaceFile *sfile);
|
||||
void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile);
|
||||
|
||||
void ED_fileselect_exit(struct wmWindowManager *wm,
|
||||
struct Scene *owner_scene,
|
||||
struct SpaceFile *sfile);
|
||||
void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile);
|
||||
|
||||
bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile);
|
||||
struct ID *ED_fileselect_active_asset_get(const struct SpaceFile *sfile);
|
||||
@@ -166,7 +162,7 @@ int ED_file_icon(const struct FileDirEntry *file);
|
||||
|
||||
void ED_file_read_bookmarks(void);
|
||||
|
||||
void ED_file_change_dir_ex(struct bContext *C, struct bScreen *screen, struct ScrArea *area);
|
||||
void ED_file_change_dir_ex(struct bContext *C, struct ScrArea *area);
|
||||
void ED_file_change_dir(struct bContext *C);
|
||||
|
||||
void ED_file_path_button(struct bScreen *screen,
|
||||
|
@@ -34,6 +34,7 @@ extern "C" {
|
||||
/* Struct Declarations */
|
||||
|
||||
struct ARegion;
|
||||
struct AssetFilterSettings;
|
||||
struct AutoComplete;
|
||||
struct EnumPropertyItem;
|
||||
struct FileSelectParams;
|
||||
@@ -375,6 +376,9 @@ typedef enum {
|
||||
/** Buttons with value >= #UI_BTYPE_SEARCH_MENU don't get undo pushes. */
|
||||
UI_BTYPE_SEARCH_MENU = 41 << 9,
|
||||
UI_BTYPE_EXTRA = 42 << 9,
|
||||
/** A preview image (#PreviewImage), with text under it. Typically bigger than normal buttons and
|
||||
* laid out in a grid, e.g. like the File Browser in thumbnail display mode. */
|
||||
UI_BTYPE_PREVIEW_TILE = 43 << 9,
|
||||
UI_BTYPE_HOTKEY_EVENT = 46 << 9,
|
||||
/** Non-interactive image, used for splash screen */
|
||||
UI_BTYPE_IMAGE = 47 << 9,
|
||||
@@ -2159,6 +2163,22 @@ void uiTemplateList(uiLayout *layout,
|
||||
int columns,
|
||||
bool sort_reverse,
|
||||
bool sort_lock);
|
||||
struct uiList *uiTemplateList_ex(uiLayout *layout,
|
||||
struct bContext *C,
|
||||
const char *listtype_name,
|
||||
const char *list_id,
|
||||
struct PointerRNA *dataptr,
|
||||
const char *propname,
|
||||
struct PointerRNA *active_dataptr,
|
||||
const char *active_propname,
|
||||
const char *item_dyntip_propname,
|
||||
int rows,
|
||||
int maxrows,
|
||||
int layout_type,
|
||||
int columns,
|
||||
bool sort_reverse,
|
||||
bool sort_lock,
|
||||
void *customdata);
|
||||
void uiTemplateNodeLink(uiLayout *layout,
|
||||
struct bContext *C,
|
||||
struct bNodeTree *ntree,
|
||||
@@ -2204,6 +2224,18 @@ int uiTemplateRecentFiles(struct uiLayout *layout, int rows);
|
||||
void uiTemplateFileSelectPath(uiLayout *layout,
|
||||
struct bContext *C,
|
||||
struct FileSelectParams *params);
|
||||
void uiTemplateAssetView(struct uiLayout *layout,
|
||||
struct bContext *C,
|
||||
const char *list_id,
|
||||
struct PointerRNA *asset_library_dataptr,
|
||||
const char *asset_library_propname,
|
||||
struct PointerRNA *assets_dataptr,
|
||||
const char *assets_propname,
|
||||
struct PointerRNA *active_dataptr,
|
||||
const char *active_propname,
|
||||
const struct AssetFilterSettings *filter_settings,
|
||||
const char *activate_opname,
|
||||
const char *drag_opname);
|
||||
|
||||
/* items */
|
||||
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname);
|
||||
@@ -2457,6 +2489,7 @@ typedef struct uiDragColorHandle {
|
||||
|
||||
void ED_operatortypes_ui(void);
|
||||
void ED_keymap_ui(struct wmKeyConfig *keyconf);
|
||||
void ED_uilisttypes_ui(void);
|
||||
|
||||
void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
|
||||
bool UI_drop_color_poll(struct bContext *C,
|
||||
|
@@ -105,7 +105,10 @@ int UI_iconfile_get_index(const char *filename);
|
||||
|
||||
struct PreviewImage *UI_icon_to_preview(int icon_id);
|
||||
|
||||
int UI_icon_from_rnaptr(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
|
||||
int UI_icon_from_rnaptr(const struct bContext *C,
|
||||
struct PointerRNA *ptr,
|
||||
int rnaicon,
|
||||
const bool big);
|
||||
int UI_icon_from_idcode(const int idcode);
|
||||
int UI_icon_from_library(const struct ID *id);
|
||||
int UI_icon_from_object_mode(const int mode);
|
||||
|
@@ -66,6 +66,7 @@ set(SRC
|
||||
interface_region_tooltip.c
|
||||
interface_regions.c
|
||||
interface_style.c
|
||||
interface_template_asset_view.cc
|
||||
interface_template_search_menu.c
|
||||
interface_template_search_operator.c
|
||||
interface_templates.c
|
||||
|
@@ -714,15 +714,24 @@ static uiAfterFunc *ui_afterfunc_new(void)
|
||||
* For executing operators after the button is pressed.
|
||||
* (some non operator buttons need to trigger operators), see: T37795.
|
||||
*
|
||||
* \param context_but: A button from which to get the context from (`uiBut.context`) for the
|
||||
* operator execution.
|
||||
*
|
||||
* \note Can only call while handling buttons.
|
||||
*/
|
||||
PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, bool create_props)
|
||||
static PointerRNA *ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot,
|
||||
int opcontext,
|
||||
bool create_props,
|
||||
const uiBut *context_but)
|
||||
{
|
||||
PointerRNA *ptr = NULL;
|
||||
uiAfterFunc *after = ui_afterfunc_new();
|
||||
|
||||
after->optype = ot;
|
||||
after->opcontext = opcontext;
|
||||
if (context_but && context_but->context) {
|
||||
after->context = CTX_store_copy(context_but->context);
|
||||
}
|
||||
|
||||
if (create_props) {
|
||||
ptr = MEM_callocN(sizeof(PointerRNA), __func__);
|
||||
@@ -733,6 +742,11 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
|
||||
return ptr;
|
||||
}
|
||||
|
||||
PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, bool create_props)
|
||||
{
|
||||
return ui_handle_afterfunc_add_operator_ex(ot, opcontext, create_props, NULL);
|
||||
}
|
||||
|
||||
static void popup_check(bContext *C, wmOperator *op)
|
||||
{
|
||||
if (op && op->type->check) {
|
||||
@@ -1057,6 +1071,43 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
|
||||
data->applied = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns true if the operator was executed, otherwise false.
|
||||
*/
|
||||
static bool ui_list_invoke_item_operator(bContext *C,
|
||||
const ARegion *region,
|
||||
const wmEvent *event,
|
||||
const char *name)
|
||||
{
|
||||
wmOperatorType *drag_ot = WM_operatortype_find(name, false);
|
||||
const uiBut *hovered_but = ui_but_find_mouse_over(region, event);
|
||||
|
||||
if (!ui_but_context_poll_operator(C, drag_ot, hovered_but)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allow the context to be set from the hovered button, so the list item draw callback can set
|
||||
* context for the operators. */
|
||||
ui_handle_afterfunc_add_operator_ex(drag_ot, WM_OP_INVOKE_DEFAULT, false, hovered_but);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ui_apply_but_LISTROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
|
||||
{
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
|
||||
uiBut *listbox = ui_list_find_mouse_over(data->region, window->eventstate);
|
||||
if (listbox) {
|
||||
uiList *list = listbox->custom_data;
|
||||
if (list && list->custom_activate_opname) {
|
||||
ui_list_invoke_item_operator(
|
||||
C, data->region, window->eventstate, list->custom_activate_opname);
|
||||
}
|
||||
}
|
||||
|
||||
ui_apply_but_ROW(C, block, but, data);
|
||||
}
|
||||
|
||||
static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
|
||||
{
|
||||
if (!data->str) {
|
||||
@@ -1525,7 +1576,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
|
||||
*/
|
||||
if (drag_info->is_xy_lock_init == false) {
|
||||
/* first store the buttons original coords */
|
||||
uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true);
|
||||
uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true, NULL);
|
||||
|
||||
if (but) {
|
||||
if (but->flag & UI_BUT_DRAG_LOCK) {
|
||||
@@ -1596,7 +1647,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
const ARegion *region = CTX_wm_region(C);
|
||||
uiBut *but = ui_but_find_mouse_over_ex(
|
||||
region, drag_info->xy_init[0], drag_info->xy_init[1], true);
|
||||
region, drag_info->xy_init[0], drag_info->xy_init[1], true, NULL);
|
||||
|
||||
if (but) {
|
||||
ui_apply_but_undo(but);
|
||||
@@ -2158,9 +2209,11 @@ static void ui_apply_but(
|
||||
ui_apply_but_TOG(C, but, data);
|
||||
break;
|
||||
case UI_BTYPE_ROW:
|
||||
case UI_BTYPE_LISTROW:
|
||||
ui_apply_but_ROW(C, block, but, data);
|
||||
break;
|
||||
case UI_BTYPE_LISTROW:
|
||||
ui_apply_but_LISTROW(C, block, but, data);
|
||||
break;
|
||||
case UI_BTYPE_TAB:
|
||||
ui_apply_but_TAB(C, but, data);
|
||||
break;
|
||||
@@ -4165,7 +4218,7 @@ static uiBut *ui_but_list_row_text_activate(bContext *C,
|
||||
uiButtonActivateType activate_type)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true);
|
||||
uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true, NULL);
|
||||
|
||||
if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) {
|
||||
/* exit listrow */
|
||||
@@ -4659,6 +4712,15 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
|
||||
if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) {
|
||||
ret = WM_UI_HANDLER_CONTINUE;
|
||||
}
|
||||
/* Same special case handling for UI lists. Return CONTINUE so that a tweak or CLICK event
|
||||
* will be sent for the list to work with. */
|
||||
const uiBut *listbox = ui_list_find_mouse_over(data->region, event);
|
||||
if (listbox) {
|
||||
const uiList *ui_list = listbox->custom_data;
|
||||
if (ui_list && ui_list->custom_drag_opname) {
|
||||
ret = WM_UI_HANDLER_CONTINUE;
|
||||
}
|
||||
}
|
||||
button_activate_state(C, but, BUTTON_STATE_EXIT);
|
||||
return ret;
|
||||
}
|
||||
@@ -7683,6 +7745,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
|
||||
case UI_BTYPE_IMAGE:
|
||||
case UI_BTYPE_PROGRESS_BAR:
|
||||
case UI_BTYPE_NODE_SOCKET:
|
||||
case UI_BTYPE_PREVIEW_TILE:
|
||||
retval = ui_do_but_EXIT(C, but, data, event);
|
||||
break;
|
||||
case UI_BTYPE_HISTOGRAM:
|
||||
@@ -9017,6 +9080,109 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool ui_but_is_listrow(const uiBut *but)
|
||||
{
|
||||
return but->type == UI_BTYPE_LISTROW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the underlying list-row button, so the row is highlighted.
|
||||
* Early exits if \a activate_dragging is true, but the custom drag operator fails to execute.
|
||||
* Gives the wanted behavior where the item is activated on a tweak event when the custom drag
|
||||
* operator is executed.
|
||||
*/
|
||||
static int ui_list_activate_hovered_row(bContext *C,
|
||||
ARegion *region,
|
||||
const uiList *ui_list,
|
||||
const wmEvent *event,
|
||||
bool activate_dragging)
|
||||
{
|
||||
const bool do_drag = activate_dragging && ui_list->custom_drag_opname;
|
||||
|
||||
if (do_drag) {
|
||||
if (!ui_list_invoke_item_operator(C, region, event, ui_list->custom_drag_opname)) {
|
||||
return WM_UI_HANDLER_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x;
|
||||
uiBut *listrow = ui_but_find_mouse_over_ex(
|
||||
region, mouse_xy[0], mouse_xy[1], false, ui_but_is_listrow);
|
||||
if (listrow) {
|
||||
const char *custom_activate_opname = ui_list->custom_activate_opname;
|
||||
|
||||
/* Hacky: Ensure the custom activate operator is not called when the custom drag operator was.
|
||||
* Only one should run! */
|
||||
if (activate_dragging && do_drag) {
|
||||
((uiList *)ui_list)->custom_activate_opname = NULL;
|
||||
}
|
||||
|
||||
/* Simulate click on listrow button itself (which may be overlapped by another button). Also
|
||||
* calls the custom activate operator (ui_list->custom_activate_opname). */
|
||||
UI_but_execute(C, region, listrow);
|
||||
|
||||
((uiList *)ui_list)->custom_activate_opname = custom_activate_opname;
|
||||
}
|
||||
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
|
||||
static bool ui_list_is_hovering_draggable_but(bContext *C,
|
||||
const uiList *list,
|
||||
const ARegion *region,
|
||||
const wmEvent *event)
|
||||
{
|
||||
/* On a tweak event, uses the coordinates from where tweaking was started. */
|
||||
const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x;
|
||||
const uiBut *hovered_but = ui_but_find_mouse_over_ex(
|
||||
region, mouse_xy[0], mouse_xy[1], false, NULL);
|
||||
|
||||
if (list->custom_drag_opname) {
|
||||
wmOperatorType *drag_ot = WM_operatortype_find(list->custom_drag_opname, false);
|
||||
if (ui_but_context_poll_operator(C, drag_ot, hovered_but)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (hovered_but && hovered_but->dragpoin);
|
||||
}
|
||||
|
||||
static int ui_list_handle_click_drag(bContext *C,
|
||||
const uiList *ui_list,
|
||||
ARegion *region,
|
||||
const wmEvent *event)
|
||||
{
|
||||
if (!ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) {
|
||||
return WM_HANDLER_CONTINUE;
|
||||
}
|
||||
|
||||
int retval = WM_HANDLER_CONTINUE;
|
||||
|
||||
const bool is_draggable = ui_list_is_hovering_draggable_but(C, ui_list, region, event);
|
||||
bool activate = false;
|
||||
bool activate_dragging = false;
|
||||
|
||||
if (event->type == EVT_TWEAK_L) {
|
||||
if (is_draggable) {
|
||||
activate_dragging = true;
|
||||
activate = true;
|
||||
}
|
||||
}
|
||||
/* KM_CLICK is only sent after an uncaught release event, so the forground button gets all
|
||||
* regular events (including mouse presses to start dragging) and this part only kicks in if it
|
||||
* hasn't handled the release event. Note that if there's no overlaid button, the row selects
|
||||
* on the press event already via regular UI_BTYPE_LISTROW handling. */
|
||||
else if ((event->type == LEFTMOUSE) && (event->val == KM_CLICK)) {
|
||||
activate = true;
|
||||
}
|
||||
|
||||
if (activate) {
|
||||
retval = ui_list_activate_hovered_row(C, region, ui_list, event, activate_dragging);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *region, uiBut *listbox)
|
||||
{
|
||||
int retval = WM_UI_HANDLER_CONTINUE;
|
||||
@@ -9050,7 +9216,10 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi
|
||||
}
|
||||
}
|
||||
|
||||
if (val == KM_PRESS) {
|
||||
if (ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) {
|
||||
retval = ui_list_handle_click_drag(C, ui_list, region, event);
|
||||
}
|
||||
else if (val == KM_PRESS) {
|
||||
if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY) &&
|
||||
!IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) ||
|
||||
((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl &&
|
||||
|
@@ -2205,7 +2205,7 @@ int UI_icon_from_library(const ID *id)
|
||||
return ICON_NONE;
|
||||
}
|
||||
|
||||
int UI_icon_from_rnaptr(bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
|
||||
int UI_icon_from_rnaptr(const bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
|
||||
{
|
||||
ID *id = NULL;
|
||||
|
||||
|
@@ -1024,8 +1024,18 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle,
|
||||
int state,
|
||||
uiMenuItemSeparatorType separator_type,
|
||||
int *r_xmax);
|
||||
void ui_draw_preview_item(
|
||||
const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
|
||||
void ui_draw_preview_item(const struct uiFontStyle *fstyle,
|
||||
rcti *rect,
|
||||
const char *name,
|
||||
int iconid,
|
||||
int state,
|
||||
eFontStyle_Align text_align);
|
||||
void ui_draw_preview_item_stateless(const struct uiFontStyle *fstyle,
|
||||
rcti *rect,
|
||||
const char *name,
|
||||
int iconid,
|
||||
const uchar text_col[4],
|
||||
eFontStyle_Align text_align);
|
||||
|
||||
#define UI_TEXT_MARGIN_X 0.4f
|
||||
#define UI_POPUP_MARGIN (UI_DPI_FAC * 12)
|
||||
@@ -1110,10 +1120,12 @@ bool ui_but_contains_point_px(const uiBut *but, const struct ARegion *region, in
|
||||
uiBut *ui_list_find_mouse_over(struct ARegion *region,
|
||||
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
typedef bool (*uiButFindPoll)(const uiBut *but);
|
||||
uiBut *ui_but_find_mouse_over_ex(const struct ARegion *region,
|
||||
const int x,
|
||||
const int y,
|
||||
const bool labeledit) ATTR_WARN_UNUSED_RESULT;
|
||||
const bool labeledit,
|
||||
uiButFindPoll find_poll) ATTR_WARN_UNUSED_RESULT;
|
||||
uiBut *ui_but_find_mouse_over(const struct ARegion *region,
|
||||
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
|
||||
uiBut *ui_but_find_rect_over(const struct ARegion *region,
|
||||
|
@@ -265,10 +265,8 @@ bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEv
|
||||
}
|
||||
|
||||
/* x and y are only used in case event is NULL... */
|
||||
uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
|
||||
const int x,
|
||||
const int y,
|
||||
const bool labeledit)
|
||||
uiBut *ui_but_find_mouse_over_ex(
|
||||
const ARegion *region, const int x, const int y, const bool labeledit, uiButFindPoll find_poll)
|
||||
{
|
||||
uiBut *butover = NULL;
|
||||
|
||||
@@ -280,6 +278,9 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
|
||||
ui_window_to_block_fl(region, block, &mx, &my);
|
||||
|
||||
LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) {
|
||||
if (find_poll && find_poll(but) == false) {
|
||||
continue;
|
||||
}
|
||||
if (ui_but_is_interactive(but, labeledit)) {
|
||||
if (but->pie_dir != UI_RADIAL_NONE) {
|
||||
if (ui_but_isect_pie_seg(block, but)) {
|
||||
@@ -308,7 +309,7 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
|
||||
|
||||
uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event)
|
||||
{
|
||||
return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0);
|
||||
return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0, NULL);
|
||||
}
|
||||
|
||||
uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
|
||||
|
@@ -599,8 +599,12 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
|
||||
ui_searchbox_butrect(&rect, data, a);
|
||||
|
||||
/* widget itself */
|
||||
ui_draw_preview_item(
|
||||
&data->fstyle, &rect, data->items.names[a], data->items.icons[a], state);
|
||||
ui_draw_preview_item(&data->fstyle,
|
||||
&rect,
|
||||
data->items.names[a],
|
||||
data->items.icons[a],
|
||||
state,
|
||||
UI_STYLE_TEXT_LEFT);
|
||||
}
|
||||
|
||||
/* indicate more */
|
||||
|
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup edinterface
|
||||
*/
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "interface_intern.h"
|
||||
|
||||
struct AssetViewListData {
|
||||
AssetLibraryReference asset_library;
|
||||
bScreen *screen;
|
||||
};
|
||||
|
||||
static void asset_view_item_but_drag_set(uiBut *but,
|
||||
AssetViewListData *list_data,
|
||||
AssetHandle *asset_handle)
|
||||
{
|
||||
if (ID *id = asset_handle->file_data->id) {
|
||||
UI_but_drag_set_id(but, id);
|
||||
}
|
||||
else {
|
||||
const blender::StringRef asset_list_path = ED_assetlist_library_path(
|
||||
&list_data->asset_library);
|
||||
char blend_path[FILE_MAX_LIBEXTRA];
|
||||
|
||||
char path[FILE_MAX_LIBEXTRA];
|
||||
BLI_join_dirfile(path, sizeof(path), asset_list_path.data(), asset_handle->file_data->relpath);
|
||||
if (BLO_library_path_explode(path, blend_path, nullptr, nullptr)) {
|
||||
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
|
||||
UI_but_drag_set_asset(but,
|
||||
asset_handle->file_data->name,
|
||||
BLI_strdup(blend_path),
|
||||
asset_handle->file_data->blentype,
|
||||
asset_handle->file_data->preview_icon_id,
|
||||
imbuf,
|
||||
1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void asset_view_draw_item(uiList *ui_list,
|
||||
bContext *UNUSED(C),
|
||||
uiLayout *layout,
|
||||
PointerRNA *UNUSED(dataptr),
|
||||
PointerRNA *itemptr,
|
||||
int UNUSED(icon),
|
||||
PointerRNA *UNUSED(active_dataptr),
|
||||
const char *UNUSED(active_propname),
|
||||
int UNUSED(index),
|
||||
int UNUSED(flt_flag))
|
||||
{
|
||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||
|
||||
BLI_assert(RNA_struct_is_a(itemptr->type, &RNA_AssetHandle));
|
||||
AssetHandle *asset_handle = (AssetHandle *)itemptr->data;
|
||||
|
||||
uiLayoutSetContextPointer(layout, "asset_handle", itemptr);
|
||||
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
/* TODO ED_fileselect_init_layout(). Share somehow? */
|
||||
float size_x = (96.0f / 20.0f) * UI_UNIT_X;
|
||||
float size_y = (96.0f / 20.0f) * UI_UNIT_Y;
|
||||
uiBut *but = uiDefIconTextBut(block,
|
||||
UI_BTYPE_PREVIEW_TILE,
|
||||
0,
|
||||
asset_handle->file_data->preview_icon_id,
|
||||
asset_handle->file_data->name,
|
||||
0,
|
||||
0,
|
||||
size_x,
|
||||
size_y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
ui_def_but_icon(but,
|
||||
asset_handle->file_data->preview_icon_id,
|
||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
if (!ui_list->custom_drag_opname) {
|
||||
asset_view_item_but_drag_set(but, list_data, asset_handle);
|
||||
}
|
||||
}
|
||||
|
||||
static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
|
||||
{
|
||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||
|
||||
if (ED_assetlist_listen(&list_data->asset_library, params->notifier)) {
|
||||
ED_region_tag_redraw(params->region);
|
||||
}
|
||||
}
|
||||
|
||||
static uiListType *UI_UL_asset_view()
|
||||
{
|
||||
uiListType *list_type = (uiListType *)MEM_callocN(sizeof(*list_type), __func__);
|
||||
|
||||
BLI_strncpy(list_type->idname, "UI_UL_asset_view", sizeof(list_type->idname));
|
||||
list_type->draw_item = asset_view_draw_item;
|
||||
list_type->listener = asset_view_listener;
|
||||
|
||||
return list_type;
|
||||
}
|
||||
|
||||
void ED_uilisttypes_ui()
|
||||
{
|
||||
WM_uilisttype_add(UI_UL_asset_view());
|
||||
}
|
||||
|
||||
static void asset_view_template_refresh_asset_collection(
|
||||
const AssetLibraryReference &asset_library,
|
||||
PointerRNA &assets_dataptr,
|
||||
const char *assets_propname)
|
||||
{
|
||||
PropertyRNA *assets_prop = RNA_struct_find_property(&assets_dataptr, assets_propname);
|
||||
if (!assets_prop) {
|
||||
RNA_warning("Asset collection not found");
|
||||
return;
|
||||
}
|
||||
if (!RNA_struct_is_a(RNA_property_pointer_type(&assets_dataptr, assets_prop),
|
||||
&RNA_AssetHandle)) {
|
||||
RNA_warning("Expected a collection property for AssetHandle items");
|
||||
return;
|
||||
}
|
||||
|
||||
RNA_property_collection_clear(&assets_dataptr, assets_prop);
|
||||
|
||||
ED_assetlist_iterate(&asset_library, [&](FileDirEntry &file) {
|
||||
PointerRNA itemptr, fileptr;
|
||||
RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr);
|
||||
|
||||
RNA_pointer_create(nullptr, &RNA_FileSelectEntry, &file, &fileptr);
|
||||
RNA_pointer_set(&itemptr, "file_data", fileptr);
|
||||
|
||||
/* Copy name from file to asset-handle name ID-property. */
|
||||
char name[MAX_NAME];
|
||||
PropertyRNA *file_name_prop = RNA_struct_name_property(fileptr.type);
|
||||
RNA_property_string_get(&fileptr, file_name_prop, name);
|
||||
PropertyRNA *asset_name_prop = RNA_struct_name_property(&RNA_AssetHandle);
|
||||
RNA_property_string_set(&itemptr, asset_name_prop, name);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void uiTemplateAssetView(uiLayout *layout,
|
||||
bContext *C,
|
||||
const char *list_id,
|
||||
PointerRNA *asset_library_dataptr,
|
||||
const char *asset_library_propname,
|
||||
PointerRNA *assets_dataptr,
|
||||
const char *assets_propname,
|
||||
PointerRNA *active_dataptr,
|
||||
const char *active_propname,
|
||||
const AssetFilterSettings *filter_settings,
|
||||
const char *activate_opname,
|
||||
const char *drag_opname)
|
||||
{
|
||||
if (!list_id || !list_id[0]) {
|
||||
RNA_warning("Asset view needs a valid identifier");
|
||||
return;
|
||||
}
|
||||
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
|
||||
PropertyRNA *asset_library_prop = RNA_struct_find_property(asset_library_dataptr,
|
||||
asset_library_propname);
|
||||
uiItemFullR(col, asset_library_dataptr, asset_library_prop, RNA_NO_INDEX, 0, 0, "", 0);
|
||||
|
||||
AssetLibraryReference asset_library = ED_asset_library_reference_from_enum_value(
|
||||
RNA_property_enum_get(asset_library_dataptr, asset_library_prop));
|
||||
ED_assetlist_storage_fetch(&asset_library, filter_settings, C);
|
||||
ED_assetlist_ensure_previews_job(&asset_library, C);
|
||||
|
||||
asset_view_template_refresh_asset_collection(asset_library, *assets_dataptr, assets_propname);
|
||||
|
||||
AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data),
|
||||
"AssetViewListData");
|
||||
list_data->asset_library = asset_library;
|
||||
list_data->screen = CTX_wm_screen(C);
|
||||
|
||||
/* TODO can we have some kind of model-view API to handle referencing, filtering and lazy loading
|
||||
* (of previews) of the items? */
|
||||
uiList *list = uiTemplateList_ex(col,
|
||||
C,
|
||||
"UI_UL_asset_view",
|
||||
list_id,
|
||||
assets_dataptr,
|
||||
assets_propname,
|
||||
active_dataptr,
|
||||
active_propname,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
UILST_LAYOUT_BIG_PREVIEW_GRID,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
list_data);
|
||||
|
||||
list->custom_activate_opname = activate_opname;
|
||||
list->custom_drag_opname = drag_opname;
|
||||
|
||||
if (!list) {
|
||||
/* List creation failed. */
|
||||
MEM_freeN(list_data);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
@@ -105,6 +105,7 @@ typedef enum {
|
||||
/* specials */
|
||||
UI_WTYPE_ICON,
|
||||
UI_WTYPE_ICON_LABEL,
|
||||
UI_WTYPE_PREVIEW_TILE,
|
||||
UI_WTYPE_SWATCH,
|
||||
UI_WTYPE_RGB_PICKER,
|
||||
UI_WTYPE_UNITVEC,
|
||||
@@ -3942,6 +3943,14 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
|
||||
static void widget_preview_tile(
|
||||
uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
|
||||
{
|
||||
const uiStyle *style = UI_style_get();
|
||||
ui_draw_preview_item_stateless(
|
||||
&style->widget, rect, but->drawstr, but->icon, wcol->text, UI_STYLE_TEXT_CENTER);
|
||||
}
|
||||
|
||||
static void widget_menuiconbut(uiWidgetColors *wcol,
|
||||
rcti *rect,
|
||||
int UNUSED(state),
|
||||
@@ -4407,6 +4416,13 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
|
||||
wt.custom = widget_icon_has_anim;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_PREVIEW_TILE:
|
||||
wt.draw = NULL;
|
||||
/* Drawn via the `custom` callback. */
|
||||
wt.text = NULL;
|
||||
wt.custom = widget_preview_tile;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_SWATCH:
|
||||
wt.custom = widget_swatch;
|
||||
break;
|
||||
@@ -4698,6 +4714,10 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
|
||||
wt = widget_type(UI_WTYPE_BOX);
|
||||
break;
|
||||
|
||||
case UI_BTYPE_PREVIEW_TILE:
|
||||
wt = widget_type(UI_WTYPE_PREVIEW_TILE);
|
||||
break;
|
||||
|
||||
case UI_BTYPE_EXTRA:
|
||||
widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
|
||||
break;
|
||||
@@ -4846,13 +4866,15 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
|
||||
wt->draw(&wt->wcol, rect, state, roundboxalign);
|
||||
}
|
||||
|
||||
if (use_alpha_blend) {
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
}
|
||||
if (wt->text) {
|
||||
if (use_alpha_blend) {
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
}
|
||||
|
||||
wt->text(fstyle, &wt->wcol, but, rect);
|
||||
if (use_alpha_blend) {
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
wt->text(fstyle, &wt->wcol, but, rect);
|
||||
if (use_alpha_blend) {
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5374,17 +5396,20 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
|
||||
}
|
||||
}
|
||||
|
||||
void ui_draw_preview_item(
|
||||
const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
|
||||
/**
|
||||
* Version of #ui_draw_preview_item() that does not draw the menu background and item text based on
|
||||
* state. It just draws the preview and text directly.
|
||||
*/
|
||||
void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
|
||||
rcti *rect,
|
||||
const char *name,
|
||||
int iconid,
|
||||
const uchar text_col[4],
|
||||
eFontStyle_Align text_align)
|
||||
{
|
||||
rcti trect = *rect;
|
||||
const float text_size = UI_UNIT_Y;
|
||||
float font_dims[2] = {0.0f, 0.0f};
|
||||
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
|
||||
|
||||
/* drawing button background */
|
||||
wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
|
||||
wt->draw(&wt->wcol, rect, 0, 0);
|
||||
|
||||
/* draw icon in rect above the space reserved for the label */
|
||||
rect->ymin += text_size;
|
||||
@@ -5396,8 +5421,6 @@ void ui_draw_preview_item(
|
||||
fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
|
||||
|
||||
/* text rect */
|
||||
trect.xmin += 0;
|
||||
trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
|
||||
trect.ymin += U.widget_unit / 2;
|
||||
trect.ymax = trect.ymin + font_dims[1];
|
||||
if (trect.xmax > rect->xmax - PREVIEW_PAD) {
|
||||
@@ -5416,11 +5439,27 @@ void ui_draw_preview_item(
|
||||
UI_fontstyle_draw(fstyle,
|
||||
&trect,
|
||||
drawstr,
|
||||
wt->wcol.text,
|
||||
text_col,
|
||||
&(struct uiFontStyleDraw_Params){
|
||||
.align = UI_STYLE_TEXT_CENTER,
|
||||
.align = text_align,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ui_draw_preview_item(const uiFontStyle *fstyle,
|
||||
rcti *rect,
|
||||
const char *name,
|
||||
int iconid,
|
||||
int state,
|
||||
eFontStyle_Align text_align)
|
||||
{
|
||||
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
|
||||
|
||||
/* drawing button background */
|
||||
wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
|
||||
wt->draw(&wt->wcol, rect, 0, 0);
|
||||
|
||||
ui_draw_preview_item_stateless(fstyle, rect, name, iconid, wt->wcol.text, text_align);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@@ -161,6 +161,12 @@ void ED_region_do_listen(wmRegionListenerParams *params)
|
||||
if (region->type && region->type->listener) {
|
||||
region->type->listener(params);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (uiList *, list, ®ion->ui_lists) {
|
||||
if (list->type && list->type->listener) {
|
||||
list->type->listener(list, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* only exported for WM */
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
@@ -111,6 +112,7 @@ const char *screen_context_dir[] = {
|
||||
"selected_editable_fcurves",
|
||||
"active_editable_fcurve",
|
||||
"selected_editable_keyframes",
|
||||
"asset_library",
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1024,6 +1026,14 @@ static eContextResult screen_ctx_selected_editable_keyframes(const bContext *C,
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
|
||||
static eContextResult screen_ctx_asset_library(const bContext *C, bContextDataResult *result)
|
||||
{
|
||||
WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
CTX_data_pointer_set(
|
||||
result, &workspace->id, &RNA_AssetLibraryReference, &workspace->active_asset_library);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
|
||||
/* Registry of context callback functions. */
|
||||
|
||||
typedef eContextResult (*context_callback)(const bContext *C, bContextDataResult *result);
|
||||
@@ -1098,6 +1108,7 @@ static void ensure_ed_screen_context_functions(void)
|
||||
register_context_function("selected_visible_fcurves", screen_ctx_selected_visible_fcurves);
|
||||
register_context_function("active_editable_fcurve", screen_ctx_active_editable_fcurve);
|
||||
register_context_function("selected_editable_keyframes", screen_ctx_selected_editable_keyframes);
|
||||
register_context_function("asset_library", screen_ctx_asset_library);
|
||||
}
|
||||
|
||||
/* Entry point for the screen context. */
|
||||
|
@@ -129,6 +129,8 @@ void ED_spacetypes_init(void)
|
||||
|
||||
ED_screen_user_menu_register();
|
||||
|
||||
ED_uilisttypes_ui();
|
||||
|
||||
/* Gizmo types. */
|
||||
ED_gizmotypes_button_2d();
|
||||
ED_gizmotypes_dial_3d();
|
||||
|
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
@@ -531,7 +532,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
|
||||
}
|
||||
|
||||
/* to make sure we show what is on disk */
|
||||
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
@@ -1065,7 +1066,7 @@ bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region)
|
||||
return false;
|
||||
}
|
||||
/* Check if the library exists. */
|
||||
if ((asset_params->asset_library.type == FILE_ASSET_LIBRARY_LOCAL) ||
|
||||
if ((asset_params->asset_library.type == ASSET_LIBRARY_LOCAL) ||
|
||||
filelist_is_dir(sfile->files, asset_params->base_params.dir)) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -1846,7 +1846,7 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
struct FSMenu *fsmenu = ED_fsmenu_get();
|
||||
|
||||
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
|
||||
/* refresh system directory menu */
|
||||
fsmenu_refresh_system_category(fsmenu);
|
||||
@@ -2323,7 +2323,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op)
|
||||
sfile->scroll_offset = 0;
|
||||
|
||||
/* reload dir to make sure we're seeing what's in the directory */
|
||||
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
|
||||
if (do_diropen) {
|
||||
BLI_strncpy(params->dir, path, sizeof(params->dir));
|
||||
@@ -2574,7 +2574,7 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
|
||||
|
||||
if (params) {
|
||||
params->flag ^= FILE_HIDE_DOT;
|
||||
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
|
||||
}
|
||||
|
||||
@@ -2834,7 +2834,7 @@ static int file_delete_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
@@ -1051,7 +1051,7 @@ static bool filelist_compare_asset_libraries(const FileSelectAssetLibraryUID *li
|
||||
if (library_a->type != library_b->type) {
|
||||
return false;
|
||||
}
|
||||
if (library_a->type == FILE_ASSET_LIBRARY_CUSTOM) {
|
||||
if (library_a->type == ASSET_LIBRARY_CUSTOM) {
|
||||
/* Don't only check the index, also check that it's valid. */
|
||||
bUserAssetLibrary *library_ptr_a = BKE_preferences_asset_library_find_from_index(
|
||||
&U, library_a->custom_library_index);
|
||||
@@ -1154,7 +1154,7 @@ ImBuf *filelist_file_getimage(const FileDirEntry *file)
|
||||
return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL;
|
||||
}
|
||||
|
||||
static ImBuf *filelist_geticon_image_ex(FileDirEntry *file)
|
||||
ImBuf *filelist_geticon_image_ex(const FileDirEntry *file)
|
||||
{
|
||||
ImBuf *ibuf = NULL;
|
||||
|
||||
@@ -3443,7 +3443,7 @@ static void filelist_readjob_free(void *flrjv)
|
||||
MEM_freeN(flrj);
|
||||
}
|
||||
|
||||
void filelist_readjob_start(FileList *filelist, const bContext *C)
|
||||
void filelist_readjob_start(FileList *filelist, int space_notifier, const bContext *C)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
wmJob *wm_job;
|
||||
@@ -3475,22 +3475,19 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
|
||||
filelist_readjob_endjob(flrj);
|
||||
filelist_readjob_free(flrj);
|
||||
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED, NULL);
|
||||
WM_event_add_notifier(C, space_notifier | NA_JOB_FINISHED, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* setup job */
|
||||
wm_job = WM_jobs_get(CTX_wm_manager(C),
|
||||
CTX_wm_window(C),
|
||||
CTX_data_scene(C),
|
||||
filelist,
|
||||
"Listing Dirs...",
|
||||
WM_JOB_PROGRESS,
|
||||
WM_JOB_TYPE_FILESEL_READDIR);
|
||||
WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free);
|
||||
WM_jobs_timer(wm_job,
|
||||
0.01,
|
||||
NC_SPACE | ND_SPACE_FILE_LIST,
|
||||
NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED);
|
||||
WM_jobs_timer(wm_job, 0.01, space_notifier, space_notifier | NA_JOB_FINISHED);
|
||||
WM_jobs_callbacks(
|
||||
wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob);
|
||||
|
||||
@@ -3498,12 +3495,12 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
|
||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||
}
|
||||
|
||||
void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene)
|
||||
void filelist_readjob_stop(FileList *filelist, wmWindowManager *wm)
|
||||
{
|
||||
WM_jobs_kill_type(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
|
||||
WM_jobs_kill_type(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR);
|
||||
}
|
||||
|
||||
int filelist_readjob_running(wmWindowManager *wm, Scene *owner_scene)
|
||||
int filelist_readjob_running(FileList *filelist, wmWindowManager *wm)
|
||||
{
|
||||
return WM_jobs_test(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
|
||||
return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR);
|
||||
}
|
||||
|
@@ -77,6 +77,7 @@ void filelist_init_icons(void);
|
||||
void filelist_free_icons(void);
|
||||
struct ImBuf *filelist_getimage(struct FileList *filelist, const int index);
|
||||
struct ImBuf *filelist_file_getimage(const FileDirEntry *file);
|
||||
struct ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);
|
||||
struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index);
|
||||
int filelist_geticon(struct FileList *filelist, const int index, const bool is_main);
|
||||
|
||||
@@ -140,9 +141,11 @@ struct BlendHandle *filelist_lib(struct FileList *filelist);
|
||||
bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group);
|
||||
void filelist_freelib(struct FileList *filelist);
|
||||
|
||||
void filelist_readjob_start(struct FileList *filelist, const struct bContext *C);
|
||||
void filelist_readjob_stop(struct wmWindowManager *wm, struct Scene *owner_scene);
|
||||
int filelist_readjob_running(struct wmWindowManager *wm, struct Scene *owner_scene);
|
||||
void filelist_readjob_start(struct FileList *filelist,
|
||||
int space_notifier,
|
||||
const struct bContext *C);
|
||||
void filelist_readjob_stop(struct FileList *filelist, struct wmWindowManager *wm);
|
||||
int filelist_readjob_running(struct FileList *filelist, struct wmWindowManager *wm);
|
||||
|
||||
bool filelist_cache_previews_update(struct FileList *filelist);
|
||||
void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
|
||||
|
@@ -39,6 +39,7 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
@@ -118,7 +119,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
|
||||
asset_params = sfile->asset_params = MEM_callocN(sizeof(*asset_params),
|
||||
"FileAssetSelectParams");
|
||||
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 = ASSET_LIBRARY_LOCAL;
|
||||
asset_params->asset_library.custom_library_index = -1;
|
||||
}
|
||||
|
||||
@@ -419,26 +420,26 @@ static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params)
|
||||
bUserAssetLibrary *user_library = NULL;
|
||||
|
||||
/* Ensure valid repository, or fall-back to local one. */
|
||||
if (library->type == FILE_ASSET_LIBRARY_CUSTOM) {
|
||||
if (library->type == ASSET_LIBRARY_CUSTOM) {
|
||||
BLI_assert(library->custom_library_index >= 0);
|
||||
|
||||
user_library = BKE_preferences_asset_library_find_from_index(&U,
|
||||
library->custom_library_index);
|
||||
if (!user_library) {
|
||||
library->type = FILE_ASSET_LIBRARY_LOCAL;
|
||||
library->type = ASSET_LIBRARY_LOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (library->type) {
|
||||
case FILE_ASSET_LIBRARY_LOCAL:
|
||||
case ASSET_LIBRARY_LOCAL:
|
||||
base_params->dir[0] = '\0';
|
||||
break;
|
||||
case FILE_ASSET_LIBRARY_CUSTOM:
|
||||
case ASSET_LIBRARY_CUSTOM:
|
||||
BLI_assert(user_library);
|
||||
BLI_strncpy(base_params->dir, user_library->path, sizeof(base_params->dir));
|
||||
break;
|
||||
}
|
||||
base_params->type = (library->type == FILE_ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB;
|
||||
base_params->type = (library->type == ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB;
|
||||
}
|
||||
|
||||
void fileselect_refresh_params(SpaceFile *sfile)
|
||||
@@ -1046,7 +1047,7 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *region)
|
||||
* Support updating the directory even when this isn't the active space
|
||||
* needed so RNA properties update function isn't context sensitive, see T70255.
|
||||
*/
|
||||
void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
|
||||
void ED_file_change_dir_ex(bContext *C, ScrArea *area)
|
||||
{
|
||||
/* May happen when manipulating non-active spaces. */
|
||||
if (UNLIKELY(area->spacetype != SPACE_FILE)) {
|
||||
@@ -1056,10 +1057,7 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
|
||||
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
|
||||
if (params) {
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
|
||||
if (LIKELY(scene != NULL)) {
|
||||
ED_fileselect_clear(wm, scene, sfile);
|
||||
}
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
|
||||
/* Clear search string, it is very rare to want to keep that filter while changing dir,
|
||||
* and usually very annoying to keep it actually! */
|
||||
@@ -1084,9 +1082,8 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
|
||||
|
||||
void ED_file_change_dir(bContext *C)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ED_file_change_dir_ex(C, screen, area);
|
||||
ED_file_change_dir_ex(C, area);
|
||||
}
|
||||
|
||||
int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file)
|
||||
@@ -1182,11 +1179,11 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
|
||||
return match;
|
||||
}
|
||||
|
||||
void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
|
||||
void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile)
|
||||
{
|
||||
/* only NULL in rare cases - T29734. */
|
||||
if (sfile->files) {
|
||||
filelist_readjob_stop(wm, owner_scene);
|
||||
filelist_readjob_stop(sfile->files, wm);
|
||||
filelist_freelib(sfile->files);
|
||||
filelist_clear(sfile->files);
|
||||
}
|
||||
@@ -1196,7 +1193,7 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi
|
||||
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
|
||||
}
|
||||
|
||||
void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
|
||||
void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile)
|
||||
{
|
||||
if (!sfile) {
|
||||
return;
|
||||
@@ -1223,7 +1220,7 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil
|
||||
folder_history_list_free(sfile);
|
||||
|
||||
if (sfile->files) {
|
||||
ED_fileselect_clear(wm, owner_scene, sfile);
|
||||
ED_fileselect_clear(wm, sfile);
|
||||
filelist_free(sfile->files);
|
||||
MEM_freeN(sfile->files);
|
||||
sfile->files = NULL;
|
||||
|
@@ -206,7 +206,7 @@ static void file_exit(wmWindowManager *wm, ScrArea *area)
|
||||
sfile->previews_timer = NULL;
|
||||
}
|
||||
|
||||
ED_fileselect_exit(wm, NULL, sfile);
|
||||
ED_fileselect_exit(wm, sfile);
|
||||
}
|
||||
|
||||
static SpaceLink *file_duplicate(SpaceLink *sl)
|
||||
@@ -360,13 +360,13 @@ static void file_refresh(const bContext *C, ScrArea *area)
|
||||
sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
|
||||
|
||||
if (filelist_needs_force_reset(sfile->files)) {
|
||||
filelist_readjob_stop(wm, CTX_data_scene(C));
|
||||
filelist_readjob_stop(sfile->files, wm);
|
||||
filelist_clear(sfile->files);
|
||||
}
|
||||
|
||||
if (filelist_needs_reading(sfile->files)) {
|
||||
if (!filelist_pending(sfile->files)) {
|
||||
filelist_readjob_start(sfile->files, C);
|
||||
filelist_readjob_start(sfile->files, NC_SPACE | ND_SPACE_FILE_LIST, C);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,7 +847,13 @@ static void file_space_subtype_item_extend(bContext *UNUSED(C),
|
||||
}
|
||||
}
|
||||
|
||||
static const char *file_context_dir[] = {"active_file", "id", NULL};
|
||||
static const char *file_context_dir[] = {
|
||||
"active_file",
|
||||
"asset_handle",
|
||||
"asset_library",
|
||||
"id",
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int /*eContextResult*/ file_context(const bContext *C,
|
||||
const char *member,
|
||||
@@ -878,6 +884,34 @@ static int /*eContextResult*/ file_context(const bContext *C,
|
||||
CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
/* TODO this kind of handle is very weak. We need something proper that doesn't depend on file
|
||||
* data. */
|
||||
if (CTX_data_equals(member, "asset_handle")) {
|
||||
FileDirEntry *file = filelist_file(sfile->files, params->active_file);
|
||||
if (file == NULL || !file->asset_data) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
|
||||
BLI_STATIC_ASSERT(sizeof(AssetHandle) == sizeof(FileDirEntry *),
|
||||
"Expected AssetHandle to match FileDirEntry");
|
||||
|
||||
CTX_data_pointer_set(result, &screen->id, &RNA_AssetHandle, file);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
if (CTX_data_equals(member, "asset_library")) {
|
||||
FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
|
||||
|
||||
BLI_STATIC_ASSERT(offsetof(FileSelectAssetLibraryUID, type) ==
|
||||
offsetof(AssetLibraryReference, type),
|
||||
"Expected FileSelectAssetLibraryUID to match AssetLibraryReference");
|
||||
BLI_STATIC_ASSERT(offsetof(FileSelectAssetLibraryUID, custom_library_index) ==
|
||||
offsetof(AssetLibraryReference, custom_library_index),
|
||||
"Expected FileSelectAssetLibraryUID to match AssetLibraryReference");
|
||||
|
||||
CTX_data_pointer_set(
|
||||
result, &screen->id, &RNA_AssetLibraryReference, &asset_params->asset_library);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
if (CTX_data_equals(member, "id")) {
|
||||
const FileDirEntry *file = filelist_file(sfile->files, params->active_file);
|
||||
if (file == NULL) {
|
||||
|
@@ -3445,7 +3445,15 @@ static void std_node_socket_draw(
|
||||
case SOCK_RGBA: {
|
||||
uiLayout *row = uiLayoutSplit(layout, 0.4f, false);
|
||||
uiItemL(row, text, 0);
|
||||
uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0);
|
||||
|
||||
const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
|
||||
if (node_tree->type == NTREE_GEOMETRY) {
|
||||
node_geometry_add_attribute_search_button(node_tree, node, ptr, row);
|
||||
}
|
||||
else {
|
||||
uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SOCK_STRING: {
|
||||
|
@@ -38,9 +38,11 @@ struct bContext;
|
||||
struct bNode;
|
||||
struct bNodeLink;
|
||||
struct bNodeSocket;
|
||||
struct uiBut;
|
||||
struct wmGizmoGroupType;
|
||||
struct wmKeyConfig;
|
||||
struct wmWindow;
|
||||
struct uiBlock;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "BLO_blend_validate.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_outliner.h"
|
||||
@@ -268,6 +269,8 @@ static void ed_undo_step_post(bContext *C,
|
||||
WM_toolsystem_refresh_active(C);
|
||||
WM_toolsystem_refresh_screen_all(bmain);
|
||||
|
||||
ED_assetlist_storage_tag_main_data_dirty();
|
||||
|
||||
if (CLOG_CHECK(&LOG, 1)) {
|
||||
BKE_undosys_print(wm->undo_stack);
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_armature.h"
|
||||
#include "ED_asset.h"
|
||||
#include "ED_image.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_object.h"
|
||||
@@ -172,6 +173,8 @@ void ED_editors_init(bContext *C)
|
||||
ED_space_image_paint_update(bmain, wm, scene);
|
||||
}
|
||||
|
||||
ED_assetlist_storage_tag_main_data_dirty();
|
||||
|
||||
SWAP(int, reports->flag, reports_flag_prev);
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
|
@@ -32,6 +32,13 @@
|
||||
0 \
|
||||
}
|
||||
|
||||
#define _DNA_DEFAULT_AssetLibraryReference \
|
||||
{ \
|
||||
.type = ASSET_LIBRARY_LOCAL, \
|
||||
/* Not needed really (should be ignored for #ASSET_LIBRARY_LOCAL), but helps debugging. */ \
|
||||
.custom_library_index = -1, \
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* clang-format on */
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_defs.h"
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -36,6 +37,14 @@ typedef struct AssetTag {
|
||||
char name[64]; /* MAX_NAME */
|
||||
} AssetTag;
|
||||
|
||||
typedef struct AssetFilterSettings {
|
||||
/** Tags to match against. These are newly allocated, and compared against the
|
||||
* #AssetMetaData.tags.
|
||||
* TODO not used and doesn't do anything yet. */
|
||||
ListBase tags; /* AssetTag */
|
||||
uint64_t id_types; /* rna_enum_id_type_filter_items */
|
||||
} AssetFilterSettings;
|
||||
|
||||
/**
|
||||
* \brief The meta-data of an asset.
|
||||
* By creating and giving this for a data-block (#ID.asset_data), the data-block becomes an asset.
|
||||
@@ -62,6 +71,52 @@ typedef struct AssetMetaData {
|
||||
char _pad[4];
|
||||
} AssetMetaData;
|
||||
|
||||
typedef enum eAssetLibraryType {
|
||||
/* For the future. Display assets bundled with Blender by default. */
|
||||
// ASSET_LIBRARY_BUNDLED = 0,
|
||||
/** Display assets from the current session (current "Main"). */
|
||||
ASSET_LIBRARY_LOCAL = 1,
|
||||
/* For the future. Display assets for the current project. */
|
||||
// ASSET_LIBRARY_PROJECT = 2,
|
||||
|
||||
/** Display assets from custom asset libraries, as defined in the preferences
|
||||
* (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname
|
||||
* then.
|
||||
* In RNA, we add the index of the custom library to this to identify it by index. So keep
|
||||
* this last! */
|
||||
ASSET_LIBRARY_CUSTOM = 100,
|
||||
} eAssetLibraryType;
|
||||
|
||||
/* TODO copy of FileSelectAssetLibraryUID */
|
||||
/**
|
||||
* Information to identify a asset library. May be either one of the predefined types (current
|
||||
* 'Main', builtin library, project library), or a custom type as defined in the Preferences.
|
||||
*
|
||||
* If the type is set to #ASSET_LIBRARY_CUSTOM, `custom_library_index` must be set to identify the
|
||||
* custom library. Otherwise it is not used.
|
||||
*/
|
||||
typedef struct AssetLibraryReference {
|
||||
short type; /* eAssetLibraryType */
|
||||
char _pad1[2];
|
||||
/**
|
||||
* If showing a custom asset library (#ASSET_LIBRARY_CUSTOM), this is the index of the
|
||||
* #bUserAssetLibrary within #UserDef.asset_libraries.
|
||||
* Should be ignored otherwise (but better set to -1 then, for sanity and debugging).
|
||||
*/
|
||||
int custom_library_index;
|
||||
} AssetLibraryReference;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* pass to the UI.
|
||||
*/
|
||||
#
|
||||
#
|
||||
typedef struct AssetHandle {
|
||||
struct FileDirEntry *file_data;
|
||||
} AssetHandle;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -269,6 +269,9 @@ typedef struct uiListDyn {
|
||||
int resize;
|
||||
int resize_prev;
|
||||
|
||||
/* Allocated custom data. Free'ed together with the uiList (and when re-assigning). */
|
||||
void *customdata;
|
||||
|
||||
/* Filtering data. */
|
||||
/** Items_len length. */
|
||||
int *items_filter_flags;
|
||||
@@ -300,6 +303,12 @@ typedef struct uiList { /* some list UI data need to be saved in file */
|
||||
int filter_flag;
|
||||
int filter_sort_flag;
|
||||
|
||||
/** Operator executed when activating an item. */
|
||||
const char *custom_activate_opname;
|
||||
/** Operator executed when dragging an item (item gets activated too, without running
|
||||
* custom_activate_opname above). */
|
||||
const char *custom_drag_opname;
|
||||
|
||||
/* Custom sub-classes properties. */
|
||||
IDProperty *properties;
|
||||
|
||||
@@ -583,6 +592,7 @@ enum {
|
||||
UILST_LAYOUT_DEFAULT = 0,
|
||||
UILST_LAYOUT_COMPACT = 1,
|
||||
UILST_LAYOUT_GRID = 2,
|
||||
UILST_LAYOUT_BIG_PREVIEW_GRID = 3,
|
||||
};
|
||||
|
||||
/** #uiList.flag */
|
||||
|
@@ -696,14 +696,14 @@ typedef enum eSpaceSeq_OverlayType {
|
||||
* Information to identify a asset library. May be either one of the predefined types (current
|
||||
* 'Main', builtin library, project library), or a custom type as defined in the Preferences.
|
||||
*
|
||||
* If the type is set to #FILE_ASSET_LIBRARY_CUSTOM, idname must have the name to identify the
|
||||
* If the type is set to #ASSET_LIBRARY_CUSTOM, idname must have the name to identify the
|
||||
* custom library. Otherwise idname is not used.
|
||||
*/
|
||||
typedef struct FileSelectAssetLibraryUID {
|
||||
short type; /* eFileAssetLibrary_Type */
|
||||
char _pad[2];
|
||||
/**
|
||||
* If showing a custom asset library (#FILE_ASSET_LIBRARY_CUSTOM), this is the index of the
|
||||
* If showing a custom asset library (#ASSET_LIBRARY_CUSTOM), this is the index of the
|
||||
* #bUserAssetLibrary within #UserDef.asset_libraries.
|
||||
* Should be ignored otherwise (but better set to -1 then, for sanity and debugging).
|
||||
*/
|
||||
@@ -868,22 +868,6 @@ typedef enum eFileBrowse_Mode {
|
||||
FILE_BROWSE_MODE_ASSETS = 1,
|
||||
} eFileBrowse_Mode;
|
||||
|
||||
typedef enum eFileAssetLibrary_Type {
|
||||
/* For the future. Display assets bundled with Blender by default. */
|
||||
// FILE_ASSET_LIBRARY_BUNDLED = 0,
|
||||
/** Display assets from the current session (current "Main"). */
|
||||
FILE_ASSET_LIBRARY_LOCAL = 1,
|
||||
/* For the future. Display assets for the current project. */
|
||||
// FILE_ASSET_LIBRARY_PROJECT = 2,
|
||||
|
||||
/** Display assets from custom asset libraries, as defined in the preferences
|
||||
* (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname
|
||||
* then.
|
||||
* In RNA, we add the index of the custom library to this to identify it by index. So keep
|
||||
* this last! */
|
||||
FILE_ASSET_LIBRARY_CUSTOM = 100,
|
||||
} eFileAssetLibrary_Type;
|
||||
|
||||
/* FileSelectParams.display */
|
||||
enum eFileDisplayType {
|
||||
/** Internal (not exposed to users): Keep whatever display type was used during the last File
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -135,6 +136,10 @@ typedef struct WorkSpace {
|
||||
|
||||
/** Info text from modal operators (runtime). */
|
||||
char *status_text;
|
||||
|
||||
/** Workspace-wide active asset library, for asset UIs to use (e.g. asset view UI template). The
|
||||
* Asset Browser has its own and doesn't use this. */
|
||||
AssetLibraryReference active_asset_library;
|
||||
} WorkSpace;
|
||||
|
||||
/**
|
||||
|
@@ -152,6 +152,7 @@
|
||||
|
||||
/* DNA_asset_defaults.h */
|
||||
SDNA_DEFAULT_DECL_STRUCT(AssetMetaData);
|
||||
SDNA_DEFAULT_DECL_STRUCT(AssetLibraryReference);
|
||||
|
||||
/* DNA_armature_defaults.h */
|
||||
SDNA_DEFAULT_DECL_STRUCT(bArmature);
|
||||
@@ -346,6 +347,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
|
||||
|
||||
/* DNA_asset_defaults.h */
|
||||
SDNA_DEFAULT_DECL(AssetMetaData),
|
||||
SDNA_DEFAULT_DECL(AssetLibraryReference),
|
||||
|
||||
/* DNA_armature_defaults.h */
|
||||
SDNA_DEFAULT_DECL(bArmature),
|
||||
|
@@ -71,6 +71,9 @@ extern StructRNA RNA_ArrayGpencilModifier;
|
||||
extern StructRNA RNA_ArrayModifier;
|
||||
extern StructRNA RNA_Attribute;
|
||||
extern StructRNA RNA_AttributeGroup;
|
||||
extern StructRNA RNA_AssetFilterSettings;
|
||||
extern StructRNA RNA_AssetHandle;
|
||||
extern StructRNA RNA_AssetLibraryReference;
|
||||
extern StructRNA RNA_AssetMetaData;
|
||||
extern StructRNA RNA_AssetTag;
|
||||
extern StructRNA RNA_BackgroundImage;
|
||||
@@ -472,6 +475,7 @@ extern StructRNA RNA_Paint;
|
||||
extern StructRNA RNA_PaintCurve;
|
||||
extern StructRNA RNA_PaintToolSlot;
|
||||
extern StructRNA RNA_Palette;
|
||||
extern StructRNA RNA_PaletteColors;
|
||||
extern StructRNA RNA_PaletteColor;
|
||||
extern StructRNA RNA_Panel;
|
||||
extern StructRNA RNA_Particle;
|
||||
|
@@ -243,6 +243,22 @@ extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id, bo
|
||||
|
||||
extern const EnumPropertyItem rna_enum_collection_color_items[];
|
||||
|
||||
/**
|
||||
* For ID filters (#FILTER_ID_AC, #FILTER_ID_AR, ...) an int isn't enough. This version allows 64
|
||||
* bit integers. So can't use the regular #EnumPropertyItem. Would be nice if RNA supported this
|
||||
* itself.
|
||||
*
|
||||
* Meant to be used with #RNA_def_property_boolean_sdna() which supports 64 bit flags as well.
|
||||
*/
|
||||
struct IDFilterEnumPropertyItem {
|
||||
const uint64_t flag;
|
||||
const char *identifier;
|
||||
const int icon;
|
||||
const char *name;
|
||||
const char *description;
|
||||
};
|
||||
extern const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[];
|
||||
|
||||
/* API calls */
|
||||
int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
|
||||
int rna_node_tree_idname_to_enum(const char *idname);
|
||||
|
@@ -4290,7 +4290,6 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
||||
{"rna_animviz.c", NULL, RNA_def_animviz},
|
||||
{"rna_armature.c", "rna_armature_api.c", RNA_def_armature},
|
||||
{"rna_attribute.c", NULL, RNA_def_attribute},
|
||||
{"rna_asset.c", NULL, RNA_def_asset},
|
||||
{"rna_boid.c", NULL, RNA_def_boid},
|
||||
{"rna_brush.c", NULL, RNA_def_brush},
|
||||
{"rna_cachefile.c", NULL, RNA_def_cachefile},
|
||||
@@ -4345,6 +4344,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
||||
{"rna_simulation.c", NULL, RNA_def_simulation},
|
||||
#endif
|
||||
{"rna_space.c", "rna_space_api.c", RNA_def_space},
|
||||
{"rna_asset.c", NULL, RNA_def_asset}, /* After spaces! */
|
||||
{"rna_speaker.c", NULL, RNA_def_speaker},
|
||||
{"rna_test.c", NULL, RNA_def_test},
|
||||
{"rna_text.c", "rna_text_api.c", RNA_def_text},
|
||||
|
@@ -126,6 +126,97 @@ static const EnumPropertyItem rna_enum_override_library_property_operation_items
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
/**
|
||||
* \note Uses #IDFilterEnumPropertyItem, not EnumPropertyItem to support 64 bit items.
|
||||
*/
|
||||
const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[] = {
|
||||
/* Datablocks */
|
||||
{FILTER_ID_AC, "filter_action", ICON_ANIM_DATA, "Actions", "Show Action data-blocks"},
|
||||
{FILTER_ID_AR,
|
||||
"filter_armature",
|
||||
ICON_ARMATURE_DATA,
|
||||
"Armatures",
|
||||
"Show Armature data-blocks"},
|
||||
{FILTER_ID_BR, "filter_brush", ICON_BRUSH_DATA, "Brushes", "Show Brushes data-blocks"},
|
||||
{FILTER_ID_CA, "filter_camera", ICON_CAMERA_DATA, "Cameras", "Show Camera data-blocks"},
|
||||
{FILTER_ID_CF, "filter_cachefile", ICON_FILE, "Cache Files", "Show Cache File data-blocks"},
|
||||
{FILTER_ID_CU, "filter_curve", ICON_CURVE_DATA, "Curves", "Show Curve data-blocks"},
|
||||
{FILTER_ID_GD,
|
||||
"filter_grease_pencil",
|
||||
ICON_GREASEPENCIL,
|
||||
"Grease Pencil",
|
||||
"Show Grease pencil data-blocks"},
|
||||
{FILTER_ID_GR,
|
||||
"filter_group",
|
||||
ICON_OUTLINER_COLLECTION,
|
||||
"Collections",
|
||||
"Show Collection data-blocks"},
|
||||
{FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"},
|
||||
{FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"},
|
||||
{FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"},
|
||||
{FILTER_ID_LP,
|
||||
"filter_light_probe",
|
||||
ICON_OUTLINER_DATA_LIGHTPROBE,
|
||||
"Light Probes",
|
||||
"Show Light Probe data-blocks"},
|
||||
{FILTER_ID_LS,
|
||||
"filter_linestyle",
|
||||
ICON_LINE_DATA,
|
||||
"Freestyle Linestyles",
|
||||
"Show Freestyle's Line Style data-blocks"},
|
||||
{FILTER_ID_LT, "filter_lattice", ICON_LATTICE_DATA, "Lattices", "Show Lattice data-blocks"},
|
||||
{FILTER_ID_MA,
|
||||
"filter_material",
|
||||
ICON_MATERIAL_DATA,
|
||||
"Materials",
|
||||
"Show Material data-blocks"},
|
||||
{FILTER_ID_MB, "filter_metaball", ICON_META_DATA, "Metaballs", "Show Metaball data-blocks"},
|
||||
{FILTER_ID_MC,
|
||||
"filter_movie_clip",
|
||||
ICON_TRACKER_DATA,
|
||||
"Movie Clips",
|
||||
"Show Movie Clip data-blocks"},
|
||||
{FILTER_ID_ME, "filter_mesh", ICON_MESH_DATA, "Meshes", "Show Mesh data-blocks"},
|
||||
{FILTER_ID_MSK, "filter_mask", ICON_MOD_MASK, "Masks", "Show Mask data-blocks"},
|
||||
{FILTER_ID_NT, "filter_node_tree", ICON_NODETREE, "Node Trees", "Show Node Tree data-blocks"},
|
||||
{FILTER_ID_OB, "filter_object", ICON_OBJECT_DATA, "Objects", "Show Object data-blocks"},
|
||||
{FILTER_ID_PA,
|
||||
"filter_particle_settings",
|
||||
ICON_PARTICLE_DATA,
|
||||
"Particles Settings",
|
||||
"Show Particle Settings data-blocks"},
|
||||
{FILTER_ID_PAL, "filter_palette", ICON_COLOR, "Palettes", "Show Palette data-blocks"},
|
||||
{FILTER_ID_PC,
|
||||
"filter_paint_curve",
|
||||
ICON_CURVE_BEZCURVE,
|
||||
"Paint Curves",
|
||||
"Show Paint Curve data-blocks"},
|
||||
{FILTER_ID_PT,
|
||||
"filter_pointcloud",
|
||||
ICON_POINTCLOUD_DATA,
|
||||
"Point Clouds",
|
||||
"Show/hide Point Cloud data-blocks"},
|
||||
{FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"},
|
||||
{FILTER_ID_SIM,
|
||||
"filter_simulation",
|
||||
ICON_PHYSICS,
|
||||
"Simulations",
|
||||
"Show Simulation data-blocks"}, /* TODO: Use correct icon. */
|
||||
{FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"},
|
||||
{FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"},
|
||||
{FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"},
|
||||
{FILTER_ID_TXT, "filter_text", ICON_TEXT, "Texts", "Show Text data-blocks"},
|
||||
{FILTER_ID_VF, "filter_font", ICON_FONT_DATA, "Fonts", "Show Font data-blocks"},
|
||||
{FILTER_ID_VO, "filter_volume", ICON_VOLUME_DATA, "Volumes", "Show/hide Volume data-blocks"},
|
||||
{FILTER_ID_WO, "filter_world", ICON_WORLD_DATA, "Worlds", "Show World data-blocks"},
|
||||
{FILTER_ID_WS,
|
||||
"filter_work_space",
|
||||
ICON_WORKSPACE,
|
||||
"Workspaces",
|
||||
"Show workspace data-blocks"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "DNA_anim_types.h"
|
||||
|
@@ -35,6 +35,8 @@
|
||||
|
||||
# include "BLI_listbase.h"
|
||||
|
||||
# include "ED_asset.h"
|
||||
|
||||
# include "RNA_access.h"
|
||||
|
||||
static AssetTag *rna_AssetMetaData_tag_new(AssetMetaData *asset_data,
|
||||
@@ -129,6 +131,87 @@ static void rna_AssetMetaData_active_tag_range(
|
||||
*max = *softmax = MAX2(asset_data->tot_tags - 1, 0);
|
||||
}
|
||||
|
||||
static PointerRNA rna_AssetHandle_file_data_get(PointerRNA *ptr)
|
||||
{
|
||||
AssetHandle *asset_handle = ptr->data;
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_AssetHandle, asset_handle->file_data);
|
||||
}
|
||||
|
||||
static void rna_AssetHandle_file_data_set(PointerRNA *ptr,
|
||||
PointerRNA value,
|
||||
struct ReportList *UNUSED(reports))
|
||||
{
|
||||
AssetHandle *asset_handle = ptr->data;
|
||||
asset_handle->file_data = value.data;
|
||||
}
|
||||
|
||||
int rna_asset_library_reference_get(const AssetLibraryReference *library)
|
||||
{
|
||||
return ED_asset_library_reference_to_enum_value(library);
|
||||
}
|
||||
|
||||
void rna_asset_library_reference_set(AssetLibraryReference *library, int value)
|
||||
{
|
||||
*library = ED_asset_library_reference_from_enum_value(value);
|
||||
}
|
||||
|
||||
const EnumPropertyItem *rna_asset_library_reference_itemf(bContext *UNUSED(C),
|
||||
PointerRNA *UNUSED(ptr),
|
||||
PropertyRNA *UNUSED(prop),
|
||||
bool *r_free)
|
||||
{
|
||||
const EnumPropertyItem predefined_items[] = {
|
||||
/* For the future. */
|
||||
// {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
|
||||
{ASSET_LIBRARY_LOCAL,
|
||||
"LOCAL",
|
||||
ICON_BLENDER,
|
||||
"Current File",
|
||||
"Show the assets currently available in this Blender session"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
EnumPropertyItem *item = NULL;
|
||||
int totitem = 0;
|
||||
|
||||
/* Add separator if needed. */
|
||||
if (!BLI_listbase_is_empty(&U.asset_libraries)) {
|
||||
const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL};
|
||||
RNA_enum_item_add(&item, &totitem, &sepr);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (bUserAssetLibrary *user_library = U.asset_libraries.first; user_library;
|
||||
user_library = user_library->next, i++) {
|
||||
/* Note that the path itself isn't checked for validity here. If an invalid library path is
|
||||
* used, the Asset Browser can give a nice hint on what's wrong. */
|
||||
const bool is_valid = (user_library->name[0] && user_library->path[0]);
|
||||
if (!is_valid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Use library path as description, it's a nice hint for users. */
|
||||
EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i,
|
||||
user_library->name,
|
||||
ICON_NONE,
|
||||
user_library->name,
|
||||
user_library->path};
|
||||
RNA_enum_item_add(&item, &totitem, &tmp);
|
||||
}
|
||||
|
||||
if (totitem) {
|
||||
const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL};
|
||||
RNA_enum_item_add(&item, &totitem, &sepr);
|
||||
}
|
||||
|
||||
/* Add predefined items. */
|
||||
RNA_enum_items_add(&item, &totitem, predefined_items);
|
||||
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
*r_free = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_asset_tag(BlenderRNA *brna)
|
||||
@@ -181,6 +264,33 @@ static void rna_def_asset_tags_api(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
|
||||
}
|
||||
|
||||
static void rna_def_asset_filter_settings(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "AssetFilterSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Asset Filter Settings", "");
|
||||
|
||||
prop = RNA_def_property(srna, "tags", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "AssetTag");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Tags",
|
||||
"Custom tags (name tokens) for the asset, used for filtering and "
|
||||
"general asset management");
|
||||
RNA_def_property_srna(prop, "AssetTags");
|
||||
|
||||
for (int i = 0; rna_enum_id_type_filter_items[i].identifier; i++) {
|
||||
prop = RNA_def_property(
|
||||
srna, rna_enum_id_type_filter_items[i].identifier, PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "id_types", rna_enum_id_type_filter_items[i].flag);
|
||||
RNA_def_property_ui_text(
|
||||
prop, rna_enum_id_type_filter_items[i].name, rna_enum_id_type_filter_items[i].description);
|
||||
RNA_def_property_ui_icon(prop, rna_enum_id_type_filter_items[i].icon, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_def_asset_data(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -215,12 +325,52 @@ static void rna_def_asset_data(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Active Tag", "Index of the tag set for editing");
|
||||
}
|
||||
|
||||
static void rna_def_asset_handle(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "AssetHandle", "PropertyGroup");
|
||||
RNA_def_struct_ui_text(srna, "Asset Handle", "Reference to some asset");
|
||||
|
||||
prop = RNA_def_property(srna, "file_data", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_struct_type(prop, "FileSelectEntry");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, "rna_AssetHandle_file_data_get", "rna_AssetHandle_file_data_set", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "File Entry", "File data used to refer to the asset");
|
||||
}
|
||||
|
||||
static void rna_def_asset_library_reference(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna = RNA_def_struct(brna, "AssetLibraryReference", NULL);
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Asset Library Reference", "Identifier to refere to the asset library");
|
||||
}
|
||||
|
||||
/**
|
||||
* \note the UI text and updating has to be set by the caller.
|
||||
*/
|
||||
PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
|
||||
const char *get,
|
||||
const char *set)
|
||||
{
|
||||
PropertyRNA *prop = RNA_def_property(srna, "active_asset_library", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, DummyRNA_NULL_items);
|
||||
RNA_def_property_enum_funcs(prop, get, set, "rna_asset_library_reference_itemf");
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
void RNA_def_asset(BlenderRNA *brna)
|
||||
{
|
||||
RNA_define_animate_sdna(false);
|
||||
|
||||
rna_def_asset_tag(brna);
|
||||
rna_def_asset_filter_settings(brna);
|
||||
rna_def_asset_data(brna);
|
||||
rna_def_asset_library_reference(brna);
|
||||
rna_def_asset_handle(brna);
|
||||
|
||||
RNA_define_animate_sdna(true);
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
#define RNA_MAGIC ((int)~0)
|
||||
|
||||
struct AssetLibraryReference;
|
||||
struct FreestyleSettings;
|
||||
struct ID;
|
||||
struct IDOverrideLibrary;
|
||||
@@ -266,6 +267,16 @@ void rna_def_mtex_common(struct BlenderRNA *brna,
|
||||
void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna);
|
||||
void rna_def_view_layer_common(struct BlenderRNA *brna, struct StructRNA *srna, const bool scene);
|
||||
|
||||
PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
|
||||
const char *get,
|
||||
const char *set);
|
||||
int rna_asset_library_reference_get(const struct AssetLibraryReference *library);
|
||||
void rna_asset_library_reference_set(struct AssetLibraryReference *library, int value);
|
||||
const EnumPropertyItem *rna_asset_library_reference_itemf(struct bContext *C,
|
||||
struct PointerRNA *ptr,
|
||||
struct PropertyRNA *prop,
|
||||
bool *r_free);
|
||||
|
||||
void rna_def_actionbone_group_common(struct StructRNA *srna,
|
||||
int update_flag,
|
||||
const char *update_cb);
|
||||
|
@@ -128,6 +128,11 @@ static void rna_def_palettecolors(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
prop, "rna_Palette_active_color_get", "rna_Palette_active_color_set", NULL, NULL);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Active Palette Color", "");
|
||||
|
||||
/* XXX just for testing. */
|
||||
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "active_color");
|
||||
RNA_def_property_ui_text(prop, "Active Palette Color Index", "");
|
||||
}
|
||||
|
||||
static void rna_def_palettecolor(BlenderRNA *brna)
|
||||
|
@@ -504,6 +504,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "DNA_anim_types.h"
|
||||
# include "DNA_asset_types.h"
|
||||
# include "DNA_scene_types.h"
|
||||
# include "DNA_screen_types.h"
|
||||
# include "DNA_userdef_types.h"
|
||||
@@ -2542,6 +2543,8 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr)
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data);
|
||||
}
|
||||
|
||||
/* TODO use rna_def_asset_library_reference_common() */
|
||||
|
||||
static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
|
||||
{
|
||||
FileAssetSelectParams *params = ptr->data;
|
||||
@@ -2549,7 +2552,7 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
|
||||
BLI_assert(ptr->type == &RNA_FileAssetSelectParams);
|
||||
|
||||
/* Simple case: Predefined repo, just set the value. */
|
||||
if (params->asset_library.type < FILE_ASSET_LIBRARY_CUSTOM) {
|
||||
if (params->asset_library.type < ASSET_LIBRARY_CUSTOM) {
|
||||
return params->asset_library.type;
|
||||
}
|
||||
|
||||
@@ -2558,11 +2561,11 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
|
||||
const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
|
||||
&U, params->asset_library.custom_library_index);
|
||||
if (user_library) {
|
||||
return FILE_ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index;
|
||||
return ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index;
|
||||
}
|
||||
|
||||
BLI_assert(0);
|
||||
return FILE_ASSET_LIBRARY_LOCAL;
|
||||
return ASSET_LIBRARY_LOCAL;
|
||||
}
|
||||
|
||||
static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int value)
|
||||
@@ -2570,26 +2573,26 @@ static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int val
|
||||
FileAssetSelectParams *params = ptr->data;
|
||||
|
||||
/* Simple case: Predefined repo, just set the value. */
|
||||
if (value < FILE_ASSET_LIBRARY_CUSTOM) {
|
||||
if (value < ASSET_LIBRARY_CUSTOM) {
|
||||
params->asset_library.type = value;
|
||||
params->asset_library.custom_library_index = -1;
|
||||
BLI_assert(ELEM(value, FILE_ASSET_LIBRARY_LOCAL));
|
||||
BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL));
|
||||
return;
|
||||
}
|
||||
|
||||
const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
|
||||
&U, value - FILE_ASSET_LIBRARY_CUSTOM);
|
||||
&U, value - ASSET_LIBRARY_CUSTOM);
|
||||
|
||||
/* Note that the path isn't checked for validity here. If an invalid library path is used, the
|
||||
* Asset Browser can give a nice hint on what's wrong. */
|
||||
const bool is_valid = (user_library->name[0] && user_library->path[0]);
|
||||
if (!user_library) {
|
||||
params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL;
|
||||
params->asset_library.type = ASSET_LIBRARY_LOCAL;
|
||||
params->asset_library.custom_library_index = -1;
|
||||
}
|
||||
else if (user_library && is_valid) {
|
||||
params->asset_library.custom_library_index = value - FILE_ASSET_LIBRARY_CUSTOM;
|
||||
params->asset_library.type = FILE_ASSET_LIBRARY_CUSTOM;
|
||||
params->asset_library.custom_library_index = value - ASSET_LIBRARY_CUSTOM;
|
||||
params->asset_library.type = ASSET_LIBRARY_CUSTOM;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2598,8 +2601,8 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf(
|
||||
{
|
||||
const EnumPropertyItem predefined_items[] = {
|
||||
/* For the future. */
|
||||
// {FILE_ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
|
||||
{FILE_ASSET_LIBRARY_LOCAL,
|
||||
// {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
|
||||
{ASSET_LIBRARY_LOCAL,
|
||||
"LOCAL",
|
||||
ICON_BLENDER,
|
||||
"Current File",
|
||||
@@ -2627,7 +2630,7 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf(
|
||||
}
|
||||
|
||||
/* Use library path as description, it's a nice hint for users. */
|
||||
EnumPropertyItem tmp = {FILE_ASSET_LIBRARY_CUSTOM + i,
|
||||
EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i,
|
||||
user_library->name,
|
||||
ICON_NONE,
|
||||
user_library->name,
|
||||
@@ -2955,7 +2958,7 @@ static void rna_FileBrowser_FSMenu_active_range(PointerRNA *UNUSED(ptr),
|
||||
static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
ScrArea *area = rna_area_from_space(ptr);
|
||||
ED_file_change_dir_ex(C, (bScreen *)ptr->owner_id, area);
|
||||
ED_file_change_dir_ex(C, area);
|
||||
}
|
||||
|
||||
static int rna_FileBrowser_FSMenuSystem_active_get(PointerRNA *ptr)
|
||||
@@ -3107,6 +3110,45 @@ static const EnumPropertyItem dt_uv_items[] = {
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static struct IDFilterEnumPropertyItem rna_enum_space_file_id_filter_categories[] = {
|
||||
/* Categories */
|
||||
{FILTER_ID_SCE, "category_scene", ICON_SCENE_DATA, "Scenes", "Show scenes"},
|
||||
{FILTER_ID_AC, "category_animation", ICON_ANIM_DATA, "Animations", "Show animation data"},
|
||||
{FILTER_ID_OB | FILTER_ID_GR,
|
||||
"category_object",
|
||||
ICON_OUTLINER_COLLECTION,
|
||||
"Objects & Collections",
|
||||
"Show objects and collections"},
|
||||
{FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA |
|
||||
FILTER_ID_PT | FILTER_ID_VO,
|
||||
"category_geometry",
|
||||
ICON_NODETREE,
|
||||
"Geometry",
|
||||
"Show meshes, curves, lattice, armatures and metaballs data"},
|
||||
{FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE,
|
||||
"category_shading",
|
||||
ICON_MATERIAL_DATA,
|
||||
"Shading",
|
||||
"Show materials, nodetrees, textures and Freestyle's linestyles"},
|
||||
{FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO,
|
||||
"category_image",
|
||||
ICON_IMAGE_DATA,
|
||||
"Images & Sounds",
|
||||
"Show images, movie clips, sounds and masks"},
|
||||
{FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO,
|
||||
"category_environment",
|
||||
ICON_WORLD_DATA,
|
||||
"Environment",
|
||||
"Show worlds, lights, cameras and speakers"},
|
||||
{FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT |
|
||||
FILTER_ID_VF | FILTER_ID_CF | FILTER_ID_WS,
|
||||
"category_misc",
|
||||
ICON_GREASEPENCIL,
|
||||
"Miscellaneous",
|
||||
"Show other data types"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int region_type_mask)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
@@ -4788,6 +4830,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
}
|
||||
|
||||
/* Nested Structs */
|
||||
|
||||
prop = RNA_def_property(srna, "shading", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_struct_type(prop, "View3DShading");
|
||||
@@ -6031,142 +6074,6 @@ static void rna_def_space_console(BlenderRNA *brna)
|
||||
/* Filter for datablock types in link/append. */
|
||||
static void rna_def_fileselect_idfilter(BlenderRNA *brna)
|
||||
{
|
||||
struct IDFilterBoolean {
|
||||
/* 64 bit, so we can't use bitflag enum. */
|
||||
const uint64_t flag;
|
||||
const char *identifier;
|
||||
const int icon;
|
||||
const char *name;
|
||||
const char *description;
|
||||
};
|
||||
|
||||
static const struct IDFilterBoolean booleans[] = {
|
||||
/* Datablocks */
|
||||
{FILTER_ID_AC, "filter_action", ICON_ANIM_DATA, "Actions", "Show Action data-blocks"},
|
||||
{FILTER_ID_AR,
|
||||
"filter_armature",
|
||||
ICON_ARMATURE_DATA,
|
||||
"Armatures",
|
||||
"Show Armature data-blocks"},
|
||||
{FILTER_ID_BR, "filter_brush", ICON_BRUSH_DATA, "Brushes", "Show Brushes data-blocks"},
|
||||
{FILTER_ID_CA, "filter_camera", ICON_CAMERA_DATA, "Cameras", "Show Camera data-blocks"},
|
||||
{FILTER_ID_CF, "filter_cachefile", ICON_FILE, "Cache Files", "Show Cache File data-blocks"},
|
||||
{FILTER_ID_CU, "filter_curve", ICON_CURVE_DATA, "Curves", "Show Curve data-blocks"},
|
||||
{FILTER_ID_GD,
|
||||
"filter_grease_pencil",
|
||||
ICON_GREASEPENCIL,
|
||||
"Grease Pencil",
|
||||
"Show Grease pencil data-blocks"},
|
||||
{FILTER_ID_GR,
|
||||
"filter_group",
|
||||
ICON_OUTLINER_COLLECTION,
|
||||
"Collections",
|
||||
"Show Collection data-blocks"},
|
||||
{FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"},
|
||||
{FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"},
|
||||
{FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"},
|
||||
{FILTER_ID_LP,
|
||||
"filter_light_probe",
|
||||
ICON_OUTLINER_DATA_LIGHTPROBE,
|
||||
"Light Probes",
|
||||
"Show Light Probe data-blocks"},
|
||||
{FILTER_ID_LS,
|
||||
"filter_linestyle",
|
||||
ICON_LINE_DATA,
|
||||
"Freestyle Linestyles",
|
||||
"Show Freestyle's Line Style data-blocks"},
|
||||
{FILTER_ID_LT, "filter_lattice", ICON_LATTICE_DATA, "Lattices", "Show Lattice data-blocks"},
|
||||
{FILTER_ID_MA,
|
||||
"filter_material",
|
||||
ICON_MATERIAL_DATA,
|
||||
"Materials",
|
||||
"Show Material data-blocks"},
|
||||
{FILTER_ID_MB, "filter_metaball", ICON_META_DATA, "Metaballs", "Show Metaball data-blocks"},
|
||||
{FILTER_ID_MC,
|
||||
"filter_movie_clip",
|
||||
ICON_TRACKER_DATA,
|
||||
"Movie Clips",
|
||||
"Show Movie Clip data-blocks"},
|
||||
{FILTER_ID_ME, "filter_mesh", ICON_MESH_DATA, "Meshes", "Show Mesh data-blocks"},
|
||||
{FILTER_ID_MSK, "filter_mask", ICON_MOD_MASK, "Masks", "Show Mask data-blocks"},
|
||||
{FILTER_ID_NT,
|
||||
"filter_node_tree",
|
||||
ICON_NODETREE,
|
||||
"Node Trees",
|
||||
"Show Node Tree data-blocks"},
|
||||
{FILTER_ID_OB, "filter_object", ICON_OBJECT_DATA, "Objects", "Show Object data-blocks"},
|
||||
{FILTER_ID_PA,
|
||||
"filter_particle_settings",
|
||||
ICON_PARTICLE_DATA,
|
||||
"Particles Settings",
|
||||
"Show Particle Settings data-blocks"},
|
||||
{FILTER_ID_PAL, "filter_palette", ICON_COLOR, "Palettes", "Show Palette data-blocks"},
|
||||
{FILTER_ID_PC,
|
||||
"filter_paint_curve",
|
||||
ICON_CURVE_BEZCURVE,
|
||||
"Paint Curves",
|
||||
"Show Paint Curve data-blocks"},
|
||||
{FILTER_ID_PT,
|
||||
"filter_pointcloud",
|
||||
ICON_POINTCLOUD_DATA,
|
||||
"Point Clouds",
|
||||
"Show/hide Point Cloud data-blocks"},
|
||||
{FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"},
|
||||
{FILTER_ID_SIM,
|
||||
"filter_simulation",
|
||||
ICON_PHYSICS,
|
||||
"Simulations",
|
||||
"Show Simulation data-blocks"}, /* TODO: Use correct icon. */
|
||||
{FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"},
|
||||
{FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"},
|
||||
{FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"},
|
||||
{FILTER_ID_TXT, "filter_text", ICON_TEXT, "Texts", "Show Text data-blocks"},
|
||||
{FILTER_ID_VF, "filter_font", ICON_FONT_DATA, "Fonts", "Show Font data-blocks"},
|
||||
{FILTER_ID_VO, "filter_volume", ICON_VOLUME_DATA, "Volumes", "Show/hide Volume data-blocks"},
|
||||
{FILTER_ID_WO, "filter_world", ICON_WORLD_DATA, "Worlds", "Show World data-blocks"},
|
||||
{FILTER_ID_WS,
|
||||
"filter_work_space",
|
||||
ICON_WORKSPACE,
|
||||
"Workspaces",
|
||||
"Show workspace data-blocks"},
|
||||
|
||||
/* Categories */
|
||||
{FILTER_ID_SCE, "category_scene", ICON_SCENE_DATA, "Scenes", "Show scenes"},
|
||||
{FILTER_ID_AC, "category_animation", ICON_ANIM_DATA, "Animations", "Show animation data"},
|
||||
{FILTER_ID_OB | FILTER_ID_GR,
|
||||
"category_object",
|
||||
ICON_OUTLINER_COLLECTION,
|
||||
"Objects & Collections",
|
||||
"Show objects and collections"},
|
||||
{FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA |
|
||||
FILTER_ID_PT | FILTER_ID_VO,
|
||||
"category_geometry",
|
||||
ICON_NODETREE,
|
||||
"Geometry",
|
||||
"Show meshes, curves, lattice, armatures and metaballs data"},
|
||||
{FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE,
|
||||
"category_shading",
|
||||
ICON_MATERIAL_DATA,
|
||||
"Shading",
|
||||
"Show materials, nodetrees, textures and Freestyle's linestyles"},
|
||||
{FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO,
|
||||
"category_image",
|
||||
ICON_IMAGE_DATA,
|
||||
"Images & Sounds",
|
||||
"Show images, movie clips, sounds and masks"},
|
||||
{FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO,
|
||||
"category_environment",
|
||||
ICON_WORLD_DATA,
|
||||
"Environment",
|
||||
"Show worlds, lights, cameras and speakers"},
|
||||
{FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT |
|
||||
FILTER_ID_VF | FILTER_ID_CF | FILTER_ID_WS,
|
||||
"category_misc",
|
||||
ICON_GREASEPENCIL,
|
||||
"Miscellaneous",
|
||||
"Show other data types"},
|
||||
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
StructRNA *srna = RNA_def_struct(brna, "FileSelectIDFilter", NULL);
|
||||
RNA_def_struct_sdna(srna, "FileSelectParams");
|
||||
@@ -6174,12 +6081,23 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "File Select ID Filter", "Which ID types to show/hide, when browsing a library");
|
||||
|
||||
for (int i = 0; booleans[i].identifier; i++) {
|
||||
PropertyRNA *prop = RNA_def_property(srna, booleans[i].identifier, PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "filter_id", booleans[i].flag);
|
||||
RNA_def_property_ui_text(prop, booleans[i].name, booleans[i].description);
|
||||
RNA_def_property_ui_icon(prop, booleans[i].icon, 0);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
|
||||
const struct IDFilterEnumPropertyItem *individual_ids_and_categories[] = {
|
||||
rna_enum_id_type_filter_items,
|
||||
rna_enum_space_file_id_filter_categories,
|
||||
NULL,
|
||||
};
|
||||
for (uint i = 0; individual_ids_and_categories[i]; i++) {
|
||||
for (int j = 0; individual_ids_and_categories[i][j].identifier; j++) {
|
||||
PropertyRNA *prop = RNA_def_property(
|
||||
srna, individual_ids_and_categories[i][j].identifier, PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, NULL, "filter_id", individual_ids_and_categories[i][j].flag);
|
||||
RNA_def_property_ui_text(prop,
|
||||
individual_ids_and_categories[i][j].name,
|
||||
individual_ids_and_categories[i][j].description);
|
||||
RNA_def_property_ui_icon(prop, individual_ids_and_categories[i][j].icon, 0);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6435,7 +6353,7 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* XXX copied from rna_def_fileselect_idfilter. */
|
||||
/* XXX copied from rna_enum_id_type_filter_items. */
|
||||
static const EnumPropertyItem asset_category_items[] = {
|
||||
{FILTER_ID_SCE, "SCENES", ICON_SCENE_DATA, "Scenes", "Show scenes"},
|
||||
{FILTER_ID_AC, "ANIMATIONS", ICON_ANIM_DATA, "Animations", "Show animation data"},
|
||||
|
@@ -50,6 +50,8 @@ const EnumPropertyItem rna_enum_icon_items[] = {
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "DNA_asset_types.h"
|
||||
|
||||
const char *rna_translate_ui_text(
|
||||
const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, bool translate)
|
||||
{
|
||||
@@ -568,6 +570,65 @@ static void rna_uiTemplateEventFromKeymapItem(
|
||||
uiTemplateEventFromKeymapItem(layout, name, kmi, true);
|
||||
}
|
||||
|
||||
static void rna_uiTemplateAssetView(uiLayout *layout,
|
||||
bContext *C,
|
||||
const char *list_id,
|
||||
PointerRNA *asset_library_dataptr,
|
||||
const char *asset_library_propname,
|
||||
PointerRNA *assets_dataptr,
|
||||
const char *assets_propname,
|
||||
PointerRNA *active_dataptr,
|
||||
const char *active_propname,
|
||||
int filter_id_types,
|
||||
const char *activate_opname,
|
||||
const char *drag_opname)
|
||||
{
|
||||
AssetFilterSettings filter_settings = {
|
||||
.id_types = filter_id_types ? filter_id_types : FILTER_ID_ALL,
|
||||
};
|
||||
uiTemplateAssetView(layout,
|
||||
C,
|
||||
list_id,
|
||||
asset_library_dataptr,
|
||||
asset_library_propname,
|
||||
assets_dataptr,
|
||||
assets_propname,
|
||||
active_dataptr,
|
||||
active_propname,
|
||||
&filter_settings,
|
||||
activate_opname,
|
||||
drag_opname);
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX Remove filter items that require more than 32 bits for storage. RNA enums don't support
|
||||
* that currently.
|
||||
*/
|
||||
static const EnumPropertyItem *rna_uiTemplateAssetView_filter_id_types_itemf(
|
||||
bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
|
||||
{
|
||||
EnumPropertyItem *items = NULL;
|
||||
int totitem = 0;
|
||||
|
||||
for (int i = 0; rna_enum_id_type_filter_items[i].identifier; i++) {
|
||||
if (rna_enum_id_type_filter_items[i].flag > (1ULL << 31)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EnumPropertyItem tmp = {0, "", 0, "", ""};
|
||||
tmp.value = rna_enum_id_type_filter_items[i].flag;
|
||||
tmp.identifier = rna_enum_id_type_filter_items[i].identifier;
|
||||
tmp.icon = rna_enum_id_type_filter_items[i].icon;
|
||||
tmp.name = rna_enum_id_type_filter_items[i].name;
|
||||
tmp.description = rna_enum_id_type_filter_items[i].description;
|
||||
RNA_enum_item_add(&items, &totitem, &tmp);
|
||||
}
|
||||
RNA_enum_item_end(&items, &totitem);
|
||||
|
||||
*r_free = true;
|
||||
return items;
|
||||
}
|
||||
|
||||
static uiLayout *rna_uiLayoutRowWithHeading(
|
||||
uiLayout *layout, bool align, const char *heading, const char *heading_ctxt, bool translate)
|
||||
{
|
||||
@@ -1677,6 +1738,65 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||
RNA_def_property_ui_text(parm, "Item", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
api_ui_item_common_text(func);
|
||||
|
||||
func = RNA_def_function(srna, "template_asset_view", "rna_uiTemplateAssetView");
|
||||
RNA_def_function_ui_description(func, "Item. A scrollable list of assets in a grid view");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
parm = RNA_def_string(func,
|
||||
"list_id",
|
||||
NULL,
|
||||
0,
|
||||
"",
|
||||
"Identifier of this asset view. Necessary to tell apart different asset "
|
||||
"views and to idenify an asset view read from a .blend");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(func,
|
||||
"asset_library_dataptr",
|
||||
"AnyType",
|
||||
"",
|
||||
"Data from which to take the active asset library property");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
parm = RNA_def_string(
|
||||
func, "asset_library_propname", NULL, 0, "", "Identifier of the asset library property");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(
|
||||
func, "assets_dataptr", "AnyType", "", "Data from which to take the asset list property");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
parm = RNA_def_string(
|
||||
func, "assets_propname", NULL, 0, "", "Identifier of the asset list property");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(func,
|
||||
"active_dataptr",
|
||||
"AnyType",
|
||||
"",
|
||||
"Data from which to take the integer property, index of the active item");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
parm = RNA_def_string(
|
||||
func,
|
||||
"active_propname",
|
||||
NULL,
|
||||
0,
|
||||
"",
|
||||
"Identifier of the integer property in active_data, index of the active item");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_property(func, "filter_id_types", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(parm, DummyRNA_NULL_items);
|
||||
RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_uiTemplateAssetView_filter_id_types_itemf");
|
||||
RNA_def_property_flag(parm, PROP_ENUM_FLAG);
|
||||
RNA_def_string(func,
|
||||
"activate_operator",
|
||||
NULL,
|
||||
0,
|
||||
"",
|
||||
"Name of a custom operator to invoke when activating an item");
|
||||
RNA_def_string(func,
|
||||
"drag_operator",
|
||||
NULL,
|
||||
0,
|
||||
"",
|
||||
"Name of a custom operator to invoke when starting to drag an item. Never "
|
||||
"invoked together with the `active_operator` (if set), it's either the drag or "
|
||||
"the activate one");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -107,6 +107,18 @@ static void rna_WorkSpace_owner_ids_clear(WorkSpace *workspace)
|
||||
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, workspace);
|
||||
}
|
||||
|
||||
static int rna_WorkSpace_active_asset_library_get(PointerRNA *ptr)
|
||||
{
|
||||
const WorkSpace *workspace = ptr->data;
|
||||
return rna_asset_library_reference_get(&workspace->active_asset_library);
|
||||
}
|
||||
|
||||
static void rna_WorkSpace_active_asset_library_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
WorkSpace *workspace = ptr->data;
|
||||
rna_asset_library_reference_set(&workspace->active_asset_library, value);
|
||||
}
|
||||
|
||||
static bToolRef *rna_WorkSpace_tools_from_tkey(WorkSpace *workspace,
|
||||
const bToolKey *tkey,
|
||||
bool create)
|
||||
@@ -407,6 +419,14 @@ static void rna_def_workspace(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Use UI Tags", "Filter the UI by tags");
|
||||
RNA_def_property_update(prop, 0, "rna_window_update_all");
|
||||
|
||||
prop = rna_def_asset_library_reference_common(
|
||||
srna, "rna_WorkSpace_active_asset_library_get", "rna_WorkSpace_active_asset_library_set");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Asset Library",
|
||||
"Active asset library to show in the UI, not used by the Asset Browser "
|
||||
"(which has its own active asset library)");
|
||||
RNA_def_property_update(prop, NC_ASSET | ND_ASSET_LIST_READING, NULL);
|
||||
|
||||
RNA_api_workspace(srna);
|
||||
}
|
||||
|
||||
|
@@ -255,6 +255,8 @@ static void geo_node_mesh_primitive_cone_exec(GeoNodeExecParams params)
|
||||
|
||||
BKE_mesh_translate(mesh, float3(0.0f, 0.0f, depth * 0.5f), false);
|
||||
|
||||
BKE_mesh_translate(mesh, float3(0.0f, 0.0f, depth * 0.5f), false);
|
||||
|
||||
params.set_output("Geometry", GeometrySet::create_with_mesh(mesh));
|
||||
}
|
||||
|
||||
|
@@ -434,6 +434,12 @@ typedef struct wmNotifier {
|
||||
#define ND_SPACE_FILE_PREVIEW (21 << 16)
|
||||
#define ND_SPACE_SPREADSHEET (22 << 16)
|
||||
|
||||
/* NC_ASSET */
|
||||
/* Denotes that the AssetList is done reading some previews. NOT that the preview generation of
|
||||
* assets is done. */
|
||||
#define ND_ASSET_LIST_PREVIEW (1 << 16)
|
||||
#define ND_ASSET_LIST_READING (2 << 16)
|
||||
|
||||
/* subtype, 256 entries too */
|
||||
#define NOTE_SUBTYPE 0x0000FF00
|
||||
|
||||
|
@@ -61,6 +61,7 @@
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_fileselect.h"
|
||||
#include "ED_info.h"
|
||||
#include "ED_screen.h"
|
||||
@@ -326,6 +327,7 @@ void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
ED_assetlist_storage_id_remap(old_id, new_id);
|
||||
|
||||
wmWindowManager *wm = bmain->wm.first;
|
||||
if (wm && wm->message_bus) {
|
||||
|
@@ -109,6 +109,7 @@
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_armature.h"
|
||||
#include "ED_asset.h"
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
#include "ED_keyframing.h"
|
||||
@@ -566,6 +567,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
|
||||
RE_engines_exit();
|
||||
|
||||
ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */
|
||||
ED_assetlist_storage_exit();
|
||||
|
||||
if (wm) {
|
||||
/* Before BKE_blender_free! - since the ListBases get freed there. */
|
||||
|
Reference in New Issue
Block a user