Merge branch 'master' of https://github.com/FirestormViewer/phoenix-firestorm
commit
7d03d5af2a
|
|
@ -308,7 +308,17 @@ jobs:
|
|||
if: ${{ matrix.variant == 'avx' }}
|
||||
shell: bash
|
||||
run: echo "EXTRA_ARGS=${{ env.EXTRA_ARGS }} --avx2" >> $GITHUB_ENV
|
||||
|
||||
- name: Add custom UA string if provided
|
||||
env:
|
||||
FS_PF_UA: ${{ secrets.FS_PF_UA }}
|
||||
run: |
|
||||
if [ -n "${FS_PF_UA}" ]; then
|
||||
echo "EXTRA_ARGS=${{ env.EXTRA_ARGS }} -DFS_PF_USER_AGENT=\"${FS_PF_UA}\"" >> $GITHUB_ENV
|
||||
echo "Building with custom user-agent string."
|
||||
else
|
||||
echo "No custom user-agent string provided."
|
||||
fi
|
||||
shell: bash
|
||||
- name: Clean up packages to give more space
|
||||
run: rm *${{ env.fallback_platform }}*bz2
|
||||
shell: bash
|
||||
|
|
@ -369,13 +379,13 @@ jobs:
|
|||
- name: Install Microsoft.Trusted.Signing.Client
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
.\nuget.exe install Microsoft.Trusted.Signing.Client -Version 1.0.53 -OutputDirectory .
|
||||
.\nuget.exe install Microsoft.Trusted.Signing.Client -Version 1.0.86 -OutputDirectory .
|
||||
shell: pwsh
|
||||
|
||||
- name: Locate Azure.CodeSigning.Dlib.dll
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
$dllPath = (Get-ChildItem ".\Microsoft.Trusted.Signing.Client.1.0.53\bin\x64\Azure.CodeSigning.Dlib.dll" -Recurse -File | Select-Object -First 1).FullName
|
||||
$dllPath = (Get-ChildItem ".\Microsoft.Trusted.Signing.Client.1.0.86\bin\x64\Azure.CodeSigning.Dlib.dll" -Recurse -File | Select-Object -First 1).FullName
|
||||
if (-not $dllPath) {
|
||||
Write-Error "Azure.CodeSigning.Dlib.dll not found."
|
||||
exit 1
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
run: pip install discord-webhook
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: dawidd6/action-download-artifact@v9
|
||||
uses: dawidd6/action-download-artifact@v11
|
||||
id: download
|
||||
with:
|
||||
workflow: build_viewer.yml
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ jobs:
|
|||
setup_files: ${{ steps.get-files.outputs.setup_files }}
|
||||
steps:
|
||||
- name: Download Build Artifacts
|
||||
uses: dawidd6/action-download-artifact@v9
|
||||
uses: dawidd6/action-download-artifact@v11
|
||||
id: download
|
||||
with:
|
||||
workflow: build_viewer.yml
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ jobs:
|
|||
echo "build_run_number=${{ github.event.inputs.build_run_number }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Download Build Artifacts
|
||||
uses: dawidd6/action-download-artifact@v9
|
||||
uses: dawidd6/action-download-artifact@v11
|
||||
id: download_build_info
|
||||
with:
|
||||
workflow: build_viewer.yml
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ Thank you for submitting code to Firestorm; we will review it and merge or provi
|
|||
We have written this guide to help you contribute code that meets our needs. It will hopefully reduce the number of iterations required before we can merge the code.
|
||||
|
||||
1. **Descriptive Title**:
|
||||
- Use a clear and descriptive title for the PR.
|
||||
Use a clear and descriptive title for the PR.
|
||||
|
||||
1. **Related Issues**:
|
||||
- Reference any related issues or pull requests by including the JIRA number and description in the commit message header (e.g., `[FIRE-12345] When I click, my head falls off` or `[FIRE-12345] prevent click detaching head`).
|
||||
Reference any related issues or pull requests by including the JIRA number and description in the commit message header (e.g., `[FIRE-12345] When I click, my head falls off` or `[FIRE-12345] prevent click detaching head`).
|
||||
|
||||
1. **Description**:
|
||||
- Provide a detailed description of the changes. Explain why the changes are necessary and what problem they solve. If a JIRA is associated with the change, there is no need to duplicate that, but we would appreciate a summary and explanation of the fix.
|
||||
Provide a detailed description of the changes. Explain why the changes are necessary and what problem they solve. If a JIRA is associated with the change, there is no need to duplicate that, but we would appreciate a summary and explanation of the fix.
|
||||
|
||||
1. **Comment tags (important)**:
|
||||
- We use comments to preserve the original upstream (LL) code when making modifications; this allows the person merging future code updates to see both the original code from LL and any new updates and then use those to determine whether the FS-specific changes need to be updated and reviewed.
|
||||
We use comments to preserve the original upstream (LL) code when making modifications; this allows the person merging future code updates to see both the original code from LL and any new updates and then use those to determine whether the FS-specific changes need to be updated and reviewed.
|
||||
If you are modifying LL code, we need the LL code preserved in a comment.
|
||||
For example:
|
||||
|
||||
|
|
@ -38,16 +38,16 @@ Would become:
|
|||
If you add new code, the same rules apply, but there is nothing to comment out.
|
||||
This is done so that when LL updates the original code, we can see what the original code was doing, what their changes do, and how that relates to the changes that we applied on top.
|
||||
|
||||
A single line change can use the shorthand `<FS:YI/>`:
|
||||
A single line change can use the shorthand `</FS:YI>`:
|
||||
|
||||
```c++
|
||||
bool break_stuff=true;
|
||||
bool break_stuff = true;
|
||||
```
|
||||
|
||||
Could be fixed as follows:
|
||||
|
||||
```c++
|
||||
bool break_stuff=false; // <FS:Beq/> [FIRE-23456] don't break stuff.
|
||||
bool break_stuff = false; // </FS:Beq> [FIRE-23456] don't break stuff.
|
||||
```
|
||||
|
||||
The Comment tags are only required when changing code maintained upstream. If the code you are changing is in an FS-created file, RLV code, OpenSim-only code, etc., then we do not need the comments.
|
||||
|
|
@ -55,9 +55,9 @@ Could be fixed as follows:
|
|||
If the code you are changing is already inside an `//<FS>` comment block, then there is no need to add a new block, but do try to make sure that any comments align with the updates you make.
|
||||
|
||||
5. **Testing**:
|
||||
- Include details on how the changes should be tested. Describe the testing environment and any steps needed to verify the changes.
|
||||
Include details on how the changes should be tested. Describe the testing environment and any steps needed to verify the changes.
|
||||
|
||||
1. **Documentation**:
|
||||
- If the change includes a new feature, it would be beneficial to suggest how we should update the FS Wiki pages to help users understand the feature
|
||||
If the change includes a new feature, it would be beneficial to suggest how we should update the FS Wiki pages to help users understand the feature
|
||||
|
||||
Thank you for your contribution!
|
||||
10
README.md
10
README.md
|
|
@ -25,4 +25,12 @@ Build instructions for each operating system can be found using the links below
|
|||
|
||||
## Contribute
|
||||
|
||||
Help make Firestorm better! You can get involved with improvements by filing bugs and suggesting enhancements via [JIRA](https://jira.firestormviewer.org) or [creating pull requests](doc/FS_PR_GUIDELINES.md).
|
||||
Help make Firestorm better! You can get involved with improvements by filing bugs and suggesting enhancements via [JIRA](https://jira.firestormviewer.org) or [creating pull requests](CONTRIBUTING.md).
|
||||
|
||||
## Community respect
|
||||
|
||||
This section is guided by the [TPV Policy](https://secondlife.com/corporate/third-party-viewers) and the [Second Life Code of Conduct](https://github.com/secondlife/viewer?tab=coc-ov-file).
|
||||
|
||||
Firestorm code is made available during ongoing development, with the **master** branch representing the current nightly build. Developers and self-compilers are encouraged to work on their own forks and contribute back via pull requests, as detailed in the [contributing guide](CONTRIBUTING.md).
|
||||
|
||||
If you intend to use our code for your own viewer beyond personal use, please only use code from official release branches (for example, `Firestorm_7.1.13`), rather than from pre-release/preview or nightly builds.
|
||||
|
|
|
|||
|
|
@ -73,6 +73,15 @@ if(TESTBUILD AND TESTBUILDPERIOD)
|
|||
endif(TESTBUILD AND TESTBUILDPERIOD)
|
||||
#</FS:Ansariel>
|
||||
|
||||
#<FS:Beq> Support for custom Primfeed UA
|
||||
option(FS_PF_USER_AGENT "Optional compile‐time Primfeed user‐agent string" "")
|
||||
if (FS_PF_USER_AGENT)
|
||||
add_compile_definitions(FS_PF_USER_AGENT="${FS_PF_USER_AGENT}")
|
||||
message(STATUS "Compiling with custom Primfeed user-agent: ${FS_PF_USER_AGENT}")
|
||||
else (FS_PF_USER_AGENT)
|
||||
message(STATUS "Compiling with standard Primfeed user-agent")
|
||||
endif (FS_PF_USER_AGENT)
|
||||
# </Beq>
|
||||
# <FS:Ansariel> [AVX Optimization]
|
||||
option(USE_AVX_OPTIMIZATION "AVX optimization support" OFF)
|
||||
option(USE_AVX2_OPTIMIZATION "AVX2 optimization support" OFF)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
// <FS:ND> Suppress warnings about the string fiddling
|
||||
#if LL_LINUX
|
||||
|
|
@ -205,6 +207,39 @@ std::string ll_stream_notation_sd(const LLSD& sd)
|
|||
return stream.str();
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Create LLSD from CSV
|
||||
LLSD ll_sd_from_csv(std::istream& csv, std::string_view delimiters)
|
||||
{
|
||||
LLSD data;
|
||||
bool headerRead{ false };
|
||||
std::vector<std::string> columnNames;
|
||||
std::string line;
|
||||
|
||||
while (std::getline(csv, line))
|
||||
{
|
||||
std::vector<std::string> columns;
|
||||
boost::split(columns, line, boost::is_any_of(delimiters));
|
||||
|
||||
if (!headerRead)
|
||||
{
|
||||
headerRead = true;
|
||||
columnNames = std::move(columns);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSD rowData;
|
||||
for (size_t i = 0; i < columnNames.size() && i < columns.size(); ++i)
|
||||
{
|
||||
rowData[columnNames.at(i)] = columns.at(i);
|
||||
}
|
||||
|
||||
data.append(rowData);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
//compares the structure of an LLSD to a template LLSD and stores the
|
||||
//"valid" values in a 3rd LLSD. Default values pulled from the template
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd);
|
|||
|
||||
LL_COMMON_API std::string ll_stream_notation_sd(const LLSD& sd);
|
||||
|
||||
// <FS:Ansariel> Create LLSD from CSV
|
||||
LL_COMMON_API LLSD ll_sd_from_csv(std::istream& csv, std::string_view delimiters = ",");
|
||||
|
||||
//compares the structure of an LLSD to a template LLSD and stores the
|
||||
//"valid" values in a 3rd LLSD. Default values
|
||||
//are pulled from the template. Extra keys/values in the test
|
||||
|
|
|
|||
|
|
@ -244,14 +244,4 @@ inline size_t hash_value(const LLUUID& id) noexcept
|
|||
return (size_t)id.getDigest64();
|
||||
}
|
||||
|
||||
// <FS:Ansariel> UUID hash calculation
|
||||
struct FSUUIDHash
|
||||
{
|
||||
inline size_t operator() (const LLUUID& id) const
|
||||
{
|
||||
return *reinterpret_cast<const size_t*>(id.mData);
|
||||
}
|
||||
};
|
||||
// </FS:Ansariel> UUID hash calculation
|
||||
|
||||
#endif // LL_LLUUID_H
|
||||
|
|
|
|||
|
|
@ -432,7 +432,8 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode
|
|||
}
|
||||
if (!bFailed && (op->mReqOffset || op->mReqLength))
|
||||
{
|
||||
if (op->mReqOffset != op->mReplyOffset || (op->mReqLength && op->mReqLength < op->mReplyLength))
|
||||
// We should only check the offset and length if we are handling a partial content request.
|
||||
if (op->mStatus == HttpStatus(HTTP_PARTIAL_CONTENT) && (op->mReqOffset != op->mReplyOffset || (op->mReqLength && op->mReqLength < op->mReplyLength)))
|
||||
{
|
||||
std::stringstream strm;
|
||||
strm << "HTTP pipelining possibly out of sync, request wanted: " << op->mReqOffset << "-";
|
||||
|
|
|
|||
|
|
@ -361,14 +361,12 @@ LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD
|
|||
new_array = q.getValue();
|
||||
}
|
||||
else
|
||||
{ // TODO: We could expand this to inspect the type and do a deep lerp based on type.
|
||||
// for now assume a heterogeneous array of reals.
|
||||
{
|
||||
size_t len = std::max(value.size(), other_value.size());
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
|
||||
new_array[i] = lerp((F32)value[i].asReal(), (F32)other_value[i].asReal(), (F32)mix);
|
||||
new_array[i] = interpolateSDValue(key_name, value[i], other_value[i], defaults, mix, skip, slerps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -661,15 +661,15 @@ void LLSettingsSky::blend(LLSettingsBase::ptr_t &end, F64 blendf)
|
|||
mHasLegacyHaze |= lerp_legacy_float(mHazeDensity, mLegacyHazeDensity, other->mHazeDensity, other->mLegacyHazeDensity, 0.7f, (F32)blendf);
|
||||
mHasLegacyHaze |= lerp_legacy_float(mDistanceMultiplier, mLegacyDistanceMultiplier, other->mDistanceMultiplier, other->mLegacyDistanceMultiplier, 0.8f, (F32)blendf);
|
||||
mHasLegacyHaze |= lerp_legacy_float(mDensityMultiplier, mLegacyDensityMultiplier, other->mDensityMultiplier, other->mLegacyDensityMultiplier, 0.0001f, (F32)blendf);
|
||||
mHasLegacyHaze |= lerp_legacy_color(mAmbientColor, mLegacyAmbientColor, other->mAmbientColor, other->mLegacyAmbientColor, LLColor3(0.25f, 0.25f, 0.25f), (F32)blendf); // <FS:Beq for Hecklezz/> import pending PR #4185 Fix sky ambient color not blending.
|
||||
mHasLegacyHaze |= lerp_legacy_color(mBlueHorizon, mLegacyBlueHorizon, other->mBlueHorizon, other->mLegacyBlueHorizon, LLColor3(0.4954f, 0.4954f, 0.6399f), (F32)blendf);
|
||||
mHasLegacyHaze |= lerp_legacy_color(mBlueDensity, mLegacyBlueDensity, other->mBlueDensity, other->mLegacyBlueDensity, LLColor3(0.2447f, 0.4487f, 0.7599f), (F32)blendf);
|
||||
|
||||
parammapping_t defaults = other->getParameterMap();
|
||||
stringset_t skip = getSkipInterpolateKeys();
|
||||
stringset_t slerps = getSlerpKeys();
|
||||
mAbsorptionConfigs = interpolateSDMap(mAbsorptionConfigs, other->mAbsorptionConfigs, defaults, blendf, skip, slerps);
|
||||
mMieConfigs = interpolateSDMap(mMieConfigs, other->mMieConfigs, defaults, blendf, skip, slerps);
|
||||
mRayleighConfigs = interpolateSDMap(mRayleighConfigs, other->mRayleighConfigs, defaults, blendf, skip, slerps);
|
||||
mAbsorptionConfigs = interpolateSDValue("absorption_config", mAbsorptionConfigs, other->mAbsorptionConfigs, defaults, blendf, skip, slerps);
|
||||
mMieConfigs = interpolateSDValue("mie_config", mMieConfigs, other->mMieConfigs, defaults, blendf, skip, slerps);
|
||||
mRayleighConfigs = interpolateSDValue("rayleigh_config", mRayleighConfigs, other->mRayleighConfigs, defaults, blendf, skip, slerps);
|
||||
|
||||
setDirtyFlag(true);
|
||||
setReplaced();
|
||||
|
|
|
|||
|
|
@ -1502,7 +1502,17 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
|||
{
|
||||
domListOfFloats& transform = t->getValue();
|
||||
auto count = transform.getCount()/16;
|
||||
|
||||
|
||||
// <FS:Beq> FIRE-34811 Crash during import due to missing inv_bind_matrices.
|
||||
if (count==0)
|
||||
{
|
||||
LL_WARNS("DAELOader") << "Invalid rigged mesh: Missing inv_bind_matrices." << LL_ENDL;
|
||||
LLSD args;
|
||||
args["Message"] = "ParsingErrorEmptyInvBindInvalidModel";
|
||||
mWarningsArray.append(args);
|
||||
setLoadState( ERROR_PARSING );
|
||||
}
|
||||
// </FS:Beq>
|
||||
for (size_t k = 0; k < count; ++k)
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
|
|
@ -1520,7 +1530,14 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <FS:Beq> FIRE-34811 Crash during import due to missing inv_bind_matrices.
|
||||
if (model->mSkinInfo.mInvBindMatrix.empty())
|
||||
{
|
||||
model->mSkinInfo.mJointNames.clear();
|
||||
model->mSkinInfo.mJointNums.clear();
|
||||
missingSkeletonOrScene = true; // set this true as we've just wiped that data.
|
||||
}
|
||||
// </FS:Beq>
|
||||
//Now that we've parsed the joint array, let's determine if we have a full rig
|
||||
//(which means we have all the joint sthat are required for an avatar versus
|
||||
//a skinned asset attached to a node in a file that contains an entire skeleton,
|
||||
|
|
|
|||
|
|
@ -1592,7 +1592,7 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi
|
|||
for (U32 i = 0; i < mJointNames.size(); ++i)
|
||||
{
|
||||
ret[ "joint_names" ][ i ] = mJointNames[ i ];
|
||||
|
||||
if (mInvBindMatrix.size() < i) break; // <FS:Beq/> FIRE-34811 Crash during import due to missing inv_bind_matrices.
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
for (U32 k = 0; k < 4; k++)
|
||||
|
|
|
|||
|
|
@ -430,6 +430,13 @@ bool LLScrollListCtrl::setMaxItemCount(S32 max_count)
|
|||
return (max_count == mMaxItemCount);
|
||||
}
|
||||
|
||||
// <FS:PP>
|
||||
S32 LLScrollListCtrl::getMaxItemCount() const
|
||||
{
|
||||
return mMaxItemCount;
|
||||
}
|
||||
// </FS:PP>
|
||||
|
||||
S32 LLScrollListCtrl::isEmpty() const
|
||||
{
|
||||
return mItemList.empty();
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ public:
|
|||
|
||||
// returns false if unable to set the max count so low
|
||||
bool setMaxItemCount(S32 max_count);
|
||||
S32 getMaxItemCount() const; // <FS:PP>
|
||||
|
||||
bool selectByID( const LLUUID& id ); // false if item not found
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ include(jemalloc)
|
|||
include(Discord)
|
||||
|
||||
# <FS:ND> if using ndPhysicsstub this variable will be unset, we don't need to build any stub code viewer side in that case
|
||||
if( LLPHYSICSEXTENSIONS_SRC_DIR )
|
||||
if (LLPHYSICSEXTENSIONS_SRC_DIR)
|
||||
# </FS:ND>
|
||||
|
||||
if (NOT HAVOK_TPV)
|
||||
|
|
@ -81,7 +81,7 @@ if (NOT HAVOK_TPV)
|
|||
endif (NOT HAVOK_TPV)
|
||||
|
||||
# <FS:ND>
|
||||
endif( LLPHYSICSEXTENSIONS_SRC_DIR )
|
||||
endif (LLPHYSICSEXTENSIONS_SRC_DIR)
|
||||
# </FS:ND>
|
||||
|
||||
set(viewer_SOURCE_FILES
|
||||
|
|
@ -128,7 +128,7 @@ set(viewer_SOURCE_FILES
|
|||
fsfloaternearbychat.cpp
|
||||
fsfloaterpartialinventory.cpp
|
||||
fsfloaterplacedetails.cpp
|
||||
fsfloaterposer.cpp
|
||||
fsfloaterposer.cpp
|
||||
fsfloaterposestand.cpp
|
||||
fsfloaterprotectedfolders.cpp
|
||||
fsfloaterradar.cpp
|
||||
|
|
@ -141,7 +141,7 @@ set(viewer_SOURCE_FILES
|
|||
fsfloatervramusage.cpp
|
||||
fsfloaterwearablefavorites.cpp
|
||||
fsfloaterwhitelisthelper.cpp
|
||||
fsjointpose.cpp
|
||||
fsjointpose.cpp
|
||||
fskeywords.cpp
|
||||
fslslbridge.cpp
|
||||
fslslbridgerequest.cpp
|
||||
|
|
@ -163,8 +163,8 @@ set(viewer_SOURCE_FILES
|
|||
fspanelradar.cpp
|
||||
fsparticipantlist.cpp
|
||||
fspose.cpp
|
||||
fsposeranimator.cpp
|
||||
fsposingmotion.cpp
|
||||
fsposeranimator.cpp
|
||||
fsposingmotion.cpp
|
||||
fsprimfeedauth.cpp
|
||||
fsradar.cpp
|
||||
fsradarentry.cpp
|
||||
|
|
@ -174,7 +174,7 @@ set(viewer_SOURCE_FILES
|
|||
fsscriptlibrary.cpp
|
||||
fsscrolllistctrl.cpp
|
||||
fsslurlcommand.cpp
|
||||
fsvirtualtrackpad.cpp
|
||||
fsvirtualtrackpad.cpp
|
||||
fsworldmapmessage.cpp
|
||||
lggbeamcolormapfloater.cpp
|
||||
lggbeammapfloater.cpp
|
||||
|
|
@ -194,10 +194,12 @@ set(viewer_SOURCE_FILES
|
|||
vjlocalmeshimportdae.cpp
|
||||
|
||||
gltfscenemanager.cpp
|
||||
gltf/asset.cpp
|
||||
gltf/accessor.cpp
|
||||
gltf/primitive.cpp
|
||||
gltf/animation.cpp
|
||||
# <FS:Ansariel> Group GLTF files into their subfolders
|
||||
#gltf/asset.cpp
|
||||
#gltf/accessor.cpp
|
||||
#gltf/primitive.cpp
|
||||
#gltf/animation.cpp
|
||||
# </FS:Ansariel> Group GLTF files into their subfolders
|
||||
groupchatlistener.cpp
|
||||
llaccountingcostmanager.cpp
|
||||
llaisapi.cpp
|
||||
|
|
@ -300,11 +302,11 @@ set(viewer_SOURCE_FILES
|
|||
llflexibleobject.cpp
|
||||
llfloater360capture.cpp
|
||||
llfloaterabout.cpp
|
||||
llfloateravatarwelcomepack.cpp
|
||||
llfloaterbvhpreview.cpp
|
||||
llfloateraddpaymentmethod.cpp
|
||||
llfloaterauction.cpp
|
||||
llfloaterautoreplacesettings.cpp
|
||||
llfloateravatar.cpp
|
||||
llfloateravatarpicker.cpp
|
||||
llfloateravatarrendersettings.cpp
|
||||
llfloateravatartextures.cpp
|
||||
|
|
@ -887,6 +889,18 @@ set(viewer_SOURCE_FILES
|
|||
NACLfloaterexploresounds.cpp
|
||||
)
|
||||
|
||||
# <FS:Ansariel> Group GLTF files into their subfolders
|
||||
set(viewer_GLTF_SOURCE_FILES
|
||||
gltf/asset.cpp
|
||||
gltf/accessor.cpp
|
||||
gltf/primitive.cpp
|
||||
gltf/animation.cpp
|
||||
)
|
||||
|
||||
source_group("Source Files\\GLTF" FILES ${viewer_GLTF_SOURCE_FILES})
|
||||
list(APPEND viewer_SOURCE_FILES ${viewer_GLTF_SOURCE_FILES})
|
||||
# </FS:Ansariel> Group GLTF files into their subfolders
|
||||
|
||||
if (OPENSIM)
|
||||
list(APPEND viewer_SOURCE_FILES
|
||||
fsgridhandler.cpp
|
||||
|
|
@ -951,7 +965,7 @@ set(viewer_HEADER_FILES
|
|||
fsfloaternearbychat.h
|
||||
fsfloaterpartialinventory.h
|
||||
fsfloaterplacedetails.h
|
||||
fsfloaterposer.h
|
||||
fsfloaterposer.h
|
||||
fsfloaterposestand.h
|
||||
fsfloaterprotectedfolders.h
|
||||
fsfloaterradar.h
|
||||
|
|
@ -987,8 +1001,8 @@ set(viewer_HEADER_FILES
|
|||
fspanelradar.h
|
||||
fsparticipantlist.h
|
||||
fspose.h
|
||||
fsposeranimator.h
|
||||
fsposingmotion.h
|
||||
fsposeranimator.h
|
||||
fsposingmotion.h
|
||||
fsprimfeedauth.h
|
||||
fsradar.h
|
||||
fsradarentry.h
|
||||
|
|
@ -999,7 +1013,7 @@ set(viewer_HEADER_FILES
|
|||
fsscrolllistctrl.h
|
||||
fsslurl.h
|
||||
fsslurlcommand.h
|
||||
fsvirtualtrackpad.h
|
||||
fsvirtualtrackpad.h
|
||||
fsworldmapmessage.h
|
||||
lggbeamcolormapfloater.h
|
||||
lggbeammapfloater.h
|
||||
|
|
@ -1019,11 +1033,13 @@ set(viewer_HEADER_FILES
|
|||
|
||||
gltfscenemanager.h
|
||||
groupchatlistener.h
|
||||
gltf/asset.h
|
||||
gltf/accessor.h
|
||||
gltf/buffer_util.h
|
||||
gltf/primitive.h
|
||||
gltf/animation.h
|
||||
# <FS:Ansariel> Group GLTF files into their subfolders
|
||||
#gltf/asset.h
|
||||
#gltf/accessor.h
|
||||
#gltf/buffer_util.h
|
||||
#gltf/primitive.h
|
||||
#gltf/animation.h
|
||||
# </FS:Ansariel> Group GLTF files into their subfolders
|
||||
llaccountingcost.h
|
||||
llaccountingcostmanager.h
|
||||
llaisapi.h
|
||||
|
|
@ -1127,11 +1143,11 @@ set(viewer_HEADER_FILES
|
|||
llflexibleobject.h
|
||||
llfloater360capture.h
|
||||
llfloaterabout.h
|
||||
llfloateravatarwelcomepack.h
|
||||
llfloaterbvhpreview.h
|
||||
llfloateraddpaymentmethod.h
|
||||
llfloaterauction.h
|
||||
llfloaterautoreplacesettings.h
|
||||
llfloateravatar.h
|
||||
llfloateravatarpicker.h
|
||||
llfloateravatarrendersettings.h
|
||||
llfloateravatartextures.h
|
||||
|
|
@ -1714,6 +1730,19 @@ set(viewer_HEADER_FILES
|
|||
list(APPEND viewer_SOURCE_FILES llperfstats.cpp)
|
||||
list(APPEND viewer_HEADER_FILES llperfstats.h)
|
||||
|
||||
# <FS:Ansariel> Group GLTF files into their subfolders
|
||||
set(viewer_GLTF_HEADER_FILES
|
||||
gltf/asset.h
|
||||
gltf/accessor.h
|
||||
gltf/buffer_util.h
|
||||
gltf/primitive.h
|
||||
gltf/animation.h
|
||||
)
|
||||
|
||||
source_group("Header Files\\GLTF" FILES ${viewer_GLTF_HEADER_FILES})
|
||||
list(APPEND viewer_HEADER_FILES ${viewer_GLTF_HEADER_FILES})
|
||||
# </FS:Ansariel> Group GLTF files into their subfolders
|
||||
|
||||
if (USE_BUGSPLAT)
|
||||
list(APPEND viewer_SOURCE_FILES
|
||||
bugsplatattributes.cpp
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ private:
|
|||
bool mBlocked;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<LLUUID, NACLAntiSpamQueueEntry*, FSUUIDHash> spam_queue_entry_map_t;
|
||||
typedef std::unordered_set<LLUUID, FSUUIDHash> collision_sound_set_t;
|
||||
typedef std::unordered_map<LLUUID, NACLAntiSpamQueueEntry*> spam_queue_entry_map_t;
|
||||
typedef std::unordered_set<LLUUID> collision_sound_set_t;
|
||||
|
||||
class NACLAntiSpamQueue
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "fscommon.h"
|
||||
#include "rlvhandler.h"
|
||||
|
||||
static const size_t num_collision_sounds = 28;
|
||||
constexpr size_t num_collision_sounds = 28;
|
||||
const LLUUID collision_sounds[num_collision_sounds] =
|
||||
{
|
||||
LLUUID("dce5fdd4-afe4-4ea1-822f-dd52cac46b08"),
|
||||
|
|
@ -73,8 +73,11 @@ bool NACLFloaterExploreSounds::postBuild()
|
|||
getChild<LLButton>("play_locally_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::handlePlayLocally, this));
|
||||
getChild<LLButton>("look_at_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::handleLookAt, this));
|
||||
getChild<LLButton>("stop_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::handleStop, this));
|
||||
getChild<LLButton>("bl_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::blacklistSound, this));
|
||||
getChild<LLButton>("bl_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::blacklistSound, this, FSAssetBlacklist::eBlacklistFlag::NONE));
|
||||
getChild<LLButton>("stop_locally_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::handleStopLocally, this));
|
||||
getChild<LLButton>("block_avatar_worn_sounds_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::blacklistSound, this, FSAssetBlacklist::eBlacklistFlag::WORN));
|
||||
getChild<LLButton>("block_avatar_rezzed_sounds_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::blacklistSound, this, FSAssetBlacklist::eBlacklistFlag::REZZED));
|
||||
getChild<LLButton>("block_avatar_gesture_sounds_btn")->setClickedCallback(boost::bind(&NACLFloaterExploreSounds::blacklistSound, this, FSAssetBlacklist::eBlacklistFlag::GESTURE));
|
||||
|
||||
mHistoryScroller = getChild<LLScrollListCtrl>("sound_list");
|
||||
mHistoryScroller->setCommitCallback(boost::bind(&NACLFloaterExploreSounds::handleSelection, this));
|
||||
|
|
@ -98,31 +101,26 @@ void NACLFloaterExploreSounds::handleSelection()
|
|||
childSetEnabled("play_locally_btn", num_selected);
|
||||
childSetEnabled("stop_btn", num_selected);
|
||||
childSetEnabled("bl_btn", num_selected);
|
||||
childSetEnabled("block_avatar_worn_sounds_btn", num_selected);
|
||||
childSetEnabled("block_avatar_rezzed_sounds_btn", num_selected);
|
||||
childSetEnabled("block_avatar_gesture_sounds_btn", num_selected);
|
||||
}
|
||||
|
||||
LLSoundHistoryItem NACLFloaterExploreSounds::getItem(const LLUUID& itemID)
|
||||
LLSoundHistoryItem NACLFloaterExploreSounds::getItem(const LLUUID& itemID) const
|
||||
{
|
||||
std::map<LLUUID, LLSoundHistoryItem>::iterator found = gSoundHistory.find(itemID);
|
||||
if (found != gSoundHistory.end())
|
||||
if (auto found = gSoundHistory.find(itemID); found != gSoundHistory.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If log is paused, hopefully we can find it in mLastHistory
|
||||
std::list<LLSoundHistoryItem>::iterator iter = mLastHistory.begin();
|
||||
std::list<LLSoundHistoryItem>::iterator end = mLastHistory.end();
|
||||
for ( ; iter != end; ++iter)
|
||||
{
|
||||
if ((*iter).mID == itemID)
|
||||
{
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
if (auto foundHistory = std::find_if(mLastHistory.begin(), mLastHistory.end(), [&](const auto& item) { return item.mID == itemID; });
|
||||
foundHistory != mLastHistory.end())
|
||||
return *foundHistory;
|
||||
}
|
||||
LLSoundHistoryItem item;
|
||||
item.mID = LLUUID::null;
|
||||
return item;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
class LLSoundHistoryItemCompare
|
||||
|
|
@ -175,11 +173,9 @@ bool NACLFloaterExploreSounds::tick()
|
|||
}
|
||||
else
|
||||
{
|
||||
std::map<LLUUID, LLSoundHistoryItem>::iterator map_iter = gSoundHistory.begin();
|
||||
std::map<LLUUID, LLSoundHistoryItem>::iterator map_end = gSoundHistory.end();
|
||||
for ( ; map_iter != map_end; ++map_iter)
|
||||
for (const auto& [id, item] : gSoundHistory)
|
||||
{
|
||||
history.push_back((*map_iter).second);
|
||||
history.emplace_back(item);
|
||||
}
|
||||
LLSoundHistoryItemCompare c;
|
||||
history.sort(c);
|
||||
|
|
@ -189,24 +185,16 @@ bool NACLFloaterExploreSounds::tick()
|
|||
// Save scroll pos and selection so they can be restored
|
||||
S32 scroll_pos = mHistoryScroller->getScrollPos();
|
||||
uuid_vec_t selected_ids;
|
||||
std::vector<LLScrollListItem*> selected_items = mHistoryScroller->getAllSelected();
|
||||
std::vector<LLScrollListItem*>::iterator selection_iter = selected_items.begin();
|
||||
std::vector<LLScrollListItem*>::iterator selection_end = selected_items.end();
|
||||
for (; selection_iter != selection_end; ++selection_iter)
|
||||
for (const auto* item : mHistoryScroller->getAllSelected())
|
||||
{
|
||||
selected_ids.push_back((*selection_iter)->getUUID());
|
||||
selected_ids.emplace_back(item->getUUID());
|
||||
}
|
||||
|
||||
mHistoryScroller->clearRows();
|
||||
|
||||
std::list<LLUUID> unique_asset_list;
|
||||
|
||||
std::list<LLSoundHistoryItem>::iterator iter = history.begin();
|
||||
std::list<LLSoundHistoryItem>::iterator end = history.end();
|
||||
for ( ; iter != end; ++iter)
|
||||
std::unordered_set<LLUUID> unique_asset_list;
|
||||
for (auto& item : history)
|
||||
{
|
||||
LLSoundHistoryItem item = (*iter);
|
||||
|
||||
bool is_avatar = item.mOwnerID == item.mSourceID;
|
||||
if (is_avatar && !show_avatars)
|
||||
{
|
||||
|
|
@ -219,7 +207,7 @@ bool NACLFloaterExploreSounds::tick()
|
|||
continue;
|
||||
}
|
||||
|
||||
bool is_repeated_asset = std::find(unique_asset_list.begin(), unique_asset_list.end(), item.mAssetID) != unique_asset_list.end();
|
||||
bool is_repeated_asset = unique_asset_list.contains(item.mAssetID);
|
||||
if (is_repeated_asset && !show_repeated_assets)
|
||||
{
|
||||
continue;
|
||||
|
|
@ -237,7 +225,7 @@ bool NACLFloaterExploreSounds::tick()
|
|||
continue;
|
||||
}
|
||||
|
||||
unique_asset_list.push_back(item.mAssetID);
|
||||
unique_asset_list.emplace(item.mAssetID);
|
||||
|
||||
LLSD element;
|
||||
element["id"] = item.mID;
|
||||
|
|
@ -315,26 +303,17 @@ bool NACLFloaterExploreSounds::tick()
|
|||
mHistoryScroller->setScrollPos(scroll_pos);
|
||||
|
||||
// Clean up stopped local audio source IDs
|
||||
uuid_vec_t stopped_audio_src_ids;
|
||||
uuid_vec_t::iterator audio_src_id_iter = mLocalPlayingAudioSourceIDs.begin();
|
||||
uuid_vec_t::iterator audio_src_id_end = mLocalPlayingAudioSourceIDs.end();
|
||||
for (; audio_src_id_iter != audio_src_id_end; ++audio_src_id_iter)
|
||||
while (audio_src_id_iter != mLocalPlayingAudioSourceIDs.end())
|
||||
{
|
||||
LLUUID audio_src_id = *audio_src_id_iter;
|
||||
LLAudioSource* audio_source = gAudiop->findAudioSource(audio_src_id);
|
||||
if (!audio_source || audio_source->isDone())
|
||||
const LLUUID& audio_src_id = *audio_src_id_iter;
|
||||
if (LLAudioSource* audio_source = gAudiop->findAudioSource(audio_src_id); !audio_source || audio_source->isDone())
|
||||
{
|
||||
stopped_audio_src_ids.push_back(audio_src_id);
|
||||
audio_src_id_iter = mLocalPlayingAudioSourceIDs.erase(audio_src_id_iter);
|
||||
}
|
||||
}
|
||||
|
||||
for (uuid_vec_t::iterator stopped_audio_src_ids_iter = stopped_audio_src_ids.begin();
|
||||
stopped_audio_src_ids_iter != stopped_audio_src_ids.end(); ++stopped_audio_src_ids_iter)
|
||||
{
|
||||
uuid_vec_t::iterator find_iter = std::find(mLocalPlayingAudioSourceIDs.begin(), mLocalPlayingAudioSourceIDs.end(), *stopped_audio_src_ids_iter);
|
||||
if (find_iter != mLocalPlayingAudioSourceIDs.end())
|
||||
else
|
||||
{
|
||||
mLocalPlayingAudioSourceIDs.erase(find_iter);
|
||||
audio_src_id_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,29 +324,26 @@ bool NACLFloaterExploreSounds::tick()
|
|||
|
||||
void NACLFloaterExploreSounds::handlePlayLocally()
|
||||
{
|
||||
std::vector<LLScrollListItem*> selection = mHistoryScroller->getAllSelected();
|
||||
std::vector<LLScrollListItem*>::iterator selection_iter = selection.begin();
|
||||
std::vector<LLScrollListItem*>::iterator selection_end = selection.end();
|
||||
uuid_vec_t asset_list;
|
||||
for ( ; selection_iter != selection_end; ++selection_iter)
|
||||
std::unordered_set<LLUUID> asset_list;
|
||||
for (const auto* selected_item : mHistoryScroller->getAllSelected())
|
||||
{
|
||||
LLSoundHistoryItem item = getItem((*selection_iter)->getValue());
|
||||
LLSoundHistoryItem item = getItem(selected_item->getValue());
|
||||
if (item.mID.isNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unique assets only
|
||||
if (std::find(asset_list.begin(), asset_list.end(), item.mAssetID) == asset_list.end())
|
||||
if (!asset_list.contains(item.mAssetID))
|
||||
{
|
||||
asset_list.push_back(item.mAssetID);
|
||||
asset_list.emplace(item.mAssetID);
|
||||
LLUUID audio_source_id = LLUUID::generateNewID();
|
||||
gAudiop->triggerSound(item.mAssetID, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI, LLVector3d::zero, LLUUID::null, audio_source_id);
|
||||
mLocalPlayingAudioSourceIDs.push_back(audio_source_id);
|
||||
mLocalPlayingAudioSourceIDs.emplace_back(audio_source_id);
|
||||
}
|
||||
}
|
||||
|
||||
childSetEnabled("stop_locally_btn", mLocalPlayingAudioSourceIDs.size() > 0);
|
||||
childSetEnabled("stop_locally_btn", !mLocalPlayingAudioSourceIDs.empty());
|
||||
}
|
||||
|
||||
void NACLFloaterExploreSounds::handleLookAt()
|
||||
|
|
@ -407,14 +383,12 @@ void NACLFloaterExploreSounds::handleLookAt()
|
|||
|
||||
void NACLFloaterExploreSounds::handleStop()
|
||||
{
|
||||
std::vector<LLScrollListItem*> selection = mHistoryScroller->getAllSelected();
|
||||
for (const auto& selection_item : selection)
|
||||
for (const auto& selection_item : mHistoryScroller->getAllSelected())
|
||||
{
|
||||
LLSoundHistoryItem item = getItem(selection_item->getValue());
|
||||
if (item.mID.notNull() && item.mPlaying)
|
||||
{
|
||||
LLAudioSource* audio_source = gAudiop->findAudioSource(item.mSourceID);
|
||||
if (audio_source)
|
||||
if (LLAudioSource* audio_source = gAudiop->findAudioSource(item.mSourceID))
|
||||
{
|
||||
S32 type = item.mType;
|
||||
audio_source->setType(LLAudioEngine::AUDIO_TYPE_UI);
|
||||
|
|
@ -449,13 +423,9 @@ void NACLFloaterExploreSounds::handleStop()
|
|||
|
||||
void NACLFloaterExploreSounds::handleStopLocally()
|
||||
{
|
||||
uuid_vec_t::iterator audio_source_id_iter = mLocalPlayingAudioSourceIDs.begin();
|
||||
uuid_vec_t::iterator audio_source_id_end = mLocalPlayingAudioSourceIDs.end();
|
||||
for (; audio_source_id_iter != audio_source_id_end; ++audio_source_id_iter)
|
||||
for (const auto& audio_source_id : mLocalPlayingAudioSourceIDs)
|
||||
{
|
||||
LLUUID audio_source_id = *audio_source_id_iter;
|
||||
LLAudioSource* audio_source = gAudiop->findAudioSource(audio_source_id);
|
||||
if (audio_source && !audio_source->isDone())
|
||||
if (LLAudioSource* audio_source = gAudiop->findAudioSource(audio_source_id); audio_source && !audio_source->isDone())
|
||||
{
|
||||
audio_source->play(LLUUID::null);
|
||||
}
|
||||
|
|
@ -465,51 +435,44 @@ void NACLFloaterExploreSounds::handleStopLocally()
|
|||
}
|
||||
|
||||
//add sound to blacklist
|
||||
void NACLFloaterExploreSounds::blacklistSound()
|
||||
void NACLFloaterExploreSounds::blacklistSound(FSAssetBlacklist::eBlacklistFlag flag)
|
||||
{
|
||||
std::vector<LLScrollListItem*> selection = mHistoryScroller->getAllSelected();
|
||||
std::vector<LLScrollListItem*>::iterator selection_iter = selection.begin();
|
||||
std::vector<LLScrollListItem*>::iterator selection_end = selection.end();
|
||||
|
||||
for ( ; selection_iter != selection_end; ++selection_iter)
|
||||
for (const auto* selected_item : mHistoryScroller->getAllSelected())
|
||||
{
|
||||
LLSoundHistoryItem item = getItem((*selection_iter)->getValue());
|
||||
LLSoundHistoryItem item = getItem(selected_item->getValue());
|
||||
if (item.mID.isNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string region_name;
|
||||
LLViewerRegion* cur_region = gAgent.getRegion();
|
||||
if (cur_region)
|
||||
if (LLViewerRegion* cur_region = gAgent.getRegion())
|
||||
{
|
||||
region_name = cur_region->getName();
|
||||
}
|
||||
|
||||
blacklist_avatar_name_cache_connection_map_t::iterator it = mBlacklistAvatarNameCacheConnections.find(item.mOwnerID);
|
||||
if (it != mBlacklistAvatarNameCacheConnections.end())
|
||||
if (LLAvatarName av_name; LLAvatarNameCache::get(item.mOwnerID, &av_name))
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mBlacklistAvatarNameCacheConnections.erase(it);
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(flag == FSAssetBlacklist::eBlacklistFlag::NONE ? item.mAssetID : item.mOwnerID, av_name.getCompleteName(), region_name, LLAssetType::AT_SOUND, flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create unique UUID here instead of avatar UUID because we might be blacklisting more than one sound of the same user
|
||||
LLUUID requestId = LLUUID::generateNewID();
|
||||
mBlacklistAvatarNameCacheConnections.try_emplace(requestId, LLAvatarNameCache::get(item.mOwnerID, boost::bind(&NACLFloaterExploreSounds::onBlacklistAvatarNameCacheCallback, this, requestId, _1, _2, item.mAssetID, region_name, flag)));
|
||||
}
|
||||
LLAvatarNameCache::callback_connection_t cb = LLAvatarNameCache::get(item.mOwnerID, boost::bind(&NACLFloaterExploreSounds::onBlacklistAvatarNameCacheCallback, this, _1, _2, item.mAssetID, region_name));
|
||||
mBlacklistAvatarNameCacheConnections.insert(std::make_pair(item.mOwnerID, cb));
|
||||
}
|
||||
}
|
||||
|
||||
void NACLFloaterExploreSounds::onBlacklistAvatarNameCacheCallback(const LLUUID& av_id, const LLAvatarName& av_name, const LLUUID& asset_id, const std::string& region_name)
|
||||
void NACLFloaterExploreSounds::onBlacklistAvatarNameCacheCallback(const LLUUID& request_id, const LLUUID& av_id, const LLAvatarName& av_name, const LLUUID& asset_id, const std::string& region_name, FSAssetBlacklist::eBlacklistFlag flag)
|
||||
{
|
||||
blacklist_avatar_name_cache_connection_map_t::iterator it = mBlacklistAvatarNameCacheConnections.find(av_id);
|
||||
if (it != mBlacklistAvatarNameCacheConnections.end())
|
||||
if (auto found = mBlacklistAvatarNameCacheConnections.find(request_id); found != mBlacklistAvatarNameCacheConnections.end())
|
||||
{
|
||||
if (it->second.connected())
|
||||
if (found->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
found->second.disconnect();
|
||||
}
|
||||
mBlacklistAvatarNameCacheConnections.erase(it);
|
||||
mBlacklistAvatarNameCacheConnections.erase(found);
|
||||
}
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(asset_id, av_name.getCompleteName(), region_name, LLAssetType::AT_SOUND);
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(flag == FSAssetBlacklist::eBlacklistFlag::NONE ? asset_id : av_id, av_name.getCompleteName(), region_name, LLAssetType::AT_SOUND, flag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "lleventtimer.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "fsassetblacklist.h"
|
||||
|
||||
class LLCheckBoxCtrl;
|
||||
class LLScrollListCtrl;
|
||||
|
|
@ -22,7 +23,7 @@ public:
|
|||
|
||||
bool tick() override;
|
||||
|
||||
LLSoundHistoryItem getItem(const LLUUID& itemID);
|
||||
LLSoundHistoryItem getItem(const LLUUID& itemID) const;
|
||||
|
||||
private:
|
||||
virtual ~NACLFloaterExploreSounds();
|
||||
|
|
@ -31,14 +32,14 @@ private:
|
|||
void handleStop();
|
||||
void handleStopLocally();
|
||||
void handleSelection();
|
||||
void blacklistSound();
|
||||
void blacklistSound(FSAssetBlacklist::eBlacklistFlag flag);
|
||||
|
||||
LLScrollListCtrl* mHistoryScroller;
|
||||
LLCheckBoxCtrl* mCollisionSounds;
|
||||
LLCheckBoxCtrl* mRepeatedAssets;
|
||||
LLCheckBoxCtrl* mAvatarSounds;
|
||||
LLCheckBoxCtrl* mObjectSounds;
|
||||
LLCheckBoxCtrl* mPaused;
|
||||
LLScrollListCtrl* mHistoryScroller{ nullptr };
|
||||
LLCheckBoxCtrl* mCollisionSounds{ nullptr };
|
||||
LLCheckBoxCtrl* mRepeatedAssets{ nullptr };
|
||||
LLCheckBoxCtrl* mAvatarSounds{ nullptr };
|
||||
LLCheckBoxCtrl* mObjectSounds{ nullptr };
|
||||
LLCheckBoxCtrl* mPaused{ nullptr };
|
||||
|
||||
std::list<LLSoundHistoryItem> mLastHistory;
|
||||
|
||||
|
|
@ -47,7 +48,7 @@ private:
|
|||
typedef std::map<LLUUID, boost::signals2::connection> blacklist_avatar_name_cache_connection_map_t;
|
||||
blacklist_avatar_name_cache_connection_map_t mBlacklistAvatarNameCacheConnections;
|
||||
|
||||
void onBlacklistAvatarNameCacheCallback(const LLUUID& av_id, const LLAvatarName& av_name, const LLUUID& asset_id, const std::string& region_name);
|
||||
void onBlacklistAvatarNameCacheCallback(const LLUUID& request_id, const LLUUID& av_id, const LLAvatarName& av_name, const LLUUID& asset_id, const std::string& region_name, FSAssetBlacklist::eBlacklistFlag flag);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@
|
|||
label_ref="Command_Avatar_Label"
|
||||
tooltip_ref="Command_Avatar_Tooltip"
|
||||
execute_function="Floater.Toggle"
|
||||
execute_parameters="avatar"
|
||||
execute_parameters="avatar_welcome_pack"
|
||||
is_enabled_function="GridFeatureCheck"
|
||||
is_enabled_parameters="avatar_picker"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="avatar"
|
||||
is_running_parameters="avatar_welcome_pack"
|
||||
/>
|
||||
<command name="build"
|
||||
available_in_toybox="true"
|
||||
|
|
|
|||
|
|
@ -2197,16 +2197,16 @@
|
|||
<key>Value</key>
|
||||
<real>16.0</real>
|
||||
</map>
|
||||
<key>AvatarPickerURL</key>
|
||||
<key>AvatarWelcomePack</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Avatar picker contents</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/avatars.html</string>
|
||||
<key>Comment</key>
|
||||
<string>Avatar Welcome Pack contents</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/vawp/index.html</string>
|
||||
</map>
|
||||
<key>AvatarRotateThresholdSlow</key>
|
||||
<map>
|
||||
|
|
@ -13266,6 +13266,26 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<real>0</real>
|
||||
</map>
|
||||
<key>FSImpostorAvatarExclude</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Allows for Animesh User or Control Avatars to be excluded from using impostor rendering. Values are: (0 - None, 1 - User, 2 - Control, 3 - Both).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>SanityCheckType</key>
|
||||
<string>Between</string>
|
||||
<key>SanityValue</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>3</integer>
|
||||
</array>
|
||||
<key>SanityComment</key>
|
||||
<string>Setting this value lower than 0 or higher than 3 has no effect.</string>
|
||||
</map>
|
||||
<key>RenderAvatarComplexityMode</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -26443,6 +26463,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSManipShowJointMarkers</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show small markers where the selectable joints are.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSLocalMeshApplyJointOffsets</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -26476,5 +26507,271 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<!-- <FS:Zi> Area Search Defaults -->
|
||||
<key>FSAreaSearch_ExcludeAttachments</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Exclude attachments</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_ExcludeChildPrims</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Exclude child prims</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_ExcludeNeighborRegions</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Exclude neighbor regions</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_ExcludePhysical</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Exclude physical objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_ExcludeReflectionProbes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Exclude reflection probes</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_ExcludeTemporary</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Exclude temporary objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_FilterDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Filter by distance</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_FilterForSale</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Only show objects that are for sale</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_MaximumDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Maximum distance</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>999999</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_MaximumPrice</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Maximum price</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>999999</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_MinimumDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Minimum distance</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_MinimumPrice</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Minimum price</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyAttachments</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only attachments</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyCopiable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only copiable objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyCurrentParcel</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only objects in the current parcel</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyForSale</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only objects that are for sale</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyLocked</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only locked objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyMOAP</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only objects that have shared media applied</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyModifiable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only modifiable objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyPhantom</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only phantom objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyPhysical</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only physical objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyReflectionProbes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only reflection probes</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyTemporary</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only temporary objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAreaSearch_OnlyTransferable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Area Search Filter: Find only transferable objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<!-- </FS:Zi> Area Search Defaults -->
|
||||
</map>
|
||||
</llsd>
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static std::string RLVa_hideNameIfRestricted(std::string_view name)
|
|||
return RlvStrings::getAnonym(std::string(name));
|
||||
}
|
||||
|
||||
F32 calculateObjectDistance(LLVector3d agent_pos, LLViewerObject* object)
|
||||
F32 static calculateObjectDistance(LLVector3d agent_pos, LLViewerObject* object)
|
||||
{
|
||||
if (object->isHUDAttachment())
|
||||
{
|
||||
|
|
@ -107,7 +107,7 @@ public:
|
|||
FSParcelChangeObserver(FSAreaSearch* area_search_floater) : mAreaSearchFloater(area_search_floater) {}
|
||||
|
||||
private:
|
||||
/*virtual*/ void changed()
|
||||
void changed() override
|
||||
{
|
||||
if (mAreaSearchFloater)
|
||||
{
|
||||
|
|
@ -139,41 +139,11 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
LLUUID mObjectID;
|
||||
LLUUID mObjectID;
|
||||
};
|
||||
|
||||
FSAreaSearch::FSAreaSearch(const LLSD& key) :
|
||||
LLFloater(key),
|
||||
mActive(false),
|
||||
mFilterForSale(false),
|
||||
mFilterForSaleMin(0),
|
||||
mFilterForSaleMax(999999),
|
||||
mFilterPhysical(false),
|
||||
mFilterTemporary(false),
|
||||
mRegexSearch(false),
|
||||
mFilterClickAction(false),
|
||||
mFilterLocked(false),
|
||||
mFilterPhantom(false),
|
||||
mFilterAttachment(false),
|
||||
mFilterMoaP(false),
|
||||
mFilterReflectionProbe(false),
|
||||
mFilterDistance(false),
|
||||
mFilterDistanceMin(0),
|
||||
mFilterDistanceMax(999999),
|
||||
mFilterPermCopy(false),
|
||||
mFilterPermModify(false),
|
||||
mFilterPermTransfer(false),
|
||||
mFilterAgentParcelOnly(false),
|
||||
mBeacons(false),
|
||||
mExcludeAttachment(true),
|
||||
mExcludeTemporary(true),
|
||||
mExcludeReflectionProbe(false),
|
||||
mExcludePhysics(true),
|
||||
mExcludeChildPrims(true),
|
||||
mExcludeNeighborRegions(true),
|
||||
mRequestQueuePause(false),
|
||||
mRequestNeedsSent(false),
|
||||
mRlvBehaviorCallbackConnection()
|
||||
LLFloater(key)
|
||||
{
|
||||
gAgent.setFSAreaSearchActive(true);
|
||||
gAgent.changeInterestListMode(IL_MODE_360);
|
||||
|
|
@ -197,7 +167,7 @@ FSAreaSearch::~FSAreaSearch()
|
|||
// Tell the Simulator not to send us everything anymore
|
||||
// and revert to the regular "keyhole" frustum of interest
|
||||
// list updates.
|
||||
if( !LLApp::isExiting() )
|
||||
if (!LLApp::isExiting())
|
||||
{
|
||||
gAgent.changeInterestListMode(IL_MODE_DEFAULT);
|
||||
}
|
||||
|
|
@ -234,8 +204,7 @@ bool FSAreaSearch::postBuild()
|
|||
|
||||
if (!gSavedSettings.getBOOL("FSAreaSearchAdvanced"))
|
||||
{
|
||||
LLPanel* advanced_tab = mTab->getPanelByName("area_search_advanced_panel");
|
||||
if (advanced_tab)
|
||||
if (LLPanel* advanced_tab = mTab->getPanelByName("area_search_advanced_panel"))
|
||||
{
|
||||
mTab->removeTabPanel(advanced_tab);
|
||||
}
|
||||
|
|
@ -263,7 +232,7 @@ void FSAreaSearch::draw()
|
|||
{
|
||||
std::vector<LLScrollListItem*> items = mPanelList->getResultList()->getAllData();
|
||||
|
||||
for (const auto item : items)
|
||||
for (const auto* item : items)
|
||||
{
|
||||
if (LLViewerObject* objectp = gObjectList.findObject(item->getUUID()); objectp)
|
||||
{
|
||||
|
|
@ -492,7 +461,7 @@ void FSAreaSearch::findObjects()
|
|||
mRequestQueuePause = false;
|
||||
}
|
||||
|
||||
bool FSAreaSearch::isSearchableObject(LLViewerObject* objectp, LLViewerRegion* our_region)
|
||||
bool FSAreaSearch::isSearchableObject(LLViewerObject* objectp, LLViewerRegion* our_region) const
|
||||
{
|
||||
// need to be connected to region object is in.
|
||||
if (!objectp->getRegion())
|
||||
|
|
@ -1140,31 +1109,30 @@ void FSAreaSearch::getNameFromUUID(const LLUUID& id, std::string& name, bool gro
|
|||
if (!gCacheName->getIfThere(id, name, is_group))
|
||||
{
|
||||
name = unknown_name;
|
||||
if (std::find(mNamesRequested.begin(), mNamesRequested.end(), id) == mNamesRequested.end())
|
||||
if (!mNamesRequested.contains(id))
|
||||
{
|
||||
mNamesRequested.push_back(id);
|
||||
boost::signals2::connection cb_connection = gCacheName->get(id, group, boost::bind(&FSAreaSearch::callbackLoadFullName, this, _1, _2));
|
||||
mNameCacheConnections.insert(std::make_pair(id, cb_connection)); // mNamesRequested will do the dupe check
|
||||
mNamesRequested.emplace(id);
|
||||
mNameCacheConnections.try_emplace(id, gCacheName->get(id, group, boost::bind(&FSAreaSearch::callbackLoadFullName, this, _1, _2))); // mNamesRequested will do the dupe check
|
||||
}
|
||||
name_requested = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLAvatarName av_name;
|
||||
if (!LLAvatarNameCache::get(id, &av_name))
|
||||
if (LLAvatarName av_name; !LLAvatarNameCache::get(id, &av_name))
|
||||
{
|
||||
name = unknown_name;
|
||||
if (std::find(mNamesRequested.begin(), mNamesRequested.end(), id) == mNamesRequested.end())
|
||||
if (!mNamesRequested.contains(id))
|
||||
{
|
||||
mNamesRequested.push_back(id);
|
||||
boost::signals2::connection cb_connection = LLAvatarNameCache::get(id, boost::bind(&FSAreaSearch::avatarNameCacheCallback, this, _1, _2));
|
||||
mNameCacheConnections.insert(std::make_pair(id, cb_connection)); // mNamesRequested will do the dupe check
|
||||
mNamesRequested.emplace(id);
|
||||
mNameCacheConnections.try_emplace(id, LLAvatarNameCache::get(id, boost::bind(&FSAreaSearch::avatarNameCacheCallback, this, _1, _2))); // mNamesRequested will do the dupe check
|
||||
}
|
||||
name_requested = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = av_name.getCompleteName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1173,7 +1141,7 @@ void FSAreaSearch::avatarNameCacheCallback(const LLUUID& id, const LLAvatarName&
|
|||
callbackLoadFullName(id, av_name.getCompleteName());
|
||||
}
|
||||
|
||||
void FSAreaSearch::callbackLoadFullName(const LLUUID& id, const std::string& full_name )
|
||||
void FSAreaSearch::callbackLoadFullName(const LLUUID& id, const std::string& full_name)
|
||||
{
|
||||
if (auto iter = mNameCacheConnections.find(id); iter != mNameCacheConnections.end())
|
||||
{
|
||||
|
|
@ -1368,7 +1336,7 @@ void FSAreaSearch::onCommitCheckboxRegex()
|
|||
}
|
||||
}
|
||||
|
||||
void FSAreaSearch::setFindOwnerText(std::string value)
|
||||
void FSAreaSearch::setFindOwnerText(const std::string& value)
|
||||
{
|
||||
mPanelFind->mOwnerLineEditor->setText(value);
|
||||
}
|
||||
|
|
@ -1380,10 +1348,7 @@ void FSAreaSearch::setFindOwnerText(std::string value)
|
|||
|
||||
FSPanelAreaSearchList::FSPanelAreaSearchList(FSAreaSearch* pointer)
|
||||
: LLPanel(),
|
||||
mCounterText(0),
|
||||
mResultList(0),
|
||||
mFSAreaSearch(pointer),
|
||||
mFSAreaSearchColumnConfigConnection()
|
||||
mFSAreaSearch(pointer)
|
||||
{
|
||||
mColumnBits["distance"] = 1;
|
||||
mColumnBits["name"] = 2;
|
||||
|
|
@ -1497,7 +1462,7 @@ void FSPanelAreaSearchList::updateScrollList()
|
|||
|
||||
// Iterate over the rows in the list, deleting ones whose object has gone away.
|
||||
std::vector<LLScrollListItem*> items = mResultList->getAllData();
|
||||
for (const auto item : items)
|
||||
for (const auto* item : items)
|
||||
{
|
||||
const LLUUID& row_id = item->getUUID();
|
||||
LLViewerObject* objectp = gObjectList.findObject(row_id);
|
||||
|
|
@ -1603,7 +1568,7 @@ void FSPanelAreaSearchList::updateName(const LLUUID& id, const std::string& name
|
|||
// Iterate over the rows in the list, updating the ones with matching id.
|
||||
std::vector<LLScrollListItem*> items = mResultList->getAllData();
|
||||
|
||||
for (const auto item : items)
|
||||
for (const auto* item : items)
|
||||
{
|
||||
const LLUUID& row_id = item->getUUID();
|
||||
FSObjectProperties& details = mFSAreaSearch->mObjectDetails[row_id];
|
||||
|
|
@ -1696,7 +1661,7 @@ bool FSPanelAreaSearchList::onContextMenuItemVisibleRLV(const LLSD& userdata)
|
|||
}
|
||||
|
||||
std::vector<LLScrollListItem*> selected = mResultList->getAllSelected();
|
||||
for (const auto item : selected)
|
||||
for (const auto* item : selected)
|
||||
{
|
||||
const LLUUID& object_id = item->getUUID();
|
||||
LLViewerObject* objectp = gObjectList.findObject(object_id);
|
||||
|
|
@ -1780,7 +1745,7 @@ bool FSPanelAreaSearchList::onContextMenuItemClick(const LLSD& userdata)
|
|||
std::vector<LLScrollListItem*> selected = mResultList->getAllSelected();
|
||||
S32 cnt = 0;
|
||||
|
||||
for (const auto item : selected)
|
||||
for (const auto* item : selected)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
|
|
@ -1985,7 +1950,7 @@ bool FSPanelAreaSearchList::onContextMenuItemClick(const LLSD& userdata)
|
|||
LLSelectMgr::getInstance()->deselectAll();
|
||||
std::vector<LLScrollListItem*> selected = mResultList->getAllSelected();
|
||||
|
||||
for (const auto item : selected)
|
||||
for (const auto* item : selected)
|
||||
{
|
||||
const LLUUID& object_id = item->getUUID();
|
||||
LLViewerObject* objectp = gObjectList.findObject(object_id);
|
||||
|
|
@ -2063,9 +2028,8 @@ void FSPanelAreaSearchList::buyObject(FSObjectProperties& details, LLViewerObjec
|
|||
{
|
||||
LLSelectMgr::getInstance()->deselectAll();
|
||||
LLSelectMgr::getInstance()->selectObjectAndFamily(objectp);
|
||||
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->findNode(objectp);
|
||||
|
||||
if (node)
|
||||
if (LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->findNode(objectp))
|
||||
{
|
||||
node->mValid = true;
|
||||
node->mPermissions->init(details.creator_id, details.owner_id, details.last_owner_id, details.group_id);
|
||||
|
|
@ -2188,89 +2152,109 @@ FSPanelAreaSearchFilter::FSPanelAreaSearchFilter(FSAreaSearch* pointer)
|
|||
bool FSPanelAreaSearchFilter::postBuild()
|
||||
{
|
||||
mCheckboxLocked = getChild<LLCheckBoxCtrl>("filter_locked");
|
||||
mCheckboxLocked->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyLocked"));
|
||||
mCheckboxLocked->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxPhysical = getChild<LLCheckBoxCtrl>("filter_physical");
|
||||
mCheckboxPhysical->setEnabled(false);
|
||||
mCheckboxPhysical->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyPhysical"));
|
||||
mCheckboxPhysical->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxTemporary = getChild<LLCheckBoxCtrl>("filter_temporary");
|
||||
mCheckboxTemporary->setEnabled(false);
|
||||
mCheckboxTemporary->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyTemporary"));
|
||||
mCheckboxTemporary->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxPhantom = getChild<LLCheckBoxCtrl>("filter_phantom");
|
||||
mCheckboxPhantom->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyPhantom"));
|
||||
mCheckboxPhantom->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxForSale = getChild<LLCheckBoxCtrl>("filter_for_sale");
|
||||
mCheckboxForSale->set(gSavedSettings.getBOOL("FSAreaSearch_FilterForSale"));
|
||||
mCheckboxForSale->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxAttachment = getChild<LLCheckBoxCtrl>("filter_attachment");
|
||||
mCheckboxAttachment->setEnabled(false);
|
||||
mCheckboxAttachment->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyAttachments"));
|
||||
mCheckboxAttachment->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mSpinForSaleMinValue= getChild<LLSpinCtrl>("min_price");
|
||||
mSpinForSaleMinValue->set((F32)gSavedSettings.getS32("FSAreaSearch_MinimumPrice"));
|
||||
mSpinForSaleMinValue->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitSpin, this));
|
||||
|
||||
mSpinForSaleMaxValue= getChild<LLSpinCtrl>("max_price");
|
||||
mSpinForSaleMaxValue->set((F32)gSavedSettings.getS32("FSAreaSearch_MaximumPrice"));
|
||||
mSpinForSaleMaxValue->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitSpin, this));
|
||||
|
||||
mComboClickAction = getChild<LLComboBox>("click_action");
|
||||
mComboClickAction->setValue(gSavedSettings.getS32("FSAreaSearch_ClickAction"));
|
||||
mComboClickAction->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCombo, this));
|
||||
|
||||
mCheckboxExcludeAttachment = getChild<LLCheckBoxCtrl>("exclude_attachment");
|
||||
mCheckboxExcludeAttachment->set(true);
|
||||
mCheckboxExcludeAttachment->set(gSavedSettings.getBOOL("FSAreaSearch_ExcludeAttachments"));
|
||||
mCheckboxExcludeAttachment->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxExcludePhysics = getChild<LLCheckBoxCtrl>("exclude_physical");
|
||||
mCheckboxExcludePhysics->set(true);
|
||||
mCheckboxExcludePhysics->set(gSavedSettings.getBOOL("FSAreaSearch_ExcludePhysical"));
|
||||
mCheckboxExcludePhysics->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxExcludetemporary = getChild<LLCheckBoxCtrl>("exclude_temporary");
|
||||
mCheckboxExcludetemporary->set(true);
|
||||
mCheckboxExcludetemporary->set(gSavedSettings.getBOOL("FSAreaSearch_ExcludeTemporary"));
|
||||
mCheckboxExcludetemporary->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxExcludeReflectionProbes = getChild<LLCheckBoxCtrl>("exclude_reflection_probes");
|
||||
mCheckboxExcludeReflectionProbes->set(false);
|
||||
mCheckboxExcludeReflectionProbes->set(gSavedSettings.getBOOL("FSAreaSearch_ExcludeReflectionProbes"));
|
||||
mCheckboxExcludeReflectionProbes->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxExcludeChildPrim = getChild<LLCheckBoxCtrl>("exclude_childprim");
|
||||
mCheckboxExcludeChildPrim->set(true);
|
||||
mCheckboxExcludeChildPrim->set(gSavedSettings.getBOOL("FSAreaSearch_ExcludeChildPrims"));
|
||||
mCheckboxExcludeChildPrim->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxExcludeNeighborRegions = getChild<LLCheckBoxCtrl>("exclude_neighbor_region");
|
||||
mCheckboxExcludeNeighborRegions->set(true);
|
||||
mCheckboxExcludeNeighborRegions->set(gSavedSettings.getBOOL("FSAreaSearch_ExcludeNeighborRegions"));
|
||||
mCheckboxExcludeNeighborRegions->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mButtonApply = getChild<LLButton>("apply");
|
||||
mButtonApply->setClickedCallback(boost::bind(&FSAreaSearch::onButtonClickedSearch, mFSAreaSearch));
|
||||
|
||||
mButtonApply = getChild<LLButton>("save_as_default");
|
||||
mButtonApply->setClickedCallback(boost::bind(&FSPanelAreaSearchFilter::onButtonClickedSaveAsDefault, this));
|
||||
|
||||
mCheckboxDistance = getChild<LLCheckBoxCtrl>("filter_distance");
|
||||
mCheckboxExcludeAttachment->set(gSavedSettings.getBOOL("FSAreaSearch_FilterDistance"));
|
||||
mCheckboxDistance->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mSpinDistanceMinValue = getChild<LLSpinCtrl>("min_distance");
|
||||
mCheckboxDistance->set(gSavedSettings.getS32("FSAreaSearch_MinimumDistance"));
|
||||
mSpinDistanceMinValue->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitSpin, this));
|
||||
|
||||
mSpinDistanceMaxValue= getChild<LLSpinCtrl>("max_distance");
|
||||
mSpinDistanceMaxValue->set((F32)gSavedSettings.getS32("FSAreaSearch_MaximumDistance"));
|
||||
mSpinDistanceMaxValue->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitSpin, this));
|
||||
|
||||
mCheckboxMoaP = getChild<LLCheckBoxCtrl>("filter_moap");
|
||||
mCheckboxMoaP->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyMOAP"));
|
||||
mCheckboxMoaP->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxReflectionProbe = getChild<LLCheckBoxCtrl>("filter_reflection_probe");
|
||||
mCheckboxReflectionProbe->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyReflectionProbes"));
|
||||
mCheckboxReflectionProbe->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxPermCopy = getChild<LLCheckBoxCtrl>("filter_perm_copy");
|
||||
mCheckboxPermCopy->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyCopiable"));
|
||||
mCheckboxPermCopy->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxPermModify = getChild<LLCheckBoxCtrl>("filter_perm_modify");
|
||||
mCheckboxPermModify->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyModifiable"));
|
||||
mCheckboxPermModify->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxPermTransfer = getChild<LLCheckBoxCtrl>("filter_perm_transfer");
|
||||
mCheckboxPermModify->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyTransferable"));
|
||||
mCheckboxPermTransfer->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
mCheckboxAgentParcelOnly = getChild<LLCheckBoxCtrl>("filter_agent_parcel_only");
|
||||
mCheckboxAgentParcelOnly->set(gSavedSettings.getBOOL("FSAreaSearch_OnlyCurrentParcel"));
|
||||
mCheckboxAgentParcelOnly->setCommitCallback(boost::bind(&FSPanelAreaSearchFilter::onCommitCheckbox, this));
|
||||
|
||||
onCommitCheckbox();
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
|
|
@ -2278,8 +2262,6 @@ void FSPanelAreaSearchFilter::onCommitCheckbox()
|
|||
{
|
||||
mFSAreaSearch->setFilterLocked(mCheckboxLocked->get());
|
||||
mFSAreaSearch->setFilterPhantom(mCheckboxPhantom->get());
|
||||
mFSAreaSearch->setFilterForSale(mCheckboxForSale->get());
|
||||
mFSAreaSearch->setFilterDistance(mCheckboxDistance->get());
|
||||
mFSAreaSearch->setFilterMoaP(mCheckboxMoaP->get());
|
||||
mFSAreaSearch->setFilterReflectionProbe(mCheckboxReflectionProbe->get());
|
||||
|
||||
|
|
@ -2338,6 +2320,14 @@ void FSPanelAreaSearchFilter::onCommitCheckbox()
|
|||
}
|
||||
mFSAreaSearch->setFilterAttachment(mCheckboxAttachment->get());
|
||||
|
||||
mFSAreaSearch->setFilterForSale(mCheckboxForSale->get());
|
||||
mSpinForSaleMinValue->setEnabled(mCheckboxForSale->get());
|
||||
mSpinForSaleMaxValue->setEnabled(mCheckboxForSale->get());
|
||||
|
||||
mFSAreaSearch->setFilterDistance(mCheckboxDistance->get());
|
||||
mSpinDistanceMinValue->setEnabled(mCheckboxDistance->get());
|
||||
mSpinDistanceMaxValue->setEnabled(mCheckboxDistance->get());
|
||||
|
||||
mFSAreaSearch->setExcludeChildPrims(mCheckboxExcludeChildPrim->get());
|
||||
|
||||
mFSAreaSearch->setExcludeNeighborRegions(mCheckboxExcludeNeighborRegions->get());
|
||||
|
|
@ -2372,6 +2362,34 @@ void FSPanelAreaSearchFilter::onCommitCombo()
|
|||
}
|
||||
}
|
||||
|
||||
void FSPanelAreaSearchFilter::onButtonClickedSaveAsDefault()
|
||||
{
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyLocked", mCheckboxLocked->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyPhysical", mCheckboxPhysical->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyTemporary", mCheckboxTemporary->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyPhantom", mCheckboxPhantom->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_FilterForSale", mCheckboxForSale->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyAttachments", mCheckboxAttachment->get());
|
||||
gSavedSettings.setS32("FSAreaSearch_MinimumPrice", (S32)mSpinForSaleMinValue->get());
|
||||
gSavedSettings.setS32("FSAreaSearch_MaximumPrice", (S32)mSpinForSaleMaxValue->get());
|
||||
gSavedSettings.setS32("FSAreaSearch_ClickAction", mComboClickAction->getValue());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_ExcludeAttachments", mCheckboxExcludeAttachment->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_ExcludePhysical", mCheckboxExcludePhysics->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_ExcludeTemporary", mCheckboxExcludetemporary->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_ExcludeReflectionProbes", mCheckboxExcludeReflectionProbes->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_ExcludeChildPrims", mCheckboxExcludeChildPrim->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_ExcludeNeighborRegions", mCheckboxExcludeNeighborRegions->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_FilterDistance", mCheckboxExcludeAttachment->get());
|
||||
gSavedSettings.setS32("FSAreaSearch_MinimumDistance", mCheckboxDistance->get());
|
||||
gSavedSettings.setS32("FSAreaSearch_MaximumDistance", (S32)mSpinDistanceMaxValue->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyMOAP", mCheckboxMoaP->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyReflectionProbes", mCheckboxReflectionProbe->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyCopiable", mCheckboxPermCopy->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyModifiable", mCheckboxPermModify->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyTransferable", mCheckboxPermModify->get());
|
||||
gSavedSettings.setBOOL("FSAreaSearch_OnlyCurrentParcel", mCheckboxAgentParcelOnly->get());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Options tab
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class FSScrollListCtrl;
|
|||
struct FSObjectProperties
|
||||
{
|
||||
LLUUID id;
|
||||
bool listed;
|
||||
bool listed{ false };
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string touch_name;
|
||||
|
|
@ -67,9 +67,13 @@ struct FSObjectProperties
|
|||
LLUUID owner_id;
|
||||
LLUUID group_id;
|
||||
LLUUID ownership_id;
|
||||
bool group_owned;
|
||||
U64 creation_date;
|
||||
U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask;
|
||||
bool group_owned{ false };
|
||||
U64 creation_date{ 0 };
|
||||
U32 base_mask{ 0 };
|
||||
U32 owner_mask{ 0 };
|
||||
U32 group_mask{ 0 };
|
||||
U32 everyone_mask{ 0 };
|
||||
U32 next_owner_mask{ 0 };
|
||||
LLSaleInfo sale_info;
|
||||
LLCategory category;
|
||||
LLUUID last_owner_id;
|
||||
|
|
@ -78,9 +82,9 @@ struct FSObjectProperties
|
|||
LLAggregatePermissions ag_texture_perms_owner;
|
||||
LLPermissions permissions;
|
||||
uuid_vec_t texture_ids;
|
||||
bool name_requested;
|
||||
U32 local_id;
|
||||
U64 region_handle;
|
||||
bool name_requested{ false };
|
||||
U32 local_id{ 0 };
|
||||
U64 region_handle{ 0 };
|
||||
|
||||
typedef enum e_object_properties_request
|
||||
{
|
||||
|
|
@ -89,14 +93,7 @@ struct FSObjectProperties
|
|||
FINISHED,
|
||||
FAILED
|
||||
} EObjectPropertiesRequest;
|
||||
EObjectPropertiesRequest request;
|
||||
|
||||
FSObjectProperties() :
|
||||
request(NEED),
|
||||
listed(false),
|
||||
name_requested(false)
|
||||
{
|
||||
}
|
||||
EObjectPropertiesRequest request{ NEED };
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
|
@ -110,9 +107,9 @@ public:
|
|||
FSAreaSearch(const LLSD &);
|
||||
virtual ~FSAreaSearch();
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
virtual void draw();
|
||||
virtual void onOpen(const LLSD& key);
|
||||
bool postBuild() override;
|
||||
virtual void draw() override;
|
||||
virtual void onOpen(const LLSD& key) override;
|
||||
|
||||
void avatarNameCacheCallback(const LLUUID& id, const LLAvatarName& av_name);
|
||||
void callbackLoadFullName(const LLUUID& id, const std::string& full_name);
|
||||
|
|
@ -126,8 +123,8 @@ public:
|
|||
void clearSearchText();
|
||||
void onButtonClickedSearch();
|
||||
void onCommitCheckboxRegex();
|
||||
bool isSearchableObject (LLViewerObject* objectp, LLViewerRegion* our_region);
|
||||
void setFindOwnerText(std::string value);
|
||||
bool isSearchableObject(LLViewerObject* objectp, LLViewerRegion* our_region) const;
|
||||
void setFindOwnerText(const std::string& value);
|
||||
|
||||
std::map<LLUUID, FSObjectProperties> mObjectDetails;
|
||||
|
||||
|
|
@ -169,10 +166,10 @@ public:
|
|||
|
||||
void setFilterAgentParcelOnly(bool b) { mFilterAgentParcelOnly = b; }
|
||||
|
||||
bool isActive() { return mActive; }
|
||||
bool isActive() const { return mActive; }
|
||||
|
||||
private:
|
||||
void requestObjectProperties(const std::vector< U32 >& request_list, bool select, LLViewerRegion* regionp);
|
||||
void requestObjectProperties(const std::vector<U32>& request_list, bool select, LLViewerRegion* regionp);
|
||||
void matchObject(FSObjectProperties& details, LLViewerObject* objectp);
|
||||
void getNameFromUUID(const LLUUID& id, std::string& name, bool group, bool& name_requested);
|
||||
|
||||
|
|
@ -181,15 +178,15 @@ private:
|
|||
void findObjects();
|
||||
void processRequestQueue();
|
||||
|
||||
boost::signals2::connection mRlvBehaviorCallbackConnection;
|
||||
boost::signals2::connection mRlvBehaviorCallbackConnection{};
|
||||
void updateRlvRestrictions(ERlvBehaviour behavior);
|
||||
|
||||
S32 mRequested;
|
||||
bool mRefresh;
|
||||
S32 mSearchableObjects;
|
||||
bool mActive;
|
||||
bool mRequestQueuePause;
|
||||
bool mRequestNeedsSent;
|
||||
S32 mRequested{ 0 };
|
||||
bool mRefresh{ false };
|
||||
S32 mSearchableObjects{ 0 };
|
||||
bool mActive{ false };
|
||||
bool mRequestQueuePause{ false };
|
||||
bool mRequestNeedsSent{ false };
|
||||
std::map<U64,S32> mRegionRequests;
|
||||
|
||||
std::string mSearchName;
|
||||
|
|
@ -199,7 +196,7 @@ private:
|
|||
std::string mSearchCreator;
|
||||
std::string mSearchLastOwner;
|
||||
|
||||
bool mRegexSearch;
|
||||
bool mRegexSearch{ false };
|
||||
boost::regex mRegexSearchName;
|
||||
boost::regex mRegexSearchDescription;
|
||||
boost::regex mRegexSearchOwner;
|
||||
|
|
@ -210,57 +207,57 @@ private:
|
|||
LLFrameTimer mLastUpdateTimer;
|
||||
LLFrameTimer mLastPropertiesReceivedTimer;
|
||||
|
||||
uuid_vec_t mNamesRequested;
|
||||
uuid_set_t mNamesRequested;
|
||||
|
||||
typedef std::map<LLUUID, boost::signals2::connection> name_cache_connection_map_t;
|
||||
using name_cache_connection_map_t = std::map<LLUUID, boost::signals2::connection>;
|
||||
name_cache_connection_map_t mNameCacheConnections;
|
||||
|
||||
LLViewerRegion* mLastRegion;
|
||||
LLViewerRegion* mLastRegion{ nullptr };
|
||||
|
||||
class FSParcelChangeObserver;
|
||||
friend class FSParcelChangeObserver;
|
||||
std::unique_ptr<FSParcelChangeObserver> mParcelChangedObserver;
|
||||
|
||||
LLTabContainer* mTab;
|
||||
FSPanelAreaSearchList* mPanelList;
|
||||
FSPanelAreaSearchFind* mPanelFind;
|
||||
FSPanelAreaSearchFilter* mPanelFilter;
|
||||
FSPanelAreaSearchOptions* mPanelOptions;
|
||||
FSPanelAreaSearchAdvanced* mPanelAdvanced;
|
||||
LLTabContainer* mTab{ nullptr };
|
||||
FSPanelAreaSearchList* mPanelList{ nullptr };
|
||||
FSPanelAreaSearchFind* mPanelFind{ nullptr };
|
||||
FSPanelAreaSearchFilter* mPanelFilter{ nullptr };
|
||||
FSPanelAreaSearchOptions* mPanelOptions{ nullptr };
|
||||
FSPanelAreaSearchAdvanced* mPanelAdvanced{ nullptr };
|
||||
|
||||
bool mBeacons;
|
||||
bool mBeacons{ false };
|
||||
|
||||
bool mExcludeAttachment;
|
||||
bool mExcludeTemporary;
|
||||
bool mExcludeReflectionProbe;
|
||||
bool mExcludePhysics;
|
||||
bool mExcludeChildPrims;
|
||||
bool mExcludeNeighborRegions;
|
||||
bool mExcludeAttachment{ false };
|
||||
bool mExcludeTemporary{ false };
|
||||
bool mExcludeReflectionProbe{ false };
|
||||
bool mExcludePhysics{ false };
|
||||
bool mExcludeChildPrims{ true };
|
||||
bool mExcludeNeighborRegions{ true };
|
||||
|
||||
bool mFilterLocked;
|
||||
bool mFilterPhysical;
|
||||
bool mFilterTemporary;
|
||||
bool mFilterPhantom;
|
||||
bool mFilterAttachment;
|
||||
bool mFilterMoaP;
|
||||
bool mFilterReflectionProbe;
|
||||
bool mFilterLocked{ false };
|
||||
bool mFilterPhysical{ true };
|
||||
bool mFilterTemporary{ true };
|
||||
bool mFilterPhantom{ false };
|
||||
bool mFilterAttachment{ false };
|
||||
bool mFilterMoaP{ false };
|
||||
bool mFilterReflectionProbe{ false };
|
||||
|
||||
bool mFilterForSale;
|
||||
S32 mFilterForSaleMin;
|
||||
S32 mFilterForSaleMax;
|
||||
bool mFilterForSale{ false };
|
||||
S32 mFilterForSaleMin{ 0 };
|
||||
S32 mFilterForSaleMax{ 999999 };
|
||||
|
||||
bool mFilterDistance;
|
||||
S32 mFilterDistanceMin;
|
||||
S32 mFilterDistanceMax;
|
||||
bool mFilterDistance{ false };
|
||||
S32 mFilterDistanceMin{ 0 };
|
||||
S32 mFilterDistanceMax{ 0 };
|
||||
|
||||
bool mFilterClickAction;
|
||||
U8 mFilterClickActionType;
|
||||
bool mFilterClickAction{ false };
|
||||
U8 mFilterClickActionType{ 0 };
|
||||
|
||||
bool mFilterPermCopy;
|
||||
bool mFilterPermModify;
|
||||
bool mFilterPermTransfer;
|
||||
bool mFilterPermCopy{ false };
|
||||
bool mFilterPermModify{ false };
|
||||
bool mFilterPermTransfer{ false };
|
||||
|
||||
bool mFilterAgentParcelOnly;
|
||||
bool mFilterAgentParcelOnly{ false };
|
||||
|
||||
protected:
|
||||
static void* createPanelList(void* data);
|
||||
|
|
@ -286,7 +283,7 @@ public:
|
|||
FSPanelAreaSearchList(FSAreaSearch* pointer);
|
||||
virtual ~FSPanelAreaSearchList();
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
bool postBuild() override;
|
||||
|
||||
void setCounterText();
|
||||
void setCounterText(LLStringUtil::format_map_t args);
|
||||
|
|
@ -316,14 +313,14 @@ private:
|
|||
|
||||
LLVector3d mAgentLastPosition;
|
||||
|
||||
FSAreaSearch* mFSAreaSearch;
|
||||
LLButton* mRefreshButton;
|
||||
FSScrollListCtrl* mResultList;
|
||||
LLCheckBoxCtrl* mCheckboxBeacons;
|
||||
LLTextBox* mCounterText;
|
||||
FSAreaSearch* mFSAreaSearch{ nullptr };
|
||||
LLButton* mRefreshButton{ nullptr };
|
||||
FSScrollListCtrl* mResultList{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxBeacons{ nullptr };
|
||||
LLTextBox* mCounterText{ nullptr };
|
||||
|
||||
std::map<std::string, U32> mColumnBits;
|
||||
boost::signals2::connection mFSAreaSearchColumnConfigConnection;
|
||||
std::map<std::string, U32, std::less<>> mColumnBits;
|
||||
boost::signals2::connection mFSAreaSearchColumnConfigConnection{};
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -339,24 +336,24 @@ public:
|
|||
FSPanelAreaSearchFind(FSAreaSearch* pointer);
|
||||
virtual ~FSPanelAreaSearchFind() = default;
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
/*virtual*/ bool handleKeyHere(KEY key,MASK mask);
|
||||
bool postBuild() override;
|
||||
bool handleKeyHere(KEY key,MASK mask) override;
|
||||
|
||||
LLLineEditor* mNameLineEditor;
|
||||
LLLineEditor* mDescriptionLineEditor;
|
||||
LLLineEditor* mOwnerLineEditor;
|
||||
LLLineEditor* mGroupLineEditor;
|
||||
LLLineEditor* mCreatorLineEditor;
|
||||
LLLineEditor* mLastOwnerLineEditor;
|
||||
LLCheckBoxCtrl* mCheckboxRegex;
|
||||
LLLineEditor* mNameLineEditor{ nullptr };
|
||||
LLLineEditor* mDescriptionLineEditor{ nullptr };
|
||||
LLLineEditor* mOwnerLineEditor{ nullptr };
|
||||
LLLineEditor* mGroupLineEditor{ nullptr };
|
||||
LLLineEditor* mCreatorLineEditor{ nullptr };
|
||||
LLLineEditor* mLastOwnerLineEditor{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxRegex{ nullptr };
|
||||
|
||||
private:
|
||||
void onButtonClickedClear();
|
||||
|
||||
FSAreaSearch* mFSAreaSearch;
|
||||
FSAreaSearch* mFSAreaSearch{ nullptr };
|
||||
|
||||
LLButton* mSearchButton;
|
||||
LLButton* mClearButton;
|
||||
LLButton* mSearchButton{ nullptr };
|
||||
LLButton* mClearButton{ nullptr };
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -372,39 +369,40 @@ public:
|
|||
FSPanelAreaSearchFilter(FSAreaSearch* pointer);
|
||||
virtual ~FSPanelAreaSearchFilter() = default;
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
bool postBuild() override;
|
||||
|
||||
private:
|
||||
void onCommitCheckbox();
|
||||
void onCommitSpin();
|
||||
void onCommitCombo();
|
||||
void onButtonClickedSaveAsDefault();
|
||||
|
||||
FSAreaSearch* mFSAreaSearch;
|
||||
LLCheckBoxCtrl* mCheckboxForSale;
|
||||
LLCheckBoxCtrl* mCheckboxPhysical;
|
||||
LLCheckBoxCtrl* mCheckboxTemporary;
|
||||
LLCheckBoxCtrl* mCheckboxLocked;
|
||||
LLCheckBoxCtrl* mCheckboxPhantom;
|
||||
LLCheckBoxCtrl* mCheckboxMoaP;
|
||||
LLCheckBoxCtrl* mCheckboxReflectionProbe;
|
||||
LLCheckBoxCtrl* mCheckboxDistance;
|
||||
LLSpinCtrl* mSpinDistanceMinValue;
|
||||
LLSpinCtrl* mSpinDistanceMaxValue;
|
||||
LLSpinCtrl* mSpinForSaleMinValue;
|
||||
LLSpinCtrl* mSpinForSaleMaxValue;
|
||||
LLButton* mButtonApply;
|
||||
LLComboBox* mComboClickAction;
|
||||
LLCheckBoxCtrl* mCheckboxAttachment;
|
||||
LLCheckBoxCtrl* mCheckboxExcludeAttachment;
|
||||
LLCheckBoxCtrl* mCheckboxExcludePhysics;
|
||||
LLCheckBoxCtrl* mCheckboxExcludetemporary;
|
||||
LLCheckBoxCtrl* mCheckboxExcludeReflectionProbes;
|
||||
LLCheckBoxCtrl* mCheckboxExcludeChildPrim;
|
||||
LLCheckBoxCtrl* mCheckboxExcludeNeighborRegions;
|
||||
LLCheckBoxCtrl* mCheckboxPermCopy;
|
||||
LLCheckBoxCtrl* mCheckboxPermModify;
|
||||
LLCheckBoxCtrl* mCheckboxPermTransfer;
|
||||
LLCheckBoxCtrl* mCheckboxAgentParcelOnly;
|
||||
FSAreaSearch* mFSAreaSearch{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxForSale{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxPhysical{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxTemporary{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxLocked{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxPhantom{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxMoaP{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxReflectionProbe{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxDistance{ nullptr };
|
||||
LLSpinCtrl* mSpinDistanceMinValue{ nullptr };
|
||||
LLSpinCtrl* mSpinDistanceMaxValue{ nullptr };
|
||||
LLSpinCtrl* mSpinForSaleMinValue{ nullptr };
|
||||
LLSpinCtrl* mSpinForSaleMaxValue{ nullptr };
|
||||
LLButton* mButtonApply{ nullptr };
|
||||
LLComboBox* mComboClickAction{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxAttachment{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxExcludeAttachment{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxExcludePhysics{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxExcludetemporary{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxExcludeReflectionProbes{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxExcludeChildPrim{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxExcludeNeighborRegions{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxPermCopy{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxPermModify{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxPermTransfer{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxAgentParcelOnly{ nullptr };
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -423,9 +421,9 @@ private:
|
|||
void onCommitCheckboxDisplayColumn(const LLSD& userdata);
|
||||
bool onEnableColumnVisibilityChecked(const LLSD& userdata);
|
||||
|
||||
FSAreaSearch* mFSAreaSearch;
|
||||
FSAreaSearch* mFSAreaSearch{ nullptr };
|
||||
|
||||
std::map<std::string, LLScrollListColumn::Params> mColumnParms;
|
||||
std::map<std::string, LLScrollListColumn::Params, std::less<>> mColumnParms;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -440,11 +438,11 @@ public:
|
|||
FSPanelAreaSearchAdvanced() = default;
|
||||
virtual ~FSPanelAreaSearchAdvanced() = default;
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
bool postBuild() override;
|
||||
|
||||
LLCheckBoxCtrl* mCheckboxClickTouch;
|
||||
LLCheckBoxCtrl* mCheckboxClickBuy;
|
||||
LLCheckBoxCtrl* mCheckboxClickSit;
|
||||
LLCheckBoxCtrl* mCheckboxClickTouch{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxClickBuy{ nullptr };
|
||||
LLCheckBoxCtrl* mCheckboxClickSit{ nullptr };
|
||||
};
|
||||
|
||||
#endif // FS_AREASEARCH_H
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730");
|
||||
|
||||
LLAssetType::EType S32toAssetType(S32 assetindex)
|
||||
static LLAssetType::EType S32toAssetType(S32 assetindex)
|
||||
{
|
||||
LLAssetType::EType type;
|
||||
switch (assetindex)
|
||||
|
|
@ -66,39 +66,9 @@ LLAssetType::EType S32toAssetType(S32 assetindex)
|
|||
return type;
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::init()
|
||||
LLSD FSAssetBlacklistData::toLLSD() const
|
||||
{
|
||||
mBlacklistFileName = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "asset_blacklist.xml");
|
||||
loadBlacklist();
|
||||
}
|
||||
|
||||
bool FSAssetBlacklist::isBlacklisted(const LLUUID& id, LLAssetType::EType type)
|
||||
{
|
||||
if (mBlacklistData.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
blacklist_type_map_t::iterator it = mBlacklistTypeContainer.find(type);
|
||||
|
||||
if (it == mBlacklistTypeContainer.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
blacklisted_uuid_container_t uuids = it->second;
|
||||
return (uuids.find(id) != uuids.end());
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::addNewItemToBlacklist(const LLUUID& id, const std::string& name, const std::string& region, LLAssetType::EType type, bool permanent /*= true*/, bool save /*= true*/)
|
||||
{
|
||||
if (isBlacklisted(id, type))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLDate curdate = LLDate((double)time_corrected());
|
||||
std::string input_date = curdate.asString();
|
||||
std::string input_date = date.asString();
|
||||
input_date.replace(input_date.find("T"), 1, " ");
|
||||
input_date.resize(input_date.size() - 1);
|
||||
|
||||
|
|
@ -106,10 +76,94 @@ void FSAssetBlacklist::addNewItemToBlacklist(const LLUUID& id, const std::string
|
|||
data["asset_name"] = name;
|
||||
data["asset_region"] = region;
|
||||
data["asset_type"] = type;
|
||||
data["asset_blacklist_flag"] = flags;
|
||||
data["asset_date"] = input_date;
|
||||
data["asset_permanent"] = permanent;
|
||||
|
||||
addNewItemToBlacklistData(id, data, save);
|
||||
return data;
|
||||
}
|
||||
|
||||
FSAssetBlacklistData FSAssetBlacklistData::fromLLSD(const LLSD& data)
|
||||
{
|
||||
FSAssetBlacklistData blacklistdata;
|
||||
|
||||
std::string asset_date = data["asset_date"].asString() + "Z";
|
||||
asset_date.replace(asset_date.find(" "), 1, "T");
|
||||
|
||||
blacklistdata.name = data["asset_name"].asString();
|
||||
blacklistdata.region = data["asset_region"].asString();
|
||||
blacklistdata.type = S32toAssetType(data["asset_type"].asInteger());
|
||||
blacklistdata.flags = data.has("asset_blacklist_flag") ? data["asset_blacklist_flag"].asInteger() : 0;
|
||||
blacklistdata.date = LLDate(asset_date);
|
||||
blacklistdata.permanent = data["asset_permanent"].asBoolean();
|
||||
|
||||
return blacklistdata;
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::init()
|
||||
{
|
||||
mBlacklistFileName = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "asset_blacklist.xml");
|
||||
loadBlacklist();
|
||||
}
|
||||
|
||||
bool FSAssetBlacklist::isBlacklisted(const LLUUID& id, LLAssetType::EType type, eBlacklistFlag flag) const
|
||||
{
|
||||
if (mBlacklistData.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mBlacklistTypeContainer.contains(type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mBlacklistTypeContainer.at(type).contains(id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& data_it = mBlacklistData.find(id);
|
||||
if (data_it == mBlacklistData.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (data_it->second.flags == eBlacklistFlag::NONE && flag == eBlacklistFlag::NONE) || (data_it->second.flags & flag) != 0;
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::addNewItemToBlacklist(const LLUUID& id, const std::string& name, const std::string& region, LLAssetType::EType type, eBlacklistFlag flag /*= eBlacklistFlag::NONE*/, bool permanent /*= true*/, bool save /*= true*/)
|
||||
{
|
||||
LLDate curdate = LLDate((double)time_corrected());
|
||||
std::string input_date = curdate.asString();
|
||||
input_date.replace(input_date.find("T"), 1, " ");
|
||||
input_date.resize(input_date.size() - 1);
|
||||
|
||||
FSAssetBlacklistData data;
|
||||
|
||||
if (auto it = mBlacklistData.find(id); it != mBlacklistData.end())
|
||||
{
|
||||
data = it->second;
|
||||
|
||||
data.name = name;
|
||||
data.region = region;
|
||||
data.date = LLDate((double)time_corrected());
|
||||
data.permanent = permanent;
|
||||
data.flags |= flag;
|
||||
|
||||
addNewItemToBlacklistData(id, data, save);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.name = name;
|
||||
data.region = region;
|
||||
data.date = LLDate((double)time_corrected());
|
||||
data.permanent = permanent;
|
||||
data.flags = flag;
|
||||
data.type = type;
|
||||
|
||||
addNewItemToBlacklistData(id, data, save);
|
||||
}
|
||||
}
|
||||
|
||||
bool FSAssetBlacklist::removeItem(const LLUUID& id)
|
||||
|
|
@ -122,14 +176,17 @@ bool FSAssetBlacklist::removeItem(const LLUUID& id)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Erase for each possible type
|
||||
for (auto& [type, container] : mBlacklistTypeContainer)
|
||||
{
|
||||
container.erase(id);
|
||||
}
|
||||
|
||||
LLSD data = it->second;
|
||||
LLAssetType::EType type = S32toAssetType(data["asset_type"].asInteger());
|
||||
|
||||
mBlacklistTypeContainer[type].erase(id);
|
||||
auto data = it->second;
|
||||
mBlacklistData.erase(it);
|
||||
|
||||
return data["asset_permanent"].asBoolean();
|
||||
return data.permanent;
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::removeItemFromBlacklist(const LLUUID& id)
|
||||
|
|
@ -142,7 +199,8 @@ void FSAssetBlacklist::removeItemsFromBlacklist(const uuid_vec_t& ids)
|
|||
if (!ids.empty())
|
||||
{
|
||||
bool need_save = false;
|
||||
LLSD data;
|
||||
|
||||
changed_signal_data_t data;
|
||||
|
||||
for (const auto& id : ids)
|
||||
{
|
||||
|
|
@ -150,7 +208,7 @@ void FSAssetBlacklist::removeItemsFromBlacklist(const uuid_vec_t& ids)
|
|||
{
|
||||
need_save = true;
|
||||
}
|
||||
data.append(id.asString());
|
||||
data.emplace_back(id, std::nullopt);
|
||||
}
|
||||
|
||||
if (need_save)
|
||||
|
|
@ -165,14 +223,43 @@ void FSAssetBlacklist::removeItemsFromBlacklist(const uuid_vec_t& ids)
|
|||
}
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::addNewItemToBlacklistData(const LLUUID& id, const LLSD& data, bool save)
|
||||
void FSAssetBlacklist::removeFlagsFromItem(const LLUUID& id, S32 combined_flags)
|
||||
{
|
||||
LLAssetType::EType type = S32toAssetType(data["asset_type"].asInteger());
|
||||
auto it = mBlacklistData.find(id);
|
||||
if (it == mBlacklistData.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
addEntryToBlacklistMap(id, type);
|
||||
mBlacklistData[id] = data;
|
||||
auto& data = it->second;
|
||||
S32 current_flags = data.flags;
|
||||
|
||||
if (type == LLAssetType::AT_SOUND)
|
||||
current_flags &= ~combined_flags;
|
||||
|
||||
if (current_flags == eBlacklistFlag::NONE)
|
||||
{
|
||||
removeItemsFromBlacklist({ id });
|
||||
}
|
||||
else
|
||||
{
|
||||
data.flags = current_flags;
|
||||
addNewItemToBlacklistData(id, data, true);
|
||||
}
|
||||
}
|
||||
|
||||
void FSAssetBlacklist::addNewItemToBlacklistData(const LLUUID& id, const FSAssetBlacklistData& data, bool save)
|
||||
{
|
||||
if (auto it = mBlacklistData.find(id); it != mBlacklistData.end())
|
||||
{
|
||||
it->second = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
addEntryToBlacklistMap(id, data.type);
|
||||
mBlacklistData.try_emplace(id, data);
|
||||
}
|
||||
|
||||
if (data.type == LLAssetType::AT_SOUND && data.flags == eBlacklistFlag::NONE)
|
||||
{
|
||||
LLFileSystem::removeFile(id, LLAssetType::AT_SOUND);
|
||||
std::string wav_path = gDirUtilp->getExpandedFilename(LL_PATH_FS_SOUND_CACHE, id.asString()) + ".dsf";
|
||||
|
|
@ -193,7 +280,7 @@ void FSAssetBlacklist::addNewItemToBlacklistData(const LLUUID& id, const LLSD& d
|
|||
|
||||
if (!mBlacklistChangedCallback.empty())
|
||||
{
|
||||
mBlacklistChangedCallback(LLSD().with(id.asString(), data), eBlacklistOperation::BLACKLIST_ADD);
|
||||
mBlacklistChangedCallback({ {id, data} }, eBlacklistOperation::BLACKLIST_ADD);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +334,7 @@ void FSAssetBlacklist::loadBlacklist()
|
|||
gObjectList.addDerenderedItem(uid, true);
|
||||
}
|
||||
|
||||
addNewItemToBlacklistData(uid, entry_data, false);
|
||||
addNewItemToBlacklistData(uid, FSAssetBlacklistData::fromLLSD(entry_data), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +372,7 @@ void FSAssetBlacklist::loadBlacklist()
|
|||
newdata["asset_date"] = data["entry_date"].asString();
|
||||
newdata["asset_permanent"] = true; // For conversion of old data
|
||||
|
||||
addNewItemToBlacklistData(uid, newdata, false);
|
||||
addNewItemToBlacklistData(uid, FSAssetBlacklistData::fromLLSD(newdata), false);
|
||||
}
|
||||
}
|
||||
oldfile.close();
|
||||
|
|
@ -306,12 +393,12 @@ void FSAssetBlacklist::saveBlacklist()
|
|||
|
||||
for (const auto& [id, data] : mBlacklistData)
|
||||
{
|
||||
if (data["asset_permanent"].asBoolean())
|
||||
if (data.permanent)
|
||||
{
|
||||
LLUUID shadow_id{ id };
|
||||
LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
|
||||
cipher.encrypt(shadow_id.mData, UUID_BYTES);
|
||||
savedata[shadow_id.asString()] = data;
|
||||
savedata[shadow_id.asString()] = data.toLLSD();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,21 +35,45 @@
|
|||
#include "llsingleton.h"
|
||||
#include "llassettype.h"
|
||||
|
||||
using blacklisted_uuid_container_t = std::unordered_set<LLUUID, FSUUIDHash>;
|
||||
struct FSAssetBlacklistData
|
||||
{
|
||||
std::string name;
|
||||
std::string region;
|
||||
LLAssetType::EType type;
|
||||
S32 flags{ 0 };
|
||||
LLDate date;
|
||||
bool permanent{ false };
|
||||
|
||||
LLSD toLLSD() const;
|
||||
static FSAssetBlacklistData fromLLSD(const LLSD& data);
|
||||
};
|
||||
|
||||
using blacklisted_uuid_container_t = std::unordered_set<LLUUID>;
|
||||
using blacklist_type_map_t = std::map<LLAssetType::EType, blacklisted_uuid_container_t>;
|
||||
using blacklist_data_t = std::unordered_map<LLUUID, LLSD, FSUUIDHash>;
|
||||
using blacklist_data_t = std::unordered_map<LLUUID, FSAssetBlacklistData>;
|
||||
|
||||
class FSAssetBlacklist : public LLSingleton<FSAssetBlacklist>
|
||||
{
|
||||
LLSINGLETON_EMPTY_CTOR(FSAssetBlacklist);
|
||||
|
||||
public:
|
||||
enum eBlacklistFlag
|
||||
{
|
||||
NONE = 0,
|
||||
WORN = 1 << 0,
|
||||
REZZED = 1 << 1,
|
||||
GESTURE = 1 << 2,
|
||||
|
||||
LAST_FLAG = 1 << 2
|
||||
};
|
||||
|
||||
void init();
|
||||
bool isBlacklisted(const LLUUID& id, LLAssetType::EType type);
|
||||
void addNewItemToBlacklist(const LLUUID& id, const std::string& name, const std::string& region, LLAssetType::EType type, bool permanent = true, bool save = true);
|
||||
void addNewItemToBlacklistData(const LLUUID& id, const LLSD& data, bool save = true);
|
||||
bool isBlacklisted(const LLUUID& id, LLAssetType::EType type, eBlacklistFlag flag = eBlacklistFlag::NONE) const;
|
||||
void addNewItemToBlacklist(const LLUUID& id, const std::string& name, const std::string& region, LLAssetType::EType type, eBlacklistFlag flag = eBlacklistFlag::NONE,bool permanent = true, bool save = true);
|
||||
void addNewItemToBlacklistData(const LLUUID& id, const FSAssetBlacklistData& data, bool save = true);
|
||||
void removeItemFromBlacklist(const LLUUID& id);
|
||||
void removeItemsFromBlacklist(const uuid_vec_t& ids);
|
||||
void removeFlagsFromItem(const LLUUID& id, S32 combined_flags);
|
||||
void saveBlacklist();
|
||||
|
||||
blacklist_data_t getBlacklistData() const { return mBlacklistData; };
|
||||
|
|
@ -60,7 +84,8 @@ public:
|
|||
BLACKLIST_REMOVE
|
||||
};
|
||||
|
||||
typedef boost::signals2::signal<void(const LLSD& data, eBlacklistOperation op)> blacklist_changed_callback_t;
|
||||
using changed_signal_data_t = std::vector<std::pair<LLUUID, std::optional<FSAssetBlacklistData>>>;
|
||||
using blacklist_changed_callback_t = boost::signals2::signal<void(const changed_signal_data_t& data, eBlacklistOperation op)>;
|
||||
boost::signals2::connection setBlacklistChangedCallback(const blacklist_changed_callback_t::slot_type& cb)
|
||||
{
|
||||
return mBlacklistChangedCallback.connect(cb);
|
||||
|
|
|
|||
|
|
@ -92,10 +92,10 @@ bool FSCommon::is_irc_me_prefix(std::string_view text)
|
|||
std::string FSCommon::unescape_name(std::string_view name)
|
||||
{
|
||||
// bugfix for SL-46920: preventing filenames that break stuff.
|
||||
char * curl_str = curl_unescape(name.data(), static_cast<int>(name.size())); // Calling data() should be ok here because we also pass the length
|
||||
char* curl_str = curl_unescape(name.data(), static_cast<int>(name.size())); // Calling data() should be ok here because we also pass the length
|
||||
std::string unescaped_name(curl_str);
|
||||
curl_free(curl_str);
|
||||
curl_str = NULL;
|
||||
curl_str = nullptr;
|
||||
|
||||
return unescaped_name;
|
||||
}
|
||||
|
|
@ -218,11 +218,9 @@ void FSCommon::applyDefaultBuildPreferences(LLViewerObject* object)
|
|||
|
||||
if (gSavedPerAccountSettings.getBOOL("FSBuildPrefs_EmbedItem"))
|
||||
{
|
||||
LLUUID item_id(gSavedPerAccountSettings.getString("FSBuildPrefs_Item"));
|
||||
if (item_id.notNull())
|
||||
if (LLUUID item_id(gSavedPerAccountSettings.getString("FSBuildPrefs_Item")); item_id.notNull())
|
||||
{
|
||||
LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(gInventory.getObject(item_id));
|
||||
if (item)
|
||||
if (LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(gInventory.getObject(item_id)))
|
||||
{
|
||||
if (item->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
{
|
||||
|
|
@ -297,22 +295,19 @@ bool FSCommon::isLinden(const LLUUID& av_id)
|
|||
{
|
||||
gCacheName->getFirstLastName(av_id, first_name, last_name);
|
||||
}
|
||||
|
||||
#ifdef OPENSIM
|
||||
if (LLGridManager::getInstance()->isInOpenSim())
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region) return false;
|
||||
bool is_god = false;
|
||||
// <FS:CR> They may not be "Lindens" per se, but opensim has gods.
|
||||
std::set<std::string> gods = region->getGods();
|
||||
if (!gods.empty())
|
||||
{
|
||||
is_god = (gods.find(first_name + " " + last_name) != gods.end()
|
||||
|| gods.find(last_name) != gods.end());
|
||||
}
|
||||
return is_god;
|
||||
if (!region)
|
||||
return false;
|
||||
|
||||
const auto& gods = region->getGods();
|
||||
return gods.contains(first_name + " " + last_name) || gods.contains(last_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (last_name == LL_LINDEN ||
|
||||
last_name == LL_MOLE ||
|
||||
last_name == LL_PRODUCTENGINE ||
|
||||
|
|
@ -333,105 +328,79 @@ bool FSCommon::requestGroupData(const LLUUID& groupID)
|
|||
|
||||
bool FSCommon::checkIsActionEnabled(const LLUUID& av_id, EFSRegistrarFunctionActionType action)
|
||||
{
|
||||
bool isSelf = (av_id == gAgentID);
|
||||
const bool isSelf = (av_id == gAgentID);
|
||||
|
||||
if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_ADD_FRIEND)
|
||||
switch (action)
|
||||
{
|
||||
return (!isSelf && !LLAvatarActions::isFriend(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_REMOVE_FRIEND)
|
||||
{
|
||||
return (!isSelf && LLAvatarActions::isFriend(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_SEND_IM)
|
||||
{
|
||||
return (!isSelf && RlvActions::canStartIM(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_VIEW_TRANSCRIPT)
|
||||
{
|
||||
return (!isSelf && LLLogChat::isTranscriptExist(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_ZOOM_IN)
|
||||
{
|
||||
return (!isSelf && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && LLAvatarActions::canZoomIn(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_OFFER_TELEPORT)
|
||||
{
|
||||
return (!isSelf && LLAvatarActions::canOfferTeleport(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_REQUEST_TELEPORT)
|
||||
{
|
||||
return (!isSelf && LLAvatarActions::canRequestTeleport(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_SHOW_PROFILE)
|
||||
{
|
||||
return (isSelf || !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_TRACK_AVATAR)
|
||||
{
|
||||
return (!isSelf && FSRadar::getInstance()->getEntry(av_id) != NULL);
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_ACT_TELEPORT_TO)
|
||||
{
|
||||
return (!isSelf && FSRadar::getInstance()->getEntry(av_id) != NULL);
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_AVATAR_BLOCKED)
|
||||
{
|
||||
return (!isSelf && LLMuteList::getInstance()->isMuted(av_id));
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_IS_SELF)
|
||||
{
|
||||
return isSelf;
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_IS_NOT_SELF)
|
||||
{
|
||||
return !isSelf;
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_WAITING_FOR_GROUP_DATA)
|
||||
{
|
||||
return !requestGroupData(av_id);
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_HAVE_GROUP_DATA)
|
||||
{
|
||||
return requestGroupData(av_id);
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_CAN_LEAVE_GROUP)
|
||||
{
|
||||
if (gAgent.getGroupID() == av_id && !RlvActions::canChangeActiveGroup())
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_ADD_FRIEND:
|
||||
return (!isSelf && !LLAvatarActions::isFriend(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_REMOVE_FRIEND:
|
||||
return (!isSelf && LLAvatarActions::isFriend(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_SEND_IM:
|
||||
return (!isSelf && RlvActions::canStartIM(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_VIEW_TRANSCRIPT:
|
||||
return (!isSelf && LLLogChat::isTranscriptExist(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_ZOOM_IN:
|
||||
return (!isSelf && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && LLAvatarActions::canZoomIn(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_OFFER_TELEPORT:
|
||||
return (!isSelf && LLAvatarActions::canOfferTeleport(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_REQUEST_TELEPORT:
|
||||
return (!isSelf && LLAvatarActions::canRequestTeleport(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_SHOW_PROFILE:
|
||||
return (isSelf || !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_TRACK_AVATAR:
|
||||
return (!isSelf && FSRadar::getInstance()->getEntry(av_id) != nullptr);
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_ACT_TELEPORT_TO:
|
||||
return (!isSelf && FSRadar::getInstance()->getEntry(av_id) != nullptr);
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_AVATAR_BLOCKED:
|
||||
return (!isSelf && LLMuteList::getInstance()->isMuted(av_id));
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_IS_SELF:
|
||||
return isSelf;
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_IS_NOT_SELF:
|
||||
return !isSelf;
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_WAITING_FOR_GROUP_DATA:
|
||||
return !requestGroupData(av_id);
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_HAVE_GROUP_DATA:
|
||||
return requestGroupData(av_id);
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_CAN_LEAVE_GROUP:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (gAgent.getGroupID() == av_id && !RlvActions::canChangeActiveGroup())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return gAgent.isInGroup(av_id);
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_CAN_JOIN_GROUP)
|
||||
{
|
||||
if (!gAgent.canJoinGroups())
|
||||
return gAgent.isInGroup(av_id);
|
||||
}
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_CAN_JOIN_GROUP:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!gAgent.canJoinGroups())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RlvActions::canChangeActiveGroup())
|
||||
if (!RlvActions::canChangeActiveGroup())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLGroupMgrGroupData* groupData = LLGroupMgr::getInstance()->getGroupData(av_id);
|
||||
if (!groupData || !groupData->mOpenEnrollment)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !gAgent.isInGroup(av_id);
|
||||
}
|
||||
case EFSRegistrarFunctionActionType::FS_RGSTR_CHK_GROUP_NOT_ACTIVE:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!RlvActions::canChangeActiveGroup())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLGroupMgrGroupData* groupData = LLGroupMgr::getInstance()->getGroupData(av_id);
|
||||
if (!groupData || !groupData->mOpenEnrollment)
|
||||
{
|
||||
return false;
|
||||
return (gAgent.isInGroup(av_id) && gAgent.getGroupID() != av_id);
|
||||
}
|
||||
|
||||
return !gAgent.isInGroup(av_id);
|
||||
}
|
||||
else if (action == EFSRegistrarFunctionActionType::FS_RGSTR_CHK_GROUP_NOT_ACTIVE)
|
||||
{
|
||||
if (!RlvActions::canChangeActiveGroup())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (gAgent.isInGroup(av_id) && gAgent.getGroupID() != av_id);
|
||||
default:;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -453,7 +422,7 @@ std::string FSCommon::getAvatarNameByDisplaySettings(const LLAvatarName& av_name
|
|||
std::string name;
|
||||
static LLCachedControl<bool> NameTagShowUsernames(gSavedSettings, "NameTagShowUsernames");
|
||||
static LLCachedControl<bool> UseDisplayNames(gSavedSettings, "UseDisplayNames");
|
||||
if ((NameTagShowUsernames) && (UseDisplayNames))
|
||||
if (NameTagShowUsernames && UseDisplayNames)
|
||||
{
|
||||
name = av_name.getCompleteName();
|
||||
}
|
||||
|
|
@ -494,21 +463,21 @@ bool FSCommon::isDefaultTexture(const LLUUID& asset_id)
|
|||
|
||||
bool FSCommon::isLegacySkin()
|
||||
{
|
||||
std::string current_skin = gSavedSettings.getString("FSInternalSkinCurrent");
|
||||
return (current_skin == "Vintage");
|
||||
static bool is_legacy_skin = gSavedSettings.getString("FSInternalSkinCurrent") == "Vintage";
|
||||
return is_legacy_skin;
|
||||
}
|
||||
|
||||
bool FSCommon::isFilterEditorKeyCombo(KEY key, MASK mask)
|
||||
{
|
||||
return (mask == MASK_CONTROL && key == 'F' && gSavedSettings.getBOOL("FSSelectLocalSearchEditorOnShortcut"));
|
||||
static LLCachedControl<bool> select_search_on_shortcut(gSavedSettings, "FSSelectLocalSearchEditorOnShortcut");
|
||||
return (mask == MASK_CONTROL && key == 'F' && select_search_on_shortcut);
|
||||
}
|
||||
|
||||
LLUUID FSCommon::getGroupForRezzing()
|
||||
{
|
||||
LLUUID group_id{ gAgent.getGroupID() };
|
||||
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
||||
|
||||
if (parcel && gSavedSettings.getBOOL("RezUnderLandGroup"))
|
||||
if (LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); parcel && gSavedSettings.getBOOL("RezUnderLandGroup"))
|
||||
{
|
||||
// In both cases, group-owned or not, the group ID is the same;
|
||||
// No need to query the parcel owner ID as it will be either
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ void FSData::processAssets(const LLSD& assets)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
FSAssetBlacklist::instance().addNewItemToBlacklistData(uid, data, false);
|
||||
FSAssetBlacklist::instance().addNewItemToBlacklistData(uid, FSAssetBlacklistData::fromLLSD(data), false);
|
||||
LL_DEBUGS("fsdata") << "Added " << uid << " to assets list." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
@ -881,23 +881,27 @@ void FSData::addAgents()
|
|||
return;
|
||||
}
|
||||
|
||||
for (std::map<LLUUID, S32>::iterator iter = mTeamAgents.begin(); iter != mTeamAgents.end(); ++iter)
|
||||
for (const auto& [id, flags] : mTeamAgents)
|
||||
{
|
||||
if (iter->second & NO_SPAM)
|
||||
if (flags & NO_SPAM)
|
||||
{
|
||||
LLUUID id = iter->first;
|
||||
avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id);
|
||||
if (it != mAvatarNameCacheConnections.end())
|
||||
if (LLAvatarName av_name; LLAvatarNameCache::get(id, &av_name))
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
onNameCache(id, av_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto it = mAvatarNameCacheConnections.find(id); it != mAvatarNameCacheConnections.end())
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
}
|
||||
|
||||
LLAvatarNameCache::callback_connection_t cb = LLAvatarNameCache::get(id, boost::bind(&FSData::onNameCache, this, _1, _2));
|
||||
mAvatarNameCacheConnections.insert(std::make_pair(id, cb));
|
||||
mAvatarNameCacheConnections.try_emplace(id, LLAvatarNameCache::get(id, boost::bind(&FSData::onNameCache, this, _1, _2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,25 +90,51 @@ void FSFloaterAssetBlacklist::onOpen(const LLSD& key)
|
|||
buildBlacklist();
|
||||
}
|
||||
|
||||
std::string FSFloaterAssetBlacklist::getTypeString(S32 type)
|
||||
FSAssetBlacklist::eBlacklistFlag FSFloaterAssetBlacklist::getFlagFromLLSD(const LLSD& data)
|
||||
{
|
||||
if (data.has("asset_blacklist_flag"))
|
||||
{
|
||||
return static_cast<FSAssetBlacklist::eBlacklistFlag>(data["asset_blacklist_flag"].asInteger());
|
||||
}
|
||||
return FSAssetBlacklist::eBlacklistFlag::NONE;
|
||||
}
|
||||
|
||||
std::string FSFloaterAssetBlacklist::getTypeString(S32 type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LLAssetType::AT_TEXTURE:
|
||||
return getString("asset_texture");
|
||||
case LLAssetType::AT_SOUND:
|
||||
return getString("asset_sound");
|
||||
case LLAssetType::AT_OBJECT:
|
||||
return getString("asset_object");
|
||||
case LLAssetType::AT_ANIMATION:
|
||||
return getString("asset_animation");
|
||||
case LLAssetType::AT_PERSON:
|
||||
return getString("asset_resident");
|
||||
case LLAssetType::AT_SOUND:
|
||||
return getString("asset_sound");
|
||||
default:
|
||||
return getString("asset_unknown");
|
||||
}
|
||||
}
|
||||
|
||||
std::string FSFloaterAssetBlacklist::getFlagString(FSAssetBlacklist::eBlacklistFlag flag) const
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case FSAssetBlacklist::eBlacklistFlag::NONE:
|
||||
return getString("blacklist_flag_none");
|
||||
case FSAssetBlacklist::eBlacklistFlag::WORN:
|
||||
return getString("blacklist_flag_mute_avatar_worn_objects_sounds");
|
||||
case FSAssetBlacklist::eBlacklistFlag::REZZED:
|
||||
return getString("blacklist_flag_mute_avatar_rezzed_objects_sounds");
|
||||
case FSAssetBlacklist::eBlacklistFlag::GESTURE:
|
||||
return getString("blacklist_flag_mute_avatar_gestures_sounds");
|
||||
default:
|
||||
return getString("blacklist_flag_unknown");
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterAssetBlacklist::buildBlacklist()
|
||||
{
|
||||
bool needs_sort = mResultList->isSorted();
|
||||
|
|
@ -123,70 +149,112 @@ void FSFloaterAssetBlacklist::buildBlacklist()
|
|||
mResultList->updateSort();
|
||||
}
|
||||
|
||||
void FSFloaterAssetBlacklist::addElementToList(const LLUUID& id, const LLSD& data)
|
||||
void FSFloaterAssetBlacklist::addElementToList(const LLUUID& id, const FSAssetBlacklistData& data)
|
||||
{
|
||||
// Undo the persisted date in legacy format...
|
||||
std::string asset_date = data["asset_date"].asString() + "Z";
|
||||
asset_date.replace(asset_date.find(" "), 1, "T");
|
||||
LLDate date(asset_date);
|
||||
|
||||
std::string date_str = getString("DateFormatString");
|
||||
LLSD substitution;
|
||||
substitution["datetime"] = date.secondsSinceEpoch();
|
||||
substitution["datetime"] = data.date.secondsSinceEpoch();
|
||||
LLStringUtil::format(date_str, substitution);
|
||||
|
||||
LLSD element;
|
||||
element["id"] = id;
|
||||
element["columns"][0]["column"] = "name";
|
||||
element["columns"][0]["type"] = "text";
|
||||
element["columns"][0]["value"] = !data["asset_name"].asString().empty() ? data["asset_name"].asString() : getString("unknown_object");
|
||||
element["columns"][1]["column"] = "region";
|
||||
element["columns"][1]["type"] = "text";
|
||||
element["columns"][1]["value"] = !data["asset_region"].asString().empty() ? data["asset_region"].asString() : getString("unknown_region");
|
||||
element["columns"][2]["column"] = "type";
|
||||
element["columns"][2]["type"] = "text";
|
||||
element["columns"][2]["value"] = getTypeString(data["asset_type"].asInteger());
|
||||
element["columns"][3]["column"] = "date";
|
||||
element["columns"][3]["type"] = "text";
|
||||
element["columns"][3]["value"] = date_str;
|
||||
element["columns"][4]["column"] = "permanent";
|
||||
element["columns"][4]["type"] = "text";
|
||||
element["columns"][4]["halign"] = "center";
|
||||
element["columns"][4]["value"] = data["asset_permanent"].asBoolean() ? getString("asset_permanent") : LLStringUtil::null;
|
||||
element["columns"][5]["column"] = "date_sort";
|
||||
element["columns"][5]["type"] = "text";
|
||||
element["columns"][5]["value"] = llformat("%u", (U64)date.secondsSinceEpoch());
|
||||
element["columns"][6]["column"] = "asset_type";
|
||||
element["columns"][6]["type"] = "integer";
|
||||
element["columns"][6]["value"] = data["asset_type"].asInteger();
|
||||
const S32 last_flag_value = static_cast<S32>(FSAssetBlacklist::eBlacklistFlag::LAST_FLAG);
|
||||
|
||||
mResultList->addElement(element, ADD_BOTTOM);
|
||||
for (S32 flag_value = 1; flag_value <= last_flag_value; flag_value <<= 1)
|
||||
{
|
||||
if ((data.flags & flag_value) || data.flags == FSAssetBlacklist::eBlacklistFlag::NONE)
|
||||
{
|
||||
FSAssetBlacklist::eBlacklistFlag flag = static_cast<FSAssetBlacklist::eBlacklistFlag>(flag_value);
|
||||
|
||||
if (data.flags == FSAssetBlacklist::eBlacklistFlag::NONE)
|
||||
flag = FSAssetBlacklist::eBlacklistFlag::NONE;
|
||||
|
||||
LLSD element;
|
||||
element["id"] = id;
|
||||
element["columns"][0]["column"] = "name";
|
||||
element["columns"][0]["type"] = "text";
|
||||
element["columns"][0]["value"] = !data.name.empty() ? data.name : getString("unknown_object");
|
||||
|
||||
element["columns"][1]["column"] = "region";
|
||||
element["columns"][1]["type"] = "text";
|
||||
element["columns"][1]["value"] = !data.region.empty() ? data.region : getString("unknown_region");
|
||||
|
||||
element["columns"][2]["column"] = "type";
|
||||
element["columns"][2]["type"] = "text";
|
||||
element["columns"][2]["value"] = getTypeString(data.type);
|
||||
|
||||
element["columns"][3]["column"] = "flags";
|
||||
element["columns"][3]["type"] = "text";
|
||||
element["columns"][3]["value"] = getFlagString(flag);
|
||||
|
||||
element["columns"][4]["column"] = "date";
|
||||
element["columns"][4]["type"] = "text";
|
||||
element["columns"][4]["value"] = date_str;
|
||||
|
||||
element["columns"][5]["column"] = "permanent";
|
||||
element["columns"][5]["type"] = "text";
|
||||
element["columns"][5]["halign"] = "center";
|
||||
element["columns"][5]["value"] = data.permanent ? getString("asset_permanent") : LLStringUtil::null;
|
||||
|
||||
element["columns"][6]["column"] = "date_sort";
|
||||
element["columns"][6]["type"] = "text";
|
||||
element["columns"][6]["value"] = llformat("%u", (U64)data.date.secondsSinceEpoch());
|
||||
|
||||
element["columns"][7]["column"] = "asset_type";
|
||||
element["columns"][7]["type"] = "integer";
|
||||
element["columns"][7]["value"] = (S32)data.type;
|
||||
|
||||
LLSD value;
|
||||
value["flag"] = static_cast<S32>(flag);
|
||||
element["alt_value"] = value;
|
||||
|
||||
mResultList->addElement(element, ADD_BOTTOM);
|
||||
|
||||
if (data.flags == FSAssetBlacklist::eBlacklistFlag::NONE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterAssetBlacklist::removeElements()
|
||||
{
|
||||
uuid_vec_t items;
|
||||
std::map<LLUUID, S32> flags_to_remove_by_id;
|
||||
|
||||
for (auto listitem : mResultList->getAllSelected())
|
||||
{
|
||||
items.emplace_back(listitem->getUUID());
|
||||
LLUUID id = listitem->getUUID();
|
||||
LLSD value = listitem->getAltValue();
|
||||
|
||||
if (value.has("flag"))
|
||||
{
|
||||
S32 flag = value["flag"].asInteger();
|
||||
flags_to_remove_by_id[id] |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback: remove full item
|
||||
FSAssetBlacklist::instance().removeItemsFromBlacklist({ id });
|
||||
}
|
||||
}
|
||||
|
||||
FSAssetBlacklist::instance().removeItemsFromBlacklist(items);
|
||||
for (const auto& [id, flags] : flags_to_remove_by_id)
|
||||
{
|
||||
FSAssetBlacklist::instance().removeFlagsFromItem(id, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterAssetBlacklist::onBlacklistChanged(const LLSD& data, FSAssetBlacklist::eBlacklistOperation op)
|
||||
void FSFloaterAssetBlacklist::onBlacklistChanged(const FSAssetBlacklist::changed_signal_data_t& data, FSAssetBlacklist::eBlacklistOperation op)
|
||||
{
|
||||
if (op == FSAssetBlacklist::eBlacklistOperation::BLACKLIST_ADD)
|
||||
{
|
||||
bool need_sort = mResultList->isSorted();
|
||||
mResultList->setNeedsSort(false);
|
||||
|
||||
for (LLSD::map_const_iterator it = data.beginMap(); it != data.endMap(); ++it)
|
||||
for (const auto& [id, data] : data)
|
||||
{
|
||||
LLUUID id = LLUUID(it->first);
|
||||
LLSD insert_data = it->second;
|
||||
addElementToList(id, insert_data);
|
||||
mResultList->deleteItems(id);
|
||||
if (data.has_value())
|
||||
{
|
||||
addElementToList(id, data.value());
|
||||
}
|
||||
}
|
||||
|
||||
mResultList->setNeedsSort(need_sort);
|
||||
|
|
@ -194,9 +262,9 @@ void FSFloaterAssetBlacklist::onBlacklistChanged(const LLSD& data, FSAssetBlackl
|
|||
}
|
||||
else
|
||||
{
|
||||
for (LLSD::array_const_iterator it = data.beginArray(); it != data.endArray(); ++it)
|
||||
for (const auto& [id, data] : data)
|
||||
{
|
||||
mResultList->deleteItems(*it);
|
||||
mResultList->deleteItems(id);
|
||||
}
|
||||
mResultList->updateLayout();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public:
|
|||
bool tick() override;
|
||||
void closeFloater(bool app_quitting = false) override;
|
||||
|
||||
void addElementToList(const LLUUID& id, const LLSD& data);
|
||||
void addElementToList(const LLUUID& id, const FSAssetBlacklistData& data);
|
||||
void removeElements();
|
||||
|
||||
protected:
|
||||
|
|
@ -60,11 +60,13 @@ protected:
|
|||
void onStopBtn();
|
||||
void onCloseBtn();
|
||||
void onFilterEdit(const std::string& search_string);
|
||||
void onBlacklistChanged(const LLSD& data, FSAssetBlacklist::eBlacklistOperation op);
|
||||
void onBlacklistChanged(const FSAssetBlacklist::changed_signal_data_t& data, FSAssetBlacklist::eBlacklistOperation op);
|
||||
void onSelectionChanged();
|
||||
|
||||
void buildBlacklist();
|
||||
std::string getTypeString(S32 type);
|
||||
std::string getTypeString(S32 type) const;
|
||||
std::string getFlagString(FSAssetBlacklist::eBlacklistFlag source) const;
|
||||
static FSAssetBlacklist::eBlacklistFlag getFlagFromLLSD(const LLSD& data);
|
||||
|
||||
LLUUID mAudioSourceID;
|
||||
|
||||
|
|
|
|||
|
|
@ -648,8 +648,7 @@ void FSFloaterContacts::addFriend(const LLUUID& agent_id)
|
|||
{
|
||||
const LLRelationship* info = at.getBuddyInfo(agent_id);
|
||||
LLUUID request_id = LLUUID::generateNewID();
|
||||
LLAvatarNameCache::callback_connection_t conn = LLAvatarNameCache::get(agent_id, boost::bind(&FSFloaterContacts::updateFriendItem, this, agent_id, info, request_id));
|
||||
mAvatarNameCacheConnections[request_id] = conn;
|
||||
mAvatarNameCacheConnections.try_emplace(request_id, LLAvatarNameCache::get(agent_id, boost::bind(&FSFloaterContacts::updateFriendItem, this, agent_id, info, request_id)));
|
||||
}
|
||||
|
||||
LLSD element;
|
||||
|
|
@ -742,8 +741,7 @@ void FSFloaterContacts::updateFriendItem(const LLUUID& agent_id, const LLRelatio
|
|||
if (!LLAvatarNameCache::get(agent_id, &av_name))
|
||||
{
|
||||
LLUUID request_id = LLUUID::generateNewID();
|
||||
LLAvatarNameCache::callback_connection_t conn = LLAvatarNameCache::get(agent_id, boost::bind(&FSFloaterContacts::updateFriendItem, this, agent_id, info, request_id));
|
||||
mAvatarNameCacheConnections[request_id] = conn;
|
||||
mAvatarNameCacheConnections.try_emplace(request_id, LLAvatarNameCache::get(agent_id, boost::bind(&FSFloaterContacts::updateFriendItem, this, agent_id, info, request_id)));
|
||||
}
|
||||
|
||||
// Name of the status icon to use
|
||||
|
|
@ -1250,21 +1248,19 @@ void FSFloaterContacts::onColumnDisplayModeChanged(const std::string& settings_n
|
|||
|
||||
void FSFloaterContacts::onDisplayNameChanged()
|
||||
{
|
||||
listitem_vec_t items = mFriendsList->getAllData();
|
||||
for (listitem_vec_t::iterator it = items.begin(); it != items.end(); ++it)
|
||||
for (auto item : mFriendsList->getAllData())
|
||||
{
|
||||
LLAvatarName av_name;
|
||||
if (LLAvatarNameCache::get((*it)->getUUID(), &av_name))
|
||||
if (LLAvatarNameCache::get(item->getUUID(), &av_name))
|
||||
{
|
||||
(*it)->getColumn(LIST_FRIEND_USER_NAME)->setValue(av_name.getUserNameForDisplay());
|
||||
(*it)->getColumn(LIST_FRIEND_DISPLAY_NAME)->setValue(av_name.getDisplayName());
|
||||
(*it)->getColumn(LIST_FRIEND_NAME)->setValue(getFullName(av_name));
|
||||
item->getColumn(LIST_FRIEND_USER_NAME)->setValue(av_name.getUserNameForDisplay());
|
||||
item->getColumn(LIST_FRIEND_DISPLAY_NAME)->setValue(av_name.getDisplayName());
|
||||
item->getColumn(LIST_FRIEND_NAME)->setValue(getFullName(av_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID request_id = LLUUID::generateNewID();
|
||||
LLAvatarNameCache::callback_connection_t conn = LLAvatarNameCache::get((*it)->getUUID(), boost::bind(&FSFloaterContacts::setDirtyNames, this, request_id));
|
||||
mAvatarNameCacheConnections[request_id] = conn;
|
||||
mAvatarNameCacheConnections.try_emplace(request_id, LLAvatarNameCache::get(item->getUUID(), boost::bind(&FSFloaterContacts::setDirtyNames, this, request_id)));
|
||||
}
|
||||
}
|
||||
mFriendsList->setNeedsSort();
|
||||
|
|
|
|||
|
|
@ -2427,7 +2427,7 @@ bool FSFloaterPoser::savePoseToBvh(LLVOAvatar* avatar, const std::string& poseFi
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return writeSuccess;
|
||||
}
|
||||
|
||||
bool FSFloaterPoser::writePoseAsBvh(llofstream* fileStream, LLVOAvatar* avatar)
|
||||
|
|
@ -2454,7 +2454,6 @@ void FSFloaterPoser::writeBvhFragment(llofstream* fileStream, LLVOAvatar* avatar
|
|||
if (!joint)
|
||||
return;
|
||||
|
||||
auto position = mPoserAnimator.getJointPosition(avatar, *joint);
|
||||
auto saveAxis = getBvhJointTranslation(joint->jointName());
|
||||
|
||||
switch (joint->boneType())
|
||||
|
|
@ -2559,7 +2558,7 @@ void FSFloaterPoser::writeBvhMotion(llofstream* fileStream, LLVOAvatar* avatar,
|
|||
switch (joint->boneType())
|
||||
{
|
||||
case WHOLEAVATAR:
|
||||
*fileStream << vec3ToXYZString(position) + " " + rotationToString(rotation);
|
||||
*fileStream << positionToString(position) + " " + rotationToString(rotation);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2575,9 +2574,10 @@ void FSFloaterPoser::writeBvhMotion(llofstream* fileStream, LLVOAvatar* avatar,
|
|||
}
|
||||
}
|
||||
|
||||
std::string FSFloaterPoser::vec3ToXYZString(const LLVector3& val)
|
||||
std::string FSFloaterPoser::positionToString(const LLVector3& val)
|
||||
{
|
||||
return std::to_string(val[VX]) + " " + std::to_string(val[VY]) + " " + std::to_string(val[VZ]);
|
||||
const float metresToInches = 39.37008f;
|
||||
return std::to_string(metresToInches * val[VY]) + " " + std::to_string(metresToInches * val[VZ]) + " " + std::to_string(metresToInches * val[VX]);
|
||||
}
|
||||
|
||||
std::string FSFloaterPoser::rotationToString(const LLVector3& val)
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ public:
|
|||
/// <summary>
|
||||
/// Transforms the supplied vector into a string of three numbers, format suiting to writing into a BVH file.
|
||||
/// </summary>
|
||||
std::string static vec3ToXYZString(const LLVector3& val);
|
||||
std::string static positionToString(const LLVector3& val);
|
||||
|
||||
/// <summary>
|
||||
/// Performs an angle module of the supplied value to between -180 & 180 (degrees).
|
||||
|
|
|
|||
|
|
@ -74,9 +74,14 @@ FSPrimfeedPhotoPanel::FSPrimfeedPhotoPanel() :
|
|||
mDescriptionTextBox(nullptr),
|
||||
mLocationCheckbox(nullptr),
|
||||
mRatingComboBox(nullptr),
|
||||
mStoresComboBox(nullptr),
|
||||
mPostButton(nullptr),
|
||||
mBtnPreview(nullptr),
|
||||
mBigPreviewFloater(nullptr)
|
||||
mBigPreviewFloater(nullptr),
|
||||
mCancelButton(nullptr),
|
||||
mCommercialCheckbox(nullptr),
|
||||
mFilterComboBox(nullptr),
|
||||
mPublicGalleryCheckbox(nullptr)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", [this](LLUICtrl*, const LLSD&) { onSend(); });
|
||||
mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", [this](LLUICtrl*, const LLSD&) { onClickNewSnapshot(); });
|
||||
|
|
@ -88,6 +93,16 @@ FSPrimfeedPhotoPanel::FSPrimfeedPhotoPanel() :
|
|||
LL_DEBUGS("primfeed") << "Info button clicked, opening " << url << LL_ENDL;
|
||||
LLWeb::loadURLExternal(url);
|
||||
});
|
||||
FSPrimfeedAuth::sPrimfeedAuthPump->listen("FSPrimfeedPhotoPanel",
|
||||
[this](const LLSD& data)
|
||||
{
|
||||
if (data["responseType"].asString() == "primfeed_user_info")
|
||||
{
|
||||
this->loadPrimfeedInfo(data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
FSPrimfeedPhotoPanel::~FSPrimfeedPhotoPanel()
|
||||
|
|
@ -97,8 +112,6 @@ FSPrimfeedPhotoPanel::~FSPrimfeedPhotoPanel()
|
|||
mPreviewHandle.get()->die();
|
||||
}
|
||||
|
||||
FSPrimfeedAuth::sPrimfeedAuthPump->stopListening("FSPrimfeedAccountPanel");
|
||||
|
||||
gSavedSettings.setS32("FSLastSnapshotToPrimfeedResolution", getChild<LLComboBox>("resolution_combobox")->getCurrentIndex());
|
||||
gSavedSettings.setS32("FSLastSnapshotToPrimfeedWidth", getChild<LLSpinCtrl>("custom_snapshot_width")->getValue().asInteger());
|
||||
gSavedSettings.setS32("FSLastSnapshotToPrimfeedHeight", getChild<LLSpinCtrl>("custom_snapshot_height")->getValue().asInteger());
|
||||
|
|
@ -121,6 +134,7 @@ bool FSPrimfeedPhotoPanel::postBuild()
|
|||
mCommercialCheckbox = getChild<LLUICtrl>("primfeed_commercial_content");
|
||||
mPublicGalleryCheckbox = getChild<LLUICtrl>("primfeed_add_to_public_gallery");
|
||||
mRatingComboBox = getChild<LLUICtrl>("rating_combobox");
|
||||
mStoresComboBox = getChild<LLComboBox>("stores_combobox");
|
||||
mPostButton = getChild<LLUICtrl>("post_photo_btn");
|
||||
mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
|
||||
mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
|
|
@ -192,6 +206,8 @@ void FSPrimfeedPhotoPanel::draw()
|
|||
mCancelButton->setEnabled(can_post);
|
||||
mDescriptionTextBox->setEnabled(can_post);
|
||||
mRatingComboBox->setEnabled(can_post);
|
||||
// If the stores combo box is present, enable it only if we have stores to select from
|
||||
mStoresComboBox->setEnabled(can_post && mStoresComboBox->getItemCount() > 1);
|
||||
mResolutionComboBox->setEnabled(can_post);
|
||||
mFilterComboBox->setEnabled(can_post);
|
||||
mRefreshBtn->setEnabled(can_post);
|
||||
|
|
@ -327,7 +343,7 @@ bool FSPrimfeedPhotoPanel::onPrimfeedConnectStateChange(const LLSD& /*data*/)
|
|||
{
|
||||
if (FSPrimfeedAuth::isAuthorized())
|
||||
{
|
||||
sendPhoto();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -352,10 +368,10 @@ void FSPrimfeedPhotoPanel::sendPhoto()
|
|||
std::string description = mDescriptionTextBox->getValue().asString();
|
||||
|
||||
// Get the content rating
|
||||
int content_rating = mRatingComboBox->getValue().asInteger();
|
||||
bool post_to_public_gallery = mPublicGalleryCheckbox->getValue().asBoolean();
|
||||
bool commercial_content = mCommercialCheckbox->getValue().asBoolean();
|
||||
|
||||
int content_rating = mRatingComboBox->getValue().asInteger();
|
||||
bool post_to_public_gallery = mPublicGalleryCheckbox->getValue().asBoolean();
|
||||
bool commercial_content = mCommercialCheckbox->getValue().asBoolean();
|
||||
std::string store_id = mStoresComboBox->getValue().asString();
|
||||
// Get the image
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
|
||||
|
|
@ -376,6 +392,11 @@ void FSPrimfeedPhotoPanel::sendPhoto()
|
|||
|
||||
params["location"] = slurl_string;
|
||||
}
|
||||
if (!store_id.empty())
|
||||
{
|
||||
// Add the store ID if we have one selected
|
||||
params["store_id"] = store_id;
|
||||
}
|
||||
|
||||
FSPrimfeedConnect::instance().uploadPhoto(params, previewp->getFormattedImage().get(),
|
||||
[this](bool success, const std::string& url)
|
||||
|
|
@ -529,6 +550,35 @@ void FSPrimfeedPhotoPanel::checkAspectRatio(S32 index)
|
|||
}
|
||||
}
|
||||
|
||||
void FSPrimfeedPhotoPanel::loadPrimfeedInfo(const LLSD& data)
|
||||
{
|
||||
if (!mStoresComboBox)
|
||||
return;
|
||||
|
||||
// Clear any existing entries
|
||||
mStoresComboBox->clearRows();
|
||||
mStoresComboBox->add(LLTrans::getString("Personal"), LLSD(""));
|
||||
|
||||
// Read the saved stores array
|
||||
const LLSD& stores = data["stores"];
|
||||
if (!stores.isArray() || stores.size() == 0)
|
||||
{
|
||||
// No stores - disable the combobox
|
||||
mStoresComboBox->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
mStoresComboBox->setEnabled(true);
|
||||
for (S32 i = 0; i < stores.size(); ++i)
|
||||
{
|
||||
const LLSD& store = stores[i];
|
||||
std::string id = store["id"].asString();
|
||||
std::string name = store["name"].asString();
|
||||
mStoresComboBox->add(name, LLSD(id));
|
||||
}
|
||||
mStoresComboBox->setCurrentByIndex(0);
|
||||
}
|
||||
|
||||
LLUICtrl* FSPrimfeedPhotoPanel::getRefreshBtn()
|
||||
{
|
||||
return mRefreshBtn;
|
||||
|
|
@ -536,13 +586,10 @@ LLUICtrl* FSPrimfeedPhotoPanel::getRefreshBtn()
|
|||
|
||||
void FSPrimfeedPhotoPanel::onOpen(const LLSD& key)
|
||||
{
|
||||
if (!FSPrimfeedAuth::isAuthorized())
|
||||
{
|
||||
// Reauthorise if necessary.
|
||||
FSPrimfeedAuth::initiateAuthRequest();
|
||||
LLSD dummy;
|
||||
onPrimfeedConnectStateChange(dummy);
|
||||
}
|
||||
// Reauthorise if necessary.
|
||||
FSPrimfeedAuth::initiateAuthRequest();
|
||||
LLSD dummy;
|
||||
onPrimfeedConnectStateChange(dummy);
|
||||
}
|
||||
|
||||
void FSPrimfeedPhotoPanel::uploadCallback(bool success, const LLSD& response)
|
||||
|
|
@ -639,9 +686,23 @@ FSPrimfeedAccountPanel::FSPrimfeedAccountPanel() :
|
|||
FSPrimfeedAuth::sPrimfeedAuthPump->listen("FSPrimfeedAccountPanel",
|
||||
[this](const LLSD& data)
|
||||
{
|
||||
bool success = data["success"].asBoolean();
|
||||
primfeedAuthResponse(success, data);
|
||||
return true;
|
||||
if (data.has("responseType"))
|
||||
{
|
||||
auto response_type = data["responseType"].asString();
|
||||
if (response_type == "primfeed_auth_response")
|
||||
{
|
||||
bool success = data["success"].asBoolean();
|
||||
primfeedAuthResponse(success, data);
|
||||
return true;
|
||||
}
|
||||
if (response_type == "primfeed_auth_reset")
|
||||
{
|
||||
bool success = data["success"].asBoolean();
|
||||
primfeedAuthResponse(success, data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
setVisibleCallback([this](LLUICtrl*, bool visible) { onVisibilityChange(visible); });
|
||||
|
|
@ -663,8 +724,8 @@ bool FSPrimfeedAccountPanel::postBuild()
|
|||
|
||||
void FSPrimfeedAccountPanel::draw()
|
||||
{
|
||||
FSPrimfeedConnect::EConnectionState connection_state = FSPrimfeedConnect::instance().getConnectionState();
|
||||
static FSPrimfeedConnect::EConnectionState last_state = FSPrimfeedConnect::PRIMFEED_DISCONNECTED;
|
||||
FSPrimfeedConnect::EConnectionState connection_state = FSPrimfeedConnect::instance().getConnectionState();
|
||||
static FSPrimfeedConnect::EConnectionState last_state = FSPrimfeedConnect::PRIMFEED_DISCONNECTED;
|
||||
|
||||
// Update the connection state if it has changed
|
||||
if (connection_state != last_state)
|
||||
|
|
@ -772,14 +833,20 @@ void FSPrimfeedAccountPanel::onConnect()
|
|||
{
|
||||
FSPrimfeedAuth::initiateAuthRequest();
|
||||
LLSD dummy;
|
||||
onPrimfeedConnectStateChange(dummy);
|
||||
onPrimfeedConnectStateChange(dummy);
|
||||
}
|
||||
|
||||
void FSPrimfeedAccountPanel::onDisconnect()
|
||||
{
|
||||
FSPrimfeedAuth::resetAuthStatus();
|
||||
LLSD dummy;
|
||||
onPrimfeedConnectStateChange(dummy);
|
||||
onPrimfeedConnectStateChange(dummy);
|
||||
}
|
||||
|
||||
FSPrimfeedAccountPanel::~FSPrimfeedAccountPanel()
|
||||
{
|
||||
// Disconnect the primfeed auth pump
|
||||
FSPrimfeedAuth::sPrimfeedAuthPump->stopListening("FSPrimfeedAccountPanel");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
|
|
@ -789,10 +856,10 @@ void FSPrimfeedAccountPanel::onDisconnect()
|
|||
FSFloaterPrimfeed::FSFloaterPrimfeed(const LLSD& key) :
|
||||
LLFloater(key),
|
||||
mPrimfeedPhotoPanel(nullptr),
|
||||
mPrimfeedAccountPanel(nullptr),
|
||||
mStatusErrorText(nullptr),
|
||||
mStatusLoadingText(nullptr),
|
||||
mStatusLoadingIndicator(nullptr),
|
||||
mPrimfeedAccountPanel(nullptr)
|
||||
mStatusLoadingIndicator(nullptr)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Cancel", [this](LLUICtrl*, const LLSD&) { onCancel(); });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
class LLIconCtrl;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLComboBox;
|
||||
class LLSnapshotLivePreview;
|
||||
class LLFloaterBigPreview;
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ public:
|
|||
bool postBuild() override;
|
||||
S32 notify(const LLSD& info);
|
||||
void draw() override;
|
||||
void loadPrimfeedInfo(const LLSD& data);
|
||||
|
||||
LLSnapshotLivePreview* getPreviewView();
|
||||
void onVisibilityChange(bool new_visibility);
|
||||
|
|
@ -80,28 +82,30 @@ private:
|
|||
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
|
||||
LLUICtrl * mResolutionComboBox;
|
||||
LLUICtrl * mFilterComboBox;
|
||||
LLUICtrl * mRefreshBtn;
|
||||
LLUICtrl * mWorkingLabel;
|
||||
LLUICtrl * mThumbnailPlaceholder;
|
||||
LLUICtrl * mDescriptionTextBox;
|
||||
LLUICtrl * mLocationCheckbox;
|
||||
LLUICtrl* mResolutionComboBox;
|
||||
LLUICtrl* mFilterComboBox;
|
||||
LLUICtrl* mRefreshBtn;
|
||||
LLUICtrl* mWorkingLabel;
|
||||
LLUICtrl* mThumbnailPlaceholder;
|
||||
LLUICtrl* mDescriptionTextBox;
|
||||
LLUICtrl* mLocationCheckbox;
|
||||
|
||||
LLUICtrl * mCommercialCheckbox;
|
||||
LLUICtrl * mPublicGalleryCheckbox;
|
||||
LLUICtrl * mRatingComboBox;
|
||||
LLUICtrl * mPostButton;
|
||||
LLUICtrl * mCancelButton;
|
||||
LLButton * mBtnPreview;
|
||||
LLUICtrl* mCommercialCheckbox;
|
||||
LLUICtrl* mPublicGalleryCheckbox;
|
||||
LLUICtrl* mRatingComboBox;
|
||||
LLUICtrl* mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
LLButton* mBtnPreview;
|
||||
LLComboBox* mStoresComboBox;
|
||||
|
||||
LLFloaterBigPreview * mBigPreviewFloater;
|
||||
LLFloaterBigPreview* mBigPreviewFloater;
|
||||
};
|
||||
|
||||
class FSPrimfeedAccountPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
FSPrimfeedAccountPanel();
|
||||
~FSPrimfeedAccountPanel();
|
||||
bool postBuild() override;
|
||||
void draw() override;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -36,19 +36,19 @@
|
|||
#include <boost/signals2.hpp>
|
||||
|
||||
extern const char* DEFAULT_LOGIN_PAGE;
|
||||
//Kokua: for llviewernetwork_test
|
||||
const S32 KNOWN_GRIDS_SIZE = 3;
|
||||
// Kokua: for llviewernetwork_test
|
||||
const S32 KNOWN_GRIDS_SIZE = 3;
|
||||
|
||||
const std::string GRID_VALUE = "name";
|
||||
const std::string GRID_LABEL_VALUE = "gridname";
|
||||
const std::string GRID_ID_VALUE = "grid_login_id";
|
||||
const std::string GRID_LOGIN_URI_VALUE = "loginuri";
|
||||
const std::string GRID_UPDATE_SERVICE_URL = "update_query_url_base";
|
||||
const std::string GRID_HELPER_URI_VALUE = "helperuri";
|
||||
const std::string GRID_LOGIN_PAGE_VALUE = "loginpage";
|
||||
const std::string GRID_IS_SYSTEM_GRID_VALUE = "system_grid";
|
||||
const std::string GRID_IS_FAVORITE_VALUE = "favorite";
|
||||
const std::string GRID_LOGIN_IDENTIFIER_TYPES = "login_identifier_types";
|
||||
const std::string GRID_VALUE = "name";
|
||||
const std::string GRID_LABEL_VALUE = "gridname";
|
||||
const std::string GRID_ID_VALUE = "grid_login_id";
|
||||
const std::string GRID_LOGIN_URI_VALUE = "loginuri";
|
||||
const std::string GRID_UPDATE_SERVICE_URL = "update_query_url_base";
|
||||
const std::string GRID_HELPER_URI_VALUE = "helperuri";
|
||||
const std::string GRID_LOGIN_PAGE_VALUE = "loginpage";
|
||||
const std::string GRID_IS_SYSTEM_GRID_VALUE = "system_grid";
|
||||
const std::string GRID_IS_FAVORITE_VALUE = "favorite";
|
||||
const std::string GRID_LOGIN_IDENTIFIER_TYPES = "login_identifier_types";
|
||||
|
||||
const std::string GRID_NICK_VALUE = "gridnick";
|
||||
const std::string GRID_REGISTER_NEW_ACCOUNT = "register";
|
||||
|
|
@ -66,8 +66,8 @@ const std::string GRID_MESSAGE = "message";
|
|||
// we need to continue to support existing forms, as slurls
|
||||
// are shared between viewers that may not understand newer
|
||||
// forms.
|
||||
const std::string GRID_SLURL_BASE = "slurl_base";
|
||||
const std::string GRID_APP_SLURL_BASE = "app_slurl_base";
|
||||
const std::string GRID_SLURL_BASE = "slurl_base";
|
||||
const std::string GRID_APP_SLURL_BASE = "app_slurl_base";
|
||||
|
||||
// Inworldz special
|
||||
#define INWORLDZ_URI "inworldz.com:8002"
|
||||
|
|
@ -76,24 +76,22 @@ class GridInfoRequestResponder;
|
|||
|
||||
struct GridEntry
|
||||
{
|
||||
LLSD grid;
|
||||
LLSD grid;
|
||||
LLXMLNodePtr info_root;
|
||||
bool set_current;
|
||||
std::string last_http_error;
|
||||
bool set_current;
|
||||
std::string last_http_error;
|
||||
};
|
||||
|
||||
class LLInvalidGridName
|
||||
{
|
||||
public:
|
||||
LLInvalidGridName(std::string grid) : mGrid(grid)
|
||||
{
|
||||
}
|
||||
LLInvalidGridName(std::string grid) : mGrid(grid) {}
|
||||
std::string name() { return mGrid; }
|
||||
|
||||
protected:
|
||||
std::string mGrid;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A class to manage the grids available to the viewer
|
||||
* including persistance. This class also maintains the currently
|
||||
|
|
@ -128,7 +126,7 @@ public:
|
|||
void initCmdLineGrids();
|
||||
void resetGrids();
|
||||
// grid list management
|
||||
bool isReadyToLogin() const {return mReadyToLogin;}
|
||||
bool isReadyToLogin() const { return mReadyToLogin; }
|
||||
|
||||
// add a grid to the list of grids
|
||||
void addGrid(const std::string& loginuri);
|
||||
|
|
@ -140,8 +138,8 @@ public:
|
|||
std::map<std::string, std::string> getKnownGrids();
|
||||
|
||||
// this was getGridInfo - renamed to avoid ambiguity with the OpenSim grid_info
|
||||
void getGridData(const std::string& grid, LLSD &grid_info);
|
||||
void getGridData(LLSD &grid_info) { getGridData(mGrid, grid_info); }
|
||||
void getGridData(const std::string& grid, LLSD& grid_info);
|
||||
void getGridData(LLSD& grid_info) { getGridData(mGrid, grid_info); }
|
||||
|
||||
// current grid management
|
||||
|
||||
|
|
@ -151,7 +149,7 @@ public:
|
|||
void setGridChoice(const std::string& grid);
|
||||
|
||||
/// Return the name of a grid, given either its name or its id
|
||||
std::string getGrid( const std::string &grid );
|
||||
std::string getGrid(const std::string& grid) const;
|
||||
|
||||
/// Get the id (short form selector) for a given grid; example: "agni"
|
||||
std::string getGridId(const std::string& grid);
|
||||
|
|
@ -160,7 +158,7 @@ public:
|
|||
std::string getGridId() { return getGridId(mGrid); }
|
||||
|
||||
/// Deprecated for compatibility with LL. Use getGridId() instead.
|
||||
//std::string getGridNick() { return mGridList[mGrid][GRID_NICK_VALUE]; }
|
||||
// std::string getGridNick() { return mGridList[mGrid][GRID_NICK_VALUE]; }
|
||||
|
||||
/// Get the user-friendly long form descriptor for a given grid; example: "Second Life"
|
||||
std::string getGridLabel(const std::string& grid);
|
||||
|
|
@ -201,67 +199,67 @@ public:
|
|||
|
||||
void setWebProfileUrl(const std::string& url) { mGridList[mGrid][GRID_WEB_PROFILE_VALUE] = url; }
|
||||
|
||||
bool hasGrid(const std::string& grid){ return mGridList.has(grid); }
|
||||
bool isTemporary(){ return mGridList[mGrid].has("FLAG_TEMPORARY"); }
|
||||
bool isTemporary(const std::string& grid){ return mGridList[grid].has("FLAG_TEMPORARY"); }
|
||||
bool hasGrid(const std::string& grid) const { return mGridList.has(grid); }
|
||||
bool isTemporary() const { return mGridList[mGrid].has("FLAG_TEMPORARY"); }
|
||||
bool isTemporary(const std::string& grid) const { return mGridList[grid].has("FLAG_TEMPORARY"); }
|
||||
|
||||
// tell if we got this from a Hypergrid SLURL
|
||||
bool isHyperGrid(const std::string& grid) { return mGridList[grid].has("HG"); }
|
||||
|
||||
// tell if we know how to acess this grid via Hypergrid
|
||||
std::string getGatekeeper() { return getGatekeeper(mGrid); }
|
||||
std::string getGatekeeper(const std::string& grid) { return mGridList[grid].has("gatekeeper") ? mGridList[grid]["gatekeeper"].asString() : std::string(); }
|
||||
|
||||
std::string getGridByLabel( const std::string &grid_label, bool case_sensitive = false);
|
||||
|
||||
std::string getGridByProbing( const std::string &probe_for, bool case_sensitive = false);
|
||||
std::string getGridByGridNick( const std::string &grid_nick, bool case_sensitive = false);
|
||||
std::string getGridByHostName( const std::string &host_name, bool case_sensitive = false);
|
||||
std::string getGridByAttribute(const std::string &attribute, const std::string &attribute_value, bool case_sensitive );
|
||||
|
||||
bool isSystemGrid(const std::string& grid)
|
||||
std::string getGatekeeper(const std::string& grid)
|
||||
{
|
||||
return mGridList.has(grid) &&
|
||||
mGridList[grid].has(GRID_IS_SYSTEM_GRID_VALUE) &&
|
||||
return mGridList[grid].has("gatekeeper") ? mGridList[grid]["gatekeeper"].asString() : std::string();
|
||||
}
|
||||
|
||||
std::string getGridByLabel(const std::string& grid_label, bool case_sensitive = false) const;
|
||||
|
||||
std::string getGridByProbing(const std::string& probe_for, bool case_sensitive = false) const;
|
||||
std::string getGridByGridNick(const std::string& grid_nick, bool case_sensitive = false) const;
|
||||
std::string getGridByHostName(const std::string& host_name, bool case_sensitive = false) const;
|
||||
std::string getGridByAttribute(const std::string& attribute, const std::string& attribute_value, bool case_sensitive) const;
|
||||
|
||||
bool isSystemGrid(const std::string& grid) const
|
||||
{
|
||||
return mGridList.has(grid) && mGridList[grid].has(GRID_IS_SYSTEM_GRID_VALUE) &&
|
||||
mGridList[grid][GRID_IS_SYSTEM_GRID_VALUE].asBoolean();
|
||||
}
|
||||
bool isSystemGrid() { return isSystemGrid(mGrid); }
|
||||
bool isSystemGrid() const { return isSystemGrid(mGrid); }
|
||||
|
||||
typedef boost::function<void(bool success)> grid_list_changed_callback_t;
|
||||
typedef boost::function<void(bool success)> grid_list_changed_callback_t;
|
||||
typedef boost::signals2::signal<void(bool success)> grid_list_changed_signal_t;
|
||||
|
||||
boost::signals2::connection addGridListChangedCallback(grid_list_changed_callback_t cb);
|
||||
grid_list_changed_signal_t mGridListChangedSignal;
|
||||
bool isInSecondLife();
|
||||
bool isInSLMain();
|
||||
bool isInSLBeta();
|
||||
bool isInOpenSim();
|
||||
bool isInAuroraSim();
|
||||
void saveGridList();
|
||||
void clearFavorites();
|
||||
void addGrid(GridEntry* grid_info, AddState state);
|
||||
bool isInSecondLife() const;
|
||||
bool isInSLMain() const;
|
||||
bool isInSLBeta() const;
|
||||
bool isInOpenSim() const;
|
||||
bool isInAuroraSim() const;
|
||||
void saveGridList();
|
||||
void addGrid(GridEntry* grid_info, AddState state);
|
||||
|
||||
void setClassifiedFee(const S32 classified_fee) { sClassifiedFee = classified_fee; }
|
||||
S32 getClassifiedFee() { return sClassifiedFee; }
|
||||
void setDirectoryFee(const S32 directory_fee) { sDirectoryFee = directory_fee; }
|
||||
S32 getDirectoryFee() { return sDirectoryFee; }
|
||||
void setClassifiedFee(const S32 classified_fee) { mClassifiedFee = classified_fee; }
|
||||
S32 getClassifiedFee() const { return mClassifiedFee; }
|
||||
void setDirectoryFee(const S32 directory_fee) { mDirectoryFee = directory_fee; }
|
||||
S32 getDirectoryFee() const { return mDirectoryFee; }
|
||||
|
||||
private:
|
||||
friend class GridInfoRequestResponder;
|
||||
|
||||
friend void gridDownloadComplete( LLSD const &aData, LLGridManager* mOwner, GridEntry* mData, LLGridManager::AddState mState );
|
||||
friend void gridDownloadError( LLSD const &aData, LLGridManager* mOwner, GridEntry* mData, LLGridManager::AddState mState );
|
||||
friend void gridDownloadComplete(LLSD const& aData, LLGridManager* mOwner, GridEntry* mData, LLGridManager::AddState mState);
|
||||
friend void gridDownloadError(LLSD const& aData, LLGridManager* mOwner, GridEntry* mData, LLGridManager::AddState mState);
|
||||
|
||||
void incResponderCount(){++mResponderCount;}
|
||||
void decResponderCount(){--mResponderCount;}
|
||||
void incResponderCount() { ++mResponderCount; }
|
||||
void decResponderCount() { --mResponderCount; }
|
||||
void gridInfoResponderCB(GridEntry* grid_data);
|
||||
|
||||
void setGridData(const LLSD &grid_info) { mGridList[mGrid]=grid_info; }
|
||||
S32 sClassifiedFee;
|
||||
S32 sDirectoryFee;
|
||||
void setGridData(const LLSD& grid_info) { mGridList[mGrid] = grid_info; }
|
||||
S32 mClassifiedFee;
|
||||
S32 mDirectoryFee;
|
||||
|
||||
protected:
|
||||
|
||||
void updateIsInProductionGrid();
|
||||
|
||||
// helper function for adding the predefined grids
|
||||
|
|
@ -272,15 +270,14 @@ protected:
|
|||
const std::string& helper,
|
||||
const std::string& login_page);
|
||||
|
||||
|
||||
std::string mGrid;
|
||||
std::string mGridFile;
|
||||
std::string mStartupGrid;
|
||||
LLSD mGridList;
|
||||
LLSD mConnectedGrid;
|
||||
int mResponderCount;
|
||||
bool mReadyToLogin;
|
||||
bool mCommandLineDone;
|
||||
LLSD mGridList;
|
||||
LLSD mConnectedGrid;
|
||||
int mResponderCount;
|
||||
bool mReadyToLogin;
|
||||
bool mCommandLineDone;
|
||||
|
||||
enum e_grid_platform
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@
|
|||
* @return void
|
||||
*
|
||||
*/
|
||||
static void renderPulsingSphere(const LLVector3& joint_world_position, const LLColor4& color = LLColor4(1.f, 1.f, 1.f, 1.f))
|
||||
static void renderPulsingSphere(const LLVector3& joint_world_position, const LLColor4& color = LLColor4(0.f, 0.f, 1.f, 0.3f))
|
||||
{
|
||||
constexpr float MAX_SPHERE_RADIUS = 0.05f; // Base radius in agent-space units.
|
||||
constexpr float PULSE_AMPLITUDE = 0.01f; // Additional radius variation.
|
||||
constexpr float MAX_SPHERE_RADIUS = 0.02f; // Base radius in agent-space units.
|
||||
constexpr float PULSE_AMPLITUDE = 0.005f; // Additional radius variation.
|
||||
constexpr float PULSE_FREQUENCY = 1.f; // Pulses per second.
|
||||
constexpr float PULSE_TIME_DOMAIN = 5.f; // Keep the time input small.
|
||||
|
||||
|
|
@ -104,9 +104,8 @@ static void renderPulsingSphere(const LLVector3& joint_world_position, const LLC
|
|||
LLGLDepthTest gls_depth(GL_FALSE);
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
LLColor4 color;
|
||||
gGL.color4f(0.f, 0.f, 1.f, 0.3f);
|
||||
gGL.diffuseColor4f(0.f, 0.f, 1.f, 0.3f);
|
||||
gGL.color4fv(color.mV);
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
|
||||
gGL.scalef(currentRadius, currentRadius, currentRadius);
|
||||
|
||||
|
|
@ -129,37 +128,82 @@ static void renderPulsingSphere(const LLVector3& joint_world_position, const LLC
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static bool isMouseOverJoint(S32 mouseX, S32 mouseY, const LLVector3& jointWorldPos, F32 jointRadius, F32& outDistanceFromCamera)
|
||||
static void renderStaticSphere(const LLVector3& joint_world_position, const LLColor4& color = LLColor4(1.f, 1.f, 0.f, .6f), float radius=0.01f)
|
||||
{
|
||||
LLViewerCamera* camera = LLViewerCamera::getInstance();
|
||||
LLGLSUIDefault gls_ui;
|
||||
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
|
||||
LLGLDepthTest gls_depth(GL_TRUE);
|
||||
LLGLEnable gl_blend(GL_BLEND);
|
||||
|
||||
// Transform joint world position to screen coordinates
|
||||
LLCoordGL jointScreenPos;
|
||||
camera->projectPosAgentToScreen(jointWorldPos, jointScreenPos);
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
|
||||
// Get the world view rect
|
||||
LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled();
|
||||
F32 half_width = (F32)world_view_rect.getWidth() / 2.f;
|
||||
F32 half_height = (F32)world_view_rect.getHeight() / 2.f;
|
||||
// Translate to the joint's position
|
||||
gGL.translatef(joint_world_position.mV[VX], joint_world_position.mV[VY], joint_world_position.mV[VZ]);
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
|
||||
// Convert mouse coordinates to be relative to the center of the screen
|
||||
LLVector2 mousePos((F32)mouseX - half_width, (F32)mouseY - half_height);
|
||||
LLGLEnable cull_face(GL_CULL_FACE);
|
||||
LLGLDepthTest gls_depth(GL_FALSE);
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
gGL.color4fv(color.mV);
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
|
||||
// Convert joint screen position to be relative to the center of the screen
|
||||
LLVector2 joint2d(jointScreenPos.mX - half_width, jointScreenPos.mY - half_height);
|
||||
gGL.scalef(radius, radius, radius);
|
||||
|
||||
// Calculate the distance between mouse and joint in screen space
|
||||
LLVector2 delta = joint2d - mousePos;
|
||||
gSphere.render();
|
||||
gGL.flush();
|
||||
}
|
||||
gGL.popMatrix();
|
||||
|
||||
// Calculate the distance from the camera to the joint
|
||||
outDistanceFromCamera = (jointWorldPos - camera->getOrigin()).magVec();
|
||||
gUIProgram.bind();
|
||||
}
|
||||
gGL.popMatrix();
|
||||
}
|
||||
gGL.popMatrix();
|
||||
|
||||
// Calculate the apparent radius of the joint on the screen
|
||||
F32 apparentRadius = jointRadius * camera->getPixelMeterRatio() / outDistanceFromCamera;
|
||||
// Check for OpenGL errors
|
||||
GLenum err;
|
||||
while ((err = glGetError()) != GL_NO_ERROR)
|
||||
{
|
||||
LL_INFOS() << "OpenGL Error: " << err << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the mouse is within the joint's radius
|
||||
return (delta.magVecSquared() < apparentRadius * apparentRadius);
|
||||
|
||||
bool FSManipRotateJoint::isMouseOverJoint(S32 mouseX, S32 mouseY, const LLVector3& jointWorldPos, F32 jointRadius, F32& outDistanceFromCamera, F32& outRayDistanceFromCenter) const
|
||||
{
|
||||
// LL_INFOS("FSManipRotateJoint") << "Checking mouse("<< mouseX << "," << mouseY << ") over joint at: " << jointWorldPos << LL_ENDL;
|
||||
|
||||
auto joint_center = gAgent.getPosGlobalFromAgent( jointWorldPos );
|
||||
|
||||
// centre in *agent* space
|
||||
LLVector3 agent_space_center = gAgent.getPosAgentFromGlobal(joint_center);
|
||||
LLVector3 ray_pt, ray_dir;
|
||||
LLManipRotate::mouseToRay(mouseX, mouseY, &ray_pt, &ray_dir);
|
||||
|
||||
// Vector from ray origin to sphere center
|
||||
LLVector3 to_center = agent_space_center - ray_pt;
|
||||
// Project that onto the ray direction
|
||||
F32 proj_len = ray_dir * to_center;
|
||||
|
||||
if (proj_len > 0.f)
|
||||
{
|
||||
// Closest approach squared = |to_center|^2 – (proj_len)^2
|
||||
F32 closest_dist_sq = to_center.magVecSquared() - (proj_len * proj_len);
|
||||
if (closest_dist_sq <= jointRadius * jointRadius)
|
||||
{
|
||||
// ray *does* hit the sphere; compute the entrance intersection distance
|
||||
F32 offset = sqrtf(jointRadius*jointRadius - closest_dist_sq);
|
||||
outDistanceFromCamera = proj_len - offset; // distance along the ray to the front intersection
|
||||
outRayDistanceFromCenter = offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -281,12 +325,18 @@ FSManipRotateJoint::BoneAxes FSManipRotateJoint::computeBoneAxes() const
|
|||
void FSManipRotateJoint::highlightHoverSpheres(S32 mouseX, S32 mouseY)
|
||||
{
|
||||
// Ensure we have an avatar to work with.
|
||||
if (!mAvatar) return;
|
||||
if (!mAvatar || mAvatar->isDead())
|
||||
return;
|
||||
|
||||
mHighlightedJoint = nullptr; // reset the highlighted joint
|
||||
|
||||
// Iterate through the avatar's joint map.
|
||||
for (const auto& entry : getSelectableJoints())
|
||||
F32 nearest_hit_distance = 0.f;
|
||||
F32 nearest_ray_distance = 0.f;
|
||||
LLJoint * nearest_joint = nullptr;
|
||||
for ( const auto& entry : getSelectableJoints())
|
||||
{
|
||||
|
||||
LLJoint* joint = mAvatar->getJoint(std::string(entry));
|
||||
if (!joint)
|
||||
continue;
|
||||
|
|
@ -297,18 +347,24 @@ void FSManipRotateJoint::highlightHoverSpheres(S32 mouseX, S32 mouseY)
|
|||
|
||||
// Retrieve the joint's world position (in agent space).
|
||||
LLVector3 jointWorldPos = joint->getWorldPosition();
|
||||
LLCachedControl<F32> target_radius(gSavedSettings, "FSManipRotateJointTargetSize", 0.2f);
|
||||
LLCachedControl<F32> target_radius(gSavedSettings, "FSManipRotateJointTargetSize", 0.03f);
|
||||
F32 distance_from_camera;
|
||||
if (isMouseOverJoint(mouseX, mouseY, jointWorldPos, target_radius, distance_from_camera) == true)
|
||||
F32 distance_from_joint;
|
||||
if (isMouseOverJoint(mouseX, mouseY, jointWorldPos, target_radius, distance_from_camera, distance_from_joint) == true)
|
||||
{
|
||||
// we want to highlight the closest
|
||||
if (!mHighlightedJoint || mHighlightedPartDistance > distance_from_camera)
|
||||
// If there is no joint or
|
||||
// this joint is a closer hit than the previous one
|
||||
if (!nearest_joint || nearest_ray_distance > distance_from_camera ||
|
||||
(nearest_ray_distance == distance_from_camera && nearest_hit_distance > distance_from_joint))
|
||||
{
|
||||
mHighlightedJoint = joint;
|
||||
mHighlightedPartDistance = distance_from_camera;
|
||||
nearest_joint = joint;
|
||||
nearest_hit_distance = distance_from_joint;
|
||||
nearest_ray_distance = distance_from_camera;
|
||||
}
|
||||
}
|
||||
}
|
||||
mHighlightedJoint = nearest_joint;
|
||||
}
|
||||
|
||||
FSManipRotateJoint::FSManipRotateJoint(LLToolComposite* composite)
|
||||
|
|
@ -375,6 +431,7 @@ bool FSManipRotateJoint::updateVisiblity()
|
|||
if (!hasMouseCapture())
|
||||
{
|
||||
mRotationCenter = gAgent.getPosGlobalFromAgent( mJoint->getWorldPosition() );
|
||||
mCamEdgeOn = false;
|
||||
}
|
||||
|
||||
bool visible = false;
|
||||
|
|
@ -413,13 +470,6 @@ bool FSManipRotateJoint::updateVisiblity()
|
|||
}
|
||||
}
|
||||
|
||||
mCamEdgeOn = false;
|
||||
F32 axis_onto_cam = mManipPart >= LL_ROT_X ? llabs( getConstraintAxis() * mCenterToCamNorm ) : 0.f;
|
||||
if (axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE)
|
||||
{
|
||||
mCamEdgeOn = true;
|
||||
}
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
|
@ -648,28 +698,50 @@ void FSManipRotateJoint::renderCenterSphere(const F32 radius, const LLColor4& no
|
|||
void FSManipRotateJoint::render()
|
||||
{
|
||||
// Early-out if no joint or avatar.
|
||||
if (!mJoint || !mAvatar)
|
||||
// Needs more something: if they log out while dots on them, asplode
|
||||
if (!mJoint || !mAvatar || mAvatar->isDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// update visibility and rotation center.
|
||||
if (!updateVisiblity())
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool activeJointVisible = updateVisiblity();
|
||||
// Setup GL state.
|
||||
LLGLSUIDefault gls_ui;
|
||||
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
|
||||
LLGLDepthTest gls_depth(GL_TRUE);
|
||||
LLGLEnable gl_blend(GL_BLEND);
|
||||
|
||||
// Optionally, if another joint is highlighted, render a pulsing sphere.
|
||||
if (mHighlightedJoint && mJoint != mHighlightedJoint)
|
||||
// Iterate through the avatar's joint map.
|
||||
// If a joint other than the currently selected is highlighted, render a pulsing sphere.
|
||||
// otherwise a small static sphere
|
||||
for (const auto& entry : getSelectableJoints())
|
||||
{
|
||||
mHighlightedJoint->updateWorldMatrixParent();
|
||||
mHighlightedJoint->updateWorldMatrix();
|
||||
renderPulsingSphere(mHighlightedJoint->getWorldPosition());
|
||||
LLJoint* joint = mAvatar->getJoint(std::string(entry));
|
||||
if (!joint)
|
||||
continue;
|
||||
// Update the joint's world matrix to ensure its position is current.
|
||||
joint->updateWorldMatrixParent();
|
||||
joint->updateWorldMatrix();
|
||||
|
||||
if( joint == mHighlightedJoint && joint != mJoint )
|
||||
{
|
||||
renderPulsingSphere(joint->getWorldPosition());
|
||||
}
|
||||
else if( joint != mJoint )
|
||||
{
|
||||
// Render a static sphere for the joint being manipulated.
|
||||
LLCachedControl<bool> show_joint_markers(gSavedSettings, "FSManipShowJointMarkers", true);
|
||||
if(show_joint_markers)
|
||||
{
|
||||
renderStaticSphere(joint->getWorldPosition(), LLColor4(1.f, 0.5f, 0.f, 0.5f), 0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!activeJointVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update joint world matrices.
|
||||
|
|
@ -683,30 +755,21 @@ void FSManipRotateJoint::render()
|
|||
LLQuaternion currentLocalRot = mJoint->getRotation();
|
||||
|
||||
LLQuaternion rotatedNaturalAlignment = mNaturalAlignmentQuat * currentLocalRot;
|
||||
rotatedNaturalAlignment.normalize();
|
||||
// Compute the final world alignment:
|
||||
LLQuaternion final_world_alignment = rotatedNaturalAlignment * parentWorldRot;
|
||||
final_world_alignment.normalize();
|
||||
|
||||
const LLVector3 agent_space_center = gAgent.getPosAgentFromGlobal(mRotationCenter);
|
||||
|
||||
LLCachedControl<bool> use_natural_direction(gSavedSettings, "FSManipRotateJointUseNaturalDirection", true);
|
||||
LLQuaternion active_rotation = use_natural_direction? final_world_alignment : joint_world_rotation;
|
||||
active_rotation.normalize();
|
||||
// Render the manipulator rings in a separate function.
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
renderAxes(agent_space_center, mRadiusMeters * 1.5f, active_rotation);
|
||||
renderManipulatorRings(agent_space_center, active_rotation);
|
||||
|
||||
// Debug: render joint's Euler angles for diagnostic purposes.
|
||||
LLVector3 euler_angles;
|
||||
active_rotation.getEulerAngles(&euler_angles.mV[0],
|
||||
&euler_angles.mV[1],
|
||||
&euler_angles.mV[2]);
|
||||
euler_angles *= RAD_TO_DEG;
|
||||
euler_angles.mV[0] = ll_round(fmodf(euler_angles.mV[0] + 360.f, 360.f), 0.05f);
|
||||
euler_angles.mV[1] = ll_round(fmodf(euler_angles.mV[1] + 360.f, 360.f), 0.05f);
|
||||
euler_angles.mV[2] = ll_round(fmodf(euler_angles.mV[2] + 360.f, 360.f), 0.05f);
|
||||
renderNameXYZ(euler_angles);
|
||||
renderNameXYZ(active_rotation);
|
||||
}
|
||||
|
||||
void FSManipRotateJoint::renderAxes(const LLVector3& agent_space_center, F32 size, const LLQuaternion& rotation)
|
||||
|
|
@ -804,13 +867,28 @@ std::string FSManipRotateJoint::getManipPartString(EManipPart part)
|
|||
* @note This function assumes the existence of class member variables such as mLastAngle, mJoint, and mManipPart.
|
||||
* It also uses global functions and objects like gViewerWindow, LLUI, and LLFontGL.
|
||||
*/
|
||||
void FSManipRotateJoint::renderNameXYZ(const LLVector3 &vec)
|
||||
void FSManipRotateJoint::renderNameXYZ(const LLQuaternion& rot)
|
||||
{
|
||||
constexpr S32 PAD = 10;
|
||||
S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2;
|
||||
S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2;
|
||||
S32 vertical_offset = window_center_y - VERTICAL_OFFSET;
|
||||
|
||||
LLVector3 euler_angles;
|
||||
rot.getEulerAngles(&euler_angles.mV[0],
|
||||
&euler_angles.mV[1],
|
||||
&euler_angles.mV[2]);
|
||||
euler_angles *= RAD_TO_DEG;
|
||||
for (S32 i = 0; i < 3; ++i)
|
||||
{
|
||||
// Ensure angles are in the range [0, 360) and rounded to 0.05f
|
||||
euler_angles.mV[i] = ll_round(fmodf(euler_angles.mV[i] + 360.f, 360.f), 0.05f);
|
||||
F32 rawDelta = euler_angles.mV[i] - mLastEuler.mV[i];
|
||||
if (rawDelta > 180.f) rawDelta -= 360.f;
|
||||
else if (rawDelta < -180.f) rawDelta += 360.f;
|
||||
mLastEuler[i] += rawDelta;
|
||||
}
|
||||
|
||||
gGL.pushMatrix();
|
||||
{
|
||||
LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
|
||||
|
|
@ -840,13 +918,22 @@ void FSManipRotateJoint::renderNameXYZ(const LLVector3 &vec)
|
|||
};
|
||||
|
||||
F32 base_y = (F32)(window_center_y + vertical_offset);
|
||||
renderTextWithShadow(llformat("X: %.3f", vec.mV[VX]), window_center_x - 122.f, base_y, LLColor4(1.f, 0.5f, 0.5f, 1.f));
|
||||
renderTextWithShadow(llformat("Y: %.3f", vec.mV[VY]), window_center_x - 47.f, base_y, LLColor4(0.5f, 1.f, 0.5f, 1.f));
|
||||
renderTextWithShadow(llformat("Z: %.3f", vec.mV[VZ]), window_center_x + 28.f, base_y, LLColor4(0.5f, 0.5f, 1.f, 1.f));
|
||||
renderTextWithShadow(llformat("Δ: %.3f", mLastAngle * RAD_TO_DEG), window_center_x + 103.f, base_y, LLColor4(1.f, 0.65f, 0.f, 1.f));
|
||||
renderTextWithShadow(llformat("X: %.3f", mLastEuler.mV[VX]), window_center_x - 122.f, base_y, LLColor4(1.f, 0.5f, 0.5f, 1.f));
|
||||
renderTextWithShadow(llformat("Y: %.3f", mLastEuler.mV[VY]), window_center_x - 47.f, base_y, LLColor4(0.5f, 1.f, 0.5f, 1.f));
|
||||
renderTextWithShadow(llformat("Z: %.3f", mLastEuler.mV[VZ]), window_center_x + 28.f, base_y, LLColor4(0.5f, 0.5f, 1.f, 1.f));
|
||||
renderTextWithShadow(llformat("⟳: %.3f", mLastAngle * RAD_TO_DEG), window_center_x + 103.f, base_y, LLColor4(1.f, 0.65f, 0.f, 1.f));
|
||||
base_y += 20.f;
|
||||
renderTextWithShadow(llformat("Joint: %s", mJoint->getName().c_str()), window_center_x - 130.f, base_y, LLColor4(1.f, 0.1f, 1.f, 1.f));
|
||||
renderTextWithShadow(llformat("Manip: %s", getManipPartString(mManipPart).c_str()), window_center_x + 30.f, base_y, LLColor4(1.f, 1.f, .1f, 1.f));
|
||||
renderTextWithShadow(llformat("Manip: %s%c", getManipPartString(mManipPart).c_str(), mCamEdgeOn?'*':' '), window_center_x + 30.f, base_y, LLColor4(1.f, 1.f, .1f, 1.f));
|
||||
if (mManipPart != LL_NO_PART)
|
||||
{
|
||||
LL_INFOS("FSManipRotateJoint") << "Joint: " << mJoint->getName()
|
||||
<< ", Manip: " << getManipPartString(mManipPart)
|
||||
<< ", Quaternion: " << rot
|
||||
<< ", Euler Angles: " << mLastEuler
|
||||
<< ", Delta Angle: " << mLastAngle * RAD_TO_DEG
|
||||
<< LL_ENDL;
|
||||
}
|
||||
}
|
||||
gGL.popMatrix();
|
||||
|
||||
|
|
@ -934,7 +1021,7 @@ bool FSManipRotateJoint::handleMouseDownOnPart(S32 x, S32 y, MASK mask)
|
|||
// Determine which ring (axis) is under the mouse, also highlights selectable joints.
|
||||
highlightManipulators(x, y);
|
||||
// For joint manipulation, require both a valid joint and avatar.
|
||||
if (!mJoint || !mAvatar || !poser)
|
||||
if (!mJoint || !mAvatar || mAvatar->isDead() || !poser)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -960,9 +1047,11 @@ bool FSManipRotateJoint::handleMouseDownOnPart(S32 x, S32 y, MASK mask)
|
|||
{
|
||||
// Constrained rotation.
|
||||
LLVector3 axis = setConstraintAxis(); // set the axis based on the manipulator part
|
||||
|
||||
mLastEuler = LLVector3::zero;
|
||||
|
||||
F32 axis_onto_cam = llabs(axis * mCenterToCamNorm);
|
||||
const F32 AXIS_ONTO_CAM_TOL = cos(85.f * DEG_TO_RAD);
|
||||
if (axis_onto_cam < AXIS_ONTO_CAM_TOL)
|
||||
if (axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE)
|
||||
{
|
||||
LLVector3 up_from_axis = mCenterToCamNorm % axis;
|
||||
up_from_axis.normalize();
|
||||
|
|
@ -979,11 +1068,13 @@ bool FSManipRotateJoint::handleMouseDownOnPart(S32 x, S32 y, MASK mask)
|
|||
}
|
||||
LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, axis);
|
||||
mMouseDown += mouse_depth * projected_center_to_cam;
|
||||
mCamEdgeOn = true; // We are in edge mode, so we can use the mouse depth.
|
||||
}
|
||||
else
|
||||
{
|
||||
mMouseDown = findNearestPointOnRing(x, y, agent_space_center, axis) - agent_space_center;
|
||||
mMouseDown.normalize();
|
||||
mCamEdgeOn = false; // Not in edge mode, so we don't use the mouse depth.
|
||||
}
|
||||
mInitialIntersection = mMouseDown;
|
||||
}
|
||||
|
|
@ -1021,6 +1112,7 @@ bool FSManipRotateJoint::handleMouseUp(S32 x, S32 y, MASK mask)
|
|||
setMouseCapture(false);
|
||||
mManipPart = LL_NO_PART;
|
||||
mLastAngle = 0.0f;
|
||||
mCamEdgeOn = false;
|
||||
return true;
|
||||
}
|
||||
else if(mHighlightedJoint)
|
||||
|
|
@ -1051,7 +1143,7 @@ void FSManipRotateJoint::highlightManipulators(S32 x, S32 y)
|
|||
mHighlightedPart = LL_NO_PART;
|
||||
// Instead of using mObjectSelection->getFirstMoveableObject(),
|
||||
// simply require that the joint (and the avatar) is valid.
|
||||
if (!mJoint || !mAvatar)
|
||||
if (!mJoint || !mAvatar || mAvatar->isDead())
|
||||
{
|
||||
highlightHoverSpheres(x, y);
|
||||
gViewerWindow->setCursor(UI_CURSOR_ARROW);
|
||||
|
|
@ -1280,13 +1372,43 @@ LLQuaternion FSManipRotateJoint::dragUnconstrained(S32 x, S32 y)
|
|||
return sphere_rot * LLQuaternion(extra_angle, axis);
|
||||
}
|
||||
}
|
||||
|
||||
static LLQuaternion extractTwist(const LLQuaternion& rot, const LLVector3& axis)
|
||||
{
|
||||
// Copy and normalise the input (defensive)
|
||||
LLQuaternion qnorm = rot;
|
||||
qnorm.normalize();
|
||||
|
||||
// Extract vector part and scalar part
|
||||
LLVector3 v(qnorm.mQ[VX], qnorm.mQ[VY], qnorm.mQ[VZ]);
|
||||
F32 w = qnorm.mQ[VW];
|
||||
|
||||
// Project v onto the axis (removing any perpendicular component)
|
||||
F32 dot = v * axis;
|
||||
LLVector3 proj = axis * dot; // proj is now purely along 'axis'
|
||||
|
||||
// Build the “twist” quaternion from (proj, w), then renormalize
|
||||
LLQuaternion twist(proj.mV[VX],
|
||||
proj.mV[VY],
|
||||
proj.mV[VZ],
|
||||
w);
|
||||
if (w < 0.f)
|
||||
{
|
||||
twist = -twist;
|
||||
}
|
||||
twist.normalize();
|
||||
return twist;
|
||||
}
|
||||
LLQuaternion FSManipRotateJoint::dragConstrained(S32 x, S32 y)
|
||||
{
|
||||
// Get the constraint axis from our joint manipulator.
|
||||
// (See the adjusted getConstraintAxis() below.)
|
||||
LLVector3 constraint_axis = getConstraintAxis();
|
||||
LLVector3 agent_space_center = gAgent.getPosAgentFromGlobal(mRotationCenter);
|
||||
|
||||
if (mCamEdgeOn)
|
||||
{
|
||||
LLQuaternion freeRot = dragUnconstrained(x, y);
|
||||
return extractTwist(freeRot, constraint_axis);
|
||||
}
|
||||
// Project the current mouse position onto the plane defined by the constraint axis.
|
||||
LLVector3 projected_mouse;
|
||||
bool hit = getMousePointOnPlaneAgent(projected_mouse, x, y, agent_space_center, constraint_axis);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class LLJoint;
|
|||
class LLVOAvatar; // or LLVOAvatarSelf, etc.
|
||||
|
||||
namespace {
|
||||
const F32 AXIS_ONTO_CAM_TOLERANCE = cos( 80.f * DEG_TO_RAD ); // cos() is not constexpr til c++26
|
||||
const F32 AXIS_ONTO_CAM_TOLERANCE = cos( 85.f * DEG_TO_RAD ); // cos() is not constexpr til c++26
|
||||
constexpr F32 RADIUS_PIXELS = 100.f; // size in screen space
|
||||
constexpr S32 CIRCLE_STEPS = 100;
|
||||
constexpr F32 CIRCLE_STEP_SIZE = 2.0f * F_PI / CIRCLE_STEPS;
|
||||
|
|
@ -83,7 +83,7 @@ public:
|
|||
void handleSelect() override;
|
||||
bool updateVisiblity();
|
||||
void render() override;
|
||||
void renderNameXYZ(const LLVector3 &vec);
|
||||
void renderNameXYZ(const LLQuaternion& rot);
|
||||
bool handleMouseDown(S32 x, S32 y, MASK mask) override;
|
||||
bool handleMouseUp(S32 x, S32 y, MASK mask) override;
|
||||
bool handleHover(S32 x, S32 y, MASK mask) override;
|
||||
|
|
@ -94,7 +94,6 @@ public:
|
|||
void highlightHoverSpheres(S32 mouseX, S32 mouseY);
|
||||
|
||||
protected:
|
||||
// void renderNameXYZ(const std::string name, const LLVector3 &vec);
|
||||
LLQuaternion dragUnconstrained( S32 x, S32 y );
|
||||
LLQuaternion dragConstrained( S32 x, S32 y );
|
||||
LLVector3 getConstraintAxis() const { return mConstraintAxis; };
|
||||
|
|
@ -109,10 +108,12 @@ protected:
|
|||
LLQuaternion mSavedJointRot;
|
||||
LLJoint * mHighlightedJoint = nullptr;
|
||||
F32 mHighlightedPartDistance = 0.f;
|
||||
LLVector3 mLastEuler = LLVector3::zero; // last euler angles in degrees
|
||||
LLVector3 mInitialIntersection; // The initial point on the manipulator’s sphere (in agent space)
|
||||
const std::vector<std::string_view> getSelectableJoints(){ return sSelectableJoints; };
|
||||
|
||||
private:
|
||||
bool isMouseOverJoint(S32 mouseX, S32 mouseY, const LLVector3& jointWorldPos, F32 jointRadius, F32& outDistanceFromCamera, F32& outDistanceFromCenter) const;
|
||||
static const std::vector<std::string_view> sSelectableJoints;
|
||||
|
||||
// Structure holding parameters needed to render one manipulator ring.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "llagent.h"
|
||||
#include "llagentdata.h"
|
||||
#include "llavatarappearancedefines.h"
|
||||
#include "llbutton.h"
|
||||
#include "llcalc.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
|
|
@ -760,7 +761,7 @@ void FSPanelFace::onMatTabChange()
|
|||
// Since we allow both PBR and BP textures to be applied at the same time,
|
||||
// we need to hide or show the GLTF material only locally based on the current tab.
|
||||
gSavedSettings.setBOOL("FSShowSelectedInBlinnPhong", (curr_mat == MATMEDIA_MATERIAL));
|
||||
if (curr_mat != MATMEDIA_PBR)
|
||||
if (curr_mat == MATMEDIA_MATERIAL)
|
||||
LLSelectMgr::getInstance()->hideGLTFMaterial();
|
||||
else
|
||||
LLSelectMgr::getInstance()->showGLTFMaterial();
|
||||
|
|
@ -1154,6 +1155,16 @@ void FSPanelFace::onVisibilityChange(bool new_visibility)
|
|||
gAgent.showLatestFeatureNotification("gltf");
|
||||
}
|
||||
LLPanel::onVisibilityChange(new_visibility);
|
||||
|
||||
// Since we allow both PBR and BP textures to be applied at the same time,
|
||||
// we need to keep FSShowSelectedInBlinnPhong in sync in case we open or close the texture panel.
|
||||
static LLCachedControl<bool> showSelectedinBP(gSavedSettings, "FSShowSelectedInBlinnPhong");
|
||||
bool should_hide_gltf = new_visibility && !showSelectedinBP && getCurrentMaterialType() == MATMEDIA_MATERIAL;
|
||||
gSavedSettings.setBOOL("FSShowSelectedInBlinnPhong", should_hide_gltf);
|
||||
if (should_hide_gltf)
|
||||
{
|
||||
LLSelectMgr::getInstance()->hideGLTFMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void FSPanelFace::draw()
|
||||
|
|
@ -6004,13 +6015,9 @@ void FSPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical)
|
|||
LLUUID get(LLViewerObject* object, S32 te_index)
|
||||
{
|
||||
LLTextureEntry *te = object->getTE(te_index);
|
||||
if (te)
|
||||
if (te && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(te->getID()))
|
||||
{
|
||||
if ((te->getID() == IMG_USE_BAKED_EYES) || (te->getID() == IMG_USE_BAKED_HAIR) || (te->getID() == IMG_USE_BAKED_HEAD) || (te->getID() == IMG_USE_BAKED_LOWER) || (te->getID() == IMG_USE_BAKED_SKIRT) || (te->getID() == IMG_USE_BAKED_UPPER)
|
||||
|| (te->getID() == IMG_USE_BAKED_LEFTARM) || (te->getID() == IMG_USE_BAKED_LEFTLEG) || (te->getID() == IMG_USE_BAKED_AUX1) || (te->getID() == IMG_USE_BAKED_AUX2) || (te->getID() == IMG_USE_BAKED_AUX3))
|
||||
{
|
||||
return te->getID();
|
||||
}
|
||||
return te->getID();
|
||||
}
|
||||
|
||||
LLUUID id;
|
||||
|
|
|
|||
|
|
@ -112,31 +112,25 @@ void FSPrimfeedAuth::initiateAuthRequest()
|
|||
// It should be called when the user clicks the "Authenticate" button.
|
||||
// Also triggered on opening the floater.
|
||||
// The actual implementation is in the create() method.
|
||||
|
||||
if (!isAuthorized())
|
||||
|
||||
if (sPrimfeedAuth)
|
||||
{
|
||||
if (sPrimfeedAuth)
|
||||
LLNotificationsUtil::add("PrimfeedAuthorizationAlreadyInProgress");
|
||||
return;
|
||||
}
|
||||
// If no token stored, begin the login request; otherwise check user status.
|
||||
sPrimfeedAuth = FSPrimfeedAuth::create(
|
||||
[](bool success, const LLSD &response)
|
||||
{
|
||||
LLNotificationsUtil::add("PrimfeedAuthorizationAlreadyInProgress");
|
||||
return;
|
||||
LLSD event_data = response;
|
||||
event_data["responseType"] = "primfeed_auth_response";
|
||||
event_data["success"] = success;
|
||||
sPrimfeedAuthPump->post(event_data);
|
||||
// Now that auth is complete, clear the static pointer.
|
||||
sPrimfeedAuth.reset();
|
||||
}
|
||||
// If no token stored, begin the login request; otherwise check user status.
|
||||
sPrimfeedAuth = FSPrimfeedAuth::create(
|
||||
[](bool success, const LLSD &response)
|
||||
{
|
||||
LLSD event_data = response;
|
||||
event_data["success"] = success;
|
||||
sPrimfeedAuthPump->post(event_data);
|
||||
// Now that auth is complete, clear the static pointer.
|
||||
sPrimfeedAuth.reset();
|
||||
}
|
||||
);
|
||||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_CONNECTING);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("PrimfeedAlreadyAuthorized");
|
||||
}
|
||||
);
|
||||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_CONNECTING);
|
||||
}
|
||||
|
||||
void FSPrimfeedAuth::resetAuthStatus()
|
||||
|
|
@ -147,7 +141,7 @@ void FSPrimfeedAuth::resetAuthStatus()
|
|||
gSavedPerAccountSettings.setString("FSPrimfeedPlan", "");
|
||||
gSavedPerAccountSettings.setString("FSPrimfeedUsername", "");
|
||||
LLSD event_data;
|
||||
event_data["status"] = "reset";
|
||||
event_data["responseType"] = "primfeed_auth_reset";
|
||||
event_data["success"] = "false";
|
||||
sPrimfeedAuthPump->post(event_data);
|
||||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_DISCONNECTED);
|
||||
|
|
@ -201,7 +195,8 @@ std::shared_ptr<FSPrimfeedAuth> FSPrimfeedAuth::create(authorized_callback_t cal
|
|||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_CONNECTING);
|
||||
|
||||
// If no token stored, begin the login request; otherwise check user status.
|
||||
if (gSavedPerAccountSettings.getString("FSPrimfeedOAuthToken").empty())
|
||||
auth->mOauthToken = gSavedPerAccountSettings.getString("FSPrimfeedOAuthToken");
|
||||
if (auth->mOauthToken.empty())
|
||||
{
|
||||
auth->beginLoginRequest();
|
||||
}
|
||||
|
|
@ -225,6 +220,7 @@ void FSPrimfeedAuth::beginLoginRequest()
|
|||
LLCore::HttpHeaders::ptr_t pHeader(new LLCore::HttpHeaders());
|
||||
LLCore::HttpOptions::ptr_t options(new LLCore::HttpOptions());
|
||||
|
||||
pHeader->append(HTTP_OUT_HEADER_USER_AGENT, FS_PF_USER_AGENT);
|
||||
pHeader->append("pf-viewer-api-key", viewer_api_key);
|
||||
pHeader->append("pf-user-uuid", user_uuid);
|
||||
|
||||
|
|
@ -326,6 +322,7 @@ void FSPrimfeedAuth::validateRequest()
|
|||
|
||||
// Create and populate the headers.
|
||||
LLCore::HttpHeaders::ptr_t pHeader(new LLCore::HttpHeaders());
|
||||
pHeader->append(HTTP_OUT_HEADER_USER_AGENT, FS_PF_USER_AGENT);
|
||||
pHeader->append("Authorization", "Bearer " + mOauthToken);
|
||||
pHeader->append("pf-viewer-api-key", viewer_api_key);
|
||||
pHeader->append("pf-viewer-request-id", mRequestId);
|
||||
|
|
@ -398,6 +395,7 @@ void FSPrimfeedAuth::checkUserStatus()
|
|||
|
||||
// Create and populate the headers.
|
||||
LLCore::HttpHeaders::ptr_t pHeader(new LLCore::HttpHeaders());
|
||||
pHeader->append(HTTP_OUT_HEADER_USER_AGENT, FS_PF_USER_AGENT);
|
||||
pHeader->append("Authorization", "Bearer " + mOauthToken);
|
||||
pHeader->append("pf-viewer-api-key", viewer_api_key);
|
||||
|
||||
|
|
@ -429,22 +427,23 @@ void FSPrimfeedAuth::checkUserStatus()
|
|||
}
|
||||
|
||||
|
||||
void FSPrimfeedAuth::gotUserStatus(bool success, const LLSD &response)
|
||||
void FSPrimfeedAuth::gotUserStatus(bool success, const LLSD &response) const
|
||||
{
|
||||
LL_INFOS("Primfeed") << "User status: " << response << "(" << success << ")" << LL_ENDL;
|
||||
if (success && response.has("plan"))
|
||||
if (success && response.has("plan") && response.has("username") && response.has("link"))
|
||||
{
|
||||
gSavedPerAccountSettings.setString("FSPrimfeedOAuthToken", mOauthToken);
|
||||
gSavedPerAccountSettings.setString("FSPrimfeedPlan", response["plan"].asString());
|
||||
gSavedPerAccountSettings.setString("FSPrimfeedProfileLink", response["link"].asString());
|
||||
gSavedPerAccountSettings.setString("FSPrimfeedUsername", response["username"].asString());
|
||||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_CONNECTED);
|
||||
LLSD event_data = response;
|
||||
event_data["responseType"] = "primfeed_user_info";
|
||||
sPrimfeedAuthPump->post(event_data);
|
||||
mCallback(true, response);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("PrimfeedUserStatusFailed");
|
||||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_DISCONNECTED);
|
||||
mCallback(false, response);
|
||||
}
|
||||
LLNotificationsUtil::add("PrimfeedUserStatusFailed");
|
||||
FSPrimfeedConnect::instance().setConnectionState(FSPrimfeedConnect::PRIMFEED_DISCONNECTED);
|
||||
mCallback(false, response);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ private:
|
|||
// Callback when the validate response is received.
|
||||
void gotValidateResponse(bool success, const LLSD &response);
|
||||
// Callback when the user status response is received.
|
||||
void gotUserStatus(bool success, const LLSD &response);
|
||||
void gotUserStatus(bool success, const LLSD &response) const;
|
||||
|
||||
boost::signals2::connection mInstantMessageConnection;
|
||||
boost::signals2::connection mChatMessageConnection;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ void FSPrimfeedConnect::uploadPhotoCoro(const LLSD& params, LLImageFormatted* im
|
|||
addPart("location", params["location"].asString());
|
||||
}
|
||||
|
||||
|
||||
LL_DEBUGS("primfeed") << "Adding image file header" << LL_ENDL;
|
||||
body << dash << sep
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << fmt << "\"" << sep
|
||||
|
|
@ -119,14 +120,14 @@ void FSPrimfeedConnect::uploadPhotoCoro(const LLSD& params, LLImageFormatted* im
|
|||
LLCore::HttpHeaders::ptr_t headers(new LLCore::HttpHeaders);
|
||||
std::string token = gSavedPerAccountSettings.getString("FSPrimfeedOAuthToken");
|
||||
std::string apiKey = gSavedSettings.getString("FSPrimfeedViewerApiKey");
|
||||
headers->append(HTTP_OUT_HEADER_USER_AGENT, FS_PF_USER_AGENT);
|
||||
headers->append("Authorization", "Bearer " + token);
|
||||
headers->append("pf-viewer-api-key", apiKey);
|
||||
headers->append("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
LL_DEBUGS("primfeed") << "Dumping HTTP headers for POST:" << LL_ENDL;
|
||||
for (auto it = headers->begin(); it != headers->end(); ++it)
|
||||
if (params.has("store_id") && !params["store_id"].asString().empty())
|
||||
{
|
||||
LL_DEBUGS("primfeed") << it->first << ": " << it->second << LL_ENDL;
|
||||
headers->append("kynno-selected-store", params["store_id"].asString());
|
||||
}
|
||||
headers->append("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
LL_DEBUGS("primfeed") << "Headers set" << LL_ENDL;
|
||||
|
||||
LL_DEBUGS("primfeed") << "Starting HTTP POST" << LL_ENDL;
|
||||
|
|
@ -181,9 +182,3 @@ bool FSPrimfeedConnect::isTransactionOngoing() const
|
|||
mConnectionState == PRIMFEED_DISCONNECTING);
|
||||
}
|
||||
|
||||
void FSPrimfeedConnect::loadPrimfeedInfo()
|
||||
{
|
||||
LL_DEBUGS("primfeed") << "loadPrimfeedInfo() called" << LL_ENDL;
|
||||
// Nothing to do here for Primfeed
|
||||
setConnectionState(PRIMFEED_CONNECTED);
|
||||
}
|
||||
|
|
@ -39,7 +39,9 @@
|
|||
#include <functional>
|
||||
|
||||
// Coro based connector designed to interface with floater designed along the same principles as LLFloaterFlickr.cpp
|
||||
|
||||
#ifndef FS_PF_USER_AGENT
|
||||
#define FS_PF_USER_AGENT "Firestorm-PF"
|
||||
#endif // FS_PF_USER_AGENT
|
||||
class FSPrimfeedConnect : public LLSingleton<FSPrimfeedConnect>
|
||||
{
|
||||
LLSINGLETON(FSPrimfeedConnect);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class FSRadar
|
|||
virtual ~FSRadar();
|
||||
|
||||
public:
|
||||
typedef std::unordered_map<const LLUUID, std::shared_ptr<FSRadarEntry>, FSUUIDHash> entry_map_t;
|
||||
typedef std::unordered_map<LLUUID, std::shared_ptr<FSRadarEntry>> entry_map_t;
|
||||
entry_map_t getRadarList() { return mEntryList; }
|
||||
|
||||
void startTracking(const LLUUID& avatar_id);
|
||||
|
|
@ -130,7 +130,7 @@ private:
|
|||
bool lastIgnore;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<LLUUID, RadarFields, FSUUIDHash> radarfields_map_t;
|
||||
typedef std::unordered_map<LLUUID, RadarFields> radarfields_map_t;
|
||||
radarfields_map_t mLastRadarSweep;
|
||||
entry_map_t mEntryList;
|
||||
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ void LFSimFeatureHandler::setSupportedFeatures()
|
|||
}
|
||||
else if (LLGridManager::instance().isInSecondLife())
|
||||
{
|
||||
mAvatarPickerURL = gSavedSettings.getString("AvatarPickerURL");
|
||||
mAvatarPickerURL = gSavedSettings.getString("AvatarWelcomePack");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -300,7 +300,7 @@ void LFSimFeatureHandler::setSupportedFeatures()
|
|||
}
|
||||
else if (in_sl)
|
||||
{
|
||||
mAvatarPickerURL = gSavedSettings.getString("AvatarPickerURL");
|
||||
mAvatarPickerURL = gSavedSettings.getString("AvatarWelcomePack");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -767,15 +767,23 @@ void LGGContactSets::setPseudonym(const LLUUID& friend_id, std::string_view pseu
|
|||
inst->fetch(friend_id);
|
||||
LLVOAvatar::invalidateNameTag(friend_id);
|
||||
|
||||
if (auto it = mAvatarNameCacheConnections.find(friend_id); it != mAvatarNameCacheConnections.end())
|
||||
if (LLAvatarName av_name; LLAvatarNameCache::get(friend_id, &av_name))
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
mChangedSignal(UPDATED_MEMBERS);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto it = mAvatarNameCacheConnections.find(friend_id); it != mAvatarNameCacheConnections.end())
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
}
|
||||
|
||||
mAvatarNameCacheConnections.try_emplace(friend_id, LLAvatarNameCache::get(friend_id, boost::bind(&LGGContactSets::onAvatarNameCache, this, _1)));
|
||||
}
|
||||
mAvatarNameCacheConnections[friend_id] = LLAvatarNameCache::get(friend_id, boost::bind(&LGGContactSets::onAvatarNameCache, this, _1));
|
||||
saveToDisk();
|
||||
}
|
||||
|
||||
|
|
@ -802,15 +810,24 @@ void LGGContactSets::clearPseudonym(const LLUUID& friend_id, bool save_changes /
|
|||
removeNonFriendFromList(friend_id, save_changes);
|
||||
}
|
||||
|
||||
if (auto it = mAvatarNameCacheConnections.find(friend_id); it != mAvatarNameCacheConnections.end())
|
||||
if (LLAvatarName av_name; LLAvatarNameCache::get(friend_id, &av_name))
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
mChangedSignal(UPDATED_MEMBERS);
|
||||
}
|
||||
mAvatarNameCacheConnections[friend_id] = LLAvatarNameCache::get(friend_id, boost::bind(&LGGContactSets::onAvatarNameCache, this, _1));
|
||||
else
|
||||
{
|
||||
if (auto it = mAvatarNameCacheConnections.find(friend_id); it != mAvatarNameCacheConnections.end())
|
||||
{
|
||||
if (it->second.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
}
|
||||
|
||||
mAvatarNameCacheConnections.try_emplace(friend_id, LLAvatarNameCache::get(friend_id, boost::bind(&LGGContactSets::onAvatarNameCache, this, _1)));
|
||||
}
|
||||
|
||||
if (save_changes)
|
||||
{
|
||||
saveToDisk();
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class LGGContactSets : public LLSingleton<LGGContactSets>
|
|||
|
||||
public:
|
||||
typedef std::vector<std::string> string_vec_t;
|
||||
typedef std::unordered_set<LLUUID, FSUUIDHash> uuid_set_t;
|
||||
typedef std::unordered_set<LLUUID> uuid_set_t;
|
||||
|
||||
void loadFromDisk();
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ private:
|
|||
LLSD exportToLLSD();
|
||||
void saveToDisk();
|
||||
|
||||
typedef std::unordered_map<LLUUID, std::string, FSUUIDHash> uuid_map_t;
|
||||
typedef std::unordered_map<LLUUID, std::string> uuid_map_t;
|
||||
typedef std::map<std::string, ContactSet*> contact_set_map_t;
|
||||
contact_set_map_t mContactSets;
|
||||
|
||||
|
|
|
|||
|
|
@ -305,7 +305,10 @@ S32 LLAgentBenefits::get2KTextureUploadCost(S32 area) const
|
|||
{
|
||||
if (m_2k_texture_upload_cost.empty())
|
||||
{
|
||||
return m_texture_upload_cost;
|
||||
// <FS:Ansariel> OpenSim legacy economy
|
||||
//return m_texture_upload_cost;
|
||||
return getTextureUploadCost();
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
return m_2k_texture_upload_cost[0];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2531,7 +2531,7 @@ void LLAvatarActions::derenderMultiple(const uuid_vec_t& agent_ids, bool permane
|
|||
//static
|
||||
void LLAvatarActions::onDerenderAvatarNameLookup(const LLUUID& agent_id, const LLAvatarName& av_name, bool permanent)
|
||||
{
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(agent_id, av_name.getUserName(), "", LLAssetType::AT_PERSON, permanent, permanent);
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(agent_id, av_name.getUserName(), "", LLAssetType::AT_PERSON, FSAssetBlacklist::eBlacklistFlag::NONE, permanent, permanent);
|
||||
|
||||
LLViewerObject* av_obj = gObjectList.findObject(agent_id);
|
||||
if (av_obj)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* @file llfloateravatar.h
|
||||
* @author Leyla Farazha
|
||||
* @brief floater for the avatar changer
|
||||
* @file llfloateravatarwelcomepack.cpp
|
||||
* @author Callum Prentice (callum@lindenlab.com)
|
||||
* @brief Floater container for the Avatar Welcome Pack we app
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloateravatar.h"
|
||||
#include "llfloateravatarwelcomepack.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llmediactrl.h"
|
||||
|
||||
|
|
@ -35,13 +35,13 @@
|
|||
#include "llhttpconstants.h"
|
||||
#include "llweb.h"
|
||||
|
||||
LLFloaterAvatar::LLFloaterAvatar(const LLSD& key)
|
||||
LLFloaterAvatarWelcomePack::LLFloaterAvatarWelcomePack(const LLSD& key)
|
||||
: LLFloater(key),
|
||||
mAvatarPickerUrlChangedSignal() // <FS:Ansariel> Avatar chooser does not change between OpenSim grids
|
||||
{
|
||||
}
|
||||
|
||||
LLFloaterAvatar::~LLFloaterAvatar()
|
||||
LLFloaterAvatarWelcomePack::~LLFloaterAvatarWelcomePack()
|
||||
{
|
||||
if (mAvatarPicker)
|
||||
{
|
||||
|
|
@ -58,32 +58,32 @@ LLFloaterAvatar::~LLFloaterAvatar()
|
|||
// </FS:Ansariel>
|
||||
}
|
||||
|
||||
bool LLFloaterAvatar::postBuild()
|
||||
bool LLFloaterAvatarWelcomePack::postBuild()
|
||||
{
|
||||
mAvatarPicker = findChild<LLMediaCtrl>("avatar_picker_contents");
|
||||
if (mAvatarPicker)
|
||||
{
|
||||
mAvatarPicker->clearCache();
|
||||
}
|
||||
enableResizeCtrls(true, true, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Avatar chooser does not change between OpenSim grids
|
||||
void LLFloaterAvatar::onOpen(const LLSD& key)
|
||||
void LLFloaterAvatarWelcomePack::onOpen(const LLSD& key)
|
||||
{
|
||||
// Connect during onOpen instead of ctor because LLFloaterAvatar instance
|
||||
// Connect during onOpen instead of ctor because LLFloaterAvatarWelcomePack instance
|
||||
// gets created before we can safely create a LFSimFeatureHandler instance!
|
||||
// Assuming we receive the avatar picker URL via login response and it
|
||||
// is the same URL being sent by region caps so we will be good for the initial
|
||||
// region the avatar logs into as well.
|
||||
if (!mAvatarPickerUrlChangedSignal.connected())
|
||||
{
|
||||
mAvatarPickerUrlChangedSignal = LFSimFeatureHandler::instance().setAvatarPickerCallback(boost::bind(&LLFloaterAvatar::handleUrlChanged, this, _1));
|
||||
mAvatarPickerUrlChangedSignal = LFSimFeatureHandler::instance().setAvatarPickerCallback(boost::bind(&LLFloaterAvatarWelcomePack::handleUrlChanged, this, _1));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterAvatar::handleUrlChanged(const std::string& url)
|
||||
void LLFloaterAvatarWelcomePack::handleUrlChanged(const std::string& url)
|
||||
{
|
||||
getChild<LLMediaCtrl>("avatar_picker_contents")->navigateTo(LLWeb::expandURLSubstitutions(url, LLSD()), HTTP_CONTENT_TEXT_HTML);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* @file llfloateravatar.h
|
||||
* @author Leyla Farazha
|
||||
* @brief floater for the avatar changer
|
||||
* @file llfloateravatarwelcomepack.h
|
||||
* @author Callum Prentice (callum@lindenlab.com)
|
||||
* @brief Floater container for the Avatar Welcome Pack we app
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
|
|
@ -25,29 +25,28 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_FLOATER_AVATAR_H
|
||||
#define LL_FLOATER_AVATAR_H
|
||||
#pragma once
|
||||
|
||||
#include "llfloater.h"
|
||||
|
||||
class LLMediaCtrl;
|
||||
|
||||
class LLFloaterAvatar:
|
||||
class LLFloaterAvatarWelcomePack:
|
||||
public LLFloater
|
||||
{
|
||||
friend class LLFloaterReg;
|
||||
private:
|
||||
LLFloaterAvatar(const LLSD& key);
|
||||
~LLFloaterAvatar();
|
||||
bool postBuild() override;
|
||||
|
||||
LLMediaCtrl* mAvatarPicker;
|
||||
private:
|
||||
LLFloaterAvatarWelcomePack(const LLSD& key);
|
||||
~LLFloaterAvatarWelcomePack();
|
||||
bool postBuild() override;
|
||||
|
||||
LLMediaCtrl* mAvatarPicker;
|
||||
|
||||
// <FS:Ansariel> Avatar chooser does not change between OpenSim grids
|
||||
/*virtual*/ void onOpen(const LLSD& key) override;
|
||||
void onOpen(const LLSD& key) override;
|
||||
void handleUrlChanged(const std::string& url);
|
||||
|
||||
boost::signals2::connection mAvatarPickerUrlChangedSignal;
|
||||
// </FS:Ansariel>
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -68,6 +68,7 @@
|
|||
#include "lluiconstants.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewertexturelist.h" // LLUIImageList
|
||||
#include "llviewermenufile.h" // <FS:PP> Ban and access lists export/import
|
||||
#include "llviewermessage.h"
|
||||
#include "llviewerparcelmgr.h"
|
||||
#include "llviewerregion.h"
|
||||
|
|
@ -2680,6 +2681,17 @@ bool LLPanelLandAccess::postBuild()
|
|||
mBtnRemoveBanned = getChild<LLButton>("remove_banned");
|
||||
mBtnRemoveBanned->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickRemoveBanned, this));
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
mBtnExportAccess = getChild<LLButton>("export_allowed");
|
||||
mBtnExportAccess->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickExportAccess, this));
|
||||
mBtnExportBanned = getChild<LLButton>("export_banned");
|
||||
mBtnExportBanned->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickExportBanned, this));
|
||||
mBtnImportAccess = getChild<LLButton>("import_allowed");
|
||||
mBtnImportAccess->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickImportAccess, this));
|
||||
mBtnImportBanned = getChild<LLButton>("import_banned");
|
||||
mBtnImportBanned->setCommitCallback(boost::bind(&LLPanelLandAccess::onClickImportBanned, this));
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
mListAccess = getChild<LLNameListCtrl>("AccessList");
|
||||
if (mListAccess)
|
||||
{
|
||||
|
|
@ -2926,6 +2938,13 @@ void LLPanelLandAccess::refresh_ui()
|
|||
mBtnAddBanned->setEnabled(false);
|
||||
mBtnRemoveBanned->setEnabled(false);
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
mBtnExportAccess->setEnabled(false);
|
||||
mBtnExportBanned->setEnabled(false);
|
||||
mBtnImportAccess->setEnabled(false);
|
||||
mBtnImportBanned->setEnabled(false);
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
LLParcel *parcel = mParcel->getParcel();
|
||||
if (parcel && !gDisconnected)
|
||||
{
|
||||
|
|
@ -2995,6 +3014,14 @@ void LLPanelLandAccess::refresh_ui()
|
|||
mBtnAddBanned->setEnabled(can_manage_banned && banned_list_count < PARCEL_MAX_ACCESS_LIST);
|
||||
has_selected = (mListBanned && mListBanned->getSelectionInterface()->getFirstSelectedIndex() >= 0);
|
||||
mBtnRemoveBanned->setEnabled(can_manage_banned && has_selected);
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
mBtnExportAccess->setEnabled(can_manage_allowed && allowed_list_count > 0);
|
||||
mBtnExportBanned->setEnabled(can_manage_banned && banned_list_count > 0);
|
||||
mBtnImportAccess->setEnabled(can_manage_allowed && allowed_list_count < PARCEL_MAX_ACCESS_LIST);
|
||||
mBtnImportBanned->setEnabled(can_manage_banned && banned_list_count < PARCEL_MAX_ACCESS_LIST);
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3268,6 +3295,166 @@ void LLPanelLandAccess::onClickRemoveBanned()
|
|||
}
|
||||
}
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
void LLPanelLandAccess::onClickExportList(LLNameListCtrl* list, const std::string& filename)
|
||||
{
|
||||
if (!list || list->getItemCount() == 0)
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("ListEmpty");
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelLandAccess::exportListCallback, this, list, _1), LLFilePicker::FFSAVE_CSV, filename);
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::onClickExportAccess()
|
||||
{
|
||||
onClickExportList(mListAccess, "land_access_list.csv");
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::onClickExportBanned()
|
||||
{
|
||||
onClickExportList(mListBanned, "land_banned_list.csv");
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::exportListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames)
|
||||
{
|
||||
if (filenames.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename = filenames[0];
|
||||
std::ofstream file(filename.c_str());
|
||||
if (!file.is_open())
|
||||
{
|
||||
LLNotificationsUtil::add("ExportFailed");
|
||||
return;
|
||||
}
|
||||
|
||||
file << "Name,UUID\n";
|
||||
std::vector<LLScrollListItem*> items = list->getAllData();
|
||||
for (std::vector<LLScrollListItem*>::iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
LLScrollListItem* item = *it;
|
||||
if (item)
|
||||
{
|
||||
const LLUUID& id = item->getUUID();
|
||||
std::string name = item->getColumn(0)->getValue().asString();
|
||||
file << name << "," << id.asString() << "\n";
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
LLSD args;
|
||||
args["FILENAME"] = filename;
|
||||
LLNotificationsUtil::add("ExportFinished", args);
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::onClickImportList(LLNameListCtrl* list)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("ListEmpty");
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelLandAccess::importListCallback, this, list, _1), LLFilePicker::FFLOAD_ALL, false);
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::onClickImportAccess()
|
||||
{
|
||||
onClickImportList(mListAccess);
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::onClickImportBanned()
|
||||
{
|
||||
onClickImportList(mListBanned);
|
||||
}
|
||||
|
||||
void LLPanelLandAccess::importListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames)
|
||||
{
|
||||
if (filenames.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename = filenames[0];
|
||||
|
||||
std::ifstream file(filename.c_str());
|
||||
if (!file.is_open())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLParcel* parcel = mParcel->getParcel();
|
||||
if (!parcel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uuid_vec_t uuids;
|
||||
LLSD csvData = ll_sd_from_csv(file);
|
||||
file.close();
|
||||
|
||||
for (const auto& entry : llsd::inArray(csvData))
|
||||
{
|
||||
if (entry.has("UUID"))
|
||||
{
|
||||
LLUUID id{ entry["UUID"].asUUID() };
|
||||
if (id.notNull())
|
||||
uuids.push_back(std::move(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (uuids.empty())
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("NoValidUUIDs");
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string listname = list->getName();
|
||||
S32 max_entries = PARCEL_MAX_ACCESS_LIST;
|
||||
S32 current_count = list->getItemCount();
|
||||
S32 available_slots = max_entries - current_count;
|
||||
|
||||
if (uuids.size() > available_slots)
|
||||
{
|
||||
LLSD args;
|
||||
args["MAX"] = llformat("%d", available_slots);
|
||||
args["COUNT"] = llformat("%d", uuids.size());
|
||||
args["MESSAGE"] = LLTrans::getString("ImportListTooLarge", args).c_str();
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const LLUUID& uuid : uuids)
|
||||
{
|
||||
if (listname == "BannedList")
|
||||
{
|
||||
parcel->addToBanList(uuid, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
parcel->addToAccessList(uuid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
U32 flags = (listname == "BannedList") ? AL_BAN : AL_ACCESS;
|
||||
LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(flags);
|
||||
refresh();
|
||||
|
||||
LLSD args;
|
||||
args["COUNT"] = llformat("%d", uuids.size());
|
||||
args["MESSAGE"] = LLTrans::getString("ImportSuccessful", args).c_str();
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
}
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPanelLandCovenant
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -405,6 +405,17 @@ public:
|
|||
void callbackAvatarCBBanned2(const uuid_vec_t& ids, S32 duration);
|
||||
void callbackAvatarCBAccess(const uuid_vec_t& ids);
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
void onClickExportAccess();
|
||||
void onClickExportBanned();
|
||||
void onClickExportList(LLNameListCtrl* list, const std::string& filename);
|
||||
void exportListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames);
|
||||
void onClickImportAccess();
|
||||
void onClickImportBanned();
|
||||
void onClickImportList(LLNameListCtrl* list);
|
||||
void importListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames);
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
protected:
|
||||
LLNameListCtrl* mListAccess;
|
||||
LLNameListCtrl* mListBanned;
|
||||
|
|
@ -423,6 +434,13 @@ protected:
|
|||
LLButton* mBtnAddBanned = nullptr;
|
||||
LLButton* mBtnRemoveBanned = nullptr;
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
LLButton* mBtnExportAccess = nullptr;
|
||||
LLButton* mBtnExportBanned = nullptr;
|
||||
LLButton* mBtnImportAccess = nullptr;
|
||||
LLButton* mBtnImportBanned = nullptr;
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
LLSafeHandle<LLParcelSelection>& mParcel;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3509,6 +3509,10 @@ bool LLPanelEstateAccess::postBuild()
|
|||
childSetAction("add_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddAllowedAgent, this));
|
||||
childSetAction("remove_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedAgent, this));
|
||||
childSetAction("copy_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedList, this));
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
childSetAction("export_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickExportAllowedList, this));
|
||||
childSetAction("import_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickImportAllowedList, this));
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
getChild<LLUICtrl>("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
|
||||
LLNameListCtrl* group_name_list = getChild<LLNameListCtrl>("allowed_group_name_list");
|
||||
|
|
@ -3522,6 +3526,10 @@ bool LLPanelEstateAccess::postBuild()
|
|||
getChild<LLUICtrl>("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onClickAddAllowedGroup, this));
|
||||
childSetAction("remove_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedGroup, this));
|
||||
childSetAction("copy_allowed_group_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedGroupList, this));
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
childSetAction("export_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickExportAllowedGroupList, this));
|
||||
childSetAction("import_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickImportAllowedGroupList, this));
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
getChild<LLUICtrl>("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
|
||||
LLNameListCtrl* banned_name_list = getChild<LLNameListCtrl>("banned_avatar_name_list");
|
||||
|
|
@ -3535,6 +3543,10 @@ bool LLPanelEstateAccess::postBuild()
|
|||
childSetAction("add_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddBannedAgent, this));
|
||||
childSetAction("remove_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveBannedAgent, this));
|
||||
childSetAction("copy_banned_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyBannedList, this));
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
childSetAction("export_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickExportBannedList, this));
|
||||
childSetAction("import_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickImportBannedList, this));
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
getChild<LLUICtrl>("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
|
||||
LLNameListCtrl* manager_name_list = getChild<LLNameListCtrl>("estate_manager_name_list");
|
||||
|
|
@ -3546,6 +3558,10 @@ bool LLPanelEstateAccess::postBuild()
|
|||
|
||||
childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickAddEstateManager, this));
|
||||
childSetAction("remove_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveEstateManager, this));
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
childSetAction("export_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickExportEstateManagerList, this));
|
||||
childSetAction("import_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickImportEstateManagerList, this));
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3590,6 +3606,17 @@ void LLPanelEstateAccess::updateControls(LLViewerRegion* region)
|
|||
getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner));
|
||||
estateManagers->setEnabled(god || owner);
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
getChildView("export_estate_manager_btn")->setEnabled(god || owner);
|
||||
getChildView("export_allowed_list_btn")->setEnabled(enable_cotrols);
|
||||
getChildView("export_allowed_group_btn")->setEnabled(enable_cotrols);
|
||||
getChildView("export_banned_avatar_btn")->setEnabled(enable_cotrols);
|
||||
getChildView("import_estate_manager_btn")->setEnabled(god || owner);
|
||||
getChildView("import_allowed_list_btn")->setEnabled(enable_cotrols);
|
||||
getChildView("import_allowed_group_btn")->setEnabled(enable_cotrols);
|
||||
getChildView("import_banned_avatar_btn")->setEnabled(enable_cotrols);
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
if (enable_cotrols != mCtrlsEnabled)
|
||||
{
|
||||
mCtrlsEnabled = enable_cotrols;
|
||||
|
|
@ -4609,3 +4636,203 @@ void LLPanelRegionEnvironment::onChkAllowOverride(bool value)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
void LLPanelEstateAccess::onClickExportList(LLNameListCtrl* list, const std::string& filename)
|
||||
{
|
||||
if (!list || list->getItemCount() == 0)
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("ListEmpty");
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelEstateAccess::exportListCallback, this, list, _1), LLFilePicker::FFSAVE_CSV, filename);
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickExportEstateManagerList()
|
||||
{
|
||||
onClickExportList(getChild<LLNameListCtrl>("estate_manager_name_list"), "estate_manager_list.csv");
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickExportAllowedList()
|
||||
{
|
||||
onClickExportList(getChild<LLNameListCtrl>("allowed_avatar_name_list"), "estate_allowed_residents.csv");
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickExportAllowedGroupList()
|
||||
{
|
||||
onClickExportList(getChild<LLNameListCtrl>("allowed_group_name_list"), "estate_allowed_groups.csv");
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickExportBannedList()
|
||||
{
|
||||
onClickExportList(getChild<LLNameListCtrl>("banned_avatar_name_list"), "estate_banned_residents.csv");
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::exportListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames)
|
||||
{
|
||||
if (filenames.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename = filenames[0];
|
||||
std::ofstream file(filename.c_str());
|
||||
if (!file.is_open())
|
||||
{
|
||||
LLNotificationsUtil::add("ExportFailed");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string listname = list->getName();
|
||||
|
||||
file << "Name,UUID";
|
||||
if (listname == "banned_avatar_name_list")
|
||||
{
|
||||
file << ",Last Login,Ban Date,Banned By";
|
||||
}
|
||||
file << "\n";
|
||||
|
||||
std::vector<LLScrollListItem*> items = list->getAllData();
|
||||
for (std::vector<LLScrollListItem*>::iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
LLScrollListItem* item = *it;
|
||||
if (item)
|
||||
{
|
||||
const LLUUID& id = item->getUUID();
|
||||
std::string name = item->getColumn(0)->getValue().asString();
|
||||
file << name << "," << id.asString();
|
||||
if (listname == "banned_avatar_name_list")
|
||||
{
|
||||
std::string last_login = item->getColumn(1)->getValue().asString();
|
||||
std::string ban_date = item->getColumn(2)->getValue().asString();
|
||||
std::string banned_by = item->getColumn(3)->getValue().asString();
|
||||
file << "," << last_login << "," << ban_date << "," << banned_by;
|
||||
}
|
||||
file << "\n";
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
LLSD args;
|
||||
args["FILENAME"] = filename;
|
||||
LLNotificationsUtil::add("ExportFinished", args);
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickImportList(LLNameListCtrl* list)
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("ListEmpty");
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelEstateAccess::importListCallback, this, list, _1), LLFilePicker::FFLOAD_ALL, false);
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickImportEstateManagerList()
|
||||
{
|
||||
onClickImportList(getChild<LLNameListCtrl>("estate_manager_name_list"));
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickImportAllowedList()
|
||||
{
|
||||
onClickImportList(getChild<LLNameListCtrl>("allowed_avatar_name_list"));
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickImportAllowedGroupList()
|
||||
{
|
||||
onClickImportList(getChild<LLNameListCtrl>("allowed_group_name_list"));
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::onClickImportBannedList()
|
||||
{
|
||||
onClickImportList(getChild<LLNameListCtrl>("banned_avatar_name_list"));
|
||||
}
|
||||
|
||||
void LLPanelEstateAccess::importListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames)
|
||||
{
|
||||
if (filenames.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename = filenames[0];
|
||||
|
||||
std::ifstream file(filename.c_str());
|
||||
if (!file.is_open())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uuid_vec_t uuids;
|
||||
LLSD csvData = ll_sd_from_csv(file);
|
||||
file.close();
|
||||
|
||||
for (const auto& entry : llsd::inArray(csvData))
|
||||
{
|
||||
if (entry.has("UUID"))
|
||||
{
|
||||
LLUUID id{ entry["UUID"].asUUID() };
|
||||
if (id.notNull())
|
||||
uuids.push_back(std::move(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (uuids.empty())
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("NoValidUUIDs");
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string listname = list->getName();
|
||||
S32 max_entries = list->getMaxItemCount();
|
||||
S32 current_count = list->getItemCount();
|
||||
S32 available_slots = max_entries - current_count;
|
||||
|
||||
if (uuids.size() > available_slots)
|
||||
{
|
||||
LLSD args;
|
||||
args["MAX"] = llformat("%d", available_slots);
|
||||
args["COUNT"] = llformat("%d", uuids.size());
|
||||
args["MESSAGE"] = LLTrans::getString("ImportListTooLarge", args).c_str();
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const LLUUID& uuid : uuids)
|
||||
{
|
||||
if (listname == "banned_avatar_name_list")
|
||||
{
|
||||
sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD, uuid);
|
||||
}
|
||||
else if (listname == "estate_manager_name_list")
|
||||
{
|
||||
sendEstateAccessDelta(ESTATE_ACCESS_MANAGER_ADD, uuid);
|
||||
}
|
||||
else if (listname == "allowed_avatar_name_list")
|
||||
{
|
||||
sendEstateAccessDelta(ESTATE_ACCESS_ALLOWED_AGENT_ADD, uuid);
|
||||
}
|
||||
else if (listname == "allowed_group_name_list")
|
||||
{
|
||||
sendEstateAccessDelta(ESTATE_ACCESS_ALLOWED_GROUP_ADD, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
|
||||
if (panel)
|
||||
{
|
||||
panel->setPendingUpdate(true);
|
||||
}
|
||||
|
||||
LLSD args;
|
||||
args["COUNT"] = llformat("%d", uuids.size());
|
||||
args["MESSAGE"] = LLTrans::getString("ImportSuccessful", args).c_str();
|
||||
LLNotificationsUtil::add("GenericAlert", args);
|
||||
}
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
|
|
|||
|
|
@ -508,6 +508,21 @@ public:
|
|||
// <FS:Ansariel> Moved to public
|
||||
static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
|
||||
|
||||
// <FS:PP> Ban and access lists export/import
|
||||
void onClickExportEstateManagerList();
|
||||
void onClickExportAllowedList();
|
||||
void onClickExportAllowedGroupList();
|
||||
void onClickExportBannedList();
|
||||
void onClickExportList(LLNameListCtrl* list, const std::string& filename);
|
||||
void exportListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames);
|
||||
void onClickImportEstateManagerList();
|
||||
void onClickImportAllowedList();
|
||||
void onClickImportAllowedGroupList();
|
||||
void onClickImportBannedList();
|
||||
void onClickImportList(LLNameListCtrl* list);
|
||||
void importListCallback(LLNameListCtrl* list, const std::vector<std::string>& filenames);
|
||||
// </FS:PP> Ban and access lists export/import
|
||||
|
||||
private:
|
||||
void onClickAddAllowedAgent();
|
||||
void onClickRemoveAllowedAgent();
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ static void touch_default_probe(LLReflectionMap* probe)
|
|||
}
|
||||
}
|
||||
|
||||
LLHeroProbeManager::LLHeroProbeManager():mMirrorNormal(0,0,1) // <FS:Beq/> [FIRE-35007][#3331] mirrors not working after relog. make sure the mirror normal is not zero length
|
||||
LLHeroProbeManager::LLHeroProbeManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -540,10 +540,22 @@ void LLHeroProbeManager::updateUniforms()
|
|||
void LLHeroProbeManager::renderDebug()
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
// <FS:Beq> Add a bit more metadata to the probe debug view
|
||||
std::map<LLSpatialGroup*, int> groupCount;
|
||||
std::map<LLViewerObject*, int> objCount;
|
||||
std::map<F32*, int> locCount;
|
||||
|
||||
for (LLReflectionMap* probe : mProbes)
|
||||
{
|
||||
if (!probe->isRelevant()) continue;
|
||||
groupCount[ probe->mGroup ]++;
|
||||
objCount[ probe->mViewerObject ]++;
|
||||
locCount[ probe->mOrigin.getF32ptr() ]++;
|
||||
}
|
||||
// </FS:Beq>
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
renderReflectionProbe(probe);
|
||||
renderReflectionProbe(probe, groupCount, objCount, locCount); // <FS:Beq/> Add a bit more metadata to the probe debug view
|
||||
}
|
||||
|
||||
gDebugProgram.unbind();
|
||||
|
|
@ -658,7 +670,7 @@ bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep)
|
|||
// Probe isn't in our list for consideration. Add it.
|
||||
mHeroVOList.push_back(drawablep);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -680,6 +692,6 @@ void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep)
|
|||
mDefaultProbe->mViewerObject = nullptr;
|
||||
}
|
||||
}
|
||||
// </FS:Beq>
|
||||
// </FS:Beq>
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,6 +254,16 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
|
|||
}
|
||||
|
||||
std::string mfa_hash = gSavedSettings.getString("MFAHash"); //non-persistent to enable testing
|
||||
// <FS:Beq> add some debug output for mfa_hash
|
||||
if (mfa_hash.empty())
|
||||
{
|
||||
LL_DEBUGS("MFA") << "MFA hash from settings is empty (expected)" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("MFA") << "MFA hash from settings is set to: " << mfa_hash << LL_ENDL;
|
||||
}
|
||||
// </FS:Beq>
|
||||
std::string grid(LLGridManager::getInstance()->getGridId());
|
||||
std::string user_id = user_credential->userID();
|
||||
if (gSecAPIHandler)
|
||||
|
|
@ -266,9 +276,20 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
|
|||
{
|
||||
mfa_hash = data_map[user_id].asString();
|
||||
}
|
||||
// <FS:Beq> add some debug output for mfa_hash
|
||||
if (mfa_hash.empty())
|
||||
{
|
||||
LL_DEBUGS("MFA") << "MFA hash from secuire store is empty" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("MFA") << "MFA hash is from secure store set to: " << mfa_hash << LL_ENDL;
|
||||
}
|
||||
// </FS:Beq>
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("MFA") << "MFA hash written to protected map" << LL_ENDL; // <FS:Beq/> add some debug output for mfa_hash
|
||||
// SL-16888 the mfa_hash is being overridden for testing so save it for consistency for future login requests
|
||||
gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, mfa_hash);
|
||||
}
|
||||
|
|
@ -277,8 +298,8 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
|
|||
{
|
||||
LL_WARNS() << "unable to access protected store for mfa_hash" << LL_ENDL;
|
||||
}
|
||||
|
||||
request_params["mfa_hash"] = mfa_hash;
|
||||
LL_DEBUGS("MFA") << "mfa_hash in request params is set to: " << request_params["mfa_hash"] << LL_ENDL; // <FS:Beq/> add some debug output for mfa_hash
|
||||
|
||||
// Specify desired timeout/retry options
|
||||
LLSD http_params;
|
||||
|
|
@ -622,17 +643,47 @@ void LLLoginInstance::saveMFAHash(LLSD const& response)
|
|||
{
|
||||
std::string grid(LLGridManager::getInstance()->getGridId());
|
||||
std::string user_id(LLStartUp::getUserId());
|
||||
|
||||
// Only save mfa_hash for future logins if the user wants their info remembered.
|
||||
// <FS:Beq> add some debug output for mfa_hash
|
||||
LL_DEBUGS("MFA") << "In saveMFAHagsh, grid: " << grid
|
||||
<< ", user_id: " << user_id
|
||||
<< ", remember user: " << (gSavedSettings.getBOOL("RememberUser")? "true" : "false")
|
||||
<< ", saveMFA: " << (LLLoginInstance::getInstance()->saveMFA()? "true" : "false")
|
||||
<< LL_ENDL;
|
||||
if (response.has("mfa_hash"))
|
||||
{
|
||||
LL_DEBUGS("MFA") << "In saveMFAHash, mfa_hash: " << response["mfa_hash"].asString()
|
||||
<< LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("MFA") << "In saveMFAHash, no mfa_hash in response"
|
||||
<< LL_ENDL;
|
||||
}
|
||||
// </FS:Beq>
|
||||
if (response.has("mfa_hash") && gSavedSettings.getBOOL("RememberUser") && LLLoginInstance::getInstance()->saveMFA())
|
||||
{
|
||||
// <FS:Beq> add some debug output for mfa_hash
|
||||
LL_DEBUGS("MFA") << "In saveMFAHash, mfa_hash: " << response["mfa_hash"].asString()
|
||||
<< LL_ENDL;
|
||||
// </FS:Beq>
|
||||
gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]);
|
||||
}
|
||||
else if (!LLLoginInstance::getInstance()->saveMFA())
|
||||
{
|
||||
// <FS:Beq> add some debug output for mfa_hash
|
||||
LL_DEBUGS("MFA") << "In saveMFAHash, removing mfa_hash from protected map"
|
||||
<< LL_ENDL;
|
||||
|
||||
// User does not want to save mfa_hash, remove it from the protected map
|
||||
gSecAPIHandler->removeFromProtectedMap("mfa_hash", grid, user_id);
|
||||
}
|
||||
|
||||
// TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically
|
||||
// <FS:Beq> add some debug output for mfa_hash
|
||||
LL_DEBUGS("MFA") << "In saveMFAHash, syncing protected map"
|
||||
<< LL_ENDL;
|
||||
|
||||
gSecAPIHandler->syncProtectedMap();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -546,6 +546,13 @@ bool LLMaterialEditor::postBuild()
|
|||
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
|
||||
}
|
||||
|
||||
// <FS:TJ> [FIRE-35544] For disabling texture previews for no-mod materials
|
||||
mBaseColorTextureCtrl->setIsPreviewDisabled(true);
|
||||
mMetallicTextureCtrl->setIsPreviewDisabled(true);
|
||||
mEmissiveTextureCtrl->setIsPreviewDisabled(true);
|
||||
mNormalTextureCtrl->setIsPreviewDisabled(true);
|
||||
// </FS:TJ>
|
||||
|
||||
// Todo:
|
||||
// Disable/enable setCanApplyImmediately() based on
|
||||
// working from inventory, upload or editing inworld
|
||||
|
|
|
|||
|
|
@ -1761,7 +1761,8 @@ bool LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
LLMenuItemCallGL::Params p;
|
||||
p.name = llformat("Profile Item %d", itAgent - mClosestAgentsToCursor.begin());
|
||||
|
||||
LLAvatarName avName; const LLUUID& idAgent = *itAgent;
|
||||
LLAvatarName avName;
|
||||
const LLUUID& idAgent = *itAgent;
|
||||
if (LLAvatarNameCache::get(idAgent, &avName))
|
||||
{
|
||||
p.label = avName.getCompleteName();
|
||||
|
|
@ -1778,7 +1779,7 @@ bool LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
}
|
||||
mAvatarNameCacheConnections.erase(it);
|
||||
}
|
||||
mAvatarNameCacheConnections[idAgent] = LLAvatarNameCache::get(idAgent, boost::bind(&LLNetMap::setAvatarProfileLabel, this, _1, _2, p.name.getValue()));
|
||||
mAvatarNameCacheConnections.try_emplace(idAgent, LLAvatarNameCache::get(idAgent, boost::bind(&LLNetMap::setAvatarProfileLabel, this, _1, _2, p.name.getValue())));
|
||||
}
|
||||
p.on_click.function = boost::bind(&LLAvatarActions::showProfile, _2);
|
||||
p.on_click.parameter = idAgent;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
|
|||
mTooManySelected(),
|
||||
mCloseCallback(NULL),
|
||||
mCloseCallbackUserData(NULL),
|
||||
mAvatarNameCacheConnection(),
|
||||
//mAvatarNameCacheConnection(), // <FS:Ansariel> Fix avatar name loading
|
||||
mRoleNames(NULL),
|
||||
mOwnerWarning(),
|
||||
mAlreadyInGroup(),
|
||||
|
|
@ -74,10 +74,19 @@ LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
|
|||
|
||||
LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl()
|
||||
{
|
||||
if (mAvatarNameCacheConnection.connected())
|
||||
// <FS:Ansariel> Fix avatar name loading
|
||||
//if (mAvatarNameCacheConnection.connected())
|
||||
//{
|
||||
// mAvatarNameCacheConnection.disconnect();
|
||||
//}
|
||||
for (auto& [id, connection] : mAvatarNameCacheConnections)
|
||||
{
|
||||
mAvatarNameCacheConnection.disconnect();
|
||||
if (connection.connected())
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
mAvatarNameCacheConnections.clear();
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
|
||||
void LLPanelGroupBulkImpl::callbackClickAdd(LLPanelGroupBulk* panelp)
|
||||
|
|
@ -134,26 +143,51 @@ void LLPanelGroupBulkImpl::addUsers(const uuid_vec_t& agent_ids)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (mAvatarNameCacheConnection.connected())
|
||||
// <FS:Ansariel> Fix avatar name loading
|
||||
//if (mAvatarNameCacheConnection.connected())
|
||||
//{
|
||||
// mAvatarNameCacheConnection.disconnect();
|
||||
//}
|
||||
//// *TODO : Add a callback per avatar name being fetched.
|
||||
//mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id,
|
||||
// [&](const LLUUID& agent_id, const LLAvatarName& av_name)
|
||||
// {
|
||||
// onAvatarNameCache(agent_id, av_name);
|
||||
// });
|
||||
|
||||
if (auto found = mAvatarNameCacheConnections.find(agent_id); found != mAvatarNameCacheConnections.end())
|
||||
{
|
||||
mAvatarNameCacheConnection.disconnect();
|
||||
if (found->second.connected())
|
||||
found->second.disconnect();
|
||||
|
||||
mAvatarNameCacheConnections.erase(found);
|
||||
}
|
||||
// *TODO : Add a callback per avatar name being fetched.
|
||||
mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id,
|
||||
|
||||
mAvatarNameCacheConnections.try_emplace(agent_id, LLAvatarNameCache::get(agent_id,
|
||||
[&](const LLUUID& agent_id, const LLAvatarName& av_name)
|
||||
{
|
||||
onAvatarNameCache(agent_id, av_name);
|
||||
});
|
||||
}));
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelGroupBulkImpl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
|
||||
{
|
||||
if (mAvatarNameCacheConnection.connected())
|
||||
// <FS:Ansariel> Fix avatar name loading
|
||||
//if (mAvatarNameCacheConnection.connected())
|
||||
//{
|
||||
// mAvatarNameCacheConnection.disconnect();
|
||||
//}
|
||||
if (auto found = mAvatarNameCacheConnections.find(agent_id); found != mAvatarNameCacheConnections.end())
|
||||
{
|
||||
mAvatarNameCacheConnection.disconnect();
|
||||
if (found->second.connected())
|
||||
found->second.disconnect();
|
||||
|
||||
mAvatarNameCacheConnections.erase(found);
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
std::vector<std::string> names;
|
||||
uuid_vec_t agent_ids;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,9 @@ public:
|
|||
|
||||
void (*mCloseCallback)(void* data);
|
||||
void* mCloseCallbackUserData;
|
||||
boost::signals2::connection mAvatarNameCacheConnection;
|
||||
// <FS:Ansariel> Fix avatar name loading
|
||||
//boost::signals2::connection mAvatarNameCacheConnection;
|
||||
std::map<LLUUID, boost::signals2::connection> mAvatarNameCacheConnections;
|
||||
|
||||
// The following are for the LLPanelGroupInvite subclass only.
|
||||
// These aren't needed for LLPanelGroupBulkBan, but if we have to add another
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ private:
|
|||
S32 sortMembersList(S32,const LLScrollListItem*,const LLScrollListItem*);
|
||||
|
||||
LLGroupMgrGroupData::member_list_t::iterator mMemberProgress;
|
||||
typedef std::unordered_map<LLUUID, boost::signals2::connection, FSUUIDHash> avatar_name_cache_connection_map_t;
|
||||
typedef std::unordered_map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
|
||||
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
|
||||
|
||||
bool mPendingMemberUpdate;
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ namespace LLPerfStats
|
|||
static void updateMeanFrameTime(U64 tot_frame_time_raw);
|
||||
// StatsArray is a uint64_t for each possible statistic type.
|
||||
using StatsArray = std::array<uint64_t, static_cast<size_t>(LLPerfStats::StatType_t::STATS_COUNT)>;
|
||||
using StatsMap = std::unordered_map<LLUUID, StatsArray, FSUUIDHash>; // <FS:Beq/>
|
||||
using StatsMap = std::unordered_map<LLUUID, StatsArray>; // <FS:Beq/>
|
||||
using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>;
|
||||
using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>;
|
||||
|
||||
|
|
|
|||
|
|
@ -291,25 +291,54 @@ bool LLReflectionMap::isActive() const
|
|||
|
||||
bool LLReflectionMap::isRelevant() const
|
||||
{
|
||||
static LLCachedControl<S32> RenderReflectionProbeLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
|
||||
static LLCachedControl<S32> sRenderReflectionProbeLevel(gSavedSettings, "RenderReflectionProbeLevel", (S32)ProbeLevel::FULL_SCENE_WITH_AUTO);
|
||||
// <FS:Beq> [FIRE-35070] Correct isRelevant() logic for coverage == None and refactor to make it less fragile
|
||||
// if (mViewerObject && RenderReflectionProbeLevel > 0)
|
||||
// { // not an automatic probe
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if (mViewerObject && RenderReflectionProbeLevel > 0)
|
||||
{ // not an automatic probe
|
||||
// if (RenderReflectionProbeLevel == 3)
|
||||
// { // all automatics are relevant
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if (RenderReflectionProbeLevel == 2)
|
||||
// { // terrain and water only, ignore probes that have a group
|
||||
// return !mGroup;
|
||||
// }
|
||||
|
||||
// // no automatic probes, yes manual probes
|
||||
// return mViewerObject != nullptr;
|
||||
// Implied logic: a probe has a group if it is either a manual or automatic, it has an object if it is manual
|
||||
// hasGroup hasObject (in parenthesis means condition not checked)
|
||||
// Manual true true
|
||||
// Terrain/Water false (false)
|
||||
// Automatic true false
|
||||
|
||||
const bool is_manual = mViewerObject != nullptr ;
|
||||
const bool is_automatic = mGroup != nullptr && !is_manual;
|
||||
const bool is_terrain = mGroup == nullptr;
|
||||
switch (sRenderReflectionProbeLevel)
|
||||
{
|
||||
case (S32)ProbeLevel::NONE:
|
||||
// no probes are relevant
|
||||
return false;
|
||||
case (S32)ProbeLevel::MANUAL_ONLY:
|
||||
// only manual probes are relevant
|
||||
return is_manual;
|
||||
case (S32)ProbeLevel::MANUAL_AND_TERRAIN:
|
||||
// manual probes and terrain/water probes are relevant
|
||||
return !is_automatic;
|
||||
case (S32)ProbeLevel::FULL_SCENE_WITH_AUTO:
|
||||
// all probes are relevant
|
||||
return true;
|
||||
default:
|
||||
LL_WARNS() << "Unknown RenderReflectionProbeLevel: " << (S32)sRenderReflectionProbeLevel()
|
||||
<< " - returning false" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RenderReflectionProbeLevel == 3)
|
||||
{ // all automatics are relevant
|
||||
return true;
|
||||
}
|
||||
|
||||
if (RenderReflectionProbeLevel == 2)
|
||||
{ // terrain and water only, ignore probes that have a group
|
||||
return !mGroup;
|
||||
}
|
||||
|
||||
// no automatic probes, yes manual probes
|
||||
return mViewerObject != nullptr;
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,13 @@ public:
|
|||
IRRADIANCE,
|
||||
REFLECTION
|
||||
};
|
||||
enum class ProbeLevel
|
||||
{
|
||||
NONE = 0,
|
||||
MANUAL_ONLY,
|
||||
MANUAL_AND_TERRAIN,
|
||||
FULL_SCENE_WITH_AUTO
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
LLReflectionMap();
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ void LLReflectionMapManager::update()
|
|||
}
|
||||
|
||||
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
|
||||
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
|
||||
// static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); // <FS:Beq/> No longer required use the pipeline cached version instead
|
||||
static LLCachedControl<U32> sReflectionProbeCount(gSavedSettings, "RenderReflectionProbeCount", 256U);
|
||||
static LLCachedControl<S32> sProbeDynamicAllocation(gSavedSettings, "RenderReflectionProbeDynamicAllocation", -1);
|
||||
mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f);
|
||||
|
|
@ -232,15 +232,15 @@ void LLReflectionMapManager::update()
|
|||
U32 probe_count_temp = mDynamicProbeCount;
|
||||
if (sProbeDynamicAllocation > -1)
|
||||
{
|
||||
if (sLevel == 0)
|
||||
if (LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::NONE)// <FS:Beq/> No longer required use the pipeline cached version instead
|
||||
{
|
||||
mDynamicProbeCount = 1;
|
||||
}
|
||||
else if (sLevel == 1)
|
||||
else if (LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::MANUAL_ONLY)// <FS:Beq/> No longer required use the pipeline cached version instead
|
||||
{
|
||||
mDynamicProbeCount = (U32)mProbes.size();
|
||||
}
|
||||
else if (sLevel == 2)
|
||||
else if (LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::MANUAL_AND_TERRAIN)// <FS:Beq/> No longer required use the pipeline cached version instead
|
||||
{
|
||||
mDynamicProbeCount = llmax((U32)mProbes.size(), 128);
|
||||
}
|
||||
|
|
@ -456,13 +456,15 @@ void LLReflectionMapManager::update()
|
|||
{
|
||||
closestDynamic = probe;
|
||||
}
|
||||
|
||||
if (sLevel == 0)
|
||||
{
|
||||
// only update default probe when coverage is set to none
|
||||
llassert(probe == mDefaultProbe);
|
||||
break;
|
||||
}
|
||||
// <FS:Beq> This code is no longer required and this update loop should self-cleanse
|
||||
// However: There appears to be something that causes the reference count to be 2 for some probes that should no longer be in use.
|
||||
// if (sLevel == 0)
|
||||
// {
|
||||
// // only update default probe when coverage is set to none
|
||||
// llassert(probe == mDefaultProbe);
|
||||
// break;
|
||||
// }
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
if (realtime && closestDynamic != nullptr)
|
||||
|
|
@ -489,12 +491,12 @@ void LLReflectionMapManager::update()
|
|||
static LLCachedControl<F32> sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f);
|
||||
if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod)
|
||||
{
|
||||
if (sLevel == 0)
|
||||
if (LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::NONE) // <FS:Beq/> No longer required use the pipeline cached version instead
|
||||
{ // when probes are disabled don't update the default probe more often than the prescribed update period
|
||||
oldestProbe = nullptr;
|
||||
}
|
||||
}
|
||||
else if (sLevel > 0)
|
||||
else if (LLPipeline::sReflectionProbeLevel > (S32)LLReflectionMap::ProbeLevel::NONE) // <FS:Beq/> No longer required use the pipeline cached version instead
|
||||
{ // when probes are enabled don't update the default probe less often than the prescribed update period
|
||||
oldestProbe = mDefaultProbe;
|
||||
}
|
||||
|
|
@ -628,6 +630,12 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma
|
|||
|
||||
LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* group)
|
||||
{
|
||||
// <FS:Beq> [FIRE-35070] Don't register probes if we're not using them
|
||||
if( LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::NONE)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
// </FS:Beq>
|
||||
if (!group)
|
||||
{
|
||||
return nullptr;
|
||||
|
|
@ -648,7 +656,10 @@ LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* gr
|
|||
|
||||
LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vobj)
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
// <FS:Beq> [FIRE-35070] Don't register manual probes if we're not using them
|
||||
// if (!LLPipeline::sReflectionProbesEnabled)
|
||||
if (LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::NONE)
|
||||
// </FS:Beq>
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -1315,7 +1326,7 @@ void LLReflectionMapManager::setUniforms()
|
|||
}
|
||||
|
||||
|
||||
void renderReflectionProbe(LLReflectionMap* probe)
|
||||
void renderReflectionProbe(LLReflectionMap* probe, std::map<LLSpatialGroup*, int> groupCount, std::map<LLViewerObject*, int> objCount, std::map<F32*, int> locCount)
|
||||
{
|
||||
if (probe->isRelevant())
|
||||
{
|
||||
|
|
@ -1338,7 +1349,7 @@ void renderReflectionProbe(LLReflectionMap* probe)
|
|||
gGL.end();
|
||||
gGL.flush();
|
||||
|
||||
gGL.diffuseColor4f(1, 1, 0, 1);
|
||||
gGL.diffuseColor4f(0, 1, 1, 1);
|
||||
gGL.begin(gGL.LINES);
|
||||
for (auto& neighbor : probe->mNeighbors)
|
||||
{
|
||||
|
|
@ -1350,6 +1361,44 @@ void renderReflectionProbe(LLReflectionMap* probe)
|
|||
}
|
||||
gGL.end();
|
||||
gGL.flush();
|
||||
|
||||
// --- New: draw a point at the probe origin color-coded by type ---
|
||||
bool dupByGroup = (probe->mGroup && groupCount[ probe->mGroup ] > 1);
|
||||
bool dupByObject= (probe->mViewerObject && objCount[ probe->mViewerObject ] > 1);
|
||||
bool dupByLoc = ( locCount[ probe->mOrigin.getF32ptr()] > 1);
|
||||
|
||||
const bool is_manual = probe->mViewerObject != nullptr;
|
||||
const bool is_automatic = (probe->mGroup != nullptr) && !is_manual;
|
||||
// terrain/water is when neither manual nor automatic
|
||||
// const bool is_terrain = !is_manual && !is_automatic;
|
||||
|
||||
if (is_manual)
|
||||
{
|
||||
// red dot for manual probes
|
||||
gGL.diffuseColor4f(1.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
else if (is_automatic)
|
||||
{
|
||||
// blue dot for automatic probes
|
||||
gGL.diffuseColor4f(0.f, 0.f, 1.f, 1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// green dot for terrain/water probes
|
||||
gGL.diffuseColor4f(0.f, 1.f, 0.f, 1.f);
|
||||
}
|
||||
|
||||
// use a bigger dot if *any* duplicate condition is true
|
||||
const float normalSize = 9.f;
|
||||
const float bigSize = 18.f;
|
||||
float pointSize = (dupByGroup || dupByObject || dupByLoc)
|
||||
? bigSize
|
||||
: normalSize;
|
||||
glPointSize(pointSize);
|
||||
gGL.begin(gGL.POINTS);
|
||||
gGL.vertex3fv(po);
|
||||
gGL.end();
|
||||
gGL.flush();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
@ -1403,10 +1452,21 @@ void renderReflectionProbe(LLReflectionMap* probe)
|
|||
void LLReflectionMapManager::renderDebug()
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
|
||||
std::map<LLSpatialGroup*, int> groupCount;
|
||||
std::map<LLViewerObject*, int> objCount;
|
||||
std::map<F32*, int> locCount;
|
||||
|
||||
for (LLReflectionMap* probe : mProbes)
|
||||
{
|
||||
if (!probe->isRelevant()) continue;
|
||||
groupCount[ probe->mGroup ]++;
|
||||
objCount[ probe->mViewerObject ]++;
|
||||
locCount[ probe->mOrigin.getF32ptr() ]++;
|
||||
}
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
renderReflectionProbe(probe);
|
||||
renderReflectionProbe(probe, groupCount, objCount, locCount);
|
||||
}
|
||||
|
||||
gDebugProgram.unbind();
|
||||
|
|
|
|||
|
|
@ -43,8 +43,7 @@ class LLViewerObject;
|
|||
// reflection probe mininum scale
|
||||
#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f;
|
||||
|
||||
void renderReflectionProbe(LLReflectionMap* probe);
|
||||
|
||||
void renderReflectionProbe(LLReflectionMap* probe, std::map<LLSpatialGroup*, int> groupCount, std::map<LLViewerObject*, int> objCount, std::map<F32*, int> locCount); // <FS:Beq/> enhanced metadata render for probes
|
||||
class alignas(16) LLReflectionMapManager
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@
|
|||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
||||
#include "rlvactions.h"
|
||||
#include "rlvhandler.h"
|
||||
#include "rlvlocks.h"
|
||||
#include "rlvmodifiers.h"
|
||||
// [/RLVa:KB]
|
||||
// <FS:CR> Aurora Sim
|
||||
|
|
@ -5303,6 +5304,18 @@ void LLSelectMgr::sendDetach()
|
|||
return;
|
||||
}
|
||||
|
||||
// [RLVa:KB]
|
||||
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) )
|
||||
{
|
||||
LLObjectSelectionHandle hSelect = LLSelectMgr::getInstance()->getSelection();
|
||||
RlvSelectHasLockedAttach f;
|
||||
if ( (hSelect->isAttachment()) && (hSelect->getFirstRootNode(&f, false) != NULL) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
// [/RLVa:KB]
|
||||
|
||||
sendListToRegions(
|
||||
"ObjectDetach",
|
||||
packAgentAndSessionID,
|
||||
|
|
|
|||
|
|
@ -742,6 +742,10 @@ bool idle_startup()
|
|||
gSavedSettings.setBOOL("FSInternalShowNavbarFavoritesPanel", gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"));
|
||||
// </FS:Ansariel>
|
||||
|
||||
// <FS:Ansariel> Added to determine if toolbar gets hidden when empty
|
||||
if (gToolBarView)
|
||||
gToolBarView->setHideBottomOnEmpty(FSCommon::isLegacySkin());
|
||||
|
||||
if (LLFeatureManager::getInstance()->isSafe())
|
||||
{
|
||||
LLNotificationsUtil::add("DisplaySetToSafe");
|
||||
|
|
@ -2910,9 +2914,6 @@ bool idle_startup()
|
|||
|
||||
do_startup_frame();
|
||||
|
||||
// We're successfully logged in.
|
||||
gSavedSettings.setBOOL("FirstLoginThisInstall", false);
|
||||
|
||||
LLFloaterReg::showInitialVisibleInstances();
|
||||
|
||||
LLFloaterGridStatus::getInstance()->startGridStatusTimer();
|
||||
|
|
@ -3342,6 +3343,30 @@ bool idle_startup()
|
|||
|
||||
LLPerfStats::StatsRecorder::setAutotuneInit();
|
||||
|
||||
// Display Avatar Welcome Pack the first time a user logs in
|
||||
// (or clears their settings....)
|
||||
if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
|
||||
{
|
||||
LLFloater* avatar_welcome_pack_floater = LLFloaterReg::findInstance("avatar_welcome_pack");
|
||||
if (avatar_welcome_pack_floater != nullptr)
|
||||
{
|
||||
// There is a (very - 1 in ~50 times) hard to repro bug where the login
|
||||
// page is not hidden when the AWP floater is presented. This (agressive)
|
||||
// approach to always close it seems like the best fix for now.
|
||||
// <FS:Ansariel> [FS Login Panel]
|
||||
//LLPanelLogin::closePanel();
|
||||
FSPanelLogin::closePanel();
|
||||
// </FS:Ansariel> [FS Login Panel]
|
||||
|
||||
avatar_welcome_pack_floater->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
//// We're successfully logged in.
|
||||
// 2025-06 Moved lower down in the state machine so the Avatar Welcome Pack
|
||||
// floater display can be triggered correctly.
|
||||
gSavedSettings.setBOOL("FirstLoginThisInstall", false);
|
||||
|
||||
// <FS:Techwolf Lupindo> FIRE-6643 Display MOTD when login screens are disabled
|
||||
if (gSavedSettings.getBOOL("FSDisableLoginScreens"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1826,7 +1826,9 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
|
|||
mTextDisabledColor(p.text_disabled_color), // <FS:Zi> Add label/caption colors
|
||||
mLabel(p.label), // <FS:Zi> FIRE-34300 - Fix label not showing in texture picker floater title
|
||||
// <FS:Ansariel> Mask texture if desired
|
||||
mIsMasked(false)
|
||||
mIsMasked(false),
|
||||
// <FS:TJ> [FIRE-35544] For disabling texture previews for no-mod materials
|
||||
mIsPreviewDisabled(false)
|
||||
{
|
||||
mCaptionHeight = p.show_caption ? BTN_HEIGHT_SMALL : 0; // <FS:Zi> leave some room underneath the image for the caption
|
||||
// Default of defaults is white image for diff tex
|
||||
|
|
@ -1992,7 +1994,7 @@ void LLTextureCtrl::setEnabled( bool enabled )
|
|||
|
||||
// <FS:Ansariel> Texture preview mode
|
||||
//LLView::setEnabled( enabled );
|
||||
LLView::setEnabled( (enabled || getValue().asUUID().notNull()) );
|
||||
LLView::setEnabled(enabled || (getValue().asUUID().notNull() && !mIsPreviewDisabled));
|
||||
mOpenTexPreview = !enabled;
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
|
|
@ -2664,7 +2666,7 @@ void LLTextureCtrl::setValue( const LLSD& value )
|
|||
//setImageAssetID(value.asUUID());
|
||||
LLUUID uuid = value.asUUID();
|
||||
setImageAssetID(uuid);
|
||||
LLView::setEnabled( (!mOpenTexPreview || uuid.notNull()) );
|
||||
LLView::setEnabled(!mOpenTexPreview || (uuid.notNull() && !mIsPreviewDisabled));
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -264,6 +264,8 @@ public:
|
|||
|
||||
// <FS:Ansariel> Mask texture if desired
|
||||
void setIsMasked(bool masked) { mIsMasked = masked; }
|
||||
// <FS:TJ> [FIRE-35544] For disabling texture previews for no-mod materials
|
||||
void setIsPreviewDisabled(bool is_preview_disabled) { mIsPreviewDisabled = is_preview_disabled; }
|
||||
|
||||
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; updateLabelColor(); } // <FS:Zi> Add label/caption colors
|
||||
void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; updateLabelColor(); } // <FS:Zi> Add label/caption colors
|
||||
|
|
@ -315,6 +317,8 @@ private:
|
|||
|
||||
// <FS:Ansariel> Mask texture if desired
|
||||
bool mIsMasked;
|
||||
// <FS:TJ> [FIRE-35544] For disabling texture previews for no-mod materials
|
||||
bool mIsPreviewDisabled;
|
||||
|
||||
LLUIColor mTextEnabledColor; // <FS:Zi> Add label/caption colors
|
||||
LLUIColor mTextDisabledColor; // <FS:Zi> Add label/caption colors
|
||||
|
|
|
|||
|
|
@ -713,7 +713,7 @@ void LLGLTexMemBar::draw()
|
|||
//text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d ",
|
||||
text = llformat("Tex: %d Fetch: %d(%d) Pkts:%d(%d) CAC R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d FCA:%d ",
|
||||
// </FS:Ansariel>
|
||||
// <FS:minerjr> Fixed up the missing variables and converted 64bit size_t's to S32's to allow proper numbers to appear
|
||||
// <FS:minerjr> Fixed up the missing variables and converted 64bit size_t's to S32's to allow proper numbers to appear
|
||||
gTextureList.getNumImages(),
|
||||
LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(),
|
||||
LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount,
|
||||
|
|
@ -727,7 +727,7 @@ void LLGLTexMemBar::draw()
|
|||
(S32)gTextureList.mCreateTextureList.size(),
|
||||
(S32)gTextureList.mFastCacheList.size());
|
||||
// </FS:Ansariel>
|
||||
// </FS:minerjr>
|
||||
// </FS:minerjr>
|
||||
x_right = 550.0f;
|
||||
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0.f, (F32)(v_offset + line_height*3),
|
||||
text_color, LLFontGL::LEFT, LLFontGL::TOP,
|
||||
|
|
|
|||
|
|
@ -131,9 +131,6 @@ bool LLToolBarView::postBuild()
|
|||
// <FS:Ansariel> Member variable needed for console chat bottom offset
|
||||
mBottomChatStack = findChild<LLView>("bottom_chat_stack");
|
||||
|
||||
// <FS:Ansariel> Added to determine if toolbar gets hidden when empty
|
||||
mHideBottomOnEmpty = FSCommon::isLegacySkin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,9 +102,12 @@ public:
|
|||
bool isModified() const;
|
||||
|
||||
// <FS:Ansariel> Getters for member variables needed for console chat bottom offset
|
||||
LLView* getBottomChatStack() const { return mBottomChatStack; };
|
||||
LLView* getBottomChatStack() const { return mBottomChatStack; }
|
||||
// </FS:Ansariel>
|
||||
|
||||
// <FS:Ansariel> Added to determine if toolbar gets hidden when empty
|
||||
void setHideBottomOnEmpty(bool hideBottomOnEmpty) { mHideBottomOnEmpty = hideBottomOnEmpty; }
|
||||
|
||||
protected:
|
||||
friend class LLUICtrlFactory;
|
||||
LLToolBarView(const Params&);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@
|
|||
#include "llfloateraddpaymentmethod.h"
|
||||
#include "llfloaterauction.h"
|
||||
#include "llfloaterautoreplacesettings.h"
|
||||
#include "llfloateravatar.h"
|
||||
#include "llfloateravatarpicker.h"
|
||||
#include "llfloateravatarwelcomepack.h"
|
||||
//#include "llfloateravatarrendersettings.h" // <FS:Ansariel> [FS Persisted Avatar Render Settings]
|
||||
#include "llfloateravatartextures.h"
|
||||
#include "llfloaterbanduration.h"
|
||||
|
|
@ -399,8 +399,8 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
|
||||
LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>);
|
||||
LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
|
||||
LLFloaterReg::add("avatar", "floater_avatar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatar>);
|
||||
LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);
|
||||
LLFloaterReg::add("avatar_welcome_pack", "floater_avatar_welcome_pack.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarWelcomePack>);
|
||||
// <FS:Ansariel> [FS Persisted Avatar Render Settings]
|
||||
//LLFloaterReg::add("avatar_render_settings", "floater_avatar_render_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarRenderSettings>);
|
||||
LLFloaterReg::add("avatar_textures", "floater_avatar_textures.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarTextures>);
|
||||
|
|
|
|||
|
|
@ -3327,7 +3327,7 @@ void derenderObject(bool permanent)
|
|||
asset_type = LLAssetType::AT_OBJECT;
|
||||
}
|
||||
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(id, entry_name, region_name, asset_type, permanent, false);
|
||||
FSAssetBlacklist::getInstance()->addNewItemToBlacklist(id, entry_name, region_name, asset_type, FSAssetBlacklist::eBlacklistFlag::NONE, permanent, false);
|
||||
|
||||
if (permanent)
|
||||
{
|
||||
|
|
@ -3476,6 +3476,15 @@ void handle_object_tex_refresh(LLViewerObject* object, LLSelectNode* node)
|
|||
LLViewerTexture* spec_img = object->getTESpecularMap(i);
|
||||
faces_per_texture[spec_img->getID()].push_back(i);
|
||||
}
|
||||
|
||||
LLPointer<LLGLTFMaterial> mat = object->getTE(i)->getGLTFRenderMaterial();
|
||||
if (mat.notNull())
|
||||
{
|
||||
for (U32 j = 0; j < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++j)
|
||||
{
|
||||
faces_per_texture[mat->mTextureId[j]].push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map_t::iterator it;
|
||||
|
|
|
|||
|
|
@ -4700,6 +4700,38 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
|
|||
(void)sun_direction, (void)moon_direction, (void)phase;
|
||||
}
|
||||
|
||||
// <FS> Sound blacklist
|
||||
static bool is_sound_blacklisted(const LLUUID& sound_id, const LLUUID& object_id, const LLUUID& owner_id)
|
||||
{
|
||||
FSAssetBlacklist& blacklist = FSAssetBlacklist::instance();
|
||||
|
||||
if (blacklist.isBlacklisted(sound_id, LLAssetType::AT_SOUND))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (object_id == owner_id)
|
||||
{
|
||||
// Gesture sound
|
||||
return blacklist.isBlacklisted(owner_id, LLAssetType::AT_SOUND, FSAssetBlacklist::eBlacklistFlag::GESTURE);
|
||||
}
|
||||
else if (LLViewerObject* object = gObjectList.findObject(object_id))
|
||||
{
|
||||
if (object->isAttachment())
|
||||
{
|
||||
// Attachment sound
|
||||
return blacklist.isBlacklisted(owner_id, LLAssetType::AT_SOUND, FSAssetBlacklist::eBlacklistFlag::WORN);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rezzed object sound
|
||||
return blacklist.isBlacklisted(owner_id, LLAssetType::AT_SOUND, FSAssetBlacklist::eBlacklistFlag::REZZED);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// </FS>
|
||||
|
||||
void process_sound_trigger(LLMessageSystem *msg, void **)
|
||||
{
|
||||
if (!gAudiop)
|
||||
|
|
@ -4728,10 +4760,8 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
|
|||
// </FS:ND>
|
||||
|
||||
// <FS> Asset blacklist
|
||||
if (FSAssetBlacklist::getInstance()->isBlacklisted(sound_id, LLAssetType::AT_SOUND))
|
||||
{
|
||||
if (is_sound_blacklisted(sound_id, object_id, owner_id))
|
||||
return;
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
|
|
@ -4837,11 +4867,14 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data)
|
|||
msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id);
|
||||
msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
|
||||
|
||||
// <FS> Asset blacklist
|
||||
if (FSAssetBlacklist::getInstance()->isBlacklisted(sound_id, LLAssetType::AT_SOUND))
|
||||
{
|
||||
// <FS:ND> Protect against corrupted sounds
|
||||
if (gAudiop->isCorruptSound(sound_id))
|
||||
return;
|
||||
// </FS:ND>
|
||||
|
||||
// <FS> Asset blacklist
|
||||
if (is_sound_blacklisted(sound_id, object_id, owner_id))
|
||||
return;
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
|
|
@ -4853,12 +4886,7 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data)
|
|||
}
|
||||
// NaCl End
|
||||
|
||||
// <FS:ND> Protect against corrupted sounds
|
||||
if( gAudiop->isCorruptSound( sound_id ) )
|
||||
return;
|
||||
// </FS:ND>
|
||||
|
||||
LLViewerObject *objectp = gObjectList.findObject(object_id);
|
||||
LLViewerObject* objectp = gObjectList.findObject(object_id);
|
||||
if (!objectp) return;
|
||||
|
||||
if (LLMuteList::getInstance()->isMuted(object_id)) return;
|
||||
|
|
@ -4894,11 +4922,14 @@ void process_attached_sound(LLMessageSystem *msg, void **user_data)
|
|||
msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id);
|
||||
msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
|
||||
|
||||
// <FS> Asset blacklist
|
||||
if (FSAssetBlacklist::getInstance()->isBlacklisted(sound_id, LLAssetType::AT_SOUND))
|
||||
{
|
||||
// <FS:ND> Protect against corrupted sounds
|
||||
if (gAudiop->isCorruptSound(sound_id))
|
||||
return;
|
||||
// </FS:ND>
|
||||
|
||||
// <FS> Asset blacklist
|
||||
if (is_sound_blacklisted(sound_id, object_id, owner_id))
|
||||
return;
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
|
|
|
|||
|
|
@ -434,7 +434,7 @@ void LLGridManager::setGridChoice(const std::string& grid)
|
|||
}
|
||||
}
|
||||
|
||||
std::string LLGridManager::getGrid( const std::string &grid )
|
||||
std::string LLGridManager::getGrid( const std::string &grid ) const
|
||||
{
|
||||
std::string grid_name;
|
||||
|
||||
|
|
@ -446,7 +446,7 @@ std::string LLGridManager::getGrid( const std::string &grid )
|
|||
else
|
||||
{
|
||||
// search the grid list for a grid with a matching id
|
||||
for(LLSD::map_iterator grid_iter = mGridList.beginMap();
|
||||
for(LLSD::map_const_iterator grid_iter = mGridList.beginMap();
|
||||
grid_name.empty() && grid_iter != mGridList.endMap();
|
||||
grid_iter++)
|
||||
{
|
||||
|
|
@ -642,12 +642,12 @@ void LLGridManager::updateIsInProductionGrid()
|
|||
}
|
||||
}
|
||||
|
||||
bool LLGridManager::isInProductionGrid()
|
||||
bool LLGridManager::isInProductionGrid() const
|
||||
{
|
||||
return mIsInProductionGrid;
|
||||
}
|
||||
|
||||
bool LLGridManager::isSystemGrid(const std::string& grid)
|
||||
bool LLGridManager::isSystemGrid(const std::string& grid) const
|
||||
{
|
||||
std::string grid_name = getGrid(grid);
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class LLGridManager : public LLSingleton<LLGridManager>
|
|||
* descriptive form (it is used in the login panel grid menu, for example).
|
||||
*/
|
||||
/// Return the name of a grid, given either its name or its id
|
||||
std::string getGrid( const std::string &grid );
|
||||
std::string getGrid( const std::string &grid ) const;
|
||||
|
||||
/// Get the id (short form selector) for a given grid
|
||||
std::string getGridId(const std::string& grid);
|
||||
|
|
@ -206,13 +206,13 @@ class LLGridManager : public LLSingleton<LLGridManager>
|
|||
//@}
|
||||
|
||||
/// Is the given grid one of the hard-coded default grids (Agni or Aditi)
|
||||
bool isSystemGrid(const std::string& grid);
|
||||
bool isSystemGrid(const std::string& grid) const;
|
||||
|
||||
/// Is the selected grid one of the hard-coded default grids (Agni or Aditi)
|
||||
bool isSystemGrid() { return isSystemGrid(mGrid); }
|
||||
bool isSystemGrid() const { return isSystemGrid(mGrid); }
|
||||
//<FS:AW compatibility with opensim api>
|
||||
/// Is the selected grid Second Life Main grid?
|
||||
bool isInSLMain() { return isInProductionGrid(); }
|
||||
bool isInSLMain() const { return isInProductionGrid(); }
|
||||
/**
|
||||
* the purpose of not just taking isInProductionGrid() is to
|
||||
* create merge conflicts so that changes that need special casing
|
||||
|
|
@ -220,12 +220,12 @@ class LLGridManager : public LLSingleton<LLGridManager>
|
|||
*/
|
||||
|
||||
/// Is the selected grid a Second Life beta grid?
|
||||
bool isInSLBeta() { return (isSystemGrid() && !isInProductionGrid()); }
|
||||
bool isInSecondLife() { return (isInSLMain() || isInSLBeta()); } // <FS:CR>
|
||||
bool isInSLBeta() const { return (isSystemGrid() && !isInProductionGrid()); }
|
||||
bool isInSecondLife() const { return (isInSLMain() || isInSLBeta()); } // <FS:CR>
|
||||
private:
|
||||
//</FS:AW compatibility with opensim api>
|
||||
/// Is the selected grid a production grid?
|
||||
bool isInProductionGrid();
|
||||
bool isInProductionGrid() const;
|
||||
/**
|
||||
* yes, that's not a very helpful description.
|
||||
* I don't really know why that is different from isSystemGrid()
|
||||
|
|
|
|||
|
|
@ -6605,13 +6605,6 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
|
|||
return;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Asset blacklist
|
||||
if (FSAssetBlacklist::getInstance()->isBlacklisted(audio_uuid, LLAssetType::AT_SOUND))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
if (flags & LL_SOUND_FLAG_LOOP
|
||||
&& mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData()
|
||||
&& mAudioSourcep->getCurrentData()->getID() == audio_uuid)
|
||||
|
|
|
|||
|
|
@ -1357,6 +1357,12 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const
|
|||
|
||||
void LLViewerRegion::updateReflectionProbes(bool full_update)
|
||||
{
|
||||
// [FIRE-35070] Don't update reflection probes if disabled
|
||||
if (LLPipeline::sReflectionProbeLevel == (S32)LLReflectionMap::ProbeLevel::NONE)
|
||||
{
|
||||
return; // no probes
|
||||
}
|
||||
// </FS:Beq>
|
||||
if (!full_update && mReflectionMaps.empty())
|
||||
{
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ public:
|
|||
|
||||
// </FS:CR>
|
||||
#ifdef OPENSIM
|
||||
std::set<std::string> getGods() { return mGodNames; };
|
||||
const std::set<std::string, std::less<>>& getGods() const { return mGodNames; };
|
||||
#endif // OPENSIM
|
||||
// </FS:CR>
|
||||
|
||||
|
|
@ -624,7 +624,7 @@ public:
|
|||
|
||||
// <FS:CR> Opensim region capabilities
|
||||
#ifdef OPENSIM
|
||||
std::set<std::string> mGodNames;
|
||||
std::set<std::string, std::less<>> mGodNames;
|
||||
#endif
|
||||
// </FS:CR>
|
||||
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ void LLViewerTextureList::dump()
|
|||
LL_CONT << image->getNumVolumes(index) << " ";
|
||||
}
|
||||
// </FS:minerjr> [FIRE-35081]
|
||||
LL_CONT << " http://asset.siva.lindenlab.com/" << image->getID() << ".texture"
|
||||
LL_CONT << " " << image->getID().asString().substr(0, 7)
|
||||
<< LL_ENDL;
|
||||
// <FS:minerjr> [FIRE-35081] Blurry prims not changing with graphics settings
|
||||
image_counts[(image->getDiscardLevel() + 1)] += 1; // Need to add +1 to make up for -1 being a possible value
|
||||
|
|
@ -1498,6 +1498,10 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
|
|||
// <FS:Ansariel> Fast cache stats
|
||||
sNumFastCacheReads++;
|
||||
// </FS:Ansariel>
|
||||
// <FS:Ansariel> Fix fast cache
|
||||
if (timer.getElapsedTimeF32() > max_time)
|
||||
break;
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
mFastCacheList.erase(mFastCacheList.begin(), enditer);
|
||||
return timer.getElapsedTimeF32();
|
||||
|
|
@ -1609,7 +1613,9 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
|
|||
LLTimer timer;
|
||||
|
||||
//loading from fast cache
|
||||
updateImagesLoadingFastCache(max_time);
|
||||
// <FS:Ansariel> Fix fast cache
|
||||
//updateImagesLoadingFastCache(max_time);
|
||||
max_time -= updateImagesLoadingFastCache(max_time);
|
||||
|
||||
// Update texture stats and priorities
|
||||
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
|
||||
|
|
|
|||
|
|
@ -2503,13 +2503,13 @@ void LLViewerWindow::initWorldUI()
|
|||
// url = LLWeb::expandURLSubstitutions(url, LLSD());
|
||||
// destinations->navigateTo(url, "text/html");
|
||||
// }
|
||||
// LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents");
|
||||
// if (avatar_picker)
|
||||
// LLMediaCtrl* avatar_welcome_pack = LLFloaterReg::getInstance("avatar_welcome_pack")->findChild<LLMediaCtrl>("avatar_picker_contents");
|
||||
// if (avatar_welcome_pack)
|
||||
// {
|
||||
// avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
|
||||
// std::string url = gSavedSettings.getString("AvatarPickerURL");
|
||||
// avatar_welcome_pack->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
|
||||
// std::string url = gSavedSettings.getString("AvatarWelcomePack");
|
||||
// url = LLWeb::expandURLSubstitutions(url, LLSD());
|
||||
// avatar_picker->navigateTo(url, "text/html");
|
||||
// avatar_welcome_pack->navigateTo(url, "text/html");
|
||||
// }
|
||||
std::string destination_guide_url;
|
||||
#ifdef OPENSIM // <FS:AW optional opensim support>
|
||||
|
|
@ -2550,18 +2550,18 @@ void LLViewerWindow::initWorldUI()
|
|||
else
|
||||
#endif // OPENSIM // <FS:AW optional opensim support>
|
||||
{
|
||||
avatar_picker_url = gSavedSettings.getString("AvatarPickerURL");
|
||||
avatar_picker_url = gSavedSettings.getString("AvatarWelcomePack");
|
||||
}
|
||||
|
||||
if(!avatar_picker_url.empty())
|
||||
{
|
||||
LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents");
|
||||
if (avatar_picker)
|
||||
LLMediaCtrl* avatar_welcome_pack = LLFloaterReg::getInstance("avatar_welcome_pack")->findChild<LLMediaCtrl>("avatar_picker_contents");
|
||||
if (avatar_welcome_pack)
|
||||
{
|
||||
avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
|
||||
avatar_welcome_pack->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
|
||||
avatar_picker_url = LLWeb::expandURLSubstitutions(avatar_picker_url, LLSD());
|
||||
LL_DEBUGS("WebApi") << "AvatarPickerURL \"" << avatar_picker_url << "\"" << LL_ENDL;
|
||||
avatar_picker->navigateTo(avatar_picker_url, HTTP_CONTENT_TEXT_HTML);
|
||||
avatar_welcome_pack->navigateTo(avatar_picker_url, HTTP_CONTENT_TEXT_HTML);
|
||||
}
|
||||
}
|
||||
// </FS:AW opensim destinations and avatar picker>
|
||||
|
|
@ -7338,11 +7338,16 @@ void LLViewerWindow::setUIVisibility(bool visible)
|
|||
// LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : false);
|
||||
mStatusBarContainer->setVisible(visible);
|
||||
|
||||
// <FS:Zi> hide utility bar if we are on a skin that uses it, e.g. Vintage
|
||||
LLView* utilityBarStack = mRootView->findChildView("chat_bar_utility_bar_stack");
|
||||
if (utilityBarStack)
|
||||
// <FS:Zi> hide utility bar if we are on a skin that uses it, i.e. Vintage
|
||||
// Beq Note: Added a skin check to fix FIRE-29517 "hitch when entering mouselook"
|
||||
// This was caused having to search for a non-existent childview. If another skin other than vintage
|
||||
// ever needs chat_bar_utility_bar_stack in the future, this will need to be updated.
|
||||
if (FSCommon::isLegacySkin())
|
||||
{
|
||||
utilityBarStack->setVisible(visible);
|
||||
if (LLView* utilityBarStack = mRootView->findChildView("chat_bar_utility_bar_stack"); utilityBarStack)
|
||||
{
|
||||
utilityBarStack->setVisible(visible);
|
||||
}
|
||||
}
|
||||
// </FS:Zi>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,6 +238,17 @@ enum ERenderName
|
|||
RENDER_NAME_FADE
|
||||
};
|
||||
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// Different settings based on FSImpostorAvatarExclude
|
||||
enum EImpostorAvatarExclude
|
||||
{
|
||||
NONE, // Default, no avatar excluded
|
||||
USER, // Check for mIsAnimesh only, exclude user Avatar's which are Animesh or have Animesh attachments
|
||||
CONTROL, // Check for mIsControlAvatar only, exclude control avatars (avtars which don't have a user UUID assigned)
|
||||
BOTH // Check both mIsAnimesh or mIsControlAvatar, exclude both User Amimesh and Control avatars.
|
||||
};
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
|
||||
#define JELLYDOLLS_SHOULD_IMPOSTOR
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -4643,6 +4654,9 @@ bool LLVOAvatar::isVisuallyMuted()
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; // <FS:Beq/> Tracy accounting for imposter testing.
|
||||
bool muted = false;
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
static LLCachedControl<U32> impostor_avatar_exclude(gSavedSettings,"FSImpostorAvatarExclude", 0);
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
|
||||
// <FS:Ansariel> FIRE-11783: Always visually mute avatars that are muted
|
||||
if (!isSelf() && isInMuteList())
|
||||
|
|
@ -4677,6 +4691,13 @@ bool LLVOAvatar::isVisuallyMuted()
|
|||
#else
|
||||
muted = false;
|
||||
#endif
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If the avatar is set to be excluded, set the muted flag to false
|
||||
if ((mIsControlAvatar && impostor_avatar_exclude >= EImpostorAvatarExclude::CONTROL) || (mIsAnimesh && (impostor_avatar_exclude & EImpostorAvatarExclude::USER)))
|
||||
{
|
||||
muted = false;
|
||||
}
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
}
|
||||
// <FS:Ansariel> FIRE-11783: Always visually mute avatars that are muted
|
||||
//else if (isInMuteList())
|
||||
|
|
@ -4686,10 +4707,26 @@ bool LLVOAvatar::isVisuallyMuted()
|
|||
// </FS:Ansariel>
|
||||
else if (mIsControlAvatar)
|
||||
{
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If the avatar is set to control or both, set the the meted flag to false
|
||||
if (impostor_avatar_exclude >= EImpostorAvatarExclude::CONTROL)
|
||||
{
|
||||
muted = false;
|
||||
}
|
||||
else
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
muted = isTooSlow();
|
||||
}
|
||||
else
|
||||
{
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If the avatar is an animesh and the FSImpostorAvatarExclude is either a USER or BOTH (Can use & as both 1 and 3 have 1 set)
|
||||
if ((impostor_avatar_exclude & EImpostorAvatarExclude::USER) && mIsAnimesh)
|
||||
{
|
||||
muted = false;
|
||||
}
|
||||
else
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
muted = isTooComplex(); // <FS:Beq/> this should not trigger based on perfstats
|
||||
}
|
||||
}
|
||||
|
|
@ -7608,6 +7645,10 @@ void LLVOAvatar::updateAttachmentOverrides()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If either the main body of the avatar is animated, or there are any animated attachedments, then flag it as an Animesh.
|
||||
mIsAnimesh = getNumAnimatedObjectAttachments() > 0 || isAnimatedObject();
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
}
|
||||
|
||||
void LLVOAvatar::notifyAttachmentMeshLoaded()
|
||||
|
|
@ -8558,6 +8599,10 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o
|
|||
|
||||
updateMeshVisibility();
|
||||
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If either the main body of the avatar is animated, or there are any animated attachedments, then flag it as an Animesh.
|
||||
mIsAnimesh = getNumAnimatedObjectAttachments() > 0 || isAnimatedObject();
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
return attachment;
|
||||
}
|
||||
|
||||
|
|
@ -8883,6 +8928,10 @@ bool LLVOAvatar::detachObject(LLViewerObject *viewer_object)
|
|||
}
|
||||
|
||||
updateMeshVisibility();
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If either the main body of the avatar is animated, or there are any animated attachedments, then flag it as an Animesh.
|
||||
mIsAnimesh = getNumAnimatedObjectAttachments() > 0 || isAnimatedObject();
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
|
||||
LL_DEBUGS() << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << LL_ENDL;
|
||||
return true;
|
||||
|
|
@ -8893,6 +8942,10 @@ bool LLVOAvatar::detachObject(LLViewerObject *viewer_object)
|
|||
if (iter != mPendingAttachment.end())
|
||||
{
|
||||
mPendingAttachment.erase(iter);
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// If either the main body of the avatar is animated, or there are any animated attachedments, then flag it as an Animesh.
|
||||
mIsAnimesh = getNumAnimatedObjectAttachments() > 0 || isAnimatedObject();
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -9679,6 +9732,15 @@ bool LLVOAvatar::isTooComplex() const
|
|||
}
|
||||
else
|
||||
{
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
static LLCachedControl<U32> impostor_avatar_exclude(gSavedSettings,"FSImpostorAvatarExclude", 0);
|
||||
|
||||
// If the avatar is set to be excluded, return that the avatar is not too complex
|
||||
if ((mIsControlAvatar && impostor_avatar_exclude >= EImpostorAvatarExclude::CONTROL) || (mIsAnimesh && (impostor_avatar_exclude & EImpostorAvatarExclude::USER)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
// Determine if visually muted or not
|
||||
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U);
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f);
|
||||
|
|
@ -12118,8 +12180,23 @@ bool LLVOAvatar::isImpostor()
|
|||
{
|
||||
// <FS:Beq> render time handling using tooSlow()
|
||||
// return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1));
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
static LLCachedControl<U32> impostor_avatar_exclude(gSavedSettings,"FSImpostorAvatarExclude", 0);
|
||||
|
||||
// Store the result of is visually muted as used in possibly 2 places
|
||||
bool is_visual_muted = isVisuallyMuted();
|
||||
|
||||
// If the avatar is set to be excluded, return that the avatar is not an Impostor
|
||||
if ((mIsControlAvatar && impostor_avatar_exclude >= EImpostorAvatarExclude::CONTROL) || (mIsAnimesh && (impostor_avatar_exclude & EImpostorAvatarExclude::USER)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
return (
|
||||
isVisuallyMuted() ||
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
// isVisuallyMuted() ||
|
||||
is_visual_muted || // Save from calling isVisuallyMuted a second time
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
isTooSlowWithoutShadows() ||
|
||||
(sLimitNonImpostors && (mUpdatePeriod > 1) )
|
||||
);
|
||||
|
|
@ -12140,6 +12217,15 @@ bool LLVOAvatar::shouldImpostor(const F32 rank_factor)
|
|||
// return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor);
|
||||
// static LLCachedControl<bool> render_jellys_As_imposters(gSavedSettings, "RenderJellyDollsAsImpostors");
|
||||
|
||||
// <FS:minerjr> [FIRE-35735] Imposter/Impostor Avatar Exclusions
|
||||
static LLCachedControl<U32> impostor_avatar_exclude(gSavedSettings,"FSImpostorAvatarExclude", 0);
|
||||
|
||||
// If the avatar is set to be excluded, return that the avatar should not be impostored
|
||||
if ((mIsControlAvatar && impostor_avatar_exclude >= EImpostorAvatarExclude::CONTROL) || (mIsAnimesh && (impostor_avatar_exclude & EImpostorAvatarExclude::USER)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// </FS:minerjr> [FIRE-35735]
|
||||
if (isTooSlowWithoutShadows())
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -685,6 +685,7 @@ public:
|
|||
// [/RLVa:KB]
|
||||
// bool mNeedsImpostorUpdate;
|
||||
S32 mLastImpostorUpdateReason;
|
||||
bool mIsAnimesh; // <FS:minerjr> FIRE-35735: Imposter/Impostor Avatar Exclusions (Flag to track if avatar or attachments have Animated Mesh flagged)
|
||||
F32SecondsImplicit mLastImpostorUpdateFrameTime;
|
||||
const LLVector3* getLastAnimExtents() const { return mLastAnimExtents; }
|
||||
void setNeedsExtentUpdate(bool val) { mNeedsExtentUpdate = val; }
|
||||
|
|
|
|||
|
|
@ -225,8 +225,7 @@ void PermissionsTracker::objectPropertiesCallback(LLMessageSystem* msg)
|
|||
mPermissionsList[source_id].objectName = object_name;
|
||||
mPermissionsList[source_id].ownerID = object_owner;
|
||||
|
||||
LLAvatarName avatar_name;
|
||||
if (LLAvatarNameCache::get(object_owner, &avatar_name))
|
||||
if (LLAvatarName avatar_name; LLAvatarNameCache::get(object_owner, &avatar_name))
|
||||
{
|
||||
LL_DEBUGS("PermissionsTracker") << "Found cached entry for owner " << object_owner.asString()
|
||||
<< ": " << avatar_name.getCompleteName() << LL_ENDL;
|
||||
|
|
@ -234,10 +233,8 @@ void PermissionsTracker::objectPropertiesCallback(LLMessageSystem* msg)
|
|||
}
|
||||
else if (mAvatarNameCacheConnections.find(object_owner) != mAvatarNameCacheConnections.end())
|
||||
{
|
||||
boost::signals2::connection cb_connection = LLAvatarNameCache::get(object_owner, boost::bind(&PermissionsTracker::avatarNameCallback, this, _1, _2));
|
||||
mAvatarNameCacheConnections.insert(std::make_pair(object_owner, cb_connection));
|
||||
|
||||
LL_DEBUGS("PermissionsTracker") << "Requesting avatar name for owner " << object_owner.asString() << LL_ENDL;
|
||||
mAvatarNameCacheConnections.try_emplace(object_owner, LLAvatarNameCache::get(object_owner, boost::bind(&PermissionsTracker::avatarNameCallback, this, _1, _2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,6 +352,7 @@ bool LLPipeline::sRenderAttachedLights = true;
|
|||
bool LLPipeline::sRenderAttachedParticles = true;
|
||||
bool LLPipeline::sRenderDeferred = false;
|
||||
bool LLPipeline::sReflectionProbesEnabled = false;
|
||||
S32 LLPipeline::sReflectionProbeLevel = (S32)LLReflectionMap::ProbeLevel::NONE; // <FS:Beq/> [FIRE-35070] Address progressive FPS loss.
|
||||
S32 LLPipeline::sVisibleLightCount = 0;
|
||||
bool LLPipeline::sRenderingHUDs;
|
||||
F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f;
|
||||
|
|
@ -1262,8 +1263,10 @@ void LLPipeline::refreshCachedSettings()
|
|||
RenderMirrors = gSavedSettings.getBOOL("RenderMirrors");
|
||||
RenderHeroProbeUpdateRate = gSavedSettings.getS32("RenderHeroProbeUpdateRate");
|
||||
RenderHeroProbeConservativeUpdateMultiplier = gSavedSettings.getS32("RenderHeroProbeConservativeUpdateMultiplier");
|
||||
|
||||
sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled");
|
||||
// <FS:Beq> [FIRE-35070] Instead of using the above we'll add a new static level variable to save some lookups. Making the above "work" with ProbeLevel will break everything.
|
||||
sReflectionProbeLevel = gSavedSettings.getS32("RenderReflectionProbeLevel");
|
||||
// <FS:Beq/>
|
||||
RenderSpotLight = nullptr;
|
||||
|
||||
if (gNonInteractive)
|
||||
|
|
|
|||
|
|
@ -690,6 +690,9 @@ public:
|
|||
static bool sRenderAttachedParticles;
|
||||
static bool sRenderDeferred;
|
||||
static bool sReflectionProbesEnabled;
|
||||
// <FS:Beq> [FIRE-35070] Address gradual slowdown issue
|
||||
static S32 sReflectionProbeLevel;
|
||||
// </FS:Beq>
|
||||
static S32 sVisibleLightCount;
|
||||
static bool sRenderingHUDs;
|
||||
static F32 sDistortionWaterClipPlaneMargin;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.07227716594934463500976562</real>
|
||||
<real>0.2199114710092544555664062</real>
|
||||
<real>0.072256624698638916015625</real>
|
||||
<real>0.2199114412069320678710938</real>
|
||||
<real>0.2693966925144195556640625</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
|
|
@ -39,9 +39,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.05256520584225654602050781</real>
|
||||
<real>0.1256637275218963623046875</real>
|
||||
<real>-0.4665162861347198486328125</real>
|
||||
<real>-0.072256624698638916015625</real>
|
||||
<real>0.2199114412069320678710938</real>
|
||||
<real>-0.2693966925144195556640625</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -64,9 +64,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.03285326063632965087890625</real>
|
||||
<real>1.455191696309032778344772e-11</real>
|
||||
<real>-0.01314130239188671112060547</real>
|
||||
<real>0.03281218931078910827636719</real>
|
||||
<real>1.455191522836685180664062e-11</real>
|
||||
<real>-0.01314130332320928573608398</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -89,9 +89,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.03285326063632965087890625</real>
|
||||
<real>1.455191696309032778344772e-11</real>
|
||||
<real>0.01314130239188671112060547</real>
|
||||
<real>-0.03281218931078910827636719</real>
|
||||
<real>1.455191522836685180664062e-11</real>
|
||||
<real>0.01314130332320928573608398</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.01971195824444293975830078</real>
|
||||
<real>0.01972222141921520233154297</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.01971195824444293975830078</real>
|
||||
<real>-0.01972222141921520233154297</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
|
|
@ -164,9 +164,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.04599455744028091430664062</real>
|
||||
<real>-4.65661342818890489070327e-10</real>
|
||||
<real>0.06570650637149810791015625</real>
|
||||
<real>0.04607669264078140258789062</real>
|
||||
<real>-2.3283064365386962890625e-10</real>
|
||||
<real>0.0657065212726593017578125</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -189,9 +189,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.09855977445840835571289062</real>
|
||||
<real>0</real>
|
||||
<real>0.006570650730282068252563477</real>
|
||||
<real>-0.04607669264078140258789062</real>
|
||||
<real>-2.3283064365386962890625e-10</real>
|
||||
<real>-0.0657065212726593017578125</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.03285325691103935241699219</real>
|
||||
<real>0.03281219303607940673828125</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
|
|
@ -239,7 +239,7 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.03285325691103935241699219</real>
|
||||
<real>-0.03281219303607940673828125</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
|
|
@ -264,8 +264,8 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.01971195638179779052734375</real>
|
||||
<real>2.910383392618065556689544e-11</real>
|
||||
<real>0.0197222232818603515625</real>
|
||||
<real>-8.731149137020111083984375e-11</real>
|
||||
<real>-0.04599456489086151123046875</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
|
|
@ -289,8 +289,8 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.01971195638179779052734375</real>
|
||||
<real>2.910383392618065556689544e-11</real>
|
||||
<real>-0.0197222232818603515625</real>
|
||||
<real>-8.731149137020111083984375e-11</real>
|
||||
<real>0.04599456489086151123046875</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
|
|
@ -314,9 +314,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.749054372310638427734375</real>
|
||||
<real>-0.749095380306243896484375</real>
|
||||
<real>-0.543495595455169677734375</real>
|
||||
<real>-0.913320600986480712890625</real>
|
||||
<real>-0.91332066059112548828125</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -339,9 +339,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-1.42372357845306396484375</real>
|
||||
<real>-0.589437425136566162109375</real>
|
||||
<real>-0.1377763897180557250976562</real>
|
||||
<real>0.749095380306243896484375</real>
|
||||
<real>-0.543495595455169677734375</real>
|
||||
<real>0.91332066059112548828125</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -365,8 +365,8 @@
|
|||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-2.0171897411346435546875</real>
|
||||
<real>-1.099557399749755859375</real>
|
||||
<real>-0.64392375946044921875</real>
|
||||
<real>-1.09955728054046630859375</real>
|
||||
<real>-0.643852174282073974609375</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -389,9 +389,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.03942390903830528259277344</real>
|
||||
<real>0.03141593188047409057617188</real>
|
||||
<real>0.03285326063632965087890625</real>
|
||||
<real>2.0171897411346435546875</real>
|
||||
<real>-1.09955728054046630859375</real>
|
||||
<real>0.643852174282073974609375</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -415,8 +415,8 @@
|
|||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.558505475521087646484375</real>
|
||||
<real>-0.56548678874969482421875</real>
|
||||
<real>-0.05256522819399833679199219</real>
|
||||
<real>-0.565486729145050048828125</real>
|
||||
<real>-0.05253438279032707214355469</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -439,9 +439,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.0131413042545318603515625</real>
|
||||
<real>5.820767479125521504101926e-11</real>
|
||||
<real>-0.1051304414868354797363281</real>
|
||||
<real>0.558505475521087646484375</real>
|
||||
<real>-0.565486729145050048828125</real>
|
||||
<real>0.05253438279032707214355469</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -464,9 +464,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.987495481967926025390625</real>
|
||||
<real>0.01987109147012233734130859</real>
|
||||
<real>-0.498646259307861328125</real>
|
||||
<real>-0.987507343292236328125</real>
|
||||
<real>0.01987109519541263580322266</real>
|
||||
<real>-0.498646318912506103515625</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -489,9 +489,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-1.4442241191864013671875</real>
|
||||
<real>-0.281714916229248046875</real>
|
||||
<real>-0.3864487111568450927734375</real>
|
||||
<real>0.987507343292236328125</real>
|
||||
<real>0.01987109519541263580322266</real>
|
||||
<real>0.498646318912506103515625</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -514,9 +514,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-1.96462452411651611328125</real>
|
||||
<real>-1.9645426273345947265625</real>
|
||||
<real>-0.4084071218967437744140625</real>
|
||||
<real>-0.551934778690338134765625</real>
|
||||
<real>-0.551934719085693359375</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -539,9 +539,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.03285326063632965087890625</real>
|
||||
<real>2.910383392618065556689544e-11</real>
|
||||
<real>-0.01971195451915264129638672</real>
|
||||
<real>1.9645426273345947265625</real>
|
||||
<real>-0.4084071218967437744140625</real>
|
||||
<real>0.551934719085693359375</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -564,7 +564,7 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.2431140989065170288085938</real>
|
||||
<real>-0.24312436580657958984375</real>
|
||||
<real>0</real>
|
||||
<real>-0.0722771584987640380859375</real>
|
||||
</array>
|
||||
|
|
@ -589,9 +589,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.01971195451915264129638672</real>
|
||||
<real>7.27595848154516389172386e-12</real>
|
||||
<real>0.006570650730282068252563477</real>
|
||||
<real>0.24312436580657958984375</real>
|
||||
<real>0</real>
|
||||
<real>0.0722771584987640380859375</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -615,8 +615,8 @@
|
|||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.1576956808567047119140625</real>
|
||||
<real>1.07128322124481201171875</real>
|
||||
<real>0.1379837095737457275390625</real>
|
||||
<real>1.0712833404541015625</real>
|
||||
<real>0.1380554884672164916992188</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -639,9 +639,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.01314130239188671112060547</real>
|
||||
<real>0</real>
|
||||
<real>0.006570651195943355560302734</real>
|
||||
<real>0.1576956808567047119140625</real>
|
||||
<real>1.0712833404541015625</real>
|
||||
<real>-0.1380554884672164916992188</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -664,9 +664,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-1.32070124149322509765625</real>
|
||||
<real>1.22522127628326416015625</real>
|
||||
<real>1.018451213836669921875</real>
|
||||
<real>-1.32070100307464599609375</real>
|
||||
<real>1.2252213954925537109375</real>
|
||||
<real>1.0183994770050048828125</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -689,9 +689,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.03942390531301498413085938</real>
|
||||
<real>5.82076609134674072265625e-11</real>
|
||||
<real>-0.01971195451915264129638672</real>
|
||||
<real>1.32070100307464599609375</real>
|
||||
<real>1.2252213954925537109375</real>
|
||||
<real>-1.0183994770050048828125</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -714,9 +714,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>-0.597929298877716064453125</real>
|
||||
<real>-0.59792935848236083984375</real>
|
||||
<real>-0.251327455043792724609375</real>
|
||||
<real>-0.08541848510503768920898438</real>
|
||||
<real>-0.08534660190343856811523438</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
@ -739,9 +739,9 @@
|
|||
</array>
|
||||
<key>rotation</key>
|
||||
<array>
|
||||
<real>0.03285325691103935241699219</real>
|
||||
<real>0</real>
|
||||
<real>-0</real>
|
||||
<real>0.59792935848236083984375</real>
|
||||
<real>-0.251327455043792724609375</real>
|
||||
<real>0.08534660190343856811523438</real>
|
||||
</array>
|
||||
<key>scale</key>
|
||||
<array>
|
||||
|
|
|
|||
|
|
@ -598,7 +598,6 @@ with the same filename but different name
|
|||
|
||||
<!-- FS:Beq: Poser icons -->
|
||||
<texture name="Poser_Visual_On" file_name="icons/visual_pose_enabled.png" />
|
||||
<texture name="Poser_Visual_Off" file_name="icons/visual_pose_disabled.png" />
|
||||
|
||||
|
||||
<!-- FS:Ansariel: Icon for script errors in V1 status bar -->
|
||||
|
|
|
|||
|
|
@ -59,20 +59,17 @@
|
|||
</combo_box>
|
||||
<search_editor label="Regionun adı" name="location" tool_tip="Regionun adını daxil edin"/>
|
||||
<button label="Axtarış" name="DoSearch" tool_tip="Regioni axtarın"/>
|
||||
<button label="Təmizlə" name="Clear" tool_tip="İzləməni təmizləyin və xəritəni standart görüntüyə qaytarın"/>
|
||||
</panel>
|
||||
<panel name="layout_panel_7">
|
||||
<text name="events_label">
|
||||
Məkan:
|
||||
</text>
|
||||
<button label="Teleport" name="Teleport" tool_tip="Seçilmiş yere teleportasiya edin"/>
|
||||
<button label="Kopyala" name="copy_slurl" tool_tip="İnternetdə istifadə üçün SL URL ünvanı ilə cari yerin nümunəsini kopyalayın."/>
|
||||
<button label="Təmizlə" name="Clear" tool_tip="İzləməni təmizləyin və xəritəni standart görüntüyə qaytarın"/>
|
||||
<button label="Məkanı göstərin" name="Show Destination" tool_tip="Xəritəni seçilmiş yerə mərkəzləşdirin"/>
|
||||
<button label="Regionu izləyin" name="track_region" tool_tip="Regioni izləməyə əlavə edin"/>
|
||||
</panel>
|
||||
<panel name="layout_panel_5">
|
||||
<text name="zoom_label">
|
||||
Yaxınlaşdırma
|
||||
</text>
|
||||
</panel>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -255,13 +255,6 @@ Susmaya görə dəyərə qayıtmaq üçün UUID yanındakı 'D' düyməsini bas
|
|||
<button name="Def_UISndSnapshot" tool_tip="Susmaya görə olan UUID-yə sıfırla."/>
|
||||
<check_box label="Səsin söndürülməsi" name="QuietSnapshotsToDiskCheckBox"/>
|
||||
|
||||
<text tool_tip="Teleportasiya zamanı UUID səsi" name="textFSTeleportOut">
|
||||
Teleportasiya:
|
||||
</text>
|
||||
<button name="Prev_UISndTeleportOut" tool_tip="Bu səsi oxut."/>
|
||||
<button name="Def_UISndTeleportOut" tool_tip="Susmaya görə olan UUID-yə sıfırla."/>
|
||||
<check_box label="Səsi yandır" name="PlayModeUISndTeleportOut"/>
|
||||
|
||||
</panel>
|
||||
<panel label="İnteerfeys 2" name="UI Sounds tab 2">
|
||||
<text name="textFSExplanation_tab2">
|
||||
|
|
@ -269,6 +262,13 @@ Susmaya görə dəyərə qayıtmaq üçün UUID yanındakı 'D' düyməsini bas
|
|||
Susmaya görə dəyərə qayıtmaq üçün UUID yanındakı 'D' düyməsini basın.
|
||||
</text>
|
||||
|
||||
<text tool_tip="Teleportasiya zamanı UUID səsi" name="textFSTeleportOut">
|
||||
Teleportasiya:
|
||||
</text>
|
||||
<button name="Prev_UISndTeleportOut" tool_tip="Bu səsi oxut."/>
|
||||
<button name="Def_UISndTeleportOut" tool_tip="Susmaya görə olan UUID-yə sıfırla."/>
|
||||
<check_box label="Səsi yandır" name="PlayModeUISndTeleportOut"/>
|
||||
|
||||
<text tool_tip="Dairəvi menyu açılan zaman UUID səsi (Pie Menu)." name="textFSPieMenuAppear">
|
||||
Dairəvi menyu açılır:
|
||||
</text>
|
||||
|
|
@ -388,13 +388,6 @@ Susmaya görə dəyərə qayıtmaq üçün UUID yanındakı 'D' düyməsini bas
|
|||
<button name="Def_UISndFriendshipOffer" tool_tip="Susmaya görə olan UUID-yə sıfırla."/>
|
||||
<check_box label="Səsi yandır" name="PlayModeUISndFriendshipOffer"/>
|
||||
|
||||
<text tool_tip="Teleport təklifi zamanı səsləndirilən UUID səsi." name="textFSTeleportOffer">
|
||||
Teleport təklifi:
|
||||
</text>
|
||||
<button name="Prev_UISndTeleportOffer" tool_tip="Bu səsi oxut."/>
|
||||
<button name="Def_UISndTeleportOffer" tool_tip="Susmaya görə olan UUID-yə sıfırla."/>
|
||||
<check_box label="Səsi yandır" name="PlayModeUISndTeleportOffer"/>
|
||||
|
||||
</panel>
|
||||
<panel label="İnteerfeys 3" name="UI Sounds tab 3">
|
||||
<text name="textFSExplanation_tab3">
|
||||
|
|
@ -402,6 +395,13 @@ Susmaya görə dəyərə qayıtmaq üçün UUID yanındakı 'D' düyməsini bas
|
|||
Susmaya görə dəyərə qayıtmaq üçün UUID yanındakı 'D' düyməsini basın.
|
||||
</text>
|
||||
|
||||
<text tool_tip="Teleport təklifi zamanı səsləndirilən UUID səsi." name="textFSTeleportOffer">
|
||||
Teleport təklifi:
|
||||
</text>
|
||||
<button name="Prev_UISndTeleportOffer" tool_tip="Bu səsi oxut."/>
|
||||
<button name="Def_UISndTeleportOffer" tool_tip="Susmaya görə olan UUID-yə sıfırla."/>
|
||||
<check_box label="Səsi yandır" name="PlayModeUISndTeleportOffer"/>
|
||||
|
||||
<text tool_tip="Avadanlıq siyahısı təklif olunan zamanı səsləndirilən UUID səsi." name="textFSInventoryOffer">
|
||||
Avadanlıq siyahısı təklifi:
|
||||
</text>
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@
|
|||
</combo_box>
|
||||
<search_editor label="Regioner efter navn" name="location" tool_tip="Indtast navn på en region"/>
|
||||
<button label="Find" name="DoSearch" tool_tip="Led efter region"/>
|
||||
</panel>
|
||||
<panel name="layout_panel_7">
|
||||
<text name="events_label">
|
||||
Lokation:
|
||||
</text>
|
||||
|
|
|
|||
|
|
@ -37,4 +37,7 @@
|
|||
<button label="Fokussieren" name="look_at_btn" />
|
||||
<button label="Stop" name="stop_btn"/>
|
||||
<button label="Blacklist" name="bl_btn"/>
|
||||
<button label="Getragene Av. Sounds blocken" name="block_avatar_worn_sounds_btn" />
|
||||
<button label="Gerezzte Av. Sounds blocken" name="block_avatar_rezzed_sounds_btn" />
|
||||
<button label="Av. Gesten-Sounds blocken" name="block_avatar_gesture_sounds_btn" />
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -496,6 +496,8 @@ Nur große Parzellen können in der Suche aufgeführt werden.
|
|||
<name_list name="AccessList" tool_tip="([LISTED] aufgeführt, [MAX] max)"/>
|
||||
<button label="Hinzufügen" name="add_allowed"/>
|
||||
<button label="Entfernen" label_selected="Entfernen" name="remove_allowed"/>
|
||||
<button label="Exportieren" label_selected="Exportieren" name="export_allowed"/>
|
||||
<button label="Importieren" label_selected="Importieren" name="import_allowed" tool_tip="Importiert eine CSV-Datei mit ausschließlich gültigen UUIDs - eine pro Zeile ohne extra Zeichen oder Formatierung"/>
|
||||
</panel>
|
||||
<panel name="Banned_layout_panel">
|
||||
<text label="Verbannen" name="BanCheck">
|
||||
|
|
@ -507,6 +509,8 @@ Nur große Parzellen können in der Suche aufgeführt werden.
|
|||
</name_list>
|
||||
<button label="Hinzufügen" name="add_banned"/>
|
||||
<button label="Entfernen" label_selected="Entfernen" name="remove_banned"/>
|
||||
<button label="Exportieren" label_selected="Exportieren" name="export_banned"/>
|
||||
<button label="Importieren" label_selected="Importieren" name="import_banned" tool_tip="Importiert eine CSV-Datei mit ausschließlich gültigen UUIDs - eine pro Zeile ohne extra Zeichen oder Formatierung"/>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel label="Erlebnis" name="land_experiences_panel"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater name="Avatar Welcome Pack" title="Avatar-Willkommenspaket"/>
|
||||
|
|
@ -96,8 +96,9 @@
|
|||
<check_box name="exclude_reflection_probes" label="Reflexionstests"/>
|
||||
<check_box name="exclude_childprim" label="Kind-Primitive"/>
|
||||
<check_box name="exclude_neighbor_region" label="Nachbarregionen"/>
|
||||
<button name="apply" label="Anwenden"/>
|
||||
</panel>
|
||||
<button name="apply" label="Anwenden"/>
|
||||
<button name="save_as_default" label="Als Standard speichern"/>
|
||||
</panel>
|
||||
<panel label="Optionen" name="area_search_options_panel">
|
||||
<text name="display_column">
|
||||
Spalten anzeigen:
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue