feat(web): add scene render border 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 == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" ||
|
||||
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")
|
||||
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")
|
||||
{
|
||||
const json properties = command.value("properties", json::object());
|
||||
if (type == "setSceneProperties") {
|
||||
@@ -2245,6 +2245,11 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
|
||||
command.value("layerName", "").c_str(), command.value("collectionId", "").c_str(),
|
||||
properties.dump().c_str(), main_error);
|
||||
}
|
||||
else if (type == "setSceneBorderSettings") {
|
||||
applied = web_engine_blend_main_set_scene_border_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(),
|
||||
|
||||
@@ -5269,6 +5269,13 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
{"saveOutput", (render_mode & R_SAVE_OUTPUT) != 0},
|
||||
{"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 ((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)}};
|
||||
|
||||
@@ -6299,6 +6299,35 @@ bool web_engine_blend_main_set_scene_collection_settings(WebBlendMainState *stat
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_scene_border_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 border 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 border settings must be a non-empty object"; return false; }
|
||||
const std::unordered_set<std::string> allowed = {"enabled", "minX", "maxX", "minY", "maxY"};
|
||||
for (const auto &[key, value] : properties.items()) { (void)value; if (!allowed.contains(key)) { error = "RENDER_PROPERTY_INVALID: unsupported scene border property " + key; return false; } }
|
||||
auto read_border = [&](const char *key, 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 < 0.0f || value > 1.0f) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " is outside the normalized border"; return false; }
|
||||
target = value; return true;
|
||||
};
|
||||
if (!read_border("minX", scene->r.border.xmin) || !read_border("maxX", scene->r.border.xmax) || !read_border("minY", scene->r.border.ymin) || !read_border("maxY", scene->r.border.ymax)) return false;
|
||||
if (scene->r.border.xmax <= scene->r.border.xmin || scene->r.border.ymax <= scene->r.border.ymin) { error = "RENDER_PROPERTY_INVALID: border max values must exceed min values"; return false; }
|
||||
if (properties.contains("enabled")) {
|
||||
if (!properties["enabled"].is_boolean()) { error = "RENDER_PROPERTY_INVALID: enabled must be boolean"; return false; }
|
||||
if (properties["enabled"].get<bool>()) scene->r.mode |= R_BORDER; else scene->r.mode &= ~R_BORDER;
|
||||
}
|
||||
scene->id.recalc |= ID_RECALC_PARAMETERS;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_write(WebBlendMainState *state,
|
||||
std::vector<uint8_t> &bytes,
|
||||
std::string &error)
|
||||
|
||||
@@ -555,6 +555,10 @@ bool web_engine_blend_main_set_scene_collection_settings(WebBlendMainState *stat
|
||||
const char *collection_id,
|
||||
const char *properties_json,
|
||||
std::string &error);
|
||||
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_write(WebBlendMainState *state,
|
||||
std::vector<uint8_t> &bytes,
|
||||
std::string &error);
|
||||
|
||||
Reference in New Issue
Block a user