Merge branch 'master' of https://vcs.firestormviewer.org/phoenix-firestorm
commit
d32853dbef
|
|
@ -1,8 +1,14 @@
|
|||
name: Build viewer
|
||||
on: push
|
||||
env:
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*release"
|
||||
- master
|
||||
schedule:
|
||||
- cron: '00 03 * * *' # Run every day at 3am UTC
|
||||
env:
|
||||
AUTOBUILD_VARIABLES_FILE: ${{github.workspace}}/build-variables/variables
|
||||
EXTRA_ARGS: -DFMODSTUDIO=ON -DUSE_KDU=ON --crashreporting
|
||||
EXTRA_ARGS: -DUSE_FMODSTUDIO=ON -DUSE_KDU=ON --crashreporting
|
||||
build_secrets_checkout: ${{github.workspace}}/signing
|
||||
|
||||
|
||||
|
|
@ -67,15 +73,22 @@ jobs:
|
|||
|
||||
- name: find channel from Branch name
|
||||
run: |
|
||||
if [[ "${{ github.ref_name }}" == *"Release"* ]]; then
|
||||
FS_RELEASE_CHAN="Release"
|
||||
if [[ "${{ github.ref_name }}" == *Release* ]]; then
|
||||
FS_RELEASE_TYPE=Release
|
||||
else
|
||||
FS_RELEASE_CHAN="Beta"
|
||||
if [[ "${{github.event_name}}" == 'schedule' ]]; then
|
||||
FS_RELEASE_TYPE=Nightly
|
||||
else
|
||||
FS_RELEASE_TYPE=Beta
|
||||
fi
|
||||
fi
|
||||
if [[ "${{ matrix.addrsize }}" == "64" ]]; then
|
||||
FS_RELEASE_CHAN="${FS_RELEASE_CHAN}x64"
|
||||
FS_RELEASE_CHAN="${FS_RELEASE_TYPE}x64"
|
||||
else
|
||||
FS_RELEASE_CHAN=${FS_RELEASE_TYPE}
|
||||
fi
|
||||
echo "FS_RELEASE_CHAN=\"${FS_RELEASE_CHAN}\"" >> $GITHUB_ENV
|
||||
echo "FS_RELEASE_TYPE=${FS_RELEASE_TYPE}" >> $GITHUB_ENV
|
||||
echo "FS_RELEASE_CHAN=${FS_RELEASE_CHAN}" >> $GITHUB_ENV
|
||||
echo "Building for channel ${FS_RELEASE_CHAN}"
|
||||
shell: bash
|
||||
|
||||
|
|
@ -187,18 +200,18 @@ jobs:
|
|||
run: rm *${{ env.fallback_platform }}*bz2
|
||||
shell: bash
|
||||
- name: Configure
|
||||
run: autobuild configure --debug -c ReleaseFS -A${{matrix.addrsize}} -- --package --chan ${{env.FS_RELEASE_CHAN}} ${{env.EXTRA_ARGS}} ${{env.FS_GRID}}
|
||||
run: autobuild configure -c ReleaseFS -A${{matrix.addrsize}} -- --package --chan ${{env.FS_RELEASE_CHAN}} ${{env.EXTRA_ARGS}} ${{env.FS_GRID}}
|
||||
shell: bash
|
||||
|
||||
- name: build
|
||||
run: autobuild build --debug -c ReleaseFS -A${{matrix.addrsize}} --no-configure
|
||||
run: autobuild build -c ReleaseFS -A${{matrix.addrsize}} --no-configure
|
||||
shell: bash
|
||||
|
||||
- name: publish Windows artifacts
|
||||
|
||||
- name: Publish artifacts
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{matrix.addrsize}}-${{matrix.grid}}-artifacts.zip
|
||||
name: ${{ env.FS_RELEASE_TYPE }}-${{ matrix.os }}-${{ matrix.addrsize }}-${{ matrix.grid }}-artifacts.zip
|
||||
path: |
|
||||
build-*/newview/Release/*Setup.exe
|
||||
build-*/newview/Release/*.xz
|
||||
|
|
@ -207,7 +220,7 @@ jobs:
|
|||
if: runner.os == 'Linux'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{matrix.addrsize}}-${{matrix.grid}}-artifacts.zip
|
||||
name: ${{ env.FS_RELEASE_TYPE }}-${{ matrix.os }}-${{matrix.addrsize}}-${{matrix.grid}}-artifacts.zip
|
||||
path: |
|
||||
build-linux-*/newview/*.xz
|
||||
build-linux-*/newview/*.bz2
|
||||
|
|
@ -216,7 +229,53 @@ jobs:
|
|||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{matrix.addrsize}}-${{matrix.grid}}-artifacts.zip
|
||||
name: ${{ env.FS_RELEASE_TYPE }}-${{ matrix.os }}-${{matrix.addrsize}}-${{matrix.grid}}-artifacts.zip
|
||||
path: |
|
||||
build-darwin-*/newview/*.dmg
|
||||
build-darwin-*/newview/*.bz2
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build_matrix
|
||||
if: always()
|
||||
steps:
|
||||
- name: Checkout files
|
||||
uses: Bhacaz/checkout-files@v2
|
||||
with:
|
||||
files: fsutils/download_list.py
|
||||
branch: ${{ github.head_ref || github.ref_name || 'master' }}
|
||||
- name: Install discord-webhook library
|
||||
run: pip install discord-webhook
|
||||
|
||||
- name: find channel from Branch name
|
||||
run: |
|
||||
if [[ "${{ github.ref_name }}" == *Release* ]]; then
|
||||
FS_RELEASE_FOLDER=release
|
||||
else
|
||||
if [[ "${{github.event_name}}" == 'schedule' ]]; then
|
||||
FS_RELEASE_FOLDER=nightly
|
||||
else
|
||||
FS_RELEASE_FOLDER=preview
|
||||
fi
|
||||
fi
|
||||
echo "FS_RELEASE_FOLDER=${FS_RELEASE_FOLDER}" >> $GITHUB_ENV
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
id: download
|
||||
with:
|
||||
path: to_deploy
|
||||
- name: List artifacts download
|
||||
run: ls -R
|
||||
working-directory: ${{steps.download.outputs.download-path}}
|
||||
|
||||
- name: Reorganise artifacts ready for server upload.
|
||||
run: python ./fsutils/download_list.py -u ${{steps.download.outputs.download-path}} -w ${{ secrets.RELEASE_WEBHOOK_URL }}
|
||||
|
||||
- name: Setup rclone and download the folder
|
||||
uses: beqjanus/setup-rclone@main
|
||||
with:
|
||||
rclone_config: ${{ secrets.RCLONE_CONFIG }}
|
||||
|
||||
- name: Copy files to remote host
|
||||
run: rclone copy ${{steps.download.outputs.download-path}}/${{ env.FS_RELEASE_FOLDER }} fs_deploy:${{ env.FS_RELEASE_FOLDER }}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,9 @@ import time
|
|||
import zipfile
|
||||
import glob
|
||||
import shutil
|
||||
from discord_webhook import DiscordWebhook
|
||||
|
||||
|
||||
# iterate over the files in a directory and pass them to a command line subshell
|
||||
def get_files(path):
|
||||
files = []
|
||||
for root, dirs, files in os.walk(path):
|
||||
# print(f"Found : {files}")
|
||||
return files
|
||||
return None
|
||||
|
||||
|
||||
# run a command line subshell and return the output
|
||||
|
|
@ -65,6 +60,14 @@ def get_files(path):
|
|||
# MD5: 9D5D8021F376194B42F6E7D8E537E45E
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------
|
||||
# iterate over the files in a directory and pass them to a command line subshell
|
||||
def get_files(path):
|
||||
files = []
|
||||
for root, dirs, filenames in os.walk(path):
|
||||
for filename in filenames:
|
||||
files.append(filename)
|
||||
print(f"Found : {files} on {path}")
|
||||
return files
|
||||
|
||||
def run_cmd(cmd):
|
||||
# print(cmd)
|
||||
|
|
@ -73,12 +76,12 @@ def run_cmd(cmd):
|
|||
#using the md5sum command get the md5 for the file
|
||||
|
||||
def get_md5(mdfile):
|
||||
# print(f"mdfile is {mdfile}")
|
||||
md5sum = run_cmd(f"md5sum {mdfile}")
|
||||
#split md5sum on space
|
||||
md5sum = md5sum.split()[0]
|
||||
#remove leading '\'
|
||||
md5sum = md5sum[1:]
|
||||
print(f"generating md5sum for {mdfile} as {md5sum}")
|
||||
return md5sum
|
||||
|
||||
def unzip_file(zip_file, unzip_dir):
|
||||
|
|
@ -86,6 +89,7 @@ def unzip_file(zip_file, unzip_dir):
|
|||
zip_ref.extractall(unzip_dir)
|
||||
|
||||
def flatten_tree(tree_root):
|
||||
print(f"Flattening tree {tree_root}")
|
||||
for root, flatten_dirs, files in os.walk(tree_root, topdown=False):
|
||||
for file in files:
|
||||
# Construct the full path to the file
|
||||
|
|
@ -107,6 +111,8 @@ parser = argparse.ArgumentParser(
|
|||
)
|
||||
parser.add_argument("-r", "--release", required=False, default=False, action="store_true", help="use the release folder in the target URL")
|
||||
parser.add_argument("-u", "--unzip", required=False, default=False, action="store_true", help="unzip the github artifact first")
|
||||
parser.add_argument("-w", "--webhook", help="post details to the webhook")
|
||||
|
||||
# add path_to_directory required parameter to parser
|
||||
parser.add_argument("path_to_directory", help="path to the directory in which we'll look for the files")
|
||||
|
||||
|
|
@ -114,102 +120,162 @@ args = parser.parse_args()
|
|||
path_to_directory = args.path_to_directory
|
||||
release = args.release
|
||||
|
||||
# Create a webhook object with the webhook URL
|
||||
if args.webhook:
|
||||
webhook = DiscordWebhook(url=args.webhook)
|
||||
|
||||
dirs = ["windows", "mac", "linux"]
|
||||
|
||||
if args.unzip:
|
||||
# unzip the github artifact for this OS (`dir`) into the folder `dir`
|
||||
# get the .zip files in args.path_to_directory using glob
|
||||
zips = glob.glob(f"{args.path_to_directory}/*.zip")
|
||||
for file in zips:
|
||||
# print(f"unzipping {file}")
|
||||
if "ubuntu" in file.lower():
|
||||
unzip_file(file, os.path.join(args.path_to_directory, "linux"))
|
||||
if "windows" in file.lower():
|
||||
unzip_file(file, os.path.join(args.path_to_directory, "windows"))
|
||||
if "macos" in file.lower():
|
||||
unzip_file(file, os.path.join(args.path_to_directory, "mac"))
|
||||
# build_types is a map from Beta, Release and Nightly to folder names preview release and nightly
|
||||
build_types = {
|
||||
"Beta": "preview",
|
||||
"Release": "release",
|
||||
"Nightly": "nightly"
|
||||
}
|
||||
|
||||
target_folder = {
|
||||
"ubuntu":"linux",
|
||||
"windows":"windows",
|
||||
"macos":"mac"
|
||||
}
|
||||
|
||||
# unzip the github artifact for this OS (`dir`) into the folder `dir`
|
||||
# get the .zip files in args.path_to_directory using glob
|
||||
print(f"Processing artifacts in {args.path_to_directory}")
|
||||
build_types_created = set()
|
||||
zips = glob.glob(f"{args.path_to_directory}/*.zip")
|
||||
for file in zips:
|
||||
# print(f"unzipping {file}")
|
||||
#extract first word (delimited by '-' from the file name)
|
||||
# build_type is a fullpath but we only want the last folder, remove the leading part of the path leaving just the foldername using basename
|
||||
filename = os.path.basename(file)
|
||||
build_type = filename.split("-")[0]
|
||||
platform = filename.split("-")[1].lower()
|
||||
|
||||
# print(f"build_type is {build_type}")
|
||||
if build_type not in build_types:
|
||||
print(f"Invalid build_type {build_type} using file {file}")
|
||||
continue
|
||||
else:
|
||||
build_folder = build_types[build_type]
|
||||
|
||||
build_types_created.add(build_type)
|
||||
|
||||
build_type_dir = os.path.join(args.path_to_directory, build_folder)
|
||||
|
||||
if platform not in target_folder:
|
||||
print(f"Invalid platform {platform} using file {file}")
|
||||
continue
|
||||
|
||||
unpack_folder = os.path.join(build_type_dir, target_folder[platform])
|
||||
print(f"unpacking {filename} to {unpack_folder}")
|
||||
|
||||
if os.path.isfile(file):
|
||||
# this is an actual zip file
|
||||
unzip_file(file, unpack_folder)
|
||||
else:
|
||||
# Create the destination folder if it doesn't exist
|
||||
# if not os.path.exists(unpack_folder):
|
||||
# os.makedirs(unpack_folder)
|
||||
# Copy the contents of the source folder to the destination folder recursively
|
||||
shutil.copytree(file, unpack_folder, dirs_exist_ok=True)
|
||||
|
||||
output = ""
|
||||
for build_type in build_types_created:
|
||||
build_type_dir = os.path.join(args.path_to_directory, build_types[build_type])
|
||||
if not os.path.exists(build_type_dir):
|
||||
print(f"Unexpected error: {build_type_dir} does not exist, even though it was in the set.")
|
||||
continue
|
||||
# loop over the folder in the build_type_dir
|
||||
for dir in dirs:
|
||||
flatten_tree(os.path.join(args.path_to_directory, dir))
|
||||
print(f"Cleaning up {dir}")
|
||||
# Traverse the directory tree and move all of the files to the root directory
|
||||
flatten_tree(os.path.join(build_type_dir, dir))
|
||||
# Now move the symbols files to the symbols folder
|
||||
symbols_folder = os.path.join(args.path_to_directory, "symbols")
|
||||
# prep the symbols folder
|
||||
symbols_folder = os.path.join(build_type_dir, "symbols")
|
||||
os.mkdir(symbols_folder)
|
||||
# Traverse the directory tree and move all of the files to the root directory
|
||||
symbol_archives = glob.glob(f"{args.path_to_directory}/**/*_hvk*", recursive=True)
|
||||
symbol_archives = glob.glob(f"{build_type_dir}/**/*_hvk*", recursive=True)
|
||||
for sym_file in symbol_archives:
|
||||
print(f"Moving {sym_file} to {symbols_folder}")
|
||||
shutil.move(sym_file, symbols_folder)
|
||||
symbol_archives = glob.glob(f"{args.path_to_directory}/**/*_oss*", recursive=True)
|
||||
symbol_archives = glob.glob(f"{build_type_dir}/**/*_oss*", recursive=True)
|
||||
for sym_file in symbol_archives:
|
||||
print(f"Moving {sym_file} to {symbols_folder}")
|
||||
shutil.move(sym_file, symbols_folder)
|
||||
|
||||
|
||||
file_dict = {}
|
||||
md5_dict = {}
|
||||
# While we're at it, let's print the md5 listing
|
||||
file_dict = {}
|
||||
md5_dict = {}
|
||||
platforms_printable = {"windows":"MS Windows", "mac":"MacOS", "linux":"Linux"}
|
||||
grids_printable = {"SL":"Second Life", "OS":"OpenSim"}
|
||||
|
||||
for dir in dirs:
|
||||
dir = dir.lower()
|
||||
files = get_files(os.path.join(args.path_to_directory, dir))
|
||||
for file in files:
|
||||
full_file = os.path.join(args.path_to_directory, dir, file)
|
||||
md5 = get_md5(full_file)
|
||||
base_name = os.path.basename(file)
|
||||
if "-Release-" in base_name or "-Beta-" in base_name:
|
||||
wordsize = "32"
|
||||
else:
|
||||
wordsize = "64"
|
||||
|
||||
if "FirestormOS-" in base_name:
|
||||
grid = "OS"
|
||||
else:
|
||||
grid = "SL"
|
||||
|
||||
if dir in dirs:
|
||||
file_dict[f"{grid}{dir}{wordsize}"] = full_file
|
||||
md5_dict[f"{grid}{dir}{wordsize}"] = md5
|
||||
|
||||
download_root_preview = "https://downloads.firestormviewer.org/preview"
|
||||
download_root_release = "https://downloads.firestormviewer.org/release"
|
||||
|
||||
if args.release:
|
||||
download_root = download_root_release
|
||||
else:
|
||||
download_root = download_root_preview
|
||||
|
||||
print('''
|
||||
DOWNLOADS''')
|
||||
|
||||
platforms_printable = {"windows":"MS Windows", "mac":"MacOS", "linux":"Linux"}
|
||||
grids_printable = {"SL":"Second Life", "OS":"OpenSim"}
|
||||
|
||||
for dir in dirs:
|
||||
print(f'''-------------------------------------------------------------------------------------------------------
|
||||
{platforms_printable[dir]}
|
||||
''')
|
||||
dir=dir.lower()
|
||||
wordsize = "64"
|
||||
platform = f"{platforms_printable[dir]}"
|
||||
for grid in ["SL", "OS"]:
|
||||
grid_printable = f"{grids_printable[grid]}"
|
||||
download_root = f"https://downloads.firestormviewer.org/{build_types[build_type]}/"
|
||||
for dir in dirs:
|
||||
print(f"Getting files for {dir} in {build_type_dir}")
|
||||
files = get_files(os.path.join(build_type_dir, dir))
|
||||
try:
|
||||
print (f"{platform} for {grid_printable} ({wordsize}-bit)")
|
||||
print ( "{}/{}/{}".format(download_root,dir,os.path.basename(file_dict[f"{grid}{dir}{wordsize}"])) )
|
||||
print ()
|
||||
print ( "MD5: {}".format(md5_dict[f"{grid}{dir}{wordsize}"]) )
|
||||
print ()
|
||||
if(dir == "windows"):
|
||||
# Need to do 32 bit as well
|
||||
wordsize = "32"
|
||||
print (f"{platform} for {grid_printable} ({wordsize}-bit)")
|
||||
print ( "{}/{}/{}".format(download_root,dir,os.path.basename(file_dict[f"{grid}{dir}{wordsize}"])) )
|
||||
print ()
|
||||
print ( "MD5: {}".format(md5_dict[f"{grid}{dir}{wordsize}"]) )
|
||||
print ()
|
||||
wordsize = "64"
|
||||
except KeyError:
|
||||
print (f"{platform} for {grid_printable} ({wordsize}-bit) - NOT AVAILABLE")
|
||||
print ()
|
||||
for file in files:
|
||||
full_file = os.path.join(build_type_dir, dir, file)
|
||||
md5 = get_md5(full_file)
|
||||
base_name = os.path.basename(file)
|
||||
if "x64" in base_name:
|
||||
wordsize = "64"
|
||||
else:
|
||||
wordsize = "32"
|
||||
|
||||
if "FirestormOS-" in base_name:
|
||||
grid = "OS"
|
||||
else:
|
||||
grid = "SL"
|
||||
|
||||
print('''
|
||||
-------------------------------------------------------------------------------------------------------''')
|
||||
if dir in dirs:
|
||||
file_dict[f"{grid}{dir}{wordsize}"] = full_file
|
||||
md5_dict[f"{grid}{dir}{wordsize}"] = md5
|
||||
except TypeError:
|
||||
print(f"No files found for {dir} in {build_type_dir}")
|
||||
|
||||
|
||||
output += f'''
|
||||
DOWNLOADS - {build_type}
|
||||
'''
|
||||
|
||||
output += f'''-------------------------------------------------------------------------------------------------------
|
||||
{platforms_printable[dir]}
|
||||
'''
|
||||
dir = dir.lower()
|
||||
wordsize = "64"
|
||||
platform = f"{platforms_printable[dir]}"
|
||||
for grid in ["SL", "OS"]:
|
||||
grid_printable = f"{grids_printable[grid]}"
|
||||
try:
|
||||
output += f"{platform} for {grid_printable} ({wordsize}-bit)\n"
|
||||
output += f"{download_root}/{dir}/{os.path.basename(file_dict[f'{grid}{dir}{wordsize}'])}\n"
|
||||
output += "\n"
|
||||
output += f"MD5: {md5_dict[f'{grid}{dir}{wordsize}']}\n"
|
||||
output += "\n"
|
||||
if dir == "windows":
|
||||
# Need to do 32 bit as well
|
||||
wordsize = "32"
|
||||
output += f"{platform} for {grid_printable} ({wordsize}-bit)\n"
|
||||
output += f"{download_root}/{dir}/{os.path.basename(file_dict[f'{grid}{dir}{wordsize}'])}\n"
|
||||
output += "\n"
|
||||
output += f"MD5: {md5_dict[f'{grid}{dir}{wordsize}']}\n"
|
||||
output += "\n"
|
||||
wordsize = "64"
|
||||
except KeyError:
|
||||
output += f"{platform} for {grid_printable} ({wordsize}-bit) - NOT AVAILABLE\n"
|
||||
output += "\n"
|
||||
output += '''
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
'''
|
||||
|
||||
if args.webhook:
|
||||
# Add the message to the webhook
|
||||
webhook.set_content(content=output)
|
||||
# Send the webhook
|
||||
response = webhook.execute()
|
||||
# Print the response
|
||||
print(f"Webhook response: {response}")
|
||||
print(output)
|
||||
|
||||
|
|
|
|||
|
|
@ -290,6 +290,20 @@ F32 LLSettingsWater::getModifiedWaterFogDensity(bool underwater) const
|
|||
if (underwater && underwater_fog_mod > 0.0f)
|
||||
{
|
||||
underwater_fog_mod = llclamp(underwater_fog_mod, 0.0f, 10.0f);
|
||||
// <FS:Beq> BUG-233797/BUG-233798 -ve underwater fog density can cause (unrecoverable) blackout.
|
||||
// raising a negative number to a non-integral power results in a non-real result (which is NaN for our purposes)
|
||||
// Two methods were tested, number 2 is being used:
|
||||
// 1) Force the fog_mod to be integral. The effect is unlikely to be nice, but it is better than blackness.
|
||||
// In this method a few of the combinations are "usable" but the water colour is effectively inverted (blue becomes yellow)
|
||||
// this seems to be unlikely to be a desirable use case for the majority.
|
||||
// 2) Force density to be an arbitrary non-negative (i.e. 1) when underwater and modifier is not an integer (1 was aribtrarily chosen as it gives at least some notion of fog in the transition)
|
||||
// This is more restrictive, effectively forcing a density under certain conditions, but allowing the range of #1 and avoiding blackness in other cases
|
||||
// at the cost of overriding the fog density.
|
||||
if(fog_density < 0.0f && underwater_fog_mod != (F32)llround(underwater_fog_mod) )
|
||||
{
|
||||
fog_density = 1.0f;
|
||||
}
|
||||
// </FS:Beq>
|
||||
fog_density = pow(fog_density, underwater_fog_mod);
|
||||
}
|
||||
return fog_density;
|
||||
|
|
|
|||
|
|
@ -103,18 +103,18 @@ NACLAntiSpamQueueEntry* NACLAntiSpamQueue::getEntry(const LLUUID& source)
|
|||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NACLAntiSpamQueue::clearEntries()
|
||||
{
|
||||
for (spam_queue_entry_map_t::iterator it = mEntries.begin(); it != mEntries.end(); ++it)
|
||||
for (auto& [id, entry] : mEntries)
|
||||
{
|
||||
//AO: Only clear entries that are not blocked.
|
||||
if (!it->second->getBlocked())
|
||||
if (!entry->getBlocked())
|
||||
{
|
||||
it->second->clearEntry();
|
||||
entry->clearEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -139,15 +139,14 @@ void NACLAntiSpamQueue::blockEntry(const LLUUID& source)
|
|||
mEntries[source]->setBlocked();
|
||||
}
|
||||
|
||||
S32 NACLAntiSpamQueue::checkEntry(const LLUUID& name, U32 multiplier)
|
||||
// Returns 0 if unblocked, 1 if check results in a new block, 2 if by an existing block
|
||||
EAntispamCheckResult NACLAntiSpamQueue::checkEntry(const LLUUID& name, U32 multiplier)
|
||||
{
|
||||
spam_queue_entry_map_t::iterator it = mEntries.find(name);
|
||||
if (it != mEntries.end())
|
||||
{
|
||||
if (it->second->getBlocked())
|
||||
{
|
||||
return 2;
|
||||
return EAntispamCheckResult::ExistingBlock;
|
||||
}
|
||||
U32 eTime = it->second->getEntryTime();
|
||||
U32 currentTime = time(0);
|
||||
|
|
@ -158,11 +157,11 @@ S32 NACLAntiSpamQueue::checkEntry(const LLUUID& name, U32 multiplier)
|
|||
if (eAmount > (mQueueAmount * multiplier))
|
||||
{
|
||||
it->second->setBlocked();
|
||||
return 1;
|
||||
return EAntispamCheckResult::NewBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return EAntispamCheckResult::Unblocked;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -170,7 +169,7 @@ S32 NACLAntiSpamQueue::checkEntry(const LLUUID& name, U32 multiplier)
|
|||
it->second->clearEntry();
|
||||
it->second->updateEntryAmount();
|
||||
it->second->updateEntryTime();
|
||||
return 0;
|
||||
return EAntispamCheckResult::Unblocked;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -180,7 +179,7 @@ S32 NACLAntiSpamQueue::checkEntry(const LLUUID& name, U32 multiplier)
|
|||
entry->updateEntryAmount();
|
||||
entry->updateEntryTime();
|
||||
mEntries[name] = entry;
|
||||
return 0;
|
||||
return EAntispamCheckResult::Unblocked;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +218,7 @@ NACLAntiSpamRegistry::~NACLAntiSpamRegistry()
|
|||
|
||||
const char* NACLAntiSpamRegistry::getQueueName(EAntispamQueue queue)
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
@ -228,7 +227,7 @@ const char* NACLAntiSpamRegistry::getQueueName(EAntispamQueue queue)
|
|||
|
||||
void NACLAntiSpamRegistry::setRegisteredQueueTime(EAntispamQueue queue, U32 time)
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return;
|
||||
|
|
@ -239,7 +238,7 @@ void NACLAntiSpamRegistry::setRegisteredQueueTime(EAntispamQueue queue, U32 time
|
|||
|
||||
void NACLAntiSpamRegistry::setRegisteredQueueAmount(EAntispamQueue queue, U32 amount)
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return;
|
||||
|
|
@ -283,7 +282,7 @@ void NACLAntiSpamRegistry::setAllQueueAmounts(U32 amount)
|
|||
|
||||
void NACLAntiSpamRegistry::clearRegisteredQueue(EAntispamQueue queue)
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return;
|
||||
|
|
@ -294,7 +293,7 @@ void NACLAntiSpamRegistry::clearRegisteredQueue(EAntispamQueue queue)
|
|||
|
||||
void NACLAntiSpamRegistry::purgeRegisteredQueue(EAntispamQueue queue)
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return;
|
||||
|
|
@ -317,7 +316,7 @@ void NACLAntiSpamRegistry::blockOnQueue(EAntispamQueue queue, const LLUUID& sour
|
|||
}
|
||||
else
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return;
|
||||
|
|
@ -362,14 +361,14 @@ bool NACLAntiSpamRegistry::checkQueue(EAntispamQueue queue, const LLUUID& source
|
|||
}
|
||||
}
|
||||
|
||||
S32 result = 0;
|
||||
EAntispamCheckResult result{ EAntispamCheckResult::Unblocked };
|
||||
if (mGlobalQueue)
|
||||
{
|
||||
result = checkGlobalEntry(source, multiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return false;
|
||||
|
|
@ -377,17 +376,17 @@ bool NACLAntiSpamRegistry::checkQueue(EAntispamQueue queue, const LLUUID& source
|
|||
result = mQueues[queue]->checkEntry(source, multiplier);
|
||||
}
|
||||
|
||||
if (result == 0) // safe
|
||||
if (result == EAntispamCheckResult::Unblocked) // safe
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result == 2) // previously blocked
|
||||
if (result == EAntispamCheckResult::ExistingBlock) // previously blocked
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result == 1) // newly blocked, result == 1
|
||||
if (result == EAntispamCheckResult::NewBlock) // newly blocked, result == 1
|
||||
{
|
||||
if (!LLMuteList::getInstance()->isMuted(source))
|
||||
{
|
||||
|
|
@ -402,16 +401,14 @@ bool NACLAntiSpamRegistry::checkQueue(EAntispamQueue queue, const LLUUID& source
|
|||
{
|
||||
bool sent = false;
|
||||
|
||||
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
|
||||
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
|
||||
for (auto region : LLWorld::getInstance()->getRegionList())
|
||||
{
|
||||
LLViewerRegion* region = *iter;
|
||||
if (gMessageSystem && region && region->isAlive())
|
||||
{
|
||||
gMessageSystem->newMessage(_PREHASH_RequestObjectPropertiesFamily);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
|
||||
gMessageSystem->addU32Fast(_PREHASH_RequestFlags, 0);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_ObjectID, source);
|
||||
|
|
@ -499,7 +496,7 @@ bool NACLAntiSpamRegistry::isBlockedOnQueue(EAntispamQueue queue, const LLUUID&
|
|||
}
|
||||
else
|
||||
{
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || mQueues[queue] == NULL)
|
||||
if (queue >= ANTISPAM_QUEUE_MAX || queue < ANTISPAM_QUEUE_CHAT || mQueues[queue] == nullptr)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was not created or was outside of the reasonable range of queues. Queue: " << getQueueName(queue) << LL_ENDL;
|
||||
return false;
|
||||
|
|
@ -547,12 +544,11 @@ void NACLAntiSpamRegistry::clearAllQueues()
|
|||
|
||||
void NACLAntiSpamRegistry::purgeAllQueues()
|
||||
{
|
||||
std::map<LLUUID, LLAvatarNameCache::callback_connection_t>::iterator it = mAvatarNameCallbackConnections.begin();
|
||||
for (; it != mAvatarNameCallbackConnections.end(); ++it)
|
||||
for (auto& [avid, callback] : mAvatarNameCallbackConnections)
|
||||
{
|
||||
if (it->second.connected())
|
||||
if (callback.connected())
|
||||
{
|
||||
it->second.disconnect();
|
||||
callback.disconnect();
|
||||
}
|
||||
}
|
||||
mAvatarNameCallbackConnections.clear();
|
||||
|
|
@ -574,14 +570,14 @@ void NACLAntiSpamRegistry::purgeAllQueues()
|
|||
mObjectData.clear();
|
||||
}
|
||||
|
||||
S32 NACLAntiSpamRegistry::checkGlobalEntry(const LLUUID& source, U32 multiplier)
|
||||
EAntispamCheckResult NACLAntiSpamRegistry::checkGlobalEntry(const LLUUID& source, U32 multiplier)
|
||||
{
|
||||
spam_queue_entry_map_t::iterator it = mGlobalEntries.find(source);
|
||||
if (it != mGlobalEntries.end())
|
||||
{
|
||||
if (it->second->getBlocked())
|
||||
{
|
||||
return 2;
|
||||
return EAntispamCheckResult::ExistingBlock;
|
||||
}
|
||||
|
||||
U32 eTime = it->second->getEntryTime();
|
||||
|
|
@ -592,11 +588,11 @@ S32 NACLAntiSpamRegistry::checkGlobalEntry(const LLUUID& source, U32 multiplier)
|
|||
U32 eAmount = it->second->getEntryAmount();
|
||||
if (eAmount > (mGlobalAmount * multiplier))
|
||||
{
|
||||
return 1;
|
||||
return EAntispamCheckResult::NewBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return EAntispamCheckResult::Unblocked;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -604,7 +600,7 @@ S32 NACLAntiSpamRegistry::checkGlobalEntry(const LLUUID& source, U32 multiplier)
|
|||
it->second->clearEntry();
|
||||
it->second->updateEntryAmount();
|
||||
it->second->updateEntryTime();
|
||||
return 0;
|
||||
return EAntispamCheckResult::Unblocked;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -613,15 +609,15 @@ S32 NACLAntiSpamRegistry::checkGlobalEntry(const LLUUID& source, U32 multiplier)
|
|||
entry->updateEntryAmount();
|
||||
entry->updateEntryTime();
|
||||
mGlobalEntries[source] = entry;
|
||||
return 0;
|
||||
return EAntispamCheckResult::Unblocked;
|
||||
}
|
||||
}
|
||||
|
||||
void NACLAntiSpamRegistry::clearGlobalEntries()
|
||||
{
|
||||
for (spam_queue_entry_map_t::iterator it = mGlobalEntries.begin(); it != mGlobalEntries.end(); ++it)
|
||||
for (auto& [id, entry] : mGlobalEntries)
|
||||
{
|
||||
it->second->clearEntry();
|
||||
entry->clearEntry();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef NACL_ANTISPAM_H
|
||||
#define NACL_ANTISPAM_H
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "llsingleton.h"
|
||||
#include "llavatarnamecache.h"
|
||||
|
||||
|
|
@ -25,6 +25,14 @@ typedef enum e_antispam_source_type
|
|||
ANTISPAM_SOURCE_OBJECT
|
||||
} EAntispamSource;
|
||||
|
||||
|
||||
enum class EAntispamCheckResult
|
||||
{
|
||||
Unblocked,
|
||||
NewBlock,
|
||||
ExistingBlock
|
||||
};
|
||||
|
||||
struct AntispamObjectData
|
||||
{
|
||||
std::string mName;
|
||||
|
|
@ -58,8 +66,8 @@ private:
|
|||
bool mBlocked;
|
||||
};
|
||||
|
||||
typedef boost::unordered_map<LLUUID, NACLAntiSpamQueueEntry*, FSUUIDHash> spam_queue_entry_map_t;
|
||||
typedef boost::unordered_set<LLUUID, FSUUIDHash> collision_sound_set_t;
|
||||
typedef std::unordered_map<LLUUID, NACLAntiSpamQueueEntry*, FSUUIDHash> spam_queue_entry_map_t;
|
||||
typedef std::unordered_set<LLUUID, FSUUIDHash> collision_sound_set_t;
|
||||
|
||||
class NACLAntiSpamQueue
|
||||
{
|
||||
|
|
@ -77,7 +85,7 @@ protected:
|
|||
void setTime(U32 time);
|
||||
|
||||
void blockEntry(const LLUUID& source);
|
||||
S32 checkEntry(const LLUUID& source, U32 multiplier);
|
||||
EAntispamCheckResult checkEntry(const LLUUID& source, U32 multiplier);
|
||||
NACLAntiSpamQueueEntry* getEntry(const LLUUID& source);
|
||||
|
||||
void clearEntries();
|
||||
|
|
@ -119,7 +127,7 @@ private:
|
|||
const char* getQueueName(EAntispamQueue queue);
|
||||
|
||||
void blockGlobalEntry(const LLUUID& source);
|
||||
S32 checkGlobalEntry(const LLUUID& source, U32 multiplier);
|
||||
EAntispamCheckResult checkGlobalEntry(const LLUUID& source, U32 multiplier);
|
||||
|
||||
void clearGlobalEntries();
|
||||
void purgeGlobalEntries();
|
||||
|
|
|
|||
|
|
@ -164,6 +164,49 @@ BOOL LLFloaterImagePreview::postBuild()
|
|||
}
|
||||
getChild<LLCheckBoxCtrl>("temp_check")->setVisible(enable_temp_uploads);
|
||||
// </FS:CR>
|
||||
|
||||
// <FS:Zi> detect and strip empty alpha layers from images on upload
|
||||
getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterImagePreview::onBtnUpload, this));
|
||||
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[X_RES]", llformat("%d", mRawImagep->getWidth()));
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[Y_RES]", llformat("%d", mRawImagep->getHeight()));
|
||||
|
||||
mEmptyAlphaCheck = getChild<LLCheckBoxCtrl>("strip_alpha_check");
|
||||
|
||||
if (mRawImagep->getComponents() != 4)
|
||||
{
|
||||
getChild<LLUICtrl>("image_alpha_warning")->setVisible(false);
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[ALPHA]", getString("no_alpha"));
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 imageBytes = mRawImagep->getWidth() * mRawImagep->getHeight() * 4;
|
||||
|
||||
U32 emptyAlphaCount = 0;
|
||||
U8* data = mRawImagep->getData();
|
||||
for (U32 i = 3; i < imageBytes; i += 4)
|
||||
{
|
||||
if (data[i] > ALPHA_EMPTY_THRESHOLD)
|
||||
{
|
||||
emptyAlphaCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyAlphaCount > (imageBytes / 4 * ALPHA_EMPTY_THRESHOLD_RATIO))
|
||||
{
|
||||
getChild<LLUICtrl>("image_alpha_warning")->setVisible(true);
|
||||
|
||||
mEmptyAlphaCheck->setCommitCallback(boost::bind(&LLFloaterImagePreview::emptyAlphaCheckboxCallback, this));
|
||||
mEmptyAlphaCheck->setValue(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild<LLUICtrl>("image_alpha_warning")->setVisible(false);
|
||||
mEmptyAlphaCheck->setValue(false);
|
||||
}
|
||||
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[ALPHA]", getString(mEmptyAlphaCheck->getValue() ? "no_alpha" : "with_alpha"));
|
||||
// </FS:Zi>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -181,47 +224,6 @@ BOOL LLFloaterImagePreview::postBuild()
|
|||
|
||||
// <FS:Zi> detect and strip empty alpha layers from images on upload
|
||||
// getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
|
||||
getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterImagePreview::onBtnUpload, this));
|
||||
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[X_RES]", llformat("%d", mRawImagep->getWidth()));
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[Y_RES]", llformat("%d", mRawImagep->getHeight()));
|
||||
|
||||
mEmptyAlphaCheck = getChild<LLCheckBoxCtrl>("strip_alpha_check");
|
||||
|
||||
if (mRawImagep->getComponents() != 4)
|
||||
{
|
||||
getChild<LLUICtrl>("image_alpha_warning")->setVisible(false);
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[ALPHA]", getString("no_alpha"));
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 imageBytes = mRawImagep->getWidth() * mRawImagep->getHeight() * 4;
|
||||
|
||||
U32 emptyAlphaCount = 0;
|
||||
U8* data = mRawImagep->getData();
|
||||
for (U32 i = 3; i < imageBytes; i += 4)
|
||||
{
|
||||
if (data[i] > ALPHA_EMPTY_THRESHOLD)
|
||||
{
|
||||
emptyAlphaCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyAlphaCount > (imageBytes / 4 * ALPHA_EMPTY_THRESHOLD_RATIO))
|
||||
{
|
||||
getChild<LLUICtrl>("image_alpha_warning")->setVisible(true);
|
||||
|
||||
mEmptyAlphaCheck->setCommitCallback(boost::bind(&LLFloaterImagePreview::emptyAlphaCheckboxCallback, this));
|
||||
mEmptyAlphaCheck->setValue(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild<LLUICtrl>("image_alpha_warning")->setVisible(false);
|
||||
mEmptyAlphaCheck->setValue(false);
|
||||
}
|
||||
|
||||
getChild<LLUICtrl>("uploaded_size_text")->setTextArg("[ALPHA]", getString(mEmptyAlphaCheck->getValue() ? "no_alpha" : "with_alpha"));
|
||||
// </FS:Zi>
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,15 +86,18 @@ void LLPanelProfileTab::setAvatarId(const LLUUID& avatar_id)
|
|||
mSelfProfile = (getAvatarId() == gAgentID);
|
||||
|
||||
// <FS:Zi> FIRE-32179: Make drag-n-drop sharing of items possible again
|
||||
LLProfileDropTarget* target = getChild<LLProfileDropTarget>("drop_target");
|
||||
if (avatar_id == gAgentID)
|
||||
LLProfileDropTarget* target = findChild<LLProfileDropTarget>("drop_target");
|
||||
if (target)
|
||||
{
|
||||
// hide drop target on own profile
|
||||
target->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->setAgentID(avatar_id);
|
||||
if (avatar_id == gAgentID)
|
||||
{
|
||||
// hide drop target on own profile
|
||||
target->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->setAgentID(avatar_id);
|
||||
}
|
||||
}
|
||||
// </FS:Zi>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1201,7 +1201,9 @@ void LLPanelProfileSecondLife::resetData()
|
|||
resetLoading();
|
||||
|
||||
// Set default image and 1:1 dimensions for it
|
||||
mSecondLifePic->setValue("Generic_Person_Large");
|
||||
// <FS:Ansariel> Retain texture picker for profile images
|
||||
//mSecondLifePic->setValue("Generic_Person_Large");
|
||||
mSecondLifePic->setImageAssetID(LLUUID::null);
|
||||
mImageId = LLUUID::null;
|
||||
|
||||
// <FS:Ansariel> Fix LL UI/UX design accident
|
||||
|
|
@ -3028,7 +3030,9 @@ void LLPanelProfileFirstLife::apply(LLAvatarData* data)
|
|||
void LLPanelProfileFirstLife::resetData()
|
||||
{
|
||||
setDescriptionText(std::string());
|
||||
mPicture->setValue("Generic_Person_Large");
|
||||
// <FS:Ansariel> Retain texture picker for profile images
|
||||
//mPicture->setValue("Generic_Person_Large");
|
||||
mPicture->setImageAssetID(LLUUID::null);
|
||||
mImageId = LLUUID::null;
|
||||
|
||||
// <FS:Beq> remove the buttons and just have click image to update profile
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
/>
|
||||
<texture_picker
|
||||
name="real_world_pic"
|
||||
image_name="Generic_Person_Large"
|
||||
fallback_image="Generic_Person_Large"
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
show_caption="false"
|
||||
|
|
|
|||
|
|
@ -353,6 +353,7 @@
|
|||
user_resize="false">
|
||||
<texture_picker
|
||||
name="2nd_life_pic"
|
||||
fallback_image="Generic_Person_Large"
|
||||
top="0"
|
||||
left="0"
|
||||
width="158"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,13 @@
|
|||
<check_box label="Включено" name="enable_media"/>
|
||||
<slider label="Голосовой чат" name="Voice Volume"/>
|
||||
<check_box label="Включено" name="enable_voice_check_volume"/>
|
||||
<text name="Listen media from" width="200">
|
||||
Слышать мультимедиа и звуки из:
|
||||
</text>
|
||||
<radio_group name="media_ear_location">
|
||||
<radio_item label="Позиции камеры" name="0"/>
|
||||
<radio_item label="Позиции аватара" name="1"/>
|
||||
</radio_group>
|
||||
<text name="auto_unmute_label" width="300">
|
||||
Автоматически включать звук после телепортации:
|
||||
</text>
|
||||
|
|
@ -51,7 +58,7 @@
|
|||
</panel>
|
||||
<panel name="Media Media Panel" label="Медиа">
|
||||
<text name="media_autoplay_label" width="130">
|
||||
Автовоспроизведение
|
||||
Автовоспроизведение
|
||||
</text>
|
||||
<combo_box name="media_auto_play_combo" width="100">
|
||||
<item label="Запрещено" name="autoplay_disabled"/>
|
||||
|
|
|
|||
|
|
@ -1,574 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<panel
|
||||
top="0"
|
||||
left="0"
|
||||
width="420"
|
||||
height="480"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="panel_profile"
|
||||
label="Profile">
|
||||
<string
|
||||
name="status_online">
|
||||
Online
|
||||
</string>
|
||||
<string
|
||||
name="status_offline">
|
||||
Offline
|
||||
</string>
|
||||
<string
|
||||
name="CaptionTextAcctInfo">
|
||||
[ACCTTYPE]
|
||||
[PAYMENTINFO]
|
||||
[FIRESTORM][FSDEV][FSSUPP][FSQA][FSGW]
|
||||
</string>
|
||||
<!-- [AGEVERIFICATION] moved out of the above, since it's not set anyway. See
|
||||
LLPanelAvatarProfile::fillAccountStatus() ...TS -->
|
||||
<string
|
||||
name="payment_update_link_url">
|
||||
http://www.secondlife.com/account/billing.php?lang=en
|
||||
</string>
|
||||
<string
|
||||
name="partner_edit_link_url">
|
||||
http://www.secondlife.com/account/partners.php?lang=en
|
||||
</string>
|
||||
<string
|
||||
name="my_account_link_url"
|
||||
value="http://secondlife.com/account" />
|
||||
<string
|
||||
name="no_partner_text"
|
||||
value="None" />
|
||||
<string
|
||||
name="no_group_text"
|
||||
value="None" />
|
||||
<string
|
||||
name="RegisterDateFormat">
|
||||
[REG_DATE]
|
||||
([AGE])
|
||||
</string>
|
||||
<string
|
||||
name="name_text_args">
|
||||
[NAME]
|
||||
</string>
|
||||
<string
|
||||
name="display_name_text_args">
|
||||
[DISPLAY_NAME]
|
||||
</string>
|
||||
<string
|
||||
name="FSDev"
|
||||
value=" Developer" />
|
||||
<string
|
||||
name="FSSupp"
|
||||
value=" Support" />
|
||||
<string
|
||||
name="FSQualityAssurance"
|
||||
value=" Bug Hunter" />
|
||||
<string
|
||||
name="FSGW"
|
||||
value=" Gateway" />
|
||||
|
||||
<!--
|
||||
|
||||
KC: Use view_border's around text_editor's due to text render issues with border_visible
|
||||
|
||||
-->
|
||||
|
||||
<loading_indicator
|
||||
top="4"
|
||||
right="-10"
|
||||
height="23"
|
||||
width="23"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="progress_indicator"
|
||||
visible="false" />
|
||||
|
||||
<text
|
||||
top="8"
|
||||
left="6"
|
||||
height="16"
|
||||
width="40"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="Name:"
|
||||
halign="right"
|
||||
value="Name:" />
|
||||
|
||||
<view_border
|
||||
left_pad="4"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
bottom_delta="2"
|
||||
left_delta="3"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="complete_name"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="0"
|
||||
v_pad="0"
|
||||
enabled="false"
|
||||
max_length="254"
|
||||
value="(loading...)" />
|
||||
|
||||
<button
|
||||
left_pad="2"
|
||||
height="20"
|
||||
width="20"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="set_name"
|
||||
image_overlay="Edit_Wrench"
|
||||
tool_tip="Set Display Name"
|
||||
visible="false"
|
||||
enabled="false" />
|
||||
|
||||
<text
|
||||
top_pad="2"
|
||||
left="6"
|
||||
height="16"
|
||||
width="40"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="Key:"
|
||||
halign="right"
|
||||
value="Key:" />
|
||||
|
||||
<view_border
|
||||
left_pad="4"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border2"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
bottom_delta="2"
|
||||
left_delta="3"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="user_key"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="0"
|
||||
v_pad="0"
|
||||
enabled="false"
|
||||
max_length="254"
|
||||
value="(loading...)" />
|
||||
|
||||
<text
|
||||
left_pad="2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="status"
|
||||
halign="center"
|
||||
value="" />
|
||||
|
||||
<button
|
||||
top_delta="-2"
|
||||
right="-6"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="copy_own_uri_button"
|
||||
label="Copy URI" />
|
||||
|
||||
<texture_picker
|
||||
top_pad="3"
|
||||
left="6"
|
||||
height="180"
|
||||
width="220"
|
||||
layout="topleft"
|
||||
follows="top|left"
|
||||
allow_no_texture="true"
|
||||
name="2nd_life_pic"
|
||||
default_image_name="None"
|
||||
enabled="false"
|
||||
fallback_image="Generic_Person_Large" />
|
||||
|
||||
<text
|
||||
top_pad="-179"
|
||||
left_pad="4"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="label"
|
||||
value="Born:" />
|
||||
|
||||
<view_border
|
||||
top_pad="0"
|
||||
left_delta="0"
|
||||
right="-6"
|
||||
height="32"
|
||||
name="info_border3"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
top_delta="2"
|
||||
left_delta="2"
|
||||
right="-6"
|
||||
height="28"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="register_date"
|
||||
max_length="254"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="2"
|
||||
v_pad="0"
|
||||
read_only="true"
|
||||
translate="false"
|
||||
word_wrap="true"/>
|
||||
|
||||
<text
|
||||
top_pad="7"
|
||||
left_delta="-2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="label2"
|
||||
value="Account:" />
|
||||
|
||||
<view_border
|
||||
top_pad="0"
|
||||
left_delta="0"
|
||||
right="-6"
|
||||
height="48"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="acct_border"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
top_delta="2"
|
||||
left_delta="2"
|
||||
right="-6"
|
||||
height="44"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="acc_status_text"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="2"
|
||||
v_pad="0"
|
||||
read_only="true"
|
||||
translate="false"
|
||||
word_wrap="true"/>
|
||||
|
||||
<text
|
||||
top_pad="7"
|
||||
left_delta="-2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="partner_label"
|
||||
value="Partner:" />
|
||||
|
||||
<view_border
|
||||
top_pad="0"
|
||||
left_delta="0"
|
||||
right="-6"
|
||||
height="18"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border4"
|
||||
bevel_style="none" />
|
||||
<text
|
||||
icon_positioning="left"
|
||||
top_delta="2"
|
||||
left_delta="2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="partner_text"
|
||||
max_length="254" />
|
||||
<!--
|
||||
<button
|
||||
top_pad="8"
|
||||
left="6"
|
||||
height="18"
|
||||
width="40"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="bigimg"
|
||||
halign="center"
|
||||
label="< <"
|
||||
label_selected="> >"
|
||||
tool_tip="Open Full Size." />
|
||||
-->
|
||||
<text
|
||||
top_pad="8"
|
||||
left="6"
|
||||
height="16"
|
||||
width="55"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="Groups:"
|
||||
halign="right"
|
||||
value="Groups:" />
|
||||
|
||||
<button
|
||||
top_delta="20"
|
||||
left="40"
|
||||
height="20"
|
||||
width="20"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="group_invite"
|
||||
label="+"
|
||||
label_selected="+"
|
||||
tool_tip="Invite to Group" />
|
||||
|
||||
<view_border
|
||||
top_delta="-20"
|
||||
left="66"
|
||||
right="-6"
|
||||
height="80"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border_group_list"
|
||||
bevel_style="none" />
|
||||
<group_list
|
||||
top_delta="1"
|
||||
left_delta="1"
|
||||
right="-7"
|
||||
height="78"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="group_list"
|
||||
border_visible="false"
|
||||
for_agent="false" />
|
||||
|
||||
<text
|
||||
top_pad="8"
|
||||
left="6"
|
||||
height="16"
|
||||
width="55"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="About:"
|
||||
halign="right"
|
||||
value="About:" />
|
||||
|
||||
<view_border
|
||||
top_delta="0"
|
||||
left="66"
|
||||
right="-6"
|
||||
height="102"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="info_border5"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
top_delta="1"
|
||||
left_delta="1"
|
||||
right="-7"
|
||||
height="100"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="sl_description_edit"
|
||||
border_visible="false"
|
||||
font="SansSerifSmall"
|
||||
enabled="false"
|
||||
trusted_content="false"
|
||||
max_length="65000"
|
||||
h_pad="2"
|
||||
word_wrap="true"
|
||||
parse_urls="true" />
|
||||
|
||||
<text
|
||||
top_pad="10"
|
||||
left="6"
|
||||
height="16"
|
||||
width="55"
|
||||
layout="topleft"
|
||||
follows="left|bottom"
|
||||
name="Give item:"
|
||||
halign="right"
|
||||
value="Give item:" />
|
||||
<view_border
|
||||
top_delta="0"
|
||||
left="66"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|bottom|right"
|
||||
name="drop_target_rect_vis"
|
||||
bevel_style="out" />
|
||||
<text
|
||||
top_delta="2"
|
||||
left_delta="0"
|
||||
height="16"
|
||||
width="321"
|
||||
layout="topleft"
|
||||
follows="left|bottom"
|
||||
name="Give inventory"
|
||||
halign="center"
|
||||
tool_tip="Drop inventory items here to give them to this person.">
|
||||
Drop inventory item here.
|
||||
</text>
|
||||
|
||||
<layout_stack
|
||||
bottom="-3"
|
||||
left="6"
|
||||
right="-6"
|
||||
height="44"
|
||||
layout="topleft"
|
||||
follows="left|bottom|right"
|
||||
name="buttonstack"
|
||||
orientation="horizontal">
|
||||
|
||||
<layout_panel
|
||||
left="2"
|
||||
right="-2"
|
||||
height="42"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="left_buttonstack"
|
||||
user_resize="false">
|
||||
|
||||
<button
|
||||
top="2"
|
||||
left="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="show_on_map_btn"
|
||||
label="Find on Map"
|
||||
label_selected="Find on Map"
|
||||
tool_tip="Locate the Resident on the map" />
|
||||
|
||||
<button
|
||||
top_pad="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="pay"
|
||||
label="Pay"
|
||||
label_selected="Pay"
|
||||
tool_tip="Pay money to the Resident" />
|
||||
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
left="2"
|
||||
right="-2"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="middle_buttonstack"
|
||||
user_resize="false">
|
||||
|
||||
<button
|
||||
top="2"
|
||||
left="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="teleport"
|
||||
label="Offer Teleport"
|
||||
label_selected="Offer Teleport"
|
||||
tool_tip="Offer a teleport to the Resident" />
|
||||
|
||||
<button
|
||||
top_pad="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="im"
|
||||
label="Instant Message"
|
||||
label_selected="Instant Message"
|
||||
tool_tip="Open instant message session" />
|
||||
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
left="2"
|
||||
right="-2"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="right_buttonstack"
|
||||
user_resize="false">
|
||||
|
||||
<button
|
||||
top="2"
|
||||
left="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="add_friend"
|
||||
label="Add Friend"
|
||||
label_selected="Add Friend"
|
||||
tool_tip="Offer friendship to the Resident" />
|
||||
|
||||
<button
|
||||
top_pad="2"
|
||||
right="-40"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="block"
|
||||
label="Block"
|
||||
tool_tip="Block this Resident" />
|
||||
|
||||
<button
|
||||
top_delta="0"
|
||||
right="-40"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="unblock"
|
||||
label="Unblock"
|
||||
tool_tip="Unblock this Resident" />
|
||||
|
||||
<menu_button
|
||||
left_pad="4"
|
||||
height="20"
|
||||
width="36"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="overflow_btn"
|
||||
image_overlay="OptionsMenu_Off" />
|
||||
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
||||
<check_box
|
||||
bottom="-30"
|
||||
left="63"
|
||||
height="16"
|
||||
width="130"
|
||||
layout="topleft"
|
||||
follows="left|bottom"
|
||||
name="show_in_search_checkbox"
|
||||
label="Show in search"
|
||||
visible="false"
|
||||
enabled="false" />
|
||||
|
||||
<profile_drop_target
|
||||
top="0"
|
||||
bottom="-1"
|
||||
left="0"
|
||||
right="-1"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="drop_target"
|
||||
mouse_opaque="false" />
|
||||
</panel>
|
||||
|
||||
|
|
@ -1,574 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<panel
|
||||
top="0"
|
||||
left="0"
|
||||
width="420"
|
||||
height="480"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="panel_profile"
|
||||
label="Profile">
|
||||
<string
|
||||
name="status_online">
|
||||
Online
|
||||
</string>
|
||||
<string
|
||||
name="status_offline">
|
||||
Offline
|
||||
</string>
|
||||
<string
|
||||
name="CaptionTextAcctInfo">
|
||||
[ACCTTYPE]
|
||||
[PAYMENTINFO]
|
||||
[FIRESTORM][FSDEV][FSSUPP][FSQA][FSGW]
|
||||
</string>
|
||||
<!-- [AGEVERIFICATION] moved out of the above, since it's not set anyway. See
|
||||
LLPanelAvatarProfile::fillAccountStatus() ...TS -->
|
||||
<string
|
||||
name="payment_update_link_url">
|
||||
http://www.secondlife.com/account/billing.php?lang=en
|
||||
</string>
|
||||
<string
|
||||
name="partner_edit_link_url">
|
||||
http://www.secondlife.com/account/partners.php?lang=en
|
||||
</string>
|
||||
<string
|
||||
name="my_account_link_url"
|
||||
value="http://secondlife.com/account" />
|
||||
<string
|
||||
name="no_partner_text"
|
||||
value="None" />
|
||||
<string
|
||||
name="no_group_text"
|
||||
value="None" />
|
||||
<string
|
||||
name="RegisterDateFormat">
|
||||
[REG_DATE]
|
||||
([AGE])
|
||||
</string>
|
||||
<string
|
||||
name="name_text_args">
|
||||
[NAME]
|
||||
</string>
|
||||
<string
|
||||
name="display_name_text_args">
|
||||
[DISPLAY_NAME]
|
||||
</string>
|
||||
<string
|
||||
name="FSDev"
|
||||
value=" Developer" />
|
||||
<string
|
||||
name="FSSupp"
|
||||
value=" Support" />
|
||||
<string
|
||||
name="FSQualityAssurance"
|
||||
value=" Bug Hunter" />
|
||||
<string
|
||||
name="FSGW"
|
||||
value=" Gateway" />
|
||||
|
||||
<!--
|
||||
|
||||
KC: Use view_border's around text_editor's due to text render issues with border_visible
|
||||
|
||||
-->
|
||||
|
||||
<loading_indicator
|
||||
top="4"
|
||||
right="-10"
|
||||
height="23"
|
||||
width="23"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="progress_indicator"
|
||||
visible="false" />
|
||||
|
||||
<text
|
||||
top="8"
|
||||
left="6"
|
||||
height="16"
|
||||
width="40"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="Name:"
|
||||
halign="right"
|
||||
value="Name:" />
|
||||
|
||||
<view_border
|
||||
left_pad="4"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
bottom_delta="2"
|
||||
left_delta="3"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="complete_name"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="0"
|
||||
v_pad="0"
|
||||
enabled="false"
|
||||
max_length="254"
|
||||
value="(loading...)" />
|
||||
|
||||
<button
|
||||
left_pad="2"
|
||||
height="20"
|
||||
width="20"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="set_name"
|
||||
image_overlay="Edit_Wrench"
|
||||
tool_tip="Set Display Name"
|
||||
visible="false"
|
||||
enabled="false" />
|
||||
|
||||
<text
|
||||
top_pad="2"
|
||||
left="6"
|
||||
height="16"
|
||||
width="40"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="Key:"
|
||||
halign="right"
|
||||
value="Key:" />
|
||||
|
||||
<view_border
|
||||
left_pad="4"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border2"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
bottom_delta="2"
|
||||
left_delta="3"
|
||||
right="-86"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="user_key"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="0"
|
||||
v_pad="0"
|
||||
enabled="false"
|
||||
max_length="254"
|
||||
value="(loading...)" />
|
||||
|
||||
<text
|
||||
left_pad="2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="status"
|
||||
halign="center"
|
||||
value="" />
|
||||
|
||||
<button
|
||||
top_delta="-2"
|
||||
right="-6"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="copy_own_uri_button"
|
||||
label="Copy URI" />
|
||||
|
||||
<texture_picker
|
||||
top_pad="3"
|
||||
left="6"
|
||||
height="180"
|
||||
width="220"
|
||||
layout="topleft"
|
||||
follows="top|left"
|
||||
allow_no_texture="true"
|
||||
name="2nd_life_pic"
|
||||
default_image_name="None"
|
||||
enabled="false"
|
||||
fallback_image="Generic_Person_Large" />
|
||||
|
||||
<text
|
||||
top_pad="-179"
|
||||
left_pad="4"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="label"
|
||||
value="Born:" />
|
||||
|
||||
<view_border
|
||||
top_pad="0"
|
||||
left_delta="0"
|
||||
right="-6"
|
||||
height="32"
|
||||
name="info_border3"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
top_delta="2"
|
||||
left_delta="2"
|
||||
right="-6"
|
||||
height="28"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="register_date"
|
||||
max_length="254"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="2"
|
||||
v_pad="0"
|
||||
read_only="true"
|
||||
translate="false"
|
||||
word_wrap="true"/>
|
||||
|
||||
<text
|
||||
top_pad="7"
|
||||
left_delta="-2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="label2"
|
||||
value="Account:" />
|
||||
|
||||
<view_border
|
||||
top_pad="0"
|
||||
left_delta="0"
|
||||
right="-6"
|
||||
height="48"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="acct_border"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
top_delta="2"
|
||||
left_delta="2"
|
||||
right="-6"
|
||||
height="44"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="acc_status_text"
|
||||
bg_visible="false"
|
||||
border_visible="false"
|
||||
allow_scroll="false"
|
||||
h_pad="2"
|
||||
v_pad="0"
|
||||
read_only="true"
|
||||
translate="false"
|
||||
word_wrap="true"/>
|
||||
|
||||
<text
|
||||
top_pad="7"
|
||||
left_delta="-2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="partner_label"
|
||||
value="Partner:" />
|
||||
|
||||
<view_border
|
||||
top_pad="0"
|
||||
left_delta="0"
|
||||
right="-6"
|
||||
height="18"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border4"
|
||||
bevel_style="none" />
|
||||
<text
|
||||
icon_positioning="left"
|
||||
top_delta="2"
|
||||
left_delta="2"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="partner_text"
|
||||
max_length="254" />
|
||||
<!--
|
||||
<button
|
||||
top_pad="8"
|
||||
left="6"
|
||||
height="18"
|
||||
width="40"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="bigimg"
|
||||
halign="center"
|
||||
label="< <"
|
||||
label_selected="> >"
|
||||
tool_tip="Open Full Size." />
|
||||
-->
|
||||
<text
|
||||
top_pad="8"
|
||||
left="6"
|
||||
height="16"
|
||||
width="55"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="Groups:"
|
||||
halign="right"
|
||||
value="Groups:" />
|
||||
|
||||
<button
|
||||
top_delta="20"
|
||||
left="40"
|
||||
height="20"
|
||||
width="20"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="group_invite"
|
||||
label="+"
|
||||
label_selected="+"
|
||||
tool_tip="Invite to Group" />
|
||||
|
||||
<view_border
|
||||
top_delta="-20"
|
||||
left="66"
|
||||
right="-6"
|
||||
height="80"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="info_border_group_list"
|
||||
bevel_style="none" />
|
||||
<group_list
|
||||
top_delta="1"
|
||||
left_delta="1"
|
||||
right="-7"
|
||||
height="78"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="group_list"
|
||||
border_visible="false"
|
||||
for_agent="false" />
|
||||
|
||||
<text
|
||||
top_pad="8"
|
||||
left="6"
|
||||
height="16"
|
||||
width="55"
|
||||
layout="topleft"
|
||||
follows="left|top"
|
||||
name="About:"
|
||||
halign="right"
|
||||
value="About:" />
|
||||
|
||||
<view_border
|
||||
top_delta="0"
|
||||
left="66"
|
||||
right="-6"
|
||||
height="102"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="info_border5"
|
||||
bevel_style="none" />
|
||||
<text_editor
|
||||
top_delta="1"
|
||||
left_delta="1"
|
||||
right="-7"
|
||||
height="100"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="sl_description_edit"
|
||||
border_visible="false"
|
||||
font="SansSerifSmall"
|
||||
enabled="false"
|
||||
trusted_content="false"
|
||||
max_length="65000"
|
||||
h_pad="2"
|
||||
word_wrap="true"
|
||||
parse_urls="true" />
|
||||
|
||||
<text
|
||||
top_pad="10"
|
||||
left="6"
|
||||
height="16"
|
||||
width="55"
|
||||
layout="topleft"
|
||||
follows="left|bottom"
|
||||
name="Give item:"
|
||||
halign="right"
|
||||
value="Give item:" />
|
||||
<view_border
|
||||
top_delta="0"
|
||||
left="66"
|
||||
right="-6"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
follows="left|bottom|right"
|
||||
name="drop_target_rect_vis"
|
||||
bevel_style="out" />
|
||||
<text
|
||||
top_delta="2"
|
||||
left_delta="0"
|
||||
height="16"
|
||||
width="321"
|
||||
layout="topleft"
|
||||
follows="left|bottom"
|
||||
name="Give inventory"
|
||||
halign="center"
|
||||
tool_tip="Drop inventory items here to give them to this person.">
|
||||
Drop inventory item here.
|
||||
</text>
|
||||
|
||||
<layout_stack
|
||||
bottom="-3"
|
||||
left="6"
|
||||
right="-6"
|
||||
height="44"
|
||||
layout="topleft"
|
||||
follows="left|bottom|right"
|
||||
name="buttonstack"
|
||||
orientation="horizontal">
|
||||
|
||||
<layout_panel
|
||||
left="2"
|
||||
right="-2"
|
||||
height="42"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="left_buttonstack"
|
||||
user_resize="false">
|
||||
|
||||
<button
|
||||
top="2"
|
||||
left="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="show_on_map_btn"
|
||||
label="Find on Map"
|
||||
label_selected="Find on Map"
|
||||
tool_tip="Locate the Resident on the map" />
|
||||
|
||||
<button
|
||||
top_pad="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="pay"
|
||||
label="Pay"
|
||||
label_selected="Pay"
|
||||
tool_tip="Pay money to the Resident" />
|
||||
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
left="2"
|
||||
right="-2"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="middle_buttonstack"
|
||||
user_resize="false">
|
||||
|
||||
<button
|
||||
top="2"
|
||||
left="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="teleport"
|
||||
label="Offer Teleport"
|
||||
label_selected="Offer Teleport"
|
||||
tool_tip="Offer a teleport to the Resident" />
|
||||
|
||||
<button
|
||||
top_pad="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="im"
|
||||
label="Instant Message"
|
||||
label_selected="Instant Message"
|
||||
tool_tip="Open instant message session" />
|
||||
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
left="2"
|
||||
right="-2"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="right_buttonstack"
|
||||
user_resize="false">
|
||||
|
||||
<button
|
||||
top="2"
|
||||
left="2"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="add_friend"
|
||||
label="Add Friend"
|
||||
label_selected="Add Friend"
|
||||
tool_tip="Offer friendship to the Resident" />
|
||||
|
||||
<button
|
||||
top_pad="2"
|
||||
right="-40"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="block"
|
||||
label="Block"
|
||||
tool_tip="Block this Resident" />
|
||||
|
||||
<button
|
||||
top_delta="0"
|
||||
right="-40"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
follows="left|top|right"
|
||||
name="unblock"
|
||||
label="Unblock"
|
||||
tool_tip="Unblock this Resident" />
|
||||
|
||||
<menu_button
|
||||
left_pad="4"
|
||||
height="20"
|
||||
width="36"
|
||||
layout="topleft"
|
||||
follows="top|right"
|
||||
name="overflow_btn"
|
||||
image_overlay="OptionsMenu_Off" />
|
||||
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
||||
<check_box
|
||||
bottom="-30"
|
||||
left="63"
|
||||
height="16"
|
||||
width="130"
|
||||
layout="topleft"
|
||||
follows="left|bottom"
|
||||
name="show_in_search_checkbox"
|
||||
label="Show in search"
|
||||
visible="false"
|
||||
enabled="false" />
|
||||
|
||||
<profile_drop_target
|
||||
top="0"
|
||||
bottom="-1"
|
||||
left="0"
|
||||
right="-1"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
name="drop_target"
|
||||
mouse_opaque="false" />
|
||||
</panel>
|
||||
|
||||
|
|
@ -233,6 +233,7 @@
|
|||
|
||||
<texture_picker
|
||||
name="2nd_life_pic"
|
||||
fallback_image="Generic_Person_Large"
|
||||
top="0"
|
||||
left="0"
|
||||
width="158"
|
||||
|
|
|
|||
|
|
@ -43,10 +43,7 @@ import tarfile
|
|||
import time
|
||||
import zipfile
|
||||
|
||||
#<FS:AO>
|
||||
import shlex
|
||||
import zipfile
|
||||
#</FS:AO>
|
||||
sys.dont_write_bytecode = True # <FS:Ansariel> Prevents creating __pycache__ directory
|
||||
|
||||
from fs_viewer_manifest import FSViewerManifest #<FS:ND/> Manifest extensions for Firestorm
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue