feat(web): persist advanced Main capability overrides
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include "BKE_object_deform.h"
|
||||
#include "BKE_packedFile.hh"
|
||||
#include "BKE_scene.hh"
|
||||
#include "BKE_text.h"
|
||||
#include "BKE_vfont.hh"
|
||||
#include "BKE_volume.hh"
|
||||
#include "BKE_fcurve.hh"
|
||||
@@ -72,6 +73,7 @@
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_text_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_userdef_enums.h"
|
||||
#include "DNA_vfont_types.h"
|
||||
@@ -134,6 +136,75 @@ std::string id_name(const ID &id)
|
||||
return id.name[0] != '\0' && id.name[1] != '\0' ? std::string(id.name + 2) : std::string();
|
||||
}
|
||||
|
||||
constexpr char WEB_ENGINE_GEOMETRY_OVERRIDE_TEXT[] = "WBV2 Geometry Node Overrides";
|
||||
constexpr char WEB_ENGINE_PHYSICS_OVERRIDE_TEXT[] = "WBV2 Physics Simulation Override";
|
||||
|
||||
std::string text_contents(Text &text)
|
||||
{
|
||||
size_t length = 0;
|
||||
char *buffer = txt_to_buf(&text, &length);
|
||||
if (buffer == nullptr) return {};
|
||||
std::string result(buffer, length);
|
||||
MEM_delete(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
Text *find_text(Main *main, const char *name)
|
||||
{
|
||||
if (main == nullptr || name == nullptr) return nullptr;
|
||||
for (Text &text : main->texts) {
|
||||
if (id_name(text.id) == name) return &text;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool write_text(Main *main, const char *name, const std::string &contents)
|
||||
{
|
||||
if (main == nullptr || name == nullptr || contents.size() > 64 * 1024 * 1024) return false;
|
||||
Text *text = find_text(main, name);
|
||||
if (text == nullptr) text = BKE_text_add(main, name);
|
||||
if (text == nullptr) return false;
|
||||
BKE_text_clear(text);
|
||||
BKE_text_write(text, contents.c_str(), int(contents.size()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_persisted_geometry_overrides(WebBlendMainState *state)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr) return;
|
||||
Text *text = find_text(state->main, WEB_ENGINE_GEOMETRY_OVERRIDE_TEXT);
|
||||
if (text == nullptr) return;
|
||||
try {
|
||||
const json payload = json::parse(text_contents(*text));
|
||||
if (!payload.is_object()) return;
|
||||
for (const auto &[graph_id, graph] : payload.items()) {
|
||||
if (graph.is_object()) state->geometry_node_graph_overrides[graph_id] = graph.dump();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
/* Invalid internal text is ignored; regular Main data remains authoritative. */
|
||||
}
|
||||
}
|
||||
|
||||
void load_persisted_physics_override(WebBlendMainState *state)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr || !state->physics_simulation_override.empty()) return;
|
||||
Text *text = find_text(state->main, WEB_ENGINE_PHYSICS_OVERRIDE_TEXT);
|
||||
if (text == nullptr) return;
|
||||
const std::string contents = text_contents(*text);
|
||||
if (!contents.empty()) state->physics_simulation_override = contents;
|
||||
}
|
||||
|
||||
bool persist_geometry_overrides(WebBlendMainState *state)
|
||||
{
|
||||
json payload = json::object();
|
||||
for (const auto &[graph_id, graph_text] : state->geometry_node_graph_overrides) {
|
||||
try { payload[graph_id] = json::parse(graph_text); }
|
||||
catch (...) { return false; }
|
||||
}
|
||||
return write_text(state->main, WEB_ENGINE_GEOMETRY_OVERRIDE_TEXT, payload.dump());
|
||||
}
|
||||
|
||||
Object *find_object(Main *main, const char *object_id)
|
||||
{
|
||||
if (main == nullptr || object_id == nullptr || strncmp(object_id, "object:", 7) != 0) {
|
||||
@@ -869,6 +940,8 @@ WebBlendMainState *web_engine_blend_main_open(const uint8_t *data,
|
||||
for (blender::ViewLayer &candidate : state->scene->view_layers) {
|
||||
blender::BKE_view_layer_synced_ensure(*state->main, state->scene, &candidate);
|
||||
}
|
||||
load_persisted_geometry_overrides(state);
|
||||
load_persisted_physics_override(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -4344,7 +4417,17 @@ bool web_engine_blend_main_set_geometry_node_graph(WebBlendMainState *state,
|
||||
error = "GN_INVALID_GRAPH: Geometry Node graph schema or bounds are invalid";
|
||||
return false;
|
||||
}
|
||||
state->geometry_node_graph_overrides[graph_id] = graph.dump();
|
||||
const std::string graph_text = graph.dump();
|
||||
const auto previous = state->geometry_node_graph_overrides.find(graph_id);
|
||||
const bool had_previous = previous != state->geometry_node_graph_overrides.end();
|
||||
const std::string previous_text = had_previous ? previous->second : std::string();
|
||||
state->geometry_node_graph_overrides[graph_id] = graph_text;
|
||||
if (!persist_geometry_overrides(state)) {
|
||||
if (!had_previous) state->geometry_node_graph_overrides.erase(graph_id);
|
||||
else state->geometry_node_graph_overrides[graph_id] = previous_text;
|
||||
error = "GN_INVALID_GRAPH: Geometry Node graph could not be persisted in Main";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &exception) {
|
||||
@@ -4508,7 +4591,12 @@ bool web_engine_blend_main_set_physics_simulation(WebBlendMainState *state,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state->physics_simulation_override = manifest.dump();
|
||||
const std::string manifest_text = manifest.dump();
|
||||
if (!write_text(state->main, WEB_ENGINE_PHYSICS_OVERRIDE_TEXT, manifest_text)) {
|
||||
error = "PHYSICS_MANIFEST_INVALID: physics manifest could not be persisted in Main";
|
||||
return false;
|
||||
}
|
||||
state->physics_simulation_override = manifest_text;
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &exception) {
|
||||
|
||||
Reference in New Issue
Block a user