WIP: Brush assets project #106303
|
@ -234,11 +234,6 @@ std::string AS_asset_library_find_suitable_root_path_from_path(blender::StringRe
|
|||
*/
|
||||
std::string AS_asset_library_find_suitable_root_path_from_main(const Main *bmain);
|
||||
|
||||
blender::asset_system::AssetCatalogService *AS_asset_library_get_catalog_service(
|
||||
const blender::asset_system::AssetLibrary *library);
|
||||
blender::asset_system::AssetCatalogTree *AS_asset_library_get_catalog_tree(
|
||||
const blender::asset_system::AssetLibrary *library);
|
||||
|
||||
/**
|
||||
* Force clearing of all asset library data. After calling this, new asset libraries can be loaded
|
||||
* just as usual using #AS_asset_library_load(), no init or other setup is needed.
|
||||
|
@ -257,10 +252,6 @@ void AS_asset_libraries_exit();
|
|||
blender::asset_system::AssetLibrary *AS_asset_library_load(const char *name,
|
||||
const char *library_dirpath);
|
||||
|
||||
/** Look up the asset's catalog and copy its simple name into #asset_data. */
|
||||
void AS_asset_library_refresh_catalog_simplename(
|
||||
blender::asset_system::AssetLibrary *asset_library, AssetMetaData *asset_data);
|
||||
|
||||
/** Return whether any loaded AssetLibrary has unsaved changes to its catalogs. */
|
||||
bool AS_asset_library_has_any_unsaved_catalogs(void);
|
||||
|
||||
|
|
|
@ -317,7 +317,7 @@ static std::string asset_definition_default_file_path_from_dir(StringRef asset_l
|
|||
|
||||
void AssetCatalogService::load_from_disk()
|
||||
{
|
||||
load_from_disk(asset_library_root_);
|
||||
this->load_from_disk(asset_library_root_);
|
||||
}
|
||||
|
||||
void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_directory_path)
|
||||
|
@ -330,10 +330,10 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
|
|||
}
|
||||
|
||||
if (S_ISREG(status.st_mode)) {
|
||||
load_single_file(file_or_directory_path);
|
||||
this->load_single_file(file_or_directory_path);
|
||||
}
|
||||
else if (S_ISDIR(status.st_mode)) {
|
||||
load_directory_recursive(file_or_directory_path);
|
||||
this->load_directory_recursive(file_or_directory_path);
|
||||
}
|
||||
else {
|
||||
/* TODO(@sybren): throw an appropriate exception. */
|
||||
|
@ -341,7 +341,7 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
|
|||
|
||||
/* TODO: Should there be a sanitize step? E.g. to remove catalogs with identical paths? */
|
||||
|
||||
rebuild_tree();
|
||||
this->rebuild_tree();
|
||||
}
|
||||
|
||||
void AssetCatalogService::add_from_existing(const AssetCatalogService &other_service)
|
||||
|
@ -423,7 +423,7 @@ void AssetCatalogService::reload_catalogs()
|
|||
const CatalogID catalog_id = catalog->catalog_id;
|
||||
cats_in_file.add(catalog_id);
|
||||
|
||||
const bool should_skip = is_catalog_known_with_unsaved_changes(catalog_id);
|
||||
const bool should_skip = this->is_catalog_known_with_unsaved_changes(catalog_id);
|
||||
if (should_skip) {
|
||||
/* Do not overwrite unsaved local changes. */
|
||||
return false;
|
||||
|
@ -447,7 +447,7 @@ void AssetCatalogService::purge_catalogs_not_listed(const Set<CatalogID> &catalo
|
|||
if (catalogs_to_keep.contains(cat_id)) {
|
||||
continue;
|
||||
}
|
||||
if (is_catalog_known_with_unsaved_changes(cat_id)) {
|
||||
if (this->is_catalog_known_with_unsaved_changes(cat_id)) {
|
||||
continue;
|
||||
}
|
||||
/* This catalog is not on disk, but also not modified, so get rid of it. */
|
||||
|
@ -455,7 +455,7 @@ void AssetCatalogService::purge_catalogs_not_listed(const Set<CatalogID> &catalo
|
|||
}
|
||||
|
||||
for (CatalogID cat_id : cats_to_remove) {
|
||||
delete_catalog_by_id_hard(cat_id);
|
||||
this->delete_catalog_by_id_hard(cat_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,12 +481,12 @@ bool AssetCatalogService::write_to_disk(const CatalogFilePath &blend_file_path)
|
|||
{
|
||||
BLI_assert(!is_read_only_);
|
||||
|
||||
if (!write_to_disk_ex(blend_file_path)) {
|
||||
if (!this->write_to_disk_ex(blend_file_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
untag_has_unsaved_changes();
|
||||
rebuild_tree();
|
||||
this->untag_has_unsaved_changes();
|
||||
this->rebuild_tree();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -496,7 +496,7 @@ bool AssetCatalogService::write_to_disk_ex(const CatalogFilePath &blend_file_pat
|
|||
|
||||
/* - Already loaded a CDF from disk? -> Always write to that file. */
|
||||
if (catalog_collection_->catalog_definition_file_) {
|
||||
reload_catalogs();
|
||||
this->reload_catalogs();
|
||||
return catalog_collection_->catalog_definition_file_->write_to_disk();
|
||||
}
|
||||
|
||||
|
@ -507,9 +507,10 @@ bool AssetCatalogService::write_to_disk_ex(const CatalogFilePath &blend_file_pat
|
|||
return true; /* Writing nothing when there is nothing to write is still a success. */
|
||||
}
|
||||
|
||||
const CatalogFilePath cdf_path_to_write = find_suitable_cdf_path_for_writing(blend_file_path);
|
||||
catalog_collection_->catalog_definition_file_ = construct_cdf_in_memory(cdf_path_to_write);
|
||||
reload_catalogs();
|
||||
const CatalogFilePath cdf_path_to_write = this->find_suitable_cdf_path_for_writing(
|
||||
blend_file_path);
|
||||
catalog_collection_->catalog_definition_file_ = this->construct_cdf_in_memory(cdf_path_to_write);
|
||||
this->reload_catalogs();
|
||||
return catalog_collection_->catalog_definition_file_->write_to_disk();
|
||||
}
|
||||
|
||||
|
@ -528,7 +529,7 @@ void AssetCatalogService::prepare_to_merge_on_write()
|
|||
|
||||
/* Mark all in-memory catalogs as "dirty", to force them to be kept around on
|
||||
* the next "load-merge-write" cycle. */
|
||||
tag_all_catalogs_as_unsaved_changes();
|
||||
this->tag_all_catalogs_as_unsaved_changes();
|
||||
}
|
||||
|
||||
CatalogFilePath AssetCatalogService::find_suitable_cdf_path_for_writing(
|
||||
|
@ -590,8 +591,8 @@ std::unique_ptr<AssetCatalogTree> AssetCatalogService::read_into_tree()
|
|||
|
||||
void AssetCatalogService::rebuild_tree()
|
||||
{
|
||||
create_missing_catalogs();
|
||||
this->catalog_tree_ = read_into_tree();
|
||||
this->create_missing_catalogs();
|
||||
this->catalog_tree_ = this->read_into_tree();
|
||||
}
|
||||
|
||||
void AssetCatalogService::create_missing_catalogs()
|
||||
|
@ -661,7 +662,7 @@ void AssetCatalogService::redo()
|
|||
|
||||
undo_snapshots_.append(std::move(catalog_collection_));
|
||||
catalog_collection_ = redo_snapshots_.pop_last();
|
||||
rebuild_tree();
|
||||
this->rebuild_tree();
|
||||
AssetLibraryService::get()->rebuild_all_library();
|
||||
}
|
||||
|
||||
|
|
|
@ -94,29 +94,6 @@ std::string AS_asset_library_find_suitable_root_path_from_main(const Main *bmain
|
|||
return AS_asset_library_find_suitable_root_path_from_path(bmain->filepath);
|
||||
}
|
||||
|
||||
AssetCatalogService *AS_asset_library_get_catalog_service(const AssetLibrary *library)
|
||||
{
|
||||
if (library == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return library->catalog_service.get();
|
||||
}
|
||||
|
||||
AssetCatalogTree *AS_asset_library_get_catalog_tree(const AssetLibrary *library)
|
||||
{
|
||||
AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(library);
|
||||
if (catalog_service == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return catalog_service->get_catalog_tree();
|
||||
}
|
||||
|
||||
void AS_asset_library_refresh_catalog_simplename(AssetLibrary *asset_library,
|
||||
AssetMetaData *asset_data)
|
||||
{
|
||||
asset_library->refresh_catalog_simplename(asset_data);
|
||||
}
|
||||
|
||||
void AS_asset_library_remap_ids(const bke::id::IDRemapper &mappings)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ OnDiskAssetLibrary::OnDiskAssetLibrary(eAssetLibraryType library_type,
|
|||
StringRef root_path)
|
||||
: AssetLibrary(library_type, name, root_path)
|
||||
{
|
||||
on_blend_save_handler_register();
|
||||
this->on_blend_save_handler_register();
|
||||
}
|
||||
|
||||
void OnDiskAssetLibrary::refresh_catalogs()
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace blender::asset_system {
|
|||
|
||||
RuntimeAssetLibrary::RuntimeAssetLibrary() : AssetLibrary(ASSET_LIBRARY_LOCAL)
|
||||
{
|
||||
on_blend_save_handler_register();
|
||||
this->on_blend_save_handler_register();
|
||||
}
|
||||
|
||||
} // namespace blender::asset_system
|
||||
|
|
|
@ -74,7 +74,7 @@ AssetLibrary *AssetLibraryService::get_asset_library(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return get_asset_library_on_disk_builtin(type, root_path);
|
||||
return this->get_asset_library_on_disk_builtin(type, root_path);
|
||||
}
|
||||
case ASSET_LIBRARY_LOCAL: {
|
||||
/* For the "Current File" library we get the asset library root path based on main. */
|
||||
|
@ -83,14 +83,14 @@ AssetLibrary *AssetLibraryService::get_asset_library(
|
|||
|
||||
if (root_path.empty()) {
|
||||
/* File wasn't saved yet. */
|
||||
return get_asset_library_current_file();
|
||||
return this->get_asset_library_current_file();
|
||||
}
|
||||
return get_asset_library_on_disk_builtin(type, root_path);
|
||||
return this->get_asset_library_on_disk_builtin(type, root_path);
|
||||
}
|
||||
case ASSET_LIBRARY_ALL:
|
||||
return get_asset_library_all(bmain);
|
||||
return this->get_asset_library_all(bmain);
|
||||
case ASSET_LIBRARY_CUSTOM: {
|
||||
bUserAssetLibrary *custom_library = find_custom_asset_library_from_library_ref(
|
||||
bUserAssetLibrary *custom_library = this->find_custom_asset_library_from_library_ref(
|
||||
library_reference);
|
||||
if (!custom_library) {
|
||||
return nullptr;
|
||||
|
@ -101,7 +101,8 @@ AssetLibrary *AssetLibraryService::get_asset_library(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
AssetLibrary *library = get_asset_library_on_disk_custom(custom_library->name, root_path);
|
||||
AssetLibrary *library = this->get_asset_library_on_disk_custom(custom_library->name,
|
||||
root_path);
|
||||
library->import_method_ = eAssetImportMethod(custom_library->import_method);
|
||||
library->may_override_import_method_ = true;
|
||||
library->use_relative_path_ = (custom_library->flag & ASSET_LIBRARY_RELATIVE_PATH) != 0;
|
||||
|
@ -156,7 +157,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(eAssetLibraryType l
|
|||
AssetLibrary *AssetLibraryService::get_asset_library_on_disk_custom(StringRef name,
|
||||
StringRefNull root_path)
|
||||
{
|
||||
return get_asset_library_on_disk(ASSET_LIBRARY_CUSTOM, name, root_path);
|
||||
return this->get_asset_library_on_disk(ASSET_LIBRARY_CUSTOM, name, root_path);
|
||||
}
|
||||
|
||||
AssetLibrary *AssetLibraryService::get_asset_library_on_disk_builtin(eAssetLibraryType type,
|
||||
|
@ -168,7 +169,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk_builtin(eAssetLibra
|
|||
|
||||
/* Builtin asset libraries don't need a name, the #eAssetLibraryType is enough to identify them
|
||||
* (and doesn't change, unlike the name). */
|
||||
return get_asset_library_on_disk(type, {}, root_path);
|
||||
return this->get_asset_library_on_disk(type, {}, root_path);
|
||||
}
|
||||
|
||||
AssetLibrary *AssetLibraryService::get_asset_library_current_file()
|
||||
|
@ -203,7 +204,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain)
|
|||
}
|
||||
|
||||
/* Ensure all asset libraries are loaded. */
|
||||
get_asset_library(bmain, library_ref);
|
||||
this->get_asset_library(bmain, library_ref);
|
||||
}
|
||||
|
||||
if (all_library_) {
|
||||
|
@ -249,8 +250,8 @@ std::string AssetLibraryService::resolve_asset_weak_reference_to_library_path(
|
|||
|
||||
switch (eAssetLibraryType(asset_reference.asset_library_type)) {
|
||||
case ASSET_LIBRARY_CUSTOM: {
|
||||
bUserAssetLibrary *custom_lib = find_custom_preferences_asset_library_from_asset_weak_ref(
|
||||
asset_reference);
|
||||
bUserAssetLibrary *custom_lib =
|
||||
this->find_custom_preferences_asset_library_from_asset_weak_ref(asset_reference);
|
||||
if (custom_lib) {
|
||||
library_dirpath = custom_lib->dirpath;
|
||||
break;
|
||||
|
@ -258,7 +259,7 @@ std::string AssetLibraryService::resolve_asset_weak_reference_to_library_path(
|
|||
|
||||
/* A bit of an odd-ball, the API supports loading custom libraries from arbitrary paths (used
|
||||
* by unit tests). So check all loaded on-disk libraries too. */
|
||||
AssetLibrary *loaded_custom_lib = find_loaded_on_disk_asset_library_from_name(
|
||||
AssetLibrary *loaded_custom_lib = this->find_loaded_on_disk_asset_library_from_name(
|
||||
asset_reference.asset_library_identifier);
|
||||
if (!loaded_custom_lib) {
|
||||
return "";
|
||||
|
@ -368,7 +369,7 @@ std::optional<AssetLibraryService::ExplodedPath> AssetLibraryService::
|
|||
|
||||
switch (eAssetLibraryType(asset_reference.asset_library_type)) {
|
||||
case ASSET_LIBRARY_LOCAL: {
|
||||
std::string path_in_file = normalize_asset_weak_reference_relative_asset_identifier(
|
||||
std::string path_in_file = this->normalize_asset_weak_reference_relative_asset_identifier(
|
||||
asset_reference);
|
||||
const int64_t group_len = int64_t(path_in_file.find(SEP));
|
||||
|
||||
|
@ -381,14 +382,14 @@ std::optional<AssetLibraryService::ExplodedPath> AssetLibraryService::
|
|||
}
|
||||
case ASSET_LIBRARY_CUSTOM:
|
||||
case ASSET_LIBRARY_ESSENTIALS: {
|
||||
std::string full_path = resolve_asset_weak_reference_to_full_path(asset_reference);
|
||||
std::string full_path = this->resolve_asset_weak_reference_to_full_path(asset_reference);
|
||||
/* #full_path uses native slashes, so others don't need to be considered in the following. */
|
||||
|
||||
if (full_path.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
int64_t blendfile_extension_pos = rfind_blendfile_extension(full_path);
|
||||
int64_t blendfile_extension_pos = this->rfind_blendfile_extension(full_path);
|
||||
BLI_assert(blendfile_extension_pos != StringRef::not_found);
|
||||
|
||||
size_t group_pos = full_path.find(SEP, blendfile_extension_pos);
|
||||
|
|
|
@ -306,6 +306,9 @@ inline int edge_other_vert(const int2 edge, const int vert)
|
|||
|
||||
} // namespace mesh
|
||||
|
||||
/** Create a mesh with no built-in attributes. */
|
||||
Mesh *mesh_new_no_attributes(int verts_num, int edges_num, int faces_num, int corners_num);
|
||||
|
||||
/** Calculate edges from faces. */
|
||||
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges);
|
||||
|
||||
|
|
|
@ -52,18 +52,10 @@ AssetMetaData *BKE_asset_metadata_copy(const AssetMetaData *source)
|
|||
|
||||
BKE_asset_metadata_catalog_id_set(copy, source->catalog_id, source->catalog_simple_name);
|
||||
|
||||
if (source->author) {
|
||||
copy->author = BLI_strdup(source->author);
|
||||
}
|
||||
if (source->description) {
|
||||
copy->description = BLI_strdup(source->description);
|
||||
}
|
||||
if (source->copyright) {
|
||||
copy->copyright = BLI_strdup(source->copyright);
|
||||
}
|
||||
if (source->license) {
|
||||
copy->license = BLI_strdup(source->license);
|
||||
}
|
||||
copy->author = BLI_strdup_null(source->author);
|
||||
copy->description = BLI_strdup_null(source->description);
|
||||
copy->copyright = BLI_strdup_null(source->copyright);
|
||||
copy->license = BLI_strdup_null(source->license);
|
||||
|
||||
BLI_duplicatelist(©->tags, &source->tags);
|
||||
copy->active_tag = source->active_tag;
|
||||
|
|
|
@ -252,7 +252,7 @@ static void test_idprop(const IDProperty *id_property,
|
|||
|
||||
static void test_idprop(const IDProperty *id_property,
|
||||
StringRef expected_name,
|
||||
const Vector<int32_t> &values)
|
||||
const Span<int32_t> values)
|
||||
{
|
||||
ASSERT_NE(id_property, nullptr);
|
||||
EXPECT_EQ(id_property->type, IDP_ARRAY);
|
||||
|
@ -267,7 +267,7 @@ static void test_idprop(const IDProperty *id_property,
|
|||
|
||||
static void test_idprop(const IDProperty *id_property,
|
||||
StringRef expected_name,
|
||||
const Vector<float> &values)
|
||||
const Span<float> values)
|
||||
{
|
||||
ASSERT_NE(id_property, nullptr);
|
||||
EXPECT_EQ(id_property->type, IDP_ARRAY);
|
||||
|
@ -282,7 +282,7 @@ static void test_idprop(const IDProperty *id_property,
|
|||
|
||||
static void test_idprop(const IDProperty *id_property,
|
||||
StringRef expected_name,
|
||||
const Vector<double> &values)
|
||||
const Span<double> values)
|
||||
{
|
||||
ASSERT_NE(id_property, nullptr);
|
||||
EXPECT_EQ(id_property->type, IDP_ARRAY);
|
||||
|
|
|
@ -702,6 +702,26 @@ Mesh *BKE_mesh_new_nomain(const int verts_num,
|
|||
return mesh;
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
Mesh *mesh_new_no_attributes(const int verts_num,
|
||||
const int edges_num,
|
||||
const int faces_num,
|
||||
const int corners_num)
|
||||
{
|
||||
Mesh *mesh = BKE_mesh_new_nomain(0, 0, faces_num, 0);
|
||||
mesh->verts_num = verts_num;
|
||||
mesh->edges_num = edges_num;
|
||||
mesh->corners_num = corners_num;
|
||||
CustomData_free_layer_named(&mesh->vert_data, "position", 0);
|
||||
CustomData_free_layer_named(&mesh->edge_data, ".edge_verts", 0);
|
||||
CustomData_free_layer_named(&mesh->corner_data, ".corner_vert", 0);
|
||||
CustomData_free_layer_named(&mesh->corner_data, ".corner_edge", 0);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
static void copy_attribute_names(const Mesh &mesh_src, Mesh &mesh_dst)
|
||||
{
|
||||
if (mesh_src.active_color_attribute) {
|
||||
|
|
|
@ -1384,8 +1384,7 @@ static void mesh_normals_corner_custom_set(const Span<float3> positions,
|
|||
* We know those two corners do not point to the same edge,
|
||||
* since we do not allow reversed winding in a same smooth fan. */
|
||||
const IndexRange face = faces[corner_to_face[lidx]];
|
||||
const int corner_prev = (lidx == face.start()) ? face.start() + face.size() - 1 :
|
||||
lidx - 1;
|
||||
const int corner_prev = face_corner_prev(face, lidx);
|
||||
const int edge = corner_edges[lidx];
|
||||
const int edge_prev = corner_edges[corner_prev];
|
||||
const int prev_edge = corner_edges[prev_corner];
|
||||
|
@ -1408,8 +1407,7 @@ static void mesh_normals_corner_custom_set(const Span<float3> positions,
|
|||
|
||||
if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
|
||||
const IndexRange face = faces[corner_to_face[lidx]];
|
||||
const int corner_prev = (lidx == face.start()) ? face.start() + face.size() - 1 :
|
||||
lidx - 1;
|
||||
const int corner_prev = face_corner_prev(face, lidx);
|
||||
const int edge = corner_edges[lidx];
|
||||
const int edge_prev = corner_edges[corner_prev];
|
||||
const int prev_edge = corner_edges[prev_corner];
|
||||
|
|
|
@ -472,7 +472,7 @@ struct Rows {
|
|||
return selected_pixels;
|
||||
}
|
||||
|
||||
void pack_into(const Vector<std::reference_wrapper<Pixel>> &selected_pixels,
|
||||
void pack_into(const Span<std::reference_wrapper<Pixel>> selected_pixels,
|
||||
CopyPixelTile ©_tile) const
|
||||
{
|
||||
std::optional<std::reference_wrapper<CopyPixelGroup>> last_group = std::nullopt;
|
||||
|
|
|
@ -98,7 +98,7 @@ template<typename T> class StringSearch : private StringSearchBase {
|
|||
* \param weight: Can be used to customize the order when multiple items have the same match
|
||||
* score.
|
||||
*/
|
||||
void add(const StringRefNull str, T *user_data, const int weight = 0)
|
||||
void add(const StringRef str, T *user_data, const int weight = 0)
|
||||
{
|
||||
this->add_impl(str, (void *)user_data, weight);
|
||||
}
|
||||
|
|
|
@ -1836,9 +1836,7 @@ void get_next_crossing_from_edge(CrossData<T> *cd,
|
|||
}
|
||||
}
|
||||
|
||||
constexpr int inline_crossings_size = 128;
|
||||
template<typename T>
|
||||
void dump_crossings(const Vector<CrossData<T>, inline_crossings_size> &crossings)
|
||||
template<typename T> void dump_crossings(const Span<CrossData<T>> crossings)
|
||||
{
|
||||
std::cout << "CROSSINGS\n";
|
||||
for (int i = 0; i < crossings.size(); ++i) {
|
||||
|
@ -1917,7 +1915,7 @@ void add_edge_constraint(
|
|||
* one hop. Saves a bunch of orient2d tests in that common case.
|
||||
*/
|
||||
int visit = ++cdt_state->visit_count;
|
||||
Vector<CrossData<T>, inline_crossings_size> crossings;
|
||||
Vector<CrossData<T>, 128> crossings;
|
||||
crossings.append(CrossData<T>(T(0), v1, nullptr, nullptr));
|
||||
int n;
|
||||
while (!((n = crossings.size()) > 0 && crossings[n - 1].vert == v2)) {
|
||||
|
@ -1949,7 +1947,7 @@ void add_edge_constraint(
|
|||
}
|
||||
|
||||
if (dbg_level > 0) {
|
||||
dump_crossings(crossings);
|
||||
dump_crossings<T>(crossings);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -149,7 +149,7 @@ class TriMeshTopology : NonCopyable {
|
|||
|
||||
/* Which edges are incident on the given vertex?
|
||||
* We assume v has some incident edges. */
|
||||
const Vector<Edge> &vert_edges(const Vert *v) const
|
||||
Span<Edge> vert_edges(const Vert *v) const
|
||||
{
|
||||
return vert_edges_.lookup(v);
|
||||
}
|
||||
|
@ -1540,7 +1540,7 @@ static int find_ambient_cell(const IMesh &tm,
|
|||
/* Find edge attached to v_extreme with max absolute slope
|
||||
* when projected onto the XY plane. That edge is guaranteed to
|
||||
* be on the convex hull of the mesh. */
|
||||
const Vector<Edge> &edges = tmtopo.vert_edges(v_extreme);
|
||||
const Span<Edge> edges = tmtopo.vert_edges(v_extreme);
|
||||
const mpq_class &extreme_x = v_extreme->co_exact.x;
|
||||
const mpq_class &extreme_y = v_extreme->co_exact.y;
|
||||
Edge ehull;
|
||||
|
@ -1625,7 +1625,7 @@ static Edge find_good_sorting_edge(const Vert *testp,
|
|||
mpq_class nlen2 = math::length_squared(normal);
|
||||
mpq_class max_abs_slope = -1;
|
||||
Edge esort;
|
||||
const Vector<Edge> &edges = tmtopo.vert_edges(closestp);
|
||||
const Span<Edge> edges = tmtopo.vert_edges(closestp);
|
||||
for (Edge e : edges) {
|
||||
const Vert *v_other = (e.v0() == closestp) ? e.v1() : e.v0();
|
||||
const mpq3 &co_other = v_other->co_exact;
|
||||
|
@ -1697,7 +1697,7 @@ static int find_containing_cell(const Vert *v,
|
|||
if (close_edge != -1) {
|
||||
const Vert *v0 = tri[close_edge];
|
||||
const Vert *v1 = tri[(close_edge + 1) % 3];
|
||||
const Vector<Edge> &edges = tmtopo.vert_edges(v0);
|
||||
const Span<Edge> edges = tmtopo.vert_edges(v0);
|
||||
if (dbg_level > 0) {
|
||||
std::cout << "look for edge containing " << v0 << " and " << v1 << "\n";
|
||||
std::cout << " in edges: ";
|
||||
|
@ -1907,7 +1907,7 @@ struct ComponentContainer {
|
|||
* (maybe not directly nested, which is why there can be more than one).
|
||||
*/
|
||||
static Vector<ComponentContainer> find_component_containers(int comp,
|
||||
const Vector<Vector<int>> &components,
|
||||
const Span<Vector<int>> components,
|
||||
const Array<int> &ambient_cell,
|
||||
const IMesh &tm,
|
||||
const PatchesInfo &pinfo,
|
||||
|
@ -2022,7 +2022,7 @@ static Vector<ComponentContainer> find_component_containers(int comp,
|
|||
* by an appropriate epsilon so that we conservatively will say
|
||||
* that components could intersect if the BBs overlap.
|
||||
*/
|
||||
static void populate_comp_bbs(const Vector<Vector<int>> &components,
|
||||
static void populate_comp_bbs(const Span<Vector<int>> components,
|
||||
const PatchesInfo &pinfo,
|
||||
const IMesh &im,
|
||||
Array<BoundingBox> &comp_bb)
|
||||
|
@ -2970,7 +2970,7 @@ static std::ostream &operator<<(std::ostream &os, const FaceMergeState &fms)
|
|||
* Hence, try to be tolerant of such unexpected topology.
|
||||
*/
|
||||
static void init_face_merge_state(FaceMergeState *fms,
|
||||
const Vector<int> &tris,
|
||||
const Span<int> tris,
|
||||
const IMesh &tm,
|
||||
const double3 &norm)
|
||||
{
|
||||
|
@ -3507,7 +3507,7 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
|
|||
Array<Face *> face(tot_out_face);
|
||||
int out_f_index = 0;
|
||||
for (int in_f : imesh_in.face_index_range()) {
|
||||
const Vector<Face *> &f_faces = face_output_face[in_f];
|
||||
const Span<Face *> f_faces = face_output_face[in_f];
|
||||
if (f_faces.size() > 0) {
|
||||
std::copy(f_faces.begin(), f_faces.end(), &face[out_f_index]);
|
||||
out_f_index += f_faces.size();
|
||||
|
|
|
@ -87,8 +87,8 @@ ExecutionSystem::~ExecutionSystem()
|
|||
groups_.clear();
|
||||
}
|
||||
|
||||
void ExecutionSystem::set_operations(const Vector<NodeOperation *> &operations,
|
||||
const Vector<ExecutionGroup *> &groups)
|
||||
void ExecutionSystem::set_operations(const Span<NodeOperation *> operations,
|
||||
const Span<ExecutionGroup *> groups)
|
||||
{
|
||||
operations_ = operations;
|
||||
groups_ = groups;
|
||||
|
|
|
@ -178,8 +178,7 @@ class ExecutionSystem {
|
|||
*/
|
||||
~ExecutionSystem();
|
||||
|
||||
void set_operations(const Vector<NodeOperation *> &operations,
|
||||
const Vector<ExecutionGroup *> &groups);
|
||||
void set_operations(Span<NodeOperation *> operations, Span<ExecutionGroup *> groups);
|
||||
|
||||
/**
|
||||
* \brief execute this system
|
||||
|
|
|
@ -98,7 +98,7 @@ class Node {
|
|||
/**
|
||||
* \brief get access to the vector of input sockets
|
||||
*/
|
||||
const Vector<NodeInput *> &get_input_sockets() const
|
||||
Span<NodeInput *> get_input_sockets() const
|
||||
{
|
||||
return inputs_;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ class Node {
|
|||
/**
|
||||
* \brief get access to the vector of input sockets
|
||||
*/
|
||||
const Vector<NodeOutput *> &get_output_sockets() const
|
||||
Span<NodeOutput *> get_output_sockets() const
|
||||
{
|
||||
return outputs_;
|
||||
}
|
||||
|
|
|
@ -37,11 +37,11 @@ class NodeGraph {
|
|||
public:
|
||||
~NodeGraph();
|
||||
|
||||
const Vector<Node *> &nodes() const
|
||||
Span<Node *> nodes() const
|
||||
{
|
||||
return nodes_;
|
||||
}
|
||||
const Vector<Link> &links() const
|
||||
Span<Link> links() const
|
||||
{
|
||||
return links_;
|
||||
}
|
||||
|
|
|
@ -107,12 +107,12 @@ class NodeOperationBuilder {
|
|||
return active_viewer_;
|
||||
}
|
||||
|
||||
const Vector<NodeOperation *> &get_operations() const
|
||||
Span<NodeOperation *> get_operations() const
|
||||
{
|
||||
return operations_;
|
||||
}
|
||||
|
||||
const Vector<Link> &get_links() const
|
||||
Span<Link> get_links() const
|
||||
{
|
||||
return links_;
|
||||
}
|
||||
|
|
|
@ -564,6 +564,7 @@ set(GLSL_SRC
|
|||
engines/eevee_next/shaders/eevee_ray_trace_screen_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_ray_trace_screen_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_ray_types_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_convolve_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_eval_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_lib.glsl
|
||||
engines/eevee_next/shaders/eevee_reflection_probe_remap_comp.glsl
|
||||
|
|
|
@ -97,7 +97,7 @@ struct SphereProbeAtlasCoord {
|
|||
{
|
||||
SphereProbePixelArea coord;
|
||||
coord.extent = atlas_extent >> (subdivision_lvl + mip_lvl);
|
||||
coord.offset = (area_location() * coord.extent) >> mip_lvl;
|
||||
coord.offset = area_location() * coord.extent;
|
||||
coord.layer = atlas_layer;
|
||||
return coord;
|
||||
}
|
||||
|
|
|
@ -46,10 +46,20 @@ void SphereProbeModule::begin_sync()
|
|||
pass.push_constant("probe_coord_packed", reinterpret_cast<int4 *>(&probe_sampling_coord_));
|
||||
pass.push_constant("write_coord_packed", reinterpret_cast<int4 *>(&probe_write_coord_));
|
||||
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_data.atlas_coord));
|
||||
pass.push_constant("mip_level", &probe_mip_level_);
|
||||
pass.push_constant("probe_brightness_clamp", probe_brightness_clamp);
|
||||
pass.dispatch(&dispatch_probe_pack_);
|
||||
}
|
||||
{
|
||||
PassSimple &pass = convolve_ps_;
|
||||
pass.init();
|
||||
pass.shader_set(instance_.shaders.static_shader_get(SPHERE_PROBE_CONVOLVE));
|
||||
pass.bind_image("in_atlas_mip_img", &convolve_input_);
|
||||
pass.bind_image("out_atlas_mip_img", &convolve_output_);
|
||||
pass.push_constant("write_coord_packed", reinterpret_cast<int4 *>(&probe_write_coord_));
|
||||
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
pass.dispatch(&dispatch_probe_convolve_);
|
||||
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
}
|
||||
{
|
||||
PassSimple &pass = update_irradiance_ps_;
|
||||
pass.init();
|
||||
|
@ -85,6 +95,7 @@ bool SphereProbeModule::ensure_atlas()
|
|||
nullptr,
|
||||
SPHERE_PROBE_MIPMAP_LEVELS))
|
||||
{
|
||||
probes_tx_.ensure_mip_views();
|
||||
/* TODO(fclem): Clearing means that we need to render all probes again.
|
||||
* If existing data exists, copy it using `CopyImageSubData`. */
|
||||
probes_tx_.clear(float4(0.0f));
|
||||
|
@ -122,11 +133,8 @@ void SphereProbeModule::end_sync()
|
|||
|
||||
void SphereProbeModule::ensure_cubemap_render_target(int resolution)
|
||||
{
|
||||
if (cubemap_tx_.ensure_cube(
|
||||
GPU_RGBA16F, resolution, GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ))
|
||||
{
|
||||
GPU_texture_mipmap_mode(cubemap_tx_, false, true);
|
||||
}
|
||||
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ;
|
||||
cubemap_tx_.ensure_cube(GPU_RGBA16F, resolution, usage);
|
||||
/* TODO(fclem): deallocate it. */
|
||||
}
|
||||
|
||||
|
@ -185,10 +193,20 @@ void SphereProbeModule::remap_to_octahedral_projection(const SphereProbeAtlasCoo
|
|||
/* Update shader parameters that change per dispatch. */
|
||||
probe_sampling_coord_ = atlas_coord.as_sampling_coord(max_resolution_);
|
||||
probe_write_coord_ = atlas_coord.as_write_coord(max_resolution_, 0);
|
||||
probe_mip_level_ = atlas_coord.subdivision_lvl;
|
||||
dispatch_probe_pack_ = int3(int2(ceil_division(resolution, SPHERE_PROBE_GROUP_SIZE)), 1);
|
||||
|
||||
instance_.manager->submit(remap_ps_);
|
||||
|
||||
/* Populate the mip levels */
|
||||
for (auto i : IndexRange(SPHERE_PROBE_MIPMAP_LEVELS - 1)) {
|
||||
convolve_input_ = probes_tx_.mip_view(i);
|
||||
convolve_output_ = probes_tx_.mip_view(i + 1);
|
||||
probe_write_coord_ = atlas_coord.as_write_coord(max_resolution_, i + 1);
|
||||
int out_mip_res = resolution >> (i + 1);
|
||||
dispatch_probe_convolve_ = int3(int2(ceil_division(out_mip_res, SPHERE_PROBE_GROUP_SIZE)), 1);
|
||||
instance_.manager->submit(convolve_ps_);
|
||||
}
|
||||
/* Sync with atlas usage for shading. */
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
}
|
||||
|
||||
void SphereProbeModule::update_world_irradiance()
|
||||
|
@ -198,11 +216,6 @@ void SphereProbeModule::update_world_irradiance()
|
|||
instance_.volume_probes.do_update_world_ = true;
|
||||
}
|
||||
|
||||
void SphereProbeModule::update_probes_texture_mipmaps()
|
||||
{
|
||||
GPU_texture_update_mipmap_chain(probes_tx_);
|
||||
}
|
||||
|
||||
void SphereProbeModule::set_view(View & /*view*/)
|
||||
{
|
||||
Vector<SphereProbe *> probe_active;
|
||||
|
|
|
@ -53,9 +53,17 @@ class SphereProbeModule {
|
|||
PassSimple remap_ps_ = {"Probe.CubemapToOctahedral"};
|
||||
/** Extract irradiance information from the world. */
|
||||
PassSimple update_irradiance_ps_ = {"Probe.UpdateIrradiance"};
|
||||
/** Copy volume probe irradiance for the center of sphere probes. */
|
||||
PassSimple select_ps_ = {"Probe.Select"};
|
||||
/** Convolve the octahedral map to fill the Mip-map levels. */
|
||||
PassSimple convolve_ps_ = {"Probe.Convolve"};
|
||||
/** Input mip level for the convolution. */
|
||||
GPUTexture *convolve_input_ = nullptr;
|
||||
/** Output mip level for the convolution. */
|
||||
GPUTexture *convolve_output_ = nullptr;
|
||||
|
||||
int3 dispatch_probe_pack_ = int3(1);
|
||||
int3 dispatch_probe_convolve_ = int3(1);
|
||||
int3 dispatch_probe_select_ = int3(1);
|
||||
|
||||
/**
|
||||
|
@ -66,8 +74,6 @@ class SphereProbeModule {
|
|||
Texture cubemap_tx_ = {"Probe.Cubemap"};
|
||||
/** Index of the probe being updated. */
|
||||
int probe_index_ = 0;
|
||||
/** Mip level being sampled for remapping. */
|
||||
int probe_mip_level_ = 0;
|
||||
/** Updated Probe coordinates in the atlas. */
|
||||
SphereProbeUvArea probe_sampling_coord_;
|
||||
SphereProbePixelArea probe_write_coord_;
|
||||
|
@ -167,7 +173,6 @@ class SphereProbeModule {
|
|||
* Internal processing passes.
|
||||
*/
|
||||
void remap_to_octahedral_projection(const SphereProbeAtlasCoord &atlas_coord);
|
||||
void update_probes_texture_mipmaps();
|
||||
void update_world_irradiance();
|
||||
|
||||
void sync_display(Vector<SphereProbe *> &probe_active);
|
||||
|
|
|
@ -214,6 +214,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
|
|||
return "eevee_lightprobe_irradiance_ray";
|
||||
case LIGHTPROBE_IRRADIANCE_LOAD:
|
||||
return "eevee_lightprobe_irradiance_load";
|
||||
case SPHERE_PROBE_CONVOLVE:
|
||||
return "eevee_reflection_probe_convolve";
|
||||
case SPHERE_PROBE_REMAP:
|
||||
return "eevee_reflection_probe_remap";
|
||||
case SPHERE_PROBE_UPDATE_IRRADIANCE:
|
||||
|
|
|
@ -104,9 +104,10 @@ enum eShaderType {
|
|||
RAY_TRACE_PLANAR,
|
||||
RAY_TRACE_SCREEN,
|
||||
|
||||
SPHERE_PROBE_CONVOLVE,
|
||||
SPHERE_PROBE_REMAP,
|
||||
SPHERE_PROBE_UPDATE_IRRADIANCE,
|
||||
SPHERE_PROBE_SELECT,
|
||||
SPHERE_PROBE_UPDATE_IRRADIANCE,
|
||||
|
||||
SHADOW_CLIPMAP_CLEAR,
|
||||
SHADOW_DEBUG,
|
||||
|
|
|
@ -263,7 +263,6 @@ void CaptureView::render_world()
|
|||
}
|
||||
|
||||
inst_.sphere_probes.remap_to_octahedral_projection(update_info->atlas_coord);
|
||||
inst_.sphere_probes.update_probes_texture_mipmaps();
|
||||
}
|
||||
|
||||
if (update_info->do_world_irradiance_update) {
|
||||
|
@ -277,10 +276,8 @@ void CaptureView::render_probes()
|
|||
{
|
||||
Framebuffer prepass_fb;
|
||||
View view = {"Capture.View"};
|
||||
bool do_update_mipmap_chain = false;
|
||||
while (const auto update_info = inst_.sphere_probes.probe_update_info_pop()) {
|
||||
GPU_debug_group_begin("Probe.Capture");
|
||||
do_update_mipmap_chain = true;
|
||||
|
||||
if (inst_.pipelines.data.is_probe_reflection != true) {
|
||||
inst_.pipelines.data.is_probe_reflection = true;
|
||||
|
@ -334,11 +331,6 @@ void CaptureView::render_probes()
|
|||
inst_.pipelines.data.is_probe_reflection = false;
|
||||
inst_.uniform_data.push_update();
|
||||
}
|
||||
|
||||
if (do_update_mipmap_chain) {
|
||||
/* TODO: only update the regions that have been updated. */
|
||||
inst_.sphere_probes.update_probes_texture_mipmaps();
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/* Shader to convert cube-map to octahedral projection. */
|
||||
|
||||
#pragma BLENDER_REQUIRE(eevee_octahedron_lib.glsl)
|
||||
|
||||
SphereProbePixelArea reinterpret_as_write_coord(ivec4 packed_coord)
|
||||
{
|
||||
SphereProbePixelArea unpacked;
|
||||
unpacked.offset = packed_coord.xy;
|
||||
unpacked.extent = packed_coord.z;
|
||||
unpacked.layer = packed_coord.w;
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
SphereProbePixelArea write_coord = reinterpret_as_write_coord(write_coord_packed);
|
||||
|
||||
/* Texel in probe. */
|
||||
ivec2 local_texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
/* Exit when pixel being written doesn't fit in the area reserved for the probe. */
|
||||
if (any(greaterThanEqual(local_texel, ivec2(write_coord.extent)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ivec2 texel_out = write_coord.offset + local_texel;
|
||||
vec4 color = vec4(0.0);
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(0, 0), write_coord.layer));
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(1, 0), write_coord.layer));
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(0, 1), write_coord.layer));
|
||||
color += imageLoad(in_atlas_mip_img, ivec3(texel_out * 2 + ivec2(1, 1), write_coord.layer));
|
||||
color *= 0.25;
|
||||
|
||||
imageStore(out_atlas_mip_img, ivec3(texel_out, write_coord.layer), color);
|
||||
}
|
|
@ -61,7 +61,7 @@ void main()
|
|||
vec2 wrapped_uv = mirror_repeat_uv(sampling_uv);
|
||||
/* Direction in world space. */
|
||||
vec3 direction = octahedral_uv_to_direction(wrapped_uv);
|
||||
vec4 radiance_and_transmittance = textureLod(cubemap_tx, direction, float(mip_level));
|
||||
vec4 radiance_and_transmittance = texture(cubemap_tx, direction);
|
||||
vec3 radiance = radiance_and_transmittance.xyz;
|
||||
|
||||
float opacity = 1.0 - radiance_and_transmittance.a;
|
||||
|
|
|
@ -22,7 +22,6 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_remap)
|
|||
.push_constant(Type::IVEC4, "probe_coord_packed")
|
||||
.push_constant(Type::IVEC4, "write_coord_packed")
|
||||
.push_constant(Type::IVEC4, "world_coord_packed")
|
||||
.push_constant(Type::INT, "mip_level")
|
||||
.push_constant(Type::FLOAT, "probe_brightness_clamp")
|
||||
.sampler(0, ImageType::FLOAT_CUBE, "cubemap_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D_ARRAY, "atlas_tx")
|
||||
|
@ -54,6 +53,15 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_select)
|
|||
.compute_source("eevee_reflection_probe_select_comp.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_reflection_probe_convolve)
|
||||
.local_group_size(SPHERE_PROBE_GROUP_SIZE, SPHERE_PROBE_GROUP_SIZE)
|
||||
.additional_info("eevee_shared")
|
||||
.push_constant(Type::IVEC4, "write_coord_packed")
|
||||
.image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "in_atlas_mip_img")
|
||||
.image(1, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_atlas_mip_img")
|
||||
.compute_source("eevee_reflection_probe_convolve_comp.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(eevee_display_probe_reflection_iface, "")
|
||||
.smooth(Type::VEC2, "lP")
|
||||
.flat(Type::INT, "probe_index");
|
||||
|
|
|
@ -456,14 +456,13 @@ static void statvis_calc_distort(const MeshRenderData &mr, float *r_distort)
|
|||
const float *f_no = mr.face_normals[face_index];
|
||||
fac = 0.0f;
|
||||
|
||||
for (int i = 1; i <= face.size(); i++) {
|
||||
const int corner_prev = face.start() + (i - 1) % face.size();
|
||||
const int corner_curr = face.start() + (i + 0) % face.size();
|
||||
const int corner_next = face.start() + (i + 1) % face.size();
|
||||
for (const int corner : face.drop_front(1)) {
|
||||
const int corner_prev = bke::mesh::face_corner_prev(face, corner);
|
||||
const int corner_next = bke::mesh::face_corner_next(face, corner);
|
||||
float no_corner[3];
|
||||
normal_tri_v3(no_corner,
|
||||
mr.vert_positions[mr.corner_verts[corner_prev]],
|
||||
mr.vert_positions[mr.corner_verts[corner_curr]],
|
||||
mr.vert_positions[mr.corner_verts[corner]],
|
||||
mr.vert_positions[mr.corner_verts[corner_next]]);
|
||||
/* simple way to detect (what is most likely) concave */
|
||||
if (dot_v3v3(f_no, no_corner) < 0.0f) {
|
||||
|
@ -540,9 +539,9 @@ static void statvis_calc_sharp(const MeshRenderData &mr, float *r_sharp)
|
|||
|
||||
for (int face_index = 0; face_index < mr.face_len; face_index++) {
|
||||
const IndexRange face = mr.faces[face_index];
|
||||
for (int i = 0; i < face.size(); i++) {
|
||||
const int vert_curr = mr.corner_verts[face.start() + (i + 0) % face.size()];
|
||||
const int vert_next = mr.corner_verts[face.start() + (i + 1) % face.size()];
|
||||
for (const int corner : face) {
|
||||
const int vert_curr = mr.corner_verts[corner];
|
||||
const int vert_next = mr.corner_verts[bke::mesh::face_corner_next(face, corner)];
|
||||
float angle;
|
||||
eh.add_or_modify(
|
||||
{vert_curr, vert_next},
|
||||
|
|
|
@ -744,10 +744,10 @@ KeyingSet *ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *tra
|
|||
return ANIM_builtin_keyingset_get_named(transformKSName);
|
||||
}
|
||||
|
||||
static void anim_keyingset_visit_for_search_impl(const bContext *C,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data,
|
||||
const bool use_poll)
|
||||
static void anim_keyingset_visit_for_search_impl(
|
||||
const bContext *C,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn,
|
||||
const bool use_poll)
|
||||
{
|
||||
/* Poll requires context. */
|
||||
if (use_poll && (C == nullptr)) {
|
||||
|
@ -758,10 +758,10 @@ static void anim_keyingset_visit_for_search_impl(const bContext *C,
|
|||
|
||||
/* Active Keying Set. */
|
||||
if (!use_poll || (scene && scene->active_keyingset)) {
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = "__ACTIVE__";
|
||||
visit_params.info = "Active Keying Set";
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_fn(visit_params);
|
||||
}
|
||||
|
||||
/* User-defined Keying Sets. */
|
||||
|
@ -770,10 +770,10 @@ static void anim_keyingset_visit_for_search_impl(const bContext *C,
|
|||
if (use_poll && !ANIM_keyingset_context_ok_poll((bContext *)C, keyingset)) {
|
||||
continue;
|
||||
}
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = keyingset->idname;
|
||||
visit_params.info = keyingset->name;
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_fn(visit_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -782,31 +782,31 @@ static void anim_keyingset_visit_for_search_impl(const bContext *C,
|
|||
if (use_poll && !ANIM_keyingset_context_ok_poll((bContext *)C, keyingset)) {
|
||||
continue;
|
||||
}
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = keyingset->idname;
|
||||
visit_params.info = keyingset->name;
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_fn(visit_params);
|
||||
}
|
||||
}
|
||||
|
||||
void ANIM_keyingset_visit_for_search(const bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
void ANIM_keyingset_visit_for_search(
|
||||
const bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
anim_keyingset_visit_for_search_impl(C, visit_fn, visit_user_data, false);
|
||||
anim_keyingset_visit_for_search_impl(C, visit_fn, false);
|
||||
}
|
||||
|
||||
void ANIM_keyingset_visit_for_search_no_poll(const bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
void ANIM_keyingset_visit_for_search_no_poll(
|
||||
const bContext *C,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
anim_keyingset_visit_for_search_impl(C, visit_fn, visit_user_data, true);
|
||||
anim_keyingset_visit_for_search_impl(C, visit_fn, true);
|
||||
}
|
||||
|
||||
/* Menu of All Keying Sets ----------------------------- */
|
||||
|
|
|
@ -28,8 +28,7 @@ using namespace blender::asset_system;
|
|||
|
||||
bool catalogs_read_only(const AssetLibrary &library)
|
||||
{
|
||||
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
&library);
|
||||
asset_system::AssetCatalogService *catalog_service = library.catalog_service.get();
|
||||
return catalog_service->is_read_only();
|
||||
}
|
||||
|
||||
|
@ -62,12 +61,11 @@ asset_system::AssetCatalog *catalog_add(AssetLibrary *library,
|
|||
StringRefNull name,
|
||||
StringRef parent_path)
|
||||
{
|
||||
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
library);
|
||||
asset_system::AssetCatalogService *catalog_service = library->catalog_service.get();
|
||||
if (!catalog_service) {
|
||||
return nullptr;
|
||||
}
|
||||
if (catalogs_read_only(*library)) {
|
||||
if (catalog_service->is_read_only()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -87,13 +85,12 @@ asset_system::AssetCatalog *catalog_add(AssetLibrary *library,
|
|||
|
||||
void catalog_remove(AssetLibrary *library, const CatalogID &catalog_id)
|
||||
{
|
||||
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
library);
|
||||
asset_system::AssetCatalogService *catalog_service = library->catalog_service.get();
|
||||
if (!catalog_service) {
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
if (catalogs_read_only(*library)) {
|
||||
if (catalog_service->is_read_only()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,13 +104,12 @@ void catalog_rename(AssetLibrary *library,
|
|||
const CatalogID catalog_id,
|
||||
const StringRefNull new_name)
|
||||
{
|
||||
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
library);
|
||||
asset_system::AssetCatalogService *catalog_service = library->catalog_service.get();
|
||||
if (!catalog_service) {
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
if (catalogs_read_only(*library)) {
|
||||
if (catalog_service->is_read_only()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,13 +133,12 @@ void catalog_move(AssetLibrary *library,
|
|||
const CatalogID src_catalog_id,
|
||||
const std::optional<CatalogID> dst_parent_catalog_id)
|
||||
{
|
||||
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
library);
|
||||
asset_system::AssetCatalogService *catalog_service = library->catalog_service.get();
|
||||
if (!catalog_service) {
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
if (catalogs_read_only(*library)) {
|
||||
if (catalog_service->is_read_only()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -181,13 +176,12 @@ void catalog_move(AssetLibrary *library,
|
|||
|
||||
void catalogs_save_from_main_path(AssetLibrary *library, const Main *bmain)
|
||||
{
|
||||
asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
library);
|
||||
asset_system::AssetCatalogService *catalog_service = library->catalog_service.get();
|
||||
if (!catalog_service) {
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
if (catalogs_read_only(*library)) {
|
||||
if (catalog_service->is_read_only()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ struct IDVecStats {
|
|||
* Helper to report stats about the IDs in context. Operator polls use this, also to report a
|
||||
* helpful disabled hint to the user.
|
||||
*/
|
||||
static IDVecStats asset_operation_get_id_vec_stats_from_ids(const Vector<PointerRNA> &id_pointers)
|
||||
static IDVecStats asset_operation_get_id_vec_stats_from_ids(const Span<PointerRNA> id_pointers)
|
||||
{
|
||||
IDVecStats stats;
|
||||
|
||||
|
@ -125,7 +125,7 @@ static const char *asset_operation_unsupported_type_msg(const bool is_single)
|
|||
|
||||
class AssetMarkHelper {
|
||||
public:
|
||||
void operator()(const bContext &C, const Vector<PointerRNA> &ids);
|
||||
void operator()(const bContext &C, Span<PointerRNA> ids);
|
||||
|
||||
void reportResults(ReportList &reports) const;
|
||||
bool wasSuccessful() const;
|
||||
|
@ -140,7 +140,7 @@ class AssetMarkHelper {
|
|||
Stats stats;
|
||||
};
|
||||
|
||||
void AssetMarkHelper::operator()(const bContext &C, const Vector<PointerRNA> &ids)
|
||||
void AssetMarkHelper::operator()(const bContext &C, const Span<PointerRNA> ids)
|
||||
{
|
||||
for (const PointerRNA &ptr : ids) {
|
||||
BLI_assert(RNA_struct_is_ID(ptr.type));
|
||||
|
@ -190,7 +190,7 @@ void AssetMarkHelper::reportResults(ReportList &reports) const
|
|||
}
|
||||
}
|
||||
|
||||
static int asset_mark_exec(const bContext *C, const wmOperator *op, const Vector<PointerRNA> &ids)
|
||||
static int asset_mark_exec(const bContext *C, const wmOperator *op, const Span<PointerRNA> ids)
|
||||
{
|
||||
AssetMarkHelper mark_helper;
|
||||
mark_helper(*C, ids);
|
||||
|
@ -206,7 +206,7 @@ static int asset_mark_exec(const bContext *C, const wmOperator *op, const Vector
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static bool asset_mark_poll(bContext *C, const Vector<PointerRNA> &ids)
|
||||
static bool asset_mark_poll(bContext *C, const Span<PointerRNA> ids)
|
||||
{
|
||||
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_ids(ids);
|
||||
|
||||
|
@ -265,7 +265,7 @@ class AssetClearHelper {
|
|||
public:
|
||||
AssetClearHelper(const bool set_fake_user) : set_fake_user_(set_fake_user) {}
|
||||
|
||||
void operator()(const Vector<PointerRNA> &ids);
|
||||
void operator()(Span<PointerRNA> ids);
|
||||
|
||||
void reportResults(const bContext *C, ReportList &reports) const;
|
||||
bool wasSuccessful() const;
|
||||
|
@ -279,7 +279,7 @@ class AssetClearHelper {
|
|||
Stats stats;
|
||||
};
|
||||
|
||||
void AssetClearHelper::operator()(const Vector<PointerRNA> &ids)
|
||||
void AssetClearHelper::operator()(const Span<PointerRNA> ids)
|
||||
{
|
||||
for (const PointerRNA &ptr : ids) {
|
||||
BLI_assert(RNA_struct_is_ID(ptr.type));
|
||||
|
@ -332,7 +332,7 @@ bool AssetClearHelper::wasSuccessful() const
|
|||
return stats.tot_cleared > 0;
|
||||
}
|
||||
|
||||
static int asset_clear_exec(const bContext *C, const wmOperator *op, const Vector<PointerRNA> &ids)
|
||||
static int asset_clear_exec(const bContext *C, const wmOperator *op, const Span<PointerRNA> ids)
|
||||
{
|
||||
const bool set_fake_user = RNA_boolean_get(op->ptr, "set_fake_user");
|
||||
AssetClearHelper clear_helper(set_fake_user);
|
||||
|
@ -349,7 +349,7 @@ static int asset_clear_exec(const bContext *C, const wmOperator *op, const Vecto
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static bool asset_clear_poll(bContext *C, const Vector<PointerRNA> &ids)
|
||||
static bool asset_clear_poll(bContext *C, const Span<PointerRNA> ids)
|
||||
{
|
||||
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_ids(ids);
|
||||
|
||||
|
@ -587,7 +587,7 @@ static asset_system::AssetCatalogService *get_catalog_service(bContext *C)
|
|||
}
|
||||
|
||||
asset_system::AssetLibrary *asset_lib = ED_fileselect_active_asset_library_get(sfile);
|
||||
return AS_asset_library_get_catalog_service(asset_lib);
|
||||
return asset_lib->catalog_service.get();
|
||||
}
|
||||
|
||||
static int asset_catalog_undo_exec(bContext *C, wmOperator * /*op*/)
|
||||
|
|
|
@ -225,19 +225,19 @@ int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks);
|
|||
*/
|
||||
KeyingSet *ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName);
|
||||
|
||||
void ANIM_keyingset_visit_for_search(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
void ANIM_keyingset_visit_for_search(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
|
||||
void ANIM_keyingset_visit_for_search_no_poll(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
void ANIM_keyingset_visit_for_search_no_poll(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
/**
|
||||
* Dynamically populate an enum of Keying Sets.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
@ -365,51 +366,46 @@ void UI_but_func_identity_compare_set(uiBut *but, uiButIdentityCompareFunc cmp_f
|
|||
/* *** RNA collection search menu *** */
|
||||
|
||||
struct CollItemSearch {
|
||||
CollItemSearch *next, *prev;
|
||||
void *data;
|
||||
char *name;
|
||||
std::string name;
|
||||
int index;
|
||||
int iconid;
|
||||
bool is_id;
|
||||
int name_prefix_offset;
|
||||
uint has_sep_char : 1;
|
||||
bool is_id;
|
||||
bool has_sep_char;
|
||||
};
|
||||
|
||||
static bool add_collection_search_item(CollItemSearch *cis,
|
||||
static bool add_collection_search_item(CollItemSearch &cis,
|
||||
const bool requires_exact_data_name,
|
||||
const bool has_id_icon,
|
||||
uiSearchItems *items)
|
||||
{
|
||||
char name_buf[UI_MAX_DRAW_STR];
|
||||
|
||||
/* If no item has an own icon to display, libraries can use the library icons rather than the
|
||||
* name prefix for showing the library status. */
|
||||
int name_prefix_offset = cis->name_prefix_offset;
|
||||
if (!has_id_icon && cis->is_id && !requires_exact_data_name) {
|
||||
cis->iconid = UI_icon_from_library(static_cast<const ID *>(cis->data));
|
||||
/* No need to re-allocate, string should be shorter than before (lib status prefix is
|
||||
* removed). */
|
||||
int name_prefix_offset = cis.name_prefix_offset;
|
||||
if (!has_id_icon && cis.is_id && !requires_exact_data_name) {
|
||||
cis.iconid = UI_icon_from_library(static_cast<const ID *>(cis.data));
|
||||
char name_buf[UI_MAX_DRAW_STR];
|
||||
BKE_id_full_name_ui_prefix_get(
|
||||
name_buf, static_cast<const ID *>(cis->data), false, UI_SEP_CHAR, &name_prefix_offset);
|
||||
const int name_buf_len = strlen(name_buf);
|
||||
BLI_assert(name_buf_len <= strlen(cis->name));
|
||||
memcpy(cis->name, name_buf, name_buf_len + 1);
|
||||
name_buf, static_cast<const ID *>(cis.data), false, UI_SEP_CHAR, &name_prefix_offset);
|
||||
cis.name = name_buf;
|
||||
}
|
||||
|
||||
return UI_search_item_add(items,
|
||||
cis->name,
|
||||
cis->data,
|
||||
cis->iconid,
|
||||
cis->has_sep_char ? int(UI_BUT_HAS_SEP_CHAR) : 0,
|
||||
cis.name.c_str(),
|
||||
cis.data,
|
||||
cis.iconid,
|
||||
cis.has_sep_char ? int(UI_BUT_HAS_SEP_CHAR) : 0,
|
||||
name_prefix_offset);
|
||||
}
|
||||
|
||||
void ui_rna_collection_search_update_fn(
|
||||
const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
|
||||
{
|
||||
using namespace blender;
|
||||
uiRNACollectionSearch *data = static_cast<uiRNACollectionSearch *>(arg);
|
||||
const int flag = RNA_property_flag(data->target_prop);
|
||||
ListBase *items_list = MEM_cnew<ListBase>("items_list");
|
||||
const bool is_ptr_target = (RNA_property_type(data->target_prop) == PROP_POINTER);
|
||||
/* For non-pointer properties, UI code acts entirely based on the item's name. So the name has to
|
||||
* match the RNA name exactly. So only for pointer properties, the name can be modified to add
|
||||
|
@ -417,16 +413,14 @@ void ui_rna_collection_search_update_fn(
|
|||
const bool requires_exact_data_name = !is_ptr_target;
|
||||
const bool skip_filter = is_first;
|
||||
char name_buf[UI_MAX_DRAW_STR];
|
||||
char *name;
|
||||
bool has_id_icon = false;
|
||||
|
||||
blender::ui::string_search::StringSearch<CollItemSearch> search;
|
||||
/* The string search API requires pointer stability. */
|
||||
Vector<std::unique_ptr<CollItemSearch>> items_list;
|
||||
|
||||
if (data->search_prop != nullptr) {
|
||||
/* build a temporary list of relevant items first */
|
||||
int item_index = 0;
|
||||
RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
|
||||
|
||||
if (flag & PROP_ID_SELF_CHECK) {
|
||||
if (itemptr.data == data->target_ptr.owner_id) {
|
||||
continue;
|
||||
|
@ -445,6 +439,7 @@ void ui_rna_collection_search_update_fn(
|
|||
bool has_sep_char = false;
|
||||
const bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type);
|
||||
|
||||
char *name;
|
||||
if (is_id) {
|
||||
iconid = ui_id_icon_get(C, static_cast<ID *>(itemptr.data), false);
|
||||
if (!ELEM(iconid, 0, ICON_BLANK1)) {
|
||||
|
@ -468,24 +463,19 @@ void ui_rna_collection_search_update_fn(
|
|||
}
|
||||
|
||||
if (name) {
|
||||
CollItemSearch *cis = MEM_cnew<CollItemSearch>(__func__);
|
||||
auto cis = std::make_unique<CollItemSearch>();
|
||||
cis->data = itemptr.data;
|
||||
cis->name = BLI_strdup(name);
|
||||
cis->index = item_index;
|
||||
cis->name = name;
|
||||
cis->index = items_list.size();
|
||||
cis->iconid = iconid;
|
||||
cis->is_id = is_id;
|
||||
cis->name_prefix_offset = name_prefix_offset;
|
||||
cis->has_sep_char = has_sep_char;
|
||||
if (!skip_filter) {
|
||||
search.add(name, cis);
|
||||
}
|
||||
BLI_addtail(items_list, cis);
|
||||
items_list.append(std::move(cis));
|
||||
if (name != name_buf) {
|
||||
MEM_freeN(name);
|
||||
}
|
||||
}
|
||||
|
||||
item_index++;
|
||||
}
|
||||
RNA_PROP_END;
|
||||
}
|
||||
|
@ -495,85 +485,66 @@ void ui_rna_collection_search_update_fn(
|
|||
data->target_prop);
|
||||
BLI_assert(search_flag & PROP_STRING_SEARCH_SUPPORTED);
|
||||
|
||||
struct SearchVisitUserData {
|
||||
blender::string_search::StringSearch<CollItemSearch> *search;
|
||||
bool skip_filter;
|
||||
int item_index;
|
||||
ListBase *items_list;
|
||||
const char *func_id;
|
||||
} user_data = {nullptr};
|
||||
const bool show_extra_info = (G.debug_value == 102);
|
||||
|
||||
user_data.search = &search;
|
||||
user_data.skip_filter = skip_filter;
|
||||
user_data.items_list = items_list;
|
||||
user_data.func_id = __func__;
|
||||
RNA_property_string_search(C,
|
||||
&data->target_ptr,
|
||||
data->target_prop,
|
||||
str,
|
||||
[&](StringPropertySearchVisitParams visit_params) {
|
||||
auto cis = std::make_unique<CollItemSearch>();
|
||||
|
||||
RNA_property_string_search(
|
||||
C,
|
||||
&data->target_ptr,
|
||||
data->target_prop,
|
||||
str,
|
||||
[](void *user_data, const StringPropertySearchVisitParams *visit_params) {
|
||||
const bool show_extra_info = (G.debug_value == 102);
|
||||
cis->data = nullptr;
|
||||
if (visit_params.info && show_extra_info) {
|
||||
cis->name = fmt::format("{}" UI_SEP_CHAR_S "{}",
|
||||
visit_params.text,
|
||||
*visit_params.info);
|
||||
}
|
||||
else {
|
||||
cis->name = std::move(visit_params.text);
|
||||
}
|
||||
|
||||
SearchVisitUserData *search_data = (SearchVisitUserData *)user_data;
|
||||
CollItemSearch *cis = MEM_cnew<CollItemSearch>(search_data->func_id);
|
||||
cis->data = nullptr;
|
||||
if (visit_params->info && show_extra_info) {
|
||||
cis->name = BLI_sprintfN(
|
||||
"%s" UI_SEP_CHAR_S "%s", visit_params->text, visit_params->info);
|
||||
}
|
||||
else {
|
||||
cis->name = BLI_strdup(visit_params->text);
|
||||
}
|
||||
cis->index = search_data->item_index;
|
||||
cis->iconid = ICON_NONE;
|
||||
cis->is_id = false;
|
||||
cis->name_prefix_offset = 0;
|
||||
cis->has_sep_char = visit_params->info != nullptr;
|
||||
if (!search_data->skip_filter) {
|
||||
search_data->search->add(visit_params->text, cis);
|
||||
}
|
||||
BLI_addtail(search_data->items_list, cis);
|
||||
search_data->item_index++;
|
||||
},
|
||||
(void *)&user_data);
|
||||
cis->index = items_list.size();
|
||||
cis->iconid = ICON_NONE;
|
||||
cis->is_id = false;
|
||||
cis->name_prefix_offset = 0;
|
||||
cis->has_sep_char = visit_params.info.has_value();
|
||||
items_list.append(std::move(cis));
|
||||
});
|
||||
|
||||
if (search_flag & PROP_STRING_SEARCH_SORT) {
|
||||
BLI_listbase_sort(items_list, [](const void *a_, const void *b_) -> int {
|
||||
const CollItemSearch *cis_a = (const CollItemSearch *)a_;
|
||||
const CollItemSearch *cis_b = (const CollItemSearch *)b_;
|
||||
return BLI_strcasecmp_natural(cis_a->name, cis_b->name);
|
||||
});
|
||||
int i = 0;
|
||||
LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
|
||||
cis->index = i;
|
||||
i++;
|
||||
std::sort(
|
||||
items_list.begin(),
|
||||
items_list.end(),
|
||||
[](const std::unique_ptr<CollItemSearch> &a, const std::unique_ptr<CollItemSearch> &b) {
|
||||
return BLI_strcasecmp_natural(a->name.c_str(), b->name.c_str()) <= 0;
|
||||
});
|
||||
for (const int i : items_list.index_range()) {
|
||||
items_list[i]->index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_filter) {
|
||||
LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
|
||||
if (!add_collection_search_item(cis, requires_exact_data_name, has_id_icon, items)) {
|
||||
for (std::unique_ptr<CollItemSearch> &cis : items_list) {
|
||||
if (!add_collection_search_item(*cis, requires_exact_data_name, has_id_icon, items)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const blender::Vector<CollItemSearch *> filtered_items = search.query(str);
|
||||
ui::string_search::StringSearch<CollItemSearch> search;
|
||||
for (std::unique_ptr<CollItemSearch> &cis : items_list) {
|
||||
search.add(cis->name, cis.get());
|
||||
}
|
||||
|
||||
const Vector<CollItemSearch *> filtered_items = search.query(str);
|
||||
for (CollItemSearch *cis : filtered_items) {
|
||||
if (!add_collection_search_item(cis, requires_exact_data_name, has_id_icon, items)) {
|
||||
if (!add_collection_search_item(*cis, requires_exact_data_name, has_id_icon, items)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
|
||||
MEM_freeN(cis->name);
|
||||
}
|
||||
BLI_freelistN(items_list);
|
||||
MEM_freeN(items_list);
|
||||
}
|
||||
|
||||
int UI_icon_from_id(const ID *id)
|
||||
|
|
|
@ -4846,6 +4846,8 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but,
|
|||
case UI_BTYPE_SEPR:
|
||||
break;
|
||||
case UI_BTYPE_SEPR_LINE:
|
||||
/* Add horizontal padding between the line and menu sides. */
|
||||
BLI_rcti_pad(rect, int(-7.0f * UI_SCALE_FAC), 0);
|
||||
ui_draw_separator(&tui->wcol_menu_item, but, rect);
|
||||
break;
|
||||
default: {
|
||||
|
|
|
@ -182,7 +182,7 @@ AssetCatalogTreeView::AssetCatalogTreeView(asset_system::AssetLibrary *library,
|
|||
FileAssetSelectParams *params,
|
||||
SpaceFile &space_file)
|
||||
: asset_library_(library),
|
||||
catalog_tree_(AS_asset_library_get_catalog_tree(library)),
|
||||
catalog_tree_(library->catalog_service->get_catalog_tree()),
|
||||
params_(params),
|
||||
space_file_(space_file)
|
||||
{
|
||||
|
@ -502,8 +502,7 @@ AssetCatalog *AssetCatalogDropTarget::get_drag_catalog(
|
|||
if (drag.type != WM_DRAG_ASSET_CATALOG) {
|
||||
return nullptr;
|
||||
}
|
||||
const AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
&asset_library);
|
||||
const AssetCatalogService *catalog_service = asset_library.catalog_service.get();
|
||||
const wmDragAssetCatalog *catalog_drag = WM_drag_get_asset_catalog_data(&drag);
|
||||
|
||||
return catalog_service->find_catalog(catalog_drag->drag_catalog_id);
|
||||
|
|
|
@ -70,25 +70,6 @@ static void remap_edges(const OffsetIndices<int> src_faces,
|
|||
});
|
||||
}
|
||||
|
||||
/** Create a mesh with no built-in attributes. */
|
||||
static Mesh *create_mesh_no_attributes(const Mesh ¶ms_mesh,
|
||||
const int verts_num,
|
||||
const int edges_num,
|
||||
const int faces_num,
|
||||
const int corners_num)
|
||||
{
|
||||
Mesh *mesh = BKE_mesh_new_nomain(0, 0, faces_num, 0);
|
||||
mesh->verts_num = verts_num;
|
||||
mesh->edges_num = edges_num;
|
||||
mesh->corners_num = corners_num;
|
||||
CustomData_free_layer_named(&mesh->vert_data, "position", 0);
|
||||
CustomData_free_layer_named(&mesh->edge_data, ".edge_verts", 0);
|
||||
CustomData_free_layer_named(&mesh->corner_data, ".corner_vert", 0);
|
||||
CustomData_free_layer_named(&mesh->corner_data, ".corner_edge", 0);
|
||||
BKE_mesh_copy_parameters_for_eval(mesh, ¶ms_mesh);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static void copy_loose_vert_hint(const Mesh &src, Mesh &dst)
|
||||
{
|
||||
const auto &src_cache = src.runtime->loose_verts_cache;
|
||||
|
@ -218,8 +199,9 @@ std::optional<Mesh *> mesh_copy_selection(
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
Mesh *dst_mesh = create_mesh_no_attributes(
|
||||
src_mesh, vert_mask.size(), edge_mask.size(), face_mask.size(), 0);
|
||||
Mesh *dst_mesh = bke::mesh_new_no_attributes(
|
||||
vert_mask.size(), edge_mask.size(), face_mask.size(), 0);
|
||||
BKE_mesh_copy_parameters_for_eval(dst_mesh, &src_mesh);
|
||||
bke::MutableAttributeAccessor dst_attributes = dst_mesh->attributes_for_write();
|
||||
dst_attributes.add<int2>(".edge_verts", bke::AttrDomain::Edge, bke::AttributeInitConstruct());
|
||||
MutableSpan<int2> dst_edges = dst_mesh->edges_for_write();
|
||||
|
@ -351,8 +333,9 @@ std::optional<Mesh *> mesh_copy_selection_keep_verts(
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
Mesh *dst_mesh = create_mesh_no_attributes(
|
||||
src_mesh, src_mesh.verts_num, edge_mask.size(), face_mask.size(), 0);
|
||||
Mesh *dst_mesh = bke::mesh_new_no_attributes(
|
||||
src_mesh.verts_num, edge_mask.size(), face_mask.size(), 0);
|
||||
BKE_mesh_copy_parameters_for_eval(dst_mesh, &src_mesh);
|
||||
bke::MutableAttributeAccessor dst_attributes = dst_mesh->attributes_for_write();
|
||||
|
||||
const OffsetIndices<int> dst_faces = offset_indices::gather_selected_offsets(
|
||||
|
@ -443,8 +426,9 @@ std::optional<Mesh *> mesh_copy_selection_keep_edges(
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
Mesh *dst_mesh = create_mesh_no_attributes(
|
||||
src_mesh, src_mesh.verts_num, src_mesh.edges_num, face_mask.size(), 0);
|
||||
Mesh *dst_mesh = bke::mesh_new_no_attributes(
|
||||
src_mesh.verts_num, src_mesh.edges_num, face_mask.size(), 0);
|
||||
BKE_mesh_copy_parameters_for_eval(dst_mesh, &src_mesh);
|
||||
bke::MutableAttributeAccessor dst_attributes = dst_mesh->attributes_for_write();
|
||||
|
||||
const OffsetIndices<int> dst_faces = offset_indices::gather_selected_offsets(
|
||||
|
|
|
@ -755,9 +755,9 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c
|
|||
std::string pre_main, post_main;
|
||||
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
const Vector<StageInterfaceInfo *> &in_interfaces = info.geometry_source_.is_empty() ?
|
||||
info.vertex_out_interfaces_ :
|
||||
info.geometry_out_interfaces_;
|
||||
const Span<StageInterfaceInfo *> in_interfaces = info.geometry_source_.is_empty() ?
|
||||
info.vertex_out_interfaces_ :
|
||||
info.geometry_out_interfaces_;
|
||||
for (const StageInterfaceInfo *iface : in_interfaces) {
|
||||
print_interface(ss, "in", *iface);
|
||||
}
|
||||
|
@ -909,7 +909,7 @@ std::string GLShader::geometry_layout_declare(const ShaderCreateInfo &info) cons
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInfo *> &ifaces,
|
||||
static StageInterfaceInfo *find_interface_by_name(const Span<StageInterfaceInfo *> ifaces,
|
||||
const StringRefNull &name)
|
||||
{
|
||||
for (auto *iface : ifaces) {
|
||||
|
|
|
@ -316,7 +316,7 @@ void VKDevice::context_unregister(VKContext &context)
|
|||
{
|
||||
contexts_.remove(contexts_.first_index_of(std::reference_wrapper(context)));
|
||||
}
|
||||
const Vector<std::reference_wrapper<VKContext>> &VKDevice::contexts_get() const
|
||||
Span<std::reference_wrapper<VKContext>> VKDevice::contexts_get() const
|
||||
{
|
||||
return contexts_;
|
||||
};
|
||||
|
|
|
@ -207,7 +207,7 @@ class VKDevice : public NonCopyable {
|
|||
|
||||
void context_register(VKContext &context);
|
||||
void context_unregister(VKContext &context);
|
||||
const Vector<std::reference_wrapper<VKContext>> &contexts_get() const;
|
||||
Span<std::reference_wrapper<VKContext>> contexts_get() const;
|
||||
|
||||
const VKBuffer &dummy_buffer_get() const
|
||||
{
|
||||
|
|
|
@ -135,7 +135,7 @@ void VKFrameBuffer::build_clear_attachments_color(const float (*clear_colors)[4]
|
|||
/** \name Clear
|
||||
* \{ */
|
||||
|
||||
void VKFrameBuffer::clear(const Vector<VkClearAttachment> &attachments) const
|
||||
void VKFrameBuffer::clear(const Span<VkClearAttachment> attachments) const
|
||||
{
|
||||
if (attachments.is_empty()) {
|
||||
return;
|
||||
|
|
|
@ -139,7 +139,7 @@ class VKFrameBuffer : public FrameBuffer {
|
|||
void build_clear_attachments_color(const float (*clear_colors)[4],
|
||||
const bool multi_clear_colors,
|
||||
Vector<VkClearAttachment> &r_attachments) const;
|
||||
void clear(const Vector<VkClearAttachment> &attachments) const;
|
||||
void clear(Span<VkClearAttachment> attachments) const;
|
||||
};
|
||||
|
||||
static inline VKFrameBuffer *unwrap(FrameBuffer *framebuffer)
|
||||
|
|
|
@ -869,7 +869,7 @@ static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
|
|||
|
||||
static void add_descriptor_set_layout_bindings(
|
||||
const VKShaderInterface &interface,
|
||||
const Vector<shader::ShaderCreateInfo::Resource> &resources,
|
||||
const Span<shader::ShaderCreateInfo::Resource> resources,
|
||||
Vector<VkDescriptorSetLayoutBinding> &r_bindings,
|
||||
VkShaderStageFlags vk_shader_stages)
|
||||
{
|
||||
|
@ -888,7 +888,7 @@ static void add_descriptor_set_layout_bindings(
|
|||
|
||||
static VkDescriptorSetLayoutCreateInfo create_descriptor_set_layout(
|
||||
const VKShaderInterface &interface,
|
||||
const Vector<shader::ShaderCreateInfo::Resource> &resources,
|
||||
const Span<shader::ShaderCreateInfo::Resource> resources,
|
||||
Vector<VkDescriptorSetLayoutBinding> &r_bindings,
|
||||
VkShaderStageFlags vk_shader_stages)
|
||||
{
|
||||
|
@ -1123,9 +1123,9 @@ std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo
|
|||
const VKWorkarounds &workarounds = VKBackend::get().device_get().workarounds_get();
|
||||
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
const Vector<StageInterfaceInfo *> &in_interfaces = info.geometry_source_.is_empty() ?
|
||||
info.vertex_out_interfaces_ :
|
||||
info.geometry_out_interfaces_;
|
||||
const Span<StageInterfaceInfo *> in_interfaces = info.geometry_source_.is_empty() ?
|
||||
info.vertex_out_interfaces_ :
|
||||
info.geometry_out_interfaces_;
|
||||
int location = 0;
|
||||
for (const StageInterfaceInfo *iface : in_interfaces) {
|
||||
print_interface(ss, "in", *iface, location);
|
||||
|
@ -1227,10 +1227,10 @@ std::string VKShader::geometry_interface_declare(const shader::ShaderCreateInfo
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInfo *> &ifaces,
|
||||
const StringRefNull &name)
|
||||
static StageInterfaceInfo *find_interface_by_name(const Span<StageInterfaceInfo *> ifaces,
|
||||
const StringRefNull name)
|
||||
{
|
||||
for (auto *iface : ifaces) {
|
||||
for (StageInterfaceInfo *iface : ifaces) {
|
||||
if (iface->instance_name == name) {
|
||||
return iface;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ static float *find_or_add_attribute(const StringRef name,
|
|||
}
|
||||
|
||||
static void load_custom_attributes(const Mesh *mesh,
|
||||
const Vector<int> &ply_to_vertex,
|
||||
const Span<int> ply_to_vertex,
|
||||
uint32_t vertex_offset,
|
||||
Vector<PlyCustomAttribute> &r_attributes)
|
||||
{
|
||||
|
|
|
@ -1247,7 +1247,7 @@ void shape_key_export_chaser(pxr::UsdStageRefPtr stage,
|
|||
|
||||
void export_deform_verts(const Mesh *mesh,
|
||||
const pxr::UsdSkelBindingAPI &skel_api,
|
||||
const Vector<std::string> &bone_names)
|
||||
const Span<std::string> bone_names)
|
||||
{
|
||||
BLI_assert(mesh);
|
||||
BLI_assert(skel_api);
|
||||
|
|
|
@ -143,6 +143,6 @@ void shape_key_export_chaser(pxr::UsdStageRefPtr stage,
|
|||
*/
|
||||
void export_deform_verts(const Mesh *mesh,
|
||||
const pxr::UsdSkelBindingAPI &skel_api,
|
||||
const Vector<std::string> &bone_names);
|
||||
Span<std::string> bone_names);
|
||||
|
||||
} // namespace blender::io::usd
|
||||
|
|
|
@ -474,7 +474,7 @@ static bool parse_keyword(const char *&p, const char *end, StringRef keyword)
|
|||
/* Special case: if there were no faces/edges in any geometries,
|
||||
* treat all the vertices as a point cloud. */
|
||||
static void use_all_vertices_if_no_faces(Geometry *geom,
|
||||
const Vector<std::unique_ptr<Geometry>> &all_geometries,
|
||||
const Span<std::unique_ptr<Geometry>> all_geometries,
|
||||
const GlobalVertices &global_vertices)
|
||||
{
|
||||
if (!global_vertices.vertices.is_empty() && geom && geom->geom_type_ == GEOM_MESH) {
|
||||
|
|
|
@ -50,11 +50,6 @@ typedef struct AssetFilterSettings {
|
|||
* more than that from the file. So pointers to other IDs or ID data are strictly forbidden.
|
||||
*/
|
||||
typedef struct AssetMetaData {
|
||||
#ifdef __cplusplus
|
||||
/** Enables use with `std::unique_ptr<AssetMetaData>`. */
|
||||
~AssetMetaData();
|
||||
#endif
|
||||
|
||||
/** Runtime type, to reference event callbacks. Only valid for local assets. */
|
||||
struct AssetTypeInfo *local_type_info;
|
||||
|
||||
|
@ -96,6 +91,11 @@ typedef struct AssetMetaData {
|
|||
short tot_tags;
|
||||
|
||||
char _pad[4];
|
||||
|
||||
#ifdef __cplusplus
|
||||
/** Enables use with `std::unique_ptr<AssetMetaData>`. */
|
||||
~AssetMetaData();
|
||||
#endif
|
||||
} AssetMetaData;
|
||||
|
||||
typedef enum eAssetLibraryType {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "RNA_types.hh"
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
|
||||
struct ID;
|
||||
struct IDOverrideLibrary;
|
||||
|
@ -378,16 +379,15 @@ void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const cha
|
|||
eStringPropertySearchFlag RNA_property_string_search_flag(PropertyRNA *prop);
|
||||
/**
|
||||
* Search candidates for string `prop` by calling `visit_fn` with each string.
|
||||
* Typically these strings are collected in `visit_user_data` in a format defined by the caller.
|
||||
*
|
||||
* See #PropStringSearchFunc for details.
|
||||
*/
|
||||
void RNA_property_string_search(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
void RNA_property_string_search(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
|
||||
/**
|
||||
* \return the length without `\0` terminator.
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#ifndef __RNA_TYPES_H__
|
||||
#define __RNA_TYPES_H__
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "../blenlib/BLI_function_ref.hh"
|
||||
#include "../blenlib/BLI_sys_types.h"
|
||||
#include "../blenlib/BLI_utildefines.h"
|
||||
|
||||
|
@ -538,10 +542,10 @@ using StringPropertyLengthFunc = int (*)(PointerRNA *ptr, PropertyRNA *prop);
|
|||
using StringPropertySetFunc = void (*)(PointerRNA *ptr, PropertyRNA *prop, const char *value);
|
||||
|
||||
struct StringPropertySearchVisitParams {
|
||||
/** Text being searched for (never NULL). */
|
||||
const char *text;
|
||||
/** Additional information to display (optional, may be NULL). */
|
||||
const char *info;
|
||||
/** Text being searched for. */
|
||||
std::string text;
|
||||
/** Additional information to display. */
|
||||
std::optional<std::string> info;
|
||||
};
|
||||
|
||||
enum eStringPropertySearchFlag {
|
||||
|
@ -562,12 +566,6 @@ enum eStringPropertySearchFlag {
|
|||
};
|
||||
ENUM_OPERATORS(eStringPropertySearchFlag, PROP_STRING_SEARCH_SUGGESTION)
|
||||
|
||||
/**
|
||||
* Visit string search candidates, `text` may be freed once this callback has finished,
|
||||
* so references to it should not be held.
|
||||
*/
|
||||
using StringPropertySearchVisitFunc = void (*)(void *visit_user_data,
|
||||
const StringPropertySearchVisitParams *params);
|
||||
/**
|
||||
* \param C: context, may be NULL (in this case all available items should be shown).
|
||||
* \param ptr: RNA pointer.
|
||||
|
@ -577,14 +575,13 @@ using StringPropertySearchVisitFunc = void (*)(void *visit_user_data,
|
|||
* for the search results (auto-complete Python attributes for e.g.).
|
||||
* \param visit_fn: This function is called with every search candidate and is typically
|
||||
* responsible for storing the search results.
|
||||
* \param visit_user_data: Caller defined data, passed to `visit_fn`.
|
||||
*/
|
||||
using StringPropertySearchFunc = void (*)(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
using StringPropertySearchFunc =
|
||||
void (*)(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
|
||||
using EnumPropertyGetFunc = int (*)(PointerRNA *ptr, PropertyRNA *prop);
|
||||
using EnumPropertySetFunc = void (*)(PointerRNA *ptr, PropertyRNA *prop, int value);
|
||||
|
|
|
@ -1169,11 +1169,10 @@ static char *rna_def_property_search_func(
|
|||
"PointerRNA *ptr, "
|
||||
"PropertyRNA *prop, "
|
||||
"const char *edit_text, "
|
||||
"StringPropertySearchVisitFunc visit_fn, "
|
||||
"void *visit_user_data)\n",
|
||||
"blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)\n",
|
||||
func);
|
||||
fprintf(f, "{\n");
|
||||
fprintf(f, "\n %s(C, ptr, prop, edit_text, visit_fn, visit_user_data);\n", manualfunc);
|
||||
fprintf(f, "\n %s(C, ptr, prop, edit_text, visit_fn);\n", manualfunc);
|
||||
fprintf(f, "}\n\n");
|
||||
return func;
|
||||
}
|
||||
|
|
|
@ -3702,12 +3702,11 @@ void RNA_property_string_search(const bContext *C,
|
|||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
BLI_assert(RNA_property_string_search_flag(prop) & PROP_STRING_SEARCH_SUPPORTED);
|
||||
StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
|
||||
sprop->search(C, ptr, prop, edit_text, visit_fn, visit_user_data);
|
||||
sprop->search(C, ptr, prop, edit_text, visit_fn);
|
||||
}
|
||||
|
||||
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
|
||||
|
|
|
@ -364,7 +364,7 @@ void rna_AssetMetaData_catalog_id_update(bContext *C, PointerRNA *ptr)
|
|||
}
|
||||
|
||||
AssetMetaData *asset_data = static_cast<AssetMetaData *>(ptr->data);
|
||||
AS_asset_library_refresh_catalog_simplename(asset_library, asset_data);
|
||||
asset_library->refresh_catalog_simplename(asset_data);
|
||||
}
|
||||
|
||||
static PointerRNA rna_AssetHandle_file_data_get(PointerRNA *ptr)
|
||||
|
|
|
@ -1597,10 +1597,10 @@ static void bpy_prop_string_set_fn(PointerRNA *ptr, PropertyRNA *prop, const cha
|
|||
}
|
||||
}
|
||||
|
||||
static bool bpy_prop_string_visit_fn_call(PyObject *py_func,
|
||||
PyObject *item,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
static bool bpy_prop_string_visit_fn_call(
|
||||
PyObject *py_func,
|
||||
PyObject *item,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
const char *text;
|
||||
const char *info = nullptr;
|
||||
|
@ -1637,19 +1637,19 @@ static bool bpy_prop_string_visit_fn_call(PyObject *py_func,
|
|||
}
|
||||
}
|
||||
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = text;
|
||||
visit_params.info = info;
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_params.info = info ? info : "";
|
||||
visit_fn(visit_params);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bpy_prop_string_visit_for_search_fn(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
static void bpy_prop_string_visit_for_search_fn(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
BPyPropStore *prop_store = static_cast<BPyPropStore *>(RNA_property_py_data_get(prop));
|
||||
PyObject *py_func;
|
||||
|
@ -1703,8 +1703,7 @@ static void bpy_prop_string_visit_for_search_fn(const bContext *C,
|
|||
if (py_text == nullptr) {
|
||||
break;
|
||||
}
|
||||
const bool ok = bpy_prop_string_visit_fn_call(
|
||||
py_func, py_text, visit_fn, visit_user_data);
|
||||
const bool ok = bpy_prop_string_visit_fn_call(py_func, py_text, visit_fn);
|
||||
Py_DECREF(py_text);
|
||||
if (!ok) {
|
||||
break;
|
||||
|
@ -1734,8 +1733,7 @@ static void bpy_prop_string_visit_for_search_fn(const bContext *C,
|
|||
const Py_ssize_t ret_num = PySequence_Fast_GET_SIZE(ret_fast);
|
||||
PyObject **ret_fast_items = PySequence_Fast_ITEMS(ret_fast);
|
||||
for (Py_ssize_t i = 0; i < ret_num; i++) {
|
||||
const bool ok = bpy_prop_string_visit_fn_call(
|
||||
py_func, ret_fast_items[i], visit_fn, visit_user_data);
|
||||
const bool ok = bpy_prop_string_visit_fn_call(py_func, ret_fast_items[i], visit_fn);
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include "RE_compositor.hh"
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "GPU_context.h"
|
||||
|
||||
#include "render_types.h"
|
||||
|
||||
namespace blender::render {
|
||||
|
@ -504,7 +508,23 @@ class RealtimeCompositor {
|
|||
* to avoid them blocking each other. */
|
||||
BLI_assert(!BLI_thread_is_main() || G.background);
|
||||
|
||||
/* The realtime compositor uses GPU module and does not rely on the draw manager, or its global
|
||||
* state. This means that activation of GPU context does not require lock of the main thread.
|
||||
*
|
||||
* However, while this has been tested on Linux and works well, on macOS it causes to
|
||||
* spontaneous invalid colors in the composite output. The Windows has not been extensively
|
||||
* tested yet. */
|
||||
#if defined(__linux__)
|
||||
void *re_system_gpu_context = RE_system_gpu_context_get(&render_);
|
||||
void *re_blender_gpu_context = RE_blender_gpu_context_ensure(&render_);
|
||||
|
||||
GPU_render_begin();
|
||||
WM_system_gpu_context_activate(re_system_gpu_context);
|
||||
GPU_context_active_set(static_cast<GPUContext *>(re_blender_gpu_context));
|
||||
#else
|
||||
DRW_render_context_enable(&render_);
|
||||
#endif
|
||||
|
||||
context_->update_input_data(input_data);
|
||||
|
||||
/* Always recreate the evaluator, as this only runs on compositing node changes and
|
||||
|
@ -517,7 +537,15 @@ class RealtimeCompositor {
|
|||
context_->output_to_render_result();
|
||||
context_->viewer_output_to_viewer_image();
|
||||
texture_pool_->free_unused_and_reset();
|
||||
|
||||
#if defined(__linux__)
|
||||
GPU_flush();
|
||||
GPU_render_end();
|
||||
GPU_context_active_set(nullptr);
|
||||
WM_system_gpu_context_release(re_system_gpu_context);
|
||||
#else
|
||||
DRW_render_context_disable(&render_);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_sys_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include "WM_keymap.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
|
@ -1122,12 +1125,12 @@ bool WM_operatortype_remove(const char *idname);
|
|||
*/
|
||||
void WM_operatortype_last_properties_clear_all();
|
||||
|
||||
void WM_operatortype_idname_visit_for_search(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
void WM_operatortype_idname_visit_for_search(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
|
||||
/**
|
||||
* Tag all operator-properties of \a ot defined after calling this, until
|
||||
|
@ -1229,12 +1232,12 @@ void WM_menutype_freelink(MenuType *mt);
|
|||
void WM_menutype_free();
|
||||
bool WM_menutype_poll(bContext *C, MenuType *mt);
|
||||
|
||||
void WM_menutype_idname_visit_for_search(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
void WM_menutype_idname_visit_for_search(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
|
||||
/* `wm_panel_type.cc` */
|
||||
|
||||
|
@ -1247,12 +1250,12 @@ PanelType *WM_paneltype_find(const char *idname, bool quiet);
|
|||
bool WM_paneltype_add(PanelType *pt);
|
||||
void WM_paneltype_remove(PanelType *pt);
|
||||
|
||||
void WM_paneltype_idname_visit_for_search(const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data);
|
||||
void WM_paneltype_idname_visit_for_search(
|
||||
const bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const char *edit_text,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
|
||||
|
||||
/* `wm_gesture_ops.cc` */
|
||||
|
||||
|
|
|
@ -101,20 +101,20 @@ bool WM_menutype_poll(bContext *C, MenuType *mt)
|
|||
return true;
|
||||
}
|
||||
|
||||
void WM_menutype_idname_visit_for_search(const bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
void WM_menutype_idname_visit_for_search(
|
||||
const bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, menutypes_hash) {
|
||||
MenuType *mt = static_cast<MenuType *>(BLI_ghashIterator_getValue(&gh_iter));
|
||||
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = mt->idname;
|
||||
visit_params.info = mt->label;
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_fn(visit_params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,12 +249,12 @@ void WM_operatortype_last_properties_clear_all()
|
|||
}
|
||||
}
|
||||
|
||||
void WM_operatortype_idname_visit_for_search(const bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
void WM_operatortype_idname_visit_for_search(
|
||||
const bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, global_ops_hash) {
|
||||
|
@ -263,10 +263,10 @@ void WM_operatortype_idname_visit_for_search(const bContext * /*C*/,
|
|||
char idname_py[OP_MAX_TYPENAME];
|
||||
WM_operator_py_idname(idname_py, ot->idname);
|
||||
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = idname_py;
|
||||
visit_params.info = ot->name;
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_fn(visit_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,20 +68,20 @@ void WM_paneltype_clear()
|
|||
BLI_ghash_free(g_paneltypes_hash, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void WM_paneltype_idname_visit_for_search(const bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
StringPropertySearchVisitFunc visit_fn,
|
||||
void *visit_user_data)
|
||||
void WM_paneltype_idname_visit_for_search(
|
||||
const bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
const char * /*edit_text*/,
|
||||
blender::FunctionRef<void(StringPropertySearchVisitParams)> visit_fn)
|
||||
{
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, g_paneltypes_hash) {
|
||||
PanelType *pt = static_cast<PanelType *>(BLI_ghashIterator_getValue(&gh_iter));
|
||||
|
||||
StringPropertySearchVisitParams visit_params = {nullptr};
|
||||
StringPropertySearchVisitParams visit_params{};
|
||||
visit_params.text = pt->idname;
|
||||
visit_params.info = pt->label;
|
||||
visit_fn(visit_user_data, &visit_params);
|
||||
visit_fn(visit_params);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue