Changeset View
Changeset View
Standalone View
Standalone View
source/blender/modifiers/intern/MOD_nodes.cc
| Show All 27 Lines | |||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "DNA_modifier_types.h" | #include "DNA_modifier_types.h" | ||||
| #include "DNA_node_types.h" | #include "DNA_node_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_pointcloud_types.h" | #include "DNA_pointcloud_types.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_screen_types.h" | #include "DNA_screen_types.h" | ||||
| #include "DNA_space_types.h" | #include "DNA_space_types.h" | ||||
| #include "DNA_view3d_types.h" | |||||
| #include "DNA_windowmanager_types.h" | #include "DNA_windowmanager_types.h" | ||||
| #include "BKE_attribute_math.hh" | #include "BKE_attribute_math.hh" | ||||
| #include "BKE_compute_contexts.hh" | #include "BKE_compute_contexts.hh" | ||||
| #include "BKE_customdata.h" | #include "BKE_customdata.h" | ||||
| #include "BKE_geometry_fields.hh" | #include "BKE_geometry_fields.hh" | ||||
| #include "BKE_geometry_set_instances.hh" | #include "BKE_geometry_set_instances.hh" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| Show All 31 Lines | |||||
| #include "MOD_modifiertypes.h" | #include "MOD_modifiertypes.h" | ||||
| #include "MOD_nodes.h" | #include "MOD_nodes.h" | ||||
| #include "MOD_ui_common.h" | #include "MOD_ui_common.h" | ||||
| #include "ED_object.h" | #include "ED_object.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_spreadsheet.h" | #include "ED_spreadsheet.h" | ||||
| #include "ED_undo.h" | #include "ED_undo.h" | ||||
| #include "ED_viewer_path.hh" | |||||
| #include "NOD_geometry.h" | #include "NOD_geometry.h" | ||||
| #include "NOD_geometry_nodes_lazy_function.hh" | #include "NOD_geometry_nodes_lazy_function.hh" | ||||
| #include "NOD_node_declaration.hh" | #include "NOD_node_declaration.hh" | ||||
| #include "FN_field.hh" | #include "FN_field.hh" | ||||
| #include "FN_field_cpp_type.hh" | #include "FN_field_cpp_type.hh" | ||||
| #include "FN_lazy_function_execute.hh" | #include "FN_lazy_function_execute.hh" | ||||
| ▲ Show 20 Lines • Show All 732 Lines • ▼ Show 20 Lines | if (use_attribute) { | ||||
| BLI_assert(cpp_type != nullptr); | BLI_assert(cpp_type != nullptr); | ||||
| cpp_type->construct_from_field(r_value, std::move(attribute_field)); | cpp_type->construct_from_field(r_value, std::move(attribute_field)); | ||||
| } | } | ||||
| else { | else { | ||||
| init_socket_cpp_value_from_property(*property, socket_data_type, r_value); | init_socket_cpp_value_from_property(*property, socket_data_type, r_value); | ||||
| } | } | ||||
| } | } | ||||
| static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) | |||||
| { | |||||
| wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; | |||||
| if (wm == nullptr) { | |||||
| return {}; | |||||
| } | |||||
| Vector<SpaceSpreadsheet *> spreadsheets; | |||||
| LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { | |||||
| bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); | |||||
| LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { | |||||
| SpaceLink *sl = (SpaceLink *)area->spacedata.first; | |||||
| if (sl->spacetype == SPACE_SPREADSHEET) { | |||||
| spreadsheets.append((SpaceSpreadsheet *)sl); | |||||
| } | |||||
| } | |||||
| } | |||||
| return spreadsheets; | |||||
| } | |||||
| static const lf::FunctionNode &find_viewer_lf_node(const bNode &viewer_bnode) | static const lf::FunctionNode &find_viewer_lf_node(const bNode &viewer_bnode) | ||||
| { | { | ||||
| return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree()) | return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree()) | ||||
| ->mapping.viewer_node_map.lookup(&viewer_bnode); | ->mapping.viewer_node_map.lookup(&viewer_bnode); | ||||
| } | } | ||||
| static const lf::FunctionNode &find_group_lf_node(const bNode &group_bnode) | static const lf::FunctionNode &find_group_lf_node(const bNode &group_bnode) | ||||
| { | { | ||||
| return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree()) | return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree()) | ||||
| ->mapping.group_node_map.lookup(&group_bnode); | ->mapping.group_node_map.lookup(&group_bnode); | ||||
| } | } | ||||
| static void find_side_effect_nodes_for_spreadsheet( | static void find_side_effect_nodes_for_viewer_path( | ||||
| const SpaceSpreadsheet &sspreadsheet, | const ViewerPath &viewer_path, | ||||
| const NodesModifierData &nmd, | const NodesModifierData &nmd, | ||||
| const ModifierEvalContext &ctx, | const ModifierEvalContext &ctx, | ||||
| const bNodeTree &root_tree, | |||||
| MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> &r_side_effect_nodes) | MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> &r_side_effect_nodes) | ||||
| { | { | ||||
| Vector<SpreadsheetContext *> context_path = sspreadsheet.context_path; | const std::optional<blender::ed::viewer_path::ViewerPathForGeometryNodesViewer> parsed_path = | ||||
| if (context_path.size() < 3) { | blender::ed::viewer_path::parse_geometry_nodes_viewer(viewer_path); | ||||
| return; | if (!parsed_path.has_value()) { | ||||
| } | |||||
| if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) { | |||||
| return; | |||||
| } | |||||
| if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) { | |||||
| return; | |||||
| } | |||||
| SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0]; | |||||
| if (object_context->object != DEG_get_original_object(ctx.object)) { | |||||
| return; | return; | ||||
| } | } | ||||
| SpreadsheetContextModifier *modifier_context = (SpreadsheetContextModifier *)context_path[1]; | if (parsed_path->object != DEG_get_original_object(ctx.object)) { | ||||
| if (StringRef(modifier_context->modifier_name) != nmd.modifier.name) { | |||||
| return; | return; | ||||
| } | } | ||||
| for (SpreadsheetContext *context : context_path.as_span().drop_front(2)) { | if (parsed_path->modifier_name != nmd.modifier.name) { | ||||
| if (context->type != SPREADSHEET_CONTEXT_NODE) { | |||||
| return; | return; | ||||
| } | } | ||||
| } | |||||
| blender::ComputeContextBuilder compute_context_builder; | blender::ComputeContextBuilder compute_context_builder; | ||||
| compute_context_builder.push<blender::bke::ModifierComputeContext>(nmd.modifier.name); | compute_context_builder.push<blender::bke::ModifierComputeContext>(parsed_path->modifier_name); | ||||
| const Span<SpreadsheetContextNode *> nested_group_contexts = | |||||
| context_path.as_span().drop_front(2).drop_back(1).cast<SpreadsheetContextNode *>(); | |||||
| const SpreadsheetContextNode *last_context = (SpreadsheetContextNode *)context_path.last(); | |||||
| const bNodeTree *group = nmd.node_group; | |||||
| Stack<const bNode *> group_node_stack; | Stack<const bNode *> group_node_stack; | ||||
| const bNodeTree *group = &root_tree; | for (const StringRefNull group_node_name : parsed_path->group_node_names) { | ||||
| for (SpreadsheetContextNode *node_context : nested_group_contexts) { | |||||
| const bNode *found_node = nullptr; | const bNode *found_node = nullptr; | ||||
| for (const bNode *node : group->group_nodes()) { | for (const bNode *node : group->group_nodes()) { | ||||
| if (STREQ(node->name, node_context->node_name)) { | if (node->name == group_node_name) { | ||||
| found_node = node; | found_node = node; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (found_node == nullptr) { | if (found_node == nullptr) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (found_node->id == nullptr) { | if (found_node->id == nullptr) { | ||||
| return; | return; | ||||
| } | } | ||||
| group_node_stack.push(found_node); | group_node_stack.push(found_node); | ||||
| group = reinterpret_cast<const bNodeTree *>(found_node->id); | group = reinterpret_cast<bNodeTree *>(found_node->id); | ||||
| compute_context_builder.push<blender::bke::NodeGroupComputeContext>(node_context->node_name); | compute_context_builder.push<blender::bke::NodeGroupComputeContext>(group_node_name); | ||||
| } | } | ||||
| const bNode *found_viewer_node = nullptr; | const bNode *found_viewer_node = nullptr; | ||||
| for (const bNode *viewer_node : group->nodes_by_type("GeometryNodeViewer")) { | for (const bNode *viewer_node : group->nodes_by_type("GeometryNodeViewer")) { | ||||
| if (STREQ(viewer_node->name, last_context->node_name)) { | if (viewer_node->name == parsed_path->viewer_node_name) { | ||||
| found_viewer_node = viewer_node; | found_viewer_node = viewer_node; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (found_viewer_node == nullptr) { | if (found_viewer_node == nullptr) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* Not only mark the viewer node as having side effects, but also all group nodes it is contained | /* Not only mark the viewer node as having side effects, but also all group nodes it is contained | ||||
| * in. */ | * in. */ | ||||
| r_side_effect_nodes.add(compute_context_builder.hash(), | r_side_effect_nodes.add(compute_context_builder.hash(), | ||||
| &find_viewer_lf_node(*found_viewer_node)); | &find_viewer_lf_node(*found_viewer_node)); | ||||
| compute_context_builder.pop(); | compute_context_builder.pop(); | ||||
| while (!compute_context_builder.is_empty()) { | while (!compute_context_builder.is_empty()) { | ||||
| r_side_effect_nodes.add(compute_context_builder.hash(), | r_side_effect_nodes.add(compute_context_builder.hash(), | ||||
| &find_group_lf_node(*group_node_stack.pop())); | &find_group_lf_node(*group_node_stack.pop())); | ||||
| compute_context_builder.pop(); | compute_context_builder.pop(); | ||||
| } | } | ||||
| } | } | ||||
| static void find_side_effect_nodes( | static void find_side_effect_nodes( | ||||
| const NodesModifierData &nmd, | const NodesModifierData &nmd, | ||||
| const ModifierEvalContext &ctx, | const ModifierEvalContext &ctx, | ||||
| const bNodeTree &tree, | |||||
| MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> &r_side_effect_nodes) | MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> &r_side_effect_nodes) | ||||
| { | { | ||||
| Main *bmain = DEG_get_bmain(ctx.depsgraph); | Main *bmain = DEG_get_bmain(ctx.depsgraph); | ||||
| wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; | |||||
| /* Based on every visible spreadsheet context path, get a list of sockets that need to have their | if (wm == nullptr) { | ||||
| * intermediate geometries cached for display. */ | return; | ||||
| Vector<SpaceSpreadsheet *> spreadsheets = find_spreadsheet_editors(bmain); | } | ||||
| for (SpaceSpreadsheet *sspreadsheet : spreadsheets) { | LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) { | ||||
| find_side_effect_nodes_for_spreadsheet(*sspreadsheet, nmd, ctx, tree, r_side_effect_nodes); | const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); | ||||
| const WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook); | |||||
| find_side_effect_nodes_for_viewer_path(workspace->viewer_path, nmd, ctx, r_side_effect_nodes); | |||||
| LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) { | |||||
| const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first); | |||||
| if (sl->spacetype == SPACE_SPREADSHEET) { | |||||
| const SpaceSpreadsheet &sspreadsheet = *reinterpret_cast<const SpaceSpreadsheet *>(sl); | |||||
| find_side_effect_nodes_for_viewer_path( | |||||
| sspreadsheet.viewer_path, nmd, ctx, r_side_effect_nodes); | |||||
| } | |||||
| if (sl->spacetype == SPACE_VIEW3D) { | |||||
| const View3D &v3d = *reinterpret_cast<const View3D *>(sl); | |||||
| find_side_effect_nodes_for_viewer_path(v3d.viewer_path, nmd, ctx, r_side_effect_nodes); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| static void clear_runtime_data(NodesModifierData *nmd) | static void clear_runtime_data(NodesModifierData *nmd) | ||||
| { | { | ||||
| if (nmd->runtime_eval_log != nullptr) { | if (nmd->runtime_eval_log != nullptr) { | ||||
| delete static_cast<GeoModifierLog *>(nmd->runtime_eval_log); | delete static_cast<GeoModifierLog *>(nmd->runtime_eval_log); | ||||
| nmd->runtime_eval_log = nullptr; | nmd->runtime_eval_log = nullptr; | ||||
| ▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | static GeometrySet compute_geometry( | ||||
| blender::nodes::GeoNodesModifierData geo_nodes_modifier_data; | blender::nodes::GeoNodesModifierData geo_nodes_modifier_data; | ||||
| geo_nodes_modifier_data.depsgraph = ctx->depsgraph; | geo_nodes_modifier_data.depsgraph = ctx->depsgraph; | ||||
| geo_nodes_modifier_data.self_object = ctx->object; | geo_nodes_modifier_data.self_object = ctx->object; | ||||
| auto eval_log = std::make_unique<GeoModifierLog>(); | auto eval_log = std::make_unique<GeoModifierLog>(); | ||||
| if (logging_enabled(ctx)) { | if (logging_enabled(ctx)) { | ||||
| geo_nodes_modifier_data.eval_log = eval_log.get(); | geo_nodes_modifier_data.eval_log = eval_log.get(); | ||||
| } | } | ||||
| MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> r_side_effect_nodes; | MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> r_side_effect_nodes; | ||||
| find_side_effect_nodes(*nmd, *ctx, btree, r_side_effect_nodes); | find_side_effect_nodes(*nmd, *ctx, r_side_effect_nodes); | ||||
| geo_nodes_modifier_data.side_effect_nodes = &r_side_effect_nodes; | geo_nodes_modifier_data.side_effect_nodes = &r_side_effect_nodes; | ||||
| blender::nodes::GeoNodesLFUserData user_data; | blender::nodes::GeoNodesLFUserData user_data; | ||||
| user_data.modifier_data = &geo_nodes_modifier_data; | user_data.modifier_data = &geo_nodes_modifier_data; | ||||
| blender::bke::ModifierComputeContext modifier_compute_context{nullptr, nmd->modifier.name}; | blender::bke::ModifierComputeContext modifier_compute_context{nullptr, nmd->modifier.name}; | ||||
| user_data.compute_context = &modifier_compute_context; | user_data.compute_context = &modifier_compute_context; | ||||
| blender::LinearAllocator<> allocator; | blender::LinearAllocator<> allocator; | ||||
| Vector<GMutablePointer> inputs_to_destruct; | Vector<GMutablePointer> inputs_to_destruct; | ||||
| ▲ Show 20 Lines • Show All 766 Lines • Show Last 20 Lines | |||||