From 9d20c8d3c8eafe7745138ce8d3c99153a0633084 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 2 Oct 2025 13:50:25 +0200 Subject: [PATCH] Spreadsheet: show volume grid stats This adds support for showing various stats of volume grids in the spreadsheet: * Extent: Number of voxels in each direction of the bounding box of the grid. * Voxels: Total number of active voxels in the grid. This includes all voxels which are stored in tiles (e.g. one leaf tile contains 512 voxels). * Leaf Voxels: Number of active voxels stored in leaf nodes. This does not contain any voxels that are part of tiles. * Tiles: Number of active tiles in the grid. * Size: Estimated size of the volume grid in memory. All these stats are cached on the volume grid now. A new `tag_tree_changed` method has been added to invalidate the cache. Computing these stats is not cheap (but not more than a few ms even for large grids). That mainly means that we can't do it for socket inspection because that would cause too much overhead. However, doing it just for the grids that are currently visible in the spreadsheet seems fine and useful. This also adds some general improvements to the spreadsheet: * Support `int64_t` and `int3` columns. * Draw ints with thousand separators. * Support showing ints as number of bytes such as `23 MB`. Pull Request: https://projects.blender.org/blender/blender/pulls/147191 --- source/blender/blenkernel/BKE_volume_grid.hh | 21 ++++ .../blender/blenkernel/intern/volume_grid.cc | 71 +++++++++++- .../space_spreadsheet/spreadsheet_column.cc | 6 + .../spreadsheet_column_values.hh | 16 ++- .../spreadsheet_data_source_geometry.cc | 70 +++++++++++- .../space_spreadsheet/spreadsheet_layout.cc | 103 +++++++++++++----- .../spreadsheet_row_filter.cc | 56 ++++++++++ .../spreadsheet_row_filter_ui.cc | 17 ++- source/blender/makesdna/DNA_space_enums.h | 2 + source/blender/makesdna/DNA_space_types.h | 3 +- source/blender/makesrna/intern/rna_space.cc | 5 + .../modifiers/intern/MOD_volume_displace.cc | 1 + .../nodes/node_geo_sdf_grid_boolean.cc | 1 + 13 files changed, 334 insertions(+), 38 deletions(-) diff --git a/source/blender/blenkernel/BKE_volume_grid.hh b/source/blender/blenkernel/BKE_volume_grid.hh index 6306ea79735..b6a8cc4219e 100644 --- a/source/blender/blenkernel/BKE_volume_grid.hh +++ b/source/blender/blenkernel/BKE_volume_grid.hh @@ -18,6 +18,7 @@ # include "BKE_volume_enums.hh" # include "BKE_volume_grid_type_traits.hh" +# include "BLI_cache_mutex.hh" # include "BLI_implicit_sharing_ptr.hh" # include "BLI_mutex.hh" # include "BLI_string_ref.hh" @@ -117,6 +118,18 @@ class VolumeGridData : public ImplicitSharingMixin { * An error produced while trying to lazily load the grid. */ mutable std::string error_message_; + + mutable CacheMutex active_voxels_mutex_; + mutable int64_t active_voxels_ = 0; + mutable CacheMutex active_leaf_voxels_mutex_; + mutable int64_t active_leaf_voxels_ = 0; + mutable CacheMutex active_tiles_mutex_; + mutable int64_t active_tiles_ = 0; + mutable CacheMutex size_in_bytes_mutex_; + mutable int64_t size_in_bytes_ = 0; + mutable CacheMutex active_bounds_mutex_; + mutable openvdb::CoordBBox active_bounds_; + /** * A token that allows detecting whether some code is currently accessing the tree (not grid) or * not. If this variable is the only owner of the `shared_ptr`, no one else has access to the @@ -238,6 +251,14 @@ class VolumeGridData : public ImplicitSharingMixin { */ bool is_reloadable() const; + void tag_tree_modified() const; + + int64_t active_voxels() const; + int64_t active_leaf_voxels() const; + int64_t active_tiles() const; + int64_t size_in_bytes() const; + const openvdb::CoordBBox &active_bounds() const; + private: /** * Unloads the tree data if it's reloadable and no one is using it right now. diff --git a/source/blender/blenkernel/intern/volume_grid.cc b/source/blender/blenkernel/intern/volume_grid.cc index 429ab0c56fb..b4566d80f0d 100644 --- a/source/blender/blenkernel/intern/volume_grid.cc +++ b/source/blender/blenkernel/intern/volume_grid.cc @@ -178,6 +178,15 @@ bool VolumeGridData::is_reloadable() const return bool(lazy_load_grid_); } +void VolumeGridData::tag_tree_modified() const +{ + active_voxels_mutex_.tag_dirty(); + active_leaf_voxels_mutex_.tag_dirty(); + active_tiles_mutex_.tag_dirty(); + size_in_bytes_mutex_.tag_dirty(); + active_bounds_mutex_.tag_dirty(); +} + bool VolumeGridData::is_loaded() const { std::lock_guard lock{mutex_}; @@ -190,9 +199,64 @@ void VolumeGridData::count_memory(MemoryCounter &memory) const if (!tree_loaded_) { return; } - const openvdb::TreeBase &tree = grid_->baseTree(); - memory.add_shared(tree_sharing_info_.get(), - [&](MemoryCounter &shared_memory) { shared_memory.add(tree.memUsage()); }); + memory.add_shared(tree_sharing_info_.get(), [&](MemoryCounter &shared_memory) { + shared_memory.add(this->size_in_bytes()); + }); +} + +int64_t VolumeGridData::active_voxels() const +{ + active_voxels_mutex_.ensure([&]() { + VolumeTreeAccessToken token; + const openvdb::GridBase &grid = this->grid(token); + const openvdb::TreeBase &tree = grid.baseTree(); + active_voxels_ = tree.activeVoxelCount(); + }); + return active_voxels_; +} + +int64_t VolumeGridData::active_leaf_voxels() const +{ + active_leaf_voxels_mutex_.ensure([&]() { + VolumeTreeAccessToken token; + const openvdb::GridBase &grid = this->grid(token); + const openvdb::TreeBase &tree = grid.baseTree(); + active_leaf_voxels_ = tree.activeLeafVoxelCount(); + }); + return active_leaf_voxels_; +} + +int64_t VolumeGridData::active_tiles() const +{ + active_tiles_mutex_.ensure([&]() { + VolumeTreeAccessToken token; + const openvdb::GridBase &grid = this->grid(token); + const openvdb::TreeBase &tree = grid.baseTree(); + active_tiles_ = tree.activeTileCount(); + }); + return active_tiles_; +} + +int64_t VolumeGridData::size_in_bytes() const +{ + size_in_bytes_mutex_.ensure([&]() { + VolumeTreeAccessToken token; + const openvdb::GridBase &grid = this->grid(token); + const openvdb::TreeBase &tree = grid.baseTree(); + size_in_bytes_ = tree.memUsage(); + }); + return size_in_bytes_; +} + +const openvdb::CoordBBox &VolumeGridData::active_bounds() const +{ + active_bounds_mutex_.ensure([&]() { + VolumeTreeAccessToken token; + const openvdb::GridBase &grid = this->grid(token); + const openvdb::TreeBase &tree = grid.baseTree(); + tree.evalActiveVoxelBoundingBox(active_bounds_); + }); + return active_bounds_; } std::string VolumeGridData::error_message() const @@ -464,6 +528,7 @@ void clear_tree(VolumeGridData &grid) #ifdef WITH_OPENVDB VolumeTreeAccessToken tree_token; grid.grid_for_write(tree_token).clear(); + grid.tag_tree_modified(); #else UNUSED_VARS(grid); #endif diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc index ee0f7a812fa..34a16e011de 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc @@ -37,9 +37,15 @@ eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type) if (type.is()) { return SPREADSHEET_VALUE_TYPE_INT32; } + if (type.is()) { + return SPREADSHEET_VALUE_TYPE_INT64; + } if (type.is_any()) { return SPREADSHEET_VALUE_TYPE_INT32_2D; } + if (type.is_any()) { + return SPREADSHEET_VALUE_TYPE_INT32_3D; + } if (type.is()) { return SPREADSHEET_VALUE_TYPE_FLOAT; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh index 3d5e590ffe7..c2f7507ce63 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh @@ -13,6 +13,11 @@ namespace blender::ed::spreadsheet { eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type); +enum class ColumnValueDisplayHint { + None, + Bytes, +}; + /** * This represents a column in a spreadsheet. It has a name and provides a value for all the cells * in the column. @@ -22,9 +27,13 @@ class ColumnValues final { std::string name_; GVArray data_; + ColumnValueDisplayHint display_hint_; public: - ColumnValues(std::string name, GVArray data) : name_(std::move(name)), data_(std::move(data)) + ColumnValues(std::string name, + GVArray data, + const ColumnValueDisplayHint display_hint = ColumnValueDisplayHint::None) + : name_(std::move(name)), data_(std::move(data)), display_hint_(display_hint) { /* The array should not be empty. */ BLI_assert(data_); @@ -52,6 +61,11 @@ class ColumnValues final { return data_; } + ColumnValueDisplayHint display_hint() const + { + return display_hint_; + } + /** * Get a good column width for the column name and values. * diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 385c71f5878..1f40f3f913e 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -4,7 +4,6 @@ #include -#include "BKE_volume_grid_fwd.hh" #include "BLI_listbase.h" #include "BLI_math_matrix.hh" #include "BLI_virtual_array.hh" @@ -559,7 +558,9 @@ void VolumeDataSource::foreach_default_column_ids( return; } - for (const char *name : {"Grid Name", "Data Type", "Class"}) { + for (const char *name : + {"Grid Name", "Data Type", "Class", "Extent", "Voxels", "Leaf Voxels", "Tiles", "Size"}) + { SpreadsheetColumnID column_id{(char *)name}; fn(column_id, false); } @@ -612,6 +613,40 @@ std::unique_ptr VolumeDataSource::get_column_values( return grid_class_name(*BKE_volume_grid_get(volume, index)); })); } + if (STREQ(column_id.name, "Voxels")) { + return std::make_unique( + IFACE_("Voxels"), VArray::from_std_func(size, [volume](const int64_t index) { + return BKE_volume_grid_get(volume, index)->active_voxels(); + })); + } + if (STREQ(column_id.name, "Leaf Voxels")) { + return std::make_unique( + IFACE_("Leaf Voxels"), VArray::from_std_func(size, [volume](const int64_t index) { + return BKE_volume_grid_get(volume, index)->active_leaf_voxels(); + })); + } + if (STREQ(column_id.name, "Tiles")) { + return std::make_unique( + IFACE_("Tiles"), VArray::from_std_func(size, [volume](const int64_t index) { + return BKE_volume_grid_get(volume, index)->active_tiles(); + })); + } + if (STREQ(column_id.name, "Size")) { + return std::make_unique( + IFACE_("Size"), + VArray::from_std_func( + size, + [volume](const int64_t index) { + return BKE_volume_grid_get(volume, index)->size_in_bytes(); + }), + ColumnValueDisplayHint::Bytes); + } + if (STREQ(column_id.name, "Extent")) { + return std::make_unique( + IFACE_("Extent"), VArray::from_std_func(size, [volume](const int64_t index) { + return int3(BKE_volume_grid_get(volume, index)->active_bounds().dim().asPointer()); + })); + } #else UNUSED_VARS(column_id); #endif @@ -642,7 +677,9 @@ void VolumeGridDataSource::foreach_default_column_ids( return; } - for (const char *name : {"Data Type", "Class"}) { + for (const char *name : + {"Data Type", "Class", "Extent", "Voxels", "Leaf Voxels", "Tiles", "Size"}) + { SpreadsheetColumnID column_id{(char *)name}; fn(column_id, false); } @@ -651,8 +688,9 @@ void VolumeGridDataSource::foreach_default_column_ids( std::unique_ptr VolumeGridDataSource::get_column_values( const SpreadsheetColumnID &column_id) const { + const bke::VolumeGridData &grid = grid_->get(); if (STREQ(column_id.name, "Data Type")) { - const VolumeGridType type = (*grid_)->grid_type(); + const VolumeGridType type = grid.grid_type(); const char *name = nullptr; RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name); return std::make_unique(IFACE_("Data Type"), @@ -663,6 +701,30 @@ std::unique_ptr VolumeGridDataSource::get_column_values( return std::make_unique(IFACE_("Class"), VArray::from_single(name, 1)); } + if (STREQ(column_id.name, "Voxels")) { + const int64_t active_voxels = grid.active_voxels(); + return std::make_unique(IFACE_("Voxels"), + VArray::from_single(active_voxels, 1)); + } + if (STREQ(column_id.name, "Leaf Voxels")) { + const int64_t active_leaf_voxels = grid.active_leaf_voxels(); + return std::make_unique(IFACE_("Leaf Voxels"), + VArray::from_single(active_leaf_voxels, 1)); + } + if (STREQ(column_id.name, "Tiles")) { + const int64_t active_tiles = grid.active_tiles(); + return std::make_unique(IFACE_("Tiles"), + VArray::from_single(active_tiles, 1)); + } + if (STREQ(column_id.name, "Size")) { + const int64_t size = grid.size_in_bytes(); + return std::make_unique( + IFACE_("Size"), VArray::from_single(size, 1), ColumnValueDisplayHint::Bytes); + } + if (STREQ(column_id.name, "Extent")) { + const int3 extent = int3(grid.active_bounds().dim().asPointer()); + return std::make_unique(IFACE_("Extent"), VArray::from_single(extent, 1)); + } return {}; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc index 7a189237ac7..6ca22dcf5da 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc @@ -13,6 +13,7 @@ #include "BLI_math_matrix.hh" #include "BLI_math_quaternion_types.hh" #include "BLI_math_vector_types.hh" +#include "BLI_string.h" #include "BKE_instances.hh" @@ -143,37 +144,21 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { const CPPType &type = data.type(); BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); data.get_to_uninitialized(real_index, buffer); - this->draw_content_cell_value(GPointer(type, buffer), params); + this->draw_content_cell_value(GPointer(type, buffer), params, column); type.destruct(buffer); } - void draw_content_cell_value(const GPointer value_ptr, const CellDrawParams ¶ms) const + void draw_content_cell_value(const GPointer value_ptr, + const CellDrawParams ¶ms, + const ColumnValues &column) const { const CPPType &type = *value_ptr.type(); if (type.is()) { - const int value = *value_ptr.get(); - const std::string value_str = std::to_string(value); - uiBut *but = uiDefIconTextBut(params.block, - ButType::Label, - 0, - ICON_NONE, - value_str, - params.xmin, - params.ymin, - params.width, - params.height, - nullptr, - std::nullopt); - UI_but_func_tooltip_set( - but, - [](bContext * /*C*/, void *argN, const StringRef /*tip*/) { - return fmt::format("{}", *((int *)argN)); - }, - MEM_dupallocN(__func__, value), - MEM_freeN); - /* Right-align Integers. */ - UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); - UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); + this->draw_int(params, *value_ptr.get(), column.display_hint()); + return; + } + if (type.is()) { + this->draw_int(params, *value_ptr.get(), column.display_hint()); return; } if (type.is()) { @@ -205,6 +190,11 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { this->draw_int_vector(params, Span(&value.x, 2)); return; } + if (type.is()) { + const int3 value = *value_ptr.get(); + this->draw_int_vector(params, Span(&value.x, 3)); + return; + } if (type.is()) { const float value = *value_ptr.get(); std::stringstream ss; @@ -343,7 +333,7 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { const bke::SocketValueVariant &value_variant = socket_value->value; if (value_variant.is_single()) { const GPointer single_value_ptr = value_variant.get_single_ptr(); - this->draw_content_cell_value(single_value_ptr, params); + this->draw_content_cell_value(single_value_ptr, params, column); return; } } @@ -387,6 +377,47 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { } } + void draw_int(const CellDrawParams ¶ms, + const int64_t value, + const ColumnValueDisplayHint display_hint) const + { + std::string value_str; + switch (display_hint) { + case ColumnValueDisplayHint::Bytes: { + char dst[BLI_STR_FORMAT_INT64_BYTE_UNIT_SIZE]; + BLI_str_format_byte_unit(dst, value, true); + value_str = dst; + break; + } + default: { + value_str = fmt::format(std::locale("en_US.UTF-8"), "{:L}", value); + break; + } + } + uiBut *but = uiDefIconTextBut(params.block, + ButType::Label, + 0, + ICON_NONE, + value_str, + params.xmin, + params.ymin, + params.width, + params.height, + nullptr, + std::nullopt); + UI_but_func_tooltip_set( + but, + [](bContext * /*C*/, void *argN, const StringRef /*tip*/) { + return fmt::format( + std::locale("en_US.UTF-8"), "{:L} {}", *((int64_t *)argN), TIP_("bytes")); + }, + MEM_dupallocN(__func__, value), + MEM_freeN); + /* Right-align Integers. */ + UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); + UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); + } + void draw_int_vector(const CellDrawParams ¶ms, const Span values) const { BLI_assert(!values.is_empty()); @@ -556,6 +587,16 @@ float ColumnValues::fit_column_values_width_px(const std::optional &max data_.typed(), [](const int value) { return fmt::format("{}", value); }); } + case SPREADSHEET_VALUE_TYPE_INT64: { + return estimate_max_column_width(get_min_width(3 * SPREADSHEET_WIDTH_UNIT), + fontid, + max_sample_size, + data_.typed(), + [](const int64_t value) { + return fmt::format( + std::locale("en_US.UTF-8"), "{:L}", value); + }); + } case SPREADSHEET_VALUE_TYPE_FLOAT: { return estimate_max_column_width( get_min_width(3 * SPREADSHEET_WIDTH_UNIT), @@ -566,12 +607,20 @@ float ColumnValues::fit_column_values_width_px(const std::optional &max } case SPREADSHEET_VALUE_TYPE_INT32_2D: { return estimate_max_column_width( - get_min_width(3 * SPREADSHEET_WIDTH_UNIT), + get_min_width(6 * SPREADSHEET_WIDTH_UNIT), fontid, max_sample_size, data_.typed(), [](const int2 value) { return fmt::format("{} {}", value.x, value.y); }); } + case SPREADSHEET_VALUE_TYPE_INT32_3D: { + return estimate_max_column_width( + get_min_width(9 * SPREADSHEET_WIDTH_UNIT), + fontid, + max_sample_size, + data_.typed(), + [](const int3 value) { return fmt::format("{} {} {}", value.x, value.y, value.z); }); + } case SPREADSHEET_VALUE_TYPE_FLOAT2: { return estimate_max_column_width( get_min_width(6 * SPREADSHEET_WIDTH_UNIT), diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc index c8317375375..880bbd44781 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc @@ -122,6 +122,32 @@ static IndexMask apply_row_filter(const SpreadsheetRowFilter &row_filter, } } } + else if (column_data.type().is()) { + const int64_t value = row_filter.value_int; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + return apply_filter_operation( + column_data.typed(), + [&](const int64_t cell) { return cell == value; }, + prev_mask, + memory); + } + case SPREADSHEET_ROW_FILTER_GREATER: { + return apply_filter_operation( + column_data.typed(), + [value](const int64_t cell) { return cell > value; }, + prev_mask, + memory); + } + case SPREADSHEET_ROW_FILTER_LESS: { + return apply_filter_operation( + column_data.typed(), + [&](const int64_t cell) { return cell < value; }, + prev_mask, + memory); + } + } + } else if (column_data.type().is()) { const int2 value = row_filter.value_int2; switch (row_filter.operation) { @@ -148,6 +174,36 @@ static IndexMask apply_row_filter(const SpreadsheetRowFilter &row_filter, } } } + else if (column_data.type().is()) { + const int3 value = row_filter.value_int3; + switch (row_filter.operation) { + case SPREADSHEET_ROW_FILTER_EQUAL: { + return apply_filter_operation( + column_data.typed(), + [&](const int3 cell) { return cell == value; }, + prev_mask, + memory); + } + case SPREADSHEET_ROW_FILTER_GREATER: { + return apply_filter_operation( + column_data.typed(), + [&](const int3 cell) { + return cell.x > value.x && cell.y > value.y && cell.z > value.z; + }, + prev_mask, + memory); + } + case SPREADSHEET_ROW_FILTER_LESS: { + return apply_filter_operation( + column_data.typed(), + [&](const int3 cell) { + return cell.x < value.x && cell.y < value.y && cell.z < value.z; + }, + prev_mask, + memory); + } + } + } else if (column_data.type().is()) { const short2 value = short2(int2(row_filter.value_int2)); switch (row_filter.operation) { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc index c6ebdd17c18..8f26801fdb6 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc @@ -3,6 +3,8 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include +#include +#include #include "BLI_listbase.h" #include "BLI_string_ref.hh" @@ -30,8 +32,6 @@ #include "spreadsheet_intern.hh" #include "spreadsheet_row_filter_ui.hh" -#include - namespace blender::ed::spreadsheet { static void filter_panel_id_fn(void * /*row_filter_v*/, char *r_name) @@ -65,6 +65,7 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter, switch (data_type) { case SPREADSHEET_VALUE_TYPE_INT8: case SPREADSHEET_VALUE_TYPE_INT32: + case SPREADSHEET_VALUE_TYPE_INT64: return std::to_string(row_filter.value_int); case SPREADSHEET_VALUE_TYPE_FLOAT: { std::ostringstream result; @@ -77,6 +78,13 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter, result << "(" << row_filter.value_int2[0] << ", " << row_filter.value_int2[1] << ")"; return result.str(); } + case SPREADSHEET_VALUE_TYPE_INT32_3D: { + std::ostringstream result; + return fmt::format("({}, {}, {})", + row_filter.value_int3[0], + row_filter.value_int3[1], + row_filter.value_int3[2]); + } case SPREADSHEET_VALUE_TYPE_FLOAT2: { std::ostringstream result; result.precision(3); @@ -213,6 +221,7 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel) layout->prop(filter_ptr, "value_int8", UI_ITEM_NONE, IFACE_("Value"), ICON_NONE); break; case SPREADSHEET_VALUE_TYPE_INT32: + case SPREADSHEET_VALUE_TYPE_INT64: layout->prop(filter_ptr, "operation", UI_ITEM_NONE, std::nullopt, ICON_NONE); layout->prop(filter_ptr, "value_int", UI_ITEM_NONE, IFACE_("Value"), ICON_NONE); break; @@ -220,6 +229,10 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel) layout->prop(filter_ptr, "operation", UI_ITEM_NONE, std::nullopt, ICON_NONE); layout->prop(filter_ptr, "value_int2", UI_ITEM_NONE, IFACE_("Value"), ICON_NONE); break; + case SPREADSHEET_VALUE_TYPE_INT32_3D: + layout->prop(filter_ptr, "operation", UI_ITEM_NONE, std::nullopt, ICON_NONE); + layout->prop(filter_ptr, "value_int3", UI_ITEM_NONE, IFACE_("Value"), ICON_NONE); + break; case SPREADSHEET_VALUE_TYPE_FLOAT: layout->prop(filter_ptr, "operation", UI_ITEM_NONE, std::nullopt, ICON_NONE); layout->prop(filter_ptr, "value_float", UI_ITEM_NONE, IFACE_("Value"), ICON_NONE); diff --git a/source/blender/makesdna/DNA_space_enums.h b/source/blender/makesdna/DNA_space_enums.h index 0b36f64c1ca..276f81e827c 100644 --- a/source/blender/makesdna/DNA_space_enums.h +++ b/source/blender/makesdna/DNA_space_enums.h @@ -1043,6 +1043,8 @@ typedef enum eSpreadsheetColumnValueType { SPREADSHEET_VALUE_TYPE_QUATERNION = 11, SPREADSHEET_VALUE_TYPE_FLOAT4X4 = 12, SPREADSHEET_VALUE_TYPE_BUNDLE_ITEM = 13, + SPREADSHEET_VALUE_TYPE_INT64 = 14, + SPREADSHEET_VALUE_TYPE_INT32_3D = 15, } eSpreadsheetColumnValueType; typedef enum eSpreadsheetColumnFlag { diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index aa212e09801..3df9cf4370c 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1263,10 +1263,11 @@ typedef struct SpreadsheetRowFilter { /* eSpaceSpreadsheet_RowFilterFlag. */ uint8_t flag; - char _pad0[2]; + char _pad0[6]; int value_int; int value_int2[2]; + int value_int3[3]; char *value_string; float value_float; float threshold; diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc index f59632b585c..4d49da7d4f1 100644 --- a/source/blender/makesrna/intern/rna_space.cc +++ b/source/blender/makesrna/intern/rna_space.cc @@ -8756,6 +8756,11 @@ static void rna_def_spreadsheet_row_filter(BlenderRNA *brna) RNA_def_property_ui_text(prop, "2D Vector Value", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, nullptr); + prop = RNA_def_property(srna, "value_int3", PROP_INT, PROP_NONE); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "3D Vector Value", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, nullptr); + prop = RNA_def_property(srna, "value_boolean", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", SPREADSHEET_ROW_FILTER_BOOL_VALUE); RNA_def_property_ui_text(prop, "Boolean Value", ""); diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index 9ca5945fdb7..bfc13f15a17 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -290,6 +290,7 @@ static void displace_volume(ModifierData *md, const ModifierEvalContext *ctx, Vo DisplaceGridOp displace_grid_op{grid, *vdmd, *ctx}; BKE_volume_grid_type_operation(grid_type, displace_grid_op); + volume_grid->tag_tree_modified(); } #else diff --git a/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc index 54c2e0c6249..e6ce6b62d26 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc @@ -135,6 +135,7 @@ static void node_geo_exec(GeoNodeExecParams params) return; } } + operands.first()->tag_tree_modified(); params.set_output("Grid", std::move(operands.first())); #else