Differential D13478 Diff 46059 source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
| /* | /* | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License | * modify it under the terms of the GNU General Public License | ||||
| * as published by the Free Software Foundation; either version 2 | * as published by the Free Software Foundation; either version 2 | ||||
| * of the License, or (at your option) any later version. | * of the License, or (at your option) any later version. | ||||
| * | * | ||||
| * This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | ||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| * GNU General Public License for more details. | * GNU General Public License for more details. | ||||
| * | * | ||||
| * You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
| * along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
| */ | */ | ||||
| #include "BLI_virtual_array.hh" | |||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_editmesh.h" | #include "BKE_editmesh.h" | ||||
| #include "BKE_lib_id.h" | #include "BKE_lib_id.h" | ||||
| #include "BKE_mesh.h" | #include "BKE_mesh.h" | ||||
| #include "BKE_mesh_wrapper.h" | #include "BKE_mesh_wrapper.h" | ||||
| #include "BKE_modifier.h" | #include "BKE_modifier.h" | ||||
| #include "BKE_volume.h" | #include "BKE_volume.h" | ||||
| Show All 19 Lines | |||||
| #include "bmesh.h" | #include "bmesh.h" | ||||
| #include "spreadsheet_data_source_geometry.hh" | #include "spreadsheet_data_source_geometry.hh" | ||||
| #include "spreadsheet_intern.hh" | #include "spreadsheet_intern.hh" | ||||
| namespace geo_log = blender::nodes::geometry_nodes_eval_log; | namespace geo_log = blender::nodes::geometry_nodes_eval_log; | ||||
| using blender::fn::GField; | using blender::fn::GField; | ||||
| namespace blender::ed::spreadsheet { | MAKE_CPP_TYPE(InstanceReference, InstanceReference, CPPTypeFlags::None) | ||||
JacquesLucke: This shouldn't be done here, but in blenkernel somewhere. | |||||
HooglyBooglyAuthorUnsubmitted Done Inline ActionsGood point. I moved it to geometry_component_instances.cc HooglyBoogly: Good point. I moved it to `geometry_component_instances.cc` | |||||
| static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type( | namespace blender::ed::spreadsheet { | ||||
| 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( | void ExtraColumns::foreach_default_column_ids( | ||||
| FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const | FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const | ||||
| { | { | ||||
| for (const auto item : columns_.items()) { | for (const auto item : columns_.items()) { | ||||
| SpreadsheetColumnID column_id; | SpreadsheetColumnID column_id; | ||||
| column_id.name = (char *)item.key.c_str(); | column_id.name = (char *)item.key.c_str(); | ||||
| fn(column_id, true); | fn(column_id, true); | ||||
| } | } | ||||
| } | } | ||||
| std::unique_ptr<ColumnValues> ExtraColumns::get_column_values( | std::unique_ptr<ColumnValues> ExtraColumns::get_column_values( | ||||
| const SpreadsheetColumnID &column_id) const | const SpreadsheetColumnID &column_id) const | ||||
| { | { | ||||
| const fn::GSpan *values = columns_.lookup_ptr(column_id.name); | const fn::GSpan *values = columns_.lookup_ptr(column_id.name); | ||||
| if (values == nullptr) { | if (values == nullptr) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| eSpreadsheetColumnValueType column_type = *cpp_type_to_column_value_type(values->type()); | return std::make_unique<ColumnValues>(column_id.name, fn::GVArray::ForSpan(*values)); | ||||
| 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; | |||||
| } | |||||
| }); | |||||
| } | } | ||||
| void GeometryDataSource::foreach_default_column_ids( | void GeometryDataSource::foreach_default_column_ids( | ||||
| FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const | FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const | ||||
| { | { | ||||
| if (component_->attribute_domain_size(domain_) == 0) { | if (component_->attribute_domain_size(domain_) == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| Show All 38 Lines | if (extra_column_values) { | ||||
| return extra_column_values; | return extra_column_values; | ||||
| } | } | ||||
| if (component_->type() == GEO_COMPONENT_TYPE_INSTANCES) { | if (component_->type() == GEO_COMPONENT_TYPE_INSTANCES) { | ||||
| const InstancesComponent &instances = static_cast<const InstancesComponent &>(*component_); | const InstancesComponent &instances = static_cast<const InstancesComponent &>(*component_); | ||||
| if (STREQ(column_id.name, "Name")) { | if (STREQ(column_id.name, "Name")) { | ||||
| Span<int> reference_handles = instances.instance_reference_handles(); | Span<int> reference_handles = instances.instance_reference_handles(); | ||||
| Span<InstanceReference> references = instances.references(); | Span<InstanceReference> references = instances.references(); | ||||
| std::unique_ptr<ColumnValues> values = column_values_from_function( | return std::make_unique<ColumnValues>( | ||||
| SPREADSHEET_VALUE_TYPE_INSTANCES, | column_id.name, | ||||
| "Name", | VArray<InstanceReference>::ForFunc(domain_size, | ||||
| domain_size, | [reference_handles, references](int64_t index) { | ||||
| [reference_handles, references](int index, CellValue &r_cell_value) { | return references[reference_handles[index]]; | ||||
| 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; | |||||
| } | } | ||||
| Span<float4x4> transforms = instances.instance_transforms(); | Span<float4x4> transforms = instances.instance_transforms(); | ||||
| if (STREQ(column_id.name, "Rotation")) { | if (STREQ(column_id.name, "Rotation")) { | ||||
| return column_values_from_function( | return std::make_unique<ColumnValues>( | ||||
| SPREADSHEET_VALUE_TYPE_FLOAT3, | column_id.name, VArray<float3>::ForFunc(domain_size, [transforms](int64_t index) { | ||||
| column_id.name, | return transforms[index].to_euler(); | ||||
| domain_size, | })); | ||||
| [transforms](int index, CellValue &r_cell_value) { | |||||
| r_cell_value.value_float3 = transforms[index].to_euler(); | |||||
| }); | |||||
| } | } | ||||
| if (STREQ(column_id.name, "Scale")) { | if (STREQ(column_id.name, "Scale")) { | ||||
| return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT3, | return std::make_unique<ColumnValues>( | ||||
| column_id.name, | column_id.name, VArray<float3>::ForFunc(domain_size, [transforms](int64_t index) { | ||||
| domain_size, | return transforms[index].scale(); | ||||
| [transforms](int index, CellValue &r_cell_value) { | })); | ||||
| r_cell_value.value_float3 = transforms[index].scale(); | |||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| bke::ReadAttributeLookup attribute = component_->attribute_try_get_for_read(column_id.name); | bke::ReadAttributeLookup attribute = component_->attribute_try_get_for_read(column_id.name); | ||||
| if (!attribute) { | if (!attribute) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| fn::GVArray varray = std::move(attribute.varray); | fn::GVArray varray = std::move(attribute.varray); | ||||
| if (attribute.domain != domain_) { | if (attribute.domain != domain_) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type()); | return std::make_unique<ColumnValues>(column_id.name, std::move(varray)); | ||||
| 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 {}; | |||||
| } | } | ||||
| int GeometryDataSource::tot_rows() const | int GeometryDataSource::tot_rows() const | ||||
| { | { | ||||
| return component_->attribute_domain_size(domain_); | return component_->attribute_domain_size(domain_); | ||||
| } | } | ||||
| using IsVertexSelectedFn = FunctionRef<bool(int vertex_index)>; | /** | ||||
| * Only data sets corresponding to mesh objects in edit mode currently support selection filtering. | |||||
| 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; | |||||
| } | |||||
| } | |||||
| bool GeometryDataSource::has_selection_filter() const | bool GeometryDataSource::has_selection_filter() const | ||||
| { | { | ||||
| Object *object_orig = DEG_get_original_object(object_eval_); | Object *object_orig = DEG_get_original_object(object_eval_); | ||||
| if (object_orig->type != OB_MESH) { | if (object_orig->type != OB_MESH) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (object_orig->mode != OB_MODE_EDIT) { | if (object_orig->mode != OB_MODE_EDIT) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (component_->type() != GEO_COMPONENT_TYPE_MESH) { | if (component_->type() != GEO_COMPONENT_TYPE_MESH) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | 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_}; | std::lock_guard lock{mutex_}; | ||||
| BLI_assert(object_eval_->mode == OB_MODE_EDIT); | BLI_assert(object_eval_->mode == OB_MODE_EDIT); | ||||
| BLI_assert(component_->type() == GEO_COMPONENT_TYPE_MESH); | BLI_assert(component_->type() == GEO_COMPONENT_TYPE_MESH); | ||||
| Object *object_orig = DEG_get_original_object(object_eval_); | Object *object_orig = DEG_get_original_object(object_eval_); | ||||
| const MeshComponent *mesh_component = static_cast<const MeshComponent *>(component_); | const MeshComponent *mesh_component = static_cast<const MeshComponent *>(component_); | ||||
| const Mesh *mesh_eval = mesh_component->get_for_read(); | const Mesh *mesh_eval = mesh_component->get_for_read(); | ||||
| Mesh *mesh_orig = (Mesh *)object_orig->data; | Mesh *mesh_orig = (Mesh *)object_orig->data; | ||||
| BMesh *bm = mesh_orig->edit_mesh->bm; | BMesh *bm = mesh_orig->edit_mesh->bm; | ||||
| BM_mesh_elem_table_ensure(bm, BM_VERT); | BM_mesh_elem_table_ensure(bm, BM_VERT); | ||||
| int *orig_indices = (int *)CustomData_get_layer(&mesh_eval->vdata, CD_ORIGINDEX); | int *orig_indices = (int *)CustomData_get_layer(&mesh_eval->vdata, CD_ORIGINDEX); | ||||
| if (orig_indices != nullptr) { | if (orig_indices != nullptr) { | ||||
| /* Use CD_ORIGINDEX layer if it exists. */ | /* Use CD_ORIGINDEX layer if it exists. */ | ||||
| auto is_vertex_selected = [&](int vertex_index) -> bool { | VArray<bool> selection = mesh_component->attribute_try_adapt_domain<bool>( | ||||
| VArray<bool>::ForFunc(mesh_eval->totvert, | |||||
| [&](int vertex_index) -> bool { | |||||
JacquesLuckeUnsubmitted Done Inline ActionsBe careful with referencing the context when building a lambda that might outlive the surrounding scope. Better be explicit about what has to be captured. Same below. JacquesLucke: Be careful with referencing the context when building a lambda that might outlive the… | |||||
| const int i_orig = orig_indices[vertex_index]; | const int i_orig = orig_indices[vertex_index]; | ||||
| if (i_orig < 0) { | if (i_orig < 0) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (i_orig >= bm->totvert) { | if (i_orig >= bm->totvert) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| BMVert *vert = bm->vtable[i_orig]; | BMVert *vert = bm->vtable[i_orig]; | ||||
| return BM_elem_flag_test(vert, BM_ELEM_SELECT); | return BM_elem_flag_test(vert, BM_ELEM_SELECT); | ||||
| }; | }), | ||||
| get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included); | ATTR_DOMAIN_POINT, | ||||
| domain_); | |||||
| return index_mask_from_bool_array(selection, indices); | |||||
| } | } | ||||
| else if (mesh_eval->totvert == bm->totvert) { | |||||
| if (mesh_eval->totvert == bm->totvert) { | |||||
| /* Use a simple heuristic to match original vertices to evaluated ones. */ | /* Use a simple heuristic to match original vertices to evaluated ones. */ | ||||
| auto is_vertex_selected = [&](int vertex_index) -> bool { | VArray<bool> selection = mesh_component->attribute_try_adapt_domain<bool>( | ||||
| VArray<bool>::ForFunc(mesh_eval->totvert, | |||||
| [&](int vertex_index) -> bool { | |||||
| BMVert *vert = bm->vtable[vertex_index]; | BMVert *vert = bm->vtable[vertex_index]; | ||||
| return BM_elem_flag_test(vert, BM_ELEM_SELECT); | return BM_elem_flag_test(vert, BM_ELEM_SELECT); | ||||
| }; | }), | ||||
| get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included); | ATTR_DOMAIN_POINT, | ||||
| domain_); | |||||
| return index_mask_from_bool_array(selection, indices); | |||||
| } | } | ||||
| return IndexMask(mesh_eval->totvert); | |||||
| } | } | ||||
| void VolumeDataSource::foreach_default_column_ids( | void VolumeDataSource::foreach_default_column_ids( | ||||
| FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const | FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const | ||||
| { | { | ||||
| if (component_->is_empty()) { | if (component_->is_empty()) { | ||||
| return; | return; | ||||
| } | } | ||||
| Show All 10 Lines | std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values( | ||||
| const Volume *volume = component_->get_for_read(); | const Volume *volume = component_->get_for_read(); | ||||
| if (volume == nullptr) { | if (volume == nullptr) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| #ifdef WITH_OPENVDB | #ifdef WITH_OPENVDB | ||||
| const int size = this->tot_rows(); | const int size = this->tot_rows(); | ||||
| if (STREQ(column_id.name, "Grid Name")) { | if (STREQ(column_id.name, "Grid Name")) { | ||||
| return column_values_from_function( | return std::make_unique<ColumnValues>( | ||||
| SPREADSHEET_VALUE_TYPE_STRING, | IFACE_("Grid Name"), VArray<std::string>::ForFunc(size, [volume](int64_t index) { | ||||
| IFACE_("Grid Name"), | |||||
| size, | |||||
| [volume](int index, CellValue &r_cell_value) { | |||||
| const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index); | const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index); | ||||
| r_cell_value.value_string = BKE_volume_grid_name(volume_grid); | return BKE_volume_grid_name(volume_grid); | ||||
| }, | })); | ||||
| 6.0f); | |||||
| } | } | ||||
| if (STREQ(column_id.name, "Data Type")) { | if (STREQ(column_id.name, "Data Type")) { | ||||
| return column_values_from_function( | return std::make_unique<ColumnValues>( | ||||
| SPREADSHEET_VALUE_TYPE_STRING, | IFACE_("Data Type"), VArray<std::string>::ForFunc(size, [volume](int64_t index) { | ||||
| IFACE_("Type"), | |||||
| size, | |||||
| [volume](int index, CellValue &r_cell_value) { | |||||
| const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index); | const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, index); | ||||
| const VolumeGridType type = BKE_volume_grid_type(volume_grid); | const VolumeGridType type = BKE_volume_grid_type(volume_grid); | ||||
| const char *name = nullptr; | const char *name = nullptr; | ||||
| RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name); | RNA_enum_name_from_value(rna_enum_volume_grid_data_type_items, type, &name); | ||||
| r_cell_value.value_string = IFACE_(name); | return IFACE_(name); | ||||
| }, | })); | ||||
| 5.0f); | |||||
| } | } | ||||
| if (STREQ(column_id.name, "Class")) { | if (STREQ(column_id.name, "Class")) { | ||||
| return column_values_from_function( | return std::make_unique<ColumnValues>( | ||||
| SPREADSHEET_VALUE_TYPE_STRING, | IFACE_("Class"), VArray<std::string>::ForFunc(size, [volume](int64_t index) { | ||||
| IFACE_("Class"), | |||||
| size, | |||||
| [volume](int index, CellValue &r_cell_value) { | |||||
| const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, 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::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); | ||||
| openvdb::GridClass grid_class = grid->getGridClass(); | openvdb::GridClass grid_class = grid->getGridClass(); | ||||
| if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) { | if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) { | ||||
| r_cell_value.value_string = IFACE_("Fog Volume"); | return IFACE_("Fog Volume"); | ||||
| } | } | ||||
| else if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) { | else if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) { | ||||
| r_cell_value.value_string = IFACE_("Level Set"); | return IFACE_("Level Set"); | ||||
| } | } | ||||
| else { | else { | ||||
| r_cell_value.value_string = IFACE_("Unknown"); | return IFACE_("Unknown"); | ||||
| } | } | ||||
| }, | })); | ||||
| 5.0f); | |||||
| } | } | ||||
| #else | #else | ||||
| UNUSED_VARS(column_id); | UNUSED_VARS(column_id); | ||||
| #endif | #endif | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 207 Lines • Show Last 20 Lines | |||||
This shouldn't be done here, but in blenkernel somewhere.