feat(web): author scene collection visibility
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 == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" ||
|
||||
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")
|
||||
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")
|
||||
{
|
||||
const json properties = command.value("properties", json::object());
|
||||
if (type == "setSceneProperties") {
|
||||
@@ -2239,6 +2239,12 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(),
|
||||
command.value("layerName", "").c_str(), properties.dump().c_str(), main_error);
|
||||
}
|
||||
else if (type == "setSceneCollectionSettings") {
|
||||
applied = web_engine_blend_main_set_scene_collection_settings(
|
||||
engine->authoritative_main, command.value("dataId", "").c_str(),
|
||||
command.value("layerName", "").c_str(), command.value("collectionId", "").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(),
|
||||
|
||||
@@ -6242,6 +6242,63 @@ bool web_engine_blend_main_set_scene_view_layer_settings(WebBlendMainState *stat
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_set_scene_collection_settings(WebBlendMainState *state,
|
||||
const char *target_id,
|
||||
const char *layer_name,
|
||||
const char *collection_id,
|
||||
const char *properties_json,
|
||||
std::string &error)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr || target_id == nullptr || layer_name == nullptr || collection_id == nullptr || properties_json == nullptr) {
|
||||
error = "RENDER_PROPERTY_INVALID: scene collection 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 collection 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 || strncmp(collection_id, "collection:", 11) != 0) {
|
||||
error = "RENDER_PROPERTY_INVALID: view layer or collection does not exist";
|
||||
return false;
|
||||
}
|
||||
const std::string collection_name(collection_id + 11);
|
||||
LayerCollection *match = nullptr;
|
||||
auto find_collection = [&](auto &&self, LayerCollection *candidate) -> LayerCollection * {
|
||||
if (candidate == nullptr) return nullptr;
|
||||
if (candidate->collection != nullptr && id_name(candidate->collection->id) == collection_name) return candidate;
|
||||
for (LayerCollection &child : candidate->layer_collections) if (LayerCollection *found = self(self, &child)) return found;
|
||||
return nullptr;
|
||||
};
|
||||
for (LayerCollection &root : layer->layer_collections) if ((match = find_collection(find_collection, &root)) != nullptr) break;
|
||||
if (match == nullptr) {
|
||||
error = "RENDER_PROPERTY_INVALID: collection is not part of the view layer";
|
||||
return false;
|
||||
}
|
||||
const json properties = json::parse(properties_json, nullptr, false);
|
||||
if (!properties.is_object() || properties.empty()) {
|
||||
error = "RENDER_PROPERTY_INVALID: collection settings must be a non-empty object";
|
||||
return false;
|
||||
}
|
||||
const std::unordered_set<std::string> allowed = {"exclude", "holdout", "indirectOnly", "hide"};
|
||||
for (const auto &[key, value] : properties.items()) {
|
||||
(void)value;
|
||||
if (!allowed.contains(key)) { error = "RENDER_PROPERTY_INVALID: unsupported collection property " + key; return false; }
|
||||
}
|
||||
const auto read_flag = [&](const char *key, eLayerCollection_Flag flag) {
|
||||
if (!properties.contains(key)) return true;
|
||||
if (!properties[key].is_boolean()) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " must be boolean"; return false; }
|
||||
if (properties[key].get<bool>()) match->flag |= flag;
|
||||
else match->flag &= ~flag;
|
||||
return true;
|
||||
};
|
||||
if (!read_flag("exclude", LAYER_COLLECTION_EXCLUDE) || !read_flag("holdout", LAYER_COLLECTION_HOLDOUT) || !read_flag("indirectOnly", LAYER_COLLECTION_INDIRECT_ONLY) || !read_flag("hide", LAYER_COLLECTION_HIDE)) 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)
|
||||
|
||||
@@ -549,6 +549,12 @@ bool web_engine_blend_main_set_scene_view_layer_settings(WebBlendMainState *stat
|
||||
const char *layer_name,
|
||||
const char *properties_json,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_set_scene_collection_settings(WebBlendMainState *state,
|
||||
const char *target_id,
|
||||
const char *layer_name,
|
||||
const char *collection_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