diff options
-rw-r--r-- | indra/newview/llgltfmateriallist.cpp | 229 | ||||
-rw-r--r-- | indra/newview/llgltfmateriallist.h | 52 | ||||
-rw-r--r-- | indra/newview/llmaterialeditor.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 24 |
4 files changed, 170 insertions, 139 deletions
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index c18988ef15..36b87b1a3d 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -51,139 +51,141 @@ LLGLTFMaterialList gGLTFMaterialList; LLGLTFMaterialList::modify_queue_t LLGLTFMaterialList::sModifyQueue; +LLGLTFMaterialList::apply_queue_t LLGLTFMaterialList::sApplyQueue; const LLUUID LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID("968cbad0-4dad-d64e-71b5-72bf13ad051a"); -namespace +class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler { - class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler - { - LOG_CLASS(LLGLTFMaterialOverrideDispatchHandler); - public: - LLGLTFMaterialOverrideDispatchHandler() = default; - ~LLGLTFMaterialOverrideDispatchHandler() override = default; + LOG_CLASS(LLGLTFMaterialOverrideDispatchHandler); +public: + LLGLTFMaterialOverrideDispatchHandler() = default; + ~LLGLTFMaterialOverrideDispatchHandler() override = default; - bool operator()(const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override - { - LL_PROFILE_ZONE_SCOPED; - // receive override data from simulator via LargeGenericMessage - // message should have: - // object_id - UUID of LLViewerObject - // side - S32 index of texture entry - // gltf_json - String of GLTF json for override data + bool operator()(const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override + { + LL_PROFILE_ZONE_SCOPED; + // receive override data from simulator via LargeGenericMessage + // message should have: + // object_id - UUID of LLViewerObject + // side - S32 index of texture entry + // gltf_json - String of GLTF json for override data - LLSD message; + LLSD message; - sparam_t::const_iterator it = strings.begin(); - if (it != strings.end()) { - const std::string& llsdRaw = *it++; - std::istringstream llsdData(llsdRaw); - if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) - { - LL_WARNS() << "LLGLTFMaterialOverrideDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; - } + sparam_t::const_iterator it = strings.begin(); + if (it != strings.end()) { + const std::string& llsdRaw = *it++; + std::istringstream llsdData(llsdRaw); + if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) + { + LL_WARNS() << "LLGLTFMaterialOverrideDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; } + } - LLUUID object_id = message["object_id"].asUUID(); + LLUUID object_id = message["object_id"].asUUID(); - LLViewerObject * obj = gObjectList.findObject(object_id); // NOTE: null object here does NOT mean nothing to do, parse message and queue results for later - bool clear_all = true; + LLViewerObject * obj = gObjectList.findObject(object_id); // NOTE: null object here does NOT mean nothing to do, parse message and queue results for later + bool clear_all = true; - if (message.has("sides") && message.has("gltf_json")) - { - LLSD& sides = message["sides"]; - LLSD& gltf_json = message["gltf_json"]; + if (message.has("sides") && message.has("gltf_json")) + { + LLSD& sides = message["sides"]; + LLSD& gltf_json = message["gltf_json"]; - if (sides.isArray() && gltf_json.isArray() && - sides.size() != 0 && - sides.size() == gltf_json.size()) - { - clear_all = false; + if (sides.isArray() && gltf_json.isArray() && + sides.size() != 0 && + sides.size() == gltf_json.size()) + { + clear_all = false; - // message should be interpreted thusly: - /// sides is a list of face indices - // gltf_json is a list of corresponding json - // any side not represented in "sides" has no override + // message should be interpreted thusly: + /// sides is a list of face indices + // gltf_json is a list of corresponding json + // any side not represented in "sides" has no override - // parse json - std::unordered_set<S32> side_set; + // parse json + std::unordered_set<S32> side_set; - for (int i = 0; i < sides.size(); ++i) - { - LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial(); + for (int i = 0; i < sides.size(); ++i) + { + LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial(); - std::string gltf_json = message["gltf_json"][i].asString(); + std::string gltf_json = message["gltf_json"][i].asString(); - std::string warn_msg, error_msg; + std::string warn_msg, error_msg; - bool success = override_data->fromJSON(gltf_json, warn_msg, error_msg); + bool success = override_data->fromJSON(gltf_json, warn_msg, error_msg); + + if (!success) + { + LL_WARNS() << "failed to parse GLTF override data. errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL; - if (!success) + // unblock material editor + if (obj && obj->isAnySelected()) { - LL_WARNS() << "failed to parse GLTF override data. errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL; + LLMaterialEditor::updateLive(object_id, sides[i].asInteger()); + } + } + else + { + S32 side = sides[i].asInteger(); + // flag this side to not be nulled out later + side_set.insert(sides[i]); - // unblock material editor - if (obj && obj->isAnySelected()) - { - LLMaterialEditor::updateLive(object_id, sides[i].asInteger()); - } + if (!obj || !obj->setTEGLTFMaterialOverride(side, override_data)) + { + // object not ready to receive override data, queue for later + gGLTFMaterialList.queueOverrideUpdate(object_id, side, override_data); } - else + else if (obj && obj->isAnySelected()) { - S32 side = sides[i].asInteger(); - // flag this side to not be nulled out later - side_set.insert(sides[i]); - - if (!obj || !obj->setTEGLTFMaterialOverride(side, override_data)) - { - // object not ready to receive override data, queue for later - gGLTFMaterialList.queueOverrideUpdate(object_id, side, override_data); - } - else if (obj && obj->isAnySelected()) - { - LLMaterialEditor::updateLive(object_id, side); - } + LLMaterialEditor::updateLive(object_id, side); } } + } - if (obj && side_set.size() != obj->getNumTEs()) - { // object exists and at least one texture entry needs to have its override data nulled out - bool object_has_selection = obj->isAnySelected(); - for (int i = 0; i < obj->getNumTEs(); ++i) + if (obj && side_set.size() != obj->getNumTEs()) + { // object exists and at least one texture entry needs to have its override data nulled out + bool object_has_selection = obj->isAnySelected(); + for (int i = 0; i < obj->getNumTEs(); ++i) + { + if (side_set.find(i) == side_set.end()) { - if (side_set.find(i) == side_set.end()) + obj->setTEGLTFMaterialOverride(i, nullptr); + if (object_has_selection) { - obj->setTEGLTFMaterialOverride(i, nullptr); - if (object_has_selection) - { - LLMaterialEditor::updateLive(object_id, i); - } + LLMaterialEditor::updateLive(object_id, i); } } } } - else - { - LL_WARNS() << "Malformed GLTF override message data: " << message << LL_ENDL; - } } + else + { + LL_WARNS() << "Malformed GLTF override message data: " << message << LL_ENDL; + } + } - if (clear_all && obj) - { // override list was empty or an error occurred, null out all overrides for this object - bool object_has_selection = obj->isAnySelected(); - for (int i = 0; i < obj->getNumTEs(); ++i) + if (clear_all && obj) + { // override list was empty or an error occurred, null out all overrides for this object + bool object_has_selection = obj->isAnySelected(); + for (int i = 0; i < obj->getNumTEs(); ++i) + { + obj->setTEGLTFMaterialOverride(i, nullptr); + if (object_has_selection) { - obj->setTEGLTFMaterialOverride(i, nullptr); - if (object_has_selection) - { - LLMaterialEditor::updateLive(obj->getID(), i); - } + LLMaterialEditor::updateLive(obj->getID(), i); } } - return true; } - }; + return true; + } +}; + +namespace +{ LLGLTFMaterialOverrideDispatchHandler handle_gltf_override_message; } @@ -229,12 +231,24 @@ void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj) } } -void LLGLTFMaterialList::queueModifyMaterial(const LLUUID& id, S32 side, const LLGLTFMaterial& mat) +void LLGLTFMaterialList::queueModifyMaterial(const LLUUID& id, S32 side, const LLGLTFMaterial* mat) +{ + if (mat == nullptr) + { + sModifyQueue.push_back({ id, side, LLGLTFMaterial(), false }); + } + else + { + sModifyQueue.push_back({ id, side, *mat, true}); + } +} + +void LLGLTFMaterialList::queueApplyMaterialAsset(const LLUUID& object_id, S32 side, const LLUUID& asset_id) { - sModifyQueue.push_back({ id, side, mat, LLUUID::null, true, false }); + sApplyQueue.push_back({ object_id, side, asset_id}); } -void LLGLTFMaterialList::flushModifyMaterialQueue(void(*done_callback)(bool)) +void LLGLTFMaterialList::flushUpdates(void(*done_callback)(bool)) { LLSD data = LLSD::emptyArray(); @@ -244,11 +258,6 @@ void LLGLTFMaterialList::flushModifyMaterialQueue(void(*done_callback)(bool)) data[i]["object_id"] = e.object_id; data[i]["side"] = e.side; - if (e.has_asset_id) - { - data[i]["asset_id"] = e.asset_id; - } - if (e.has_override) { data[i]["gltf_json"] = e.override_data.asJSON(); @@ -256,19 +265,29 @@ void LLGLTFMaterialList::flushModifyMaterialQueue(void(*done_callback)(bool)) ++i; } + sModifyQueue.clear(); - std::stringstream str; + for (auto& e : sApplyQueue) + { + data[i]["object_id"] = e.object_id; + data[i]["side"] = e.side; + data[i]["asset_id"] = e.asset_id; + data[i]["gltf_json"] = ""; // null out any existing overrides when applying a material asset + ++i; + } + sApplyQueue.clear(); +#if 0 // debug output of data being sent to capability + std::stringstream str; LLSDSerialize::serialize(data, str, LLSDSerialize::LLSD_NOTATION, LLSDFormatter::OPTIONS_PRETTY); LL_INFOS() << "\n" << str.str() << LL_ENDL; +#endif LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, gAgent.getRegionCapability("ModifyMaterialParams"), data, done_callback)); - - sModifyQueue.clear(); } class AssetLoadUserData diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index 2dae11d2ca..9f64f89961 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -53,24 +53,45 @@ public: static void registerCallbacks(); - // save an override update that we want to send to the simulator for later - static void queueModifyMaterial(const LLUUID& id, S32 side, const LLGLTFMaterial& mat); + // Queue an override update that we want to send to the simulator. Call "flushUpdates" to flush pending updates. + // id - ID of object to modify + // side - TexureEntry index to modify, or -1 for all sides + // mat - material to apply as override, or nullptr to remove existing overrides and revert to asset + // + // NOTE: do not use to revert to asset when applying a new asset id, use queueApplyMaterialAsset below + static void queueModifyMaterial(const LLUUID& id, S32 side, const LLGLTFMaterial* mat); + + // Queue an application of a material asset we want to send to the simulator. Call "flushUpdates" to flush pending updates. + // object_id - ID of object to apply material asset to + // side - TextureEntry index to apply material to, or -1 for all sides + // asset_id - ID of material asset to apply, or LLUUID::null to disassociate current material asset + // + // NOTE: implicitly removes any override data if present + static void queueApplyMaterialAsset(const LLUUID& object_id, S32 side, const LLUUID& asset_id); // flush pending material updates to the simulator - static void flushModifyMaterialQueue(void(*done_callback)(bool)); + static void flushUpdates(void(*done_callback)(bool) = nullptr); // apply given override data via given cap url // cap_url -- should be gAgent.getRegionCapability("ModifyMaterialParams") - // overrides -- LLSD map in the format - // "object_id": LLUUID - object to be modified - // "side": integer - index of face to be modified - // "gltf_json" : string - GLTF compliant json of override data (optional, if omitted any existing override data will be cleared) + // overrides -- LLSD map (or array of maps) in the format: + // object_id UUID(required) id of object + // side integer(required) TE index of face to set, or -1 for all faces + // gltf_json string(optional) override data to set, empty string nulls out override data, omissions of this parameter keeps existing data + // asset_id UUID(optional) id of material asset to set, omission of this parameter keeps existing material asset id + // + // NOTE: if you're calling this from outside of flushUpdates, you're probably doing it wrong. Use the "queue"/"flush" API above. + // If the queue/flush API is insufficient, extend it. static void modifyMaterialCoro(std::string cap_url, LLSD overrides, void(*done_callback)(bool)); - + + void applyQueuedOverrides(LLViewerObject* obj); + +private: + friend class LLGLTFMaterialOverrideDispatchHandler; // save an override update that we got from the simulator for later (for example, if an override arrived for an unknown object) + // NOTE: this is NOT for applying overrides from the UI, see queueModifyMaterial above void queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data); - void applyQueuedOverrides(LLViewerObject* obj); protected: static void onAssetLoadComplete( @@ -80,7 +101,6 @@ protected: S32 status, LLExtStat ext_status); -private: typedef std::unordered_map<LLUUID, LLPointer<LLFetchedGLTFMaterial > > uuid_mat_map_t; uuid_mat_map_t mList; @@ -95,15 +115,23 @@ private: LLUUID object_id; S32 side = -1; LLGLTFMaterial override_data; - LLUUID asset_id; bool has_override = false; - bool has_asset_id = false; }; typedef std::list<ModifyMaterialData> modify_queue_t; static modify_queue_t sModifyQueue; + struct ApplyMaterialAssetData + { + LLUUID object_id; + S32 side = -1; + LLUUID asset_id; + }; + + typedef std::list<ApplyMaterialAssetData> apply_queue_t; + static apply_queue_t sApplyQueue; + }; extern LLGLTFMaterialList gGLTFMaterialList; diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 675ca610ce..17da7e8853 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2526,7 +2526,7 @@ public: { mSuccess = true; } - LLGLTFMaterialList::queueModifyMaterial(objectp->getID(), te, *material); + LLGLTFMaterialList::queueModifyMaterial(objectp->getID(), te, material); #else std::string overrides_json = material->asJSON(); @@ -2598,7 +2598,7 @@ void LLMaterialEditor::applyToSelection() void(*done_callback)(bool) = LLRenderMaterialOverrideFunctor::modifyCallback; - LLGLTFMaterialList::flushModifyMaterialQueue(done_callback); + LLGLTFMaterialList::flushUpdates(done_callback); if (!override_func.getResult()) { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1efc4ea3d5..3cd5b1dbe7 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7205,19 +7205,15 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat if (update_server) { - // blank out any override data on the ser + // update via ModifyMaterialParams cap (server will echo back changes) for (S32 te = start_idx; te < end_idx; ++te) { - LLCoros::instance().launch("modifyMaterialCoro", - std::bind(&LLGLTFMaterialList::modifyMaterialCoro, - gAgent.getRegionCapability("ModifyMaterialParams"), - llsd::map( - "object_id", getID(), - "side", te), nullptr)); + LLGLTFMaterialList::queueApplyMaterialAsset(getID(), te, id); } + LLGLTFMaterialList::flushUpdates(); } - // update and send LLRenderMaterialParams + // predictively update LLRenderMaterialParams (don't wait for server) LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); if (!param_block && id.notNull()) { // block doesn't exist, but it will need to @@ -7230,18 +7226,6 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat { param_block->setMaterial(te, id); } - - if (update_server) - { - // If 'in use' changes, it will send an update itself. - bool in_use_changed = setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, !param_block->isEmpty(), true); - - if (!in_use_changed) - { - // In use didn't change, but the parameter did, send an update - parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, param_block, !param_block->isEmpty(), true); - } - } } } |