Merge pull request #3634 from secondlife/release/2024.12-ForeverFPS
Update develop with ForeverFPSmaster
commit
5d78ff48cb
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
needs: setup
|
||||
strategy:
|
||||
matrix:
|
||||
runner: [windows-large, macos-12-large]
|
||||
runner: [windows-large, macos-15-xlarge]
|
||||
configuration: ${{ fromJSON(needs.setup.outputs.configurations) }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
outputs:
|
||||
|
|
@ -64,7 +64,7 @@ jobs:
|
|||
# autobuild-package.xml.
|
||||
AUTOBUILD_VCS_INFO: "true"
|
||||
AUTOBUILD_VSVER: "170"
|
||||
DEVELOPER_DIR: "/Applications/Xcode_14.0.1.app/Contents/Developer"
|
||||
DEVELOPER_DIR: "/Applications/Xcode_16.1.app/Contents/Developer"
|
||||
# Ensure that Linden viewer builds engage Bugsplat.
|
||||
BUGSPLAT_DB: ${{ needs.setup.outputs.bugsplat_db }}
|
||||
build_coverity: false
|
||||
|
|
|
|||
|
|
@ -37,7 +37,12 @@ jobs:
|
|||
- name: Update Tag
|
||||
uses: actions/github-script@v7.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# use a real access token instead of GITHUB_TOKEN default.
|
||||
# required so that the results of this tag creation can trigger the build workflow
|
||||
# https://stackoverflow.com/a/71372524
|
||||
# https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
|
||||
# this token will need to be renewed anually in January
|
||||
github-token: ${{ secrets.LL_TAG_RELEASE_TOKEN }}
|
||||
script: |
|
||||
github.rest.git.createRef({
|
||||
owner: context.repo.owner,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ else()
|
|||
set( USE_AUTOBUILD_3P ON )
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(Variables)
|
||||
include(BuildVersion)
|
||||
|
||||
|
|
|
|||
|
|
@ -300,7 +300,8 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::strin
|
|||
|
||||
LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) const
|
||||
{
|
||||
return getTexture(index)->mWearableType;
|
||||
auto* tex = getTexture(index);
|
||||
return tex ? tex->mWearableType : LLWearableType::WT_INVALID;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -652,7 +652,7 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS() << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL;
|
||||
LL_WARNS() << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -665,7 +665,7 @@ F32 LLWearable::getVisualParamWeight(S32 param_index) const
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL;
|
||||
LL_WARNS() << "LLWearable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL;
|
||||
}
|
||||
return (F32)-1.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,11 @@ public:
|
|||
}
|
||||
|
||||
// shadow base-class string() method with UTF-8 aware method
|
||||
std::string string() const { return super::u8string(); }
|
||||
std::string string() const
|
||||
{
|
||||
auto u8 = super::u8string();
|
||||
return std::string(u8.begin(), u8.end());
|
||||
}
|
||||
// On Posix systems, where value_type is already char, this operator
|
||||
// std::string() method shadows the base class operator string_type()
|
||||
// method. But on Windows, where value_type is wchar_t, the base class
|
||||
|
|
|
|||
|
|
@ -1604,11 +1604,11 @@ namespace LLError
|
|||
std::string LLUserWarningMsg::sLocalizedOutOfMemoryWarning;
|
||||
LLUserWarningMsg::Handler LLUserWarningMsg::sHandler;
|
||||
|
||||
void LLUserWarningMsg::show(const std::string& message)
|
||||
void LLUserWarningMsg::show(const std::string& message, S32 error_code)
|
||||
{
|
||||
if (sHandler)
|
||||
{
|
||||
sHandler(std::string(), message);
|
||||
sHandler(std::string(), message, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1616,7 +1616,7 @@ namespace LLError
|
|||
{
|
||||
if (sHandler && !sLocalizedOutOfMemoryTitle.empty())
|
||||
{
|
||||
sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning);
|
||||
sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning, ERROR_BAD_ALLOC);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1627,7 +1627,7 @@ namespace LLError
|
|||
"Second Life viewer couldn't access some of the files it needs and will be closed."
|
||||
"\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and "
|
||||
"contact https://support.secondlife.com if issue persists after reinstall.";
|
||||
sHandler("Missing Files", error_string);
|
||||
sHandler("Missing Files", error_string, ERROR_MISSING_FILES);
|
||||
}
|
||||
|
||||
void LLUserWarningMsg::setHandler(const LLUserWarningMsg::Handler &handler)
|
||||
|
|
|
|||
|
|
@ -308,7 +308,16 @@ namespace LLError
|
|||
class LLUserWarningMsg
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(const std::string&, const std::string&)> Handler;
|
||||
// error codes, tranlates to last_exec states like LAST_EXEC_OTHER_CRASH
|
||||
typedef enum
|
||||
{
|
||||
ERROR_OTHER = 0,
|
||||
ERROR_BAD_ALLOC = 1,
|
||||
ERROR_MISSING_FILES = 2,
|
||||
} eLastExecEvent;
|
||||
|
||||
// tittle, message and error code to include in error marker file
|
||||
typedef std::function<void(const std::string&, const std::string&, S32 error_code)> Handler;
|
||||
static void setHandler(const Handler&);
|
||||
static void setOutOfMemoryStrings(const std::string& title, const std::string& message);
|
||||
|
||||
|
|
@ -316,7 +325,7 @@ namespace LLError
|
|||
static void showOutOfMemory();
|
||||
static void showMissingFiles();
|
||||
// Genering error
|
||||
static void show(const std::string&);
|
||||
static void show(const std::string&, S32 error_code = -1);
|
||||
|
||||
private:
|
||||
// needs to be preallocated before viewer runs out of memory
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms)
|
|||
// schedule a call to threadedUpdate for every call to updateQueue
|
||||
if (!isQuitting())
|
||||
{
|
||||
mRequestQueue.post([=]()
|
||||
mRequestQueue.post([=, this]()
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update");
|
||||
mIdleThread = false;
|
||||
|
|
@ -474,7 +474,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
|
|||
#else
|
||||
using namespace std::chrono_literals;
|
||||
auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms;
|
||||
mRequestQueue.post([=]
|
||||
mRequestQueue.post([=, this]
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("processRequest - retry");
|
||||
if (LL::WorkQueue::TimePoint::clock::now() < retry_time)
|
||||
|
|
|
|||
|
|
@ -918,7 +918,7 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
|
|||
}
|
||||
//sd[INV_FLAGS_LABEL] = (S32)mFlags;
|
||||
sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
|
||||
sd[INV_SALE_INFO_LABEL] = mSaleInfo;
|
||||
sd[INV_SALE_INFO_LABEL] = mSaleInfo.asLLSD();
|
||||
sd[INV_NAME_LABEL] = mName;
|
||||
sd[INV_DESC_LABEL] = mDescription;
|
||||
sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
|
||||
|
|
|
|||
|
|
@ -89,8 +89,14 @@ bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
|
|||
|
||||
LLSD LLSaleInfo::asLLSD() const
|
||||
{
|
||||
LLSD sd = LLSD();
|
||||
sd["sale_type"] = lookup(mSaleType);
|
||||
LLSD sd;
|
||||
const char* type = lookup(mSaleType);
|
||||
if (!type)
|
||||
{
|
||||
LL_WARNS_ONCE() << "Unknown sale type: " << mSaleType << LL_ENDL;
|
||||
type = lookup(LLSaleInfo::FS_NOT);
|
||||
}
|
||||
sd["sale_type"] = type;
|
||||
sd["sale_price"] = mSalePrice;
|
||||
return sd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ const std::string LLSettingsSky::SETTING_REFLECTION_PROBE_AMBIANCE("reflection_p
|
|||
|
||||
const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("651510b8-5f4d-8991-1592-e7eeab2a5a06");
|
||||
|
||||
F32 LLSettingsSky::sAutoAdjustProbeAmbiance = 1.f;
|
||||
const F32 LLSettingsSky::DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE = 1.f;
|
||||
F32 LLSettingsSky::sAutoAdjustProbeAmbiance = DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE;
|
||||
|
||||
static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver
|
||||
static const LLUUID DEFAULT_MOON_ID("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
|
||||
|
|
@ -2032,43 +2033,43 @@ F32 LLSettingsSky::getGamma() const
|
|||
return mGamma;
|
||||
}
|
||||
|
||||
F32 LLSettingsSky::getHDRMin() const
|
||||
F32 LLSettingsSky::getHDRMin(bool auto_adjust) const
|
||||
{
|
||||
if (mCanAutoAdjust)
|
||||
if (mCanAutoAdjust && !auto_adjust)
|
||||
return 0.f;
|
||||
|
||||
return mHDRMin;
|
||||
}
|
||||
|
||||
F32 LLSettingsSky::getHDRMax() const
|
||||
F32 LLSettingsSky::getHDRMax(bool auto_adjust) const
|
||||
{
|
||||
if (mCanAutoAdjust)
|
||||
if (mCanAutoAdjust && !auto_adjust)
|
||||
return 0.f;
|
||||
|
||||
return mHDRMax;
|
||||
}
|
||||
|
||||
F32 LLSettingsSky::getHDROffset() const
|
||||
F32 LLSettingsSky::getHDROffset(bool auto_adjust) const
|
||||
{
|
||||
if (mCanAutoAdjust)
|
||||
if (mCanAutoAdjust && !auto_adjust)
|
||||
return 1.0f;
|
||||
|
||||
return mHDROffset;
|
||||
}
|
||||
|
||||
F32 LLSettingsSky::getTonemapMix() const
|
||||
F32 LLSettingsSky::getTonemapMix(bool auto_adjust) const
|
||||
{
|
||||
if (mCanAutoAdjust)
|
||||
if (mCanAutoAdjust && !auto_adjust)
|
||||
{
|
||||
// legacy settings do not support tonemaping
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return mTonemapMix;
|
||||
}
|
||||
|
||||
void LLSettingsSky::setTonemapMix(F32 mix)
|
||||
{
|
||||
if (mCanAutoAdjust)
|
||||
return;
|
||||
|
||||
mTonemapMix = mix;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public:
|
|||
|
||||
static const LLUUID DEFAULT_ASSET_ID;
|
||||
|
||||
static const F32 DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE;
|
||||
static F32 sAutoAdjustProbeAmbiance;
|
||||
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsSky> ptr_t;
|
||||
|
|
@ -209,10 +210,10 @@ public:
|
|||
|
||||
F32 getGamma() const;
|
||||
|
||||
F32 getHDRMin() const;
|
||||
F32 getHDRMax() const;
|
||||
F32 getHDROffset() const;
|
||||
F32 getTonemapMix() const;
|
||||
F32 getHDRMin(bool auto_adjust = false) const;
|
||||
F32 getHDRMax(bool auto_adjust = false) const;
|
||||
F32 getHDROffset(bool auto_adjust = false) const;
|
||||
F32 getTonemapMix(bool auto_adjust = false) const;
|
||||
void setTonemapMix(F32 mix);
|
||||
|
||||
void setGamma(F32 val);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ class LLRotation;
|
|||
#include <assert.h>
|
||||
#include "llpreprocessor.h"
|
||||
#include "llmemory.h"
|
||||
#include "glm/vec3.hpp"
|
||||
#include "glm/vec4.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
///////////////////////////////////
|
||||
// FIRST TIME USERS PLEASE READ
|
||||
|
|
@ -364,6 +367,16 @@ public:
|
|||
|
||||
inline operator LLQuad() const;
|
||||
|
||||
explicit inline operator glm::vec3() const
|
||||
{
|
||||
return glm::make_vec3(getF32ptr());
|
||||
};
|
||||
|
||||
explicit inline operator glm::vec4() const
|
||||
{
|
||||
return glm::make_vec4(getF32ptr());
|
||||
};
|
||||
|
||||
private:
|
||||
LLQuad mQ{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
#include "llmath.h"
|
||||
|
||||
#include "llsd.h"
|
||||
|
||||
#include "glm/vec3.hpp"
|
||||
#include "glm/vec4.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
class LLVector2;
|
||||
class LLVector4;
|
||||
class LLVector4a;
|
||||
|
|
@ -66,6 +71,11 @@ class LLVector3
|
|||
explicit LLVector3(const LLVector4a& vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2])
|
||||
explicit LLVector3(const LLSD& sd);
|
||||
|
||||
// GLM interop
|
||||
explicit LLVector3(const glm::vec3& vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2])
|
||||
explicit LLVector3(const glm::vec4& vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2])
|
||||
explicit inline operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2])
|
||||
explicit inline operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], 1)
|
||||
|
||||
LLSD getValue() const;
|
||||
|
||||
|
|
@ -92,6 +102,8 @@ class LLVector3
|
|||
inline void set(const F32 *vec); // Sets LLVector3 to vec
|
||||
const LLVector3& set(const LLVector4 &vec);
|
||||
const LLVector3& set(const LLVector3d &vec);// Sets LLVector3 to vec
|
||||
inline void set(const glm::vec4& vec); // Sets LLVector3 to vec
|
||||
inline void set(const glm::vec3& vec); // Sets LLVector3 to vec
|
||||
|
||||
inline void setVec(F32 x, F32 y, F32 z); // deprecated
|
||||
inline void setVec(const LLVector3 &vec); // deprecated
|
||||
|
|
@ -190,6 +202,20 @@ inline LLVector3::LLVector3(const F32 *vec)
|
|||
mV[VZ] = vec[VZ];
|
||||
}
|
||||
|
||||
inline LLVector3::LLVector3(const glm::vec3& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
}
|
||||
|
||||
inline LLVector3::LLVector3(const glm::vec4& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
}
|
||||
|
||||
/*
|
||||
inline LLVector3::LLVector3(const LLVector3 ©)
|
||||
{
|
||||
|
|
@ -259,6 +285,20 @@ inline void LLVector3::set(const F32 *vec)
|
|||
mV[2] = vec[2];
|
||||
}
|
||||
|
||||
inline void LLVector3::set(const glm::vec4& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
}
|
||||
|
||||
inline void LLVector3::set(const glm::vec3& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
inline void LLVector3::setVec(F32 x, F32 y, F32 z)
|
||||
{
|
||||
|
|
@ -471,6 +511,17 @@ inline LLVector3 operator-(const LLVector3 &a)
|
|||
return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] );
|
||||
}
|
||||
|
||||
inline LLVector3::operator glm::vec3() const
|
||||
{
|
||||
// Do not use glm::make_vec3 it can result in a buffer overrun on some platforms due to glm::vec3 being a simd vector internally
|
||||
return glm::vec3(mV[VX], mV[VY], mV[VZ]);
|
||||
}
|
||||
|
||||
inline LLVector3::operator glm::vec4() const
|
||||
{
|
||||
return glm::vec4(mV[VX], mV[VY], mV[VZ], 1.f);
|
||||
}
|
||||
|
||||
inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b)
|
||||
{
|
||||
F32 x = a.mV[0] - b.mV[0];
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@
|
|||
#include "v3math.h"
|
||||
#include "v2math.h"
|
||||
|
||||
#include "glm/vec3.hpp"
|
||||
#include "glm/vec4.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
class LLMatrix3;
|
||||
class LLMatrix4;
|
||||
class LLQuaternion;
|
||||
|
|
@ -73,6 +77,11 @@ class LLVector4
|
|||
mV[3] = (F32)sd[3].asReal();
|
||||
}
|
||||
|
||||
// GLM interop
|
||||
explicit LLVector4(const glm::vec3& vec); // Initializes LLVector4 to (vec, 1)
|
||||
explicit LLVector4(const glm::vec4& vec); // Initializes LLVector4 to vec
|
||||
explicit operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2])
|
||||
explicit operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], vec[3])
|
||||
|
||||
inline bool isFinite() const; // checks to see if all values of LLVector3 are finite
|
||||
|
||||
|
|
@ -85,6 +94,8 @@ class LLVector4
|
|||
inline void set(const LLVector4 &vec); // Sets LLVector4 to vec
|
||||
inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec
|
||||
inline void set(const F32 *vec); // Sets LLVector4 to vec
|
||||
inline void set(const glm::vec4& vec); // Sets LLVector4 to vec
|
||||
inline void set(const glm::vec3& vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec with w defaulted to 1
|
||||
|
||||
inline void setVec(F32 x, F32 y, F32 z); // deprecated
|
||||
inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated
|
||||
|
|
@ -223,6 +234,21 @@ inline LLVector4::LLVector4(const LLSD &sd)
|
|||
setValue(sd);
|
||||
}
|
||||
|
||||
inline LLVector4::LLVector4(const glm::vec3& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
mV[VW] = 1.f;
|
||||
}
|
||||
|
||||
inline LLVector4::LLVector4(const glm::vec4& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
mV[VW] = vec.w;
|
||||
}
|
||||
|
||||
inline bool LLVector4::isFinite() const
|
||||
{
|
||||
|
|
@ -297,6 +323,21 @@ inline void LLVector4::set(const F32 *vec)
|
|||
mV[VW] = vec[VW];
|
||||
}
|
||||
|
||||
inline void LLVector4::set(const glm::vec4& vec)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
mV[VW] = vec.w;
|
||||
}
|
||||
|
||||
inline void LLVector4::set(const glm::vec3& vec, F32 w)
|
||||
{
|
||||
mV[VX] = vec.x;
|
||||
mV[VY] = vec.y;
|
||||
mV[VZ] = vec.z;
|
||||
mV[VW] = w;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
inline void LLVector4::setVec(F32 x, F32 y, F32 z)
|
||||
|
|
@ -466,6 +507,16 @@ inline LLVector4 operator-(const LLVector4 &a)
|
|||
return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] );
|
||||
}
|
||||
|
||||
inline LLVector4::operator glm::vec3() const
|
||||
{
|
||||
return glm::vec3(mV[VX], mV[VY], mV[VZ]);
|
||||
}
|
||||
|
||||
inline LLVector4::operator glm::vec4() const
|
||||
{
|
||||
return glm::make_vec4(mV);
|
||||
}
|
||||
|
||||
inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b)
|
||||
{
|
||||
LLVector4 vec = a - b;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ LLCubeMapArray::~LLCubeMapArray()
|
|||
{
|
||||
}
|
||||
|
||||
void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool use_mips)
|
||||
void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool use_mips, bool hdr)
|
||||
{
|
||||
U32 texname = 0;
|
||||
mWidth = resolution;
|
||||
|
|
@ -127,7 +127,11 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us
|
|||
bind(0);
|
||||
free_cur_tex_image();
|
||||
|
||||
U32 format = components == 4 ? GL_RGBA16F : GL_RGB16F;
|
||||
U32 format = components == 4 ? GL_RGBA16F : GL_R11F_G11F_B10F;
|
||||
if (!hdr)
|
||||
{
|
||||
format = components == 4 ? GL_RGBA8 : GL_RGB8;
|
||||
}
|
||||
U32 mip = 0;
|
||||
U32 mip_resolution = resolution;
|
||||
while (mip_resolution >= 1)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public:
|
|||
// components - number of components per pixel
|
||||
// count - number of cube maps in the array
|
||||
// use_mips - if true, mipmaps will be allocated for this cube map array and anisotropic filtering will be used
|
||||
void allocate(U32 res, U32 components, U32 count, bool use_mips = true);
|
||||
void allocate(U32 res, U32 components, U32 count, bool use_mips = true, bool hdr = true);
|
||||
void bind(S32 stage);
|
||||
void unbind();
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
|
|||
mBitmapHeight = image_height;
|
||||
|
||||
S32 num_components = getNumComponents(bitmap_type);
|
||||
mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
|
||||
mImageRawVec[bitmap_idx].emplace_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
|
||||
bitmap_num = static_cast<U32>(mImageRawVec[bitmap_idx].size()) - 1;
|
||||
|
||||
LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
|
||||
|
|
@ -117,7 +117,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
|
|||
}
|
||||
|
||||
// Make corresponding GL image.
|
||||
mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false, false));
|
||||
mImageGLVec[bitmap_idx].emplace_back(new LLImageGL(image_raw, false, false));
|
||||
LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
|
||||
|
||||
// Start at beginning of the new image.
|
||||
|
|
@ -141,6 +141,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
|
|||
bitmap_num = getNumBitmaps(bitmap_type) - 1;
|
||||
|
||||
mCurrentOffsetX[bitmap_idx] += width + 1;
|
||||
mGeneration++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -168,6 +169,7 @@ void LLFontBitmapCache::reset()
|
|||
|
||||
mBitmapWidth = 0;
|
||||
mBitmapHeight = 0;
|
||||
mGeneration++;
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ public:
|
|||
U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? static_cast<U32>(mImageRawVec[static_cast<U32>(bitmapType)].size()) : 0U; }
|
||||
S32 getBitmapWidth() const { return mBitmapWidth; }
|
||||
S32 getBitmapHeight() const { return mBitmapHeight; }
|
||||
S32 getCacheGeneration() const { return mGeneration; }
|
||||
|
||||
protected:
|
||||
static U32 getNumComponents(EFontGlyphType bitmap_type);
|
||||
|
|
@ -74,6 +75,7 @@ private:
|
|||
S32 mCurrentOffsetY[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
|
||||
S32 mMaxCharWidth = 0;
|
||||
S32 mMaxCharHeight = 0;
|
||||
S32 mGeneration = 0;
|
||||
std::vector<LLPointer<LLImageRaw>> mImageRawVec[static_cast<U32>(EFontGlyphType::Count)];
|
||||
std::vector<LLPointer<LLImageGL>> mImageGLVec[static_cast<U32>(EFontGlyphType::Count)];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -146,7 +146,6 @@ LLFontFreetype::LLFontFreetype()
|
|||
mIsFallback(false),
|
||||
mFTFace(NULL),
|
||||
mRenderGlyphCount(0),
|
||||
mAddGlyphCount(0),
|
||||
mStyle(0),
|
||||
mPointSize(0)
|
||||
{
|
||||
|
|
@ -552,7 +551,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
|
|||
return NULL;
|
||||
|
||||
llassert(!mIsFallback);
|
||||
fontp->renderGlyph(requested_glyph_type, glyph_index);
|
||||
fontp->renderGlyph(requested_glyph_type, glyph_index, wch);
|
||||
|
||||
EFontGlyphType bitmap_glyph_type = EFontGlyphType::Unspecified;
|
||||
switch (fontp->mFTFace->glyph->bitmap.pixel_mode)
|
||||
|
|
@ -574,7 +573,6 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
|
|||
S32 pos_x, pos_y;
|
||||
U32 bitmap_num;
|
||||
mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_glyph_type, bitmap_num);
|
||||
mAddGlyphCount++;
|
||||
|
||||
LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index, requested_glyph_type);
|
||||
gi->mXBitmapOffset = pos_x;
|
||||
|
|
@ -697,7 +695,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
|
|||
}
|
||||
}
|
||||
|
||||
void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const
|
||||
void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const
|
||||
{
|
||||
if (mFTFace == NULL)
|
||||
return;
|
||||
|
|
@ -712,11 +710,28 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) co
|
|||
FT_Error error = FT_Load_Glyph(mFTFace, glyph_index, load_flags);
|
||||
if (FT_Err_Ok != error)
|
||||
{
|
||||
if (error == FT_Err_Out_Of_Memory)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS() << "Out of memory loading glyph for character " << llformat("U+%xu", U32(wch)) << LL_ENDL;
|
||||
}
|
||||
|
||||
std::string message = llformat(
|
||||
"Error %d (%s) loading glyph %u: bitmap_type=%u, load_flags=%d",
|
||||
error, FT_Error_String(error), glyph_index, bitmap_type, load_flags);
|
||||
"Error %d (%s) loading wchar %u glyph %u/%u: bitmap_type=%u, load_flags=%d",
|
||||
error, FT_Error_String(error), wch, glyph_index, mFTFace->num_glyphs, bitmap_type, load_flags);
|
||||
LL_WARNS_ONCE() << message << LL_ENDL;
|
||||
error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR);
|
||||
if (FT_Err_Invalid_Outline == error
|
||||
|| FT_Err_Invalid_Composite == error
|
||||
|| (FT_Err_Ok != error && LLStringOps::isEmoji(wch)))
|
||||
{
|
||||
glyph_index = FT_Get_Char_Index(mFTFace, '?');
|
||||
// if '?' is not present, potentially can use last index, that's supposed to be null glyph
|
||||
if (glyph_index > 0)
|
||||
{
|
||||
error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR);
|
||||
}
|
||||
}
|
||||
llassert_always_msg(FT_Err_Ok == error, message.c_str());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ private:
|
|||
bool hasGlyph(llwchar wch) const; // Has a glyph for this character
|
||||
LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
|
||||
LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
|
||||
void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const;
|
||||
void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const;
|
||||
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
|
||||
|
||||
std::string mName;
|
||||
|
|
@ -187,7 +187,6 @@ private:
|
|||
mutable LLFontBitmapCache* mFontBitmapCachep;
|
||||
|
||||
mutable S32 mRenderGlyphCount;
|
||||
mutable S32 mAddGlyphCount;
|
||||
};
|
||||
|
||||
#endif // LL_FONTFREETYPE_H
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ F32 LLFontGL::sVertDPI = 96.f;
|
|||
F32 LLFontGL::sHorizDPI = 96.f;
|
||||
F32 LLFontGL::sScaleX = 1.f;
|
||||
F32 LLFontGL::sScaleY = 1.f;
|
||||
S32 LLFontGL::sResolutionGeneration = 0;
|
||||
bool LLFontGL::sDisplayFont = true ;
|
||||
std::string LLFontGL::sAppDir;
|
||||
|
||||
|
|
@ -109,6 +110,12 @@ S32 LLFontGL::getNumFaces(const std::string& filename)
|
|||
return mFontFreetype->getNumFaces(filename);
|
||||
}
|
||||
|
||||
S32 LLFontGL::getCacheGeneration() const
|
||||
{
|
||||
const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
|
||||
return font_bitmap_cache->getCacheGeneration();
|
||||
}
|
||||
|
||||
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
|
||||
ShadowType shadow, S32 max_chars, F32* right_x, bool use_ellipses, bool use_color) const
|
||||
{
|
||||
|
|
@ -249,6 +256,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
|
||||
|
||||
// This looks wrong, value is dynamic.
|
||||
// LLFontBitmapCache::nextOpenPos can alter these values when
|
||||
// new characters get added to cache, which affects whole string.
|
||||
// Todo: Perhaps value should update after symbols were added?
|
||||
F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth();
|
||||
F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight();
|
||||
|
||||
|
|
@ -270,6 +281,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
const LLFontGlyphInfo* next_glyph = NULL;
|
||||
|
||||
// string can have more than one glyph per char (ex: bold or shadow),
|
||||
// make sure that GLYPH_BATCH_SIZE won't end up with half a symbol.
|
||||
// See drawGlyph.
|
||||
// Ex: with shadows it's 6 glyps per char. 30 fits exactly 5 chars.
|
||||
static constexpr S32 GLYPH_BATCH_SIZE = 30;
|
||||
static thread_local LLVector4a vertices[GLYPH_BATCH_SIZE * 6];
|
||||
static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6];
|
||||
|
|
@ -282,6 +297,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
|
||||
S32 glyph_count = 0;
|
||||
llwchar last_char = wstr[begin_offset];
|
||||
for (i = begin_offset; i < begin_offset + length; i++)
|
||||
{
|
||||
llwchar wch = wstr[i];
|
||||
|
|
@ -299,7 +315,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
}
|
||||
// Per-glyph bitmap texture.
|
||||
std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry;
|
||||
if (next_bitmap_entry != bitmap_entry)
|
||||
if (next_bitmap_entry != bitmap_entry || last_char != wch)
|
||||
{
|
||||
// Actually draw the queued glyphs before switching their texture;
|
||||
// otherwise the queued glyphs will be taken from wrong textures.
|
||||
|
|
@ -316,6 +332,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
bitmap_entry = next_bitmap_entry;
|
||||
LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
|
||||
gGL.getTexUnit(0)->bind(font_image);
|
||||
|
||||
// For some reason it's not enough to compare by bitmap_entry.
|
||||
// Issue hits emojis, japenese and chinese glyphs, only on first run.
|
||||
// Todo: figure it out, there might be a bug with raw image data.
|
||||
last_char = wch;
|
||||
}
|
||||
|
||||
if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
|
||||
|
||||
S32 getNumFaces(const std::string& filename);
|
||||
S32 getCacheGeneration() const;
|
||||
|
||||
S32 render(const LLWString &text, S32 begin_offset,
|
||||
const LLRect& rect,
|
||||
|
|
@ -224,6 +225,7 @@ public:
|
|||
static F32 sHorizDPI;
|
||||
static F32 sScaleX;
|
||||
static F32 sScaleY;
|
||||
static S32 sResolutionGeneration;
|
||||
static bool sDisplayFont ;
|
||||
static std::string sAppDir; // For loading fonts
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,9 @@ S32 LLFontVertexBuffer::render(
|
|||
|| mLastScaleY != LLFontGL::sScaleY
|
||||
|| mLastVertDPI != LLFontGL::sVertDPI
|
||||
|| mLastHorizDPI != LLFontGL::sHorizDPI
|
||||
|| mLastOrigin != LLFontGL::sCurOrigin)
|
||||
|| mLastOrigin != LLFontGL::sCurOrigin
|
||||
|| mLastResGeneration != LLFontGL::sResolutionGeneration
|
||||
|| mLastFontCacheGen != fontp->getCacheGeneration())
|
||||
{
|
||||
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
|
||||
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
|
||||
|
|
@ -178,6 +180,9 @@ void LLFontVertexBuffer::genBuffers(
|
|||
{
|
||||
// todo: add a debug build assert if this triggers too often for to long?
|
||||
mBufferList.clear();
|
||||
// Save before rendreing, it can change mid-render,
|
||||
// so will need to rerender previous characters
|
||||
mLastFontCacheGen = fontp->getCacheGeneration();
|
||||
|
||||
gGL.beginList(&mBufferList);
|
||||
mChars = fontp->render(text, begin_offset, x, y, color, halign, valign,
|
||||
|
|
@ -201,6 +206,7 @@ void LLFontVertexBuffer::genBuffers(
|
|||
mLastVertDPI = LLFontGL::sVertDPI;
|
||||
mLastHorizDPI = LLFontGL::sHorizDPI;
|
||||
mLastOrigin = LLFontGL::sCurOrigin;
|
||||
mLastResGeneration = LLFontGL::sResolutionGeneration;
|
||||
|
||||
if (right_x)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,8 +117,13 @@ private:
|
|||
F32 mLastScaleY = 1.f;
|
||||
F32 mLastVertDPI = 0.f;
|
||||
F32 mLastHorizDPI = 0.f;
|
||||
S32 mLastResGeneration = 0;
|
||||
LLCoordGL mLastOrigin;
|
||||
|
||||
// Adding new characters to bitmap cache can alter value from getBitmapWidth();
|
||||
// which alters whole string. So rerender when new characters were added to cache.
|
||||
S32 mLastFontCacheGen = 0;
|
||||
|
||||
static bool sEnableBufferCollection;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ public:
|
|||
bool attachNothing = false;
|
||||
bool hasHeroProbes = false;
|
||||
bool isPBRTerrain = false;
|
||||
bool hasTonemap = false;
|
||||
};
|
||||
|
||||
// ============= Structure for caching shader uniforms ===============
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
|
|||
case GL_RGB: return 24;
|
||||
case GL_SRGB: return 24;
|
||||
case GL_RGB8: return 24;
|
||||
case GL_R11F_G11F_B10F: return 32;
|
||||
case GL_RGBA: return 32;
|
||||
case GL_RGBA8: return 32;
|
||||
case GL_RGB10_A2: return 32;
|
||||
|
|
@ -1773,7 +1774,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
|
|||
ref();
|
||||
LL::WorkQueue::postMaybe(
|
||||
mMainQueue,
|
||||
[=]()
|
||||
[=, this]()
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("cglt - delete callback");
|
||||
syncTexName(new_tex_name);
|
||||
|
|
|
|||
|
|
@ -737,9 +737,8 @@ void LLLightState::setPosition(const LLVector4& position)
|
|||
++gGL.mLightHash;
|
||||
mPosition = position;
|
||||
//transform position by current modelview matrix
|
||||
glm::vec4 pos(glm::make_vec4(position.mV));
|
||||
const glm::mat4& mat = gGL.getModelviewMatrix();
|
||||
pos = mat * pos;
|
||||
glm::vec4 pos(position);
|
||||
pos = gGL.getModelviewMatrix() * pos;
|
||||
mPosition.set(glm::value_ptr(pos));
|
||||
}
|
||||
|
||||
|
|
@ -794,7 +793,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction)
|
|||
++gGL.mLightHash;
|
||||
|
||||
//transform direction by current modelview matrix
|
||||
glm::vec3 dir(glm::make_vec3(direction.mV));
|
||||
glm::vec3 dir(direction);
|
||||
const glm::mat3 mat(gGL.getModelviewMatrix());
|
||||
dir = mat * dir;
|
||||
|
||||
|
|
@ -2088,12 +2087,14 @@ void set_last_projection(const glm::mat4& mat)
|
|||
|
||||
glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec)
|
||||
{
|
||||
//const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3];
|
||||
//return glm::vec3(
|
||||
// (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w,
|
||||
// (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w,
|
||||
// (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w
|
||||
//);
|
||||
#if 1 // SIMD path results in strange crashes. Fall back to scalar for now.
|
||||
const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3];
|
||||
return glm::vec3(
|
||||
(vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w,
|
||||
(vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w,
|
||||
(vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w
|
||||
);
|
||||
#else
|
||||
LLVector4a x, y, z, s, t, p, q;
|
||||
|
||||
x.splat(vec.x);
|
||||
|
|
@ -2123,4 +2124,5 @@ glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec)
|
|||
res.setAdd(x, z);
|
||||
res.div(q);
|
||||
return glm::make_vec3(res.getF32ptr());
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,6 +291,14 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
}
|
||||
}
|
||||
|
||||
if (features->hasTonemap)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/tonemapUtilF.glsl"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE order of shader object attaching is VERY IMPORTANT!!!
|
||||
if (features->hasAtmospherics)
|
||||
{
|
||||
|
|
@ -466,6 +474,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
|
||||
if (filename.empty())
|
||||
{
|
||||
LL_WARNS("ShaderLoading") << "tried loading empty filename" << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -923,6 +932,8 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
}
|
||||
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("ShaderLoading") << "loadShaderFile() completed, ret: " << U32(ret) << LL_ENDL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1389,6 +1400,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("screenTex");
|
||||
mReservedUniforms.push_back("screenDepth");
|
||||
mReservedUniforms.push_back("refTex");
|
||||
mReservedUniforms.push_back("exclusionTex");
|
||||
mReservedUniforms.push_back("eyeVec");
|
||||
mReservedUniforms.push_back("time");
|
||||
mReservedUniforms.push_back("waveDir1");
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ public:
|
|||
LLShaderMgr();
|
||||
virtual ~LLShaderMgr();
|
||||
|
||||
// Note: although you can use statically hashed strings to just bind a random uniform, it's generally preferably that you use this.
|
||||
// Always document what the actual shader uniform is next to the shader uniform in this struct.
|
||||
// clang-format off
|
||||
typedef enum
|
||||
{ // Shader uniform name, set in LLShaderMgr::initAttribsAndUniforms()
|
||||
|
|
@ -234,6 +236,7 @@ public:
|
|||
WATER_SCREENTEX, // "screenTex"
|
||||
WATER_SCREENDEPTH, // "screenDepth"
|
||||
WATER_REFTEX, // "refTex"
|
||||
WATER_EXCLUSIONTEX, // "exclusionTex"
|
||||
WATER_EYEVEC, // "eyeVec"
|
||||
WATER_TIME, // "time"
|
||||
WATER_WAVE_DIR1, // "waveDir1"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "llfolderview.h"
|
||||
#include "llfolderviewmodel.h"
|
||||
#include "llcallbacklist.h"
|
||||
#include "llclipboard.h" // *TODO: remove this once hack below gone.
|
||||
#include "llkeyboard.h"
|
||||
#include "lllineeditor.h"
|
||||
|
|
@ -274,7 +275,11 @@ LLFolderView::~LLFolderView( void )
|
|||
mRenamer = NULL;
|
||||
mStatusTextBox = NULL;
|
||||
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
if (mPopupMenuHandle.get())
|
||||
{
|
||||
mPopupMenuHandle.get()->die();
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
mPopupMenuHandle.markDead();
|
||||
|
||||
mAutoOpenItems.removeAllNodes();
|
||||
|
|
@ -1095,7 +1100,10 @@ bool LLFolderView::handleKeyHere( KEY key, MASK mask )
|
|||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->isOpen())
|
||||
{
|
||||
LLMenuGL::sMenuContainer->hideMenus();
|
||||
if (LLMenuGL::sMenuContainer->hideMenus())
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
switch( key )
|
||||
|
|
@ -1340,7 +1348,10 @@ bool LLFolderView::handleUnicodeCharHere(llwchar uni_char)
|
|||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->isOpen())
|
||||
{
|
||||
LLMenuGL::sMenuContainer->hideMenus();
|
||||
if (LLMenuGL::sMenuContainer->hideMenus())
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
//do text search
|
||||
|
|
@ -1612,7 +1623,11 @@ void LLFolderView::deleteAllChildren()
|
|||
{
|
||||
LLUI::getInstance()->removePopup(mRenamer);
|
||||
}
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
if (mPopupMenuHandle.get())
|
||||
{
|
||||
mPopupMenuHandle.get()->die();
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
mPopupMenuHandle.markDead();
|
||||
mScrollContainer = NULL;
|
||||
mRenameItem = NULL;
|
||||
|
|
@ -1979,9 +1994,24 @@ void LLFolderView::updateMenu()
|
|||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->getVisible())
|
||||
{
|
||||
updateMenuOptions(menu);
|
||||
// When fetching folders in bulk or in parts, each callback
|
||||
// cause updateMenu individually, so make sure it gets called
|
||||
// only once per frame, after callbacks are done.
|
||||
// gIdleCallbacks has built in dupplicate protection.
|
||||
gIdleCallbacks.addFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFolderView::onIdleUpdateMenu(void* user_data)
|
||||
{
|
||||
LLFolderView* self = (LLFolderView*)user_data;
|
||||
LLMenuGL* menu = (LLMenuGL*)self->mPopupMenuHandle.get();
|
||||
if (menu)
|
||||
{
|
||||
self->updateMenuOptions(menu);
|
||||
menu->needsArrange(); // update menu height if needed
|
||||
}
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, self);
|
||||
}
|
||||
|
||||
bool LLFolderView::isFolderSelected()
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ public:
|
|||
private:
|
||||
void updateMenuOptions(LLMenuGL* menu);
|
||||
void updateRenamerPosition();
|
||||
static void onIdleUpdateMenu(void* user_data);
|
||||
|
||||
protected:
|
||||
LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container.
|
||||
|
|
@ -414,6 +415,7 @@ public:
|
|||
virtual void doItem(LLFolderViewItem* item) {}
|
||||
void setApply(bool apply);
|
||||
void clearOpenFolders() { mOpenFolders.clear(); }
|
||||
bool hasOpenFolders() { return !mOpenFolders.empty(); }
|
||||
protected:
|
||||
std::set<LLUUID> mOpenFolders;
|
||||
bool mApply;
|
||||
|
|
|
|||
|
|
@ -1555,7 +1555,7 @@ bool LLNotifications::loadTemplates()
|
|||
gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS);
|
||||
if (search_paths.empty())
|
||||
{
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES);
|
||||
LL_ERRS() << "Problem finding notifications.xml" << LL_ENDL;
|
||||
}
|
||||
|
||||
|
|
@ -1565,7 +1565,7 @@ bool LLNotifications::loadTemplates()
|
|||
|
||||
if (!success || root.isNull() || !root->hasName( "notifications" ))
|
||||
{
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES);
|
||||
LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1576,7 +1576,7 @@ bool LLNotifications::loadTemplates()
|
|||
|
||||
if(!params.validateBlock())
|
||||
{
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES);
|
||||
LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1643,7 +1643,7 @@ bool LLNotifications::loadVisibilityRules()
|
|||
|
||||
if(!params.validateBlock())
|
||||
{
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"));
|
||||
LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES);
|
||||
LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ LLStyle::Params::Params()
|
|||
readonly_color("readonly_color", LLColor4::black),
|
||||
selected_color("selected_color", LLColor4::black),
|
||||
alpha("alpha", 1.f),
|
||||
font("font", LLFontGL::getFontMonospace()),
|
||||
font("font", LLStyle::getDefaultFont()),
|
||||
image("image"),
|
||||
link_href("href"),
|
||||
is_link("is_link")
|
||||
|
|
@ -70,6 +70,11 @@ const LLFontGL* LLStyle::getFont() const
|
|||
return mFont;
|
||||
}
|
||||
|
||||
const LLFontGL* LLStyle::getDefaultFont()
|
||||
{
|
||||
return LLFontGL::getFontMonospace();
|
||||
}
|
||||
|
||||
void LLStyle::setLinkHREF(const std::string& href)
|
||||
{
|
||||
mLink = href;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public:
|
|||
|
||||
void setFont(const LLFontGL* font);
|
||||
const LLFontGL* getFont() const;
|
||||
static const LLFontGL* getDefaultFont();
|
||||
|
||||
const std::string& getLinkHREF() const { return mLink; }
|
||||
void setLinkHREF(const std::string& href);
|
||||
|
|
|
|||
|
|
@ -1438,7 +1438,8 @@ void LLTextBase::onVisibilityChange( bool new_visibility )
|
|||
//virtual
|
||||
void LLTextBase::setValue(const LLSD& value )
|
||||
{
|
||||
setText(value.asString());
|
||||
static const LLStyle::Params input_params = LLStyle::Params();
|
||||
setText(value.asString(), input_params);
|
||||
}
|
||||
|
||||
//virtual
|
||||
|
|
@ -3880,8 +3881,7 @@ bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& w
|
|||
if (mForceNewLine)
|
||||
{
|
||||
// Chat, string can't be smaller then font height even if it is empty
|
||||
LLStyleSP s(new LLStyle(LLStyle::Params().visible(true)));
|
||||
height = s->getFont()->getLineHeight();
|
||||
height = LLStyle::getDefaultFont()->getLineHeight();
|
||||
|
||||
return true; // new line
|
||||
}
|
||||
|
|
@ -3945,9 +3945,7 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
|
|||
|
||||
LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1)
|
||||
{
|
||||
LLStyleSP s( new LLStyle(LLStyle::Params().visible(true)));
|
||||
|
||||
mFontHeight = s->getFont()->getLineHeight();
|
||||
mFontHeight = LLStyle::getDefaultFont()->getLineHeight();
|
||||
}
|
||||
LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ LLSD LLTextBox::getValue() const
|
|||
bool LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )
|
||||
{
|
||||
mText.setArg(key, text);
|
||||
LLTextBase::setText(mText.getString());
|
||||
static const LLStyle::Params input_params = LLStyle::Params();
|
||||
LLTextBase::setText(mText.getString(), input_params);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
|
|||
"Second Life viewer couldn't access some of the files it needs and will be closed."
|
||||
"\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and "
|
||||
"contact https://support.secondlife.com if issue persists after reinstall.";
|
||||
LLError::LLUserWarningMsg::show(error_string);
|
||||
LLError::LLUserWarningMsg::show(error_string, LLError::LLUserWarningMsg::ERROR_MISSING_FILES);
|
||||
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,11 @@ bool LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLWindowCallbacks::handleDisplayChanged()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLWindowCallbacks::handleWindowDidChangeScreen(LLWindow *window)
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ public:
|
|||
virtual bool handleTimerEvent(LLWindow *window);
|
||||
virtual bool handleDeviceChange(LLWindow *window);
|
||||
virtual bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
|
||||
virtual bool handleDisplayChanged();
|
||||
virtual bool handleWindowDidChangeScreen(LLWindow *window);
|
||||
|
||||
enum DragNDropAction {
|
||||
|
|
|
|||
|
|
@ -1060,7 +1060,7 @@ F32 LLWindowMacOSX::getGamma()
|
|||
&greenGamma,
|
||||
&blueMin,
|
||||
&blueMax,
|
||||
&blueGamma) == noErr)
|
||||
&blueGamma) == kCGErrorSuccess)
|
||||
{
|
||||
// So many choices...
|
||||
// Let's just return the green channel gamma for now.
|
||||
|
|
@ -1111,7 +1111,7 @@ bool LLWindowMacOSX::setGamma(const F32 gamma)
|
|||
&greenGamma,
|
||||
&blueMin,
|
||||
&blueMax,
|
||||
&blueGamma) != noErr)
|
||||
&blueGamma) != kCGErrorSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1126,7 +1126,7 @@ bool LLWindowMacOSX::setGamma(const F32 gamma)
|
|||
gamma,
|
||||
blueMin,
|
||||
blueMax,
|
||||
gamma) != noErr)
|
||||
gamma) != kCGErrorSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1178,7 +1178,7 @@ bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
|
|||
newPosition.y = screen_pos.mY;
|
||||
|
||||
CGSetLocalEventsSuppressionInterval(0.0);
|
||||
if(CGWarpMouseCursorPosition(newPosition) == noErr)
|
||||
if(CGWarpMouseCursorPosition(newPosition) == kCGErrorSuccess)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "llstring.h"
|
||||
#include "lldir.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llsys.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llthreadsafequeue.h"
|
||||
#include "stringize.h"
|
||||
|
|
@ -80,10 +81,6 @@ const S32 BITS_PER_PIXEL = 32;
|
|||
const S32 MAX_NUM_RESOLUTIONS = 32;
|
||||
const F32 ICON_FLASH_TIME = 0.5f;
|
||||
|
||||
#ifndef WM_DPICHANGED
|
||||
#define WM_DPICHANGED 0x02E0
|
||||
#endif
|
||||
|
||||
#ifndef USER_DEFAULT_SCREEN_DPI
|
||||
#define USER_DEFAULT_SCREEN_DPI 96 // Win7
|
||||
#endif
|
||||
|
|
@ -1317,8 +1314,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
|
|||
catch (...)
|
||||
{
|
||||
LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat");
|
||||
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
|
||||
mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1329,8 +1325,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
|
|||
if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
|
||||
&pfd))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
|
||||
mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1368,8 +1363,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
|
|||
|
||||
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
|
||||
mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1377,16 +1371,14 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
|
|||
|
||||
if (!(mhRC = SafeCreateContext(mhDC)))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
|
||||
mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wglMakeCurrent(mhDC, mhRC))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
|
||||
mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1592,15 +1584,14 @@ const S32 max_format = (S32)num_formats - 1;
|
|||
|
||||
if (!mhDC)
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBDevContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
|
||||
mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1632,7 +1623,7 @@ const S32 max_format = (S32)num_formats - 1;
|
|||
{
|
||||
LL_WARNS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL;
|
||||
// cannot proceed without wgl_ARB_pixel_format extension, shutdown same as any other gGLManager.initGL() failure
|
||||
OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1641,7 +1632,7 @@ const S32 max_format = (S32)num_formats - 1;
|
|||
if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
|
||||
&pfd))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1663,14 +1654,14 @@ const S32 max_format = (S32)num_formats - 1;
|
|||
|
||||
if (!wglMakeCurrent(mhDC, mhRC))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gGLManager.initGL())
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1875,7 +1866,7 @@ void* LLWindowWin32::createSharedContext()
|
|||
if (!rc && !(rc = wglCreateContext(mhDC)))
|
||||
{
|
||||
close();
|
||||
OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
|
||||
LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
@ -2974,6 +2965,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
|||
return 0;
|
||||
}
|
||||
|
||||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
WINDOW_IMP_POST(window_imp->mCallbacks->handleDisplayChanged());
|
||||
}
|
||||
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETFOCUS");
|
||||
|
|
@ -4681,6 +4677,23 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem()
|
|||
|
||||
// Alternatively use GetDesc from below to get adapter's memory
|
||||
UINT64 budget_mb = info.Budget / (1024 * 1024);
|
||||
if (gGLManager.mIsIntel)
|
||||
{
|
||||
U32Megabytes phys_mb = gSysMemory.getPhysicalMemoryKB();
|
||||
LL_WARNS() << "Physical memory: " << phys_mb << " MB" << LL_ENDL;
|
||||
|
||||
if (phys_mb > 0)
|
||||
{
|
||||
// Intel uses 'shared' vram, cap it to 25% of total memory
|
||||
// Todo: consider caping all adapters at least to 50% ram
|
||||
budget_mb = llmin(budget_mb, (UINT64)(phys_mb * 0.25));
|
||||
}
|
||||
else
|
||||
{
|
||||
// if no data available, cap to 2Gb
|
||||
budget_mb = llmin(budget_mb, (UINT64)2048);
|
||||
}
|
||||
}
|
||||
if (gGLManager.mVRAM < (S32)budget_mb)
|
||||
{
|
||||
gGLManager.mVRAM = (S32)budget_mb;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ set(viewer_SOURCE_FILES
|
|||
lldrawpooltree.cpp
|
||||
lldrawpoolwater.cpp
|
||||
lldrawpoolwlsky.cpp
|
||||
lldrawpoolwaterexclusion.cpp
|
||||
lldynamictexture.cpp
|
||||
llemote.cpp
|
||||
llenvironment.cpp
|
||||
|
|
@ -823,6 +824,7 @@ set(viewer_HEADER_FILES
|
|||
lldrawpooltree.h
|
||||
lldrawpoolwater.h
|
||||
lldrawpoolwlsky.h
|
||||
lldrawpoolwaterexclusion.h
|
||||
lldynamictexture.h
|
||||
llemote.h
|
||||
llenvironment.h
|
||||
|
|
|
|||
|
|
@ -12717,7 +12717,7 @@
|
|||
<key>UpdaterWillingToTest</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether or not the updater should offer test candidate upgrades.</string>
|
||||
<string>Whether or not the updater should offer Beta upgrades.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
|
|||
|
|
@ -28,138 +28,11 @@
|
|||
out vec4 frag_color;
|
||||
|
||||
uniform sampler2D diffuseRect;
|
||||
uniform sampler2D exposureMap;
|
||||
|
||||
uniform vec2 screen_res;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
vec3 linear_to_srgb(vec3 cl);
|
||||
|
||||
//===============================================================
|
||||
// tone mapping taken from Khronos sample implementation
|
||||
//===============================================================
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const mat3 ACESInputMat = mat3
|
||||
(
|
||||
0.59719, 0.07600, 0.02840,
|
||||
0.35458, 0.90834, 0.13383,
|
||||
0.04823, 0.01566, 0.83777
|
||||
);
|
||||
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const mat3 ACESOutputMat = mat3
|
||||
(
|
||||
1.60475, -0.10208, -0.00327,
|
||||
-0.53108, 1.10813, -0.07276,
|
||||
-0.07367, -0.00605, 1.07602
|
||||
);
|
||||
|
||||
// ACES tone map (faster approximation)
|
||||
// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
vec3 toneMapACES_Narkowicz(vec3 color)
|
||||
{
|
||||
const float A = 2.51;
|
||||
const float B = 0.03;
|
||||
const float C = 2.43;
|
||||
const float D = 0.59;
|
||||
const float E = 0.14;
|
||||
return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
// ACES filmic tone map approximation
|
||||
// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
vec3 RRTAndODTFit(vec3 color)
|
||||
{
|
||||
vec3 a = color * (color + 0.0245786) - 0.000090537;
|
||||
vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
// tone mapping
|
||||
vec3 toneMapACES_Hill(vec3 color)
|
||||
{
|
||||
color = ACESInputMat * color;
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit(color);
|
||||
|
||||
color = ACESOutputMat * color;
|
||||
|
||||
// Clamp to [0, 1]
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Khronos Neutral tonemapping
|
||||
// https://github.com/KhronosGroup/ToneMapping/tree/main
|
||||
// Input color is non-negative and resides in the Linear Rec. 709 color space.
|
||||
// Output color is also Linear Rec. 709, but in the [0, 1] range.
|
||||
vec3 PBRNeutralToneMapping( vec3 color )
|
||||
{
|
||||
const float startCompression = 0.8 - 0.04;
|
||||
const float desaturation = 0.15;
|
||||
|
||||
float x = min(color.r, min(color.g, color.b));
|
||||
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
|
||||
color -= offset;
|
||||
|
||||
float peak = max(color.r, max(color.g, color.b));
|
||||
if (peak < startCompression) return color;
|
||||
|
||||
const float d = 1. - startCompression;
|
||||
float newPeak = 1. - d * d / (peak + d - startCompression);
|
||||
color *= newPeak / peak;
|
||||
|
||||
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
|
||||
return mix(color, newPeak * vec3(1, 1, 1), g);
|
||||
}
|
||||
|
||||
uniform float exposure;
|
||||
uniform float tonemap_mix;
|
||||
uniform int tonemap_type;
|
||||
|
||||
vec3 toneMap(vec3 color)
|
||||
{
|
||||
#ifndef NO_POST
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
|
||||
color *= exposure * exp_scale;
|
||||
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
void debugExposure(inout vec3 color)
|
||||
{
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
exp_scale *= 0.5;
|
||||
if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1)
|
||||
{
|
||||
color = vec3(1,0,0);
|
||||
}
|
||||
}
|
||||
vec3 toneMap(vec3 color);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* @file postDeferredTonemap.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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$
|
||||
*/
|
||||
|
||||
/*[EXTRA_CODE_HERE]*/
|
||||
|
||||
uniform sampler2D exposureMap;
|
||||
uniform vec2 screen_res;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
//===============================================================
|
||||
// tone mapping taken from Khronos sample implementation
|
||||
//===============================================================
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const mat3 ACESInputMat = mat3
|
||||
(
|
||||
0.59719, 0.07600, 0.02840,
|
||||
0.35458, 0.90834, 0.13383,
|
||||
0.04823, 0.01566, 0.83777
|
||||
);
|
||||
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const mat3 ACESOutputMat = mat3
|
||||
(
|
||||
1.60475, -0.10208, -0.00327,
|
||||
-0.53108, 1.10813, -0.07276,
|
||||
-0.07367, -0.00605, 1.07602
|
||||
);
|
||||
|
||||
// ACES tone map (faster approximation)
|
||||
// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
vec3 toneMapACES_Narkowicz(vec3 color)
|
||||
{
|
||||
const float A = 2.51;
|
||||
const float B = 0.03;
|
||||
const float C = 2.43;
|
||||
const float D = 0.59;
|
||||
const float E = 0.14;
|
||||
return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
// ACES filmic tone map approximation
|
||||
// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
vec3 RRTAndODTFit(vec3 color)
|
||||
{
|
||||
vec3 a = color * (color + 0.0245786) - 0.000090537;
|
||||
vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
// tone mapping
|
||||
vec3 toneMapACES_Hill(vec3 color)
|
||||
{
|
||||
color = ACESInputMat * color;
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit(color);
|
||||
|
||||
color = ACESOutputMat * color;
|
||||
|
||||
// Clamp to [0, 1]
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Khronos Neutral tonemapping
|
||||
// https://github.com/KhronosGroup/ToneMapping/tree/main
|
||||
// Input color is non-negative and resides in the Linear Rec. 709 color space.
|
||||
// Output color is also Linear Rec. 709, but in the [0, 1] range.
|
||||
vec3 PBRNeutralToneMapping( vec3 color )
|
||||
{
|
||||
const float startCompression = 0.8 - 0.04;
|
||||
const float desaturation = 0.15;
|
||||
|
||||
float x = min(color.r, min(color.g, color.b));
|
||||
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
|
||||
color -= offset;
|
||||
|
||||
float peak = max(color.r, max(color.g, color.b));
|
||||
if (peak < startCompression) return color;
|
||||
|
||||
const float d = 1. - startCompression;
|
||||
float newPeak = 1. - d * d / (peak + d - startCompression);
|
||||
color *= newPeak / peak;
|
||||
|
||||
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
|
||||
return mix(color, newPeak * vec3(1, 1, 1), g);
|
||||
}
|
||||
|
||||
uniform float exposure;
|
||||
uniform float tonemap_mix;
|
||||
uniform int tonemap_type;
|
||||
|
||||
vec3 toneMap(vec3 color)
|
||||
{
|
||||
#ifndef NO_POST
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
|
||||
color *= exposure * exp_scale;
|
||||
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
vec3 toneMapNoExposure(vec3 color)
|
||||
{
|
||||
#ifndef NO_POST
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
//===============================================================
|
||||
|
||||
void debugExposure(inout vec3 color)
|
||||
{
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
exp_scale *= 0.5;
|
||||
if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1)
|
||||
{
|
||||
color = vec3(1,0,0);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,6 +41,26 @@ vec3 srgb_to_linear(vec3 cs)
|
|||
|
||||
}
|
||||
|
||||
|
||||
vec4 srgb_to_linear4(vec4 cs)
|
||||
{
|
||||
vec4 low_range = cs / vec4(12.92);
|
||||
vec4 high_range = pow((cs+vec4(0.055))/vec4(1.055), vec4(2.4));
|
||||
bvec4 lte = lessThanEqual(cs,vec4(0.04045));
|
||||
|
||||
#ifdef OLD_SELECT
|
||||
vec4 result;
|
||||
result.r = lte.r ? low_range.r : high_range.r;
|
||||
result.g = lte.g ? low_range.g : high_range.g;
|
||||
result.b = lte.b ? low_range.b : high_range.b;
|
||||
result.a = lte.a ? low_range.a : high_range.a;
|
||||
return result;
|
||||
#else
|
||||
return mix(high_range, low_range, lte);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
vec3 linear_to_srgb(vec3 cl)
|
||||
{
|
||||
cl = clamp(cl, vec3(0), vec3(1));
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ vec4 getWaterFogViewNoClip(vec3 pos)
|
|||
float t2 = kd + ks * es;
|
||||
float t3 = pow(F, t2*l) - 1.0;
|
||||
|
||||
float L = min(t1/t2*t3, 1.0);
|
||||
float L = pow(min(t1/t2*t3, 1.0), 1.0/1.7);
|
||||
|
||||
float D = pow(0.98, l*kd);
|
||||
|
||||
return vec4(srgb_to_linear(kc.rgb*L), D);
|
||||
return vec4(srgb_to_linear(kc.rgb)*L, D);
|
||||
}
|
||||
|
||||
vec4 getWaterFogView(vec3 pos)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file simpleColorF.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, 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$
|
||||
*/
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
in vec4 vertex_color;
|
||||
in vec4 vertex_position;
|
||||
|
||||
uniform vec4 waterPlane;
|
||||
uniform float waterSign;
|
||||
|
||||
void waterClip(vec3 pos)
|
||||
{
|
||||
// TODO: make this less branchy
|
||||
if (waterSign > 0)
|
||||
{
|
||||
if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) > 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
frag_color = vertex_color;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file simpleNoAtmosV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, 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$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
uniform vec4 color;
|
||||
|
||||
in vec3 position;
|
||||
|
||||
out vec4 vertex_color;
|
||||
out vec4 vertex_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
//transform vertex
|
||||
vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0));
|
||||
vertex_position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
gl_Position = vertex_position;
|
||||
vertex_color = color;
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec
|
|||
float amb_da = 0.0;//ambiance;
|
||||
if (da > 0)
|
||||
{
|
||||
lit = max(da * dist_atten,0.0);
|
||||
lit = clamp(da * dist_atten, 0.0, 1.0);
|
||||
col = lit * light_col * diffuse;
|
||||
amb_da += (da*0.5+0.5) * ambiance;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe
|
|||
float amb_da = ambiance;
|
||||
if (da >= 0)
|
||||
{
|
||||
lit = max(da * dist_atten, 0.0);
|
||||
lit = clamp(da * dist_atten, 0.0, 1.0);
|
||||
col = lit * light_col * diffuse;
|
||||
amb_da += (da*0.5 + 0.5) * ambiance;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ uniform float max_probe_lod;
|
|||
|
||||
uniform bool transparent_surface;
|
||||
|
||||
uniform int classic_mode;
|
||||
|
||||
#define MAX_REFMAP_COUNT 256 // must match LL_MAX_REFLECTION_PROBE_COUNT
|
||||
|
||||
layout (std140) uniform ReflectionProbes
|
||||
|
|
@ -739,7 +741,10 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
|
|||
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
|
||||
ambenv = sampleProbeAmbient(pos, norm, amblit);
|
||||
ambenv = amblit;
|
||||
|
||||
if (classic_mode == 0)
|
||||
ambenv = sampleProbeAmbient(pos, norm, amblit);
|
||||
|
||||
float lod = (1.0-glossiness)*reflection_lods;
|
||||
glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
|
||||
|
|
@ -784,9 +789,6 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
|
|||
probeIndex[probeInfluences++] = 0;
|
||||
|
||||
doProbeSample(ambenv, glossenv, tc, pos, norm, glossiness, false, amblit);
|
||||
|
||||
// fudge factor to get PBR water at a similar luminance ot legacy water
|
||||
glossenv *= 0.4;
|
||||
}
|
||||
|
||||
void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
|
||||
|
|
@ -845,7 +847,10 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
|
|||
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
|
||||
ambenv = sampleProbeAmbient(pos, norm, amblit);
|
||||
ambenv = amblit;
|
||||
|
||||
if (classic_mode == 0)
|
||||
ambenv = sampleProbeAmbient(pos, norm, amblit);
|
||||
|
||||
if (glossiness > 0.0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,13 +35,25 @@ vec4 getWaterFogView(vec3 pos);
|
|||
|
||||
uniform int above_water;
|
||||
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5;
|
||||
float depth = getDepth(tc.xy);
|
||||
float mask = texture(exclusionTex, tc.xy).r;
|
||||
|
||||
if (above_water > 0)
|
||||
{
|
||||
// Just discard if we're in the exclusion mask.
|
||||
// The previous invisiprim hack we're replacing would also crank up water fog desntiy.
|
||||
// But doing that makes exclusion surfaces very slow as we'd need to render even more into the mask.
|
||||
// - Geenz 2025-02-06
|
||||
if (mask < 1)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
// we want to depth test when the camera is above water, but some GPUs have a hard time
|
||||
// with depth testing against render targets that are bound for sampling in the same shader
|
||||
// so we do it manually here
|
||||
|
|
@ -51,11 +63,13 @@ void main()
|
|||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vec4 pos = getPositionWithDepth(tc, depth);
|
||||
|
||||
vec4 fogged = getWaterFogView(pos.xyz);
|
||||
fogged.a = max(pow(fogged.a, 1.7), 0);
|
||||
|
||||
frag_color = max(fogged, vec4(0)); //output linear since local lights will be added to this shader's results
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
out vec4 frag_color;
|
||||
|
||||
uniform sampler2D bumpMap;
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
#ifdef TRANSPARENT_WATER
|
||||
uniform sampler2D screenTex;
|
||||
|
|
@ -59,6 +60,9 @@ void mirrorClip(vec3 position);
|
|||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vec2 screen_tc = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
|
||||
float water_mask = texture(exclusionTex, screen_tc).r;
|
||||
|
||||
vec4 color;
|
||||
|
||||
//get detail normals
|
||||
|
|
@ -68,8 +72,8 @@ void main()
|
|||
vec3 wavef = normalize(wave1+wave2+wave3);
|
||||
|
||||
//figure out distortion vector (ripply)
|
||||
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
|
||||
distort = distort+wavef.xy*refScale;
|
||||
vec2 distort = screen_tc;
|
||||
distort = mix(distort, distort+wavef.xy*refScale, water_mask);
|
||||
|
||||
#ifdef TRANSPARENT_WATER
|
||||
vec4 fb = texture(screenTex, distort);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
// class3/environment/waterF.glsl
|
||||
|
||||
#define WATER_MINIMAL 1
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
#ifdef HAS_SUN_SHADOW
|
||||
|
|
@ -86,23 +88,17 @@ uniform sampler2D screenTex;
|
|||
uniform sampler2D depthMap;
|
||||
#endif
|
||||
|
||||
uniform sampler2D refTex;
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
uniform float sunAngle;
|
||||
uniform float sunAngle2;
|
||||
uniform int classic_mode;
|
||||
uniform vec3 lightDir;
|
||||
uniform vec3 specular;
|
||||
uniform float lightExp;
|
||||
uniform float blurMultiplier;
|
||||
uniform float refScale;
|
||||
uniform float kd;
|
||||
uniform vec2 screenRes;
|
||||
uniform vec3 normScale;
|
||||
uniform float fresnelScale;
|
||||
uniform float fresnelOffset;
|
||||
uniform float blurMultiplier;
|
||||
uniform vec4 waterFogColor;
|
||||
uniform vec3 waterFogColorLinear;
|
||||
|
||||
|
||||
//bigWave is (refCoord.w, view.w);
|
||||
in vec4 refCoord;
|
||||
|
|
@ -122,6 +118,10 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
|
|||
vec3 srgb_to_linear(vec3 col);
|
||||
vec3 linear_to_srgb(vec3 col);
|
||||
|
||||
vec3 atmosLighting(vec3 light);
|
||||
vec3 scaleSoftClip(vec3 light);
|
||||
vec3 toneMapNoExposure(vec3 color);
|
||||
|
||||
vec3 vN, vT, vB;
|
||||
|
||||
vec3 transform_normal(vec3 vNt)
|
||||
|
|
@ -132,59 +132,107 @@ vec3 transform_normal(vec3 vNt)
|
|||
void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, vec3 amblit_linear);
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit);
|
||||
|
||||
|
||||
vec3 getPositionWithNDC(vec3 ndc);
|
||||
|
||||
void generateWaveNormals(out vec3 wave1, out vec3 wave2, out vec3 wave3)
|
||||
{
|
||||
// Generate all of our wave normals.
|
||||
// We layer these back and forth.
|
||||
|
||||
vec2 bigwave = vec2(refCoord.w, view.w);
|
||||
|
||||
vec3 wave1_a = texture(bumpMap, bigwave).xyz * 2.0 - 1.0;
|
||||
vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz * 2.0 - 1.0;
|
||||
vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz * 2.0 - 1.0;
|
||||
|
||||
vec3 wave1_b = texture(bumpMap2, bigwave).xyz * 2.0 - 1.0;
|
||||
vec3 wave2_b = texture(bumpMap2, littleWave.xy).xyz * 2.0 - 1.0;
|
||||
vec3 wave3_b = texture(bumpMap2, littleWave.zw).xyz * 2.0 - 1.0;
|
||||
|
||||
wave1 = BlendNormal(wave1_a, wave1_b);
|
||||
wave2 = BlendNormal(wave2_a, wave2_b);
|
||||
wave3 = BlendNormal(wave3_a, wave3_b);
|
||||
}
|
||||
|
||||
void calculateFresnelFactors(out vec3 df3, out vec2 df2, vec3 viewVec, vec3 wave1, vec3 wave2, vec3 wave3, vec3 wavef)
|
||||
{
|
||||
// We calculate the fresnel here.
|
||||
// We do this by getting the dot product for each sets of waves, and applying scale and offset.
|
||||
|
||||
df3 = max(vec3(0), vec3(
|
||||
dot(viewVec, wave1),
|
||||
dot(viewVec, (wave2 + wave3) * 0.5),
|
||||
dot(viewVec, wave3)
|
||||
) * fresnelScale + fresnelOffset);
|
||||
|
||||
df3 *= df3;
|
||||
|
||||
df2 = max(vec2(0), vec2(
|
||||
df3.x + df3.y + df3.z,
|
||||
dot(viewVec, wavef) * fresnelScale + fresnelOffset
|
||||
));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vN = vary_normal;
|
||||
vT = vary_tangent;
|
||||
vB = cross(vN, vT);
|
||||
|
||||
vec3 pos = vary_position.xyz;
|
||||
float linear_depth = 1 / -pos.z;
|
||||
|
||||
float dist = length(pos.xyz);
|
||||
|
||||
//normalize view vector
|
||||
vec3 viewVec = normalize(pos.xyz);
|
||||
|
||||
//get wave normals
|
||||
vec2 bigwave = vec2(refCoord.w, view.w);
|
||||
vec3 wave1_a = texture(bumpMap, bigwave, -2 ).xyz*2.0-1.0;
|
||||
vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz*2.0-1.0;
|
||||
vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz*2.0-1.0;
|
||||
// Setup our waves.
|
||||
|
||||
vec3 wave1_b = texture(bumpMap2, bigwave ).xyz*2.0-1.0;
|
||||
vec3 wave2_b = texture(bumpMap2, littleWave.xy).xyz*2.0-1.0;
|
||||
vec3 wave3_b = texture(bumpMap2, littleWave.zw).xyz*2.0-1.0;
|
||||
vec3 wave1 = vec3(0, 0, 1);
|
||||
vec3 wave2 = vec3(0, 0, 1);
|
||||
vec3 wave3 = vec3(0, 0, 1);
|
||||
|
||||
//wave1_a = wave2_a = wave3_a = wave1_b = wave2_b = wave3_b = vec3(0,0,1);
|
||||
|
||||
vec3 wave1 = BlendNormal(wave1_a, wave1_b);
|
||||
vec3 wave2 = BlendNormal(wave2_a, wave2_b);
|
||||
vec3 wave3 = BlendNormal(wave3_a, wave3_b);
|
||||
generateWaveNormals(wave1, wave2, wave3);
|
||||
|
||||
float dmod = sqrt(dist);
|
||||
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
|
||||
|
||||
//wave1 = transform_normal(wave1);
|
||||
//wave2 = transform_normal(wave2);
|
||||
//wave3 = transform_normal(wave3);
|
||||
|
||||
vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
|
||||
|
||||
vec3 df3 = vec3(0);
|
||||
vec2 df2 = vec2(0);
|
||||
|
||||
vec3 sunlit;
|
||||
vec3 amblit;
|
||||
vec3 additive;
|
||||
vec3 atten;
|
||||
calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
|
||||
|
||||
calculateFresnelFactors(df3, df2, normalize(view.xyz), wave1, wave2, wave3, wavef);
|
||||
|
||||
vec3 waver = wavef*3;
|
||||
|
||||
vec3 up = transform_normal(vec3(0,0,1));
|
||||
float vdu = -dot(viewVec, up)*2;
|
||||
|
||||
vec3 wave_ibl = wavef;
|
||||
vec3 wave_ibl = wavef * normScale;
|
||||
wave_ibl.z *= 2.0;
|
||||
wave_ibl = transform_normal(normalize(wave_ibl));
|
||||
|
||||
vec3 norm = transform_normal(normalize(wavef));
|
||||
|
||||
vdu = clamp(vdu, 0, 1);
|
||||
wavef.z *= max(vdu*vdu*vdu, 0.1);
|
||||
//wavef.z *= max(vdu*vdu*vdu, 0.1);
|
||||
|
||||
wavef = normalize(wavef);
|
||||
|
||||
|
|
@ -194,62 +242,66 @@ void main()
|
|||
float dist2 = dist;
|
||||
dist = max(dist, 5.0);
|
||||
|
||||
float dmod = sqrt(dist);
|
||||
|
||||
//figure out distortion vector (ripply)
|
||||
vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0);
|
||||
vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0) * 2;
|
||||
|
||||
distort2 = clamp(distort2, vec2(0), vec2(0.999));
|
||||
|
||||
vec3 sunlit;
|
||||
vec3 amblit;
|
||||
vec3 additive;
|
||||
vec3 atten;
|
||||
|
||||
float shadow = 1.0f;
|
||||
|
||||
float water_mask = texture(exclusionTex, distort).r;
|
||||
|
||||
#ifdef HAS_SUN_SHADOW
|
||||
shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, distort);
|
||||
#endif
|
||||
|
||||
calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
|
||||
|
||||
vec3 sunlit_linear = srgb_to_linear(sunlit);
|
||||
|
||||
vec3 sunlit_linear = sunlit;
|
||||
float fade = 1;
|
||||
#ifdef TRANSPARENT_WATER
|
||||
vec4 fb = texture(screenTex, distort2);
|
||||
float depth = texture(depthMap, distort2).r;
|
||||
vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0));
|
||||
float depth = texture(depthMap, distort).r;
|
||||
|
||||
if (refPos.z > pos.z-0.05)
|
||||
vec3 refPos = getPositionWithNDC(vec3(distort*2.0-vec2(1.0), depth*2.0-1.0));
|
||||
|
||||
// Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect".
|
||||
fade = max(0,min(1, (pos.z - refPos.z) / 10)) * water_mask;
|
||||
distort2 = mix(distort, distort2, min(1, fade * 10));
|
||||
depth = texture(depthMap, distort2).r;
|
||||
|
||||
refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
|
||||
|
||||
if (pos.z < refPos.z - 0.05)
|
||||
{
|
||||
//we sampled an above water sample, don't distort
|
||||
distort2 = distort;
|
||||
fb = texture(screenTex, distort2);
|
||||
depth = texture(depthMap, distort2).r;
|
||||
refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
|
||||
}
|
||||
|
||||
vec4 fb = texture(screenTex, distort2);
|
||||
|
||||
#else
|
||||
vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0));
|
||||
|
||||
if (water_mask < 1)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
// fudge sample on other side of water to be a tad darker
|
||||
fb.rgb *= 0.75;
|
||||
|
||||
float metallic = 0.0;
|
||||
float perceptualRoughness = 0.05;
|
||||
float gloss = 1.0 - perceptualRoughness;
|
||||
float metallic = 1.0;
|
||||
float perceptualRoughness = blurMultiplier;
|
||||
float gloss = 1 - perceptualRoughness;
|
||||
|
||||
vec3 irradiance = vec3(0);
|
||||
vec3 radiance = vec3(0);
|
||||
sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit);
|
||||
vec3 legacyenv = vec3(0);
|
||||
|
||||
irradiance = vec3(0);
|
||||
// TODO: Make this an option.
|
||||
#ifdef WATER_MINIMAL
|
||||
sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit);
|
||||
#elif WATER_MINIMAL_PLUS
|
||||
sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, false, amblit);
|
||||
#endif
|
||||
|
||||
vec3 diffuseColor = vec3(0);
|
||||
vec3 specularColor = vec3(0);
|
||||
calcDiffuseSpecular(vec3(1), metallic, diffuseColor, specularColor);
|
||||
vec3 specular_linear = srgb_to_linear(specular);
|
||||
calcDiffuseSpecular(specular_linear, metallic, diffuseColor, specularColor);
|
||||
|
||||
vec3 v = -normalize(pos.xyz);
|
||||
|
||||
|
|
@ -257,46 +309,36 @@ void main()
|
|||
float ao = 1.0;
|
||||
vec3 light_dir = transform_normal(lightDir);
|
||||
|
||||
perceptualRoughness = 0.0;
|
||||
metallic = 1.0;
|
||||
|
||||
float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0);
|
||||
|
||||
float nl = 0;
|
||||
vec3 diffPunc = vec3(0);
|
||||
vec3 specPunc = vec3(0);
|
||||
|
||||
pbrPunctual(vec3(0), specularColor, 0.1, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc);
|
||||
pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc);
|
||||
|
||||
vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10));
|
||||
vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)) * sunlit_linear * shadow * atten;
|
||||
radiance *= df2.y;
|
||||
//radiance = toneMapNoExposure(radiance);
|
||||
vec3 color = vec3(0);
|
||||
color = mix(fb.rgb, radiance, min(1, df2.x)) + punctual.rgb;
|
||||
|
||||
vec3 color = punctual * sunlit_linear * 2.75 * shadow;
|
||||
vec3 iblDiff;
|
||||
vec3 iblSpec;
|
||||
pbrIbl(vec3(0), vec3(1), radiance, vec3(0), ao, NdotV, 0.0, iblDiff, iblSpec);
|
||||
float water_haze_scale = 4;
|
||||
|
||||
color += iblDiff + iblSpec;
|
||||
if (classic_mode > 0)
|
||||
water_haze_scale = 1;
|
||||
|
||||
float nv = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0);
|
||||
vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0);
|
||||
float f = 1.0-brdf.y; //1.0 - (brdf.x+brdf.y);
|
||||
f *= 0.9;
|
||||
f *= f;
|
||||
// This looks super janky, but we do this to restore water haze in the distance.
|
||||
// These values were finagled in to try and bring back some of the distant brightening on legacy water. Also works reasonably well on PBR skies such as PBR midday.
|
||||
// color = mix(color, additive * water_haze_scale, (1 - atten));
|
||||
|
||||
// incoming scale is [0, 1] with 0.5 being default
|
||||
// shift to 0.5 to 1.5
|
||||
f *= (fresnelScale - 0.5)+1.0;
|
||||
// We shorten the fade here at the shoreline so it doesn't appear too soft from a distance.
|
||||
fade *= 60;
|
||||
fade = min(1, fade);
|
||||
color = mix(fb.rgb, color, fade);
|
||||
|
||||
// incoming offset is [0, 1] with 0.5 being default
|
||||
// shift from -1 to 1
|
||||
f += (fresnelOffset - 0.5) * 2.0;
|
||||
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0);
|
||||
|
||||
f = clamp(f, 0, 1);
|
||||
|
||||
color = ((1.0 - f) * color) + fb.rgb;
|
||||
|
||||
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05);
|
||||
|
||||
frag_color = max(vec4(color, spec), vec4(0));
|
||||
frag_color = min(vec4(1),max(vec4(color.rgb, spec * water_mask), vec4(0)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ RenderExposure 1 4
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 1
|
||||
RenderDisableVintageMode 1 1
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Low Graphics Settings
|
||||
|
|
@ -126,6 +127,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 512
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -167,6 +169,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 1024
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -207,6 +210,7 @@ RenderCASSharpness 1 0
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -247,6 +251,7 @@ RenderCASSharpness 1 0
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -287,6 +292,7 @@ RenderCASSharpness 1 0.4
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (deferred + SSAO + all shadows)
|
||||
|
|
@ -327,6 +333,7 @@ RenderCASSharpness 1 0.4
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -367,6 +374,7 @@ RenderCASSharpness 1 0.4
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -399,6 +407,7 @@ RenderShadowDetail 0 0
|
|||
RenderReflectionProbeDetail 0 -1
|
||||
RenderMirrors 0 0
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
list Intel
|
||||
RenderAnisotropic 1 0
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ RenderTonemapType 1 1
|
|||
RenderTonemapMix 1 1
|
||||
RenderDisableVintageMode 1 1
|
||||
RenderDownScaleMethod 1 0
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Low Graphics Settings
|
||||
|
|
@ -126,6 +127,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 512
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -167,6 +169,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 1024
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -207,6 +210,7 @@ RenderCASSharpness 1 0
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -247,6 +251,7 @@ RenderCASSharpness 1 0
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -287,6 +292,7 @@ RenderCASSharpness 1 0
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (SSAO + all shadows)
|
||||
|
|
@ -327,6 +333,7 @@ RenderCASSharpness 1 0.4
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -367,6 +374,7 @@ RenderCASSharpness 1 0.4
|
|||
RenderExposure 1 1
|
||||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -398,6 +406,7 @@ RenderDeferredSSAO 0 0
|
|||
RenderShadowDetail 0 0
|
||||
RenderMirrors 0 0
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 2048
|
||||
|
||||
list TexUnit8orLess
|
||||
RenderDeferredSSAO 0 0
|
||||
|
|
|
|||
|
|
@ -356,8 +356,9 @@ void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
|
|||
llassert(obj->getVolume()->getParams().getSculptID() == gltf_id);
|
||||
llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF);
|
||||
|
||||
if (obj->mGLTFAsset)
|
||||
{ // object already has a GLTF asset, don't reload it
|
||||
if (obj->mGLTFAsset || obj->mIsGLTFAssetMissing )
|
||||
{
|
||||
// object already has a GLTF asset or load failed, don't reload it
|
||||
|
||||
// TODO: below assertion fails on dupliate requests for assets -- possibly need to touch up asset loading state machine
|
||||
// llassert(std::find(mObjects.begin(), mObjects.end(), obj) != mObjects.end());
|
||||
|
|
@ -398,16 +399,19 @@ void GLTFSceneManager::onGLTFBinLoadComplete(const LLUUID& id, LLAssetType::ETyp
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("GLTF") << "Failed to prepare GLTF asset: " << id << LL_ENDL;
|
||||
LL_WARNS("GLTF") << "Failed to prepare GLTF asset: " << id << ". Marking as missing." << LL_ENDL;
|
||||
obj->mIsGLTFAssetMissing = true;
|
||||
obj->mGLTFAsset = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
obj->unref(); // todo: use LLPointer
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << LL_ENDL;
|
||||
LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << ". Marking as missing." << LL_ENDL;
|
||||
obj->mIsGLTFAssetMissing = true;
|
||||
obj->unref();
|
||||
}
|
||||
});
|
||||
|
|
@ -446,7 +450,8 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("GLTF") << "Buffer URI is not a valid UUID: " << buffer.mUri << LL_ENDL;
|
||||
LL_WARNS("GLTF") << "Buffer URI is not a valid UUID: " << buffer.mUri << " for asset id: " << id << ". Marking as missing." << LL_ENDL;
|
||||
obj->mIsGLTFAssetMissing = true;
|
||||
obj->unref();
|
||||
return;
|
||||
}
|
||||
|
|
@ -455,7 +460,8 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << LL_ENDL;
|
||||
LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << ". Marking as missing." << LL_ENDL;
|
||||
obj->mIsGLTFAssetMissing = true;
|
||||
obj->unref();
|
||||
}
|
||||
}
|
||||
|
|
@ -500,7 +506,7 @@ void GLTFSceneManager::update()
|
|||
LLNewBufferedResourceUploadInfo::uploadFinish_f finish = [this, buffer](LLUUID assetId, LLSD response)
|
||||
{
|
||||
LLAppViewer::instance()->postToMainCoro(
|
||||
[=]()
|
||||
[=, this]()
|
||||
{
|
||||
if (mUploadingAsset)
|
||||
{
|
||||
|
|
@ -517,6 +523,7 @@ void GLTFSceneManager::update()
|
|||
if (mUploadingObject)
|
||||
{
|
||||
mUploadingObject->mGLTFAsset = nullptr;
|
||||
mUploadingObject->mIsGLTFAssetMissing = false;
|
||||
mUploadingObject->setGLTFAsset(assetId);
|
||||
mUploadingObject->markForUpdate();
|
||||
mUploadingObject = nullptr;
|
||||
|
|
@ -975,9 +982,9 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset)
|
|||
|
||||
LLVector4a t;
|
||||
agent_to_asset.affineTransform(gDebugRaycastStart, t);
|
||||
start = glm::make_vec4(t.getF32ptr());
|
||||
start = vec4(t);
|
||||
agent_to_asset.affineTransform(gDebugRaycastEnd, t);
|
||||
end = glm::make_vec4(t.getF32ptr());
|
||||
end = vec4(t);
|
||||
|
||||
start.w = end.w = 1.0;
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "llgroupmgr.h"
|
||||
#include "llhudmanager.h"
|
||||
#include "lljoystickbutton.h"
|
||||
#include "lllandmarkactions.h"
|
||||
#include "llmorphview.h"
|
||||
#include "llmoveview.h"
|
||||
#include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state
|
||||
|
|
@ -4317,8 +4318,17 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
|
|||
|
||||
void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id)
|
||||
{
|
||||
LLViewerRegion *regionp = getRegion();
|
||||
if(regionp && teleportCore())
|
||||
bool is_local(false);
|
||||
LLViewerRegion* regionp = getRegion();
|
||||
|
||||
if (LLLandmark* landmark = gLandmarkList.getAsset(landmark_asset_id, NULL))
|
||||
{
|
||||
LLVector3d pos_global;
|
||||
landmark->getGlobalPos(pos_global);
|
||||
is_local = (regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]));
|
||||
}
|
||||
|
||||
if(regionp && teleportCore(is_local))
|
||||
{
|
||||
LL_INFOS("Teleport") << "Sending TeleportLandmarkRequest. Current region handle " << regionp->getHandle()
|
||||
<< " region id " << regionp->getRegionID()
|
||||
|
|
@ -4879,10 +4889,19 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename)
|
|||
LLXMLNodePtr root;
|
||||
bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
|
||||
|
||||
if (!success || !root || !root->hasName( "teleport_messages" ))
|
||||
if (!success)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showMissingFiles();
|
||||
LL_ERRS() << "Problem reading teleport string XML file: "
|
||||
<< xml_filename << LL_ENDL;
|
||||
<< xml_filename << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root || !root->hasName("teleport_messages"))
|
||||
{
|
||||
LLError::LLUserWarningMsg::showMissingFiles();
|
||||
LL_ERRS() << "Invalid teleport string XML file: "
|
||||
<< xml_filename << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "llagentpicksinfo.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentbenefits.h"
|
||||
#include "llavatarpropertiesprocessor.h"
|
||||
|
||||
const S32 MAX_AVATAR_PICKS = 10;
|
||||
|
|
@ -85,10 +86,9 @@ private:
|
|||
|
||||
LLAgentPicksInfo::LLAgentPicksInfo()
|
||||
: mAgentPicksObserver(NULL)
|
||||
, mMaxNumberOfPicks(MAX_AVATAR_PICKS)
|
||||
// Disable Pick creation until we get number of Picks from server - in case
|
||||
// avatar has maximum number of Picks.
|
||||
, mNumberOfPicks(mMaxNumberOfPicks)
|
||||
, mNumberOfPicks(S32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +110,13 @@ void LLAgentPicksInfo::requestNumberOfPicks()
|
|||
mAgentPicksObserver->sendAgentPicksRequest();
|
||||
}
|
||||
|
||||
bool LLAgentPicksInfo::isPickLimitReached()
|
||||
// static
|
||||
S32 LLAgentPicksInfo::getMaxNumberOfPicks()
|
||||
{
|
||||
return LLAgentBenefitsMgr::current().getPicksLimit();
|
||||
}
|
||||
|
||||
bool LLAgentPicksInfo::isPickLimitReached() const
|
||||
{
|
||||
return getNumberOfPicks() >= getMaxNumberOfPicks();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,17 +52,17 @@ public:
|
|||
/**
|
||||
* Returns number of Picks.
|
||||
*/
|
||||
S32 getNumberOfPicks() { return mNumberOfPicks; }
|
||||
S32 getNumberOfPicks() const { return mNumberOfPicks; }
|
||||
|
||||
/**
|
||||
* Returns maximum number of Picks.
|
||||
*/
|
||||
S32 getMaxNumberOfPicks() { return mMaxNumberOfPicks; }
|
||||
static S32 getMaxNumberOfPicks();
|
||||
|
||||
/**
|
||||
* Returns true if Agent has maximum allowed number of Picks.
|
||||
*/
|
||||
bool isPickLimitReached();
|
||||
bool isPickLimitReached() const;
|
||||
|
||||
/**
|
||||
* After creating or deleting a Pick we can assume operation on server will be
|
||||
|
|
@ -83,15 +83,9 @@ private:
|
|||
*/
|
||||
void setNumberOfPicks(S32 number) { mNumberOfPicks = number; }
|
||||
|
||||
/**
|
||||
* Sets maximum number of Picks.
|
||||
*/
|
||||
void setMaxNumberOfPicks(S32 max_picks) { mMaxNumberOfPicks = max_picks; }
|
||||
|
||||
private:
|
||||
|
||||
LLAgentPicksObserver* mAgentPicksObserver;
|
||||
S32 mMaxNumberOfPicks;
|
||||
S32 mNumberOfPicks;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -537,9 +537,14 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
|
|||
|
||||
selfStopPhase("update_appearance_on_destroy");
|
||||
|
||||
LLAppearanceMgr::instance().updateAppearanceFromCOF(mEnforceItemRestrictions,
|
||||
mEnforceOrdering,
|
||||
mPostUpdateFunc);
|
||||
//avoid calling an update inside coroutine
|
||||
bool force_restrictions(mEnforceItemRestrictions);
|
||||
bool enforce_ordering(mEnforceOrdering);
|
||||
nullary_func_t post_update_func(mPostUpdateFunc);
|
||||
doOnIdleOneTime([force_restrictions,enforce_ordering,post_update_func]()
|
||||
{
|
||||
LLAppearanceMgr::instance().updateAppearanceFromCOF(force_restrictions, enforce_ordering, post_update_func);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ bool gUseQuickTime = true;
|
|||
|
||||
eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
|
||||
S32 gLastExecDuration = -1; // (<0 indicates unknown)
|
||||
LLUUID gLastAgentSessionId;
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define LL_PLATFORM_KEY "win"
|
||||
|
|
@ -372,7 +373,6 @@ const int MAX_MARKER_LENGTH = 1024;
|
|||
const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
|
||||
const std::string START_MARKER_FILE_NAME("SecondLife.start_marker");
|
||||
const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
|
||||
const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
|
||||
const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
|
||||
static bool gDoDisconnect = false;
|
||||
static std::string gLaunchFileOnQuit;
|
||||
|
|
@ -2219,6 +2219,7 @@ bool LLAppViewer::initThreads()
|
|||
return true;
|
||||
}
|
||||
|
||||
// Callback for all LL_ERROR calls
|
||||
void errorCallback(LLError::ELevel level, const std::string &error_string)
|
||||
{
|
||||
if (level == LLError::LEVEL_ERROR)
|
||||
|
|
@ -2234,15 +2235,38 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
|
|||
// haven't actually trashed anything yet, we can afford to write the whole
|
||||
// static info file.
|
||||
LLAppViewer::instance()->writeDebugInfo();
|
||||
|
||||
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
|
||||
if (!LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
|
||||
{
|
||||
// If marker doesn't exist, create a marker with llerror code for next launch
|
||||
// otherwise don't override existing file
|
||||
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LLERROR_CRASH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void errorMSG(const std::string& title_string, const std::string& message_string)
|
||||
// Callback for LLError::LLUserWarningMsg
|
||||
void errorHandler(const std::string& title_string, const std::string& message_string, S32 code)
|
||||
{
|
||||
if (!message_string.empty())
|
||||
{
|
||||
OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case LLError::LLUserWarningMsg::ERROR_OTHER:
|
||||
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_OTHER_CRASH);
|
||||
break;
|
||||
case LLError::LLUserWarningMsg::ERROR_BAD_ALLOC:
|
||||
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_BAD_ALLOC);
|
||||
break;
|
||||
case LLError::LLUserWarningMsg::ERROR_MISSING_FILES:
|
||||
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LLAppViewer::initLoggingAndGetLastDuration()
|
||||
|
|
@ -2256,7 +2280,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
|
|||
LLError::addGenericRecorder(&errorCallback);
|
||||
//LLError::setTimeFunction(getRuntime);
|
||||
|
||||
LLError::LLUserWarningMsg::setHandler(errorMSG);
|
||||
LLError::LLUserWarningMsg::setHandler(errorHandler);
|
||||
|
||||
|
||||
if (mSecondInstance)
|
||||
|
|
@ -2540,6 +2564,7 @@ bool LLAppViewer::initConfiguration()
|
|||
OSMessageBox(
|
||||
"Unable to load default settings file. The installation may be corrupted.",
|
||||
LLStringUtil::null,OSMB_OK);
|
||||
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -3702,16 +3727,21 @@ bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const
|
|||
bool sameVersion = false;
|
||||
|
||||
std::string my_version(LLVersionInfo::instance().getChannelAndVersion());
|
||||
char marker_version[MAX_MARKER_LENGTH];
|
||||
char marker_data[MAX_MARKER_LENGTH];
|
||||
S32 marker_version_length;
|
||||
|
||||
LLAPRFile marker_file;
|
||||
marker_file.open(marker_name, LL_APR_RB);
|
||||
if (marker_file.getFileHandle())
|
||||
{
|
||||
marker_version_length = marker_file.read(marker_version, sizeof(marker_version));
|
||||
std::string marker_string(marker_version, marker_version_length);
|
||||
if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) )
|
||||
marker_version_length = marker_file.read(marker_data, sizeof(marker_data));
|
||||
std::string marker_string(marker_data, marker_version_length);
|
||||
size_t pos = marker_string.find('\n');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
marker_string = marker_string.substr(0, pos);
|
||||
}
|
||||
if ( 0 == my_version.compare( 0, my_version.length(), marker_string, 0, marker_string.length()) )
|
||||
{
|
||||
sameVersion = true;
|
||||
}
|
||||
|
|
@ -3725,6 +3755,88 @@ bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const
|
|||
return sameVersion;
|
||||
}
|
||||
|
||||
void LLAppViewer::recordSessionToMarker()
|
||||
{
|
||||
std::string marker_version(LLVersionInfo::instance().getChannelAndVersion());
|
||||
std::string uuid_str = "\n" + gAgentSessionID.asString();
|
||||
if (marker_version.length() + uuid_str.length() > MAX_MARKER_LENGTH)
|
||||
{
|
||||
LL_WARNS_ONCE("MarkerFile") << "Version length (" << marker_version.length() << ")"
|
||||
<< " greater than maximum (" << MAX_MARKER_LENGTH << ")"
|
||||
<< ": marker matching may be incorrect"
|
||||
<< LL_ENDL;
|
||||
}
|
||||
|
||||
mMarkerFile.seek(APR_SET, (S32)marker_version.length());
|
||||
mMarkerFile.write(uuid_str.data(), (S32)uuid_str.length());
|
||||
}
|
||||
|
||||
LLUUID LLAppViewer::getMarkerSessionId(const std::string& marker_name) const
|
||||
{
|
||||
std::string data;
|
||||
if (getMarkerData(marker_name, data))
|
||||
{
|
||||
return LLUUID(data);
|
||||
}
|
||||
return LLUUID();
|
||||
}
|
||||
|
||||
S32 LLAppViewer::getMarkerErrorCode(const std::string& marker_name) const
|
||||
{
|
||||
std::string data;
|
||||
if (getMarkerData(marker_name, data))
|
||||
{
|
||||
if (data.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::stoi(data);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool LLAppViewer::getMarkerData(const std::string& marker_name, std::string& data) const
|
||||
{
|
||||
bool sameVersion = false;
|
||||
|
||||
std::string my_version(LLVersionInfo::instance().getChannelAndVersion());
|
||||
char marker_data[MAX_MARKER_LENGTH];
|
||||
S32 marker_version_length;
|
||||
|
||||
LLAPRFile marker_file;
|
||||
marker_file.open(marker_name, LL_APR_RB);
|
||||
if (marker_file.getFileHandle())
|
||||
{
|
||||
marker_version_length = marker_file.read(marker_data, sizeof(marker_data));
|
||||
marker_file.close();
|
||||
std::string marker_string(marker_data, marker_version_length);
|
||||
size_t pos = marker_string.find('\n');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
data = marker_string.substr(pos + 1, marker_version_length - pos - 1);
|
||||
marker_string = marker_string.substr(0, pos);
|
||||
}
|
||||
if (0 == my_version.compare(0, my_version.length(), marker_string, 0, marker_string.length()))
|
||||
{
|
||||
sameVersion = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': "
|
||||
<< "\n mine '" << my_version << "'"
|
||||
<< "\n marker '" << marker_string << "'"
|
||||
<< "\n " << (sameVersion ? "same" : "different") << " version"
|
||||
<< LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLAppViewer::processMarkerFiles()
|
||||
{
|
||||
//We've got 4 things to test for here
|
||||
|
|
@ -3743,6 +3855,10 @@ void LLAppViewer::processMarkerFiles()
|
|||
// File exists...
|
||||
// first, read it to see if it was created by the same version (we need this later)
|
||||
marker_is_same_version = markerIsSameVersion(mMarkerFileName);
|
||||
if (marker_is_same_version)
|
||||
{
|
||||
gLastAgentSessionId = getMarkerSessionId(mMarkerFileName);
|
||||
}
|
||||
|
||||
// now test to see if this file is locked by a running process (try to open for write)
|
||||
marker_log_stream << "Checking exec marker file for lock...";
|
||||
|
|
@ -3832,44 +3948,27 @@ void LLAppViewer::processMarkerFiles()
|
|||
}
|
||||
LLAPRFile::remove(logout_marker_file);
|
||||
}
|
||||
// further refine based on whether or not a marker created during an llerr crash is found
|
||||
std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
|
||||
if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
|
||||
{
|
||||
if (markerIsSameVersion(llerror_marker_file))
|
||||
{
|
||||
if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE )
|
||||
{
|
||||
gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
|
||||
LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
|
||||
LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL;
|
||||
}
|
||||
LLAPRFile::remove(llerror_marker_file);
|
||||
}
|
||||
// and last refine based on whether or not a marker created during a non-llerr crash is found
|
||||
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
|
||||
if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
|
||||
{
|
||||
if (markerIsSameVersion(error_marker_file))
|
||||
S32 marker_code = getMarkerErrorCode(error_marker_file);
|
||||
if (marker_code >= 0)
|
||||
{
|
||||
if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
|
||||
{
|
||||
gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
|
||||
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
|
||||
}
|
||||
else if (marker_code > 0 && marker_code < (S32)LAST_EXEC_COUNT)
|
||||
{
|
||||
gLastExecEvent = (eLastExecEvent)marker_code;
|
||||
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gLastExecEvent = LAST_EXEC_OTHER_CRASH;
|
||||
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
|
||||
LL_INFOS("MarkerFile") << "Error marker '" << error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -5159,6 +5258,24 @@ void LLAppViewer::postToMainCoro(const LL::WorkQueue::Work& work)
|
|||
gMainloopWork.post(work);
|
||||
}
|
||||
|
||||
void LLAppViewer::createErrorMarker(eLastExecEvent error_code) const
|
||||
{
|
||||
if (!mSecondInstance)
|
||||
{
|
||||
std::string error_marker = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
|
||||
|
||||
LLAPRFile file;
|
||||
file.open(error_marker, LL_APR_WB);
|
||||
if (file.getFileHandle())
|
||||
{
|
||||
recordMarkerVersion(file);
|
||||
std::string data = "\n" + std::to_string((S32)error_code);
|
||||
file.write(data.data(), static_cast<S32>(data.length()));
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLAppViewer::outOfMemorySoftQuit()
|
||||
{
|
||||
if (!mQuitRequested)
|
||||
|
|
|
|||
|
|
@ -66,6 +66,20 @@ class LLViewerRegion;
|
|||
|
||||
extern LLTrace::BlockTimerStatHandle FTM_FRAME;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LAST_EXEC_NORMAL = 0,
|
||||
LAST_EXEC_FROZE,
|
||||
LAST_EXEC_LLERROR_CRASH,
|
||||
LAST_EXEC_OTHER_CRASH,
|
||||
LAST_EXEC_LOGOUT_FROZE,
|
||||
LAST_EXEC_LOGOUT_CRASH,
|
||||
LAST_EXEC_BAD_ALLOC,
|
||||
LAST_EXEC_MISSING_FILES,
|
||||
LAST_EXEC_GRAPHICS_INIT,
|
||||
LAST_EXEC_COUNT
|
||||
} eLastExecEvent;
|
||||
|
||||
class LLAppViewer : public LLApp
|
||||
{
|
||||
public:
|
||||
|
|
@ -147,6 +161,7 @@ public:
|
|||
void saveExperienceCache();
|
||||
|
||||
void removeMarkerFiles();
|
||||
void recordSessionToMarker();
|
||||
|
||||
void removeDumpDir();
|
||||
// LLAppViewer testing helpers.
|
||||
|
|
@ -227,6 +242,9 @@ public:
|
|||
// post given work to the "mainloop" work queue for handling on the main thread
|
||||
void postToMainCoro(const LL::WorkQueue::Work& work);
|
||||
|
||||
// Writes an error code into the error_marker file for use on next startup.
|
||||
void createErrorMarker(eLastExecEvent error_code) const;
|
||||
|
||||
// Attempt a 'soft' quit with disconnect and saving of settings/cache.
|
||||
// Intended to be thread safe.
|
||||
// Good chance of viewer crashing either way, but better than alternatives.
|
||||
|
|
@ -272,6 +290,9 @@ private:
|
|||
void processMarkerFiles();
|
||||
static void recordMarkerVersion(LLAPRFile& marker_file);
|
||||
bool markerIsSameVersion(const std::string& marker_name) const;
|
||||
LLUUID getMarkerSessionId(const std::string& marker_name) const;
|
||||
S32 getMarkerErrorCode(const std::string& marker_name) const;
|
||||
bool getMarkerData(const std::string& marker_name, std::string &data) const;
|
||||
|
||||
void idle();
|
||||
void idleShutdown();
|
||||
|
|
@ -347,18 +368,9 @@ private:
|
|||
extern LLSD gDebugInfo;
|
||||
extern bool gShowObjectUpdates;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LAST_EXEC_NORMAL = 0,
|
||||
LAST_EXEC_FROZE,
|
||||
LAST_EXEC_LLERROR_CRASH,
|
||||
LAST_EXEC_OTHER_CRASH,
|
||||
LAST_EXEC_LOGOUT_FROZE,
|
||||
LAST_EXEC_LOGOUT_CRASH
|
||||
} eLastExecEvent;
|
||||
|
||||
extern eLastExecEvent gLastExecEvent; // llstartup
|
||||
extern S32 gLastExecDuration; ///< the duration of the previous run in seconds (<0 indicates unknown)
|
||||
extern LLUUID gLastAgentSessionId; // will be set if agent logged in
|
||||
|
||||
extern const char* gPlatform;
|
||||
|
||||
|
|
|
|||
|
|
@ -357,8 +357,9 @@ void LLConversationItemSession::clearParticipants()
|
|||
|
||||
void LLConversationItemSession::clearAndDeparentModels()
|
||||
{
|
||||
for (LLFolderViewModelItem* child : mChildren)
|
||||
for (child_list_t::iterator it = mChildren.begin(); it != mChildren.end();)
|
||||
{
|
||||
LLFolderViewModelItem* child = *it;
|
||||
if (child->getNumRefs() == 0)
|
||||
{
|
||||
// LLConversationItemParticipant can be created but not assigned to any view,
|
||||
|
|
@ -370,8 +371,8 @@ void LLConversationItemSession::clearAndDeparentModels()
|
|||
// Model is still assigned to some view/widget
|
||||
child->setParent(NULL);
|
||||
}
|
||||
it = mChildren.erase(it);
|
||||
}
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "lldrawpooltree.h"
|
||||
#include "lldrawpoolterrain.h"
|
||||
#include "lldrawpoolwater.h"
|
||||
#include "lldrawpoolwaterexclusion.h"
|
||||
#include "llface.h"
|
||||
#include "llviewerobjectlist.h" // For debug listing.
|
||||
#include "pipeline.h"
|
||||
|
|
@ -119,6 +120,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
|
|||
case POOL_GLTF_PBR_ALPHA_MASK:
|
||||
poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK);
|
||||
break;
|
||||
case POOL_WATEREXCLUSION:
|
||||
poolp = new LLDrawPoolWaterExclusion();
|
||||
break;
|
||||
default:
|
||||
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
// based on fill rate and likelihood to occlude future passes (faster, large occluders first).
|
||||
//
|
||||
POOL_SKY = 1,
|
||||
POOL_WATEREXCLUSION,
|
||||
POOL_WL_SKY,
|
||||
POOL_SIMPLE,
|
||||
POOL_FULLBRIGHT,
|
||||
|
|
@ -140,7 +141,7 @@ public:
|
|||
PASS_GRASS,
|
||||
PASS_FULLBRIGHT,
|
||||
PASS_FULLBRIGHT_RIGGED,
|
||||
PASS_INVISIBLE,
|
||||
PASS_INVISIBLE, // Formerly, invisiprims. Now, water exclusion surfaces.
|
||||
PASS_INVISIBLE_RIGGED,
|
||||
PASS_INVISI_SHINY,
|
||||
PASS_INVISI_SHINY_RIGGED,
|
||||
|
|
|
|||
|
|
@ -176,175 +176,158 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass)
|
|||
light_diffuse *= (1.5f + (6.f * ground_proj_sq));
|
||||
}
|
||||
|
||||
// set up normal maps filtering
|
||||
for (auto norm_map : mWaterNormp)
|
||||
{
|
||||
if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
|
||||
}
|
||||
LLTexUnit::eTextureFilterOptions filter_mode = has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT;
|
||||
|
||||
LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor());
|
||||
F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f;
|
||||
LLGLSLShader *shader = nullptr;
|
||||
|
||||
// two passes, first with standard water shader bound, second with edge water shader bound
|
||||
for (int edge = 0; edge < 2; edge++)
|
||||
// One pass, one of two shaders. Void water and region water share state.
|
||||
// There isn't a good reason anymore to really have void water run in a separate pass.
|
||||
// It also just introduced a bunch of weird state consistency stuff that we really don't need.
|
||||
// Not to mention, re-binding the the same shader and state for that shader is kind of wasteful.
|
||||
// - Geenz 2025-02-11
|
||||
// select shader
|
||||
if (underwater)
|
||||
{
|
||||
// select shader
|
||||
if (underwater)
|
||||
{
|
||||
shader = &gUnderWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edge)
|
||||
{
|
||||
shader = &gWaterEdgeProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gWaterProgram;
|
||||
}
|
||||
}
|
||||
|
||||
gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis);
|
||||
|
||||
//bind normal map
|
||||
S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
|
||||
S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2);
|
||||
|
||||
LLViewerTexture* tex_a = mWaterNormp[0];
|
||||
LLViewerTexture* tex_b = mWaterNormp[1];
|
||||
|
||||
F32 blend_factor = (F32)pwater->getBlendFactor();
|
||||
|
||||
gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
if (tex_a && (!tex_b || (tex_a == tex_b)))
|
||||
{
|
||||
gGL.getTexUnit(bumpTex)->bind(tex_a);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b && !tex_a)
|
||||
{
|
||||
gGL.getTexUnit(bumpTex)->bind(tex_b);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b != tex_a)
|
||||
{
|
||||
gGL.getTexUnit(bumpTex)->bind(tex_a);
|
||||
gGL.getTexUnit(bumpTex2)->bind(tex_b);
|
||||
}
|
||||
|
||||
// bind reflection texture from RenderTarget
|
||||
S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
|
||||
|
||||
F32 screenRes[] = { 1.f / gGLViewport[2], 1.f / gGLViewport[3] };
|
||||
|
||||
shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
|
||||
shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
|
||||
|
||||
F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
|
||||
|
||||
if (screentex > -1)
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
|
||||
gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);
|
||||
}
|
||||
|
||||
if (mShaderLevel == 1)
|
||||
{
|
||||
fog_color.mV[VALPHA] = (F32)(log(fog_density) / log(2));
|
||||
}
|
||||
|
||||
F32 water_height = environment.getWaterHeight();
|
||||
F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
|
||||
shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height);
|
||||
shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time);
|
||||
shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV);
|
||||
shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
|
||||
shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR_LINEAR, 1, fog_color_linear.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
|
||||
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
|
||||
shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier());
|
||||
|
||||
F32 sunAngle = llmax(0.f, light_dir.mV[1]);
|
||||
F32 scaledAngle = 1.f - sunAngle;
|
||||
|
||||
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle);
|
||||
shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
|
||||
|
||||
// SL-15861 This was changed from getRotatedLightNorm() as it was causing
|
||||
// lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV.
|
||||
LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm();
|
||||
shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
if (LLViewerCamera::getInstance()->cameraUnderWater())
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
|
||||
}
|
||||
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
|
||||
LLVOWater* water = nullptr;
|
||||
for (LLFace* const& face : mDrawFace)
|
||||
{
|
||||
if (!face) continue;
|
||||
water = static_cast<LLVOWater*>(face->getViewerObject());
|
||||
if (!water) continue;
|
||||
|
||||
if ((bool)edge == (bool)water->getIsEdgePatch())
|
||||
{
|
||||
face->renderIndexed();
|
||||
|
||||
// Note non-void water being drawn, updates required
|
||||
if (!edge) // SL-16461 remove !LLPipeline::sUseOcclusion check
|
||||
{
|
||||
sNeedsReflectionUpdate = true;
|
||||
sNeedsDistortionUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||
shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);
|
||||
shader->disableTexture(LLShaderMgr::BUMP_MAP);
|
||||
shader->disableTexture(LLShaderMgr::WATER_REFTEX);
|
||||
|
||||
// clean up
|
||||
gPipeline.unbindDeferredShader(*shader);
|
||||
|
||||
gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
shader = &gUnderWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gWaterProgram;
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->activate();
|
||||
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
|
||||
gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis);
|
||||
|
||||
LLViewerTexture* tex_a = mWaterNormp[0];
|
||||
LLViewerTexture* tex_b = mWaterNormp[1];
|
||||
|
||||
F32 blend_factor = (F32)pwater->getBlendFactor();
|
||||
|
||||
if (tex_a && (!tex_b || (tex_a == tex_b)))
|
||||
{
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
|
||||
tex_a->setFilteringOption(filter_mode);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b && !tex_a)
|
||||
{
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_b);
|
||||
tex_b->setFilteringOption(filter_mode);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b != tex_a)
|
||||
{
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
|
||||
tex_a->setFilteringOption(filter_mode);
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP2, tex_b);
|
||||
tex_b->setFilteringOption(filter_mode);
|
||||
}
|
||||
|
||||
shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask);
|
||||
|
||||
shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
|
||||
|
||||
F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
|
||||
|
||||
shader->bindTexture(LLShaderMgr::WATER_SCREENTEX, &gPipeline.mWaterDis);
|
||||
|
||||
if (mShaderLevel == 1)
|
||||
{
|
||||
fog_color.mV[VALPHA] = (F32)(log(fog_density) / log(2));
|
||||
}
|
||||
|
||||
F32 water_height = environment.getWaterHeight();
|
||||
F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
|
||||
shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height);
|
||||
shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time);
|
||||
shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
|
||||
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
|
||||
shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, fmaxf(0, pwater->getBlurMultiplier()) * 2);
|
||||
|
||||
static LLStaticHashedString s_exposure("exposure");
|
||||
static LLStaticHashedString tonemap_mix("tonemap_mix");
|
||||
static LLStaticHashedString tonemap_type("tonemap_type");
|
||||
|
||||
static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f);
|
||||
|
||||
F32 e = llclamp(exposure(), 0.5f, 4.f);
|
||||
|
||||
static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", false);
|
||||
|
||||
shader->uniform1f(s_exposure, e);
|
||||
static LLCachedControl<U32> tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U);
|
||||
shader->uniform1i(tonemap_type, tonemap_type_setting);
|
||||
shader->uniform1f(tonemap_mix, psky->getTonemapMix(should_auto_adjust()));
|
||||
|
||||
F32 sunAngle = llmax(0.f, light_dir.mV[1]);
|
||||
F32 scaledAngle = 1.f - sunAngle;
|
||||
|
||||
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0);
|
||||
|
||||
// SL-15861 This was changed from getRotatedLightNorm() as it was causing
|
||||
// lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV.
|
||||
LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm();
|
||||
shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
if (LLViewerCamera::getInstance()->cameraUnderWater())
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
|
||||
}
|
||||
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
|
||||
// Only push the water planes once.
|
||||
// Previously we did this twice: once for void water and one for region water.
|
||||
// However, the void water and region water shaders are the same exact shader.
|
||||
// They also had the same exact state with the sole exception setting an edge water flag.
|
||||
// That flag was not actually used anywhere in the shaders.
|
||||
// - Geenz 2025-02-11
|
||||
pushWaterPlanes(0);
|
||||
|
||||
// clean up
|
||||
gPipeline.unbindDeferredShader(*shader);
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
}
|
||||
|
||||
void LLDrawPoolWater::pushWaterPlanes(int pass)
|
||||
{
|
||||
LLVOWater* water = nullptr;
|
||||
for (LLFace* const& face : mDrawFace)
|
||||
{
|
||||
water = static_cast<LLVOWater*>(face->getViewerObject());
|
||||
|
||||
face->renderIndexed();
|
||||
|
||||
// Note non-void water being drawn, updates required
|
||||
// Previously we had some logic to determine if this pass was also our water edge pass.
|
||||
// Now we only have one pass. Check if we're doing a region water plane or void water plane.
|
||||
// - Geenz 2025-02-11
|
||||
if (!water->getIsEdgePatch())
|
||||
{
|
||||
sNeedsReflectionUpdate = true;
|
||||
sNeedsDistortionUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerTexture *LLDrawPoolWater::getDebugTexture()
|
||||
{
|
||||
return LLViewerTextureManager::getFetchedTexture(IMG_SMOKE);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ public:
|
|||
void setOpaqueTexture(const LLUUID& opaqueTextureId);
|
||||
void setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId);
|
||||
|
||||
void pushWaterPlanes(int pass);
|
||||
|
||||
protected:
|
||||
void renderOpaqueLegacyWater();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @file lldrawpool.cpp
|
||||
* @brief LLDrawPoolMaterials class implementation
|
||||
* @author Jonathan "Geenz" Goodman
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "lldrawpoolwaterexclusion.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "pipeline.h"
|
||||
#include "llglcommonfunc.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "lldrawpoolwater.h"
|
||||
|
||||
LLDrawPoolWaterExclusion::LLDrawPoolWaterExclusion() : LLRenderPass(LLDrawPool::POOL_WATEREXCLUSION)
|
||||
{
|
||||
LL_INFOS("DPInvisible") << "Creating water exclusion draw pool" << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
void LLDrawPoolWaterExclusion::render(S32 pass)
|
||||
{ // render invisiprims
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; // LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE);
|
||||
|
||||
if (gPipeline.shadersLoaded())
|
||||
{
|
||||
gDrawColorProgram.bind();
|
||||
}
|
||||
|
||||
|
||||
LLGLDepthTest depth(GL_TRUE);
|
||||
gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 1, 1, 1, 1);
|
||||
|
||||
LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER);
|
||||
if (pwaterpool)
|
||||
{
|
||||
// Just treat our water planes as double sided for the purposes of generating the exclusion mask.
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
pwaterpool->pushWaterPlanes(0);
|
||||
|
||||
// Take care of the edge water tiles.
|
||||
pwaterpool->pushWaterPlanes(1);
|
||||
}
|
||||
|
||||
gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 0, 0, 0, 1);
|
||||
|
||||
static LLStaticHashedString waterSign("waterSign");
|
||||
gDrawColorProgram.uniform1f(waterSign, 1.f);
|
||||
|
||||
pushBatches(LLRenderPass::PASS_INVISIBLE, false, false);
|
||||
|
||||
|
||||
if (gPipeline.shadersLoaded())
|
||||
{
|
||||
gDrawColorProgram.unbind();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file lldrawpoolwaterexclusion.h
|
||||
* @brief LLDrawPoolWaterExclusion class definition
|
||||
* @author Jonathan "Geenz" Goodman
|
||||
*
|
||||
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLDRAWPOOLWATEREXCLUSION_H
|
||||
#define LL_LLDRAWPOOLWATEREXCLUSION_H
|
||||
|
||||
#include "v4coloru.h"
|
||||
#include "v2math.h"
|
||||
#include "v3math.h"
|
||||
#include "llvertexbuffer.h"
|
||||
#include "lldrawpool.h"
|
||||
|
||||
class LLViewerTexture;
|
||||
class LLDrawInfo;
|
||||
class LLGLSLShader;
|
||||
|
||||
class LLDrawPoolWaterExclusion : public LLRenderPass
|
||||
{
|
||||
public:
|
||||
LLDrawPoolWaterExclusion();
|
||||
|
||||
enum
|
||||
{
|
||||
VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX
|
||||
};
|
||||
|
||||
virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
|
||||
|
||||
virtual void prerender() {}
|
||||
|
||||
virtual void render(S32 pass = 0);
|
||||
virtual void beginRenderPass(S32 pass) {}
|
||||
virtual void endRenderPass(S32 pass) {}
|
||||
virtual S32 getNumPasses() { return 1; }
|
||||
};
|
||||
|
||||
#endif // LL_LLDRAWPOOLWATEREXCLUSION_H
|
||||
|
|
@ -893,7 +893,7 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& po
|
|||
|
||||
//VECTORIZE THIS
|
||||
// see if we have a non-default mapping
|
||||
U8 texgen = getTextureEntry()->getTexGen();
|
||||
U8 texgen = tep->getTexGen();
|
||||
if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
|
||||
{
|
||||
LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter);
|
||||
|
|
@ -983,8 +983,17 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
|
|||
return false;
|
||||
}
|
||||
const LLTextureEntry *orig_tep = align_to->getTextureEntry();
|
||||
if (!orig_tep)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const LLTextureEntry* tep = getTextureEntry();
|
||||
if (!tep)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) ||
|
||||
(getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR))
|
||||
(tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1563,7 +1572,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);
|
||||
}
|
||||
|
||||
U8 texgen = getTextureEntry()->getTexGen();
|
||||
const LLTextureEntry* tep = getTextureEntry();
|
||||
U8 texgen = tep ? tep->getTexGen() : LLTextureEntry::TEX_GEN_DEFAULT;
|
||||
if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
|
||||
{ //planar texgen needs binormals
|
||||
mVObjp->getVolume()->genTangents(face_index);
|
||||
|
|
@ -2051,7 +2061,12 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
LLStrider<LLColor4U> emissive;
|
||||
mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount);
|
||||
|
||||
U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255);
|
||||
const LLTextureEntry* tep = getTextureEntry();
|
||||
U8 glow = 0;
|
||||
if (tep)
|
||||
{
|
||||
glow = (U8)llclamp((S32)(tep->getGlow() * 255), 0, 255);
|
||||
}
|
||||
|
||||
LLVector4a src;
|
||||
|
||||
|
|
|
|||
|
|
@ -633,7 +633,8 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD& args)
|
|||
chat_args["show_names_for_p2p_conv"] = !mIsP2PChat ||
|
||||
gSavedSettings.getBOOL("IMShowNamesForP2PConv");
|
||||
|
||||
mChatHistory->appendMessage(chat, chat_args);
|
||||
static const LLStyle::Params input_append_params = LLStyle::Params();
|
||||
mChatHistory->appendMessage(chat, chat_args, input_append_params);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::updateUsedEmojis(LLWStringView text)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase*
|
|||
{
|
||||
LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
|
||||
LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel());
|
||||
if (!active_panel)
|
||||
{
|
||||
LL_WARNS() << "No snapshot active panel, current panel index: " << panel_container->getCurrentPanelIndex() << LL_ENDL;
|
||||
}
|
||||
if (!ok_if_not_found)
|
||||
{
|
||||
llassert_always(active_panel != NULL);
|
||||
|
|
@ -643,20 +647,18 @@ void LLFloaterSnapshotBase::ImplBase::setWorking(bool working)
|
|||
working_lbl->setVisible(working);
|
||||
mFloater->getChild<LLUICtrl>("working_indicator")->setVisible(working);
|
||||
|
||||
if (working)
|
||||
{
|
||||
const std::string panel_name = getActivePanel(mFloater, false)->getName();
|
||||
const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size());
|
||||
std::string progress_text = mFloater->getString(prefix + "_" + "progress_str");
|
||||
working_lbl->setValue(progress_text);
|
||||
}
|
||||
|
||||
// All controls should be disabled while posting.
|
||||
mFloater->setCtrlsEnabled(!working);
|
||||
LLPanelSnapshot* active_panel = getActivePanel(mFloater);
|
||||
if (active_panel)
|
||||
if (LLPanelSnapshot* active_panel = getActivePanel(mFloater))
|
||||
{
|
||||
active_panel->enableControls(!working);
|
||||
if (working)
|
||||
{
|
||||
const std::string panel_name = active_panel->getName();
|
||||
const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size());
|
||||
std::string progress_text = mFloater->getString(prefix + "_" + "progress_str");
|
||||
working_lbl->setValue(progress_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -472,9 +472,9 @@ bool LLGLTFPreviewTexture::render()
|
|||
|
||||
gPipeline.setupHWLights();
|
||||
glm::mat4 mat = get_current_modelview();
|
||||
glm::vec4 transformed_light_dir = glm::make_vec4(light_dir.mV);
|
||||
glm::vec4 transformed_light_dir(light_dir);
|
||||
transformed_light_dir = mat * transformed_light_dir;
|
||||
SetTemporarily<LLVector4> force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(glm::value_ptr(transformed_light_dir)));
|
||||
SetTemporarily<LLVector4> force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(transformed_light_dir));
|
||||
// Override lights to ensure the sun is always shining from a certain direction (low graphics)
|
||||
// See also force_sun_direction_high_graphics and fixup_shader_constants
|
||||
{
|
||||
|
|
|
|||
|
|
@ -80,6 +80,17 @@ void LLHeroProbeManager::update()
|
|||
return;
|
||||
}
|
||||
|
||||
// Part of a hacky workaround to fix #3331.
|
||||
// For some reason clearing shaders will cause mirrors to actually work.
|
||||
// There's likely some deeper state issue that needs to be resolved.
|
||||
// - Geenz 2025-02-25
|
||||
if (!mInitialized && LLStartUp::getStartupState() > STATE_PRECACHE)
|
||||
{
|
||||
LLViewerShaderMgr::instance()->clearShaderCache();
|
||||
LLViewerShaderMgr::instance()->setShaders();
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
llassert(!gCubeSnapshot); // assert a snapshot is not in progress
|
||||
if (LLAppViewer::instance()->logoutRequestSent())
|
||||
|
|
@ -89,9 +100,11 @@ void LLHeroProbeManager::update()
|
|||
|
||||
initReflectionMaps();
|
||||
|
||||
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
|
||||
|
||||
if (!mRenderTarget.isComplete())
|
||||
{
|
||||
U32 color_fmt = GL_RGBA16F;
|
||||
U32 color_fmt = render_hdr ? GL_RGBA16F : GL_RGBA8;
|
||||
mRenderTarget.allocate(mProbeResolution, mProbeResolution, color_fmt, true);
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +116,7 @@ void LLHeroProbeManager::update()
|
|||
mMipChain.resize(count);
|
||||
for (U32 i = 0; i < count; ++i)
|
||||
{
|
||||
mMipChain[i].allocate(res, res, GL_RGBA16F);
|
||||
mMipChain[i].allocate(res, res, render_hdr ? GL_RGBA16F : GL_RGBA8);
|
||||
res /= 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -220,7 +233,7 @@ void LLHeroProbeManager::renderProbes()
|
|||
static LLCachedControl<S32> sUpdateRate(gSavedSettings, "RenderHeroProbeUpdateRate", 0);
|
||||
|
||||
F32 near_clip = 0.01f;
|
||||
if (mNearestHero != nullptr &&
|
||||
if (mNearestHero != nullptr && !mNearestHero->isDead() &&
|
||||
!gTeleportDisplay && !gDisconnected && !LLAppViewer::instance()->logoutRequestSent())
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime");
|
||||
|
|
@ -249,12 +262,13 @@ void LLHeroProbeManager::renderProbes()
|
|||
LL_PROFILE_ZONE_NUM(gFrameCount % rate);
|
||||
LL_PROFILE_ZONE_NUM(rate);
|
||||
|
||||
bool dynamic = mNearestHero->getReflectionProbeIsDynamic() && sDetail() > 0;
|
||||
for (U32 i = 0; i < 6; ++i)
|
||||
{
|
||||
if ((gFrameCount % rate) == (i % rate))
|
||||
{ // update 6/rate faces per frame
|
||||
LL_PROFILE_ZONE_NUM(i);
|
||||
updateProbeFace(mProbes[0], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip);
|
||||
updateProbeFace(mProbes[0], i, dynamic, near_clip);
|
||||
}
|
||||
}
|
||||
generateRadiance(mProbes[0]);
|
||||
|
|
@ -537,8 +551,10 @@ void LLHeroProbeManager::initReflectionMaps()
|
|||
|
||||
mTexture = new LLCubeMapArray();
|
||||
|
||||
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
|
||||
|
||||
// store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source)
|
||||
mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2);
|
||||
mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr);
|
||||
|
||||
if (mDefaultProbe.isNull())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ private:
|
|||
std::vector<LLPointer<LLVOVolume>> mHeroVOList;
|
||||
LLPointer<LLVOVolume> mNearestHero;
|
||||
|
||||
|
||||
// Part of a hacky workaround to fix #3331.
|
||||
bool mInitialized = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
|
|||
LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
|
||||
glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight());
|
||||
|
||||
glm::vec3 win_coord = glm::project(glm::make_vec3(render_pos.mV), get_current_modelview(), get_current_projection(), viewport);
|
||||
glm::vec3 win_coord = glm::project(glm::vec3(render_pos), get_current_modelview(), get_current_projection(), viewport);
|
||||
|
||||
//fonts all render orthographically, set up projection``
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
|
|
|
|||
|
|
@ -4231,14 +4231,9 @@ void LLFolderBridge::staticFolderOptionsMenu()
|
|||
|
||||
bool LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
|
||||
{
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
model->collectDescendentsIf(mUUID,
|
||||
cat_array,
|
||||
item_array,
|
||||
return model->hasMatchingDescendents(mUUID,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_type);
|
||||
return !item_array.empty();
|
||||
}
|
||||
|
||||
void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items)
|
||||
|
|
@ -4415,21 +4410,26 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
//Added by aura to force inventory pull on right-click to display folder options correctly. 07-17-06
|
||||
mCallingCards = mWearables = false;
|
||||
|
||||
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
|
||||
if (checkFolderForContentsOfType(model, is_callingcard))
|
||||
if (gInventory.getRootFolderID() != mUUID)
|
||||
{
|
||||
mCallingCards=true;
|
||||
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
|
||||
if (checkFolderForContentsOfType(model, is_callingcard))
|
||||
{
|
||||
mCallingCards = true;
|
||||
}
|
||||
|
||||
const std::vector<LLAssetType::EType> types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE };
|
||||
LLIsOneOfTypes is_wearable(types);
|
||||
|
||||
if (checkFolderForContentsOfType(model, is_wearable))
|
||||
{
|
||||
mWearables = true;
|
||||
}
|
||||
}
|
||||
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
|
||||
if (checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture) )
|
||||
else
|
||||
{
|
||||
mWearables=true;
|
||||
// Assume that there are wearables in the root folder
|
||||
mWearables = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -4442,13 +4442,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
LLFolderType::EType type = category->getPreferredType();
|
||||
const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
|
||||
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object(LLAssetType::AT_OBJECT);
|
||||
LLIsType is_gesture(LLAssetType::AT_GESTURE);
|
||||
const std::vector<LLAssetType::EType> types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE };
|
||||
LLIsOneOfTypes is_wearable(types);
|
||||
|
||||
if (checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture))
|
||||
if (checkFolderForContentsOfType(model, is_wearable))
|
||||
{
|
||||
mWearables = true;
|
||||
}
|
||||
|
|
@ -4571,14 +4568,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
|
|||
|
||||
// wearables related functionality for folders.
|
||||
//is_wearable
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
const std::vector<LLAssetType::EType> types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE };
|
||||
LLIsOneOfTypes is_wearable(types);
|
||||
|
||||
if (mWearables ||
|
||||
checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture) )
|
||||
checkFolderForContentsOfType(model, is_wearable))
|
||||
{
|
||||
// Only enable add/replace outfit for non-system folders.
|
||||
if (!is_system_folder)
|
||||
|
|
|
|||
|
|
@ -2634,6 +2634,22 @@ bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLIsOneOfTypes::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
for (LLAssetType::EType &type : mTypes)
|
||||
{
|
||||
if (type == LLAssetType::AT_CATEGORY)
|
||||
{
|
||||
if (cat) return true;
|
||||
}
|
||||
if (item)
|
||||
{
|
||||
if (item->getType() == type) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
if(mType == LLAssetType::AT_CATEGORY)
|
||||
|
|
|
|||
|
|
@ -245,6 +245,24 @@ protected:
|
|||
LLAssetType::EType mType;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLIsOneOfTypes
|
||||
//
|
||||
// Implementation of a LLInventoryCollectFunctor which returns true if
|
||||
// the type is one of the types passed in during construction.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLIsOneOfTypes : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLIsOneOfTypes(const std::vector<LLAssetType::EType> &types) : mTypes(types) {}
|
||||
virtual ~LLIsOneOfTypes() {}
|
||||
virtual bool operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item);
|
||||
protected:
|
||||
std::vector <LLAssetType::EType> mTypes;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLIsNotType
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1305,6 +1305,47 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
|
|||
}
|
||||
}
|
||||
|
||||
bool LLInventoryModel::hasMatchingDescendents(const LLUUID& id,
|
||||
bool include_trash,
|
||||
LLInventoryCollectFunctor& matches)
|
||||
{
|
||||
if (!include_trash)
|
||||
{
|
||||
const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (trash_id.notNull() && (trash_id == id))
|
||||
return false;
|
||||
}
|
||||
cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
|
||||
if (cat_array)
|
||||
{
|
||||
for (auto& cat : *cat_array)
|
||||
{
|
||||
if (matches(cat, NULL))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (hasMatchingDescendents(cat->getUUID(), include_trash, matches))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
|
||||
|
||||
if (item_array)
|
||||
{
|
||||
for (auto& item : *item_array)
|
||||
{
|
||||
if (matches(NULL, item))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
|
||||
{
|
||||
const LLInventoryObject *obj = getObject(object_id);
|
||||
|
|
|
|||
|
|
@ -287,6 +287,9 @@ public:
|
|||
item_array_t& items,
|
||||
bool include_trash,
|
||||
LLInventoryCollectFunctor& add);
|
||||
bool hasMatchingDescendents(const LLUUID& id,
|
||||
bool include_trash,
|
||||
LLInventoryCollectFunctor& add);
|
||||
|
||||
// Collect all items in inventory that are linked to item_id.
|
||||
// Assumes item_id is itself not a linked item.
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
|
|||
{
|
||||
if (model_item && view_item && viewmodel_item)
|
||||
{
|
||||
const LLUUID& idp = viewmodel_item->getUUID();
|
||||
const LLUUID idp = viewmodel_item->getUUID();
|
||||
view_item->destroyView();
|
||||
removeItemID(idp);
|
||||
}
|
||||
|
|
@ -1334,6 +1334,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory()
|
|||
LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
|
||||
if (fchild
|
||||
&& fchild->getViewModelItem()
|
||||
// Is this right? Name might be localized,
|
||||
// use FT_ROOT_INVENTORY or gInventory.getRootFolderID()?
|
||||
&& fchild->getViewModelItem()->getName() == "My Inventory")
|
||||
{
|
||||
fchild->setOpen(true);
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
|
|||
request_params["read_critical"] = false; // handleTOSResponse
|
||||
request_params["last_exec_event"] = mLastExecEvent;
|
||||
request_params["last_exec_duration"] = mLastExecDuration;
|
||||
request_params["last_exec_session_id"] = mLastAgentSessionId.asString();
|
||||
request_params["mac"] = (char*)hashed_unique_id_string;
|
||||
request_params["version"] = LLVersionInfo::instance().getVersion();
|
||||
request_params["channel"] = LLVersionInfo::instance().getChannel();
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public:
|
|||
void setSerialNumber(const std::string& sn) { mSerialNumber = sn; }
|
||||
void setLastExecEvent(int lee) { mLastExecEvent = lee; }
|
||||
void setLastExecDuration(S32 duration) { mLastExecDuration = duration; }
|
||||
void setLastAgentSessionId(const LLUUID& id) { mLastAgentSessionId = id; }
|
||||
void setPlatformInfo(const std::string platform, const std::string platform_version, const std::string platform_name);
|
||||
|
||||
void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; }
|
||||
|
|
@ -101,6 +102,7 @@ private:
|
|||
std::string mSerialNumber;
|
||||
int mLastExecEvent;
|
||||
S32 mLastExecDuration;
|
||||
LLUUID mLastAgentSessionId;
|
||||
std::string mPlatform;
|
||||
std::string mPlatformVersion;
|
||||
std::string mPlatformVersionName;
|
||||
|
|
|
|||
|
|
@ -548,8 +548,8 @@ LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMate
|
|||
return ppTex ? (*ppTex).get() : NULL;
|
||||
}
|
||||
|
||||
volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||
volatile S32 LLMeshRepoThread::sActiveLODRequests = 0;
|
||||
std::atomic<S32> LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||
std::atomic<S32> LLMeshRepoThread::sActiveLODRequests = 0;
|
||||
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
|
||||
S32 LLMeshRepoThread::sRequestLowWater = REQUEST2_LOW_WATER_MIN;
|
||||
S32 LLMeshRepoThread::sRequestHighWater = REQUEST2_HIGH_WATER_MIN;
|
||||
|
|
@ -3916,7 +3916,7 @@ void LLMeshRepository::notifyLoadedMeshes()
|
|||
}
|
||||
|
||||
// erase from background thread
|
||||
mThread->mWorkQueue.post([=]()
|
||||
mThread->mWorkQueue.post([=, this]()
|
||||
{
|
||||
mThread->mSkinMap.erase(id);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -256,8 +256,8 @@ class LLMeshRepoThread : public LLThread
|
|||
{
|
||||
public:
|
||||
|
||||
volatile static S32 sActiveHeaderRequests;
|
||||
volatile static S32 sActiveLODRequests;
|
||||
static std::atomic<S32> sActiveHeaderRequests;
|
||||
static std::atomic<S32> sActiveLODRequests;
|
||||
static U32 sMaxConcurrentRequests;
|
||||
static S32 sRequestLowWater;
|
||||
static S32 sRequestHighWater;
|
||||
|
|
|
|||
|
|
@ -139,32 +139,60 @@ void LLPanelContents::getState(LLViewerObject *objectp )
|
|||
void LLPanelContents::onFilterEdit()
|
||||
{
|
||||
const std::string& filter_substring = mFilterEditor->getText();
|
||||
if (filter_substring.empty())
|
||||
if (!mPanelInventoryObject->hasInventory())
|
||||
{
|
||||
if (mPanelInventoryObject->getFilter().getFilterSubString().empty())
|
||||
{
|
||||
// The current filter and the new filter are empty, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
mSavedFolderState.setApply(true);
|
||||
mPanelInventoryObject->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
|
||||
|
||||
// Add a folder with the current item to the list of previously opened folders
|
||||
LLOpenFoldersWithSelection opener;
|
||||
mPanelInventoryObject->getRootFolder()->applyFunctorRecursively(opener);
|
||||
mPanelInventoryObject->getRootFolder()->scrollToShowSelection();
|
||||
mDirtyFilter = true;
|
||||
}
|
||||
else if (mPanelInventoryObject->getFilter().getFilterSubString().empty())
|
||||
else
|
||||
{
|
||||
// The first letter in search term, save existing folder open state
|
||||
if (!mPanelInventoryObject->getFilter().isNotDefault())
|
||||
LLFolderView* root_folder = mPanelInventoryObject->getRootFolder();
|
||||
if (filter_substring.empty())
|
||||
{
|
||||
mSavedFolderState.setApply(false);
|
||||
mPanelInventoryObject->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
|
||||
if (mPanelInventoryObject->getFilter().getFilterSubString().empty())
|
||||
{
|
||||
// The current filter and the new filter are empty, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDirtyFilter && !mSavedFolderState.hasOpenFolders())
|
||||
{
|
||||
if (root_folder)
|
||||
{
|
||||
root_folder->setOpenArrangeRecursively(true, LLFolderViewFolder::ERecurseType::RECURSE_DOWN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSavedFolderState.setApply(true);
|
||||
if (root_folder)
|
||||
{
|
||||
root_folder->applyFunctorRecursively(mSavedFolderState);
|
||||
}
|
||||
}
|
||||
mDirtyFilter = false;
|
||||
|
||||
// Add a folder with the current item to the list of previously opened folders
|
||||
if (root_folder)
|
||||
{
|
||||
LLOpenFoldersWithSelection opener;
|
||||
root_folder->applyFunctorRecursively(opener);
|
||||
root_folder->scrollToShowSelection();
|
||||
}
|
||||
}
|
||||
else if (mPanelInventoryObject->getFilter().getFilterSubString().empty())
|
||||
{
|
||||
// The first letter in search term, save existing folder open state
|
||||
if (!mPanelInventoryObject->getFilter().isNotDefault())
|
||||
{
|
||||
mSavedFolderState.setApply(false);
|
||||
if (root_folder)
|
||||
{
|
||||
root_folder->applyFunctorRecursively(mSavedFolderState);
|
||||
}
|
||||
mDirtyFilter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mPanelInventoryObject->getFilter().setFilterSubString(filter_substring);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ protected:
|
|||
void getState(LLViewerObject *object);
|
||||
void onFilterEdit();
|
||||
|
||||
bool mDirtyFilter { false };
|
||||
|
||||
public:
|
||||
class LLFilterEditor* mFilterEditor;
|
||||
LLSaveFolderState mSavedFolderState;
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ void LLPanelEmojiComplete::updateConstraints()
|
|||
{
|
||||
mRenderRect = getLocalRect();
|
||||
|
||||
mEmojiWidth = (U16)(mIconFont->getWidthF32(u8"\U0001F431") + mPadding * 2);
|
||||
mEmojiWidth = (U16)(mIconFont->getWidthF32(LLWString(1, 0x1F431).c_str()) + mPadding * 2);
|
||||
if (mVertical)
|
||||
{
|
||||
mEmojiHeight = mIconFont->getLineHeight() + mPadding * 2;
|
||||
|
|
|
|||
|
|
@ -898,6 +898,10 @@ struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor
|
|||
if (facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot))
|
||||
{
|
||||
const LLTextureEntry* tep = facep->getTextureEntry();
|
||||
if (!tep)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LLVector2 st_offset, st_scale;
|
||||
tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]);
|
||||
tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
|
|||
mGroupID(group_id),
|
||||
mBulkAgentList(NULL),
|
||||
mOKButton(NULL),
|
||||
mAddButton(nullptr),
|
||||
mRemoveButton(NULL),
|
||||
mGroupName(NULL),
|
||||
mLoadingText(),
|
||||
|
|
@ -79,29 +80,18 @@ LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl()
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPanelGroupBulkImpl::callbackClickAdd(void* userdata)
|
||||
void LLPanelGroupBulkImpl::callbackClickAdd(LLPanelGroupBulk* panelp)
|
||||
{
|
||||
if (LLPanelGroupBulk* panelp = (LLPanelGroupBulk*)userdata)
|
||||
{
|
||||
// Right now this is hard coded with some knowledge that it is part
|
||||
// of a floater since the avatar picker needs to be added as a dependent
|
||||
// floater to the parent floater.
|
||||
// Soon the avatar picker will be embedded into this panel
|
||||
// instead of being it's own separate floater. But that is next week.
|
||||
// This will do for now. -jwolk May 10, 2006
|
||||
LLView* button = panelp->findChild<LLButton>("add_button");
|
||||
LLFloater* root_floater = gFloaterView->getParentFloater(panelp);
|
||||
LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(
|
||||
[&](const uuid_vec_t& agent_ids, const std::vector<LLAvatarName>&)
|
||||
{
|
||||
panelp->mImplementation->addUsers(agent_ids);
|
||||
}, true, false, false, root_floater->getName(), button);
|
||||
if (picker)
|
||||
LLFloater* root_floater = gFloaterView->getParentFloater(panelp);
|
||||
LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(
|
||||
[this](const uuid_vec_t& agent_ids, const std::vector<LLAvatarName>&)
|
||||
{
|
||||
root_floater->addDependentFloater(picker);
|
||||
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(panelp->mImplementation->mGroupID);
|
||||
}
|
||||
addUsers(agent_ids);
|
||||
}, true, false, false, root_floater->getName(), mAddButton);
|
||||
if (picker)
|
||||
{
|
||||
root_floater->addDependentFloater(picker);
|
||||
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,35 +68,26 @@ bool LLPanelGroupBulkBan::postBuild()
|
|||
mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation);
|
||||
}
|
||||
|
||||
LLButton* button = getChild<LLButton>("add_button", recurse);
|
||||
if ( button )
|
||||
mImplementation->mAddButton = getChild<LLButton>("add_button", recurse);
|
||||
// default to opening avatarpicker automatically
|
||||
mImplementation->mAddButton->setClickedCallback(
|
||||
[this](LLUICtrl* ctrl, const LLSD& param)
|
||||
{
|
||||
// default to opening avatarpicker automatically
|
||||
// (*impl::callbackClickAdd)((void*)this);
|
||||
button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this);
|
||||
}
|
||||
mImplementation->callbackClickAdd(this);
|
||||
});
|
||||
|
||||
mImplementation->mRemoveButton =
|
||||
getChild<LLButton>("remove_button", recurse);
|
||||
if ( mImplementation->mRemoveButton )
|
||||
{
|
||||
mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation);
|
||||
mImplementation->mRemoveButton->setEnabled(false);
|
||||
}
|
||||
mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation);
|
||||
mImplementation->mRemoveButton->setEnabled(false);
|
||||
|
||||
mImplementation->mOKButton =
|
||||
getChild<LLButton>("ban_button", recurse);
|
||||
if ( mImplementation->mOKButton )
|
||||
{
|
||||
mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this);
|
||||
mImplementation->mOKButton->setEnabled(false);
|
||||
}
|
||||
mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this);
|
||||
mImplementation->mOKButton->setEnabled(false);
|
||||
|
||||
button = getChild<LLButton>("cancel_button", recurse);
|
||||
if ( button )
|
||||
{
|
||||
button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation);
|
||||
}
|
||||
LLButton* button = getChild<LLButton>("cancel_button", recurse);
|
||||
button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation);
|
||||
|
||||
mImplementation->mTooManySelected = getString("ban_selection_too_large");
|
||||
mImplementation->mBanNotPermitted = getString("ban_not_permitted");
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
LLPanelGroupBulkImpl(const LLUUID& group_id);
|
||||
~LLPanelGroupBulkImpl();
|
||||
|
||||
static void callbackClickAdd(void* userdata);
|
||||
void callbackClickAdd(LLPanelGroupBulk* panelp);
|
||||
static void callbackClickRemove(void* userdata);
|
||||
|
||||
static void callbackClickCancel(void* userdata);
|
||||
|
|
@ -70,6 +70,7 @@ public:
|
|||
|
||||
LLNameListCtrl* mBulkAgentList;
|
||||
LLButton* mOKButton;
|
||||
LLButton* mAddButton;
|
||||
LLButton* mRemoveButton;
|
||||
LLTextBox* mGroupName;
|
||||
|
||||
|
|
|
|||
|
|
@ -2425,10 +2425,14 @@ void LLPanelMainInventory::updateCombinationVisibility()
|
|||
|
||||
mCombinationGalleryLayoutPanel->setVisible(!is_gallery_empty);
|
||||
mCombinationListLayoutPanel->setVisible(show_inv_pane);
|
||||
mCombinationInventoryPanel->getRootFolder()->setForceArrange(!show_inv_pane);
|
||||
if(mCombinationInventoryPanel->hasVisibleItems())
|
||||
LLFolderView* root_folder = mCombinationInventoryPanel->getRootFolder();
|
||||
if (root_folder)
|
||||
{
|
||||
mForceShowInvLayout = false;
|
||||
root_folder->setForceArrange(!show_inv_pane);
|
||||
if (mCombinationInventoryPanel->hasVisibleItems())
|
||||
{
|
||||
mForceShowInvLayout = false;
|
||||
}
|
||||
}
|
||||
if(is_gallery_empty)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ public:
|
|||
|
||||
static void idle(void* user_data);
|
||||
|
||||
bool hasInventory(){ return mHaveInventory; };
|
||||
|
||||
protected:
|
||||
void reset();
|
||||
/*virtual*/ void inventoryChanged(LLViewerObject* object,
|
||||
|
|
|
|||
|
|
@ -660,11 +660,11 @@ void LLPanelPrimMediaControls::updateShape()
|
|||
for(; vert_it != vert_end; ++vert_it)
|
||||
{
|
||||
// project silhouette vertices into screen space
|
||||
glm::vec3 screen_vert(glm::make_vec3(vert_it->mV));
|
||||
glm::vec3 screen_vert(*vert_it);
|
||||
screen_vert = mul_mat4_vec3(mat, screen_vert);
|
||||
|
||||
// add to screenspace bounding box
|
||||
update_min_max(min, max, LLVector3(glm::value_ptr(screen_vert)));
|
||||
update_min_max(min, max, LLVector3(screen_vert));
|
||||
}
|
||||
|
||||
// convert screenspace bbox to pixels (in screen coords)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue