feat(web): add scene stamp 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 == "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 == "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")
|
||||
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")
|
||||
{
|
||||
const json properties = command.value("properties", json::object());
|
||||
if (type == "setSceneProperties") {
|
||||
@@ -2295,6 +2295,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 == "setSceneStampSettings") {
|
||||
applied = web_engine_blend_main_set_scene_stamp_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(),
|
||||
|
||||
@@ -5271,6 +5271,13 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
{"compression", read_integer(*blend.sdna, *image_format, "compress").value_or(15)},
|
||||
{"exrCodec", read_integer(*blend.sdna, *image_format, "exr_codec").value_or(0)}};
|
||||
}
|
||||
const std::vector<float> foreground = read_float_array(*blend.sdna, *render, "fg_stamp", 4);
|
||||
const std::vector<float> background = read_float_array(*blend.sdna, *render, "bg_stamp", 4);
|
||||
scene["stampSettings"] = {{"stampMask", read_integer(*blend.sdna, *render, "stamp").value_or(0)},
|
||||
{"fontId", read_integer(*blend.sdna, *render, "stamp_font_id").value_or(12)},
|
||||
{"userText", read_string(*blend.sdna, *render, "stamp_udata")},
|
||||
{"foreground", foreground.size() == 4 ? json(foreground) : json::array({0.8f, 0.8f, 0.8f, 1.0f})},
|
||||
{"background", background.size() == 4 ? json(background) : json::array({0.0f, 0.0f, 0.0f, 0.25f})}};
|
||||
scene["motionBlurSettings"] = {{"enabled", (render_mode & R_MBLUR) != 0},
|
||||
{"shutter", read_float(*blend.sdna, *render, "motion_blur_shutter").value_or(0.5f)},
|
||||
{"position", read_integer(*blend.sdna, *render, "motion_blur_position").value_or(SCE_MB_CENTER)}};
|
||||
|
||||
@@ -6619,6 +6619,53 @@ bool web_engine_blend_main_set_scene_multiview_settings(WebBlendMainState *state
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_scene_stamp_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 stamp 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 stamp settings must be a non-empty object"; return false; }
|
||||
const std::unordered_set<std::string> allowed = {"stampMask", "fontId", "userText", "foreground", "background"};
|
||||
for (const auto &[key, value] : properties.items()) { (void)value; if (!allowed.contains(key)) { error = "RENDER_PROPERTY_INVALID: unsupported stamp property " + key; return false; } }
|
||||
if (properties.contains("stampMask")) {
|
||||
if (!properties["stampMask"].is_number_integer()) { error = "RENDER_PROPERTY_INVALID: stampMask must be an integer"; return false; }
|
||||
const int64_t value = properties["stampMask"].get<int64_t>();
|
||||
if (value < 0 || value > 0x1ffff) { error = "RENDER_PROPERTY_INVALID: stampMask is outside the bounded range"; return false; }
|
||||
scene->r.stamp = int(value);
|
||||
}
|
||||
if (properties.contains("fontId")) {
|
||||
if (!properties["fontId"].is_number_integer()) { error = "RENDER_PROPERTY_INVALID: fontId must be an integer"; return false; }
|
||||
const int value = properties["fontId"].get<int>();
|
||||
if (value < 0 || value > 128) { error = "RENDER_PROPERTY_INVALID: fontId is outside the bounded range"; return false; }
|
||||
scene->r.stamp_font_id = short(value);
|
||||
}
|
||||
if (properties.contains("userText")) {
|
||||
if (!properties["userText"].is_string()) { error = "RENDER_PROPERTY_INVALID: userText must be a string"; return false; }
|
||||
const std::string value = properties["userText"].get<std::string>();
|
||||
if (value.size() >= sizeof(scene->r.stamp_udata)) { error = "RENDER_PROPERTY_INVALID: userText exceeds the bounded string size"; return false; }
|
||||
BLI_strncpy_utf8(scene->r.stamp_udata, value.c_str(), sizeof(scene->r.stamp_udata));
|
||||
}
|
||||
const auto read_color = [&](const char *key, float *target) {
|
||||
if (!properties.contains(key)) return true;
|
||||
const json &color = properties[key];
|
||||
if (!color.is_array() || color.size() != 4) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " must contain four channels"; return false; }
|
||||
for (int index = 0; index < 4; index++) {
|
||||
if (!color[index].is_number()) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " contains a non-number"; return false; }
|
||||
const float value = color[index].get<float>();
|
||||
if (!std::isfinite(value) || value < 0.0f || value > 1.0f) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " is outside the normalized range"; return false; }
|
||||
target[index] = value;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (!read_color("foreground", scene->r.fg_stamp) || !read_color("background", scene->r.bg_stamp)) 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)
|
||||
|
||||
@@ -595,6 +595,10 @@ bool web_engine_blend_main_set_scene_multiview_settings(WebBlendMainState *state
|
||||
const char *target_id,
|
||||
const char *properties_json,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_scene_stamp_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