feat(web): materialize geometry nodes in Blender Main
This commit is contained in:
@@ -4637,9 +4637,9 @@ bool web_engine_blend_main_set_geometry_node_graph(WebBlendMainState *state,
|
||||
error = "GN_INVALID_GRAPH: Geometry Node graph could not be persisted in Main";
|
||||
return false;
|
||||
}
|
||||
/* Materialize a native GeometryNodeTree datablock as the durable owner of
|
||||
* this graph. The bounded JSON remains the transport representation, while
|
||||
* future node-family slices can populate the tree incrementally. */
|
||||
/* Materialize the bounded graph into a native GeometryNodeTree. The JSON
|
||||
* remains the lossless transport record, while Blender owns the editable
|
||||
* node instances and links used by the modifier. */
|
||||
bNodeTree *native_tree = nullptr;
|
||||
for (bNodeTree &candidate : state->main->nodetrees) {
|
||||
if (id_name(candidate.id) == graph_id) {
|
||||
@@ -4656,6 +4656,60 @@ bool web_engine_blend_main_set_geometry_node_graph(WebBlendMainState *state,
|
||||
error = "GN_INVALID_GRAPH: Blender could not create a GeometryNodeTree datablock";
|
||||
return false;
|
||||
}
|
||||
while (native_tree->nodes.first != nullptr) {
|
||||
bke::node_remove_node(state->main,
|
||||
*native_tree,
|
||||
*static_cast<bNode *>(native_tree->nodes.first),
|
||||
true);
|
||||
}
|
||||
std::unordered_map<std::string, bNode *> native_nodes;
|
||||
for (const json &node : graph["nodes"]) {
|
||||
const std::string node_id = node.value("id", "");
|
||||
const std::string node_type = node.value("type", "");
|
||||
const std::string node_name = node.value("name", node_id);
|
||||
if (node_id.empty() || node_type.empty() || node_name.empty()) {
|
||||
error = "GN_INVALID_GRAPH: Geometry Node node identity is incomplete";
|
||||
return false;
|
||||
}
|
||||
if (bke::node_type_find(UString(node_type)) == nullptr) {
|
||||
error = "GN_NODE_UNSUPPORTED: Blender does not register the requested Geometry Node type";
|
||||
return false;
|
||||
}
|
||||
bNode *native = bke::node_add_node(nullptr, *native_tree, UString(node_type));
|
||||
if (native == nullptr) {
|
||||
error = "GN_INVALID_GRAPH: Blender could not materialize a Geometry Node";
|
||||
return false;
|
||||
}
|
||||
STRNCPY_UTF8(native->name, node_name.c_str());
|
||||
STRNCPY_UTF8(native->label, node_name.c_str());
|
||||
native_nodes.emplace(node_id, native);
|
||||
}
|
||||
const auto socket_for = [](bNode &node, const eNodeSocketInOut direction, const std::string &socket_id) -> bNodeSocket * {
|
||||
const size_t separator = socket_id.rfind(':');
|
||||
const std::string identifier = separator == std::string::npos ? socket_id : socket_id.substr(separator + 1);
|
||||
ListBase *sockets = direction == SOCK_IN ? &node.inputs : &node.outputs;
|
||||
for (bNodeSocket *socket = static_cast<bNodeSocket *>(sockets->first); socket != nullptr; socket = socket->next) {
|
||||
if (identifier == socket->identifier || identifier == socket->name || socket_id == socket->identifier) return socket;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
for (const json &link : graph["links"]) {
|
||||
const std::string from_id = link.value("fromNodeId", "");
|
||||
const std::string to_id = link.value("toNodeId", "");
|
||||
if (!native_nodes.contains(from_id) || !native_nodes.contains(to_id)) {
|
||||
error = "GN_INVALID_GRAPH: Geometry Node link references a missing node";
|
||||
return false;
|
||||
}
|
||||
bNodeSocket *from = socket_for(*native_nodes.at(from_id), SOCK_OUT, link.value("fromSocketId", ""));
|
||||
bNodeSocket *to = socket_for(*native_nodes.at(to_id), SOCK_IN, link.value("toSocketId", ""));
|
||||
if (from == nullptr || to == nullptr) {
|
||||
error = "GN_INVALID_GRAPH: Geometry Node link references an unavailable socket";
|
||||
return false;
|
||||
}
|
||||
bke::node_add_link(*native_tree, *native_nodes.at(from_id), *from, *native_nodes.at(to_id), *to);
|
||||
}
|
||||
BKE_ntree_update_tag_all(native_tree);
|
||||
BKE_ntree_update_after_single_tree_change(*state->main, *native_tree);
|
||||
Object *target_object = find_mesh_object(state->main, mesh_id);
|
||||
NodesModifierData *nodes_modifier = nullptr;
|
||||
if (target_object != nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user