feat(web): bind scene camera and world settings
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-29 13:35:53 +08:00
parent 62b45c9592
commit 27b1f77ffb
44 changed files with 1929 additions and 33 deletions

View File

@@ -1592,7 +1592,7 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
type == "insertGreasePencilFrame" || type == "removeGreasePencilFrame" ||
type == "setGreasePencilStrokes" || type == "setVertexColors" ||
type == "setVertexWeights" || type == "setCameraProperties" || type == "setLightProperties" ||
type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" ||
type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" ||
type == "setSculptMeshAttributes" ||
type == "sculptStroke") {
if (!engine->authoritative_commands || engine->authoritative_main == nullptr) {
@@ -2196,7 +2196,7 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
command.value("normalize", false), command.value("limit", 0u), command.value("mirror", false),
command.value("mirrorAxis", 0), command.value("mirrorTolerance", 1e-4f), main_error);
}
else if (type == "setCameraProperties" || type == "setLightProperties" || type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings")
else if (type == "setCameraProperties" || type == "setLightProperties" || type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings")
{
const json properties = command.value("properties", json::object());
if (type == "setSceneProperties") {
@@ -2229,6 +2229,11 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
engine->authoritative_main, command.value("dataId", "").c_str(),
properties.dump().c_str(), main_error);
}
else if (type == "setSceneBindings") {
applied = web_engine_blend_main_set_scene_bindings(
engine->authoritative_main, command.value("dataId", "").c_str(),
properties.dump().c_str(), main_error);
}
else {
applied = web_engine_blend_main_set_render_properties(
engine->authoritative_main, command.value("dataId", "").c_str(),

View File

@@ -6113,6 +6113,69 @@ bool web_engine_blend_main_set_scene_pipeline_settings(WebBlendMainState *state,
return true;
}
bool web_engine_blend_main_set_scene_bindings(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
std::string &error)
{
if (state == nullptr || state->main == nullptr || target_id == nullptr || properties_json == nullptr) {
error = "RENDER_PROPERTY_INVALID: scene binding target is missing";
return false;
}
Scene *scene = find_scene(state->main, target_id);
if (scene == nullptr || scene->id.lib != nullptr) {
error = "LINKED_DATA_MUTATION_BLOCKED: Scene is not editable";
return false;
}
const json properties = json::parse(properties_json, nullptr, false);
if (!properties.is_object() || properties.empty()) {
error = "RENDER_PROPERTY_INVALID: scene bindings must be a non-empty object";
return false;
}
const std::unordered_set<std::string> allowed = {"cameraObjectId", "worldId"};
for (const auto &[key, value] : properties.items()) {
(void)value;
if (!allowed.contains(key)) {
error = "RENDER_PROPERTY_INVALID: unsupported scene binding " + key;
return false;
}
}
if (properties.contains("cameraObjectId")) {
if (properties["cameraObjectId"].is_null()) scene->camera = nullptr;
else if (properties["cameraObjectId"].is_string()) {
const std::string id = properties["cameraObjectId"].get<std::string>();
Object *object = find_object(state->main, id.c_str());
if (object == nullptr || object->type != OB_CAMERA || object->data == nullptr) {
error = "RENDER_PROPERTY_INVALID: cameraObjectId must reference a Camera object";
return false;
}
scene->camera = object;
}
else {
error = "RENDER_PROPERTY_INVALID: cameraObjectId must be an object id or null";
return false;
}
}
if (properties.contains("worldId")) {
if (properties["worldId"].is_null()) scene->world = nullptr;
else if (properties["worldId"].is_string()) {
const std::string id = properties["worldId"].get<std::string>();
World *world = find_world(state->main, id.c_str());
if (world == nullptr) {
error = "RENDER_PROPERTY_INVALID: worldId must reference a World data block";
return false;
}
scene->world = world;
}
else {
error = "RENDER_PROPERTY_INVALID: worldId must be a data id or null";
return false;
}
}
scene->id.recalc |= ID_RECALC_PARAMETERS;
return true;
}
bool web_engine_blend_main_write(WebBlendMainState *state,
std::vector<uint8_t> &bytes,
std::string &error)

View File

@@ -540,6 +540,10 @@ bool web_engine_blend_main_set_scene_pipeline_settings(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
std::string &error);
bool web_engine_blend_main_set_scene_bindings(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
std::string &error);
bool web_engine_blend_main_write(WebBlendMainState *state,
std::vector<uint8_t> &bytes,
std::string &error);