diff --git a/.gitattributes b/.gitattributes
index 30cc9de8f1..5c7f5b73b0 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,8 +1,5 @@
* text eol=lf
-# VSTool (normalization disabled)
-indra/tools/vstool/* -text
-
# Images
*.bmp binary
*.BMP binary
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..5fe8870337
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,37 @@
+## Description
+
+
+
+## Related Issues
+
+- [ ] **Please link to a relevant GitHub issue for additional context.**
+ - **Bug Fix:** Link to an issue that includes reproduction steps and testing guidance.
+ - **Feature/Enhancement:** Link to an issue with a write-up, rationale, and requirements.
+
+Issue Link:
+
+---
+
+## Checklist
+
+Please ensure the following before requesting review:
+
+- [ ] I have provided a clear title and detailed description for this pull request.
+- [ ] If useful, I have included media such as screenshots and video to show off my changes.
+- [ ] The PR is linked to a relevant issue with sufficient context.
+- [ ] I have tested the changes locally and verified they work as intended.
+- [ ] All new and existing tests pass.
+- [ ] Code follows the project's style guidelines.
+- [ ] Documentation has been updated if needed.
+- [ ] Any dependent changes have been merged and published in downstream modules
+- [ ] I have reviewed the [contributing guidelines](https://github.com/secondlife/viewer/blob/develop/CONTRIBUTING.md).
+
+---
+
+## Additional Notes
+
+
diff --git a/.github/workflows/.gitattributes b/.github/workflows/.gitattributes
new file mode 100644
index 0000000000..6dc1cca42a
--- /dev/null
+++ b/.github/workflows/.gitattributes
@@ -0,0 +1 @@
+qatest.yaml -text eol=crlf
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 50b0cf02bc..4bf2af644a 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -218,8 +218,10 @@ jobs:
prefix=${ba[0]}
if [ "$prefix" == "project" ]; then
IFS='_' read -ra prj <<< "${ba[1]}"
+ prj_str="${prj[*]}"
# uppercase first letter of each word
- export viewer_channel="Second Life Project ${prj[*]^}"
+ capitalized=$(echo "$prj_str" | awk '{for (i=1; i<=NF; i++) $i = toupper(substr($i,1,1)) substr($i,2); print}')
+ export viewer_channel="Second Life Project $capitalized"
elif [[ "$prefix" == "release" || "$prefix" == "main" ]];
then
export viewer_channel="Second Life Release"
@@ -304,7 +306,7 @@ jobs:
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
needs: build
- runs-on: windows-large
+ runs-on: windows-latest
steps:
- name: Sign and package Windows viewer
if: env.AZURE_KEY_VAULT_URI && env.AZURE_CERT_NAME && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET && env.AZURE_TENANT_ID
@@ -455,7 +457,6 @@ jobs:
prerelease: true
generate_release_notes: true
target_commitish: ${{ github.sha }}
- previous_tag: release
append_body: true
fail_on_unmatched_files: true
files: |
diff --git a/.github/workflows/check-pr.yaml b/.github/workflows/check-pr.yaml
new file mode 100644
index 0000000000..a5cee9157c
--- /dev/null
+++ b/.github/workflows/check-pr.yaml
@@ -0,0 +1,21 @@
+name: Check PR
+
+on:
+ pull_request:
+ types: [opened, edited, reopened, synchronize]
+
+permissions:
+ contents: read
+
+jobs:
+ check-description:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check PR description
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const description = context.payload.pull_request.body || '';
+ if (description.trim().length < 20) {
+ core.setFailed("❌ PR description is too short. Please provide at least 20 characters.");
+ }
diff --git a/.github/workflows/qatest.yaml b/.github/workflows/qatest.yaml
new file mode 100644
index 0000000000..457e915726
--- /dev/null
+++ b/.github/workflows/qatest.yaml
@@ -0,0 +1,602 @@
+name: Run QA Test # Runs automated tests on self-hosted QA machines
+
+permissions:
+ contents: read
+
+on:
+ workflow_run:
+ workflows: ["Build"]
+ types:
+ - completed
+ workflow_dispatch:
+ inputs:
+ build_id:
+ description: 'Build workflow run ID (e.g. For github.com/secondlife/viewer/actions/runs/1234567890 the ID is 1234567890)'
+ required: true
+ default: '14806728332'
+
+jobs:
+ debug-workflow:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Debug Workflow Variables
+ run: |
+ echo "Workflow Conclusion: ${{ github.event.workflow_run.conclusion }}"
+ echo "Workflow Head Branch: ${{ github.event.workflow_run.head_branch }}"
+ echo "Workflow Run ID: ${{ github.event.workflow_run.id }}"
+ echo "Head Commit Message: ${{ github.event.workflow_run.head_commit.message }}"
+ echo "GitHub Ref: ${{ github.ref }}"
+ echo "GitHub Ref Name: ${{ github.ref_name }}"
+ echo "GitHub Event Name: ${{ github.event_name }}"
+ echo "GitHub Workflow Name: ${{ github.workflow }}"
+
+ install-viewer-and-run-tests:
+ concurrency:
+ group: ${{ github.workflow }}-${{ matrix.runner }}
+ cancel-in-progress: false # Prevents cancellation of in-progress jobs
+
+ strategy:
+ matrix:
+ include:
+ - os: windows
+ runner: qa-windows-atlas
+ artifact: Windows-installer
+ install-path: 'C:\viewer-automation-main'
+ - os: windows
+ runner: qa-windows-asus-dan
+ artifact: Windows-installer
+ install-path: 'C:\viewer-automation-main'
+ - os: windows
+ runner: qa-windows-z600-dan
+ artifact: Windows-installer
+ install-path: 'C:\viewer-automation-main'
+ - os: mac
+ runner: qa-mac-atlas
+ artifact: macOS-installer
+ install-path: '$HOME/Documents/viewer-automation'
+ fail-fast: false
+
+ runs-on: [self-hosted, "${{ matrix.runner }}"]
+ # Run test only on successful builds of Second_Life_X branches or on manual dispatch
+ if: >
+ (github.event_name == 'workflow_run' &&
+ github.event.workflow_run.conclusion == 'success' &&
+ startsWith(github.event.workflow_run.head_branch, 'Second_Life')) ||
+ github.event_name == 'workflow_dispatch'
+
+ steps:
+ # Windows-specific steps
+ - name: Set Build ID
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ if ("${{ github.event_name }}" -eq "workflow_dispatch") {
+ echo "BUILD_ID=${{ github.event.inputs.build_id }}" | Out-File -FilePath $env:GITHUB_ENV -Append
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.inputs.build_id }}/artifacts" | Out-File -FilePath $env:GITHUB_ENV -Append
+ } else {
+ echo "BUILD_ID=${{ github.event.workflow_run.id }}" | Out-File -FilePath $env:GITHUB_ENV -Append
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.workflow_run.id }}/artifacts" | Out-File -FilePath $env:GITHUB_ENV -Append
+ }
+
+ - name: Temporarily Allow PowerShell Scripts (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Set-ExecutionPolicy RemoteSigned -Scope Process -Force
+
+ - name: Verify viewer-automation-main Exists (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ if (-Not (Test-Path -Path '${{ matrix.install-path }}')) {
+ Write-Host '❌ Error: viewer-automation folder not found on runner!'
+ exit 1
+ }
+ Write-Host '✅ viewer-automation folder is provided.'
+
+ - name: Verify viewer-automation-main is Up-To-Date (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ continue-on-error: true
+ run: |
+ cd ${{ matrix.install-path }}
+ Write-Host "Checking for repository updates..."
+
+ # Check if .git directory exists
+ if (Test-Path -Path ".git") {
+ try {
+ # Save local changes instead of discarding them
+ git stash push -m "Automated stash before update $(Get-Date)"
+ Write-Host "Local changes saved (if any)"
+
+ # Update the repository
+ git pull
+ Write-Host "✅ Repository updated successfully"
+
+ # Try to restore local changes if any were stashed
+ $stashList = git stash list
+ if ($stashList -match "Automated stash before update") {
+ try {
+ git stash pop
+ Write-Host "✅ Local changes restored successfully"
+ } catch {
+ Write-Host "⚠️ Conflict when restoring local changes"
+ # Save the conflicted state in a new branch for later review
+ $branchName = "conflict-recovery-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
+ git checkout -b $branchName
+ Write-Host "✅ Created branch '$branchName' with conflicted state"
+
+ # For test execution, revert to a clean state
+ git reset --hard HEAD
+ Write-Host "✅ Reset to clean state for test execution"
+ }
+ }
+ } catch {
+ Write-Host "⚠️ Could not update repository: $_"
+ Write-Host "Continuing with existing files..."
+ }
+ } else {
+ Write-Host "⚠️ Not a Git repository, using existing files"
+ }
+
+ - name: Verify Python Installation (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ try {
+ $pythonVersion = (python --version)
+ Write-Host "✅ Python found: $pythonVersion"
+ } catch {
+ Write-Host "❌ Error: Python not found in PATH. Please install Python on this runner."
+ exit 1
+ }
+
+ - name: Setup Python Virtual Environment (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
+ cd ${{ matrix.install-path }}
+
+ if (-Not (Test-Path -Path ".venv")) {
+ Write-Host "Creating virtual environment..."
+ python -m venv .venv
+ } else {
+ Write-Host "Using existing virtual environment"
+ }
+
+ # Direct environment activation to avoid script execution issues
+ $env:VIRTUAL_ENV = "$PWD\.venv"
+ $env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH"
+
+ # Install dependencies
+ if (Test-Path -Path "requirements.txt") {
+ Write-Host "Installing dependencies from requirements.txt..."
+ pip install -r requirements.txt
+
+ # Install Playwright browsers - add this line
+ Write-Host "Installing Playwright browsers..."
+ python -m playwright install
+ } else {
+ pip install outleap requests behave playwright
+ # Install Playwright browsers - add this line
+ Write-Host "Installing Playwright browsers..."
+ python -m playwright install
+ }
+
+ - name: Fetch & Download Installer Artifact (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ $BUILD_ID = "${{ env.BUILD_ID }}"
+ $ARTIFACTS_URL = "${{ env.ARTIFACTS_URL }}"
+
+ # Fetch the correct artifact URL
+ $response = Invoke-RestMethod -Headers @{Authorization="token ${{ secrets.GITHUB_TOKEN }}" } -Uri $ARTIFACTS_URL
+ $ARTIFACT_NAME = ($response.artifacts | Where-Object { $_.name -eq "${{ matrix.artifact }}" }).archive_download_url
+
+ if (-Not $ARTIFACT_NAME) {
+ Write-Host "❌ Error: ${{ matrix.artifact }} artifact not found!"
+ exit 1
+ }
+
+ Write-Host "✅ Artifact found: $ARTIFACT_NAME"
+
+ # Secure download path
+ $DownloadPath = "$env:TEMP\secondlife-build-$BUILD_ID"
+ New-Item -ItemType Directory -Path $DownloadPath -Force | Out-Null
+ $InstallerPath = "$DownloadPath\installer.zip"
+
+ # Download the ZIP
+ Invoke-WebRequest -Uri $ARTIFACT_NAME -Headers @{Authorization="token ${{ secrets.GITHUB_TOKEN }}"} -OutFile $InstallerPath
+
+ # Ensure download succeeded
+ if (-Not (Test-Path $InstallerPath)) {
+ Write-Host "❌ Error: Failed to download ${{ matrix.artifact }}.zip"
+ exit 1
+ }
+
+ # Set the path for other steps
+ echo "DOWNLOAD_PATH=$DownloadPath" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+ - name: Extract Installer & Locate Executable (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ $BUILD_ID = "${{ env.BUILD_ID }}"
+ $ExtractPath = "${{ env.DOWNLOAD_PATH }}"
+ $InstallerZip = "$ExtractPath\installer.zip"
+
+ # Print paths for debugging
+ Write-Host "Extract Path: $ExtractPath"
+ Write-Host "Installer ZIP Path: $InstallerZip"
+
+ # Verify ZIP exists before extracting
+ if (-Not (Test-Path $InstallerZip)) {
+ Write-Host "❌ Error: ZIP file not found at $InstallerZip!"
+ exit 1
+ }
+
+ Write-Host "✅ ZIP file exists and is valid. Extracting..."
+
+ Expand-Archive -Path $InstallerZip -DestinationPath $ExtractPath -Force
+
+ # Find installer executable
+ $INSTALLER_PATH = (Get-ChildItem -Path $ExtractPath -Filter '*.exe' -Recurse | Select-Object -First 1).FullName
+
+ if (-Not $INSTALLER_PATH -or $INSTALLER_PATH -eq "") {
+ Write-Host "❌ Error: No installer executable found in the extracted files!"
+ Write-Host "📂 Extracted Files:"
+ Get-ChildItem -Path $ExtractPath -Recurse | Format-Table -AutoSize
+ exit 1
+ }
+
+ Write-Host "✅ Installer found: $INSTALLER_PATH"
+ echo "INSTALLER_PATH=$INSTALLER_PATH" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+ - name: Install Second Life (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ # Windows - Use Task Scheduler to bypass UAC
+ $action = New-ScheduledTaskAction -Execute "${{ env.INSTALLER_PATH }}" -Argument "/S"
+ $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
+ $task = New-ScheduledTask -Action $action -Principal $principal
+ Register-ScheduledTask -TaskName "SilentSLInstaller" -InputObject $task -Force
+ Start-ScheduledTask -TaskName "SilentSLInstaller"
+
+ - name: Wait for Installation to Complete (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Write-Host "Waiting for the Second Life installer to finish..."
+ do {
+ Start-Sleep -Seconds 5
+ $installerProcess = Get-Process | Where-Object { $_.Path -eq "${{ env.INSTALLER_PATH }}" }
+ } while ($installerProcess)
+
+ Write-Host "✅ Installation completed!"
+
+ - name: Cleanup After Installation (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ # Cleanup Task Scheduler Entry
+ Unregister-ScheduledTask -TaskName "SilentSLInstaller" -Confirm:$false
+ Write-Host "✅ Task Scheduler entry removed."
+
+ # Delete Installer ZIP
+ $DeletePath = "${{ env.DOWNLOAD_PATH }}\installer.zip"
+
+ Write-Host "Checking if installer ZIP exists: $DeletePath"
+
+ # Ensure the ZIP file exists before trying to delete it
+ if (Test-Path $DeletePath) {
+ Remove-Item -Path $DeletePath -Force
+ Write-Host "✅ Successfully deleted: $DeletePath"
+ } else {
+ Write-Host "⚠️ Warning: ZIP file does not exist, skipping deletion."
+ }
+
+ - name: Run QA Test Script (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Write-Host "Running QA Test script on Windows runner: ${{ matrix.runner }}..."
+ cd ${{ matrix.install-path }}
+
+ # Activate virtual environment
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
+ $env:VIRTUAL_ENV = "$PWD\.venv"
+ $env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH"
+
+ # Set runner name as environment variable
+ $env:RUNNER_NAME = "${{ matrix.runner }}"
+
+ # Run the test script
+ python runTests.py
+
+ # Mac-specific steps
+ - name: Set Build ID (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
+ echo "BUILD_ID=${{ github.event.inputs.build_id }}" >> $GITHUB_ENV
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.inputs.build_id }}/artifacts" >> $GITHUB_ENV
+ else
+ echo "BUILD_ID=${{ github.event.workflow_run.id }}" >> $GITHUB_ENV
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.workflow_run.id }}/artifacts" >> $GITHUB_ENV
+ fi
+
+ - name: Verify viewer-automation-main Exists (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ if [ ! -d "${{ matrix.install-path }}" ]; then
+ echo "❌ Error: viewer-automation folder not found on runner!"
+ exit 1
+ fi
+ echo "✅ viewer-automation is provided."
+
+ - name: Verify viewer-automation-main is Up-To-Date (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ continue-on-error: true
+ run: |
+ cd ${{ matrix.install-path }}
+ echo "Checking for repository updates..."
+
+ # Check if .git directory exists
+ if [ -d ".git" ]; then
+ # Save local changes instead of discarding them
+ git stash push -m "Automated stash before update $(date)"
+ echo "Local changes saved (if any)"
+
+ # Update the repository
+ git pull || echo "⚠️ Could not update repository"
+ echo "✅ Repository updated (or attempted update)"
+
+ # Try to restore local changes if any were stashed
+ if git stash list | grep -q "Automated stash before update"; then
+ # Try to pop the stash, but be prepared for conflicts
+ if ! git stash pop; then
+ echo "⚠️ Conflict when restoring local changes"
+ # Save the conflicted state in a new branch for later review
+ branch_name="conflict-recovery-$(date +%Y%m%d-%H%M%S)"
+ git checkout -b "$branch_name"
+ echo "✅ Created branch '$branch_name' with conflicted state"
+
+ # For test execution, revert to a clean state
+ git reset --hard HEAD
+ echo "✅ Reset to clean state for test execution"
+ else
+ echo "✅ Local changes restored successfully"
+ fi
+ fi
+ else
+ echo "⚠️ Not a Git repository, using existing files"
+ fi
+
+ - name: Verify Python Installation (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ if command -v python3 &> /dev/null; then
+ PYTHON_VERSION=$(python3 --version)
+ echo "✅ Python found: $PYTHON_VERSION"
+ else
+ echo "❌ Error: Python3 not found in PATH. Please install Python on this runner."
+ exit 1
+ fi
+
+ - name: Setup Python Virtual Environment (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ cd ${{ matrix.install-path }}
+
+ # Create virtual environment if it doesn't exist
+ if [ ! -d ".venv" ]; then
+ echo "Creating virtual environment..."
+ python3 -m venv .venv
+ else
+ echo "Using existing virtual environment"
+ fi
+
+ # Activate virtual environment
+ source .venv/bin/activate
+
+ # Install dependencies
+ if [ -f "requirements.txt" ]; then
+ pip install -r requirements.txt
+ echo "✅ Installed dependencies from requirements.txt"
+
+ # Install Playwright browsers - add this line
+ echo "Installing Playwright browsers..."
+ python -m playwright install
+ else
+ pip install outleap requests behave playwright
+ echo "⚠️ requirements.txt not found, installed basic dependencies"
+
+ # Install Playwright browsers - add this line
+ echo "Installing Playwright browsers..."
+ python -m playwright install
+ fi
+
+ - name: Fetch & Download Installer Artifact (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ # Mac-specific Bash commands
+ response=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s ${{ env.ARTIFACTS_URL }})
+ ARTIFACT_NAME=$(echo $response | jq -r '.artifacts[] | select(.name=="${{ matrix.artifact }}") | .archive_download_url')
+
+ if [ -z "$ARTIFACT_NAME" ]; then
+ echo "❌ Error: ${{ matrix.artifact }} artifact not found!"
+ exit 1
+ fi
+
+ echo "✅ Artifact found: $ARTIFACT_NAME"
+
+ # Secure download path
+ DOWNLOAD_PATH="/tmp/secondlife-build-${{ env.BUILD_ID }}"
+ mkdir -p $DOWNLOAD_PATH
+ INSTALLER_PATH="$DOWNLOAD_PATH/installer.zip"
+
+ # Download the ZIP
+ curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -L $ARTIFACT_NAME -o $INSTALLER_PATH
+
+ # Ensure download succeeded
+ if [ ! -f "$INSTALLER_PATH" ]; then
+ echo "❌ Error: Failed to download ${{ matrix.artifact }}.zip"
+ exit 1
+ fi
+
+ # Set the path for other steps
+ echo "DOWNLOAD_PATH=$DOWNLOAD_PATH" >> $GITHUB_ENV
+
+ - name: Extract Installer & Locate Executable (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ EXTRACT_PATH="${{ env.DOWNLOAD_PATH }}"
+ INSTALLER_ZIP="$EXTRACT_PATH/installer.zip"
+
+ # Debug output
+ echo "Extract Path: $EXTRACT_PATH"
+ echo "Installer ZIP Path: $INSTALLER_ZIP"
+
+ # Verify ZIP exists
+ if [ ! -f "$INSTALLER_ZIP" ]; then
+ echo "❌ Error: ZIP file not found at $INSTALLER_ZIP!"
+ exit 1
+ fi
+
+ echo "✅ ZIP file exists and is valid. Extracting..."
+
+ # Extract the ZIP
+ unzip -o "$INSTALLER_ZIP" -d "$EXTRACT_PATH"
+
+ # Find DMG file
+ INSTALLER_PATH=$(find "$EXTRACT_PATH" -name "*.dmg" -type f | head -1)
+
+ if [ -z "$INSTALLER_PATH" ]; then
+ echo "❌ Error: No installer DMG found in the extracted files!"
+ echo "📂 Extracted Files:"
+ ls -la "$EXTRACT_PATH"
+ exit 1
+ fi
+
+ echo "✅ Installer found: $INSTALLER_PATH"
+ echo "INSTALLER_PATH=$INSTALLER_PATH" >> $GITHUB_ENV
+
+ - name: Install Second Life (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ # Mac installation
+ echo "Mounting DMG installer..."
+ MOUNT_POINT="/tmp/secondlife-dmg"
+ mkdir -p "$MOUNT_POINT"
+
+ # Mount the DMG
+ hdiutil attach "$INSTALLER_PATH" -mountpoint "$MOUNT_POINT" -nobrowse
+
+ echo "✅ DMG mounted at $MOUNT_POINT"
+
+ echo "Installing application to default location from DMG..."
+
+ # Find the .app bundle in the DMG
+ APP_PATH=$(find "$MOUNT_POINT" -name "*.app" -type d | head -1)
+
+ if [ -z "$APP_PATH" ]; then
+ echo "❌ Error: No .app bundle found in the mounted DMG!"
+ exit 1
+ fi
+
+ APP_NAME=$(basename "$APP_PATH")
+ DEST_PATH="/Applications/$APP_NAME"
+
+ # Handle existing installation
+ if [ -d "$DEST_PATH" ]; then
+ echo "Found existing installation at: $DEST_PATH"
+ echo "Moving existing installation to trash..."
+
+ # Move to trash instead of force removing
+ TRASH_PATH="$HOME/.Trash/$(date +%Y%m%d_%H%M%S)_$APP_NAME"
+ mv "$DEST_PATH" "$TRASH_PATH" || {
+ echo "⚠️ Could not move to trash, trying direct removal..."
+ rm -rf "$DEST_PATH" || {
+ echo "❌ Could not remove existing installation"
+ echo "Please manually remove: $DEST_PATH"
+ exit 1
+ }
+ }
+
+ echo "✅ Existing installation handled successfully"
+ fi
+
+ # Copy the .app to /Applications
+ echo "Copying app from: $APP_PATH"
+ echo "To destination: /Applications/"
+ cp -R "$APP_PATH" /Applications/
+
+ # Verify the app was copied successfully
+ if [ ! -d "$DEST_PATH" ]; then
+ echo "❌ Error: Failed to install application to /Applications!"
+ exit 1
+ fi
+
+ echo "✅ Application installed successfully to /Applications"
+
+ # Save mount point for cleanup
+ echo "MOUNT_POINT=$MOUNT_POINT" >> $GITHUB_ENV
+
+ - name: Wait for Installation to Complete (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ echo "Waiting for installation to complete..."
+ # Sleep to allow installation to finish (adjust as needed)
+ sleep 30
+ echo "✅ Installation completed"
+
+ - name: Cleanup After Installation (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ # Mac cleanup
+ # Unmount the DMG
+ echo "Unmounting DMG..."
+ hdiutil detach "${{ env.MOUNT_POINT }}" -force
+
+ # Clean up temporary files
+ echo "Cleaning up temporary files..."
+ rm -rf "${{ env.DOWNLOAD_PATH }}"
+ rm -rf "${{ env.MOUNT_POINT }}"
+
+ echo "✅ Cleanup completed"
+
+ - name: Run QA Test Script (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ echo "Running QA Test script on Mac runner: ${{ matrix.runner }}..."
+ cd ${{ matrix.install-path }}
+
+ # Activate virtual environment
+ source .venv/bin/activate
+
+ # Set runner name as environment variable
+ export RUNNER_NAME="${{ matrix.runner }}"
+
+ # Run the test script
+ python runTests.py
+
+ # - name: Upload Test Results
+ # if: always()
+ # uses: actions/upload-artifact@v4
+ # with:
+ # name: test-results-${{ matrix.runner }}
+ # path: ${{ matrix.install-path }}/regressionTest/test_results.html
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 1dd7c8c800..8baac5a81d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -12,7 +12,7 @@ repos:
- id: indent-with-spaces
files: \.(cpp|c|h|inl|py|glsl|cmake)$
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.4.0
+ rev: v5.0.0
hooks:
- id: check-xml
- id: mixed-line-ending
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6bd8a2b74c..9f38432ff7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,6 +8,7 @@ changes.
## Table of contents
- [Communication](#communication)
+- [What to work on](#what-to-work-on)
- [Reporting bugs and requesting features](#reporting-bugs-and-requesting-features)
- [Contributing pull requests](#contributing-pull-requests)
@@ -32,8 +33,19 @@ developer-to-developer or support.
- [Official forums][] exist for many topics including content creation,
scripting, social topics and more.
- The [opensource-dev mailing list][] is useful for announcements and
- discussion between viewer maintainers.
+ discussion between viewer maintainers.
+- Our [discord channel](https://discord.com/channels/677442248157167619/1357059883400167585) is available for real-time discussion.
+## What to work on
+
+If you're looking for ways to contribute code, here are some ways to get involved:
+
+- Explore existing issues on the [GitHub issue tracker](https://github.com/secondlife/viewer/issues) to find known problems, bugs, or enhancement discussions.
+- File new issues if you’ve discovered a bug or have a specific idea to propose. If your idea is user-facing, consider submitting it through feedback.secondlife.com so it can reach a broader audience and be prioritized by Linden Lab staff.
+- Look for the [help wanted](https://github.com/secondlife/viewer/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22) label. These are tasks the core maintainers have specifically identified as good candidates for community help.
+- Talk to maintainers before starting significant work. Even if an issue exists, discussing your approach first ensures alignment with ongoing efforts and increases the likelihood your pull request will be accepted.
+
+Collaboration is essential. We encourage contributors to work closely with the Second Life engineering team and other developers to keep work consistent and maintainable.
## Reporting bugs and requesting features
diff --git a/autobuild.xml b/autobuild.xml
index f76b05bda3..ada8059708 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1423,11 +1423,11 @@
creds
github
hash
- 9e59c93c7110e87b4ff3db330f11a23c50e5000f
+ 7facda95e2f00c260513f3d4db42588fa8ba703c
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/178910560
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/196289774
name
darwin64
@@ -1439,11 +1439,11 @@
creds
github
hash
- 7ed994db5bafa9a7ad09a1b53da850a84715c65e
+ 01d08f13c7bc8d1b95b0330fa6833b7d8274e4d0
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/178910561
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/196289775
name
linux64
@@ -1455,24 +1455,24 @@
creds
github
hash
- 66824c02e0e5eabbfbe37bfb173360195f89697c
+ 6d00345c7d3471bc5f7c1218e014dd0f1a2c069b
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/178910562
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/196289778
name
windows64
+ copyright
+ Copyright (c) 2010, Linden Research, Inc.
license
internal
license_file
LICENSES/llphysicsextensions.txt
- copyright
- Copyright (c) 2010, Linden Research, Inc.
version
- 1.0.66e6919
+ 1.0.11137145495
name
llphysicsextensions_source
@@ -2354,59 +2354,33 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
threejs
tinygltf
@@ -2918,6 +2892,64 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
version
1.0.9-5e8947c
+ discord_sdk
+
+ platforms
+
+ windows64
+
+ archive
+
+ creds
+ github
+ hash
+ e11571bf76b27d15c244069988ae372eaa5afae9
+ hash_algorithm
+ sha1
+ url
+ https://api.github.com/repos/secondlife/3p-discord-sdk/releases/assets/279333720
+
+ name
+ windows64
+
+ darwin64
+
+ archive
+
+ creds
+ github
+ hash
+ dc21df8b051c425163acf3eff8f06e32f407c9e0
+ hash_algorithm
+ sha1
+ url
+ https://api.github.com/repos/secondlife/3p-discord-sdk/releases/assets/279333706
+
+ name
+ darwin64
+
+
+ license
+ discord_sdk
+ license_file
+ LICENSES/discord_sdk.txt
+ copyright
+ Discord Inc.
+ version
+ 1.4.9649.16733550144
+ name
+ discord_sdk
+ vcs_branch
+ main
+ vcs_revision
+ ef5c7c4a490ceac2df2b2f046788b1daf1bbb392
+ vcs_url
+ https://github.com/secondlife/3p-discord-sdk
+ canonical_repo
+ https://github.com/secondlife/3p-discord-sdk
+ description
+ Discord Social SDK
+
package_description
diff --git a/doc/testplans/PRIM_MEDIA_FIRST_CLICK_INTERACT.md b/doc/testplans/PRIM_MEDIA_FIRST_CLICK_INTERACT.md
new file mode 100644
index 0000000000..afb3d5b337
--- /dev/null
+++ b/doc/testplans/PRIM_MEDIA_FIRST_CLICK_INTERACT.md
@@ -0,0 +1,158 @@
+# Test plan for PRIM_MEDIA_FIRST_CLICK_INTERACT
+
+## Requirements
+
+- At least two accounts
+- At least one group
+- Land under your control
+
+## Feature Brief
+
+Historically media-on-a-prim (MOAP) in Second Life has been bound to a focus system which blocks mouse click/hover events, this feature creates exceptions to this focus system for a configurable set of objects to meet user preference.
+
+## Testing
+
+The following scripts and test cases cover each individual operational mode of the feature; in practice these modes can be combined by advanced users in any configuration they desire from debug settings. Even though the intended use case combines multiple modes, individual modes can be tested for functionality when tested as described below.
+
+If testing an arbitrary combination of operational modes beyond what the GUI offers is desired, the parameters of the bitfield for calculation are located in lltoolpie.h under the MediaFirstClickTypes enum. As of writing there exists a total of ~127 possible unique/valid combinations, which is why testing each mode individually is considered the most efficient for a full functionality test.
+
+### Scripts
+
+#### Script A
+
+This script creates a media surface that is eligible for media first-click interact. Depending on test conditions, this will exhibit new behavior.
+
+```lsl
+default {
+ state_entry() {
+ llSetLinkMedia( LINK_THIS, 0, [
+ PRIM_MEDIA_CURRENT_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_HOME_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_FIRST_CLICK_INTERACT, TRUE,
+ PRIM_MEDIA_AUTO_PLAY, TRUE,
+ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI
+ ] );
+ }
+}
+
+```
+
+#### Script B
+
+This script creates a media surface that is NOT eligible for media first-click interact. In all but one test case, this will behave the same way.
+
+```lsl
+default {
+ state_entry() {
+ llSetLinkMedia( LINK_THIS, 0, [
+ PRIM_MEDIA_CURRENT_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_HOME_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_FIRST_CLICK_INTERACT, FALSE,
+ PRIM_MEDIA_AUTO_PLAY, TRUE,
+ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI
+ ] );
+ }
+}
+
+```
+
+## Standard testing procedure
+
+You will be asked to enable media faces on multiple cubes, make sure that the webpage loads on each, and interact with them in the following ways.
+
+1. Enable media for the cube, and verify that it displays a webpage.
+2. Click on the terrain to clear any focus.
+3. Hover your mouse over UI elements of the webpage, and **observe** if they highlight/react to the mouse cursor.
+4. If hover events are not registered, clicking on the webpage and then **observe** if they begin reacting to hover events.
+5. Clicking on the terrain to clear any focus once again.
+6. Clicking on a UI element of the webpage and **observe** if it reacts to the first click, or requires a second click. *(Maximum of 2 clicks per attempt)*
+
+These steps will be repeated for one or more pairs of cubes per test case to ensure that media first click interact is functioning within expectations. Unless otherwise mentioned for a specific test case, you simply need only be in the same region as the cubes to test with them.
+
+## Test cases
+
+All test cases begin with at least two cubes rezzed, one containing Script A henceforth referred to as Cube A and one with Script B referred to as Cube B. The steps of some test cases may impact the condition of the cubes, so keeping a spare set rezzed or in inventory to rapidly duplicate should improve efficiency if testing cases in series.
+
+### Case 1 (MEDIA_FIRST_CLICK_NONE)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `0`
+
+Starting with Cube A and Cube B, perform the testing procedure on each.
+
+**Expected observations:** Both webpages do not react to hover events until clicked, both webpages do not react to clicks until clicked once to establish focus
+
+### Case 2 (MEDIA_FIRST_CLICK_HUD)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `1`
+
+Starting with Cube A and Cube B, attach them both to your HUD and perform the testing procedure on each. You may need to rotate or scale the cubes to fit on your screen before beginning testing. You may attach both at the same time, or only one at a time.
+
+**Expected observations:** The webpage on Cube A will react to mouse cursor hover events and clicks without needing a focus click, but the webpage on Cube B will not.
+
+### Case 3 (MEDIA_FIRST_CLICK_OWN)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `2`
+
+This test case requires two pairs of cubes, and the second pair must not be owned by your testing account. What owns them is not important, it can be a group or your second testing account.
+
+Perform the testing procedure on both sets of cubes.
+
+**Expected observations:** The webpage on Cube A will react to mouse cursor hover events and clicks without needing a focus click, but the webpage on Cube B will not. The other pair of cubes will react the same as your Cube B.
+
+### Case 4 (MEDIA_FIRST_CLICK_GROUP)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `4`
+
+This test case requires two cubes, and the second cube must be deeded or set to a group that your testing account is a member of. As long as the second set of cubes is set to a group that your test account is a member of, the avatar that owns them does not matter.
+
+Perform the testing procedure on both sets of cubes.
+
+**Expected observations:** The cube owned by your primary account will not react to mouse cursor hover events and clicks without needing a focus click. The cube set to group will react to mouse cursor hover events and clicks without needing a focus click.
+
+### Case 5 (MEDIA_FIRST_CLICK_FRIEND)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `8`
+
+This test case requires three sets of cubes, one owned by you, one owned by another avatar on your friend list, and a third set owned by an avatar that is not on your friend list, or deeded to group. You can optionally use two sets of cubes, and dissolve friendship with your second account to test non-friend cubes.
+
+Perform the testing procedure on all cubes
+
+**Expected observations:** Cube A owned by a friended avatar will react to mouse cursor hover events and clicks without needing a focus click. All other cubes will not.
+
+### Case 6 (MEDIA_FIRST_CLICK_LAND)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `16`
+
+This is the most tricky test case due to the multiple combinations that this operational mode considers valid. You will need multiple cubes, and can omit Cube B for brevity unless running a full test pass. This is probably most efficiently tested from your second account, using your first account to adjust the test parameters to fit other sub-cases.
+
+Note: This requires the avatar that is performing the tests to physically be in the same parcel as the test cube(s). If you are standing outside of the parcel the media cubes are in, they will never react to mouse cursor hover events and clicks without needing a focus click under this operational mode.
+
+1. Place down a set of cubes owned by the same avatar as the land
+ - The second account should see Cube A react to mouse cursor hover events and clicks without needing a focus click
+ - Cube B if tested, will not react in all further sub-cases and will not be mentioned further.
+
+2. Adjust the conditions of the cubes and parcel such that they are owned by another avatar, but have the same group as the land set
+ - The second account should see Cube A react to mouse cursor hover events and clicks without needing a focus click
+
+3. Adjust the conditions of the cubes and parcel such that they are deeded to the same group that the parcel is deeded to
+ - The second account should see Cube A react to mouse cursor hover events and clicks without needing a focus click
+
+4. Adjust the conditions of the cubes and parcel such that the parcel and cubes do not share an owner, or a group
+ - The second account should see Cube A NOT react to mouse cursor hover events until clicked, and clicks WILL need a focus click before registering.
+
+### Case 7 (MEDIA_FIRST_CLICK_ANY) (optional)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `32767`
+
+Repeat test cases 1-6.
+
+1. Test case 1 should fail
+2. Test cases 2-6 should pass
+
+### Case 8 (MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG) (optional)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `65535`
+
+Repeat test cases 1-6, there is no pass/fail for this run.
+
+All cubes including B types should exhibit the same first-click interact behavior.
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 6c1b1f4d1d..4608f68f50 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -20,6 +20,7 @@ set(cmake_SOURCE_FILES
Copy3rdPartyLibs.cmake
DBusGlib.cmake
DeploySharedLibs.cmake
+ Discord.cmake
DragDrop.cmake
EXPAT.cmake
FindAutobuild.cmake
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 2ac82308cf..680f2f3ac2 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -6,6 +6,9 @@
include(CMakeCopyIfDifferent)
include(Linking)
+if (USE_DISCORD)
+ include(Discord)
+endif ()
include(OPENAL)
# When we copy our dependent libraries, we almost always want to copy them to
@@ -70,6 +73,10 @@ if(WINDOWS)
endif(ADDRESS_SIZE EQUAL 32)
endif (USE_BUGSPLAT)
+ if (TARGET ll::discord_sdk)
+ list(APPEND release_files discord_partner_sdk.dll)
+ endif ()
+
if (TARGET ll::openal)
list(APPEND release_files openal32.dll alut.dll)
endif ()
@@ -166,6 +173,10 @@ elseif(DARWIN)
libndofdev.dylib
)
+ if (TARGET ll::discord_sdk)
+ list(APPEND release_files libdiscord_partner_sdk.dylib)
+ endif ()
+
if (TARGET ll::openal)
list(APPEND release_files libalut.dylib libopenal.dylib)
endif ()
diff --git a/indra/cmake/Discord.cmake b/indra/cmake/Discord.cmake
new file mode 100644
index 0000000000..95cfaacf5b
--- /dev/null
+++ b/indra/cmake/Discord.cmake
@@ -0,0 +1,11 @@
+include(Prebuilt)
+
+include_guard()
+
+add_library(ll::discord_sdk INTERFACE IMPORTED)
+target_compile_definitions(ll::discord_sdk INTERFACE LL_DISCORD=1)
+
+use_prebuilt_binary(discord_sdk)
+
+target_include_directories(ll::discord_sdk SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/discord_sdk)
+target_link_libraries(ll::discord_sdk INTERFACE discord_partner_sdk)
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index 3f4d0ed534..900a64e2dd 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -73,7 +73,6 @@ else()
find_library(COCOA_LIBRARY Cocoa)
find_library(IOKIT_LIBRARY IOKit)
- find_library(AGL_LIBRARY AGL)
find_library(APPKIT_LIBRARY AppKit)
find_library(COREAUDIO_LIBRARY CoreAudio)
find_library(COREGRAPHICS_LIBRARY CoreGraphics)
@@ -84,7 +83,6 @@ else()
${IOKIT_LIBRARY}
${COREFOUNDATION_LIBRARY}
${CARBON_LIBRARY}
- ${AGL_LIBRARY}
${APPKIT_LIBRARY}
${COREAUDIO_LIBRARY}
${AUDIOTOOLBOX_LIBRARY}
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index da5d2ef22c..7cce190f6a 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -13,7 +13,7 @@ elseif (WINDOWS)
foreach(hive HKEY_CURRENT_USER HKEY_LOCAL_MACHINE)
# prefer more recent Python versions to older ones, if multiple versions
# are installed
- foreach(pyver 3.12 3.11 3.10 3.9 3.8 3.7)
+ foreach(pyver 3.13 3.12 3.11 3.10 3.9 3.8 3.7)
list(APPEND regpaths "[${hive}\\SOFTWARE\\Python\\PythonCore\\${pyver}\\InstallPath]")
endforeach()
endforeach()
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
deleted file mode 100644
index 8b13789179..0000000000
--- a/indra/edit-me-to-trigger-new-build.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
index c3be8bc78e..6744c8d8a4 100644
--- a/indra/llappearance/CMakeLists.txt
+++ b/indra/llappearance/CMakeLists.txt
@@ -14,6 +14,7 @@ set(llappearance_SOURCE_FILES
llavatarjoint.cpp
llavatarjointmesh.cpp
lldriverparam.cpp
+ lljointdata.h
lllocaltextureobject.cpp
llpolyskeletaldistortion.cpp
llpolymesh.cpp
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 3d66809ed6..dab18c240d 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -29,16 +29,17 @@
#include "llavatarappearance.h"
#include "llavatarappearancedefines.h"
#include "llavatarjointmesh.h"
+#include "lljointdata.h"
#include "llstl.h"
#include "lldir.h"
#include "llpolymorph.h"
#include "llpolymesh.h"
#include "llpolyskeletaldistortion.h"
-#include "llstl.h"
#include "lltexglobalcolor.h"
#include "llwearabledata.h"
#include "boost/bind.hpp"
#include "boost/tokenizer.hpp"
+#include "v4math.h"
using namespace LLAvatarAppearanceDefines;
@@ -71,11 +72,13 @@ public:
mChildren.clear();
}
bool parseXml(LLXmlTreeNode* node);
+ glm::mat4 getJointMatrix();
private:
std::string mName;
std::string mSupport;
std::string mAliases;
+ std::string mGroup;
bool mIsJoint;
LLVector3 mPos;
LLVector3 mEnd;
@@ -105,11 +108,17 @@ public:
S32 getNumBones() const { return mNumBones; }
S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; }
+private:
+ typedef std::vector bone_info_list_t;
+ static void getJointMatricesAndHierarhy(
+ LLAvatarBoneInfo* bone_info,
+ LLJointData& data,
+ const glm::mat4& parent_mat);
+
private:
S32 mNumBones;
S32 mNumCollisionVolumes;
LLAvatarAppearance::joint_alias_map_t mJointAliasMap;
- typedef std::vector bone_info_list_t;
bone_info_list_t mBoneInfoList;
};
@@ -1598,6 +1607,15 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
mSupport = "base";
}
+ // Skeleton has 133 bones, but shader only allows 110 (LL_MAX_JOINTS_PER_MESH_OBJECT)
+ // Groups can be used by importer to cut out unused groups of joints
+ static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
+ if (!node->getFastAttributeString(group_string, mGroup))
+ {
+ LL_WARNS() << "Bone without group " << mName << LL_ENDL;
+ mGroup = "global";
+ }
+
if (mIsJoint)
{
static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
@@ -1623,6 +1641,21 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
return true;
}
+
+glm::mat4 LLAvatarBoneInfo::getJointMatrix()
+{
+ glm::mat4 mat(1.0f);
+ // 1. Scaling
+ mat = glm::scale(mat, glm::vec3(mScale[0], mScale[1], mScale[2]));
+ // 2. Rotation (Euler angles rad)
+ mat = glm::rotate(mat, mRot[0], glm::vec3(1, 0, 0));
+ mat = glm::rotate(mat, mRot[1], glm::vec3(0, 1, 0));
+ mat = glm::rotate(mat, mRot[2], glm::vec3(0, 0, 1));
+ // 3. Position
+ mat = glm::translate(mat, glm::vec3(mPos[0], mPos[1], mPos[2]));
+ return mat;
+}
+
//-----------------------------------------------------------------------------
// LLAvatarSkeletonInfo::parseXml()
//-----------------------------------------------------------------------------
@@ -1653,6 +1686,25 @@ bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
return true;
}
+void LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(
+ LLAvatarBoneInfo* bone_info,
+ LLJointData& data,
+ const glm::mat4& parent_mat)
+{
+ data.mName = bone_info->mName;
+ data.mJointMatrix = bone_info->getJointMatrix();
+ data.mScale = glm::vec3(bone_info->mScale[0], bone_info->mScale[1], bone_info->mScale[2]);
+ data.mRotation = bone_info->mRot;
+ data.mRestMatrix = parent_mat * data.mJointMatrix;
+ data.mIsJoint = bone_info->mIsJoint;
+ data.mGroup = bone_info->mGroup;
+ for (LLAvatarBoneInfo* child_info : bone_info->mChildren)
+ {
+ LLJointData& child_data = data.mChildren.emplace_back();
+ getJointMatricesAndHierarhy(child_info, child_data, data.mRestMatrix);
+ }
+}
+
//Make aliases for joint and push to map.
void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info)
{
@@ -1714,6 +1766,16 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases
return mJointAliasMap;
}
+void LLAvatarAppearance::getJointMatricesAndHierarhy(std::vector &data) const
+{
+ glm::mat4 identity(1.f);
+ for (LLAvatarBoneInfo* bone_info : sAvatarSkeletonInfo->mBoneInfoList)
+ {
+ LLJointData& child_data = data.emplace_back();
+ LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(bone_info, child_data, identity);
+ }
+}
+
//-----------------------------------------------------------------------------
// parseXmlSkeletonNode(): parses nodes from XML tree
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 13e504e639..84cb42056a 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -34,6 +34,7 @@
#include "lltexlayer.h"
#include "llviewervisualparam.h"
#include "llxmltree.h"
+#include "v4math.h"
class LLTexLayerSet;
class LLTexGlobalColor;
@@ -41,6 +42,7 @@ class LLTexGlobalColorInfo;
class LLWearableData;
class LLAvatarBoneInfo;
class LLAvatarSkeletonInfo;
+class LLJointData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLAvatarAppearance
@@ -138,7 +140,7 @@ public:
LLVector3 mHeadOffset{}; // current head position
LLAvatarJoint* mRoot{ nullptr };
- typedef std::map joint_map_t;
+ typedef std::map> joint_map_t;
joint_map_t mJointMap;
typedef std::map joint_state_map_t;
@@ -151,9 +153,11 @@ public:
public:
typedef std::vector avatar_joint_list_t;
const avatar_joint_list_t& getSkeleton() { return mSkeleton; }
- typedef std::map joint_alias_map_t;
+ typedef std::map> joint_alias_map_t;
const joint_alias_map_t& getJointAliases();
-
+ typedef std::map joint_parent_map_t; // matrix plus parent
+ typedef std::map joint_rest_map_t;
+ void getJointMatricesAndHierarhy(std::vector &data) const;
protected:
static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree);
diff --git a/indra/llappearance/lljointdata.h b/indra/llappearance/lljointdata.h
new file mode 100644
index 0000000000..2fc26198ee
--- /dev/null
+++ b/indra/llappearance/lljointdata.h
@@ -0,0 +1,66 @@
+/**
+ * @file lljointdata.h
+ * @brief LLJointData class for holding individual joint data and skeleton
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLJOINTDATA_H
+#define LL_LLJOINTDATA_H
+
+#include "v4math.h"
+
+// may be just move LLAvatarBoneInfo
+class LLJointData
+{
+public:
+ std::string mName;
+ std::string mGroup;
+ glm::mat4 mJointMatrix;
+ glm::mat4 mRestMatrix;
+ glm::vec3 mScale;
+ LLVector3 mRotation;
+
+ typedef std::vector bones_t;
+ bones_t mChildren;
+
+ bool mIsJoint; // if not, collision_volume
+ enum SupportCategory
+ {
+ SUPPORT_BASE,
+ SUPPORT_EXTENDED
+ };
+ SupportCategory mSupport;
+ void setSupport(const std::string& support)
+ {
+ if (support == "extended")
+ {
+ mSupport = SUPPORT_EXTENDED;
+ }
+ else
+ {
+ mSupport = SUPPORT_BASE;
+ }
+ }
+};
+
+#endif //LL_LLJOINTDATA_H
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index 8df8a9726f..5ee6649164 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -550,12 +550,12 @@ void LLPolyMorphTarget::apply( ESex avatar_sex )
mLastSex = avatar_sex;
- // Check for NaN condition (NaN is detected if a variable doesn't equal itself.
- if (mCurWeight != mCurWeight)
+ // Check for NaN condition
+ if (llisnan(mCurWeight))
{
- mCurWeight = 0.0;
+ mCurWeight = 0.f;
}
- if (mLastWeight != mLastWeight)
+ if (llisnan(mLastWeight))
{
mLastWeight = mCurWeight+.001f;
}
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index aa48a2d621..b3800e6981 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1293,7 +1293,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
{
if (!force_render && !hasMorph())
{
- LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL;
+ LL_DEBUGS("Morph") << "skipping renderMorphMasks for " << getUUID() << LL_ENDL;
return;
}
LL_PROFILE_ZONE_SCOPED;
@@ -1325,7 +1325,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
success &= param->render( x, y, width, height );
if (!success && !force_render)
{
- LL_DEBUGS() << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL;
+ LL_DEBUGS("Morph") << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL;
return;
}
}
@@ -1365,7 +1365,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
else
{
- LL_WARNS() << "Skipping rendering of " << getInfo()->mStaticImageFileName
+ LL_WARNS("Morph") << "Skipping rendering of " << getInfo()->mStaticImageFileName
<< "; expected 1 or 4 components." << LL_ENDL;
}
}
@@ -1404,8 +1404,8 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// We can get bad morph masks during login, on minimize, and occasional gl errors.
// We should only be doing this when we believe something has changed with respect to the user's appearance.
{
- LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
- // clear out a slot if we have filled our cache
+ LL_DEBUGS("Morph") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
+ // clear out a slot if we have filled our cache
S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
while ((S32)mAlphaCache.size() >= max_cache_entries)
{
@@ -1444,13 +1444,20 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
-
- U8* alpha_cursor = alpha_data;
- U8* pixel = temp;
- for (int i = 0; i < pixels; i++)
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR)
{
- *alpha_cursor++ = pixel[3];
- pixel += 4;
+ LL_INFOS("Morph") << "GL Error while reading back morph texture. Error code: " << error << LL_ENDL;
+ }
+ else
+ {
+ U8* alpha_cursor = alpha_data;
+ U8* pixel = temp;
+ for (int i = 0; i < pixels; i++)
+ {
+ *alpha_cursor++ = pixel[3];
+ pixel += 4;
+ }
}
gGL.getTexUnit(0)->disable();
diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index 9dace08e6f..581e9f62d5 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -131,7 +131,7 @@ LLQuaternion::Order bvhStringToOrder( char *str )
// LLBVHLoader()
//-----------------------------------------------------------------------------
-LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map& joint_alias_map )
+LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map>& joint_alias_map )
{
reset();
errorLine = 0;
@@ -156,9 +156,9 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error
}
// Recognize all names we've been told are legal.
- for (std::map::value_type& alias_pair : joint_alias_map)
+ for (const auto& [alias, joint] : joint_alias_map)
{
- makeTranslation( alias_pair.first , alias_pair.second );
+ makeTranslation(alias, joint);
}
char error_text[128]; /* Flawfinder: ignore */
diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h
index de31f76dd3..ae2e347ba1 100644
--- a/indra/llcharacter/llbvhloader.h
+++ b/indra/llcharacter/llbvhloader.h
@@ -227,7 +227,7 @@ class LLBVHLoader
friend class LLKeyframeMotion;
public:
// Constructor
- LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map& joint_alias_map );
+ LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map>& joint_alias_map );
~LLBVHLoader();
/*
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index ecbcdb3bf5..8efcd9dd29 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -77,12 +77,11 @@ LLCharacter::~LLCharacter()
//-----------------------------------------------------------------------------
// getJoint()
//-----------------------------------------------------------------------------
-LLJoint *LLCharacter::getJoint( const std::string &name )
+LLJoint* LLCharacter::getJoint(std::string_view name)
{
- LLJoint* joint = NULL;
+ LLJoint* joint = nullptr;
- LLJoint *root = getRootJoint();
- if (root)
+ if (LLJoint* root = getRootJoint())
{
joint = root->findJoint(name);
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 6143ec8cd1..079bcd132a 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -76,7 +76,7 @@ public:
// get the specified joint
// default implementation does recursive search,
// subclasses may optimize/cache results.
- virtual LLJoint *getJoint( const std::string &name );
+ virtual LLJoint* getJoint(std::string_view name);
// get the position of the character
virtual LLVector3 getCharacterPosition() = 0;
@@ -119,6 +119,8 @@ public:
virtual void addDebugText( const std::string& text ) = 0;
+ virtual std::string getDebugName() const { return getID().asString(); }
+
virtual const LLUUID& getID() const = 0;
//-------------------------------------------------------------------------
// End Interface
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index f31aa5d4c9..405e62a38b 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -242,21 +242,20 @@ LLJoint *LLJoint::getRoot()
//-----------------------------------------------------------------------------
// findJoint()
//-----------------------------------------------------------------------------
-LLJoint *LLJoint::findJoint( const std::string &name )
+LLJoint* LLJoint::findJoint(std::string_view name)
{
if (name == getName())
return this;
for (LLJoint* joint : mChildren)
{
- LLJoint *found = joint->findJoint(name);
- if (found)
+ if (LLJoint* found = joint->findJoint(name))
{
return found;
}
}
- return NULL;
+ return nullptr;
}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 763c1e3865..b58dc797f8 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -222,7 +222,7 @@ public:
LLJoint *getRoot();
// search for child joints by name
- LLJoint *findJoint( const std::string &name );
+ LLJoint* findJoint(std::string_view name);
// add/remove children
void addChild( LLJoint *joint );
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index c6bdab007f..a0394da281 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -31,15 +31,15 @@
class LLUUID;
-static const F32 REGION_WIDTH_METERS = 256.f;
-static const S32 REGION_WIDTH_UNITS = 256;
-static const U32 REGION_WIDTH_U32 = 256;
+static constexpr F32 REGION_WIDTH_METERS = 256.f;
+static constexpr S32 REGION_WIDTH_UNITS = 256;
+static constexpr U32 REGION_WIDTH_U32 = 256;
-const F32 REGION_HEIGHT_METERS = 4096.f;
+constexpr F32 REGION_HEIGHT_METERS = 4096.f;
-const F32 DEFAULT_AGENT_DEPTH = 0.45f;
-const F32 DEFAULT_AGENT_WIDTH = 0.60f;
-const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
+constexpr F32 DEFAULT_AGENT_DEPTH = 0.45f;
+constexpr F32 DEFAULT_AGENT_WIDTH = 0.60f;
+constexpr F32 DEFAULT_AGENT_HEIGHT = 1.9f;
enum ETerrainBrushType
{
@@ -67,112 +67,112 @@ enum EMouseClickType{
// keys
// Bit masks for various keyboard modifier keys.
-const MASK MASK_NONE = 0x0000;
-const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
-const MASK MASK_ALT = 0x0002;
-const MASK MASK_SHIFT = 0x0004;
-const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
-const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
-const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
+constexpr MASK MASK_NONE = 0x0000;
+constexpr MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
+constexpr MASK MASK_ALT = 0x0002;
+constexpr MASK MASK_SHIFT = 0x0004;
+constexpr MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
+constexpr MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
+constexpr MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
// Special keys go into >128
-const KEY KEY_SPECIAL = 0x80; // special keys start here
-const KEY KEY_RETURN = 0x81;
-const KEY KEY_LEFT = 0x82;
-const KEY KEY_RIGHT = 0x83;
-const KEY KEY_UP = 0x84;
-const KEY KEY_DOWN = 0x85;
-const KEY KEY_ESCAPE = 0x86;
-const KEY KEY_BACKSPACE =0x87;
-const KEY KEY_DELETE = 0x88;
-const KEY KEY_SHIFT = 0x89;
-const KEY KEY_CONTROL = 0x8A;
-const KEY KEY_ALT = 0x8B;
-const KEY KEY_HOME = 0x8C;
-const KEY KEY_END = 0x8D;
-const KEY KEY_PAGE_UP = 0x8E;
-const KEY KEY_PAGE_DOWN = 0x8F;
-const KEY KEY_HYPHEN = 0x90;
-const KEY KEY_EQUALS = 0x91;
-const KEY KEY_INSERT = 0x92;
-const KEY KEY_CAPSLOCK = 0x93;
-const KEY KEY_TAB = 0x94;
-const KEY KEY_ADD = 0x95;
-const KEY KEY_SUBTRACT =0x96;
-const KEY KEY_MULTIPLY =0x97;
-const KEY KEY_DIVIDE = 0x98;
-const KEY KEY_F1 = 0xA1;
-const KEY KEY_F2 = 0xA2;
-const KEY KEY_F3 = 0xA3;
-const KEY KEY_F4 = 0xA4;
-const KEY KEY_F5 = 0xA5;
-const KEY KEY_F6 = 0xA6;
-const KEY KEY_F7 = 0xA7;
-const KEY KEY_F8 = 0xA8;
-const KEY KEY_F9 = 0xA9;
-const KEY KEY_F10 = 0xAA;
-const KEY KEY_F11 = 0xAB;
-const KEY KEY_F12 = 0xAC;
+constexpr KEY KEY_SPECIAL = 0x80; // special keys start here
+constexpr KEY KEY_RETURN = 0x81;
+constexpr KEY KEY_LEFT = 0x82;
+constexpr KEY KEY_RIGHT = 0x83;
+constexpr KEY KEY_UP = 0x84;
+constexpr KEY KEY_DOWN = 0x85;
+constexpr KEY KEY_ESCAPE = 0x86;
+constexpr KEY KEY_BACKSPACE =0x87;
+constexpr KEY KEY_DELETE = 0x88;
+constexpr KEY KEY_SHIFT = 0x89;
+constexpr KEY KEY_CONTROL = 0x8A;
+constexpr KEY KEY_ALT = 0x8B;
+constexpr KEY KEY_HOME = 0x8C;
+constexpr KEY KEY_END = 0x8D;
+constexpr KEY KEY_PAGE_UP = 0x8E;
+constexpr KEY KEY_PAGE_DOWN = 0x8F;
+constexpr KEY KEY_HYPHEN = 0x90;
+constexpr KEY KEY_EQUALS = 0x91;
+constexpr KEY KEY_INSERT = 0x92;
+constexpr KEY KEY_CAPSLOCK = 0x93;
+constexpr KEY KEY_TAB = 0x94;
+constexpr KEY KEY_ADD = 0x95;
+constexpr KEY KEY_SUBTRACT =0x96;
+constexpr KEY KEY_MULTIPLY =0x97;
+constexpr KEY KEY_DIVIDE = 0x98;
+constexpr KEY KEY_F1 = 0xA1;
+constexpr KEY KEY_F2 = 0xA2;
+constexpr KEY KEY_F3 = 0xA3;
+constexpr KEY KEY_F4 = 0xA4;
+constexpr KEY KEY_F5 = 0xA5;
+constexpr KEY KEY_F6 = 0xA6;
+constexpr KEY KEY_F7 = 0xA7;
+constexpr KEY KEY_F8 = 0xA8;
+constexpr KEY KEY_F9 = 0xA9;
+constexpr KEY KEY_F10 = 0xAA;
+constexpr KEY KEY_F11 = 0xAB;
+constexpr KEY KEY_F12 = 0xAC;
-const KEY KEY_PAD_UP = 0xC0;
-const KEY KEY_PAD_DOWN = 0xC1;
-const KEY KEY_PAD_LEFT = 0xC2;
-const KEY KEY_PAD_RIGHT = 0xC3;
-const KEY KEY_PAD_HOME = 0xC4;
-const KEY KEY_PAD_END = 0xC5;
-const KEY KEY_PAD_PGUP = 0xC6;
-const KEY KEY_PAD_PGDN = 0xC7;
-const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
-const KEY KEY_PAD_INS = 0xC9;
-const KEY KEY_PAD_DEL = 0xCA;
-const KEY KEY_PAD_RETURN = 0xCB;
-const KEY KEY_PAD_ADD = 0xCC; // not used
-const KEY KEY_PAD_SUBTRACT = 0xCD; // not used
-const KEY KEY_PAD_MULTIPLY = 0xCE; // not used
-const KEY KEY_PAD_DIVIDE = 0xCF; // not used
+constexpr KEY KEY_PAD_UP = 0xC0;
+constexpr KEY KEY_PAD_DOWN = 0xC1;
+constexpr KEY KEY_PAD_LEFT = 0xC2;
+constexpr KEY KEY_PAD_RIGHT = 0xC3;
+constexpr KEY KEY_PAD_HOME = 0xC4;
+constexpr KEY KEY_PAD_END = 0xC5;
+constexpr KEY KEY_PAD_PGUP = 0xC6;
+constexpr KEY KEY_PAD_PGDN = 0xC7;
+constexpr KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
+constexpr KEY KEY_PAD_INS = 0xC9;
+constexpr KEY KEY_PAD_DEL = 0xCA;
+constexpr KEY KEY_PAD_RETURN = 0xCB;
+constexpr KEY KEY_PAD_ADD = 0xCC; // not used
+constexpr KEY KEY_PAD_SUBTRACT = 0xCD; // not used
+constexpr KEY KEY_PAD_MULTIPLY = 0xCE; // not used
+constexpr KEY KEY_PAD_DIVIDE = 0xCF; // not used
-const KEY KEY_BUTTON0 = 0xD0;
-const KEY KEY_BUTTON1 = 0xD1;
-const KEY KEY_BUTTON2 = 0xD2;
-const KEY KEY_BUTTON3 = 0xD3;
-const KEY KEY_BUTTON4 = 0xD4;
-const KEY KEY_BUTTON5 = 0xD5;
-const KEY KEY_BUTTON6 = 0xD6;
-const KEY KEY_BUTTON7 = 0xD7;
-const KEY KEY_BUTTON8 = 0xD8;
-const KEY KEY_BUTTON9 = 0xD9;
-const KEY KEY_BUTTON10 = 0xDA;
-const KEY KEY_BUTTON11 = 0xDB;
-const KEY KEY_BUTTON12 = 0xDC;
-const KEY KEY_BUTTON13 = 0xDD;
-const KEY KEY_BUTTON14 = 0xDE;
-const KEY KEY_BUTTON15 = 0xDF;
+constexpr KEY KEY_BUTTON0 = 0xD0;
+constexpr KEY KEY_BUTTON1 = 0xD1;
+constexpr KEY KEY_BUTTON2 = 0xD2;
+constexpr KEY KEY_BUTTON3 = 0xD3;
+constexpr KEY KEY_BUTTON4 = 0xD4;
+constexpr KEY KEY_BUTTON5 = 0xD5;
+constexpr KEY KEY_BUTTON6 = 0xD6;
+constexpr KEY KEY_BUTTON7 = 0xD7;
+constexpr KEY KEY_BUTTON8 = 0xD8;
+constexpr KEY KEY_BUTTON9 = 0xD9;
+constexpr KEY KEY_BUTTON10 = 0xDA;
+constexpr KEY KEY_BUTTON11 = 0xDB;
+constexpr KEY KEY_BUTTON12 = 0xDC;
+constexpr KEY KEY_BUTTON13 = 0xDD;
+constexpr KEY KEY_BUTTON14 = 0xDE;
+constexpr KEY KEY_BUTTON15 = 0xDF;
-const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
+constexpr KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
-const S32 KEY_COUNT = 256;
+constexpr S32 KEY_COUNT = 256;
-const F32 DEFAULT_WATER_HEIGHT = 20.0f;
+constexpr F32 DEFAULT_WATER_HEIGHT = 20.0f;
// Maturity ratings for simulators
-const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
-const U8 SIM_ACCESS_PG = 13;
-const U8 SIM_ACCESS_MATURE = 21;
-const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
-const U8 SIM_ACCESS_DOWN = 254;
-const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
+constexpr U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
+constexpr U8 SIM_ACCESS_PG = 13;
+constexpr U8 SIM_ACCESS_MATURE = 21;
+constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
+constexpr U8 SIM_ACCESS_DOWN = 254;
+constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
// attachment constants
-const U8 ATTACHMENT_ADD = 0x80;
+constexpr U8 ATTACHMENT_ADD = 0x80;
// god levels
-const U8 GOD_MAINTENANCE = 250;
-const U8 GOD_FULL = 200;
-const U8 GOD_LIAISON = 150;
-const U8 GOD_CUSTOMER_SERVICE = 100;
-const U8 GOD_LIKE = 1;
-const U8 GOD_NOT = 0;
+constexpr U8 GOD_MAINTENANCE = 250;
+constexpr U8 GOD_FULL = 200;
+constexpr U8 GOD_LIAISON = 150;
+constexpr U8 GOD_CUSTOMER_SERVICE = 100;
+constexpr U8 GOD_LIKE = 1;
+constexpr U8 GOD_NOT = 0;
// "agent id" for things that should be done to ALL agents
LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
@@ -239,120 +239,120 @@ LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL;
LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID;
// radius within which a chat message is fully audible
-const F32 CHAT_NORMAL_RADIUS = 20.f;
+constexpr F32 CHAT_NORMAL_RADIUS = 20.f;
// media commands
-const U32 PARCEL_MEDIA_COMMAND_STOP = 0;
-const U32 PARCEL_MEDIA_COMMAND_PAUSE = 1;
-const U32 PARCEL_MEDIA_COMMAND_PLAY = 2;
-const U32 PARCEL_MEDIA_COMMAND_LOOP = 3;
-const U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4;
-const U32 PARCEL_MEDIA_COMMAND_URL = 5;
-const U32 PARCEL_MEDIA_COMMAND_TIME = 6;
-const U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
-const U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
-const U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
-const U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
-const U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
-const U32 PARCEL_MEDIA_COMMAND_DESC = 12;
-const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
+constexpr U32 PARCEL_MEDIA_COMMAND_STOP = 0;
+constexpr U32 PARCEL_MEDIA_COMMAND_PAUSE = 1;
+constexpr U32 PARCEL_MEDIA_COMMAND_PLAY = 2;
+constexpr U32 PARCEL_MEDIA_COMMAND_LOOP = 3;
+constexpr U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4;
+constexpr U32 PARCEL_MEDIA_COMMAND_URL = 5;
+constexpr U32 PARCEL_MEDIA_COMMAND_TIME = 6;
+constexpr U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
+constexpr U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
+constexpr U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
+constexpr U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
+constexpr U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
+constexpr U32 PARCEL_MEDIA_COMMAND_DESC = 12;
+constexpr U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
const S32 CHAT_CHANNEL_DEBUG = S32_MAX;
// agent constants
-const U32 CONTROL_AT_POS_INDEX = 0;
-const U32 CONTROL_AT_NEG_INDEX = 1;
-const U32 CONTROL_LEFT_POS_INDEX = 2;
-const U32 CONTROL_LEFT_NEG_INDEX = 3;
-const U32 CONTROL_UP_POS_INDEX = 4;
-const U32 CONTROL_UP_NEG_INDEX = 5;
-const U32 CONTROL_PITCH_POS_INDEX = 6;
-const U32 CONTROL_PITCH_NEG_INDEX = 7;
-const U32 CONTROL_YAW_POS_INDEX = 8;
-const U32 CONTROL_YAW_NEG_INDEX = 9;
-const U32 CONTROL_FAST_AT_INDEX = 10;
-const U32 CONTROL_FAST_LEFT_INDEX = 11;
-const U32 CONTROL_FAST_UP_INDEX = 12;
-const U32 CONTROL_FLY_INDEX = 13;
-const U32 CONTROL_STOP_INDEX = 14;
-const U32 CONTROL_FINISH_ANIM_INDEX = 15;
-const U32 CONTROL_STAND_UP_INDEX = 16;
-const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
-const U32 CONTROL_MOUSELOOK_INDEX = 18;
-const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
-const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
-const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
-const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
-const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
-const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
-const U32 CONTROL_TURN_LEFT_INDEX = 25;
-const U32 CONTROL_TURN_RIGHT_INDEX = 26;
-const U32 CONTROL_AWAY_INDEX = 27;
-const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
-const U32 CONTROL_LBUTTON_UP_INDEX = 29;
-const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
-const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
-const U32 TOTAL_CONTROLS = 32;
+constexpr U32 CONTROL_AT_POS_INDEX = 0;
+constexpr U32 CONTROL_AT_NEG_INDEX = 1;
+constexpr U32 CONTROL_LEFT_POS_INDEX = 2;
+constexpr U32 CONTROL_LEFT_NEG_INDEX = 3;
+constexpr U32 CONTROL_UP_POS_INDEX = 4;
+constexpr U32 CONTROL_UP_NEG_INDEX = 5;
+constexpr U32 CONTROL_PITCH_POS_INDEX = 6;
+constexpr U32 CONTROL_PITCH_NEG_INDEX = 7;
+constexpr U32 CONTROL_YAW_POS_INDEX = 8;
+constexpr U32 CONTROL_YAW_NEG_INDEX = 9;
+constexpr U32 CONTROL_FAST_AT_INDEX = 10;
+constexpr U32 CONTROL_FAST_LEFT_INDEX = 11;
+constexpr U32 CONTROL_FAST_UP_INDEX = 12;
+constexpr U32 CONTROL_FLY_INDEX = 13;
+constexpr U32 CONTROL_STOP_INDEX = 14;
+constexpr U32 CONTROL_FINISH_ANIM_INDEX = 15;
+constexpr U32 CONTROL_STAND_UP_INDEX = 16;
+constexpr U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
+constexpr U32 CONTROL_MOUSELOOK_INDEX = 18;
+constexpr U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
+constexpr U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
+constexpr U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
+constexpr U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
+constexpr U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
+constexpr U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
+constexpr U32 CONTROL_TURN_LEFT_INDEX = 25;
+constexpr U32 CONTROL_TURN_RIGHT_INDEX = 26;
+constexpr U32 CONTROL_AWAY_INDEX = 27;
+constexpr U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
+constexpr U32 CONTROL_LBUTTON_UP_INDEX = 29;
+constexpr U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
+constexpr U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
+constexpr U32 TOTAL_CONTROLS = 32;
-const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
-const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
-const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
-const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
-const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
-const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
-const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
-const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
-const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
-const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
+constexpr U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
+constexpr U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
+constexpr U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
+constexpr U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
+constexpr U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
+constexpr U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
+constexpr U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
+constexpr U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
+constexpr U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
+constexpr U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
-const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
-const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
-const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
+constexpr U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
+constexpr U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
+constexpr U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
-const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
-const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
-const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
-const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
-const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
-const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
+constexpr U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
+constexpr U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
+constexpr U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
+constexpr U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
+constexpr U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
+constexpr U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
-const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
-const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
-const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
-const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
-const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
-const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
-const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
-const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
+constexpr U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
+constexpr U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
+constexpr U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
+constexpr U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
+constexpr U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
+constexpr U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
+constexpr U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
+constexpr U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
-const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
+constexpr U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
-const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
-const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
-const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
-const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
+constexpr U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
+constexpr U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
+constexpr U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
+constexpr U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
// move these up so that we can hide them in "State" for object updates
// (for now)
-const U32 AGENT_ATTACH_OFFSET = 4;
-const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
+constexpr U32 AGENT_ATTACH_OFFSET = 4;
+constexpr U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
// RN: this method swaps the upper and lower nibbles to maintain backward
// compatibility with old objects that only used the upper nibble
#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
-const U8 CLICK_ACTION_NONE = 0;
-const U8 CLICK_ACTION_TOUCH = 0;
-const U8 CLICK_ACTION_SIT = 1;
-const U8 CLICK_ACTION_BUY = 2;
-const U8 CLICK_ACTION_PAY = 3;
-const U8 CLICK_ACTION_OPEN = 4;
-const U8 CLICK_ACTION_PLAY = 5;
-const U8 CLICK_ACTION_OPEN_MEDIA = 6;
-const U8 CLICK_ACTION_ZOOM = 7;
-const U8 CLICK_ACTION_DISABLED = 8;
-const U8 CLICK_ACTION_IGNORE = 9;
+constexpr U8 CLICK_ACTION_NONE = 0;
+constexpr U8 CLICK_ACTION_TOUCH = 0;
+constexpr U8 CLICK_ACTION_SIT = 1;
+constexpr U8 CLICK_ACTION_BUY = 2;
+constexpr U8 CLICK_ACTION_PAY = 3;
+constexpr U8 CLICK_ACTION_OPEN = 4;
+constexpr U8 CLICK_ACTION_PLAY = 5;
+constexpr U8 CLICK_ACTION_OPEN_MEDIA = 6;
+constexpr U8 CLICK_ACTION_ZOOM = 7;
+constexpr U8 CLICK_ACTION_DISABLED = 8;
+constexpr U8 CLICK_ACTION_IGNORE = 9;
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
constexpr U32 BEACON_SHOW_MAP = 0x0001;
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index c09cf7abd2..9672a3262b 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -29,6 +29,7 @@
#include "llassettype.h"
#include "lldictionary.h"
#include "llmemory.h"
+#include "llsd.h"
#include "llsingleton.h"
///----------------------------------------------------------------------------
@@ -246,3 +247,19 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type)
}
return false;
}
+
+LLSD LLAssetType::getTypeNames()
+{
+ LLSD type_names;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (S32 type = AT_TEXTURE; type < AT_COUNT; ++type)
+ {
+ const AssetEntry *entry = dict->lookup((LLAssetType::EType) type);
+ // skip llassettype_bad_lookup
+ if (entry)
+ {
+ type_names.append(entry->mTypeName);
+ }
+ }
+ return type_names;
+}
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 547c3f4329..17177d81c3 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -165,6 +165,8 @@ public:
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
+ static LLSD getTypeNames();
+
static const std::string BADLOOKUP;
protected:
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 2fbb26dc1a..232987da14 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -171,13 +171,13 @@ constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 +
// recursion tail
template
-inline auto llmax(T data)
+constexpr auto llmax(T data)
{
return data;
}
template
-inline auto llmax(T0 d0, T1 d1, Ts... rest)
+constexpr auto llmax(T0 d0, T1 d1, Ts... rest)
{
auto maxrest = llmax(d1, rest...);
return (d0 > maxrest)? d0 : maxrest;
@@ -185,20 +185,20 @@ inline auto llmax(T0 d0, T1 d1, Ts... rest)
// recursion tail
template
-inline auto llmin(T data)
+constexpr auto llmin(T data)
{
return data;
}
template
-inline auto llmin(T0 d0, T1 d1, Ts... rest)
+constexpr auto llmin(T0 d0, T1 d1, Ts... rest)
{
auto minrest = llmin(d1, rest...);
return (d0 < minrest) ? d0 : minrest;
}
template
-inline A llclamp(A a, MIN minval, MAX maxval)
+constexpr A llclamp(A a, MIN minval, MAX maxval)
{
A aminval{ static_cast(minval) }, amaxval{ static_cast(maxval) };
if ( a < aminval )
@@ -213,13 +213,13 @@ inline A llclamp(A a, MIN minval, MAX maxval)
}
template
-inline LLDATATYPE llclampf(LLDATATYPE a)
+constexpr LLDATATYPE llclampf(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
}
template
-inline LLDATATYPE llclampb(LLDATATYPE a)
+constexpr LLDATATYPE llclampb(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index c31030c5ea..497c0ad3eb 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -553,6 +553,45 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
} // namespace llsd
+/*****************************************************************************
+* LLSDParam>
+*****************************************************************************/
+// Given an LLSD array, return a const std::vector&, where T is a type
+// supported by LLSDParam. Bonus: if the LLSD value is actually a scalar,
+// return a single-element vector containing the converted value.
+template
+class LLSDParam>: public LLSDParamBase
+{
+public:
+ LLSDParam(const LLSD& array)
+ {
+ // treat undefined "array" as empty vector
+ if (array.isDefined())
+ {
+ // what if it's a scalar?
+ if (! array.isArray())
+ {
+ v.push_back(LLSDParam(array));
+ }
+ else // really is an array
+ {
+ // reserve space for the array entries
+ v.reserve(array.size());
+ for (const auto& item : llsd::inArray(array))
+ {
+ v.push_back(LLSDParam(item));
+ }
+ }
+ }
+ }
+
+ operator const std::vector&() const { return v; }
+
+private:
+ std::vector v;
+};
+
+
/*****************************************************************************
* toArray(), toMap()
*****************************************************************************/
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e5d25b52f0..692941a892 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -28,6 +28,7 @@
#include "apr_portable.h"
+#include "llapp.h"
#include "llthread.h"
#include "llmutex.h"
@@ -35,6 +36,7 @@
#include "lltrace.h"
#include "lltracethreadrecorder.h"
#include "llexception.h"
+#include "workqueue.h"
#if LL_LINUX
#include
@@ -106,6 +108,27 @@ namespace
return s_thread_id;
}
+#if LL_WINDOWS
+
+ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+
+ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
+ {
+ if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
+ {
+ // Handled
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // handle it, convert to std::exception
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+#endif // LL_WINDOWS
} // anonymous namespace
LL_COMMON_API bool on_main_thread()
@@ -157,20 +180,11 @@ void LLThread::threadRun()
// Run the user supplied function
do
{
- try
- {
- run();
- }
- catch (const LLContinueError &e)
- {
- LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
- "' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
- //output possible call stacks to log file.
- LLError::LLCallStacks::print();
-
- LOG_UNHANDLED_EXCEPTION("LLThread");
- continue;
- }
+#ifdef LL_WINDOWS
+ sehHandle(); // Structured Exception Handling
+#else
+ tryRun();
+#endif
break;
} while (true);
@@ -188,6 +202,69 @@ void LLThread::threadRun()
mStatus = STOPPED;
}
+void LLThread::tryRun()
+{
+ try
+ {
+ run();
+ }
+ catch (const LLContinueError& e)
+ {
+ LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
+ "'. Error what is: '" << e.what() << "'" << LL_ENDL;
+ LLError::LLCallStacks::print();
+
+ LOG_UNHANDLED_EXCEPTION("LLThread");
+ }
+ catch (std::bad_alloc&)
+ {
+ // Todo: improve this, this is going to have a different callstack
+ // instead of showing where it crashed
+ LL_WARNS("THREAD") << "Out of memory in a thread: " << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ []() {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("THREAD") << "Out of memory in a thread" << LL_ENDL;
+ });
+ }
+#ifndef LL_WINDOWS
+ catch (...)
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("THREAD") << "Capturing and rethrowing uncaught exception in LLThread "
+ << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+#endif // else LL_WINDOWS
+}
+
+#ifdef LL_WINDOWS
+void LLThread::sehHandle()
+{
+ __try
+ {
+ // handle stop and continue exceptions first
+ tryRun();
+ }
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ // convert to C++ styled exception
+ // Note: it might be better to use _se_set_translator
+ // if you want exception to inherit full callstack
+ char integer_string[512];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
+}
+#endif
+
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(false),
mName(name),
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 4194e0014d..8794ac93aa 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -68,7 +68,7 @@ public:
// Called from MAIN THREAD.
void pause();
void unpause();
- bool isPaused() { return isStopped() || mPaused; }
+ bool isPaused() const { return isStopped() || mPaused; }
// Cause the thread to wake up and check its condition
void wake();
@@ -97,6 +97,11 @@ private:
// static function passed to APR thread creation routine
void threadRun();
+ void tryRun();
+
+#ifdef LL_WINDOWS
+ void sehHandle();
+#endif
protected:
std::string mName;
diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h
index 28e50b3d21..f1e4c2bc78 100644
--- a/indra/llcommon/stdtypes.h
+++ b/indra/llcommon/stdtypes.h
@@ -164,14 +164,14 @@ private:
FROM mValue;
public:
- narrow(FROM value): mValue(value) {}
+ constexpr narrow(FROM value): mValue(value) {}
/*---------------------- Narrowing unsigned to signed ----------------------*/
template ::value &&
std::is_signed::value,
bool>::type = true>
- inline
+ constexpr
operator TO() const
{
// The reason we skip the
@@ -189,7 +189,7 @@ public:
typename std::enable_if::value &&
std::is_signed::value),
bool>::type = true>
- inline
+ constexpr
operator TO() const
{
// two different assert()s so we can tell which condition failed
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index 0eb1891754..ac4f415f3e 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -55,7 +55,7 @@ namespace LL
* ThreadPool listens for application shutdown messages on the "LLApp"
* LLEventPump. Call close() to shut down this ThreadPool early.
*/
- virtual void close();
+ void close();
std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); }
@@ -122,7 +122,7 @@ namespace LL
size_t threads=1,
size_t capacity=1024*1024,
bool auto_shutdown = true):
- ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown)
+ ThreadPoolBase(name, threads, new queue_t(name, capacity, false), auto_shutdown)
{}
~ThreadPoolUsing() override {}
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index c8ece616b2..7efaebd569 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -21,6 +21,7 @@
#include "llcoros.h"
#include LLCOROS_MUTEX_HEADER
#include "llerror.h"
+#include "llevents.h"
#include "llexception.h"
#include "stringize.h"
@@ -30,11 +31,38 @@ using Lock = LLCoros::LockType;
/*****************************************************************************
* WorkQueueBase
*****************************************************************************/
-LL::WorkQueueBase::WorkQueueBase(const std::string& name):
- super(makeName(name))
+LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown)
+ : super(makeName(name))
{
- // TODO: register for "LLApp" events so we can implicitly close() on
- // viewer shutdown.
+ if (auto_shutdown)
+ {
+ // Register for "LLApp" events so we can implicitly close() on viewer shutdown
+ std::string listener_name = "WorkQueue:" + getKey();
+ LLEventPumps::instance().obtain("LLApp").listen(
+ listener_name,
+ [this](const LLSD& stat)
+ {
+ std::string status(stat["status"]);
+ if (status != "running")
+ {
+ // Viewer is shutting down, close this queue
+ LL_DEBUGS("WorkQueue") << getKey() << " closing on app shutdown" << LL_ENDL;
+ close();
+ }
+ return false;
+ });
+
+ // Store the listener name so we can unregister in the destructor
+ mListenerName = listener_name;
+ }
+}
+
+LL::WorkQueueBase::~WorkQueueBase()
+{
+ if (!mListenerName.empty() && !LLEventPumps::wasDeleted())
+ {
+ LLEventPumps::instance().obtain("LLApp").stopListening(mListenerName);
+ }
}
void LL::WorkQueueBase::runUntilClose()
@@ -182,14 +210,22 @@ void LL::WorkQueueBase::callWork(const Work& work)
}
catch (...)
{
- // Stash any other kind of uncaught exception to be rethrown by main thread.
- LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
- << getKey() << LL_ENDL;
+ if (getKey() != "mainloop")
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
+ << getKey() << LL_ENDL;
- LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
- main_queue->post(
- // Bind the current exception, rethrow it in main loop.
- [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+ else
+ {
+ // let main loop crash
+ throw;
+ }
}
#endif // else LL_WINDOWS
}
@@ -212,8 +248,8 @@ void LL::WorkQueueBase::checkCoroutine(const std::string& method)
/*****************************************************************************
* WorkQueue
*****************************************************************************/
-LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
- super(name),
+LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity, bool auto_shutdown):
+ super(name, auto_shutdown),
mQueue(capacity)
{
}
@@ -261,8 +297,8 @@ bool LL::WorkQueue::tryPop_(Work& work)
/*****************************************************************************
* WorkSchedule
*****************************************************************************/
-LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity):
- super(name),
+LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity, bool auto_shutdown):
+ super(name, auto_shutdown),
mQueue(capacity)
{
}
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 9d7bbfbf7a..735ad38a26 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -51,7 +51,9 @@ namespace LL
* You may omit the WorkQueueBase name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueueBase(const std::string& name);
+ WorkQueueBase(const std::string& name, bool auto_shutdown);
+
+ virtual ~WorkQueueBase();
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -197,6 +199,9 @@ namespace LL
private:
virtual Work pop_() = 0;
virtual bool tryPop_(Work&) = 0;
+
+ // Name used for the LLApp event listener (empty if not registered)
+ std::string mListenerName;
};
/*****************************************************************************
@@ -212,7 +217,7 @@ namespace LL
* You may omit the WorkQueue name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+ WorkQueue(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -282,7 +287,7 @@ namespace LL
* You may omit the WorkSchedule name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkSchedule(const std::string& name = std::string(), size_t capacity=1024);
+ WorkSchedule(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/**
* Since the point of WorkSchedule is to pass work to some other worker
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 6186e7a308..081a4d9bac 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -538,6 +538,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
long sslHostV(0L);
long dnsCacheTimeout(-1L);
long nobody(0L);
+ curl_off_t lastModified(0L);
if (mReqOptions)
{
@@ -546,6 +547,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L;
dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;
+ lastModified = (curl_off_t)mReqOptions->getLastModified();
}
check_curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
@@ -554,6 +556,17 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
+ if (lastModified)
+ {
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+#if (LIBCURL_VERSION_NUM >= 0x073B00)
+ // requires curl 7.59.0
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEVALUE_LARGE, lastModified);
+#else
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEVALUE, (long)lastModified);
+#endif
+ }
+
// The Linksys WRT54G V5 router has an issue with frequent
// DNS lookups from LAN machines. If they happen too often,
// like for every HTTP request, the router gets annoyed after
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index d85f6039b1..5abd28e211 100644
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -47,6 +47,7 @@ HttpOptions::HttpOptions() :
mVerifyPeer(sDefaultVerifyPeer),
mVerifyHost(false),
mDNSCacheTimeout(-1L),
+ mLastModified(0),
mNoBody(false)
{}
@@ -129,6 +130,11 @@ void HttpOptions::setHeadersOnly(bool nobody)
}
}
+void HttpOptions::setLastModified(time_t lastModified)
+{
+ mLastModified = lastModified;
+}
+
void HttpOptions::setDefaultSSLVerifyPeer(bool verify)
{
sDefaultVerifyPeer = verify;
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 56a28013cb..fdb277c66e 100644
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -178,6 +178,13 @@ public:
return mNoBody;
}
+ // Default: 0
+ void setLastModified(time_t lastModified);
+ time_t getLastModified() const
+ {
+ return mLastModified;
+ }
+
/// Sets default behavior for verifying that the name in the
/// security certificate matches the name of the host contacted.
/// Defaults false if not set, but should be set according to
@@ -199,6 +206,7 @@ protected:
bool mVerifyHost;
int mDNSCacheTimeout;
bool mNoBody;
+ time_t mLastModified;
static bool sDefaultVerifyPeer;
}; // end class HttpOptions
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index 9c61c25ada..ea33a3bb90 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -110,9 +110,10 @@ std::vector LLDir::getFilesInDir(const std::string &dirname)
std::vector v;
- if (exists(p))
+ boost::system::error_code ec;
+ if (exists(p, ec) && !ec.failed())
{
- if (is_directory(p))
+ if (is_directory(p, ec) && !ec.failed())
{
boost::filesystem::directory_iterator end_iter;
for (boost::filesystem::directory_iterator dir_itr(p);
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index 2a328675c2..c8f99380ea 100644
--- a/indra/llimage/llimagebmp.cpp
+++ b/indra/llimage/llimagebmp.cpp
@@ -558,6 +558,12 @@ bool LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
LL_INFOS() << "Dropping alpha information during BMP encoding" << LL_ENDL;
}
+ if (raw_image->isBufferInvalid())
+ {
+ setLastError("Invalid input, no buffer");
+ return false;
+ }
+
setSize(raw_image->getWidth(), raw_image->getHeight(), dst_components);
U8 magic[14];
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index d4efbcfad2..c896d60c85 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -75,7 +75,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec)
bool LLImageDimensionsInfo::getImageDimensionsBmp()
{
// Make sure the file is long enough.
- const S32 DATA_LEN = 26; // BMP header (14) + DIB header size (4) + width (4) + height (4)
+ constexpr S32 DATA_LEN = 26; // BMP header (14) + DIB header size (4) + width (4) + height (4)
if (!checkFileLength(DATA_LEN))
{
LL_WARNS() << "Premature end of file" << LL_ENDL;
@@ -105,7 +105,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp()
bool LLImageDimensionsInfo::getImageDimensionsTga()
{
- const S32 TGA_FILE_HEADER_SIZE = 12;
+ constexpr S32 TGA_FILE_HEADER_SIZE = 12;
// Make sure the file is long enough.
if (!checkFileLength(TGA_FILE_HEADER_SIZE + 1 /* width */ + 1 /* height */))
@@ -124,7 +124,7 @@ bool LLImageDimensionsInfo::getImageDimensionsTga()
bool LLImageDimensionsInfo::getImageDimensionsPng()
{
- const S32 PNG_MAGIC_SIZE = 8;
+ constexpr S32 PNG_MAGIC_SIZE = 8;
// Make sure the file is long enough.
if (!checkFileLength(PNG_MAGIC_SIZE + 8 + sizeof(S32) * 2 /* width, height */))
@@ -134,7 +134,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng()
}
// Read PNG signature.
- const U8 png_magic[PNG_MAGIC_SIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
+ constexpr U8 png_magic[PNG_MAGIC_SIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
U8 signature[PNG_MAGIC_SIZE];
mInfile.read((void*)signature, PNG_MAGIC_SIZE);
@@ -166,34 +166,36 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
{
sJpegErrorEncountered = false;
clean();
- FILE *fp = LLFile::fopen(mSrcFilename, "rb");
- if (fp == NULL)
+ FILE* fp = LLFile::fopen(mSrcFilename, "rb");
+ if (!fp)
{
setLastError("Unable to open file for reading", mSrcFilename);
return false;
}
/* Make sure this is a JPEG file. */
- const size_t JPEG_MAGIC_SIZE = 2;
- const U8 jpeg_magic[JPEG_MAGIC_SIZE] = {0xFF, 0xD8};
+ constexpr size_t JPEG_MAGIC_SIZE = 2;
+ constexpr U8 jpeg_magic[JPEG_MAGIC_SIZE] = {0xFF, 0xD8};
U8 signature[JPEG_MAGIC_SIZE];
if (fread(signature, sizeof(signature), 1, fp) != 1)
{
LL_WARNS() << "Premature end of file" << LL_ENDL;
+ fclose(fp);
return false;
}
if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0)
{
LL_WARNS() << "Not a JPEG" << LL_ENDL;
mWarning = "texture_load_format_error";
+ fclose(fp);
return false;
}
fseek(fp, 0, SEEK_SET); // go back to start of the file
/* Init jpeg */
jpeg_error_mgr jerr;
- jpeg_decompress_struct cinfo;
+ jpeg_decompress_struct cinfo{};
cinfo.err = jpeg_std_error(&jerr);
// Call our function instead of exit() if Libjpeg encounters an error.
// This is done to avoid crash in this case (STORM-472).
diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h
index 681d66ae4e..4870f2e815 100644
--- a/indra/llimage/llimagedimensionsinfo.h
+++ b/indra/llimage/llimagedimensionsinfo.h
@@ -38,7 +38,7 @@ class LLImageDimensionsInfo
{
public:
LLImageDimensionsInfo():
- mData(NULL)
+ mData(nullptr)
,mHeight(0)
,mWidth(0)
{}
@@ -67,7 +67,7 @@ protected:
{
mInfile.close();
delete[] mData;
- mData = NULL;
+ mData = nullptr;
mWidth = 0;
mHeight = 0;
}
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 6b960f9077..c3fd0c5aa8 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -329,6 +329,12 @@ bool LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_
{
llassert_always(raw_image);
+ if (raw_image->isBufferInvalid())
+ {
+ setLastError("Invalid input, no buffer");
+ return false;
+ }
+
S32 ncomponents = raw_image->getComponents();
EFileFormat format;
switch (ncomponents)
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index aa161709a1..5a941dc958 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -281,10 +281,11 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
S32 height = (h > 0) ? h : 2048;
S32 max_dimension = llmax(width, height); // Find largest dimension
S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
- block_area *= llmax((max_dimension / MAX_BLOCK_SIZE / max_components), 1); // Adjust initial block area by ratio of largest dimension to block size per component
- S32 totalbytes = (S32) (block_area * max_components * precision); // First block layer computed before loop without compression rate
- S32 block_layers = 1; // Start at layer 1 since first block layer is computed outside loop
- while (block_layers < 6) // Walk five layers for the five discards in JPEG2000
+ S32 max_layers = (S32)llmax(llround(log2f((float)max_dimension) - log2f((float)MAX_BLOCK_SIZE)), 4); // Find number of powers of two between extents and block size to a minimum of 4
+ block_area *= llmax(max_layers, 1); // Adjust initial block area by max number of layers
+ S32 totalbytes = (S32) (MIN_LAYER_SIZE * max_components * precision); // Start estimation with a minimum reasonable size
+ S32 block_layers = 0;
+ while (block_layers <= max_layers) // Walk the layers
{
if (block_layers <= (5 - discard_level)) // Walk backwards from discard 5 to required discard layer.
totalbytes += (S32) (block_area * max_components * precision * rate); // Add each block layer reduced by assumed compression rate
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index 50536a2798..ab6c593fc2 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -499,6 +499,12 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
resetLastError();
+ if (raw_image->isBufferInvalid())
+ {
+ setLastError("Invalid input, no buffer");
+ return false;
+ }
+
LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this);
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index a5943fc0ef..5fa53657a0 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -30,8 +30,6 @@
// this is defined so that we get static linking.
#include "openjpeg.h"
-#define MAX_ENCODED_DISCARD_LEVELS 5
-
// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
{
@@ -112,73 +110,96 @@ public:
static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data)
{
- llassert(user_data);
+ llassert(user_data && buffer);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
- OPJ_SIZE_T remainder = (jpeg_codec->size - jpeg_codec->offset);
- if (remainder <= 0)
+
+ if (jpeg_codec->offset < 0 || static_cast(jpeg_codec->offset) >= jpeg_codec->size)
{
jpeg_codec->offset = jpeg_codec->size;
- // Indicate end of stream (hacky?)
- return (OPJ_OFF_T)-1;
+ return static_cast(-1); // Indicate EOF
}
- OPJ_SIZE_T to_read = llclamp(U32(bytes), U32(0), U32(remainder));
+
+ OPJ_SIZE_T remainder = jpeg_codec->size - static_cast(jpeg_codec->offset);
+ OPJ_SIZE_T to_read = (bytes < remainder) ? bytes : remainder;
+
memcpy(buffer, jpeg_codec->buffer + jpeg_codec->offset, to_read);
jpeg_codec->offset += to_read;
+
return to_read;
}
static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)
{
- llassert(user_data);
+ llassert(user_data && buffer);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
- OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset;
- if (remainder < bytes)
+ OPJ_OFF_T required_offset = jpeg_codec->offset + static_cast(bytes);
+
+ // Overflow check
+ if (required_offset < jpeg_codec->offset)
+ return 0; // Overflow detected
+
+ // Resize if needed (exponential growth)
+ if (required_offset > static_cast(jpeg_codec->size))
{
- OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder);
+ OPJ_SIZE_T new_size = jpeg_codec->size ? jpeg_codec->size : 1024;
+ while (required_offset > static_cast(new_size))
+ new_size *= 2;
+
+ const OPJ_SIZE_T MAX_BUFFER_SIZE = 512 * 1024 * 1024; // 512 MB, increase if needed
+ if (new_size > MAX_BUFFER_SIZE) return 0;
+
U8* new_buffer = (U8*)ll_aligned_malloc_16(new_size);
- memcpy(new_buffer, jpeg_codec->buffer, jpeg_codec->offset);
- U8* old_buffer = jpeg_codec->buffer;
+ if (!new_buffer) return 0; // Allocation failed
+
+ if (jpeg_codec->offset > 0)
+ memcpy(new_buffer, jpeg_codec->buffer, static_cast(jpeg_codec->offset));
+
+ ll_aligned_free_16(jpeg_codec->buffer);
jpeg_codec->buffer = new_buffer;
- ll_aligned_free_16(old_buffer);
jpeg_codec->size = new_size;
}
- memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, bytes);
- jpeg_codec->offset += bytes;
+
+ memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, static_cast(bytes));
+ jpeg_codec->offset = required_offset;
return bytes;
}
static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
{
+ llassert(user_data);
JPEG2KBase* jpeg_codec = static_cast(user_data);
- jpeg_codec->offset += bytes;
- if (jpeg_codec->offset > (OPJ_OFF_T)jpeg_codec->size)
+ OPJ_OFF_T new_offset = jpeg_codec->offset + bytes;
+
+ if (new_offset < 0 || new_offset > static_cast(jpeg_codec->size))
{
- jpeg_codec->offset = jpeg_codec->size;
- // Indicate end of stream
- return (OPJ_OFF_T)-1;
- }
-
- if (jpeg_codec->offset < 0)
- {
- // Shouldn't be possible?
- jpeg_codec->offset = 0;
+ // Clamp and indicate EOF or error
+ jpeg_codec->offset = llclamp(new_offset, 0, static_cast(jpeg_codec->size));
return (OPJ_OFF_T)-1;
}
+ jpeg_codec->offset = new_offset;
return bytes;
}
-static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data)
+static OPJ_BOOL opj_seek(OPJ_OFF_T offset, void * user_data)
{
+ llassert(user_data);
JPEG2KBase* jpeg_codec = static_cast(user_data);
- jpeg_codec->offset = bytes;
- jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size));
+
+ if (offset < 0 || offset > static_cast(jpeg_codec->size))
+ return OPJ_FALSE;
+
+ jpeg_codec->offset = offset;
return OPJ_TRUE;
}
static void opj_free_user_data(void * user_data)
{
+ llassert(user_data);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
// Don't free, data is managed externally
jpeg_codec->buffer = nullptr;
@@ -188,14 +209,54 @@ static void opj_free_user_data(void * user_data)
static void opj_free_user_data_write(void * user_data)
{
+ llassert(user_data);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
// Free, data was allocated here
- ll_aligned_free_16(jpeg_codec->buffer);
- jpeg_codec->buffer = nullptr;
+ if (jpeg_codec->buffer)
+ {
+ ll_aligned_free_16(jpeg_codec->buffer);
+ jpeg_codec->buffer = nullptr;
+ }
jpeg_codec->size = 0;
jpeg_codec->offset = 0;
}
+/**
+ * Estimates the number of layers necessary depending on the image surface (w x h)
+ */
+static U32 estimate_num_layers(U32 surface)
+{
+ if (surface <= 1024) return 2; // Tiny (≤32×32)
+ else if (surface <= 16384) return 3; // Small (≤128×128)
+ else if (surface <= 262144) return 4; // Medium (≤512×512)
+ else if (surface <= 1048576) return 5; // Up to ~1MP
+ else return 6; // Up to ~1.5–2MP
+}
+
+/**
+ * Sets the parameters.tcp_rates according to the number of layers and a last tcp_rate value (which equals to the final compression ratio).
+ *
+ * Example for 6 layers:
+ *
+ * i = 5, parameters.tcp_rates[6 - 1 - 5] = 8.0f * (1 << (5 << 1)) = 8192 // Layer 5 (lowest quality)
+ * i = 4, parameters.tcp_rates[6 - 1 - 4] = 8.0f * (1 << (4 << 1)) = 2048 // Layer 4
+ * i = 3, parameters.tcp_rates[6 - 1 - 3] = 8.0f * (1 << (3 << 1)) = 512 // Layer 3
+ * i = 2, parameters.tcp_rates[6 - 1 - 2] = 8.0f * (1 << (2 << 1)) = 128 // Layer 2
+ * i = 1, parameters.tcp_rates[6 - 1 - 1] = 8.0f * (1 << (1 << 1)) = 32 // Layer 1
+ * i = 0, parameters.tcp_rates[6 - 1 - 0] = 8.0f * (1 << (0 << 1)) = 8 // Layer 0 (highest quality)
+ *
+ */
+static void set_tcp_rates(opj_cparameters_t* parameters, U32 num_layers = 1, F32 last_tcp_rate = LAST_TCP_RATE)
+{
+ parameters->tcp_numlayers = num_layers;
+
+ for (int i = num_layers - 1; i >= 0; i--)
+ {
+ parameters->tcp_rates[num_layers - 1 - i] = last_tcp_rate * static_cast(1 << (i << 1));
+ }
+}
+
class JPEG2KDecode : public JPEG2KBase
{
public:
@@ -406,15 +467,16 @@ public:
opj_set_default_encoder_parameters(¶meters);
parameters.cod_format = OPJ_CODEC_J2K;
- parameters.cp_disto_alloc = 1;
+ parameters.prog_order = OPJ_RLCP; // should be the default, but, just in case
+ parameters.cp_disto_alloc = 1; // enable rate allocation by distortion
+ parameters.max_cs_size = 0; // do not cap max size because we're using tcp_rates and also irrelevant with lossless.
if (reversible)
{
- parameters.max_cs_size = 0; // do not limit size for reversible compression
parameters.irreversible = 0; // should be the default, but, just in case
parameters.tcp_numlayers = 1;
/* documentation seems to be wrong, should be 0.0f for lossless, not 1.0f
- see https://github.com/uclouvain/openjpeg/blob/39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae/src/lib/openjp2/j2k.c#L7755
+ see https://github.com/uclouvain/openjpeg/blob/e7453e398b110891778d8da19209792c69ca7169/src/lib/openjp2/j2k.c#L7817
*/
parameters.tcp_rates[0] = 0.0f;
}
@@ -474,53 +536,22 @@ public:
opj_set_warning_handler(encoder, warning_callback, nullptr);
opj_set_info_handler(encoder, info_callback, nullptr);
- parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0;
- parameters.cod_format = OPJ_CODEC_J2K;
- parameters.prog_order = OPJ_RLCP;
- parameters.cp_disto_alloc = 1;
+ parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0; // no color transform for RGBA images
+
// if not lossless compression, computes tcp_numlayers and max_cs_size depending on the image dimensions
- if( parameters.irreversible ) {
+ if( parameters.irreversible )
+ {
// computes a number of layers
U32 surface = rawImageIn.getWidth() * rawImageIn.getHeight();
- U32 nb_layers = 1;
- U32 s = 64*64;
- while (surface > s)
- {
- nb_layers++;
- s *= 4;
- }
- nb_layers = llclamp(nb_layers, 1, 6);
- parameters.tcp_numlayers = nb_layers;
- parameters.tcp_rates[nb_layers - 1] = (U32)(1.f / DEFAULT_COMPRESSION_RATE); // 1:8 by default
+ // gets the necessary number of layers
+ U32 nb_layers = estimate_num_layers(surface);
- // for each subsequent layer, computes its rate and adds surface * numcomps * 1/rate to the max_cs_size
- U32 max_cs_size = (U32)(surface * image->numcomps * DEFAULT_COMPRESSION_RATE);
- U32 multiplier;
- for (int i = nb_layers - 2; i >= 0; i--)
- {
- if( i == nb_layers - 2 )
- {
- multiplier = 15;
- }
- else if( i == nb_layers - 3 )
- {
- multiplier = 4;
- }
- else
- {
- multiplier = 2;
- }
- parameters.tcp_rates[i] = parameters.tcp_rates[i + 1] * multiplier;
- max_cs_size += (U32)(surface * image->numcomps * (1 / parameters.tcp_rates[i]));
- }
+ // fills parameters.tcp_rates and updates parameters.tcp_numlayers
+ set_tcp_rates(¶meters, nb_layers, LAST_TCP_RATE);
- //ensure that we have at least a minimal size
- max_cs_size = llmax(max_cs_size, (U32)FIRST_PACKET_SIZE);
-
- parameters.max_cs_size = max_cs_size;
}
if (!opj_setup_encoder(encoder, ¶meters, image))
@@ -528,7 +559,20 @@ public:
return false;
}
- U32 tile_count = (rawImageIn.getWidth() >> 6) * (rawImageIn.getHeight() >> 6);
+ U32 width_tiles = (rawImageIn.getWidth() >> 6);
+ U32 height_tiles = (rawImageIn.getHeight() >> 6);
+
+ // Allow images with a width or height that are MIN_IMAGE_SIZE <= x < 64
+ if (width_tiles == 0 && (rawImageIn.getWidth() >= MIN_IMAGE_SIZE))
+ {
+ width_tiles = 1;
+ }
+ if (height_tiles == 0 && (rawImageIn.getHeight() >= MIN_IMAGE_SIZE))
+ {
+ height_tiles = 1;
+ }
+
+ U32 tile_count = width_tiles * height_tiles;
U32 data_size_guess = tile_count * TILE_SIZE;
// will be freed in opj_free_user_data_write
@@ -543,7 +587,7 @@ public:
opj_stream_destroy(stream);
}
- stream = opj_stream_create(data_size_guess, false);
+ stream = opj_stream_create(data_size_guess, OPJ_FALSE);
if (!stream)
{
return false;
@@ -584,17 +628,15 @@ public:
void setImage(const LLImageRaw& raw)
{
- opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS];
- memset(&cmptparm[0], 0, MAX_ENCODED_DISCARD_LEVELS * sizeof(opj_image_cmptparm_t));
-
S32 numcomps = raw.getComponents();
- S32 width = raw.getWidth();
- S32 height = raw.getHeight();
+ S32 width = raw.getWidth();
+ S32 height = raw.getHeight();
+
+ std::vector cmptparm(numcomps);
for (S32 c = 0; c < numcomps; c++)
{
- cmptparm[c].prec = 8;
- cmptparm[c].bpp = 8;
+ cmptparm[c].prec = 8; // replaces .bpp
cmptparm[c].sgnd = 0;
cmptparm[c].dx = parameters.subsampling_dx;
cmptparm[c].dy = parameters.subsampling_dy;
@@ -602,7 +644,7 @@ public:
cmptparm[c].h = height;
}
- image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
+ image = opj_image_create(numcomps, cmptparm.data(), OPJ_CLRSPC_SRGB);
image->x1 = width;
image->y1 = height;
@@ -614,7 +656,7 @@ public:
{
for (S32 x = 0; x < width; x++)
{
- const U8 *pixel = src_datap + (y*width + x) * numcomps;
+ const U8 *pixel = src_datap + (y * width + x) * numcomps;
for (S32 c = 0; c < numcomps; c++)
{
image->comps[c].data[i] = *pixel;
@@ -831,14 +873,19 @@ bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
{
+ if (raw_image.isBufferInvalid())
+ {
+ base.setLastError("Invalid input, no buffer");
+ return false;
+ }
+
JPEG2KEncode encode(comment_text, reversible);
bool encoded = encode.encode(raw_image, base);
- if (encoded)
+ if (!encoded)
{
- LL_WARNS() << "Openjpeg encoding implementation isn't complete, returning false" << LL_ENDL;
+ LL_WARNS() << "Openjpeg encoding was unsuccessful, returning false" << LL_ENDL;
}
return encoded;
- //return false;
}
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h
index 498502451a..da49597302 100644
--- a/indra/llimagej2coj/llimagej2coj.h
+++ b/indra/llimagej2coj/llimagej2coj.h
@@ -29,6 +29,8 @@
#include "llimagej2c.h"
+const F32 LAST_TCP_RATE = 1.f/DEFAULT_COMPRESSION_RATE; // should be 8, giving a 1:8 ratio
+
class LLImageJ2COJ : public LLImageJ2CImpl
{
public:
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 7e1be17ecc..670405e9b5 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -29,6 +29,7 @@
#include "llfoldertype.h"
#include "lldictionary.h"
#include "llmemory.h"
+#include "llsd.h"
#include "llsingleton.h"
///----------------------------------------------------------------------------
@@ -220,3 +221,21 @@ const std::string &LLFolderType::badLookup()
static const std::string sBadLookup = "llfoldertype_bad_lookup";
return sBadLookup;
}
+
+LLSD LLFolderType::getTypeNames()
+{
+ LLSD type_names;
+ for (S32 type = FT_TEXTURE; type < FT_COUNT; ++type)
+ {
+ if (lookupIsEnsembleType((LLFolderType::EType)type))
+ continue;
+
+ const FolderEntry* entry = LLFolderDictionary::getInstance()->lookup((LLFolderType::EType)type);
+ // skip llfoldertype_bad_lookup
+ if (entry)
+ {
+ type_names.append(entry->mName);
+ }
+ }
+ return type_names;
+}
diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h
index 46a1b92a96..dd12693f66 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -115,6 +115,8 @@ public:
static const std::string& badLookup(); // error string when a lookup fails
+ static LLSD getTypeNames();
+
protected:
LLFolderType() {}
~LLFolderType() {}
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 075abf9536..3defad8f3b 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -46,6 +46,7 @@ static const std::string INV_ITEM_ID_LABEL("item_id");
static const std::string INV_FOLDER_ID_LABEL("cat_id");
static const std::string INV_PARENT_ID_LABEL("parent_id");
static const std::string INV_THUMBNAIL_LABEL("thumbnail");
+static const std::string INV_FAVORITE_LABEL("favorite");
static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id");
static const std::string INV_ASSET_TYPE_LABEL("type");
static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
@@ -59,6 +60,7 @@ static const std::string INV_LINKED_ID_LABEL("linked_id");
static const std::string INV_SALE_INFO_LABEL("sale_info");
static const std::string INV_FLAGS_LABEL("flags");
static const std::string INV_CREATION_DATE_LABEL("created_at");
+static const std::string INV_TOGGLED_LABEL("toggled");
// key used by agent-inventory-service
static const std::string INV_ASSET_TYPE_LABEL_WS("type_default");
@@ -82,14 +84,16 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
mParentUUID(parent_uuid),
mType(type),
mName(name),
- mCreationDate(0)
+ mCreationDate(0),
+ mFavorite(false)
{
correctInventoryName(mName);
}
LLInventoryObject::LLInventoryObject()
: mType(LLAssetType::AT_NONE),
- mCreationDate(0)
+ mCreationDate(0),
+ mFavorite(false)
{
}
@@ -104,6 +108,7 @@ void LLInventoryObject::copyObject(const LLInventoryObject* other)
mType = other->mType;
mName = other->mName;
mThumbnailUUID = other->mThumbnailUUID;
+ mFavorite = other->mFavorite;
}
const LLUUID& LLInventoryObject::getUUID() const
@@ -121,6 +126,11 @@ const LLUUID& LLInventoryObject::getThumbnailUUID() const
return mThumbnailUUID;
}
+bool LLInventoryObject::getIsFavorite() const
+{
+ return mFavorite;
+}
+
const std::string& LLInventoryObject::getName() const
{
return mName;
@@ -175,6 +185,11 @@ void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid)
mThumbnailUUID = thumbnail_uuid;
}
+void LLInventoryObject::setFavorite(bool favorite)
+{
+ mFavorite = favorite;
+}
+
void LLInventoryObject::setType(LLAssetType::EType type)
{
mType = type;
@@ -247,6 +262,23 @@ bool LLInventoryObject::importLegacyStream(std::istream& input_stream)
{
setThumbnailUUID(LLUUID::null);
}
+
+ if (metadata.has("favorite"))
+ {
+ const LLSD& favorite = metadata["favorite"];
+ if (favorite.has("toggled"))
+ {
+ setFavorite(favorite["toggled"].asBoolean());
+ }
+ else
+ {
+ setFavorite(false);
+ }
+ }
+ else
+ {
+ setFavorite(false);
+ }
}
else if(0 == strcmp("name", keyword))
{
@@ -735,6 +767,23 @@ bool LLInventoryItem::importLegacyStream(std::istream& input_stream)
{
setThumbnailUUID(LLUUID::null);
}
+
+ if (metadata.has("favorite"))
+ {
+ const LLSD& favorite = metadata["favorite"];
+ if (favorite.has("toggled"))
+ {
+ setFavorite(favorite["toggled"].asBoolean());
+ }
+ else
+ {
+ setFavorite(false);
+ }
+ }
+ else
+ {
+ setFavorite(false);
+ }
}
else if(0 == strcmp("inv_type", keyword))
{
@@ -879,7 +928,7 @@ bool LLInventoryItem::exportLegacyStream(std::ostream& output_stream, bool inclu
LLSD LLInventoryItem::asLLSD() const
{
- LLSD sd = LLSD();
+ LLSD sd;
asLLSD(sd);
return sd;
}
@@ -888,13 +937,18 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
{
sd[INV_ITEM_ID_LABEL] = mUUID;
sd[INV_PARENT_ID_LABEL] = mParentUUID;
- sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
+ ll_fill_sd_from_permissions(sd[INV_PERMISSIONS_LABEL], mPermissions);
if (mThumbnailUUID.notNull())
{
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
+ if (mFavorite)
+ {
+ sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
+
U32 mask = mPermissions.getMaskBase();
if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|| (mAssetUUID.isNull()))
@@ -909,19 +963,22 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
cipher.encrypt(shadow_id.mData, UUID_BYTES);
sd[INV_SHADOW_ID_LABEL] = shadow_id;
}
- sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
- sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
+ sd[INV_ASSET_TYPE_LABEL] = std::string(LLAssetType::lookup(mType));
const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
if(!inv_type_str.empty())
{
sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
}
+ else
+ {
+ sd[INV_INVENTORY_TYPE_LABEL] = (LLSD::Integer)mInventoryType;
+ }
//sd[INV_FLAGS_LABEL] = (S32)mFlags;
sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
- sd[INV_SALE_INFO_LABEL] = mSaleInfo.asLLSD();
+ mSaleInfo.asLLSD(sd[INV_SALE_INFO_LABEL]);
sd[INV_NAME_LABEL] = mName;
sd[INV_DESC_LABEL] = mDescription;
- sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
+ sd[INV_CREATION_DATE_LABEL] = (LLSD::Integer)mCreationDate;
}
bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
@@ -937,6 +994,8 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
// TODO - figure out if this should be moved into the noclobber fields above
mThumbnailUUID.setNull();
+ mFavorite = false;
+ mPermissions.init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
// iterate as map to avoid making unnecessary temp copies of everything
LLSD::map_const_iterator i, end;
@@ -982,9 +1041,20 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
continue;
}
+ if (i->first == INV_FAVORITE_LABEL)
+ {
+ const LLSD& favorite_map = i->second;
+ const std::string w = INV_TOGGLED_LABEL;
+ if (favorite_map.has(w))
+ {
+ mFavorite = favorite_map[w].asBoolean();
+ }
+ continue;
+ }
+
if (i->first == INV_PERMISSIONS_LABEL)
{
- mPermissions = ll_permissions_from_sd(i->second);
+ mPermissions.importLLSD(i->second);
continue;
}
@@ -1177,6 +1247,11 @@ LLSD LLInventoryCategory::asLLSD() const
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
+ if (mFavorite)
+ {
+ sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
+
return sd;
}
@@ -1188,11 +1263,17 @@ LLSD LLInventoryCategory::asAISCreateCatLLSD() const
S8 type = static_cast(mPreferredType);
sd[INV_ASSET_TYPE_LABEL_WS] = type;
sd[INV_NAME_LABEL] = mName;
+
if (mThumbnailUUID.notNull())
{
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
+ if (mFavorite)
+ {
+ sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
+
return sd;
}
@@ -1240,6 +1321,17 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
mThumbnailUUID = sd[w];
}
}
+ mFavorite = false;
+ w = INV_FAVORITE_LABEL;
+ if (sd.has(w))
+ {
+ const LLSD& favorite_map = sd[w];
+ w = INV_TOGGLED_LABEL;
+ if (favorite_map.has(w))
+ {
+ mFavorite = favorite_map[w].asBoolean();
+ }
+ }
w = INV_ASSET_TYPE_LABEL;
if (sd.has(w))
{
@@ -1362,6 +1454,23 @@ bool LLInventoryCategory::importLegacyStream(std::istream& input_stream)
{
setThumbnailUUID(LLUUID::null);
}
+
+ if (metadata.has("favorite"))
+ {
+ const LLSD& favorite = metadata["favorite"];
+ if (favorite.has("toggled"))
+ {
+ setFavorite(favorite["toggled"].asBoolean());
+ }
+ else
+ {
+ setFavorite(false);
+ }
+ }
+ else
+ {
+ setFavorite(false);
+ }
}
else
{
@@ -1396,12 +1505,11 @@ bool LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, bool)
return true;
}
-LLSD LLInventoryCategory::exportLLSD() const
+void LLInventoryCategory::exportLLSD(LLSD& cat_data) const
{
- LLSD cat_data;
cat_data[INV_FOLDER_ID_LABEL] = mUUID;
cat_data[INV_PARENT_ID_LABEL] = mParentUUID;
- cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
+ cat_data[INV_ASSET_TYPE_LABEL] = std::string(LLAssetType::lookup(mType));
cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
cat_data[INV_NAME_LABEL] = mName;
@@ -1409,49 +1517,76 @@ LLSD LLInventoryCategory::exportLLSD() const
{
cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
-
- return cat_data;
+ if (mFavorite)
+ {
+ cat_data[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
}
-bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
+bool LLInventoryCategory::importLLSDMap(const LLSD& cat_data)
{
- if (cat_data.has(INV_FOLDER_ID_LABEL))
+ LLSD::map_const_iterator i, end;
+ end = cat_data.endMap();
+ for ( i = cat_data.beginMap(); i != end; ++i)
{
- setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID());
+ importLLSD(i->first, i->second);
}
- if (cat_data.has(INV_PARENT_ID_LABEL))
- {
- setParent(cat_data[INV_PARENT_ID_LABEL].asUUID());
- }
- if (cat_data.has(INV_ASSET_TYPE_LABEL))
- {
- setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString()));
- }
- if (cat_data.has(INV_PREFERRED_TYPE_LABEL))
- {
- setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
- }
- if (cat_data.has(INV_THUMBNAIL_LABEL))
- {
- LLUUID thumbnail_uuid;
- const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
- if (thumbnail_data.has(INV_ASSET_ID_LABEL))
- {
- thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
- }
- setThumbnailUUID(thumbnail_uuid);
- }
- if (cat_data.has(INV_NAME_LABEL))
- {
- mName = cat_data[INV_NAME_LABEL].asString();
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
-
return true;
}
+
+bool LLInventoryCategory::importLLSD(const std::string& label, const LLSD& value)
+{
+ if (label == INV_FOLDER_ID_LABEL)
+ {
+ setUUID(value.asUUID());
+ return true;
+ }
+ else if (label == INV_PARENT_ID_LABEL)
+ {
+ setParent(value.asUUID());
+ return true;
+ }
+ else if (label == INV_ASSET_TYPE_LABEL)
+ {
+ setType(LLAssetType::lookup(value.asString()));
+ return true;
+ }
+ else if (label == INV_PREFERRED_TYPE_LABEL)
+ {
+ setPreferredType(LLFolderType::lookup(value.asString()));
+ return true;
+ }
+ else if (label == INV_THUMBNAIL_LABEL)
+ {
+ LLUUID thumbnail_uuid;
+ if (value.has(INV_ASSET_ID_LABEL))
+ {
+ thumbnail_uuid = value[INV_ASSET_ID_LABEL].asUUID();
+ }
+ setThumbnailUUID(thumbnail_uuid);
+ return true;
+ }
+ if (label == INV_FAVORITE_LABEL)
+ {
+ bool favorite = false;
+ if (value.has(INV_TOGGLED_LABEL))
+ {
+ favorite = value[INV_TOGGLED_LABEL].asBoolean();
+ }
+ setFavorite(favorite);
+ }
+ else if (label == INV_NAME_LABEL)
+ {
+ mName = value.asString();
+ LLStringUtil::replaceNonstandardASCII(mName, ' ');
+ LLStringUtil::replaceChar(mName, '|', ' ');
+ return true;
+ }
+ return false;
+}
+
///----------------------------------------------------------------------------
-/// Local function definitions
+/// Local function definitions for testing purposes
///----------------------------------------------------------------------------
LLSD ll_create_sd_from_inventory_item(LLPointer item)
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index e63f2deba7..181c46226c 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -71,6 +71,7 @@ public:
virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID
const LLUUID& getParentUUID() const;
virtual const LLUUID& getThumbnailUUID() const;
+ virtual bool getIsFavorite() const;
virtual const std::string& getName() const;
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@@ -86,6 +87,7 @@ public:
virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid);
+ virtual void setFavorite(bool favorite);
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
@@ -111,6 +113,7 @@ protected:
LLUUID mUUID;
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
LLUUID mThumbnailUUID;
+ bool mFavorite;
LLAssetType::EType mType;
std::string mName;
time_t mCreationDate; // seconds from 1/1/1970, UTC
@@ -270,8 +273,9 @@ public:
virtual bool importLegacyStream(std::istream& input_stream);
virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const;
- LLSD exportLLSD() const;
- bool importLLSD(const LLSD& cat_data);
+ virtual void exportLLSD(LLSD& sd) const;
+ bool importLLSDMap(const LLSD& cat_data);
+ virtual bool importLLSD(const std::string& label, const LLSD& value);
//--------------------------------------------------------------------
// Member Variables
//--------------------------------------------------------------------
@@ -285,6 +289,7 @@ protected:
//
// These functions convert between structured data and an inventory
// item, appropriate for serialization.
+// Not up to date (no favorites, nor thumbnails), for testing purposes
//-----------------------------------------------------------------------------
LLSD ll_create_sd_from_inventory_item(LLPointer item);
LLSD ll_create_sd_from_inventory_category(LLPointer cat);
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 67d713db1f..ac50b428bf 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -37,98 +37,98 @@
#include "llsettingsdaycycle.h"
// Grid out of which parcels taken is stepped every 4 meters.
-const F32 PARCEL_GRID_STEP_METERS = 4.f;
+constexpr F32 PARCEL_GRID_STEP_METERS = 4.f;
// Area of one "square" of parcel
-const S32 PARCEL_UNIT_AREA = 16;
+constexpr S32 PARCEL_UNIT_AREA = 16;
// Height _above_ground_ that parcel boundary ends
-const F32 PARCEL_HEIGHT = 50.f;
+constexpr F32 PARCEL_HEIGHT = 50.f;
//Height above ground which parcel boundries exist for explicitly banned avatars
-const F32 BAN_HEIGHT = 5000.f;
+constexpr F32 BAN_HEIGHT = 5000.f;
// Maximum number of entries in an access list
-const S32 PARCEL_MAX_ACCESS_LIST = 300;
+constexpr S32 PARCEL_MAX_ACCESS_LIST = 300;
//Maximum number of entires in an update packet
//for access/ban lists.
-const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
+constexpr F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
// Maximum number of experiences
-const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
+constexpr S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
// Weekly charge for listing a parcel in the directory
-const S32 PARCEL_DIRECTORY_FEE = 30;
+constexpr S32 PARCEL_DIRECTORY_FEE = 30;
-const S32 PARCEL_PASS_PRICE_DEFAULT = 10;
-const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
+constexpr S32 PARCEL_PASS_PRICE_DEFAULT = 10;
+constexpr F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
// Number of "chunks" in which parcel overlay data is sent
// Chunk 0 = southern rows, entire width
-const S32 PARCEL_OVERLAY_CHUNKS = 4;
+constexpr S32 PARCEL_OVERLAY_CHUNKS = 4;
// Bottom three bits are a color index for the land overlay
-const U8 PARCEL_COLOR_MASK = 0x07;
-const U8 PARCEL_PUBLIC = 0x00;
-const U8 PARCEL_OWNED = 0x01;
-const U8 PARCEL_GROUP = 0x02;
-const U8 PARCEL_SELF = 0x03;
-const U8 PARCEL_FOR_SALE = 0x04;
-const U8 PARCEL_AUCTION = 0x05;
+constexpr U8 PARCEL_COLOR_MASK = 0x07;
+constexpr U8 PARCEL_PUBLIC = 0x00;
+constexpr U8 PARCEL_OWNED = 0x01;
+constexpr U8 PARCEL_GROUP = 0x02;
+constexpr U8 PARCEL_SELF = 0x03;
+constexpr U8 PARCEL_FOR_SALE = 0x04;
+constexpr U8 PARCEL_AUCTION = 0x05;
// unused 0x06
// unused 0x07
// flag, unused 0x08
-const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
-const U8 PARCEL_SOUND_LOCAL = 0x20;
-const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
-const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
+constexpr U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
+constexpr U8 PARCEL_SOUND_LOCAL = 0x20;
+constexpr U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
+constexpr U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
// Transmission results for parcel properties
-const S32 PARCEL_RESULT_NO_DATA = -1;
-const S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
-const S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
+constexpr S32 PARCEL_RESULT_NO_DATA = -1;
+constexpr S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
+constexpr S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
-const S32 SELECTED_PARCEL_SEQ_ID = -10000;
-const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
-const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
-const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
-const S32 HOVERED_PARCEL_SEQ_ID = -50000;
+constexpr S32 SELECTED_PARCEL_SEQ_ID = -10000;
+constexpr S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
+constexpr S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
+constexpr S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
+constexpr S32 HOVERED_PARCEL_SEQ_ID = -50000;
-const U32 RT_NONE = 0x1 << 0;
-const U32 RT_OWNER = 0x1 << 1;
-const U32 RT_GROUP = 0x1 << 2;
-const U32 RT_OTHER = 0x1 << 3;
-const U32 RT_LIST = 0x1 << 4;
-const U32 RT_SELL = 0x1 << 5;
+constexpr U32 RT_NONE = 0x1 << 0;
+constexpr U32 RT_OWNER = 0x1 << 1;
+constexpr U32 RT_GROUP = 0x1 << 2;
+constexpr U32 RT_OTHER = 0x1 << 3;
+constexpr U32 RT_LIST = 0x1 << 4;
+constexpr U32 RT_SELL = 0x1 << 5;
-const S32 INVALID_PARCEL_ID = -1;
+constexpr S32 INVALID_PARCEL_ID = -1;
-const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
+constexpr S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
// if Region settings are used, parcel env. version is -1
-const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
+constexpr S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
// Timeouts for parcels
// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
-const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
+constexpr U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
-const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
+constexpr U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
// ***** TESTING is 10 minutes
//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
// default sale timeout is 2 days -> 172800000000
-const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
+constexpr U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
// more grace period extensions.
-const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
+constexpr U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
// if more than 100,000s before sale revert, and no extra extension
// has been given, go ahead and extend it more. That's about 1.2 days.
-const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
+constexpr S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
@@ -250,9 +250,9 @@ public:
void setMediaURL(const std::string& url);
void setMediaType(const std::string& type);
void setMediaDesc(const std::string& desc);
- void setMediaID(const LLUUID& id) { mMediaID = id; }
- void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
- void setMediaLoop (U8 loop) { mMediaLoop = loop; }
+ void setMediaID(const LLUUID& id) { mMediaID = id; }
+ void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
+ void setMediaLoop(U8 loop) { mMediaLoop = loop; }
void setMediaWidth(S32 width);
void setMediaHeight(S32 height);
void setMediaCurrentURL(const std::string& url);
@@ -262,6 +262,8 @@ public:
void setMediaURLResetTimer(F32 time);
virtual void setLocalID(S32 local_id);
+ void setRegionID(const LLUUID& id) { mRegionID = id; }
+ const LLUUID& getRegionID() const { return mRegionID; }
// blow away all the extra stuff lurking in parcels, including urls, access lists, etc
void clearParcel();
@@ -651,6 +653,7 @@ public:
S32 mLocalID;
LLUUID mBanListTransactionID;
LLUUID mAccessListTransactionID;
+ LLUUID mRegionID;
std::map mAccessList;
std::map mBanList;
std::map mTempBanList;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index c8963881df..ebf7445c65 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -704,6 +704,79 @@ bool LLPermissions::exportLegacyStream(std::ostream& output_stream) const
return true;
}
+static const std::string PERM_CREATOR_ID_LABEL("creator_id");
+static const std::string PERM_OWNER_ID_LABEL("owner_id");
+static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
+static const std::string PERM_GROUP_ID_LABEL("group_id");
+static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
+static const std::string PERM_BASE_MASK_LABEL("base_mask");
+static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
+static const std::string PERM_GROUP_MASK_LABEL("group_mask");
+static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
+static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
+
+void LLPermissions::importLLSD(const LLSD& sd_perm)
+{
+ LLSD::map_const_iterator i, end;
+ end = sd_perm.endMap();
+ for (i = sd_perm.beginMap(); i != end; ++i)
+ {
+ const std::string& label = i->first;
+ if (label == PERM_CREATOR_ID_LABEL)
+ {
+ mCreator = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_OWNER_ID_LABEL)
+ {
+ mOwner = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_LAST_OWNER_ID_LABEL)
+ {
+ mLastOwner = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_GROUP_ID_LABEL)
+ {
+ mGroup = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_BASE_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskBase = mask;
+ continue;
+ }
+ if (label == PERM_OWNER_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskOwner = mask;
+ continue;
+ }
+ if (label == PERM_EVERYONE_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskEveryone = mask;
+ continue;
+ }
+ if (label == PERM_GROUP_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskGroup = mask;
+ continue;
+ }
+ if (label == PERM_NEXT_OWNER_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskNextOwner = mask;
+ continue;
+ }
+ }
+
+ fix();
+}
+
bool LLPermissions::operator==(const LLPermissions &rhs) const
{
return
@@ -998,55 +1071,30 @@ std::string mask_to_string(U32 mask)
///----------------------------------------------------------------------------
/// exported functions
///----------------------------------------------------------------------------
-static const std::string PERM_CREATOR_ID_LABEL("creator_id");
-static const std::string PERM_OWNER_ID_LABEL("owner_id");
-static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
-static const std::string PERM_GROUP_ID_LABEL("group_id");
-static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
-static const std::string PERM_BASE_MASK_LABEL("base_mask");
-static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
-static const std::string PERM_GROUP_MASK_LABEL("group_mask");
-static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
-static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
LLSD ll_create_sd_from_permissions(const LLPermissions& perm)
{
LLSD rv;
+ ll_fill_sd_from_permissions(rv, perm);
+ return rv;
+}
+void ll_fill_sd_from_permissions(LLSD& rv, const LLPermissions& perm)
+{
rv[PERM_CREATOR_ID_LABEL] = perm.getCreator();
rv[PERM_OWNER_ID_LABEL] = perm.getOwner();
rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner();
rv[PERM_GROUP_ID_LABEL] = perm.getGroup();
rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned();
- rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase();
- rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner();
- rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup();
- rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone();
- rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner();
- return rv;
+ rv[PERM_BASE_MASK_LABEL] = (LLSD::Integer)perm.getMaskBase();
+ rv[PERM_OWNER_MASK_LABEL] = (LLSD::Integer)perm.getMaskOwner();
+ rv[PERM_GROUP_MASK_LABEL] = (LLSD::Integer)perm.getMaskGroup();
+ rv[PERM_EVERYONE_MASK_LABEL] = (LLSD::Integer)perm.getMaskEveryone();
+ rv[PERM_NEXT_OWNER_MASK_LABEL] = (LLSD::Integer)perm.getMaskNextOwner();
}
LLPermissions ll_permissions_from_sd(const LLSD& sd_perm)
{
LLPermissions rv;
- rv.init(
- sd_perm[PERM_CREATOR_ID_LABEL].asUUID(),
- sd_perm[PERM_OWNER_ID_LABEL].asUUID(),
- sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(),
- sd_perm[PERM_GROUP_ID_LABEL].asUUID());
-
- // We do a cast to U32 here since LLSD does not attempt to
- // represent unsigned ints.
- PermissionMask mask;
- mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger());
- rv.setMaskBase(mask);
- mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger());
- rv.setMaskOwner(mask);
- mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger());
- rv.setMaskEveryone(mask);
- mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger());
- rv.setMaskGroup(mask);
- mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger());
- rv.setMaskNext(mask);
- rv.fix();
+ rv.importLLSD(sd_perm);
return rv;
}
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index a68abcfa34..82cdc03727 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -299,6 +299,8 @@ public:
bool importLegacyStream(std::istream& input_stream);
bool exportLegacyStream(std::ostream& output_stream) const;
+ void importLLSD(const LLSD& sd_perm);
+
bool operator==(const LLPermissions &rhs) const;
bool operator!=(const LLPermissions &rhs) const;
@@ -435,6 +437,7 @@ protected:
// like 'creator_id', 'owner_id', etc, with the value copied from the
// permission object.
LLSD ll_create_sd_from_permissions(const LLPermissions& perm);
+void ll_fill_sd_from_permissions(LLSD& rv, const LLPermissions& perm);
LLPermissions ll_permissions_from_sd(const LLSD& sd_perm);
#endif
diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp
index 35bbc1dbb1..b4d64bb4fb 100644
--- a/indra/llinventory/llsaleinfo.cpp
+++ b/indra/llinventory/llsaleinfo.cpp
@@ -90,15 +90,20 @@ bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
LLSD LLSaleInfo::asLLSD() const
{
LLSD sd;
+ asLLSD(sd);
+ return sd;
+}
+
+void LLSaleInfo::asLLSD(LLSD& sd) const
+{
const char* type = lookup(mSaleType);
if (!type)
{
LL_WARNS_ONCE() << "Unknown sale type: " << mSaleType << LL_ENDL;
type = lookup(LLSaleInfo::FS_NOT);
}
- sd["sale_type"] = type;
+ sd["sale_type"] = std::string(type);
sd["sale_price"] = mSalePrice;
- return sd;
}
bool LLSaleInfo::fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask)
diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h
index 44eb841641..7186e8ab49 100644
--- a/indra/llinventory/llsaleinfo.h
+++ b/indra/llinventory/llsaleinfo.h
@@ -86,6 +86,7 @@ public:
bool exportLegacyStream(std::ostream& output_stream) const;
LLSD asLLSD() const;
+ void asLLSD(LLSD &sd) const;
operator LLSD() const { return asLLSD(); }
bool fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask);
bool importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask);
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
index d483b33288..d7a94d61a5 100644
--- a/indra/llinventory/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -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);
}
}
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index 7de71588ef..bea6fdec97 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -398,7 +398,7 @@ protected:
private:
bool mLLSDDirty;
- bool mDirty;
+ bool mDirty; // gates updateSettings
bool mReplaced; // super dirty!
static LLSD combineSDMaps(const LLSD &first, const LLSD &other);
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index ff28c30563..4957cf3c02 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -657,15 +657,16 @@ 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);
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();
@@ -1932,6 +1933,7 @@ LLUUID LLSettingsSky::getCloudNoiseTextureId() const
void LLSettingsSky::setCloudNoiseTextureId(const LLUUID &id)
{
mCloudTextureId = id;
+ setDirtyFlag(true);
setLLSDDirty();
}
@@ -1976,6 +1978,7 @@ LLVector2 LLSettingsSky::getCloudScrollRate() const
void LLSettingsSky::setCloudScrollRate(const LLVector2 &val)
{
mScrollRate = val;
+ setDirtyFlag(true);
setLLSDDirty();
}
@@ -2134,6 +2137,7 @@ LLUUID LLSettingsSky::getMoonTextureId() const
void LLSettingsSky::setMoonTextureId(LLUUID id)
{
mMoonTextureId = id;
+ setDirtyFlag(true);
setLLSDDirty();
}
@@ -2218,6 +2222,7 @@ LLUUID LLSettingsSky::getSunTextureId() const
void LLSettingsSky::setSunTextureId(LLUUID id)
{
mSunTextureId = id;
+ setDirtyFlag(true);
setLLSDDirty();
}
diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp
index 9779cb8fbc..f11a4c3bf7 100644
--- a/indra/llinventory/tests/inventorymisc_test.cpp
+++ b/indra/llinventory/tests/inventorymisc_test.cpp
@@ -39,6 +39,34 @@
#pragma warning(disable: 4702)
#endif
+void set_random_inventory_metadata(LLInventoryObject* obj)
+{
+ S32 extra = rand() % 4;
+ switch (extra)
+ {
+ case 0:
+ {
+ LLUUID thumbnail_id;
+ thumbnail_id.generate();
+ obj->setThumbnailUUID(thumbnail_id);
+ break;
+ }
+ case 1:
+ obj->setFavorite(true);
+ break;
+ case 2:
+ {
+ LLUUID thumbnail_id;
+ thumbnail_id.generate();
+ obj->setThumbnailUUID(thumbnail_id);
+ obj->setFavorite(true);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
LLPointer create_random_inventory_item()
{
LLUUID item_id;
@@ -75,6 +103,7 @@ LLPointer create_random_inventory_item()
sale_info,
flags,
creation);
+ set_random_inventory_metadata(item);
return item;
}
@@ -90,6 +119,7 @@ LLPointer create_random_inventory_cat()
parent_id,
LLFolderType::FT_NONE,
std::string("Sample category"));
+ set_random_inventory_metadata(cat);
return cat;
}
@@ -290,6 +320,7 @@ namespace tut
src->setCreationDate(new_creation);
// test a save/load cycle to LLSD and back again
+ // Note: ll_create_sd_from_inventory_item does not support metadata
LLSD sd = ll_create_sd_from_inventory_item(src);
LLPointer dst = new LLInventoryItem;
bool successful_parse = dst->fromLLSD(sd);
@@ -329,7 +360,9 @@ namespace tut
}
LLPointer src1 = create_random_inventory_item();
- fileXML << LLSDOStreamer(src1->asLLSD()) << std::endl;
+ LLSD sd;
+ src1->asLLSD(sd);
+ fileXML << LLSDOStreamer(sd) << std::endl;
fileXML.close();
@@ -364,13 +397,13 @@ namespace tut
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
-
+ ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("14.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
}
template<> template<>
void inventory_object::test<8>()
{
-
LLPointer src1 = create_random_inventory_item();
std::ostringstream ostream;
@@ -390,8 +423,8 @@ namespace tut
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
-
-
+ ensure_equals("11.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("12.favorites::getIsFavorite() failed", false, src2->getIsFavorite()); // not supposed to carry over
}
template<> template<>
@@ -421,6 +454,8 @@ namespace tut
ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
+ ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("14.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
}
//******class LLInventoryCategory*******//
@@ -458,7 +493,9 @@ namespace tut
}
LLPointer src1 = create_random_inventory_cat();
- fileXML << LLSDOStreamer(src1->exportLLSD()) << std::endl;
+ LLSD sd;
+ src1->exportLLSD(sd);
+ fileXML << LLSDOStreamer(sd) << std::endl;
fileXML.close();
llifstream file(filename.c_str());
@@ -481,13 +518,15 @@ namespace tut
file.close();
LLPointer src2 = new LLInventoryCategory();
- src2->importLLSD(s_item);
+ src2->importLLSDMap(s_item);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
+ ensure_equals("6.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("7.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
}
template<> template<>
@@ -507,6 +546,7 @@ namespace tut
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
-
+ ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("14.favorites::getIsFavorite() failed", false, src2->getIsFavorite()); // currently not supposed to carry over
}
}
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 8e2bd5b2d9..598455a31a 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -280,103 +280,118 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
{
LLImageDataLock lock(&base);
- S32 data_size = base.getDataSize();
- S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
-
- //
- // Initialization
- //
- mCodeStreamp.reset();
-
- // It's not clear to nat under what circumstances we would reuse a
- // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
- // two U32s and a pointer, so it's not as if it would be a huge overhead
- // to allocate a new one every time.
- // Also -- why is base.getData() tested specifically here? If that returns
- // nullptr, shouldn't we bail out of the whole method?
- if (!mInputp && base.getData())
+ try
{
- // The compressed data has been loaded
- // Setup the source for the codestream
- mInputp = std::make_unique(base.getData(), data_size);
- }
- if (mInputp)
- {
- // This is LLKDUMemSource::reset(), not std::unique_ptr::reset().
- mInputp->reset();
- }
+ S32 data_size = base.getDataSize();
+ S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
- mCodeStreamp->create(mInputp.get());
+ //
+ // Initialization
+ //
+ mCodeStreamp.reset();
- // Set the maximum number of bytes to use from the codestream
- // *TODO: This seems to be wrong. The base class should have no idea of
- // how j2c compression works so no good way of computing what's the byte
- // range to be used.
+ // It's not clear to nat under what circumstances we would reuse a
+ // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
+ // two U32s and a pointer, so it's not as if it would be a huge overhead
+ // to allocate a new one every time.
+ // Also -- why is base.getData() tested specifically here? If that returns
+ // nullptr, shouldn't we bail out of the whole method?
+ if (!mInputp && base.getData())
+ {
+ // The compressed data has been loaded
+ // Setup the source for the codestream
+ mInputp = std::make_unique(base.getData(), data_size);
+ }
+
+ if (mInputp)
+ {
+ // This is LLKDUMemSource::reset(), not std::unique_ptr::reset().
+ mInputp->reset();
+ }
+
+ mCodeStreamp->create(mInputp.get());
+
+ // Set the maximum number of bytes to use from the codestream
+ // *TODO: This seems to be wrong. The base class should have no idea of
+ // how j2c compression works so no good way of computing what's the byte
+ // range to be used.
mCodeStreamp->set_max_bytes(max_bytes);
- // If you want to flip or rotate the image for some reason, change
- // the resolution, or identify a restricted region of interest, this is
- // the place to do it. You may use "kdu_codestream::change_appearance"
- // and "kdu_codestream::apply_input_restrictions" for this purpose.
- // If you wish to truncate the code-stream prior to decompression, you
- // may use "kdu_codestream::set_max_bytes".
- // If you wish to retain all compressed data so that the material
- // can be decompressed multiple times, possibly with different appearance
- // parameters, you should call "kdu_codestream::set_persistent" here.
- // There are a variety of other features which must be enabled at
- // this point if you want to take advantage of them. See the
- // descriptions appearing with the "kdu_codestream" interface functions
- // in "kdu_compressed.h" for an itemized account of these capabilities.
+ // If you want to flip or rotate the image for some reason, change
+ // the resolution, or identify a restricted region of interest, this is
+ // the place to do it. You may use "kdu_codestream::change_appearance"
+ // and "kdu_codestream::apply_input_restrictions" for this purpose.
+ // If you wish to truncate the code-stream prior to decompression, you
+ // may use "kdu_codestream::set_max_bytes".
+ // If you wish to retain all compressed data so that the material
+ // can be decompressed multiple times, possibly with different appearance
+ // parameters, you should call "kdu_codestream::set_persistent" here.
+ // There are a variety of other features which must be enabled at
+ // this point if you want to take advantage of them. See the
+ // descriptions appearing with the "kdu_codestream" interface functions
+ // in "kdu_compressed.h" for an itemized account of these capabilities.
- switch (mode)
- {
- case MODE_FAST:
- mCodeStreamp->set_fast();
- break;
- case MODE_RESILIENT:
- mCodeStreamp->set_resilient();
- break;
- case MODE_FUSSY:
- mCodeStreamp->set_fussy();
- break;
- default:
- llassert(0);
- mCodeStreamp->set_fast();
- }
-
- kdu_dims dims;
- mCodeStreamp->get_dims(0,dims);
-
- S32 components = mCodeStreamp->get_num_components();
-
- // Check that components have consistent dimensions (for PPM file)
- for (int idx = 1; idx < components; ++idx)
- {
- kdu_dims other_dims;
- mCodeStreamp->get_dims(idx, other_dims);
- if (other_dims != dims)
+ switch (mode)
{
- // This method is only called from methods that catch KDUError.
- // We want to fail the image load, not crash the viewer.
- LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
- << stringize(other_dims)
- << " do not match component 0 dimensions "
- << stringize(dims) << "!")));
+ case MODE_FAST:
+ mCodeStreamp->set_fast();
+ break;
+ case MODE_RESILIENT:
+ mCodeStreamp->set_resilient();
+ break;
+ case MODE_FUSSY:
+ mCodeStreamp->set_fussy();
+ break;
+ default:
+ llassert(0);
+ mCodeStreamp->set_fast();
+ }
+
+ kdu_dims dims;
+ mCodeStreamp->get_dims(0, dims);
+
+ S32 components = mCodeStreamp->get_num_components();
+
+ // Check that components have consistent dimensions (for PPM file)
+ for (int idx = 1; idx < components; ++idx)
+ {
+ kdu_dims other_dims;
+ mCodeStreamp->get_dims(idx, other_dims);
+ if (other_dims != dims)
+ {
+ // This method is only called from methods that catch KDUError.
+ // We want to fail the image load, not crash the viewer.
+ LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
+ << stringize(other_dims)
+ << " do not match component 0 dimensions "
+ << stringize(dims) << "!")));
+ }
+ }
+
+ // Get the number of resolution levels in that image
+ mLevels = mCodeStreamp->get_min_dwt_levels();
+
+ // Set the base dimensions
+ base.setSize(dims.size.x, dims.size.y, components);
+ base.setLevels(mLevels);
+
+ if (!keep_codestream)
+ {
+ mCodeStreamp.reset();
+ mInputp.reset();
}
}
-
- // Get the number of resolution levels in that image
- mLevels = mCodeStreamp->get_min_dwt_levels();
-
- // Set the base dimensions
- base.setSize(dims.size.x, dims.size.y, components);
- base.setLevels(mLevels);
-
- if (!keep_codestream)
+ catch (std::bad_alloc&)
{
- mCodeStreamp.reset();
- mInputp.reset();
+ // we are in a thread, can't show an 'out of memory' here,
+ // main thread will keep going
+ throw;
+ }
+ catch (...)
+ {
+ LLTHROW(KDUError(STRINGIZE("Unknown J2C error : " +
+ boost::current_exception_diagnostic_information() << "!")));
}
}
@@ -647,6 +662,12 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
bool vflip = true;
bool hflip = false;
+ if (raw_image.isBufferInvalid())
+ {
+ base.setLastError("Invalid input, no buffer");
+ return false;
+ }
+
try
{
// Set up input image files
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index b6e0e4a2be..6201761c46 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -33,23 +33,23 @@
#include "llplane.h"
#include "llvector4a.h"
-const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD;
-const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
-const F32 DEFAULT_NEAR_PLANE = 0.25f;
-const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions
+constexpr F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD;
+constexpr F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
+constexpr F32 DEFAULT_NEAR_PLANE = 0.25f;
+constexpr F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions
-const F32 MAX_ASPECT_RATIO = 50.0f;
-const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends
-const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
-const F32 MAX_FAR_CLIP = 512.0f;
+constexpr F32 MAX_ASPECT_RATIO = 50.0f;
+constexpr F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends
+constexpr F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
+constexpr F32 MAX_FAR_CLIP = 512.0f;
-const F32 MIN_ASPECT_RATIO = 0.02f;
-const F32 MIN_NEAR_PLANE = 0.1f;
-const F32 MIN_FAR_PLANE = 0.2f;
+constexpr F32 MIN_ASPECT_RATIO = 0.02f;
+constexpr F32 MIN_NEAR_PLANE = 0.1f;
+constexpr F32 MIN_FAR_PLANE = 0.2f;
// Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio.
-static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
-static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
+constexpr F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
+constexpr F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
// An LLCamera is an LLCoorFrame with a view frustum.
// This means that it has several methods for moving it around
diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp
index 15c9f6ff3f..b42541c7c0 100644
--- a/indra/llmath/llcoordframe.cpp
+++ b/indra/llmath/llcoordframe.cpp
@@ -328,28 +328,30 @@ void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix)
}
+// Rotate 2 normalized orthogonal vectors in direction from `source` to `target`
+static void rotate2(LLVector3& source, LLVector3& target, F32 angle)
+{
+ F32 sx = source[VX], sy = source[VY], sz = source[VZ];
+ F32 tx = target[VX], ty = target[VY], tz = target[VZ];
+ F32 c = cosf(angle), s = sinf(angle);
+
+ source.set(sx * c + tx * s, sy * c + ty * s, sz * c + tz * s);
+ target.set(tx * c - sx * s, ty * c - sy * s, tz * c - sz * s);
+}
+
void LLCoordFrame::roll(F32 angle)
{
- LLQuaternion q(angle, mXAxis);
- LLMatrix3 rotation_matrix(q);
- rotate(rotation_matrix);
- CHECK_FINITE_OBJ();
+ rotate2(mYAxis, mZAxis, angle);
}
void LLCoordFrame::pitch(F32 angle)
{
- LLQuaternion q(angle, mYAxis);
- LLMatrix3 rotation_matrix(q);
- rotate(rotation_matrix);
- CHECK_FINITE_OBJ();
+ rotate2(mZAxis, mXAxis, angle);
}
void LLCoordFrame::yaw(F32 angle)
{
- LLQuaternion q(angle, mZAxis);
- LLMatrix3 rotation_matrix(q);
- rotate(rotation_matrix);
- CHECK_FINITE_OBJ();
+ rotate2(mXAxis, mYAxis, angle);
}
// get*() routines
diff --git a/indra/llmath/llcoordframe.h b/indra/llmath/llcoordframe.h
index aaa701f792..458f6132c9 100644
--- a/indra/llmath/llcoordframe.h
+++ b/indra/llmath/llcoordframe.h
@@ -61,7 +61,7 @@ public:
//LLCoordFrame(const F32 *origin, const F32 *rotation); // Assumes "origin" is 1x3 and "rotation" is 1x9 array
//LLCoordFrame(const F32 *origin_and_rotation); // Assumes "origin_and_rotation" is 1x12 array
- bool isFinite() { return mOrigin.isFinite() && mXAxis.isFinite() && mYAxis.isFinite() && mZAxis.isFinite(); }
+ bool isFinite() const { return mOrigin.isFinite() && mXAxis.isFinite() && mYAxis.isFinite() && mZAxis.isFinite(); }
void reset();
void resetAxes();
diff --git a/indra/llmath/llline.h b/indra/llmath/llline.h
index 2c66f2267d..fa151f8b20 100644
--- a/indra/llmath/llline.h
+++ b/indra/llmath/llline.h
@@ -33,7 +33,7 @@
#include "stdtypes.h"
#include "v3math.h"
-const F32 DEFAULT_INTERSECTION_ERROR = 0.000001f;
+constexpr F32 DEFAULT_INTERSECTION_ERROR = 0.000001f;
class LLLine
{
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index fa315291a3..891f0ffc4c 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -39,18 +39,8 @@
// llcommon depend on llmath.
#include "is_approx_equal_fraction.h"
-// work around for Windows & older gcc non-standard function names.
-#if LL_WINDOWS
-#include
-#define llisnan(val) _isnan(val)
-#define llfinite(val) _finite(val)
-#elif (LL_LINUX && __GNUC__ <= 2)
-#define llisnan(val) isnan(val)
-#define llfinite(val) isfinite(val)
-#else
-#define llisnan(val) std::isnan(val)
-#define llfinite(val) std::isfinite(val)
-#endif
+#define llisnan(val) std::isnan(val)
+#define llfinite(val) std::isfinite(val)
// Single Precision Floating Point Routines
// (There used to be more defined here, but they appeared to be redundant and
@@ -75,7 +65,7 @@ constexpr F32 DEG_TO_RAD = 0.017453292519943295769236907684886f;
constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f;
constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f;
constexpr F32 F_LN10 = 2.3025850929940456840179914546844f;
-constexpr F32 OO_LN10 = 0.43429448190325182765112891891661;
+constexpr F32 OO_LN10 = 0.43429448190325182765112891891661f;
constexpr F32 F_LN2 = 0.69314718056f;
constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f;
@@ -89,7 +79,7 @@ constexpr F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0
constexpr F32 FP_MAG_THRESHOLD = 0.0000001f;
// TODO: Replace with logic like is_approx_equal
-inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
+constexpr bool is_approx_zero(F32 f) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
// These functions work by interpreting sign+exp+mantissa as an unsigned
// integer.
@@ -148,33 +138,17 @@ inline F64 llabs(const F64 a)
return F64(std::fabs(a));
}
-inline S32 lltrunc( F32 f )
+constexpr S32 lltrunc(F32 f)
{
-#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32)
- // Avoids changing the floating point control word.
- // Add or subtract 0.5 - epsilon and then round
- const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF };
- S32 result;
- __asm {
- fld f
- mov eax, f
- shr eax, 29
- and eax, 4
- fadd dword ptr [zpfp + eax]
- fistp result
- }
- return result;
-#else
- return (S32)f;
-#endif
+ return narrow(f);
}
-inline S32 lltrunc( F64 f )
+constexpr S32 lltrunc(F64 f)
{
- return (S32)f;
+ return narrow(f);
}
-inline S32 llfloor( F32 f )
+inline S32 llfloor(F32 f)
{
#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32)
// Avoids changing the floating point control word.
@@ -284,7 +258,7 @@ constexpr F32 FAST_MAG_BETA = 0.397824734759f;
//constexpr F32 FAST_MAG_ALPHA = 0.948059448969f;
//constexpr F32 FAST_MAG_BETA = 0.392699081699f;
-inline F32 fastMagnitude(F32 a, F32 b)
+constexpr F32 fastMagnitude(F32 a, F32 b)
{
a = (a > 0) ? a : -a;
b = (b > 0) ? b : -b;
@@ -342,7 +316,7 @@ inline F32 llfastpow(const F32 x, const F32 y)
}
-inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
+constexpr F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
{
// compute the power of ten
F32 bar = 1.f;
@@ -358,12 +332,9 @@ inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
return new_foo;
}
-inline F32 lerp(F32 a, F32 b, F32 u)
-{
- return a + ((b - a) * u);
-}
+using std::lerp;
-inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
+constexpr F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
{
F32 a = x00 + (x01-x00)*u;
F32 b = x10 + (x11-x10)*u;
@@ -371,17 +342,17 @@ inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
return r;
}
-inline F32 ramp(F32 x, F32 a, F32 b)
+constexpr F32 ramp(F32 x, F32 a, F32 b)
{
return (a == b) ? 0.0f : ((a - x) / (a - b));
}
-inline F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
+constexpr F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
{
return lerp(y1, y2, ramp(x, x1, x2));
}
-inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
+constexpr F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
{
if (y1 < y2)
{
@@ -394,7 +365,7 @@ inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
}
-inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
+constexpr F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
{
if (x <= x0)
return s0;
@@ -407,14 +378,14 @@ inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
return s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f);
}
-inline F32 cubic_step( F32 x )
+constexpr F32 cubic_step( F32 x )
{
x = llclampf(x);
return (x * x) * (3.0f - 2.0f * x);
}
-inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
+constexpr F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
{
if (x <= x0)
return s0;
@@ -428,7 +399,7 @@ inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
return (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared);
}
-inline F32 llsimple_angle(F32 angle)
+constexpr F32 llsimple_angle(F32 angle)
{
while(angle <= -F_PI)
angle += F_TWO_PI;
@@ -438,7 +409,7 @@ inline F32 llsimple_angle(F32 angle)
}
//SDK - Renamed this to get_lower_power_two, since this is what this actually does.
-inline U32 get_lower_power_two(U32 val, U32 max_power_two)
+constexpr U32 get_lower_power_two(U32 val, U32 max_power_two)
{
if(!max_power_two)
{
@@ -460,7 +431,7 @@ inline U32 get_lower_power_two(U32 val, U32 max_power_two)
// number of digits, then add one. We subtract 1 initially to handle
// the case where the number passed in is actually a power of two.
// WARNING: this only works with 32 bit ints.
-inline U32 get_next_power_two(U32 val, U32 max_power_two)
+constexpr U32 get_next_power_two(U32 val, U32 max_power_two)
{
if(!max_power_two)
{
@@ -486,7 +457,7 @@ inline U32 get_next_power_two(U32 val, U32 max_power_two)
//get the gaussian value given the linear distance from axis x and guassian value o
inline F32 llgaussian(F32 x, F32 o)
{
- return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o));
+ return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2.f*o*o));
}
//helper function for removing outliers
@@ -539,7 +510,8 @@ inline void ll_remove_outliers(std::vector& data, F32 k)
// Note: in our code, values labeled as sRGB are ALWAYS gamma corrected linear values, NOT linear values with monitor gamma applied
// Note: stored color values should always be gamma corrected linear (i.e. the values returned from an on-screen color swatch)
// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses
-inline float linearTosRGB(const float val) {
+inline float linearTosRGB(const float val)
+{
if (val < 0.0031308f) {
return val * 12.92f;
}
@@ -554,7 +526,8 @@ inline float linearTosRGB(const float val) {
// Note: Stored color values should generally be gamma corrected sRGB.
// If you're serializing the return value of this function, you're probably doing it wrong.
// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses.
-inline float sRGBtoLinear(const float val) {
+inline float sRGBtoLinear(const float val)
+{
if (val < 0.04045f) {
return val / 12.92f;
}
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index aefb82b2f0..3a6748bdb3 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -30,7 +30,6 @@
#include "llquaternion.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
@@ -58,7 +57,7 @@ LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
{
- F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ F32 mag = vec.length();
if (mag > FP_MAG_THRESHOLD)
{
angle *= 0.5;
@@ -77,7 +76,7 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
{
- F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ F32 mag = vec.length();
if (mag > FP_MAG_THRESHOLD)
{
angle *= 0.5;
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 76e5e3aae9..7c60253618 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1294,10 +1294,11 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en
c = cos(ang)*lerp(radius_start, radius_end, t);
- pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
+ pt->mPos.set(0 + lerp(0.f, params.getShear().mV[VX], s)
+ lerp(-skew ,skew, t) * 0.5f,
- c + lerp(0,params.getShear().mV[1],s),
+ c + lerp(0.f, params.getShear().mV[VY], s),
s);
+
pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
hole_y * lerp(taper_y_begin, taper_y_end, t),
0,1);
@@ -1327,9 +1328,9 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en
c = cos(ang)*lerp(radius_start, radius_end, t);
s = sin(ang)*lerp(radius_start, radius_end, t);
- pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
+ pt->mPos.set(0 + lerp(0.f, params.getShear().mV[VX], s)
+ lerp(-skew ,skew, t) * 0.5f,
- c + lerp(0,params.getShear().mV[1],s),
+ c + lerp(0.f, params.getShear().mV[VY], s),
s);
pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
@@ -1354,9 +1355,9 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en
c = cos(ang)*lerp(radius_start, radius_end, t);
s = sin(ang)*lerp(radius_start, radius_end, t);
- pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
+ pt->mPos.set(0 + lerp(0.f, params.getShear().mV[VX], s)
+ lerp(-skew ,skew, t) * 0.5f,
- c + lerp(0,params.getShear().mV[1],s),
+ c + lerp(0.f, params.getShear().mV[VY], s),
s);
pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
hole_y * lerp(taper_y_begin, taper_y_end, t),
@@ -1494,8 +1495,8 @@ bool LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
for (S32 i=0;i(meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count));
+ try
+ {
+ vert_count = static_cast(meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count));
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL;
+ }
}
if (vert_count < 65535 && vert_count != 0)
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 27c5fc5a49..3496928f7b 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -45,7 +45,6 @@ class LLVolumeOctree;
#include "lluuid.h"
#include "v4color.h"
-//#include "vmath.h"
#include "v2math.h"
#include "v3math.h"
#include "v3dmath.h"
diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp
index 472d340af5..3c2097f947 100644
--- a/indra/llmath/m3math.cpp
+++ b/indra/llmath/m3math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index 2a6e52798b..1724a50601 100644
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v4math.h"
#include "m4math.h"
diff --git a/indra/llmath/raytrace.cpp b/indra/llmath/raytrace.cpp
index 893bf1fc70..c0b5f48f2d 100644
--- a/indra/llmath/raytrace.cpp
+++ b/indra/llmath/raytrace.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "math.h"
-//#include "vmath.h"
#include "v3math.h"
#include "llquaternion.h"
#include "m3math.h"
diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp
index 4649e13376..175f08df88 100644
--- a/indra/llmath/v2math.cpp
+++ b/indra/llmath/v2math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v2math.h"
#include "v3math.h"
#include "v4math.h"
@@ -47,8 +46,8 @@ bool LLVector2::abs()
{
bool ret{ false };
- if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; }
- if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; }
+ if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; }
+ if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; }
return ret;
}
@@ -67,14 +66,21 @@ F32 angle_between(const LLVector2& a, const LLVector2& b)
return angle;
}
-bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon)
+F32 signed_angle_between(const LLVector2& a, const LLVector2& b)
+{
+ F32 angle = angle_between(a, b);
+ F32 rhombus_square = a[VX] * b[VY] - b[VX] * a[VY];
+ return rhombus_square < 0 ? -angle : angle;
+}
+
+bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon)
{
LLVector2 an = a;
LLVector2 bn = b;
an.normVec();
bn.normVec();
F32 dot = an * bn;
- if ( (1.0f - fabs(dot)) < epsilon)
+ if ((1.0f - fabs(dot)) < epsilon)
{
return true;
}
@@ -82,28 +88,28 @@ bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon)
}
-F32 dist_vec(const LLVector2 &a, const LLVector2 &b)
+F32 dist_vec(const LLVector2& a, const LLVector2& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return (F32) sqrt( x*x + y*y );
}
-F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b)
+F32 dist_vec_squared(const LLVector2& a, const LLVector2& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return x*x + y*y;
}
-F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b)
+F32 dist_vec_squared2D(const LLVector2& a, const LLVector2& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return x*x + y*y;
}
-LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u)
+LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u)
{
return LLVector2(
a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
@@ -113,14 +119,14 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u)
LLSD LLVector2::getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
+ ret[VX] = mV[VX];
+ ret[VY] = mV[VY];
return ret;
}
void LLVector2::setValue(const LLSD& sd)
{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
+ mV[VX] = (F32) sd[0].asReal();
+ mV[VY] = (F32) sd[1].asReal();
}
diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h
index c84c441492..b31e4056a3 100644
--- a/indra/llmath/v2math.h
+++ b/indra/llmath/v2math.h
@@ -36,7 +36,7 @@ class LLQuaternion;
// Llvector2 = |x y z w|
-static const U32 LENGTHOFVECTOR2 = 2;
+static constexpr U32 LENGTHOFVECTOR2 = 2;
class LLVector2
{
@@ -82,7 +82,7 @@ class LLVector2
const LLVector2& scaleVec(const LLVector2& vec); // scales per component by vec
- bool isNull(); // Returns true if vector has a _very_small_ length
+ bool isNull() const; // Returns true if vector has a _very_small_ length
bool isExactlyZero() const { return !mV[VX] && !mV[VY]; }
F32 operator[](int idx) const { return mV[idx]; }
@@ -107,7 +107,7 @@ class LLVector2
friend LLVector2 operator-(const LLVector2 &a); // Return vector -a
- friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a
+ friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a
};
static_assert(std::is_trivially_copyable::value, "LLVector2 must be trivial copy");
@@ -116,37 +116,34 @@ static_assert(std::is_standard_layout::value, "LLVector2 must be a st
// Non-member functions
-F32 angle_between(const LLVector2 &a, const LLVector2 &b); // Returns angle (radians) between a and b
-bool are_parallel(const LLVector2 &a, const LLVector2 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel
-F32 dist_vec(const LLVector2 &a, const LLVector2 &b); // Returns distance between a and b
-F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b
-F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b ignoring Z component
-LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u); // Returns a vector that is a linear interpolation between a and b
+F32 angle_between(const LLVector2& a, const LLVector2& b); // Returns angle (radians) between a and b
+F32 signed_angle_between(const LLVector2& a, const LLVector2& b); // Returns signed angle (radians) between a and b
+bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel
+F32 dist_vec(const LLVector2& a, const LLVector2& b); // Returns distance between a and b
+F32 dist_vec_squared(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b
+F32 dist_vec_squared2D(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b ignoring Z component
+LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u); // Returns a vector that is a linear interpolation between a and b
// Constructors
-inline LLVector2::LLVector2(void)
+inline LLVector2::LLVector2()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
inline LLVector2::LLVector2(F32 x, F32 y)
{
- mV[VX] = x;
- mV[VY] = y;
+ set(x, y);
}
inline LLVector2::LLVector2(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
+ set(vec);
}
inline LLVector2::LLVector2(const LLVector3 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
+ set(vec.mV);
}
inline LLVector2::LLVector2(const LLSD &sd)
@@ -156,30 +153,26 @@ inline LLVector2::LLVector2(const LLSD &sd)
// Clear and Assignment Functions
-inline void LLVector2::clear(void)
+inline void LLVector2::clear()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ mV[VX] = mV[VY] = 0.f;
}
-inline void LLVector2::setZero(void)
+inline void LLVector2::setZero()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
// deprecated
-inline void LLVector2::clearVec(void)
+inline void LLVector2::clearVec()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
// deprecated
-inline void LLVector2::zeroVec(void)
+inline void LLVector2::zeroVec()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
inline void LLVector2::set(F32 x, F32 y)
@@ -190,108 +183,84 @@ inline void LLVector2::set(F32 x, F32 y)
inline void LLVector2::set(const LLVector2 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
+ set(vec.mV);
}
inline void LLVector2::set(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
+ set(vec[VX], vec[VY]);
}
// deprecated
inline void LLVector2::setVec(F32 x, F32 y)
{
- mV[VX] = x;
- mV[VY] = y;
+ set(x, y);
}
// deprecated
inline void LLVector2::setVec(const LLVector2 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
+ set(vec);
}
// deprecated
inline void LLVector2::setVec(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
+ set(vec);
}
// LLVector2 Magnitude and Normalization Functions
-inline F32 LLVector2::length(void) const
+inline F32 LLVector2::length() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
+ return sqrt(lengthSquared());
}
-inline F32 LLVector2::lengthSquared(void) const
+inline F32 LLVector2::lengthSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1];
+ return mV[VX]*mV[VX] + mV[VY]*mV[VY];
}
-inline F32 LLVector2::normalize(void)
+inline F32 LLVector2::normalize()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
- F32 oomag;
+ F32 mag = length();
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
+ *this /= mag;
}
else
{
- mV[0] = 0.f;
- mV[1] = 0.f;
+ clear();
mag = 0;
}
- return (mag);
+ return mag;
}
// checker
inline bool LLVector2::isFinite() const
{
- return (llfinite(mV[VX]) && llfinite(mV[VY]));
+ return llfinite(mV[VX]) && llfinite(mV[VY]);
}
// deprecated
-inline F32 LLVector2::magVec(void) const
+inline F32 LLVector2::magVec() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
+ return length();
}
// deprecated
-inline F32 LLVector2::magVecSquared(void) const
+inline F32 LLVector2::magVecSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1];
+ return lengthSquared();
}
// deprecated
-inline F32 LLVector2::normVec(void)
+inline F32 LLVector2::normVec()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
- F32 oomag;
-
- if (mag > FP_MAG_THRESHOLD)
- {
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- }
- else
- {
- mV[0] = 0.f;
- mV[1] = 0.f;
- mag = 0;
- }
- return (mag);
+ return normalize();
}
inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
@@ -302,22 +271,18 @@ inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
return *this;
}
-inline bool LLVector2::isNull()
+inline bool LLVector2::isNull() const
{
- if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] )
- {
- return true;
- }
- return false;
+ return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY];
}
// LLVector2 Operators
// For sorting. By convention, x is "more significant" than y.
-inline bool operator<(const LLVector2 &a, const LLVector2 &b)
+inline bool operator<(const LLVector2& a, const LLVector2& b)
{
- if( a.mV[VX] == b.mV[VX] )
+ if (a.mV[VX] == b.mV[VX])
{
return a.mV[VY] < b.mV[VY];
}
@@ -328,95 +293,92 @@ inline bool operator<(const LLVector2 &a, const LLVector2 &b)
}
-inline LLVector2 operator+(const LLVector2 &a, const LLVector2 &b)
+inline LLVector2 operator+(const LLVector2& a, const LLVector2& b)
{
LLVector2 c(a);
return c += b;
}
-inline LLVector2 operator-(const LLVector2 &a, const LLVector2 &b)
+inline LLVector2 operator-(const LLVector2& a, const LLVector2& b)
{
LLVector2 c(a);
return c -= b;
}
-inline F32 operator*(const LLVector2 &a, const LLVector2 &b)
+inline F32 operator*(const LLVector2& a, const LLVector2& b)
{
- return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1]);
+ return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY]);
}
-inline LLVector2 operator%(const LLVector2 &a, const LLVector2 &b)
+inline LLVector2 operator%(const LLVector2& a, const LLVector2& b)
{
- return LLVector2(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]);
+ return LLVector2(a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY], a.mV[VY]*b.mV[VX] - b.mV[VY]*a.mV[VX]);
}
-inline LLVector2 operator/(const LLVector2 &a, F32 k)
+inline LLVector2 operator/(const LLVector2& a, F32 k)
{
F32 t = 1.f / k;
- return LLVector2( a.mV[0] * t, a.mV[1] * t );
+ return LLVector2( a.mV[VX] * t, a.mV[VY] * t );
}
-inline LLVector2 operator*(const LLVector2 &a, F32 k)
+inline LLVector2 operator*(const LLVector2& a, F32 k)
{
- return LLVector2( a.mV[0] * k, a.mV[1] * k );
+ return LLVector2( a.mV[VX] * k, a.mV[VY] * k );
}
-inline LLVector2 operator*(F32 k, const LLVector2 &a)
+inline LLVector2 operator*(F32 k, const LLVector2& a)
{
- return LLVector2( a.mV[0] * k, a.mV[1] * k );
+ return LLVector2( a.mV[VX] * k, a.mV[VY] * k );
}
-inline bool operator==(const LLVector2 &a, const LLVector2 &b)
+inline bool operator==(const LLVector2& a, const LLVector2& b)
{
- return ( (a.mV[0] == b.mV[0])
- &&(a.mV[1] == b.mV[1]));
+ return ( (a.mV[VX] == b.mV[VX])
+ &&(a.mV[VY] == b.mV[VY]));
}
-inline bool operator!=(const LLVector2 &a, const LLVector2 &b)
+inline bool operator!=(const LLVector2& a, const LLVector2& b)
{
- return ( (a.mV[0] != b.mV[0])
- ||(a.mV[1] != b.mV[1]));
+ return ( (a.mV[VX] != b.mV[VX])
+ ||(a.mV[VY] != b.mV[VY]));
}
-inline const LLVector2& operator+=(LLVector2 &a, const LLVector2 &b)
+inline const LLVector2& operator+=(LLVector2& a, const LLVector2& b)
{
- a.mV[0] += b.mV[0];
- a.mV[1] += b.mV[1];
+ a.mV[VX] += b.mV[VX];
+ a.mV[VY] += b.mV[VY];
return a;
}
-inline const LLVector2& operator-=(LLVector2 &a, const LLVector2 &b)
+inline const LLVector2& operator-=(LLVector2& a, const LLVector2& b)
{
- a.mV[0] -= b.mV[0];
- a.mV[1] -= b.mV[1];
+ a.mV[VX] -= b.mV[VX];
+ a.mV[VY] -= b.mV[VY];
return a;
}
-inline const LLVector2& operator%=(LLVector2 &a, const LLVector2 &b)
+inline const LLVector2& operator%=(LLVector2& a, const LLVector2& b)
{
- LLVector2 ret(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]);
+ LLVector2 ret(a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY], a.mV[VY]*b.mV[VX] - b.mV[VY]*a.mV[VX]);
a = ret;
return a;
}
-inline const LLVector2& operator*=(LLVector2 &a, F32 k)
+inline const LLVector2& operator*=(LLVector2& a, F32 k)
{
- a.mV[0] *= k;
- a.mV[1] *= k;
+ a.mV[VX] *= k;
+ a.mV[VY] *= k;
return a;
}
-inline const LLVector2& operator/=(LLVector2 &a, F32 k)
+inline const LLVector2& operator/=(LLVector2& a, F32 k)
{
- F32 t = 1.f / k;
- a.mV[0] *= t;
- a.mV[1] *= t;
- return a;
+ return a *= 1.f / k;
}
-inline LLVector2 operator-(const LLVector2 &a)
+inline LLVector2 operator-(const LLVector2& a)
{
- return LLVector2( -a.mV[0], -a.mV[1] );
+ return LLVector2( -a.mV[VX], -a.mV[VY] );
}
inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos)
@@ -434,7 +396,7 @@ inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos)
}
}
-inline std::ostream& operator<<(std::ostream& s, const LLVector2 &a)
+inline std::ostream& operator<<(std::ostream& s, const LLVector2& a)
{
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << " }";
return s;
diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp
index 4367b993f8..08b3795020 100644
--- a/indra/llmath/v3color.cpp
+++ b/indra/llmath/v3color.cpp
@@ -32,74 +32,79 @@
LLColor3 LLColor3::white(1.0f, 1.0f, 1.0f);
LLColor3 LLColor3::black(0.0f, 0.0f, 0.0f);
-LLColor3 LLColor3::grey (0.5f, 0.5f, 0.5f);
+LLColor3 LLColor3::grey(0.5f, 0.5f, 0.5f);
-LLColor3::LLColor3(const LLColor4 &a)
+LLColor3::LLColor3(const LLColor4& a)
{
- mV[0] = a.mV[0];
- mV[1] = a.mV[1];
- mV[2] = a.mV[2];
+ mV[VRED] = a.mV[VRED];
+ mV[VGREEN] = a.mV[VGREEN];
+ mV[VBLUE] = a.mV[VBLUE];
}
-LLColor3::LLColor3(const LLVector4 &a)
+LLColor3::LLColor3(const LLVector4& a)
{
- mV[0] = a.mV[0];
- mV[1] = a.mV[1];
- mV[2] = a.mV[2];
+ mV[VRED] = a.mV[VRED];
+ mV[VGREEN] = a.mV[VGREEN];
+ mV[VBLUE] = a.mV[VBLUE];
}
-LLColor3::LLColor3(const LLSD &sd)
+LLColor3::LLColor3(const LLSD& sd)
{
setValue(sd);
}
-const LLColor3& LLColor3::operator=(const LLColor4 &a)
+const LLColor3& LLColor3::operator=(const LLColor4& a)
{
- mV[0] = a.mV[0];
- mV[1] = a.mV[1];
- mV[2] = a.mV[2];
+ mV[VRED] = a.mV[VRED];
+ mV[VGREEN] = a.mV[VGREEN];
+ mV[VBLUE] = a.mV[VBLUE];
return (*this);
}
-std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
+std::ostream& operator<<(std::ostream& s, const LLColor3& a)
{
s << "{ " << a.mV[VRED] << ", " << a.mV[VGREEN] << ", " << a.mV[VBLUE] << " }";
return s;
}
-static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+static F32 hueToRgb(F32 val1In, F32 val2In, F32 valHUeIn)
{
- if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
- if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
- if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
- if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
- if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
- return ( val1In );
+ if (valHUeIn < 0.0f)
+ valHUeIn += 1.0f;
+ if (valHUeIn > 1.0f)
+ valHUeIn -= 1.0f;
+ if ((6.0f * valHUeIn) < 1.0f)
+ return (val1In + (val2In - val1In) * 6.0f * valHUeIn);
+ if ((2.0f * valHUeIn) < 1.0f)
+ return (val2In);
+ if ((3.0f * valHUeIn) < 2.0f)
+ return (val1In + (val2In - val1In) * ((2.0f / 3.0f) - valHUeIn) * 6.0f);
+ return (val1In);
}
-void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+void LLColor3::setHSL(F32 hValIn, F32 sValIn, F32 lValIn)
{
- if ( sValIn < 0.00001f )
+ if (sValIn < 0.00001f)
{
- mV[VRED] = lValIn;
+ mV[VRED] = lValIn;
mV[VGREEN] = lValIn;
- mV[VBLUE] = lValIn;
+ mV[VBLUE] = lValIn;
}
else
{
F32 interVal1;
F32 interVal2;
- if ( lValIn < 0.5f )
- interVal2 = lValIn * ( 1.0f + sValIn );
+ if (lValIn < 0.5f)
+ interVal2 = lValIn * (1.0f + sValIn);
else
- interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+ interVal2 = (lValIn + sValIn) - (sValIn * lValIn);
interVal1 = 2.0f * lValIn - interVal2;
- mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
- mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
- mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ mV[VRED] = hueToRgb(interVal1, interVal2, hValIn + (1.f / 3.f));
+ mV[VGREEN] = hueToRgb(interVal1, interVal2, hValIn);
+ mV[VBLUE] = hueToRgb(interVal1, interVal2, hValIn - (1.f / 3.f));
}
}
@@ -109,45 +114,48 @@ void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
F32 var_G = mV[VGREEN];
F32 var_B = mV[VBLUE];
- F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
- F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+ F32 var_Min = (var_R < (var_G < var_B ? var_G : var_B) ? var_R : (var_G < var_B ? var_G : var_B));
+ F32 var_Max = (var_R > (var_G > var_B ? var_G : var_B) ? var_R : (var_G > var_B ? var_G : var_B));
F32 del_Max = var_Max - var_Min;
- F32 L = ( var_Max + var_Min ) / 2.0f;
+ F32 L = (var_Max + var_Min) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
- if ( del_Max == 0.0f )
+ if (del_Max == 0.0f)
{
- H = 0.0f;
- S = 0.0f;
+ H = 0.0f;
+ S = 0.0f;
}
else
{
- if ( L < 0.5 )
- S = del_Max / ( var_Max + var_Min );
+ if (L < 0.5)
+ S = del_Max / (var_Max + var_Min);
else
- S = del_Max / ( 2.0f - var_Max - var_Min );
+ S = del_Max / (2.0f - var_Max - var_Min);
- F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+ F32 del_R = (((var_Max - var_R) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_G = (((var_Max - var_G) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_B = (((var_Max - var_B) / 6.0f) + (del_Max / 2.0f)) / del_Max;
- if ( var_R >= var_Max )
+ if (var_R >= var_Max)
H = del_B - del_G;
- else
- if ( var_G >= var_Max )
- H = ( 1.0f / 3.0f ) + del_R - del_B;
- else
- if ( var_B >= var_Max )
- H = ( 2.0f / 3.0f ) + del_G - del_R;
+ else if (var_G >= var_Max)
+ H = (1.0f / 3.0f) + del_R - del_B;
+ else if (var_B >= var_Max)
+ H = (2.0f / 3.0f) + del_G - del_R;
- if ( H < 0.0f ) H += 1.0f;
- if ( H > 1.0f ) H -= 1.0f;
+ if (H < 0.0f)
+ H += 1.0f;
+ if (H > 1.0f)
+ H -= 1.0f;
}
- if (hue) *hue = H;
- if (saturation) *saturation = S;
- if (luminance) *luminance = L;
+ if (hue)
+ *hue = H;
+ if (saturation)
+ *saturation = S;
+ if (luminance)
+ *luminance = L;
}
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index 139db9539f..7357d93599 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -33,12 +33,12 @@ class LLVector4;
#include "llerror.h"
#include "llmath.h"
#include "llsd.h"
-#include "v3math.h" // needed for linearColor3v implemtation below
+#include "v3math.h" // needed for linearColor3v implemtation below
#include
// LLColor3 = |r g b|
-static const U32 LENGTHOFCOLOR3 = 3;
+static constexpr U32 LENGTHOFCOLOR3 = 3;
class LLColor3
{
@@ -50,44 +50,43 @@ public:
static LLColor3 grey;
public:
- LLColor3(); // Initializes LLColor3 to (0, 0, 0)
- LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b)
- LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2])
- LLColor3(const char *color_string); // html format color ie "#FFDDEE"
- explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion
- explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion
+ LLColor3(); // Initializes LLColor3 to (0, 0, 0)
+ LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b)
+ LLColor3(const F32* vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2])
+ LLColor3(const char* color_string); // html format color ie "#FFDDEE"
+ explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion
+ explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion
LLColor3(const LLSD& sd);
-
LLSD getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
+ ret[VRED] = mV[VRED];
+ ret[VGREEN] = mV[VGREEN];
+ ret[VBLUE] = mV[VBLUE];
return ret;
}
void setValue(const LLSD& sd)
{
- mV[0] = (F32) sd[0].asReal();;
- mV[1] = (F32) sd[1].asReal();;
- mV[2] = (F32) sd[2].asReal();;
+ mV[VRED] = (F32)sd[VRED].asReal();
+ mV[VGREEN] = (F32)sd[VGREEN].asReal();
+ mV[VBLUE] = (F32)sd[VBLUE].asReal();
}
void setHSL(F32 hue, F32 saturation, F32 luminance);
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
- const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
- const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0)
+ const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
+ const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0)
- const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated
- const LLColor3& setVec(const LLColor3 &vec); // deprecated
- const LLColor3& setVec(const F32 *vec); // deprecated
+ const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated
+ const LLColor3& setVec(const LLColor3& vec); // deprecated
+ const LLColor3& setVec(const F32* vec); // deprecated
- const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
- const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec
- const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec
+ const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
+ const LLColor3& set(const LLColor3& vec); // Sets LLColor3 to vec
+ const LLColor3& set(const F32* vec); // Sets LLColor3 to vec
// set from a vector of unknown type and size
// may leave some data unmodified
@@ -99,56 +98,50 @@ public:
template
void write(std::vector& v) const;
- F32 magVec() const; // deprecated
- F32 magVecSquared() const; // deprecated
- F32 normVec(); // deprecated
+ F32 magVec() const; // deprecated
+ F32 magVecSquared() const; // deprecated
+ F32 normVec(); // deprecated
- F32 length() const; // Returns magnitude of LLColor3
- F32 lengthSquared() const; // Returns magnitude squared of LLColor3
- F32 normalize(); // Normalizes and returns the magnitude of LLColor3
+ F32 length() const; // Returns magnitude of LLColor3
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor3
+ F32 normalize(); // Normalizes and returns the magnitude of LLColor3
- F32 brightness() const; // Returns brightness of LLColor3
+ F32 brightness() const; // Returns brightness of LLColor3
- const LLColor3& operator=(const LLColor4 &a);
+ const LLColor3& operator=(const LLColor4& a);
- LL_FORCE_INLINE LLColor3 divide(const LLColor3 &col2)
+ LL_FORCE_INLINE LLColor3 divide(const LLColor3& col2) const
{
- return LLColor3(
- mV[0] / col2.mV[0],
- mV[1] / col2.mV[1],
- mV[2] / col2.mV[2] );
+ return LLColor3(mV[VRED] / col2.mV[VRED], mV[VGREEN] / col2.mV[VGREEN], mV[VBLUE] / col2.mV[VBLUE]);
}
- LL_FORCE_INLINE LLColor3 color_norm()
+ LL_FORCE_INLINE LLColor3 color_norm() const
{
F32 l = length();
- return LLColor3(
- mV[0] / l,
- mV[1] / l,
- mV[2] / l );
+ return LLColor3(mV[VRED] / l, mV[VGREEN] / l, mV[VBLUE] / l);
}
- friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a
- friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b
- friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b
+ friend std::ostream& operator<<(std::ostream& s, const LLColor3& a); // Print a
+ friend LLColor3 operator+(const LLColor3& a, const LLColor3& b); // Return vector a + b
+ friend LLColor3 operator-(const LLColor3& a, const LLColor3& b); // Return vector a minus b
- friend const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b); // Return vector a + b
- friend const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b); // Return vector a minus b
- friend const LLColor3& operator*=(LLColor3 &a, const LLColor3 &b);
+ friend const LLColor3& operator+=(LLColor3& a, const LLColor3& b); // Return vector a + b
+ friend const LLColor3& operator-=(LLColor3& a, const LLColor3& b); // Return vector a minus b
+ friend const LLColor3& operator*=(LLColor3& a, const LLColor3& b);
- friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return component wise a * b
- friend LLColor3 operator*(const LLColor3 &a, F32 k); // Return a times scaler k
- friend LLColor3 operator*(F32 k, const LLColor3 &a); // Return a times scaler k
+ friend LLColor3 operator*(const LLColor3& a, const LLColor3& b); // Return component wise a * b
+ friend LLColor3 operator*(const LLColor3& a, F32 k); // Return a times scaler k
+ friend LLColor3 operator*(F32 k, const LLColor3& a); // Return a times scaler k
- friend bool operator==(const LLColor3 &a, const LLColor3 &b); // Return a == b
- friend bool operator!=(const LLColor3 &a, const LLColor3 &b); // Return a != b
+ friend bool operator==(const LLColor3& a, const LLColor3& b); // Return a == b
+ friend bool operator!=(const LLColor3& a, const LLColor3& b); // Return a != b
- friend const LLColor3& operator*=(LLColor3 &a, F32 k); // Return a times scaler k
+ friend const LLColor3& operator*=(LLColor3& a, F32 k); // Return a times scaler k
- friend LLColor3 operator-(const LLColor3 &a); // Return vector 1-rgb (inverse)
+ friend LLColor3 operator-(const LLColor3& a); // Return vector 1-rgb (inverse)
inline void clamp();
- inline void exp(); // Do an exponential on the color
+ inline void exp(); // Do an exponential on the color
};
static_assert(std::is_trivially_copyable::value, "LLColor3 must be trivial copy");
@@ -156,360 +149,342 @@ static_assert(std::is_trivially_move_assignable::value, "LLColor3 must
static_assert(std::is_standard_layout::value, "LLColor3 must be a standard layout type");
LLColor3 lerp(const LLColor3& a, const LLColor3& b, F32 u);
-
void LLColor3::clamp()
{
// Clamp the color...
- if (mV[0] < 0.f)
+ if (mV[VRED] < 0.f)
{
- mV[0] = 0.f;
+ mV[VRED] = 0.f;
}
- else if (mV[0] > 1.f)
+ else if (mV[VRED] > 1.f)
{
- mV[0] = 1.f;
+ mV[VRED] = 1.f;
}
- if (mV[1] < 0.f)
+ if (mV[VGREEN] < 0.f)
{
- mV[1] = 0.f;
+ mV[VGREEN] = 0.f;
}
- else if (mV[1] > 1.f)
+ else if (mV[VGREEN] > 1.f)
{
- mV[1] = 1.f;
+ mV[VGREEN] = 1.f;
}
- if (mV[2] < 0.f)
+ if (mV[VBLUE] < 0.f)
{
- mV[2] = 0.f;
+ mV[VBLUE] = 0.f;
}
- else if (mV[2] > 1.f)
+ else if (mV[VBLUE] > 1.f)
{
- mV[2] = 1.f;
+ mV[VBLUE] = 1.f;
}
}
// Non-member functions
-F32 distVec(const LLColor3 &a, const LLColor3 &b); // Returns distance between a and b
-F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance squared between a and b
+F32 distVec(const LLColor3& a, const LLColor3& b); // Returns distance between a and b
+F32 distVec_squared(const LLColor3& a, const LLColor3& b); // Returns distance squared between a and b
-inline LLColor3::LLColor3(void)
+inline LLColor3::LLColor3()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ mV[VRED] = 0.f;
+ mV[VGREEN] = 0.f;
+ mV[VBLUE] = 0.f;
}
inline LLColor3::LLColor3(F32 r, F32 g, F32 b)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
}
-
-inline LLColor3::LLColor3(const F32 *vec)
+inline LLColor3::LLColor3(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
}
inline LLColor3::LLColor3(const char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF
{
- if (strlen(color_string) < 6) /* Flawfinder: ignore */
+ if (strlen(color_string) < 6) /* Flawfinder: ignore */
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ mV[VRED] = 0.f;
+ mV[VGREEN] = 0.f;
+ mV[VBLUE] = 0.f;
return;
}
char tempstr[7];
- strncpy(tempstr,color_string,6); /* Flawfinder: ignore */
+ strncpy(tempstr, color_string, 6); /* Flawfinder: ignore */
tempstr[6] = '\0';
- mV[VBLUE] = (F32)strtol(&tempstr[4],NULL,16)/255.f;
+ mV[VBLUE] = (F32)strtol(&tempstr[4], nullptr, 16) / 255.f;
tempstr[4] = '\0';
- mV[VGREEN] = (F32)strtol(&tempstr[2],NULL,16)/255.f;
+ mV[VGREEN] = (F32)strtol(&tempstr[2], nullptr, 16) / 255.f;
tempstr[2] = '\0';
- mV[VRED] = (F32)strtol(&tempstr[0],NULL,16)/255.f;
+ mV[VRED] = (F32)strtol(&tempstr[0], nullptr, 16) / 255.f;
}
-inline const LLColor3& LLColor3::setToBlack(void)
+inline const LLColor3& LLColor3::setToBlack()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ mV[VRED] = 0.f;
+ mV[VGREEN] = 0.f;
+ mV[VBLUE] = 0.f;
return (*this);
}
-inline const LLColor3& LLColor3::setToWhite(void)
+inline const LLColor3& LLColor3::setToWhite()
{
- mV[0] = 1.f;
- mV[1] = 1.f;
- mV[2] = 1.f;
+ mV[VRED] = 1.f;
+ mV[VGREEN] = 1.f;
+ mV[VBLUE] = 1.f;
return (*this);
}
-inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b)
+inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b)
{
- mV[0] = r;
- mV[1] = g;
- mV[2] = b;
+ mV[VRED] = r;
+ mV[VGREEN] = g;
+ mV[VBLUE] = b;
return (*this);
}
-inline const LLColor3& LLColor3::set(const LLColor3 &vec)
+inline const LLColor3& LLColor3::set(const LLColor3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VRED] = vec.mV[VRED];
+ mV[VGREEN] = vec.mV[VGREEN];
+ mV[VBLUE] = vec.mV[VBLUE];
return (*this);
}
-inline const LLColor3& LLColor3::set(const F32 *vec)
+inline const LLColor3& LLColor3::set(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ mV[VRED] = vec[VRED];
+ mV[VGREEN] = vec[VGREEN];
+ mV[VBLUE] = vec[VBLUE];
return (*this);
}
// deprecated
-inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b)
+inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b)
{
- mV[0] = r;
- mV[1] = g;
- mV[2] = b;
+ mV[VRED] = r;
+ mV[VGREEN] = g;
+ mV[VBLUE] = b;
return (*this);
}
// deprecated
-inline const LLColor3& LLColor3::setVec(const LLColor3 &vec)
+inline const LLColor3& LLColor3::setVec(const LLColor3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VRED] = vec.mV[VRED];
+ mV[VGREEN] = vec.mV[VGREEN];
+ mV[VBLUE] = vec.mV[VBLUE];
return (*this);
}
// deprecated
-inline const LLColor3& LLColor3::setVec(const F32 *vec)
+inline const LLColor3& LLColor3::setVec(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ mV[VRED] = vec[VRED];
+ mV[VGREEN] = vec[VGREEN];
+ mV[VBLUE] = vec[VBLUE];
return (*this);
}
-inline F32 LLColor3::brightness(void) const
+inline F32 LLColor3::brightness() const
{
- return (mV[0] + mV[1] + mV[2]) / 3.0f;
+ return (mV[VRED] + mV[VGREEN] + mV[VBLUE]) / 3.0f;
}
-inline F32 LLColor3::length(void) const
+inline F32 LLColor3::length() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
}
-inline F32 LLColor3::lengthSquared(void) const
+inline F32 LLColor3::lengthSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE];
}
-inline F32 LLColor3::normalize(void)
+inline F32 LLColor3::normalize()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ F32 mag = sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
F32 oomag;
if (mag)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
+ oomag = 1.f / mag;
+ mV[VRED] *= oomag;
+ mV[VGREEN] *= oomag;
+ mV[VBLUE] *= oomag;
}
- return (mag);
+ return mag;
}
// deprecated
-inline F32 LLColor3::magVec(void) const
+inline F32 LLColor3::magVec() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
}
// deprecated
-inline F32 LLColor3::magVecSquared(void) const
+inline F32 LLColor3::magVecSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE];
}
// deprecated
-inline F32 LLColor3::normVec(void)
+inline F32 LLColor3::normVec()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ F32 mag = sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
F32 oomag;
if (mag)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
+ oomag = 1.f / mag;
+ mV[VRED] *= oomag;
+ mV[VGREEN] *= oomag;
+ mV[VBLUE] *= oomag;
}
- return (mag);
+ return mag;
}
inline void LLColor3::exp()
{
#if 0
- mV[0] = ::exp(mV[0]);
- mV[1] = ::exp(mV[1]);
- mV[2] = ::exp(mV[2]);
+ mV[VRED] = ::exp(mV[VRED]);
+ mV[VGREEN] = ::exp(mV[VGREEN]);
+ mV[VBLUE] = ::exp(mV[VBLUE]);
#else
- mV[0] = (F32)LL_FAST_EXP(mV[0]);
- mV[1] = (F32)LL_FAST_EXP(mV[1]);
- mV[2] = (F32)LL_FAST_EXP(mV[2]);
+ mV[VRED] = (F32)LL_FAST_EXP(mV[VRED]);
+ mV[VGREEN] = (F32)LL_FAST_EXP(mV[VGREEN]);
+ mV[VBLUE] = (F32)LL_FAST_EXP(mV[VBLUE]);
#endif
}
-
-inline LLColor3 operator+(const LLColor3 &a, const LLColor3 &b)
+inline LLColor3 operator+(const LLColor3& a, const LLColor3& b)
{
- return LLColor3(
- a.mV[0] + b.mV[0],
- a.mV[1] + b.mV[1],
- a.mV[2] + b.mV[2]);
+ return LLColor3(a.mV[VRED] + b.mV[VRED], a.mV[VGREEN] + b.mV[VGREEN], a.mV[VBLUE] + b.mV[VBLUE]);
}
-inline LLColor3 operator-(const LLColor3 &a, const LLColor3 &b)
+inline LLColor3 operator-(const LLColor3& a, const LLColor3& b)
{
- return LLColor3(
- a.mV[0] - b.mV[0],
- a.mV[1] - b.mV[1],
- a.mV[2] - b.mV[2]);
+ return LLColor3(a.mV[VRED] - b.mV[VRED], a.mV[VGREEN] - b.mV[VGREEN], a.mV[VBLUE] - b.mV[VBLUE]);
}
-inline LLColor3 operator*(const LLColor3 &a, const LLColor3 &b)
+inline LLColor3 operator*(const LLColor3& a, const LLColor3& b)
{
- return LLColor3(
- a.mV[0] * b.mV[0],
- a.mV[1] * b.mV[1],
- a.mV[2] * b.mV[2]);
+ return LLColor3(a.mV[VRED] * b.mV[VRED], a.mV[VGREEN] * b.mV[VGREEN], a.mV[VBLUE] * b.mV[VBLUE]);
}
-inline LLColor3 operator*(const LLColor3 &a, F32 k)
+inline LLColor3 operator*(const LLColor3& a, F32 k)
{
- return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLColor3(a.mV[VRED] * k, a.mV[VGREEN] * k, a.mV[VBLUE] * k);
}
-inline LLColor3 operator*(F32 k, const LLColor3 &a)
+inline LLColor3 operator*(F32 k, const LLColor3& a)
{
- return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLColor3(a.mV[VRED] * k, a.mV[VGREEN] * k, a.mV[VBLUE] * k);
}
-inline bool operator==(const LLColor3 &a, const LLColor3 &b)
+inline bool operator==(const LLColor3& a, const LLColor3& b)
{
- return ( (a.mV[0] == b.mV[0])
- &&(a.mV[1] == b.mV[1])
- &&(a.mV[2] == b.mV[2]));
+ return ((a.mV[VRED] == b.mV[VRED]) && (a.mV[VGREEN] == b.mV[VGREEN]) && (a.mV[VBLUE] == b.mV[VBLUE]));
}
-inline bool operator!=(const LLColor3 &a, const LLColor3 &b)
+inline bool operator!=(const LLColor3& a, const LLColor3& b)
{
- return ( (a.mV[0] != b.mV[0])
- ||(a.mV[1] != b.mV[1])
- ||(a.mV[2] != b.mV[2]));
+ return ((a.mV[VRED] != b.mV[VRED]) || (a.mV[VGREEN] != b.mV[VGREEN]) || (a.mV[VBLUE] != b.mV[VBLUE]));
}
-inline const LLColor3 &operator*=(LLColor3 &a, const LLColor3 &b)
+inline const LLColor3& operator*=(LLColor3& a, const LLColor3& b)
{
- a.mV[0] *= b.mV[0];
- a.mV[1] *= b.mV[1];
- a.mV[2] *= b.mV[2];
+ a.mV[VRED] *= b.mV[VRED];
+ a.mV[VGREEN] *= b.mV[VGREEN];
+ a.mV[VBLUE] *= b.mV[VBLUE];
return a;
}
-inline const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b)
+inline const LLColor3& operator+=(LLColor3& a, const LLColor3& b)
{
- a.mV[0] += b.mV[0];
- a.mV[1] += b.mV[1];
- a.mV[2] += b.mV[2];
+ a.mV[VRED] += b.mV[VRED];
+ a.mV[VGREEN] += b.mV[VGREEN];
+ a.mV[VBLUE] += b.mV[VBLUE];
return a;
}
-inline const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b)
+inline const LLColor3& operator-=(LLColor3& a, const LLColor3& b)
{
- a.mV[0] -= b.mV[0];
- a.mV[1] -= b.mV[1];
- a.mV[2] -= b.mV[2];
+ a.mV[VRED] -= b.mV[VRED];
+ a.mV[VGREEN] -= b.mV[VGREEN];
+ a.mV[VBLUE] -= b.mV[VBLUE];
return a;
}
-inline const LLColor3& operator*=(LLColor3 &a, F32 k)
+inline const LLColor3& operator*=(LLColor3& a, F32 k)
{
- a.mV[0] *= k;
- a.mV[1] *= k;
- a.mV[2] *= k;
+ a.mV[VRED] *= k;
+ a.mV[VGREEN] *= k;
+ a.mV[VBLUE] *= k;
return a;
}
-inline LLColor3 operator-(const LLColor3 &a)
+inline LLColor3 operator-(const LLColor3& a)
{
- return LLColor3(
- 1.f - a.mV[0],
- 1.f - a.mV[1],
- 1.f - a.mV[2] );
+ return LLColor3(1.f - a.mV[VRED], 1.f - a.mV[VGREEN], 1.f - a.mV[VBLUE]);
}
// Non-member functions
-inline F32 distVec(const LLColor3 &a, const LLColor3 &b)
+inline F32 distVec(const LLColor3& a, const LLColor3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
- return (F32) sqrt( x*x + y*y + z*z );
+ F32 x = a.mV[VRED] - b.mV[VRED];
+ F32 y = a.mV[VGREEN] - b.mV[VGREEN];
+ F32 z = a.mV[VBLUE] - b.mV[VBLUE];
+ return sqrt(x * x + y * y + z * z);
}
-inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b)
+inline F32 distVec_squared(const LLColor3& a, const LLColor3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
- return x*x + y*y + z*z;
+ F32 x = a.mV[VRED] - b.mV[VRED];
+ F32 y = a.mV[VGREEN] - b.mV[VGREEN];
+ F32 z = a.mV[VBLUE] - b.mV[VBLUE];
+ return x * x + y * y + z * z;
}
-inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u)
+inline LLColor3 lerp(const LLColor3& a, const LLColor3& b, F32 u)
{
- return LLColor3(
- a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
- a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u,
- a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u);
+ return LLColor3(a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u);
}
-inline const LLColor3 srgbColor3(const LLColor3 &a) {
+inline const LLColor3 srgbColor3(const LLColor3& a)
+{
LLColor3 srgbColor;
- srgbColor.mV[0] = linearTosRGB(a.mV[0]);
- srgbColor.mV[1] = linearTosRGB(a.mV[1]);
- srgbColor.mV[2] = linearTosRGB(a.mV[2]);
+ srgbColor.mV[VRED] = linearTosRGB(a.mV[VRED]);
+ srgbColor.mV[VGREEN] = linearTosRGB(a.mV[VGREEN]);
+ srgbColor.mV[VBLUE] = linearTosRGB(a.mV[VBLUE]);
return srgbColor;
}
-inline const LLColor3 linearColor3p(const F32* v) {
+inline const LLColor3 linearColor3p(const F32* v)
+{
LLColor3 linearColor;
- linearColor.mV[0] = sRGBtoLinear(v[0]);
- linearColor.mV[1] = sRGBtoLinear(v[1]);
- linearColor.mV[2] = sRGBtoLinear(v[2]);
+ linearColor.mV[VRED] = sRGBtoLinear(v[VRED]);
+ linearColor.mV[VGREEN] = sRGBtoLinear(v[VGREEN]);
+ linearColor.mV[VBLUE] = sRGBtoLinear(v[VBLUE]);
return linearColor;
}
template
-inline const LLColor3 linearColor3(const T& a) {
+inline const LLColor3 linearColor3(const T& a)
+{
return linearColor3p(a.mV);
}
template
-inline const LLVector3 linearColor3v(const T& a) {
+inline const LLVector3 linearColor3v(const T& a)
+{
return LLVector3(linearColor3p(a.mV).mV);
}
diff --git a/indra/llmath/v3colorutil.h b/indra/llmath/v3colorutil.h
index af8799e42a..4dc3100443 100644
--- a/indra/llmath/v3colorutil.h
+++ b/indra/llmath/v3colorutil.h
@@ -30,59 +30,46 @@
#include "v3color.h"
#include "v4color.h"
-inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
+inline LLColor3 componentDiv(const LLColor3& left, const LLColor3& right)
{
- return LLColor3(left.mV[0] / right.mV[0],
- left.mV[1] / right.mV[1],
- left.mV[2] / right.mV[2]);
+ return LLColor3(left.mV[VRED] / right.mV[VRED], left.mV[VGREEN] / right.mV[VGREEN], left.mV[VBLUE] / right.mV[VBLUE]);
}
-
-inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
+inline LLColor3 componentMult(const LLColor3& left, const LLColor3& right)
{
- return LLColor3(left.mV[0] * right.mV[0],
- left.mV[1] * right.mV[1],
- left.mV[2] * right.mV[2]);
+ return LLColor3(left.mV[VRED] * right.mV[VRED], left.mV[VGREEN] * right.mV[VGREEN], left.mV[VBLUE] * right.mV[VBLUE]);
}
-
-inline LLColor3 componentExp(LLColor3 const &v)
+inline LLColor3 componentExp(const LLColor3& v)
{
- return LLColor3(exp(v.mV[0]),
- exp(v.mV[1]),
- exp(v.mV[2]));
+ return LLColor3(exp(v.mV[VRED]), exp(v.mV[VGREEN]), exp(v.mV[VBLUE]));
}
-inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
+inline LLColor3 componentPow(const LLColor3& v, F32 exponent)
{
- return LLColor3(pow(v.mV[0], exponent),
- pow(v.mV[1], exponent),
- pow(v.mV[2], exponent));
+ return LLColor3(pow(v.mV[VRED], exponent), pow(v.mV[VGREEN], exponent), pow(v.mV[VBLUE], exponent));
}
-inline LLColor3 componentSaturate(LLColor3 const &v)
+inline LLColor3 componentSaturate(const LLColor3& v)
{
- return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
- std::max(std::min(v.mV[1], 1.f), 0.f),
- std::max(std::min(v.mV[2], 1.f), 0.f));
+ return LLColor3(std::max(std::min(v.mV[VRED], 1.f), 0.f),
+ std::max(std::min(v.mV[VGREEN], 1.f), 0.f),
+ std::max(std::min(v.mV[VBLUE], 1.f), 0.f));
}
-
-inline LLColor3 componentSqrt(LLColor3 const &v)
+inline LLColor3 componentSqrt(const LLColor3& v)
{
- return LLColor3(sqrt(v.mV[0]),
- sqrt(v.mV[1]),
- sqrt(v.mV[2]));
+ return LLColor3(sqrt(v.mV[VRED]), sqrt(v.mV[VGREEN]), sqrt(v.mV[VBLUE]));
}
-inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
+inline void componentMultBy(LLColor3& left, const LLColor3& right)
{
- left.mV[0] *= right.mV[0];
- left.mV[1] *= right.mV[1];
- left.mV[2] *= right.mV[2];
+ left.mV[VRED] *= right.mV[VRED];
+ left.mV[VGREEN] *= right.mV[VGREEN];
+ left.mV[VBLUE] *= right.mV[VBLUE];
}
-inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
+inline LLColor3 colorMix(const LLColor3& left, const LLColor3& right, F32 amount)
{
return (left + ((right - left) * amount));
}
@@ -92,25 +79,24 @@ inline LLColor3 smear(F32 val)
return LLColor3(val, val, val);
}
-inline F32 color_intens(const LLColor3 &col)
+inline F32 color_intens(const LLColor3& col)
{
- return col.mV[0] + col.mV[1] + col.mV[2];
+ return col.mV[VRED] + col.mV[VGREEN] + col.mV[VBLUE];
}
-inline F32 color_max(const LLColor3 &col)
+inline F32 color_max(const LLColor3& col)
{
- return llmax(col.mV[0], col.mV[1], col.mV[2]);
+ return llmax(col.mV[VRED], col.mV[VGREEN], col.mV[VBLUE]);
}
-inline F32 color_max(const LLColor4 &col)
+inline F32 color_max(const LLColor4& col)
{
- return llmax(col.mV[0], col.mV[1], col.mV[2]);
+ return llmax(col.mV[VRED], col.mV[VGREEN], col.mV[VBLUE]);
}
-
-inline F32 color_min(const LLColor3 &col)
+inline F32 color_min(const LLColor3& col)
{
- return llmin(col.mV[0], col.mV[1], col.mV[2]);
+ return llmin(col.mV[VRED], col.mV[VGREEN], col.mV[VBLUE]);
}
#endif
diff --git a/indra/llmath/v3dmath.cpp b/indra/llmath/v3dmath.cpp
index bb55c812b5..b051303686 100644
--- a/indra/llmath/v3dmath.cpp
+++ b/indra/llmath/v3dmath.cpp
@@ -30,7 +30,6 @@
#include "v3dmath.h"
-//#include "vmath.h"
#include "v4math.h"
#include "m4math.h"
#include "m3math.h"
@@ -57,13 +56,13 @@ bool LLVector3d::clamp(F64 min, F64 max)
{
bool ret{ false };
- if (mdV[0] < min) { mdV[0] = min; ret = true; }
- if (mdV[1] < min) { mdV[1] = min; ret = true; }
- if (mdV[2] < min) { mdV[2] = min; ret = true; }
+ if (mdV[VX] < min) { mdV[VX] = min; ret = true; }
+ if (mdV[VY] < min) { mdV[VY] = min; ret = true; }
+ if (mdV[VZ] < min) { mdV[VZ] = min; ret = true; }
- if (mdV[0] > max) { mdV[0] = max; ret = true; }
- if (mdV[1] > max) { mdV[1] = max; ret = true; }
- if (mdV[2] > max) { mdV[2] = max; ret = true; }
+ if (mdV[VX] > max) { mdV[VX] = max; ret = true; }
+ if (mdV[VY] > max) { mdV[VY] = max; ret = true; }
+ if (mdV[VZ] > max) { mdV[VZ] = max; ret = true; }
return ret;
}
@@ -74,9 +73,9 @@ bool LLVector3d::abs()
{
bool ret{ false };
- if (mdV[0] < 0.0) { mdV[0] = -mdV[0]; ret = true; }
- if (mdV[1] < 0.0) { mdV[1] = -mdV[1]; ret = true; }
- if (mdV[2] < 0.0) { mdV[2] = -mdV[2]; ret = true; }
+ if (mdV[VX] < 0.0) { mdV[VX] = -mdV[VX]; ret = true; }
+ if (mdV[VY] < 0.0) { mdV[VY] = -mdV[VY]; ret = true; }
+ if (mdV[VZ] < 0.0) { mdV[VZ] = -mdV[VZ]; ret = true; }
return ret;
}
@@ -89,37 +88,37 @@ std::ostream& operator<<(std::ostream& s, const LLVector3d &a)
const LLVector3d& LLVector3d::operator=(const LLVector4 &a)
{
- mdV[0] = a.mV[0];
- mdV[1] = a.mV[1];
- mdV[2] = a.mV[2];
+ mdV[VX] = a.mV[VX];
+ mdV[VY] = a.mV[VY];
+ mdV[VZ] = a.mV[VZ];
return *this;
}
-const LLVector3d& LLVector3d::rotVec(const LLMatrix3 &mat)
+const LLVector3d& LLVector3d::rotVec(const LLMatrix3& mat)
{
*this = *this * mat;
return *this;
}
-const LLVector3d& LLVector3d::rotVec(const LLQuaternion &q)
+const LLVector3d& LLVector3d::rotVec(const LLQuaternion& q)
{
*this = *this * q;
return *this;
}
-const LLVector3d& LLVector3d::rotVec(F64 angle, const LLVector3d &vec)
+const LLVector3d& LLVector3d::rotVec(F64 angle, const LLVector3d& vec)
{
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLMatrix3((F32)angle, vec);
}
return *this;
}
-const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
+const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
{
LLVector3d vec(x, y, z);
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLMatrix3((F32)angle, vec);
}
@@ -129,16 +128,16 @@ const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
bool LLVector3d::parseVector3d(const std::string& buf, LLVector3d* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
LLVector3d v;
- S32 count = sscanf( buf.c_str(), "%lf %lf %lf", v.mdV + 0, v.mdV + 1, v.mdV + 2 );
- if( 3 == count )
+ S32 count = sscanf(buf.c_str(), "%lf %lf %lf", v.mdV + VX, v.mdV + VY, v.mdV + VZ);
+ if (3 == count)
{
- value->setVec( v );
+ value->setVec(v);
return true;
}
diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h
index d261e9de88..7c56cf138d 100644
--- a/indra/llmath/v3dmath.h
+++ b/indra/llmath/v3dmath.h
@@ -32,102 +32,101 @@
class LLVector3d
{
- public:
- F64 mdV[3];
+public:
+ F64 mdV[3];
- const static LLVector3d zero;
- const static LLVector3d x_axis;
- const static LLVector3d y_axis;
- const static LLVector3d z_axis;
- const static LLVector3d x_axis_neg;
- const static LLVector3d y_axis_neg;
- const static LLVector3d z_axis_neg;
+ const static LLVector3d zero;
+ const static LLVector3d x_axis;
+ const static LLVector3d y_axis;
+ const static LLVector3d z_axis;
+ const static LLVector3d x_axis_neg;
+ const static LLVector3d y_axis_neg;
+ const static LLVector3d z_axis_neg;
- inline LLVector3d(); // Initializes LLVector3d to (0, 0, 0)
- inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
- inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
- inline explicit LLVector3d(const LLVector3 &vec);
- explicit LLVector3d(const LLSD& sd)
- {
- setValue(sd);
- }
+ inline LLVector3d(); // Initializes LLVector3d to (0, 0, 0)
+ inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
+ inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
+ inline explicit LLVector3d(const LLVector3 &vec);
+ explicit LLVector3d(const LLSD& sd)
+ {
+ setValue(sd);
+ }
- void setValue(const LLSD& sd)
- {
- mdV[0] = sd[0].asReal();
- mdV[1] = sd[1].asReal();
- mdV[2] = sd[2].asReal();
- }
+ void setValue(const LLSD& sd)
+ {
+ mdV[VX] = sd[0].asReal();
+ mdV[VY] = sd[1].asReal();
+ mdV[VZ] = sd[2].asReal();
+ }
- LLSD getValue() const
- {
- LLSD ret;
- ret[0] = mdV[0];
- ret[1] = mdV[1];
- ret[2] = mdV[2];
- return ret;
- }
+ LLSD getValue() const
+ {
+ LLSD ret;
+ ret[0] = mdV[VX];
+ ret[1] = mdV[VY];
+ ret[2] = mdV[VZ];
+ return ret;
+ }
- inline bool isFinite() const; // checks to see if all values of LLVector3d are finite
- bool clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns true if data changed
- bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed
+ inline bool isFinite() const; // checks to see if all values of LLVector3d are finite
+ bool clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns true if data changed
+ bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed
- inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1)
- inline const LLVector3d& clearVec(); // deprecated
- inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0)
- inline const LLVector3d& zeroVec(); // deprecated
- inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1)
- inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec
- inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec
- inline const LLVector3d& set(const LLVector3 &vec);
- inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated
- inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated
- inline const LLVector3d& setVec(const F64 *vec); // deprecated
- inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated
+ inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1)
+ inline const LLVector3d& clearVec(); // deprecated
+ inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0)
+ inline const LLVector3d& zeroVec(); // deprecated
+ inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1)
+ inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec
+ inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec
+ inline const LLVector3d& set(const LLVector3 &vec);
+ inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated
+ inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated
+ inline const LLVector3d& setVec(const F64 *vec); // deprecated
+ inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated
- F64 magVec() const; // deprecated
- F64 magVecSquared() const; // deprecated
- inline F64 normVec(); // deprecated
+ F64 magVec() const; // deprecated
+ F64 magVecSquared() const; // deprecated
+ inline F64 normVec(); // deprecated
- F64 length() const; // Returns magnitude of LLVector3d
- F64 lengthSquared() const; // Returns magnitude squared of LLVector3d
- inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d
+ F64 length() const; // Returns magnitude of LLVector3d
+ F64 lengthSquared() const; // Returns magnitude squared of LLVector3d
+ inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d
- const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians
- const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians
- const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
- const LLVector3d& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
+ const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians
+ const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians
+ const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
+ const LLVector3d& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
- bool isNull() const; // Returns true if vector has a _very_small_ length
- bool isExactlyZero() const { return !mdV[VX] && !mdV[VY] && !mdV[VZ]; }
+ bool isNull() const; // Returns true if vector has a _very_small_ length
+ bool isExactlyZero() const { return !mdV[VX] && !mdV[VY] && !mdV[VZ]; }
- const LLVector3d& operator=(const LLVector4 &a);
+ const LLVector3d& operator=(const LLVector4 &a);
- F64 operator[](int idx) const { return mdV[idx]; }
- F64 &operator[](int idx) { return mdV[idx]; }
+ F64 operator[](int idx) const { return mdV[idx]; }
+ F64 &operator[](int idx) { return mdV[idx]; }
- friend LLVector3d operator+(const LLVector3d& a, const LLVector3d& b); // Return vector a + b
- friend LLVector3d operator-(const LLVector3d& a, const LLVector3d& b); // Return vector a minus b
- friend F64 operator*(const LLVector3d& a, const LLVector3d& b); // Return a dot b
- friend LLVector3d operator%(const LLVector3d& a, const LLVector3d& b); // Return a cross b
- friend LLVector3d operator*(const LLVector3d& a, const F64 k); // Return a times scaler k
- friend LLVector3d operator/(const LLVector3d& a, const F64 k); // Return a divided by scaler k
- friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k
- friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b
- friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b
+ friend LLVector3d operator+(const LLVector3d& a, const LLVector3d& b); // Return vector a + b
+ friend LLVector3d operator-(const LLVector3d& a, const LLVector3d& b); // Return vector a minus b
+ friend F64 operator*(const LLVector3d& a, const LLVector3d& b); // Return a dot b
+ friend LLVector3d operator%(const LLVector3d& a, const LLVector3d& b); // Return a cross b
+ friend LLVector3d operator*(const LLVector3d& a, const F64 k); // Return a times scaler k
+ friend LLVector3d operator/(const LLVector3d& a, const F64 k); // Return a divided by scaler k
+ friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k
+ friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b
+ friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b
- friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b
- friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b
- friend const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b); // Return a cross b
- friend const LLVector3d& operator*=(LLVector3d& a, const F64 k); // Return a times scaler k
- friend const LLVector3d& operator/=(LLVector3d& a, const F64 k); // Return a divided by scaler k
+ friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b
+ friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b
+ friend const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b); // Return a cross b
+ friend const LLVector3d& operator*=(LLVector3d& a, const F64 k); // Return a times scaler k
+ friend const LLVector3d& operator/=(LLVector3d& a, const F64 k); // Return a divided by scaler k
- friend LLVector3d operator-(const LLVector3d& a); // Return vector -a
+ friend LLVector3d operator-(const LLVector3d& a); // Return vector -a
- friend std::ostream& operator<<(std::ostream& s, const LLVector3d& a); // Stream a
-
- static bool parseVector3d(const std::string& buf, LLVector3d* value);
+ friend std::ostream& operator<<(std::ostream& s, const LLVector3d& a); // Stream a
+ static bool parseVector3d(const std::string& buf, LLVector3d* value);
};
static_assert(std::is_trivially_copyable::value, "LLVector3d must be trivial copy");
@@ -138,26 +137,26 @@ typedef LLVector3d LLGlobalVec;
inline const LLVector3d &LLVector3d::set(const LLVector3 &vec)
{
- mdV[0] = vec.mV[0];
- mdV[1] = vec.mV[1];
- mdV[2] = vec.mV[2];
+ mdV[VX] = vec.mV[VX];
+ mdV[VY] = vec.mV[VY];
+ mdV[VZ] = vec.mV[VZ];
return *this;
}
inline const LLVector3d &LLVector3d::setVec(const LLVector3 &vec)
{
- mdV[0] = vec.mV[0];
- mdV[1] = vec.mV[1];
- mdV[2] = vec.mV[2];
+ mdV[VX] = vec.mV[VX];
+ mdV[VY] = vec.mV[VY];
+ mdV[VZ] = vec.mV[VZ];
return *this;
}
inline LLVector3d::LLVector3d(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
}
inline LLVector3d::LLVector3d(const F64 x, const F64 y, const F64 z)
@@ -203,33 +202,33 @@ inline bool LLVector3d::isFinite() const
inline const LLVector3d& LLVector3d::clear(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2]= 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
inline const LLVector3d& LLVector3d::clearVec(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2]= 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
inline const LLVector3d& LLVector3d::setZero(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
inline const LLVector3d& LLVector3d::zeroVec(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
@@ -243,17 +242,17 @@ inline const LLVector3d& LLVector3d::set(const F64 x, const F64 y, const F64
inline const LLVector3d& LLVector3d::set(const LLVector3d &vec)
{
- mdV[0] = vec.mdV[0];
- mdV[1] = vec.mdV[1];
- mdV[2] = vec.mdV[2];
+ mdV[VX] = vec.mdV[VX];
+ mdV[VY] = vec.mdV[VY];
+ mdV[VZ] = vec.mdV[VZ];
return (*this);
}
inline const LLVector3d& LLVector3d::set(const F64 *vec)
{
- mdV[0] = vec[0];
- mdV[1] = vec[1];
- mdV[2] = vec[2];
+ mdV[VX] = vec[0];
+ mdV[VY] = vec[1];
+ mdV[VZ] = vec[2];
return (*this);
}
@@ -265,61 +264,62 @@ inline const LLVector3d& LLVector3d::setVec(const F64 x, const F64 y, const F
return (*this);
}
-inline const LLVector3d& LLVector3d::setVec(const LLVector3d &vec)
+inline const LLVector3d& LLVector3d::setVec(const LLVector3d& vec)
{
- mdV[0] = vec.mdV[0];
- mdV[1] = vec.mdV[1];
- mdV[2] = vec.mdV[2];
+ mdV[VX] = vec.mdV[VX];
+ mdV[VY] = vec.mdV[VY];
+ mdV[VZ] = vec.mdV[VZ];
return (*this);
}
-inline const LLVector3d& LLVector3d::setVec(const F64 *vec)
+inline const LLVector3d& LLVector3d::setVec(const F64* vec)
{
- mdV[0] = vec[0];
- mdV[1] = vec[1];
- mdV[2] = vec[2];
+ mdV[VX] = vec[VX];
+ mdV[VY] = vec[VY];
+ mdV[VZ] = vec[VZ];
return (*this);
}
-inline F64 LLVector3d::normVec(void)
+inline F64 LLVector3d::normVec()
{
- F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ F64 mag = (F32)sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); // This explicit cast to F32 limits the precision for numerical stability.
+ // Without it, Unit test "v3dmath_h" fails at "1:angle_between" on macos.
F64 oomag;
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mdV[0] *= oomag;
- mdV[1] *= oomag;
- mdV[2] *= oomag;
+ oomag = 1.0/mag;
+ mdV[VX] *= oomag;
+ mdV[VY] *= oomag;
+ mdV[VZ] *= oomag;
}
else
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.0;
+ mdV[VY] = 0.0;
+ mdV[VZ] = 0.0;
mag = 0;
}
return (mag);
}
-inline F64 LLVector3d::normalize(void)
+inline F64 LLVector3d::normalize()
{
- F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ F64 mag = (F32)sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); // Same as in normVec() above.
F64 oomag;
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mdV[0] *= oomag;
- mdV[1] *= oomag;
- mdV[2] *= oomag;
+ oomag = 1.0/mag;
+ mdV[VX] *= oomag;
+ mdV[VY] *= oomag;
+ mdV[VZ] *= oomag;
}
else
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.0;
+ mdV[VY] = 0.0;
+ mdV[VZ] = 0.0;
mag = 0;
}
return (mag);
@@ -327,24 +327,24 @@ inline F64 LLVector3d::normalize(void)
// LLVector3d Magnitude and Normalization Functions
-inline F64 LLVector3d::magVec(void) const
+inline F64 LLVector3d::magVec() const
{
- return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ return sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]);
}
-inline F64 LLVector3d::magVecSquared(void) const
+inline F64 LLVector3d::magVecSquared() const
{
- return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2];
+ return mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ];
}
-inline F64 LLVector3d::length(void) const
+inline F64 LLVector3d::length() const
{
- return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ return sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]);
}
-inline F64 LLVector3d::lengthSquared(void) const
+inline F64 LLVector3d::lengthSquared() const
{
- return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2];
+ return mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ];
}
inline LLVector3d operator+(const LLVector3d& a, const LLVector3d& b)
@@ -361,109 +361,109 @@ inline LLVector3d operator-(const LLVector3d& a, const LLVector3d& b)
inline F64 operator*(const LLVector3d& a, const LLVector3d& b)
{
- return (a.mdV[0]*b.mdV[0] + a.mdV[1]*b.mdV[1] + a.mdV[2]*b.mdV[2]);
+ return (a.mdV[VX]*b.mdV[VX] + a.mdV[VY]*b.mdV[VY] + a.mdV[VZ]*b.mdV[VZ]);
}
inline LLVector3d operator%(const LLVector3d& a, const LLVector3d& b)
{
- return LLVector3d( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1] );
+ return LLVector3d( a.mdV[VY]*b.mdV[VZ] - b.mdV[VY]*a.mdV[VZ], a.mdV[VZ]*b.mdV[VX] - b.mdV[VZ]*a.mdV[VX], a.mdV[VX]*b.mdV[VY] - b.mdV[VX]*a.mdV[VY] );
}
inline LLVector3d operator/(const LLVector3d& a, const F64 k)
{
F64 t = 1.f / k;
- return LLVector3d( a.mdV[0] * t, a.mdV[1] * t, a.mdV[2] * t );
+ return LLVector3d( a.mdV[VX] * t, a.mdV[VY] * t, a.mdV[VZ] * t );
}
inline LLVector3d operator*(const LLVector3d& a, const F64 k)
{
- return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k );
+ return LLVector3d( a.mdV[VX] * k, a.mdV[VY] * k, a.mdV[VZ] * k );
}
inline LLVector3d operator*(F64 k, const LLVector3d& a)
{
- return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k );
+ return LLVector3d( a.mdV[VX] * k, a.mdV[VY] * k, a.mdV[VZ] * k );
}
inline bool operator==(const LLVector3d& a, const LLVector3d& b)
{
- return ( (a.mdV[0] == b.mdV[0])
- &&(a.mdV[1] == b.mdV[1])
- &&(a.mdV[2] == b.mdV[2]));
+ return ( (a.mdV[VX] == b.mdV[VX])
+ &&(a.mdV[VY] == b.mdV[VY])
+ &&(a.mdV[VZ] == b.mdV[VZ]));
}
inline bool operator!=(const LLVector3d& a, const LLVector3d& b)
{
- return ( (a.mdV[0] != b.mdV[0])
- ||(a.mdV[1] != b.mdV[1])
- ||(a.mdV[2] != b.mdV[2]));
+ return ( (a.mdV[VX] != b.mdV[VX])
+ ||(a.mdV[VY] != b.mdV[VY])
+ ||(a.mdV[VZ] != b.mdV[VZ]));
}
inline const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b)
{
- a.mdV[0] += b.mdV[0];
- a.mdV[1] += b.mdV[1];
- a.mdV[2] += b.mdV[2];
+ a.mdV[VX] += b.mdV[VX];
+ a.mdV[VY] += b.mdV[VY];
+ a.mdV[VZ] += b.mdV[VZ];
return a;
}
inline const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b)
{
- a.mdV[0] -= b.mdV[0];
- a.mdV[1] -= b.mdV[1];
- a.mdV[2] -= b.mdV[2];
+ a.mdV[VX] -= b.mdV[VX];
+ a.mdV[VY] -= b.mdV[VY];
+ a.mdV[VZ] -= b.mdV[VZ];
return a;
}
inline const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b)
{
- LLVector3d ret( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1]);
+ LLVector3d ret( a.mdV[VY]*b.mdV[VZ] - b.mdV[VY]*a.mdV[VZ], a.mdV[VZ]*b.mdV[VX] - b.mdV[VZ]*a.mdV[VX], a.mdV[VX]*b.mdV[VY] - b.mdV[VX]*a.mdV[VY]);
a = ret;
return a;
}
inline const LLVector3d& operator*=(LLVector3d& a, const F64 k)
{
- a.mdV[0] *= k;
- a.mdV[1] *= k;
- a.mdV[2] *= k;
+ a.mdV[VX] *= k;
+ a.mdV[VY] *= k;
+ a.mdV[VZ] *= k;
return a;
}
inline const LLVector3d& operator/=(LLVector3d& a, const F64 k)
{
F64 t = 1.f / k;
- a.mdV[0] *= t;
- a.mdV[1] *= t;
- a.mdV[2] *= t;
+ a.mdV[VX] *= t;
+ a.mdV[VY] *= t;
+ a.mdV[VZ] *= t;
return a;
}
inline LLVector3d operator-(const LLVector3d& a)
{
- return LLVector3d( -a.mdV[0], -a.mdV[1], -a.mdV[2] );
+ return LLVector3d( -a.mdV[VX], -a.mdV[VY], -a.mdV[VZ] );
}
inline F64 dist_vec(const LLVector3d& a, const LLVector3d& b)
{
- F64 x = a.mdV[0] - b.mdV[0];
- F64 y = a.mdV[1] - b.mdV[1];
- F64 z = a.mdV[2] - b.mdV[2];
+ F64 x = a.mdV[VX] - b.mdV[VX];
+ F64 y = a.mdV[VY] - b.mdV[VY];
+ F64 z = a.mdV[VZ] - b.mdV[VZ];
return (F32) sqrt( x*x + y*y + z*z );
}
inline F64 dist_vec_squared(const LLVector3d& a, const LLVector3d& b)
{
- F64 x = a.mdV[0] - b.mdV[0];
- F64 y = a.mdV[1] - b.mdV[1];
- F64 z = a.mdV[2] - b.mdV[2];
+ F64 x = a.mdV[VX] - b.mdV[VX];
+ F64 y = a.mdV[VY] - b.mdV[VY];
+ F64 z = a.mdV[VZ] - b.mdV[VZ];
return x*x + y*y + z*z;
}
inline F64 dist_vec_squared2D(const LLVector3d& a, const LLVector3d& b)
{
- F64 x = a.mdV[0] - b.mdV[0];
- F64 y = a.mdV[1] - b.mdV[1];
+ F64 x = a.mdV[VX] - b.mdV[VX];
+ F64 y = a.mdV[VY] - b.mdV[VY];
return x*x + y*y;
}
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index 73ad2a4ed6..eac95ed023 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -28,7 +28,6 @@
#include "v3math.h"
-//#include "vmath.h"
#include "v2math.h"
#include "v4math.h"
#include "m4math.h"
@@ -58,13 +57,13 @@ bool LLVector3::clamp(F32 min, F32 max)
{
bool ret{ false };
- if (mV[0] < min) { mV[0] = min; ret = true; }
- if (mV[1] < min) { mV[1] = min; ret = true; }
- if (mV[2] < min) { mV[2] = min; ret = true; }
+ if (mV[VX] < min) { mV[VX] = min; ret = true; }
+ if (mV[VY] < min) { mV[VY] = min; ret = true; }
+ if (mV[VZ] < min) { mV[VZ] = min; ret = true; }
- if (mV[0] > max) { mV[0] = max; ret = true; }
- if (mV[1] > max) { mV[1] = max; ret = true; }
- if (mV[2] > max) { mV[2] = max; ret = true; }
+ if (mV[VX] > max) { mV[VX] = max; ret = true; }
+ if (mV[VY] > max) { mV[VY] = max; ret = true; }
+ if (mV[VZ] > max) { mV[VZ] = max; ret = true; }
return ret;
}
@@ -85,9 +84,9 @@ bool LLVector3::clampLength( F32 length_limit )
{
length_limit = 0.f;
}
- mV[0] *= length_limit;
- mV[1] *= length_limit;
- mV[2] *= length_limit;
+ mV[VX] *= length_limit;
+ mV[VY] *= length_limit;
+ mV[VZ] *= length_limit;
changed = true;
}
}
@@ -116,35 +115,35 @@ bool LLVector3::clampLength( F32 length_limit )
{
// yes it can be salvaged -->
// bring the components down before we normalize
- mV[0] /= max_abs_component;
- mV[1] /= max_abs_component;
- mV[2] /= max_abs_component;
+ mV[VX] /= max_abs_component;
+ mV[VY] /= max_abs_component;
+ mV[VZ] /= max_abs_component;
normalize();
if (length_limit < 0.f)
{
length_limit = 0.f;
}
- mV[0] *= length_limit;
- mV[1] *= length_limit;
- mV[2] *= length_limit;
+ mV[VX] *= length_limit;
+ mV[VY] *= length_limit;
+ mV[VZ] *= length_limit;
}
}
return changed;
}
-bool LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec)
+bool LLVector3::clamp(const LLVector3& min_vec, const LLVector3& max_vec)
{
bool ret{ false };
- if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = true; }
- if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = true; }
- if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = true; }
+ if (mV[VX] < min_vec[0]) { mV[VX] = min_vec[0]; ret = true; }
+ if (mV[VY] < min_vec[1]) { mV[VY] = min_vec[1]; ret = true; }
+ if (mV[VZ] < min_vec[2]) { mV[VZ] = min_vec[2]; ret = true; }
- if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = true; }
- if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = true; }
- if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = true; }
+ if (mV[VX] > max_vec[0]) { mV[VX] = max_vec[0]; ret = true; }
+ if (mV[VY] > max_vec[1]) { mV[VY] = max_vec[1]; ret = true; }
+ if (mV[VZ] > max_vec[2]) { mV[VZ] = max_vec[2]; ret = true; }
return ret;
}
@@ -156,15 +155,15 @@ bool LLVector3::abs()
{
bool ret{ false };
- if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; }
- if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; }
- if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; }
+ if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; }
+ if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; }
+ if (mV[VZ] < 0.f) { mV[VZ] = -mV[VZ]; ret = true; }
return ret;
}
// Quatizations
-void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
+void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
{
F32 x = mV[VX];
F32 y = mV[VY];
@@ -179,7 +178,7 @@ void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
mV[VZ] = z;
}
-void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
+void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
{
mV[VX] = U8_to_F32(F32_to_U8(mV[VX], lowerxy, upperxy), lowerxy, upperxy);;
mV[VY] = U8_to_F32(F32_to_U8(mV[VY], lowerxy, upperxy), lowerxy, upperxy);
@@ -187,20 +186,20 @@ void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
}
-void LLVector3::snap(S32 sig_digits)
+void LLVector3::snap(S32 sig_digits)
{
mV[VX] = snap_to_sig_figs(mV[VX], sig_digits);
mV[VY] = snap_to_sig_figs(mV[VY], sig_digits);
mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
}
-const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat)
+const LLVector3& LLVector3::rotVec(const LLMatrix3& mat)
{
*this = *this * mat;
return *this;
}
-const LLVector3& LLVector3::rotVec(const LLQuaternion &q)
+const LLVector3& LLVector3::rotVec(const LLQuaternion& q)
{
*this = *this * q;
return *this;
@@ -228,26 +227,26 @@ const LLVector3& LLVector3::transVec(const LLMatrix4& mat)
}
-const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec)
+const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3& vec)
{
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLQuaternion(angle, vec);
}
return *this;
}
-const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
+const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
{
LLVector3 vec(x, y, z);
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLQuaternion(angle, vec);
}
return *this;
}
-const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
+const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
{
mV[VX] *= vec.mV[VX];
mV[VY] *= vec.mV[VY];
@@ -256,42 +255,42 @@ const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
return *this;
}
-LLVector3 LLVector3::scaledVec(const LLVector3& vec) const
+LLVector3 LLVector3::scaledVec(const LLVector3& vec) const
{
LLVector3 ret = LLVector3(*this);
ret.scaleVec(vec);
return ret;
}
-const LLVector3& LLVector3::set(const LLVector3d &vec)
+const LLVector3& LLVector3::set(const LLVector3d& vec)
{
- mV[0] = (F32)vec.mdV[0];
- mV[1] = (F32)vec.mdV[1];
- mV[2] = (F32)vec.mdV[2];
+ mV[VX] = (F32)vec.mdV[VX];
+ mV[VY] = (F32)vec.mdV[VY];
+ mV[VZ] = (F32)vec.mdV[VZ];
return (*this);
}
-const LLVector3& LLVector3::set(const LLVector4 &vec)
+const LLVector3& LLVector3::set(const LLVector4& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
return (*this);
}
-const LLVector3& LLVector3::setVec(const LLVector3d &vec)
+const LLVector3& LLVector3::setVec(const LLVector3d& vec)
{
- mV[0] = (F32)vec.mdV[0];
- mV[1] = (F32)vec.mdV[1];
- mV[2] = (F32)vec.mdV[2];
+ mV[VX] = (F32)vec.mdV[0];
+ mV[VY] = (F32)vec.mdV[1];
+ mV[VZ] = (F32)vec.mdV[2];
return (*this);
}
-const LLVector3& LLVector3::setVec(const LLVector4 &vec)
+const LLVector3& LLVector3::setVec(const LLVector4& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
return (*this);
}
@@ -299,17 +298,17 @@ LLVector3::LLVector3(const LLVector2 &vec)
{
mV[VX] = (F32)vec.mV[VX];
mV[VY] = (F32)vec.mV[VY];
- mV[VZ] = 0;
+ mV[VZ] = 0.f;
}
-LLVector3::LLVector3(const LLVector3d &vec)
+LLVector3::LLVector3(const LLVector3d& vec)
{
mV[VX] = (F32)vec.mdV[VX];
mV[VY] = (F32)vec.mdV[VY];
mV[VZ] = (F32)vec.mdV[VZ];
}
-LLVector3::LLVector3(const LLVector4 &vec)
+LLVector3::LLVector3(const LLVector4& vec)
{
mV[VX] = (F32)vec.mV[VX];
mV[VY] = (F32)vec.mV[VY];
@@ -319,7 +318,6 @@ LLVector3::LLVector3(const LLVector4 &vec)
LLVector3::LLVector3(const LLVector4a& vec)
: LLVector3(vec.getF32ptr())
{
-
}
LLVector3::LLVector3(const LLSD& sd)
@@ -330,20 +328,20 @@ LLVector3::LLVector3(const LLSD& sd)
LLSD LLVector3::getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
+ ret[VX] = mV[VX];
+ ret[VY] = mV[VY];
+ ret[VZ] = mV[VZ];
return ret;
}
void LLVector3::setValue(const LLSD& sd)
{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
+ mV[VX] = (F32) sd[VX].asReal();
+ mV[VY] = (F32) sd[VY].asReal();
+ mV[VZ] = (F32) sd[VZ].asReal();
}
-const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
+const LLVector3& operator*=(LLVector3& a, const LLQuaternion& rot)
{
const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
const F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
@@ -360,16 +358,16 @@ const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
// static
bool LLVector3::parseVector3(const std::string& buf, LLVector3* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
LLVector3 v;
- S32 count = sscanf( buf.c_str(), "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 );
- if( 3 == count )
+ S32 count = sscanf(buf.c_str(), "%f %f %f", v.mV + VX, v.mV + VY, v.mV + VZ);
+ if (3 == count)
{
- value->setVec( v );
+ value->setVec(v);
return true;
}
@@ -381,7 +379,7 @@ bool LLVector3::parseVector3(const std::string& buf, LLVector3* value)
LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box)
{
LLVector3 offset;
- for (S32 k=0; k<3; k++)
+ for (S32 k = 0; k < 3; k++)
{
offset[k] = 0;
if (pos[k] < box[0][k])
@@ -410,4 +408,3 @@ bool box_valid_and_non_zero(const LLVector3* box)
}
return false;
}
-
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index 8f0d00270d..196ecdcf7d 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -46,7 +46,7 @@ class LLQuaternion;
// LLvector3 = |x y z w|
-static const U32 LENGTHOFVECTOR3 = 3;
+static constexpr U32 LENGTHOFVECTOR3 = 3;
class LLVector3
{
@@ -112,24 +112,24 @@ class LLVector3
const LLVector3& setVec(const LLVector4 &vec); // deprecated
const LLVector3& setVec(const LLVector3d &vec); // deprecated
- F32 length() const; // Returns magnitude of LLVector3
- F32 lengthSquared() const; // Returns magnitude squared of LLVector3
- F32 magVec() const; // deprecated
- F32 magVecSquared() const; // deprecated
+ F32 length() const; // Returns magnitude of LLVector3
+ F32 lengthSquared() const; // Returns magnitude squared of LLVector3
+ F32 magVec() const; // deprecated
+ F32 magVecSquared() const; // deprecated
- inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
- inline F32 normVec(); // deprecated
+ inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
+ inline F32 normVec(); // deprecated
- inline bool inRange( F32 min, F32 max ) const; // Returns true if all values of the vector are between min and max
+ inline bool inRange(F32 min, F32 max) const; // Returns true if all values of the vector are between min and max
- const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians
- const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
- const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
- const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
- const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
+ const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians
+ const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
+ const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
+ const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
+ const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
- const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec
- LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec
+ const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec
+ LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec
bool isNull() const; // Returns true if vector has a _very_small_ length
bool isExactlyZero() const { return !mV[VX] && !mV[VY] && !mV[VZ]; }
@@ -185,25 +185,19 @@ LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vect
LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box); // Displacement from query point to nearest point on bounding box.
bool box_valid_and_non_zero(const LLVector3* box);
-inline LLVector3::LLVector3(void)
+inline LLVector3::LLVector3()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
+ set(x, y, z);
}
inline LLVector3::LLVector3(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
- mV[VZ] = vec[VZ];
+ set(vec);
}
inline LLVector3::LLVector3(const glm::vec3& vec)
@@ -234,38 +228,30 @@ inline LLVector3::LLVector3(const LLVector3 ©)
// checker
inline bool LLVector3::isFinite() const
{
- return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]));
+ return llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]);
}
// Clear and Assignment Functions
-inline void LLVector3::clear(void)
+inline void LLVector3::clear()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ set(0.f, 0.f, 0.f);
}
-inline void LLVector3::setZero(void)
+inline void LLVector3::setZero()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
-inline void LLVector3::clearVec(void)
+inline void LLVector3::clearVec()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
-inline void LLVector3::zeroVec(void)
+inline void LLVector3::zeroVec()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
inline void LLVector3::set(F32 x, F32 y, F32 z)
@@ -275,18 +261,14 @@ inline void LLVector3::set(F32 x, F32 y, F32 z)
mV[VZ] = z;
}
-inline void LLVector3::set(const LLVector3 &vec)
+inline void LLVector3::set(const LLVector3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ set(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
}
-inline void LLVector3::set(const F32 *vec)
+inline void LLVector3::set(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ set(vec[VX], vec[VY], vec[VZ]);
}
inline void LLVector3::set(const glm::vec4& vec)
@@ -306,213 +288,181 @@ inline void LLVector3::set(const glm::vec3& vec)
// deprecated
inline void LLVector3::setVec(F32 x, F32 y, F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
+ set(x, y, z);
}
// deprecated
-inline void LLVector3::setVec(const LLVector3 &vec)
+inline void LLVector3::setVec(const LLVector3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ set(vec);
}
// deprecated
-inline void LLVector3::setVec(const F32 *vec)
+inline void LLVector3::setVec(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ set(vec);
}
-inline F32 LLVector3::normalize(void)
+inline F32 LLVector3::normalize()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
- F32 oomag;
+ F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
+ *this /= mag;
}
else
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
mag = 0;
}
- return (mag);
+ return mag;
}
// deprecated
-inline F32 LLVector3::normVec(void)
+inline F32 LLVector3::normVec()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
- F32 oomag;
-
- if (mag > FP_MAG_THRESHOLD)
- {
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
- }
- else
- {
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
- mag = 0;
- }
- return (mag);
+ return normalize();
}
// LLVector3 Magnitude and Normalization Functions
-inline F32 LLVector3::length(void) const
+inline F32 LLVector3::length() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return sqrt(lengthSquared());
}
-inline F32 LLVector3::lengthSquared(void) const
+inline F32 LLVector3::lengthSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
-inline F32 LLVector3::magVec(void) const
+inline F32 LLVector3::magVec() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return length();
}
-inline F32 LLVector3::magVecSquared(void) const
+inline F32 LLVector3::magVecSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return lengthSquared();
}
-inline bool LLVector3::inRange( F32 min, F32 max ) const
+inline bool LLVector3::inRange(F32 min, F32 max) const
{
- return mV[0] >= min && mV[0] <= max &&
- mV[1] >= min && mV[1] <= max &&
- mV[2] >= min && mV[2] <= max;
+ return mV[VX] >= min && mV[VX] <= max &&
+ mV[VY] >= min && mV[VY] <= max &&
+ mV[VZ] >= min && mV[VZ] <= max;
}
-inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 operator+(const LLVector3& a, const LLVector3& b)
{
LLVector3 c(a);
return c += b;
}
-inline LLVector3 operator-(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 operator-(const LLVector3& a, const LLVector3& b)
{
LLVector3 c(a);
return c -= b;
}
-inline F32 operator*(const LLVector3 &a, const LLVector3 &b)
+inline F32 operator*(const LLVector3& a, const LLVector3& b)
{
- return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]);
+ return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]);
}
-inline LLVector3 operator%(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 operator%(const LLVector3& a, const LLVector3& b)
{
- return LLVector3( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1] );
+ return LLVector3(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
}
-inline LLVector3 operator/(const LLVector3 &a, F32 k)
+inline LLVector3 operator/(const LLVector3& a, F32 k)
{
F32 t = 1.f / k;
- return LLVector3( a.mV[0] * t, a.mV[1] * t, a.mV[2] * t );
+ return LLVector3( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t );
}
-inline LLVector3 operator*(const LLVector3 &a, F32 k)
+inline LLVector3 operator*(const LLVector3& a, F32 k)
{
- return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLVector3( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k );
}
-inline LLVector3 operator*(F32 k, const LLVector3 &a)
+inline LLVector3 operator*(F32 k, const LLVector3& a)
{
- return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLVector3( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k );
}
-inline bool operator==(const LLVector3 &a, const LLVector3 &b)
+inline bool operator==(const LLVector3& a, const LLVector3& b)
{
- return ( (a.mV[0] == b.mV[0])
- &&(a.mV[1] == b.mV[1])
- &&(a.mV[2] == b.mV[2]));
+ return ( (a.mV[VX] == b.mV[VX])
+ &&(a.mV[VY] == b.mV[VY])
+ &&(a.mV[VZ] == b.mV[VZ]));
}
-inline bool operator!=(const LLVector3 &a, const LLVector3 &b)
+inline bool operator!=(const LLVector3& a, const LLVector3& b)
{
- return ( (a.mV[0] != b.mV[0])
- ||(a.mV[1] != b.mV[1])
- ||(a.mV[2] != b.mV[2]));
+ return ( (a.mV[VX] != b.mV[VX])
+ ||(a.mV[VY] != b.mV[VY])
+ ||(a.mV[VZ] != b.mV[VZ]));
}
-inline bool operator<(const LLVector3 &a, const LLVector3 &b)
+inline bool operator<(const LLVector3& a, const LLVector3& b)
{
- return (a.mV[0] < b.mV[0]
- || (a.mV[0] == b.mV[0]
- && (a.mV[1] < b.mV[1]
- || ((a.mV[1] == b.mV[1])
- && a.mV[2] < b.mV[2]))));
+ return (a.mV[VX] < b.mV[VX]
+ || (a.mV[VX] == b.mV[VX]
+ && (a.mV[VY] < b.mV[VY]
+ || ((a.mV[VY] == b.mV[VY])
+ && a.mV[VZ] < b.mV[VZ]))));
}
-inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator+=(LLVector3& a, const LLVector3& b)
{
- a.mV[0] += b.mV[0];
- a.mV[1] += b.mV[1];
- a.mV[2] += b.mV[2];
+ a.mV[VX] += b.mV[VX];
+ a.mV[VY] += b.mV[VY];
+ a.mV[VZ] += b.mV[VZ];
return a;
}
-inline const LLVector3& operator-=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator-=(LLVector3& a, const LLVector3& b)
{
- a.mV[0] -= b.mV[0];
- a.mV[1] -= b.mV[1];
- a.mV[2] -= b.mV[2];
+ a.mV[VX] -= b.mV[VX];
+ a.mV[VY] -= b.mV[VY];
+ a.mV[VZ] -= b.mV[VZ];
return a;
}
-inline const LLVector3& operator%=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator%=(LLVector3& a, const LLVector3& b)
{
- LLVector3 ret( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1]);
+ LLVector3 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
a = ret;
return a;
}
-inline const LLVector3& operator*=(LLVector3 &a, F32 k)
+inline const LLVector3& operator*=(LLVector3& a, F32 k)
{
- a.mV[0] *= k;
- a.mV[1] *= k;
- a.mV[2] *= k;
+ a.mV[VX] *= k;
+ a.mV[VY] *= k;
+ a.mV[VZ] *= k;
return a;
}
-inline const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator*=(LLVector3& a, const LLVector3& b)
{
- a.mV[0] *= b.mV[0];
- a.mV[1] *= b.mV[1];
- a.mV[2] *= b.mV[2];
+ a.mV[VX] *= b.mV[VX];
+ a.mV[VY] *= b.mV[VY];
+ a.mV[VZ] *= b.mV[VZ];
return a;
}
-inline const LLVector3& operator/=(LLVector3 &a, F32 k)
+inline const LLVector3& operator/=(LLVector3& a, F32 k)
{
- F32 t = 1.f / k;
- a.mV[0] *= t;
- a.mV[1] *= t;
- a.mV[2] *= t;
+ a *= 1.f / k;
return a;
}
-inline LLVector3 operator-(const LLVector3 &a)
+inline LLVector3 operator-(const LLVector3& a)
{
- return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] );
+ return LLVector3(-a.mV[VX], -a.mV[VY], -a.mV[VZ]);
}
inline LLVector3::operator glm::vec3() const
@@ -526,40 +476,37 @@ inline LLVector3::operator glm::vec4() const
return glm::vec4(mV[VX], mV[VY], mV[VZ], 1.f);
}
-inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b)
+inline F32 dist_vec(const LLVector3& a, const LLVector3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
- return (F32) sqrt( x*x + y*y + z*z );
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
+ F32 z = a.mV[VZ] - b.mV[VZ];
+ return sqrt(x*x + y*y + z*z);
}
-inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b)
+inline F32 dist_vec_squared(const LLVector3& a, const LLVector3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
+ F32 z = a.mV[VZ] - b.mV[VZ];
return x*x + y*y + z*z;
}
-inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b)
+inline F32 dist_vec_squared2D(const LLVector3& a, const LLVector3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return x*x + y*y;
}
-inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 projected_vec(const LLVector3& a, const LLVector3& b)
{
F32 bb = b * b;
if (bb > FP_MAG_THRESHOLD * FP_MAG_THRESHOLD)
{
return ((a * b) / bb) * b;
}
- else
- {
- return b.zero;
- }
+ return b.zero;
}
inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
@@ -574,18 +521,18 @@ inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
return normalized_a * (b_length / dot_product);
}
-inline LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 parallel_component(const LLVector3& a, const LLVector3& b)
{
return projected_vec(a, b);
}
-inline LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 orthogonal_component(const LLVector3& a, const LLVector3& b)
{
return a - projected_vec(a, b);
}
-inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u)
+inline LLVector3 lerp(const LLVector3& a, const LLVector3& b, F32 u)
{
return LLVector3(
a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
@@ -596,11 +543,7 @@ inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u)
inline bool LLVector3::isNull() const
{
- if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ] )
- {
- return true;
- }
- return false;
+ return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos)
@@ -641,17 +584,17 @@ inline F32 angle_between(const LLVector3& a, const LLVector3& b)
ab = 0.0f; // get rid of negative zero
}
LLVector3 c = a % b; // crossproduct
- return atan2f(sqrtf(c * c), ab); // return the angle
+ return atan2f(c.length(), ab); // return the angle
}
-inline bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
+inline bool are_parallel(const LLVector3& a, const LLVector3& b, F32 epsilon)
{
LLVector3 an = a;
LLVector3 bn = b;
an.normalize();
bn.normalize();
F32 dot = an * bn;
- if ( (1.0f - fabs(dot)) < epsilon)
+ if (1.0f - fabs(dot) < epsilon)
{
return true;
}
diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp
index ad13656bbd..1b687642ca 100644
--- a/indra/llmath/v4color.cpp
+++ b/indra/llmath/v4color.cpp
@@ -124,65 +124,64 @@ LLColor4 LLColor4::cyan6(0.2f, 0.6f, 0.6f, 1.0f);
// conversion
LLColor4::operator LLColor4U() const
{
- return LLColor4U(
- (U8)llclampb(ll_round(mV[VRED]*255.f)),
- (U8)llclampb(ll_round(mV[VGREEN]*255.f)),
- (U8)llclampb(ll_round(mV[VBLUE]*255.f)),
- (U8)llclampb(ll_round(mV[VALPHA]*255.f)));
+ return LLColor4U((U8)llclampb(ll_round(mV[VRED] * 255.f)),
+ (U8)llclampb(ll_round(mV[VGREEN] * 255.f)),
+ (U8)llclampb(ll_round(mV[VBLUE] * 255.f)),
+ (U8)llclampb(ll_round(mV[VALPHA] * 255.f)));
}
-LLColor4::LLColor4(const LLColor3 &vec, F32 a)
+LLColor4::LLColor4(const LLColor3& vec, F32 a)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = a;
}
LLColor4::LLColor4(const LLColor4U& color4u)
{
- const F32 SCALE = 1.f/255.f;
- mV[VRED] = color4u.mV[VRED] * SCALE;
- mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
- mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
- mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
+ constexpr F32 SCALE = 1.f / 255.f;
+ mV[VRED] = color4u.mV[VRED] * SCALE;
+ mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
+ mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
+ mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
}
LLColor4::LLColor4(const LLVector4& vector4)
{
- mV[VRED] = vector4.mV[VRED];
+ mV[VRED] = vector4.mV[VRED];
mV[VGREEN] = vector4.mV[VGREEN];
- mV[VBLUE] = vector4.mV[VBLUE];
+ mV[VBLUE] = vector4.mV[VBLUE];
mV[VALPHA] = vector4.mV[VALPHA];
}
const LLColor4& LLColor4::set(const LLColor4U& color4u)
{
- const F32 SCALE = 1.f/255.f;
- mV[VRED] = color4u.mV[VRED] * SCALE;
- mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
- mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
- mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
+ constexpr F32 SCALE = 1.f / 255.f;
+ mV[VRED] = color4u.mV[VRED] * SCALE;
+ mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
+ mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
+ mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
return (*this);
}
-const LLColor4& LLColor4::set(const LLColor3 &vec)
+const LLColor4& LLColor4::set(const LLColor3& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
-const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a)
+const LLColor4& LLColor4::set(const LLColor3& vec, F32 a)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = a;
return (*this);
}
@@ -190,33 +189,33 @@ const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a)
// deprecated -- use set()
const LLColor4& LLColor4::setVec(const LLColor4U& color4u)
{
- const F32 SCALE = 1.f/255.f;
- mV[VRED] = color4u.mV[VRED] * SCALE;
- mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
- mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
- mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
+ constexpr F32 SCALE = 1.f / 255.f;
+ mV[VRED] = color4u.mV[VRED] * SCALE;
+ mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
+ mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
+ mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
return (*this);
}
// deprecated -- use set()
-const LLColor4& LLColor4::setVec(const LLColor3 &vec)
+const LLColor4& LLColor4::setVec(const LLColor3& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
// deprecated -- use set()
-const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a)
+const LLColor4& LLColor4::setVec(const LLColor3& vec, F32 a)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = a;
return (*this);
}
@@ -228,110 +227,110 @@ void LLColor4::setValue(const LLSD& sd)
F32 val;
bool out_of_range = false;
val = sd[0].asReal();
- mV[0] = llclamp(val, 0.f, 1.f);
- out_of_range = mV[0] != val;
+ mV[VRED] = llclamp(val, 0.f, 1.f);
+ out_of_range = mV[VRED] != val;
val = sd[1].asReal();
- mV[1] = llclamp(val, 0.f, 1.f);
- out_of_range |= mV[1] != val;
+ mV[VGREEN] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[VGREEN] != val;
val = sd[2].asReal();
- mV[2] = llclamp(val, 0.f, 1.f);
- out_of_range |= mV[2] != val;
+ mV[VBLUE] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[VBLUE] != val;
val = sd[3].asReal();
- mV[3] = llclamp(val, 0.f, 1.f);
- out_of_range |= mV[3] != val;
+ mV[VALPHA] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[VALPHA] != val;
if (out_of_range)
{
LL_WARNS() << "LLSD color value out of range!" << LL_ENDL;
}
#else
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
- mV[3] = (F32) sd[3].asReal();
+ mV[VRED] = (F32)sd[VRED].asReal();
+ mV[VGREEN] = (F32)sd[VGREEN].asReal();
+ mV[VBLUE] = (F32)sd[VBLUE].asReal();
+ mV[VALPHA] = (F32)sd[VALPHA].asReal();
#endif
}
-const LLColor4& LLColor4::operator=(const LLColor3 &a)
+const LLColor4& LLColor4::operator=(const LLColor3& a)
{
- mV[VRED] = a.mV[VRED];
+ mV[VRED] = a.mV[VRED];
mV[VGREEN] = a.mV[VGREEN];
- mV[VBLUE] = a.mV[VBLUE];
+ mV[VBLUE] = a.mV[VBLUE];
-// converting from an rgb sets a=1 (opaque)
+ // converting from an rgb sets a=1 (opaque)
mV[VALPHA] = 1.f;
return (*this);
}
-
-std::ostream& operator<<(std::ostream& s, const LLColor4 &a)
+std::ostream& operator<<(std::ostream& s, const LLColor4& a)
{
s << "{ " << a.mV[VRED] << ", " << a.mV[VGREEN] << ", " << a.mV[VBLUE] << ", " << a.mV[VALPHA] << " }";
return s;
}
-bool operator==(const LLColor4 &a, const LLColor3 &b)
+bool operator==(const LLColor4& a, const LLColor3& b)
{
- return ( (a.mV[VRED] == b.mV[VRED])
- &&(a.mV[VGREEN] == b.mV[VGREEN])
- &&(a.mV[VBLUE] == b.mV[VBLUE]));
+ return ((a.mV[VRED] == b.mV[VRED]) && (a.mV[VGREEN] == b.mV[VGREEN]) && (a.mV[VBLUE] == b.mV[VBLUE]));
}
-bool operator!=(const LLColor4 &a, const LLColor3 &b)
+bool operator!=(const LLColor4& a, const LLColor3& b)
{
- return ( (a.mV[VRED] != b.mV[VRED])
- ||(a.mV[VGREEN] != b.mV[VGREEN])
- ||(a.mV[VBLUE] != b.mV[VBLUE]));
+ return ((a.mV[VRED] != b.mV[VRED]) || (a.mV[VGREEN] != b.mV[VGREEN]) || (a.mV[VBLUE] != b.mV[VBLUE]));
}
-LLColor3 vec4to3(const LLColor4 &vec)
+LLColor3 vec4to3(const LLColor4& vec)
{
- LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
+ LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
return temp;
}
-LLColor4 vec3to4(const LLColor3 &vec)
+LLColor4 vec3to4(const LLColor3& vec)
{
- LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
+ LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
return temp;
}
-static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+static F32 hueToRgb(F32 val1In, F32 val2In, F32 valHUeIn)
{
- if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
- if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
- if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
- if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
- if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
- return ( val1In );
+ if (valHUeIn < 0.0f)
+ valHUeIn += 1.0f;
+ if (valHUeIn > 1.0f)
+ valHUeIn -= 1.0f;
+ if ((6.0f * valHUeIn) < 1.0f)
+ return (val1In + (val2In - val1In) * 6.0f * valHUeIn);
+ if ((2.0f * valHUeIn) < 1.0f)
+ return (val2In);
+ if ((3.0f * valHUeIn) < 2.0f)
+ return (val1In + (val2In - val1In) * ((2.0f / 3.0f) - valHUeIn) * 6.0f);
+ return (val1In);
}
-void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+void LLColor4::setHSL(F32 hValIn, F32 sValIn, F32 lValIn)
{
- if ( sValIn < 0.00001f )
+ if (sValIn < 0.00001f)
{
- mV[VRED] = lValIn;
+ mV[VRED] = lValIn;
mV[VGREEN] = lValIn;
- mV[VBLUE] = lValIn;
+ mV[VBLUE] = lValIn;
}
else
{
F32 interVal1;
F32 interVal2;
- if ( lValIn < 0.5f )
- interVal2 = lValIn * ( 1.0f + sValIn );
+ if (lValIn < 0.5f)
+ interVal2 = lValIn * (1.0f + sValIn);
else
- interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+ interVal2 = (lValIn + sValIn) - (sValIn * lValIn);
interVal1 = 2.0f * lValIn - interVal2;
- mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
- mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
- mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ mV[VRED] = hueToRgb(interVal1, interVal2, hValIn + (1.f / 3.f));
+ mV[VGREEN] = hueToRgb(interVal1, interVal2, hValIn);
+ mV[VBLUE] = hueToRgb(interVal1, interVal2, hValIn - (1.f / 3.f));
}
}
@@ -341,58 +340,61 @@ void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
F32 var_G = mV[VGREEN];
F32 var_B = mV[VBLUE];
- F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
- F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+ F32 var_Min = (var_R < (var_G < var_B ? var_G : var_B) ? var_R : (var_G < var_B ? var_G : var_B));
+ F32 var_Max = (var_R > (var_G > var_B ? var_G : var_B) ? var_R : (var_G > var_B ? var_G : var_B));
F32 del_Max = var_Max - var_Min;
- F32 L = ( var_Max + var_Min ) / 2.0f;
+ F32 L = (var_Max + var_Min) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
- if ( del_Max == 0.0f )
+ if (del_Max == 0.0f)
{
- H = 0.0f;
- S = 0.0f;
+ H = 0.0f;
+ S = 0.0f;
}
else
{
- if ( L < 0.5 )
- S = del_Max / ( var_Max + var_Min );
+ if (L < 0.5f)
+ S = del_Max / (var_Max + var_Min);
else
- S = del_Max / ( 2.0f - var_Max - var_Min );
+ S = del_Max / (2.0f - var_Max - var_Min);
- F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+ F32 del_R = (((var_Max - var_R) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_G = (((var_Max - var_G) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_B = (((var_Max - var_B) / 6.0f) + (del_Max / 2.0f)) / del_Max;
- if ( var_R >= var_Max )
+ if (var_R >= var_Max)
H = del_B - del_G;
- else
- if ( var_G >= var_Max )
- H = ( 1.0f / 3.0f ) + del_R - del_B;
- else
- if ( var_B >= var_Max )
- H = ( 2.0f / 3.0f ) + del_G - del_R;
+ else if (var_G >= var_Max)
+ H = (1.0f / 3.0f) + del_R - del_B;
+ else if (var_B >= var_Max)
+ H = (2.0f / 3.0f) + del_G - del_R;
- if ( H < 0.0f ) H += 1.0f;
- if ( H > 1.0f ) H -= 1.0f;
+ if (H < 0.0f)
+ H += 1.0f;
+ if (H > 1.0f)
+ H -= 1.0f;
}
- if (hue) *hue = H;
- if (saturation) *saturation = S;
- if (luminance) *luminance = L;
+ if (hue)
+ *hue = H;
+ if (saturation)
+ *saturation = S;
+ if (luminance)
+ *luminance = L;
}
// static
bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
{
- if( buf.empty() || color == nullptr)
+ if (buf.empty() || color == nullptr)
{
return false;
}
- boost_tokenizer tokens(buf, boost::char_separator(", "));
+ boost_tokenizer tokens(buf, boost::char_separator(", "));
boost_tokenizer::iterator token_iter = tokens.begin();
if (token_iter == tokens.end())
{
@@ -401,16 +403,16 @@ bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
// Grab the first token into a string, since we don't know
// if this is a float or a color name.
- std::string color_name( (*token_iter) );
+ std::string color_name((*token_iter));
++token_iter;
if (token_iter != tokens.end())
{
// There are more tokens to read. This must be a vector.
LLColor4 v;
- LLStringUtil::convertToF32( color_name, v.mV[VRED] );
- LLStringUtil::convertToF32( *token_iter, v.mV[VGREEN] );
- v.mV[VBLUE] = 0.0f;
+ LLStringUtil::convertToF32(color_name, v.mV[VRED]);
+ LLStringUtil::convertToF32(*token_iter, v.mV[VGREEN]);
+ v.mV[VBLUE] = 0.0f;
v.mV[VALPHA] = 1.0f;
++token_iter;
@@ -422,283 +424,284 @@ bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
else
{
// There is a z-component.
- LLStringUtil::convertToF32( *token_iter, v.mV[VBLUE] );
+ LLStringUtil::convertToF32(*token_iter, v.mV[VBLUE]);
++token_iter;
if (token_iter != tokens.end())
{
// There is an alpha component.
- LLStringUtil::convertToF32( *token_iter, v.mV[VALPHA] );
+ LLStringUtil::convertToF32(*token_iter, v.mV[VALPHA]);
}
}
// Make sure all values are between 0 and 1.
if (v.mV[VRED] > 1.f || v.mV[VGREEN] > 1.f || v.mV[VBLUE] > 1.f || v.mV[VALPHA] > 1.f)
{
- v = v * (1.f / 255.f);
+ constexpr F32 SCALE{ 1.f / 255.f };
+ v *= SCALE;
}
- color->set( v );
+ color->set(v);
}
else // Single value. Read as a named color.
{
// We have a color name
- if ( "red" == color_name )
+ if ("red" == color_name)
{
color->set(LLColor4::red);
}
- else if ( "red1" == color_name )
+ else if ("red1" == color_name)
{
color->set(LLColor4::red1);
}
- else if ( "red2" == color_name )
+ else if ("red2" == color_name)
{
color->set(LLColor4::red2);
}
- else if ( "red3" == color_name )
+ else if ("red3" == color_name)
{
color->set(LLColor4::red3);
}
- else if ( "red4" == color_name )
+ else if ("red4" == color_name)
{
color->set(LLColor4::red4);
}
- else if ( "red5" == color_name )
+ else if ("red5" == color_name)
{
color->set(LLColor4::red5);
}
- else if( "green" == color_name )
+ else if ("green" == color_name)
{
color->set(LLColor4::green);
}
- else if( "green1" == color_name )
+ else if ("green1" == color_name)
{
color->set(LLColor4::green1);
}
- else if( "green2" == color_name )
+ else if ("green2" == color_name)
{
color->set(LLColor4::green2);
}
- else if( "green3" == color_name )
+ else if ("green3" == color_name)
{
color->set(LLColor4::green3);
}
- else if( "green4" == color_name )
+ else if ("green4" == color_name)
{
color->set(LLColor4::green4);
}
- else if( "green5" == color_name )
+ else if ("green5" == color_name)
{
color->set(LLColor4::green5);
}
- else if( "green6" == color_name )
+ else if ("green6" == color_name)
{
color->set(LLColor4::green6);
}
- else if( "blue" == color_name )
+ else if ("blue" == color_name)
{
color->set(LLColor4::blue);
}
- else if( "blue1" == color_name )
+ else if ("blue1" == color_name)
{
color->set(LLColor4::blue1);
}
- else if( "blue2" == color_name )
+ else if ("blue2" == color_name)
{
color->set(LLColor4::blue2);
}
- else if( "blue3" == color_name )
+ else if ("blue3" == color_name)
{
color->set(LLColor4::blue3);
}
- else if( "blue4" == color_name )
+ else if ("blue4" == color_name)
{
color->set(LLColor4::blue4);
}
- else if( "blue5" == color_name )
+ else if ("blue5" == color_name)
{
color->set(LLColor4::blue5);
}
- else if( "blue6" == color_name )
+ else if ("blue6" == color_name)
{
color->set(LLColor4::blue6);
}
- else if( "black" == color_name )
+ else if ("black" == color_name)
{
color->set(LLColor4::black);
}
- else if( "white" == color_name )
+ else if ("white" == color_name)
{
color->set(LLColor4::white);
}
- else if( "yellow" == color_name )
+ else if ("yellow" == color_name)
{
color->set(LLColor4::yellow);
}
- else if( "yellow1" == color_name )
+ else if ("yellow1" == color_name)
{
color->set(LLColor4::yellow1);
}
- else if( "yellow2" == color_name )
+ else if ("yellow2" == color_name)
{
color->set(LLColor4::yellow2);
}
- else if( "yellow3" == color_name )
+ else if ("yellow3" == color_name)
{
color->set(LLColor4::yellow3);
}
- else if( "yellow4" == color_name )
+ else if ("yellow4" == color_name)
{
color->set(LLColor4::yellow4);
}
- else if( "yellow5" == color_name )
+ else if ("yellow5" == color_name)
{
color->set(LLColor4::yellow5);
}
- else if( "yellow6" == color_name )
+ else if ("yellow6" == color_name)
{
color->set(LLColor4::yellow6);
}
- else if( "magenta" == color_name )
+ else if ("magenta" == color_name)
{
color->set(LLColor4::magenta);
}
- else if( "magenta1" == color_name )
+ else if ("magenta1" == color_name)
{
color->set(LLColor4::magenta1);
}
- else if( "magenta2" == color_name )
+ else if ("magenta2" == color_name)
{
color->set(LLColor4::magenta2);
}
- else if( "magenta3" == color_name )
+ else if ("magenta3" == color_name)
{
color->set(LLColor4::magenta3);
}
- else if( "magenta4" == color_name )
+ else if ("magenta4" == color_name)
{
color->set(LLColor4::magenta4);
}
- else if( "purple" == color_name )
+ else if ("purple" == color_name)
{
color->set(LLColor4::purple);
}
- else if( "purple1" == color_name )
+ else if ("purple1" == color_name)
{
color->set(LLColor4::purple1);
}
- else if( "purple2" == color_name )
+ else if ("purple2" == color_name)
{
color->set(LLColor4::purple2);
}
- else if( "purple3" == color_name )
+ else if ("purple3" == color_name)
{
color->set(LLColor4::purple3);
}
- else if( "purple4" == color_name )
+ else if ("purple4" == color_name)
{
color->set(LLColor4::purple4);
}
- else if( "purple5" == color_name )
+ else if ("purple5" == color_name)
{
color->set(LLColor4::purple5);
}
- else if( "purple6" == color_name )
+ else if ("purple6" == color_name)
{
color->set(LLColor4::purple6);
}
- else if( "pink" == color_name )
+ else if ("pink" == color_name)
{
color->set(LLColor4::pink);
}
- else if( "pink1" == color_name )
+ else if ("pink1" == color_name)
{
color->set(LLColor4::pink1);
}
- else if( "pink2" == color_name )
+ else if ("pink2" == color_name)
{
color->set(LLColor4::pink2);
}
- else if( "cyan" == color_name )
+ else if ("cyan" == color_name)
{
color->set(LLColor4::cyan);
}
- else if( "cyan1" == color_name )
+ else if ("cyan1" == color_name)
{
color->set(LLColor4::cyan1);
}
- else if( "cyan2" == color_name )
+ else if ("cyan2" == color_name)
{
color->set(LLColor4::cyan2);
}
- else if( "cyan3" == color_name )
+ else if ("cyan3" == color_name)
{
color->set(LLColor4::cyan3);
}
- else if( "cyan4" == color_name )
+ else if ("cyan4" == color_name)
{
color->set(LLColor4::cyan4);
}
- else if( "cyan5" == color_name )
+ else if ("cyan5" == color_name)
{
color->set(LLColor4::cyan5);
}
- else if( "cyan6" == color_name )
+ else if ("cyan6" == color_name)
{
color->set(LLColor4::cyan6);
}
- else if( "smoke" == color_name )
+ else if ("smoke" == color_name)
{
color->set(LLColor4::smoke);
}
- else if( "grey" == color_name )
+ else if ("grey" == color_name)
{
color->set(LLColor4::grey);
}
- else if( "grey1" == color_name )
+ else if ("grey1" == color_name)
{
color->set(LLColor4::grey1);
}
- else if( "grey2" == color_name )
+ else if ("grey2" == color_name)
{
color->set(LLColor4::grey2);
}
- else if( "grey3" == color_name )
+ else if ("grey3" == color_name)
{
color->set(LLColor4::grey3);
}
- else if( "grey4" == color_name )
+ else if ("grey4" == color_name)
{
color->set(LLColor4::grey4);
}
- else if( "orange" == color_name )
+ else if ("orange" == color_name)
{
color->set(LLColor4::orange);
}
- else if( "orange1" == color_name )
+ else if ("orange1" == color_name)
{
color->set(LLColor4::orange1);
}
- else if( "orange2" == color_name )
+ else if ("orange2" == color_name)
{
color->set(LLColor4::orange2);
}
- else if( "orange3" == color_name )
+ else if ("orange3" == color_name)
{
color->set(LLColor4::orange3);
}
- else if( "orange4" == color_name )
+ else if ("orange4" == color_name)
{
color->set(LLColor4::orange4);
}
- else if( "orange5" == color_name )
+ else if ("orange5" == color_name)
{
color->set(LLColor4::orange5);
}
- else if( "orange6" == color_name )
+ else if ("orange6" == color_name)
{
color->set(LLColor4::orange6);
}
- else if ( "clear" == color_name )
+ else if ("clear" == color_name)
{
color->set(0.f, 0.f, 0.f, 0.f);
}
@@ -714,21 +717,21 @@ bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
// static
bool LLColor4::parseColor4(const std::string& buf, LLColor4* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
LLColor4 v;
- S32 count = sscanf( buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
- if (1 == count )
+ S32 count = sscanf(buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3);
+ if (1 == count)
{
// try this format
- count = sscanf( buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
+ count = sscanf(buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3);
}
- if( 4 == count )
+ if (4 == count)
{
- value->setVec( v );
+ value->setVec(v);
return true;
}
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 97ffead7a0..d48020c223 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -28,7 +28,6 @@
#define LL_V4COLOR_H
#include "llerror.h"
-//#include "vmath.h"
#include "llmath.h"
#include "llsd.h"
@@ -38,198 +37,198 @@ class LLVector4;
// LLColor4 = |x y z w|
-static const U32 LENGTHOFCOLOR4 = 4;
+static constexpr U32 LENGTHOFCOLOR4 = 4;
-static const U32 MAX_LENGTH_OF_COLOR_NAME = 15; //Give plenty of room for additional colors...
+static constexpr U32 MAX_LENGTH_OF_COLOR_NAME = 15; // Give plenty of room for additional colors...
class LLColor4
{
- public:
- F32 mV[LENGTHOFCOLOR4];
- LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1)
- LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1)
- LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a)
- LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
- explicit LLColor4(const LLSD& sd);
- explicit LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
- explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
- explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
- explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
+public:
+ F32 mV[LENGTHOFCOLOR4];
+ LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1)
+ LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1)
+ LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a)
+ LLColor4(const LLColor3& vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
+ explicit LLColor4(const LLSD& sd);
+ explicit LLColor4(const F32* vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
+ explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
+ explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
+ explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
- LLSD getValue() const
- {
- LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
- ret[3] = mV[3];
- return ret;
- }
+ LLSD getValue() const
+ {
+ LLSD ret;
+ ret[VRED] = mV[VRED];
+ ret[VGREEN] = mV[VGREEN];
+ ret[VBLUE] = mV[VBLUE];
+ ret[VALPHA] = mV[VALPHA];
+ return ret;
+ }
- void setValue(const LLSD& sd);
+ void setValue(const LLSD& sd);
- void setHSL(F32 hue, F32 saturation, F32 luminance);
- void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
+ void setHSL(F32 hue, F32 saturation, F32 luminance);
+ void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
- const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
- const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1)
+ const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
+ const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1)
- const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set()
- const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set()
- const LLColor4& setVec(const LLColor4 &vec); // deprecated -- use set()
- const LLColor4& setVec(const LLColor3 &vec); // deprecated -- use set()
- const LLColor4& setVec(const LLColor3 &vec, F32 a); // deprecated -- use set()
- const LLColor4& setVec(const F32 *vec); // deprecated -- use set()
- const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set()
+ const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set()
+ const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor4& vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor3& vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor3& vec, F32 a); // deprecated -- use set()
+ const LLColor4& setVec(const F32* vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set()
- const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a)
- const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a)
- const LLColor4& set(const LLColor4 &vec); // Sets LLColor4 to vec
- const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
- const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
- const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec
- const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec
- const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a)
+ const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a)
+ const LLColor4& set(const LLColor4& vec); // Sets LLColor4 to vec
+ const LLColor4& set(const LLColor3& vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
+ const LLColor4& set(const LLColor3& vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
+ const LLColor4& set(const F32* vec); // Sets LLColor4 to vec
+ const LLColor4& set(const F64* vec); // Sets LLColor4 to (double)vec
+ const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
- // set from a vector of unknown type and size
- // may leave some data unmodified
- template
- const LLColor4& set(const std::vector& v);
+ // set from a vector of unknown type and size
+ // may leave some data unmodified
+ template
+ const LLColor4& set(const std::vector& v);
- // write to a vector of unknown type and size
- // maye leave some data unmodified
- template
- void write(std::vector& v) const;
+ // write to a vector of unknown type and size
+ // maye leave some data unmodified
+ template
+ void write(std::vector& v) const;
- const LLColor4& setAlpha(F32 a);
+ const LLColor4& setAlpha(F32 a);
- F32 magVec() const; // deprecated -- use length()
- F32 magVecSquared() const; // deprecated -- use lengthSquared()
- F32 normVec(); // deprecated -- use normalize()
+ F32 magVec() const; // deprecated -- use length()
+ F32 magVecSquared() const; // deprecated -- use lengthSquared()
+ F32 normVec(); // deprecated -- use normalize()
- F32 length() const; // Returns magnitude of LLColor4
- F32 lengthSquared() const; // Returns magnitude squared of LLColor4
- F32 normalize(); // deprecated -- use normalize()
+ F32 length() const; // Returns magnitude of LLColor4
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor4
+ F32 normalize(); // deprecated -- use normalize()
- bool isOpaque() { return mV[VALPHA] == 1.f; }
+ bool isOpaque() const { return mV[VALPHA] == 1.f; }
- F32 operator[](int idx) const { return mV[idx]; }
- F32 &operator[](int idx) { return mV[idx]; }
+ F32 operator[](int idx) const { return mV[idx]; }
+ F32& operator[](int idx) { return mV[idx]; }
- const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4
+ const LLColor4& operator=(const LLColor3& a); // Assigns vec3 to vec4 and returns vec4
- bool operator<(const LLColor4& rhs) const;
- friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
- friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
- friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b
- friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b
- friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change)
- friend LLColor4 operator/(const LLColor4 &a, F32 k); // Return rgb divided by scalar k (no alpha change)
- friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change)
- friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change)
- friend LLColor4 operator%(F32 k, const LLColor4 &a); // Return alpha times scaler k (no rgb change)
+ bool operator<(const LLColor4& rhs) const;
+ friend std::ostream& operator<<(std::ostream& s, const LLColor4& a); // Print a
+ friend LLColor4 operator+(const LLColor4& a, const LLColor4& b); // Return vector a + b
+ friend LLColor4 operator-(const LLColor4& a, const LLColor4& b); // Return vector a minus b
+ friend LLColor4 operator*(const LLColor4& a, const LLColor4& b); // Return component wise a * b
+ friend LLColor4 operator*(const LLColor4& a, F32 k); // Return rgb times scaler k (no alpha change)
+ friend LLColor4 operator/(const LLColor4& a, F32 k); // Return rgb divided by scalar k (no alpha change)
+ friend LLColor4 operator*(F32 k, const LLColor4& a); // Return rgb times scaler k (no alpha change)
+ friend LLColor4 operator%(const LLColor4& a, F32 k); // Return alpha times scaler k (no rgb change)
+ friend LLColor4 operator%(F32 k, const LLColor4& a); // Return alpha times scaler k (no rgb change)
- friend bool operator==(const LLColor4 &a, const LLColor4 &b); // Return a == b
- friend bool operator!=(const LLColor4 &a, const LLColor4 &b); // Return a != b
+ friend bool operator==(const LLColor4& a, const LLColor4& b); // Return a == b
+ friend bool operator!=(const LLColor4& a, const LLColor4& b); // Return a != b
- friend bool operator==(const LLColor4 &a, const LLColor3 &b); // Return a == b
- friend bool operator!=(const LLColor4 &a, const LLColor3 &b); // Return a != b
+ friend bool operator==(const LLColor4& a, const LLColor3& b); // Return a == b
+ friend bool operator!=(const LLColor4& a, const LLColor3& b); // Return a != b
- friend const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b); // Return vector a + b
- friend const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b); // Return vector a minus b
- friend const LLColor4& operator*=(LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change)
- friend const LLColor4& operator%=(LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change)
+ friend const LLColor4& operator+=(LLColor4& a, const LLColor4& b); // Return vector a + b
+ friend const LLColor4& operator-=(LLColor4& a, const LLColor4& b); // Return vector a minus b
+ friend const LLColor4& operator*=(LLColor4& a, F32 k); // Return rgb times scaler k (no alpha change)
+ friend const LLColor4& operator%=(LLColor4& a, F32 k); // Return alpha times scaler k (no rgb change)
- friend const LLColor4& operator*=(LLColor4 &a, const LLColor4 &b); // Doesn't multiply alpha! (for lighting)
+ friend const LLColor4& operator*=(LLColor4& a, const LLColor4& b); // Doesn't multiply alpha! (for lighting)
- // conversion
- operator LLColor4U() const;
+ // conversion
+ operator LLColor4U() const;
- // Basic color values.
- static LLColor4 red;
- static LLColor4 green;
- static LLColor4 blue;
- static LLColor4 black;
- static LLColor4 white;
- static LLColor4 yellow;
- static LLColor4 magenta;
- static LLColor4 cyan;
- static LLColor4 smoke;
- static LLColor4 grey;
- static LLColor4 orange;
- static LLColor4 purple;
- static LLColor4 pink;
- static LLColor4 transparent;
+ // Basic color values.
+ static LLColor4 red;
+ static LLColor4 green;
+ static LLColor4 blue;
+ static LLColor4 black;
+ static LLColor4 white;
+ static LLColor4 yellow;
+ static LLColor4 magenta;
+ static LLColor4 cyan;
+ static LLColor4 smoke;
+ static LLColor4 grey;
+ static LLColor4 orange;
+ static LLColor4 purple;
+ static LLColor4 pink;
+ static LLColor4 transparent;
- // Extra color values.
- static LLColor4 grey1;
- static LLColor4 grey2;
- static LLColor4 grey3;
- static LLColor4 grey4;
+ // Extra color values.
+ static LLColor4 grey1;
+ static LLColor4 grey2;
+ static LLColor4 grey3;
+ static LLColor4 grey4;
- static LLColor4 red1;
- static LLColor4 red2;
- static LLColor4 red3;
- static LLColor4 red4;
- static LLColor4 red5;
+ static LLColor4 red1;
+ static LLColor4 red2;
+ static LLColor4 red3;
+ static LLColor4 red4;
+ static LLColor4 red5;
- static LLColor4 green1;
- static LLColor4 green2;
- static LLColor4 green3;
- static LLColor4 green4;
- static LLColor4 green5;
- static LLColor4 green6;
+ static LLColor4 green1;
+ static LLColor4 green2;
+ static LLColor4 green3;
+ static LLColor4 green4;
+ static LLColor4 green5;
+ static LLColor4 green6;
- static LLColor4 blue1;
- static LLColor4 blue2;
- static LLColor4 blue3;
- static LLColor4 blue4;
- static LLColor4 blue5;
- static LLColor4 blue6;
+ static LLColor4 blue1;
+ static LLColor4 blue2;
+ static LLColor4 blue3;
+ static LLColor4 blue4;
+ static LLColor4 blue5;
+ static LLColor4 blue6;
- static LLColor4 yellow1;
- static LLColor4 yellow2;
- static LLColor4 yellow3;
- static LLColor4 yellow4;
- static LLColor4 yellow5;
- static LLColor4 yellow6;
- static LLColor4 yellow7;
- static LLColor4 yellow8;
- static LLColor4 yellow9;
+ static LLColor4 yellow1;
+ static LLColor4 yellow2;
+ static LLColor4 yellow3;
+ static LLColor4 yellow4;
+ static LLColor4 yellow5;
+ static LLColor4 yellow6;
+ static LLColor4 yellow7;
+ static LLColor4 yellow8;
+ static LLColor4 yellow9;
- static LLColor4 orange1;
- static LLColor4 orange2;
- static LLColor4 orange3;
- static LLColor4 orange4;
- static LLColor4 orange5;
- static LLColor4 orange6;
+ static LLColor4 orange1;
+ static LLColor4 orange2;
+ static LLColor4 orange3;
+ static LLColor4 orange4;
+ static LLColor4 orange5;
+ static LLColor4 orange6;
- static LLColor4 magenta1;
- static LLColor4 magenta2;
- static LLColor4 magenta3;
- static LLColor4 magenta4;
+ static LLColor4 magenta1;
+ static LLColor4 magenta2;
+ static LLColor4 magenta3;
+ static LLColor4 magenta4;
- static LLColor4 purple1;
- static LLColor4 purple2;
- static LLColor4 purple3;
- static LLColor4 purple4;
- static LLColor4 purple5;
- static LLColor4 purple6;
+ static LLColor4 purple1;
+ static LLColor4 purple2;
+ static LLColor4 purple3;
+ static LLColor4 purple4;
+ static LLColor4 purple5;
+ static LLColor4 purple6;
- static LLColor4 pink1;
- static LLColor4 pink2;
+ static LLColor4 pink1;
+ static LLColor4 pink2;
- static LLColor4 cyan1;
- static LLColor4 cyan2;
- static LLColor4 cyan3;
- static LLColor4 cyan4;
- static LLColor4 cyan5;
- static LLColor4 cyan6;
+ static LLColor4 cyan1;
+ static LLColor4 cyan2;
+ static LLColor4 cyan3;
+ static LLColor4 cyan4;
+ static LLColor4 cyan5;
+ static LLColor4 cyan6;
- static bool parseColor(const std::string& buf, LLColor4* color);
- static bool parseColor4(const std::string& buf, LLColor4* color);
+ static bool parseColor(const std::string& buf, LLColor4* color);
+ static bool parseColor4(const std::string& buf, LLColor4* color);
- inline void clamp();
+ inline void clamp();
};
static_assert(std::is_trivially_copyable::value, "LLColor4 must be trivial copy");
@@ -237,17 +236,17 @@ static_assert(std::is_trivially_move_assignable::value, "LLColor4 must
static_assert(std::is_standard_layout::value, "LLColor4 must be a standard layout type");
// Non-member functions
-F32 distVec(const LLColor4 &a, const LLColor4 &b); // Returns distance between a and b
-F32 distVec_squared(const LLColor4 &a, const LLColor4 &b); // Returns distance squared between a and b
-LLColor3 vec4to3(const LLColor4 &vec);
-LLColor4 vec3to4(const LLColor3 &vec);
-LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u);
+F32 distVec(const LLColor4& a, const LLColor4& b); // Returns distance between a and b
+F32 distVec_squared(const LLColor4& a, const LLColor4& b); // Returns distance squared between a and b
+LLColor3 vec4to3(const LLColor4& vec);
+LLColor4 vec3to4(const LLColor3& vec);
+LLColor4 lerp(const LLColor4& a, const LLColor4& b, F32 u);
-inline LLColor4::LLColor4(void)
+inline LLColor4::LLColor4()
{
- mV[VRED] = 0.f;
+ mV[VRED] = 0.f;
mV[VGREEN] = 0.f;
- mV[VBLUE] = 0.f;
+ mV[VBLUE] = 0.f;
mV[VALPHA] = 1.f;
}
@@ -258,149 +257,146 @@ inline LLColor4::LLColor4(const LLSD& sd)
inline LLColor4::LLColor4(F32 r, F32 g, F32 b)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
mV[VALPHA] = 1.f;
}
inline LLColor4::LLColor4(F32 r, F32 g, F32 b, F32 a)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
mV[VALPHA] = a;
}
inline LLColor4::LLColor4(U32 clr)
{
- mV[VRED] = (clr&0xff) * (1.0f/255.0f);
- mV[VGREEN] = ((clr>>8)&0xff) * (1.0f/255.0f);
- mV[VBLUE] = ((clr>>16)&0xff) * (1.0f/255.0f);
- mV[VALPHA] = (clr>>24) * (1.0f/255.0f);
+ mV[VRED] = (clr & 0xff) * (1.0f / 255.0f);
+ mV[VGREEN] = ((clr >> 8) & 0xff) * (1.0f / 255.0f);
+ mV[VBLUE] = ((clr >> 16) & 0xff) * (1.0f / 255.0f);
+ mV[VALPHA] = (clr >> 24) * (1.0f / 255.0f);
}
-
-inline LLColor4::LLColor4(const F32 *vec)
+inline LLColor4::LLColor4(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
}
-inline const LLColor4& LLColor4::setToBlack(void)
+inline const LLColor4& LLColor4::setToBlack(void)
{
- mV[VRED] = 0.f;
+ mV[VRED] = 0.f;
mV[VGREEN] = 0.f;
- mV[VBLUE] = 0.f;
+ mV[VBLUE] = 0.f;
mV[VALPHA] = 1.f;
return (*this);
}
-inline const LLColor4& LLColor4::setToWhite(void)
+inline const LLColor4& LLColor4::setToWhite(void)
{
- mV[VRED] = 1.f;
+ mV[VRED] = 1.f;
mV[VGREEN] = 1.f;
- mV[VBLUE] = 1.f;
+ mV[VBLUE] = 1.f;
mV[VALPHA] = 1.f;
return (*this);
}
-inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z)
+inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
-inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a)
+inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
mV[VALPHA] = a;
return (*this);
}
-inline const LLColor4& LLColor4::set(const LLColor4 &vec)
+inline const LLColor4& LLColor4::set(const LLColor4& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = vec.mV[VALPHA];
return (*this);
}
-
-inline const LLColor4& LLColor4::set(const F32 *vec)
+inline const LLColor4& LLColor4::set(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
return (*this);
}
-inline const LLColor4& LLColor4::set(const F64 *vec)
+inline const LLColor4& LLColor4::set(const F64* vec)
{
- mV[VRED] = static_cast(vec[VRED]);
+ mV[VRED] = static_cast(vec[VRED]);
mV[VGREEN] = static_cast(vec[VGREEN]);
- mV[VBLUE] = static_cast(vec[VBLUE]);
+ mV[VBLUE] = static_cast(vec[VBLUE]);
mV[VALPHA] = static_cast(vec[VALPHA]);
return (*this);
}
// deprecated
-inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
+inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
// deprecated
-inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z, F32 a)
+inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z, F32 a)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
mV[VALPHA] = a;
return (*this);
}
// deprecated
-inline const LLColor4& LLColor4::setVec(const LLColor4 &vec)
+inline const LLColor4& LLColor4::setVec(const LLColor4& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = vec.mV[VALPHA];
return (*this);
}
-
// deprecated
-inline const LLColor4& LLColor4::setVec(const F32 *vec)
+inline const LLColor4& LLColor4::setVec(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
return (*this);
}
-inline const LLColor4& LLColor4::setAlpha(F32 a)
+inline const LLColor4& LLColor4::setAlpha(F32 a)
{
mV[VALPHA] = a;
return (*this);
@@ -408,155 +404,116 @@ inline const LLColor4& LLColor4::setAlpha(F32 a)
// LLColor4 Magnitude and Normalization Functions
-inline F32 LLColor4::length(void) const
+inline F32 LLColor4::length() const
{
- return (F32) sqrt(mV[VRED]*mV[VRED] + mV[VGREEN]*mV[VGREEN] + mV[VBLUE]*mV[VBLUE]);
+ return sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
}
-inline F32 LLColor4::lengthSquared(void) const
+inline F32 LLColor4::lengthSquared() const
{
- return mV[VRED]*mV[VRED] + mV[VGREEN]*mV[VGREEN] + mV[VBLUE]*mV[VBLUE];
+ return mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE];
}
-inline F32 LLColor4::normalize(void)
+inline F32 LLColor4::normalize()
{
- F32 mag = (F32) sqrt(mV[VRED]*mV[VRED] + mV[VGREEN]*mV[VGREEN] + mV[VBLUE]*mV[VBLUE]);
+ F32 mag = sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
F32 oomag;
if (mag)
{
- oomag = 1.f/mag;
+ oomag = 1.f / mag;
mV[VRED] *= oomag;
mV[VGREEN] *= oomag;
mV[VBLUE] *= oomag;
}
- return (mag);
+ return mag;
}
// deprecated
-inline F32 LLColor4::magVec(void) const
+inline F32 LLColor4::magVec() const
{
- return (F32) sqrt(mV[VRED]*mV[VRED] + mV[VGREEN]*mV[VGREEN] + mV[VBLUE]*mV[VBLUE]);
+ return sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
}
// deprecated
-inline F32 LLColor4::magVecSquared(void) const
+inline F32 LLColor4::magVecSquared() const
{
- return mV[VRED]*mV[VRED] + mV[VGREEN]*mV[VGREEN] + mV[VBLUE]*mV[VBLUE];
+ return mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE];
}
// deprecated
-inline F32 LLColor4::normVec(void)
+inline F32 LLColor4::normVec()
{
- F32 mag = (F32) sqrt(mV[VRED]*mV[VRED] + mV[VGREEN]*mV[VGREEN] + mV[VBLUE]*mV[VBLUE]);
+ F32 mag = sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
F32 oomag;
if (mag)
{
- oomag = 1.f/mag;
+ oomag = 1.f / mag;
mV[VRED] *= oomag;
mV[VGREEN] *= oomag;
mV[VBLUE] *= oomag;
}
- return (mag);
+ return mag;
}
// LLColor4 Operators
-
-inline LLColor4 operator+(const LLColor4 &a, const LLColor4 &b)
+inline LLColor4 operator+(const LLColor4& a, const LLColor4& b)
{
- return LLColor4(
- a.mV[VRED] + b.mV[VRED],
- a.mV[VGREEN] + b.mV[VGREEN],
- a.mV[VBLUE] + b.mV[VBLUE],
- a.mV[VALPHA] + b.mV[VALPHA]);
+ return LLColor4(a.mV[VRED] + b.mV[VRED], a.mV[VGREEN] + b.mV[VGREEN], a.mV[VBLUE] + b.mV[VBLUE], a.mV[VALPHA] + b.mV[VALPHA]);
}
-inline LLColor4 operator-(const LLColor4 &a, const LLColor4 &b)
+inline LLColor4 operator-(const LLColor4& a, const LLColor4& b)
{
- return LLColor4(
- a.mV[VRED] - b.mV[VRED],
- a.mV[VGREEN] - b.mV[VGREEN],
- a.mV[VBLUE] - b.mV[VBLUE],
- a.mV[VALPHA] - b.mV[VALPHA]);
+ return LLColor4(a.mV[VRED] - b.mV[VRED], a.mV[VGREEN] - b.mV[VGREEN], a.mV[VBLUE] - b.mV[VBLUE], a.mV[VALPHA] - b.mV[VALPHA]);
}
-inline LLColor4 operator*(const LLColor4 &a, const LLColor4 &b)
+inline LLColor4 operator*(const LLColor4& a, const LLColor4& b)
{
- return LLColor4(
- a.mV[VRED] * b.mV[VRED],
- a.mV[VGREEN] * b.mV[VGREEN],
- a.mV[VBLUE] * b.mV[VBLUE],
- a.mV[VALPHA] * b.mV[VALPHA]);
+ return LLColor4(a.mV[VRED] * b.mV[VRED], a.mV[VGREEN] * b.mV[VGREEN], a.mV[VBLUE] * b.mV[VBLUE], a.mV[VALPHA] * b.mV[VALPHA]);
}
-inline LLColor4 operator*(const LLColor4 &a, F32 k)
+inline LLColor4 operator*(const LLColor4& a, F32 k)
{
// only affects rgb (not a!)
- return LLColor4(
- a.mV[VRED] * k,
- a.mV[VGREEN] * k,
- a.mV[VBLUE] * k,
- a.mV[VALPHA]);
+ return LLColor4(a.mV[VRED] * k, a.mV[VGREEN] * k, a.mV[VBLUE] * k, a.mV[VALPHA]);
}
-inline LLColor4 operator/(const LLColor4 &a, F32 k)
+inline LLColor4 operator/(const LLColor4& a, F32 k)
{
- return LLColor4(
- a.mV[VRED] / k,
- a.mV[VGREEN] / k,
- a.mV[VBLUE] / k,
- a.mV[VALPHA]);
+ return LLColor4(a.mV[VRED] / k, a.mV[VGREEN] / k, a.mV[VBLUE] / k, a.mV[VALPHA]);
}
-inline LLColor4 operator*(F32 k, const LLColor4 &a)
+inline LLColor4 operator*(F32 k, const LLColor4& a)
{
// only affects rgb (not a!)
- return LLColor4(
- a.mV[VRED] * k,
- a.mV[VGREEN] * k,
- a.mV[VBLUE] * k,
- a.mV[VALPHA]);
+ return LLColor4(a.mV[VRED] * k, a.mV[VGREEN] * k, a.mV[VBLUE] * k, a.mV[VALPHA]);
}
-inline LLColor4 operator%(F32 k, const LLColor4 &a)
+inline LLColor4 operator%(F32 k, const LLColor4& a)
{
// only affects alpha (not rgb!)
- return LLColor4(
- a.mV[VRED],
- a.mV[VGREEN],
- a.mV[VBLUE],
- a.mV[VALPHA] * k);
+ return LLColor4(a.mV[VRED], a.mV[VGREEN], a.mV[VBLUE], a.mV[VALPHA] * k);
}
-inline LLColor4 operator%(const LLColor4 &a, F32 k)
+inline LLColor4 operator%(const LLColor4& a, F32 k)
{
// only affects alpha (not rgb!)
- return LLColor4(
- a.mV[VRED],
- a.mV[VGREEN],
- a.mV[VBLUE],
- a.mV[VALPHA] * k);
+ return LLColor4(a.mV[VRED], a.mV[VGREEN], a.mV[VBLUE], a.mV[VALPHA] * k);
}
-inline bool operator==(const LLColor4 &a, const LLColor4 &b)
+inline bool operator==(const LLColor4& a, const LLColor4& b)
{
- return ( (a.mV[VRED] == b.mV[VRED])
- &&(a.mV[VGREEN] == b.mV[VGREEN])
- &&(a.mV[VBLUE] == b.mV[VBLUE])
- &&(a.mV[VALPHA] == b.mV[VALPHA]));
+ return ((a.mV[VRED] == b.mV[VRED]) && (a.mV[VGREEN] == b.mV[VGREEN]) && (a.mV[VBLUE] == b.mV[VBLUE]) && (a.mV[VALPHA] == b.mV[VALPHA]));
}
-inline bool operator!=(const LLColor4 &a, const LLColor4 &b)
+inline bool operator!=(const LLColor4& a, const LLColor4& b)
{
- return ( (a.mV[VRED] != b.mV[VRED])
- ||(a.mV[VGREEN] != b.mV[VGREEN])
- ||(a.mV[VBLUE] != b.mV[VBLUE])
- ||(a.mV[VALPHA] != b.mV[VALPHA]));
+ return ((a.mV[VRED] != b.mV[VRED]) || (a.mV[VGREEN] != b.mV[VGREEN]) || (a.mV[VBLUE] != b.mV[VBLUE]) || (a.mV[VALPHA] != b.mV[VALPHA]));
}
-inline const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b)
+inline const LLColor4& operator+=(LLColor4& a, const LLColor4& b)
{
a.mV[VRED] += b.mV[VRED];
a.mV[VGREEN] += b.mV[VGREEN];
@@ -565,7 +522,7 @@ inline const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b)
return a;
}
-inline const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b)
+inline const LLColor4& operator-=(LLColor4& a, const LLColor4& b)
{
a.mV[VRED] -= b.mV[VRED];
a.mV[VGREEN] -= b.mV[VGREEN];
@@ -574,7 +531,7 @@ inline const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b)
return a;
}
-inline const LLColor4& operator*=(LLColor4 &a, F32 k)
+inline const LLColor4& operator*=(LLColor4& a, F32 k)
{
// only affects rgb (not a!)
a.mV[VRED] *= k;
@@ -583,121 +540,120 @@ inline const LLColor4& operator*=(LLColor4 &a, F32 k)
return a;
}
-inline const LLColor4& operator *=(LLColor4 &a, const LLColor4 &b)
+inline const LLColor4& operator*=(LLColor4& a, const LLColor4& b)
{
a.mV[VRED] *= b.mV[VRED];
a.mV[VGREEN] *= b.mV[VGREEN];
a.mV[VBLUE] *= b.mV[VBLUE];
-// a.mV[VALPHA] *= b.mV[VALPHA];
+ // a.mV[VALPHA] *= b.mV[VALPHA];
return a;
}
-inline const LLColor4& operator%=(LLColor4 &a, F32 k)
+inline const LLColor4& operator%=(LLColor4& a, F32 k)
{
// only affects alpha (not rgb!)
a.mV[VALPHA] *= k;
return a;
}
-
// Non-member functions
-inline F32 distVec(const LLColor4 &a, const LLColor4 &b)
+inline F32 distVec(const LLColor4& a, const LLColor4& b)
{
LLColor4 vec = a - b;
- return (vec.length());
+ return vec.length();
}
-inline F32 distVec_squared(const LLColor4 &a, const LLColor4 &b)
+inline F32 distVec_squared(const LLColor4& a, const LLColor4& b)
{
LLColor4 vec = a - b;
- return (vec.lengthSquared());
+ return vec.lengthSquared();
}
-inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u)
+inline LLColor4 lerp(const LLColor4& a, const LLColor4& b, F32 u)
{
- return LLColor4(
- a.mV[VRED] + (b.mV[VRED] - a.mV[VRED]) * u,
- a.mV[VGREEN] + (b.mV[VGREEN] - a.mV[VGREEN]) * u,
- a.mV[VBLUE] + (b.mV[VBLUE] - a.mV[VBLUE]) * u,
- a.mV[VALPHA] + (b.mV[VALPHA] - a.mV[VALPHA]) * u);
+ return LLColor4(a.mV[VRED] + (b.mV[VRED] - a.mV[VRED]) * u,
+ a.mV[VGREEN] + (b.mV[VGREEN] - a.mV[VGREEN]) * u,
+ a.mV[VBLUE] + (b.mV[VBLUE] - a.mV[VBLUE]) * u,
+ a.mV[VALPHA] + (b.mV[VALPHA] - a.mV[VALPHA]) * u);
}
inline bool LLColor4::operator<(const LLColor4& rhs) const
{
- if (mV[0] != rhs.mV[0])
+ if (mV[VRED] != rhs.mV[VRED])
{
- return mV[0] < rhs.mV[0];
+ return mV[VRED] < rhs.mV[VRED];
}
- if (mV[1] != rhs.mV[1])
+ if (mV[VGREEN] != rhs.mV[VGREEN])
{
- return mV[1] < rhs.mV[1];
+ return mV[VGREEN] < rhs.mV[VGREEN];
}
- if (mV[2] != rhs.mV[2])
+ if (mV[VBLUE] != rhs.mV[VBLUE])
{
- return mV[2] < rhs.mV[2];
+ return mV[VBLUE] < rhs.mV[VBLUE];
}
- return mV[3] < rhs.mV[3];
+ return mV[VALPHA] < rhs.mV[VALPHA];
}
void LLColor4::clamp()
{
// Clamp the color...
- if (mV[0] < 0.f)
+ if (mV[VRED] < 0.f)
{
- mV[0] = 0.f;
+ mV[VRED] = 0.f;
}
- else if (mV[0] > 1.f)
+ else if (mV[VRED] > 1.f)
{
- mV[0] = 1.f;
+ mV[VRED] = 1.f;
}
- if (mV[1] < 0.f)
+ if (mV[VGREEN] < 0.f)
{
- mV[1] = 0.f;
+ mV[VGREEN] = 0.f;
}
- else if (mV[1] > 1.f)
+ else if (mV[VGREEN] > 1.f)
{
- mV[1] = 1.f;
+ mV[VGREEN] = 1.f;
}
- if (mV[2] < 0.f)
+ if (mV[VBLUE] < 0.f)
{
- mV[2] = 0.f;
+ mV[VBLUE] = 0.f;
}
- else if (mV[2] > 1.f)
+ else if (mV[VBLUE] > 1.f)
{
- mV[2] = 1.f;
+ mV[VBLUE] = 1.f;
}
- if (mV[3] < 0.f)
+ if (mV[VALPHA] < 0.f)
{
- mV[3] = 0.f;
+ mV[VALPHA] = 0.f;
}
- else if (mV[3] > 1.f)
+ else if (mV[VALPHA] > 1.f)
{
- mV[3] = 1.f;
+ mV[VALPHA] = 1.f;
}
}
// Return the given linear space color value in gamma corrected (sRGB) space
-inline const LLColor4 srgbColor4(const LLColor4 &a) {
+inline const LLColor4 srgbColor4(const LLColor4& a)
+{
LLColor4 srgbColor;
- srgbColor.mV[0] = linearTosRGB(a.mV[0]);
- srgbColor.mV[1] = linearTosRGB(a.mV[1]);
- srgbColor.mV[2] = linearTosRGB(a.mV[2]);
- srgbColor.mV[3] = a.mV[3];
+ srgbColor.mV[VRED] = linearTosRGB(a.mV[VRED]);
+ srgbColor.mV[VGREEN] = linearTosRGB(a.mV[VGREEN]);
+ srgbColor.mV[VBLUE] = linearTosRGB(a.mV[VBLUE]);
+ srgbColor.mV[VALPHA] = a.mV[VALPHA];
return srgbColor;
}
// Return the given gamma corrected (sRGB) color in linear space
-inline const LLColor4 linearColor4(const LLColor4 &a)
+inline const LLColor4 linearColor4(const LLColor4& a)
{
LLColor4 linearColor;
- linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
- linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
- linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
- linearColor.mV[3] = a.mV[3];
+ linearColor.mV[VRED] = sRGBtoLinear(a.mV[VRED]);
+ linearColor.mV[VGREEN] = sRGBtoLinear(a.mV[VGREEN]);
+ linearColor.mV[VBLUE] = sRGBtoLinear(a.mV[VBLUE]);
+ linearColor.mV[VALPHA] = a.mV[VALPHA];
return linearColor;
}
@@ -723,4 +679,3 @@ void LLColor4::write(std::vector& v) const
}
#endif
-
diff --git a/indra/llmath/v4coloru.cpp b/indra/llmath/v4coloru.cpp
index acf349245a..c495ffdb4c 100644
--- a/indra/llmath/v4coloru.cpp
+++ b/indra/llmath/v4coloru.cpp
@@ -26,10 +26,7 @@
#include "linden_common.h"
-//#include "v3coloru.h"
#include "v4coloru.h"
-#include "v4color.h"
-//#include "vmath.h"
#include "llmath.h"
// LLColor4U
@@ -39,49 +36,7 @@ LLColor4U LLColor4U::red (255, 0, 0, 255);
LLColor4U LLColor4U::green( 0, 255, 0, 255);
LLColor4U LLColor4U::blue ( 0, 0, 255, 255);
-// conversion
-/* inlined to fix gcc compile link error
-LLColor4U::operator LLColor4()
-{
- return(LLColor4((F32)mV[VRED]/255.f,(F32)mV[VGREEN]/255.f,(F32)mV[VBLUE]/255.f,(F32)mV[VALPHA]/255.f));
-}
-*/
-
-// Constructors
-
-
-/*
-LLColor4U::LLColor4U(const LLColor3 &vec)
-{
- mV[VRED] = vec.mV[VRED];
- mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
- mV[VALPHA] = 255;
-}
-*/
-
-
-// Clear and Assignment Functions
-
-
-
-// LLColor4U Operators
-
-/*
-LLColor4U LLColor4U::operator=(const LLColor3 &a)
-{
- mV[VRED] = a.mV[VRED];
- mV[VGREEN] = a.mV[VGREEN];
- mV[VBLUE] = a.mV[VBLUE];
-
-// converting from an rgb sets a=1 (opaque)
- mV[VALPHA] = 255;
- return (*this);
-}
-*/
-
-
-std::ostream& operator<<(std::ostream& s, const LLColor4U &a)
+std::ostream& operator<<(std::ostream& s, const LLColor4U& a)
{
s << "{ " << (S32)a.mV[VRED] << ", " << (S32)a.mV[VGREEN] << ", " << (S32)a.mV[VBLUE] << ", " << (S32)a.mV[VALPHA] << " }";
return s;
@@ -90,31 +45,31 @@ std::ostream& operator<<(std::ostream& s, const LLColor4U &a)
// static
bool LLColor4U::parseColor4U(const std::string& buf, LLColor4U* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
- U32 v[4];
- S32 count = sscanf( buf.c_str(), "%u, %u, %u, %u", v + 0, v + 1, v + 2, v + 3 );
- if (1 == count )
+ U32 v[4]{};
+ S32 count = sscanf(buf.c_str(), "%u, %u, %u, %u", v + 0, v + 1, v + 2, v + 3);
+ if (1 == count)
{
// try this format
- count = sscanf( buf.c_str(), "%u %u %u %u", v + 0, v + 1, v + 2, v + 3 );
+ count = sscanf(buf.c_str(), "%u %u %u %u", v + 0, v + 1, v + 2, v + 3);
}
- if( 4 != count )
+ if (4 != count)
{
return false;
}
- for( S32 i = 0; i < 4; i++ )
+ for (S32 i = 0; i < 4; i++)
{
- if( v[i] > U8_MAX )
+ if (v[i] > U8_MAX)
{
return false;
}
}
- value->set( U8(v[0]), U8(v[1]), U8(v[2]), U8(v[3]) );
+ value->set(U8(v[VRED]), U8(v[VGREEN]), U8(v[VBLUE]), U8(v[VALPHA]));
return true;
}
diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h
index e17db7704a..e495fd3eea 100644
--- a/indra/llmath/v4coloru.h
+++ b/indra/llmath/v4coloru.h
@@ -28,104 +28,93 @@
#define LL_V4COLORU_H
#include "llerror.h"
-//#include "vmath.h"
#include "llmath.h"
-//#include "v4color.h"
#include "v3color.h"
#include "v4color.h"
-//class LLColor3U;
class LLColor4;
// LLColor4U = | red green blue alpha |
-static const U32 LENGTHOFCOLOR4U = 4;
-
+static constexpr U32 LENGTHOFCOLOR4U = 4;
class LLColor4U
{
public:
-
U8 mV[LENGTHOFCOLOR4U];
- LLColor4U(); // Initializes LLColor4U to (0, 0, 0, 1)
- LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1)
- LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a)
- LLColor4U(const U8 *vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1)
- explicit LLColor4U(const LLSD& sd)
- {
- setValue(sd);
- }
+ LLColor4U(); // Initializes LLColor4U to (0, 0, 0, 1)
+ LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1)
+ LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a)
+ LLColor4U(const U8* vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1)
+ explicit LLColor4U(const LLSD& sd) { setValue(sd); }
void setValue(const LLSD& sd)
{
- mV[0] = sd[0].asInteger();
- mV[1] = sd[1].asInteger();
- mV[2] = sd[2].asInteger();
- mV[3] = sd[3].asInteger();
+ mV[VRED] = sd[VRED].asInteger();
+ mV[VGREEN] = sd[VGREEN].asInteger();
+ mV[VBLUE] = sd[VBLUE].asInteger();
+ mV[VALPHA] = sd[VALPHA].asInteger();
}
LLSD getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
- ret[3] = mV[3];
+ ret[VRED] = mV[VRED];
+ ret[VGREEN] = mV[VGREEN];
+ ret[VBLUE] = mV[VBLUE];
+ ret[VALPHA] = mV[VALPHA];
return ret;
}
- const LLColor4U& setToBlack(); // zero LLColor4U to (0, 0, 0, 1)
- const LLColor4U& setToWhite(); // zero LLColor4U to (0, 0, 0, 1)
+ const LLColor4U& setToBlack(); // zero LLColor4U to (0, 0, 0, 1)
+ const LLColor4U& setToWhite(); // zero LLColor4U to (0, 0, 0, 1)
- const LLColor4U& set(U8 r, U8 g, U8 b, U8 a);// Sets LLColor4U to (r, g, b, a)
- const LLColor4U& set(U8 r, U8 g, U8 b); // Sets LLColor4U to (r, g, b) (no change in a)
- const LLColor4U& set(const LLColor4U &vec); // Sets LLColor4U to vec
- const LLColor4U& set(const U8 *vec); // Sets LLColor4U to vec
+ const LLColor4U& set(U8 r, U8 g, U8 b, U8 a); // Sets LLColor4U to (r, g, b, a)
+ const LLColor4U& set(U8 r, U8 g, U8 b); // Sets LLColor4U to (r, g, b) (no change in a)
+ const LLColor4U& set(const LLColor4U& vec); // Sets LLColor4U to vec
+ const LLColor4U& set(const U8* vec); // Sets LLColor4U to vec
- const LLColor4U& setVec(U8 r, U8 g, U8 b, U8 a); // deprecated -- use set()
- const LLColor4U& setVec(U8 r, U8 g, U8 b); // deprecated -- use set()
- const LLColor4U& setVec(const LLColor4U &vec); // deprecated -- use set()
- const LLColor4U& setVec(const U8 *vec); // deprecated -- use set()
+ const LLColor4U& setVec(U8 r, U8 g, U8 b, U8 a); // deprecated -- use set()
+ const LLColor4U& setVec(U8 r, U8 g, U8 b); // deprecated -- use set()
+ const LLColor4U& setVec(const LLColor4U& vec); // deprecated -- use set()
+ const LLColor4U& setVec(const U8* vec); // deprecated -- use set()
- const LLColor4U& setAlpha(U8 a);
+ const LLColor4U& setAlpha(U8 a);
- F32 magVec() const; // deprecated -- use length()
- F32 magVecSquared() const; // deprecated -- use lengthSquared()
+ F32 magVec() const; // deprecated -- use length()
+ F32 magVecSquared() const; // deprecated -- use lengthSquared()
- F32 length() const; // Returns magnitude squared of LLColor4U
- F32 lengthSquared() const; // Returns magnitude squared of LLColor4U
+ F32 length() const; // Returns magnitude squared of LLColor4U
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor4U
- friend std::ostream& operator<<(std::ostream& s, const LLColor4U &a); // Print a
- friend LLColor4U operator+(const LLColor4U &a, const LLColor4U &b); // Return vector a + b
- friend LLColor4U operator-(const LLColor4U &a, const LLColor4U &b); // Return vector a minus b
- friend LLColor4U operator*(const LLColor4U &a, const LLColor4U &b); // Return a * b
- friend bool operator==(const LLColor4U &a, const LLColor4U &b); // Return a == b
- friend bool operator!=(const LLColor4U &a, const LLColor4U &b); // Return a != b
+ friend std::ostream& operator<<(std::ostream& s, const LLColor4U& a); // Print a
+ friend LLColor4U operator+(const LLColor4U& a, const LLColor4U& b); // Return vector a + b
+ friend LLColor4U operator-(const LLColor4U& a, const LLColor4U& b); // Return vector a minus b
+ friend LLColor4U operator*(const LLColor4U& a, const LLColor4U& b); // Return a * b
+ friend bool operator==(const LLColor4U& a, const LLColor4U& b); // Return a == b
+ friend bool operator!=(const LLColor4U& a, const LLColor4U& b); // Return a != b
- friend const LLColor4U& operator+=(LLColor4U &a, const LLColor4U &b); // Return vector a + b
- friend const LLColor4U& operator-=(LLColor4U &a, const LLColor4U &b); // Return vector a minus b
- friend const LLColor4U& operator*=(LLColor4U &a, U8 k); // Return rgb times scaler k (no alpha change)
- friend const LLColor4U& operator%=(LLColor4U &a, U8 k); // Return alpha times scaler k (no rgb change)
+ friend const LLColor4U& operator+=(LLColor4U& a, const LLColor4U& b); // Return vector a + b
+ friend const LLColor4U& operator-=(LLColor4U& a, const LLColor4U& b); // Return vector a minus b
+ friend const LLColor4U& operator*=(LLColor4U& a, U8 k); // Return rgb times scaler k (no alpha change)
+ friend const LLColor4U& operator%=(LLColor4U& a, U8 k); // Return alpha times scaler k (no rgb change)
- LLColor4U addClampMax(const LLColor4U &color); // Add and clamp the max
+ LLColor4U addClampMax(const LLColor4U& color); // Add and clamp the max
- LLColor4U multAll(const F32 k); // Multiply ALL channels by scalar k
+ LLColor4U multAll(const F32 k); // Multiply ALL channels by scalar k
- inline void setVecScaleClamp(const LLColor3 &color);
- inline void setVecScaleClamp(const LLColor4 &color);
+ inline void setVecScaleClamp(const LLColor3& color);
+ inline void setVecScaleClamp(const LLColor4& color);
static bool parseColor4U(const std::string& buf, LLColor4U* value);
// conversion
- operator LLColor4() const
- {
- return LLColor4(*this);
- }
+ operator LLColor4() const { return LLColor4(*this); }
- U32 asRGBA() const;
- void fromRGBA( U32 aVal );
+ U32 asRGBA() const;
+ void fromRGBA(U32 aVal);
static LLColor4U white;
static LLColor4U black;
@@ -139,102 +128,94 @@ static_assert(std::is_trivially_move_assignable::value, "LLColor4U mu
static_assert(std::is_standard_layout::value, "LLColor4U must be a standard layout type");
// Non-member functions
-F32 distVec(const LLColor4U &a, const LLColor4U &b); // Returns distance between a and b
-F32 distVec_squared(const LLColor4U &a, const LLColor4U &b); // Returns distance squared between a and b
-
+F32 distVec(const LLColor4U& a, const LLColor4U& b); // Returns distance between a and b
+F32 distVec_squared(const LLColor4U& a, const LLColor4U& b); // Returns distance squared between a and b
inline LLColor4U::LLColor4U()
{
- mV[VRED] = 0;
+ mV[VRED] = 0;
mV[VGREEN] = 0;
- mV[VBLUE] = 0;
+ mV[VBLUE] = 0;
mV[VALPHA] = 255;
}
inline LLColor4U::LLColor4U(U8 r, U8 g, U8 b)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
mV[VALPHA] = 255;
}
inline LLColor4U::LLColor4U(U8 r, U8 g, U8 b, U8 a)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
mV[VALPHA] = a;
}
-inline LLColor4U::LLColor4U(const U8 *vec)
+inline LLColor4U::LLColor4U(const U8* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
}
-/*
-inline LLColor4U::operator LLColor4()
-{
- return(LLColor4((F32)mV[VRED]/255.f,(F32)mV[VGREEN]/255.f,(F32)mV[VBLUE]/255.f,(F32)mV[VALPHA]/255.f));
-}
-*/
-
inline const LLColor4U& LLColor4U::setToBlack(void)
{
- mV[VRED] = 0;
+ mV[VRED] = 0;
mV[VGREEN] = 0;
- mV[VBLUE] = 0;
+ mV[VBLUE] = 0;
mV[VALPHA] = 255;
return (*this);
}
inline const LLColor4U& LLColor4U::setToWhite(void)
{
- mV[VRED] = 255;
+ mV[VRED] = 255;
mV[VGREEN] = 255;
- mV[VBLUE] = 255;
+ mV[VBLUE] = 255;
mV[VALPHA] = 255;
return (*this);
}
inline const LLColor4U& LLColor4U::set(const U8 x, const U8 y, const U8 z)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
-// no change to alpha!
-// mV[VALPHA] = 255;
+ // no change to alpha!
+ // mV[VALPHA] = 255;
return (*this);
}
inline const LLColor4U& LLColor4U::set(const U8 r, const U8 g, const U8 b, U8 a)
{
- mV[0] = r;
- mV[1] = g;
- mV[2] = b;
- mV[3] = a;
+ mV[VRED] = r;
+ mV[VGREEN] = g;
+ mV[VBLUE] = b;
+ mV[VALPHA] = a;
return (*this);
}
-inline const LLColor4U& LLColor4U::set(const LLColor4U &vec)
+inline const LLColor4U& LLColor4U::set(const LLColor4U& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = vec.mV[VALPHA];
return (*this);
}
-inline const LLColor4U& LLColor4U::set(const U8 *vec)
+inline const LLColor4U& LLColor4U::set(const U8* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
return (*this);
}
@@ -242,12 +223,12 @@ inline const LLColor4U& LLColor4U::set(const U8 *vec)
// deprecated
inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
-// no change to alpha!
-// mV[VALPHA] = 255;
+ // no change to alpha!
+ // mV[VALPHA] = 255;
return (*this);
}
@@ -255,29 +236,29 @@ inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z)
// deprecated
inline const LLColor4U& LLColor4U::setVec(const U8 r, const U8 g, const U8 b, U8 a)
{
- mV[0] = r;
- mV[1] = g;
- mV[2] = b;
- mV[3] = a;
+ mV[VRED] = r;
+ mV[VGREEN] = g;
+ mV[VBLUE] = b;
+ mV[VALPHA] = a;
return (*this);
}
// deprecated
-inline const LLColor4U& LLColor4U::setVec(const LLColor4U &vec)
+inline const LLColor4U& LLColor4U::setVec(const LLColor4U& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = vec.mV[VALPHA];
return (*this);
}
// deprecated
-inline const LLColor4U& LLColor4U::setVec(const U8 *vec)
+inline const LLColor4U& LLColor4U::setVec(const U8* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
return (*this);
}
@@ -290,131 +271,68 @@ inline const LLColor4U& LLColor4U::setAlpha(U8 a)
// LLColor4U Magnitude and Normalization Functions
-inline F32 LLColor4U::length(void) const
+inline F32 LLColor4U::length() const
{
- return (F32) sqrt( ((F32)mV[VRED]) * mV[VRED] + ((F32)mV[VGREEN]) * mV[VGREEN] + ((F32)mV[VBLUE]) * mV[VBLUE] );
+ return sqrt(((F32)mV[VRED]) * mV[VRED] + ((F32)mV[VGREEN]) * mV[VGREEN] + ((F32)mV[VBLUE]) * mV[VBLUE]);
}
-inline F32 LLColor4U::lengthSquared(void) const
+inline F32 LLColor4U::lengthSquared() const
{
return ((F32)mV[VRED]) * mV[VRED] + ((F32)mV[VGREEN]) * mV[VGREEN] + ((F32)mV[VBLUE]) * mV[VBLUE];
}
// deprecated
-inline F32 LLColor4U::magVec(void) const
+inline F32 LLColor4U::magVec() const
{
- return (F32) sqrt( ((F32)mV[VRED]) * mV[VRED] + ((F32)mV[VGREEN]) * mV[VGREEN] + ((F32)mV[VBLUE]) * mV[VBLUE] );
+ return sqrt(((F32)mV[VRED]) * mV[VRED] + ((F32)mV[VGREEN]) * mV[VGREEN] + ((F32)mV[VBLUE]) * mV[VBLUE]);
}
// deprecated
-inline F32 LLColor4U::magVecSquared(void) const
+inline F32 LLColor4U::magVecSquared() const
{
return ((F32)mV[VRED]) * mV[VRED] + ((F32)mV[VGREEN]) * mV[VGREEN] + ((F32)mV[VBLUE]) * mV[VBLUE];
}
-inline LLColor4U operator+(const LLColor4U &a, const LLColor4U &b)
+inline LLColor4U operator+(const LLColor4U& a, const LLColor4U& b)
{
- return LLColor4U(
- a.mV[VRED] + b.mV[VRED],
- a.mV[VGREEN] + b.mV[VGREEN],
- a.mV[VBLUE] + b.mV[VBLUE],
- a.mV[VALPHA] + b.mV[VALPHA]);
+ return LLColor4U(a.mV[VRED] + b.mV[VRED], a.mV[VGREEN] + b.mV[VGREEN], a.mV[VBLUE] + b.mV[VBLUE], a.mV[VALPHA] + b.mV[VALPHA]);
}
-inline LLColor4U operator-(const LLColor4U &a, const LLColor4U &b)
+inline LLColor4U operator-(const LLColor4U& a, const LLColor4U& b)
{
- return LLColor4U(
- a.mV[VRED] - b.mV[VRED],
- a.mV[VGREEN] - b.mV[VGREEN],
- a.mV[VBLUE] - b.mV[VBLUE],
- a.mV[VALPHA] - b.mV[VALPHA]);
+ return LLColor4U(a.mV[VRED] - b.mV[VRED], a.mV[VGREEN] - b.mV[VGREEN], a.mV[VBLUE] - b.mV[VBLUE], a.mV[VALPHA] - b.mV[VALPHA]);
}
-inline LLColor4U operator*(const LLColor4U &a, const LLColor4U &b)
+inline LLColor4U operator*(const LLColor4U& a, const LLColor4U& b)
{
- return LLColor4U(
- a.mV[VRED] * b.mV[VRED],
- a.mV[VGREEN] * b.mV[VGREEN],
- a.mV[VBLUE] * b.mV[VBLUE],
- a.mV[VALPHA] * b.mV[VALPHA]);
+ return LLColor4U(a.mV[VRED] * b.mV[VRED], a.mV[VGREEN] * b.mV[VGREEN], a.mV[VBLUE] * b.mV[VBLUE], a.mV[VALPHA] * b.mV[VALPHA]);
}
-inline LLColor4U LLColor4U::addClampMax(const LLColor4U &color)
+inline LLColor4U LLColor4U::addClampMax(const LLColor4U& color)
{
return LLColor4U(llmin((S32)mV[VRED] + color.mV[VRED], 255),
- llmin((S32)mV[VGREEN] + color.mV[VGREEN], 255),
- llmin((S32)mV[VBLUE] + color.mV[VBLUE], 255),
- llmin((S32)mV[VALPHA] + color.mV[VALPHA], 255));
+ llmin((S32)mV[VGREEN] + color.mV[VGREEN], 255),
+ llmin((S32)mV[VBLUE] + color.mV[VBLUE], 255),
+ llmin((S32)mV[VALPHA] + color.mV[VALPHA], 255));
}
inline LLColor4U LLColor4U::multAll(const F32 k)
{
// Round to nearest
- return LLColor4U(
- (U8)ll_round(mV[VRED] * k),
- (U8)ll_round(mV[VGREEN] * k),
- (U8)ll_round(mV[VBLUE] * k),
- (U8)ll_round(mV[VALPHA] * k));
-}
-/*
-inline LLColor4U operator*(const LLColor4U &a, U8 k)
-{
- // only affects rgb (not a!)
- return LLColor4U(
- a.mV[VRED] * k,
- a.mV[VGREEN] * k,
- a.mV[VBLUE] * k,
- a.mV[VALPHA]);
+ return LLColor4U((U8)ll_round(mV[VRED] * k), (U8)ll_round(mV[VGREEN] * k), (U8)ll_round(mV[VBLUE] * k), (U8)ll_round(mV[VALPHA] * k));
}
-inline LLColor4U operator*(U8 k, const LLColor4U &a)
+inline bool operator==(const LLColor4U& a, const LLColor4U& b)
{
- // only affects rgb (not a!)
- return LLColor4U(
- a.mV[VRED] * k,
- a.mV[VGREEN] * k,
- a.mV[VBLUE] * k,
- a.mV[VALPHA]);
+ return ((a.mV[VRED] == b.mV[VRED]) && (a.mV[VGREEN] == b.mV[VGREEN]) && (a.mV[VBLUE] == b.mV[VBLUE]) && (a.mV[VALPHA] == b.mV[VALPHA]));
}
-inline LLColor4U operator%(U8 k, const LLColor4U &a)
+inline bool operator!=(const LLColor4U& a, const LLColor4U& b)
{
- // only affects alpha (not rgb!)
- return LLColor4U(
- a.mV[VRED],
- a.mV[VGREEN],
- a.mV[VBLUE],
- a.mV[VALPHA] * k );
+ return ((a.mV[VRED] != b.mV[VRED]) || (a.mV[VGREEN] != b.mV[VGREEN]) || (a.mV[VBLUE] != b.mV[VBLUE]) || (a.mV[VALPHA] != b.mV[VALPHA]));
}
-inline LLColor4U operator%(const LLColor4U &a, U8 k)
-{
- // only affects alpha (not rgb!)
- return LLColor4U(
- a.mV[VRED],
- a.mV[VGREEN],
- a.mV[VBLUE],
- a.mV[VALPHA] * k );
-}
-*/
-
-inline bool operator==(const LLColor4U &a, const LLColor4U &b)
-{
- return ( (a.mV[VRED] == b.mV[VRED])
- &&(a.mV[VGREEN] == b.mV[VGREEN])
- &&(a.mV[VBLUE] == b.mV[VBLUE])
- &&(a.mV[VALPHA] == b.mV[VALPHA]));
-}
-
-inline bool operator!=(const LLColor4U &a, const LLColor4U &b)
-{
- return ( (a.mV[VRED] != b.mV[VRED])
- ||(a.mV[VGREEN] != b.mV[VGREEN])
- ||(a.mV[VBLUE] != b.mV[VBLUE])
- ||(a.mV[VALPHA] != b.mV[VALPHA]));
-}
-
-inline const LLColor4U& operator+=(LLColor4U &a, const LLColor4U &b)
+inline const LLColor4U& operator+=(LLColor4U& a, const LLColor4U& b)
{
a.mV[VRED] += b.mV[VRED];
a.mV[VGREEN] += b.mV[VGREEN];
@@ -423,7 +341,7 @@ inline const LLColor4U& operator+=(LLColor4U &a, const LLColor4U &b)
return a;
}
-inline const LLColor4U& operator-=(LLColor4U &a, const LLColor4U &b)
+inline const LLColor4U& operator-=(LLColor4U& a, const LLColor4U& b)
{
a.mV[VRED] -= b.mV[VRED];
a.mV[VGREEN] -= b.mV[VGREEN];
@@ -432,7 +350,7 @@ inline const LLColor4U& operator-=(LLColor4U &a, const LLColor4U &b)
return a;
}
-inline const LLColor4U& operator*=(LLColor4U &a, U8 k)
+inline const LLColor4U& operator*=(LLColor4U& a, U8 k)
{
// only affects rgb (not a!)
a.mV[VRED] *= k;
@@ -441,20 +359,20 @@ inline const LLColor4U& operator*=(LLColor4U &a, U8 k)
return a;
}
-inline const LLColor4U& operator%=(LLColor4U &a, U8 k)
+inline const LLColor4U& operator%=(LLColor4U& a, U8 k)
{
// only affects alpha (not rgb!)
a.mV[VALPHA] *= k;
return a;
}
-inline F32 distVec(const LLColor4U &a, const LLColor4U &b)
+inline F32 distVec(const LLColor4U& a, const LLColor4U& b)
{
LLColor4U vec = a - b;
return (vec.length());
}
-inline F32 distVec_squared(const LLColor4U &a, const LLColor4U &b)
+inline F32 distVec_squared(const LLColor4U& a, const LLColor4U& b)
{
LLColor4U vec = a - b;
return (vec.lengthSquared());
@@ -463,13 +381,13 @@ inline F32 distVec_squared(const LLColor4U &a, const LLColor4U &b)
void LLColor4U::setVecScaleClamp(const LLColor4& color)
{
F32 color_scale_factor = 255.f;
- F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]);
+ F32 max_color = llmax(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]);
if (max_color > 1.f)
{
color_scale_factor /= max_color;
}
- const S32 MAX_COLOR = 255;
- S32 r = ll_round(color.mV[0] * color_scale_factor);
+ constexpr S32 MAX_COLOR = 255;
+ S32 r = ll_round(color.mV[VRED] * color_scale_factor);
if (r > MAX_COLOR)
{
r = MAX_COLOR;
@@ -478,9 +396,9 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color)
{
r = 0;
}
- mV[0] = r;
+ mV[VRED] = r;
- S32 g = ll_round(color.mV[1] * color_scale_factor);
+ S32 g = ll_round(color.mV[VGREEN] * color_scale_factor);
if (g > MAX_COLOR)
{
g = MAX_COLOR;
@@ -489,9 +407,9 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color)
{
g = 0;
}
- mV[1] = g;
+ mV[VGREEN] = g;
- S32 b = ll_round(color.mV[2] * color_scale_factor);
+ S32 b = ll_round(color.mV[VBLUE] * color_scale_factor);
if (b > MAX_COLOR)
{
b = MAX_COLOR;
@@ -500,10 +418,10 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color)
{
b = 0;
}
- mV[2] = b;
+ mV[VBLUE] = b;
// Alpha shouldn't be scaled, just clamped...
- S32 a = ll_round(color.mV[3] * MAX_COLOR);
+ S32 a = ll_round(color.mV[VALPHA] * MAX_COLOR);
if (a > MAX_COLOR)
{
a = MAX_COLOR;
@@ -512,44 +430,42 @@ void LLColor4U::setVecScaleClamp(const LLColor4& color)
{
a = 0;
}
- mV[3] = a;
+ mV[VALPHA] = a;
}
void LLColor4U::setVecScaleClamp(const LLColor3& color)
{
F32 color_scale_factor = 255.f;
- F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]);
+ F32 max_color = llmax(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]);
if (max_color > 1.f)
{
color_scale_factor /= max_color;
}
const S32 MAX_COLOR = 255;
- S32 r = ll_round(color.mV[0] * color_scale_factor);
+ S32 r = ll_round(color.mV[VRED] * color_scale_factor);
if (r > MAX_COLOR)
{
r = MAX_COLOR;
}
- else
- if (r < 0)
+ else if (r < 0)
{
r = 0;
}
- mV[0] = r;
+ mV[VRED] = r;
- S32 g = ll_round(color.mV[1] * color_scale_factor);
+ S32 g = ll_round(color.mV[VGREEN] * color_scale_factor);
if (g > MAX_COLOR)
{
g = MAX_COLOR;
}
- else
- if (g < 0)
+ else if (g < 0)
{
g = 0;
}
- mV[1] = g;
+ mV[VGREEN] = g;
- S32 b = ll_round(color.mV[2] * color_scale_factor);
+ S32 b = ll_round(color.mV[VBLUE] * color_scale_factor);
if (b > MAX_COLOR)
{
b = MAX_COLOR;
@@ -558,31 +474,29 @@ void LLColor4U::setVecScaleClamp(const LLColor3& color)
{
b = 0;
}
- mV[2] = b;
+ mV[VBLUE] = b;
- mV[3] = 255;
+ mV[VALPHA] = 255;
}
inline U32 LLColor4U::asRGBA() const
{
// Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here
- return (mV[3] << 24) | (mV[2] << 16) | (mV[1] << 8) | mV[0];
+ return (mV[VALPHA] << 24) | (mV[VBLUE] << 16) | (mV[VGREEN] << 8) | mV[VRED];
}
-inline void LLColor4U::fromRGBA( U32 aVal )
+inline void LLColor4U::fromRGBA(U32 aVal)
{
// Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here
- mV[ 0 ] = aVal & 0xFF;
+ mV[VRED] = aVal & 0xFF;
aVal >>= 8;
- mV[ 1 ] = aVal & 0xFF;
+ mV[VGREEN] = aVal & 0xFF;
aVal >>= 8;
- mV[ 2 ] = aVal & 0xFF;
+ mV[VBLUE] = aVal & 0xFF;
aVal >>= 8;
- mV[ 3 ] = aVal & 0xFF;
+ mV[VALPHA] = aVal & 0xFF;
}
-
#endif
-
diff --git a/indra/llmath/v4math.cpp b/indra/llmath/v4math.cpp
index 0aa6eb09c3..cd475380d6 100644
--- a/indra/llmath/v4math.cpp
+++ b/indra/llmath/v4math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v4math.h"
#include "m4math.h"
@@ -36,13 +35,13 @@
// LLVector4
// Axis-Angle rotations
-const LLVector4& LLVector4::rotVec(const LLMatrix4 &mat)
+const LLVector4& LLVector4::rotVec(const LLMatrix4& mat)
{
*this = *this * mat;
return *this;
}
-const LLVector4& LLVector4::rotVec(const LLQuaternion &q)
+const LLVector4& LLVector4::rotVec(const LLQuaternion& q)
{
*this = *this * q;
return *this;
@@ -64,16 +63,16 @@ bool LLVector4::abs()
{
bool ret{ false };
- if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; }
- if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; }
- if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; }
- if (mV[3] < 0.f) { mV[3] = -mV[3]; ret = true; }
+ if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; }
+ if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; }
+ if (mV[VZ] < 0.f) { mV[VZ] = -mV[VZ]; ret = true; }
+ if (mV[VW] < 0.f) { mV[VW] = -mV[VW]; ret = true; }
return ret;
}
-std::ostream& operator<<(std::ostream& s, const LLVector4 &a)
+std::ostream& operator<<(std::ostream& s, const LLVector4& a)
{
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << ", " << a.mV[VW] << " }";
return s;
@@ -108,12 +107,12 @@ bool are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon)
}
-LLVector3 vec4to3(const LLVector4 &vec)
+LLVector3 vec4to3(const LLVector4& vec)
{
return LLVector3( vec.mV[VX], vec.mV[VY], vec.mV[VZ] );
}
-LLVector4 vec3to4(const LLVector3 &vec)
+LLVector4 vec3to4(const LLVector3& vec)
{
return LLVector4(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
}
diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h
index f5b79759b0..edfc2f8592 100644
--- a/indra/llmath/v4math.h
+++ b/indra/llmath/v4math.h
@@ -42,108 +42,108 @@ class LLQuaternion;
// LLVector4 = |x y z w|
-static const U32 LENGTHOFVECTOR4 = 4;
+static constexpr U32 LENGTHOFVECTOR4 = 4;
class LLVector4
{
- public:
- F32 mV[LENGTHOFVECTOR4];
- LLVector4(); // Initializes LLVector4 to (0, 0, 0, 1)
- explicit LLVector4(const F32 *vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3])
- explicit LLVector4(const F64 *vec); // Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]);
- explicit LLVector4(const LLVector2 &vec);
- explicit LLVector4(const LLVector2 &vec, F32 z, F32 w);
- explicit LLVector4(const LLVector3 &vec); // Initializes LLVector4 to (vec, 1)
- explicit LLVector4(const LLVector3 &vec, F32 w); // Initializes LLVector4 to (vec, w)
- explicit LLVector4(const LLSD &sd);
- LLVector4(F32 x, F32 y, F32 z); // Initializes LLVector4 to (x. y, z, 1)
- LLVector4(F32 x, F32 y, F32 z, F32 w);
+public:
+ F32 mV[LENGTHOFVECTOR4];
+ LLVector4(); // Initializes LLVector4 to (0, 0, 0, 1)
+ explicit LLVector4(const F32 *vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3])
+ explicit LLVector4(const F64 *vec); // Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]);
+ explicit LLVector4(const LLVector2 &vec);
+ explicit LLVector4(const LLVector2 &vec, F32 z, F32 w);
+ explicit LLVector4(const LLVector3 &vec); // Initializes LLVector4 to (vec, 1)
+ explicit LLVector4(const LLVector3 &vec, F32 w); // Initializes LLVector4 to (vec, w)
+ explicit LLVector4(const LLSD &sd);
+ LLVector4(F32 x, F32 y, F32 z); // Initializes LLVector4 to (x. y, z, 1)
+ LLVector4(F32 x, F32 y, F32 z, F32 w);
- LLSD getValue() const
- {
- LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
- ret[3] = mV[3];
- return ret;
- }
+ LLSD getValue() const
+ {
+ LLSD ret;
+ ret[VX] = mV[VX];
+ ret[VY] = mV[VY];
+ ret[VZ] = mV[VZ];
+ ret[VW] = mV[VW];
+ return ret;
+ }
- void setValue(const LLSD& sd)
- {
- mV[0] = (F32)sd[0].asReal();
- mV[1] = (F32)sd[1].asReal();
- mV[2] = (F32)sd[2].asReal();
- mV[3] = (F32)sd[3].asReal();
- }
+ void setValue(const LLSD& sd)
+ {
+ mV[VX] = (F32)sd[VX].asReal();
+ mV[VY] = (F32)sd[VY].asReal();
+ mV[VZ] = (F32)sd[VZ].asReal();
+ mV[VW] = (F32)sd[VW].asReal();
+ }
- // GLM interop
- explicit LLVector4(const glm::vec3& vec); // Initializes LLVector4 to (vec, 1)
- explicit LLVector4(const glm::vec4& vec); // Initializes LLVector4 to vec
- explicit operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2])
- explicit operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], vec[3])
+ // GLM interop
+ explicit LLVector4(const glm::vec3& vec); // Initializes LLVector4 to (vec, 1)
+ explicit LLVector4(const glm::vec4& vec); // Initializes LLVector4 to vec
+ explicit operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2])
+ explicit operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], vec[3])
- inline bool isFinite() const; // checks to see if all values of LLVector3 are finite
+ inline bool isFinite() const; // checks to see if all values of LLVector3 are finite
- inline void clear(); // Clears LLVector4 to (0, 0, 0, 1)
- inline void clearVec(); // deprecated
- inline void zeroVec(); // deprecated
+ inline void clear(); // Clears LLVector4 to (0, 0, 0, 1)
+ inline void clearVec(); // deprecated
+ inline void zeroVec(); // deprecated
- inline void set(F32 x, F32 y, F32 z); // Sets LLVector4 to (x, y, z, 1)
- inline void set(F32 x, F32 y, F32 z, F32 w); // Sets LLVector4 to (x, y, z, w)
- inline void set(const LLVector4 &vec); // Sets LLVector4 to vec
- inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec
- inline void set(const F32 *vec); // Sets LLVector4 to vec
- inline void set(const glm::vec4& vec); // Sets LLVector4 to vec
- inline void set(const glm::vec3& vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec with w defaulted to 1
+ inline void set(F32 x, F32 y, F32 z); // Sets LLVector4 to (x, y, z, 1)
+ inline void set(F32 x, F32 y, F32 z, F32 w); // Sets LLVector4 to (x, y, z, w)
+ inline void set(const LLVector4 &vec); // Sets LLVector4 to vec
+ inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec
+ inline void set(const F32 *vec); // Sets LLVector4 to vec
+ inline void set(const glm::vec4& vec); // Sets LLVector4 to vec
+ inline void set(const glm::vec3& vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec with w defaulted to 1
- inline void setVec(F32 x, F32 y, F32 z); // deprecated
- inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated
- inline void setVec(const LLVector4 &vec); // deprecated
- inline void setVec(const LLVector3 &vec, F32 w = 1.f); // deprecated
- inline void setVec(const F32 *vec); // deprecated
+ inline void setVec(F32 x, F32 y, F32 z); // deprecated
+ inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated
+ inline void setVec(const LLVector4 &vec); // deprecated
+ inline void setVec(const LLVector3 &vec, F32 w = 1.f); // deprecated
+ inline void setVec(const F32 *vec); // deprecated
- F32 length() const; // Returns magnitude of LLVector4
- F32 lengthSquared() const; // Returns magnitude squared of LLVector4
- F32 normalize(); // Normalizes and returns the magnitude of LLVector4
+ F32 length() const; // Returns magnitude of LLVector4
+ F32 lengthSquared() const; // Returns magnitude squared of LLVector4
+ F32 normalize(); // Normalizes and returns the magnitude of LLVector4
- F32 magVec() const; // deprecated
- F32 magVecSquared() const; // deprecated
- F32 normVec(); // deprecated
+ F32 magVec() const; // deprecated
+ F32 magVecSquared() const; // deprecated
+ F32 normVec(); // deprecated
- // Sets all values to absolute value of their original values
- // Returns true if data changed
- bool abs();
+ // Sets all values to absolute value of their original values
+ // Returns true if data changed
+ bool abs();
- bool isExactlyClear() const { return (mV[VW] == 1.0f) && !mV[VX] && !mV[VY] && !mV[VZ]; }
- bool isExactlyZero() const { return !mV[VW] && !mV[VX] && !mV[VY] && !mV[VZ]; }
+ bool isExactlyClear() const { return (mV[VW] == 1.0f) && !mV[VX] && !mV[VY] && !mV[VZ]; }
+ bool isExactlyZero() const { return !mV[VW] && !mV[VX] && !mV[VY] && !mV[VZ]; }
- const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat
- const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q
+ const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat
+ const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q
- const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec
+ const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec
- F32 operator[](int idx) const { return mV[idx]; }
- F32 &operator[](int idx) { return mV[idx]; }
+ F32 operator[](int idx) const { return mV[idx]; }
+ F32 &operator[](int idx) { return mV[idx]; }
- friend std::ostream& operator<<(std::ostream& s, const LLVector4 &a); // Print a
- friend LLVector4 operator+(const LLVector4 &a, const LLVector4 &b); // Return vector a + b
- friend LLVector4 operator-(const LLVector4 &a, const LLVector4 &b); // Return vector a minus b
- friend F32 operator*(const LLVector4 &a, const LLVector4 &b); // Return a dot b
- friend LLVector4 operator%(const LLVector4 &a, const LLVector4 &b); // Return a cross b
- friend LLVector4 operator/(const LLVector4 &a, F32 k); // Return a divided by scaler k
- friend LLVector4 operator*(const LLVector4 &a, F32 k); // Return a times scaler k
- friend LLVector4 operator*(F32 k, const LLVector4 &a); // Return a times scaler k
- friend bool operator==(const LLVector4 &a, const LLVector4 &b); // Return a == b
- friend bool operator!=(const LLVector4 &a, const LLVector4 &b); // Return a != b
+ friend std::ostream& operator<<(std::ostream& s, const LLVector4 &a); // Print a
+ friend LLVector4 operator+(const LLVector4 &a, const LLVector4 &b); // Return vector a + b
+ friend LLVector4 operator-(const LLVector4 &a, const LLVector4 &b); // Return vector a minus b
+ friend F32 operator*(const LLVector4 &a, const LLVector4 &b); // Return a dot b
+ friend LLVector4 operator%(const LLVector4 &a, const LLVector4 &b); // Return a cross b
+ friend LLVector4 operator/(const LLVector4 &a, F32 k); // Return a divided by scaler k
+ friend LLVector4 operator*(const LLVector4 &a, F32 k); // Return a times scaler k
+ friend LLVector4 operator*(F32 k, const LLVector4 &a); // Return a times scaler k
+ friend bool operator==(const LLVector4 &a, const LLVector4 &b); // Return a == b
+ friend bool operator!=(const LLVector4 &a, const LLVector4 &b); // Return a != b
- friend const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b); // Return vector a + b
- friend const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b); // Return vector a minus b
- friend const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b); // Return a cross b
- friend const LLVector4& operator*=(LLVector4 &a, F32 k); // Return a times scaler k
- friend const LLVector4& operator/=(LLVector4 &a, F32 k); // Return a divided by scaler k
+ friend const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b); // Return vector a + b
+ friend const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b); // Return vector a minus b
+ friend const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b); // Return a cross b
+ friend const LLVector4& operator*=(LLVector4 &a, F32 k); // Return a times scaler k
+ friend const LLVector4& operator/=(LLVector4 &a, F32 k); // Return a divided by scaler k
- friend LLVector4 operator-(const LLVector4 &a); // Return vector -a
+ friend LLVector4 operator-(const LLVector4 &a); // Return vector -a
};
static_assert(std::is_trivially_copyable::value, "LLVector4 must be trivial copy");
@@ -163,34 +163,22 @@ LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u); // Returns a vect
inline LLVector4::LLVector4(void)
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
- mV[VZ] = 0.f;
- mV[VW] = 1.f;
+ clear();
}
inline LLVector4::LLVector4(F32 x, F32 y, F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
- mV[VW] = 1.f;
+ set(x, y, z, 1.f);
}
inline LLVector4::LLVector4(F32 x, F32 y, F32 z, F32 w)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
- mV[VW] = w;
+ set(x, y, z, w);
}
inline LLVector4::LLVector4(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
- mV[VZ] = vec[VZ];
- mV[VW] = vec[VW];
+ set(vec);
}
inline LLVector4::LLVector4(const F64 *vec)
@@ -219,18 +207,12 @@ inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w)
inline LLVector4::LLVector4(const LLVector3 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
- mV[VZ] = vec.mV[VZ];
- mV[VW] = 1.f;
+ set(vec, 1.f);
}
inline LLVector4::LLVector4(const LLVector3 &vec, F32 w)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
- mV[VZ] = vec.mV[VZ];
- mV[VW] = w;
+ set(vec, w);
}
inline LLVector4::LLVector4(const LLSD &sd)
@@ -256,43 +238,31 @@ inline LLVector4::LLVector4(const glm::vec4& vec)
inline bool LLVector4::isFinite() const
{
- return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW]));
+ return llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW]);
}
// Clear and Assignment Functions
-inline void LLVector4::clear(void)
+inline void LLVector4::clear()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
- mV[VZ] = 0.f;
- mV[VW] = 1.f;
+ set(0.f, 0.f, 0.f, 1.f);
}
// deprecated
-inline void LLVector4::clearVec(void)
+inline void LLVector4::clearVec()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
- mV[VZ] = 0.f;
- mV[VW] = 1.f;
+ clear();
}
// deprecated
-inline void LLVector4::zeroVec(void)
+inline void LLVector4::zeroVec()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
- mV[VZ] = 0.f;
- mV[VW] = 0.f;
+ set(0.f, 0.f, 0.f, 0.f);
}
inline void LLVector4::set(F32 x, F32 y, F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
- mV[VW] = 1.f;
+ set(x, y, z, 1.f);
}
inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w)
@@ -303,15 +273,12 @@ inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w)
mV[VW] = w;
}
-inline void LLVector4::set(const LLVector4 &vec)
+inline void LLVector4::set(const LLVector4& vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
- mV[VZ] = vec.mV[VZ];
- mV[VW] = vec.mV[VW];
+ set(vec.mV);
}
-inline void LLVector4::set(const LLVector3 &vec, F32 w)
+inline void LLVector4::set(const LLVector3& vec, F32 w)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
@@ -319,14 +286,13 @@ inline void LLVector4::set(const LLVector3 &vec, F32 w)
mV[VW] = w;
}
-inline void LLVector4::set(const F32 *vec)
+inline void LLVector4::set(const F32* vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
mV[VW] = vec[VW];
}
-
inline void LLVector4::set(const glm::vec4& vec)
{
mV[VX] = vec.x;
@@ -346,119 +312,104 @@ inline void LLVector4::set(const glm::vec3& vec, F32 w)
// deprecated
inline void LLVector4::setVec(F32 x, F32 y, F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
- mV[VW] = 1.f;
+ set(x, y, z);
}
// deprecated
inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
- mV[VW] = w;
+ set(x, y, z, w);
}
// deprecated
-inline void LLVector4::setVec(const LLVector4 &vec)
+inline void LLVector4::setVec(const LLVector4& vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
- mV[VZ] = vec.mV[VZ];
- mV[VW] = vec.mV[VW];
+ set(vec);
}
// deprecated
-inline void LLVector4::setVec(const LLVector3 &vec, F32 w)
+inline void LLVector4::setVec(const LLVector3& vec, F32 w)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
- mV[VZ] = vec.mV[VZ];
- mV[VW] = w;
+ set(vec, w);
}
// deprecated
-inline void LLVector4::setVec(const F32 *vec)
+inline void LLVector4::setVec(const F32* vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
- mV[VZ] = vec[VZ];
- mV[VW] = vec[VW];
+ set(vec);
}
// LLVector4 Magnitude and Normalization Functions
-inline F32 LLVector4::length(void) const
+inline F32 LLVector4::length() const
{
- return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
+ return sqrt(lengthSquared());
}
-inline F32 LLVector4::lengthSquared(void) const
+inline F32 LLVector4::lengthSquared() const
{
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
-inline F32 LLVector4::magVec(void) const
+inline F32 LLVector4::magVec() const
{
- return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
+ return length();
}
-inline F32 LLVector4::magVecSquared(void) const
+inline F32 LLVector4::magVecSquared() const
{
- return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
+ return lengthSquared();
}
// LLVector4 Operators
-inline LLVector4 operator+(const LLVector4 &a, const LLVector4 &b)
+inline LLVector4 operator+(const LLVector4& a, const LLVector4& b)
{
LLVector4 c(a);
return c += b;
}
-inline LLVector4 operator-(const LLVector4 &a, const LLVector4 &b)
+inline LLVector4 operator-(const LLVector4& a, const LLVector4& b)
{
LLVector4 c(a);
return c -= b;
}
-inline F32 operator*(const LLVector4 &a, const LLVector4 &b)
+inline F32 operator*(const LLVector4& a, const LLVector4& b)
{
- return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]);
+ return a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ];
}
-inline LLVector4 operator%(const LLVector4 &a, const LLVector4 &b)
+inline LLVector4 operator%(const LLVector4& a, const LLVector4& b)
{
return LLVector4(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
}
-inline LLVector4 operator/(const LLVector4 &a, F32 k)
+inline LLVector4 operator/(const LLVector4& a, F32 k)
{
F32 t = 1.f / k;
return LLVector4( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t );
}
-inline LLVector4 operator*(const LLVector4 &a, F32 k)
+inline LLVector4 operator*(const LLVector4& a, F32 k)
{
return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k );
}
-inline LLVector4 operator*(F32 k, const LLVector4 &a)
+inline LLVector4 operator*(F32 k, const LLVector4& a)
{
return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k );
}
-inline bool operator==(const LLVector4 &a, const LLVector4 &b)
+inline bool operator==(const LLVector4& a, const LLVector4& b)
{
return ( (a.mV[VX] == b.mV[VX])
&&(a.mV[VY] == b.mV[VY])
&&(a.mV[VZ] == b.mV[VZ]));
}
-inline bool operator!=(const LLVector4 &a, const LLVector4 &b)
+inline bool operator!=(const LLVector4& a, const LLVector4& b)
{
return ( (a.mV[VX] != b.mV[VX])
||(a.mV[VY] != b.mV[VY])
@@ -466,7 +417,7 @@ inline bool operator!=(const LLVector4 &a, const LLVector4 &b)
||(a.mV[VW] != b.mV[VW]) );
}
-inline const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b)
+inline const LLVector4& operator+=(LLVector4& a, const LLVector4& b)
{
a.mV[VX] += b.mV[VX];
a.mV[VY] += b.mV[VY];
@@ -474,7 +425,7 @@ inline const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b)
return a;
}
-inline const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b)
+inline const LLVector4& operator-=(LLVector4& a, const LLVector4& b)
{
a.mV[VX] -= b.mV[VX];
a.mV[VY] -= b.mV[VY];
@@ -482,14 +433,14 @@ inline const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b)
return a;
}
-inline const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b)
+inline const LLVector4& operator%=(LLVector4& a, const LLVector4& b)
{
LLVector4 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
a = ret;
return a;
}
-inline const LLVector4& operator*=(LLVector4 &a, F32 k)
+inline const LLVector4& operator*=(LLVector4& a, F32 k)
{
a.mV[VX] *= k;
a.mV[VY] *= k;
@@ -497,16 +448,12 @@ inline const LLVector4& operator*=(LLVector4 &a, F32 k)
return a;
}
-inline const LLVector4& operator/=(LLVector4 &a, F32 k)
+inline const LLVector4& operator/=(LLVector4& a, F32 k)
{
- F32 t = 1.f / k;
- a.mV[VX] *= t;
- a.mV[VY] *= t;
- a.mV[VZ] *= t;
- return a;
+ return a *= 1.f / k;
}
-inline LLVector4 operator-(const LLVector4 &a)
+inline LLVector4 operator-(const LLVector4& a)
{
return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] );
}
@@ -521,19 +468,19 @@ inline LLVector4::operator glm::vec4() const
return glm::make_vec4(mV);
}
-inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b)
+inline F32 dist_vec(const LLVector4& a, const LLVector4& b)
{
LLVector4 vec = a - b;
- return (vec.length());
+ return vec.length();
}
-inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b)
+inline F32 dist_vec_squared(const LLVector4& a, const LLVector4& b)
{
LLVector4 vec = a - b;
- return (vec.lengthSquared());
+ return vec.lengthSquared();
}
-inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u)
+inline LLVector4 lerp(const LLVector4& a, const LLVector4& b, F32 u)
{
return LLVector4(
a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
@@ -542,59 +489,39 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u)
a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u);
}
-inline F32 LLVector4::normalize(void)
+inline F32 LLVector4::normalize()
{
- F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
- F32 oomag;
+ F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mV[VX] *= oomag;
- mV[VY] *= oomag;
- mV[VZ] *= oomag;
+ *this /= mag;
}
else
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
- mag = 0;
+ mV[VX] = 0.f;
+ mV[VY] = 0.f;
+ mV[VZ] = 0.f;
+ mag = 0.f;
}
- return (mag);
+ return mag;
}
// deprecated
-inline F32 LLVector4::normVec(void)
+inline F32 LLVector4::normVec()
{
- F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
- F32 oomag;
-
- if (mag > FP_MAG_THRESHOLD)
- {
- oomag = 1.f/mag;
- mV[VX] *= oomag;
- mV[VY] *= oomag;
- mV[VZ] *= oomag;
- }
- else
- {
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
- mag = 0;
- }
- return (mag);
+ return normalize();
}
// Because apparently some parts of the viewer use this for color info.
-inline const LLVector4 srgbVector4(const LLVector4 &a) {
+inline const LLVector4 srgbVector4(const LLVector4& a)
+{
LLVector4 srgbColor;
- srgbColor.mV[0] = linearTosRGB(a.mV[0]);
- srgbColor.mV[1] = linearTosRGB(a.mV[1]);
- srgbColor.mV[2] = linearTosRGB(a.mV[2]);
- srgbColor.mV[3] = a.mV[3];
+ srgbColor.mV[VX] = linearTosRGB(a.mV[VX]);
+ srgbColor.mV[VY] = linearTosRGB(a.mV[VY]);
+ srgbColor.mV[VZ] = linearTosRGB(a.mV[VZ]);
+ srgbColor.mV[VW] = a.mV[VW];
return srgbColor;
}
diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h
index 7434301670..fa45fffeae 100644
--- a/indra/llmath/xform.h
+++ b/indra/llmath/xform.h
@@ -115,7 +115,7 @@ public:
void clearChanged(U32 bits) { mChanged &= ~bits; }
void setScaleChildOffset(bool scale) { mScaleChildOffset = scale; }
- bool getScaleChildOffset() { return mScaleChildOffset; }
+ bool getScaleChildOffset() const { return mScaleChildOffset; }
LLXform* getParent() const { return mParent; }
LLXform* getRoot() const;
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index 6a663a8e97..563dd9459c 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -50,7 +50,7 @@ static const U32 DEFAULT_POOL_SIZE = 5;
// SL-14399: When we teleport to a brand-new simulator, the coprocedure queue
// gets absolutely slammed with fetch requests. Make this queue effectively
// unlimited.
-const U32 LLCoprocedureManager::DEFAULT_QUEUE_SIZE = 1024*1024;
+const U32 LLCoprocedureManager::DEFAULT_QUEUE_SIZE = 1024*512;
//=========================================================================
class LLCoprocedurePool: private boost::noncopyable
@@ -58,7 +58,7 @@ class LLCoprocedurePool: private boost::noncopyable
public:
typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t;
- LLCoprocedurePool(const std::string &name, size_t size);
+ LLCoprocedurePool(const std::string &name, size_t size, size_t queue_size);
~LLCoprocedurePool();
/// Places the coprocedure on the queue for processing.
@@ -118,7 +118,7 @@ private:
typedef std::shared_ptr CoprocQueuePtr;
std::string mPoolName;
- size_t mPoolSize, mActiveCoprocsCount, mPending;
+ size_t mPoolSize, mQueueSize, mActiveCoprocsCount, mPending;
CoprocQueuePtr mPendingCoprocs;
LLTempBoundListener mStatusListener;
@@ -141,7 +141,7 @@ LLCoprocedureManager::~LLCoprocedureManager()
close();
}
-void LLCoprocedureManager::initializePool(const std::string &poolName)
+void LLCoprocedureManager::initializePool(const std::string &poolName, size_t queue_size)
{
poolMap_t::iterator it = mPoolMap.find(poolName);
@@ -180,7 +180,7 @@ void LLCoprocedureManager::initializePool(const std::string &poolName)
LL_WARNS("CoProcMgr") << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL;
}
- poolPtr_t pool(new LLCoprocedurePool(poolName, size));
+ poolPtr_t pool(new LLCoprocedurePool(poolName, size, queue_size));
LL_ERRS_IF(!pool, "CoprocedureManager") << "Unable to create pool named \"" << poolName << "\" FATAL!" << LL_ENDL;
bool inserted = mPoolMap.emplace(poolName, pool).second;
@@ -212,7 +212,8 @@ void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpd
mPropertyQueryFn = queryfn;
mPropertyDefineFn = updatefn;
- initializePool("Upload");
+ constexpr size_t UPLOAD_QUEUE_SIZE = 2048;
+ initializePool("Upload", UPLOAD_QUEUE_SIZE);
initializePool("AIS"); // it might be better to have some kind of on-demand initialization for AIS
// "ExpCache" pool gets initialized in LLExperienceCache
// asset storage pool gets initialized in LLViewerAssetStorage
@@ -296,17 +297,19 @@ void LLCoprocedureManager::close(const std::string &pool)
}
//=========================================================================
-LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
+LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size, size_t queue_size):
mPoolName(poolName),
mPoolSize(size),
+ mQueueSize(queue_size),
mActiveCoprocsCount(0),
mPending(0),
mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mCoroMapping()
{
+ llassert_always(mQueueSize > mPoolSize); // queue should be able to fit pool
try
{
- mPendingCoprocs = std::make_shared(LLCoprocedureManager::DEFAULT_QUEUE_SIZE);
+ mPendingCoprocs = std::make_shared(mQueueSize);
// store in our LLTempBoundListener so that when the LLCoprocedurePool is
// destroyed, we implicitly disconnect from this LLEventPump
// Monitores application status
@@ -357,7 +360,7 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
mCoroMapping.insert(CoroAdapterMap_t::value_type(pooledCoro, httpAdapter));
}
- LL_INFOS("CoProcMgr") << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items, queue max " << LLCoprocedureManager::DEFAULT_QUEUE_SIZE << LL_ENDL;
+ LL_INFOS("CoProcMgr") << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items, queue max " << mQueueSize << LL_ENDL;
}
LLCoprocedurePool::~LLCoprocedurePool()
@@ -376,7 +379,7 @@ LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoproced
<< "\" at "
<< mPending << LL_ENDL;
- if (mPending >= (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
+ if (mPending >= (mQueueSize - 1))
{
// If it's all used up (not supposed to happen,
// fetched should cap it), we are going to crash
diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h
index 6c6e506654..485333657c 100644
--- a/indra/llmessage/llcoproceduremanager.h
+++ b/indra/llmessage/llcoproceduremanager.h
@@ -79,7 +79,7 @@ public:
void close();
void close(const std::string &pool);
- void initializePool(const std::string &poolName);
+ void initializePool(const std::string &poolName, size_t queue_size = DEFAULT_QUEUE_SIZE);
private:
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index 83a070df32..78cca47456 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -110,7 +110,8 @@ void LLExperienceCache::initSingleton()
cache_stream >> (*this);
}
- LLCoprocedureManager::instance().initializePool("ExpCache");
+ constexpr size_t CORO_QUEUE_SIZE = 2048;
+ LLCoprocedureManager::instance().initializePool("ExpCache", CORO_QUEUE_SIZE);
LLCoros::instance().launch("LLExperienceCache::idleCoro",
boost::bind(&LLExperienceCache::idleCoro, this));
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp
index eb6650c6c5..b8284334ea 100644
--- a/indra/llmessage/llpacketring.cpp
+++ b/indra/llmessage/llpacketring.cpp
@@ -209,8 +209,14 @@ S32 LLPacketRing::receiveOrDropBufferedPacket(char *datap, bool drop)
if (!drop)
{
- assert(packet_size > 0);
- memcpy(datap, packet->getData(), packet_size);
+ if (packet_size > 0)
+ {
+ memcpy(datap, packet->getData(), packet_size);
+ }
+ else
+ {
+ assert(false);
+ }
}
else
{
diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
index d04ca52ad6..d79d5c3a11 100644
--- a/indra/llmessage/llproxy.cpp
+++ b/indra/llmessage/llproxy.cpp
@@ -506,6 +506,7 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
rv = apr_socket_recv(apr_socket, datain, &maxinlen);
if (rv != APR_SUCCESS)
{
+ // if rv == 70060 it's WSAETIMEDOUT
char buf[MAX_STRING];
LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
ll_apr_warn_status(rv);
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index c264a9f086..21dbf35783 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -1402,3 +1402,4 @@ char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->ge
char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience");
char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID");
char const* const _PREHASH_LargeGenericMessage = LLMessageStringTable::getInstance()->getString("LargeGenericMessage");
+char const* const _PREHASH_MetaData = LLMessageStringTable::getInstance()->getString("MetaData");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 1d30b69b67..8a2ad1587c 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -1403,5 +1403,6 @@ extern char const* const _PREHASH_HoverHeight;
extern char const* const _PREHASH_Experience;
extern char const* const _PREHASH_ExperienceID;
extern char const* const _PREHASH_LargeGenericMessage;
+extern char const* const _PREHASH_MetaData;
#endif
diff --git a/indra/llmessage/patch_code.cpp b/indra/llmessage/patch_code.cpp
index 489b6ce6a6..9f9f4c852a 100644
--- a/indra/llmessage/patch_code.cpp
+++ b/indra/llmessage/patch_code.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "patch_dct.h"
#include "patch_code.h"
diff --git a/indra/llmessage/patch_dct.cpp b/indra/llmessage/patch_dct.cpp
index 728fe84537..e74e5fd459 100644
--- a/indra/llmessage/patch_dct.cpp
+++ b/indra/llmessage/patch_dct.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "patch_dct.h"
diff --git a/indra/llmessage/patch_idct.cpp b/indra/llmessage/patch_idct.cpp
index 5483cf98c0..4bcc439917 100644
--- a/indra/llmessage/patch_idct.cpp
+++ b/indra/llmessage/patch_idct.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "patch_dct.h"
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 19a0ce639a..afee099697 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -575,7 +575,7 @@ void LLPluginProcessParent::idle(void)
params.args.add("-e");
params.args.add("tell application \"Terminal\"");
params.args.add("-e");
- params.args.add(STRINGIZE("set win to do script \"lldb -pid "
+ params.args.add(STRINGIZE("set win to do script \"lldb -p "
<< mProcess->getProcessID() << "\""));
params.args.add("-e");
params.args.add("do script \"continue\" in win");
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index 3d8e02cb16..e13f0bbd96 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -12,7 +12,6 @@ include(TinyGLTF)
set(llprimitive_SOURCE_FILES
lldaeloader.cpp
- llgltfloader.cpp
llgltfmaterial.cpp
llmaterialid.cpp
llmaterial.cpp
@@ -32,7 +31,6 @@ set(llprimitive_SOURCE_FILES
set(llprimitive_HEADER_FILES
CMakeLists.txt
lldaeloader.h
- llgltfloader.h
llgltfmaterial.h
llgltfmaterial_templates.h
legacy_object_types.h
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 4c028e7128..81ebe631c5 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -204,12 +204,15 @@ LLModel::EModelStatus load_face_from_dom_triangles(
if (idx_stride <= 0
|| (pos_source && pos_offset >= idx_stride)
+ || (pos_source && pos_offset < 0)
|| (tc_source && tc_offset >= idx_stride)
- || (norm_source && norm_offset >= idx_stride))
+ || (tc_source && tc_offset < 0)
+ || (norm_source && norm_offset >= idx_stride)
+ || (norm_source && norm_offset < 0))
{
// Looks like these offsets should fit inside idx_stride
// Might be good idea to also check idx.getCount()%idx_stride != 0
- LL_WARNS() << "Invalid pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
+ LL_WARNS() << "Invalid idx_stride " << idx_stride << ", pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
return LLModel::BAD_ELEMENT;
}
@@ -880,9 +883,10 @@ LLDAELoader::LLDAELoader(
void* opaque_userdata,
JointTransformMap& jointTransformMap,
JointNameSet& jointsFromNodes,
- std::map& jointAliasMap,
+ std::map>& jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit,
+ U32 debugMode,
bool preprocess)
: LLModelLoader(
filename,
@@ -895,8 +899,9 @@ LLDAELoader::LLDAELoader(
jointTransformMap,
jointsFromNodes,
jointAliasMap,
- maxJointsPerMesh),
- mGeneratedModelLimit(modelLimit),
+ maxJointsPerMesh,
+ modelLimit,
+ debugMode),
mPreprocessDAE(preprocess)
{
}
@@ -1680,6 +1685,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
{
materials[model->mMaterialList[i]] = LLImportMaterial();
}
+ // todo: likely a bug here, shouldn't be using suffixed label, see how it gets used in other places.
mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
stretch_extents(model, transformation);
}
@@ -2412,7 +2418,7 @@ std::string LLDAELoader::getElementLabel(daeElement *element)
}
// static
-size_t LLDAELoader::getSuffixPosition(std::string label)
+size_t LLDAELoader::getSuffixPosition(const std::string &label)
{
if ((label.find("_LOD") != -1) || (label.find("_PHYS") != -1))
{
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 4531e03474..0335011a56 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -47,19 +47,20 @@ public:
dae_model_map mModelsMap;
LLDAELoader(
- std::string filename,
- S32 lod,
- LLModelLoader::load_callback_t load_cb,
- LLModelLoader::joint_lookup_func_t joint_lookup_func,
- LLModelLoader::texture_load_func_t texture_load_func,
- LLModelLoader::state_callback_t state_cb,
- void* opaque_userdata,
- JointTransformMap& jointTransformMap,
- JointNameSet& jointsFromNodes,
- std::map& jointAliasMap,
- U32 maxJointsPerMesh,
- U32 modelLimit,
- bool preprocess);
+ std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void* opaque_userdata,
+ JointTransformMap& jointTransformMap,
+ JointNameSet& jointsFromNodes,
+ std::map>& jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit,
+ U32 debugMode,
+ bool preprocess);
virtual ~LLDAELoader() ;
virtual bool OpenFile(const std::string& filename);
@@ -97,13 +98,12 @@ protected:
bool loadModelsFromDomMesh(domMesh* mesh, std::vector& models_out, U32 submodel_limit);
static std::string getElementLabel(daeElement *element);
- static size_t getSuffixPosition(std::string label);
+ static size_t getSuffixPosition(const std::string& label);
static std::string getLodlessLabel(daeElement *element);
static std::string preprocessDAE(std::string filename);
private:
- U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
bool mPreprocessDAE;
};
diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp
deleted file mode 100644
index 480012699a..0000000000
--- a/indra/llprimitive/llgltfloader.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-/**
- * @file LLGLTFLoader.cpp
- * @brief LLGLTFLoader class implementation
- *
- * $LicenseInfo:firstyear=2022&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2022, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llgltfloader.h"
-
-// Import & define single-header gltf import/export lib
-#define TINYGLTF_IMPLEMENTATION
-#define TINYGLTF_USE_CPP14 // default is C++ 11
-
-// tinygltf by default loads image files using STB
-#define STB_IMAGE_IMPLEMENTATION
-// to use our own image loading:
-// 1. replace this definition with TINYGLTF_NO_STB_IMAGE
-// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)
-
-// tinygltf saves image files using STB
-#define STB_IMAGE_WRITE_IMPLEMENTATION
-// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data)
-
-// Additionally, disable inclusion of STB header files entirely with
-// TINYGLTF_NO_INCLUDE_STB_IMAGE
-// TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
-#include "tinygltf/tiny_gltf.h"
-
-
-// TODO: includes inherited from dae loader. Validate / prune
-
-#include "llsdserialize.h"
-#include "lljoint.h"
-
-#include "llmatrix4a.h"
-
-#include
-#include
-
-static const std::string lod_suffix[LLModel::NUM_LODS] =
-{
- "_LOD0",
- "_LOD1",
- "_LOD2",
- "",
- "_PHYS",
-};
-
-
-LLGLTFLoader::LLGLTFLoader(std::string filename,
- S32 lod,
- LLModelLoader::load_callback_t load_cb,
- LLModelLoader::joint_lookup_func_t joint_lookup_func,
- LLModelLoader::texture_load_func_t texture_load_func,
- LLModelLoader::state_callback_t state_cb,
- void * opaque_userdata,
- JointTransformMap & jointTransformMap,
- JointNameSet & jointsFromNodes,
- std::map &jointAliasMap,
- U32 maxJointsPerMesh,
- U32 modelLimit) //,
- //bool preprocess)
- : LLModelLoader( filename,
- lod,
- load_cb,
- joint_lookup_func,
- texture_load_func,
- state_cb,
- opaque_userdata,
- jointTransformMap,
- jointsFromNodes,
- jointAliasMap,
- maxJointsPerMesh ),
- //mPreprocessGLTF(preprocess),
- mMeshesLoaded(false),
- mMaterialsLoaded(false)
-{
-}
-
-LLGLTFLoader::~LLGLTFLoader() {}
-
-bool LLGLTFLoader::OpenFile(const std::string &filename)
-{
- tinygltf::TinyGLTF loader;
- std::string error_msg;
- std::string warn_msg;
- std::string filename_lc(filename);
- LLStringUtil::toLower(filename_lc);
-
- // Load a tinygltf model fom a file. Assumes that the input filename has already been
- // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
- if (std::string::npos == filename_lc.rfind(".gltf"))
- { // file is binary
- mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
- }
- else
- { // file is ascii
- mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
- }
-
- if (!mGltfLoaded)
- {
- if (!warn_msg.empty())
- LL_WARNS("GLTF_IMPORT") << "gltf load warning: " << warn_msg.c_str() << LL_ENDL;
- if (!error_msg.empty())
- LL_WARNS("GLTF_IMPORT") << "gltf load error: " << error_msg.c_str() << LL_ENDL;
- return false;
- }
-
- mMeshesLoaded = parseMeshes();
- if (mMeshesLoaded) uploadMeshes();
-
- mMaterialsLoaded = parseMaterials();
- if (mMaterialsLoaded) uploadMaterials();
-
- return (mMeshesLoaded || mMaterialsLoaded);
-}
-
-bool LLGLTFLoader::parseMeshes()
-{
- if (!mGltfLoaded) return false;
-
- // 2022-04 DJH Volume params from dae example. TODO understand PCODE
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
-
- for (tinygltf::Mesh mesh : mGltfModel.meshes)
- {
- LLModel *pModel = new LLModel(volume_params, 0.f);
-
- if (populateModelFromMesh(pModel, mesh) &&
- (LLModel::NO_ERRORS == pModel->getStatus()) &&
- validate_model(pModel))
- {
- mModelList.push_back(pModel);
- }
- else
- {
- setLoadState(ERROR_MODEL + pModel->getStatus());
- delete(pModel);
- return false;
- }
- }
- return true;
-}
-
-bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh)
-{
- pModel->mLabel = mesh.name;
- int pos_idx;
- tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a;
-
- auto prims = mesh.primitives;
- for (auto prim : prims)
- {
- if (prim.indices >= 0) indices_a = mGltfModel.accessors[prim.indices];
-
- pos_idx = (prim.attributes.count("POSITION") > 0) ? prim.attributes.at("POSITION") : -1;
- if (pos_idx >= 0)
- {
- positions_a = mGltfModel.accessors[pos_idx];
- if (TINYGLTF_COMPONENT_TYPE_FLOAT != positions_a.componentType)
- continue;
- auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView];
- auto positions_buf = mGltfModel.buffers[positions_bv.buffer];
- //auto type = positions_vb.
- //if (positions_buf.name
- }
-
-#if 0
- int norm_idx, tan_idx, uv0_idx, uv1_idx, color0_idx, color1_idx;
- norm_idx = (prim.attributes.count("NORMAL") > 0) ? prim.attributes.at("NORMAL") : -1;
- tan_idx = (prim.attributes.count("TANGENT") > 0) ? prim.attributes.at("TANGENT") : -1;
- uv0_idx = (prim.attributes.count("TEXCOORDS_0") > 0) ? prim.attributes.at("TEXCOORDS_0") : -1;
- uv1_idx = (prim.attributes.count("TEXCOORDS_1") > 0) ? prim.attributes.at("TEXCOORDS_1") : -1;
- color0_idx = (prim.attributes.count("COLOR_0") > 0) ? prim.attributes.at("COLOR_0") : -1;
- color1_idx = (prim.attributes.count("COLOR_1") > 0) ? prim.attributes.at("COLOR_1") : -1;
-#endif
-
- if (prim.mode == TINYGLTF_MODE_TRIANGLES)
- {
- //auto pos = mesh. TODO resume here DJH 2022-04
- }
- }
-
- //pModel->addFace()
- return false;
-}
-
-bool LLGLTFLoader::parseMaterials()
-{
- if (!mGltfLoaded) return false;
-
- // fill local texture data structures
- mSamplers.clear();
- for (auto in_sampler : mGltfModel.samplers)
- {
- gltf_sampler sampler;
- sampler.magFilter = in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR;
- sampler.minFilter = in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;;
- sampler.wrapS = in_sampler.wrapS;
- sampler.wrapT = in_sampler.wrapT;
- sampler.name = in_sampler.name; // unused
- mSamplers.push_back(sampler);
- }
-
- mImages.clear();
- for (auto in_image : mGltfModel.images)
- {
- gltf_image image;
- image.numChannels = in_image.component;
- image.bytesPerChannel = in_image.bits >> 3; // Convert bits to bytes
- image.pixelType = in_image.pixel_type; // Maps exactly, i.e. TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc
- image.size = static_cast(in_image.image.size());
- image.height = in_image.height;
- image.width = in_image.width;
- image.data = in_image.image.data();
-
- if (in_image.as_is)
- {
- LL_WARNS("GLTF_IMPORT") << "Unsupported image encoding" << LL_ENDL;
- return false;
- }
-
- if (image.size != image.height * image.width * image.numChannels * image.bytesPerChannel)
- {
- LL_WARNS("GLTF_IMPORT") << "Image size error" << LL_ENDL;
- return false;
- }
-
- mImages.push_back(image);
- }
-
- mTextures.clear();
- for (auto in_tex : mGltfModel.textures)
- {
- gltf_texture tex;
- tex.imageIdx = in_tex.source;
- tex.samplerIdx = in_tex.sampler;
- tex.imageUuid.setNull();
-
- if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size())
- {
- LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL;
- return false;
- }
-
- mTextures.push_back(tex);
- }
-
- // parse each material
- for (tinygltf::Material gltf_material : mGltfModel.materials)
- {
- gltf_render_material mat;
- mat.name = gltf_material.name;
-
- tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness;
- mat.hasPBR = true; // Always true, for now
-
- mat.baseColor.set(pbr.baseColorFactor.data());
- mat.hasBaseTex = pbr.baseColorTexture.index >= 0;
- mat.baseColorTexIdx = pbr.baseColorTexture.index;
- mat.baseColorTexCoords = pbr.baseColorTexture.texCoord;
-
- mat.metalness = pbr.metallicFactor;
- mat.roughness = pbr.roughnessFactor;
- mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0;
- mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index;
- mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord;
-
- mat.normalScale = gltf_material.normalTexture.scale;
- mat.hasNormalTex = gltf_material.normalTexture.index >= 0;
- mat.normalTexIdx = gltf_material.normalTexture.index;
- mat.normalTexCoords = gltf_material.normalTexture.texCoord;
-
- mat.occlusionScale = gltf_material.occlusionTexture.strength;
- mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0;
- mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
- mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord;
-
- mat.emissiveColor.set(gltf_material.emissiveFactor.data());
- mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0;
- mat.emissiveTexIdx = gltf_material.emissiveTexture.index;
- mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord;
-
- mat.alphaMode = gltf_material.alphaMode;
- mat.alphaMask = gltf_material.alphaCutoff;
-
- if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) ||
- (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) ||
- (mat.hasEmissiveTex && (mat.emissiveTexIdx >= mTextures.size())) ||
- (mat.hasBaseTex && (mat.baseColorTexIdx >= mTextures.size())) ||
- (mat.hasMRTex && (mat.metalRoughTexIdx >= mTextures.size())))
- {
- LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL;
- return false;
- }
-
- if ((mat.hasNormalTex && (mat.normalTexCoords > 2)) || // mesh can have up to 3 sets of UV
- (mat.hasOcclusionTex && (mat.occlusionTexCoords > 2)) ||
- (mat.hasEmissiveTex && (mat.emissiveTexCoords > 2)) ||
- (mat.hasBaseTex && (mat.baseColorTexCoords > 2)) ||
- (mat.hasMRTex && (mat.metalRoughTexCoords > 2)))
- {
- LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL;
- return false;
- }
-
- mMaterials.push_back(mat);
- }
-
- return true;
-}
-
-// TODO: convert raw vertex buffers to UUIDs
-void LLGLTFLoader::uploadMeshes()
-{
- llassert(0);
-}
-
-// convert raw image buffers to texture UUIDs & assemble into a render material
-void LLGLTFLoader::uploadMaterials()
-{
- for (gltf_render_material mat : mMaterials) // Initially 1 material per gltf file, but design for multiple
- {
- if (mat.hasBaseTex)
- {
- gltf_texture& gtex = mTextures[mat.baseColorTexIdx];
- if (gtex.imageUuid.isNull())
- {
- gtex.imageUuid = imageBufferToTextureUUID(gtex);
- }
- }
-
- if (mat.hasMRTex)
- {
- gltf_texture& gtex = mTextures[mat.metalRoughTexIdx];
- if (gtex.imageUuid.isNull())
- {
- gtex.imageUuid = imageBufferToTextureUUID(gtex);
- }
- }
-
- if (mat.hasNormalTex)
- {
- gltf_texture& gtex = mTextures[mat.normalTexIdx];
- if (gtex.imageUuid.isNull())
- {
- gtex.imageUuid = imageBufferToTextureUUID(gtex);
- }
- }
-
- if (mat.hasOcclusionTex)
- {
- gltf_texture& gtex = mTextures[mat.occlusionTexIdx];
- if (gtex.imageUuid.isNull())
- {
- gtex.imageUuid = imageBufferToTextureUUID(gtex);
- }
- }
-
- if (mat.hasEmissiveTex)
- {
- gltf_texture& gtex = mTextures[mat.emissiveTexIdx];
- if (gtex.imageUuid.isNull())
- {
- gtex.imageUuid = imageBufferToTextureUUID(gtex);
- }
- }
- }
-}
-
-LLUUID LLGLTFLoader::imageBufferToTextureUUID(const gltf_texture& tex)
-{
- //gltf_image& image = mImages[tex.imageIdx];
- //gltf_sampler& sampler = mSamplers[tex.samplerIdx];
-
- // fill an LLSD container with image+sampler data
-
- // upload texture
-
- // retrieve UUID
-
- return LLUUID::null;
-}
diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h
deleted file mode 100644
index 66671d1c5a..0000000000
--- a/indra/llprimitive/llgltfloader.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * @file LLGLTFLoader.h
- * @brief LLGLTFLoader class definition
- *
- * $LicenseInfo:firstyear=2022&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2022, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLGLTFLoader_H
-#define LL_LLGLTFLoader_H
-
-#include "tinygltf/tiny_gltf.h"
-
-#include "llglheaders.h"
-#include "llmodelloader.h"
-
-// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD
-
-class gltf_sampler
-{
-public:
- // Uses GL enums
- S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR
- S32 magFilter; // GL_NEAREST or GL_LINEAR
- S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
- S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
- //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored.
- std::string name; // optional, currently unused
- // extensions and extras are sampler optional fields that we don't support - at least initially
-};
-
-class gltf_image
-{
-public:// Note that glTF images are defined with row 0 at the top (opposite of OpenGL)
- U8* data; // ptr to decoded image data
- U32 size; // in bytes, regardless of channel width
- U32 width;
- U32 height;
- U32 numChannels; // range 1..4
- U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input
- U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT
-};
-
-class gltf_texture
-{
-public:
- U32 imageIdx;
- U32 samplerIdx;
- LLUUID imageUuid = LLUUID::null;
-};
-
-class gltf_render_material
-{
-public:
- std::string name;
-
- // scalar values
- LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present.
- double metalness;
- double roughness;
- double normalScale; // scale applies only to X,Y components of normal
- double occlusionScale; // strength multiplier for occlusion
- LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent)
- std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
- double alphaMask; // alpha cut-off
-
- // textures
- U32 baseColorTexIdx; // always sRGB encoded
- U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel
- U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0)
- U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded
- U32 emissiveTexIdx; // always stored as sRGB, in nits (candela / meter^2)
-
- // texture coordinates
- U32 baseColorTexCoords;
- U32 metalRoughTexCoords;
- U32 normalTexCoords;
- U32 occlusionTexCoords;
- U32 emissiveTexCoords;
-
- // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??
-
- bool hasPBR;
- bool hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex;
-
- // This field is populated after upload
- LLUUID material_uuid = LLUUID::null;
-
-};
-
-class gltf_mesh
-{
-public:
- std::string name;
-
- // TODO add mesh import DJH 2022-04
-
-};
-
-class LLGLTFLoader : public LLModelLoader
-{
- public:
- typedef std::map material_map;
-
- LLGLTFLoader(std::string filename,
- S32 lod,
- LLModelLoader::load_callback_t load_cb,
- LLModelLoader::joint_lookup_func_t joint_lookup_func,
- LLModelLoader::texture_load_func_t texture_load_func,
- LLModelLoader::state_callback_t state_cb,
- void * opaque_userdata,
- JointTransformMap & jointTransformMap,
- JointNameSet & jointsFromNodes,
- std::map &jointAliasMap,
- U32 maxJointsPerMesh,
- U32 modelLimit); //,
- //bool preprocess );
- virtual ~LLGLTFLoader();
-
- virtual bool OpenFile(const std::string &filename);
-
-protected:
- tinygltf::Model mGltfModel;
- bool mGltfLoaded;
- bool mMeshesLoaded;
- bool mMaterialsLoaded;
-
- std::vector mMeshes;
- std::vector mMaterials;
-
- std::vector mTextures;
- std::vector mImages;
- std::vector mSamplers;
-
-private:
- bool parseMeshes();
- void uploadMeshes();
- bool parseMaterials();
- void uploadMaterials();
- bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh);
- LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
-
- // bool mPreprocessGLTF;
-
- /* Below inherited from dae loader - unknown if/how useful here
-
- void processElement(gltfElement *element, bool &badElement, GLTF *gltf);
- void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin);
-
- material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf);
- LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf);
- LLColor4 getGltfColor(gltfElement *element);
-
- gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name);
-
- bool isNodeAJoint(gltfNode *pNode);
- void processJointNode(gltfNode *pNode, std::map &jointTransforms);
- void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform);
- void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform);
- void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform);
- void buildJointToNodeMappingFromScene(gltfElement *pRoot);
- void processJointToNodeMapping(gltfNode *pNode);
- void processChildJoints(gltfNode *pParentNode);
-
- bool verifyCount(int expected, int result);
-
- // Verify that a controller matches vertex counts
- bool verifyController(gltfController *pController);
-
- static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg);
- static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh);
-
- static LLModel *loadModelFromGltfMesh(gltfMesh *mesh);
-
- // Loads a mesh breaking it into one or more models as necessary
- // to get around volume face limitations while retaining >8 materials
- //
- bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector &models_out, U32 submodel_limit);
-
- static std::string getElementLabel(gltfElement *element);
- static size_t getSuffixPosition(std::string label);
- static std::string getLodlessLabel(gltfElement *element);
-
- static std::string preprocessGLTF(std::string filename);
- */
-
-};
-#endif // LL_LLGLTFLLOADER_H
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 4e3e49ec9f..00ef79ce7f 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -66,7 +66,12 @@ LLModel::~LLModel()
{
if (mDecompID >= 0)
{
- LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID);
+ // can be null on shutdown
+ LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
+ if (decomp)
+ {
+ decomp->deleteDecomposition(mDecompID);
+ }
}
mPhysics.mMesh.clear();
}
@@ -334,6 +339,162 @@ void LLModel::normalizeVolumeFaces()
}
}
+void LLModel::normalizeVolumeFacesAndWeights()
+{
+ if (!mVolumeFaces.empty())
+ {
+ LLVector4a min, max;
+
+ // For all of the volume faces
+ // in the model, loop over
+ // them and see what the extents
+ // of the volume along each axis.
+ min = mVolumeFaces[0].mExtents[0];
+ max = mVolumeFaces[0].mExtents[1];
+
+ for (U32 i = 1; i < mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = mVolumeFaces[i];
+
+ update_min_max(min, max, face.mExtents[0]);
+ update_min_max(min, max, face.mExtents[1]);
+
+ if (face.mTexCoords)
+ {
+ LLVector2& min_tc = face.mTexCoordExtents[0];
+ LLVector2& max_tc = face.mTexCoordExtents[1];
+
+ min_tc = face.mTexCoords[0];
+ max_tc = face.mTexCoords[0];
+
+ for (S32 j = 1; j < face.mNumVertices; ++j)
+ {
+ update_min_max(min_tc, max_tc, face.mTexCoords[j]);
+ }
+ }
+ else
+ {
+ face.mTexCoordExtents[0].set(0, 0);
+ face.mTexCoordExtents[1].set(1, 1);
+ }
+ }
+
+ // Now that we have the extents of the model
+ // we can compute the offset needed to center
+ // the model at the origin.
+
+ // Compute center of the model
+ // and make it negative to get translation
+ // needed to center at origin.
+ LLVector4a trans;
+ trans.setAdd(min, max);
+ trans.mul(-0.5f);
+
+ // Compute the total size along all
+ // axes of the model.
+ LLVector4a size;
+ size.setSub(max, min);
+
+ // Prevent division by zero.
+ F32 x = size[0];
+ F32 y = size[1];
+ F32 z = size[2];
+ F32 w = size[3];
+ if (fabs(x) < F_APPROXIMATELY_ZERO)
+ {
+ x = 1.0;
+ }
+ if (fabs(y) < F_APPROXIMATELY_ZERO)
+ {
+ y = 1.0;
+ }
+ if (fabs(z) < F_APPROXIMATELY_ZERO)
+ {
+ z = 1.0;
+ }
+ size.set(x, y, z, w);
+
+ // Compute scale as reciprocal of size
+ LLVector4a scale;
+ scale.splat(1.f);
+ scale.div(size);
+
+ LLVector4a inv_scale(1.f);
+ inv_scale.div(scale);
+
+ for (U32 i = 0; i < mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = mVolumeFaces[i];
+
+ // We shrink the extents so
+ // that they fall within
+ // the unit cube.
+ // VFExtents change
+ face.mExtents[0].add(trans);
+ face.mExtents[0].mul(scale);
+
+ face.mExtents[1].add(trans);
+ face.mExtents[1].mul(scale);
+
+ // For all the positions, we scale
+ // the positions to fit within the unit cube.
+ LLVector4a* pos = (LLVector4a*)face.mPositions;
+ LLVector4a* norm = (LLVector4a*)face.mNormals;
+ LLVector4a* t = (LLVector4a*)face.mTangents;
+
+ for (S32 j = 0; j < face.mNumVertices; ++j)
+ {
+ pos[j].add(trans);
+ pos[j].mul(scale);
+ if (norm && !norm[j].equals3(LLVector4a::getZero()))
+ {
+ norm[j].mul(inv_scale);
+ norm[j].normalize3();
+ }
+
+ if (t)
+ {
+ F32 w = t[j].getF32ptr()[3];
+ t[j].mul(inv_scale);
+ t[j].normalize3();
+ t[j].getF32ptr()[3] = w;
+ }
+ }
+ }
+
+ weight_map old_weights = mSkinWeights;
+ mSkinWeights.clear();
+ mPosition.clear();
+
+ for (auto& weights : old_weights)
+ {
+ LLVector4a pos(weights.first.mV[VX], weights.first.mV[VY], weights.first.mV[VZ]);
+ pos.add(trans);
+ pos.mul(scale);
+ LLVector3 scaled_pos(pos.getF32ptr());
+ mPosition.push_back(scaled_pos);
+ mSkinWeights[scaled_pos] = weights.second;
+ }
+
+ // mNormalizedScale is the scale at which
+ // we would need to multiply the model
+ // by to get the original size of the
+ // model instead of the normalized size.
+ LLVector4a normalized_scale;
+ normalized_scale.splat(1.f);
+ normalized_scale.div(scale);
+ mNormalizedScale.set(normalized_scale.getF32ptr());
+ mNormalizedTranslation.set(trans.getF32ptr());
+ mNormalizedTranslation *= -1.f;
+
+ // remember normalized scale so original dimensions can be recovered for mesh processing (i.e. tangent generation)
+ for (auto& face : mVolumeFaces)
+ {
+ face.mNormalizedScale = mNormalizedScale;
+ }
+ }
+}
+
void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const
{
scale_out = mNormalizedScale;
@@ -662,7 +823,7 @@ LLSD LLModel::writeModel(
bool upload_skin,
bool upload_joints,
bool lock_scale_if_joint_position,
- bool nowrite,
+ EWriteModelMode write_mode,
bool as_slm,
int submodel_id)
{
@@ -941,10 +1102,10 @@ LLSD LLModel::writeModel(
}
}
- return writeModelToStream(ostr, mdl, nowrite, as_slm);
+ return writeModelToStream(ostr, mdl, write_mode, as_slm);
}
-LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, bool nowrite, bool as_slm)
+LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, EWriteModelMode write_mode, bool as_slm)
{
std::string::size_type cur_offset = 0;
@@ -1006,7 +1167,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, bool nowrite, bo
}
}
- if (!nowrite)
+ if (write_mode == WRITE_HUMAN)
+ {
+ ostr << mdl;
+ }
+ else if (write_mode == WRITE_BINARY)
{
LLSDSerialize::toBinary(header, ostr);
@@ -1561,11 +1726,21 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi
{
ret["joint_names"][i] = mJointNames[i];
+ // For model to work at all there must be a matching bind matrix,
+ // so supply an indentity one if it isn't true
+ // Note: can build an actual bind matrix from joints
+ const LLMatrix4a& inv_bind = mInvBindMatrix.size() > i ? mInvBindMatrix[i] : LLMatrix4a::identity();
+ if (i >= mInvBindMatrix.size())
+ {
+ LL_WARNS("MESHSKININFO") << "Joint index " << i << " (" << mJointNames[i] << ") exceeds inverse bind matrix size "
+ << mInvBindMatrix.size() << LL_ENDL;
+ }
+
for (U32 j = 0; j < 4; j++)
{
for (U32 k = 0; k < 4; k++)
{
- ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k];
+ ret["inverse_bind_matrix"][i][j * 4 + k] = inv_bind.mMatrix[j][k];
}
}
}
@@ -1578,15 +1753,25 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi
}
}
- if ( include_joints && mAlternateBindMatrix.size() > 0 )
+ // optional 'joint overrides'
+ if (include_joints && mAlternateBindMatrix.size() > 0)
{
for (U32 i = 0; i < mJointNames.size(); ++i)
{
+ // If there is not enough to match mJointNames,
+ // either supply no alternate matrixes at all or supply
+ // replacements
+ const LLMatrix4a& alt_bind = mAlternateBindMatrix.size() > i ? mAlternateBindMatrix[i] : LLMatrix4a::identity();
+ if (i >= mAlternateBindMatrix.size())
+ {
+ LL_WARNS("MESHSKININFO") << "Joint index " << i << " (" << mJointNames[i] << ") exceeds alternate bind matrix size "
+ << mAlternateBindMatrix.size() << LL_ENDL;
+ }
for (U32 j = 0; j < 4; j++)
{
for (U32 k = 0; k < 4; k++)
{
- ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k];
+ ret["alt_inverse_bind_matrix"][i][j * 4 + k] = alt_bind.mMatrix[j][k];
}
}
}
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index fe28926720..6501b3dc50 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -160,6 +160,12 @@ public:
bool loadSkinInfo(LLSD& header, std::istream& is);
bool loadDecomposition(LLSD& header, std::istream& is);
+ enum EWriteModelMode
+ {
+ WRITE_NO = 0,
+ WRITE_BINARY,
+ WRITE_HUMAN,
+ };
static LLSD writeModel(
std::ostream& ostr,
LLModel* physics,
@@ -171,14 +177,14 @@ public:
bool upload_skin,
bool upload_joints,
bool lock_scale_if_joint_position,
- bool nowrite = false,
+ EWriteModelMode write_mode = WRITE_BINARY,
bool as_slm = false,
int submodel_id = 0);
static LLSD writeModelToStream(
std::ostream& ostr,
LLSD& mdl,
- bool nowrite = false, bool as_slm = false);
+ EWriteModelMode write_mode = WRITE_BINARY, bool as_slm = false);
void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); }
@@ -202,6 +208,7 @@ public:
void sortVolumeFacesByMaterialName();
void normalizeVolumeFaces();
+ void normalizeVolumeFacesAndWeights();
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void remapVolumeFaces();
void optimizeVolumeFaces();
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 7facd53a72..0383659f62 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -33,6 +33,7 @@
#include "llmatrix4a.h"
#include
+#include
std::list LLModelLoader::sActiveLoaderList;
@@ -113,7 +114,9 @@ LLModelLoader::LLModelLoader(
JointTransformMap& jointTransformMap,
JointNameSet& jointsFromNodes,
JointMap& legalJointNamesMap,
- U32 maxJointsPerMesh)
+ U32 maxJointsPerMesh,
+ U32 modelLimit,
+ U32 debugMode)
: mJointList( jointTransformMap )
, mJointsFromNode( jointsFromNodes )
, LLThread("Model Loader")
@@ -121,7 +124,6 @@ LLModelLoader::LLModelLoader(
, mLod(lod)
, mTrySLM(false)
, mFirstTransform(true)
-, mNumOfFetchingTextures(0)
, mLoadCallback(load_cb)
, mJointLookupFunc(joint_lookup_func)
, mTextureLoadFunc(texture_load_func)
@@ -132,7 +134,10 @@ LLModelLoader::LLModelLoader(
, mNoNormalize(false)
, mNoOptimize(false)
, mCacheOnlyHitIfRigged(false)
+, mTexturesNeedScaling(false)
, mMaxJointsPerMesh(maxJointsPerMesh)
+, mGeneratedModelLimit(modelLimit)
+, mDebugMode(debugMode)
, mJointMap(legalJointNamesMap)
{
assert_main_thread();
@@ -149,7 +154,44 @@ LLModelLoader::~LLModelLoader()
void LLModelLoader::run()
{
mWarningsArray.clear();
- doLoadModel();
+ try
+ {
+ doLoadModel();
+ }
+ // Model loader isn't mission critical, so we just log all exceptions
+ catch (const LLException& e)
+ {
+ LL_WARNS("THREAD") << "LLException in model loader: " << e.what() << "" << LL_ENDL;
+ LLSD args;
+ args["Message"] = "UnknownException";
+ args["FILENAME"] = mFilename;
+ args["EXCEPTION"] = e.what();
+ mWarningsArray.append(args);
+ setLoadState(ERROR_PARSING);
+ }
+ catch (const std::exception& e)
+ {
+ LL_WARNS() << "Exception in LLModelLoader::run: " << e.what() << LL_ENDL;
+ LLSD args;
+ args["Message"] = "UnknownException";
+ args["FILENAME"] = mFilename;
+ args["EXCEPTION"] = e.what();
+ mWarningsArray.append(args);
+ setLoadState(ERROR_PARSING);
+ }
+ catch (...)
+ {
+ LOG_UNHANDLED_EXCEPTION("LLModelLoader");
+ LLSD args;
+ args["Message"] = "UnknownException";
+ args["FILENAME"] = mFilename;
+ args["EXCEPTION"] = boost::current_exception_diagnostic_information();
+ mWarningsArray.append(args);
+ setLoadState(ERROR_PARSING);
+ }
+
+ // todo: we are inside of a thread, push this into main thread worker,
+ // not into doOnIdleOneTime that laks tread safety
doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
}
@@ -201,7 +243,9 @@ bool LLModelLoader::doLoadModel()
}
}
- return OpenFile(mFilename);
+ bool res = OpenFile(mFilename);
+ dumpDebugData(); // conditional on mDebugMode
+ return res;
}
void LLModelLoader::setLoadState(U32 state)
@@ -466,6 +510,148 @@ bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector inv_bind;
+ std::map alt_bind;
+ for (LLPointer& mdl : mModelList)
+ {
+
+ file << "Model name: " << mdl->mLabel << "\n";
+ const LLMeshSkinInfo& skin_info = mdl->mSkinInfo;
+ file << "Shape Bind matrix: " << skin_info.mBindShapeMatrix << "\n";
+ file << "Skin Weights count: " << (S32)mdl->mSkinWeights.size() << "\n";
+
+ // some objects might have individual bind matrices,
+ // but for now it isn't accounted for
+ size_t joint_count = skin_info.mJointNames.size();
+ for (size_t i = 0; i< joint_count;i++)
+ {
+ const std::string& joint = skin_info.mJointNames[i];
+ if (skin_info.mInvBindMatrix.size() > i)
+ {
+ inv_bind[joint] = skin_info.mInvBindMatrix[i];
+ }
+ if (skin_info.mAlternateBindMatrix.size() > i)
+ {
+ alt_bind[joint] = skin_info.mAlternateBindMatrix[i];
+ }
+ }
+ }
+
+ file << "\nInv Bind matrices.\n";
+ for (auto& bind : inv_bind)
+ {
+ file << "Joint: " << bind.first << " Matrix: " << bind.second << "\n";
+ }
+
+ file << "\nAlt Bind matrices.\n";
+ for (auto& bind : alt_bind)
+ {
+ file << "Joint: " << bind.first << " Matrix: " << bind.second << "\n";
+ }
+
+ if (mDebugMode == 2)
+ {
+ S32 model_count = 0;
+ for (LLPointer& mdl : mModelList)
+ {
+ const LLVolume::face_list_t &face_list = mdl->getVolumeFaces();
+ for (S32 face = 0; face < face_list.size(); face++)
+ {
+ const LLVolumeFace& vf = face_list[face];
+ file << "\nModel: " << mdl->mLabel
+ << " face " << face
+ << " has " << vf.mNumVertices
+ << " vertices and " << vf.mNumIndices
+ << " indices " << "\n";
+
+ file << "\nPositions for model: " << mdl->mLabel << " face " << face << "\n";
+
+ for (S32 pos = 0; pos < vf.mNumVertices; ++pos)
+ {
+ file << vf.mPositions[pos] << " ";
+ }
+
+ file << "\n\nIndices for model: " << mdl->mLabel << " face " << face << "\n";
+
+ for (S32 ind = 0; ind < vf.mNumIndices; ++ind)
+ {
+ file << vf.mIndices[ind] << " ";
+ }
+ }
+
+ file << "\n\nWeights for model: " << mdl->mLabel;
+ for (auto& weights : mdl->mSkinWeights)
+ {
+ file << "\nVertex: " << weights.first << " Weights: ";
+ for (auto& weight : weights.second)
+ {
+ file << weight.mJointIdx << ":" << weight.mWeight << " ";
+ }
+ }
+
+ file << "\n";
+ model_count++;
+ if (model_count == 5)
+ {
+ file << "Too many models, stopping at 5.\n";
+ break;
+ }
+ }
+ }
+ else if (mDebugMode > 2)
+ {
+ file << "\nModel LLSDs\n";
+ S32 model_count = 0;
+ // some files contain too many models, so stop at 5.
+ for (LLPointer& mdl : mModelList)
+ {
+ const LLMeshSkinInfo& skin_info = mdl->mSkinInfo;
+ size_t joint_count = skin_info.mJointNames.size();
+ size_t alt_count = skin_info.mAlternateBindMatrix.size();
+
+ LLModel::writeModel(
+ file,
+ nullptr,
+ mdl,
+ nullptr,
+ nullptr,
+ nullptr,
+ mdl->mPhysics,
+ joint_count > 0,
+ alt_count > 0,
+ false,
+ LLModel::WRITE_HUMAN,
+ false,
+ mdl->mSubmodelID);
+
+ file << "\n";
+ model_count++;
+ if (model_count == 5)
+ {
+ file << "Too many models, stopping at 5.\n";
+ break;
+ }
+ }
+ }
+}
//called in the main thread
void LLModelLoader::loadTextures()
@@ -484,7 +670,7 @@ void LLModelLoader::loadTextures()
if(!material.mDiffuseMapFilename.empty())
{
- mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData);
+ mTextureLoadFunc(material, mOpaqueData);
}
}
}
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
index 530e61e2b8..335d809386 100644
--- a/indra/llprimitive/llmodelloader.h
+++ b/indra/llprimitive/llmodelloader.h
@@ -36,7 +36,7 @@ class LLJoint;
typedef std::map JointTransformMap;
typedef std::map::iterator JointTransformMapIt;
-typedef std::map JointMap;
+typedef std::map> JointMap;
typedef std::deque JointNameSet;
const S32 SLM_SUPPORTED_VERSION = 3;
@@ -109,8 +109,10 @@ public:
bool mTrySLM;
bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)
+ bool mTexturesNeedScaling;
model_list mModelList;
+ // The scene is pretty much what ends up getting loaded for upload. Basically assign things to this guy if you want something uploaded.
scene mScene;
typedef std::queue > model_queue;
@@ -119,10 +121,16 @@ public:
model_queue mPhysicsQ;
//map of avatar joints as named in COLLADA assets to internal joint names
+ // Do not use this for anything other than looking up the name of a joint. This is populated elsewhere.
JointMap mJointMap;
+
+ // The joint list is what you want to use to actually setup the specific joint transformations.
JointTransformMap& mJointList;
JointNameSet& mJointsFromNode;
+
+
U32 mMaxJointsPerMesh;
+ U32 mDebugMode; // see dumDebugData() for details
LLModelLoader(
std::string filename,
@@ -135,7 +143,9 @@ public:
JointTransformMap& jointTransformMap,
JointNameSet& jointsFromNodes,
JointMap& legalJointNamesMap,
- U32 maxJointsPerMesh);
+ U32 maxJointsPerMesh,
+ U32 modelLimit,
+ U32 debugMode);
virtual ~LLModelLoader();
virtual void setNoNormalize() { mNoNormalize = true; }
@@ -161,9 +171,6 @@ public:
void stretch_extents(const LLModel* model, const LLMatrix4& mat);
- S32 mNumOfFetchingTextures ; // updated in the main thread
- bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread.
-
bool verifyCount( int expected, int result );
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
@@ -192,6 +199,7 @@ public:
const LLSD logOut() const { return mWarningsArray; }
void clearLog() { mWarningsArray.clear(); }
+ void dumpDebugData();
protected:
@@ -203,6 +211,7 @@ protected:
bool mRigValidJointUpload;
U32 mLegacyRigFlags;
+ U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
bool mNoNormalize;
bool mNoOptimize;
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 97f01da084..d37b16ce0c 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -582,7 +582,14 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num);
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num);
- image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
+ if (image_gl && image_raw)
+ {
+ image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
+ }
+ else
+ {
+ llassert(false); //images were just inserted by nextOpenPos, they shouldn't be missing
+ }
return gi;
}
@@ -766,7 +773,12 @@ bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U1
{
LLImageRaw* image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, bitmap_num);
llassert(!mIsFallback);
- llassert(image_raw && (image_raw->getComponents() == 4));
+ if (!image_raw)
+ {
+ llassert(false);
+ return false;
+ }
+ llassert(image_raw->getComponents() == 4);
// NOTE: inspired by LLImageRaw::setSubImage()
U32* image_data = (U32*)image_raw->getData();
@@ -794,10 +806,17 @@ bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U1
void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
{
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, bitmap_num);
- LLImageDataLock lock(image_raw);
llassert(!mIsFallback);
- llassert(image_raw && (image_raw->getComponents() == 2));
+ if (!image_raw)
+ {
+ llassert(false);
+ return;
+ }
+
+ LLImageDataLock lock(image_raw);
+
+ llassert(image_raw->getComponents() == 2);
U8 *target = image_raw->getData();
llassert(target);
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index b062eca132..9cd5dc8145 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -1079,8 +1079,8 @@ void LLGLSLShader::bind()
void LLGLSLShader::bind(U8 variant)
{
- llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS);
- llassert(variant < LLGLSLShader::NUM_GLTF_VARIANTS);
+ llassert_always(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS);
+ llassert_always(variant < LLGLSLShader::NUM_GLTF_VARIANTS);
mGLTFVariants[variant].bind();
}
@@ -1088,7 +1088,7 @@ void LLGLSLShader::bind(bool rigged)
{
if (rigged)
{
- llassert(mRiggedVariant);
+ llassert_always(mRiggedVariant);
mRiggedVariant->bind();
}
else
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 3f8903ca09..1db36d91f9 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1870,8 +1870,17 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes);
if(!imageraw->allocateDataSize(width, height, ncomponents, glbytes))
{
- LL_WARNS() << "Memory allocation failed for reading back texture. Size is: " << glbytes << LL_ENDL ;
- LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ;
+ constexpr S64 MAX_GL_BYTES = 2048 * 2048;
+ if (glbytes > 0 && glbytes <= MAX_GL_BYTES)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Memory allocation failed for reading back texture. Data size: " << glbytes << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "Memory allocation failed for reading back texture. Data size is: " << glbytes << LL_ENDL;
+ LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL;
+ }
return false ;
}
@@ -1882,8 +1891,18 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
{
if(!imageraw->allocateDataSize(width, height, ncomponents))
{
- LL_WARNS() << "Memory allocation failed for reading back texture." << LL_ENDL ;
- LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ;
+ constexpr F32 MAX_IMAGE_SIZE = 2048 * 2048;
+ F32 size = (F32)width * (F32)height * (F32)ncomponents;
+ if (size > 0 && size <= MAX_IMAGE_SIZE)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS() << "Memory allocation failed for reading back texture. Data size: " << size << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "Memory allocation failed for reading back texture." << LL_ENDL;
+ LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL;
+ }
return false ;
}
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 38bc5ff331..0b0d69812f 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -492,22 +492,6 @@ U32 LLRenderTarget::getNumTextures() const
void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
{
gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index), filter_options == LLTexUnit::TFO_TRILINEAR || filter_options == LLTexUnit::TFO_ANISOTROPIC);
-
- bool isSRGB = false;
- llassert(mInternalFormat.size() > index);
- switch (mInternalFormat[index])
- {
- case GL_SRGB:
- case GL_SRGB8:
- case GL_SRGB_ALPHA:
- case GL_SRGB8_ALPHA8:
- isSRGB = true;
- break;
-
- default:
- break;
- }
-
gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
}
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index a0314cb5f2..908e94b24c 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -18,6 +18,7 @@ set(llui_SOURCE_FILES
llbadgeowner.cpp
llbutton.cpp
llchatentry.cpp
+ llchatmentionhelper.cpp
llcheckboxctrl.cpp
llclipboard.cpp
llcombobox.cpp
@@ -130,6 +131,7 @@ set(llui_HEADER_FILES
llcallbackmap.h
llchatentry.h
llchat.h
+ llchatmentionhelper.h
llcheckboxctrl.h
llclipboard.h
llcombobox.h
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index cf3569683e..bb0b8ce04f 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -126,7 +126,7 @@ public:
void setSelected(bool is_selected);
- bool getCollapsible() { return mCollapsible; };
+ bool getCollapsible() const { return mCollapsible; };
void setCollapsible(bool collapsible) { mCollapsible = collapsible; };
void changeOpenClose(bool is_open);
@@ -140,7 +140,7 @@ public:
S32 notify(const LLSD& info);
bool notifyChildren(const LLSD& info);
- void draw();
+ virtual void draw();
void storeOpenCloseState();
void restoreOpenCloseState();
@@ -181,7 +181,7 @@ public:
void setHeaderVisible(bool value);
- bool getHeaderVisible() { return mHeaderVisible;}
+ bool getHeaderVisible() const { return mHeaderVisible;}
S32 mExpandedHeight; // Height of expanded ctrl.
// Used to restore height after expand.
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index da5afd0386..7506cd99c0 100644
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -45,12 +45,14 @@ LLChatEntry::LLChatEntry(const Params& p)
mExpandLinesCount(p.expand_lines_count),
mPrevLinesCount(0),
mSingleLineMode(false),
- mPrevExpandedLineCount(S32_MAX)
+ mPrevExpandedLineCount(S32_MAX),
+ mCurrentInput("")
{
// Initialize current history line iterator
mCurrentHistoryLine = mLineHistory.begin();
mAutoIndent = false;
+ mShowChatMentionPicker = true;
keepSelectionOnReturn(true);
}
@@ -189,6 +191,7 @@ bool LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
needsReflow();
}
+ mCurrentInput = "";
break;
case KEY_UP:
@@ -196,6 +199,11 @@ bool LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin())
{
+ if (mCurrentHistoryLine == mLineHistory.end())
+ {
+ mCurrentInput = getText();
+ }
+
setText(*(--mCurrentHistoryLine));
endOfDoc();
}
@@ -210,16 +218,15 @@ bool LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
case KEY_DOWN:
if (mHasHistory && MASK_CONTROL == mask)
{
- if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) )
+ if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1))
{
setText(*(++mCurrentHistoryLine));
endOfDoc();
}
- else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) )
+ else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1))
{
mCurrentHistoryLine++;
- std::string empty("");
- setText(empty);
+ setText(mCurrentInput);
needsReflow();
endOfDoc();
}
diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h
index 5621ede1e7..9a0e8ee91e 100644
--- a/indra/llui/llchatentry.h
+++ b/indra/llui/llchatentry.h
@@ -101,6 +101,8 @@ private:
S32 mExpandLinesCount;
S32 mPrevLinesCount;
S32 mPrevExpandedLineCount;
+
+ std::string mCurrentInput;
};
#endif /* LLCHATENTRY_H_ */
diff --git a/indra/llui/llchatmentionhelper.cpp b/indra/llui/llchatmentionhelper.cpp
new file mode 100644
index 0000000000..5745389a58
--- /dev/null
+++ b/indra/llui/llchatmentionhelper.cpp
@@ -0,0 +1,158 @@
+/**
+* @file llchatmentionhelper.cpp
+*
+* $LicenseInfo:firstyear=2025&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2025, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+
+#include "llchatmentionhelper.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "lluictrl.h"
+
+constexpr char CHAT_MENTION_HELPER_FLOATER[] = "chat_mention_picker";
+
+bool LLChatMentionHelper::isActive(const LLUICtrl* ctrl) const
+{
+ return mHostHandle.get() == ctrl;
+}
+
+bool LLChatMentionHelper::isCursorInNameMention(const LLWString& wtext, S32 cursor_pos, S32* mention_start_pos) const
+{
+ if (cursor_pos <= 0 || cursor_pos > static_cast(wtext.size()))
+ return false;
+
+ // Find the beginning of the current word
+ S32 start = cursor_pos - 1;
+ while (start > 0 && wtext[start - 1] != U32(' ') && wtext[start - 1] != U32('\n'))
+ {
+ --start;
+ }
+
+ if (wtext[start] != U32('@'))
+ return false;
+
+ if (mention_start_pos)
+ *mention_start_pos = start;
+
+ S32 word_length = cursor_pos - start;
+
+ if (word_length == 1)
+ {
+ return true;
+ }
+
+ // Get the name after '@'
+ std::string name = wstring_to_utf8str(wtext.substr(start + 1, word_length - 1));
+ LLStringUtil::toLower(name);
+ for (const auto& av_name : mAvatarNames)
+ {
+ if (av_name == name || av_name.find(name) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void LLChatMentionHelper::showHelper(LLUICtrl* host_ctrl, S32 local_x, S32 local_y, const std::string& av_name, std::function cb)
+{
+ if (mHelperHandle.isDead())
+ {
+ LLFloater* av_picker_floater = LLFloaterReg::getInstance(CHAT_MENTION_HELPER_FLOATER);
+ mHelperHandle = av_picker_floater->getHandle();
+ mHelperCommitConn = av_picker_floater->setCommitCallback([&](LLUICtrl* ctrl, const LLSD& param) { onCommitName(param.asString()); });
+ }
+ setHostCtrl(host_ctrl);
+ mNameCommitCb = cb;
+
+ S32 floater_x, floater_y;
+ if (!host_ctrl->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView))
+ {
+ LL_WARNS() << "Cannot show helper for non-floater controls." << LL_ENDL;
+ return;
+ }
+
+ LLFloater* av_picker_floater = mHelperHandle.get();
+ LLRect rect = av_picker_floater->getRect();
+ rect.setLeftTopAndSize(floater_x, floater_y + rect.getHeight(), rect.getWidth(), rect.getHeight());
+ av_picker_floater->setRect(rect);
+ if (av_picker_floater->isShown())
+ {
+ av_picker_floater->onOpen(LLSD().with("av_name", av_name));
+ }
+ else
+ {
+ av_picker_floater->openFloater(LLSD().with("av_name", av_name));
+ }
+}
+
+void LLChatMentionHelper::hideHelper(const LLUICtrl* ctrl)
+{
+ if ((ctrl && !isActive(ctrl)))
+ {
+ return;
+ }
+ setHostCtrl(nullptr);
+}
+
+bool LLChatMentionHelper::handleKey(const LLUICtrl* ctrl, KEY key, MASK mask)
+{
+ if (mHelperHandle.isDead() || !isActive(ctrl))
+ {
+ return false;
+ }
+
+ return mHelperHandle.get()->handleKey(key, mask, true);
+}
+
+void LLChatMentionHelper::onCommitName(std::string name_url)
+{
+ if (!mHostHandle.isDead() && mNameCommitCb)
+ {
+ mNameCommitCb(name_url);
+ }
+}
+
+void LLChatMentionHelper::setHostCtrl(LLUICtrl* host_ctrl)
+{
+ const LLUICtrl* pCurHostCtrl = mHostHandle.get();
+ if (pCurHostCtrl != host_ctrl)
+ {
+ mHostCtrlFocusLostConn.disconnect();
+ mHostHandle.markDead();
+ mNameCommitCb = {};
+
+ if (!mHelperHandle.isDead())
+ {
+ mHelperHandle.get()->closeFloater();
+ }
+
+ if (host_ctrl)
+ {
+ mHostHandle = host_ctrl->getHandle();
+ mHostCtrlFocusLostConn = host_ctrl->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); }));
+ }
+ }
+}
diff --git a/indra/llui/llchatmentionhelper.h b/indra/llui/llchatmentionhelper.h
new file mode 100644
index 0000000000..5f95d06f31
--- /dev/null
+++ b/indra/llui/llchatmentionhelper.h
@@ -0,0 +1,66 @@
+/**
+* @file llchatmentionhelper.h
+* @brief Header file for LLChatMentionHelper
+*
+* $LicenseInfo:firstyear=2025&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2025, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#pragma once
+
+#include "llhandle.h"
+#include "llsingleton.h"
+
+#include
+
+class LLFloater;
+class LLUICtrl;
+
+class LLChatMentionHelper : public LLSingleton
+{
+ LLSINGLETON(LLChatMentionHelper) {}
+ ~LLChatMentionHelper() override {}
+
+public:
+
+ bool isActive(const LLUICtrl* ctrl) const;
+ bool isCursorInNameMention(const LLWString& wtext, S32 cursor_pos, S32* mention_start_pos = nullptr) const;
+ void showHelper(LLUICtrl* host_ctrl, S32 local_x, S32 local_y, const std::string& av_name, std::function commit_cb);
+ void hideHelper(const LLUICtrl* ctrl = nullptr);
+
+ bool handleKey(const LLUICtrl* ctrl, KEY key, MASK mask);
+ void onCommitName(std::string name_url);
+
+ void updateAvatarList(std::vector av_names) { mAvatarNames = av_names; }
+
+protected:
+ void setHostCtrl(LLUICtrl* host_ctrl);
+ LLUICtrl* getHostCtrl() const { return mHostHandle.get(); }
+
+private:
+ LLHandle mHostHandle;
+ LLHandle mHelperHandle;
+ boost::signals2::connection mHostCtrlFocusLostConn;
+ boost::signals2::connection mHelperCommitConn;
+ std::function mNameCommitCb;
+
+ std::vector mAvatarNames;
+};
diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h
index 135f128692..4068741978 100644
--- a/indra/llui/llcheckboxctrl.h
+++ b/indra/llui/llcheckboxctrl.h
@@ -36,8 +36,8 @@
// Constants
//
-const bool RADIO_STYLE = true;
-const bool CHECK_STYLE = false;
+constexpr bool RADIO_STYLE = true;
+constexpr bool CHECK_STYLE = false;
//
// Classes
@@ -94,7 +94,7 @@ public:
// LLUICtrl interface
virtual void setValue(const LLSD& value );
virtual LLSD getValue() const;
- bool get() { return (bool)getValue().asBoolean(); }
+ bool get() const { return (bool)getValue().asBoolean(); }
void set(bool value) { setValue(value); }
virtual void setTentative(bool b);
@@ -106,7 +106,7 @@ public:
virtual void onCommit();
// LLCheckBoxCtrl interface
- virtual bool toggle() { return mButton->toggleState(); } // returns new state
+ virtual bool toggle() { return mButton->toggleState(); } // returns new state
void setBtnFocus() { mButton->setFocus(true); }
diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h
index c6dd401e85..2675d21c22 100644
--- a/indra/llui/llcontainerview.h
+++ b/indra/llui/llcontainerview.h
@@ -65,21 +65,21 @@ protected:
public:
~LLContainerView();
- /*virtual*/ bool postBuild();
- /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
+ bool postBuild() override;
+ bool addChild(LLView* view, S32 tab_group = 0) override;
- /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask);
+ bool handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleMouseUp(S32 x, S32 y, MASK mask) override;
- /*virtual*/ void draw();
- /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true);
- /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options.
+ void draw() override;
+ void reshape(S32 width, S32 height, bool called_from_parent = true) override;
+ LLRect getRequiredRect() override; // Return the height of this object, given the set options.
void setLabel(const std::string& label);
void showLabel(bool show) { mShowLabel = show; }
void setDisplayChildren(bool displayChildren);
- bool getDisplayChildren() { return mDisplayChildren; }
+ bool getDisplayChildren() const { return mDisplayChildren; }
void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;}
private:
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 3effc977db..9c516e23a4 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -112,8 +112,8 @@ public:
virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); }
virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; }
- bool getUniqueDocking() { return mUniqueDocking; }
- bool getUseTongue() { return mUseTongue; }
+ bool getUniqueDocking() const { return mUniqueDocking; }
+ bool getUseTongue() const { return mUseTongue; }
void setUseTongue(bool use_tongue) { mUseTongue = use_tongue;}
private:
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 11dbad8c09..1a00c03856 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -156,7 +156,7 @@ void LLDockControl::repositionDockable()
}
}
-bool LLDockControl::isDockVisible()
+bool LLDockControl::isDockVisible() const
{
bool res = true;
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
index 7e31330713..b6ac9c19dd 100644
--- a/indra/llui/lldockcontrol.h
+++ b/indra/llui/lldockcontrol.h
@@ -61,19 +61,19 @@ public:
void off();
void forceRecalculatePosition();
void setDock(LLView* dockWidget);
- LLView* getDock()
+ LLView* getDock() const
{
return mDockWidgetHandle.get();
}
void repositionDockable();
void drawToungue();
- bool isDockVisible();
+ bool isDockVisible() const;
// gets a rect that bounds possible positions for a dockable control (EXT-1111)
void getAllowedRect(LLRect& rect);
- S32 getTongueWidth() { return mDockTongue->getWidth(); }
- S32 getTongueHeight() { return mDockTongue->getHeight(); }
+ S32 getTongueWidth() const { return mDockTongue->getWidth(); }
+ S32 getTongueHeight() const { return mDockTongue->getHeight(); }
private:
virtual void moveDockable();
diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h
index a522e63243..73211d5292 100644
--- a/indra/llui/lldraghandle.h
+++ b/indra/llui/lldraghandle.h
@@ -66,7 +66,7 @@ public:
void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); }
S32 getMaxTitleWidth() const { return mMaxTitleWidth; }
void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; }
- LLRect getButtonsRect() { return mButtonsRect; }
+ LLRect getButtonsRect() const { return mButtonsRect; }
void setTitleVisible(bool visible);
virtual void setTitle( const std::string& title ) = 0;
diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h
index 686827d94c..685219c9f6 100644
--- a/indra/llui/llfiltereditor.h
+++ b/indra/llui/llfiltereditor.h
@@ -49,7 +49,7 @@ protected:
LLFilterEditor(const Params&);
friend class LLUICtrlFactory;
- /*virtual*/ void handleKeystroke();
+ void handleKeystroke() override;
};
#endif // LL_FILTEREDITOR_H
diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp
index c3db24c987..54f54653e2 100644
--- a/indra/llui/llflashtimer.cpp
+++ b/indra/llui/llflashtimer.cpp
@@ -85,12 +85,12 @@ void LLFlashTimer::stopFlashing()
mCurrentTickCount = 0;
}
-bool LLFlashTimer::isFlashingInProgress()
+bool LLFlashTimer::isFlashingInProgress() const
{
return mIsFlashingInProgress;
}
-bool LLFlashTimer::isCurrentlyHighlighted()
+bool LLFlashTimer::isCurrentlyHighlighted() const
{
return mIsCurrentlyHighlighted;
}
diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h
index b55ce53fc0..4ef70faf2d 100644
--- a/indra/llui/llflashtimer.h
+++ b/indra/llui/llflashtimer.h
@@ -51,8 +51,8 @@ public:
void startFlashing();
void stopFlashing();
- bool isFlashingInProgress();
- bool isCurrentlyHighlighted();
+ bool isFlashingInProgress() const;
+ bool isCurrentlyHighlighted() const;
/*
* Use this instead of deleting this object.
* The next call to tick() will return true and that will destroy this object.
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 53f39766c6..5be20bd314 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -459,6 +459,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
, mNoItemsCommentTextbox(NULL)
, mIsConsecutiveSelection(false)
, mKeepSelectionVisibleOnReshape(p.keep_selection_visible_on_reshape)
+ , mFocusOnItemClicked(true)
{
mBorderThickness = getBorderWidth();
@@ -610,7 +611,10 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
return;
}
- setFocus(true);
+ if (mFocusOnItemClicked)
+ {
+ setFocus(true);
+ }
bool select_item = !isSelected(item_pair);
@@ -1337,14 +1341,22 @@ void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string)
}
}
-bool LLFlatListViewEx::getForceShowingUnmatchedItems()
+bool LLFlatListViewEx::getForceShowingUnmatchedItems() const
{
return mForceShowingUnmatchedItems;
}
-void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show)
+void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show, bool notify_parent)
+{
+ if (mForceShowingUnmatchedItems != show)
{
mForceShowingUnmatchedItems = show;
+ if (!mFilterSubString.empty())
+ {
+ updateNoItemsMessage(mFilterSubString);
+ filterItems(false, true);
+ }
+ }
}
void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent)
@@ -1412,6 +1424,7 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)
if (visibility_changed && notify_parent)
{
+ rearrangeItems();
notifyParentItemsRectChanged();
}
}
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 6d75e9f282..1f22360a8a 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -113,7 +113,7 @@ public:
};
// disable traversal when finding widget to hand focus off to
- /*virtual*/ bool canFocusChildren() const { return false; }
+ /*virtual*/ bool canFocusChildren() const override { return false; }
/**
* Connects callback to signal called when Return key is pressed.
@@ -121,15 +121,15 @@ public:
boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); }
/** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */
- virtual void reshape(S32 width, S32 height, bool called_from_parent = true);
+ virtual void reshape(S32 width, S32 height, bool called_from_parent = true) override;
/** Returns full rect of child panel */
const LLRect& getItemsRect() const;
- LLRect getRequiredRect() { return getItemsRect(); }
+ LLRect getRequiredRect() override { return getItemsRect(); }
/** Returns distance between items */
- const S32 getItemsPad() { return mItemPad; }
+ const S32 getItemsPad() const { return mItemPad; }
/**
* Adds and item and LLSD value associated with it to the list at specified position
@@ -264,13 +264,13 @@ public:
void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; }
/** Get number of selected items in the list */
- U32 numSelected() const {return static_cast(mSelectedItemPairs.size()); }
+ U32 numSelected() const { return static_cast(mSelectedItemPairs.size()); }
/** Get number of (visible) items in the list */
U32 size(const bool only_visible_items = true) const;
/** Removes all items from the list */
- virtual void clear();
+ virtual void clear() override;
/**
* Removes all items that can be detached from the list but doesn't destroy
@@ -294,10 +294,12 @@ public:
void scrollToShowFirstSelectedItem();
- void selectFirstItem ();
- void selectLastItem ();
+ void selectFirstItem();
+ void selectLastItem();
- virtual S32 notify(const LLSD& info) ;
+ virtual S32 notify(const LLSD& info) override;
+
+ void setFocusOnItemClicked(bool b) { mFocusOnItemClicked = b; }
virtual ~LLFlatListView();
@@ -346,8 +348,8 @@ protected:
virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection);
- virtual bool canSelectAll() const;
- virtual void selectAll();
+ virtual bool canSelectAll() const override;
+ virtual void selectAll() override;
virtual bool isSelected(item_pair_t* item_pair) const;
@@ -364,15 +366,15 @@ protected:
*/
void notifyParentItemsRectChanged();
- virtual bool handleKeyHere(KEY key, MASK mask);
+ virtual bool handleKeyHere(KEY key, MASK mask) override;
- virtual bool postBuild();
+ virtual bool postBuild() override;
- virtual void onFocusReceived();
+ virtual void onFocusReceived() override;
- virtual void onFocusLost();
+ virtual void onFocusLost() override;
- virtual void draw();
+ virtual void draw() override;
LLRect getLastSelectedItemRect();
@@ -423,6 +425,8 @@ private:
bool mKeepSelectionVisibleOnReshape;
+ bool mFocusOnItemClicked;
+
/** All pairs of the list */
pairs_list_t mItemPairs;
@@ -478,15 +482,19 @@ public:
void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; }
void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; }
- bool getForceShowingUnmatchedItems();
+ bool getForceShowingUnmatchedItems() const;
- void setForceShowingUnmatchedItems(bool show);
+ /**
+ * Sets filtered out items to stay visible. Can result in rect changes,
+ * so can notify_parent if rect changes
+ */
+ void setForceShowingUnmatchedItems(bool show, bool notify_parent);
/**
* Sets up new filter string and filters the list.
*/
void setFilterSubString(const std::string& filter_str, bool notify_parent);
- std::string getFilterSubString() { return mFilterSubString; }
+ std::string getFilterSubString() const { return mFilterSubString; }
/**
* Filters the list, rearranges and notifies parent about shape changes.
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 4b904f09e0..fd07b2ec5d 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2165,7 +2165,7 @@ void LLFloater::setCanDrag(bool can_drag)
}
}
-bool LLFloater::getCanDrag()
+bool LLFloater::getCanDrag() const
{
return mDragHandle->getEnabled();
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index eae2435117..9e1594bdd2 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -46,24 +46,24 @@ class LLMultiFloater;
class LLFloater;
-const bool RESIZE_YES = true;
-const bool RESIZE_NO = false;
+constexpr bool RESIZE_YES = true;
+constexpr bool RESIZE_NO = false;
-const bool DRAG_ON_TOP = false;
-const bool DRAG_ON_LEFT = true;
+constexpr bool DRAG_ON_TOP = false;
+constexpr bool DRAG_ON_LEFT = true;
-const bool MINIMIZE_YES = true;
-const bool MINIMIZE_NO = false;
+constexpr bool MINIMIZE_YES = true;
+constexpr bool MINIMIZE_NO = false;
-const bool CLOSE_YES = true;
-const bool CLOSE_NO = false;
+constexpr bool CLOSE_YES = true;
+constexpr bool CLOSE_NO = false;
-const bool ADJUST_VERTICAL_YES = true;
-const bool ADJUST_VERTICAL_NO = false;
+constexpr bool ADJUST_VERTICAL_YES = true;
+constexpr bool ADJUST_VERTICAL_NO = false;
-const F32 CONTEXT_CONE_IN_ALPHA = 0.f;
-const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
-const F32 CONTEXT_CONE_FADE_TIME = .08f;
+constexpr F32 CONTEXT_CONE_IN_ALPHA = 0.f;
+constexpr F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
+constexpr F32 CONTEXT_CONE_FADE_TIME = .08f;
namespace LLFloaterEnums
{
@@ -228,7 +228,7 @@ public:
/*virtual*/ void setIsChrome(bool is_chrome);
/*virtual*/ void setRect(const LLRect &rect);
void setIsSingleInstance(bool is_single_instance);
- bool getIsSingleInstance() { return mSingleInstance; }
+ bool getIsSingleInstance() const { return mSingleInstance; }
void initFloater(const Params& p);
@@ -274,17 +274,17 @@ public:
static bool isShown(const LLFloater* floater);
static bool isVisible(const LLFloater* floater);
static bool isMinimized(const LLFloater* floater);
- bool isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts
+ bool isFirstLook() const { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts
virtual bool isFrontmost();
- bool isDependent() { return !mDependeeHandle.isDead(); }
+ bool isDependent() const { return !mDependeeHandle.isDead(); }
void setCanMinimize(bool can_minimize);
void setCanClose(bool can_close);
void setCanTearOff(bool can_tear_off);
virtual void setCanResize(bool can_resize);
void setCanDrag(bool can_drag);
- bool getCanDrag();
+ bool getCanDrag() const;
void setHost(LLMultiFloater* host);
- bool isResizable() const { return mResizable; }
+ bool isResizable() const { return mResizable; }
void setResizeLimits( S32 min_width, S32 min_height );
void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; }
@@ -347,7 +347,7 @@ public:
virtual void setDocked(bool docked, bool pop_on_undock = true);
virtual void setTornOff(bool torn_off) { mTornOff = torn_off; }
- bool isTornOff() {return mTornOff;}
+ bool isTornOff() const { return mTornOff; }
void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;}
@@ -425,7 +425,6 @@ protected:
private:
void setForeground(bool b); // called only by floaterview
void cleanupHandles(); // remove handles to dead floaters
- void createMinimizeButton();
void buildButtons(const Params& p);
// Images and tooltips are named in the XML, but we want to look them
diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h
index a36072892c..28f6e7c66b 100644
--- a/indra/llui/llfloaterreglistener.h
+++ b/indra/llui/llfloaterreglistener.h
@@ -30,7 +30,6 @@
#define LL_LLFLOATERREGLISTENER_H
#include "lleventapi.h"
-#include
class LLSD;
diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h
index 7a49501318..73190fc984 100644
--- a/indra/llui/llflyoutbutton.h
+++ b/indra/llui/llflyoutbutton.h
@@ -54,7 +54,7 @@ protected:
LLFlyoutButton(const Params&);
friend class LLUICtrlFactory;
public:
- virtual void draw();
+ void draw() override;
void setToggleState(bool state);
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index 1fa0ac137e..89fee5c9f1 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -97,7 +97,7 @@ public:
LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; }
bool childHasKeyboardFocus( const LLView* parent ) const;
void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus );
- bool getKeystrokesOnly() { return mKeystrokesOnly; }
+ bool getKeystrokesOnly() const { return mKeystrokesOnly; }
void setKeystrokesOnly(bool keystrokes_only) { mKeystrokesOnly = keystrokes_only; }
F32 getFocusFlashAmt() const;
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 7ed10d9223..368a86ea84 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -124,11 +124,11 @@ public:
void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); }
- bool getAllowMultiSelect() { return mAllowMultiSelect; }
- bool getAllowDrag() { return mAllowDrag; }
+ bool getAllowMultiSelect() const { return mAllowMultiSelect; }
+ bool getAllowDrag() const { return mAllowDrag; }
void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; }
- bool isSingleFolderMode() { return mSingleFolderMode; }
+ bool isSingleFolderMode() const { return mSingleFolderMode; }
// Close all folders in the view
void closeAllFolders();
@@ -142,7 +142,7 @@ public:
virtual S32 getItemHeight() const;
void arrangeAll() { mArrangeGeneration++; }
- S32 getArrangeGeneration() { return mArrangeGeneration; }
+ S32 getArrangeGeneration() const { return mArrangeGeneration; }
// applies filters to control visibility of items
virtual void filter( LLFolderViewFilter& filter);
@@ -221,33 +221,34 @@ public:
void scrollToShowSelection();
void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);
void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; }
+ LLScrollContainer* getScrollContainer() { return mScrollContainer; }
LLRect getVisibleRect();
bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward);
void setShowSelectionContext(bool show) { mShowSelectionContext = show; }
bool getShowSelectionContext();
void setShowSingleSelection(bool show);
- bool getShowSingleSelection() { return mShowSingleSelection; }
- F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
- bool getUseEllipses() { return mUseEllipses; }
- S32 getSelectedCount() { return (S32)mSelectedItems.size(); }
+ bool getShowSingleSelection() const { return mShowSingleSelection; }
+ F32 getSelectionFadeElapsedTime() const { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
+ bool getUseEllipses() const { return mUseEllipses; }
+ S32 getSelectedCount() const { return (S32)mSelectedItems.size(); }
- void update(); // needs to be called periodically (e.g. once per frame)
+ void update(); // needs to be called periodically (e.g. once per frame)
- bool needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; }
- bool needsAutoRename() { return mNeedsAutoRename; }
+ bool needsAutoSelect() const { return mNeedsAutoSelect && !mAutoSelectOverride; }
+ bool needsAutoRename() const { return mNeedsAutoRename; }
void setNeedsAutoRename(bool val) { mNeedsAutoRename = val; }
void setPinningSelectedItem(bool val) { mPinningSelectedItem = val; }
void setAutoSelectOverride(bool val) { mAutoSelectOverride = val; }
- bool showItemLinkOverlays() { return mShowItemLinkOverlays; }
+ bool showItemLinkOverlays() const { return mShowItemLinkOverlays; }
void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; }
void setForceArrange(bool force) { mForceArrange = force; }
- LLPanel* getParentPanel() { return mParentPanel.get(); }
+ LLPanel* getParentPanel() const { return mParentPanel.get(); }
// DEBUG only
void dumpSelectionInformation();
@@ -255,7 +256,7 @@ public:
void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; }
- bool useLabelSuffix() { return mUseLabelSuffix; }
+ bool useLabelSuffix() const { return mUseLabelSuffix; }
virtual void updateMenu();
void finishRenamingItem( void );
@@ -391,7 +392,7 @@ public:
virtual ~LLSelectFirstFilteredItem() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
- bool wasItemSelected() { return mItemSelected || mFolderSelected; }
+ bool wasItemSelected() const { return mItemSelected || mFolderSelected; }
protected:
bool mItemSelected;
bool mFolderSelected;
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 6d0cfcba95..9ca77dbe46 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -31,11 +31,12 @@
#include "llfolderviewitem.h"
#include "llfolderview.h"
#include "llfolderviewmodel.h"
-#include "llpanel.h"
#include "llcallbacklist.h"
#include "llcriticaldamp.h"
#include "llclipboard.h"
#include "llfocusmgr.h" // gFocusMgr
+#include "llnotificationsutil.h"
+#include "llpanel.h"
#include "lltrans.h"
#include "llwindow.h"
@@ -60,7 +61,11 @@ LLUIColor LLFolderViewItem::sSearchStatusColor;
S32 LLFolderViewItem::sTopPad = 0;
LLUIImagePtr LLFolderViewItem::sFolderArrowImg;
LLUIImagePtr LLFolderViewItem::sSelectionImg;
+LLUIImagePtr LLFolderViewItem::sFavoriteImg;
+LLUIImagePtr LLFolderViewItem::sFavoriteContentImg;
LLFontGL* LLFolderViewItem::sSuffixFont = nullptr;
+LLUIColor LLFolderViewItem::sFavoriteColor;
+bool LLFolderViewItem::sColorSetInitialized = false;
// only integers can be initialized in header
const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
@@ -68,6 +73,9 @@ const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f;
const LLColor4U DEFAULT_WHITE(255, 255, 255);
+constexpr S32 FAVORITE_IMAGE_SIZE = 14;
+constexpr S32 FAVORITE_IMAGE_PAD = 3;
+
//static
LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
@@ -102,6 +110,8 @@ void LLFolderViewItem::initClass()
sTopPad = default_params.item_top_pad;
sFolderArrowImg = default_params.folder_arrow_image;
sSelectionImg = default_params.selection_image;
+ sFavoriteImg = default_params.favorite_image;
+ sFavoriteContentImg = default_params.favorite_content_image;
sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL);
sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
@@ -121,6 +131,8 @@ void LLFolderViewItem::cleanupClass()
sFonts.clear();
sFolderArrowImg = nullptr;
sSelectionImg = nullptr;
+ sFavoriteImg = nullptr;
+ sFavoriteContentImg = nullptr;
sSuffixFont = nullptr;
}
@@ -129,13 +141,15 @@ void LLFolderViewItem::cleanupClass()
LLFolderViewItem::Params::Params()
: root(),
listener(),
+ favorite_image("favorite_image"),
+ favorite_content_image("favorite_content_image"),
folder_arrow_image("folder_arrow_image"),
folder_indentation("folder_indentation"),
selection_image("selection_image"),
item_height("item_height"),
item_top_pad("item_top_pad"),
creation_date(),
- allow_wear("allow_wear", true),
+ marketplace_item("marketplace_item", false),
allow_drop("allow_drop", true),
font_color("font_color"),
font_highlight_color("font_highlight_color"),
@@ -155,6 +169,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
: LLView(p),
mLabelWidth(0),
mLabelWidthDirty(false),
+ mIsFavorite(false),
+ mHasFavorites(false),
mSuffixNeedsRefresh(false),
mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT),
mParentFolder( NULL ),
@@ -175,7 +191,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mRoot(p.root),
mViewModelItem(p.listener),
mIsMouseOverTitle(false),
- mAllowWear(p.allow_wear),
+ mMarketplaceItem(p.marketplace_item),
mAllowDrop(p.allow_drop),
mFontColor(p.font_color),
mFontHighlightColor(p.font_highlight_color),
@@ -189,6 +205,21 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mMaxFolderItemOverlap(p.max_folder_item_overlap),
mDoubleClickOverride(p.double_click_override)
{
+ if (!sColorSetInitialized)
+ {
+ sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
+ sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
+ sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE);
+ sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
+ sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
+ sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
+ sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
+ sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
+ sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
+ sFavoriteColor = LLUIColorTable::instance().getColor("InventoryFavoriteColor", DEFAULT_WHITE);
+ sColorSetInitialized = true;
+ }
+
if (mViewModelItem)
{
mViewModelItem->setFolderViewItem(this);
@@ -211,6 +242,7 @@ bool LLFolderViewItem::postBuild()
// getDisplayName() is expensive (due to internal getLabelSuffix() and name building)
// it also sets search strings so it requires a filter reset
mLabel = utf8str_to_wstring(vmi->getDisplayName());
+ mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
setToolTip(vmi->getName());
// Dirty the filter flag of the model from the view (CHUI-849)
@@ -325,6 +357,7 @@ void LLFolderViewItem::refresh()
mLabel = utf8str_to_wstring(vmi.getDisplayName());
mLabelFontBuffer.reset();
+ mIsFavorite = vmi.isFavorite() && !vmi.isItemInTrash();
setToolTip(vmi.getName());
// icons are slightly expensive to get, can be optimized
// see LLInventoryIcon::getIcon()
@@ -359,6 +392,8 @@ void LLFolderViewItem::refreshSuffix()
mIconOpen = vmi->getIconOpen();
mIconOverlay = vmi->getIconOverlay();
+ mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
+
if (mRoot->useLabelSuffix())
{
// Very Expensive!
@@ -428,6 +463,10 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
}
mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel.c_str()) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix.c_str()) + mLabelPaddingRight;
mLabelWidthDirty = false;
+ if (mIsFavorite)
+ {
+ mLabelWidth += FAVORITE_IMAGE_SIZE + FAVORITE_IMAGE_PAD;
+ }
}
*width = llmax(*width, mLabelWidth);
@@ -554,10 +593,15 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)
void LLFolderViewItem::openItem( void )
{
- if (mAllowWear || !getViewModelItem()->isItemWearable())
+ if (!mMarketplaceItem || !getViewModelItem()->isItemWearable())
{
getViewModelItem()->openItem();
}
+ else if (mMarketplaceItem)
+ {
+ // Wearing an object from any listing, active or not, is verbotten
+ LLNotificationsUtil::add("AlertMerchantListingCannotWear");
+ }
}
void LLFolderViewItem::rename(const std::string& new_name)
@@ -771,6 +815,45 @@ void LLFolderViewItem::drawOpenFolderArrow()
}
}
+void LLFolderViewItem::drawFavoriteIcon()
+{
+ static LLUICachedControl draw_star("InventoryFavoritesUseStar", true);
+ static LLUICachedControl draw_hollow_star("InventoryFavoritesUseHollowStar", true);
+
+ LLUIImage* favorite_image = nullptr;
+ if (draw_star && mIsFavorite)
+ {
+ favorite_image = sFavoriteImg;
+ }
+ else if (draw_hollow_star && mHasFavorites && !isOpen())
+ {
+ favorite_image = sFavoriteContentImg;
+ }
+
+ if (favorite_image)
+ {
+ S32 x_offset = 0;
+ LLScrollContainer* scroll = mRoot->getScrollContainer();
+ if (scroll)
+ {
+ S32 width = scroll->getVisibleContentRect().getWidth();
+ S32 offset = scroll->getDocPosHorizontal();
+ x_offset = width + offset;
+ }
+ else
+ {
+ x_offset = getRect().getWidth();
+ }
+ gl_draw_scaled_image(
+ x_offset - FAVORITE_IMAGE_SIZE - FAVORITE_IMAGE_PAD,
+ getRect().getHeight() - mItemHeight + FAVORITE_IMAGE_PAD,
+ FAVORITE_IMAGE_SIZE,
+ FAVORITE_IMAGE_SIZE,
+ favorite_image->getImage(),
+ sFgColor);
+ }
+}
+
/*virtual*/ bool LLFolderViewItem::isHighlightAllowed()
{
return mIsSelected;
@@ -928,6 +1011,7 @@ void LLFolderViewItem::draw()
{
drawOpenFolderArrow();
}
+ drawFavoriteIcon();
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
@@ -999,7 +1083,20 @@ void LLFolderViewItem::draw()
}
}
- LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor;
+ static LLUICachedControl highlight_color("InventoryFavoritesColorText", true);
+ LLColor4 color;
+ if (mIsSelected && filled)
+ {
+ color = mFontHighlightColor;
+ }
+ else if (mIsFavorite && highlight_color)
+ {
+ color = sFavoriteColor;
+ }
+ else
+ {
+ color = mFontColor;
+ }
if (isFadeItem())
{
@@ -1093,7 +1190,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mIsFolderComplete(false), // folder might have children that are not loaded yet.
mAreChildrenInited(false), // folder might have children that are not built yet.
mLastArrangeGeneration( -1 ),
- mLastCalculatedWidth(0)
+ mLastCalculatedWidth(0),
+ mFavoritesDirtyFlags(0)
{
}
@@ -1119,6 +1217,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
// The LLView base class takes care of object destruction. make sure that we
// don't have mouse or keyboard focus
gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
+
+ if (mFavoritesDirtyFlags)
+ {
+ gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this);
+ }
}
// addToFolder() returns true if it succeeds. false otherwise
@@ -1762,6 +1865,140 @@ bool LLFolderViewFolder::isMovable()
return true;
}
+void LLFolderViewFolder::updateHasFavorites(bool new_childs_value)
+{
+ if (mFavoritesDirtyFlags == 0)
+ {
+ gIdleCallbacks.addFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this);
+ }
+ if (new_childs_value)
+ {
+ mFavoritesDirtyFlags |= FAVORITE_ADDED;
+ }
+ else
+ {
+ mFavoritesDirtyFlags |= FAVORITE_REMOVED;
+ }
+}
+
+void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
+{
+ LLFolderViewFolder* self = reinterpret_cast(data);
+ if (self->mFavoritesDirtyFlags == 0)
+ {
+ // already processed either on previous run or by a different callback
+ gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
+ return;
+ }
+
+ if (self->getViewModelItem()->isItemInTrash())
+ {
+ // do not display favorite-stars in trash
+ self->mFavoritesDirtyFlags = 0;
+ gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
+ return;
+ }
+
+ if (self->mFavoritesDirtyFlags == FAVORITE_ADDED)
+ {
+ if (!self->mHasFavorites)
+ {
+ // propagate up, exclude root
+ LLFolderViewFolder* parent = self;
+ while (parent
+ && (!parent->hasFavorites() || parent->mFavoritesDirtyFlags)
+ && !parent->getViewModelItem()->isAgentInventoryRoot())
+ {
+ parent->setHasFavorites(true);
+ if (parent->mFavoritesDirtyFlags)
+ {
+ // Parent will remove onIdleUpdateFavorites later, don't remove now,
+ // We are inside gIdleCallbacks. Removing 'self' callback is safe,
+ // but removing 'parent' can invalidate following iterator
+ parent->mFavoritesDirtyFlags = 0;
+ }
+ parent = parent->getParentFolder();
+ }
+ }
+ else
+ {
+ // already up to date
+ self->mFavoritesDirtyFlags = 0;
+ gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
+ }
+ }
+ else if (self->mFavoritesDirtyFlags > FAVORITE_ADDED)
+ {
+ // full check
+ LLFolderViewFolder* parent = self;
+ while (parent && !parent->getViewModelItem()->isAgentInventoryRoot())
+ {
+ bool has_favorites = false;
+ for (items_t::iterator iter = parent->mItems.begin();
+ iter != parent->mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ if ((*iit)->isFavorite())
+ {
+ has_favorites = true;
+ break;
+ }
+ }
+
+ for (folders_t::iterator iter = parent->mFolders.begin();
+ iter != parent->mFolders.end() && !has_favorites;)
+ {
+ folders_t::iterator fit = iter++;
+ if ((*fit)->isFavorite() || (*fit)->hasFavorites())
+ {
+ has_favorites = true;
+ break;
+ }
+ }
+
+ if (!has_favorites)
+ {
+ if (parent->hasFavorites())
+ {
+ parent->setHasFavorites(false);
+ }
+ else
+ {
+ // Nothing changed
+ break;
+ }
+ }
+ else
+ {
+ // propagate up, exclude root
+ while (parent
+ && (!parent->hasFavorites() || parent->mFavoritesDirtyFlags)
+ && !parent->getViewModelItem()->isAgentInventoryRoot())
+ {
+ parent->setHasFavorites(true);
+ if (parent->mFavoritesDirtyFlags)
+ {
+ // Parent will remove onIdleUpdateFavorites later, don't remove now,
+ // We are inside gIdleCallbacks. Removing 'self' callback is safe,
+ // but removing 'parent' can invalidate following iterator
+ parent->mFavoritesDirtyFlags = 0;
+ }
+ parent = parent->getParentFolder();
+ }
+ break;
+ }
+ if (parent->mFavoritesDirtyFlags)
+ {
+ // Parent will remove onIdleUpdateFavorites later, don't remove now.
+ // We are inside gIdleCallbacks. Removing 'self' callback is safe,
+ // but removing 'parent' can invalidate following iterator
+ parent->mFavoritesDirtyFlags = 0;
+ }
+ parent = parent->getParentFolder();
+ }
+ }
+}
+
bool LLFolderViewFolder::isRemovable()
{
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index cc8a7d934c..c9b003b892 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -50,7 +50,9 @@ class LLFolderViewItem : public LLView
public:
struct Params : public LLInitParam::Block
{
- Optional folder_arrow_image,
+ Optional favorite_image,
+ favorite_content_image,
+ folder_arrow_image,
selection_image;
Mandatory root;
Mandatory listener;
@@ -60,7 +62,7 @@ public:
item_top_pad;
Optional creation_date;
- Optional allow_wear;
+ Optional marketplace_item;
Optional allow_drop;
Optional font_color;
@@ -93,6 +95,8 @@ protected:
LLWString mLabel;
S32 mLabelWidth;
bool mLabelWidthDirty;
+ bool mIsFavorite;
+ bool mHasFavorites;
S32 mLabelPaddingRight;
LLFolderViewFolder* mParentFolder;
LLPointer mViewModelItem;
@@ -122,7 +126,7 @@ protected:
mIsCurSelection,
mDragAndDropTarget,
mIsMouseOverTitle,
- mAllowWear,
+ mMarketplaceItem,
mAllowDrop,
mSingleFolderMode,
mDoubleClickOverride,
@@ -133,6 +137,7 @@ protected:
LLUIColor mFontColor;
LLUIColor mFontHighlightColor;
+ static bool sColorSetInitialized;
// For now assuming all colors are the same in derived classes.
static LLUIColor sFgColor;
@@ -145,6 +150,8 @@ protected:
static LLUIColor sFilterTextColor;
static LLUIColor sSuffixColor;
static LLUIColor sSearchStatusColor;
+ static LLUIColor sFavoriteColor;
+
// this is an internal method used for adding items to folders. A
// no-op at this level, but reimplemented in derived classes.
@@ -154,7 +161,7 @@ protected:
virtual bool isHighlightActive();
virtual bool isFadeItem();
virtual bool isFlashing() { return false; }
- virtual void setFlashState(bool) { }
+ virtual void setFlashState(bool, bool) { }
static LLFontGL* getLabelFontForStyle(U8 style);
const LLFontGL* getLabelFont();
@@ -208,6 +215,8 @@ public:
// Returns true is this object and all of its children can be moved
virtual bool isMovable();
+ bool isFavorite() const { return mIsFavorite; }
+
// destroys this item recursively
virtual void destroyView();
@@ -282,7 +291,7 @@ public:
// Does not need filter update
virtual void refreshSuffix();
- bool isSingleFolderMode() { return mSingleFolderMode; }
+ bool isSingleFolderMode() const { return mSingleFolderMode; }
// LLView functionality
virtual bool handleRightMouseDown( S32 x, S32 y, MASK mask );
@@ -298,6 +307,7 @@ public:
// virtual void handleDropped();
virtual void draw();
void drawOpenFolderArrow();
+ void drawFavoriteIcon();
void drawHighlight(bool showContent, bool hasKeyboardFocus, const LLUIColor& selectColor, const LLUIColor& flashColor, const LLUIColor& outlineColor, const LLUIColor& mouseOverColor);
void drawLabel(const LLFontGL* font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);
virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
@@ -311,6 +321,8 @@ private:
static S32 sTopPad;
static LLUIImagePtr sFolderArrowImg;
static LLUIImagePtr sSelectionImg;
+ static LLUIImagePtr sFavoriteImg;
+ static LLUIImagePtr sFavoriteContentImg;
static LLFontGL* sSuffixFont;
LLFontVertexBuffer mLabelFontBuffer;
@@ -400,6 +412,18 @@ public:
// Returns true is this object and all of its children can be moved
virtual bool isMovable();
+ bool isFavorite() const { return mIsFavorite; }
+ bool hasFavorites() const { return mHasFavorites; }
+ void setHasFavorites(bool val) { mHasFavorites = val; }
+ void updateHasFavorites(bool new_childs_value);
+private:
+ static void onIdleUpdateFavorites(void* data);
+
+ constexpr static S32 FAVORITE_ADDED = 1;
+ constexpr static S32 FAVORITE_REMOVED = 2;
+ S32 mFavoritesDirtyFlags { 0 };
+public:
+
// destroys this folder, and all children
virtual void destroyView();
void destroyRoot();
@@ -415,9 +439,6 @@ public:
// doesn't delete it.
virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true);
- // This function is called by a child that needs to be resorted.
- void resort(LLFolderViewItem* item);
-
void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; }
// folders can be opened. This will usually be called by internal
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 9372818ca5..2865b789b9 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -162,6 +162,7 @@ public:
virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0;
+ virtual bool isFavorite() const = 0;
virtual bool isItemWearable() const { return false; }
virtual bool isItemRenameable() const = 0;
@@ -170,7 +171,8 @@ public:
virtual bool isItemMovable( void ) const = 0; // Can be moved to another folder
virtual void move( LLFolderViewModelItem* parent_listener ) = 0;
- virtual bool isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed
+ virtual bool isItemRemovable( bool check_worn = true) const = 0; // Can be destroyed
+ virtual bool isItemInTrash(void) const = 0;
virtual bool removeItem() = 0;
virtual void removeBatch(std::vector& batch) = 0;
@@ -183,6 +185,9 @@ public:
virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0;
+ virtual bool isAgentInventory() const = 0;
+ virtual bool isAgentInventoryRoot() const = 0;
+
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet?
@@ -219,6 +224,7 @@ public:
virtual S32 getSortVersion() = 0;
virtual void setSortVersion(S32 version) = 0;
virtual void setParent(LLFolderViewModelItem* parent) = 0;
+ virtual const LLFolderViewModelItem* getParent() = 0;
virtual bool hasParent() = 0;
protected:
@@ -249,14 +255,14 @@ public:
mChildren.clear();
}
- void requestSort() { mSortVersion = -1; }
- S32 getSortVersion() { return mSortVersion; }
- void setSortVersion(S32 version) { mSortVersion = version;}
+ void requestSort() override { mSortVersion = -1; }
+ S32 getSortVersion() override { return mSortVersion; }
+ void setSortVersion(S32 version) override { mSortVersion = version;}
- S32 getLastFilterGeneration() const { return mLastFilterGeneration; }
+ S32 getLastFilterGeneration() const override { return mLastFilterGeneration; }
S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; }
- S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; }
- void dirtyFilter()
+ S32 getMarkedDirtyGeneration() const override { return mMarkedDirtyGeneration; }
+ void dirtyFilter() override
{
if(mMarkedDirtyGeneration < 0)
{
@@ -271,7 +277,7 @@ public:
mParent->dirtyFilter();
}
}
- void dirtyDescendantsFilter()
+ void dirtyDescendantsFilter() override
{
mMostFilteredDescendantGeneration = -1;
if (mParent)
@@ -279,13 +285,13 @@ public:
mParent->dirtyDescendantsFilter();
}
}
- bool hasFilterStringMatch();
- std::string::size_type getFilterStringOffset();
- std::string::size_type getFilterStringSize();
+ bool hasFilterStringMatch() override;
+ std::string::size_type getFilterStringOffset() override;
+ std::string::size_type getFilterStringSize() override;
- typedef std::list child_list_t;
+ typedef std::list > child_list_t;
- virtual void addChild(LLFolderViewModelItem* child)
+ virtual void addChild(LLFolderViewModelItem* child) override
{
mChildren.push_back(child);
child->setParent(this);
@@ -293,15 +299,15 @@ public:
requestSort();
}
- virtual void removeChild(LLFolderViewModelItem* child)
+ virtual void removeChild(LLFolderViewModelItem* child) override final
{
- mChildren.remove(child);
child->setParent(NULL);
+ mChildren.remove(child);
dirtyDescendantsFilter();
dirtyFilter();
}
- virtual void clearChildren()
+ virtual void clearChildren() override
{
// We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest
std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); });
@@ -314,7 +320,7 @@ public:
child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); }
child_list_t::size_type getChildrenCount() const { return mChildren.size(); }
- void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0)
+ void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) override
{
mPassedFilter = passed;
mLastFilterGeneration = filter_generation;
@@ -323,20 +329,20 @@ public:
mMarkedDirtyGeneration = -1;
}
- void setPassedFolderFilter(bool passed, S32 filter_generation)
+ void setPassedFolderFilter(bool passed, S32 filter_generation) override
{
mPassedFolderFilter = passed;
mLastFolderFilterGeneration = filter_generation;
}
- virtual bool potentiallyVisible()
+ virtual bool potentiallyVisible() override
{
return passedFilter() // we've passed the filter
|| (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet
|| descendantsPassedFilter();
}
- virtual bool passedFilter(S32 filter_generation = -1)
+ virtual bool passedFilter(S32 filter_generation = -1) override
{
if (filter_generation < 0)
{
@@ -347,7 +353,7 @@ public:
return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));
}
- virtual bool descendantsPassedFilter(S32 filter_generation = -1)
+ virtual bool descendantsPassedFilter(S32 filter_generation = -1) override
{
if (filter_generation < 0)
{
@@ -356,10 +362,10 @@ public:
return mMostFilteredDescendantGeneration >= filter_generation;
}
-
protected:
- virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; }
- virtual bool hasParent() { return mParent != NULL; }
+ virtual void setParent(LLFolderViewModelItem* parent) override final { mParent = parent; }
+ virtual const LLFolderViewModelItem* getParent() override { return mParent; };
+ virtual bool hasParent() override { return mParent != NULL; }
S32 mSortVersion;
bool mPassedFilter;
@@ -376,7 +382,7 @@ protected:
LLFolderViewModelItem* mParent;
LLFolderViewModelInterface& mRootViewModel;
- void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;}
+ void setFolderViewItem(LLFolderViewItem* folder_view_item) override { mFolderViewItem = folder_view_item;}
LLFolderViewItem* mFolderViewItem;
};
@@ -390,15 +396,15 @@ public:
mFolderView(NULL)
{}
- virtual void requestSortAll()
+ virtual void requestSortAll() override
{
// sort everything
mTargetSortVersion++;
}
- virtual std::string getStatusText(bool is_empty_folder = false);
- virtual void filter();
+ virtual std::string getStatusText(bool is_empty_folder = false) override;
+ virtual void filter() override;
- void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;}
+ void setFolderView(LLFolderView* folder_view) override { mFolderView = folder_view;}
protected:
bool needsSort(class LLFolderViewModelItem* item);
@@ -428,14 +434,14 @@ public:
virtual const SortType& getSorter() const { return *mSorter; }
virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); }
- virtual FilterType& getFilter() { return *mFilter; }
- virtual const FilterType& getFilter() const { return *mFilter; }
+ virtual FilterType& getFilter() override { return *mFilter; }
+ virtual const FilterType& getFilter() const override { return *mFilter; }
virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); }
// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
// this method needs to be overloaded and return the relevant fetch status.
- virtual bool contentsReady() { return true; }
- virtual bool isFolderComplete(LLFolderViewFolder* folder) { return true; }
+ virtual bool contentsReady() override { return true; }
+ virtual bool isFolderComplete(LLFolderViewFolder* folder) override { return true; }
struct ViewModelCompare
{
@@ -456,7 +462,7 @@ public:
const SortType& mSorter;
};
- void sort(LLFolderViewFolder* folder)
+ void sort(LLFolderViewFolder* folder) override
{
if (needsSort(folder->getViewModelItem()))
{
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index 7bf43c22c1..2bea8fb4ed 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -170,7 +170,7 @@ std::string LLKeywords::getAttribute(std::string_view key)
return (it != mAttributes.end()) ? it->second : "";
}
-LLUIColor LLKeywords::getColorGroup(std::string_view key_in)
+LLUIColor LLKeywords::getColorGroup(std::string_view key_in) const
{
std::string color_group = "ScriptText";
if (key_in == "functions")
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index 328561c92a..5892238593 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -111,8 +111,8 @@ public:
~LLKeywords();
void clearLoaded() { mLoaded = false; }
- LLUIColor getColorGroup(std::string_view key_in);
- bool isLoaded() const { return mLoaded; }
+ LLUIColor getColorGroup(std::string_view key_in) const;
+ bool isLoaded() const { return mLoaded; }
void findSegments(std::vector *seg_list,
const LLWString& text,
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 1c59938f90..fe0591ce4b 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -36,8 +36,8 @@
#include "lliconctrl.h"
#include "boost/foreach.hpp"
-static const F32 MIN_FRACTIONAL_SIZE = 0.00001f;
-static const F32 MAX_FRACTIONAL_SIZE = 1.f;
+static constexpr F32 MIN_FRACTIONAL_SIZE = 0.00001f;
+static constexpr F32 MAX_FRACTIONAL_SIZE = 1.f;
static LLDefaultChildRegistry::Register register_layout_stack("layout_stack");
static LLLayoutStack::LayoutStackRegistry::Register register_layout_panel("layout_panel");
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 8459921c60..9e3536aaff 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -75,9 +75,6 @@ public:
/*virtual*/ bool addChild(LLView* child, S32 tab_group = 0);
/*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true);
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
-
typedef enum e_animate
{
NO_ANIMATE,
@@ -86,7 +83,7 @@ public:
void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE);
void collapsePanel(LLPanel* panel, bool collapsed = true);
- S32 getNumPanels() { return static_cast(mPanels.size()); }
+ S32 getNumPanels() const { return static_cast(mPanels.size()); }
void updateLayout();
@@ -190,7 +187,6 @@ public:
bool isCollapsed() const { return mCollapsed;}
void setOrientation(LLView::EOrientation orientation);
- void storeOriginalDim();
void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; }
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 66b274c33f..b534c8d4e8 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2230,6 +2230,9 @@ void LLLineEditor::clear()
{
mText.clear();
setCursor(0);
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
//virtual
@@ -2505,9 +2508,24 @@ void LLLineEditor::resetPreedit()
if (hasPreeditString())
{
const S32 preedit_pos = mPreeditPositions.front();
- mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
- mText.insert(preedit_pos, mPreeditOverwrittenWString);
- setCursor(preedit_pos);
+ const S32 end = mPreeditPositions.back();
+ const S32 len = end - preedit_pos;
+ const S32 size = mText.length();
+ if (preedit_pos < size
+ && end <= size
+ && preedit_pos >= 0
+ && len > 0)
+ {
+ mText.erase(preedit_pos, len);
+ mText.insert(preedit_pos, mPreeditOverwrittenWString);
+ setCursor(preedit_pos);
+ }
+ else
+ {
+ LL_WARNS() << "Index out of bounds. Start: " << preedit_pos
+ << ", end:" << end
+ << ", full string length: " << size << LL_ENDL;
+ }
mPreeditWString.clear();
mPreeditOverwrittenWString.clear();
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 12fe800acb..7533f76f1d 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -306,8 +306,6 @@ public:
S32 calcCursorPos(S32 mouse_x);
bool handleSpecialKey(KEY key, MASK mask);
bool handleSelectionKey(KEY key, MASK mask);
- bool handleControlKey(KEY key, MASK mask);
- S32 handleCommitKey(KEY key, MASK mask);
void updateTextPadding();
// Draw the background image depending on enabled/focused state.
@@ -444,7 +442,7 @@ private:
mText = ed->getText();
}
- void doRollback( LLLineEditor* ed )
+ void doRollback(LLLineEditor* ed) const
{
ed->mCursorPos = mCursorPos;
ed->mScrollHPos = mScrollHPos;
@@ -455,7 +453,7 @@ private:
ed->mPrevText = mText;
}
- std::string getText() { return mText; }
+ std::string getText() const { return mText; }
private:
std::string mText;
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
index a77ae7dae7..3f96b28246 100644
--- a/indra/llui/llmenubutton.h
+++ b/indra/llui/llmenubutton.h
@@ -65,8 +65,8 @@ public:
boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb );
- /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleKeyHere(KEY key, MASK mask );
+ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleKeyHere(KEY key, MASK mask) override;
void hideMenu();
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index c11b42a348..2ca2454040 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -46,6 +46,7 @@
#include "llfocusmgr.h"
#include "llcoord.h"
#include "llwindow.h"
+#include "llemojihelper.h"
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
@@ -1411,6 +1412,7 @@ void LLMenuItemBranchDownGL::openMenu( void )
}
else
{
+ LLEmojiHelper::instance().hideHelper(nullptr, true);
if (branch->getTornOff())
{
LLFloater * branch_parent = dynamic_cast(branch->getParent());
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 66f84393fe..ff9456acc6 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -439,8 +439,6 @@ protected:
public:
virtual ~LLMenuGL( void );
- void parseChildXML(LLXMLNodePtr child, LLView* parent);
-
// LLView Functionality
/*virtual*/ bool handleUnicodeCharHere( llwchar uni_char );
/*virtual*/ bool handleHover( S32 x, S32 y, MASK mask );
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index c5c31f7252..225ff607ad 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -28,6 +28,7 @@
#include "llmodaldialog.h"
+#include "llemojihelper.h"
#include "llfocusmgr.h"
#include "v4color.h"
#include "v2math.h"
@@ -35,6 +36,7 @@
#include "llwindow.h"
#include "llkeyboard.h"
#include "llmenugl.h"
+
// static
std::list LLModalDialog::sModalStack;
@@ -98,7 +100,7 @@ void LLModalDialog::onOpen(const LLSD& key)
{
if (mModal)
{
- // If Modal, Hide the active modal dialog
+ // If Modal, hide the active modal dialog
if (!sModalStack.empty())
{
LLModalDialog* front = sModalStack.front();
@@ -155,6 +157,12 @@ void LLModalDialog::setVisible( bool visible )
{
if( visible )
{
+ // Hide all menus currently shown
+ LLMenuGL::sMenuContainer->hideMenus();
+
+ // Hide EmojiPicker if it is shown
+ LLEmojiHelper::instance().hideHelper(nullptr, true);
+
// This is a modal dialog. It sucks up all mouse and keyboard operations.
gFocusMgr.setMouseCapture( this );
@@ -301,7 +309,6 @@ void LLModalDialog::centerOnScreen()
centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY])));
}
-
// static
void LLModalDialog::onAppFocusLost()
{
@@ -333,6 +340,7 @@ void LLModalDialog::onAppFocusGained()
}
}
+// static
void LLModalDialog::shutdownModals()
{
// This method is only for use during app shutdown. ~LLModalDialog()
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
index a7f9b8b2d9..f53e22c349 100644
--- a/indra/llui/llmultifloater.cpp
+++ b/indra/llui/llmultifloater.cpp
@@ -390,7 +390,7 @@ LLFloater* LLMultiFloater::getActiveFloater()
return (LLFloater*)mTabContainer->getCurrentPanel();
}
-S32 LLMultiFloater::getFloaterCount()
+S32 LLMultiFloater::getFloaterCount() const
{
return mTabContainer->getTabCount();
}
diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h
index eb0f917695..e0cd58aa3f 100644
--- a/indra/llui/llmultifloater.h
+++ b/indra/llui/llmultifloater.h
@@ -66,7 +66,7 @@ public:
virtual LLFloater* getActiveFloater();
virtual bool isFloaterFlashing(LLFloater* floaterp);
- virtual S32 getFloaterCount();
+ virtual S32 getFloaterCount() const;
virtual void setFloaterFlashing(LLFloater* floaterp, bool flashing);
virtual bool closeAllFloaters(); //Returns false if the floater could not be closed due to pending confirmation dialogs
diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h
index b2bfc8bc84..af255bcc8f 100644
--- a/indra/llui/llmultislider.h
+++ b/indra/llui/llmultislider.h
@@ -117,10 +117,10 @@ public:
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override;
/*virtual*/ void draw() override;
- S32 getMaxNumSliders() { return mMaxNumSliders; }
- S32 getCurNumSliders() { return static_cast(mValue.size()); }
- F32 getOverlapThreshold() { return mOverlapThreshold; }
- bool canAddSliders() { return mValue.size() < mMaxNumSliders; }
+ S32 getMaxNumSliders() const { return mMaxNumSliders; }
+ S32 getCurNumSliders() const { return static_cast(mValue.size()); }
+ F32 getOverlapThreshold() const { return mOverlapThreshold; }
+ bool canAddSliders() const { return mValue.size() < mMaxNumSliders; }
protected:
diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h
index dec6cb48b9..2c2bc5e4d9 100644
--- a/indra/llui/llmultisliderctrl.h
+++ b/indra/llui/llmultisliderctrl.h
@@ -124,10 +124,10 @@ public:
F32 getMinValue() const { return mMultiSlider->getMinValue(); }
F32 getMaxValue() const { return mMultiSlider->getMaxValue(); }
- S32 getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); }
- S32 getCurNumSliders() { return mMultiSlider->getCurNumSliders(); }
- F32 getOverlapThreshold() { return mMultiSlider->getOverlapThreshold(); }
- bool canAddSliders() { return mMultiSlider->canAddSliders(); }
+ S32 getMaxNumSliders() const { return mMultiSlider->getMaxNumSliders(); }
+ S32 getCurNumSliders() const { return mMultiSlider->getCurNumSliders(); }
+ F32 getOverlapThreshold() const { return mMultiSlider->getOverlapThreshold(); }
+ bool canAddSliders() const { return mMultiSlider->canAddSliders(); }
void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); }
void setLabelColor(const LLUIColor& c) { mTextEnabledColor = c; }
@@ -147,7 +147,6 @@ public:
static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
- static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
private:
void updateText();
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 138f1969d5..3c8e1e85fa 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -247,7 +247,6 @@ public:
LLNotificationForm(const LLSD& sd);
LLNotificationForm(const std::string& name, const Params& p);
- void fromLLSD(const LLSD& sd);
LLSD asLLSD() const;
S32 getNumElements() { return static_cast(mFormData.size()); }
@@ -266,8 +265,8 @@ public:
bool getIgnored();
void setIgnored(bool ignored);
- EIgnoreType getIgnoreType() { return mIgnore; }
- std::string getIgnoreMessage() { return mIgnoreMsg; }
+ EIgnoreType getIgnoreType()const { return mIgnore; }
+ std::string getIgnoreMessage() const { return mIgnoreMsg; }
private:
LLSD mFormData;
@@ -971,8 +970,6 @@ private:
/*virtual*/ void initSingleton() override;
/*virtual*/ void cleanupSingleton() override;
- void loadPersistentNotifications();
-
bool expirationFilter(LLNotificationPtr pNotification);
bool expirationHandler(const LLSD& payload);
bool uniqueFilter(LLNotificationPtr pNotification);
diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h
index 0d5d32cf21..7245bbf1cf 100644
--- a/indra/llui/llprogressbar.h
+++ b/indra/llui/llprogressbar.h
@@ -48,9 +48,9 @@ public:
LLProgressBar(const Params&);
virtual ~LLProgressBar();
- void setValue(const LLSD& value);
+ void setValue(const LLSD& value) override;
- /*virtual*/ void draw();
+ void draw() override;
private:
F32 mPercentDone;
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index 4b0f435834..68bf0fd95e 100644
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -61,7 +61,7 @@ public:
void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; }
void setEnableSnapping(bool enable) { mSnappingEnabled = enable; }
void setAllowDoubleClickSnapping(bool allow) { mAllowDoubleClickSnapping = allow; }
- bool canResize() { return getEnabled() && mMaxSize > mMinSize; }
+ bool canResize() const { return getEnabled() && mMaxSize > mMinSize; }
void setResizeListener(boost::function listener) {mResizeListener = listener;}
void setImagePanel(LLPanel * panelp);
LLPanel * getImagePanel() const;
diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h
index 9cc4123544..caec33405c 100644
--- a/indra/llui/llresizehandle.h
+++ b/indra/llui/llresizehandle.h
@@ -50,10 +50,10 @@ protected:
LLResizeHandle(const LLResizeHandle::Params&);
friend class LLUICtrlFactory;
public:
- virtual void draw();
- virtual bool handleHover(S32 x, S32 y, MASK mask);
- virtual bool handleMouseDown(S32 x, S32 y, MASK mask);
- virtual bool handleMouseUp(S32 x, S32 y, MASK mask);
+ void draw() override;
+ bool handleHover(S32 x, S32 y, MASK mask) override;
+ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleMouseUp(S32 x, S32 y, MASK mask) override;
void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; }
@@ -71,8 +71,8 @@ private:
const ECorner mCorner;
};
-const S32 RESIZE_HANDLE_HEIGHT = 11;
-const S32 RESIZE_HANDLE_WIDTH = 11;
+constexpr S32 RESIZE_HANDLE_HEIGHT = 11;
+constexpr S32 RESIZE_HANDLE_WIDTH = 11;
#endif // LL_RESIZEHANDLE_H
diff --git a/indra/llui/llrngwriter.h b/indra/llui/llrngwriter.h
index 33ec049a1a..2c39472607 100644
--- a/indra/llui/llrngwriter.h
+++ b/indra/llui/llrngwriter.h
@@ -37,7 +37,7 @@ public:
void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace);
void addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block);
- /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; }
+ std::string getCurrentElementName() override { return LLStringUtil::null; }
LLRNGWriter();
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
index e7ff5c8424..7dded3c0b7 100644
--- a/indra/llui/llscrolllistcell.h
+++ b/indra/llui/llscrolllistcell.h
@@ -105,7 +105,7 @@ public:
virtual const LLSD getAltValue() const;
virtual void setValue(const LLSD& value) { }
virtual void setAltValue(const LLSD& value) { }
- virtual const std::string &getToolTip() const { return mToolTip; }
+ virtual const std::string& getToolTip() const { return mToolTip; }
virtual void setToolTip(const std::string &str) { mToolTip = str; }
virtual bool getVisible() const { return true; }
virtual void setWidth(S32 width) { mWidth = width; }
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 245339b107..ff77b4d482 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1007,7 +1007,7 @@ void LLScrollListCtrl::deleteItems(const LLSD& sd)
void LLScrollListCtrl::deleteSelectedItems()
{
item_list::iterator iter;
- for (iter = mItemList.begin(); iter < mItemList.end(); )
+ for (iter = mItemList.begin(); iter != mItemList.end(); )
{
LLScrollListItem* itemp = *iter;
if (itemp->getSelected())
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index c24784338a..1f04100306 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -165,7 +165,6 @@ public:
void deleteAllItems() { clearRows(); }
// Sets an array of column descriptors
- void setColumnHeadings(const LLSD& headings);
void sortByColumnIndex(U32 column, bool ascending);
// LLCtrlListInterface functions
@@ -318,7 +317,7 @@ public:
void setAllowKeyboardMovement(bool b) { mAllowKeyboardMovement = b; }
void setMaxSelectable(U32 max_selected) { mMaxSelectable = max_selected; }
- S32 getMaxSelectable() { return mMaxSelectable; }
+ S32 getMaxSelectable() const { return mMaxSelectable; }
virtual S32 getScrollPos() const;
@@ -334,7 +333,7 @@ public:
// support right-click context menus for avatar/group lists
enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP };
void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; }
- ContextMenuType getContextMenuType() { return mContextMenuType; }
+ ContextMenuType getContextMenuType() const { return mContextMenuType; }
// Overridden from LLView
/*virtual*/ void draw();
@@ -362,7 +361,6 @@ public:
virtual void fitContents(S32 max_width, S32 max_height);
virtual LLRect getRequiredRect();
- static bool rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row);
LLRect getItemListRect() { return mItemListRect; }
@@ -384,7 +382,6 @@ public:
* then display all items.
*/
void setPageLines(S32 page_lines );
- void setCollapseEmptyColumns(bool collapse);
LLScrollListItem* hitItem(S32 x,S32 y);
virtual void scrollToShowSelected();
@@ -401,7 +398,7 @@ public:
void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; }
void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width);
- S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; }
+ S32 getTotalStaticColumnWidth() const { return mTotalStaticColumnWidth; }
std::string getSortColumnName();
bool getSortAscending() { return mSortColumns.empty() ? true : mSortColumns.back().second; }
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 311377a61f..23ce8fd955 100644
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -132,7 +132,6 @@ public:
static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
- static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
protected:
virtual std::string _getSearchText() const
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index 58b38dc630..4ba8c97c63 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -94,7 +94,6 @@ public:
void onEditorCommit(const LLSD& data);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorLostFocus(LLFocusableElement* caller, void *userdata);
- static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
void onUpBtn(const LLSD& data);
void onDownBtn(const LLSD& data);
diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h
index c36a138566..bbbf0b3a19 100644
--- a/indra/llui/llstatbar.h
+++ b/indra/llui/llstatbar.h
@@ -67,7 +67,7 @@ public:
void setStat(const std::string& stat_name);
void setRange(F32 bar_min, F32 bar_max);
- void getRange(F32& bar_min, F32& bar_max) { bar_min = mTargetMinBar; bar_max = mTargetMaxBar; }
+ void getRange(F32& bar_min, F32& bar_max) const { bar_min = mTargetMinBar; bar_max = mTargetMaxBar; }
/*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options.
diff --git a/indra/llui/llstatgraph.cpp b/indra/llui/llstatgraph.cpp
index d97051247e..0af717d447 100644
--- a/indra/llui/llstatgraph.cpp
+++ b/indra/llui/llstatgraph.cpp
@@ -36,7 +36,6 @@
#include "llglheaders.h"
#include "lltracerecording.h"
#include "lltracethreadrecorder.h"
-//#include "llviewercontrol.h"
///////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/llui/llstatgraph.h b/indra/llui/llstatgraph.h
index c254821870..6d9e3d1064 100644
--- a/indra/llui/llstatgraph.h
+++ b/indra/llui/llstatgraph.h
@@ -99,9 +99,7 @@ public:
void setMin(const F32 min);
void setMax(const F32 max);
- virtual void draw();
-
- /*virtual*/ void setValue(const LLSD& value);
+ void draw() override;
private:
LLTrace::StatType* mNewStatFloatp;
@@ -133,9 +131,6 @@ private:
};
typedef std::vector threshold_vec_t;
threshold_vec_t mThresholds;
- //S32 mNumThresholds;
- //F32 mThresholds[4];
- //LLColor4 mThresholdColors[4];
};
#endif // LL_LLSTATGRAPH_H
diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h
index b5187f886d..a396773057 100644
--- a/indra/llui/llstatview.h
+++ b/indra/llui/llstatview.h
@@ -29,7 +29,6 @@
#include "llstatbar.h"
#include "llcontainerview.h"
-#include
class LLStatBar;
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 4714665e8b..7a0e620d61 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -38,11 +38,13 @@ LLStyle::Params::Params()
color("color", LLColor4::black),
readonly_color("readonly_color", LLColor4::black),
selected_color("selected_color", LLColor4::black),
+ highlight_bg_color("highlight_bg_color", LLColor4::green),
alpha("alpha", 1.f),
font("font", LLStyle::getDefaultFont()),
image("image"),
link_href("href"),
- is_link("is_link")
+ is_link("is_link"),
+ draw_highlight_bg("draw_highlight_bg", false)
{}
@@ -51,12 +53,14 @@ LLStyle::LLStyle(const LLStyle::Params& p)
mColor(p.color),
mReadOnlyColor(p.readonly_color),
mSelectedColor(p.selected_color),
+ mHighlightBgColor(p.highlight_bg_color),
mFont(p.font()),
mLink(p.link_href),
mIsLink(p.is_link.isProvided() ? p.is_link : !p.link_href().empty()),
mDropShadow(p.drop_shadow),
mImagep(p.image()),
- mAlpha(p.alpha)
+ mAlpha(p.alpha),
+ mDrawHighlightBg(p.draw_highlight_bg)
{}
void LLStyle::setFont(const LLFontGL* font)
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 0c78fe5a9f..71c3f88109 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -43,15 +43,25 @@ public:
Optional drop_shadow;
Optional color,
readonly_color,
- selected_color;
+ selected_color,
+ highlight_bg_color;
Optional alpha;
Optional font;
Optional image;
Optional link_href;
Optional is_link;
+ Optional draw_highlight_bg;
Params();
};
LLStyle(const Params& p = Params());
+
+ enum EUnderlineLink
+ {
+ UNDERLINE_ALWAYS = 0,
+ UNDERLINE_ON_HOVER,
+ UNDERLINE_NEVER
+ };
+
public:
const LLUIColor& getColor() const { return mColor; }
void setColor(const LLUIColor &color) { mColor = color; }
@@ -84,6 +94,9 @@ public:
bool isImage() const { return mImagep.notNull(); }
+ bool getDrawHighlightBg() const { return mDrawHighlightBg; }
+ const LLUIColor& getHighlightBgColor() const { return mHighlightBgColor; }
+
bool operator==(const LLStyle &rhs) const
{
return
@@ -91,11 +104,13 @@ public:
&& mColor == rhs.mColor
&& mReadOnlyColor == rhs.mReadOnlyColor
&& mSelectedColor == rhs.mSelectedColor
+ && mHighlightBgColor == rhs.mHighlightBgColor
&& mFont == rhs.mFont
&& mLink == rhs.mLink
&& mImagep == rhs.mImagep
&& mDropShadow == rhs.mDropShadow
- && mAlpha == rhs.mAlpha;
+ && mAlpha == rhs.mAlpha
+ && mDrawHighlightBg == rhs.mDrawHighlightBg;
}
bool operator!=(const LLStyle& rhs) const { return !(*this == rhs); }
@@ -112,11 +127,13 @@ private:
LLUIColor mColor;
LLUIColor mReadOnlyColor;
LLUIColor mSelectedColor;
+ LLUIColor mHighlightBgColor;
const LLFontGL* mFont;
LLPointer mImagep;
F32 mAlpha;
bool mVisible;
bool mIsLink;
+ bool mDrawHighlightBg;
};
typedef LLPointer LLStyleSP;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 595ab0bd2b..5e0985c79c 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1370,17 +1370,17 @@ LLPanel* LLTabContainer::getCurrentPanel()
return NULL;
}
-S32 LLTabContainer::getCurrentPanelIndex()
+S32 LLTabContainer::getCurrentPanelIndex() const
{
return mCurrentTabIdx;
}
-S32 LLTabContainer::getTabCount()
+S32 LLTabContainer::getTabCount() const
{
return static_cast(mTabList.size());
}
-LLPanel* LLTabContainer::getPanelByIndex(S32 index)
+LLPanel* LLTabContainer::getPanelByIndex(S32 index) const
{
if (index >= 0 && index < (S32)mTabList.size())
{
@@ -1389,7 +1389,7 @@ LLPanel* LLTabContainer::getPanelByIndex(S32 index)
return NULL;
}
-S32 LLTabContainer::getIndexForPanel(LLPanel* panel)
+S32 LLTabContainer::getIndexForPanel(LLPanel* panel) const
{
for (S32 index = 0; index < (S32)mTabList.size(); index++)
{
@@ -1401,7 +1401,7 @@ S32 LLTabContainer::getIndexForPanel(LLPanel* panel)
return -1;
}
-S32 LLTabContainer::getPanelIndexByTitle(std::string_view title)
+S32 LLTabContainer::getPanelIndexByTitle(std::string_view title) const
{
for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
{
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 40f272ffa8..4ac7e73d25 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -182,15 +182,15 @@ public:
void removeTabPanel( LLPanel* child );
void lockTabs(S32 num_tabs = 0);
void unlockTabs();
- S32 getNumLockedTabs() { return mLockedTabCount; }
+ S32 getNumLockedTabs() const { return mLockedTabCount; }
void enableTabButton(S32 which, bool enable);
void deleteAllTabs();
LLPanel* getCurrentPanel();
- S32 getCurrentPanelIndex();
- S32 getTabCount();
- LLPanel* getPanelByIndex(S32 index);
- S32 getIndexForPanel(LLPanel* panel);
- S32 getPanelIndexByTitle(std::string_view title);
+ S32 getCurrentPanelIndex() const;
+ S32 getTabCount() const;
+ LLPanel* getPanelByIndex(S32 index) const;
+ S32 getIndexForPanel(LLPanel* panel) const;
+ S32 getPanelIndexByTitle(std::string_view title) const;
LLPanel* getPanelByName(std::string_view name);
S32 getTotalTabWidth() const;
void setCurrentTabName(const std::string& name);
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 41e7094163..d5755ae4b6 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -460,6 +460,62 @@ std::vector LLTextBase::getSelectionRects()
return selection_rects;
}
+std::vector> LLTextBase::getHighlightedBgRects()
+{
+ std::vector> highlight_rects;
+
+ LLRect content_display_rect = getVisibleDocumentRect();
+
+ // binary search for line that starts before top of visible buffer
+ line_list_t::const_iterator line_iter =
+ std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
+ line_list_t::const_iterator end_iter =
+ std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());
+
+ for (; line_iter != end_iter; ++line_iter)
+ {
+ segment_set_t::iterator segment_iter;
+ S32 segment_offset;
+ getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
+
+ // Use F32 otherwise a string of multiple segments
+ // will accumulate a large error
+ F32 left_precise = (F32)line_iter->mRect.mLeft;
+ F32 right_precise = (F32)line_iter->mRect.mLeft;
+
+ for (; segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
+ {
+ LLTextSegmentPtr segmentp = *segment_iter;
+
+ S32 segment_line_start = segmentp->getStart() + segment_offset;
+ S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
+
+ if (segment_line_start > segment_line_end)
+ break;
+
+ F32 segment_width = 0;
+ S32 segment_height = 0;
+
+ S32 num_chars = segment_line_end - segment_line_start;
+ segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height);
+ right_precise += segment_width;
+
+ if (segmentp->getStyle()->getDrawHighlightBg())
+ {
+ LLRect selection_rect;
+ selection_rect.mLeft = (S32)left_precise;
+ selection_rect.mRight = (S32)right_precise;
+ selection_rect.mBottom = line_iter->mRect.mBottom;
+ selection_rect.mTop = line_iter->mRect.mTop;
+
+ highlight_rects.push_back(std::pair(selection_rect, segmentp->getStyle()->getHighlightBgColor()));
+ }
+ left_precise += segment_width;
+ }
+ }
+ return highlight_rects;
+}
+
// Draws the black box behind the selected text
void LLTextBase::drawSelectionBackground()
{
@@ -529,6 +585,71 @@ void LLTextBase::drawSelectionBackground()
}
}
+void LLTextBase::drawHighlightedBackground()
+{
+ if (!mLineInfoList.empty())
+ {
+ std::vector> highlight_rects = getHighlightedBgRects();
+
+ if (highlight_rects.empty())
+ return;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ LLRect content_display_rect = getVisibleDocumentRect();
+
+ for (std::vector>::iterator rect_it = highlight_rects.begin();
+ rect_it != highlight_rects.end(); ++rect_it)
+ {
+ LLRect selection_rect = rect_it->first;
+ const LLColor4& color = rect_it->second;
+ if (mScroller)
+ {
+ // If scroller is On content_display_rect has correct rect and safe to use as is
+ // Note: we might need to account for border
+ selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom);
+ }
+ else
+ {
+ // If scroller is Off content_display_rect will have rect from document, adjusted to text width, heigh and position
+ // and we have to acount for offset depending on position
+ S32 v_delta = 0;
+ S32 h_delta = 0;
+ switch (mVAlign)
+ {
+ case LLFontGL::TOP:
+ v_delta = mVisibleTextRect.mTop - content_display_rect.mTop - mVPad;
+ break;
+ case LLFontGL::VCENTER:
+ v_delta = (llmax(mVisibleTextRect.getHeight() - content_display_rect.mTop, -content_display_rect.mBottom) + (mVisibleTextRect.mBottom - content_display_rect.mBottom)) / 2;
+ break;
+ case LLFontGL::BOTTOM:
+ v_delta = mVisibleTextRect.mBottom - content_display_rect.mBottom;
+ break;
+ default:
+ break;
+ }
+ switch (mHAlign)
+ {
+ case LLFontGL::LEFT:
+ h_delta = mVisibleTextRect.mLeft - content_display_rect.mLeft + mHPad;
+ break;
+ case LLFontGL::HCENTER:
+ h_delta = (llmax(mVisibleTextRect.getWidth() - content_display_rect.mLeft, -content_display_rect.mRight) + (mVisibleTextRect.mRight - content_display_rect.mRight)) / 2;
+ break;
+ case LLFontGL::RIGHT:
+ h_delta = mVisibleTextRect.mRight - content_display_rect.mRight;
+ break;
+ default:
+ break;
+ }
+ selection_rect.translate(h_delta, v_delta);
+ }
+ gl_rect_2d(selection_rect, color);
+ }
+ }
+}
+
void LLTextBase::drawCursor()
{
F32 alpha = getDrawContext().mAlpha;
@@ -1399,6 +1520,7 @@ void LLTextBase::draw()
drawChild(mDocumentView);
}
+ drawHighlightedBackground();
drawSelectionBackground();
drawText();
drawCursor();
@@ -2105,7 +2227,9 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.RemoveFriend", boost::bind(&LLUrlAction::removeFriend, url));
registrar.add("Url.ReportAbuse", boost::bind(&LLUrlAction::reportAbuse, url));
registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));
+ registrar.add("Url.ZoomInObject", boost::bind(&LLUrlAction::zoomInObject, url));
registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
+ registrar.add("Url.ShowParcelOnMap", boost::bind(&LLUrlAction::showParcelOnMap, url));
registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
@@ -2200,20 +2324,20 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
}
-void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
+void LLTextBase::appendTextImpl(const std::string& new_text, const LLStyle::Params& input_params, bool force_slurl)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
LLStyle::Params style_params(getStyleParams());
style_params.overwriteFrom(input_params);
S32 part = (S32)LLTextParser::WHOLE;
- if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
+ if ((mParseHTML || force_slurl) && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
{
S32 start=0,end=0;
LLUrlMatch match;
std::string text = new_text;
while (LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3), isContentTrusted() || mAlwaysShowIcons))
+ boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3), isContentTrusted() || mAlwaysShowIcons, force_slurl))
{
start = match.getStart();
end = match.getEnd()+1;
@@ -2245,7 +2369,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
}
// output the styled Url
- appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
+ appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.getUnderline());
bool tooltip_required = !match.getTooltip().empty();
// set the tooltip for the Url label
@@ -2260,7 +2384,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
{
link_params.color = LLColor4::grey;
link_params.readonly_color = LLColor4::grey;
- appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly());
+ appendAndHighlightTextImpl(label, part, link_params, match.getUnderline());
// set the tooltip for the query part of url
if (tooltip_required)
@@ -2428,7 +2552,7 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s
insertStringNoUndo(getLength(), widget_wide_text, &segments);
}
-void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
+void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link)
{
// Save old state
S32 selection_start = mSelectionStart;
@@ -2458,7 +2582,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
S32 cur_length = getLength();
LLStyleConstSP sp(new LLStyle(highlight_params));
LLTextSegmentPtr segmentp;
- if (underline_on_hover_only || mSkipLinkUnderline)
+ if ((underline_link == e_underline::UNDERLINE_ON_HOVER) || mSkipLinkUnderline)
{
highlight_params.font.style("NORMAL");
LLStyleConstSP normal_sp(new LLStyle(highlight_params));
@@ -2482,7 +2606,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
S32 segment_start = old_length;
S32 segment_end = old_length + static_cast(wide_text.size());
LLStyleConstSP sp(new LLStyle(style_params));
- if (underline_on_hover_only || mSkipLinkUnderline)
+ if ((underline_link == e_underline::UNDERLINE_ON_HOVER) || mSkipLinkUnderline)
{
LLStyle::Params normal_style_params(style_params);
normal_style_params.font.style("NORMAL");
@@ -2516,7 +2640,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
}
}
-void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
+void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link)
{
if (new_text.empty())
{
@@ -2531,7 +2655,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
if (pos != start)
{
std::string str = std::string(new_text,start,pos-start);
- appendAndHighlightTextImpl(str, highlight_part, style_params, underline_on_hover_only);
+ appendAndHighlightTextImpl(str, highlight_part, style_params, underline_link);
}
appendLineBreakSegment(style_params);
start = pos+1;
@@ -2539,7 +2663,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
}
std::string str = std::string(new_text, start, new_text.length() - start);
- appendAndHighlightTextImpl(str, highlight_part, style_params, underline_on_hover_only);
+ appendAndHighlightTextImpl(str, highlight_part, style_params, underline_link);
}
@@ -3336,6 +3460,7 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e
mLastGeneration(-1)
{
mFontHeight = mStyle->getFont()->getLineHeight();
+ mCanEdit = !mStyle->getDrawHighlightBg();
LLUIImagePtr image = mStyle->getImage();
if (image.notNull())
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 76d4e160af..8ca653acb9 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -35,6 +35,7 @@
#include "llstyle.h"
#include "llkeywords.h"
#include "llpanel.h"
+#include "llurlmatch.h"
#include
#include
@@ -139,13 +140,12 @@ public:
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;
/*virtual*/ void updateLayout(const class LLTextBase& editor);
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect);
- /*virtual*/ bool canEdit() const { return true; }
+ /*virtual*/ bool canEdit() const { return mCanEdit; }
/*virtual*/ const LLUIColor& getColor() const { return mStyle->getColor(); }
/*virtual*/ LLStyleConstSP getStyle() const { return mStyle; }
/*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; }
/*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
/*virtual*/ LLKeywordToken* getToken() const { return mToken; }
- /*virtual*/ bool getToolTip( std::string& msg ) const;
/*virtual*/ void setToolTip(const std::string& tooltip);
/*virtual*/ void dump() const;
@@ -162,6 +162,8 @@ protected:
virtual const LLWString& getWText() const;
virtual const S32 getLength() const;
+ void setAllowEdit(bool can_edit) { mCanEdit = can_edit; }
+
protected:
class LLTextBase& mEditor;
LLStyleConstSP mStyle;
@@ -170,6 +172,8 @@ protected:
std::string mTooltip;
boost::signals2::connection mImageLoadedConnection;
+ bool mCanEdit { true };
+
// font rendering
LLFontVertexBuffer mFontBufferPreSelection;
LLFontVertexBuffer mFontBufferSelection;
@@ -450,7 +454,7 @@ public:
virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style
/*virtual*/ const std::string& getText() const override;
void setMaxTextLength(S32 length) { mMaxTextByteLength = length; }
- S32 getMaxTextLength() { return mMaxTextByteLength; }
+ S32 getMaxTextLength() const { return mMaxTextByteLength; }
// wide-char versions
void setWText(const LLWString& text);
@@ -489,10 +493,10 @@ public:
LLRect getTextBoundingRect();
LLRect getVisibleDocumentRect() const;
- S32 getVPad() { return mVPad; }
- S32 getHPad() { return mHPad; }
- F32 getLineSpacingMult() { return mLineSpacingMult; }
- S32 getLineSpacingPixels() { return mLineSpacingPixels; } // only for multiline
+ S32 getVPad() const { return mVPad; }
+ S32 getHPad() const { return mHPad; }
+ F32 getLineSpacingMult() const { return mLineSpacingMult; }
+ S32 getLineSpacingPixels() const { return mLineSpacingPixels; } // only for multiline
S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, bool round, bool hit_past_end_of_line = true) const;
LLRect getLocalRectFromDocIndex(S32 pos) const;
@@ -502,7 +506,7 @@ public:
bool getReadOnly() const { return mReadOnly; }
void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; }
- bool getSkipLinkUnderline() { return mSkipLinkUnderline; }
+ bool getSkipLinkUnderline() const { return mSkipLinkUnderline; }
void setParseURLs(bool parse_urls) { mParseHTML = parse_urls; }
@@ -516,8 +520,8 @@ public:
void endOfLine();
void startOfDoc();
void endOfDoc();
- void changePage( S32 delta );
- void changeLine( S32 delta );
+ void changePage(S32 delta);
+ void changeLine(S32 delta);
bool scrolledToStart();
bool scrolledToEnd();
@@ -607,6 +611,7 @@ protected:
bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const;
};
typedef std::multiset segment_set_t;
+ typedef LLStyle::EUnderlineLink e_underline;
// member functions
LLTextBase(const Params &p);
@@ -620,12 +625,13 @@ protected:
virtual void drawSelectionBackground(); // draws the black box behind the selected text
void drawCursor();
void drawText();
+ void drawHighlightedBackground();
// modify contents
S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
S32 removeStringNoUndo(S32 pos, S32 length);
S32 overwriteCharNoUndo(S32 pos, llwchar wc);
- void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false);
+ void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, e_underline underline_link = e_underline::UNDERLINE_ALWAYS);
// manage segments
@@ -673,8 +679,8 @@ protected:
// avatar names are looked up.
void replaceUrl(const std::string &url, const std::string &label, const std::string& icon);
- void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
- void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
+ void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params(), bool force_slurl = false);
+ void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link = e_underline::UNDERLINE_ALWAYS);
S32 normalizeUri(std::string& uri);
protected:
@@ -685,6 +691,7 @@ protected:
}
std::vector getSelectionRects();
+ std::vector> getHighlightedBgRects();
protected:
// text segmentation and flow
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index 500dc8669f..507d8f3ee6 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -46,39 +46,39 @@ protected:
friend class LLUICtrlFactory;
public:
- virtual ~LLTextBox();
+ ~LLTextBox() override;
- /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
+ 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;
- /*virtual*/ void setEnabled(bool enabled);
+ void setEnabled(bool enabled) override;
- /*virtual*/ void setText( const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params() );
+ void setText(const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params()) override;
- void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
- void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
- void setClickedCallback( boost::function cb, void* userdata = NULL );
+ void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
+ void setHAlign(LLFontGL::HAlign align) { mHAlign = align; }
+ void setClickedCallback(boost::function cb, void* userdata = NULL);
- void reshapeToFitText(bool called_from_parent = false);
+ void reshapeToFitText(bool called_from_parent = false);
- S32 getTextPixelWidth();
- S32 getTextPixelHeight();
+ S32 getTextPixelWidth();
+ S32 getTextPixelHeight();
- /*virtual*/ LLSD getValue() const;
- /*virtual*/ bool setTextArg( const std::string& key, const LLStringExplicit& text );
+ LLSD getValue() const override;
+ bool setTextArg(const std::string& key, const LLStringExplicit& text) override;
- void setShowCursorHand(bool show_cursor) { mShowCursorHand = show_cursor; }
+ void setShowCursorHand(bool show_cursor) { mShowCursorHand = show_cursor; }
protected:
- void onUrlLabelUpdated(const std::string &url, const std::string &label);
+ void onUrlLabelUpdated(const std::string& url, const std::string& label);
LLUIString mText;
callback_t mClickedCallback;
bool mShowCursorHand;
protected:
- virtual std::string _getSearchText() const
+ virtual std::string _getSearchText() const override
{
return LLTextBase::_getSearchText() + mText.getString();
}
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index fe4cce29ab..58b785fcdd 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -60,6 +60,7 @@
#include "llurlregistry.h"
#include "lltooltip.h"
#include "llmenugl.h"
+#include "llchatmentionhelper.h"
#include
#include "llcombobox.h"
@@ -270,9 +271,12 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mPrevalidator(p.prevalidator()),
mShowContextMenu(p.show_context_menu),
mShowEmojiHelper(p.show_emoji_helper),
+ mShowChatMentionPicker(false),
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(false),
- mKeepSelectionOnReturn(false)
+ mKeepSelectionOnReturn(false),
+ mSelectAllOnFocusReceived(false),
+ mSelectedOnFocusReceived(false)
{
mSourceID.generate();
@@ -396,6 +400,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen
setCursorPos(loc);
mIsSelecting = true;
+ mSelectedOnFocusReceived = false;
mSelectionEnd = mCursorPos;
mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
}
@@ -675,6 +680,13 @@ bool LLTextEditor::canSelectAll() const
return true;
}
+//virtual
+void LLTextEditor::deselect()
+{
+ LLTextBase::deselect();
+ mSelectedOnFocusReceived = false;
+}
+
// virtual
void LLTextEditor::selectAll()
{
@@ -692,6 +704,11 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p
endSelection();
}
+void LLTextEditor::setSelectAllOnFocusReceived(bool b)
+{
+ mSelectAllOnFocusReceived = b;
+}
+
void LLTextEditor::insertEmoji(llwchar emoji)
{
LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
@@ -714,6 +731,30 @@ void LLTextEditor::handleEmojiCommit(llwchar emoji)
}
}
+void LLTextEditor::handleMentionCommit(std::string name_url)
+{
+ S32 mention_start_pos;
+ if (LLChatMentionHelper::instance().isCursorInNameMention(getWText(), mCursorPos, &mention_start_pos))
+ {
+ remove(mention_start_pos, mCursorPos - mention_start_pos, true);
+ insert(mention_start_pos, utf8str_to_wstring(name_url), false, LLTextSegmentPtr());
+
+ std::string new_text(wstring_to_utf8str(getConvertedText()));
+ clear();
+ appendTextImpl(new_text, LLStyle::Params(), true);
+
+ segment_set_t::const_iterator it = getSegIterContaining(mention_start_pos);
+ if (it != mSegments.end())
+ {
+ setCursorPos((*it)->getEnd() + 1);
+ }
+ else
+ {
+ setCursorPos(mention_start_pos);
+ }
+ }
+}
+
bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
bool handled = false;
@@ -769,8 +810,16 @@ bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
// Delay cursor flashing
resetCursorBlink();
+ mSelectedOnFocusReceived = false;
if (handled && !gFocusMgr.getMouseCapture())
{
+ if (!mask && mSelectAllOnFocusReceived)
+ {
+ mIsSelecting = false;
+ mSelectionStart = getLength();
+ mSelectionEnd = 0;
+ mSelectedOnFocusReceived = true;
+ }
gFocusMgr.setMouseCapture( this );
}
return handled;
@@ -1103,6 +1152,7 @@ void LLTextEditor::removeCharOrTab()
}
tryToShowEmojiHelper();
+ tryToShowMentionHelper();
}
else
{
@@ -1128,6 +1178,7 @@ void LLTextEditor::removeChar()
setCursorPos(mCursorPos - 1);
removeChar(mCursorPos);
tryToShowEmojiHelper();
+ tryToShowMentionHelper();
}
else
{
@@ -1189,6 +1240,7 @@ void LLTextEditor::addChar(llwchar wc)
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
tryToShowEmojiHelper();
+ tryToShowMentionHelper();
if (!mReadOnly && mAutoreplaceCallback != NULL)
{
@@ -1247,6 +1299,31 @@ void LLTextEditor::tryToShowEmojiHelper()
}
}
+void LLTextEditor::tryToShowMentionHelper()
+{
+ if (mReadOnly || !mShowChatMentionPicker)
+ return;
+
+ S32 mention_start_pos;
+ LLWString text(getWText());
+ if (LLChatMentionHelper::instance().isCursorInNameMention(text, mCursorPos, &mention_start_pos))
+ {
+ const LLRect cursor_rect(getLocalRectFromDocIndex(mention_start_pos));
+ std::string name_part(wstring_to_utf8str(text.substr(mention_start_pos, mCursorPos - mention_start_pos)));
+ name_part.erase(0, 1);
+ auto cb = [this](std::string name_url)
+ {
+ handleMentionCommit(name_url);
+ };
+ LLChatMentionHelper::instance().showHelper(this, cursor_rect.mLeft, cursor_rect.mTop, name_part, cb);
+ }
+ else
+ {
+ LLChatMentionHelper::instance().hideHelper();
+ }
+}
+
+
void LLTextEditor::addLineBreakChar(bool group_together)
{
if( !getEnabled() )
@@ -1873,7 +1950,7 @@ bool LLTextEditor::handleKeyHere(KEY key, MASK mask )
// not handled and let the parent take care of field movement.
if (KEY_TAB == key && mTabsToNextField)
{
- return false;
+ return mShowChatMentionPicker && LLChatMentionHelper::instance().handleKey(this, key, mask);
}
if (mReadOnly && mScroller)
@@ -1884,9 +1961,13 @@ bool LLTextEditor::handleKeyHere(KEY key, MASK mask )
}
else
{
- if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask))
+ if (!mReadOnly)
{
- return true;
+ if ((mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) ||
+ (mShowChatMentionPicker && LLChatMentionHelper::instance().handleKey(this, key, mask)))
+ {
+ return true;
+ }
}
if (mEnableTooltipPaste &&
@@ -2142,6 +2223,11 @@ void LLTextEditor::focusLostHelper()
gEditMenuHandler = NULL;
}
+ if (mSelectedOnFocusReceived)
+ {
+ deselect();
+ }
+
if (mCommitOnFocusLost)
{
onCommit();
@@ -3083,3 +3169,21 @@ S32 LLTextEditor::spacesPerTab()
{
return SPACES_PER_TAB;
}
+
+LLWString LLTextEditor::getConvertedText() const
+{
+ LLWString text = getWText();
+ S32 diff = 0;
+ for (auto segment : mSegments)
+ {
+ if (segment && segment->getStyle() && segment->getStyle()->getDrawHighlightBg())
+ {
+ S32 seg_length = segment->getEnd() - segment->getStart();
+ std::string slurl = segment->getStyle()->getLinkHREF();
+
+ text.replace(segment->getStart() + diff, seg_length, utf8str_to_wstring(slurl));
+ diff += (S32)slurl.size() - seg_length;
+ }
+ }
+ return text;
+}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index b2b14b01e2..cdfcbcdd63 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -95,6 +95,8 @@ public:
void insertEmoji(llwchar emoji);
void handleEmojiCommit(llwchar emoji);
+ void handleMentionCommit(std::string name_url);
+
// mousehandler overrides
virtual bool handleMouseDown(S32 x, S32 y, MASK mask);
virtual bool handleMouseUp(S32 x, S32 y, MASK mask);
@@ -142,8 +144,10 @@ public:
virtual bool canDoDelete() const;
virtual void selectAll();
virtual bool canSelectAll() const;
+ virtual void deselect();
void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos);
+ void setSelectAllOnFocusReceived(bool b);
virtual bool canLoadOrSaveToFile();
@@ -200,7 +204,6 @@ public:
const LLUUID& getSourceID() const { return mSourceID; }
const LLTextSegmentPtr getPreviousSegment() const;
- const LLTextSegmentPtr getLastSegment() const;
void getSelectedSegments(segment_vec_t& segments) const;
void setShowContextMenu(bool show) { mShowContextMenu = show; }
@@ -213,12 +216,12 @@ public:
void setPassDelete(bool b) { mPassDelete = b; }
+ LLWString getConvertedText() const;
+
protected:
void showContextMenu(S32 x, S32 y);
void drawPreeditMarker();
- void assignEmbedded(const std::string &s);
-
void removeCharOrTab();
void indentSelectedLines( S32 spaces );
@@ -238,7 +241,6 @@ protected:
void autoIndent();
- void findEmbeddedItemSegments(S32 start, S32 end);
void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
@@ -258,6 +260,7 @@ protected:
S32 remove(S32 pos, S32 length, bool group_with_next_op);
void tryToShowEmojiHelper();
+ void tryToShowMentionHelper();
void focusLostHelper();
void updateAllowingLanguageInput();
bool hasPreeditString() const;
@@ -295,6 +298,7 @@ protected:
bool mAutoIndent;
bool mParseOnTheFly;
+ bool mShowChatMentionPicker;
void updateLinkSegments();
void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; }
@@ -305,7 +309,7 @@ private:
// Methods
//
void pasteHelper(bool is_primary);
- void cleanStringForPaste(LLWString & clean_string);
+ void cleanStringForPaste(LLWString& clean_string);
void pasteTextWithLinebreaks(LLWString & clean_string);
void onKeyStroke();
@@ -334,6 +338,8 @@ private:
bool mEnableTooltipPaste;
bool mPassDelete;
bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
+ bool mSelectAllOnFocusReceived;
+ bool mSelectedOnFocusReceived;
LLUUID mSourceID;
diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h
index c57c979525..5556406fbd 100644
--- a/indra/llui/lltoolbar.h
+++ b/indra/llui/lltoolbar.h
@@ -68,7 +68,7 @@ public:
void reshape(S32 width, S32 height, bool called_from_parent = true);
void setEnabled(bool enabled);
void setCommandId(const LLCommandId& id) { mId = id; }
- LLCommandId getCommandId() { return mId; }
+ LLCommandId getCommandId() const { return mId; }
void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; }
void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; }
@@ -256,7 +256,7 @@ public:
// Methods used in loading and saving toolbar settings
void setButtonType(LLToolBarEnums::ButtonType button_type);
- LLToolBarEnums::ButtonType getButtonType() { return mButtonType; }
+ LLToolBarEnums::ButtonType getButtonType() const { return mButtonType; }
command_id_list_t& getCommandsList() { return mButtonCommands; }
void clearCommandsList();
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 86525c2f7e..74f03618cf 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -390,22 +390,22 @@ void LLToolTip::draw()
}
}
-bool LLToolTip::isFading()
+bool LLToolTip::isFading() const
{
return mFadeTimer.getStarted();
}
-F32 LLToolTip::getVisibleTime()
+F32 LLToolTip::getVisibleTime() const
{
return mVisibleTimer.getStarted() ? mVisibleTimer.getElapsedTimeF32() : 0.f;
}
-bool LLToolTip::hasClickCallback()
+bool LLToolTip::hasClickCallback() const
{
return mHasClickCallback;
}
-void LLToolTip::getToolTipMessage(std::string & message)
+void LLToolTip::getToolTipMessage(std::string& message) const
{
if (mTextBox)
{
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
index 8515504e3b..760acddd6f 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -44,15 +44,15 @@ public:
Params();
};
LLToolTipView(const LLToolTipView::Params&);
- /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ bool handleScrollWheel( S32 x, S32 y, S32 clicks );
+ bool handleHover(S32 x, S32 y, MASK mask) override;
+ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleScrollWheel( S32 x, S32 y, S32 clicks ) override;
void drawStickyRect();
- /*virtual*/ void draw();
+ void draw() override;
};
class LLToolTip : public LLPanel
@@ -98,20 +98,20 @@ public:
Params();
};
- /*virtual*/ void draw();
- /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask);
- /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
- /*virtual*/ void setVisible(bool visible);
+ void draw() override;
+ bool handleHover(S32 x, S32 y, MASK mask) override;
+ void onMouseLeave(S32 x, S32 y, MASK mask) override;
+ void setVisible(bool visible) override;
- bool isFading();
- F32 getVisibleTime();
- bool hasClickCallback();
+ bool isFading() const;
+ F32 getVisibleTime() const;
+ bool hasClickCallback() const;
LLToolTip(const Params& p);
virtual void initFromParams(const LLToolTip::Params& params);
- void getToolTipMessage(std::string & message);
- bool isTooltipPastable() { return mIsTooltipPastable; }
+ void getToolTipMessage(std::string & message) const;
+ bool isTooltipPastable() const { return mIsTooltipPastable; }
protected:
void updateTextBox();
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 9890d3f7ef..b2dcb6dc88 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -154,7 +154,7 @@ public:
sanitizeRange();
}
- S32 clamp(S32 input)
+ S32 clamp(S32 input) const
{
if (input < mMin) return mMin;
if (input > mMax) return mMax;
@@ -168,8 +168,8 @@ public:
sanitizeRange();
}
- S32 getMin() { return mMin; }
- S32 getMax() { return mMax; }
+ S32 getMin() const { return mMin; }
+ S32 getMax() const { return mMax; }
bool operator==(const RangeS32& other) const
{
@@ -223,7 +223,7 @@ public:
mValue = clamp(value);
}
- S32 get()
+ S32 get() const
{
return mValue;
}
@@ -253,7 +253,7 @@ public:
static std::string getLanguage(); // static for lldateutil_test compatibility
//helper functions (should probably move free standing rendering helper functions here)
- LLView* getRootView() { return mRootView; }
+ LLView* getRootView() const { return mRootView; }
void setRootView(LLView* view) { mRootView = view; }
/**
* Walk the LLView tree to resolve a path
@@ -296,7 +296,7 @@ public:
LLControlGroup& getControlControlGroup (std::string_view controlname);
F32 getMouseIdleTime() { return mMouseIdleTimer.getElapsedTimeF32(); }
void resetMouseIdleTimer() { mMouseIdleTimer.reset(); }
- LLWindow* getWindow() { return mWindow; }
+ LLWindow* getWindow() const { return mWindow; }
void addPopup(LLView*);
void removePopup(LLView*);
diff --git a/indra/llui/lluiconstants.h b/indra/llui/lluiconstants.h
index 5fdfd37c6e..a317c66008 100644
--- a/indra/llui/lluiconstants.h
+++ b/indra/llui/lluiconstants.h
@@ -28,23 +28,23 @@
#define LL_LLUICONSTANTS_H
// spacing for small font lines of text, like LLTextBoxes
-const S32 LINE = 16;
+constexpr S32 LINE = 16;
// spacing for larger lines of text
-const S32 LINE_BIG = 24;
+constexpr S32 LINE_BIG = 24;
// default vertical padding
-const S32 VPAD = 4;
+constexpr S32 VPAD = 4;
// default horizontal padding
-const S32 HPAD = 4;
+constexpr S32 HPAD = 4;
// Account History, how far to look into past
-const S32 SUMMARY_INTERVAL = 7; // one week
-const S32 SUMMARY_MAX = 8; //
-const S32 DETAILS_INTERVAL = 1; // one day
-const S32 DETAILS_MAX = 30; // one month
-const S32 TRANSACTIONS_INTERVAL = 1;// one day
-const S32 TRANSACTIONS_MAX = 30; // one month
+constexpr S32 SUMMARY_INTERVAL = 7; // one week
+constexpr S32 SUMMARY_MAX = 8; //
+constexpr S32 DETAILS_INTERVAL = 1; // one day
+constexpr S32 DETAILS_MAX = 30; // one month
+constexpr S32 TRANSACTIONS_INTERVAL = 1;// one day
+constexpr S32 TRANSACTIONS_MAX = 30; // one month
#endif
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 8cd9950917..bcaf479b0f 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -39,9 +39,9 @@
#include "llviewmodel.h" // *TODO move dependency to .cpp file
#include "llsearchablecontrol.h"
-const bool TAKE_FOCUS_YES = true;
-const bool TAKE_FOCUS_NO = false;
-const S32 DROP_SHADOW_FLOATER = 5;
+constexpr bool TAKE_FOCUS_YES = true;
+constexpr bool TAKE_FOCUS_NO = false;
+constexpr S32 DROP_SHADOW_FLOATER = 5;
class LLUICtrl
: public LLView, public boost::signals2::trackable
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 75e7e396bc..91221dc7f3 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -184,7 +184,7 @@ fail:
template
static T* getDefaultWidget(std::string_view name)
{
- typename T::Params widget_params;
+ typename T::Params widget_params{};
widget_params.name = std::string(name);
return create(widget_params);
}
diff --git a/indra/llui/llundo.h b/indra/llui/llundo.h
index dc40702be0..990745e530 100644
--- a/indra/llui/llundo.h
+++ b/indra/llui/llundo.h
@@ -42,7 +42,7 @@ public:
LLUndoAction(): mClusterID(0) {};
virtual ~LLUndoAction(){};
private:
- S32 mClusterID;
+ S32 mClusterID;
};
LLUndoBuffer( LLUndoAction (*create_func()), S32 initial_count );
@@ -51,8 +51,8 @@ public:
LLUndoAction *getNextAction(bool setClusterBegin = true);
bool undoAction();
bool redoAction();
- bool canUndo() { return (mNextAction != mFirstAction); }
- bool canRedo() { return (mNextAction != mLastAction); }
+ bool canUndo() const { return (mNextAction != mFirstAction); }
+ bool canRedo() const { return (mNextAction != mLastAction); }
void flushActions();
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index b6b450c2a1..8b320b59cc 100644
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -30,6 +30,7 @@
#include "llview.h"
#include "llwindow.h"
#include "llurlregistry.h"
+#include "v3dmath.h"
// global state for the callback functions
@@ -116,6 +117,16 @@ void LLUrlAction::teleportToLocation(std::string url)
}
}
+void LLUrlAction::zoomInObject(std::string url)
+{
+ LLUrlMatch match;
+ std::string object_id = getObjectId(url);
+ if (LLUUID::validate(object_id) && LLUrlRegistry::instance().findUrl(url, match))
+ {
+ executeSLURL("secondlife:///app/object/" + object_id + "/zoomin/" + match.getLocation());
+ }
+}
+
void LLUrlAction::showLocationOnMap(std::string url)
{
LLUrlMatch match;
@@ -128,6 +139,23 @@ void LLUrlAction::showLocationOnMap(std::string url)
}
}
+void LLUrlAction::showParcelOnMap(std::string url)
+{
+ LLSD path_array = LLURI(url).pathArray();
+ auto path_parts = path_array.size();
+
+ if (path_parts < 3) // no parcel id
+ {
+ LL_WARNS() << "Global coordinates are missing in url: [" << url << "]" << LL_ENDL;
+ return;
+ }
+
+ LLVector3d parcel_pos = LLUrlEntryParcel::getParcelPos(LLUUID(LLURI::unescape(path_array[2])));
+ std::ostringstream pos;
+ pos << parcel_pos.mdV[VX] << '/' << parcel_pos.mdV[VY] << '/' << parcel_pos.mdV[VZ];
+ executeSLURL("secondlife:///app/worldmap_global/" + pos.str());
+}
+
void LLUrlAction::copyURLToClipboard(std::string url)
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url));
@@ -142,6 +170,16 @@ void LLUrlAction::copyLabelToClipboard(std::string url)
}
}
+std::string LLUrlAction::getURLLabel(std::string url)
+{
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return match.getLabel();
+ }
+ return "";
+}
+
void LLUrlAction::showProfile(std::string url)
{
// Get id from 'secondlife:///app/{cmd}/{id}/{action}'
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index 0f54b66299..56d459bb26 100644
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -45,8 +45,6 @@
class LLUrlAction
{
public:
- LLUrlAction();
-
/// load a Url in the user's preferred web browser
static void openURL(std::string url);
@@ -62,9 +60,15 @@ public:
/// if the Url specifies an SL location, teleport there
static void teleportToLocation(std::string url);
+ /// If the Url specifies an object id, attempt to zoom in.
+ /// If not possible to zoom in, show on map
+ static void zoomInObject(std::string url);
+
/// if the Url specifies an SL location, show it on a map
static void showLocationOnMap(std::string url);
+ static void showParcelOnMap(std::string url);
+
/// perform the appropriate action for left-clicking on a Url
static void clickAction(std::string url, bool trusted_content);
@@ -74,6 +78,8 @@ public:
/// copy a Url to the clipboard
static void copyURLToClipboard(std::string url);
+ static std::string getURLLabel(std::string url);
+
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url);
static std::string getUserID(std::string url);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 77f132e9d8..95603d7ed5 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -29,7 +29,6 @@
#include "llurlentry.h"
#include "lluictrl.h"
#include "lluri.h"
-#include "llurlmatch.h"
#include "llurlregistry.h"
#include "lluriparser.h"
@@ -42,13 +41,12 @@
#include "lluicolortable.h"
#include "message.h"
#include "llexperiencecache.h"
-
-#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
+#include "v3dmath.h"
// Utility functions
std::string localize_slapp_label(const std::string& url, const std::string& full_name);
-
+LLUUID LLUrlEntryBase::sAgentID(LLUUID::null);
LLUrlEntryBase::LLUrlEntryBase()
{
}
@@ -68,7 +66,7 @@ std::string LLUrlEntryBase::getIcon(const std::string &url)
return mIcon;
}
-LLStyle::Params LLUrlEntryBase::getStyle() const
+LLStyle::Params LLUrlEntryBase::getStyle(const std::string &url) const
{
LLStyle::Params style_params;
style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
@@ -631,6 +629,11 @@ LLUUID LLUrlEntryAgent::getID(const std::string &string) const
return LLUUID(getIDStringFromUrl(string));
}
+bool LLUrlEntryAgent::isAgentID(const std::string& url) const
+{
+ return sAgentID == getID(url);
+}
+
std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
{
// return a tooltip corresponding to the URL type instead of the generic one
@@ -667,10 +670,14 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
return LLTrans::getString("TooltipAgentUrl");
}
-bool LLUrlEntryAgent::underlineOnHoverOnly(const std::string &string) const
+LLStyle::EUnderlineLink LLUrlEntryAgent::getUnderline(const std::string& string) const
{
std::string url = getUrl(string);
- return LLStringUtil::endsWith(url, "/about") || LLStringUtil::endsWith(url, "/inspect");
+ if (LLStringUtil::endsWith(url, "/about") || LLStringUtil::endsWith(url, "/inspect"))
+ {
+ return LLStyle::EUnderlineLink::UNDERLINE_ON_HOVER;
+ }
+ return LLStyle::EUnderlineLink::UNDERLINE_ALWAYS;
}
std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
@@ -712,11 +719,12 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
}
-LLStyle::Params LLUrlEntryAgent::getStyle() const
+LLStyle::Params LLUrlEntryAgent::getStyle(const std::string &url) const
{
- LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+ LLStyle::Params style_params = LLUrlEntryBase::getStyle(url);
style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+
return style_params;
}
@@ -751,6 +759,10 @@ std::string localize_slapp_label(const std::string& url, const std::string& full
{
return LLTrans::getString("SLappAgentRemoveFriend") + " " + full_name;
}
+ if (LLStringUtil::endsWith(url, "/mention"))
+ {
+ return "@" + full_name;
+ }
return full_name;
}
@@ -762,6 +774,36 @@ std::string LLUrlEntryAgent::getIcon(const std::string &url)
return mIcon;
}
+///
+/// LLUrlEntryAgentMention Describes a chat mention Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/mention
+///
+LLUrlEntryAgentMention::LLUrlEntryAgentMention()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/mention", boost::regex::perl | boost::regex::icase);
+ mMenuName = "menu_url_agent.xml";
+ mIcon = std::string();
+}
+
+LLStyle::EUnderlineLink LLUrlEntryAgentMention::getUnderline(const std::string& string) const
+{
+ return LLStyle::EUnderlineLink::UNDERLINE_NEVER;
+}
+
+LLStyle::Params LLUrlEntryAgentMention::getStyle(const std::string& url) const
+{
+ LLStyle::Params style_params = LLUrlEntryAgent::getStyle(url);
+ style_params.color = LLUIColorTable::instance().getColor("ChatMentionFont");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("ChatMentionFont");
+ style_params.font.style = "NORMAL";
+ style_params.draw_highlight_bg = true;
+
+ LLUUID agent_id(getIDStringFromUrl(url));
+ style_params.highlight_bg_color = LLUIColorTable::instance().getColor((agent_id == sAgentID) ? "ChatSelfMentionHighlight" : "ChatMentionHighlight");
+
+ return style_params;
+}
+
//
// LLUrlEntryAgentName describes a Second Life agent name Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
@@ -823,7 +865,7 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab
}
}
-LLStyle::Params LLUrlEntryAgentName::getStyle() const
+LLStyle::Params LLUrlEntryAgentName::getStyle(const std::string &url) const
{
// don't override default colors
return LLStyle::Params().is_link(false);
@@ -959,9 +1001,9 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
}
}
-LLStyle::Params LLUrlEntryGroup::getStyle() const
+LLStyle::Params LLUrlEntryGroup::getStyle(const std::string &url) const
{
- LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+ LLStyle::Params style_params = LLUrlEntryBase::getStyle(url);
style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
return style_params;
@@ -1037,11 +1079,11 @@ std::string LLUrlEntryChat::getLabel(const std::string &url, const LLUrlLabelCal
}
// LLUrlEntryParcel statics.
-LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null);
LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null);
LLHost LLUrlEntryParcel::sRegionHost;
bool LLUrlEntryParcel::sDisconnected(false);
std::set LLUrlEntryParcel::sParcelInfoObservers;
+std::map LLUrlEntryParcel::sParcelPos;
///
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
@@ -1134,6 +1176,20 @@ void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data)
url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label);
}
}
+ if (sParcelPos.find(parcel_data.parcel_id) == sParcelPos.end())
+ {
+ sParcelPos[parcel_data.parcel_id] = LLVector3d(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z);
+ }
+}
+
+// static
+LLVector3d LLUrlEntryParcel::getParcelPos(const LLUUID& parcel_id)
+{
+ if (sParcelPos.find(parcel_id) != sParcelPos.end())
+ {
+ return sParcelPos[parcel_id];
+ }
+ return LLVector3d();
}
//
@@ -1371,17 +1427,17 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const
return LLUrlEntryBase::getTooltip(string);
}
-bool LLUrlEntrySLLabel::underlineOnHoverOnly(const std::string &string) const
+LLStyle::EUnderlineLink LLUrlEntrySLLabel::getUnderline(const std::string& string) const
{
std::string url = getUrl(string);
- LLUrlMatch match;
+ LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
- return match.underlineOnHoverOnly();
+ return match.getUnderline();
}
// unrecognized URL? should not happen
- return LLUrlEntryBase::underlineOnHoverOnly(string);
+ return LLUrlEntryBase::getUnderline(string);
}
//
@@ -1445,7 +1501,7 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
return getUrl(url);
}
-LLStyle::Params LLUrlEntryNoLink::getStyle() const
+LLStyle::Params LLUrlEntryNoLink::getStyle(const std::string &url) const
{
// Don't render as URL (i.e. no context menu or hand cursor).
return LLStyle::Params().is_link(false);
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index fffee88496..efb5081103 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -41,6 +41,9 @@
#include
class LLAvatarName;
+class LLVector3d;
+
+#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
typedef boost::signals2::signal mObservers;
+
+ static LLUUID sAgentID;
};
///
@@ -224,9 +233,13 @@ public:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getIcon(const std::string &url);
/*virtual*/ std::string getTooltip(const std::string &string) const;
- /*virtual*/ LLStyle::Params getStyle() const;
+ /*virtual*/ LLStyle::Params getStyle(const std::string &url) const;
/*virtual*/ LLUUID getID(const std::string &string) const;
- /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
+
+ bool isAgentID(const std::string& url) const;
+
+ LLStyle::EUnderlineLink getUnderline(const std::string& string) const;
+
protected:
/*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
private:
@@ -236,6 +249,19 @@ private:
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
};
+///
+/// LLUrlEntryAgentMention Describes a chat mention Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/mention
+class LLUrlEntryAgentMention : public LLUrlEntryAgent
+{
+public:
+ LLUrlEntryAgentMention();
+
+ LLStyle::Params getStyle(const std::string& url) const;
+ LLStyle::EUnderlineLink getUnderline(const std::string& string) const;
+ bool getSkipProfileIcon(const std::string& string) const { return true; };
+};
+
///
/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
@@ -257,7 +283,7 @@ public:
mAvatarNameCacheConnections.clear();
}
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
- /*virtual*/ LLStyle::Params getStyle() const;
+ /*virtual*/ LLStyle::Params getStyle(const std::string &url) const;
protected:
// override this to pull out relevant name fields
virtual std::string getName(const LLAvatarName& avatar_name) = 0;
@@ -339,7 +365,7 @@ class LLUrlEntryGroup : public LLUrlEntryBase
public:
LLUrlEntryGroup();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
- /*virtual*/ LLStyle::Params getStyle() const;
+ /*virtual*/ LLStyle::Params getStyle(const std::string &url) const;
/*virtual*/ LLUUID getID(const std::string &string) const;
private:
void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
@@ -411,21 +437,22 @@ public:
// Processes parcel label and triggers notifying observers.
static void processParcelInfo(const LLParcelData& parcel_data);
- // Next 4 setters are used to update agent and viewer connection information
+ static LLVector3d getParcelPos(const LLUUID& parcel_id);
+
+ // Next setters are used to update agent and viewer connection information
// upon events like user login, viewer disconnect and user changing region host.
// These setters are made public to be accessible from newview and should not be
// used in other cases.
- static void setAgentID(const LLUUID& id) { sAgentID = id; }
static void setSessionID(const LLUUID& id) { sSessionID = id; }
static void setRegionHost(const LLHost& host) { sRegionHost = host; }
static void setDisconnected(bool disconnected) { sDisconnected = disconnected; }
private:
- static LLUUID sAgentID;
static LLUUID sSessionID;
static LLHost sRegionHost;
static bool sDisconnected;
static std::set sParcelInfoObservers;
+ static std::map sParcelPos;
};
///
@@ -486,7 +513,7 @@ public:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getTooltip(const std::string &string) const;
- /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
+ LLStyle::EUnderlineLink getUnderline(const std::string& string) const;
};
///
@@ -510,7 +537,7 @@ public:
LLUrlEntryNoLink();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
- /*virtual*/ LLStyle::Params getStyle() const;
+ /*virtual*/ LLStyle::Params getStyle(const std::string &url) const;
};
///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index bfa3b167b1..f093934ca9 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -37,8 +37,9 @@ LLUrlMatch::LLUrlMatch() :
mIcon(""),
mMenuName(""),
mLocation(""),
- mUnderlineOnHoverOnly(false),
- mTrusted(false)
+ mUnderline(e_underline::UNDERLINE_ALWAYS),
+ mTrusted(false),
+ mSkipProfileIcon(false)
{
}
@@ -46,7 +47,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, const std
const std::string& query, const std::string &tooltip,
const std::string &icon, const LLStyle::Params& style,
const std::string &menu, const std::string &location,
- const LLUUID& id, bool underline_on_hover_only, bool trusted)
+ const LLUUID& id, e_underline underline, bool trusted, bool skip_icon)
{
mStart = start;
mEnd = end;
@@ -60,6 +61,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, const std
mMenuName = menu;
mLocation = location;
mID = id;
- mUnderlineOnHoverOnly = underline_on_hover_only;
+ mUnderline = underline;
mTrusted = trusted;
+ mSkipProfileIcon = skip_icon;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index ba822fbda6..418a21f963 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -31,7 +31,6 @@
//#include "linden_common.h"
#include
-#include
#include "llstyle.h"
///
@@ -80,18 +79,20 @@ public:
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
- /// Should this link text be underlined only when mouse is hovered over it?
- bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
+ typedef LLStyle::EUnderlineLink e_underline;
+ e_underline getUnderline() const { return mUnderline; }
/// Return true if Url is trusted.
bool isTrusted() const { return mTrusted; }
+ bool getSkipProfileIcon() const { return mSkipProfileIcon; }
+
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string& query, const std::string &tooltip, const std::string &icon,
const LLStyle::Params& style, const std::string &menu,
const std::string &location, const LLUUID& id,
- bool underline_on_hover_only = false, bool trusted = false);
+ e_underline underline = e_underline::UNDERLINE_ALWAYS, bool trusted = false, bool skip_icon = false);
const LLUUID& getID() const { return mID; }
private:
@@ -106,8 +107,9 @@ private:
std::string mLocation;
LLUUID mID;
LLStyle::Params mStyle;
- bool mUnderlineOnHoverOnly;
+ e_underline mUnderline;
bool mTrusted;
+ bool mSkipProfileIcon;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index cec1ddfc57..cb101d325d 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -62,6 +62,8 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntryAgentUserName());
// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
// LLUrlEntryAgent is a less specific (catchall for agent urls)
+ mUrlEntryAgentMention = new LLUrlEntryAgentMention();
+ registerUrl(mUrlEntryAgentMention);
registerUrl(new LLUrlEntryAgent());
registerUrl(new LLUrlEntryChat());
registerUrl(new LLUrlEntryGroup());
@@ -155,7 +157,7 @@ static bool stringHasUrl(const std::string &text)
text.find("@") != std::string::npos);
}
-bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted)
+bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted, bool skip_non_mentions)
{
// avoid costly regexes if there is clearly no URL in the text
if (! stringHasUrl(text))
@@ -176,6 +178,11 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
continue;
}
+ if (skip_non_mentions && (mUrlEntryAgentMention != *it))
+ {
+ continue;
+ }
+
LLUrlEntryBase *url_entry = *it;
U32 start = 0, end = 0;
@@ -233,12 +240,13 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getQuery(url),
match_entry->getTooltip(url),
match_entry->getIcon(url),
- match_entry->getStyle(),
+ match_entry->getStyle(url),
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->getID(url),
- match_entry->underlineOnHoverOnly(url),
- match_entry->isTrusted());
+ match_entry->getUnderline(url),
+ match_entry->isTrusted(),
+ match_entry->getSkipProfileIcon(url));
return true;
}
@@ -274,7 +282,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getMenuName(),
match.getLocation(),
match.getID(),
- match.underlineOnHoverOnly());
+ match.getUnderline(),
+ false,
+ match.getSkipProfileIcon());
return true;
}
return false;
@@ -317,3 +327,30 @@ void LLUrlRegistry::setKeybindingHandler(LLKeyBindingToStringHandler* handler)
LLUrlEntryKeybinding *entry = (LLUrlEntryKeybinding*)mUrlEntryKeybinding;
entry->setHandler(handler);
}
+
+bool LLUrlRegistry::containsAgentMention(const std::string& text)
+{
+ // avoid costly regexes if there is clearly no URL in the text
+ if (!stringHasUrl(text))
+ {
+ return false;
+ }
+
+ try
+ {
+ boost::sregex_iterator it(text.begin(), text.end(), mUrlEntryAgentMention->getPattern());
+ boost::sregex_iterator end;
+ for (; it != end; ++it)
+ {
+ if (mUrlEntryAgentMention->isAgentID(it->str()))
+ {
+ return true;
+ }
+ }
+ }
+ catch (boost::regex_error&)
+ {
+ LL_INFOS() << "Regex error for: " << text << LL_ENDL;
+ }
+ return false;
+}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 64cfec3960..592e422487 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -34,7 +34,6 @@
#include "llstring.h"
#include
-#include
class LLKeyBindingToStringHandler;
@@ -76,7 +75,7 @@ public:
/// your callback is invoked if the matched Url's label changes in the future
bool findUrl(const std::string &text, LLUrlMatch &match,
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback,
- bool is_content_trusted = false);
+ bool is_content_trusted = false, bool skip_non_mentions = false);
/// a slightly less efficient version of findUrl for wide strings
bool findUrl(const LLWString &text, LLUrlMatch &match,
@@ -93,6 +92,8 @@ public:
// Set handler for url registry to be capable of parsing and populating keybindings
void setKeybindingHandler(LLKeyBindingToStringHandler* handler);
+ bool containsAgentMention(const std::string& text);
+
private:
std::vector mUrlEntry;
LLUrlEntryBase* mUrlEntryTrusted;
@@ -102,6 +103,7 @@ private:
LLUrlEntryBase* mUrlEntrySLLabel;
LLUrlEntryBase* mUrlEntryNoLink;
LLUrlEntryBase* mUrlEntryKeybinding;
+ LLUrlEntryBase* mUrlEntryAgentMention;
};
#endif
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 710ec3d05e..97212a9d2d 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -54,17 +54,17 @@
class LLSD;
-const U32 FOLLOWS_NONE = 0x00;
-const U32 FOLLOWS_LEFT = 0x01;
-const U32 FOLLOWS_RIGHT = 0x02;
-const U32 FOLLOWS_TOP = 0x10;
-const U32 FOLLOWS_BOTTOM = 0x20;
-const U32 FOLLOWS_ALL = 0x33;
+constexpr U32 FOLLOWS_NONE = 0x00;
+constexpr U32 FOLLOWS_LEFT = 0x01;
+constexpr U32 FOLLOWS_RIGHT = 0x02;
+constexpr U32 FOLLOWS_TOP = 0x10;
+constexpr U32 FOLLOWS_BOTTOM = 0x20;
+constexpr U32 FOLLOWS_ALL = 0x33;
-const bool MOUSE_OPAQUE = true;
-const bool NOT_MOUSE_OPAQUE = false;
+constexpr bool MOUSE_OPAQUE = true;
+constexpr bool NOT_MOUSE_OPAQUE = false;
-const U32 GL_NAME_UI_RESERVED = 2;
+constexpr U32 GL_NAME_UI_RESERVED = 2;
// maintains render state during traversal of UI tree
@@ -241,7 +241,7 @@ public:
void setUseBoundingRect( bool use_bounding_rect );
bool getUseBoundingRect() const;
- ECursorType getHoverCursor() { return mHoverCursor; }
+ ECursorType getHoverCursor() const { return mHoverCursor; }
static F32 getTooltipTimeout();
virtual const std::string getToolTip() const;
@@ -265,7 +265,7 @@ public:
void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; }
S32 getDefaultTabGroup() const { return mDefaultTabGroup; }
- S32 getLastTabGroup() { return mLastTabGroup; }
+ S32 getLastTabGroup() const { return mLastTabGroup; }
bool isInVisibleChain() const;
bool isInEnabledChain() const;
diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h
index 1f118a0d20..a4bb748b77 100644
--- a/indra/llui/llviewborder.h
+++ b/indra/llui/llviewborder.h
@@ -92,7 +92,6 @@ public:
private:
void drawOnePixelLines();
void drawTwoPixelLines();
- void drawTextures();
EBevel mBevel;
EStyle mStyle;
diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h
index 9e752e8090..5636c068d8 100644
--- a/indra/llui/llviewereventrecorder.h
+++ b/indra/llui/llviewereventrecorder.h
@@ -61,7 +61,7 @@ public:
std::string get_xui();
void update_xui(std::string xui);
- bool getLoggingStatus(){return logEvents;};
+ bool getLoggingStatus() const { return logEvents; }
void setEventLoggingOn();
void setEventLoggingOff();
diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h
index 61a78b2398..fbfda04585 100644
--- a/indra/llui/llvirtualtrackball.h
+++ b/indra/llui/llvirtualtrackball.h
@@ -78,20 +78,20 @@ public:
};
- virtual ~LLVirtualTrackball();
- /*virtual*/ bool postBuild();
+ ~LLVirtualTrackball() override;
+ bool postBuild() override;
- virtual bool handleHover(S32 x, S32 y, MASK mask);
- virtual bool handleMouseUp(S32 x, S32 y, MASK mask);
- virtual bool handleMouseDown(S32 x, S32 y, MASK mask);
- virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask);
- virtual bool handleKeyHere(KEY key, MASK mask);
+ bool handleHover(S32 x, S32 y, MASK mask) override;
+ bool handleMouseUp(S32 x, S32 y, MASK mask) override;
+ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ bool handleKeyHere(KEY key, MASK mask) override;
- virtual void draw();
+ void draw() override;
- virtual void setValue(const LLSD& value);
- void setValue(F32 x, F32 y, F32 z, F32 w);
- virtual LLSD getValue() const;
+ void setValue(const LLSD& value) override;
+ void setValue(F32 x, F32 y, F32 z, F32 w);
+ LLSD getValue() const override;
void setRotation(const LLQuaternion &value);
LLQuaternion getRotation() const;
@@ -102,7 +102,6 @@ public:
protected:
friend class LLUICtrlFactory;
LLVirtualTrackball(const Params&);
- void onEditChange();
protected:
LLTextBox* mNLabel;
diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h
index da29188943..ee230cd2f6 100644
--- a/indra/llui/llwindowshade.h
+++ b/indra/llui/llwindowshade.h
@@ -49,7 +49,7 @@ public:
};
void show(LLNotificationPtr);
- /*virtual*/ void draw();
+ void draw() override;
void hide();
bool isShown() const;
diff --git a/indra/llui/llxyvector.h b/indra/llui/llxyvector.h
index bc41213c13..646771f387 100644
--- a/indra/llui/llxyvector.h
+++ b/indra/llui/llxyvector.h
@@ -65,18 +65,18 @@ public:
};
- virtual ~LLXYVector();
- /*virtual*/ bool postBuild();
+ ~LLXYVector() override;
+ bool postBuild() override;
- virtual bool handleHover(S32 x, S32 y, MASK mask);
- virtual bool handleMouseUp(S32 x, S32 y, MASK mask);
- virtual bool handleMouseDown(S32 x, S32 y, MASK mask);
+ bool handleHover(S32 x, S32 y, MASK mask) override;
+ bool handleMouseUp(S32 x, S32 y, MASK mask) override;
+ bool handleMouseDown(S32 x, S32 y, MASK mask) override;
- virtual void draw();
+ void draw() override;
- virtual void setValue(const LLSD& value);
- void setValue(F32 x, F32 y);
- virtual LLSD getValue() const;
+ void setValue(const LLSD& value) override;
+ void setValue(F32 x, F32 y);
+ LLSD getValue() const override;
protected:
friend class LLUICtrlFactory;
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index 0daa767766..20951ff816 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -430,9 +430,7 @@ void ll_set_device_module_capture_device(rtc::scoped_refptrSetRecordingDevice(device + 1);
#endif
- device_module->SetStereoRecording(false);
device_module->InitMicrophone();
- device_module->InitRecording();
}
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
@@ -473,6 +471,8 @@ void LLWebRTCImpl::setCaptureDevice(const std::string &id)
ll_set_device_module_capture_device(mPeerDeviceModule, recordingDevice);
if (recording)
{
+ mPeerDeviceModule->SetStereoRecording(false);
+ mPeerDeviceModule->InitRecording();
mPeerDeviceModule->StartRecording();
}
});
@@ -494,9 +494,7 @@ void ll_set_device_module_render_device(rtc::scoped_refptrSetPlayoutDevice(device + 1);
#endif
- device_module->SetStereoPlayout(true);
device_module->InitSpeaker();
- device_module->InitPlayout();
}
void LLWebRTCImpl::setRenderDevice(const std::string &id)
@@ -540,6 +538,8 @@ void LLWebRTCImpl::setRenderDevice(const std::string &id)
ll_set_device_module_render_device(mPeerDeviceModule, playoutDevice);
if (playing)
{
+ mPeerDeviceModule->SetStereoPlayout(true);
+ mPeerDeviceModule->InitPlayout();
mPeerDeviceModule->StartPlayout();
}
});
@@ -670,7 +670,10 @@ LLWebRTCPeerConnectionInterface *LLWebRTCImpl::newPeerConnection()
peerConnection->init(this);
mPeerConnections.emplace_back(peerConnection);
- peerConnection->enableSenderTracks(!mMute);
+ // Should it really start disabled?
+ // Seems like something doesn't get the memo and senders need to be reset later
+ // to remove the voice indicator from taskbar
+ peerConnection->enableSenderTracks(false);
if (mPeerConnections.empty())
{
setRecording(true);
@@ -704,7 +707,7 @@ void LLWebRTCImpl::freePeerConnection(LLWebRTCPeerConnectionInterface* peer_conn
LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() :
mWebRTCImpl(nullptr),
mPeerConnection(nullptr),
- mMute(true),
+ mMute(MUTE_INITIAL),
mAnswerReceived(false)
{
}
@@ -739,6 +742,19 @@ void LLWebRTCPeerConnectionImpl::terminate()
}
}
+ // to remove 'Secondlife is recording' icon from taskbar
+ // if user was speaking
+ auto senders = mPeerConnection->GetSenders();
+ for (auto& sender : senders)
+ {
+ auto track = sender->track();
+ if (track)
+ {
+ track->set_enabled(false);
+ }
+ }
+ mPeerConnection->SetAudioRecording(false);
+
mPeerConnection->Close();
if (mLocalStream)
{
@@ -828,6 +844,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
audioOptions.auto_gain_control = true;
audioOptions.echo_cancellation = true;
audioOptions.noise_suppression = true;
+ audioOptions.init_recording_on_send = false;
mLocalStream = mPeerConnectionFactory->CreateLocalMediaStream("SLStream");
@@ -887,6 +904,7 @@ void LLWebRTCPeerConnectionImpl::enableSenderTracks(bool enable)
// set_enabled shouldn't be done on the worker thread.
if (mPeerConnection)
{
+ mPeerConnection->SetAudioRecording(enable);
auto senders = mPeerConnection->GetSenders();
for (auto &sender : senders)
{
@@ -932,12 +950,23 @@ void LLWebRTCPeerConnectionImpl::AnswerAvailable(const std::string &sdp)
void LLWebRTCPeerConnectionImpl::setMute(bool mute)
{
- mMute = mute;
+ EMicMuteState new_state = mute ? MUTE_MUTED : MUTE_UNMUTED;
+ if (new_state == mMute)
+ {
+ return; // no change
+ }
+ bool force_reset = mMute == MUTE_INITIAL && mute;
+ bool enable = !mute;
+ mMute = new_state;
+
mWebRTCImpl->PostSignalingTask(
- [this]()
+ [this, force_reset, enable]()
{
if (mPeerConnection)
{
+ // SetAudioRecording must be called before enabling/disabling tracks.
+ mPeerConnection->SetAudioRecording(enable);
+
auto senders = mPeerConnection->GetSenders();
RTC_LOG(LS_INFO) << __FUNCTION__ << (mMute ? "disabling" : "enabling") << " streams count " << senders.size();
@@ -946,7 +975,14 @@ void LLWebRTCPeerConnectionImpl::setMute(bool mute)
auto track = sender->track();
if (track)
{
- track->set_enabled(!mMute);
+ if (force_reset)
+ {
+ // Force notify observers
+ // Was it disabled too early?
+ // Without this microphone icon in Win's taskbar will stay
+ track->set_enabled(true);
+ }
+ track->set_enabled(enable);
}
}
}
@@ -955,7 +991,17 @@ void LLWebRTCPeerConnectionImpl::setMute(bool mute)
void LLWebRTCPeerConnectionImpl::resetMute()
{
- setMute(mMute);
+ switch(mMute)
+ {
+ case MUTE_MUTED:
+ setMute(true);
+ break;
+ case MUTE_UNMUTED:
+ setMute(false);
+ break;
+ default:
+ break;
+ }
}
void LLWebRTCPeerConnectionImpl::setReceiveVolume(float volume)
diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h
index b93a1fdb01..b6294dbd4a 100644
--- a/indra/llwebrtc/llwebrtc_impl.h
+++ b/indra/llwebrtc/llwebrtc_impl.h
@@ -417,7 +417,12 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
rtc::scoped_refptr mPeerConnectionFactory;
- bool mMute;
+ typedef enum {
+ MUTE_INITIAL,
+ MUTE_MUTED,
+ MUTE_UNMUTED,
+ } EMicMuteState;
+ EMicMuteState mMute;
// signaling
std::vector mSignalingObserverList;
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index d40e549559..58a17227a7 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -629,7 +629,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
};
int string_length = [aString length];
- unichar* text = (unichar*)malloc(sizeof(unichar) * string_length);
+ unichar *text = new unichar[string_length];
attributedStringInfo segments;
// I used 'respondsToSelector:@selector(string)'
// to judge aString is an attributed string or not.
@@ -647,7 +647,6 @@ attributedStringInfo getSegments(NSAttributedString *str)
segments.seg_standouts.push_back(true);
}
setMarkedText(text, selected, replacement, string_length, segments);
- free(text);
if (string_length > 0)
{
mHasMarkedText = TRUE;
@@ -658,6 +657,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
// we must clear the marked text when aString is null.
[self unmarkText];
}
+
+ delete [] text;
} else {
if (mHasMarkedText)
{
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 378e633cd2..eb11a28360 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -103,7 +103,6 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags)
mFullscreen(fullscreen),
mFullscreenWidth(0),
mFullscreenHeight(0),
- mFullscreenBits(0),
mFullscreenRefresh(0),
mSupportedResolutions(NULL),
mNumSupportedResolutions(0),
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 5e06e665f3..151028113a 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -223,7 +223,6 @@ protected:
bool mFullscreen;
S32 mFullscreenWidth;
S32 mFullscreenHeight;
- S32 mFullscreenBits;
S32 mFullscreenRefresh;
LLWindowResolution* mSupportedResolutions;
S32 mNumSupportedResolutions;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index e46e3de4c0..6afbdffc1a 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -76,6 +76,11 @@
#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems
#pragma comment(lib, "dinput8")
+#pragma comment(lib, "UxTheme.lib")
+#pragma comment(lib, "Dwmapi.lib")
+#include
+#include // needed for DwmSetWindowAttribute to set window theme
+
const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
@@ -85,6 +90,10 @@ const F32 ICON_FLASH_TIME = 0.5f;
#define USER_DEFAULT_SCREEN_DPI 96 // Win7
#endif
+#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
+#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
+#endif
+
// Claim a couple unused GetMessage() message IDs
const UINT WM_DUMMY_(WM_USER + 0x0017);
const UINT WM_POST_FUNCTION_(WM_USER + 0x0018);
@@ -104,6 +113,7 @@ static std::thread::id sMainThreadId;
LPWSTR gIconResource = IDI_APPLICATION;
+LPWSTR gIconSmallResource = IDI_APPLICATION;
LPDIRECTINPUT8 gDirectInput8;
LLW32MsgCallback gAsyncMsgCallback = NULL;
@@ -137,6 +147,17 @@ typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
_Out_ UINT *dpiX,
_Out_ UINT *dpiY);
+typedef enum PREFERRED_APP_MODE
+{
+ DEFAULT,
+ ALLOW_DARK,
+ FORCE_DARK,
+ FORCE_LIGHT,
+ MAX
+} PREFERRED_APP_MODE;
+
+typedef PREFERRED_APP_MODE(WINAPI* fnSetPreferredAppMode)(PREFERRED_APP_MODE mode);
+
//
// LLWindowWin32
//
@@ -350,10 +371,14 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
LLWindowWin32Thread();
void run() override;
- void close() override;
- // closes queue, wakes thread, waits until thread closes
- void wakeAndDestroy();
+ // Detroys handles and window
+ // Either post to or call from window thread
+ void destroyWindow();
+
+ // Closes queue, wakes thread, waits until thread closes.
+ // Call from main thread
+ bool wakeAndDestroy();
void glReady()
{
@@ -410,6 +435,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
bool mGLReady = false;
bool mGotGLBuffer = false;
+ LLAtomicBool mDeleteOnExit = false;
};
@@ -507,6 +533,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFSAASamples = fsaa_samples;
mIconResource = gIconResource;
+ mIconSmallResource = gIconSmallResource;
mOverrideAspectRatio = 0.f;
mNativeAspectRatio = 0.f;
mInputProcessingPaused = false;
@@ -695,8 +722,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
}
if (dev_mode.dmPelsWidth == width &&
- dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
+ dev_mode.dmPelsHeight == height)
{
success = true;
if ((dev_mode.dmDisplayFrequency - current_refresh)
@@ -736,7 +762,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// If we found a good resolution, use it.
if (success)
{
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ success = setDisplayResolution(width, height, closest_refresh);
}
// Keep a copy of the actual current device mode in case we minimize
@@ -749,7 +775,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
mFullscreenRefresh = dev_mode.dmDisplayFrequency;
LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
@@ -763,7 +788,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
- mFullscreenBits = -1;
mFullscreenRefresh = -1;
std::map args;
@@ -842,6 +866,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// Initialize (boot strap) the Language text input management,
// based on the system's (or user's) default settings.
allowLanguageTextInput(NULL, false);
+ updateWindowTheme();
+ setCustomIcon();
}
@@ -853,6 +879,7 @@ LLWindowWin32::~LLWindowWin32()
}
delete mDragDrop;
+ mDragDrop = NULL;
delete [] mWindowTitle;
mWindowTitle = NULL;
@@ -864,6 +891,7 @@ LLWindowWin32::~LLWindowWin32()
mWindowClassName = NULL;
delete mWindowThread;
+ mWindowThread = NULL;
}
void LLWindowWin32::show()
@@ -972,7 +1000,7 @@ void LLWindowWin32::close()
// Restore gamma to the system values.
restoreGamma();
- LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
+ LL_INFOS("Window") << "Destroying Window Thread" << LL_ENDL;
if (sWindowHandleForMessageBox == mWindowHandle)
{
@@ -982,7 +1010,11 @@ void LLWindowWin32::close()
mhDC = NULL;
mWindowHandle = NULL;
- mWindowThread->wakeAndDestroy();
+ if (mWindowThread->wakeAndDestroy())
+ {
+ // thread will delete itselfs once done
+ mWindowThread = NULL;
+ }
}
bool LLWindowWin32::isValid()
@@ -1185,7 +1217,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
// If we found a good resolution, use it.
if (success)
{
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ success = setDisplayResolution(width, height, closest_refresh);
}
// Keep a copy of the actual current device mode in case we minimize
@@ -1197,7 +1229,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
mFullscreenRefresh = dev_mode.dmDisplayFrequency;
LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
@@ -1223,7 +1254,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
- mFullscreenBits = -1;
mFullscreenRefresh = -1;
LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
@@ -3015,6 +3045,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
WINDOW_IMP_POST(window_imp->mMouseVanish = true);
}
}
+ // Check if theme-related settings changed
+ else if (l_param && (wcscmp((LPCWSTR)l_param, L"ImmersiveColorSet") == 0))
+ {
+ WINDOW_IMP_POST(window_imp->updateWindowTheme());
+ }
+ }
+ break;
+
+ case WM_DWMCOLORIZATIONCOLORCHANGED:
+ {
+ WINDOW_IMP_POST(window_imp->updateWindowTheme());
}
break;
@@ -3107,10 +3148,14 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
}
}
- else
+ else // (NULL == window_imp)
{
- // (NULL == window_imp)
LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
+ if (u_msg == WM_DESTROY)
+ {
+ PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0
+ return 0;
+ }
}
// pass unhandled messages down to Windows
@@ -3520,7 +3565,7 @@ F32 LLWindowWin32::getPixelAspectRatio()
// Change display resolution. Returns true if successful.
// protected
-bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
+bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 refresh)
{
DEVMODE dev_mode;
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
@@ -3532,7 +3577,6 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
{
if (dev_mode.dmPelsWidth == width &&
dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == bits &&
dev_mode.dmDisplayFrequency == refresh )
{
// ...display mode identical, do nothing
@@ -3544,9 +3588,8 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
dev_mode.dmSize = sizeof(dev_mode);
dev_mode.dmPelsWidth = width;
dev_mode.dmPelsHeight = height;
- dev_mode.dmBitsPerPel = bits;
dev_mode.dmDisplayFrequency = refresh;
- dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
+ dev_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
// CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
@@ -3556,7 +3599,7 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
if (!success)
{
LL_WARNS("Window") << "setDisplayResolution failed, "
- << width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
+ << width << "x" << height << " @ " << refresh << LL_ENDL;
}
return success;
@@ -3567,7 +3610,7 @@ bool LLWindowWin32::setFullscreenResolution()
{
if (mFullscreen)
{
- return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
+ return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenRefresh);
}
else
{
@@ -4042,7 +4085,15 @@ void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont)
break;
}
- logfont->lfHeight = mPreeditor->getPreeditFontSize();
+ if (mPreeditor)
+ {
+ logfont->lfHeight = mPreeditor->getPreeditFontSize();
+ }
+ else
+ {
+ // todo: extract from some font * LLUI::getScaleFactor() intead
+ logfont->lfHeight = 10;
+ }
logfont->lfWeight = FW_NORMAL;
}
@@ -4573,25 +4624,11 @@ std::vector LLWindowWin32::getDynamicFallbackFontList()
#endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
- : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, true /*should be false, temporary workaround for SL-18721*/)
+ : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
{
LL::ThreadPool::start();
}
-void LLWindowWin32::LLWindowWin32Thread::close()
-{
- if (!mQueue->isClosed())
- {
- LL_WARNS() << "Closing window thread without using destroy_window_handler" << LL_ENDL;
- LL::ThreadPool::close();
-
- // Workaround for SL-18721 in case window closes too early and abruptly
- LLSplashScreen::show();
- LLSplashScreen::update("..."); // will be updated later
- }
-}
-
-
/**
* LogChange is to log changes in status while trying to avoid spamming the
* log with repeated messages, especially in a tight loop. It refuses to log
@@ -4815,108 +4852,110 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
#endif
}
+
+ destroyWindow();
+
+ if (mDeleteOnExit)
+ {
+ delete this;
+ }
}
-void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
+void LLWindowWin32::LLWindowWin32Thread::destroyWindow()
+{
+ if (mWindowHandleThrd != NULL && IsWindow(mWindowHandleThrd))
+ {
+ if (mhDCThrd)
+ {
+ if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
+ {
+ LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
+ }
+ mhDCThrd = NULL;
+ }
+
+ // This causes WM_DESTROY to be sent *immediately*
+ if (!destroy_window_handler(mWindowHandleThrd))
+ {
+ LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
+ }
+ }
+ else
+ {
+ // Something killed the window while we were busy destroying gl or handle somehow got broken
+ LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
+ }
+ mWindowHandleThrd = NULL;
+ mhDCThrd = NULL;
+}
+
+bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
{
if (mQueue->isClosed())
{
- LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
- return;
+ LL_WARNS("Window") << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
+ return false;
}
- // Make sure we don't leave a blank toolbar button.
- // Also hiding window now prevents user from suspending it
- // via some action (like dragging it around)
- ShowWindow(mWindowHandleThrd, SW_HIDE);
+ // Hide the window immediately to prevent user interaction during shutdown
+ if (mWindowHandleThrd)
+ {
+ ShowWindow(mWindowHandleThrd, SW_HIDE);
+ }
+ else
+ {
+ LL_WARNS("Window") << "Tried to hide window, but Win32 window handle is NULL." << LL_ENDL;
+ return false;
+ }
- // Schedule destruction
+ mGLReady = false;
+
+ // Capture current handle before we lose it
HWND old_handle = mWindowHandleThrd;
- post([this]()
- {
- if (IsWindow(mWindowHandleThrd))
- {
- if (mhDCThrd)
- {
- if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
- {
- LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
- }
- mhDCThrd = NULL;
- }
- // This causes WM_DESTROY to be sent *immediately*
- if (!destroy_window_handler(mWindowHandleThrd))
- {
- LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
- }
- }
- else
- {
- // Something killed the window while we were busy destroying gl or handle somehow got broken
- LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
- }
- mWindowHandleThrd = NULL;
- mhDCThrd = NULL;
- mGLReady = false;
- });
+ // Clear the user data to prevent callbacks from finding us
+ if (old_handle)
+ {
+ SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL);
+ }
+ // Signal thread to clean up when done
+ mDeleteOnExit = true;
+
+ // Close the queue first
LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
mQueue->close();
- // Post a nonsense user message to wake up the thread in
- // case it is waiting for a getMessage()
+ // Wake up the thread if it's stuck in GetMessage()
if (old_handle)
{
WPARAM wparam{ 0xB0B0 };
LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle
<< ", " << WM_DUMMY_
<< ", " << wparam << ")" << std::dec << LL_ENDL;
+
+ // Use PostMessage to signal thread to wake up
PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
}
- // There are cases where window will refuse to close,
- // can't wait forever on join, check state instead
- LLTimer timeout;
- timeout.setTimerExpirySec(2.0);
- while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd)
+ // Cleanly detach threads instead of joining them to avoid blocking the main thread
+ // This is acceptable since the thread will self-delete with mDeleteOnExit
+ for (auto& pair : mThreads)
{
- ms_sleep(100);
+ try {
+ // Only detach if the thread is joinable
+ if (pair.second.joinable())
+ {
+ pair.second.detach();
+ }
+ }
+ catch (const std::system_error& e) {
+ LL_WARNS("Window") << "Exception detaching thread: " << e.what() << LL_ENDL;
+ }
}
- if (getQueue().done() || mWindowHandleThrd == NULL)
- {
- // Window is closed, started closing or is cleaning up
- // now wait for our single thread to die.
- if (mWindowHandleThrd)
- {
- LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
- }
- for (auto& pair : mThreads)
- {
- pair.second.join();
- }
- }
- else
- {
- // Something suspended window thread, can't afford to wait forever
- // so kill thread instead
- // Ex: This can happen if user starts dragging window arround (if it
- // was visible) or a modal notification pops up
- LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL;
-
- for (auto& pair : mThreads)
- {
- // very unsafe
- TerminateThread(pair.second.native_handle(), 0);
- pair.second.detach();
- }
- }
LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
+ return true;
}
void LLWindowWin32::post(const std::function& func)
@@ -4963,3 +5002,69 @@ void LLWindowWin32::updateWindowRect()
});
}
}
+
+bool LLWindowWin32::isSystemAppDarkMode()
+{
+ HKEY hKey;
+ DWORD dwValue = 1; // Default to light theme
+ DWORD dwSize = sizeof(DWORD);
+
+ // Check registry for system theme preference
+ LSTATUS ret_code =
+ RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey);
+ if (ERROR_SUCCESS == ret_code)
+ {
+ if (RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS)
+ {
+ // If AppsUseLightTheme is not found, check SystemUsesLightTheme
+ dwSize = sizeof(DWORD);
+ RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize);
+ }
+ RegCloseKey(hKey);
+ }
+
+ // Return true if dark mode
+ return dwValue == 0;
+}
+
+void LLWindowWin32::updateWindowTheme()
+{
+ bool use_dark_mode = isSystemAppDarkMode();
+ if (use_dark_mode == mCurrentDarkMode)
+ {
+ return;
+ }
+ mCurrentDarkMode = use_dark_mode;
+
+ HMODULE hUxTheme = LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (hUxTheme)
+ {
+ auto SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxTheme, "SetPreferredAppMode");
+ if (SetPreferredAppMode)
+ {
+ SetPreferredAppMode(use_dark_mode ? ALLOW_DARK : FORCE_LIGHT);
+ }
+ FreeLibrary(hUxTheme);
+ }
+ BOOL dark_mode(use_dark_mode);
+ DwmSetWindowAttribute(mWindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark_mode, sizeof(dark_mode));
+
+ LL_INFOS("Window") << "Viewer window theme is set to " << (use_dark_mode ? "dark" : "light") << " mode" << LL_ENDL;
+}
+
+void LLWindowWin32::setCustomIcon()
+{
+ if (mWindowHandle)
+ {
+ HICON hDefaultIcon = LoadIcon(mhInstance, mIconResource);
+ HICON hSmallIcon = LoadIcon(mhInstance, mIconSmallResource);
+ mWindowThread->post([=]()
+ {
+ SendMessage(mWindowHandle, WM_SETICON, ICON_BIG, (LPARAM)hDefaultIcon);
+ SendMessage(mWindowHandle, WM_SETICON, ICON_SMALL, (LPARAM)hSmallIcon);
+
+ SetClassLongPtr(mWindowHandle, GCLP_HICON, (LONG_PTR)hDefaultIcon);
+ SetClassLongPtr(mWindowHandle, GCLP_HICONSM, (LONG_PTR)hSmallIcon);
+ });
+ }
+}
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 36e89e4586..7196706f87 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -150,7 +150,7 @@ protected:
virtual LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
- bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
@@ -214,6 +214,7 @@ protected:
bool mCustomGammaSet;
LPWSTR mIconResource;
+ LPWSTR mIconSmallResource;
bool mInputProcessingPaused;
// The following variables are for Language Text Input control.
@@ -246,6 +247,11 @@ protected:
RECT mRect;
RECT mClientRect;
+ void updateWindowTheme();
+ bool isSystemAppDarkMode();
+ void setCustomIcon();
+ bool mCurrentDarkMode { false };
+
struct LLWindowWin32Thread;
LLWindowWin32Thread* mWindowThread = nullptr;
LLThreadSafeQueue> mFunctionQueue;
@@ -281,6 +287,7 @@ private:
extern LLW32MsgCallback gAsyncMsgCallback;
extern LPWSTR gIconResource;
+extern LPWSTR gIconSmallResource;
S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type);
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index bb590ebd76..562a30e8d1 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -157,6 +157,9 @@ LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
{
if ((persist != PERSIST_NO) && mComment.empty())
{
+ // File isn't actually missing, but something is wrong with it
+ // so the main point is to warn user to reinstall
+ LLError::LLUserWarningMsg::showMissingFiles();
LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL;
}
//Push back versus setValue'ing here, since we don't want to call a signal yet
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 23b0a7723e..117473554e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -15,6 +15,9 @@ include(CMakeCopyIfDifferent)
include(CubemapToEquirectangularJS)
include(DBusGlib)
include(DragDrop)
+if (USE_DISCORD)
+ include(Discord)
+endif ()
include(EXPAT)
include(Hunspell)
include(JPEGEncoderBasic)
@@ -76,6 +79,7 @@ set(viewer_SOURCE_FILES
gltf/accessor.cpp
gltf/primitive.cpp
gltf/animation.cpp
+ gltf/llgltfloader.cpp
groupchatlistener.cpp
llaccountingcostmanager.cpp
llaisapi.cpp
@@ -178,11 +182,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
@@ -201,6 +205,7 @@ set(viewer_SOURCE_FILES
llfloatercamera.cpp
llfloatercamerapresets.cpp
llfloaterchangeitemthumbnail.cpp
+ llfloaterchatmentionpicker.cpp
llfloaterchatvoicevolume.cpp
llfloaterclassified.cpp
llfloatercolorpicker.cpp
@@ -337,6 +342,7 @@ set(viewer_SOURCE_FILES
llhudeffectpointat.cpp
llhudeffecttrail.cpp
llhudeffectblob.cpp
+ llhudeffectresetskeleton.cpp
llhudicon.cpp
llhudmanager.cpp
llhudnametag.cpp
@@ -362,6 +368,7 @@ set(viewer_SOURCE_FILES
llinventorygallerymenu.cpp
llinventoryicon.cpp
llinventoryitemslist.cpp
+ llinventorylistener.cpp
llinventorylistitem.cpp
llinventorymodel.cpp
llinventorymodelbackgroundfetch.cpp
@@ -745,6 +752,7 @@ set(viewer_HEADER_FILES
gltf/buffer_util.h
gltf/primitive.h
gltf/animation.h
+ gltf/llgltfloader.h
llaccountingcost.h
llaccountingcostmanager.h
llaisapi.h
@@ -848,11 +856,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
@@ -870,6 +878,7 @@ set(viewer_HEADER_FILES
llfloaterbuyland.h
llfloatercamerapresets.h
llfloaterchangeitemthumbnail.h
+ llfloaterchatmentionpicker.h
llfloatercamera.h
llfloaterchatvoicevolume.h
llfloaterclassified.h
@@ -1009,6 +1018,7 @@ set(viewer_HEADER_FILES
llhudeffectpointat.h
llhudeffecttrail.h
llhudeffectblob.h
+ llhudeffectresetskeleton.h
llhudicon.h
llhudmanager.h
llhudnametag.h
@@ -1033,6 +1043,7 @@ set(viewer_HEADER_FILES
llinventorygallerymenu.h
llinventoryicon.h
llinventoryitemslist.h
+ llinventorylistener.h
llinventorylistitem.h
llinventorymodel.h
llinventorymodelbackgroundfetch.h
@@ -1564,6 +1575,7 @@ if (WINDOWS)
res-sdl/ll_icon.BMP
res/ll_icon.BMP
res/ll_icon.ico
+ res/ll_icon_small.ico
res/resource.h
res/toolpickobject.cur
res/toolpickobject2.cur
@@ -1656,7 +1668,7 @@ set(viewer_APPSETTINGS_FILES
app_settings/toolbars.xml
app_settings/trees.xml
app_settings/viewerart.xml
- ${CMAKE_SOURCE_DIR}/../etc/message.xml
+ app_settings/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
packages-info.txt
featuretable.txt
@@ -1750,7 +1762,7 @@ if (WINDOWS)
set(COPY_INPUT_DEPENDENCIES
# The following commented dependencies are determined variably at build time. Can't do this here.
- ${CMAKE_SOURCE_DIR}/../etc/message.xml
+ app_settings/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
${SHARED_LIB_STAGING_DIR}/openjp2.dll
${SHARED_LIB_STAGING_DIR}/llwebrtc.dll
@@ -1779,6 +1791,12 @@ if (WINDOWS)
)
endif (ADDRESS_SIZE EQUAL 64)
+ if (TARGET ll::discord_sdk)
+ list(APPEND COPY_INPUT_DEPENDENCIES
+ ${SHARED_LIB_STAGING_DIR}/discord_partner_sdk.dll
+ )
+ endif ()
+
if (TARGET ll::openal)
list(APPEND COPY_INPUT_DEPENDENCIES
${SHARED_LIB_STAGING_DIR}/OpenAL32.dll
@@ -1795,6 +1813,7 @@ if (WINDOWS)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -1833,6 +1852,7 @@ if (WINDOWS)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -1897,6 +1917,7 @@ if (WINDOWS)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -1993,6 +2014,10 @@ target_link_libraries(${VIEWER_BINARY_NAME}
ll::openxr
)
+if (USE_DISCORD)
+ target_link_libraries(${VIEWER_BINARY_NAME} ll::discord_sdk )
+endif ()
+
if( TARGET ll::intel_memops )
target_link_libraries(${VIEWER_BINARY_NAME} ll::intel_memops )
endif()
@@ -2049,6 +2074,7 @@ if (LINUX)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -2077,6 +2103,7 @@ if (LINUX)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -2151,6 +2178,7 @@ if (DARWIN)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
@@ -2183,6 +2211,7 @@ if (DARWIN)
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
+ "--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 991d8e5c5f..b26a34e470 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-7.1.13
+7.2.1
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 4a3dfffde1..7bcfecf9fa 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -26,9 +26,9 @@
label_ref="Command_Avatar_Label"
tooltip_ref="Command_Avatar_Tooltip"
execute_function="Floater.ToggleOrBringToFront"
- execute_parameters="avatar"
+ execute_parameters="avatar_welcome_pack"
is_running_function="Floater.IsOpen"
- is_running_parameters="avatar"
+ is_running_parameters="avatar_welcome_pack"
/>
- ImporterDebug
+ ImporterDebugVerboseLogging
Comment
Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines.
@@ -27,7 +27,7 @@
ImporterModelLimit
Comment
- Limits amount of importer generated models for dae files
+ Limits amount of importer generated (when over 8 faces) models for dae and gltf files
Persist
1
Type
@@ -35,6 +35,17 @@
Value
768
+ ImporterDebugMode
+
+ Comment
+ At 0 does nothing, at 1 dumps skinning data near orifinal file, at 2 dumps skining data and positions/weights of first 5 models, at 3 dumps skinning data and models as llsd
+ Persist
+ 1
+ Type
+ U32
+ Value
+ 0
+
ImporterPreprocessDAE
Comment
@@ -91,7 +102,7 @@
Type
S32
Value
- 300.0
+ 300
AckCollectTime
@@ -621,16 +632,16 @@
Value
16.0
- AvatarPickerURL
+ AvatarWelcomePack
- Comment
- Avatar picker contents
- Persist
- 1
- Type
- String
- Value
- http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/avatars.html
+ Comment
+ Avatar Welcome Pack contents
+ Persist
+ 1
+ Type
+ String
+ Value
+ http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/vawp/index.html
AvatarBakedTextureUploadTimeout
@@ -1139,6 +1150,39 @@
Value
1
+ EnableDiscord
+
+ Comment
+ When set, connect to Discord to enable Rich Presence
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 1
+
+ ShowDiscordActivityDetails
+
+ Comment
+ When set, show avatar name on Discord Rich Presence
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 0
+
+ ShowDiscordActivityState
+
+ Comment
+ When set, show location on Discord Rich Presence
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 0
+
EnableDiskCacheDebugInfo
Comment
@@ -1153,13 +1197,13 @@
DiskCachePercentOfTotal
Comment
- The percent of total cache size (defined by CacheSize) to use for the disk cache
+ The percent of total cache size (defined by CacheSize) to use for the disk cache (ex: asset storage, excludes textures)
Persist
1
Type
F32
Value
- 40.0
+ 35.0
DiskCacheDirName
@@ -1203,7 +1247,7 @@
Type
U32
Value
- 4096
+ 6144
CacheValidateCounter
@@ -1864,6 +1908,17 @@
Value
0
+ DebugSelectionLODs
+
+ Comment
+ Force selection to show specific LOD, -1 for off, 0 - lowest, 4 - high.
+ Persist
+ 0
+ Type
+ S32
+ Value
+ -1
+
AnimatedObjectsAllowLeftClick
Comment
@@ -6361,6 +6416,17 @@
Value
0
+ PlaySoundChatMention
+
+ Comment
+ Plays a sound when got mentioned in a chat
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 0
+
PluginAttachDebuggerToPlugins
Comment
@@ -7830,7 +7896,7 @@
RenderMinFreeMainMemoryThreshold