Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-12-15 18:34:13 +0300
committerHans Goudey <h.goudey@me.com>2021-12-15 18:34:13 +0300
commit474adc6f883c2d5a854d7324364f7996044d83cb (patch)
tree7ed0cf70d7195526e389c586fdd87af193c8215b
parentd79868c4e678b22f7f277d98ae3ce729893fdfb7 (diff)
Refactor: Simplify spreadsheet handling of cell values
Previously we used a `CellValue` class to hold the data for a cell, and called a function to fill it whenever necessary. This is an unnecessary complication when we have virtual generic arrays and most data is already easily accessible that way anyway. This patch removes `CellValue` and uses `fn::GVArray` to provide access to data instead. In the future, if rows have different types within a single column, we can use a `GVArray` of `blender::Any` to interface with the drawing. Along with that, the use of virtual arrays made it easy to do a few other cleanups: - Use selection domain interpolations from rB5841f8656d95 for the mesh selection filter. - Change the row filter to only calculate for necessary indices. Differential Revision: https://developer.blender.org/D13478
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc4
-rw-r--r--source/blender/editors/space_spreadsheet/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh64
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_column.cc38
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh60
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc376
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_layout.cc171
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_layout.hh2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc413
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh8
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc6
-rw-r--r--source/blender/functions/FN_generic_virtual_array.hh15
-rw-r--r--source/blender/makesdna/DNA_space_types.h1
15 files changed, 449 insertions, 714 deletions
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 62d66f13e9f..93a7646fed0 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -31,6 +31,8 @@
#include "attribute_access_intern.hh"
+#include "FN_cpp_type_make.hh"
+
using blender::float4x4;
using blender::Map;
using blender::MutableSpan;
@@ -39,6 +41,8 @@ using blender::Span;
using blender::VectorSet;
using blender::fn::GSpan;
+MAKE_CPP_TYPE(InstanceReference, InstanceReference, CPPTypeFlags::None)
+
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index 27446fe1a94..f1db8dedf1a 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -49,7 +49,6 @@ set(SRC
spreadsheet_row_filter_ui.cc
spreadsheet_cache.hh
- spreadsheet_cell_value.hh
spreadsheet_column.hh
spreadsheet_column_values.hh
spreadsheet_context.hh
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index 0cb4a52eb2f..61cc70830af 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -323,6 +323,8 @@ static float get_default_column_width(const ColumnValues &values)
return 8.0f;
case SPREADSHEET_VALUE_TYPE_STRING:
return 5.0f;
+ case SPREADSHEET_VALUE_TYPE_UNKNOWN:
+ return 2.0f;
}
return float_width;
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
deleted file mode 100644
index c11b4a2b23d..00000000000
--- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include <optional>
-
-#include "BLI_color.hh"
-#include "BLI_float2.hh"
-#include "BLI_float3.hh"
-
-struct Collection;
-struct Object;
-
-namespace blender::ed::spreadsheet {
-
-struct ObjectCellValue {
- const Object *object;
-};
-
-struct CollectionCellValue {
- const Collection *collection;
-};
-
-struct GeometrySetCellValue {
- const GeometrySet *geometry_set;
-};
-
-/**
- * This is a type that can hold the value of a cell in a spreadsheet. This type allows us to
- * decouple the drawing of individual cells from the code that generates the data to be displayed.
- */
-class CellValue {
- public:
- /* The implementation just uses a bunch of `std::option` for now. Unfortunately, we cannot use
- * `std::variant` yet, due to missing compiler support. This type can really be optimized more,
- * but it does not really matter too much currently. */
-
- std::optional<int> value_int;
- std::optional<float> value_float;
- std::optional<bool> value_bool;
- std::optional<float2> value_float2;
- std::optional<float3> value_float3;
- std::optional<ColorGeometry4f> value_color;
- std::optional<ObjectCellValue> value_object;
- std::optional<CollectionCellValue> value_collection;
- std::optional<GeometrySetCellValue> value_geometry_set;
- std::optional<std::string> value_string;
-};
-
-} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc
index ee08c86b29f..7551593ef38 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_column.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_column.cc
@@ -18,14 +18,52 @@
#include "MEM_guardedalloc.h"
+#include "BLI_color.hh"
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
#include "BLI_hash.hh"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
+#include "BKE_geometry_set.hh"
+
+#include "FN_cpp_type.hh"
+
#include "spreadsheet_column.hh"
+#include "spreadsheet_column_values.hh"
namespace blender::ed::spreadsheet {
+eSpreadsheetColumnValueType cpp_type_to_column_type(const fn::CPPType &type)
+{
+ if (type.is<bool>()) {
+ return SPREADSHEET_VALUE_TYPE_BOOL;
+ }
+ if (type.is<int>()) {
+ return SPREADSHEET_VALUE_TYPE_INT32;
+ }
+ if (type.is<float>()) {
+ return SPREADSHEET_VALUE_TYPE_FLOAT;
+ }
+ if (type.is<float2>()) {
+ return SPREADSHEET_VALUE_TYPE_FLOAT2;
+ }
+ if (type.is<float3>()) {
+ return SPREADSHEET_VALUE_TYPE_FLOAT3;
+ }
+ if (type.is<ColorGeometry4f>()) {
+ return SPREADSHEET_VALUE_TYPE_COLOR;
+ }
+ if (type.is<std::string>()) {
+ return SPREADSHEET_VALUE_TYPE_STRING;
+ }
+ if (type.is<InstanceReference>()) {
+ return SPREADSHEET_VALUE_TYPE_INSTANCES;
+ }
+
+ return SPREADSHEET_VALUE_TYPE_UNKNOWN;
+}
+
SpreadsheetColumnID *spreadsheet_column_id_new()
{
SpreadsheetColumnID *column_id = (SpreadsheetColumnID *)MEM_callocN(sizeof(SpreadsheetColumnID),
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh
index 877651d6530..83e3217e5c8 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh
@@ -20,33 +20,36 @@
#include "BLI_string_ref.hh"
-#include "spreadsheet_cell_value.hh"
+#include "FN_generic_virtual_array.hh"
namespace blender::ed::spreadsheet {
+struct CellDrawParams;
+
+eSpreadsheetColumnValueType cpp_type_to_column_type(const fn::CPPType &type);
+
/**
* This represents a column in a spreadsheet. It has a name and provides a value for all the cells
* in the column.
*/
-class ColumnValues {
+class ColumnValues final {
protected:
- eSpreadsheetColumnValueType type_;
std::string name_;
- int size_;
+
+ fn::GVArray data_;
public:
- ColumnValues(const eSpreadsheetColumnValueType type, std::string name, const int size)
- : type_(type), name_(std::move(name)), size_(size)
+ ColumnValues(std::string name, fn::GVArray data) : name_(std::move(name)), data_(std::move(data))
{
+ /* The array should not be empty. */
+ BLI_assert(data_);
}
virtual ~ColumnValues() = default;
- virtual void get_value(int index, CellValue &r_cell_value) const = 0;
-
eSpreadsheetColumnValueType type() const
{
- return type_;
+ return cpp_type_to_column_type(data_.type());
}
StringRefNull name() const
@@ -56,45 +59,16 @@ class ColumnValues {
int size() const
{
- return size_;
+ return data_.size();
}
- /* The default width of newly created columns, in UI units. */
- float default_width = 0.0f;
-};
-
-/* Utility class for the function below. */
-template<typename GetValueF> class LambdaColumnValues : public ColumnValues {
- private:
- GetValueF get_value_;
-
- public:
- LambdaColumnValues(const eSpreadsheetColumnValueType type,
- std::string name,
- int size,
- GetValueF get_value)
- : ColumnValues(type, std::move(name), size), get_value_(std::move(get_value))
+ const fn::GVArray &data() const
{
+ return data_;
}
- void get_value(int index, CellValue &r_cell_value) const final
- {
- get_value_(index, r_cell_value);
- }
+ /* The default width of newly created columns, in UI units. */
+ float default_width = 0.0f;
};
-/* Utility function that simplifies creating a spreadsheet column from a lambda function. */
-template<typename GetValueF>
-std::unique_ptr<ColumnValues> column_values_from_function(const eSpreadsheetColumnValueType type,
- std::string name,
- const int size,
- GetValueF get_value,
- const float default_width = 0.0f)
-{
- std::unique_ptr<ColumnValues> column_values = std::make_unique<LambdaColumnValues<GetValueF>>(
- type, std::move(name), size, std::move(get_value));
- column_values->default_width = default_width;
- return column_values;
-}
-
} // namespace blender::ed::spreadsheet
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 173ef43bfb6..337a6037c42 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -14,6 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "BLI_virtual_array.hh"
+
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_lib_id.h"
@@ -51,30 +53,6 @@ using blender::fn::GField;
namespace blender::ed::spreadsheet {
-static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type(
- const fn::CPPType &type)
-{
- if (type.is<bool>()) {
- return SPREADSHEET_VALUE_TYPE_BOOL;
- }
- if (type.is<int>()) {
- return SPREADSHEET_VALUE_TYPE_INT32;
- }
- if (type.is<float>()) {
- return SPREADSHEET_VALUE_TYPE_FLOAT;
- }
- if (type.is<float2>()) {
- return SPREADSHEET_VALUE_TYPE_FLOAT2;
- }
- if (type.is<float3>()) {
- return SPREADSHEET_VALUE_TYPE_FLOAT3;
- }
- if (type.is<ColorGeometry4f>()) {
- return SPREADSHEET_VALUE_TYPE_COLOR;
- }
- return std::nullopt;
-}
-
void ExtraColumns::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
@@ -92,39 +70,7 @@ std::unique_ptr<ColumnValues> ExtraColumns::get_column_values(
if (values == nullptr) {
return {};
}
- eSpreadsheetColumnValueType column_type = *cpp_type_to_column_value_type(values->type());
- return column_values_from_function(column_type,
- column_id.name,
- values->size(),
- [column_type, values](int index, CellValue &r_cell_value) {
- const void *value = (*values)[index];
- switch (column_type) {
- case SPREADSHEET_VALUE_TYPE_BOOL:
- r_cell_value.value_bool = *(const bool *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_INT32:
- r_cell_value.value_int = *(const int *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_FLOAT:
- r_cell_value.value_float = *(const float *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_FLOAT2:
- r_cell_value.value_float2 = *(const float2 *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_FLOAT3:
- r_cell_value.value_float3 = *(const float3 *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_COLOR:
- r_cell_value.value_color = *(
- const ColorGeometry4f *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_STRING:
- r_cell_value.value_string = *(const std::string *)value;
- break;
- case SPREADSHEET_VALUE_TYPE_INSTANCES:
- break;
- }
- });
+ return std::make_unique<ColumnValues>(column_id.name, fn::GVArray::ForSpan(*values));
}
void GeometryDataSource::foreach_default_column_ids(
@@ -179,52 +125,25 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
if (STREQ(column_id.name, "Name")) {
Span<int> reference_handles = instances.instance_reference_handles();
Span<InstanceReference> references = instances.references();
- std::unique_ptr<ColumnValues> values = column_values_from_function(
- SPREADSHEET_VALUE_TYPE_INSTANCES,
- "Name",
- domain_size,
- [reference_handles, references](int index, CellValue &r_cell_value) {
- const InstanceReference &reference = references[reference_handles[index]];
- switch (reference.type()) {
- case InstanceReference::Type::Object: {
- Object &object = reference.object();
- r_cell_value.value_object = ObjectCellValue{&object};
- break;
- }
- case InstanceReference::Type::Collection: {
- Collection &collection = reference.collection();
- r_cell_value.value_collection = CollectionCellValue{&collection};
- break;
- }
- case InstanceReference::Type::GeometrySet: {
- const GeometrySet &geometry_set = reference.geometry_set();
- r_cell_value.value_geometry_set = GeometrySetCellValue{&geometry_set};
- break;
- }
- case InstanceReference::Type::None: {
- break;
- }
- }
- });
- return values;
+ return std::make_unique<ColumnValues>(
+ column_id.name,
+ VArray<InstanceReference>::ForFunc(domain_size,
+ [reference_handles, references](int64_t index) {
+ return references[reference_handles[index]];
+ }));
}
Span<float4x4> transforms = instances.instance_transforms();
if (STREQ(column_id.name, "Rotation")) {
- return column_values_from_function(
- SPREADSHEET_VALUE_TYPE_FLOAT3,
- column_id.name,
- domain_size,
- [transforms](int index, CellValue &r_cell_value) {
- r_cell_value.value_float3 = transforms[index].to_euler();
- });
+ return std::make_unique<ColumnValues>(
+ column_id.name, VArray<float3>::ForFunc(domain_size, [transforms](int64_t index) {
+ return transforms[index].to_euler();
+ }));
}
if (STREQ(column_id.name, "Scale")) {
- return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT3,
- column_id.name,
- domain_size,
- [transforms](int index, CellValue &r_cell_value) {
- r_cell_value.value_float3 = transforms[index].scale();
- });
+ return std::make_unique<ColumnValues>(
+ column_id.name, VArray<float3>::ForFunc(domain_size, [transforms](int64_t index) {
+ return transforms[index].scale();
+ }));
}
}
@@ -237,71 +156,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
return {};
}
- const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type());
- switch (type) {
- case CD_PROP_FLOAT:
- return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT,
- column_id.name,
- domain_size,
- [varray](int index, CellValue &r_cell_value) {
- float value;
- varray.get(index, &value);
- r_cell_value.value_float = value;
- });
- case CD_PROP_INT32:
- return column_values_from_function(
- SPREADSHEET_VALUE_TYPE_INT32,
- column_id.name,
- domain_size,
- [varray](int index, CellValue &r_cell_value) {
- int value;
- varray.get(index, &value);
- r_cell_value.value_int = value;
- },
- STREQ(column_id.name, "id") ? 5.5f : 0.0f);
- case CD_PROP_BOOL:
- return column_values_from_function(SPREADSHEET_VALUE_TYPE_BOOL,
- column_id.name,
- domain_size,
- [varray](int index, CellValue &r_cell_value) {
- bool value;
- varray.get(index, &value);
- r_cell_value.value_bool = value;
- });
- case CD_PROP_FLOAT2: {
- return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT2,
- column_id.name,
- domain_size,
- [varray](int index, CellValue &r_cell_value) {
- float2 value;
- varray.get(index, &value);
- r_cell_value.value_float2 = value;
- });
- }
- case CD_PROP_FLOAT3: {
- return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT3,
- column_id.name,
- domain_size,
- [varray](int index, CellValue &r_cell_value) {
- float3 value;
- varray.get(index, &value);
- r_cell_value.value_float3 = value;
- });
- }
- case CD_PROP_COLOR: {
- return column_values_from_function(SPREADSHEET_VALUE_TYPE_COLOR,
- column_id.name,
- domain_size,
- [varray](int index, CellValue &r_cell_value) {
- ColorGeometry4f value;
- varray.get(index, &value);
- r_cell_value.value_color = value;
- });
- }
- default:
- break;
- }
- return {};
+ return std::make_unique<ColumnValues>(column_id.name, std::move(varray));
}
int GeometryDataSource::tot_rows() const
@@ -309,90 +164,9 @@ int GeometryDataSource::tot_rows() const
return component_->attribute_domain_size(domain_);
}
-using IsVertexSelectedFn = FunctionRef<bool(int vertex_index)>;
-
-static void get_selected_vertex_indices(const Mesh &mesh,
- const IsVertexSelectedFn is_vertex_selected_fn,
- MutableSpan<bool> selection)
-{
- for (const int i : IndexRange(mesh.totvert)) {
- if (!selection[i]) {
- continue;
- }
- if (!is_vertex_selected_fn(i)) {
- selection[i] = false;
- }
- }
-}
-
-static void get_selected_corner_indices(const Mesh &mesh,
- const IsVertexSelectedFn is_vertex_selected_fn,
- MutableSpan<bool> selection)
-{
- for (const int i : IndexRange(mesh.totloop)) {
- const MLoop &loop = mesh.mloop[i];
- if (!selection[i]) {
- continue;
- }
- if (!is_vertex_selected_fn(loop.v)) {
- selection[i] = false;
- }
- }
-}
-
-static void get_selected_face_indices(const Mesh &mesh,
- const IsVertexSelectedFn is_vertex_selected_fn,
- MutableSpan<bool> selection)
-{
- for (const int poly_index : IndexRange(mesh.totpoly)) {
- if (!selection[poly_index]) {
- continue;
- }
- const MPoly &poly = mesh.mpoly[poly_index];
- for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
- const MLoop &loop = mesh.mloop[loop_index];
- if (!is_vertex_selected_fn(loop.v)) {
- selection[poly_index] = false;
- break;
- }
- }
- }
-}
-
-static void get_selected_edge_indices(const Mesh &mesh,
- const IsVertexSelectedFn is_vertex_selected_fn,
- MutableSpan<bool> selection)
-{
- for (const int i : IndexRange(mesh.totedge)) {
- if (!selection[i]) {
- continue;
- }
- const MEdge &edge = mesh.medge[i];
- if (!is_vertex_selected_fn(edge.v1) || !is_vertex_selected_fn(edge.v2)) {
- selection[i] = false;
- }
- }
-}
-
-static void get_selected_indices_on_domain(const Mesh &mesh,
- const AttributeDomain domain,
- const IsVertexSelectedFn is_vertex_selected_fn,
- MutableSpan<bool> selection)
-{
- switch (domain) {
- case ATTR_DOMAIN_POINT:
- return get_selected_vertex_indices(mesh, is_vertex_selected_fn, selection);
- case ATTR_DOMAIN_FACE:
- return get_selected_face_indices(mesh, is_vertex_selected_fn, selection);
- case ATTR_DOMAIN_CORNER:
- return get_selected_corner_indices(mesh, is_vertex_selected_fn, selection);
- case ATTR_DOMAIN_EDGE:
- return get_selected_edge_indices(mesh, is_vertex_selected_fn, selection);
- default:
- return;
- }
-}
-
+/**
+ * Only data sets corresponding to mesh objects in edit mode currently support selection filtering.
+ */
bool GeometryDataSource::has_selection_filter() const
{
Object *object_orig = DEG_get_original_object(object_eval_);
@@ -409,7 +183,18 @@ bool GeometryDataSource::has_selection_filter() const
return true;
}
-void GeometryDataSource::apply_selection_filter(MutableSpan<bool> rows_included) const
+static IndexMask index_mask_from_bool_array(const VArray<bool> &selection,
+ Vector<int64_t> &indices)
+{
+ for (const int i : selection.index_range()) {
+ if (selection[i]) {
+ indices.append(i);
+ }
+ }
+ return IndexMask(indices);
+}
+
+IndexMask GeometryDataSource::apply_selection_filter(Vector<int64_t> &indices) const
{
std::lock_guard lock{mutex_};
@@ -425,27 +210,38 @@ void GeometryDataSource::apply_selection_filter(MutableSpan<bool> rows_included)
int *orig_indices = (int *)CustomData_get_layer(&mesh_eval->vdata, CD_ORIGINDEX);
if (orig_indices != nullptr) {
/* Use CD_ORIGINDEX layer if it exists. */
- auto is_vertex_selected = [&](int vertex_index) -> bool {
- const int i_orig = orig_indices[vertex_index];
- if (i_orig < 0) {
- return false;
- }
- if (i_orig >= bm->totvert) {
- return false;
- }
- BMVert *vert = bm->vtable[i_orig];
- return BM_elem_flag_test(vert, BM_ELEM_SELECT);
- };
- get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included);
- }
- else if (mesh_eval->totvert == bm->totvert) {
+ VArray<bool> selection = mesh_component->attribute_try_adapt_domain<bool>(
+ VArray<bool>::ForFunc(mesh_eval->totvert,
+ [bm, orig_indices](int vertex_index) -> bool {
+ const int i_orig = orig_indices[vertex_index];
+ if (i_orig < 0) {
+ return false;
+ }
+ if (i_orig >= bm->totvert) {
+ return false;
+ }
+ BMVert *vert = bm->vtable[i_orig];
+ return BM_elem_flag_test(vert, BM_ELEM_SELECT);
+ }),
+ ATTR_DOMAIN_POINT,
+ domain_);
+ return index_mask_from_bool_array(selection, indices);
+ }
+
+ if (mesh_eval->totvert == bm->totvert) {
/* Use a simple heuristic to match original vertices to evaluated ones. */
- auto is_vertex_selected = [&](int vertex_index) -> bool {
- BMVert *vert = bm->vtable[vertex_index];
- return BM_elem_flag_test(vert, BM_ELEM_SELECT);
- };
- get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included);
- }
+ VArray<bool> selection = mesh_component->attribute_try_adapt_domain<bool>(
+ VArray<bool>::ForFunc(mesh_eval->totvert,
+ [bm](int vertex_index) -> bool {
+ BMVert *vert = bm->vtable[vertex_index];
+ return BM_elem_flag_test(vert, BM_ELEM_SELECT);
+ }),
+ ATTR_DOMAIN_POINT,
+ domain_);
+ return index_mask_from_bool_array(selection, indices);
+ }
+
+ return IndexMask(mesh_eval->totvert);
}
void VolumeDataSource::foreach_default_column_ids(
@@ -472,50 +268,36 @@ std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values(
#ifdef WITH_OPENVDB
const int size = this->tot_rows();
if (STREQ(column_id.name, "Grid Name")) {
- return column_values_from_function(
- SPREADSHEET_VALUE_TYPE_STRING,
- IFACE_("Grid Name"),
- size,
- [volume](int index, CellValue &r_cell_value) {
+ return std::make_unique<ColumnValues>(
+ IFACE_("Grid Name"), VArray<std::string>::ForFunc(size, [volume](int64_t index) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
- r_cell_value.value_string = BKE_volume_grid_name(volume_grid);
- },
- 6.0f);
+ return BKE_volume_grid_name(volume_grid);
+ }));
}
if (STREQ(column_id.name, "Data Type")) {
- return column_values_from_function(
- SPREADSHEET_VALUE_TYPE_STRING,
- IFACE_("Type"),
- size,
- [volume](int index, CellValue &r_cell_value) {
+ return std::make_unique<ColumnValues>(
+ IFACE_("Data Type"), VArray<std::string>::ForFunc(size, [volume](int64_t index) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
const VolumeGridType type = BKE_volume_grid_type(volume_grid);
const char *name = nullptr;
RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name);
- r_cell_value.value_string = IFACE_(name);
- },
- 5.0f);
+ return IFACE_(name);
+ }));
}
if (STREQ(column_id.name, "Class")) {
- return column_values_from_function(
- SPREADSHEET_VALUE_TYPE_STRING,
- IFACE_("Class"),
- size,
- [volume](int index, CellValue &r_cell_value) {
+ return std::make_unique<ColumnValues>(
+ IFACE_("Class"), VArray<std::string>::ForFunc(size, [volume](int64_t index) {
const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index);
openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
openvdb::GridClass grid_class = grid->getGridClass();
if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {
- r_cell_value.value_string = IFACE_("Fog Volume");
- }
- else if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
- r_cell_value.value_string = IFACE_("Level Set");
+ return IFACE_("Fog Volume");
}
- else {
- r_cell_value.value_string = IFACE_("Unknown");
+ if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
+ return IFACE_("Level Set");
}
- },
- 5.0f);
+ return IFACE_("Unknown");
+ }));
}
#else
UNUSED_VARS(column_id);
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
index 23207734d2b..b5105050d2b 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
@@ -87,7 +87,7 @@ class GeometryDataSource : public DataSource {
* filtering.
*/
bool has_selection_filter() const override;
- void apply_selection_filter(MutableSpan<bool> rows_included) const;
+ IndexMask apply_selection_filter(Vector<int64_t> &indices) const;
void foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const override;
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
index 202523c0e64..7cc2d8d0b48 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
@@ -17,8 +17,16 @@
#include <iomanip>
#include <sstream>
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
+
+#include "BKE_geometry_set.hh"
+
+#include "spreadsheet_column_values.hh"
#include "spreadsheet_layout.hh"
+#include "DNA_collection_types.h"
+#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
#include "UI_interface.h"
@@ -92,13 +100,14 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
{
const int real_index = spreadsheet_layout_.row_indices[row_index];
const ColumnValues &column = *spreadsheet_layout_.columns[column_index].values;
- CellValue cell_value;
- if (real_index < column.size()) {
- column.get_value(real_index, cell_value);
+ if (real_index > column.size()) {
+ return;
}
- if (cell_value.value_int.has_value()) {
- const int value = *cell_value.value_int;
+ const fn::GVArray &data = column.data();
+
+ if (data.type().is<int>()) {
+ const int value = data.get<int>(real_index);
const std::string value_str = std::to_string(value);
uiBut *but = uiDefIconTextBut(params.block,
UI_BTYPE_LABEL,
@@ -119,8 +128,8 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
}
- else if (cell_value.value_float.has_value()) {
- const float value = *cell_value.value_float;
+ else if (data.type().is<float>()) {
+ const float value = data.get<float>(real_index);
std::stringstream ss;
ss << std::fixed << std::setprecision(3) << value;
const std::string value_str = ss.str();
@@ -143,8 +152,8 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
}
- else if (cell_value.value_bool.has_value()) {
- const bool value = *cell_value.value_bool;
+ else if (data.type().is<bool>()) {
+ const bool value = data.get<bool>(real_index);
const int icon = value ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
uiBut *but = uiDefIconTextBut(params.block,
UI_BTYPE_LABEL,
@@ -163,87 +172,81 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
nullptr);
UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT);
}
- else if (cell_value.value_float2.has_value()) {
- const float2 value = *cell_value.value_float2;
+ else if (data.type().is<float2>()) {
+ const float2 value = data.get<float2>(real_index);
this->draw_float_vector(params, Span(&value.x, 2));
}
- else if (cell_value.value_float3.has_value()) {
- const float3 value = *cell_value.value_float3;
+ else if (data.type().is<float3>()) {
+ const float3 value = data.get<float3>(real_index);
this->draw_float_vector(params, Span(&value.x, 3));
}
- else if (cell_value.value_color.has_value()) {
- const ColorGeometry4f value = *cell_value.value_color;
+ else if (data.type().is<ColorGeometry4f>()) {
+ const ColorGeometry4f value = data.get<ColorGeometry4f>(real_index);
this->draw_float_vector(params, Span(&value.r, 4));
}
- else if (cell_value.value_object.has_value()) {
- const ObjectCellValue value = *cell_value.value_object;
- uiDefIconTextBut(params.block,
- UI_BTYPE_LABEL,
- 0,
- ICON_OBJECT_DATA,
- reinterpret_cast<const ID *const>(value.object)->name + 2,
- params.xmin,
- params.ymin,
- params.width,
- params.height,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- nullptr);
- }
- else if (cell_value.value_collection.has_value()) {
- const CollectionCellValue value = *cell_value.value_collection;
- uiDefIconTextBut(params.block,
- UI_BTYPE_LABEL,
- 0,
- ICON_OUTLINER_COLLECTION,
- reinterpret_cast<const ID *const>(value.collection)->name + 2,
- params.xmin,
- params.ymin,
- params.width,
- params.height,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- nullptr);
- }
- else if (cell_value.value_geometry_set.has_value()) {
- uiDefIconTextBut(params.block,
- UI_BTYPE_LABEL,
- 0,
- ICON_MESH_DATA,
- "Geometry",
- params.xmin,
- params.ymin,
- params.width,
- params.height,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- nullptr);
- }
- else if (cell_value.value_string.has_value()) {
- uiDefIconTextBut(params.block,
- UI_BTYPE_LABEL,
- 0,
- ICON_NONE,
- cell_value.value_string->c_str(),
- params.xmin,
- params.ymin,
- params.width,
- params.height,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- nullptr);
+ else if (data.type().is<InstanceReference>()) {
+ const InstanceReference value = data.get<InstanceReference>(real_index);
+ switch (value.type()) {
+ case InstanceReference::Type::Object: {
+ const Object &object = value.object();
+ uiDefIconTextBut(params.block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_OBJECT_DATA,
+ object.id.name + 2,
+ params.xmin,
+ params.ymin,
+ params.width,
+ params.height,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+ break;
+ }
+ case InstanceReference::Type::Collection: {
+ Collection &collection = value.collection();
+ uiDefIconTextBut(params.block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_OUTLINER_COLLECTION,
+ collection.id.name + 2,
+ params.xmin,
+ params.ymin,
+ params.width,
+ params.height,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+ break;
+ }
+ case InstanceReference::Type::GeometrySet: {
+ uiDefIconTextBut(params.block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_MESH_DATA,
+ "Geometry",
+ params.xmin,
+ params.ymin,
+ params.width,
+ params.height,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+ break;
+ }
+ case InstanceReference::Type::None: {
+ break;
+ }
+ }
}
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.hh b/source/blender/editors/space_spreadsheet/spreadsheet_layout.hh
index 1768af6ae09..f996cd99dad 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.hh
@@ -32,7 +32,7 @@ struct ColumnLayout {
/* Layout information for the entire spreadsheet. */
struct SpreadsheetLayout {
Vector<ColumnLayout> columns;
- Span<int64_t> row_indices;
+ IndexMask row_indices;
int index_column_width = 100;
};
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc
index 1e46fef8d71..a6a0266fcc1 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc
@@ -18,7 +18,6 @@
#include "BLI_listbase.h"
-#include "DNA_collection_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -38,238 +37,197 @@
namespace blender::ed::spreadsheet {
-template<typename OperationFn>
-static void apply_filter_operation(const ColumnValues &values,
+template<typename T, typename OperationFn>
+static void apply_filter_operation(const VArray<T> &data,
OperationFn check_fn,
- MutableSpan<bool> rows_included)
+ const IndexMask mask,
+ Vector<int64_t> &new_indices)
{
- for (const int i : rows_included.index_range()) {
- if (!rows_included[i]) {
- continue;
- }
- CellValue cell_value;
- values.get_value(i, cell_value);
- if (!check_fn(cell_value)) {
- rows_included[i] = false;
+ for (const int64_t i : mask) {
+ if (check_fn(data[i])) {
+ new_indices.append(i);
}
}
}
-static void apply_row_filter(const SpreadsheetLayout &spreadsheet_layout,
- const SpreadsheetRowFilter &row_filter,
- MutableSpan<bool> rows_included)
+static void apply_row_filter(const SpreadsheetRowFilter &row_filter,
+ const Map<StringRef, const ColumnValues *> &columns,
+ const IndexMask prev_mask,
+ Vector<int64_t> &new_indices)
{
- for (const ColumnLayout &column : spreadsheet_layout.columns) {
- const ColumnValues &values = *column.values;
- if (values.name() != row_filter.column_name) {
- continue;
+ const ColumnValues &column = *columns.lookup(row_filter.column_name);
+ const fn::GVArray &column_data = column.data();
+ if (column_data.type().is<float>()) {
+ const float value = row_filter.value_float;
+ switch (row_filter.operation) {
+ case SPREADSHEET_ROW_FILTER_EQUAL: {
+ const float threshold = row_filter.threshold;
+ apply_filter_operation(
+ column_data.typed<float>(),
+ [&](const float cell) { return std::abs(cell - value) < threshold; },
+ prev_mask,
+ new_indices);
+ break;
+ }
+ case SPREADSHEET_ROW_FILTER_GREATER: {
+ apply_filter_operation(
+ column_data.typed<float>(),
+ [&](const float cell) { return cell > value; },
+ prev_mask,
+ new_indices);
+ break;
+ }
+ case SPREADSHEET_ROW_FILTER_LESS: {
+ apply_filter_operation(
+ column_data.typed<float>(),
+ [&](const float cell) { return cell < value; },
+ prev_mask,
+ new_indices);
+ break;
+ }
}
-
- switch (values.type()) {
- case SPREADSHEET_VALUE_TYPE_INT32: {
- const int value = row_filter.value_int;
- switch (row_filter.operation) {
- case SPREADSHEET_ROW_FILTER_EQUAL: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return *cell_value.value_int == value;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_GREATER: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return *cell_value.value_int > value;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_LESS: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return *cell_value.value_int < value;
- },
- rows_included);
- break;
- }
- }
+ }
+ else if (column_data.type().is<int>()) {
+ const int value = row_filter.value_int;
+ switch (row_filter.operation) {
+ case SPREADSHEET_ROW_FILTER_EQUAL: {
+ apply_filter_operation(
+ column_data.typed<int>(),
+ [&](const int cell) { return cell == value; },
+ prev_mask,
+ new_indices);
break;
}
- case SPREADSHEET_VALUE_TYPE_FLOAT: {
- const float value = row_filter.value_float;
- switch (row_filter.operation) {
- case SPREADSHEET_ROW_FILTER_EQUAL: {
- const float threshold = row_filter.threshold;
- apply_filter_operation(
- values,
- [value, threshold](const CellValue &cell_value) -> bool {
- return std::abs(*cell_value.value_float - value) < threshold;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_GREATER: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return *cell_value.value_float > value;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_LESS: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return *cell_value.value_float < value;
- },
- rows_included);
- break;
- }
- }
+ case SPREADSHEET_ROW_FILTER_GREATER: {
+ apply_filter_operation(
+ column_data.typed<int>(),
+ [value](const int cell) { return cell > value; },
+ prev_mask,
+ new_indices);
break;
}
- case SPREADSHEET_VALUE_TYPE_FLOAT2: {
- const float2 value = row_filter.value_float2;
- switch (row_filter.operation) {
- case SPREADSHEET_ROW_FILTER_EQUAL: {
- const float threshold_squared = row_filter.threshold * row_filter.threshold;
- apply_filter_operation(
- values,
- [value, threshold_squared](const CellValue &cell_value) -> bool {
- return float2::distance_squared(*cell_value.value_float2, value) <
- threshold_squared;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_GREATER: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return cell_value.value_float2->x > value.x &&
- cell_value.value_float2->y > value.y;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_LESS: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return cell_value.value_float2->x < value.x &&
- cell_value.value_float2->y < value.y;
- },
- rows_included);
- break;
- }
- }
+ case SPREADSHEET_ROW_FILTER_LESS: {
+ apply_filter_operation(
+ column_data.typed<int>(),
+ [&](const int cell) { return cell < value; },
+ prev_mask,
+ new_indices);
break;
}
- case SPREADSHEET_VALUE_TYPE_FLOAT3: {
- const float3 value = row_filter.value_float3;
- switch (row_filter.operation) {
- case SPREADSHEET_ROW_FILTER_EQUAL: {
- const float threshold_squared = row_filter.threshold * row_filter.threshold;
- apply_filter_operation(
- values,
- [value, threshold_squared](const CellValue &cell_value) -> bool {
- return float3::distance_squared(*cell_value.value_float3, value) <
- threshold_squared;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_GREATER: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return cell_value.value_float3->x > value.x &&
- cell_value.value_float3->y > value.y &&
- cell_value.value_float3->z > value.z;
- },
- rows_included);
- break;
- }
- case SPREADSHEET_ROW_FILTER_LESS: {
- apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return cell_value.value_float3->x < value.x &&
- cell_value.value_float3->y < value.y &&
- cell_value.value_float3->z < value.z;
- },
- rows_included);
- break;
- }
- }
+ }
+ }
+ else if (column_data.type().is<float2>()) {
+ const float2 value = row_filter.value_float2;
+ switch (row_filter.operation) {
+ case SPREADSHEET_ROW_FILTER_EQUAL: {
+ const float threshold_sq = row_filter.threshold;
+ apply_filter_operation(
+ column_data.typed<float2>(),
+ [&](const float2 cell) {
+ return float2::distance_squared(cell, value) > threshold_sq;
+ },
+ prev_mask,
+ new_indices);
break;
}
- case SPREADSHEET_VALUE_TYPE_COLOR: {
- const ColorGeometry4f value = row_filter.value_color;
- switch (row_filter.operation) {
- case SPREADSHEET_ROW_FILTER_EQUAL: {
- const float threshold_squared = row_filter.threshold * row_filter.threshold;
- apply_filter_operation(
- values,
- [value, threshold_squared](const CellValue &cell_value) -> bool {
- return len_squared_v4v4(value, *cell_value.value_color) < threshold_squared;
- },
- rows_included);
- break;
- }
- }
+ case SPREADSHEET_ROW_FILTER_GREATER: {
+ apply_filter_operation(
+ column_data.typed<float2>(),
+ [&](const float2 cell) { return cell.x > value.x && cell.y > value.y; },
+ prev_mask,
+ new_indices);
break;
}
- case SPREADSHEET_VALUE_TYPE_BOOL: {
- const bool value = (row_filter.flag & SPREADSHEET_ROW_FILTER_BOOL_VALUE) != 0;
+ case SPREADSHEET_ROW_FILTER_LESS: {
apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- return *cell_value.value_bool == value;
+ column_data.typed<float2>(),
+ [&](const float2 cell) { return cell.x < value.x && cell.y < value.y; },
+ prev_mask,
+ new_indices);
+ break;
+ }
+ }
+ }
+ else if (column_data.type().is<float3>()) {
+ const float3 value = row_filter.value_float3;
+ switch (row_filter.operation) {
+ case SPREADSHEET_ROW_FILTER_EQUAL: {
+ const float threshold_sq = row_filter.threshold;
+ apply_filter_operation(
+ column_data.typed<float3>(),
+ [&](const float3 cell) {
+ return float3::distance_squared(cell, value) > threshold_sq;
},
- rows_included);
+ prev_mask,
+ new_indices);
break;
}
- case SPREADSHEET_VALUE_TYPE_INSTANCES: {
- const StringRef value = row_filter.value_string;
+ case SPREADSHEET_ROW_FILTER_GREATER: {
apply_filter_operation(
- values,
- [value](const CellValue &cell_value) -> bool {
- const ID *id = nullptr;
- if (cell_value.value_object) {
- id = &cell_value.value_object->object->id;
- }
- else if (cell_value.value_collection) {
- id = &cell_value.value_collection->collection->id;
- }
- if (id == nullptr) {
- return false;
- }
-
- return value == id->name + 2;
+ column_data.typed<float3>(),
+ [&](const float3 cell) {
+ return cell.x > value.x && cell.y > value.y && cell.z > value.z;
},
- rows_included);
+ prev_mask,
+ new_indices);
break;
}
- default:
+ case SPREADSHEET_ROW_FILTER_LESS: {
+ apply_filter_operation(
+ column_data.typed<float3>(),
+ [&](const float3 cell) {
+ return cell.x < value.x && cell.y < value.y && cell.z < value.z;
+ },
+ prev_mask,
+ new_indices);
break;
+ }
}
-
- /* Only one column should have this name. */
- break;
}
-}
-
-static void index_vector_from_bools(Span<bool> selection, Vector<int64_t> &indices)
-{
- for (const int i : selection.index_range()) {
- if (selection[i]) {
- indices.append(i);
+ else if (column_data.type().is<ColorGeometry4f>()) {
+ const ColorGeometry4f value = row_filter.value_color;
+ switch (row_filter.operation) {
+ case SPREADSHEET_ROW_FILTER_EQUAL: {
+ const float threshold_sq = row_filter.threshold;
+ apply_filter_operation(
+ column_data.typed<ColorGeometry4f>(),
+ [&](const ColorGeometry4f cell) {
+ return len_squared_v4v4(cell, value) > threshold_sq;
+ },
+ prev_mask,
+ new_indices);
+ break;
+ }
+ }
+ }
+ else if (column_data.type().is<InstanceReference>()) {
+ const StringRef value = row_filter.value_string;
+ switch (row_filter.operation) {
+ case SPREADSHEET_ROW_FILTER_EQUAL: {
+ apply_filter_operation(
+ column_data.typed<InstanceReference>(),
+ [&](const InstanceReference cell) {
+ switch (cell.type()) {
+ case InstanceReference::Type::Object: {
+ return value == (reinterpret_cast<ID &>(cell.object()).name + 2);
+ }
+ case InstanceReference::Type::Collection: {
+ return value == (reinterpret_cast<ID &>(cell.collection()).name + 2);
+ }
+ case InstanceReference::Type::GeometrySet: {
+ return false;
+ }
+ case InstanceReference::Type::None: {
+ return false;
+ }
+ }
+ BLI_assert_unreachable();
+ return false;
+ },
+ prev_mask,
+ new_indices);
+ break;
+ }
}
}
}
@@ -297,10 +255,10 @@ static bool use_selection_filter(const SpaceSpreadsheet &sspreadsheet,
return true;
}
-Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
- const SpreadsheetLayout &spreadsheet_layout,
- const DataSource &data_source,
- ResourceScope &scope)
+IndexMask spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
+ const SpreadsheetLayout &spreadsheet_layout,
+ const DataSource &data_source,
+ ResourceScope &scope)
{
const int tot_rows = data_source.tot_rows();
@@ -309,29 +267,46 @@ Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
/* Avoid allocating an array if no row filtering is necessary. */
if (!(use_filters || use_selection)) {
- return IndexRange(tot_rows).as_span();
+ return IndexMask(tot_rows);
}
- Array<bool> rows_included(tot_rows, true);
+ IndexMask mask(tot_rows);
+
+ Vector<int64_t> mask_indices;
+ mask_indices.reserve(tot_rows);
+
+ if (use_selection) {
+ const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>(
+ &data_source);
+ mask = geometry_data_source->apply_selection_filter(mask_indices);
+ }
if (use_filters) {
+ Map<StringRef, const ColumnValues *> columns;
+ for (const ColumnLayout &column : spreadsheet_layout.columns) {
+ columns.add(column.values->name(), column.values);
+ }
+
LISTBASE_FOREACH (const SpreadsheetRowFilter *, row_filter, &sspreadsheet.row_filters) {
if (row_filter->flag & SPREADSHEET_ROW_FILTER_ENABLED) {
- apply_row_filter(spreadsheet_layout, *row_filter, rows_included);
+ if (!columns.contains(row_filter->column_name)) {
+ continue;
+ }
+ Vector<int64_t> new_indices;
+ new_indices.reserve(mask_indices.size());
+ apply_row_filter(*row_filter, columns, mask, new_indices);
+ std::swap(new_indices, mask_indices);
+ mask = IndexMask(mask_indices);
}
}
}
- if (use_selection) {
- const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>(
- &data_source);
- geometry_data_source->apply_selection_filter(rows_included);
+ if (mask_indices.is_empty()) {
+ BLI_assert(mask.is_empty() || mask.is_range());
+ return mask;
}
- Vector<int64_t> &indices = scope.construct<Vector<int64_t>>();
- index_vector_from_bools(rows_included, indices);
-
- return indices;
+ return IndexMask(scope.add_value(std::move(mask_indices)));
}
SpreadsheetRowFilter *spreadsheet_row_filter_new()
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh
index 0a5783e318d..3788baaa993 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.hh
@@ -23,10 +23,10 @@
namespace blender::ed::spreadsheet {
-Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
- const SpreadsheetLayout &spreadsheet_layout,
- const DataSource &data_source,
- ResourceScope &scope);
+IndexMask spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
+ const SpreadsheetLayout &spreadsheet_layout,
+ const DataSource &data_source,
+ ResourceScope &scope);
SpreadsheetRowFilter *spreadsheet_row_filter_new();
SpreadsheetRowFilter *spreadsheet_row_filter_copy(const SpreadsheetRowFilter *src_row_filter);
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 a07abac4474..bcced7b5937 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
@@ -114,6 +114,8 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter,
}
case SPREADSHEET_VALUE_TYPE_STRING:
return row_filter.value_string;
+ case SPREADSHEET_VALUE_TYPE_UNKNOWN:
+ return "";
}
BLI_assert_unreachable();
return "";
@@ -238,6 +240,10 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE);
break;
case SPREADSHEET_VALUE_TYPE_STRING:
+ uiItemR(layout, filter_ptr, "value_string", 0, IFACE_("Value"), ICON_NONE);
+ break;
+ case SPREADSHEET_VALUE_TYPE_UNKNOWN:
+ uiItemL(layout, IFACE_("Unkown column type"), ICON_ERROR);
break;
}
}
diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh
index 03e81b13714..fc8612d6f87 100644
--- a/source/blender/functions/FN_generic_virtual_array.hh
+++ b/source/blender/functions/FN_generic_virtual_array.hh
@@ -174,6 +174,11 @@ class GVArrayCommon {
void get_internal_single_to_uninitialized(void *r_value) const;
void get(const int64_t index, void *r_value) const;
+ /**
+ * Returns a copy of the value at the given index. Usually a typed virtual array should
+ * be used instead, but sometimes this is simpler when only a few indices are needed.
+ */
+ template<typename T> T get(const int64_t index) const;
void get_to_uninitialized(const int64_t index, void *r_value) const;
};
@@ -691,6 +696,16 @@ inline void GVArrayCommon::get(const int64_t index, void *r_value) const
impl_->get(index, r_value);
}
+template<typename T> inline T GVArrayCommon::get(const int64_t index) const
+{
+ BLI_assert(index >= 0);
+ BLI_assert(index < this->size());
+ BLI_assert(this->type().is<T>());
+ T value{};
+ impl_->get(index, &value);
+ return value;
+}
+
/* Same as `get`, but `r_value` is expected to point to uninitialized memory. */
inline void GVArrayCommon::get_to_uninitialized(const int64_t index, void *r_value) const
{
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 3ae7b3b68b8..a7a19be5b3e 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -2006,6 +2006,7 @@ typedef enum eSpaceSpreadsheet_ContextType {
} eSpaceSpreadsheet_ContextType;
typedef enum eSpreadsheetColumnValueType {
+ SPREADSHEET_VALUE_TYPE_UNKNOWN = -1,
SPREADSHEET_VALUE_TYPE_BOOL = 0,
SPREADSHEET_VALUE_TYPE_INT32 = 1,
SPREADSHEET_VALUE_TYPE_FLOAT = 2,