feat(web): add view layer lightgroup 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-30 07:08:55 +08:00
parent 0a0f36a358
commit 49b42a0f99
46 changed files with 1907 additions and 38 deletions

View File

@@ -1612,7 +1612,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 == "setSceneSimplifySettings" || type == "setSceneColorManagement" || type == "setSceneImageFormat" || type == "setSceneMotionBlur" || type == "setSceneHairSettings" || type == "setSceneCompositorSettings" || type == "setScenePerformanceSettings" || type == "setSceneSamplingSettings" || type == "setSceneMultiviewSettings" || type == "setSceneStampSettings" || type == "setSceneLineSettings" || type == "setSceneViewLayerPassSettings" || type == "setSceneViewLayerAOVs" ||
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 == "setSceneColorManagement" || type == "setSceneImageFormat" || type == "setSceneMotionBlur" || type == "setSceneHairSettings" || type == "setSceneCompositorSettings" || type == "setScenePerformanceSettings" || type == "setSceneSamplingSettings" || type == "setSceneMultiviewSettings" || type == "setSceneStampSettings" || type == "setSceneLineSettings" || type == "setSceneViewLayerPassSettings" || type == "setSceneViewLayerAOVs" || type == "setSceneViewLayerLightgroups" ||
type == "setSculptMeshAttributes" ||
type == "sculptStroke") {
if (!engine->authoritative_commands || engine->authoritative_main == nullptr) {
@@ -2216,7 +2216,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" || type == "setSceneSimplifySettings" || type == "setSceneColorManagement" || type == "setSceneImageFormat" || type == "setSceneMotionBlur" || type == "setSceneHairSettings" || type == "setSceneCompositorSettings" || type == "setScenePerformanceSettings" || type == "setSceneSamplingSettings" || type == "setSceneMultiviewSettings" || type == "setSceneStampSettings" || type == "setSceneLineSettings" || type == "setSceneViewLayerPassSettings" || type == "setSceneViewLayerAOVs")
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" || type == "setSceneColorManagement" || type == "setSceneImageFormat" || type == "setSceneMotionBlur" || type == "setSceneHairSettings" || type == "setSceneCompositorSettings" || type == "setScenePerformanceSettings" || type == "setSceneSamplingSettings" || type == "setSceneMultiviewSettings" || type == "setSceneStampSettings" || type == "setSceneLineSettings" || type == "setSceneViewLayerPassSettings" || type == "setSceneViewLayerAOVs" || type == "setSceneViewLayerLightgroups")
{
const json properties = command.value("properties", json::object());
if (type == "setSceneProperties") {
@@ -2335,6 +2335,11 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
engine->authoritative_main, command.value("dataId", "").c_str(),
command.value("layerName", "").c_str(), command.value("aovs", json::array()).dump().c_str(), main_error);
}
else if (type == "setSceneViewLayerLightgroups") {
applied = web_engine_blend_main_set_scene_view_layer_lightgroups(
engine->authoritative_main, command.value("dataId", "").c_str(),
command.value("layerName", "").c_str(), command.value("lightgroups", json::array()).dump().c_str(), main_error);
}
else {
applied = web_engine_blend_main_set_render_properties(
engine->authoritative_main, command.value("dataId", "").c_str(),

View File

@@ -5378,7 +5378,8 @@ json scene_ir_from_blend(const ParsedBlend &blend,
{"cryptomatteMask", read_integer(*blend.sdna, view_layer, "cryptomatte_flag").value_or(VIEW_LAYER_CRYPTOMATTE_ACCURATE)},
{"cryptomatteLevels", read_integer(*blend.sdna, view_layer, "cryptomatte_levels").value_or(6)},
{"alphaThreshold", read_float(*blend.sdna, view_layer, "pass_alpha_threshold").value_or(0.5f)},
{"aovs", [&]() { json values = json::array(); for (const ElementRef &aov : linked_list_elements(blend, view_layer, "aovs")) values.push_back({{"name", read_string(*blend.sdna, aov, "name")}, {"type", read_integer(*blend.sdna, aov, "type").value_or(AOV_TYPE_VALUE)}}); return values; }()}});
{"aovs", [&]() { json values = json::array(); for (const ElementRef &aov : linked_list_elements(blend, view_layer, "aovs")) values.push_back({{"name", read_string(*blend.sdna, aov, "name")}, {"type", read_integer(*blend.sdna, aov, "type").value_or(AOV_TYPE_VALUE)}}); return values; }()},
{"lightgroups", [&]() { json values = json::array(); for (const ElementRef &group : linked_list_elements(blend, view_layer, "lightgroups")) values.push_back(read_string(*blend.sdna, group, "name")); return values; }()}});
}
if (!view_layers.empty()) scene["viewLayers"] = std::move(view_layers);
if (const std::optional<ElementRef> view = embedded_element(*blend.sdna, element, "view_settings")) {

View File

@@ -6769,6 +6769,28 @@ bool web_engine_blend_main_set_scene_view_layer_aovs(WebBlendMainState *state,
return true;
}
bool web_engine_blend_main_set_scene_view_layer_lightgroups(WebBlendMainState *state,
const char *target_id,
const char *layer_name,
const char *lightgroups_json,
std::string &error)
{
if (state == nullptr || state->main == nullptr || target_id == nullptr || layer_name == nullptr || lightgroups_json == nullptr) { error = "RENDER_PROPERTY_INVALID: scene ViewLayer lightgroup target is missing"; return false; }
Scene *scene = find_scene(state->main, target_id);
if (scene == nullptr || scene->id.lib != nullptr || layer_name[0] == '\0') { error = "LINKED_DATA_MUTATION_BLOCKED: Scene lightgroups are not editable"; return false; }
ViewLayer *layer = nullptr;
for (ViewLayer &candidate : scene->view_layers) if (strncmp(candidate.name, layer_name, sizeof(candidate.name)) == 0) { layer = &candidate; break; }
if (layer == nullptr) { error = "RENDER_PROPERTY_INVALID: view layer does not exist in Scene"; return false; }
const json groups = json::parse(lightgroups_json, nullptr, false);
if (!groups.is_array() || groups.size() > 128) { error = "RENDER_PROPERTY_INVALID: lightgroup list must contain at most 128 entries"; return false; }
std::unordered_set<std::string> names;
for (const json &entry : groups) { if (!entry.is_string()) { error = "RENDER_PROPERTY_INVALID: lightgroup name must be a string"; return false; } const std::string name = entry.get<std::string>(); if (name.empty() || name.size() >= 64 || !names.insert(name).second) { error = "RENDER_PROPERTY_INVALID: lightgroup name is invalid or duplicated"; return false; } }
while (layer->lightgroups.first != nullptr) BKE_view_layer_remove_lightgroup(layer, static_cast<ViewLayerLightgroup *>(layer->lightgroups.first));
for (const json &entry : groups) BKE_view_layer_add_lightgroup(layer, entry.get<std::string>().c_str());
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

@@ -613,6 +613,11 @@ bool web_engine_blend_main_set_scene_view_layer_aovs(WebBlendMainState *state,
const char *layer_name,
const char *aovs_json,
std::string &error);
bool web_engine_blend_main_set_scene_view_layer_lightgroups(WebBlendMainState *state,
const char *target_id,
const char *layer_name,
const char *lightgroups_json,
std::string &error);
bool web_engine_blend_main_write(WebBlendMainState *state,
std::vector<uint8_t> &bytes,
std::string &error);