diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index b24fa5fbfe02c14be4b877d8e4283bb969668ed3..7971068fa22466a2bca41f90dfda883c0658b0f8 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -29,6 +29,7 @@ set(llmessage_SOURCE_FILES lldispatcher.cpp llexperiencecache.cpp llfiltersd2xmlrpc.cpp + llgenericstreamingmessage.cpp llhost.cpp llhttpnode.cpp llhttpsdhandler.cpp @@ -113,6 +114,7 @@ set(llmessage_HEADER_FILES llextendedstatus.h llfiltersd2xmlrpc.h llfollowcamparams.h + llgenericstreamingmessage.h llhost.h llhttpnode.h llhttpnodeadapter.h diff --git a/indra/llmessage/llgenericstreamingmessage.cpp b/indra/llmessage/llgenericstreamingmessage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8627675c54edd74d8ef3f8ed8c88bf962c7754bc --- /dev/null +++ b/indra/llmessage/llgenericstreamingmessage.cpp @@ -0,0 +1,72 @@ +/** + * @file llgenericstreamingmessage.cpp + * @brief Generic Streaming Message helpers. Shared between viewer and simulator. + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgenericstreamingmessage.h" + +#include "message.h" + +void LLGenericStreamingMessage::send(LLMessageSystem* msg) +{ +#if 0 // viewer cannot send GenericStreamingMessage + msg->newMessageFast(_PREHASH_GenericStreamingMessage); + + if (mData.size() < 1024 * 7) + { // disable warning about big messages unless we're sending a REALLY big message + msg->tempDisableWarnAboutBigMessage(); + } + else + { + LL_WARNS("Messaging") << "Attempted to send too large GenericStreamingMessage, dropping." << LL_ENDL; + return; + } + + msg->nextBlockFast(_PREHASH_MethodData); + msg->addU16Fast(_PREHASH_Method, mMethod); + msg->nextBlockFast(_PREHASH_DataBlock); + msg->addStringFast(_PREHASH_Data, mData.c_str()); +#endif +} + +void LLGenericStreamingMessage::unpack(LLMessageSystem* msg) +{ + U16* m = (U16*)&mMethod; // squirrely pass enum as U16 by reference + msg->getU16Fast(_PREHASH_MethodData, _PREHASH_Method, *m); + + constexpr int MAX_SIZE = 7 * 1024; + + char buffer[MAX_SIZE]; + + // NOTE: don't use getStringFast to avoid 1200 byte truncation + U32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Data); + msg->getBinaryDataFast(_PREHASH_DataBlock, _PREHASH_Data, buffer, size, 0, MAX_SIZE); + + mData.assign(buffer, size); +} + + + diff --git a/indra/llmessage/llgenericstreamingmessage.h b/indra/llmessage/llgenericstreamingmessage.h new file mode 100644 index 0000000000000000000000000000000000000000..9ac9719ea1402a815147a67dd1db38b90c511108 --- /dev/null +++ b/indra/llmessage/llgenericstreamingmessage.h @@ -0,0 +1,50 @@ +/** + * @file llgenericstreamingmessage.h + * @brief Generic Streaming Message helpers. Shared between viewer and simulator. + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#pragma once + +#include <string> +#include "stdtypes.h" + +class LLMessageSystem; + +class LLGenericStreamingMessage +{ +public: + enum Method : U16 + { + METHOD_GLTF_MATERIAL_OVERRIDE = 0x4175, + METHOD_UNKNOWN = 0xFFFF, + }; + + void send(LLMessageSystem* msg); + void unpack(LLMessageSystem* msg); + + Method mMethod = METHOD_UNKNOWN; + std::string mData; +}; + + diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index e82b8e61c9189b11688e8474dfa5a29a51fd5ca9..346082cf68bedd5a223f816a495f735692e2472f 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1432,6 +1432,7 @@ char const* const _PREHASH_IMViaEMail = LLMessageStringTable::getInstance()->get char const* const _PREHASH_RentPrice = LLMessageStringTable::getInstance()->getString("RentPrice"); char const* const _PREHASH_GenericMessage = LLMessageStringTable::getInstance()->getString("GenericMessage"); char const* const _PREHASH_LargeGenericMessage = LLMessageStringTable::getInstance()->getString("LargeGenericMessage"); +char const* const _PREHASH_GenericStreamingMessage = LLMessageStringTable::getInstance()->getString("GenericStreamingMessage"); char const* const _PREHASH_ChildAgentAlive = LLMessageStringTable::getInstance()->getString("ChildAgentAlive"); char const* const _PREHASH_AssetType = LLMessageStringTable::getInstance()->getString("AssetType"); char const* const _PREHASH_SpawnPointBlock = LLMessageStringTable::getInstance()->getString("SpawnPointBlock"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 209633c3c91107ec1934736f30e9b29b4dd5a8b6..c58436a1498d285e5e5c3d5c93848773bfb2faad 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1433,6 +1433,7 @@ extern char const* const _PREHASH_IMViaEMail; extern char const* const _PREHASH_RentPrice; extern char const* const _PREHASH_GenericMessage; extern char const* const _PREHASH_LargeGenericMessage; +extern char const* const _PREHASH_GenericStreamingMessage; extern char const* const _PREHASH_ChildAgentAlive; extern char const* const _PREHASH_AssetType; extern char const* const _PREHASH_SpawnPointBlock; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 25368f633a3db9c28d3cfcabd32414e5d13df888..337091f5e13c40d37e37fc1caeb68ba94040dbd4 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -165,9 +165,9 @@ class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler // sides - array of S32 indices of texture entries // gltf_json - array of corresponding Strings of GLTF json for override data - LLSD message; bool success = true; +#if 0 //deprecated for(const std::string& llsdRaw : strings) { std::istringstream llsdData(llsdRaw); @@ -203,6 +203,7 @@ class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler applyData(object_override); } +#endif return success; } @@ -218,6 +219,7 @@ class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler { // Parse the data +#if 0 // DEPRECATED LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); @@ -231,98 +233,92 @@ class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler if (!object_override.mSides.empty()) { - // fromJson() is performance heavy offload to a thread. - main_queue->postTo( - general_queue, - [sides=object_override.mSides]() // Work done on general queue - { - std::vector<ReturnData> results; - - results.reserve(sides.size()); - // parse json - std::unordered_map<S32, std::string>::const_iterator iter = sides.begin(); - std::unordered_map<S32, std::string>::const_iterator end = sides.end(); - while (iter != end) - { - std::string warn_msg, error_msg; - - ReturnData result; - - bool success = result.mMaterial.fromJSON(iter->second, warn_msg, error_msg); - - result.mSuccess = success; - result.mSide = iter->first; - - if (!success) - { - LL_WARNS("GLTF") << "failed to parse GLTF override data. errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL; - } - - results.push_back(result); - iter++; - } - return results; - }, - [object_id=object_override.mObjectId, this](std::vector<ReturnData> results) // Callback to main thread - { - LLViewerObject * obj = gObjectList.findObject(object_id); - - if (results.size() > 0 ) - { - std::unordered_set<S32> side_set; - - for (auto const & result : results) - { - S32 side = result.mSide; - if (result.mSuccess) - { - // copy to heap here because LLTextureEntry is going to take ownership with an LLPointer - LLGLTFMaterial * material = new LLGLTFMaterial(result.mMaterial); - - // flag this side to not be nulled out later - side_set.insert(side); - - if (obj) - { - obj->setTEGLTFMaterialOverride(side, material); - } - } - - // unblock material editor - if (obj && obj->getTE(side) && obj->getTE(side)->isSelected()) - { - doSelectionCallbacks(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 - for (int i = 0; i < obj->getNumTEs(); ++i) - { - if (side_set.find(i) == side_set.end()) - { - obj->setTEGLTFMaterialOverride(i, nullptr); - if (obj->getTE(i) && obj->getTE(i)->isSelected()) - { - doSelectionCallbacks(object_id, i); - } - } - } - } - } - else if (obj) - { // override list was empty or an error occurred, null out all overrides for this object - for (int i = 0; i < obj->getNumTEs(); ++i) - { - obj->setTEGLTFMaterialOverride(i, nullptr); - if (obj->getTE(i) && obj->getTE(i)->isSelected()) - { - doSelectionCallbacks(obj->getID(), i); - } - } - } - }); + // fromJson() is performance heavy offload to a thread. + main_queue->postTo( + general_queue, + [sides=object_override.mSides]() // Work done on general queue + { + std::vector<ReturnData> results; + + results.reserve(sides.size()); + // parse json + std::unordered_map<S32, LLSD>::const_iterator iter = sides.begin(); + std::unordered_map<S32, LLSD>::const_iterator end = sides.end(); + while (iter != end) + { + ReturnData result; + + result.mMaterial.applyOverrideLLSD(iter->second); + + result.mSuccess = true; + result.mSide = iter->first; + + results.push_back(result); + iter++; + } + return results; + }, + [object_id=object_override.mObjectId, this](std::vector<ReturnData> results) // Callback to main thread + { + LLViewerObject * obj = gObjectList.findObject(object_id); + + if (results.size() > 0 ) + { + std::unordered_set<S32> side_set; + + for (auto const & result : results) + { + S32 side = result.mSide; + if (result.mSuccess) + { + // copy to heap here because LLTextureEntry is going to take ownership with an LLPointer + LLGLTFMaterial * material = new LLGLTFMaterial(result.mMaterial); + + // flag this side to not be nulled out later + side_set.insert(side); + + if (obj) + { + obj->setTEGLTFMaterialOverride(side, material); + } + } + + // unblock material editor + if (obj && obj->getTE(side) && obj->getTE(side)->isSelected()) + { + doSelectionCallbacks(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 + for (int i = 0; i < obj->getNumTEs(); ++i) + { + if (side_set.find(i) == side_set.end()) + { + obj->setTEGLTFMaterialOverride(i, nullptr); + if (obj->getTE(i) && obj->getTE(i)->isSelected()) + { + doSelectionCallbacks(object_id, i); + } + } + } + } + } + else if (obj) + { // override list was empty or an error occurred, null out all overrides for this object + for (int i = 0; i < obj->getNumTEs(); ++i) + { + obj->setTEGLTFMaterialOverride(i, nullptr); + if (obj->getTE(i) && obj->getTE(i)->isSelected()) + { + doSelectionCallbacks(obj->getID(), i); + } + } + } + }); } +#endif } private: @@ -335,6 +331,70 @@ namespace LLGLTFMaterialOverrideDispatchHandler handle_gltf_override_message; } +void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::string& data_in) +{ + std::istringstream str(data_in); + + LLSD data; + + LLSDSerialize::fromNotation(data, str, data_in.length()); + + const LLHost& host = msg->getSender(); + + LLViewerRegion* region = LLWorld::instance().getRegion(host); + llassert(region); + + if (region) + { + U32 local_id = data.get("id").asInteger(); + LLUUID id; + gObjectList.getUUIDFromLocal(id, local_id, host.getAddress(), host.getPort()); + LLViewerObject* obj = gObjectList.findObject(id); + + // NOTE: obj may be null if the viewer hasn't heard about the object yet, cache update in any case + + if (obj && gShowObjectUpdates) + { // display a cyan blip for override updates when "Show Updates to Objects" enabled + LLColor4 color(0.f, 1.f, 1.f, 1.f); + gPipeline.addDebugBlip(obj->getPositionAgent(), color); + } + + const LLSD& tes = data["te"]; + const LLSD& od = data["od"]; + + if (tes.isArray()) + { + LLGLTFOverrideCacheEntry cache; + cache.mLocalId = local_id; + cache.mObjectId = id; + cache.mRegionHandle = region->getHandle(); + + for (int i = 0; i < tes.size(); ++i) + { + LLGLTFMaterial* mat = new LLGLTFMaterial(); // setTEGLTFMaterialOverride and cache will take ownership + mat->applyOverrideLLSD(od[i]); + + S32 te = tes[i].asInteger(); + + cache.mSides[te] = od[i]; + cache.mGLTFMaterial[te] = mat; + + if (obj) + { + obj->setTEGLTFMaterialOverride(te, mat); + if (obj->getTE(te) && obj->getTE(te)->isSelected()) + { + handle_gltf_override_message.doSelectionCallbacks(id, te); + } + } + } + + region->cacheFullUpdateGLTFOverride(cache); + } + + } +} + void LLGLTFMaterialList::queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFMaterial* override_data) { #if 0 diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index 3669ed955005dc1004273f17579d9f8cb6122354..830c35d1f2843babcb93116c1795f6b6392f7ce6 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -101,6 +101,9 @@ class LLGLTFMaterialList static void loadCacheOverrides(const LLGLTFOverrideCacheEntry& override); + // Apply an override update with the given data + void applyOverrideMessage(LLMessageSystem* msg, const std::string& data); + 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) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 535b3b0047e4ac1445a333ca81e06995a843a797..c5b4bd3ceb4284548013fbb8d17dc70fd7efa412 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2810,6 +2810,7 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFuncFast(_PREHASH_InitiateDownload, process_initiate_download); msg->setHandlerFuncFast(_PREHASH_LandStatReply, LLFloaterTopObjects::handle_land_reply); msg->setHandlerFuncFast(_PREHASH_GenericMessage, process_generic_message); + msg->setHandlerFunc("GenericStreamingMessage", process_generic_streaming_message); msg->setHandlerFuncFast(_PREHASH_LargeGenericMessage, process_large_generic_message); msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message); diff --git a/indra/newview/llviewergenericmessage.cpp b/indra/newview/llviewergenericmessage.cpp index 53f3bf558118cdb74e87e4a30d69d4a649b8e290..f4a47cdbb7ef2698cc874f9ff8a77f2fdb764044 100644 --- a/indra/newview/llviewergenericmessage.cpp +++ b/indra/newview/llviewergenericmessage.cpp @@ -32,9 +32,10 @@ #include "lldispatcher.h" #include "lluuid.h" #include "message.h" +#include "llgenericstreamingmessage.h" #include "llagent.h" - +#include "llgltfmateriallist.h" LLDispatcher gGenericDispatcher; @@ -92,6 +93,21 @@ void process_generic_message(LLMessageSystem* msg, void**) } } +void process_generic_streaming_message(LLMessageSystem* msg, void**) +{ + LLGenericStreamingMessage data; + data.unpack(msg); + switch (data.mMethod) + { + case LLGenericStreamingMessage::METHOD_GLTF_MATERIAL_OVERRIDE: + gGLTFMaterialList.applyOverrideMessage(msg, data.mData); + break; + default: + LL_WARNS_ONCE() << "Received unknown method" << LL_ENDL; + break; + } +} + void process_large_generic_message(LLMessageSystem* msg, void**) { LLUUID agent_id; diff --git a/indra/newview/llviewergenericmessage.h b/indra/newview/llviewergenericmessage.h index 170f38a48552931faed09f1bea03b5e350c3092f..96a73a3d5f0a14fd15e2f633d052fd989dac00ba 100644 --- a/indra/newview/llviewergenericmessage.h +++ b/indra/newview/llviewergenericmessage.h @@ -38,6 +38,7 @@ void send_generic_message(const std::string& method, const LLUUID& invoice = LLUUID::null); void process_generic_message(LLMessageSystem* msg, void**); +void process_generic_streaming_message(LLMessageSystem* msg, void**); void process_large_generic_message(LLMessageSystem* msg, void**); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 1863ae0c2e015e8476548d08dd247ca06893ee2a..ed0734f58fb04d233ee8fea197485135a1ffec53 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -228,7 +228,7 @@ class LLViewerRegionImpl LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //must-be-created visible entries wait for objects creation. LLVOCacheEntry::vocache_entry_priority_list_t mWaitingList; //transient list storing sorted visible entries waiting for object creation. std::set<U32> mNonCacheableCreatedList; //list of local ids of all non-cacheable objects - LLVOCacheEntry::vocache_gltf_overrides_map_t mGLTFOverridesJson; // for materials + LLVOCacheEntry::vocache_gltf_overrides_map_t mGLTFOverridesLLSD; // for materials // time? // LRU info? @@ -833,7 +833,7 @@ void LLViewerRegion::loadObjectCache() { LLVOCache & vocache = LLVOCache::instance(); vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); - vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesJson); + vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD); if (mImpl->mCacheMap.empty()) { @@ -863,7 +863,7 @@ void LLViewerRegion::saveObjectCache() LLVOCache & instance = LLVOCache::instance(); instance.writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled); - instance.writeGenericExtrasToCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesJson, mCacheDirty, removal_enabled); + instance.writeGenericExtrasToCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mCacheDirty, removal_enabled); mCacheDirty = FALSE; } @@ -2898,7 +2898,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data) { U32 local_id = override_data.mLocalId; - mImpl->mGLTFOverridesJson[local_id] = override_data; + mImpl->mGLTFOverridesLLSD[local_id] = override_data; } LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id) @@ -3986,8 +3986,8 @@ std::string LLViewerRegion::getSimHostName() void LLViewerRegion::loadCacheMiscExtras(U32 local_id) { - auto iter = mImpl->mGLTFOverridesJson.find(local_id); - if (iter != mImpl->mGLTFOverridesJson.end()) + auto iter = mImpl->mGLTFOverridesLLSD.find(local_id); + if (iter != mImpl->mGLTFOverridesLLSD.end()) { LLGLTFMaterialList::loadCacheOverrides(iter->second); } @@ -3999,8 +3999,8 @@ void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj) llassert(obj); U32 local_id = obj->getLocalID(); - auto iter = mImpl->mGLTFOverridesJson.find(local_id); - if (iter != mImpl->mGLTFOverridesJson.end()) + auto iter = mImpl->mGLTFOverridesLLSD.find(local_id); + if (iter != mImpl->mGLTFOverridesLLSD.end()) { llassert(iter->second.mGLTFMaterial.size() == iter->second.mSides.size()); diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index e1fd2b206ceabac16e84021d03733ba95a076e4c..094e05974f5db61cfa9981c01e2b22b86dabfd7c 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -85,40 +85,24 @@ bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data) // message should be interpreted thusly: /// sides is a list of face indices - // gltf_json is a list of corresponding json + // gltf_llsd is a list of corresponding GLTF override LLSD // any side not represented in "sides" has no override - if (data.has("sides") && data.has("gltf_json")) + if (data.has("sides") && data.has("gltf_llsd")) { LLSD const& sides = data.get("sides"); - LLSD const& gltf_json = data.get("gltf_json"); + LLSD const& gltf_llsd = data.get("gltf_llsd"); - if (sides.isArray() && gltf_json.isArray() && + if (sides.isArray() && gltf_llsd.isArray() && sides.size() != 0 && - sides.size() == gltf_json.size()) + sides.size() == gltf_llsd.size()) { for (int i = 0; i < sides.size(); ++i) { S32 side_idx = sides[i].asInteger(); - std::string gltf_json_str = gltf_json[i].asString(); - mSides[side_idx] = gltf_json_str; + mSides[side_idx] = gltf_llsd[i]; LLGLTFMaterial* override_mat = new LLGLTFMaterial(); - std::string error, warn; - if (override_mat->fromJSON(gltf_json_str, warn, error)) - { - mGLTFMaterial[side_idx] = override_mat; - } - else - { - LL_WARNS() << "Invalid GLTF string: \n" << gltf_json_str << LL_ENDL; - if (!error.empty()) - { - LL_WARNS() << "Error: " << error << LL_ENDL; - } - if (!warn.empty()) - { - LL_WARNS() << "Warning: " << warn << LL_ENDL; - } - } + override_mat->applyOverrideLLSD(gltf_llsd[i]); + mGLTFMaterial[side_idx] = override_mat; } } else @@ -157,7 +141,7 @@ LLSD LLGLTFOverrideCacheEntry::toLLSD() const // check that mSides and mGLTFMaterial have exactly the same keys present llassert(mGLTFMaterial.count(side.first) == 1); data["sides"].append(LLSD::Integer(side.first)); - data["gltf_json"].append(side.second); + data["gltf_llsd"].append(side.second); } return data; diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index c0f4b3ae6a5d817e0ac07af7ea3c219a9fe72795..888026c4ce3c068a8de1d327fdd217d6fc56ddd3 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -48,7 +48,7 @@ class LLGLTFOverrideCacheEntry LLUUID mObjectId; U32 mLocalId = 0; - std::unordered_map<S32, std::string> mSides; //json per side + std::unordered_map<S32, LLSD> mSides; //override LLSD per side std::unordered_map<S32, LLPointer<LLGLTFMaterial> > mGLTFMaterial; //GLTF material per side U64 mRegionHandle = 0; }; diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 714da02fe6e3940b025b4908dddb9b12f9d70292..7f317dae426dd37fa0c9d6d76e8611a0944319aa 100755 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -5807,6 +5807,25 @@ version 2.0 } } +// GenericStreamingMessage +// Optimized generic message for streaming arbitrary data to viewer +// Avoid payloads over 7KB (8KB ceiling) +// Method -- magic number indicating method to use to decode payload: +// 0x4175 - GLTF material override data +// Payload -- data to be decoded +{ + GenericStreamingMessage High 31 Trusted Unencoded + { + MethodData Single + { Method U16 } + } + + { + DataBlock Single + { Data Variable 2 } + } +} + // LargeGenericMessage // Similar to the above messages, but can handle larger payloads and serialized // LLSD. Uses HTTP transport