diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/geometry_fields.cc | 171 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.cc | 100 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/screen.c | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/viewer_path.cc | 270 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/workspace.cc | 10 |
6 files changed, 543 insertions, 23 deletions
diff --git a/source/blender/blenkernel/intern/geometry_fields.cc b/source/blender/blenkernel/intern/geometry_fields.cc index 56e9e9dcdff..e242154cb5b 100644 --- a/source/blender/blenkernel/intern/geometry_fields.cc +++ b/source/blender/blenkernel/intern/geometry_fields.cc @@ -157,6 +157,12 @@ GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &conte return {}; } +std::optional<eAttrDomain> GeometryFieldInput::preferred_domain( + const GeometryComponent & /*component*/) const +{ + return std::nullopt; +} + GVArray MeshFieldInput::get_varray_for_context(const fn::FieldContext &context, const IndexMask mask, ResourceScope & /*scope*/) const @@ -173,6 +179,11 @@ GVArray MeshFieldInput::get_varray_for_context(const fn::FieldContext &context, return {}; } +std::optional<eAttrDomain> MeshFieldInput::preferred_domain(const Mesh & /*mesh*/) const +{ + return std::nullopt; +} + GVArray CurvesFieldInput::get_varray_for_context(const fn::FieldContext &context, IndexMask mask, ResourceScope & /*scope*/) const @@ -190,6 +201,12 @@ GVArray CurvesFieldInput::get_varray_for_context(const fn::FieldContext &context return {}; } +std::optional<eAttrDomain> CurvesFieldInput::preferred_domain( + const CurvesGeometry & /*curves*/) const +{ + return std::nullopt; +} + GVArray PointCloudFieldInput::get_varray_for_context(const fn::FieldContext &context, IndexMask mask, ResourceScope & /*scope*/) const @@ -254,6 +271,20 @@ bool AttributeFieldInput::is_equal_to(const fn::FieldNode &other) const return false; } +std::optional<eAttrDomain> AttributeFieldInput::preferred_domain( + const GeometryComponent &component) const +{ + const std::optional<AttributeAccessor> attributes = component.attributes(); + if (!attributes.has_value()) { + return std::nullopt; + } + const std::optional<AttributeMetaData> meta_data = attributes->lookup_meta_data(name_); + if (!meta_data.has_value()) { + return std::nullopt; + } + return meta_data->domain; +} + static StringRef get_random_id_attribute_name(const eAttrDomain domain) { switch (domain) { @@ -325,6 +356,21 @@ bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const return false; } +std::optional<eAttrDomain> AnonymousAttributeFieldInput::preferred_domain( + const GeometryComponent &component) const +{ + const std::optional<AttributeAccessor> attributes = component.attributes(); + if (!attributes.has_value()) { + return std::nullopt; + } + const std::optional<AttributeMetaData> meta_data = attributes->lookup_meta_data( + anonymous_id_.get()); + if (!meta_data.has_value()) { + return std::nullopt; + } + return meta_data->domain; +} + } // namespace blender::bke /* -------------------------------------------------------------------- */ @@ -360,6 +406,131 @@ bool NormalFieldInput::is_equal_to(const fn::FieldNode &other) const return dynamic_cast<const NormalFieldInput *>(&other) != nullptr; } +bool try_capture_field_on_geometry(GeometryComponent &component, + const AttributeIDRef &attribute_id, + const eAttrDomain domain, + const fn::GField &field) +{ + MutableAttributeAccessor attributes = *component.attributes_for_write(); + const int domain_size = attributes.domain_size(domain); + const CPPType &type = field.cpp_type(); + const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(type); + + if (domain_size == 0) { + return attributes.add(attribute_id, domain, data_type, AttributeInitConstruct{}); + } + + bke::GeometryFieldContext field_context{component, domain}; + const IndexMask mask{IndexMask(domain_size)}; + const bke::AttributeValidator validator = attributes.lookup_validator(attribute_id); + + /* Could avoid allocating a new buffer if: + * - We are writing to an attribute that exists already with the correct domain and type. + * - The field does not depend on that attribute (we can't easily check for that yet). */ + void *buffer = MEM_mallocN(type.size() * domain_size, __func__); + + fn::FieldEvaluator evaluator{field_context, &mask}; + evaluator.add_with_destination(validator.validate_field_if_necessary(field), + GMutableSpan{type, buffer, domain_size}); + evaluator.evaluate(); + + if (GAttributeWriter attribute = attributes.lookup_for_write(attribute_id)) { + if (attribute.domain == domain && attribute.varray.type() == type) { + attribute.varray.set_all(buffer); + attribute.finish(); + type.destruct_n(buffer, domain_size); + MEM_freeN(buffer); + return true; + } + } + attributes.remove(attribute_id); + if (attributes.add(attribute_id, domain, data_type, bke::AttributeInitMoveArray{buffer})) { + return true; + } + + /* If the name corresponds to a builtin attribute, removing the attribute might fail if + * it's required, and adding the attribute might fail if the domain or type is incorrect. */ + type.destruct_n(buffer, domain_size); + MEM_freeN(buffer); + return false; +} + +std::optional<eAttrDomain> try_detect_field_domain(const GeometryComponent &component, + const fn::GField &field) +{ + const GeometryComponentType component_type = component.type(); + if (component_type == GEO_COMPONENT_TYPE_POINT_CLOUD) { + return ATTR_DOMAIN_POINT; + } + if (component_type == GEO_COMPONENT_TYPE_INSTANCES) { + return ATTR_DOMAIN_INSTANCE; + } + const std::shared_ptr<const fn::FieldInputs> &field_inputs = field.node().field_inputs(); + if (!field_inputs) { + return std::nullopt; + } + std::optional<eAttrDomain> output_domain; + auto handle_domain = [&](const std::optional<eAttrDomain> domain) { + if (!domain.has_value()) { + return false; + } + if (output_domain.has_value()) { + if (*output_domain != *domain) { + return false; + } + return true; + } + output_domain = domain; + return true; + }; + if (component_type == GEO_COMPONENT_TYPE_MESH) { + const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); + const Mesh *mesh = mesh_component.get_for_read(); + if (mesh == nullptr) { + return std::nullopt; + } + for (const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) { + if (auto geometry_field_input = dynamic_cast<const GeometryFieldInput *>(&field_input)) { + if (!handle_domain(geometry_field_input->preferred_domain(component))) { + return std::nullopt; + } + } + else if (auto mesh_field_input = dynamic_cast<const MeshFieldInput *>(&field_input)) { + if (!handle_domain(mesh_field_input->preferred_domain(*mesh))) { + return std::nullopt; + } + } + else { + return std::nullopt; + } + } + } + if (component_type == GEO_COMPONENT_TYPE_CURVE) { + const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); + const Curves *curves = curve_component.get_for_read(); + if (curves == nullptr) { + return std::nullopt; + } + for (const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) { + if (auto geometry_field_input = dynamic_cast<const GeometryFieldInput *>(&field_input)) { + if (!handle_domain(geometry_field_input->preferred_domain(component))) { + return std::nullopt; + } + } + else if (auto curves_field_input = dynamic_cast<const CurvesFieldInput *>(&field_input)) { + if (!handle_domain( + curves_field_input->preferred_domain(CurvesGeometry::wrap(curves->geometry)))) { + return std::nullopt; + } + } + else { + return std::nullopt; + } + } + } + return output_domain; +} + } // namespace blender::bke /** \} */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 0dcb2aa3139..7d381ed2a69 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -3114,7 +3114,7 @@ void ntreeSetOutput(bNodeTree *ntree) LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) { /* we need a check for which output node should be tagged like this, below an exception */ - if (node->type == CMP_NODE_OUTPUT_FILE) { + if (ELEM(node->type, CMP_NODE_OUTPUT_FILE, GEO_NODE_VIEWER)) { continue; } @@ -3125,8 +3125,8 @@ void ntreeSetOutput(bNodeTree *ntree) if (ntree->type == NTREE_COMPOSIT) { /* same type, exception for viewer */ if (tnode->type == node->type || - (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER) && - ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER))) { + (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && + ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) { if (tnode->flag & NODE_DO_OUTPUT) { output++; if (output > 1) { diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index e28aaabb4e1..15a4a0bbb32 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -24,8 +24,10 @@ #include "DNA_anim_types.h" #include "DNA_collection_types.h" +#include "DNA_curves_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_vfont_types.h" @@ -44,6 +46,7 @@ #include "BKE_mesh.h" #include "BKE_mesh_iterators.h" #include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" @@ -53,13 +56,15 @@ #include "DEG_depsgraph_query.h" #include "BLI_hash.h" -#include "BLI_strict_flags.h" + +#include "NOD_geometry_nodes_log.hh" using blender::Array; using blender::float3; using blender::float4x4; using blender::Span; using blender::Vector; +namespace geo_log = blender::nodes::geo_eval_log; /* -------------------------------------------------------------------- */ /** \name Internal Duplicate Context @@ -75,6 +80,15 @@ struct DupliContext { Scene *scene; Object *object; float space_mat[4][4]; + /** + * Index of the top-level instance that contains this context or -1 when unused. + * This is an index into the instances component of #preview_base_geometry. + */ + int preview_instance_index; + /** + * Top level geometry set that is previewed. + */ + const GeometrySet *preview_base_geometry; /** * A stack that contains all the "parent" objects of a particular instance when recursive @@ -127,6 +141,8 @@ static void init_context(DupliContext *r_ctx, r_ctx->gen = get_dupli_generator(r_ctx); r_ctx->duplilist = nullptr; + r_ctx->preview_instance_index = -1; + r_ctx->preview_base_geometry = nullptr; } /** @@ -139,7 +155,7 @@ static bool copy_dupli_context( /* XXX annoying, previously was done by passing an ID* argument, * this at least is more explicit. */ - if (ctx->gen->type == OB_DUPLICOLLECTION) { + if (ctx->gen && ctx->gen->type == OB_DUPLICOLLECTION) { r_ctx->collection = ctx->object->instance_collection; } @@ -183,7 +199,9 @@ static DupliObject *make_dupli( dob->ob = ob; dob->ob_data = const_cast<ID *>(object_data); mul_m4_m4m4(dob->mat, (float(*)[4])ctx->space_mat, mat); - dob->type = ctx->gen->type; + dob->type = ctx->gen == nullptr ? 0 : ctx->gen->type; + dob->preview_base_geometry = ctx->preview_base_geometry; + dob->preview_instance_index = ctx->preview_instance_index; /* Set persistent id, which is an array with a persistent index for each level * (particle number, vertex number, ..). by comparing this we can find the same @@ -780,7 +798,8 @@ static const DupliGenerator gen_dupli_verts_font = { static void make_duplis_geometry_set_impl(const DupliContext *ctx, const GeometrySet &geometry_set, const float parent_transform[4][4], - bool geometry_set_is_instance) + bool geometry_set_is_instance, + bool use_new_curves_type) { int component_index = 0; if (ctx->object->type != OB_MESH || geometry_set_is_instance) { @@ -795,8 +814,15 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, } if (!ELEM(ctx->object->type, OB_CURVES_LEGACY, OB_FONT, OB_CURVES) || geometry_set_is_instance) { if (const CurveComponent *component = geometry_set.get_component_for_read<CurveComponent>()) { - if (const Curve *curve = component->get_curve_for_render()) { - make_dupli(ctx, ctx->object, &curve->id, parent_transform, component_index++); + if (use_new_curves_type) { + if (const Curves *curves = component->get_for_read()) { + make_dupli(ctx, ctx->object, &curves->id, parent_transform, component_index++); + } + } + else { + if (const Curve *curve = component->get_curve_for_render()) { + make_dupli(ctx, ctx->object, &curve->id, parent_transform, component_index++); + } } } } @@ -832,17 +858,26 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, const InstanceReference &reference = references[instance_reference_handles[i]]; const int id = almost_unique_ids[i]; + const DupliContext *ctx_for_instance = instances_ctx; + /* Set the #preview_instance_index when necessary. */ + DupliContext tmp_ctx_for_instance; + if (instances_ctx->preview_base_geometry == &geometry_set) { + tmp_ctx_for_instance = *instances_ctx; + tmp_ctx_for_instance.preview_instance_index = i; + ctx_for_instance = &tmp_ctx_for_instance; + } + switch (reference.type()) { case InstanceReference::Type::Object: { Object &object = reference.object(); float matrix[4][4]; mul_m4_m4m4(matrix, parent_transform, instance_offset_matrices[i].values); - make_dupli(instances_ctx, &object, matrix, id); + make_dupli(ctx_for_instance, &object, matrix, id); float space_matrix[4][4]; mul_m4_m4m4(space_matrix, instance_offset_matrices[i].values, object.imat); mul_m4_m4_pre(space_matrix, parent_transform); - make_recursive_duplis(instances_ctx, &object, space_matrix, id); + make_recursive_duplis(ctx_for_instance, &object, space_matrix, id); break; } case InstanceReference::Type::Collection: { @@ -854,14 +889,15 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, mul_m4_m4_pre(collection_matrix, parent_transform); DupliContext sub_ctx; - if (!copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id)) { + if (!copy_dupli_context( + &sub_ctx, ctx_for_instance, ctx_for_instance->object, nullptr, id)) { break; } - eEvaluationMode mode = DEG_get_mode(instances_ctx->depsgraph); + eEvaluationMode mode = DEG_get_mode(ctx_for_instance->depsgraph); int object_id = 0; FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (&collection, object, mode) { - if (object == instances_ctx->object) { + if (object == ctx_for_instance->object) { continue; } @@ -879,8 +915,10 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, mul_m4_m4m4(new_transform, parent_transform, instance_offset_matrices[i].values); DupliContext sub_ctx; - if (copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id)) { - make_duplis_geometry_set_impl(&sub_ctx, reference.geometry_set(), new_transform, true); + if (copy_dupli_context( + &sub_ctx, ctx_for_instance, ctx_for_instance->object, nullptr, id)) { + make_duplis_geometry_set_impl( + &sub_ctx, reference.geometry_set(), new_transform, true, false); } break; } @@ -894,7 +932,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx, static void make_duplis_geometry_set(const DupliContext *ctx) { const GeometrySet *geometry_set = ctx->object->runtime.geometry_set_eval; - make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->obmat, false); + make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->obmat, false, false); } static const DupliGenerator gen_dupli_geometry_set = { @@ -1632,6 +1670,40 @@ ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob) return duplilist; } +ListBase *object_duplilist_preview(Depsgraph *depsgraph, + Scene *sce, + Object *ob_eval, + const ViewerPath *viewer_path) +{ + ListBase *duplilist = MEM_cnew<ListBase>("duplilist"); + DupliContext ctx; + Vector<Object *> instance_stack; + instance_stack.append(ob_eval); + init_context(&ctx, depsgraph, sce, ob_eval, nullptr, instance_stack); + ctx.duplilist = duplilist; + + Object *ob_orig = DEG_get_original_object(ob_eval); + + LISTBASE_FOREACH (ModifierData *, md_orig, &ob_orig->modifiers) { + if (md_orig->type != eModifierType_Nodes) { + continue; + } + NodesModifierData *nmd_orig = reinterpret_cast<NodesModifierData *>(md_orig); + if (nmd_orig->runtime_eval_log == nullptr) { + continue; + } + geo_log::GeoModifierLog *log = static_cast<geo_log::GeoModifierLog *>( + nmd_orig->runtime_eval_log); + if (const geo_log::ViewerNodeLog *viewer_log = log->find_viewer_node_log_for_path( + *viewer_path)) { + ctx.preview_base_geometry = &viewer_log->geometry; + make_duplis_geometry_set_impl( + &ctx, viewer_log->geometry, ob_eval->obmat, true, ob_eval->type == OB_CURVES); + } + } + return duplilist; +} + void free_object_duplilist(ListBase *lb) { BLI_freelistN(lb); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 8517995a0d8..3e5dbc47c40 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -46,6 +46,7 @@ #include "BKE_lib_query.h" #include "BKE_node.h" #include "BKE_screen.h" +#include "BKE_viewer_path.h" #include "BKE_workspace.h" #include "BLO_read_write.h" @@ -97,6 +98,7 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area if (v3d->localvd) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, v3d->localvd->camera, IDWALK_CB_NOP); } + BKE_viewer_path_foreach_id(data, &v3d->viewer_path); break; } case SPACE_GRAPH: { @@ -197,12 +199,7 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area } case SPACE_SPREADSHEET: { SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl; - LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) { - if (context->type == SPREADSHEET_CONTEXT_OBJECT) { - BKE_LIB_FOREACHID_PROCESS_IDSUPER( - data, ((SpreadsheetContextObject *)context)->object, IDWALK_CB_NOP); - } - } + BKE_viewer_path_foreach_id(data, &sspreadsheet->viewer_path); break; } default: diff --git a/source/blender/blenkernel/intern/viewer_path.cc b/source/blender/blenkernel/intern/viewer_path.cc new file mode 100644 index 00000000000..3074a007af4 --- /dev/null +++ b/source/blender/blenkernel/intern/viewer_path.cc @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_lib_query.h" +#include "BKE_lib_remap.h" +#include "BKE_viewer_path.h" + +#include "BLI_index_range.hh" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_ref.hh" + +#include "MEM_guardedalloc.h" + +#include "BLO_read_write.h" + +using blender::IndexRange; +using blender::StringRef; + +void BKE_viewer_path_init(ViewerPath *viewer_path) +{ + BLI_listbase_clear(&viewer_path->path); +} + +void BKE_viewer_path_clear(ViewerPath *viewer_path) +{ + LISTBASE_FOREACH_MUTABLE (ViewerPathElem *, elem, &viewer_path->path) { + BKE_viewer_path_elem_free(elem); + } + BLI_listbase_clear(&viewer_path->path); +} + +void BKE_viewer_path_copy(ViewerPath *dst, const ViewerPath *src) +{ + BKE_viewer_path_init(dst); + LISTBASE_FOREACH (const ViewerPathElem *, src_elem, &src->path) { + ViewerPathElem *new_elem = BKE_viewer_path_elem_copy(src_elem); + BLI_addtail(&dst->path, new_elem); + } +} + +bool BKE_viewer_path_equal(const ViewerPath *a, const ViewerPath *b) +{ + const ViewerPathElem *elem_a = static_cast<const ViewerPathElem *>(a->path.first); + const ViewerPathElem *elem_b = static_cast<const ViewerPathElem *>(b->path.first); + + while (elem_a != nullptr && elem_b != nullptr) { + if (!BKE_viewer_path_elem_equal(elem_a, elem_b)) { + return false; + } + elem_a = elem_a->next; + elem_b = elem_b->next; + } + if (elem_a == nullptr && elem_b == nullptr) { + return true; + } + return false; +} + +void BKE_viewer_path_blend_write(struct BlendWriter *writer, const ViewerPath *viewer_path) +{ + LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) { + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + auto typed_elem = reinterpret_cast<IDViewerPathElem *>(elem); + BLO_write_struct(writer, IDViewerPathElem, typed_elem); + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: { + auto typed_elem = reinterpret_cast<ModifierViewerPathElem *>(elem); + BLO_write_struct(writer, ModifierViewerPathElem, typed_elem); + BLO_write_string(writer, typed_elem->modifier_name); + break; + } + case VIEWER_PATH_ELEM_TYPE_NODE: { + auto typed_elem = reinterpret_cast<NodeViewerPathElem *>(elem); + BLO_write_struct(writer, NodeViewerPathElem, typed_elem); + BLO_write_string(writer, typed_elem->node_name); + break; + } + } + } +} + +void BKE_viewer_path_blend_read_data(struct BlendDataReader *reader, ViewerPath *viewer_path) +{ + BLO_read_list(reader, &viewer_path->path); + LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) { + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: { + auto typed_elem = reinterpret_cast<ModifierViewerPathElem *>(elem); + BLO_read_data_address(reader, &typed_elem->modifier_name); + break; + } + case VIEWER_PATH_ELEM_TYPE_NODE: { + auto typed_elem = reinterpret_cast<NodeViewerPathElem *>(elem); + BLO_read_data_address(reader, &typed_elem->node_name); + break; + } + } + } +} + +void BKE_viewer_path_blend_read_lib(BlendLibReader *reader, Library *lib, ViewerPath *viewer_path) +{ + LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) { + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + auto typed_elem = reinterpret_cast<IDViewerPathElem *>(elem); + BLO_read_id_address(reader, lib, &typed_elem->id); + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: + case VIEWER_PATH_ELEM_TYPE_NODE: { + break; + } + } + } +} + +void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_path) +{ + LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) { + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + auto typed_elem = reinterpret_cast<IDViewerPathElem *>(elem); + BKE_LIB_FOREACHID_PROCESS_ID(data, typed_elem->id, IDWALK_CB_NOP); + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: + case VIEWER_PATH_ELEM_TYPE_NODE: { + break; + } + } + } +} + +void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mappings) +{ + LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) { + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + auto typed_elem = reinterpret_cast<IDViewerPathElem *>(elem); + BKE_id_remapper_apply(mappings, &typed_elem->id, ID_REMAP_APPLY_DEFAULT); + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: + case VIEWER_PATH_ELEM_TYPE_NODE: { + break; + } + } + } +} + +ViewerPathElem *BKE_viewer_path_elem_new(const ViewerPathElemType type) +{ + switch (type) { + case VIEWER_PATH_ELEM_TYPE_ID: { + IDViewerPathElem *elem = MEM_cnew<IDViewerPathElem>(__func__); + elem->base.type = type; + return &elem->base; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: { + ModifierViewerPathElem *elem = MEM_cnew<ModifierViewerPathElem>(__func__); + elem->base.type = type; + return &elem->base; + } + case VIEWER_PATH_ELEM_TYPE_NODE: { + NodeViewerPathElem *elem = MEM_cnew<NodeViewerPathElem>(__func__); + elem->base.type = type; + return &elem->base; + } + } + BLI_assert_unreachable(); + return nullptr; +} + +IDViewerPathElem *BKE_viewer_path_elem_new_id() +{ + return reinterpret_cast<IDViewerPathElem *>(BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_ID)); +} + +ModifierViewerPathElem *BKE_viewer_path_elem_new_modifier() +{ + return reinterpret_cast<ModifierViewerPathElem *>( + BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_MODIFIER)); +} + +NodeViewerPathElem *BKE_viewer_path_elem_new_node() +{ + return reinterpret_cast<NodeViewerPathElem *>( + BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_NODE)); +} + +ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src) +{ + ViewerPathElem *dst = BKE_viewer_path_elem_new(ViewerPathElemType(src->type)); + switch (ViewerPathElemType(src->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + auto old_elem = reinterpret_cast<const IDViewerPathElem *>(src); + auto new_elem = reinterpret_cast<IDViewerPathElem *>(dst); + new_elem->id = old_elem->id; + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: { + auto old_elem = reinterpret_cast<const ModifierViewerPathElem *>(src); + auto new_elem = reinterpret_cast<ModifierViewerPathElem *>(dst); + if (old_elem->modifier_name != nullptr) { + new_elem->modifier_name = BLI_strdup(old_elem->modifier_name); + } + break; + } + case VIEWER_PATH_ELEM_TYPE_NODE: { + auto old_elem = reinterpret_cast<const NodeViewerPathElem *>(src); + auto new_elem = reinterpret_cast<NodeViewerPathElem *>(dst); + if (old_elem->node_name != nullptr) { + new_elem->node_name = BLI_strdup(old_elem->node_name); + } + break; + } + } + return dst; +} + +bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b) +{ + if (a->type != b->type) { + return false; + } + switch (ViewerPathElemType(a->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + auto a_elem = reinterpret_cast<const IDViewerPathElem *>(a); + auto b_elem = reinterpret_cast<const IDViewerPathElem *>(b); + return a_elem->id == b_elem->id; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: { + auto a_elem = reinterpret_cast<const ModifierViewerPathElem *>(a); + auto b_elem = reinterpret_cast<const ModifierViewerPathElem *>(b); + return StringRef(a_elem->modifier_name) == StringRef(b_elem->modifier_name); + } + case VIEWER_PATH_ELEM_TYPE_NODE: { + auto a_elem = reinterpret_cast<const NodeViewerPathElem *>(a); + auto b_elem = reinterpret_cast<const NodeViewerPathElem *>(b); + return StringRef(a_elem->node_name) == StringRef(b_elem->node_name); + } + } + return false; +} + +void BKE_viewer_path_elem_free(ViewerPathElem *elem) +{ + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_ID: { + break; + } + case VIEWER_PATH_ELEM_TYPE_MODIFIER: { + auto typed_elem = reinterpret_cast<ModifierViewerPathElem *>(elem); + MEM_SAFE_FREE(typed_elem->modifier_name); + break; + } + case VIEWER_PATH_ELEM_TYPE_NODE: { + auto typed_elem = reinterpret_cast<NodeViewerPathElem *>(elem); + MEM_SAFE_FREE(typed_elem->node_name); + break; + } + } + MEM_freeN(elem); +} diff --git a/source/blender/blenkernel/intern/workspace.cc b/source/blender/blenkernel/intern/workspace.cc index 8008dacc853..a7fd433b42b 100644 --- a/source/blender/blenkernel/intern/workspace.cc +++ b/source/blender/blenkernel/intern/workspace.cc @@ -24,6 +24,7 @@ #include "BKE_main.h" #include "BKE_object.h" #include "BKE_scene.h" +#include "BKE_viewer_path.h" #include "BKE_workspace.h" #include "DNA_object_types.h" @@ -61,6 +62,7 @@ static void workspace_free_data(ID *id) } MEM_SAFE_FREE(workspace->status_text); + BKE_viewer_path_clear(&workspace->viewer_path); } static void workspace_foreach_id(ID *id, LibraryForeachIDData *data) @@ -72,6 +74,8 @@ static void workspace_foreach_id(ID *id, LibraryForeachIDData *data) LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, layout->screen, IDWALK_CB_USER); } + + BKE_viewer_path_foreach_id(data, &workspace->viewer_path); } static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address) @@ -89,6 +93,8 @@ static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_ad IDP_BlendWrite(writer, tref->properties); } } + + BKE_viewer_path_blend_write(writer, &workspace->viewer_path); } static void workspace_blend_read_data(BlendDataReader *reader, ID *id) @@ -115,6 +121,8 @@ static void workspace_blend_read_data(BlendDataReader *reader, ID *id) workspace->status_text = nullptr; id_us_ensure_real(&workspace->id); + + BKE_viewer_path_blend_read_data(reader, &workspace->viewer_path); } static void workspace_blend_read_lib(BlendLibReader *reader, ID *id) @@ -164,6 +172,8 @@ static void workspace_blend_read_lib(BlendLibReader *reader, ID *id) BKE_workspace_layout_remove(bmain, workspace, layout); } } + + BKE_viewer_path_blend_read_lib(reader, id->lib, &workspace->viewer_path); } static void workspace_blend_read_expand(BlendExpander *expander, ID *id) |