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
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,9 +37,15 @@ eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type)
|
||||
if (type.is<int>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_INT32;
|
||||
}
|
||||
if (type.is<int64_t>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_INT64;
|
||||
}
|
||||
if (type.is_any<short2, int2>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_INT32_2D;
|
||||
}
|
||||
if (type.is_any<int3>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_INT32_3D;
|
||||
}
|
||||
if (type.is<float>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_FLOAT;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#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<ColumnValues> VolumeDataSource::get_column_values(
|
||||
return grid_class_name(*BKE_volume_grid_get(volume, index));
|
||||
}));
|
||||
}
|
||||
if (STREQ(column_id.name, "Voxels")) {
|
||||
return std::make_unique<ColumnValues>(
|
||||
IFACE_("Voxels"), VArray<int64_t>::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<ColumnValues>(
|
||||
IFACE_("Leaf Voxels"), VArray<int64_t>::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<ColumnValues>(
|
||||
IFACE_("Tiles"), VArray<int64_t>::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<ColumnValues>(
|
||||
IFACE_("Size"),
|
||||
VArray<int64_t>::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<ColumnValues>(
|
||||
IFACE_("Extent"), VArray<int3>::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<ColumnValues> 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<ColumnValues>(IFACE_("Data Type"),
|
||||
@@ -663,6 +701,30 @@ std::unique_ptr<ColumnValues> VolumeGridDataSource::get_column_values(
|
||||
return std::make_unique<ColumnValues>(IFACE_("Class"),
|
||||
VArray<std::string>::from_single(name, 1));
|
||||
}
|
||||
if (STREQ(column_id.name, "Voxels")) {
|
||||
const int64_t active_voxels = grid.active_voxels();
|
||||
return std::make_unique<ColumnValues>(IFACE_("Voxels"),
|
||||
VArray<int64_t>::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<ColumnValues>(IFACE_("Leaf Voxels"),
|
||||
VArray<int64_t>::from_single(active_leaf_voxels, 1));
|
||||
}
|
||||
if (STREQ(column_id.name, "Tiles")) {
|
||||
const int64_t active_tiles = grid.active_tiles();
|
||||
return std::make_unique<ColumnValues>(IFACE_("Tiles"),
|
||||
VArray<int64_t>::from_single(active_tiles, 1));
|
||||
}
|
||||
if (STREQ(column_id.name, "Size")) {
|
||||
const int64_t size = grid.size_in_bytes();
|
||||
return std::make_unique<ColumnValues>(
|
||||
IFACE_("Size"), VArray<int64_t>::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<ColumnValues>(IFACE_("Extent"), VArray<int3>::from_single(extent, 1));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<int>()) {
|
||||
const int value = *value_ptr.get<int>();
|
||||
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<int>(__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<int>(), column.display_hint());
|
||||
return;
|
||||
}
|
||||
if (type.is<int64_t>()) {
|
||||
this->draw_int(params, *value_ptr.get<int64_t>(), column.display_hint());
|
||||
return;
|
||||
}
|
||||
if (type.is<int8_t>()) {
|
||||
@@ -205,6 +190,11 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
|
||||
this->draw_int_vector(params, Span(&value.x, 2));
|
||||
return;
|
||||
}
|
||||
if (type.is<int3>()) {
|
||||
const int3 value = *value_ptr.get<int3>();
|
||||
this->draw_int_vector(params, Span(&value.x, 3));
|
||||
return;
|
||||
}
|
||||
if (type.is<float>()) {
|
||||
const float value = *value_ptr.get<float>();
|
||||
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<int64_t>(__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<int> values) const
|
||||
{
|
||||
BLI_assert(!values.is_empty());
|
||||
@@ -556,6 +587,16 @@ float ColumnValues::fit_column_values_width_px(const std::optional<int64_t> &max
|
||||
data_.typed<int>(),
|
||||
[](const int value) { return fmt::format("{}", value); });
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_INT64: {
|
||||
return estimate_max_column_width<int64_t>(get_min_width(3 * SPREADSHEET_WIDTH_UNIT),
|
||||
fontid,
|
||||
max_sample_size,
|
||||
data_.typed<int64_t>(),
|
||||
[](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<float>(
|
||||
get_min_width(3 * SPREADSHEET_WIDTH_UNIT),
|
||||
@@ -566,12 +607,20 @@ float ColumnValues::fit_column_values_width_px(const std::optional<int64_t> &max
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_INT32_2D: {
|
||||
return estimate_max_column_width<int2>(
|
||||
get_min_width(3 * SPREADSHEET_WIDTH_UNIT),
|
||||
get_min_width(6 * SPREADSHEET_WIDTH_UNIT),
|
||||
fontid,
|
||||
max_sample_size,
|
||||
data_.typed<int2>(),
|
||||
[](const int2 value) { return fmt::format("{} {}", value.x, value.y); });
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_INT32_3D: {
|
||||
return estimate_max_column_width<int3>(
|
||||
get_min_width(9 * SPREADSHEET_WIDTH_UNIT),
|
||||
fontid,
|
||||
max_sample_size,
|
||||
data_.typed<int3>(),
|
||||
[](const int3 value) { return fmt::format("{} {} {}", value.x, value.y, value.z); });
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT2: {
|
||||
return estimate_max_column_width<float2>(
|
||||
get_min_width(6 * SPREADSHEET_WIDTH_UNIT),
|
||||
|
||||
@@ -122,6 +122,32 @@ static IndexMask apply_row_filter(const SpreadsheetRowFilter &row_filter,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (column_data.type().is<int64_t>()) {
|
||||
const int64_t value = row_filter.value_int;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
return apply_filter_operation(
|
||||
column_data.typed<int64_t>(),
|
||||
[&](const int64_t cell) { return cell == value; },
|
||||
prev_mask,
|
||||
memory);
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
return apply_filter_operation(
|
||||
column_data.typed<int64_t>(),
|
||||
[value](const int64_t cell) { return cell > value; },
|
||||
prev_mask,
|
||||
memory);
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_LESS: {
|
||||
return apply_filter_operation(
|
||||
column_data.typed<int64_t>(),
|
||||
[&](const int64_t cell) { return cell < value; },
|
||||
prev_mask,
|
||||
memory);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (column_data.type().is<int2>()) {
|
||||
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<int3>()) {
|
||||
const int3 value = row_filter.value_int3;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
return apply_filter_operation(
|
||||
column_data.typed<int3>(),
|
||||
[&](const int3 cell) { return cell == value; },
|
||||
prev_mask,
|
||||
memory);
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
return apply_filter_operation(
|
||||
column_data.typed<int3>(),
|
||||
[&](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<int3>(),
|
||||
[&](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<short2>()) {
|
||||
const short2 value = short2(int2(row_filter.value_int2));
|
||||
switch (row_filter.operation) {
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <cstring>
|
||||
#include <fmt/format.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
@@ -30,8 +32,6 @@
|
||||
#include "spreadsheet_intern.hh"
|
||||
#include "spreadsheet_row_filter_ui.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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", "");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user