feat(web): add scene simplify authoring
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 14:57:19 +08:00
parent 013aee26f8
commit ae614dc039
47 changed files with 1922 additions and 43 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 == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" ||
type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" || type == "setSceneSimplifySettings" ||
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" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings")
else if (type == "setCameraProperties" || type == "setLightProperties" || type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" || type == "setSceneSimplifySettings")
{
const json properties = command.value("properties", json::object());
if (type == "setSceneProperties") {
@@ -2250,6 +2250,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 == "setSceneSimplifySettings") {
applied = web_engine_blend_main_set_scene_simplify_settings(
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

@@ -5270,16 +5270,23 @@ json scene_ir_from_blend(const ParsedBlend &blend,
{"alphaPremultiplied", read_integer(*blend.sdna, *render, "alphamode").value_or(0) == R_ALPHAPREMUL}};
const int64_t render_flags = read_integer(*blend.sdna, *render, "flag").value_or(0);
if ((render_mode & R_BORDER) != 0) {
scene["borderSettings"] = {{"enabled", true},
{"minX", read_float(*blend.sdna, *render, "border.xmin").value_or(0.0f)},
{"maxX", read_float(*blend.sdna, *render, "border.xmax").value_or(1.0f)},
{"minY", read_float(*blend.sdna, *render, "border.ymin").value_or(0.0f)},
{"maxY", read_float(*blend.sdna, *render, "border.ymax").value_or(1.0f)}};
if (const std::optional<ElementRef> border = embedded_element(*blend.sdna, *render, "border")) {
scene["borderSettings"] = {{"enabled", true},
{"minX", read_float(*blend.sdna, *border, "xmin").value_or(0.0f)},
{"maxX", read_float(*blend.sdna, *border, "xmax").value_or(1.0f)},
{"minY", read_float(*blend.sdna, *border, "ymin").value_or(0.0f)},
{"maxY", read_float(*blend.sdna, *border, "ymax").value_or(1.0f)}};
}
}
if ((render_flags & SCER_PRV_RANGE) != 0) {
scene["previewRange"] = {{"start", read_integer(*blend.sdna, *render, "psfra").value_or(frame_start)},
{"end", read_integer(*blend.sdna, *render, "pefra").value_or(frame_end)}};
}
scene["simplifySettings"] = {{"subsurfViewport", read_integer(*blend.sdna, *render, "simplify_subsurf").value_or(6)},
{"subsurfRender", read_integer(*blend.sdna, *render, "simplify_subsurf_render").value_or(0)},
{"particlesViewport", read_float(*blend.sdna, *render, "simplify_particles").value_or(1.0f)},
{"particlesRender", read_float(*blend.sdna, *render, "simplify_particles_render").value_or(0.0f)},
{"volumes", read_float(*blend.sdna, *render, "simplify_volumes").value_or(1.0f)}};
}
if (const std::optional<ElementRef> audio = embedded_element(*blend.sdna, element, "audio")) {
const int64_t audio_flags = read_integer(*blend.sdna, *audio, "flag").value_or(AUDIO_SYNC);

View File

@@ -6328,6 +6328,37 @@ bool web_engine_blend_main_set_scene_border_settings(WebBlendMainState *state,
return true;
}
bool web_engine_blend_main_set_scene_simplify_settings(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 simplify 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 simplify settings must be a non-empty object"; return false; }
const std::unordered_set<std::string> allowed = {"subsurfViewport", "subsurfRender", "particlesViewport", "particlesRender", "volumes"};
for (const auto &[key, value] : properties.items()) { (void)value; if (!allowed.contains(key)) { error = "RENDER_PROPERTY_INVALID: unsupported scene simplify property " + key; return false; } }
auto read_int = [&](const char *key, int minimum, int maximum, short &target) {
if (!properties.contains(key)) return true;
if (!properties[key].is_number_integer()) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " must be an integer"; return false; }
const int64_t value = properties[key].get<int64_t>();
if (value < minimum || value > maximum) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " is outside the bounded range"; return false; }
target = short(value); return true;
};
auto read_float = [&](const char *key, float minimum, float maximum, float &target) {
if (!properties.contains(key)) return true;
if (!properties[key].is_number()) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " must be numeric"; return false; }
const float value = properties[key].get<float>();
if (!std::isfinite(value) || value < minimum || value > maximum) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " is outside the bounded range"; return false; }
target = value; return true;
};
if (!read_int("subsurfViewport", 0, 64, scene->r.simplify_subsurf) || !read_int("subsurfRender", 0, 64, scene->r.simplify_subsurf_render) || !read_float("particlesViewport", 0.0f, 1000.0f, scene->r.simplify_particles) || !read_float("particlesRender", 0.0f, 1000.0f, scene->r.simplify_particles_render) || !read_float("volumes", 0.0f, 1000.0f, scene->r.simplify_volumes)) 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

@@ -559,6 +559,10 @@ bool web_engine_blend_main_set_scene_border_settings(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
std::string &error);
bool web_engine_blend_main_set_scene_simplify_settings(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);