diff options
-rw-r--r-- | indra/llcommon/llerror.cpp | 16 | ||||
-rw-r--r-- | indra/llcommon/llerror.h | 11 | ||||
-rw-r--r-- | indra/llinventory/llsettingsbase.cpp | 7 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 10 | ||||
-rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
-rw-r--r-- | indra/newview/gltfscenemanager.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llenvironment.cpp | 149 | ||||
-rw-r--r-- | indra/newview/llface.cpp | 12 | ||||
-rw-r--r-- | indra/newview/llfloatereditextdaycycle.cpp | 19 | ||||
-rw-r--r-- | indra/newview/llfloatereditextdaycycle.h | 1 | ||||
-rw-r--r-- | indra/newview/llfloaterregioninfo.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanelenvironment.cpp | 94 | ||||
-rw-r--r-- | indra/newview/llpanelenvironment.h | 2 | ||||
-rw-r--r-- | indra/newview/llsettingspicker.cpp | 26 | ||||
-rw-r--r-- | indra/newview/llsettingspicker.h | 1 | ||||
-rw-r--r-- | indra/newview/llsettingsvo.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llviewermenu.cpp | 15 | ||||
-rw-r--r-- | indra/newview/llviewershadermgr.cpp | 9 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 4 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 11 |
20 files changed, 239 insertions, 176 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 41c69ba194..ad35bc84f2 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1641,19 +1641,3 @@ namespace LLError sLocalizedOutOfMemoryWarning = message; } } - -void crashdriver(void (*callback)(int*)) -{ - // The LLERROR_CRASH macro used to have inline code of the form: - //int* make_me_crash = NULL; - //*make_me_crash = 0; - - // But compilers are getting smart enough to recognize that, so we must - // assign to an address supplied by a separate source file. We could do - // the assignment here in crashdriver() -- but then BugSplat would group - // all LL_ERRS() crashes as the fault of this one function, instead of - // identifying the specific LL_ERRS() source line. So instead, do the - // assignment in a lambda in the caller's source. We just provide the - // nullptr target. - callback(nullptr); -} diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 6176ce0d1d..8a143ff30a 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -408,9 +408,11 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; #define LL_NEWLINE '\n' // Use this only in LL_ERRS or in a place that LL_ERRS may not be used -#define LLERROR_CRASH \ -{ \ - crashdriver([](int* ptr){ *ptr = 0; exit(*ptr); }); \ +#define LLERROR_CRASH \ +{ \ + int* make_me_crash = (int*)0xDEADBEEFDEADBEEFUL; \ + *make_me_crash = 0; \ + exit(*make_me_crash); \ } #define LL_ENDL \ @@ -512,7 +514,4 @@ LL_DEBUGS("SomeTag") performs the locking and map-searching ONCE, then caches the result in a static variable. */ -// used by LLERROR_CRASH -void crashdriver(void (*)(int*)); - #endif // LL_LLERROR_H diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp index 7b55fbc9e8..4aab3dee3b 100644 --- a/indra/llinventory/llsettingsbase.cpp +++ b/indra/llinventory/llsettingsbase.cpp @@ -355,10 +355,11 @@ LLSD LLSettingsBase::getSettings() const LLSD LLSettingsBase::cloneSettings() const { - U32 flags = getFlags(); - LLSD settings (combineSDMaps(getSettings(), LLSD())); - if (flags) + LLSD settings(combineSDMaps(getSettings(), LLSD())); + if (U32 flags = getFlags()) + { settings[SETTING_FLAGS] = LLSD::Integer(flags); + } return settings; } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 03ac10c00a..68c20048ec 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -70,6 +70,7 @@ static U64 sTextureBytes = 0; void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 intformat, U32 count) { U32 texUnit = gGL.getCurrentTexUnitIndex(); + llassert(texUnit == 0); // allocations should always be done on tex unit 0 U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); U64 size = LLImageGL::dataFormatBytes(intformat, width, height); size *= count; @@ -77,6 +78,8 @@ void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 intformat, U32 llassert(size >= 0); sTexMemMutex.lock(); + + // it is a precondition that no existing allocation exists for this texture llassert(sTextureAllocs.find(texName) == sTextureAllocs.end()); sTextureAllocs[texName] = size; @@ -90,7 +93,7 @@ void LLImageGLMemory::free_tex_image(U32 texName) { sTexMemMutex.lock(); auto iter = sTextureAllocs.find(texName); - if (iter != sTextureAllocs.end()) + if (iter != sTextureAllocs.end()) // sometimes a texName will be "freed" before allocated (e.g. first call to setManualImage for a given texName) { llassert(iter->second <= sTextureBytes); // sTextureBytes MUST NOT go below zero @@ -115,6 +118,7 @@ void LLImageGLMemory::free_tex_images(U32 count, const U32* texNames) void LLImageGLMemory::free_cur_tex_image() { U32 texUnit = gGL.getCurrentTexUnitIndex(); + llassert(texUnit == 0); // frees should always be done on tex unit 0 U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); free_tex_image(texName); } @@ -1240,8 +1244,8 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) if (!sFreeList[idx].empty()) { - glDeleteTextures((GLsizei) sFreeList[idx].size(), sFreeList[idx].data()); free_tex_images((GLsizei) sFreeList[idx].size(), sFreeList[idx].data()); + glDeleteTextures((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); sFreeList[idx].resize(0); } } @@ -2461,7 +2465,7 @@ bool LLImageGL::scaleDown(S32 desired_discard) { // use a PBO to downscale the texture U64 size = getBytes(desired_discard); llassert(size <= 2048 * 2048 * 4); // we shouldn't be using this method to downscale huge textures, but it'll work - gGL.getTexUnit(0)->bind(this); + gGL.getTexUnit(0)->bind(this, false, true); if (sScratchPBO == 0) { diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 356462bdf5..d2c3c96317 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7172,6 +7172,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderCanUseGLTFPBROpaqueShaders</key> + <map> + <key>Comment</key> + <string>Hardware has support for GLTF scene shaders</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderClass1MemoryBandwidth</key> <map> <key>Comment</key> diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 086f41c1cb..e55d630940 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -45,6 +45,7 @@ #include "llfloaterreg.h" #include "llagentbenefits.h" #include "llfilesystem.h" +#include "llviewercontrol.h" #include "boost/json.hpp" #define GLTF_SIM_SUPPORT 1 @@ -618,6 +619,13 @@ void GLTFSceneManager::render(Asset& asset, U8 variant) { LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF; + static LLCachedControl<bool> can_use_shaders(gSavedSettings, "RenderCanUseGLTFPBROpaqueShaders", true); + if (!can_use_shaders) + { + // user should already have been notified of unsupported hardware + return; + } + for (U32 ds = 0; ds < 2; ++ds) { RenderData& rd = asset.mRenderData[ds]; diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 6e31760e9e..0b4630dfc3 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1051,8 +1051,8 @@ bool LLEnvironment::isExtendedEnvironmentEnabled() const bool LLEnvironment::isInventoryEnabled() const { - return (!gAgent.getRegionCapability("UpdateSettingsAgentInventory").empty() && - !gAgent.getRegionCapability("UpdateSettingsTaskInventory").empty()); + return !gAgent.getRegionCapability("UpdateSettingsAgentInventory").empty() && + !gAgent.getRegionCapability("UpdateSettingsTaskInventory").empty(); } void LLEnvironment::onRegionChange() @@ -1079,9 +1079,8 @@ void LLEnvironment::onRegionChange() void LLEnvironment::onParcelChange() { S32 parcel_id(INVALID_PARCEL_ID); - LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel(); - if (parcel) + if (LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel()) { parcel_id = parcel->getLocalID(); } @@ -1092,7 +1091,8 @@ void LLEnvironment::onParcelChange() //------------------------------------------------------------------------- F32 LLEnvironment::getCamHeight() const { - return (mCurrentEnvironment->getSky()->getDomeOffset() * mCurrentEnvironment->getSky()->getDomeRadius()); + auto sky = mCurrentEnvironment ? mCurrentEnvironment->getSky() : nullptr; + return sky ? sky->getDomeOffset() * sky->getDomeRadius() : 0; } F32 LLEnvironment::getWaterHeight() const @@ -1103,16 +1103,14 @@ F32 LLEnvironment::getWaterHeight() const bool LLEnvironment::getIsSunUp() const { - if (!mCurrentEnvironment || !mCurrentEnvironment->getSky()) - return false; - return mCurrentEnvironment->getSky()->getIsSunUp(); + auto sky = mCurrentEnvironment ? mCurrentEnvironment->getSky() : nullptr; + return sky && sky->getIsSunUp(); } bool LLEnvironment::getIsMoonUp() const { - if (!mCurrentEnvironment || !mCurrentEnvironment->getSky()) - return false; - return mCurrentEnvironment->getSky()->getIsMoonUp(); + auto sky = mCurrentEnvironment ? mCurrentEnvironment->getSky() : nullptr; + return sky && sky->getIsMoonUp(); } //------------------------------------------------------------------------- @@ -1139,13 +1137,19 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getEnvironmentInstance(LLEnviro if (create) { if (environment) + { environment = environment->clone(); + } else { if (env == ENV_PUSH) + { environment = std::make_shared<DayInjection>(env); + } else + { environment = std::make_shared<DayInstance>(env); + } } mEnvironments[env] = environment; } @@ -1172,7 +1176,9 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe environment->animate(); if (!mSignalEnvChanged.empty()) + { mSignalEnvChanged(env, env_version); + } } void LLEnvironment::setCurrentEnvironmentSelection(LLEnvironment::EnvSelection_t env) @@ -1282,7 +1288,9 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm } if (!mSignalEnvChanged.empty()) + { mSignalEnvChanged(env, env_version); + } } void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version) @@ -1375,7 +1383,9 @@ void LLEnvironment::clearEnvironment(LLEnvironment::EnvSelection_t env) mEnvironments[env].reset(); if (!mSignalEnvChanged.empty()) + { mSignalEnvChanged(env, VERSION_CLEANUP); + } } void LLEnvironment::logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version) @@ -1415,10 +1425,10 @@ LLSettingsDay::ptr_t LLEnvironment::getEnvironmentDay(LLEnvironment::EnvSelectio return LLSettingsDay::ptr_t(); } - DayInstance::ptr_t environment = getEnvironmentInstance(env); - - if (environment) + if (DayInstance::ptr_t environment = getEnvironmentInstance(env)) + { return environment->getDayCycle(); + } return LLSettingsDay::ptr_t(); } @@ -1431,10 +1441,10 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayLength(EnvSelection_t env return LLSettingsDay::Seconds(0); } - DayInstance::ptr_t environment = getEnvironmentInstance(env); - - if (environment) + if (DayInstance::ptr_t environment = getEnvironmentInstance(env)) + { return environment->getDayLength(); + } return LLSettingsDay::Seconds(0); } @@ -1447,9 +1457,10 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayOffset(EnvSelection_t env return LLSettingsDay::Seconds(0); } - DayInstance::ptr_t environment = getEnvironmentInstance(env); - if (environment) + if (DayInstance::ptr_t environment = getEnvironmentInstance(env)) + { return environment->getDayOffset(); + } return LLSettingsDay::Seconds(0); } @@ -1479,7 +1490,9 @@ LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironme } if (!fixed.first || !fixed.second) + { LL_WARNS("ENVIRONMENT") << "Can not construct complete fixed environment. Missing Sky and/or Water." << LL_ENDL; + } return fixed; } @@ -1490,10 +1503,10 @@ LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironme return fixedEnvironment_t(); } - DayInstance::ptr_t environment = getEnvironmentInstance(env); - - if (environment) + if (DayInstance::ptr_t environment = getEnvironmentInstance(env)) + { return fixedEnvironment_t(environment->getSky(), environment->getWater()); + } return fixedEnvironment_t(); } @@ -1503,7 +1516,9 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getSelectedEnvironmentInstance( for (S32 idx = mSelectedEnvironment; idx < ENV_DEFAULT; ++idx) { if (mEnvironments[idx]) + { return mEnvironments[idx]; + } } return mEnvironments[ENV_DEFAULT]; @@ -1514,7 +1529,9 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getSharedEnvironmentInstance() for (S32 idx = ENV_PARCEL; idx < ENV_DEFAULT; ++idx) { if (mEnvironments[idx]) + { return mEnvironments[idx]; + } } return mEnvironments[ENV_DEFAULT]; @@ -1673,21 +1690,19 @@ void LLEnvironment::update(const LLViewerCamera * cam) updateSettingsUniforms(); + LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; + end_shaders = LLViewerShaderMgr::instance()->endShaders(); + for (shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) { - LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; - end_shaders = LLViewerShaderMgr::instance()->endShaders(); - for (shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + shaders_iter->mUniformsDirty = true; + if (shaders_iter->mRiggedVariant) { - shaders_iter->mUniformsDirty = true; - if (shaders_iter->mRiggedVariant) - { - shaders_iter->mRiggedVariant->mUniformsDirty = true; - } + shaders_iter->mRiggedVariant->mUniformsDirty = true; + } - for (auto& variant : shaders_iter->mGLTFVariants) - { - variant.mUniformsDirty = true; - } + for (auto& variant : shaders_iter->mGLTFVariants) + { + variant.mUniformsDirty = true; } } } @@ -1971,7 +1986,6 @@ void LLEnvironment::updateRegion(const LLSettingsWater::ptr_t &pwater, S32 day_l updateParcel(INVALID_PARCEL_ID, pwater, day_length, day_offset, altitudes, cb); } - void LLEnvironment::resetRegion(environment_apply_fn cb) { resetParcel(INVALID_PARCEL_ID, cb); @@ -1996,7 +2010,10 @@ void LLEnvironment::requestParcel(S32 parcel_id, environment_apply_fn cb) LLEnvironmentRequest::initiate(cb); } else if (cb) + { cb(parcel_id, EnvironmentInfo::ptr_t()); + } + return; } @@ -2006,16 +2023,14 @@ void LLEnvironment::requestParcel(S32 parcel_id, environment_apply_fn cb) cb = [this, transition](S32 pid, EnvironmentInfo::ptr_t envinfo) { recordEnvironment(pid, envinfo, transition); }; } - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroRequestEnvironment", + LLCoros::instance().launch("LLEnvironment::coroRequestEnvironment", [this, parcel_id, cb]() { coroRequestEnvironment(parcel_id, cb); }); } void LLEnvironment::updateParcel(S32 parcel_id, const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb) { UpdateInfo::ptr_t updates(std::make_shared<UpdateInfo>(asset_id, display_name, day_length, day_offset, altitudes, flags)); - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", + LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", [this, parcel_id, track_num, updates, cb]() { coroUpdateEnvironment(parcel_id, track_num, updates, cb); }); } @@ -2031,7 +2046,9 @@ void LLEnvironment::onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::p LLSettingsDay::ptr_t pday; if (settings->getSettingsType() == "daycycle") + { pday = std::static_pointer_cast<LLSettingsDay>(settings); + } else { pday = createDayCycleFromEnvironment( (parcel_id == INVALID_PARCEL_ID) ? ENV_REGION : ENV_PARCEL, settings); @@ -2065,8 +2082,7 @@ void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday { UpdateInfo::ptr_t updates(std::make_shared<UpdateInfo>(pday, day_length, day_offset, altitudes)); - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", + LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment", [this, parcel_id, track_num, updates, cb]() { coroUpdateEnvironment(parcel_id, track_num, updates, cb); }); } @@ -2075,12 +2091,9 @@ void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday updateParcel(parcel_id, pday, NO_TRACK, day_length, day_offset, altitudes, cb); } - - void LLEnvironment::resetParcel(S32 parcel_id, environment_apply_fn cb) { - std::string coroname = - LLCoros::instance().launch("LLEnvironment::coroResetEnvironment", + LLCoros::instance().launch("LLEnvironment::coroResetEnvironment", [this, parcel_id, cb]() { coroResetEnvironment(parcel_id, NO_TRACK, cb); }); } @@ -2130,7 +2143,6 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ }); } } - } void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInfo::ptr_t updates, environment_apply_fn apply) @@ -2150,9 +2162,14 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf if (track_no == NO_TRACK) { // day length and offset are only applicable if we are addressing the entire day cycle. if (updates->mDayLength > 0) + { body[KEY_ENVIRONMENT][KEY_DAYLENGTH] = updates->mDayLength; + } + if (updates->mDayOffset > 0) + { body[KEY_ENVIRONMENT][KEY_DAYOFFSET] = updates->mDayOffset; + } if ((parcel_id == INVALID_PARCEL_ID) && (updates->mAltitudes.size() == 3)) { // only test for altitude changes if we are changing the region. @@ -2165,12 +2182,16 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf } if (updates->mDayp) + { body[KEY_ENVIRONMENT][KEY_DAYCYCLE] = updates->mDayp->getSettings(); + } else if (!updates->mSettingsAsset.isNull()) { body[KEY_ENVIRONMENT][KEY_DAYASSET] = updates->mSettingsAsset; if (!updates->mDayName.empty()) + { body[KEY_ENVIRONMENT][KEY_DAYNAME] = updates->mDayName; + } } body[KEY_ENVIRONMENT][KEY_FLAGS] = LLSD::Integer(updates->mFlags); @@ -2188,22 +2209,27 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf if (track_no != NO_TRACK) query << "&"; } + if (track_no != NO_TRACK) { query << "trackno=" << track_no; } + url += query.str(); } LLSD result = httpAdapter->putAndSuspend(httpRequest, url, body); // results that come back may contain the new settings + if (LLApp::isExiting()) + return; + LLSD notify; LLSD httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - if ((!status) || !result["success"].asBoolean()) + if (!status || !result["success"].asBoolean()) { LL_WARNS("ENVIRONMENT") << "Couldn't update Windlight settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; @@ -2218,10 +2244,6 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf notify["FAIL_REASON"] = reason; } } - else if (LLApp::isExiting()) - { - return; - } else { LLSD environment = result[KEY_ENVIRONMENT]; @@ -2272,34 +2294,26 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url); // results that come back may contain the new settings + if (LLApp::isExiting()) + return; + LLSD notify; LLSD httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - if ((!status) || !result["success"].asBoolean()) + if (!status || !result["success"].asBoolean()) { LL_WARNS("ENVIRONMENT") << "Couldn't reset Windlight settings in " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; notify = LLSD::emptyMap(); std::string reason = result["message"].asString(); - if (reason.empty()) - { - notify["FAIL_REASON"] = status.toString(); - } - else - { - notify["FAIL_REASON"] = reason; - } - } - else if (LLApp::isExiting()) - { - return; + notify["FAIL_REASON"] = reason.empty() ? status.toString() : reason; } - else + else if (apply) { - LLSD environment = result[KEY_ENVIRONMENT]; - if (environment.isDefined() && apply) + LLSD environment = result[KEY_ENVIRONMENT]; + if (environment.isDefined()) { EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment); apply(parcel_id, envinfo); @@ -2311,7 +2325,6 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen LLNotificationsUtil::add("WLRegionApplyFail", notify); //LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); } - } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index df08dcf503..ccfef09b09 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -573,12 +573,14 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) if (LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial()) { vertex_buffer = mVertexBufferGLTF.get(); - vertex_buffer->unmapBuffer(); } } // Draw the selection marker using the correctly chosen vertex buffer - vertex_buffer->setBuffer(); - vertex_buffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); + if (vertex_buffer) + { + vertex_buffer->setBuffer(); + vertex_buffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); + } } gGL.popMatrix(); @@ -1217,7 +1219,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, mVertexBufferGLTF = new LLVertexBuffer(mVertexBuffer->getTypeMask()); } - // Clone the existing vertex buffer into the temporary one + // Clone the existing vertex buffer into the temporary one + // TODO: factor out the need for mVertexBufferGLTF and make selection highlight shader work with the existing vertex buffer mVertexBuffer->clone(*mVertexBufferGLTF); // Recursive call the same function with the argument rebuild_for_gltf set to true @@ -1225,6 +1228,7 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, mVertexBufferGLTF.swap(mVertexBufferGLTF, mVertexBuffer); getGeometryVolume(volume, face_index, mat_vert_in, mat_norm_in, index_offset, force_rebuild, no_debug_assert, true); mVertexBufferGLTF.swap(mVertexBufferGLTF, mVertexBuffer); + mVertexBufferGLTF->unmapBuffer(); } else if (!tep->isSelected() && mVertexBufferGLTF.notNull()) { diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index d6e7cd97f3..fd58cd8aaf 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -132,7 +132,6 @@ namespace { //========================================================================= const std::string LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT("edit_context"); const std::string LLFloaterEditExtDayCycle::KEY_DAY_LENGTH("day_length"); -const std::string LLFloaterEditExtDayCycle::KEY_CANMOD("canmod"); const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_INVENTORY("inventory"); const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_PARCEL("parcel"); @@ -286,11 +285,6 @@ void LLFloaterEditExtDayCycle::onOpen(const LLSD& key) mEditContext = CONTEXT_REGION; } - if (key.has(KEY_CANMOD)) - { - mCanMod = key[KEY_CANMOD].asBoolean(); - } - if (mEditContext == CONTEXT_UNKNOWN) { LL_WARNS("ENVDAYEDIT") << "Unknown editing context!" << LL_ENDL; @@ -298,6 +292,7 @@ void LLFloaterEditExtDayCycle::onOpen(const LLSD& key) if (key.has(KEY_INVENTORY_ID)) { + // mCanMod is initialized inside this call loadInventoryItem(key[KEY_INVENTORY_ID].asUUID()); } else @@ -519,14 +514,20 @@ void LLFloaterEditExtDayCycle::setEditDefaultDayCycle() std::string LLFloaterEditExtDayCycle::getEditName() const { if (mEditDay) + { return mEditDay->getName(); + } + return "new"; } void LLFloaterEditExtDayCycle::setEditName(const std::string &name) { if (mEditDay) + { mEditDay->setName(name); + } + getChild<LLLineEditor>(TXT_DAY_NAME)->setText(name); } @@ -548,13 +549,13 @@ bool LLFloaterEditExtDayCycle::handleKeyUp(KEY key, MASK mask, bool called_from_ keymap_t::iterator it = mSliderKeyMap.find(curslider); if (it != mSliderKeyMap.end()) { - if (mEditDay->moveTrackKeyframe(mCurrentTrack, (*it).second.mFrame, sliderpos)) + if (mEditDay->moveTrackKeyframe(mCurrentTrack, it->second.mFrame, sliderpos)) { - (*it).second.mFrame = sliderpos; + it->second.mFrame = sliderpos; } else { - mFramesSlider->setCurSliderValue((*it).second.mFrame); + mFramesSlider->setCurSliderValue(it->second.mFrame); } } else diff --git a/indra/newview/llfloatereditextdaycycle.h b/indra/newview/llfloatereditextdaycycle.h index 926a24f8a4..992b532967 100644 --- a/indra/newview/llfloatereditextdaycycle.h +++ b/indra/newview/llfloatereditextdaycycle.h @@ -60,7 +60,6 @@ class LLFloaterEditExtDayCycle : public LLFloaterEditEnvironmentBase public: static const std::string KEY_EDIT_CONTEXT; static const std::string KEY_DAY_LENGTH; - static const std::string KEY_CANMOD; static const std::string VALUE_CONTEXT_INVENTORY; static const std::string VALUE_CONTEXT_PARCEL; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 7869abf66d..66e88e8841 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -4291,7 +4291,7 @@ void LLPanelRegionEnvironment::refreshFromSource() } LLEnvironment::instance().requestRegion( - [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); }); + [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { onEnvironmentReceived(that_h, parcel_id, envifo); }); setControlsEnabled(false); } diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp index c1d8ce50ff..423ca376d1 100644 --- a/indra/newview/llpanelenvironment.cpp +++ b/indra/newview/llpanelenvironment.cpp @@ -392,8 +392,10 @@ std::string LLPanelEnvironmentInfo::getNameForTrackIndex(U32 index) if (invname.empty()) { invname = getNameForTrackIndex(index - 1); - if (invname[0] != '(') + if (!invname.empty() && invname.front() != '(') + { invname = "(" + invname + ")"; + } } return invname; @@ -764,7 +766,7 @@ void LLPanelEnvironmentInfo::commitDayLenOffsetChanges(bool need_callback) (S32)mCurrentEnvironment->mDayLength.value(), (S32)mCurrentEnvironment->mDayOffset.value(), LLEnvironment::altitudes_vect_t(), - [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); }); + [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { onEnvironmentReceived(that_h, parcel_id, envifo); }); } else { @@ -852,7 +854,7 @@ void LLPanelEnvironmentInfo::onBtnDefault() if (opt == 0) { LLEnvironment::instance().resetParcel(parcel_id, - [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); }); + [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { onEnvironmentReceived(that_h, parcel_id, envifo); }); } }); } @@ -864,8 +866,7 @@ void LLPanelEnvironmentInfo::onBtnEdit() LLFloaterEditExtDayCycle *dayeditor = getEditFloater(); LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, isRegion() ? LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION : LLFloaterEditExtDayCycle::VALUE_CONTEXT_PARCEL) - (LLFloaterEditExtDayCycle::KEY_DAY_LENGTH, mCurrentEnvironment ? (S32)(mCurrentEnvironment->mDayLength.value()) : FOURHOURS) - (LLFloaterEditExtDayCycle::KEY_CANMOD, LLSD::Boolean(true))); + (LLFloaterEditExtDayCycle::KEY_DAY_LENGTH, mCurrentEnvironment ? (S32)(mCurrentEnvironment->mDayLength.value()) : FOURHOURS)); dayeditor->openFloater(params); @@ -882,13 +883,13 @@ void LLPanelEnvironmentInfo::onBtnEdit() void LLPanelEnvironmentInfo::onBtnSelect() { - LLFloaterSettingsPicker *picker = getSettingsPicker(); - if (picker) + if (LLFloaterSettingsPicker* picker = getSettingsPicker()) { LLUUID item_id; if (mCurrentEnvironment && mCurrentEnvironment->mDayCycle) { - item_id = LLFloaterSettingsPicker::findItemID(mCurrentEnvironment->mDayCycle->getAssetId(), false, false); + LLUUID asset_id = mCurrentEnvironment->mDayCycle->getAssetId(); + item_id = LLFloaterSettingsPicker::findItemID(asset_id, false); } picker->setSettingsFilter(LLSettingsType::ST_NONE); picker->setSettingsItemId(item_id); @@ -919,7 +920,7 @@ void LLPanelEnvironmentInfo::onBtnRstAltitudes() mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayLength.value() : -1, mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayOffset.value() : -1, alts, - [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); }); + [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { onEnvironmentReceived(that_h, parcel_id, envifo); }); } } @@ -985,32 +986,41 @@ void LLPanelEnvironmentInfo::onPickerCommitted(LLUUID item_id, std::string sourc void LLPanelEnvironmentInfo::onPickerCommitted(LLUUID item_id, S32 track_num) { - LLInventoryItem *itemp = gInventory.getItem(item_id); - if (itemp) + if (LLInventoryItem* itemp = gInventory.getItem(item_id)) { + LL_INFOS("ENVPANEL") << "item '" << item_id << "' : '" << itemp->getDescription() << "'" << LL_ENDL; + LLHandle<LLPanel> that_h = getHandle(); clearDirtyFlag(DIRTY_FLAG_DAYLENGTH); clearDirtyFlag(DIRTY_FLAG_DAYOFFSET); U32 flags(0); - if (itemp) + if (!itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) { - if (!itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) - flags |= LLSettingsBase::FLAG_NOMOD; - if (!itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) - flags |= LLSettingsBase::FLAG_NOTRANS; + flags |= LLSettingsBase::FLAG_NOMOD; } - LLEnvironment::instance().updateParcel(getParcelId(), - itemp->getAssetUUID(), - itemp->getName(), - track_num, - mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayLength.value() : -1, - mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayOffset.value() : -1, - flags, - LLEnvironment::altitudes_vect_t(), - [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); }); + if (!itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + flags |= LLSettingsBase::FLAG_NOTRANS; + } + + LLEnvironment::instance().updateParcel + ( + getParcelId(), + itemp->getAssetUUID(), + itemp->getName(), + track_num, + mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayLength.value() : -1, + mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayOffset.value() : -1, + flags, + LLEnvironment::altitudes_vect_t(), + [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) + { + onEnvironmentReceived(that_h, parcel_id, envifo); + } + ); } } @@ -1018,17 +1028,20 @@ void LLPanelEnvironmentInfo::onEditCommitted(LLSettingsDay::ptr_t newday) { LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT); LLEnvironment::instance().updateEnvironment(); + if (!newday) { LL_WARNS("ENVPANEL") << "Editor committed an empty day. Do nothing." << LL_ENDL; return; } + if (!mCurrentEnvironment) { // Attempting to save mid update? LL_WARNS("ENVPANEL") << "Failed to apply changes from editor! Dirty state: " << mDirtyFlag << " env version: " << mCurEnvVersion << LL_ENDL; return; } + size_t newhash(newday->getHash()); size_t oldhash((mCurrentEnvironment->mDayCycle) ? mCurrentEnvironment->mDayCycle->getHash() : 0); @@ -1043,7 +1056,7 @@ void LLPanelEnvironmentInfo::onEditCommitted(LLSettingsDay::ptr_t newday) mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayLength.value() : -1, mCurrentEnvironment ? (S32)mCurrentEnvironment->mDayOffset.value() : -1, LLEnvironment::altitudes_vect_t(), - [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); }); + [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { onEnvironmentReceived(that_h, parcel_id, envifo); }); } } @@ -1080,8 +1093,7 @@ void LLPanelEnvironmentInfo::onEnvironmentChanged(LLEnvironment::EnvSelection_t else if ((env == LLEnvironment::ENV_PARCEL) && (getParcelId() == LLViewerParcelMgr::instance().getAgentParcelId())) { - LLParcel *parcel = getParcel(); - if (parcel) + if (LLParcel* parcel = getParcel()) { // first for parcel own settings, second is for case when parcel uses region settings if (mCurEnvVersion < new_version @@ -1143,17 +1155,21 @@ void LLPanelEnvironmentInfo::onEnvironmentReceived(S32 parcel_id, LLEnvironment: // todo: we have envifo and parcel env version, should we just setEnvironment() and parcel's property to prevent dupplicate requests? } -void LLPanelEnvironmentInfo::_onEnvironmentReceived(LLHandle<LLPanel> that_h, S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) +// static +void LLPanelEnvironmentInfo::onEnvironmentReceived(LLHandle<LLPanel> that_h, S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { - LLPanelEnvironmentInfo *that = (LLPanelEnvironmentInfo *)that_h.get(); - if (!that) - return; - that->onEnvironmentReceived(parcel_id, envifo); + if (LLPanelEnvironmentInfo* that = (LLPanelEnvironmentInfo*)that_h.get()) + { + that->onEnvironmentReceived(parcel_id, envifo); + } } LLSettingsDropTarget::LLSettingsDropTarget(const LLSettingsDropTarget::Params& p) - : LLView(p), mEnvironmentInfoPanel(NULL), mDndEnabled(false) -{} + : LLView(p) + , mEnvironmentInfoPanel(NULL) + , mDndEnabled(false) +{ +} bool LLSettingsDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, @@ -1170,11 +1186,9 @@ bool LLSettingsDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, switch (cargo_type) { case DAD_SETTINGS: - { - LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; - if (inv_item && mEnvironmentInfoPanel) + if (cargo_data && mEnvironmentInfoPanel) { - LLUUID item_id = inv_item->getUUID(); + LLUUID item_id = ((LLViewerInventoryItem*)cargo_data)->getUUID(); if (gInventory.getItem(item_id)) { *accept = ACCEPT_YES_COPY_SINGLE; @@ -1190,11 +1204,11 @@ bool LLSettingsDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, *accept = ACCEPT_NO; } break; - } default: *accept = ACCEPT_NO; break; } } + return handled; } diff --git a/indra/newview/llpanelenvironment.h b/indra/newview/llpanelenvironment.h index c9b95cc348..e9a42c8962 100644 --- a/indra/newview/llpanelenvironment.h +++ b/indra/newview/llpanelenvironment.h @@ -137,7 +137,7 @@ protected: void onPickerAssetDownloaded(LLSettingsBase::ptr_t settings); void onEnvironmentReceived(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo); - static void _onEnvironmentReceived(LLHandle<LLPanel> that_h, S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo); + static void onEnvironmentReceived(LLHandle<LLPanel> that_h, S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo); virtual bool isLargeEnough() = 0; virtual void refreshFromSource() = 0; diff --git a/indra/newview/llsettingspicker.cpp b/indra/newview/llsettingspicker.cpp index 85f0678c4c..24cf543864 100644 --- a/indra/newview/llsettingspicker.cpp +++ b/indra/newview/llsettingspicker.cpp @@ -349,6 +349,11 @@ void LLFloaterSettingsPicker::onButtonCancel() void LLFloaterSettingsPicker::onButtonSelect() { + applySelectedItemAndCloseFloater(); +} + +void LLFloaterSettingsPicker::applySelectedItemAndCloseFloater() +{ if (mCommitSignal) { LLSD res; @@ -378,14 +383,7 @@ bool LLFloaterSettingsPicker::handleDoubleClick(S32 x, S32 y, MASK mask) if (target_rect.pointInRect(x, y)) { // Quick-apply - if (mCommitSignal) - { - LLSD res; - res["ItemId"] = mSettingItemID; - res["Track"] = getChild<LLComboBox>(CMB_TRACK_SELECTION)->getValue(); - (*mCommitSignal)(this, res); - } - closeFloater(); + applySelectedItemAndCloseFloater(); // hit inside panel on selected item, double click should do nothing result = true; } @@ -408,14 +406,7 @@ bool LLFloaterSettingsPicker::handleKeyHere(KEY key, MASK mask) if (item_viewp && item_viewp->getIsCurSelection() && item_viewp->getVisible()) { // Quick-apply - if (mCommitSignal) - { - LLSD res; - res["ItemId"] = mSettingItemID; - res["Track"] = getChild<LLComboBox>(CMB_TRACK_SELECTION)->getValue(); - (*mCommitSignal)(this, res); - } - closeFloater(); + applySelectedItemAndCloseFloater(); return true; } } @@ -466,6 +457,9 @@ void LLFloaterSettingsPicker::setSettingsItemId(const LLUUID &settings_id, bool LLInventoryItem* LLFloaterSettingsPicker::findItem(const LLUUID& asset_id, bool copyable_only, bool ignore_library) { + if (asset_id.isNull()) + return nullptr; + LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLAssetIDMatches asset_id_matches(asset_id); diff --git a/indra/newview/llsettingspicker.h b/indra/newview/llsettingspicker.h index 29827dfb94..e5b1e15899 100644 --- a/indra/newview/llsettingspicker.h +++ b/indra/newview/llsettingspicker.h @@ -111,6 +111,7 @@ private: bool handleKeyHere(KEY key, MASK mask) override; void onFocusLost() override; + void applySelectedItemAndCloseFloater(); LLHandle<LLView> mOwnerHandle; LLUUID mSettingItemID; diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 5152570786..e05b6f3736 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -1387,9 +1387,12 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildClone() const LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings); - U32 flags = getFlags(); - if (flags) + dayp->setName(getName()); + + if (U32 flags = getFlags()) + { dayp->setFlags(flags); + } dayp->initialize(); return dayp; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 97d5781566..e1664752e7 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3414,7 +3414,9 @@ bool enable_os_exception() bool enable_gltf() { static LLCachedControl<bool> enablegltf(gSavedSettings, "GLTFEnabled", false); - return enablegltf; + static LLCachedControl<bool> can_use(gSavedSettings, "RenderCanUseGLTFPBROpaqueShaders", true); + + return enablegltf && can_use; } bool enable_gltf_save_as() @@ -8207,7 +8209,16 @@ class LLAdvancedClickGLTFOpen: public view_listener_t { bool handleEvent(const LLSD& userdata) { - LL::GLTFSceneManager::instance().load(); + static LLCachedControl<bool> can_use_shaders(gSavedSettings, "RenderCanUseGLTFPBROpaqueShaders", true); + if (can_use_shaders) + { + LL::GLTFSceneManager::instance().load(); + } + else + { + LLNotificationsUtil::add("NoSupportGLTFShader"); + } + return true; } }; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 873a59e6f6..c422e1d3ae 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1353,7 +1353,14 @@ bool LLViewerShaderMgr::loadShadersDeferred() success = make_gltf_variants(gGLTFPBRMetallicRoughnessProgram, use_sun_shadow); - llassert(success); + //llassert(success); + if (!success) + { + LL_WARNS() << "Failed to create GLTF PBR Metallic Roughness Shader, disabling!" << LL_ENDL; + gSavedSettings.setBOOL("RenderCanUseGLTFPBROpaqueShaders", false); + // continue as if this shader never happened + success = true; + } } if (success) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b7738b9135..7da4358f86 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5766,9 +5766,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) continue; } - if (facep->hasGeometry() && - (rigged || // <-- HACK FIXME -- getPixelArea might be incorrect for rigged objects - facep->getPixelArea() > FORCE_CULL_AREA)) // <-- don't render tiny faces + if (facep->hasGeometry()) { cur_total += facep->getGeomCount(); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4a9dd62666..848d9aca7c 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -12557,4 +12557,15 @@ are wearing now. yestext="OK"/> </notification> + <notification + icon="alertmodal.tga" + name="NoSupportGLTFShader" + type="notify"> + GLTF scenes are not yet supported on your graphics hardware. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + </notifications> |