feat(web): add view layer pass authoring
This commit is contained in:
@@ -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 == "setSceneSimplifySettings" || type == "setSceneColorManagement" || type == "setSceneImageFormat" || type == "setSceneMotionBlur" || type == "setSceneHairSettings" || type == "setSceneCompositorSettings" || type == "setScenePerformanceSettings" || type == "setSceneSamplingSettings" || type == "setSceneMultiviewSettings" || type == "setSceneStampSettings" || type == "setSceneLineSettings" ||
|
||||
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 == "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" || type == "setSceneSimplifySettings" || type == "setSceneColorManagement" || type == "setSceneImageFormat" || type == "setSceneMotionBlur" || type == "setSceneHairSettings" || type == "setSceneCompositorSettings" || type == "setScenePerformanceSettings" || type == "setSceneSamplingSettings" || type == "setSceneMultiviewSettings" || type == "setSceneStampSettings" || type == "setSceneLineSettings")
|
||||
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")
|
||||
{
|
||||
const json properties = command.value("properties", json::object());
|
||||
if (type == "setSceneProperties") {
|
||||
@@ -2305,6 +2305,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 == "setSceneViewLayerPassSettings") {
|
||||
applied = web_engine_blend_main_set_scene_view_layer_pass_settings(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(),
|
||||
command.value("layerName", "").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(),
|
||||
|
||||
@@ -5373,7 +5373,11 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
view_layers.push_back({{"name", read_string(*blend.sdna, view_layer, "name")},
|
||||
{"useRender", (flags & VIEW_LAYER_RENDER) != 0},
|
||||
{"useFreestyle", (flags & VIEW_LAYER_FREESTYLE) != 0},
|
||||
{"samples", read_integer(*blend.sdna, view_layer, "samples").value_or(0)}});
|
||||
{"samples", read_integer(*blend.sdna, view_layer, "samples").value_or(0)},
|
||||
{"passMask", read_integer(*blend.sdna, view_layer, "passflag").value_or(SCE_PASS_COMBINED)},
|
||||
{"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)}});
|
||||
}
|
||||
if (!view_layers.empty()) scene["viewLayers"] = std::move(view_layers);
|
||||
if (const std::optional<ElementRef> view = embedded_element(*blend.sdna, element, "view_settings")) {
|
||||
|
||||
@@ -6694,6 +6694,50 @@ bool web_engine_blend_main_set_scene_line_settings(WebBlendMainState *state,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_scene_view_layer_pass_settings(WebBlendMainState *state,
|
||||
const char *target_id,
|
||||
const char *layer_name,
|
||||
const char *properties_json,
|
||||
std::string &error)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr || target_id == nullptr || layer_name == nullptr || properties_json == nullptr) { error = "RENDER_PROPERTY_INVALID: scene view layer pass 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; }
|
||||
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 properties = json::parse(properties_json, nullptr, false);
|
||||
if (!properties.is_object() || properties.empty()) { error = "RENDER_PROPERTY_INVALID: view layer pass settings must be a non-empty object"; return false; }
|
||||
const std::unordered_set<std::string> allowed = {"passMask", "cryptomatteMask", "cryptomatteLevels", "alphaThreshold"};
|
||||
for (const auto &[key, value] : properties.items()) { (void)value; if (!allowed.contains(key)) { error = "RENDER_PROPERTY_INVALID: unsupported view layer pass property " + key; return false; } }
|
||||
if (properties.contains("passMask")) {
|
||||
if (!properties["passMask"].is_number_unsigned() && !properties["passMask"].is_number_integer()) { error = "RENDER_PROPERTY_INVALID: passMask must be an integer"; return false; }
|
||||
const int64_t value = properties["passMask"].get<int64_t>();
|
||||
if (value < 0 || value > 0x7fffffff) { error = "RENDER_PROPERTY_INVALID: passMask is outside the bounded range"; return false; }
|
||||
layer->passflag = int(value);
|
||||
}
|
||||
if (properties.contains("cryptomatteMask")) {
|
||||
if (!properties["cryptomatteMask"].is_number_integer()) { error = "RENDER_PROPERTY_INVALID: cryptomatteMask must be an integer"; return false; }
|
||||
const int64_t value = properties["cryptomatteMask"].get<int64_t>();
|
||||
if (value < 0 || value > 0x7fff) { error = "RENDER_PROPERTY_INVALID: cryptomatteMask is outside the bounded range"; return false; }
|
||||
layer->cryptomatte_flag = eViewLayerCryptomatteFlags(value);
|
||||
}
|
||||
if (properties.contains("cryptomatteLevels")) {
|
||||
if (!properties["cryptomatteLevels"].is_number_integer()) { error = "RENDER_PROPERTY_INVALID: cryptomatteLevels must be an integer"; return false; }
|
||||
const int value = properties["cryptomatteLevels"].get<int>();
|
||||
if (value < 1 || value > 16) { error = "RENDER_PROPERTY_INVALID: cryptomatteLevels is outside the bounded range"; return false; }
|
||||
layer->cryptomatte_levels = short(value);
|
||||
}
|
||||
if (properties.contains("alphaThreshold")) {
|
||||
if (!properties["alphaThreshold"].is_number()) { error = "RENDER_PROPERTY_INVALID: alphaThreshold must be numeric"; return false; }
|
||||
const float value = properties["alphaThreshold"].get<float>();
|
||||
if (!std::isfinite(value) || value < 0.0f || value > 1.0f) { error = "RENDER_PROPERTY_INVALID: alphaThreshold is outside the bounded range"; return false; }
|
||||
layer->pass_alpha_threshold = value;
|
||||
}
|
||||
scene->id.recalc |= ID_RECALC_PARAMETERS;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_write(WebBlendMainState *state,
|
||||
std::vector<uint8_t> &bytes,
|
||||
std::string &error)
|
||||
|
||||
@@ -603,6 +603,11 @@ bool web_engine_blend_main_set_scene_line_settings(WebBlendMainState *state,
|
||||
const char *target_id,
|
||||
const char *properties_json,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_scene_view_layer_pass_settings(WebBlendMainState *state,
|
||||
const char *target_id,
|
||||
const char *layer_name,
|
||||
const char *properties_json,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_write(WebBlendMainState *state,
|
||||
std::vector<uint8_t> &bytes,
|
||||
std::string &error);
|
||||
|
||||
Reference in New Issue
Block a user