diff options
author | Jacques Lucke <jacques@blender.org> | 2021-03-11 14:23:01 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-03-11 14:23:01 +0300 |
commit | 5f1f233dc97de34f6be0f51edd3cbf2d8247fbda (patch) | |
tree | 744a8e1345bacc9827553a6113caa8264047c8d4 /source/blender | |
parent | 74f3edc3431875223c1045f918729a43f94a6924 (diff) |
Spreadsheet: expore more domains and point cloud data
Ref T86135.
Differential Revision: https://developer.blender.org/D10681
Diffstat (limited to 'source/blender')
4 files changed, 198 insertions, 30 deletions
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 53424c60d59..8ab1baaaea3 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -126,7 +126,7 @@ static std::unique_ptr<SpreadsheetDrawer> generate_spreadsheet_drawer(const bCon return {}; } Object *object_orig = (Object *)used_id; - if (object_orig->type != OB_MESH) { + if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD)) { return {}; } Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig); diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc index 8459973ed4a..35dc9d62aa3 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc @@ -332,10 +332,11 @@ static void add_columns_for_attribute(const ReadAttribute *attribute, } } -static GeometrySet get_display_geometry_set(Object *object_eval) +static GeometrySet get_display_geometry_set(Object *object_eval, + const GeometryComponentType used_component_type) { GeometrySet geometry_set; - if (object_eval->mode == OB_MODE_EDIT) { + if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) { Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false); if (mesh == nullptr) { return geometry_set; @@ -354,10 +355,87 @@ static GeometrySet get_display_geometry_set(Object *object_eval) return geometry_set; } -static Span<int64_t> filter_visible_mesh_vertex_rows(const bContext *C, - Object *object_eval, - const MeshComponent *component, - ResourceCollector &resources) +using IsVertexSelectedFn = FunctionRef<bool(int vertex_index)>; + +static void get_selected_vertex_indices(const Mesh &mesh, + const IsVertexSelectedFn is_vertex_selected_fn, + Vector<int64_t> &r_vertex_indices) +{ + for (const int i : IndexRange(mesh.totvert)) { + if (is_vertex_selected_fn(i)) { + r_vertex_indices.append(i); + } + } +} + +static void get_selected_corner_indices(const Mesh &mesh, + const IsVertexSelectedFn is_vertex_selected_fn, + Vector<int64_t> &r_corner_indices) +{ + for (const int i : IndexRange(mesh.totloop)) { + const MLoop &loop = mesh.mloop[i]; + if (is_vertex_selected_fn(loop.v)) { + r_corner_indices.append(i); + } + } +} + +static void get_selected_polygon_indices(const Mesh &mesh, + const IsVertexSelectedFn is_vertex_selected_fn, + Vector<int64_t> &r_polygon_indices) +{ + for (const int poly_index : IndexRange(mesh.totpoly)) { + const MPoly &poly = mesh.mpoly[poly_index]; + bool is_selected = true; + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const MLoop &loop = mesh.mloop[loop_index]; + if (!is_vertex_selected_fn(loop.v)) { + is_selected = false; + break; + } + } + if (is_selected) { + r_polygon_indices.append(poly_index); + } + } +} + +static void get_selected_edge_indices(const Mesh &mesh, + const IsVertexSelectedFn is_vertex_selected_fn, + Vector<int64_t> &r_edge_indices) +{ + for (const int i : IndexRange(mesh.totedge)) { + const MEdge &edge = mesh.medge[i]; + if (is_vertex_selected_fn(edge.v1) && is_vertex_selected_fn(edge.v2)) { + r_edge_indices.append(i); + } + } +} + +static void get_selected_indices_on_domain(const Mesh &mesh, + const AttributeDomain domain, + const IsVertexSelectedFn is_vertex_selected_fn, + Vector<int64_t> &r_indices) +{ + switch (domain) { + case ATTR_DOMAIN_POINT: + return get_selected_vertex_indices(mesh, is_vertex_selected_fn, r_indices); + case ATTR_DOMAIN_POLYGON: + return get_selected_polygon_indices(mesh, is_vertex_selected_fn, r_indices); + case ATTR_DOMAIN_CORNER: + return get_selected_corner_indices(mesh, is_vertex_selected_fn, r_indices); + case ATTR_DOMAIN_EDGE: + return get_selected_edge_indices(mesh, is_vertex_selected_fn, r_indices); + default: + return; + } +} + +static Span<int64_t> filter_mesh_elements_by_selection(const bContext *C, + Object *object_eval, + const MeshComponent *component, + const AttributeDomain domain, + ResourceCollector &resources) { SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); const bool show_only_selected = sspreadsheet->filter_flag & SPREADSHEET_FILTER_SELECTED_ONLY; @@ -372,47 +450,55 @@ static Span<int64_t> filter_visible_mesh_vertex_rows(const bContext *C, int *orig_indices = (int *)CustomData_get_layer(&mesh_eval->vdata, CD_ORIGINDEX); if (orig_indices != nullptr) { /* Use CD_ORIGINDEX layer if it exists. */ - for (const int i_eval : IndexRange(mesh_eval->totvert)) { - const int i_orig = orig_indices[i_eval]; - if (i_orig >= 0 && i_orig < bm->totvert) { - BMVert *vert = bm->vtable[i_orig]; - if (BM_elem_flag_test(vert, BM_ELEM_SELECT)) { - visible_rows.append(i_eval); - } + 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, visible_rows); } else if (mesh_eval->totvert == bm->totvert) { /* Use a simple heuristic to match original vertices to evaluated ones. */ - for (const int i : IndexRange(mesh_eval->totvert)) { - BMVert *vert = bm->vtable[i]; - if (BM_elem_flag_test(vert, BM_ELEM_SELECT)) { - visible_rows.append(i); - } - } + 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, visible_rows); } /* This is safe, because the vector lives in the resource collector. */ return visible_rows.as_span(); } /* No filter is used. */ - const int domain_size = component->attribute_domain_size(ATTR_DOMAIN_POINT); + const int domain_size = component->attribute_domain_size(domain); return IndexRange(domain_size).as_span(); } std::unique_ptr<SpreadsheetDrawer> spreadsheet_drawer_from_geometry_attributes(const bContext *C, Object *object_eval) { + SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); + const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain; + const GeometryComponentType component_type = (GeometryComponentType) + sspreadsheet->geometry_component_type; + /* Create a resource collector that owns stuff that needs to live until drawing is done. */ std::unique_ptr<ResourceCollector> resources = std::make_unique<ResourceCollector>(); - GeometrySet &geometry_set = resources->add_value(get_display_geometry_set(object_eval), - "geometry set"); + GeometrySet &geometry_set = resources->add_value( + get_display_geometry_set(object_eval, component_type), "geometry set"); - const AttributeDomain domain = ATTR_DOMAIN_POINT; - const GeometryComponentType component_type = GEO_COMPONENT_TYPE_MESH; const GeometryComponent *component = geometry_set.get_component_for_read(component_type); if (component == nullptr) { return {}; } + if (!component->attribute_domain_supported(domain)) { + return {}; + } Vector<std::string> attribute_names = get_sorted_attribute_names_to_display(*component, domain); @@ -425,9 +511,14 @@ std::unique_ptr<SpreadsheetDrawer> spreadsheet_drawer_from_geometry_attributes(c } /* The filter below only works for mesh vertices currently. */ - BLI_assert(domain == ATTR_DOMAIN_POINT && component_type == GEO_COMPONENT_TYPE_MESH); - Span<int64_t> visible_rows = filter_visible_mesh_vertex_rows( - C, object_eval, static_cast<const MeshComponent *>(component), *resources); + Span<int64_t> visible_rows; + if (component_type == GEO_COMPONENT_TYPE_MESH) { + visible_rows = filter_mesh_elements_by_selection( + C, object_eval, static_cast<const MeshComponent *>(component), domain, *resources); + } + else { + visible_rows = IndexRange(component->attribute_domain_size(domain)).as_span(); + } const int domain_size = component->attribute_domain_size(domain); return std::make_unique<GeometryAttributeSpreadsheetDrawer>( diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index b18add0a826..300956c28fd 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1858,7 +1858,12 @@ typedef struct SpaceSpreadsheet { /* eSpaceSpreadsheet_FilterFlag. */ uint8_t filter_flag; - char _pad1[7]; + /* #GeometryComponentType. */ + uint8_t geometry_component_type; + /* #AttributeDomain. */ + uint8_t attribute_domain; + + char _pad1[5]; } SpaceSpreadsheet; /** \} */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 574c4e98819..9e8e9030925 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -25,6 +25,8 @@ #include "BLT_translation.h" +#include "BKE_attribute.h" +#include "BKE_geometry_set.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_movieclip.h" @@ -2991,6 +2993,48 @@ static void rna_SpaceSpreadsheet_pinned_id_set(PointerRNA *ptr, sspreadsheet->pinned_id = value.data; } +static void rna_SpaceSpreadsheet_geometry_component_type_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)ptr->data; + if (sspreadsheet->geometry_component_type == GEO_COMPONENT_TYPE_POINT_CLOUD) { + sspreadsheet->attribute_domain = ATTR_DOMAIN_POINT; + } +} + +const EnumPropertyItem *rna_SpaceSpreadsheet_attribute_domain_itemf(bContext *UNUSED(C), + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)ptr->data; + EnumPropertyItem *item_array = NULL; + int items_len = 0; + for (const EnumPropertyItem *item = rna_enum_attribute_domain_items; item->identifier != NULL; + item++) { + if (sspreadsheet->geometry_component_type == GEO_COMPONENT_TYPE_MESH) { + if (!ELEM(item->value, + ATTR_DOMAIN_CORNER, + ATTR_DOMAIN_EDGE, + ATTR_DOMAIN_POINT, + ATTR_DOMAIN_POLYGON)) { + continue; + } + } + if (sspreadsheet->geometry_component_type == GEO_COMPONENT_TYPE_POINT_CLOUD) { + if (item->value != ATTR_DOMAIN_POINT) { + continue; + } + } + RNA_enum_item_add(&item_array, &items_len, item); + } + RNA_enum_item_end(&item_array, &items_len); + + *r_free = true; + return item_array; +} + #else static const EnumPropertyItem dt_uv_items[] = { @@ -7196,6 +7240,20 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna) PropertyRNA *prop; StructRNA *srna; + static const EnumPropertyItem geometry_component_type_items[] = { + {GEO_COMPONENT_TYPE_MESH, + "MESH", + ICON_MESH_DATA, + "Mesh", + "Mesh component containing point, corner, edge and polygon data"}, + {GEO_COMPONENT_TYPE_POINT_CLOUD, + "POINTCLOUD", + ICON_POINTCLOUD_DATA, + "Point Cloud", + "Point cloud component containing only point data"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "SpaceSpreadsheet", "Space"); RNA_def_struct_ui_text(srna, "Space Spreadsheet", "Spreadsheet space data"); @@ -7210,6 +7268,20 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Show Only Selected", "Only include rows that correspond to selected elements"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL); + + prop = RNA_def_property(srna, "geometry_component_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, geometry_component_type_items); + RNA_def_property_ui_text( + prop, "Geometry Component", "Part of the geometry to display data from"); + RNA_def_property_update(prop, + NC_SPACE | ND_SPACE_SPREADSHEET, + "rna_SpaceSpreadsheet_geometry_component_type_update"); + + prop = RNA_def_property(srna, "attribute_domain", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_attribute_domain_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceSpreadsheet_attribute_domain_itemf"); + RNA_def_property_ui_text(prop, "Attribute Domain", "Attribute domain to display"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL); } void RNA_def_space(BlenderRNA *brna) |