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) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
- task: `WBV2-P27-002`; parent: `WBV2-P27-001`; status: `in_progress`
|
||||
- source prerequisite: `PASS`; Blender 5.2.0 `web_engine` compiled from `blender-5.2.0` with local Emscripten 3.1.69
|
||||
- compiled artifacts copied to `web/app/src/vendor/blender/` and `web/app/public/vendor/blender/`
|
||||
- application package rebuilt with `web_engine-C1wwLZyc.wasm` and `web-engine.worker-C3G0ZxMq.js`
|
||||
- build command exit: `0`; log: `tests/golden/WBV2-P27-002/source-build.log`
|
||||
- Chromium production receipt, malformed/transaction/persistence/determinism verification: `DEFERRED_BY_IMPLEMENTATION_FIRST_MODE`
|
||||
- inventory unchanged: `6900` total, `281` legacy completed, `6618` legacy pending, `290/6609` effective carried forward
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"sourceMainState": {
|
||||
"path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp",
|
||||
"sha256": "f48e424f53969cf2d9bce3ad9be565179d415301739f07785a1ed3271e430307"
|
||||
"sha256": "dace3c17f47a2c267ed9a0dec649ec5fe3091873c99e0f1824d24b94f25e9127"
|
||||
},
|
||||
"sourceMainHeader": {
|
||||
"path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h",
|
||||
@@ -37,7 +37,7 @@
|
||||
},
|
||||
"wasm": {
|
||||
"path": "web/app/src/vendor/blender/web_engine.wasm",
|
||||
"sha256": "7981e66ccc37f3183c8c6244a667de6a2a2b39aa6934c9cefc280ea93773ccda"
|
||||
"sha256": "08a5caccd99f9d51221d0a0adea3db1a57ab5d2718b6b026dc7f4af096054d07"
|
||||
},
|
||||
"publicLoader": {
|
||||
"path": "web/app/public/vendor/blender/web_engine.js",
|
||||
@@ -45,19 +45,19 @@
|
||||
},
|
||||
"publicWasm": {
|
||||
"path": "web/app/public/vendor/blender/web_engine.wasm",
|
||||
"sha256": "7981e66ccc37f3183c8c6244a667de6a2a2b39aa6934c9cefc280ea93773ccda"
|
||||
"sha256": "08a5caccd99f9d51221d0a0adea3db1a57ab5d2718b6b026dc7f4af096054d07"
|
||||
},
|
||||
"webDistIndex": {
|
||||
"path": "web/dist/index.html",
|
||||
"sha256": "f63ea65367e10bea54c4d10428c2401db6d2aca9006c18692ced5e55b0e1527f"
|
||||
"sha256": "6987bd43643d2c9f8abef1db4abab4df76e5a4acf567f374a01e073d9c410bff"
|
||||
},
|
||||
"webDistWorker": {
|
||||
"path": "web/dist/assets/web-engine.worker-C3G0ZxMq.js",
|
||||
"sha256": "b9083c4a38c16ba9ece02cb87c3c1a37cbea458b39db514c3abb8bd276ff9ff1"
|
||||
"path": "web/dist/assets/web-engine.worker-Bm3nUTqn.js",
|
||||
"sha256": "de3fcef592876e81b572dcc9e3d2118f4089e6170939310974d64866f493490b"
|
||||
},
|
||||
"webDistWasm": {
|
||||
"path": "web/dist/assets/web_engine-C1wwLZyc.wasm",
|
||||
"sha256": "7981e66ccc37f3183c8c6244a667de6a2a2b39aa6934c9cefc280ea93773ccda"
|
||||
"path": "web/dist/assets/web_engine-CDU-hUyU.wasm",
|
||||
"sha256": "08a5caccd99f9d51221d0a0adea3db1a57ab5d2718b6b026dc7f4af096054d07"
|
||||
}
|
||||
},
|
||||
"verification": {
|
||||
|
||||
@@ -1 +1,26 @@
|
||||
ninja: no work to do.
|
||||
[1/3] Building CXX object source/blender/web_engine/CMakeFiles/blender_web_engine_core.dir/web_engine_main_state.cpp.o
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp:35:
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/blenkernel/BKE_node.hh:20:
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_node_types.h:15:
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_scene_types.h:35:
|
||||
/home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_view3d_types.h:126:26: warning: implicit conversion from 'int' to 'char' changes value from 128 to -128 [-Wconstant-conversion]
|
||||
126 | RV3D_VIEWLOCK_INIT = 1 << 7,
|
||||
| ~~^~~~
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp:35:
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/blenkernel/BKE_node.hh:20:
|
||||
In file included from /home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_node_types.h:15:
|
||||
/home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_scene_types.h:2053:33: warning: implicit conversion from 'int' to 'char' changes value from 128 to -128 [-Wconstant-conversion]
|
||||
2053 | UVCALC_UNWRAP_USE_WEIGHTS = 1 << 7,
|
||||
| ~~^~~~
|
||||
/home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_scene_types.h:2324:25: warning: implicit conversion from 'blender::eSnapMode' to 'char' changes value from 128 to -128 [-Wconstant-conversion]
|
||||
2324 | char snap_node_mode = SCE_SNAP_TO_GRID;
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
/home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_scene_types.h:2324:25: warning: implicit conversion from 'blender::eSnapMode' to 'char' changes value from 128 to -128 [-Wconstant-conversion]
|
||||
2324 | char snap_node_mode = SCE_SNAP_TO_GRID;
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
/home/mes123456/workinf_Blender_Wasm/blender-5.2.0/source/blender/makesdna/DNA_scene_types.h:2200:26: note: in defaulted default constructor for 'blender::ToolSettings' first required here
|
||||
2200 | DNA_DEFINE_CXX_METHODS(ToolSettings)
|
||||
| ^
|
||||
4 warnings generated.
|
||||
[2/3] Linking CXX static library lib/libblender_web_engine_core.a
|
||||
[3/3] Linking CXX executable bin/web_engine.js
|
||||
|
||||
@@ -13,10 +13,15 @@ const buildDir = "build_web_blender6";
|
||||
const jsPath = "web/app/src/vendor/blender/web_engine.js";
|
||||
const wasmPath = "web/app/src/vendor/blender/web_engine.wasm";
|
||||
const logPath = `${out}/source-build.log`;
|
||||
const distAssets = fs.readdirSync(abs("web/dist/assets"));
|
||||
const distWorker = distAssets.find((file) => /^web-engine\.worker-.*\.js$/u.test(file));
|
||||
const distWasm = distAssets.find((file) => /^web_engine-.*\.wasm$/u.test(file));
|
||||
assert.ok(fs.existsSync(abs(`${buildDir}/bin/web_engine.js`)));
|
||||
assert.ok(fs.existsSync(abs(`${buildDir}/bin/web_engine.wasm`)));
|
||||
assert.equal(sha(`${buildDir}/bin/web_engine.js`), sha(jsPath));
|
||||
assert.equal(sha(`${buildDir}/bin/web_engine.wasm`), sha(wasmPath));
|
||||
assert.ok(distWorker);
|
||||
assert.ok(distWasm);
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P27-002",
|
||||
@@ -41,6 +46,9 @@ const report = {
|
||||
wasm: { path: wasmPath, sha256: sha(wasmPath) },
|
||||
publicLoader: { path: "web/app/public/vendor/blender/web_engine.js", sha256: sha("web/app/public/vendor/blender/web_engine.js") },
|
||||
publicWasm: { path: "web/app/public/vendor/blender/web_engine.wasm", sha256: sha("web/app/public/vendor/blender/web_engine.wasm") },
|
||||
webDistIndex: { path: "web/dist/index.html", sha256: sha("web/dist/index.html") },
|
||||
webDistWorker: { path: `web/dist/assets/${distWorker}`, sha256: sha(`web/dist/assets/${distWorker}`) },
|
||||
webDistWasm: { path: `web/dist/assets/${distWasm}`, sha256: sha(`web/dist/assets/${distWasm}`) },
|
||||
},
|
||||
verification: { chromium: "DEFERRED", productionReceipts: false, malformedBoundary: false, undoRedo: false, saveReopen: false, deterministicSecondRun: false, completionOverlay: false },
|
||||
inventory: { total: 6900, legacyCompleted: 281, legacyPending: 6618, effectiveCompleted: 290, effectivePending: 6609 },
|
||||
|
||||
BIN
web/app/public/vendor/blender/web_engine.wasm
vendored
BIN
web/app/public/vendor/blender/web_engine.wasm
vendored
Binary file not shown.
BIN
web/app/src/vendor/blender/web_engine.wasm
vendored
BIN
web/app/src/vendor/blender/web_engine.wasm
vendored
Binary file not shown.
Reference in New Issue
Block a user