Differential D16083 Diff 56430 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
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | attributes.for_all( | ||||
| if (attribute_id.is_anonymous()) { | if (attribute_id.is_anonymous()) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| if (!bke::allow_procedural_attribute_access(attribute_id.name())) { | if (!bke::allow_procedural_attribute_access(attribute_id.name())) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| SpreadsheetColumnID column_id; | SpreadsheetColumnID column_id; | ||||
| column_id.name = (char *)attribute_id.name().data(); | column_id.name = (char *)attribute_id.name().data(); | ||||
| fn(column_id, false); | const bool is_front = attribute_id.name() == ".viewer"; | ||||
| fn(column_id, is_front); | |||||
| return true; | return true; | ||||
| }); | }); | ||||
| if (component_->type() == GEO_COMPONENT_TYPE_INSTANCES) { | if (component_->type() == GEO_COMPONENT_TYPE_INSTANCES) { | ||||
| fn({(char *)"Rotation"}, false); | fn({(char *)"Rotation"}, false); | ||||
| fn({(char *)"Scale"}, false); | fn({(char *)"Scale"}, false); | ||||
| } | } | ||||
| else if (G.debug_value == 4001 && component_->type() == GEO_COMPONENT_TYPE_MESH) { | else if (G.debug_value == 4001 && component_->type() == GEO_COMPONENT_TYPE_MESH) { | ||||
| ▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( | ||||
| if (!attribute) { | if (!attribute) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| GVArray varray = std::move(attribute.varray); | GVArray varray = std::move(attribute.varray); | ||||
| if (attribute.domain != domain_) { | if (attribute.domain != domain_) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| return std::make_unique<ColumnValues>(column_id.name, std::move(varray)); | StringRefNull column_display_name = column_id.name; | ||||
| if (column_display_name == ".viewer") { | |||||
| column_display_name = "Viewer"; | |||||
| } | |||||
| return std::make_unique<ColumnValues>(column_display_name, std::move(varray)); | |||||
| } | } | ||||
| int GeometryDataSource::tot_rows() const | int GeometryDataSource::tot_rows() const | ||||
| { | { | ||||
| if (!component_->attributes().has_value()) { | if (!component_->attributes().has_value()) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| const bke::AttributeAccessor attributes = *component_->attributes(); | const bke::AttributeAccessor attributes = *component_->attributes(); | ||||
| ▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | if (object_eval->mode == OB_MODE_EDIT && object_eval->type == OB_MESH) { | ||||
| if (mesh == nullptr) { | if (mesh == nullptr) { | ||||
| return geometry_set; | return geometry_set; | ||||
| } | } | ||||
| BKE_mesh_wrapper_ensure_mdata(mesh); | BKE_mesh_wrapper_ensure_mdata(mesh); | ||||
| MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); | MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); | ||||
| mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); | mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); | ||||
| } | } | ||||
| else { | else { | ||||
| if (BLI_listbase_count(&sspreadsheet->context_path) == 1) { | if (BLI_listbase_count(&sspreadsheet->viewer_path.path) == 1) { | ||||
| /* Use final evaluated object. */ | /* Use final evaluated object. */ | ||||
| if (object_eval->runtime.geometry_set_eval != nullptr) { | if (object_eval->runtime.geometry_set_eval != nullptr) { | ||||
| geometry_set = *object_eval->runtime.geometry_set_eval; | geometry_set = *object_eval->runtime.geometry_set_eval; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (const ViewerNodeLog *viewer_log = | if (const ViewerNodeLog *viewer_log = | ||||
| nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_spreadsheet( | nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_path( | ||||
| *sspreadsheet)) { | sspreadsheet->viewer_path)) { | ||||
| geometry_set = viewer_log->geometry; | geometry_set = viewer_log->geometry; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return geometry_set; | return geometry_set; | ||||
| } | } | ||||
| static void find_fields_to_evaluate(const SpaceSpreadsheet *sspreadsheet, | |||||
| Map<std::string, GField> &r_fields) | |||||
| { | |||||
| if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { | |||||
| return; | |||||
| } | |||||
| if (BLI_listbase_count(&sspreadsheet->context_path) <= 1) { | |||||
| /* No viewer is currently referenced by the context path. */ | |||||
| return; | |||||
| } | |||||
| if (const ViewerNodeLog *viewer_log = | |||||
| nodes::geo_eval_log::GeoModifierLog::find_viewer_node_log_for_spreadsheet( | |||||
| *sspreadsheet)) { | |||||
| if (viewer_log->field) { | |||||
| r_fields.add("Viewer", viewer_log->field); | |||||
| } | |||||
| } | |||||
| } | |||||
| class GeometryComponentCacheKey : public SpreadsheetCache::Key { | class GeometryComponentCacheKey : public SpreadsheetCache::Key { | ||||
| public: | public: | ||||
| /* Use the pointer to the geometry component as a key to detect when the geometry changed. */ | /* Use the pointer to the geometry component as a key to detect when the geometry changed. */ | ||||
| const GeometryComponent *component; | const GeometryComponent *component; | ||||
| GeometryComponentCacheKey(const GeometryComponent &component) : component(&component) | GeometryComponentCacheKey(const GeometryComponent &component) : component(&component) | ||||
| { | { | ||||
| } | } | ||||
| Show All 15 Lines | |||||
| class GeometryComponentCacheValue : public SpreadsheetCache::Value { | class GeometryComponentCacheValue : public SpreadsheetCache::Value { | ||||
| public: | public: | ||||
| /* Stores the result of fields evaluated on a geometry component. Without this, fields would have | /* Stores the result of fields evaluated on a geometry component. Without this, fields would have | ||||
| * to be reevaluated on every redraw. */ | * to be reevaluated on every redraw. */ | ||||
| Map<std::pair<eAttrDomain, GField>, GArray<>> arrays; | Map<std::pair<eAttrDomain, GField>, GArray<>> arrays; | ||||
| }; | }; | ||||
| static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet, | |||||
| const GeometryComponent &component, | |||||
| ExtraColumns &r_extra_columns) | |||||
| { | |||||
| Map<std::string, GField> fields_to_show; | |||||
| find_fields_to_evaluate(sspreadsheet, fields_to_show); | |||||
| GeometryComponentCacheValue &cache = | |||||
| sspreadsheet->runtime->cache.lookup_or_add<GeometryComponentCacheValue>( | |||||
| std::make_unique<GeometryComponentCacheKey>(component)); | |||||
| const eAttrDomain domain = (eAttrDomain)sspreadsheet->attribute_domain; | |||||
| const int domain_num = component.attribute_domain_size(domain); | |||||
| for (const auto item : fields_to_show.items()) { | |||||
| const StringRef name = item.key; | |||||
| const GField &field = item.value; | |||||
| /* Use the cached evaluated array if it exists, otherwise evaluate the field now. */ | |||||
| GArray<> &evaluated_array = cache.arrays.lookup_or_add_cb({domain, field}, [&]() { | |||||
| GArray<> evaluated_array(field.cpp_type(), domain_num); | |||||
| bke::GeometryFieldContext field_context{component, domain}; | |||||
| fn::FieldEvaluator field_evaluator{field_context, domain_num}; | |||||
| field_evaluator.add_with_destination(field, evaluated_array); | |||||
| field_evaluator.evaluate(); | |||||
| return evaluated_array; | |||||
| }); | |||||
| r_extra_columns.add(name, evaluated_array.as_span()); | |||||
| } | |||||
| } | |||||
| std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval) | std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval) | ||||
| { | { | ||||
| SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); | ||||
| const eAttrDomain domain = (eAttrDomain)sspreadsheet->attribute_domain; | const eAttrDomain domain = (eAttrDomain)sspreadsheet->attribute_domain; | ||||
| const GeometryComponentType component_type = GeometryComponentType( | const GeometryComponentType component_type = GeometryComponentType( | ||||
| sspreadsheet->geometry_component_type); | sspreadsheet->geometry_component_type); | ||||
| GeometrySet geometry_set = spreadsheet_get_display_geometry_set(sspreadsheet, object_eval); | GeometrySet geometry_set = spreadsheet_get_display_geometry_set(sspreadsheet, object_eval); | ||||
| if (!geometry_set.has(component_type)) { | if (!geometry_set.has(component_type)) { | ||||
| return {}; | return {}; | ||||
| } | } | ||||
| const GeometryComponent &component = *geometry_set.get_component_for_read(component_type); | |||||
| ExtraColumns extra_columns; | |||||
| add_fields_as_extra_columns(sspreadsheet, component, extra_columns); | |||||
| if (component_type == GEO_COMPONENT_TYPE_VOLUME) { | if (component_type == GEO_COMPONENT_TYPE_VOLUME) { | ||||
| return std::make_unique<VolumeDataSource>(std::move(geometry_set)); | return std::make_unique<VolumeDataSource>(std::move(geometry_set)); | ||||
| } | } | ||||
| return std::make_unique<GeometryDataSource>( | return std::make_unique<GeometryDataSource>( | ||||
| object_eval, std::move(geometry_set), component_type, domain, std::move(extra_columns)); | object_eval, std::move(geometry_set), component_type, domain); | ||||
| } | } | ||||
| } // namespace blender::ed::spreadsheet | } // namespace blender::ed::spreadsheet | ||||