feat(web): continue source-backed implementation waves
This commit is contained in:
@@ -1585,7 +1585,7 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
|
||||
type == "moveObjectToCollection" || type == "renameId" || type == "joinObjects" ||
|
||||
type == "separateMeshFaces" || type == "applyObjectTransform" || type == "setObjectOrigin" ||
|
||||
type == "setCurveControlPoints" || type == "setCurveHandle" || type == "setCurveTopology" || type == "setCurveSplines" || type == "setSurfaceTopology" || type == "setFontBody" ||
|
||||
type == "setFontProperties" || type == "setFontAdvanced" || type == "importVFont" || type == "setFontLinks" || type == "setVolumeProperties" || type == "deleteNonMeshData" ||
|
||||
type == "setFontProperties" || type == "setFontAdvanced" || type == "importVFont" || type == "setFontLinks" || type == "setTextSource" || type == "setVolumeProperties" || type == "deleteNonMeshData" ||
|
||||
type == "setMetaballElements" || type == "createGreasePencilLayer" ||
|
||||
type == "removeGreasePencilLayer" || type == "moveGreasePencilLayer" ||
|
||||
type == "moveGreasePencilFrame" ||
|
||||
@@ -1994,6 +1994,11 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
|
||||
applied = main_error.empty() && web_engine_blend_main_set_font_links(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(), font_ids, main_error);
|
||||
}
|
||||
else if (type == "setTextSource") {
|
||||
applied = web_engine_blend_main_set_text_source(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(),
|
||||
command.value("source", "").c_str(), main_error);
|
||||
}
|
||||
else if (type == "setVolumeProperties") {
|
||||
WebVolumePropertiesEdit properties;
|
||||
properties.source_path = command.value("sourcePath", "");
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "BKE_material.hh"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_node_legacy_types.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
@@ -46,6 +47,7 @@
|
||||
#include "BKE_volume.hh"
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_image.hh"
|
||||
#include "BKE_idprop.hh"
|
||||
|
||||
#include "ANIM_action.hh"
|
||||
#include "ANIM_fcurve.hh"
|
||||
@@ -169,6 +171,22 @@ bool write_text(Main *main, const char *name, const std::string &contents)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_id_string(ID &id, const char *name, const std::string &contents)
|
||||
{
|
||||
if (name == nullptr || contents.size() > 16 * 1024 * 1024) return false;
|
||||
IDProperty *group = IDP_EnsureProperties(&id);
|
||||
if (group == nullptr) return false;
|
||||
if (IDProperty *existing = IDP_GetPropertyFromGroup_null(group, name)) {
|
||||
IDP_FreeFromGroup(group, existing);
|
||||
}
|
||||
IDProperty *property = bke::idprop::create(name, contents.c_str()).release();
|
||||
if (property == nullptr || !IDP_AddToGroup(group, property)) {
|
||||
if (property != nullptr) IDP_FreeProperty(property);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_persisted_geometry_overrides(WebBlendMainState *state)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr) return;
|
||||
@@ -3964,6 +3982,28 @@ bool web_engine_blend_main_set_font_links(WebBlendMainState *state,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_text_source(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const char *source,
|
||||
std::string &error)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr || data_id == nullptr || source == nullptr ||
|
||||
strncmp(data_id, "text:", 5) != 0 || strlen(source) > 1024 * 1024)
|
||||
{
|
||||
error = "NON_MESH_PROPERTY_INVALID: Text source must be a local text data-block within the 1 MiB budget";
|
||||
return false;
|
||||
}
|
||||
Text *text = find_text(state->main, data_id + 5);
|
||||
if (text == nullptr || text->id.lib != nullptr) {
|
||||
error = "NON_MESH_DATA_UNSUPPORTED: Text data-block was not found or is linked read-only";
|
||||
return false;
|
||||
}
|
||||
BKE_text_clear(text);
|
||||
BKE_text_write(text, source, int(strlen(source)));
|
||||
text->flags |= TXT_ISDIRTY;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_volume_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebVolumePropertiesEdit &properties,
|
||||
@@ -4428,6 +4468,53 @@ 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. */
|
||||
bNodeTree *native_tree = nullptr;
|
||||
for (bNodeTree &candidate : state->main->nodetrees) {
|
||||
if (id_name(candidate.id) == graph_id) {
|
||||
native_tree = &candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (native_tree == nullptr) {
|
||||
native_tree = bke::node_tree_add_tree(state->main, graph_id, "GeometryNodeTree");
|
||||
}
|
||||
if (native_tree == nullptr) {
|
||||
state->geometry_node_graph_overrides.erase(graph_id);
|
||||
persist_geometry_overrides(state);
|
||||
error = "GN_INVALID_GRAPH: Blender could not create a GeometryNodeTree datablock";
|
||||
return false;
|
||||
}
|
||||
Object *target_object = find_mesh_object(state->main, mesh_id);
|
||||
NodesModifierData *nodes_modifier = nullptr;
|
||||
if (target_object != nullptr) {
|
||||
nodes_modifier = reinterpret_cast<NodesModifierData *>(
|
||||
BKE_modifiers_findby_type(target_object, eModifierType_Nodes));
|
||||
if (nodes_modifier == nullptr) {
|
||||
nodes_modifier = reinterpret_cast<NodesModifierData *>(BKE_modifier_new(eModifierType_Nodes));
|
||||
if (nodes_modifier == nullptr) {
|
||||
error = "GN_INVALID_GRAPH: Blender could not create a Geometry Nodes modifier";
|
||||
return false;
|
||||
}
|
||||
STRNCPY_UTF8(nodes_modifier->modifier.name, "Web Geometry Nodes");
|
||||
BKE_modifier_unique_name(&target_object->modifiers, &nodes_modifier->modifier);
|
||||
BKE_modifiers_persistent_uid_init(*target_object, nodes_modifier->modifier);
|
||||
BLI_addtail(&target_object->modifiers, nodes_modifier);
|
||||
}
|
||||
if (nodes_modifier->node_group != native_tree) {
|
||||
if (nodes_modifier->node_group != nullptr) id_us_min(&nodes_modifier->node_group->id);
|
||||
nodes_modifier->node_group = native_tree;
|
||||
id_us_plus(&native_tree->id);
|
||||
}
|
||||
target_object->id.recalc |= ID_RECALC_GEOMETRY;
|
||||
if (!write_id_string(target_object->id, "web_geometry_node_graph", graph_text)) {
|
||||
error = "GN_INVALID_GRAPH: Geometry Node graph metadata could not be written to Object";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
native_tree->id.recalc |= ID_RECALC_NTREE_OUTPUT;
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &exception) {
|
||||
@@ -4596,6 +4683,15 @@ bool web_engine_blend_main_set_physics_simulation(WebBlendMainState *state,
|
||||
error = "PHYSICS_MANIFEST_INVALID: physics manifest could not be persisted in Main";
|
||||
return false;
|
||||
}
|
||||
for (const json &system : manifest["systems"]) {
|
||||
const std::string owner_id = system.value("ownerObjectId", "");
|
||||
if (Object *owner = find_object(state->main, owner_id.c_str())) {
|
||||
if (!write_id_string(owner->id, "web_physics_manifest", manifest_text)) {
|
||||
error = "PHYSICS_MANIFEST_INVALID: physics metadata could not be written to Object";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
state->physics_simulation_override = manifest_text;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -366,6 +366,10 @@ bool web_engine_blend_main_set_font_links(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const std::array<std::string, 4> &font_ids,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_text_source(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const char *source,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_volume_properties(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const WebVolumePropertiesEdit &properties,
|
||||
|
||||
Reference in New Issue
Block a user