mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-09 14:33:41 +02:00
Merge remote-tracking branch 'overte/master' into application
This commit is contained in:
commit
22bd86f122
100 changed files with 1225 additions and 1250 deletions
16
.github/workflows/linux_server_build.yml
vendored
16
.github/workflows/linux_server_build.yml
vendored
|
@ -82,16 +82,6 @@ jobs:
|
|||
arch: aarch64
|
||||
runner: [self_hosted, type-cax41, image-arm-app-docker-ce]
|
||||
|
||||
- os: fedora-39
|
||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-39-amd64
|
||||
arch: amd64
|
||||
runner: [self_hosted, type-cx52, image-x86-app-docker-ce]
|
||||
|
||||
- os: fedora-39
|
||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-39-aarch64
|
||||
arch: aarch64
|
||||
runner: [self_hosted, type-cax41, image-arm-app-docker-ce]
|
||||
|
||||
- os: fedora-40
|
||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-40-amd64
|
||||
arch: amd64
|
||||
|
@ -224,10 +214,6 @@ jobs:
|
|||
else # RPM
|
||||
if [ "${{ matrix.os }}" == "rockylinux-9" ]; then
|
||||
echo "ARTIFACT_PATTERN=overte-server-$RPMVERSION-1.el9.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.os }}" == "fedora-38" ]; then
|
||||
echo "ARTIFACT_PATTERN=overte-server-$RPMVERSION-1.fc38.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.os }}" == "fedora-39" ]; then
|
||||
echo "ARTIFACT_PATTERN=overte-server-$RPMVERSION-1.fc39.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.os }}" == "fedora-40" ]; then
|
||||
echo "ARTIFACT_PATTERN=overte-server-$RPMVERSION-1.fc40.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
else
|
||||
|
@ -266,7 +252,7 @@ jobs:
|
|||
|
||||
- name: Archive cmake logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cmake-logs-${{ matrix.os }}-${{ matrix.arch }}-${{ github.event.number }}.tar.xz
|
||||
path: cmake-logs-${{ matrix.os }}-${{ matrix.arch }}-${{ github.event.number }}.tar.xz
|
||||
|
|
6
.github/workflows/master_build.yml
vendored
6
.github/workflows/master_build.yml
vendored
|
@ -65,7 +65,7 @@ jobs:
|
|||
run: |
|
||||
|
||||
echo "UPLOAD_PREFIX=build/overte/master" >> $GITHUB_ENV
|
||||
echo ::set-output name=github_sha_short::`echo $GIT_COMMIT | cut -c1-7`
|
||||
echo "{github_sha_short}={`echo $GIT_COMMIT | cut -c1-7`}" >> $GITHUB_OUTPUT
|
||||
echo "JOB_NAME=build (${{matrix.os}}, ${{matrix.build_type}})" >> $GITHUB_ENV
|
||||
echo "APP_TARGET_NAME=$APP_NAME" >> $GITHUB_ENV
|
||||
# Linux build variables
|
||||
|
@ -82,7 +82,7 @@ jobs:
|
|||
echo "ZIP_ARGS=-r" >> $GITHUB_ENV
|
||||
echo "INSTALLER_EXT=dmg" >> $GITHUB_ENV
|
||||
echo "CMAKE_EXTRA=-DOVERTE_CPU_ARCHITECTURE= -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DOPENSSL_LIBRARIES=/usr/local/opt/openssl/lib -G Xcode" >> $GITHUB_ENV
|
||||
echo "::set-output name=symbols_archive::${BUILD_NUMBER}-${{ matrix.build_type }}-mac-symbols.zip"
|
||||
echo "symbols_archive=${BUILD_NUMBER}-${{ matrix.build_type }}-mac-symbols.zip" >> $GITHUB_ENV
|
||||
echo "APP_TARGET_NAME=Overte" >> $GITHUB_ENV
|
||||
fi
|
||||
# Windows build variables
|
||||
|
@ -91,7 +91,7 @@ jobs:
|
|||
echo "ZIP_COMMAND=7z" >> $GITHUB_ENV
|
||||
echo "ZIP_ARGS=a" >> $GITHUB_ENV
|
||||
echo "INSTALLER_EXT=exe" >> $GITHUB_ENV
|
||||
echo "CMAKE_EXTRA=-A x64" >> $GITHUB_ENV
|
||||
echo "CMAKE_EXTRA=-A x64 -DJSDOC_ENABLED:BOOL=TRUE" >> $GITHUB_ENV
|
||||
echo "SYMBOL_REGEX=\(exe\|dll\|pdb\)" >> $GITHUB_ENV
|
||||
echo "symbols_archive=${BUILD_NUMBER}-${{ matrix.build_type }}-win-symbols.zip" >> $GITHUB_ENV
|
||||
# echo "HF_PFX_PASSPHRASE=${{secrets.pfx_key}}" >> $GITHUB_ENV
|
||||
|
|
2
.github/workflows/master_deploy_apidocs.yml
vendored
2
.github/workflows/master_deploy_apidocs.yml
vendored
|
@ -31,7 +31,7 @@ jobs:
|
|||
jsdoc root.js -r api-mainpage.md -c config.json -d output
|
||||
|
||||
- name: Deploy API-docs
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
|
||||
with:
|
||||
server: www531.your-server.de
|
||||
protocol: ftps
|
||||
|
|
2
.github/workflows/master_deploy_doxygen.yml
vendored
2
.github/workflows/master_deploy_doxygen.yml
vendored
|
@ -29,7 +29,7 @@ jobs:
|
|||
doxygen Doxyfile
|
||||
|
||||
- name: Deploy Doxygen
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
|
||||
with:
|
||||
server: www531.your-server.de
|
||||
protocol: ftps
|
||||
|
|
12
.github/workflows/pr_build.yml
vendored
12
.github/workflows/pr_build.yml
vendored
|
@ -64,8 +64,8 @@ jobs:
|
|||
runner: [self_hosted, type-cx52, image-x86-app-docker-ce]
|
||||
arch: amd64
|
||||
build_type: full
|
||||
apt-dependencies: pkg-config libxext-dev libdouble-conversion-dev libpcre2-16-0 libpulse0 libharfbuzz-dev libnss3 libnspr4 libxdamage1 libasound2 # add missing dependencies to docker image when convenient
|
||||
image: docker.io/overte/overte-full-build:0.1.1-ubuntu-20.04-amd64
|
||||
# apt-dependencies: # add missing dependencies to docker image when convenient
|
||||
image: docker.io/overte/overte-full-build:0.1.2-ubuntu-20.04-amd64
|
||||
# Android builds are currently failing
|
||||
#- os: ubuntu-18.04
|
||||
# build_type: android
|
||||
|
@ -75,7 +75,7 @@ jobs:
|
|||
runner: [self_hosted, type-cax41, image-arm-app-docker-ce]
|
||||
arch: aarch64
|
||||
build_type: full
|
||||
image: docker.io/overte/overte-full-build:0.1.1-ubuntu-22.04-aarch64
|
||||
image: docker.io/overte/overte-full-build:0.1.2-ubuntu-22.04-aarch64
|
||||
fail-fast: false
|
||||
runs-on: ${{matrix.runner}}
|
||||
container: ${{matrix.image}}
|
||||
|
@ -137,9 +137,9 @@ jobs:
|
|||
echo "PYTHON_EXEC=python" >> $GITHUB_ENV
|
||||
echo "INSTALLER_EXT=exe" >> $GITHUB_ENV
|
||||
if [ "${{ matrix.build_type }}" = "full" ]; then
|
||||
echo "CMAKE_EXTRA=-A x64" >> $GITHUB_ENV
|
||||
echo "CMAKE_EXTRA=-A x64 -DJSDOC_ENABLED:BOOL=TRUE" >> $GITHUB_ENV
|
||||
else
|
||||
echo "CMAKE_EXTRA=-A x64 -DCLIENT_ONLY=1" >> $GITHUB_ENV
|
||||
echo "CMAKE_EXTRA=-A x64 -DJSDOC_ENABLED:BOOL=TRUE -DCLIENT_ONLY=1" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
# Android + Quest build variables
|
||||
|
@ -244,7 +244,7 @@ jobs:
|
|||
|
||||
- name: Archive cmake logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cmake-logs-${{ matrix.os }}-${{ github.event.number }}.tar.xz
|
||||
path: ./cmake-logs-${{ matrix.os }}-${{ github.event.number }}.tar.xz
|
||||
|
|
3
.github/workflows/release_build.yml
vendored
3
.github/workflows/release_build.yml
vendored
|
@ -56,7 +56,6 @@ jobs:
|
|||
echo "UPLOAD_PREFIX=build/overte/release/" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo ::set-output name=github_sha_short::`echo $GIT_COMMIT | cut -c1-7`
|
||||
echo "JOB_NAME=${{matrix.os}}, ${{matrix.build_type}}" >> $GITHUB_ENV
|
||||
echo "APP_TARGET_NAME=$APP_NAME" >> $GITHUB_ENV
|
||||
|
||||
|
@ -101,7 +100,7 @@ jobs:
|
|||
- name: Configure CMake
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release -DCLIENT_ONLY:BOOLEAN=$CLIENT_ONLY -DBYPASS_SIGNING:BOOLEAN=TRUE $CMAKE_EXTRA
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release -DJSDOC_ENABLED:BOOL=TRUE -DCLIENT_ONLY:BOOLEAN=$CLIENT_ONLY -DBYPASS_SIGNING:BOOLEAN=TRUE $CMAKE_EXTRA
|
||||
|
||||
- name: Build application
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -51,6 +51,7 @@ local.properties
|
|||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.cache
|
||||
# Workspace
|
||||
*.code-workspace
|
||||
|
||||
|
|
84
CHANGELOG.md
84
CHANGELOG.md
|
@ -12,9 +12,84 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
This project does **not** adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
<!-- ## [2024.09.1] Unreleased -->
|
||||
## [2024.11.1] 2024.11.23
|
||||
|
||||
## [2024.07.1] 2023.07.12
|
||||
### Fixes
|
||||
- Hard code link colors in Armored Chat (PR1083)
|
||||
- ArmoredChat: Alleviate scrolling issue (PR1106)
|
||||
- Armored Chat: Change the 'open in new window' character (PR1084)
|
||||
- Fix mouselook ignoring setting. (PR1081)
|
||||
- Fix controllerScripts uncaught exception. (PR1086)
|
||||
- Fix wireshark dissector (PR1088)
|
||||
- Create App: Material Assistant: Add Mtoon, Shader_simple, missing PBR properties and bug fixes. (PR1091)
|
||||
- Fix login failure handling and improve logging. (PR1093)
|
||||
- add a setting to workaround the GLES colorspace conversion issue (PR1105)
|
||||
- Improve model load priority (PR1085)
|
||||
- fix accidentally clearing url fields when you don't have view permission (PR1138)
|
||||
- Avatar App: Fixed lingering references to now deleted QML element (PR1155)
|
||||
- Fix selfie mode movement (PR1127)
|
||||
- Fix Create App not honoring menu bar actions (PR1123)
|
||||
- Fix Uuid.NULL behavior (PR1168)
|
||||
- Rebuild fonts with full charset (NOT -allglyphs) (PR1172)
|
||||
- fix web entities not accepting keyboard focus (PR1187)
|
||||
- Fix stutter when an object is fading (PR1185)
|
||||
- fix density max typo (PR1195)
|
||||
- Fix ArmoredChat quick_message qml dialog colors on light theme systems (PR1196)
|
||||
- Fix missing properties in Script API (PR1215)
|
||||
- Fix ArmoredChat scrolling (PR1210)
|
||||
- Force enable JSDoc to get scripting console autocomplete working on Windows (PR1219)
|
||||
- Fix lack of entityHostType property (PR1224)
|
||||
- Fix access-after-delete on leaving domain with entity scripts (PR1230)
|
||||
- fix fade out not working in forward rendering (PR1234)
|
||||
- Fix access-after-delete during entity script engine cleanup (PR1236)
|
||||
- Fix script-related crashes on exiting a domain (PR1251)
|
||||
- Update privacy policy link (PR1237)
|
||||
|
||||
### Changes
|
||||
- Replace Floofchat with ArmoredChat (PR961)
|
||||
- MouseLook.js refactor (PR1004)
|
||||
- Custom shader fallbacks (PR1058)
|
||||
- Update outdated language (PR1102)
|
||||
- Automated entity property serialization (PR1098)
|
||||
- Create app: highlight avatar entities (PR1152)
|
||||
- Update Avatar App icons (PR1141)
|
||||
- Place App: Weekly promoted place (PR1153)
|
||||
- Change minimum angular velocity to a lower one (PR1171)
|
||||
- Places App: Persisted Maturity Filter and Default value for Newbies. (PR1164)
|
||||
|
||||
### Additions
|
||||
- Mirrors + Portals (PR721)
|
||||
- Entity tags (PR748)
|
||||
- Web Entity wantsKeyboardFocus (PR814)
|
||||
- Audio Zone Properties (PR847)
|
||||
- Ability to smooth model animations (PR889)
|
||||
- GPU Particles (PR884)
|
||||
- Unlit Shapes (PR1041)
|
||||
- Ambient Light Color (PR1043)
|
||||
- Dump protocol data (PR1087)
|
||||
- Sound Entities (PR894)
|
||||
- Zone properties for tonemapping and ambient occlusion (PR1050)
|
||||
- Add bloom, haze, AO, and procedural shaders to Graphics settings (PR1053)
|
||||
- Create App: Revolutionary "Paste" Url buttons for the "Create Model", "Create Material" and "Create Voxels" UI (PR1094)
|
||||
- Text verticalAlignment, send entity property enums as uint8_t, fix text recalculating too often, fix textSize (PR1111)
|
||||
- Create app: Grab and Equip (PR1160)
|
||||
- Create App: Add "Paste" button for NewSoundDialog QML (PR1202)
|
||||
- Added sounds to all incoming chat messages (PR1250)
|
||||
|
||||
### Removals
|
||||
- Remove (deprecated) attachments (PR1069)
|
||||
- Remove unused onFirstRun.js (PR1089)
|
||||
- Remove Google Poly (PR1137)
|
||||
- Remove hifi screenshare (PR1165)
|
||||
|
||||
### Build System
|
||||
- Add CLion-style build directories to .gitignore (PR1135)
|
||||
|
||||
### Security
|
||||
- Sanitize notificationCore text to prevent XSS (PR1078)
|
||||
|
||||
|
||||
## [2024.07.1] 2024.07.12
|
||||
|
||||
### Fixes
|
||||
- Fix more warnings (PR1007)
|
||||
|
@ -57,7 +132,7 @@ This project does **not** adhere to [Semantic Versioning](https://semver.org/spe
|
|||
- Remove remnants of RELEASE_NAME. (PR1077)
|
||||
|
||||
|
||||
## [2024.06.1] 2023.06.24
|
||||
## [2024.06.1] 2024.06.24
|
||||
|
||||
### Fixes
|
||||
- Fix QNetworkRequest::FollowRedirectsAttribute deprecated warning (PR711)
|
||||
|
@ -306,9 +381,6 @@ This project does **not** adhere to [Semantic Versioning](https://semver.org/spe
|
|||
- Added a setting to disable snapshot notifications (PR189)
|
||||
- Added a setting to switch between screenshot formats (PR134)
|
||||
|
||||
### Removals
|
||||
-
|
||||
|
||||
### Build system
|
||||
- Fixed "may be used uninitialized" warning for blendtime (PR269)
|
||||
- Updated SPIRV-Cross to sdk-1.3.231.1 (PR271)
|
||||
|
|
|
@ -567,6 +567,7 @@ void EntityScriptServer::addingEntity(const EntityItemID& entityID) {
|
|||
|
||||
void EntityScriptServer::deletingEntity(const EntityItemID& entityID) {
|
||||
if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptManager) {
|
||||
// TODO: Check if this is running on script engine thread, otherwise lambda capturing script engine pointer is needed
|
||||
_entitiesScriptManager->unloadEntityScript(entityID, true);
|
||||
}
|
||||
}
|
||||
|
@ -584,6 +585,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, bool
|
|||
EntityScriptDetails details;
|
||||
bool isRunning = _entitiesScriptManager->getEntityScriptDetails(entityID, details);
|
||||
if (entity && (forceRedownload || !isRunning || details.scriptText != entity->getServerScripts())) {
|
||||
// TODO: Check if this is running on script engine thread, otherwise lambda capturing script engine pointer is needed
|
||||
if (isRunning) {
|
||||
_entitiesScriptManager->unloadEntityScript(entityID, true);
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ endif()
|
|||
u_major = int( distro.major_version() or '0' )
|
||||
if distro.id() == 'ubuntu' or distro.id() == 'linuxmint':
|
||||
if (distro.id() == 'ubuntu' and u_major == 20) or distro.id() == 'linuxmint' and u_major == 20:
|
||||
self.qtUrl = self.assets_url + '/dependencies/qt5/qt5-install-5.15.14-2024.06.17-kde_570f5b2105df1ea052bec0d6dbf8a00137274371-ubuntu-20.04-amd64.tar.xz'
|
||||
self.qtUrl = self.assets_url + '/dependencies/qt5/qt5-install-5.15.16-2024.12.14-kde_32be154325bfba3ad2ba8bf75dad702f3588e8d3-ubuntu-20.04-amd64.tar.xz'
|
||||
elif (distro.id() == 'ubuntu' and u_major > 20) or (distro.id() == 'linuxmint' and u_major > 20):
|
||||
self.__no_qt_package_error()
|
||||
else:
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by Stephen Birarda on 7 Dec 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -395,7 +396,7 @@ Item {
|
|||
text: signUpBody.termsContainerText
|
||||
Component.onCompleted: {
|
||||
// with the link.
|
||||
termsText.text = qsTr("By signing up, you agree to <a href='https://overte.org/legal/privacy/'>Overte Terms of Service</a>")
|
||||
termsText.text = qsTr("By signing up, you agree to <a href='https://overte.org/privacy_policy.html'>Overte Terms of Service</a>")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1039,6 +1039,14 @@ Rectangle {
|
|||
anchors.top: pal.top;
|
||||
anchors.topMargin: 10;
|
||||
anchors.left: pal.left;
|
||||
RalewayRegular {
|
||||
text: " Display Name";
|
||||
size: hifi.fontSizes.tabularData;
|
||||
anchors.left: parent.left;
|
||||
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
}
|
||||
// This NameCard refers to the current user's NameCard (the one above the nearbyTable)
|
||||
NameCard {
|
||||
id: myCard;
|
||||
|
@ -1054,7 +1062,7 @@ Rectangle {
|
|||
width: myCardWidth;
|
||||
height: parent.height;
|
||||
// Anchors
|
||||
anchors.top: parent.top
|
||||
anchors.top: parent.children[0].bottom;
|
||||
anchors.left: parent.left;
|
||||
}
|
||||
Item {
|
||||
|
@ -1066,7 +1074,7 @@ Rectangle {
|
|||
|
||||
RalewayRegular {
|
||||
id: availabilityText;
|
||||
text: "set availability";
|
||||
text: "Availability";
|
||||
// Text size
|
||||
size: hifi.fontSizes.tabularData;
|
||||
// Anchors
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Created by Dante Ruiz on 6/5/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -928,7 +930,7 @@ Flickable {
|
|||
hoverEnabled: true
|
||||
onEntered: privacyPolicyUnderline.visible = true;
|
||||
onExited: privacyPolicyUnderline.visible = false;
|
||||
onClicked: About.openUrl("https://overte.org/privacy-policy");
|
||||
onClicked: About.openUrl("https://overte.org/privacy_policy.html");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@ const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true;
|
|||
const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false;
|
||||
const bool DEFAULT_PREFER_STYLUS_OVER_LASER = false;
|
||||
const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false;
|
||||
const bool DEFAULT_SHOW_GRAPHICS_ICON = true;
|
||||
const bool DEFAULT_MINI_TABLET_ENABLED = false;
|
||||
const bool DEFAULT_AWAY_STATE_WHEN_FOCUS_LOST_IN_VR_ENABLED = true;
|
||||
|
||||
|
@ -224,6 +225,7 @@ Application::Application(
|
|||
_hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR),
|
||||
_preferStylusOverLaserSetting("preferStylusOverLaser", DEFAULT_PREFER_STYLUS_OVER_LASER),
|
||||
_preferAvatarFingerOverStylusSetting("preferAvatarFingerOverStylus", DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS),
|
||||
_showGraphicsIconSetting("showGraphicsIcon", DEFAULT_SHOW_GRAPHICS_ICON),
|
||||
_constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true),
|
||||
_awayStateWhenFocusLostInVREnabled("awayStateWhenFocusLostInVREnabled", DEFAULT_AWAY_STATE_WHEN_FOCUS_LOST_IN_VR_ENABLED),
|
||||
_preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME),
|
||||
|
|
|
@ -189,6 +189,9 @@ public:
|
|||
bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); }
|
||||
void setPreferAvatarFingerOverStylus(bool value) { _preferAvatarFingerOverStylusSetting.set(value); }
|
||||
|
||||
bool getShowGraphicsIcon() { return _showGraphicsIconSetting.get(); }
|
||||
void setShowGraphicsIcon(bool value);
|
||||
|
||||
bool getMiniTabletEnabled() { return _miniTabletEnabledSetting.get(); }
|
||||
void setMiniTabletEnabled(bool enabled);
|
||||
|
||||
|
@ -785,6 +788,7 @@ private:
|
|||
Setting::Handle<bool> _hmdTabletBecomesToolbarSetting;
|
||||
Setting::Handle<bool> _preferStylusOverLaserSetting;
|
||||
Setting::Handle<bool> _preferAvatarFingerOverStylusSetting;
|
||||
Setting::Handle<bool> _showGraphicsIconSetting;
|
||||
Setting::Handle<bool> _constrainToolbarPosition;
|
||||
Setting::Handle<bool> _awayStateWhenFocusLostInVREnabled;
|
||||
Setting::Handle<QString> _preferredCursor;
|
||||
|
|
|
@ -269,6 +269,11 @@ void Application::setHmdTabletBecomesToolbarSetting(bool value) {
|
|||
updateSystemTabletMode();
|
||||
}
|
||||
|
||||
void Application::setShowGraphicsIcon(bool value) {
|
||||
_showGraphicsIconSetting.set(value);
|
||||
DependencyManager::get<MessagesClient>()->sendLocalMessage("Overte-ShowGraphicsIconChanged", "");
|
||||
}
|
||||
|
||||
void Application::setMiniTabletEnabled(bool enabled) {
|
||||
_miniTabletEnabledSetting.set(enabled);
|
||||
emit miniTabletEnabledChanged(enabled);
|
||||
|
|
|
@ -76,6 +76,8 @@
|
|||
#include "WarningsSuppression.h"
|
||||
#include "ScriptPermissions.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f;
|
||||
|
@ -227,6 +229,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
_scaleSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "scale", _targetScale),
|
||||
_yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed),
|
||||
_hmdYawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "hmdYawSpeed", _hmdYawSpeed),
|
||||
_cameraSensitivitySetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "cameraSensitivity", qApp->getCamera().getSensitivity()),
|
||||
_pitchSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "pitchSpeed", _pitchSpeed),
|
||||
_fullAvatarURLSetting(QStringList() << SETTINGS_FULL_PRIVATE_GROUP_NAME << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarURL",
|
||||
AvatarData::defaultFullAvatarModelUrl()),
|
||||
|
@ -1325,6 +1328,7 @@ void MyAvatar::saveData() {
|
|||
_scaleSetting.set(_targetScale);
|
||||
_yawSpeedSetting.set(_yawSpeed);
|
||||
_hmdYawSpeedSetting.set(_hmdYawSpeed);
|
||||
_cameraSensitivitySetting.set(getCameraSensitivity());
|
||||
_pitchSpeedSetting.set(_pitchSpeed);
|
||||
|
||||
// only save the fullAvatarURL if it has not been overwritten on command line
|
||||
|
@ -2085,6 +2089,7 @@ void MyAvatar::loadData() {
|
|||
|
||||
_yawSpeed = _yawSpeedSetting.get(_yawSpeed);
|
||||
_hmdYawSpeed = _hmdYawSpeedSetting.get(_hmdYawSpeed);
|
||||
setCameraSensitivity(_cameraSensitivitySetting.get(getCameraSensitivity()));
|
||||
_pitchSpeed = _pitchSpeedSetting.get(_pitchSpeed);
|
||||
|
||||
_prefOverrideAnimGraphUrl.set(_animGraphURLSetting.get().toString());
|
||||
|
@ -7003,3 +7008,11 @@ void MyAvatar::resetPointAt() {
|
|||
POINT_BLEND_LINEAR_ALPHA_NAME, POINT_ALPHA_BLENDING);
|
||||
}
|
||||
}
|
||||
|
||||
float MyAvatar::getCameraSensitivity() const {
|
||||
return qApp->getCamera().getSensitivity();
|
||||
}
|
||||
|
||||
void MyAvatar::setCameraSensitivity(float cameraSensitivity) {
|
||||
qApp->getCamera().setSensitivity(cameraSensitivity);
|
||||
}
|
||||
|
|
|
@ -1407,6 +1407,9 @@ public:
|
|||
float getHMDYawSpeed() const { return _hmdYawSpeed; }
|
||||
void setHMDYawSpeed(float speed) { _hmdYawSpeed = speed; }
|
||||
|
||||
float getCameraSensitivity() const;
|
||||
void setCameraSensitivity(float cameraSensitivity);
|
||||
|
||||
static const float ZOOM_MIN;
|
||||
static const float ZOOM_MAX;
|
||||
static const float ZOOM_DEFAULT;
|
||||
|
@ -3007,6 +3010,7 @@ private:
|
|||
Setting::Handle<float> _scaleSetting;
|
||||
Setting::Handle<float> _yawSpeedSetting;
|
||||
Setting::Handle<float> _hmdYawSpeedSetting;
|
||||
Setting::Handle<float> _cameraSensitivitySetting;
|
||||
Setting::Handle<float> _pitchSpeedSetting;
|
||||
Setting::Handle<QUrl> _fullAvatarURLSetting;
|
||||
Setting::Handle<QUrl> _fullAvatarModelNameSetting;
|
||||
|
|
|
@ -225,6 +225,12 @@ void setupPreferences() {
|
|||
preferences->addPreference(delaySlider);
|
||||
}
|
||||
|
||||
{
|
||||
auto getter = []() -> bool { return qApp->getShowGraphicsIcon(); };
|
||||
auto setter = [](bool value) { qApp->setShowGraphicsIcon(value); };
|
||||
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Show Graphics icon on tablet and toolbar", getter, setter));
|
||||
}
|
||||
|
||||
static const QString VIEW_CATEGORY{ "View" };
|
||||
{
|
||||
auto getter = [myAvatar]()->float { return myAvatar->getRealWorldFieldOfView(); };
|
||||
|
|
|
@ -994,9 +994,9 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
|
||||
QString statsFormat = QString("(%1 Kbps, %2 Hz)");
|
||||
if (!renderedDisplayName.isEmpty()) {
|
||||
statsFormat.prepend(" - ");
|
||||
statsFormat.append("\n");
|
||||
}
|
||||
renderedDisplayName += statsFormat.arg(QString::number(kilobitsPerSecond, 'f', 2)).arg(getReceiveRate());
|
||||
renderedDisplayName = statsFormat.arg(QString::number(kilobitsPerSecond, 'f', 2)).arg(getReceiveRate()) + renderedDisplayName;
|
||||
}
|
||||
|
||||
// Compute display name extent/position offset
|
||||
|
@ -1010,18 +1010,18 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
// Compute background position/size
|
||||
static const float SLIGHTLY_IN_FRONT = 0.1f;
|
||||
static const float BORDER_RELATIVE_SIZE = 0.1f;
|
||||
static const float BEVEL_FACTOR = 0.1f;
|
||||
// static const float BEVEL_FACTOR = 0.1f;
|
||||
const int border = BORDER_RELATIVE_SIZE * nameDynamicRect.height();
|
||||
const int left = text_x - border;
|
||||
const int bottom = text_y - border;
|
||||
const int width = nameDynamicRect.width() + 2.0f * border;
|
||||
// FIXME: Beveled box is broken
|
||||
// const int left = text_x - border;
|
||||
// const int bottom = text_y - border;
|
||||
// const int width = nameDynamicRect.width() + 2.0f * border;
|
||||
const int height = nameDynamicRect.height() + 2.0f * border;
|
||||
const int bevelDistance = BEVEL_FACTOR * height;
|
||||
// const int bevelDistance = BEVEL_FACTOR * height;
|
||||
|
||||
// Display name and background colors
|
||||
glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha);
|
||||
glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f,
|
||||
(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
|
||||
glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f,(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
|
||||
|
||||
// Compute display name transform
|
||||
auto textTransform = calculateDisplayNameTransform(view, textPosition);
|
||||
|
@ -1029,12 +1029,11 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
textTransform.postScale(1.0f / height);
|
||||
batch.setModelTransform(textTransform);
|
||||
|
||||
{
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, forward);
|
||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||
bevelDistance, backgroundColor, _nameRectGeometryID);
|
||||
}
|
||||
// {
|
||||
// PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
|
||||
// DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, forward);
|
||||
// DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height, bevelDistance, backgroundColor, _nameRectGeometryID);
|
||||
// }
|
||||
|
||||
// Render actual name
|
||||
QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit();
|
||||
|
@ -1044,7 +1043,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
batch.setModelTransform(textTransform);
|
||||
{
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText");
|
||||
displayNameRenderer->draw(batch, { nameUTF8.data(), textColor, { text_x, -text_y }, glm::vec2(-1.0f), forward });
|
||||
displayNameRenderer->draw(batch, { nameUTF8.data(), textColor, { text_x, -text_y }, glm::vec2(-1.0f), TextAlignment::LEFT, forward });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,8 +220,11 @@ void EntityTreeRenderer::setupEntityScriptEngineSignals(const ScriptManagerPoint
|
|||
void EntityTreeRenderer::resetPersistentEntitiesScriptEngine() {
|
||||
// This runs script engine shutdown procedure in a separate thread, avoiding a deadlock when script engine is doing
|
||||
// a blocking call to main thread
|
||||
if (_persistentEntitiesScriptManager) {
|
||||
QtConcurrent::run([manager = _persistentEntitiesScriptManager] {
|
||||
ScriptManagerPointer scriptManager = _persistentEntitiesScriptManager;
|
||||
// Clear the pointer before lambda is run on another thread.
|
||||
_persistentEntitiesScriptManager.reset();
|
||||
if (scriptManager) {
|
||||
QtConcurrent::run([manager = scriptManager] {
|
||||
manager->unloadAllEntityScripts(true);
|
||||
manager->stop();
|
||||
manager->waitTillDoneRunning();
|
||||
|
@ -251,8 +254,11 @@ void EntityTreeRenderer::resetPersistentEntitiesScriptEngine() {
|
|||
void EntityTreeRenderer::resetNonPersistentEntitiesScriptEngine() {
|
||||
// This runs script engine shutdown procedure in a separate thread, avoiding a deadlock when script engine is doing
|
||||
// a blocking call to main thread
|
||||
if (_nonPersistentEntitiesScriptManager) {
|
||||
QtConcurrent::run([manager = _nonPersistentEntitiesScriptManager] {
|
||||
ScriptManagerPointer scriptManager = _nonPersistentEntitiesScriptManager;
|
||||
// Release the pointer as soon as possible.
|
||||
_nonPersistentEntitiesScriptManager.reset();
|
||||
if (scriptManager) {
|
||||
QtConcurrent::run([manager = scriptManager] {
|
||||
manager->unloadAllEntityScripts(true);
|
||||
manager->stop();
|
||||
manager->waitTillDoneRunning();
|
||||
|
@ -288,7 +294,10 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() {
|
|||
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
||||
if (entityItem && !entityItem->getScript().isEmpty()) {
|
||||
if (!(entityItem->isLocalEntity() || entityItem->isMyAvatarEntity())) {
|
||||
_nonPersistentEntitiesScriptManager->unloadEntityScript(entityID, true);
|
||||
auto scriptEnginePtr = _nonPersistentEntitiesScriptManager;
|
||||
QMetaObject::invokeMethod(scriptEnginePtr.get(), [scriptEnginePtr, entityID]{
|
||||
scriptEnginePtr->unloadEntityScript(entityID, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1110,7 +1119,9 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
|||
if (_currentEntitiesInside.contains(entityID)) {
|
||||
scriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||
}
|
||||
scriptEngine->unloadEntityScript(entityID, true);
|
||||
QMetaObject::invokeMethod(scriptEngine.get(), [scriptEngine, entityID]{
|
||||
scriptEngine->unloadEntityScript(entityID, true);
|
||||
});
|
||||
}
|
||||
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
|
@ -1163,7 +1174,9 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool
|
|||
if (_currentEntitiesInside.contains(entityID)) {
|
||||
scriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||
}
|
||||
scriptEngine->unloadEntityScript(entityID);
|
||||
QMetaObject::invokeMethod(scriptEngine.get(), [scriptEngine, entityID]{
|
||||
scriptEngine->unloadEntityScript(entityID);
|
||||
});
|
||||
}
|
||||
entity->scriptHasUnloaded();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Clement on 4/22/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -39,46 +40,46 @@ ZoneEntityRenderer::ZoneEntityRenderer(const EntityItemPointer& entity)
|
|||
void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
|
||||
if (_stage) {
|
||||
if (!LightStage::isIndexInvalid(_sunIndex)) {
|
||||
_stage->removeLight(_sunIndex);
|
||||
_stage->removeElement(_sunIndex);
|
||||
_sunIndex = INVALID_INDEX;
|
||||
}
|
||||
if (!LightStage::isIndexInvalid(_ambientIndex)) {
|
||||
_stage->removeLight(_ambientIndex);
|
||||
_stage->removeElement(_ambientIndex);
|
||||
_ambientIndex = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
if (_backgroundStage) {
|
||||
if (!BackgroundStage::isIndexInvalid(_backgroundIndex)) {
|
||||
_backgroundStage->removeBackground(_backgroundIndex);
|
||||
_backgroundStage->removeElement(_backgroundIndex);
|
||||
_backgroundIndex = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
if (_hazeStage) {
|
||||
if (!HazeStage::isIndexInvalid(_hazeIndex)) {
|
||||
_hazeStage->removeHaze(_hazeIndex);
|
||||
_hazeStage->removeElement(_hazeIndex);
|
||||
_hazeIndex = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
if (_bloomStage) {
|
||||
if (!BloomStage::isIndexInvalid(_bloomIndex)) {
|
||||
_bloomStage->removeBloom(_bloomIndex);
|
||||
_bloomStage->removeElement(_bloomIndex);
|
||||
_bloomIndex = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
if (_tonemappingStage) {
|
||||
if (!TonemappingStage::isIndexInvalid(_tonemappingIndex)) {
|
||||
_tonemappingStage->removeTonemapping(_tonemappingIndex);
|
||||
_tonemappingStage->removeElement(_tonemappingIndex);
|
||||
_tonemappingIndex = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
if (_ambientOcclusionStage) {
|
||||
if (!AmbientOcclusionStage::isIndexInvalid(_ambientOcclusionIndex)) {
|
||||
_ambientOcclusionStage->removeAmbientOcclusion(_ambientOcclusionIndex);
|
||||
_ambientOcclusionStage->removeElement(_ambientOcclusionIndex);
|
||||
_ambientOcclusionIndex = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
{ // Sun
|
||||
if (_needSunUpdate) {
|
||||
if (LightStage::isIndexInvalid(_sunIndex)) {
|
||||
_sunIndex = _stage->addLight(_sunLight);
|
||||
_sunIndex = _stage->addElement(_sunLight);
|
||||
} else {
|
||||
_stage->updateLightArrayBuffer(_sunIndex);
|
||||
}
|
||||
|
@ -136,7 +137,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
if (_needAmbientUpdate) {
|
||||
if (LightStage::isIndexInvalid(_ambientIndex)) {
|
||||
_ambientIndex = _stage->addLight(_ambientLight);
|
||||
_ambientIndex = _stage->addElement(_ambientLight);
|
||||
} else {
|
||||
_stage->updateLightArrayBuffer(_ambientIndex);
|
||||
}
|
||||
|
@ -149,7 +150,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
if (_needBackgroundUpdate) {
|
||||
if (BackgroundStage::isIndexInvalid(_backgroundIndex)) {
|
||||
_backgroundIndex = _backgroundStage->addBackground(_background);
|
||||
_backgroundIndex = _backgroundStage->addElement(_background);
|
||||
}
|
||||
_needBackgroundUpdate = false;
|
||||
}
|
||||
|
@ -158,7 +159,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
{
|
||||
if (_needHazeUpdate) {
|
||||
if (HazeStage::isIndexInvalid(_hazeIndex)) {
|
||||
_hazeIndex = _hazeStage->addHaze(_haze);
|
||||
_hazeIndex = _hazeStage->addElement(_haze);
|
||||
}
|
||||
_needHazeUpdate = false;
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
{
|
||||
if (_needBloomUpdate) {
|
||||
if (BloomStage::isIndexInvalid(_bloomIndex)) {
|
||||
_bloomIndex = _bloomStage->addBloom(_bloom);
|
||||
_bloomIndex = _bloomStage->addElement(_bloom);
|
||||
}
|
||||
_needBloomUpdate = false;
|
||||
}
|
||||
|
@ -176,7 +177,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
{
|
||||
if (_needTonemappingUpdate) {
|
||||
if (TonemappingStage::isIndexInvalid(_tonemappingIndex)) {
|
||||
_tonemappingIndex = _tonemappingStage->addTonemapping(_tonemapping);
|
||||
_tonemappingIndex = _tonemappingStage->addElement(_tonemapping);
|
||||
}
|
||||
_needTonemappingUpdate = false;
|
||||
}
|
||||
|
@ -185,7 +186,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
{
|
||||
if (_needAmbientOcclusionUpdate) {
|
||||
if (AmbientOcclusionStage::isIndexInvalid(_ambientOcclusionIndex)) {
|
||||
_ambientOcclusionIndex = _ambientOcclusionStage->addAmbientOcclusion(_ambientOcclusion);
|
||||
_ambientOcclusionIndex = _ambientOcclusionStage->addElement(_ambientOcclusion);
|
||||
}
|
||||
_needAmbientOcclusionUpdate = false;
|
||||
}
|
||||
|
@ -205,9 +206,9 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
}
|
||||
|
||||
if (_skyboxMode == COMPONENT_MODE_DISABLED) {
|
||||
_backgroundStage->_currentFrame.pushBackground(INVALID_INDEX);
|
||||
_backgroundStage->_currentFrame.pushElement(INVALID_INDEX);
|
||||
} else if (_skyboxMode == COMPONENT_MODE_ENABLED) {
|
||||
_backgroundStage->_currentFrame.pushBackground(_backgroundIndex);
|
||||
_backgroundStage->_currentFrame.pushElement(_backgroundIndex);
|
||||
}
|
||||
|
||||
if (_ambientLightMode == COMPONENT_MODE_DISABLED) {
|
||||
|
@ -218,25 +219,25 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
// Haze only if the mode is not inherit, as the model deals with on/off
|
||||
if (_hazeMode != COMPONENT_MODE_INHERIT) {
|
||||
_hazeStage->_currentFrame.pushHaze(_hazeIndex);
|
||||
_hazeStage->_currentFrame.pushElement(_hazeIndex);
|
||||
}
|
||||
|
||||
if (_bloomMode == COMPONENT_MODE_DISABLED) {
|
||||
_bloomStage->_currentFrame.pushBloom(INVALID_INDEX);
|
||||
_bloomStage->_currentFrame.pushElement(INVALID_INDEX);
|
||||
} else if (_bloomMode == COMPONENT_MODE_ENABLED) {
|
||||
_bloomStage->_currentFrame.pushBloom(_bloomIndex);
|
||||
_bloomStage->_currentFrame.pushElement(_bloomIndex);
|
||||
}
|
||||
|
||||
if (_tonemappingMode == COMPONENT_MODE_DISABLED) {
|
||||
_tonemappingStage->_currentFrame.pushTonemapping(0); // Use the fallback tonemapping for "off"
|
||||
_tonemappingStage->_currentFrame.pushElement(0); // Use the fallback tonemapping for "off"
|
||||
} else if (_tonemappingMode == COMPONENT_MODE_ENABLED) {
|
||||
_tonemappingStage->_currentFrame.pushTonemapping(_tonemappingIndex);
|
||||
_tonemappingStage->_currentFrame.pushElement(_tonemappingIndex);
|
||||
}
|
||||
|
||||
if (_ambientOcclusionMode == COMPONENT_MODE_DISABLED) {
|
||||
_ambientOcclusionStage->_currentFrame.pushAmbientOcclusion(INVALID_INDEX);
|
||||
_ambientOcclusionStage->_currentFrame.pushElement(INVALID_INDEX);
|
||||
} else if (_ambientOcclusionMode == COMPONENT_MODE_ENABLED) {
|
||||
_ambientOcclusionStage->_currentFrame.pushAmbientOcclusion(_ambientOcclusionIndex);
|
||||
_ambientOcclusionStage->_currentFrame.pushElement(_ambientOcclusionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,11 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
|
||||
@Base_REQUESTED_PROPS@
|
||||
|
||||
// Some of the properties not transmitted over network need to be added manually here:
|
||||
requestedProperties += PROP_ENTITY_HOST_TYPE;
|
||||
requestedProperties += PROP_OWNING_AVATAR_ID;
|
||||
requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ group:grab,
|
|||
enum:MIRROR_MODE prop:mirrorMode type:MirrorMode default:MirrorMode::NONE enum renderProp,
|
||||
enum:PORTAL_EXIT_ID prop:portalExitID type:QUuid default:UNKNOWN_ENTITY_ID renderProp,
|
||||
Physics
|
||||
enum:DENSITY prop:density type:float default:ENTITY_ITEM_DEFAULT_DENSITY min:ENTITY_ITEM_MIN_DENSITY max:ENTITY_ITEM_MIN_DENSITY,
|
||||
enum:DENSITY prop:density type:float default:ENTITY_ITEM_DEFAULT_DENSITY min:ENTITY_ITEM_MIN_DENSITY max:ENTITY_ITEM_MAX_DENSITY,
|
||||
enum:VELOCITY prop:velocity type:vec3 default:ENTITY_ITEM_DEFAULT_VELOCITY inherited variableCopyGetter:getLocalVelocity variableNetworkGetter:getLocalVelocity() variableNetworkSetter:customUpdateVelocityFromNetwork debugString:"m/s" debugGetter:getWorldVelocity(),
|
||||
enum:ANGULAR_VELOCITY prop:angularVelocity type:vec3 default:ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY inherited variableCopyGetter:getLocalAngularVelocity variableNetworkGetter:getLocalAngularVelocity() variableNetworkSetter:customUpdateAngularVelocityFromNetwork debugGetter:getWorldAngularVelocity(),
|
||||
enum:GRAVITY prop:gravity type:vec3 default:ENTITY_ITEM_DEFAULT_GRAVITY debugString:"m/s^2",
|
||||
|
|
|
@ -935,7 +935,9 @@
|
|||
*
|
||||
* @typedef {object} Entities.EntityProperties-Image
|
||||
* @property {Vec3} dimensions=0.1,0.1,0.01 - The dimensions of the entity.
|
||||
* @property {string} imageURL="" - The URL of the image to use.
|
||||
* @property {string} imageURL="" - The URL of the image to use. It can also contain a base64 encoded image, in the same format as glTF.
|
||||
* For network transmitted entities there's about 1000-character limit for the length of this field. For base64 image
|
||||
* the property string needs to begin with `data:image/png;base64,`, `data:image/jpeg;base64,` or `data:image/webp;base64,`.
|
||||
* @property {boolean} emissive=false - <code>true</code> if the image should be emissive (unlit), <code>false</code> if it
|
||||
* shouldn't.
|
||||
* @property {boolean} keepAspectRatio=true - <code>true</code> if the image should maintain its aspect ratio,
|
||||
|
|
|
@ -288,6 +288,10 @@ public:
|
|||
_glUniformMatrix3fv(location, 1, false, glm::value_ptr(v));
|
||||
}
|
||||
|
||||
void _glUniform(int location, const glm::mat4& v) {
|
||||
_glUniformMatrix4fv(location, 1, false, glm::value_ptr(v));
|
||||
}
|
||||
|
||||
// Maybe useful but shoudln't be public. Please convince me otherwise
|
||||
// Well porting to gles i need it...
|
||||
void runLambda(std::function<void()> f);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Nissim Hadar on 9/13/2017.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -182,3 +183,7 @@ void Haze::setHazeBackgroundBlend(const float hazeBackgroundBlend) {
|
|||
_hazeParametersBuffer.edit<Parameters>().hazeBackgroundBlend = newBlend;
|
||||
}
|
||||
}
|
||||
|
||||
bool Haze::isActive() const {
|
||||
return (_hazeParametersBuffer.get<Parameters>().hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Nissim Hadar on 9/13/2017.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -95,6 +96,8 @@ namespace graphics {
|
|||
using UniformBufferView = gpu::BufferView;
|
||||
UniformBufferView getHazeParametersBuffer() const { return _hazeParametersBuffer; }
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
protected:
|
||||
class Parameters {
|
||||
public:
|
||||
|
|
|
@ -254,6 +254,18 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs
|
|||
if (url.scheme() == RESOURCE_SCHEME) {
|
||||
return getResourceTexture(url);
|
||||
}
|
||||
|
||||
QString urlString = url.toString();
|
||||
if (content.isEmpty() && (urlString.startsWith("data:image/jpeg;base64,")
|
||||
|| urlString.startsWith("data:image/png;base64,")
|
||||
|| urlString.startsWith("data:image/webp;base64,"))) {
|
||||
QString binaryUrl = urlString.split(",")[1];
|
||||
auto decodedContent = binaryUrl.isEmpty() ? QByteArray() : QByteArray::fromBase64(binaryUrl.toUtf8());
|
||||
if (!decodedContent.isEmpty()) {
|
||||
return getTexture(url, type, decodedContent, maxNumPixels, sourceChannel);
|
||||
}
|
||||
}
|
||||
|
||||
QString decodedURL = QUrl::fromPercentEncoding(url.toEncoded());
|
||||
if (decodedURL.startsWith("{")) {
|
||||
return getTextureByUUID(decodedURL);
|
||||
|
|
|
@ -1335,7 +1335,7 @@ HFMTexture GLTFSerializer::getHFMTexture(const cgltf_texture *texture) {
|
|||
hfmTex.filename = textureUrl.toEncoded().append(QString::number(imageIndex).toUtf8());
|
||||
}
|
||||
|
||||
if (url.contains("data:image/jpeg;base64,") || url.contains("data:image/png;base64,") || url.contains("data:image/webp;base64,")) {
|
||||
if (url.startsWith("data:image/jpeg;base64,") || url.startsWith("data:image/png;base64,") || url.startsWith("data:image/webp;base64,")) {
|
||||
hfmTex.content = requestEmbeddedData(url);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -356,16 +356,53 @@ void Procedural::prepare(gpu::Batch& batch,
|
|||
}
|
||||
}
|
||||
// Then fill in every reflections the new custom bindings
|
||||
int customSlot = procedural::slot::uniform::Custom;
|
||||
size_t customSlot = procedural::slot::uniform::Custom;
|
||||
_slotMap.clear();
|
||||
for (const auto& key : _data.uniforms.keys()) {
|
||||
std::string uniformName = key.toLocal8Bit().data();
|
||||
for (auto reflection : allFragmentReflections) {
|
||||
reflection->uniforms[uniformName] = customSlot;
|
||||
bool isArrayUniform = false;
|
||||
size_t numSlots = 0;
|
||||
const QJsonValue& value = _data.uniforms[key];
|
||||
if (value.isDouble()) {
|
||||
numSlots = 1;
|
||||
} else if (value.isArray()) {
|
||||
const QJsonArray valueArray = value.toArray();
|
||||
if (valueArray.size() > 0) {
|
||||
if (valueArray[0].isArray()) {
|
||||
const size_t valueLength = valueArray[0].toArray().size();
|
||||
size_t count = 0;
|
||||
for (const QJsonValue& value : valueArray) {
|
||||
if (value.isArray()) {
|
||||
const QJsonArray innerValueArray = value.toArray();
|
||||
if (innerValueArray.size() == valueLength) {
|
||||
if (valueLength == 3 || valueLength == 4 || valueLength == 9 || valueLength == 16) {
|
||||
count++;
|
||||
isArrayUniform = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
numSlots = count;
|
||||
} else if (valueArray[0].isDouble()) {
|
||||
numSlots = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto reflection : allVertexReflections) {
|
||||
reflection->uniforms[uniformName] = customSlot;
|
||||
|
||||
if (numSlots > 0) {
|
||||
std::string uniformName = key.toLocal8Bit().data();
|
||||
std::string trueUniformName = uniformName;
|
||||
if (isArrayUniform) {
|
||||
trueUniformName += "[0]";
|
||||
}
|
||||
for (auto reflection : allFragmentReflections) {
|
||||
reflection->uniforms[trueUniformName] = customSlot;
|
||||
}
|
||||
for (auto reflection : allVertexReflections) {
|
||||
reflection->uniforms[trueUniformName] = customSlot;
|
||||
}
|
||||
_slotMap[uniformName] = customSlot;
|
||||
customSlot += numSlots;
|
||||
}
|
||||
++customSlot;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,59 +485,138 @@ void Procedural::prepare(gpu::Batch& batch,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Procedural::setupUniforms() {
|
||||
_uniforms.clear();
|
||||
// Set any userdata specified uniforms
|
||||
int slot = procedural::slot::uniform::Custom;
|
||||
for (const auto& key : _data.uniforms.keys()) {
|
||||
std::string uniformName = key.toLocal8Bit().data();
|
||||
QJsonValue value = _data.uniforms[key];
|
||||
const std::string uniformName = key.toLocal8Bit().data();
|
||||
auto slotItr = _slotMap.find(uniformName);
|
||||
if (slotItr == _slotMap.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t slot = slotItr->second;
|
||||
const QJsonValue& value = _data.uniforms[key];
|
||||
if (value.isDouble()) {
|
||||
float v = value.toDouble();
|
||||
const float v = value.toDouble();
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform1f(slot, v); });
|
||||
} else if (value.isArray()) {
|
||||
auto valueArray = value.toArray();
|
||||
switch (valueArray.size()) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1: {
|
||||
float v = valueArray[0].toDouble();
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform1f(slot, v); });
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
glm::vec2 v{ valueArray[0].toDouble(), valueArray[1].toDouble() };
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform2f(slot, v.x, v.y); });
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
glm::vec3 v{
|
||||
valueArray[0].toDouble(),
|
||||
valueArray[1].toDouble(),
|
||||
valueArray[2].toDouble(),
|
||||
};
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform3f(slot, v.x, v.y, v.z); });
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
case 4: {
|
||||
glm::vec4 v{
|
||||
valueArray[0].toDouble(),
|
||||
valueArray[1].toDouble(),
|
||||
valueArray[2].toDouble(),
|
||||
valueArray[3].toDouble(),
|
||||
};
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform4f(slot, v.x, v.y, v.z, v.w); });
|
||||
break;
|
||||
}
|
||||
const QJsonArray valueArray = value.toArray();
|
||||
if (valueArray.size() > 0) {
|
||||
if (valueArray[0].isArray()) {
|
||||
const size_t valueLength = valueArray[0].toArray().size();
|
||||
std::vector<float> vs;
|
||||
vs.reserve(valueLength * valueArray.size());
|
||||
size_t count = 0;
|
||||
for (const QJsonValue& value : valueArray) {
|
||||
if (value.isArray()) {
|
||||
const QJsonArray innerValueArray = value.toArray();
|
||||
if (innerValueArray.size() == valueLength) {
|
||||
if (valueLength == 3 || valueLength == 4 || valueLength == 9 || valueLength == 16) {
|
||||
for (size_t i = 0; i < valueLength; i++) {
|
||||
vs.push_back(innerValueArray[i].toDouble());
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
switch (valueLength) {
|
||||
case 3: {
|
||||
_uniforms.push_back([slot, vs, count](gpu::Batch& batch) { batch._glUniform3fv(slot, count, vs.data()); });
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
_uniforms.push_back([slot, vs, count](gpu::Batch& batch) { batch._glUniform4fv(slot, count, vs.data()); });
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
_uniforms.push_back([slot, vs, count](gpu::Batch& batch) { batch._glUniformMatrix3fv(slot, count, false, vs.data()); });
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
_uniforms.push_back([slot, vs, count](gpu::Batch& batch) { batch._glUniformMatrix4fv(slot, count, false, vs.data()); });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (valueArray[0].isDouble()) {
|
||||
switch (valueArray.size()) {
|
||||
case 1: {
|
||||
const float v = valueArray[0].toDouble();
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform(slot, v); });
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const glm::vec2 v{ valueArray[0].toDouble(), valueArray[1].toDouble() };
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform(slot, v); });
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const glm::vec3 v{
|
||||
valueArray[0].toDouble(),
|
||||
valueArray[1].toDouble(),
|
||||
valueArray[2].toDouble(),
|
||||
};
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform(slot, v); });
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const glm::vec4 v{
|
||||
valueArray[0].toDouble(),
|
||||
valueArray[1].toDouble(),
|
||||
valueArray[2].toDouble(),
|
||||
valueArray[3].toDouble(),
|
||||
};
|
||||
_uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform(slot, v); });
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
const glm::mat3 m{
|
||||
valueArray[0].toDouble(),
|
||||
valueArray[1].toDouble(),
|
||||
valueArray[2].toDouble(),
|
||||
valueArray[3].toDouble(),
|
||||
valueArray[4].toDouble(),
|
||||
valueArray[5].toDouble(),
|
||||
valueArray[6].toDouble(),
|
||||
valueArray[7].toDouble(),
|
||||
valueArray[8].toDouble(),
|
||||
};
|
||||
_uniforms.push_back([slot, m](gpu::Batch& batch) { batch._glUniform(slot, m); });
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
const glm::mat4 m{
|
||||
valueArray[0].toDouble(),
|
||||
valueArray[1].toDouble(),
|
||||
valueArray[2].toDouble(),
|
||||
valueArray[3].toDouble(),
|
||||
valueArray[4].toDouble(),
|
||||
valueArray[5].toDouble(),
|
||||
valueArray[6].toDouble(),
|
||||
valueArray[7].toDouble(),
|
||||
valueArray[8].toDouble(),
|
||||
valueArray[9].toDouble(),
|
||||
valueArray[10].toDouble(),
|
||||
valueArray[11].toDouble(),
|
||||
valueArray[12].toDouble(),
|
||||
valueArray[13].toDouble(),
|
||||
valueArray[14].toDouble(),
|
||||
valueArray[15].toDouble(),
|
||||
};
|
||||
_uniforms.push_back([slot, m](gpu::Batch& batch) { batch._glUniform(slot, m); });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
|
||||
_uniforms.push_back([this](gpu::Batch& batch) {
|
||||
|
@ -578,4 +694,4 @@ void graphics::ProceduralMaterial::initializeProcedural() {
|
|||
_procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent);
|
||||
|
||||
_procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorShader.frag").path();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,6 +190,7 @@ protected:
|
|||
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
|
||||
std::unordered_map<std::string, std::string> _vertexReplacements;
|
||||
std::unordered_map<std::string, std::string> _fragmentReplacements;
|
||||
std::unordered_map<std::string, size_t> _slotMap;
|
||||
|
||||
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _proceduralPipelines;
|
||||
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _errorPipelines;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Niraj Venkat on 7/15/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -606,8 +607,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
graphics::AmbientOcclusionPointer ambientOcclusion;
|
||||
if (_debug) {
|
||||
ambientOcclusion = _debugAmbientOcclusion;
|
||||
} else if (ambientOcclusionStage && ambientOcclusionFrame->_ambientOcclusions.size()) {
|
||||
ambientOcclusion = ambientOcclusionStage->getAmbientOcclusion(ambientOcclusionFrame->_ambientOcclusions.front());
|
||||
} else if (ambientOcclusionStage && ambientOcclusionFrame->_elements.size()) {
|
||||
ambientOcclusion = ambientOcclusionStage->getElement(ambientOcclusionFrame->_elements.front());
|
||||
}
|
||||
|
||||
if (!ambientOcclusion || !lightingModel->isAmbientOcclusionEnabled()) {
|
||||
|
|
|
@ -7,50 +7,8 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AmbientOcclusionStage.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
std::string AmbientOcclusionStage::_stageName { "AMBIENT_OCCLUSION_STAGE" };
|
||||
const AmbientOcclusionStage::Index AmbientOcclusionStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
AmbientOcclusionStage::Index AmbientOcclusionStage::findAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion) const {
|
||||
auto found = _ambientOcclusionMap.find(ambientOcclusion);
|
||||
if (found != _ambientOcclusionMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
AmbientOcclusionStage::Index AmbientOcclusionStage::addAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion) {
|
||||
auto found = _ambientOcclusionMap.find(ambientOcclusion);
|
||||
if (found == _ambientOcclusionMap.end()) {
|
||||
auto ambientOcclusionId = _ambientOcclusions.newElement(ambientOcclusion);
|
||||
// Avoid failing to allocate a ambientOcclusion, just pass
|
||||
if (ambientOcclusionId != INVALID_INDEX) {
|
||||
// Insert the ambientOcclusion and its index in the reverse map
|
||||
_ambientOcclusionMap.insert(AmbientOcclusionMap::value_type(ambientOcclusion, ambientOcclusionId));
|
||||
}
|
||||
return ambientOcclusionId;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
AmbientOcclusionStage::AmbientOcclusionPointer AmbientOcclusionStage::removeAmbientOcclusion(Index index) {
|
||||
AmbientOcclusionPointer removed = _ambientOcclusions.freeElement(index);
|
||||
if (removed) {
|
||||
_ambientOcclusionMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
AmbientOcclusionStageSetup::AmbientOcclusionStageSetup() {}
|
||||
|
||||
void AmbientOcclusionStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(AmbientOcclusionStage::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(AmbientOcclusionStage::getName(), std::make_shared<AmbientOcclusionStage>());
|
||||
}
|
||||
}
|
||||
template <>
|
||||
std::string render::PointerStage<graphics::AmbientOcclusion, graphics::AmbientOcclusionPointer>::_name { "AMBIENT_OCCLUSION_STAGE" };
|
||||
|
|
|
@ -11,74 +11,17 @@
|
|||
#ifndef hifi_render_utils_AmbientOcclusionStage_h
|
||||
#define hifi_render_utils_AmbientOcclusionStage_h
|
||||
|
||||
#include <graphics/Stage.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
|
||||
#include <render/Forward.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <graphics/AmbientOcclusion.h>
|
||||
#include <render/Stage.h>
|
||||
#include <render/StageSetup.h>
|
||||
|
||||
// AmbientOcclusion stage to set up ambientOcclusion-related rendering tasks
|
||||
class AmbientOcclusionStage : public render::Stage {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using AmbientOcclusionPointer = graphics::AmbientOcclusionPointer;
|
||||
using AmbientOcclusions = render::indexed_container::IndexedPointerVector<graphics::AmbientOcclusion>;
|
||||
using AmbientOcclusionMap = std::unordered_map<AmbientOcclusionPointer, Index>;
|
||||
|
||||
using AmbientOcclusionIndices = std::vector<Index>;
|
||||
|
||||
Index findAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion) const;
|
||||
Index addAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion);
|
||||
|
||||
AmbientOcclusionPointer removeAmbientOcclusion(Index index);
|
||||
|
||||
bool checkAmbientOcclusionId(Index index) const { return _ambientOcclusions.checkIndex(index); }
|
||||
|
||||
Index getNumAmbientOcclusions() const { return _ambientOcclusions.getNumElements(); }
|
||||
Index getNumFreeAmbientOcclusions() const { return _ambientOcclusions.getNumFreeIndices(); }
|
||||
Index getNumAllocatedAmbientOcclusions() const { return _ambientOcclusions.getNumAllocatedIndices(); }
|
||||
|
||||
AmbientOcclusionPointer getAmbientOcclusion(Index ambientOcclusionId) const {
|
||||
return _ambientOcclusions.get(ambientOcclusionId);
|
||||
}
|
||||
|
||||
AmbientOcclusions _ambientOcclusions;
|
||||
AmbientOcclusionMap _ambientOcclusionMap;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _ambientOcclusions.clear(); }
|
||||
|
||||
void pushAmbientOcclusion(AmbientOcclusionStage::Index index) { _ambientOcclusions.emplace_back(index); }
|
||||
|
||||
AmbientOcclusionStage::AmbientOcclusionIndices _ambientOcclusions;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
class AmbientOcclusionStage : public render::PointerStage<graphics::AmbientOcclusion, graphics::AmbientOcclusionPointer> {};
|
||||
using AmbientOcclusionStagePointer = std::shared_ptr<AmbientOcclusionStage>;
|
||||
|
||||
class AmbientOcclusionStageSetup {
|
||||
class AmbientOcclusionStageSetup : public render::StageSetup<AmbientOcclusionStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<AmbientOcclusionStageSetup>;
|
||||
|
||||
AmbientOcclusionStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//
|
||||
// Created by Samuel Gateau on 2018/12/06
|
||||
// Copyright 2013-2018 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
|
|
@ -3,58 +3,20 @@
|
|||
//
|
||||
// Created by Sam Gateau on 5/9/2017.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "BackgroundStage.h"
|
||||
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
#include <graphics/ShaderConstants.h>
|
||||
|
||||
std::string BackgroundStage::_stageName { "BACKGROUND_STAGE" };
|
||||
const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const {
|
||||
auto found = _backgroundMap.find(background);
|
||||
if (found != _backgroundMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BackgroundStage::Index BackgroundStage::addBackground(const BackgroundPointer& background) {
|
||||
|
||||
auto found = _backgroundMap.find(background);
|
||||
if (found == _backgroundMap.end()) {
|
||||
auto backgroundId = _backgrounds.newElement(background);
|
||||
// Avoid failing to allocate a background, just pass
|
||||
if (backgroundId != INVALID_INDEX) {
|
||||
|
||||
// Insert the background and its index in the reverse map
|
||||
_backgroundMap.insert(BackgroundMap::value_type(background, backgroundId));
|
||||
}
|
||||
return backgroundId;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BackgroundStage::BackgroundPointer BackgroundStage::removeBackground(Index index) {
|
||||
BackgroundPointer removed = _backgrounds.freeElement(index);
|
||||
|
||||
if (removed) {
|
||||
_backgroundMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string render::PointerStage<graphics::SunSkyStage, graphics::SunSkyStagePointer>::_name { "BACKGROUND_STAGE" };
|
||||
|
||||
void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
const auto& lightingModel = inputs.get0();
|
||||
|
@ -66,8 +28,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
|
|||
const auto& backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
const auto& backgroundFrame = inputs.get1();
|
||||
graphics::SkyboxPointer skybox;
|
||||
if (backgroundStage && backgroundFrame->_backgrounds.size()) {
|
||||
const auto& background = backgroundStage->getBackground(backgroundFrame->_backgrounds.front());
|
||||
if (backgroundStage && backgroundFrame->_elements.size()) {
|
||||
const auto& background = backgroundStage->getElement(backgroundFrame->_elements.front());
|
||||
if (background) {
|
||||
skybox = background->getSkybox();
|
||||
}
|
||||
|
@ -98,8 +60,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
|
|||
// If we're using forward rendering, we need to calculate haze
|
||||
if (args->_renderMethod == render::Args::RenderMethod::FORWARD) {
|
||||
const auto& hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazeStage && hazeFrame->_elements.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getElement(hazeFrame->_elements.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
|
@ -111,14 +73,3 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
|
|||
args->_batch = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundStageSetup::BackgroundStageSetup() {
|
||||
}
|
||||
|
||||
void BackgroundStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(BackgroundStage::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(BackgroundStage::getName(), std::make_shared<BackgroundStage>());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//
|
||||
// BackgroundStage.h
|
||||
|
||||
//
|
||||
// Created by Sam Gateau on 5/9/2017.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -12,72 +13,19 @@
|
|||
#define hifi_render_utils_BackgroundStage_h
|
||||
|
||||
#include <graphics/Stage.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
#include "HazeStage.h"
|
||||
#include <render/StageSetup.h>
|
||||
|
||||
#include "HazeStage.h"
|
||||
#include "LightingModel.h"
|
||||
|
||||
|
||||
// Background stage to set up background-related rendering tasks
|
||||
class BackgroundStage : public render::Stage {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using BackgroundPointer = graphics::SunSkyStagePointer;
|
||||
using Backgrounds = render::indexed_container::IndexedPointerVector<graphics::SunSkyStage>;
|
||||
using BackgroundMap = std::unordered_map<BackgroundPointer, Index>;
|
||||
|
||||
using BackgroundIndices = std::vector<Index>;
|
||||
|
||||
|
||||
Index findBackground(const BackgroundPointer& background) const;
|
||||
Index addBackground(const BackgroundPointer& background);
|
||||
|
||||
BackgroundPointer removeBackground(Index index);
|
||||
|
||||
bool checkBackgroundId(Index index) const { return _backgrounds.checkIndex(index); }
|
||||
|
||||
Index getNumBackgrounds() const { return _backgrounds.getNumElements(); }
|
||||
Index getNumFreeBackgrounds() const { return _backgrounds.getNumFreeIndices(); }
|
||||
Index getNumAllocatedBackgrounds() const { return _backgrounds.getNumAllocatedIndices(); }
|
||||
|
||||
BackgroundPointer getBackground(Index backgroundId) const {
|
||||
return _backgrounds.get(backgroundId);
|
||||
}
|
||||
|
||||
Backgrounds _backgrounds;
|
||||
BackgroundMap _backgroundMap;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _backgrounds.clear(); }
|
||||
|
||||
void pushBackground(BackgroundStage::Index index) { _backgrounds.emplace_back(index); }
|
||||
|
||||
BackgroundStage::BackgroundIndices _backgrounds;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
class BackgroundStage : public render::PointerStage<graphics::SunSkyStage, graphics::SunSkyStagePointer> {};
|
||||
using BackgroundStagePointer = std::shared_ptr<BackgroundStage>;
|
||||
|
||||
class BackgroundStageSetup {
|
||||
class BackgroundStageSetup : public render::StageSetup<BackgroundStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<BackgroundStageSetup>;
|
||||
|
||||
BackgroundStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
};
|
||||
|
||||
class DrawBackgroundStage {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Olivier Prat on 09/25/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -43,8 +44,8 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
const auto lightingModel = inputs.get3();
|
||||
const auto& bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
graphics::BloomPointer bloom;
|
||||
if (bloomStage && bloomFrame->_blooms.size()) {
|
||||
bloom = bloomStage->getBloom(bloomFrame->_blooms.front());
|
||||
if (bloomStage && bloomFrame->_elements.size()) {
|
||||
bloom = bloomStage->getElement(bloomFrame->_elements.front());
|
||||
}
|
||||
if (!bloom || (lightingModel && !lightingModel->isBloomEnabled())) {
|
||||
renderContext->taskFlow.abortTask();
|
||||
|
|
|
@ -3,56 +3,13 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 8/7/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "BloomStage.h"
|
||||
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
std::string BloomStage::_stageName { "BLOOM_STAGE" };
|
||||
const BloomStage::Index BloomStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
BloomStage::Index BloomStage::findBloom(const BloomPointer& bloom) const {
|
||||
auto found = _bloomMap.find(bloom);
|
||||
if (found != _bloomMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
BloomStage::Index BloomStage::addBloom(const BloomPointer& bloom) {
|
||||
auto found = _bloomMap.find(bloom);
|
||||
if (found == _bloomMap.end()) {
|
||||
auto bloomId = _blooms.newElement(bloom);
|
||||
// Avoid failing to allocate a bloom, just pass
|
||||
if (bloomId != INVALID_INDEX) {
|
||||
// Insert the bloom and its index in the reverse map
|
||||
_bloomMap.insert(BloomMap::value_type(bloom, bloomId));
|
||||
}
|
||||
return bloomId;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
BloomStage::BloomPointer BloomStage::removeBloom(Index index) {
|
||||
BloomPointer removed = _blooms.freeElement(index);
|
||||
if (removed) {
|
||||
_bloomMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
BloomStageSetup::BloomStageSetup() {}
|
||||
|
||||
void BloomStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(BloomStage::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(BloomStage::getName(), std::make_shared<BloomStage>());
|
||||
}
|
||||
}
|
||||
template <>
|
||||
std::string render::PointerStage<graphics::Bloom, graphics::BloomPointer>::_name { "BLOOM_STAGE" };
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// Created by Sam Gondelman on 8/7/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -11,74 +12,17 @@
|
|||
#ifndef hifi_render_utils_BloomStage_h
|
||||
#define hifi_render_utils_BloomStage_h
|
||||
|
||||
#include <graphics/Stage.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
|
||||
#include <render/Forward.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <graphics/Bloom.h>
|
||||
#include <render/Stage.h>
|
||||
#include <render/StageSetup.h>
|
||||
|
||||
// Bloom stage to set up bloom-related rendering tasks
|
||||
class BloomStage : public render::Stage {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using BloomPointer = graphics::BloomPointer;
|
||||
using Blooms = render::indexed_container::IndexedPointerVector<graphics::Bloom>;
|
||||
using BloomMap = std::unordered_map<BloomPointer, Index>;
|
||||
|
||||
using BloomIndices = std::vector<Index>;
|
||||
|
||||
Index findBloom(const BloomPointer& bloom) const;
|
||||
Index addBloom(const BloomPointer& bloom);
|
||||
|
||||
BloomPointer removeBloom(Index index);
|
||||
|
||||
bool checkBloomId(Index index) const { return _blooms.checkIndex(index); }
|
||||
|
||||
Index getNumBlooms() const { return _blooms.getNumElements(); }
|
||||
Index getNumFreeBlooms() const { return _blooms.getNumFreeIndices(); }
|
||||
Index getNumAllocatedBlooms() const { return _blooms.getNumAllocatedIndices(); }
|
||||
|
||||
BloomPointer getBloom(Index bloomId) const {
|
||||
return _blooms.get(bloomId);
|
||||
}
|
||||
|
||||
Blooms _blooms;
|
||||
BloomMap _bloomMap;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _blooms.clear(); }
|
||||
|
||||
void pushBloom(BloomStage::Index index) { _blooms.emplace_back(index); }
|
||||
|
||||
BloomStage::BloomIndices _blooms;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
class BloomStage : public render::PointerStage<graphics::Bloom, graphics::BloomPointer> {};
|
||||
using BloomStagePointer = std::shared_ptr<BloomStage>;
|
||||
|
||||
class BloomStageSetup {
|
||||
class BloomStageSetup : public render::StageSetup<BloomStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<BloomStageSetup>;
|
||||
|
||||
BloomStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Andrzej Kapolka on 9/11/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -375,7 +376,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
// Global directional light, maybe shadow and ambient pass
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
assert(lightStage->getNumLights() > 0);
|
||||
assert(lightStage->getNumElements() > 0);
|
||||
auto keyLight = lightStage->getCurrentKeyLight(*lightFrame);
|
||||
|
||||
// Check if keylight casts shadows
|
||||
|
@ -391,7 +392,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
// Global Ambient light
|
||||
graphics::LightPointer ambientLight;
|
||||
if (lightStage && lightFrame->_ambientLights.size()) {
|
||||
ambientLight = lightStage->getLight(lightFrame->_ambientLights.front());
|
||||
ambientLight = lightStage->getElement(lightFrame->_ambientLights.front());
|
||||
}
|
||||
bool hasAmbientMap = (ambientLight != nullptr);
|
||||
|
||||
|
@ -430,8 +431,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
|
||||
// Haze
|
||||
const auto& hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazeStage && hazeFrame->_elements.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getElement(hazeFrame->_elements.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
|
@ -636,7 +637,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
|
|||
|
||||
// Add the global light to the light stage (for later shadow rendering)
|
||||
// Set this light to be the default
|
||||
_defaultLightID = lightStage->addLight(lp, true);
|
||||
_defaultLightID = lightStage->addElement(lp, true);
|
||||
}
|
||||
|
||||
auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
|
@ -649,7 +650,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
|
|||
_defaultBackground = background;
|
||||
|
||||
// Add the global light to the light stage (for later shadow rendering)
|
||||
_defaultBackgroundID = backgroundStage->addBackground(_defaultBackground);
|
||||
_defaultBackgroundID = backgroundStage->addElement(_defaultBackground);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -659,7 +660,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
|
|||
auto haze = std::make_shared<graphics::Haze>();
|
||||
|
||||
_defaultHaze = haze;
|
||||
_defaultHazeID = hazeStage->addHaze(_defaultHaze);
|
||||
_defaultHazeID = hazeStage->addElement(_defaultHaze);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,7 +670,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
|
|||
auto tonemapping = std::make_shared<graphics::Tonemapping>();
|
||||
|
||||
_defaultTonemapping = tonemapping;
|
||||
_defaultTonemappingID = tonemappingStage->addTonemapping(_defaultTonemapping);
|
||||
_defaultTonemappingID = tonemappingStage->addElement(_defaultTonemapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Nissim Hadar on 9/1/2017.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -39,8 +40,8 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
|
|||
const auto hazeFrame = inputs.get0();
|
||||
const auto& hazeStage = renderContext->args->_scene->getStage<HazeStage>();
|
||||
graphics::HazePointer haze;
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
haze = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazeStage && hazeFrame->_elements.size() > 0) {
|
||||
haze = hazeStage->getElement(hazeFrame->_elements.front());
|
||||
}
|
||||
|
||||
if (!haze) {
|
||||
|
@ -55,6 +56,10 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
|
|||
|
||||
auto depthBuffer = framebuffer->getLinearDepthTexture();
|
||||
|
||||
if (!lightingModel->isHazeEnabled() || !haze->isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
if (!_hazePipeline) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// Created by Olivier Prat on 17/07/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -28,10 +29,8 @@ FadeEffect::FadeEffect() {
|
|||
}
|
||||
|
||||
void FadeEffect::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||
auto editedFadeCategory = task.addJob<FadeJob>("Fade");
|
||||
|
||||
const auto fadeEditInput = FadeEditJob::Input(inputs, editedFadeCategory).asVarying();
|
||||
task.addJob<FadeEditJob>("FadeEdit", fadeEditInput);
|
||||
const auto editedFadeCategory = task.addJob<FadeJob>("Fade");
|
||||
task.addJob<FadeEditJob>("FadeEdit", editedFadeCategory);
|
||||
}
|
||||
|
||||
render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() {
|
||||
|
@ -47,7 +46,7 @@ render::ShapePipeline::ItemSetter FadeEffect::getItemUniformSetter() {
|
|||
const auto& scene = args->_scene;
|
||||
const auto& batch = args->_batch;
|
||||
auto transitionStage = scene->getStage<render::TransitionStage>();
|
||||
auto& transitionState = transitionStage->getTransition(item.getTransitionId());
|
||||
auto& transitionState = transitionStage->getElement(item.getTransitionId());
|
||||
|
||||
if (transitionState.paramsBuffer._size != sizeof(gpu::StructBuffer<FadeObjectParams>)) {
|
||||
static_assert(sizeof(transitionState.paramsBuffer) == sizeof(gpu::StructBuffer<FadeObjectParams>), "Assuming gpu::StructBuffer is a helper class for gpu::BufferView");
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
|
||||
class FadeEffect {
|
||||
public:
|
||||
using Input = render::ItemBounds;
|
||||
using JobModel = render::Task::ModelI<FadeEffect, render::ItemBounds>;
|
||||
using JobModel = render::Task::Model<FadeEffect>;
|
||||
|
||||
FadeEffect();
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// Created by Olivier Prat on 07/07/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -35,7 +36,7 @@ void FadeEditJob::configure(const Config& config) {
|
|||
_isEditEnabled = config.editFade;
|
||||
}
|
||||
|
||||
void FadeEditJob::run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs) {
|
||||
void FadeEditJob::run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& input) {
|
||||
auto scene = renderContext->_scene;
|
||||
|
||||
if (_isEditEnabled) {
|
||||
|
@ -63,7 +64,7 @@ void FadeEditJob::run(const render::RenderContextPointer& renderContext, const F
|
|||
render::Transition::AVATAR_CHANGE
|
||||
};
|
||||
|
||||
auto transitionType = categoryToTransition[inputs.get1()];
|
||||
auto transitionType = categoryToTransition[input];
|
||||
|
||||
transaction.queryTransitionOnItem(_editedItem, [transitionType, scene](render::ItemID id, const render::Transition* transition) {
|
||||
if (transition == nullptr || transition->isFinished || transition->eventType != transitionType) {
|
||||
|
@ -572,7 +573,7 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou
|
|||
|
||||
// And now update fade effect
|
||||
for (auto transitionId : *transitionStage) {
|
||||
auto& state = transitionStage->editTransition(transitionId);
|
||||
auto& state = transitionStage->editElement(transitionId);
|
||||
#ifdef DEBUG
|
||||
auto& item = scene->getItem(state.itemId);
|
||||
assert(item.getTransitionId() == transitionId);
|
||||
|
|
|
@ -177,13 +177,13 @@ class FadeEditJob {
|
|||
public:
|
||||
|
||||
using Config = FadeEditConfig;
|
||||
using Input = render::VaryingSet2<render::ItemBounds, FadeCategory>;
|
||||
using Input = FadeCategory;
|
||||
using JobModel = render::Job::ModelI<FadeEditJob, Input, Config>;
|
||||
|
||||
FadeEditJob() {}
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs);
|
||||
void run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& input);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
// Created by Nissim Hadar on 9/5/2107.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -45,10 +46,6 @@ layout(location=0) in vec2 varTexCoord0;
|
|||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
if ((isHazeEnabled() == 0.0) || (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0);
|
||||
mat4 viewInverse = getViewInverse();
|
||||
|
||||
|
|
|
@ -3,59 +3,13 @@
|
|||
//
|
||||
// Created by Nissim Hadar on 9/26/2017.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "HazeStage.h"
|
||||
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
std::string HazeStage::_stageName { "HAZE_STAGE" };
|
||||
const HazeStage::Index HazeStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
HazeStage::Index HazeStage::findHaze(const HazePointer& haze) const {
|
||||
auto found = _hazeMap.find(haze);
|
||||
if (found != _hazeMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
HazeStage::Index HazeStage::addHaze(const HazePointer& haze) {
|
||||
auto found = _hazeMap.find(haze);
|
||||
if (found == _hazeMap.end()) {
|
||||
auto hazeId = _hazes.newElement(haze);
|
||||
// Avoid failing to allocate a haze, just pass
|
||||
if (hazeId != INVALID_INDEX) {
|
||||
|
||||
// Insert the haze and its index in the reverse map
|
||||
_hazeMap.insert(HazeMap::value_type(haze, hazeId));
|
||||
}
|
||||
return hazeId;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
HazeStage::HazePointer HazeStage::removeHaze(Index index) {
|
||||
HazePointer removed = _hazes.freeElement(index);
|
||||
|
||||
if (removed) {
|
||||
_hazeMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
HazeStageSetup::HazeStageSetup() {
|
||||
}
|
||||
|
||||
void HazeStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(HazeStage::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(HazeStage::getName(), std::make_shared<HazeStage>());
|
||||
}
|
||||
}
|
||||
template <>
|
||||
std::string render::PointerStage<graphics::Haze, graphics::HazePointer>::_name { "HAZE_STAGE" };
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// Created by Nissim Hadar on 9/26/2017.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -11,74 +12,17 @@
|
|||
#ifndef hifi_render_utils_HazeStage_h
|
||||
#define hifi_render_utils_HazeStage_h
|
||||
|
||||
#include <graphics/Stage.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
|
||||
#include <render/Forward.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <graphics/Haze.h>
|
||||
#include <render/Stage.h>
|
||||
#include <render/StageSetup.h>
|
||||
|
||||
// Haze stage to set up haze-related rendering tasks
|
||||
class HazeStage : public render::Stage {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using HazePointer = graphics::HazePointer;
|
||||
using Hazes = render::indexed_container::IndexedPointerVector<graphics::Haze>;
|
||||
using HazeMap = std::unordered_map<HazePointer, Index>;
|
||||
|
||||
using HazeIndices = std::vector<Index>;
|
||||
|
||||
Index findHaze(const HazePointer& haze) const;
|
||||
Index addHaze(const HazePointer& haze);
|
||||
|
||||
HazePointer removeHaze(Index index);
|
||||
|
||||
bool checkHazeId(Index index) const { return _hazes.checkIndex(index); }
|
||||
|
||||
Index getNumHazes() const { return _hazes.getNumElements(); }
|
||||
Index getNumFreeHazes() const { return _hazes.getNumFreeIndices(); }
|
||||
Index getNumAllocatedHazes() const { return _hazes.getNumAllocatedIndices(); }
|
||||
|
||||
HazePointer getHaze(Index hazeId) const {
|
||||
return _hazes.get(hazeId);
|
||||
}
|
||||
|
||||
Hazes _hazes;
|
||||
HazeMap _hazeMap;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _hazes.clear(); }
|
||||
|
||||
void pushHaze(HazeStage::Index index) { _hazes.emplace_back(index); }
|
||||
|
||||
HazeStage::HazeIndices _hazes;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
class HazeStage : public render::PointerStage<graphics::Haze, graphics::HazePointer> {};
|
||||
using HazeStagePointer = std::shared_ptr<HazeStage>;
|
||||
|
||||
class HazeStageSetup {
|
||||
class HazeStageSetup : public render::StageSetup<HazeStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<HazeStageSetup>;
|
||||
|
||||
HazeStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
class FetchHazeConfig : public render::Job::Config {
|
||||
|
|
|
@ -161,7 +161,7 @@ void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, c
|
|||
|
||||
if (!inShapes.empty() && !render::HighlightStage::isIndexInvalid(highlightId)) {
|
||||
auto resources = inputs.get1();
|
||||
auto& highlight = highlightStage->getHighlight(highlightId);
|
||||
auto& highlight = highlightStage->getElement(highlightId);
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
|
@ -247,7 +247,7 @@ void DrawHighlight::run(const render::RenderContextPointer& renderContext, const
|
|||
auto highlightStage = renderContext->_scene->getStage<render::HighlightStage>();
|
||||
auto highlightId = _sharedParameters->_highlightIds[_highlightPassIndex];
|
||||
if (!render::HighlightStage::isIndexInvalid(highlightId)) {
|
||||
auto& highlight = highlightStage->getHighlight(highlightId);
|
||||
auto& highlight = highlightStage->getElement(highlightId);
|
||||
auto pipeline = getPipeline(highlight._style);
|
||||
{
|
||||
auto& shaderParameters = _configuration.edit();
|
||||
|
@ -432,7 +432,7 @@ void SelectionToHighlight::run(const render::RenderContextPointer& renderContext
|
|||
auto highlightList = highlightStage->getActiveHighlightIds();
|
||||
|
||||
for (auto styleId : highlightList) {
|
||||
auto highlight = highlightStage->getHighlight(styleId);
|
||||
auto highlight = highlightStage->getElement(styleId);
|
||||
|
||||
if (!scene->isSelectionEmpty(highlight._selectionName)) {
|
||||
auto highlightId = highlightStage->getHighlightIdBySelection(highlight._selectionName);
|
||||
|
@ -572,8 +572,8 @@ void HighlightCleanup::run(const render::RenderContextPointer& renderContext, co
|
|||
auto highlightStage = scene->getStage<render::HighlightStage>();
|
||||
|
||||
for (auto index : inputs.get0()) {
|
||||
std::string selectionName = highlightStage->getHighlight(index)._selectionName;
|
||||
highlightStage->removeHighlight(index);
|
||||
std::string selectionName = highlightStage->getElement(index)._selectionName;
|
||||
highlightStage->removeElement(index);
|
||||
scene->removeSelection(selectionName);
|
||||
}
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ glm::ivec3 LightClusters::updateClusters() {
|
|||
uint32_t numClusteredLights = 0;
|
||||
for (size_t lightNum = 1; lightNum < _visibleLightIndices.size(); ++lightNum) {
|
||||
auto lightId = _visibleLightIndices[lightNum];
|
||||
auto light = _lightStage->getLight(lightId);
|
||||
auto light = _lightStage->getElement(lightId);
|
||||
if (!light) {
|
||||
continue;
|
||||
}
|
||||
|
@ -567,9 +567,9 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext,
|
|||
output = _lightClusters;
|
||||
|
||||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||
config->numSceneLights = lightStage->getNumLights();
|
||||
config->numFreeSceneLights = lightStage->getNumFreeLights();
|
||||
config->numAllocatedSceneLights = lightStage->getNumAllocatedLights();
|
||||
config->numSceneLights = lightStage->getNumElements();
|
||||
config->numFreeSceneLights = lightStage->getNumFreeElements();
|
||||
config->numAllocatedSceneLights = lightStage->getNumAllocatedElements();
|
||||
config->setNumInputLights(clusteringStats.x);
|
||||
config->setNumClusteredLights(clusteringStats.y);
|
||||
config->setNumClusteredLightReferences(clusteringStats.z);
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
|
||||
FrustumGrid::Planes _gridPlanes[3];
|
||||
|
||||
LightStage::LightIndices _visibleLightIndices;
|
||||
render::ElementIndices _visibleLightIndices;
|
||||
gpu::BufferView _lightIndicesBuffer;
|
||||
|
||||
const uint32_t EMPTY_CLUSTER { 0x0000FFFF };
|
||||
|
|
|
@ -52,7 +52,7 @@ LightPayload::LightPayload() :
|
|||
LightPayload::~LightPayload() {
|
||||
if (!LightStage::isIndexInvalid(_index)) {
|
||||
if (_stage) {
|
||||
_stage->removeLight(_index);
|
||||
_stage->removeElement(_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ void LightPayload::render(RenderArgs* args) {
|
|||
}
|
||||
// Do we need to allocate the light in the stage ?
|
||||
if (LightStage::isIndexInvalid(_index)) {
|
||||
_index = _stage->addLight(_light);
|
||||
_index = _stage->addElement(_light);
|
||||
_needUpdate = false;
|
||||
}
|
||||
// Need an update ?
|
||||
|
@ -122,7 +122,7 @@ _light(std::make_shared<graphics::Light>())
|
|||
KeyLightPayload::~KeyLightPayload() {
|
||||
if (!LightStage::isIndexInvalid(_index)) {
|
||||
if (_stage) {
|
||||
_stage->removeLight(_index);
|
||||
_stage->removeElement(_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ void KeyLightPayload::render(RenderArgs* args) {
|
|||
}
|
||||
// Do we need to allocate the light in the stage ?
|
||||
if (LightStage::isIndexInvalid(_index)) {
|
||||
_index = _stage->addLight(_light);
|
||||
_index = _stage->addElement(_light);
|
||||
_needUpdate = false;
|
||||
}
|
||||
// Need an update ?
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Zach Pomerantz on 1/14/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -15,7 +16,9 @@
|
|||
|
||||
#include "ViewFrustum.h"
|
||||
|
||||
std::string LightStage::_stageName { "LIGHT_STAGE" };
|
||||
template <>
|
||||
std::string render::PointerStage<graphics::Light, graphics::LightPointer, LightFrame>::_name { "LIGHT_STAGE" };
|
||||
|
||||
// The bias matrix goes from homogeneous coordinates to UV coords (see http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#basic-shader)
|
||||
const glm::mat4 LightStage::Shadow::_biasMatrix {
|
||||
0.5, 0.0, 0.0, 0.0,
|
||||
|
@ -24,8 +27,6 @@ const glm::mat4 LightStage::Shadow::_biasMatrix {
|
|||
0.5, 0.5, 0.5, 1.0 };
|
||||
const int LightStage::Shadow::MAP_SIZE = 1024;
|
||||
|
||||
const LightStage::Index LightStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
LightStage::LightStage() {
|
||||
// Add off lights
|
||||
const LightPointer ambientOffLight { std::make_shared<graphics::Light>() };
|
||||
|
@ -33,28 +34,28 @@ LightStage::LightStage() {
|
|||
ambientOffLight->setColor(graphics::Vec3(0.0));
|
||||
ambientOffLight->setIntensity(0.0f);
|
||||
ambientOffLight->setType(graphics::Light::Type::AMBIENT);
|
||||
_ambientOffLightId = addLight(ambientOffLight);
|
||||
_ambientOffLightId = addElement(ambientOffLight);
|
||||
|
||||
const LightPointer pointOffLight { std::make_shared<graphics::Light>() };
|
||||
pointOffLight->setAmbientIntensity(0.0f);
|
||||
pointOffLight->setColor(graphics::Vec3(0.0));
|
||||
pointOffLight->setIntensity(0.0f);
|
||||
pointOffLight->setType(graphics::Light::Type::POINT);
|
||||
_pointOffLightId = addLight(pointOffLight);
|
||||
_pointOffLightId = addElement(pointOffLight);
|
||||
|
||||
const LightPointer spotOffLight { std::make_shared<graphics::Light>() };
|
||||
spotOffLight->setAmbientIntensity(0.0f);
|
||||
spotOffLight->setColor(graphics::Vec3(0.0));
|
||||
spotOffLight->setIntensity(0.0f);
|
||||
spotOffLight->setType(graphics::Light::Type::SPOT);
|
||||
_spotOffLightId = addLight(spotOffLight);
|
||||
_spotOffLightId = addElement(spotOffLight);
|
||||
|
||||
const LightPointer sunOffLight { std::make_shared<graphics::Light>() };
|
||||
sunOffLight->setAmbientIntensity(0.0f);
|
||||
sunOffLight->setColor(graphics::Vec3(0.0));
|
||||
sunOffLight->setIntensity(0.0f);
|
||||
sunOffLight->setType(graphics::Light::Type::SUN);
|
||||
_sunOffLightId = addLight(sunOffLight);
|
||||
_sunOffLightId = addElement(sunOffLight);
|
||||
|
||||
// Set default light to the off ambient light (until changed)
|
||||
_defaultLightId = _ambientOffLightId;
|
||||
|
@ -72,7 +73,7 @@ LightStage::Shadow::Schema::Schema() {
|
|||
maxDistance = 20.0f;
|
||||
}
|
||||
|
||||
LightStage::Shadow::Cascade::Cascade() :
|
||||
LightStage::Shadow::Cascade::Cascade() :
|
||||
_frustum{ std::make_shared<ViewFrustum>() },
|
||||
_minDistance{ 0.0f },
|
||||
_maxDistance{ 20.0f } {
|
||||
|
@ -88,7 +89,7 @@ const glm::mat4& LightStage::Shadow::Cascade::getProjection() const {
|
|||
|
||||
float LightStage::Shadow::Cascade::computeFarDistance(const ViewFrustum& viewFrustum, const Transform& shadowViewInverse,
|
||||
float left, float right, float bottom, float top, float viewMaxShadowDistance) const {
|
||||
// Far distance should be extended to the intersection of the infinitely extruded shadow frustum
|
||||
// Far distance should be extended to the intersection of the infinitely extruded shadow frustum
|
||||
// with the view frustum side planes. To do so, we generate 10 triangles in shadow space which are the result of
|
||||
// tesselating the side and far faces of the view frustum and clip them with the 4 side planes of the
|
||||
// shadow frustum. The resulting clipped triangle vertices with the farthest Z gives the desired
|
||||
|
@ -121,7 +122,7 @@ float LightStage::Shadow::Cascade::computeFarDistance(const ViewFrustum& viewFru
|
|||
return far;
|
||||
}
|
||||
|
||||
LightStage::Shadow::Shadow(graphics::LightPointer light, unsigned int cascadeCount) :
|
||||
LightStage::Shadow::Shadow(graphics::LightPointer light, unsigned int cascadeCount) :
|
||||
_light{ light } {
|
||||
cascadeCount = std::min(cascadeCount, (unsigned int)SHADOW_CASCADE_MAX_COUNT);
|
||||
Schema schema;
|
||||
|
@ -323,21 +324,12 @@ void LightStage::Shadow::setCascadeFrustum(unsigned int cascadeIndex, const View
|
|||
schemaCascade.reprojection = _biasMatrix * shadowFrustum.getProjection() * viewInverse.getMatrix();
|
||||
}
|
||||
|
||||
LightStage::Index LightStage::findLight(const LightPointer& light) const {
|
||||
auto found = _lightMap.find(light);
|
||||
if (found != _lightMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
LightStage::Index LightStage::addLight(const LightPointer& light, const bool shouldSetAsDefault) {
|
||||
LightStage::Index LightStage::addElement(const LightPointer& light, const bool shouldSetAsDefault) {
|
||||
Index lightId;
|
||||
|
||||
auto found = _lightMap.find(light);
|
||||
if (found == _lightMap.end()) {
|
||||
lightId = _lights.newElement(light);
|
||||
auto found = _elementMap.find(light);
|
||||
if (found == _elementMap.end()) {
|
||||
lightId = _elements.newElement(light);
|
||||
// Avoid failing to allocate a light, just pass
|
||||
if (lightId != INVALID_INDEX) {
|
||||
|
||||
|
@ -349,8 +341,8 @@ LightStage::Index LightStage::addLight(const LightPointer& light, const bool sho
|
|||
_descs[lightId] = Desc();
|
||||
}
|
||||
|
||||
// INsert the light and its index in the reverese map
|
||||
_lightMap.insert(LightMap::value_type(light, lightId));
|
||||
// Insert the light and its index in the reverese map
|
||||
_elementMap[light] = lightId;
|
||||
|
||||
updateLightArrayBuffer(lightId);
|
||||
}
|
||||
|
@ -365,30 +357,30 @@ LightStage::Index LightStage::addLight(const LightPointer& light, const bool sho
|
|||
return lightId;
|
||||
}
|
||||
|
||||
LightStage::LightPointer LightStage::removeLight(Index index) {
|
||||
LightPointer removedLight = _lights.freeElement(index);
|
||||
LightStage::LightPointer LightStage::removeElement(Index index) {
|
||||
LightPointer removedLight = _elements.freeElement(index);
|
||||
if (removedLight) {
|
||||
_lightMap.erase(removedLight);
|
||||
_elementMap.erase(removedLight);
|
||||
_descs[index] = Desc();
|
||||
}
|
||||
assert(_descs.size() <= (size_t)index || _descs[index].shadowId == INVALID_INDEX);
|
||||
return removedLight;
|
||||
}
|
||||
|
||||
LightStage::LightPointer LightStage::getCurrentKeyLight(const LightStage::Frame& frame) const {
|
||||
LightStage::LightPointer LightStage::getCurrentKeyLight(const LightFrame& frame) const {
|
||||
Index keyLightId { _defaultLightId };
|
||||
if (!frame._sunLights.empty()) {
|
||||
keyLightId = frame._sunLights.front();
|
||||
}
|
||||
return _lights.get(keyLightId);
|
||||
return _elements.get(keyLightId);
|
||||
}
|
||||
|
||||
LightStage::LightPointer LightStage::getCurrentAmbientLight(const LightStage::Frame& frame) const {
|
||||
LightStage::LightPointer LightStage::getCurrentAmbientLight(const LightFrame& frame) const {
|
||||
Index keyLightId { _defaultLightId };
|
||||
if (!frame._ambientLights.empty()) {
|
||||
keyLightId = frame._ambientLights.front();
|
||||
}
|
||||
return _lights.get(keyLightId);
|
||||
return _elements.get(keyLightId);
|
||||
}
|
||||
|
||||
void LightStage::updateLightArrayBuffer(Index lightId) {
|
||||
|
@ -397,14 +389,12 @@ void LightStage::updateLightArrayBuffer(Index lightId) {
|
|||
_lightArrayBuffer = std::make_shared<gpu::Buffer>(lightSize);
|
||||
}
|
||||
|
||||
assert(checkLightId(lightId));
|
||||
|
||||
if (lightId > (Index)_lightArrayBuffer->getNumTypedElements<graphics::Light::LightSchema>()) {
|
||||
_lightArrayBuffer->resize(lightSize * (lightId + 10));
|
||||
}
|
||||
|
||||
// lightArray is big enough so we can remap
|
||||
auto light = _lights._elements[lightId];
|
||||
auto light = _elements._elements[lightId];
|
||||
if (light) {
|
||||
const auto& lightSchema = light->getLightSchemaBuffer().get();
|
||||
_lightArrayBuffer->setSubData<graphics::Light::LightSchema>(lightId, lightSchema);
|
||||
|
@ -412,17 +402,3 @@ void LightStage::updateLightArrayBuffer(Index lightId) {
|
|||
// this should not happen ?
|
||||
}
|
||||
}
|
||||
|
||||
LightStageSetup::LightStageSetup() {
|
||||
}
|
||||
|
||||
void LightStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
if (renderContext->_scene) {
|
||||
auto stage = renderContext->_scene->getStage(LightStage::getName());
|
||||
if (!stage) {
|
||||
stage = std::make_shared<LightStage>();
|
||||
renderContext->_scene->resetStage(LightStage::getName(), stage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Zach Pomerantz on 1/14/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -12,34 +13,44 @@
|
|||
#ifndef hifi_render_utils_LightStage_h
|
||||
#define hifi_render_utils_LightStage_h
|
||||
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <gpu/Framebuffer.h>
|
||||
|
||||
#include <graphics/Light.h>
|
||||
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
#include <render/Engine.h>
|
||||
#include <render/StageSetup.h>
|
||||
|
||||
class ViewFrustum;
|
||||
|
||||
// Light stage to set up light-related rendering tasks
|
||||
class LightStage : public render::Stage {
|
||||
class LightFrame {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
LightFrame() {}
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using LightPointer = graphics::LightPointer;
|
||||
using Lights = render::indexed_container::IndexedPointerVector<graphics::Light>;
|
||||
using LightMap = std::unordered_map<LightPointer, Index>;
|
||||
|
||||
using LightIndices = std::vector<Index>;
|
||||
void clear() { _pointLights.clear(); _spotLights.clear(); _sunLights.clear(); _ambientLights.clear(); }
|
||||
void pushLight(Index index, graphics::Light::Type type) {
|
||||
switch (type) {
|
||||
case graphics::Light::POINT: { pushPointLight(index); break; }
|
||||
case graphics::Light::SPOT: { pushSpotLight(index); break; }
|
||||
case graphics::Light::SUN: { pushSunLight(index); break; }
|
||||
case graphics::Light::AMBIENT: { pushAmbientLight(index); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
void pushPointLight(Index index) { _pointLights.emplace_back(index); }
|
||||
void pushSpotLight(Index index) { _spotLights.emplace_back(index); }
|
||||
void pushSunLight(Index index) { _sunLights.emplace_back(index); }
|
||||
void pushAmbientLight(Index index) { _ambientLights.emplace_back(index); }
|
||||
|
||||
render::ElementIndices _pointLights;
|
||||
render::ElementIndices _spotLights;
|
||||
render::ElementIndices _sunLights;
|
||||
render::ElementIndices _ambientLights;
|
||||
};
|
||||
|
||||
// Light stage to set up light-related rendering tasks
|
||||
class LightStage : public render::PointerStage<graphics::Light, graphics::LightPointer, LightFrame> {
|
||||
public:
|
||||
using LightPointer = graphics::LightPointer;
|
||||
|
||||
class Shadow {
|
||||
public:
|
||||
|
@ -74,9 +85,9 @@ public:
|
|||
float left, float right, float bottom, float top, float viewMaxShadowDistance) const;
|
||||
};
|
||||
|
||||
Shadow(graphics::LightPointer light, unsigned int cascadeCount = 1);
|
||||
Shadow(LightPointer light, unsigned int cascadeCount = 1);
|
||||
|
||||
void setLight(graphics::LightPointer light);
|
||||
void setLight(LightPointer light);
|
||||
|
||||
void setKeylightFrustum(const ViewFrustum& viewFrustum,
|
||||
float nearDepth = 1.0f, float farDepth = 1000.0f);
|
||||
|
@ -93,83 +104,46 @@ public:
|
|||
float getMaxDistance() const { return _maxDistance; }
|
||||
void setMaxDistance(float value);
|
||||
|
||||
const graphics::LightPointer& getLight() const { return _light; }
|
||||
const LightPointer& getLight() const { return _light; }
|
||||
|
||||
gpu::TexturePointer map;
|
||||
#include "Shadows_shared.slh"
|
||||
class Schema : public ShadowParameters {
|
||||
public:
|
||||
|
||||
Schema();
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
using Cascades = std::vector<Cascade>;
|
||||
|
||||
static const glm::mat4 _biasMatrix;
|
||||
|
||||
graphics::LightPointer _light;
|
||||
LightPointer _light;
|
||||
float _maxDistance{ 0.0f };
|
||||
Cascades _cascades;
|
||||
|
||||
UniformBufferView _schemaBuffer = nullptr;
|
||||
};
|
||||
|
||||
using ShadowPointer = std::shared_ptr<Shadow>;
|
||||
|
||||
Index findLight(const LightPointer& light) const;
|
||||
Index addLight(const LightPointer& light, const bool shouldSetAsDefault = false);
|
||||
|
||||
Index addElement(const LightPointer& light) override { return addElement(light, false); }
|
||||
Index addElement(const LightPointer& light, const bool shouldSetAsDefault);
|
||||
LightPointer removeElement(Index index) override;
|
||||
|
||||
Index getDefaultLight() { return _defaultLightId; }
|
||||
|
||||
LightPointer removeLight(Index index);
|
||||
|
||||
bool checkLightId(Index index) const { return _lights.checkIndex(index); }
|
||||
|
||||
Index getNumLights() const { return _lights.getNumElements(); }
|
||||
Index getNumFreeLights() const { return _lights.getNumFreeIndices(); }
|
||||
Index getNumAllocatedLights() const { return _lights.getNumAllocatedIndices(); }
|
||||
|
||||
LightPointer getLight(Index lightId) const { return _lights.get(lightId); }
|
||||
|
||||
LightStage();
|
||||
|
||||
gpu::BufferPointer getLightArrayBuffer() const { return _lightArrayBuffer; }
|
||||
void updateLightArrayBuffer(Index lightId);
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _pointLights.clear(); _spotLights.clear(); _sunLights.clear(); _ambientLights.clear(); }
|
||||
void pushLight(LightStage::Index index, graphics::Light::Type type) {
|
||||
switch (type) {
|
||||
case graphics::Light::POINT: { pushPointLight(index); break; }
|
||||
case graphics::Light::SPOT: { pushSpotLight(index); break; }
|
||||
case graphics::Light::SUN: { pushSunLight(index); break; }
|
||||
case graphics::Light::AMBIENT: { pushAmbientLight(index); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
void pushPointLight(LightStage::Index index) { _pointLights.emplace_back(index); }
|
||||
void pushSpotLight(LightStage::Index index) { _spotLights.emplace_back(index); }
|
||||
void pushSunLight(LightStage::Index index) { _sunLights.emplace_back(index); }
|
||||
void pushAmbientLight(LightStage::Index index) { _ambientLights.emplace_back(index); }
|
||||
|
||||
LightStage::LightIndices _pointLights;
|
||||
LightStage::LightIndices _spotLights;
|
||||
LightStage::LightIndices _sunLights;
|
||||
LightStage::LightIndices _ambientLights;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
class ShadowFrame {
|
||||
public:
|
||||
ShadowFrame() {}
|
||||
|
||||
|
||||
void clear() {}
|
||||
|
||||
|
||||
using Object = ShadowPointer;
|
||||
using Objects = std::vector<Object>;
|
||||
|
||||
|
@ -177,20 +151,17 @@ public:
|
|||
_objects.emplace_back(shadow);
|
||||
}
|
||||
|
||||
|
||||
Objects _objects;
|
||||
};
|
||||
using ShadowFramePointer = std::shared_ptr<ShadowFrame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
|
||||
Index getAmbientOffLight() { return _ambientOffLightId; }
|
||||
Index getPointOffLight() { return _pointOffLightId; }
|
||||
Index getSpotOffLight() { return _spotOffLightId; }
|
||||
Index getSunOffLight() { return _sunOffLightId; }
|
||||
|
||||
LightPointer getCurrentKeyLight(const LightStage::Frame& frame) const;
|
||||
LightPointer getCurrentAmbientLight(const LightStage::Frame& frame) const;
|
||||
LightPointer getCurrentKeyLight(const LightFrame& frame) const;
|
||||
LightPointer getCurrentAmbientLight(const LightFrame& frame) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -201,9 +172,7 @@ protected:
|
|||
|
||||
gpu::BufferPointer _lightArrayBuffer;
|
||||
|
||||
Lights _lights;
|
||||
Descs _descs;
|
||||
LightMap _lightMap;
|
||||
|
||||
// define off lights
|
||||
Index _ambientOffLightId;
|
||||
|
@ -216,16 +185,9 @@ protected:
|
|||
};
|
||||
using LightStagePointer = std::shared_ptr<LightStage>;
|
||||
|
||||
|
||||
class LightStageSetup {
|
||||
class LightStageSetup : public render::StageSetup<LightStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<LightStageSetup>;
|
||||
|
||||
LightStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
//
|
||||
// RenderCommonTask.cpp
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2018/01/09
|
||||
// Copyright 2013-2018 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -78,9 +81,9 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
|
||||
graphics::HazePointer haze;
|
||||
const auto& hazeStage = renderContext->args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
if (hazeStage && hazeFrame->_elements.size() > 0) {
|
||||
// We use _hazes.back() here because the last haze object will always have haze disabled.
|
||||
haze = hazeStage->getHaze(hazeFrame->_hazes.back());
|
||||
haze = hazeStage->getElement(hazeFrame->_elements.back());
|
||||
}
|
||||
|
||||
// Clear the framebuffer without stereo
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
//
|
||||
// RenderCommonTask.h
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2018/01/09
|
||||
// Copyright 2013-2018 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//
|
||||
// Created by Sam Gateau on 5/29/15.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -145,10 +146,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
// Shadow Stage Frame
|
||||
const auto shadowFrame = shadowTaskOutputs[1];
|
||||
|
||||
if (depth == 0) {
|
||||
task.addJob<FadeEffect>("FadeEffect", opaques);
|
||||
}
|
||||
|
||||
const auto jitter = task.addJob<JitterSample>("JitterCam");
|
||||
|
||||
// GPU jobs: Start preparing the primary, deferred and lighting buffer
|
||||
|
@ -515,8 +512,8 @@ void RenderTransparentDeferred::run(const RenderContextPointer& renderContext, c
|
|||
|
||||
// Setup haze if current zone has haze
|
||||
const auto& hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazeStage && hazeFrame->_elements.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getElement(hazeFrame->_elements.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//
|
||||
// Created by Zach Pomerantz on 12/13/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -271,8 +272,8 @@ void DrawForward::run(const RenderContextPointer& renderContext, const Inputs& i
|
|||
|
||||
graphics::HazePointer haze;
|
||||
const auto& hazeStage = renderContext->args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
haze = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazeStage && hazeFrame->_elements.size() > 0) {
|
||||
haze = hazeStage->getElement(hazeFrame->_elements.front());
|
||||
}
|
||||
|
||||
gpu::doInBatch("DrawForward::run", args->_context, [&](gpu::Batch& batch) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
#include "RenderViewTask.h"
|
||||
|
||||
#include "FadeEffect.h"
|
||||
#include "RenderShadowTask.h"
|
||||
#include "RenderCommonTask.h"
|
||||
#include "RenderDeferredTask.h"
|
||||
|
@ -40,6 +41,13 @@ void DeferredForwardSwitchJob::build(JobModel& task, const render::Varying& inpu
|
|||
void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask, size_t depth) {
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, tagBits, tagMask);
|
||||
|
||||
if (depth == 0 && tagBits == render::ItemKey::TAG_BITS_0) {
|
||||
// TODO: This doesn't actually do any rendering, it simply processes the fade transactions. Even though forward rendering
|
||||
// doesn't support fading right now, we still need to do this once for both paths, otherwise we are left with orphaned objects
|
||||
// after they fade out. In the future, we should refactor this to happen elsewhere.
|
||||
task.addJob<FadeEffect>("FadeEffect");
|
||||
}
|
||||
|
||||
// Issue the lighting model, aka the big global settings for the view
|
||||
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
|
||||
|
||||
|
|
|
@ -473,8 +473,8 @@ void DebugSubsurfaceScattering::run(const render::RenderContextPointer& renderCo
|
|||
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
// const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage()->getLight(0);
|
||||
const auto light = lightStage->getLight(0);
|
||||
// const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage()->getElement(0);
|
||||
const auto light = lightStage->getElement(0);
|
||||
if (!_debugParams) {
|
||||
_debugParams = std::make_shared<gpu::Buffer>(sizeof(glm::vec4), nullptr);
|
||||
_debugParams->setSubData(0, _debugCursorTexcoord);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Anna Brewer on 7/3/19.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -74,8 +75,8 @@ void ToneMapAndResample::run(const RenderContextPointer& renderContext, const In
|
|||
|
||||
const auto& tonemappingStage = renderContext->_scene->getStage<TonemappingStage>();
|
||||
graphics::TonemappingPointer tonemapping;
|
||||
if (tonemappingStage && tonemappingFrame->_tonemappings.size()) {
|
||||
tonemapping = tonemappingStage->getTonemapping(tonemappingFrame->_tonemappings.front());
|
||||
if (tonemappingStage && tonemappingFrame->_elements.size()) {
|
||||
tonemapping = tonemappingStage->getElement(tonemappingFrame->_elements.front());
|
||||
}
|
||||
|
||||
if (_debug) {
|
||||
|
|
|
@ -7,50 +7,8 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "TonemappingStage.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
std::string TonemappingStage::_stageName { "TONEMAPPING_STAGE" };
|
||||
const TonemappingStage::Index TonemappingStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
TonemappingStage::Index TonemappingStage::findTonemapping(const TonemappingPointer& tonemapping) const {
|
||||
auto found = _tonemappingMap.find(tonemapping);
|
||||
if (found != _tonemappingMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
TonemappingStage::Index TonemappingStage::addTonemapping(const TonemappingPointer& tonemapping) {
|
||||
auto found = _tonemappingMap.find(tonemapping);
|
||||
if (found == _tonemappingMap.end()) {
|
||||
auto tonemappingId = _tonemappings.newElement(tonemapping);
|
||||
// Avoid failing to allocate a tonemapping, just pass
|
||||
if (tonemappingId != INVALID_INDEX) {
|
||||
// Insert the tonemapping and its index in the reverse map
|
||||
_tonemappingMap.insert(TonemappingMap::value_type(tonemapping, tonemappingId));
|
||||
}
|
||||
return tonemappingId;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
TonemappingStage::TonemappingPointer TonemappingStage::removeTonemapping(Index index) {
|
||||
TonemappingPointer removed = _tonemappings.freeElement(index);
|
||||
if (removed) {
|
||||
_tonemappingMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
TonemappingStageSetup::TonemappingStageSetup() {}
|
||||
|
||||
void TonemappingStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(TonemappingStage::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(TonemappingStage::getName(), std::make_shared<TonemappingStage>());
|
||||
}
|
||||
}
|
||||
template <>
|
||||
std::string render::PointerStage<graphics::Tonemapping, graphics::TonemappingPointer>::_name { "TONEMAPPING_STAGE" };
|
||||
|
|
|
@ -11,74 +11,17 @@
|
|||
#ifndef hifi_render_utils_TonemappingStage_h
|
||||
#define hifi_render_utils_TonemappingStage_h
|
||||
|
||||
#include <graphics/Stage.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
|
||||
#include <render/Forward.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <graphics/Tonemapping.h>
|
||||
#include <render/Stage.h>
|
||||
#include <render/StageSetup.h>
|
||||
|
||||
// Tonemapping stage to set up tonemapping-related rendering tasks
|
||||
class TonemappingStage : public render::Stage {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using TonemappingPointer = graphics::TonemappingPointer;
|
||||
using Tonemappings = render::indexed_container::IndexedPointerVector<graphics::Tonemapping>;
|
||||
using TonemappingMap = std::unordered_map<TonemappingPointer, Index>;
|
||||
|
||||
using TonemappingIndices = std::vector<Index>;
|
||||
|
||||
Index findTonemapping(const TonemappingPointer& tonemapping) const;
|
||||
Index addTonemapping(const TonemappingPointer& tonemapping);
|
||||
|
||||
TonemappingPointer removeTonemapping(Index index);
|
||||
|
||||
bool checkTonemappingId(Index index) const { return _tonemappings.checkIndex(index); }
|
||||
|
||||
Index getNumTonemappings() const { return _tonemappings.getNumElements(); }
|
||||
Index getNumFreeTonemappings() const { return _tonemappings.getNumFreeIndices(); }
|
||||
Index getNumAllocatedTonemappings() const { return _tonemappings.getNumAllocatedIndices(); }
|
||||
|
||||
TonemappingPointer getTonemapping(Index tonemappingId) const {
|
||||
return _tonemappings.get(tonemappingId);
|
||||
}
|
||||
|
||||
Tonemappings _tonemappings;
|
||||
TonemappingMap _tonemappingMap;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _tonemappings.clear(); }
|
||||
|
||||
void pushTonemapping(TonemappingStage::Index index) { _tonemappings.emplace_back(index); }
|
||||
|
||||
TonemappingStage::TonemappingIndices _tonemappings;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
class TonemappingStage : public render::PointerStage<graphics::Tonemapping, graphics::TonemappingPointer> {};
|
||||
using TonemappingStagePointer = std::shared_ptr<TonemappingStage>;
|
||||
|
||||
class TonemappingStageSetup {
|
||||
class TonemappingStageSetup : public render::StageSetup<TonemappingStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<TonemappingStageSetup>;
|
||||
|
||||
TonemappingStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Sam Gateau on 4/4/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -86,11 +87,11 @@ void SetupZones::run(const RenderContextPointer& context, const Input& input) {
|
|||
// Finally add the default lights and background:
|
||||
lightStage->_currentFrame.pushSunLight(lightStage->getDefaultLight());
|
||||
lightStage->_currentFrame.pushAmbientLight(lightStage->getDefaultLight());
|
||||
backgroundStage->_currentFrame.pushBackground(0);
|
||||
hazeStage->_currentFrame.pushHaze(0);
|
||||
bloomStage->_currentFrame.pushBloom(INVALID_INDEX);
|
||||
tonemappingStage->_currentFrame.pushTonemapping(0);
|
||||
ambientOcclusionStage->_currentFrame.pushAmbientOcclusion(INVALID_INDEX);
|
||||
backgroundStage->_currentFrame.pushElement(0);
|
||||
hazeStage->_currentFrame.pushElement(0);
|
||||
bloomStage->_currentFrame.pushElement(INVALID_INDEX);
|
||||
tonemappingStage->_currentFrame.pushElement(0);
|
||||
ambientOcclusionStage->_currentFrame.pushElement(INVALID_INDEX);
|
||||
}
|
||||
|
||||
gpu::PipelinePointer DebugZoneLighting::_keyLightPipeline;
|
||||
|
@ -144,22 +145,22 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I
|
|||
std::vector<graphics::LightPointer> keyLightStack;
|
||||
if (lightStage && lightFrame->_sunLights.size()) {
|
||||
for (auto index : lightFrame->_sunLights) {
|
||||
keyLightStack.push_back(lightStage->getLight(index));
|
||||
keyLightStack.push_back(lightStage->getElement(index));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<graphics::LightPointer> ambientLightStack;
|
||||
if (lightStage && lightFrame->_ambientLights.size()) {
|
||||
for (auto index : lightFrame->_ambientLights) {
|
||||
ambientLightStack.push_back(lightStage->getLight(index));
|
||||
ambientLightStack.push_back(lightStage->getElement(index));
|
||||
}
|
||||
}
|
||||
|
||||
auto backgroundStage = context->_scene->getStage<BackgroundStage>(BackgroundStage::getName());
|
||||
std::vector<graphics::SkyboxPointer> skyboxStack;
|
||||
if (backgroundStage && backgroundFrame->_backgrounds.size()) {
|
||||
for (auto index : backgroundFrame->_backgrounds) {
|
||||
auto background = backgroundStage->getBackground(index);
|
||||
if (backgroundStage && backgroundFrame->_elements.size()) {
|
||||
for (auto index : backgroundFrame->_elements) {
|
||||
auto background = backgroundStage->getElement(index);
|
||||
if (background) {
|
||||
skyboxStack.push_back(background->getSkybox());
|
||||
}
|
||||
|
|
|
@ -95,8 +95,8 @@ vec4 evalSDFColor(vec2 texCoord, vec4 glyphBounds) {
|
|||
|
||||
vec4 evalSDFSuperSampled(vec2 texCoord, vec2 positionMS, vec4 glyphBounds) {
|
||||
// Clip to edges. Note: We don't need to check the top edge.
|
||||
if (positionMS.x < params.bounds.x || positionMS.x > (params.bounds.x + params.bounds.z) ||
|
||||
positionMS.y < params.bounds.y - params.bounds.w) {
|
||||
if ((params.bounds.z > 0.0 && (positionMS.x < params.bounds.x || positionMS.x > (params.bounds.x + params.bounds.z))) ||
|
||||
(params.bounds.w > 0.0 && (positionMS.y < params.bounds.y - params.bounds.w))) {
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -438,7 +438,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
|
|||
|
||||
// Draw the token
|
||||
for (const QChar& c : token) {
|
||||
if (advance.x > rightEdge) {
|
||||
if (bounds.x != -1 && advance.x > rightEdge) {
|
||||
break;
|
||||
}
|
||||
const Glyph& glyph = _glyphs[c];
|
||||
|
|
|
@ -71,8 +71,8 @@ public:
|
|||
bool forward, bool mirror) :
|
||||
str(str), color(color), effectColor(effectColor), origin(origin), bounds(bounds), scale(scale), effectThickness(effectThickness),
|
||||
effect(effect), alignment(alignment), verticalAlignment(verticalAlignment), unlit(unlit), forward(forward), mirror(mirror) {}
|
||||
DrawProps(const QString& str, const glm::vec4& color, const glm::vec2& origin, const glm::vec2& bounds, bool forward) :
|
||||
str(str), color(color), origin(origin), bounds(bounds), forward(forward) {}
|
||||
DrawProps(const QString& str, const glm::vec4& color, const glm::vec2& origin, const glm::vec2& bounds, TextAlignment alignment, bool forward) :
|
||||
str(str), color(color), origin(origin), bounds(bounds), alignment(alignment), forward(forward) {}
|
||||
|
||||
const QString& str;
|
||||
const glm::vec4& color;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Niraj Venkat on 6/29/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -163,7 +164,7 @@ void DrawStatus::run(const RenderContextPointer& renderContext, const Input& inp
|
|||
status.setColor(Item::Status::Value::RED);
|
||||
}
|
||||
// Set icon based on transition type
|
||||
auto& transition = transitionStage->getTransition(transitionID);
|
||||
auto& transition = transitionStage->getElement(transitionID);
|
||||
switch (transition.eventType) {
|
||||
case Transition::Type::USER_ENTER_DOMAIN:
|
||||
status.setIcon((unsigned char)Item::Status::Icon::USER_TRANSITION_IN);
|
||||
|
|
|
@ -1,33 +1,31 @@
|
|||
//
|
||||
// HighlightStage.cpp
|
||||
//
|
||||
// Created by Olivier Prat on 07/07/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "HighlightStage.h"
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
std::string HighlightStage::_name("Highlight");
|
||||
const HighlightStage::Index HighlightStage::INVALID_INDEX{ render::indexed_container::INVALID_INDEX };
|
||||
template <>
|
||||
std::string TypedStage<Highlight>::_name { "HIGHLIGHT_STAGE" };
|
||||
|
||||
HighlightStage::Index HighlightStage::addHighlight(const std::string& selectionName, const HighlightStyle& style) {
|
||||
Highlight outline{ selectionName, style };
|
||||
Index id;
|
||||
|
||||
id = _highlights.newElement(outline);
|
||||
_activeHighlightIds.push_back(id);
|
||||
|
||||
return id;
|
||||
Highlight outline { selectionName, style };
|
||||
return addElement(outline);
|
||||
}
|
||||
|
||||
void HighlightStage::removeHighlight(Index index) {
|
||||
HighlightIdList::iterator idIterator = std::find(_activeHighlightIds.begin(), _activeHighlightIds.end(), index);
|
||||
if (idIterator != _activeHighlightIds.end()) {
|
||||
_activeHighlightIds.erase(idIterator);
|
||||
}
|
||||
if (!_highlights.isElementFreed(index)) {
|
||||
_highlights.freeElement(index);
|
||||
}
|
||||
}
|
||||
|
||||
Index HighlightStage::getHighlightIdBySelection(const std::string& selectionName) const {
|
||||
for (auto outlineId : _activeHighlightIds) {
|
||||
const auto& outline = _highlights.get(outlineId);
|
||||
HighlightStage::Index HighlightStage::getHighlightIdBySelection(const std::string& selectionName) const {
|
||||
for (auto outlineId : _activeElementIDs) {
|
||||
const auto& outline = _elements.get(outlineId);
|
||||
if (outline._selectionName == selectionName) {
|
||||
return outlineId;
|
||||
}
|
||||
|
@ -100,9 +98,6 @@ void HighlightStageConfig::setOccludedFillOpacity(float value) {
|
|||
emit dirty();
|
||||
}
|
||||
|
||||
HighlightStageSetup::HighlightStageSetup() {
|
||||
}
|
||||
|
||||
void HighlightStageSetup::configure(const Config& config) {
|
||||
// Copy the styles here but update the stage with the new styles in run to be sure everything is
|
||||
// thread safe...
|
||||
|
@ -112,8 +107,7 @@ void HighlightStageSetup::configure(const Config& config) {
|
|||
void HighlightStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage<HighlightStage>(HighlightStage::getName());
|
||||
if (!stage) {
|
||||
stage = std::make_shared<HighlightStage>();
|
||||
renderContext->_scene->resetStage(HighlightStage::getName(), stage);
|
||||
renderContext->_scene->resetStage(HighlightStage::getName(), std::make_shared<HighlightStage>());
|
||||
}
|
||||
|
||||
if (!_styles.empty()) {
|
||||
|
@ -127,4 +121,3 @@ void HighlightStageSetup::run(const render::RenderContextPointer& renderContext)
|
|||
_styles.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// Created by Olivier Prat on 07/07/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -11,56 +12,27 @@
|
|||
#ifndef hifi_render_utils_HighlightStage_h
|
||||
#define hifi_render_utils_HighlightStage_h
|
||||
|
||||
#include "Stage.h"
|
||||
#include "Engine.h"
|
||||
#include "IndexedContainer.h"
|
||||
#include "HighlightStyle.h"
|
||||
#include "Stage.h"
|
||||
|
||||
namespace render {
|
||||
|
||||
// Highlight stage to set up HighlightStyle-related effects
|
||||
class HighlightStage : public Stage {
|
||||
class Highlight {
|
||||
public:
|
||||
Highlight(const std::string& selectionName, const HighlightStyle& style) : _selectionName{ selectionName }, _style{ style } { }
|
||||
|
||||
class Highlight {
|
||||
public:
|
||||
|
||||
Highlight(const std::string& selectionName, const HighlightStyle& style) : _selectionName{ selectionName }, _style{ style } { }
|
||||
|
||||
std::string _selectionName;
|
||||
HighlightStyle _style;
|
||||
|
||||
};
|
||||
|
||||
static const std::string& getName() { return _name; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
using HighlightIdList = render::indexed_container::Indices;
|
||||
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
bool checkHighlightId(Index index) const { return _highlights.checkIndex(index); }
|
||||
|
||||
const Highlight& getHighlight(Index index) const { return _highlights.get(index); }
|
||||
Highlight& editHighlight(Index index) { return _highlights.edit(index); }
|
||||
std::string _selectionName;
|
||||
HighlightStyle _style;
|
||||
};
|
||||
|
||||
// Highlight stage to set up HighlightStyle-related effects
|
||||
class HighlightStage : public TypedStage<Highlight> {
|
||||
public:
|
||||
Index addHighlight(const std::string& selectionName, const HighlightStyle& style = HighlightStyle());
|
||||
Index getHighlightIdBySelection(const std::string& selectionName) const;
|
||||
void removeHighlight(Index index);
|
||||
|
||||
HighlightIdList::iterator begin() { return _activeHighlightIds.begin(); }
|
||||
HighlightIdList::iterator end() { return _activeHighlightIds.end(); }
|
||||
const HighlightIdList& getActiveHighlightIds() const { return _activeHighlightIds; }
|
||||
|
||||
private:
|
||||
|
||||
using Highlights = render::indexed_container::IndexedVector<Highlight>;
|
||||
|
||||
static std::string _name;
|
||||
|
||||
Highlights _highlights;
|
||||
HighlightIdList _activeHighlightIds;
|
||||
const IDList& getActiveHighlightIds() const { return _activeElementIDs; }
|
||||
};
|
||||
using HighlightStagePointer = std::shared_ptr<HighlightStage>;
|
||||
|
||||
|
@ -122,7 +94,7 @@ namespace render {
|
|||
using Config = HighlightStageConfig;
|
||||
using JobModel = render::Job::Model<HighlightStageSetup, Config>;
|
||||
|
||||
HighlightStageSetup();
|
||||
HighlightStageSetup() {}
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const RenderContextPointer& renderContext);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
namespace render {
|
||||
|
||||
// This holds the configuration for a particular outline style
|
||||
|
|
|
@ -440,7 +440,7 @@ void Scene::queryTransitionItems(const Transaction::TransitionQueries& transacti
|
|||
auto transitionId = item.getTransitionId();
|
||||
|
||||
if (!TransitionStage::isIndexInvalid(transitionId)) {
|
||||
auto& transition = transitionStage->getTransition(transitionId);
|
||||
auto& transition = transitionStage->getElement(transitionId);
|
||||
func(itemId, &transition);
|
||||
} else {
|
||||
func(itemId, nullptr);
|
||||
|
@ -477,7 +477,7 @@ void Scene::resetHighlights(const Transaction::HighlightResets& transactions) {
|
|||
if (HighlightStage::isIndexInvalid(outlineId)) {
|
||||
outlineStage->addHighlight(selectionName, newStyle);
|
||||
} else {
|
||||
outlineStage->editHighlight(outlineId)._style = newStyle;
|
||||
outlineStage->editElement(outlineId)._style = newStyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ void Scene::removeHighlights(const Transaction::HighlightRemoves& transactions)
|
|||
auto outlineId = outlineStage->getHighlightIdBySelection(selectionName);
|
||||
|
||||
if (!HighlightStage::isIndexInvalid(outlineId)) {
|
||||
outlineStage->removeHighlight(outlineId);
|
||||
outlineStage->removeElement(outlineId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ void Scene::queryHighlights(const Transaction::HighlightQueries& transactions) {
|
|||
auto outlineId = outlineStage->getHighlightIdBySelection(selectionName);
|
||||
|
||||
if (!HighlightStage::isIndexInvalid(outlineId)) {
|
||||
func(&outlineStage->editHighlight(outlineId)._style);
|
||||
func(&outlineStage->editElement(outlineId)._style);
|
||||
} else {
|
||||
func(nullptr);
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ void Scene::removeItemTransition(ItemID itemId) {
|
|||
auto& item = _items[itemId];
|
||||
TransitionStage::Index transitionId = item.getTransitionId();
|
||||
if (!render::TransitionStage::isIndexInvalid(transitionId)) {
|
||||
const auto& transition = transitionStage->getTransition(transitionId);
|
||||
const auto& transition = transitionStage->getElement(transitionId);
|
||||
const auto transitionOwner = transition.itemId;
|
||||
if (transitionOwner == itemId) {
|
||||
// No more items will be using this transition. Clean it up.
|
||||
|
@ -570,7 +570,7 @@ void Scene::removeItemTransition(ItemID itemId) {
|
|||
}
|
||||
}
|
||||
_transitionFinishedOperatorMap.erase(transitionId);
|
||||
transitionStage->removeTransition(transitionId);
|
||||
transitionStage->removeElement(transitionId);
|
||||
}
|
||||
|
||||
setItemTransition(itemId, render::TransitionStage::INVALID_INDEX);
|
||||
|
|
|
@ -4,23 +4,13 @@
|
|||
//
|
||||
// Created by Sam Gateau on 6/14/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "Stage.h"
|
||||
|
||||
|
||||
using namespace render;
|
||||
|
||||
|
||||
|
||||
Stage::~Stage() {
|
||||
|
||||
}
|
||||
|
||||
Stage::Stage() :
|
||||
_name()
|
||||
{
|
||||
}
|
||||
|
||||
const Stage::Index Stage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Sam Gateau on 6/14/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -12,27 +13,141 @@
|
|||
#ifndef hifi_render_Stage_h
|
||||
#define hifi_render_Stage_h
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#include "IndexedContainer.h"
|
||||
|
||||
namespace render {
|
||||
|
||||
using ElementIndices = std::vector<indexed_container::Index>;
|
||||
|
||||
class Stage {
|
||||
public:
|
||||
Stage() {}
|
||||
virtual ~Stage() {}
|
||||
|
||||
using Name = std::string;
|
||||
using Index = indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
using IDList = indexed_container::Indices;
|
||||
|
||||
Stage();
|
||||
virtual ~Stage();
|
||||
|
||||
protected:
|
||||
Name _name;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
};
|
||||
|
||||
using StagePointer = std::shared_ptr<Stage>;
|
||||
|
||||
using StageMap = std::map<const Stage::Name, StagePointer>;
|
||||
|
||||
template<typename T>
|
||||
class TypedStage : public Stage {
|
||||
public:
|
||||
TypedStage() {}
|
||||
virtual ~TypedStage() {}
|
||||
|
||||
static const Name& getName() { return _name; }
|
||||
|
||||
bool checkId(Index index) const { return _elements.checkIndex(index); }
|
||||
|
||||
const T& getElement(Index id) const { return _elements.get(id); }
|
||||
T& editElement(Index id) { return _elements.edit(id); }
|
||||
Index addElement(const T& element) {
|
||||
Index id = _elements.newElement(element);
|
||||
_activeElementIDs.push_back(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
void removeElement(Index index) {
|
||||
IDList::iterator idIterator = std::find(_activeElementIDs.begin(), _activeElementIDs.end(), index);
|
||||
if (idIterator != _activeElementIDs.end()) {
|
||||
_activeElementIDs.erase(idIterator);
|
||||
}
|
||||
if (!_elements.isElementFreed(index)) {
|
||||
_elements.freeElement(index);
|
||||
}
|
||||
}
|
||||
|
||||
IDList::iterator begin() { return _activeElementIDs.begin(); }
|
||||
IDList::iterator end() { return _activeElementIDs.end(); }
|
||||
protected:
|
||||
static Name _name;
|
||||
|
||||
indexed_container::IndexedVector<T> _elements;
|
||||
IDList _activeElementIDs;
|
||||
};
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
using Index = indexed_container::Index;
|
||||
|
||||
void clear() { _elements.clear(); }
|
||||
void pushElement(Index index) { _elements.emplace_back(index); }
|
||||
|
||||
ElementIndices _elements;
|
||||
};
|
||||
|
||||
template<typename T, typename P, typename F = Frame>
|
||||
class PointerStage : public Stage {
|
||||
public:
|
||||
PointerStage() {}
|
||||
virtual ~PointerStage() {}
|
||||
|
||||
static const Name& getName() { return _name; }
|
||||
|
||||
bool checkId(Index index) const { return _elements.checkIndex(index); }
|
||||
|
||||
Index getNumElements() const { return _elements.getNumElements(); }
|
||||
Index getNumFreeElements() const { return _elements.getNumFreeIndices(); }
|
||||
Index getNumAllocatedElements() const { return _elements.getNumAllocatedIndices(); }
|
||||
|
||||
P getElement(Index id) const { return _elements.get(id); }
|
||||
|
||||
Index findElement(const P& element) const {
|
||||
auto found = _elementMap.find(element);
|
||||
if (found != _elementMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Index addElement(const P& element) {
|
||||
auto found = _elementMap.find(element);
|
||||
if (found == _elementMap.end()) {
|
||||
auto id = _elements.newElement(element);
|
||||
// Avoid failing to allocate an element, just pass
|
||||
if (id != INVALID_INDEX) {
|
||||
// Insert the element and its index in the reverse map
|
||||
_elementMap[element] = id;
|
||||
}
|
||||
return id;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
virtual P removeElement(Index index) {
|
||||
P removed = _elements.freeElement(index);
|
||||
|
||||
if (removed) {
|
||||
_elementMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
using Frame = F;
|
||||
using FramePointer = std::shared_ptr<F>;
|
||||
F _currentFrame;
|
||||
|
||||
protected:
|
||||
static Name _name;
|
||||
|
||||
indexed_container::IndexedPointerVector<T> _elements;
|
||||
std::unordered_map<P, Index> _elementMap;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // hifi_render_Stage_h
|
||||
|
|
35
libraries/render/src/render/StageSetup.h
Normal file
35
libraries/render/src/render/StageSetup.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// StageSetup.h
|
||||
// render/src/render
|
||||
//
|
||||
// Created by HifiExperiments on 10/16/24
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_render_StageSetup_h
|
||||
#define hifi_render_StageSetup_h
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
namespace render {
|
||||
|
||||
template <typename T>
|
||||
class StageSetup {
|
||||
public:
|
||||
StageSetup() {}
|
||||
|
||||
void run(const RenderContextPointer& renderContext) {
|
||||
if (renderContext->_scene) {
|
||||
auto stage = renderContext->_scene->getStage(T::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(T::getName(), std::make_shared<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // hifi_render_StageSetup_h
|
|
@ -1,43 +1,25 @@
|
|||
#include "TransitionStage.h"
|
||||
//
|
||||
// TransitionStage.cpp
|
||||
//
|
||||
// Created by Olivier Prat on 07/07/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include "TransitionStage.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
std::string TransitionStage::_name("Transition");
|
||||
const TransitionStage::Index TransitionStage::INVALID_INDEX{ indexed_container::INVALID_INDEX };
|
||||
template <>
|
||||
std::string TypedStage<Transition>::_name { "TRANSITION_STAGE" };
|
||||
|
||||
TransitionStage::Index TransitionStage::addTransition(ItemID itemId, Transition::Type type, ItemID boundId) {
|
||||
Transition transition;
|
||||
Index id;
|
||||
|
||||
transition.eventType = type;
|
||||
transition.itemId = itemId;
|
||||
transition.boundItemId = boundId;
|
||||
id = _transitions.newElement(transition);
|
||||
_activeTransitionIds.push_back(id);
|
||||
|
||||
return id;
|
||||
return addElement(transition);
|
||||
}
|
||||
|
||||
void TransitionStage::removeTransition(Index index) {
|
||||
TransitionIdList::iterator idIterator = std::find(_activeTransitionIds.begin(), _activeTransitionIds.end(), index);
|
||||
if (idIterator != _activeTransitionIds.end()) {
|
||||
_activeTransitionIds.erase(idIterator);
|
||||
}
|
||||
if (!_transitions.isElementFreed(index)) {
|
||||
_transitions.freeElement(index);
|
||||
}
|
||||
}
|
||||
|
||||
TransitionStageSetup::TransitionStageSetup() {
|
||||
}
|
||||
|
||||
void TransitionStageSetup::run(const RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(TransitionStage::getName());
|
||||
if (!stage) {
|
||||
stage = std::make_shared<TransitionStage>();
|
||||
renderContext->_scene->resetStage(TransitionStage::getName(), stage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//
|
||||
// TransitionStage.h
|
||||
|
||||
//
|
||||
// Created by Olivier Prat on 07/07/2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -12,55 +13,22 @@
|
|||
#define hifi_render_TransitionStage_h
|
||||
|
||||
#include "Stage.h"
|
||||
#include "IndexedContainer.h"
|
||||
#include "Engine.h"
|
||||
#include "StageSetup.h"
|
||||
#include "Transition.h"
|
||||
|
||||
namespace render {
|
||||
|
||||
// Transition stage to set up Transition-related effects
|
||||
class TransitionStage : public render::Stage {
|
||||
class TransitionStage : public TypedStage<Transition> {
|
||||
public:
|
||||
|
||||
static const std::string& getName() { return _name; }
|
||||
|
||||
using Index = indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
using TransitionIdList = indexed_container::Indices;
|
||||
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
bool isTransitionUsed(Index index) const { return _transitions.checkIndex(index) && !_transitions.isElementFreed(index); }
|
||||
|
||||
const Transition& getTransition(Index TransitionId) const { return _transitions.get(TransitionId); }
|
||||
|
||||
Transition& editTransition(Index TransitionId) { return _transitions.edit(TransitionId); }
|
||||
|
||||
bool isTransitionUsed(Index index) const { return _elements.checkIndex(index) && !_elements.isElementFreed(index); }
|
||||
Index addTransition(ItemID itemId, Transition::Type type, ItemID boundId);
|
||||
void removeTransition(Index index);
|
||||
|
||||
TransitionIdList::iterator begin() { return _activeTransitionIds.begin(); }
|
||||
TransitionIdList::iterator end() { return _activeTransitionIds.end(); }
|
||||
|
||||
private:
|
||||
|
||||
using Transitions = indexed_container::IndexedVector<Transition>;
|
||||
|
||||
static std::string _name;
|
||||
|
||||
Transitions _transitions;
|
||||
TransitionIdList _activeTransitionIds;
|
||||
};
|
||||
using TransitionStagePointer = std::shared_ptr<TransitionStage>;
|
||||
|
||||
class TransitionStageSetup {
|
||||
class TransitionStageSetup : public StageSetup<TransitionStage> {
|
||||
public:
|
||||
using JobModel = render::Job::Model<TransitionStageSetup>;
|
||||
|
||||
TransitionStageSetup();
|
||||
void run(const RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
using JobModel = Job::Model<TransitionStageSetup>;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -381,6 +381,7 @@ ScriptManager::~ScriptManager() {
|
|||
if (_type == ScriptManager::Type::ENTITY_CLIENT) {
|
||||
printf("ScriptManager::~ScriptManager");
|
||||
}
|
||||
_isDeleted = true;
|
||||
}
|
||||
|
||||
void ScriptManager::disconnectNonEssentialSignals() {
|
||||
|
@ -426,7 +427,10 @@ void ScriptManager::runInThread() {
|
|||
|
||||
void ScriptManager::executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type ) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "executeOnScriptThread", type, Q_ARG(std::function<void()>, function));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->executeOnScriptThread(function, type);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -858,10 +862,10 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri
|
|||
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||
"entityID:" << entityID << " eventName:" << eventName;
|
||||
#endif
|
||||
QMetaObject::invokeMethod(this, "removeEventHandler",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, eventName),
|
||||
Q_ARG(const ScriptValue&, handler));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->removeEventHandler(entityID, eventName, handler);
|
||||
});
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -905,10 +909,10 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString&
|
|||
"entityID:" << entityID << " eventName:" << eventName;
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "addEventHandler",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, eventName),
|
||||
Q_ARG(const ScriptValue&, handler));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->addEventHandler(entityID, eventName, handler);
|
||||
});
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -1167,7 +1171,10 @@ void ScriptManager::stop(bool marshal) {
|
|||
_isStopping = true; // this can be done on any thread
|
||||
|
||||
if (marshal) {
|
||||
QMetaObject::invokeMethod(this, "stop");
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero if this gets called from different thread
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->stop(false);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2011,11 +2018,10 @@ bool ScriptManager::hasEntityScriptDetails(const EntityItemID& entityID) const {
|
|||
|
||||
void ScriptManager::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "loadEntityScript",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, entityScript),
|
||||
Q_ARG(bool, forceRedownload)
|
||||
);
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->loadEntityScript(entityID, entityScript, forceRedownload);
|
||||
});
|
||||
return;
|
||||
}
|
||||
PROFILE_RANGE(script, __FUNCTION__);
|
||||
|
@ -2092,13 +2098,10 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
|
|||
<< contents << "isURL:" << isURL << "success:" << success;
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "entityScriptContentAvailable",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, scriptOrURL),
|
||||
Q_ARG(const QString&, contents),
|
||||
Q_ARG(bool, isURL),
|
||||
Q_ARG(bool, success),
|
||||
Q_ARG(const QString&, status));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success, status);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2442,9 +2445,10 @@ void ScriptManager::unloadEntityScript(const EntityItemID& entityID, bool should
|
|||
"entityID:" << entityID;
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "unloadEntityScript",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(bool, shouldRemoveFromMap));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->unloadEntityScript(entityID, shouldRemoveFromMap);
|
||||
});
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -2494,9 +2498,10 @@ void ScriptManager::unloadAllEntityScripts(bool blockingCall) {
|
|||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::unloadAllEntityScripts() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]";
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "unloadAllEntityScripts",
|
||||
blockingCall ? Qt::BlockingQueuedConnection : Qt::QueuedConnection);
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()] {
|
||||
manager->unloadAllEntityScripts(blockingCall);
|
||||
}, blockingCall ? Qt::BlockingQueuedConnection : Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -2589,12 +2594,10 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q
|
|||
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||
"entityID:" << entityID << "methodName:" << methodName;
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, methodName),
|
||||
Q_ARG(const QStringList&, params),
|
||||
Q_ARG(const QUuid&, remoteCallerID));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->callEntityScriptMethod(entityID, methodName, params, remoteCallerID);
|
||||
});
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -2659,10 +2662,10 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q
|
|||
"entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, methodName),
|
||||
Q_ARG(const PointerEvent&, event));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->callEntityScriptMethod(entityID, methodName, event);
|
||||
});
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -2698,11 +2701,10 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q
|
|||
"entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
|
||||
#endif
|
||||
|
||||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, methodName),
|
||||
Q_ARG(const EntityItemID&, otherID),
|
||||
Q_ARG(const Collision&, collision));
|
||||
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||
manager->callEntityScriptMethod(entityID, methodName, otherID, collision);
|
||||
});
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
|
|
@ -280,9 +280,6 @@ public:
|
|||
*/
|
||||
class ScriptManager : public QObject, public EntitiesScriptEngineProvider, public std::enable_shared_from_this<ScriptManager> {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString context READ getContext)
|
||||
Q_PROPERTY(QString type READ getTypeAsString)
|
||||
Q_PROPERTY(QString fileName MEMBER _fileNameString CONSTANT)
|
||||
public:
|
||||
static const QString SCRIPT_EXCEPTION_FORMAT;
|
||||
static const QString SCRIPT_BACKTRACE_SEP;
|
||||
|
@ -381,8 +378,11 @@ public:
|
|||
Q_ENUM(Type);
|
||||
|
||||
static int processLevelMaxRetries;
|
||||
ScriptManager(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine"));
|
||||
~ScriptManager();
|
||||
private:
|
||||
// Constructor is private so that only properly generated shared pointer can be used
|
||||
explicit ScriptManager(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine"));
|
||||
public:
|
||||
~ScriptManager() override;
|
||||
|
||||
// static initialization support
|
||||
typedef void (*ScriptManagerInitializer)(ScriptManager*);
|
||||
|
@ -390,7 +390,7 @@ public:
|
|||
public:
|
||||
ScriptManagerInitializer init;
|
||||
StaticInitializerNode* prev;
|
||||
inline StaticInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticInitializer(this); }
|
||||
inline explicit StaticInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticInitializer(this); }
|
||||
};
|
||||
static void registerNewStaticInitializer(StaticInitializerNode* dest);
|
||||
|
||||
|
@ -398,7 +398,7 @@ public:
|
|||
public:
|
||||
ScriptManagerInitializer init;
|
||||
StaticTypesInitializerNode* prev;
|
||||
inline StaticTypesInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticTypesInitializer(this); }
|
||||
inline explicit StaticTypesInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticTypesInitializer(this); }
|
||||
};
|
||||
static void registerNewStaticTypesInitializer(StaticTypesInitializerNode* dest);
|
||||
|
||||
|
@ -1668,6 +1668,7 @@ protected:
|
|||
friend ScriptManagerPointer newScriptManager(Context context, const QString& scriptContents, const QString& fileNameString);
|
||||
friend class ScriptManagerScriptingInterface;
|
||||
|
||||
std::atomic<bool> _isDeleted {false}; // This is used for debugging use-after-delete. It happens quite often, so I'm keeping it here for now.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,6 +58,9 @@ public:
|
|||
|
||||
class ScriptManagerScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString context READ getContext)
|
||||
Q_PROPERTY(QString type READ getTypeAsString)
|
||||
Q_PROPERTY(QString fileName READ getAbsoluteFilename CONSTANT)
|
||||
public:
|
||||
ScriptManagerScriptingInterface(ScriptManager *parent);
|
||||
|
||||
|
@ -96,6 +99,26 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE QString getContext() const { return _manager->getContext(); }
|
||||
|
||||
/*@jsdoc
|
||||
* Gets the type of script that is running: Interface, avatar, client entity, server entity, or assignment client.
|
||||
* @function Script.getTypeAsString
|
||||
* @returns {string} The type of script that is running:
|
||||
* <ul>
|
||||
* <li><code>"client"</code>: An Interface script.</li>
|
||||
* <li><code>"entity_client"</code>: A client entity script.</li>
|
||||
* <li><code>"avatar"</code>: An avatar script.</li>
|
||||
* <li><code>"entity_server"</code>: A server entity script.</li>
|
||||
* <li><code>"agent"</code>: An assignment client script.</li>
|
||||
* </ul>
|
||||
*/
|
||||
Q_INVOKABLE QString getTypeAsString() const { return _manager->getTypeAsString(); }
|
||||
|
||||
/*@jsdoc
|
||||
* Gets the filename of the script file.
|
||||
* @function Script.getAbsoluteFilename
|
||||
* @returns {string} The filename of the script file.
|
||||
*/
|
||||
Q_INVOKABLE QString getAbsoluteFilename() const { return _manager->getAbsoluteFilename(); }
|
||||
|
||||
/*@jsdoc
|
||||
* Checks whether the script is running as an Interface or avatar script.
|
||||
|
|
18
libraries/script-engine/src/v8/ScriptEngineDebugFlags.h
Normal file
18
libraries/script-engine/src/v8/ScriptEngineDebugFlags.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// ScriptEngineDebugFlags.h
|
||||
// libraries/script-engine/src/v8/ScriptEngineDebugFlags.h
|
||||
//
|
||||
// Created by dr Karol Suprynowicz on 2024/11/14.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#ifndef overte_ScriptEngineDebugFlags_h
|
||||
#define overte_ScriptEngineDebugFlags_h
|
||||
|
||||
#define OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||
|
||||
#endif
|
|
@ -258,6 +258,13 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager),
|
|||
}
|
||||
|
||||
ScriptEngineV8::~ScriptEngineV8() {
|
||||
// Process remaining events to avoid problems with `deleteLater` calling destructor of script proxies after script engine has been deleted:
|
||||
{
|
||||
QEventLoop loop;
|
||||
loop.processEvents();
|
||||
}
|
||||
// This is necessary for script engines that don't run in ScriptManager::run(), for example entity scripts:
|
||||
disconnectSignalProxies();
|
||||
deleteUnusedValueWrappers();
|
||||
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||
_wasDestroyed = true;
|
||||
|
@ -272,14 +279,14 @@ void ScriptEngineV8::perManagerLoopIterationCleanup() {
|
|||
void ScriptEngineV8::disconnectSignalProxies() {
|
||||
_signalProxySetLock.lockForRead();
|
||||
while (!_signalProxySet.empty()) {
|
||||
auto proxy = *_signalProxySet.begin();
|
||||
_signalProxySetLock.unlock();
|
||||
delete *_signalProxySet.begin();
|
||||
delete proxy;
|
||||
_signalProxySetLock.lockForRead();
|
||||
}
|
||||
_signalProxySetLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
void ScriptEngineV8::deleteUnusedValueWrappers() {
|
||||
while (!_scriptValueWrappersToDelete.empty()) {
|
||||
auto wrapper = _scriptValueWrappersToDelete.dequeue();
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
|
||||
#include "ScriptEngineDebugFlags.h"
|
||||
#include "../ScriptEngine.h"
|
||||
#include "../ScriptManager.h"
|
||||
#include "../ScriptException.h"
|
||||
|
@ -58,8 +59,6 @@ using ScriptContextV8Pointer = std::shared_ptr<ScriptContextV8Wrapper>;
|
|||
|
||||
const double GARBAGE_COLLECTION_TIME_LIMIT_S = 1.0;
|
||||
|
||||
#define OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||
|
||||
Q_DECLARE_METATYPE(ScriptEngine::FunctionSignature)
|
||||
|
||||
/// [V8] Implements ScriptEngine for V8 and translates calls for QScriptEngine
|
||||
|
|
|
@ -1217,7 +1217,9 @@ ScriptSignalV8Proxy::~ScriptSignalV8Proxy() {
|
|||
_objectLifetime.Reset();
|
||||
_v8Context.Reset();
|
||||
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||
Q_ASSERT(!_wasDeleted);
|
||||
Q_ASSERT(!_engine->_wasDestroyed);
|
||||
_wasDeleted = true;
|
||||
#endif
|
||||
_engine->_signalProxySetLock.lockForWrite();
|
||||
_engine->_signalProxySet.remove(this);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "ScriptEngineDebugFlags.h"
|
||||
#include "../ScriptEngine.h"
|
||||
#include "../Scriptable.h"
|
||||
#include "ScriptEngineV8.h"
|
||||
|
@ -295,6 +296,9 @@ private: // storage
|
|||
// Call counter for debugging purposes. It can be used to determine which signals are overwhelming script engine.
|
||||
int _callCounter{0};
|
||||
float _totalCallTime_s{ 0.0 };
|
||||
#ifdef OVERTE_SCRIPT_USE_AFTER_DELETE_GUARD
|
||||
std::atomic<bool> _wasDeleted{false};
|
||||
#endif
|
||||
|
||||
Q_DISABLE_COPY(ScriptSignalV8Proxy)
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
var settings = {
|
||||
external_window: false,
|
||||
maximum_messages: 200,
|
||||
join_notification: true
|
||||
};
|
||||
|
||||
// Global vars
|
||||
|
@ -97,24 +98,31 @@
|
|||
if (channel !== "chat") return;
|
||||
message = JSON.parse(message);
|
||||
|
||||
// Get the message data
|
||||
const currentTimestamp = _getTimestamp();
|
||||
const timeArray = _formatTimestamp(currentTimestamp);
|
||||
|
||||
if (!message.channel) message.channel = "domain"; // We don't know where to put this message. Assume it is a domain wide message.
|
||||
if (message.forApp) return; // Floofchat
|
||||
|
||||
// Floofchat compatibility hook
|
||||
message = floofChatCompatibilityConversion(message);
|
||||
message.channel = message.channel.toLowerCase(); // Make sure the "local", "domain", etc. is formatted consistently
|
||||
message.channel = message.channel.toLowerCase();
|
||||
|
||||
if (!channels.includes(message.channel)) return; // Check the channel
|
||||
if (
|
||||
message.channel == "local" &&
|
||||
Vec3.distance(MyAvatar.position, message.position) >
|
||||
maxLocalDistance
|
||||
)
|
||||
return; // If message is local, and if player is too far away from location, don't do anything
|
||||
// Check the channel. If the channel is not one we have, do nothing.
|
||||
if (!channels.includes(message.channel)) return;
|
||||
|
||||
// If message is local, and if player is too far away from location, do nothing.
|
||||
if (message.channel == "local" && isTooFar(message.position)) return;
|
||||
|
||||
// Format the timestamp
|
||||
message.timeString = timeArray[0];
|
||||
message.dateString = timeArray[1];
|
||||
|
||||
// Update qml view of to new message
|
||||
_emitEvent({ type: "show_message", ...message });
|
||||
|
||||
// Show new message on screen
|
||||
Messages.sendLocalMessage(
|
||||
"Floof-Notif",
|
||||
JSON.stringify({
|
||||
|
@ -125,20 +133,25 @@
|
|||
|
||||
// Save message to history
|
||||
let savedMessage = message;
|
||||
|
||||
// Remove unnecessary data.
|
||||
delete savedMessage.position;
|
||||
savedMessage.timeString = new Date().toLocaleTimeString(undefined, {
|
||||
hour12: false,
|
||||
});
|
||||
savedMessage.dateString = new Date().toLocaleDateString(undefined, {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
delete savedMessage.timeString;
|
||||
delete savedMessage.dateString;
|
||||
delete savedMessage.action;
|
||||
|
||||
savedMessage.timestamp = currentTimestamp;
|
||||
|
||||
messageHistory.push(savedMessage);
|
||||
while (messageHistory.length > settings.maximum_messages) {
|
||||
messageHistory.shift();
|
||||
}
|
||||
Settings.setValue("ArmoredChat-Messages", messageHistory);
|
||||
|
||||
// Check to see if the message is close enough to the user
|
||||
function isTooFar(messagePosition) {
|
||||
return Vec3.distance(MyAvatar.position, messagePosition) > maxLocalDistance;
|
||||
}
|
||||
}
|
||||
function fromQML(event) {
|
||||
switch (event.type) {
|
||||
|
@ -146,25 +159,25 @@
|
|||
_sendMessage(event.message, event.channel);
|
||||
break;
|
||||
case "setting_change":
|
||||
// Set the setting value, and save the config
|
||||
settings[event.setting] = event.value; // Update local settings
|
||||
_saveSettings(); // Save local settings
|
||||
|
||||
// Extra actions to preform.
|
||||
switch (event.setting) {
|
||||
case "external_window":
|
||||
chatOverlayWindow.presentationMode = event.value
|
||||
? Desktop.PresentationMode.NATIVE
|
||||
: Desktop.PresentationMode.VIRTUAL;
|
||||
break;
|
||||
case "maximum_messages":
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case "action":
|
||||
switch (event.action) {
|
||||
case "erase_history":
|
||||
Settings.setValue("ArmoredChat-Messages", []);
|
||||
Settings.setValue("ArmoredChat-Messages", null);
|
||||
messageHistory = [];
|
||||
_emitEvent({
|
||||
type: "clear_messages",
|
||||
});
|
||||
|
@ -213,9 +226,7 @@
|
|||
|
||||
// Get the display name of the user
|
||||
let displayName = "";
|
||||
displayName =
|
||||
AvatarManager.getPalData([sessionId])?.data[0]
|
||||
?.sessionDisplayName || null;
|
||||
displayName = AvatarManager.getPalData([sessionId])?.data[0]?.sessionDisplayName || null;
|
||||
if (displayName == null) {
|
||||
for (let i = 0; i < palData.length; i++) {
|
||||
if (palData[i].sessionUUID == sessionId) {
|
||||
|
@ -226,8 +237,22 @@
|
|||
|
||||
// Format the packet
|
||||
let message = {};
|
||||
const timeArray = _formatTimestamp(_getTimestamp());
|
||||
message.timeString = timeArray[0];
|
||||
message.dateString = timeArray[1];
|
||||
message.message = `${displayName} ${type}`;
|
||||
|
||||
// Show new message on screen
|
||||
if (settings.join_notification){
|
||||
Messages.sendLocalMessage(
|
||||
"Floof-Notif",
|
||||
JSON.stringify({
|
||||
sender: displayName,
|
||||
text: type,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
_emitEvent({ type: "notification", ...message });
|
||||
}, 1500);
|
||||
}
|
||||
|
@ -237,7 +262,9 @@
|
|||
if (messageHistory) {
|
||||
// Load message history
|
||||
messageHistory.forEach((message) => {
|
||||
delete message.action;
|
||||
const timeArray = _formatTimestamp(_getTimestamp());
|
||||
message.timeString = timeArray[0];
|
||||
message.dateString = timeArray[1];
|
||||
_emitEvent({ type: "show_message", ...message });
|
||||
});
|
||||
}
|
||||
|
@ -249,6 +276,24 @@
|
|||
console.log("Saving config");
|
||||
Settings.setValue("ArmoredChat-Config", settings);
|
||||
}
|
||||
function _getTimestamp(){
|
||||
return Date.now();
|
||||
}
|
||||
function _formatTimestamp(timestamp){
|
||||
let timeArray = [];
|
||||
|
||||
timeArray.push(new Date().toLocaleTimeString(undefined, {
|
||||
hour12: false,
|
||||
}));
|
||||
|
||||
timeArray.push(new Date(timestamp).toLocaleDateString(undefined, {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
}));
|
||||
|
||||
return timeArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a packet to the HTML front end. Easy communication!
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.3
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
|
||||
|
@ -30,7 +30,7 @@ Rectangle {
|
|||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
scrollToBottom();
|
||||
scrollToBottom(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,49 +145,60 @@ Rectangle {
|
|||
anchors.top: navigation_bar.bottom
|
||||
visible: ["local", "domain"].includes(pageVal) ? true : false
|
||||
|
||||
|
||||
// Chat Message History
|
||||
ListView {
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: parent.height - 40
|
||||
contentWidth: parent.width
|
||||
contentHeight: listview.height
|
||||
clip: true
|
||||
interactive: true
|
||||
spacing: 5
|
||||
id: listview
|
||||
id: messageViewFlickable
|
||||
|
||||
delegate: Loader {
|
||||
property int delegateIndex: index
|
||||
property string delegateText: model.text
|
||||
property string delegateUsername: model.username
|
||||
property string delegateDate: model.date
|
||||
width: listview.width
|
||||
ColumnLayout {
|
||||
id: listview
|
||||
Layout.fillWidth: true
|
||||
|
||||
sourceComponent: {
|
||||
if (model.type === "chat") {
|
||||
return template_chat_message;
|
||||
} else if (model.type === "notification") {
|
||||
return template_notification;
|
||||
Repeater {
|
||||
model: getChannel(pageVal)
|
||||
delegate: Loader {
|
||||
property int delegateIndex: model.index
|
||||
property string delegateText: model.text
|
||||
property string delegateUsername: model.username
|
||||
property string delegateDate: model.date
|
||||
|
||||
sourceComponent: {
|
||||
if (model.type === "chat") {
|
||||
return template_chat_message;
|
||||
} else if (model.type === "notification") {
|
||||
return template_notification;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
id: chat_scrollbar
|
||||
height: 100
|
||||
size: 0.05
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
size: 100
|
||||
minimumSize: 0.1
|
||||
}
|
||||
|
||||
model: getChannel(pageVal)
|
||||
|
||||
rebound: Transition {
|
||||
NumberAnimation {
|
||||
properties: "x,y"
|
||||
duration: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ListModel {
|
||||
id: local
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: domain
|
||||
}
|
||||
}
|
||||
|
||||
// Chat Entry
|
||||
Rectangle {
|
||||
|
@ -205,6 +216,8 @@ Rectangle {
|
|||
height: parent.height
|
||||
placeholderText: pageVal.charAt(0).toUpperCase() + pageVal.slice(1) + " chat message..."
|
||||
clip: false
|
||||
font.italic: text == ""
|
||||
|
||||
Keys.onPressed: {
|
||||
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && !(event.modifiers & Qt.ShiftModifier)) {
|
||||
event.accepted = true;
|
||||
|
@ -335,6 +348,31 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Join notification
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 40
|
||||
color: "transparent"
|
||||
|
||||
Text{
|
||||
text: "Join notification"
|
||||
color: "white"
|
||||
font.pointSize: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
CheckBox{
|
||||
id: s_join_notification
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
onCheckedChanged: {
|
||||
toScript({type: 'setting_change', setting: 'join_notification', value: checked})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,7 +382,7 @@ Rectangle {
|
|||
Component {
|
||||
id: template_chat_message
|
||||
|
||||
Rectangle{
|
||||
Rectangle {
|
||||
property int index: delegateIndex
|
||||
property string texttest: delegateText
|
||||
property string username: delegateUsername
|
||||
|
@ -352,6 +390,8 @@ Rectangle {
|
|||
|
||||
height: Math.max(65, children[1].height + 30)
|
||||
color: index % 2 === 0 ? "transparent" : Qt.rgba(0.15,0.15,0.15,1)
|
||||
width: listview.parent.parent.width
|
||||
Layout.fillWidth: true
|
||||
|
||||
Item {
|
||||
width: parent.width - 10
|
||||
|
@ -370,7 +410,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
TextEdit{
|
||||
TextEdit {
|
||||
anchors.top: parent.children[0].bottom
|
||||
x: 5
|
||||
text: texttest
|
||||
|
@ -451,16 +491,25 @@ Rectangle {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
property var channels: {
|
||||
"local": local,
|
||||
"domain": domain,
|
||||
}
|
||||
|
||||
function scrollToBottom() {
|
||||
if (listview.count == 0) return;
|
||||
listview.positionViewAtEnd();
|
||||
function scrollToBottom(bypassDistanceCheck = false, extraMoveDistance = 0) {
|
||||
const totalHeight = listview.height; // Total height of the content
|
||||
const currentPosition = messageViewFlickable.contentY; // Current position of the view
|
||||
const windowHeight = listview.parent.parent.height; // Total height of the window
|
||||
const bottomPosition = currentPosition + windowHeight;
|
||||
|
||||
// Check if the view is within 300 units from the bottom
|
||||
const closeEnoughToBottom = totalHeight - bottomPosition <= 300;
|
||||
if (!bypassDistanceCheck && !closeEnoughToBottom) return;
|
||||
if (totalHeight < windowHeight) return; // No reason to scroll, we don't have an overflow.
|
||||
if (bottomPosition == totalHeight) return; // At the bottom, do nothing.
|
||||
|
||||
messageViewFlickable.contentY = listview.height - listview.parent.parent.height;
|
||||
messageViewFlickable.returnToBounds();
|
||||
}
|
||||
|
||||
|
||||
|
@ -469,13 +518,13 @@ Rectangle {
|
|||
|
||||
// Format content
|
||||
message = formatContent(message);
|
||||
|
||||
message = embedImages(message);
|
||||
|
||||
if (type === "notification"){
|
||||
channel.append({ text: message, date: date, type: "notification" });
|
||||
last_message_user = "";
|
||||
scrollToBottom();
|
||||
scrollToBottom(null, 30);
|
||||
|
||||
last_message_time = new Date();
|
||||
return;
|
||||
}
|
||||
|
@ -487,22 +536,18 @@ Rectangle {
|
|||
var last_item_index = channel.count - 1;
|
||||
var last_item = channel.get(last_item_index);
|
||||
|
||||
// FIXME: When adding a new message this would check to see if we could append the incoming message
|
||||
// to the bottom of the last message. This current implimentation causes issues with scrollToBottom()
|
||||
// Specifically, scrolling to the bottom does not like image embeds.
|
||||
// This needs to be reworked entirely before it can be reimplimented
|
||||
// if (last_message_user === username && elapsed_minutes < 1 && last_item){
|
||||
// message = "<br>" + message
|
||||
// last_item.text = last_item.text += "\n" + message;
|
||||
// scrollToBottom()
|
||||
// last_message_time = new Date();
|
||||
// return;
|
||||
// }
|
||||
if (last_message_user === username && elapsed_minutes < 1 && last_item){
|
||||
message = "<br>" + message
|
||||
last_item.text = last_item.text += "\n" + message;
|
||||
load_scroll_timer.running = true;
|
||||
last_message_time = new Date();
|
||||
return;
|
||||
}
|
||||
|
||||
last_message_user = username;
|
||||
last_message_time = new Date();
|
||||
channel.append({ text: message, username: username, date: date, type: type });
|
||||
scrollToBottom();
|
||||
load_scroll_timer.running = true;
|
||||
}
|
||||
|
||||
function getChannel(id) {
|
||||
|
@ -542,15 +587,13 @@ Rectangle {
|
|||
|
||||
// Messages from script
|
||||
function fromScript(message) {
|
||||
let time = new Date().toLocaleTimeString(undefined, { hour12: false });
|
||||
let date = new Date().toLocaleDateString(undefined, { year: "numeric", month: "long", day: "numeric", });
|
||||
|
||||
switch (message.type){
|
||||
case "show_message":
|
||||
addMessage(message.displayName, message.message, `[ ${message.timeString || time} - ${message.dateString || date} ]`, message.channel, "chat");
|
||||
addMessage(message.displayName, message.message, `[ ${message.timeString} - ${message.dateString} ]`, message.channel, "chat");
|
||||
break;
|
||||
case "notification":
|
||||
addMessage("SYSTEM", message.message, `[ ${time} - ${date} ]`, "domain", "notification");
|
||||
addMessage("SYSTEM", message.message, `[ ${message.timeString} - ${message.dateString} ]`, "domain", "notification");
|
||||
break;
|
||||
case "clear_messages":
|
||||
local.clear();
|
||||
|
@ -559,6 +602,7 @@ Rectangle {
|
|||
case "initial_settings":
|
||||
if (message.settings.external_window) s_external_window.checked = true;
|
||||
if (message.settings.maximum_messages) s_maximum_messages.value = message.settings.maximum_messages;
|
||||
if (message.settings.join_notification) s_join_notification.checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
Rectangle {
|
||||
Item {
|
||||
id: root
|
||||
property var window
|
||||
|
||||
|
@ -21,15 +21,22 @@ Rectangle {
|
|||
z: 99
|
||||
visible: false
|
||||
|
||||
TextArea {
|
||||
id: textArea
|
||||
x: 0
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
text:""
|
||||
textColor: "#ffffff"
|
||||
color: Qt.rgba(0.95,0.95,0.95,1)
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: textArea
|
||||
x: 5
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
text: ""
|
||||
color: "#000"
|
||||
clip: false
|
||||
font.pointSize: 18
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
Keys.onReturnPressed: { _onEnterPressed(); }
|
||||
Keys.onEnterPressed: { _onEnterPressed(); }
|
||||
|
@ -52,33 +59,36 @@ Rectangle {
|
|||
text: "Local message..."
|
||||
font.pointSize: 16
|
||||
color: "gray"
|
||||
x: 0
|
||||
x: 5
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: textArea.text == ""
|
||||
font.italic: true
|
||||
}
|
||||
|
||||
Button {
|
||||
Rectangle {
|
||||
id: button
|
||||
x: parent.width - width
|
||||
y: 0
|
||||
width: 64
|
||||
height: parent.height
|
||||
clip: false
|
||||
visible: true
|
||||
|
||||
color: "#262626"
|
||||
|
||||
Image {
|
||||
id: image
|
||||
width: 30
|
||||
height: 30
|
||||
fillMode: Image.PreserveAspectFit
|
||||
visible: true
|
||||
anchors.centerIn: parent
|
||||
source: "./img/ui/send_white.png"
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
_onEnterPressed();
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
_onEnterPressed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,12 @@ var DEFAULT_OFFSET = 10;
|
|||
var FLOOF_NOTIFICATION_CHANNEL = "Floof-Notif";
|
||||
var MAIN_CHAT_APP_CHANNEL = "Chat";
|
||||
var ARROW_REGEX = /\</gi;
|
||||
|
||||
var notificationSound = SoundCache.getSound(Script.resolvePath("resources/click.wav"));
|
||||
var soundInjectorOptions = {
|
||||
localOnly: true,
|
||||
position: MyAvatar.position,
|
||||
volume: 0.04
|
||||
};
|
||||
|
||||
var offset = DEFAULT_OFFSET;
|
||||
|
||||
|
@ -48,6 +53,7 @@ function messageReceived(channel, message, sender, local) {
|
|||
}
|
||||
} else {
|
||||
notificationCore.add(cmd.text, cmd.sender, cmd.colour);
|
||||
playSound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +119,10 @@ function cleanUp() {
|
|||
});
|
||||
}
|
||||
|
||||
function playSound() {
|
||||
Audio.playSound(notificationSound, soundInjectorOptions);
|
||||
}
|
||||
|
||||
function notif(text, colour) {
|
||||
|
||||
var noti = {
|
||||
|
|
BIN
scripts/communityScripts/notificationCore/resources/click.wav
Normal file
BIN
scripts/communityScripts/notificationCore/resources/click.wav
Normal file
Binary file not shown.
|
@ -2,7 +2,7 @@
|
|||
// NewSoundDialog.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by HifiExperiments on 4/7/24
|
||||
// Created by HifiExperiments on April 7th, 2024
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -53,17 +53,32 @@ Rectangle {
|
|||
|
||||
Text {
|
||||
id: text1
|
||||
text: qsTr("Sound URL")
|
||||
text: qsTr("Sound URL <i></i> ")
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
Button {
|
||||
id: pasteBtn
|
||||
text: "Paste"
|
||||
font.pixelSize: 11
|
||||
height: 16
|
||||
width: 40
|
||||
radius: 4
|
||||
anchors.top: text1.top
|
||||
anchors.left: text1.right
|
||||
anchors.bottom: text1.bottom
|
||||
onClicked: {
|
||||
soundURL.paste()
|
||||
}
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: soundURL
|
||||
height: 20
|
||||
text: qsTr("")
|
||||
color: "white"
|
||||
anchors.top: text1.bottom
|
||||
anchors.top: pasteBtn.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
//
|
||||
// graphicsSettings.js
|
||||
//
|
||||
// Created by Kalila L. on 8/5/2020
|
||||
// Created by Kalila L. on August 5th, 2020
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
||||
var channelComm = "Overte-ShowGraphicsIconChanged";
|
||||
var appStatus = false;
|
||||
var GRAPHICS_HIDE_AND_SHOW_SETTING_KEY = "showGraphicsIcon";
|
||||
var GRAPHICS_HIDE_AND_SHOW_DEFAULT_VALUE = true;
|
||||
|
||||
var AppUi = Script.require('appUi');
|
||||
|
||||
// cellphone-cog MDI
|
||||
|
@ -49,22 +54,49 @@
|
|||
}
|
||||
|
||||
function startup() {
|
||||
ui = new AppUi({
|
||||
buttonName: BUTTON_NAME,
|
||||
sortOrder: 8,
|
||||
normalButton: getIcon(),
|
||||
activeButton: getIcon().replace('white', 'black'),
|
||||
home: GRAPHICS_QML_SOURCE
|
||||
});
|
||||
if (!appStatus) {
|
||||
ui = new AppUi({
|
||||
buttonName: BUTTON_NAME,
|
||||
sortOrder: 8,
|
||||
normalButton: getIcon(),
|
||||
activeButton: getIcon().replace('white', 'black'),
|
||||
home: GRAPHICS_QML_SOURCE
|
||||
});
|
||||
}
|
||||
appStatus = true;
|
||||
}
|
||||
|
||||
function shutdown() {
|
||||
if (appStatus) {
|
||||
ui.onScriptEnding();
|
||||
appStatus = false;
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
Messages.messageReceived.disconnect(onMessageReceived);
|
||||
Messages.unsubscribe(channelComm);
|
||||
}
|
||||
|
||||
function onMessageReceived(channel, message, sender, localOnly) {
|
||||
if (channel === channelComm && localOnly) {
|
||||
if (Settings.getValue(GRAPHICS_HIDE_AND_SHOW_SETTING_KEY, GRAPHICS_HIDE_AND_SHOW_DEFAULT_VALUE)) {
|
||||
startup();
|
||||
} else {
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Run the functions.
|
||||
//
|
||||
startup();
|
||||
Script.scriptEnding.connect(shutdown);
|
||||
if (Settings.getValue(GRAPHICS_HIDE_AND_SHOW_SETTING_KEY, GRAPHICS_HIDE_AND_SHOW_DEFAULT_VALUE)) {
|
||||
startup();
|
||||
}
|
||||
Messages.subscribe(channelComm);
|
||||
Messages.messageReceived.connect(onMessageReceived);
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
|
@ -56,7 +56,7 @@ const menuNotificationIcon = path.join(__dirname, '../resources/tray-menu-notifi
|
|||
const DELETE_LOG_FILES_OLDER_THAN_X_SECONDS = 60 * 60 * 24 * 7; // 7 Days
|
||||
const LOG_FILE_REGEX = /(domain-server|ac-monitor|ac)-.*-std(out|err).txt/;
|
||||
|
||||
const HOME_CONTENT_URL = "http://cdn-1.vircadia.com/us-e-1/DomainContent/Sandbox/Rearranged_Basic_Sandbox.tar.gz";
|
||||
const HOME_CONTENT_URL = "https://content.overte.org/DomainContent/Sandbox/Rearranged_Basic_Sandbox.tar.gz";
|
||||
|
||||
const buildInfo = GetBuildInfo();
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Copyright 2022-2023 Overte e.V.
|
||||
# Copyright 2022-2024 Overte e.V.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Docker file for building Overte
|
||||
# Example build: docker build -t overte/overte-full-build:0.1.1-ubuntu-20.04 -f Dockerfile_build_ubuntu-20.04 .
|
||||
# Example build: docker build -t overte/overte-full-build:0.1.2-ubuntu-20.04 -f Dockerfile_build_ubuntu-20.04 .
|
||||
FROM ubuntu:20.04
|
||||
LABEL maintainer="Julian Groß (julian.gro@overte.org)"
|
||||
LABEL description="Development image for full Overte builds"
|
||||
|
@ -18,6 +18,8 @@ RUN apt-get update && apt-get -y install tzdata
|
|||
RUN apt-get -y install curl ninja-build git cmake g++ libssl-dev python3-distutils python3-distro mesa-common-dev libgl1-mesa-dev libsystemd-dev
|
||||
# Install server-console build dependencies
|
||||
RUN apt-get -y install npm
|
||||
# Install Interface dependencies
|
||||
RUN apt-get -y install pkg-config libxext-dev libdouble-conversion-dev libpcre2-16-0 libpulse0 libharfbuzz-dev libnss3 libnspr4 libxdamage1 libasound2 vulkan-validationlayers libvulkan-dev libvulkan1
|
||||
|
||||
# Install tools for package creation
|
||||
RUN apt-get -y install sudo chrpath binutils dh-make
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Copyright 2022-2023 Overte e.V.
|
||||
# Copyright 2022-2024 Overte e.V.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Docker file for building Overte
|
||||
# Example build: docker build -t overte/overte-full-build:0.1.1-ubuntu-22.04 -f Dockerfile_build_ubuntu-22.04 .
|
||||
# Example build: docker build -t overte/overte-full-build:0.1.2-ubuntu-22.04 -f Dockerfile_build_ubuntu-22.04 .
|
||||
FROM ubuntu:22.04
|
||||
LABEL maintainer="Julian Groß (julian.gro@overte.org)"
|
||||
LABEL description="Development image for full Overte builds"
|
||||
|
@ -19,7 +19,7 @@ RUN apt-get -y install curl ninja-build git cmake g++ libssl-dev libqt5websocket
|
|||
# Install Overte tools build dependencies
|
||||
RUN apt-get -y install libqt5webchannel5-dev qtwebengine5-dev libqt5xmlpatterns5-dev
|
||||
# Install Overte Interface build dependencies
|
||||
RUN apt-get -y install libqt5svg5-dev qttools5-dev
|
||||
RUN apt-get -y install libqt5svg5-dev qttools5-dev vulkan-validationlayers libvulkan-dev libvulkan1 libqt5x11extras5-dev qtbase5-private-dev
|
||||
# Install server-console build dependencies
|
||||
RUN apt-get -y install npm
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# Copyright 2022-2024 Overte e.V.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Docker file for building Overte Server
|
||||
# Example build: docker build -t overte/overte-server-build:0.1.4-fedora-39 -f Dockerfile_build_fedora-39 .
|
||||
FROM fedora:39
|
||||
LABEL maintainer="Julian Groß (julian.gro@overte.org)"
|
||||
LABEL description="Development image for Overte Domain server and assignment clients."
|
||||
|
||||
# Install Overte domain-server and assignment-client build dependencies
|
||||
RUN dnf -y install curl ninja-build git cmake gcc gcc-c++ openssl-devel qt5-qtwebsockets-devel qt5-qtmultimedia-devel unzip libXext-devel qt5-qtwebchannel-devel qt5-qtwebengine-devel qt5-qtxmlpatterns-devel systemd-devel python3.11
|
||||
|
||||
# Install additional build tools
|
||||
RUN dnf -y install zip unzip
|
||||
|
||||
# Install tools for package creation
|
||||
RUN dnf -y install chrpath rpmdevtools
|
||||
|
||||
# Install tools needed for our Github Actions Workflow
|
||||
Run dnf -y install python3-boto3 python3-pygithub
|
|
@ -71,7 +71,7 @@ exports.handlers = {
|
|||
];
|
||||
|
||||
// only files with this extension will be searched for jsdoc comments.
|
||||
var exts = ['.h', '.cpp'];
|
||||
var exts = ['.h', '.h.in', '.cpp', '.cpp.in'];
|
||||
|
||||
var fs = require('fs');
|
||||
dirList.forEach(function (dir) {
|
||||
|
@ -123,9 +123,9 @@ exports.handlers = {
|
|||
// Append an Available In: sentence at the beginning of the namespace description.
|
||||
if (rows.length > 0) {
|
||||
var availableIn = "<p class='availableIn'><b>Supported Script Types:</b> " + rows.join(" • ") + "</p>";
|
||||
|
||||
|
||||
e.doclet.description = availableIn + (e.doclet.description ? e.doclet.description : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e.doclet.kind === "function" && e.doclet.returns && e.doclet.returns[0].type
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
# - Check which commit you are building https://invent.kde.org/qt/qt/qt5/-/tree/kde/5.15
|
||||
# - Adjust this file to include the commit hash you are building, the date, the number of threads you want to use (-j10), the platform, and the Qt and QtWebEngine versions.
|
||||
# Keep in mind that building Qt requires a lot of memory. You should have over 1.2GiB of system memory available per thread.
|
||||
# - Run the build process with something like `PROGRESS_NO_TRUNC=1 DOCKER_BUILDKIT=1 BUILDKIT_STEP_LOG_MAX_SIZE=-1 docker build --progress plain -t overte-qt5:5.15.14-2024.06.17-kde_570f5b2105df1ea052bec0d6dbf8a00137274371 -f Dockerfile_Ubuntu_20.04_Qt5 .`
|
||||
# - Run the build process with something like `PROGRESS_NO_TRUNC=1 DOCKER_BUILDKIT=1 BUILDKIT_STEP_LOG_MAX_SIZE=-1 docker build --progress plain -t overte-qt5:5.15.16-2024.12.14-kde_32be154325bfba3ad2ba8bf75dad702f3588e8d3 -f Dockerfile_Ubuntu_20.04_Qt5 .`
|
||||
# Buildkit is used to cache intermittent steps in case you need to modify something afterwards.
|
||||
# - Once the build has completed, create a container from the image and export the created Qt package.
|
||||
# `docker create --name extract overte-qt5:5.15.14-2024.06.17-kde_570f5b2105df1ea052bec0d6dbf8a00137274371`
|
||||
# `docker cp extract:qt5-install-5.15.14-2024.06.17-kde_570f5b2105df1ea052bec0d6dbf8a00137274371-ubuntu-20.04-amd64.tar.xz /path/on/host`
|
||||
# `docker create --name extract overte-qt5:5.15.16-2024.12.14-kde_32be154325bfba3ad2ba8bf75dad702f3588e8d3`
|
||||
# `docker cp extract:qt5-install-5.15.16-2024.12.14-kde_32be154325bfba3ad2ba8bf75dad702f3588e8d3-ubuntu-20.04-amd64.tar.xz /path/on/host`
|
||||
# `docker rm extract`
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
@ -47,7 +47,7 @@ RUN apt-get -y install git python gperf flex bison pkg-config mesa-utils libgl1-
|
|||
|
||||
RUN mkdir qt5-install && mkdir qt5-build
|
||||
WORKDIR qt5-build
|
||||
RUN ../qt5/configure -force-debug-info -release -opensource -confirm-license -platform linux-g++ -recheck-all -nomake tests -nomake examples -skip qttranslations -skip qtserialport -skip qt3d -skip qtlocation -skip qtwayland -skip qtsensors -skip qtgamepad -skip qtcharts -skip qtx11extras -skip qtmacextras -skip qtvirtualkeyboard -skip qtpurchasing -skip qtdatavis3d -skip qtlottie -skip qtquick3d -skip qtpim -skip qtdocgallery -no-warnings-are-errors -no-pch -no-icu -prefix ../qt5-install
|
||||
RUN ../qt5/configure -force-debug-info -release -opensource -confirm-license -platform linux-g++ -recheck-all -nomake tests -nomake examples -skip qttranslations -skip qtserialport -skip qt3d -skip qtlocation -skip qtwayland -skip qtsensors -skip qtgamepad -skip qtcharts -skip qtmacextras -skip qtvirtualkeyboard -skip qtpurchasing -skip qtdatavis3d -skip qtlottie -skip qtquick3d -skip qtpim -skip qtdocgallery -no-warnings-are-errors -no-pch -no-icu -prefix ../qt5-install
|
||||
|
||||
RUN NINJAFLAGS='-j6' make -j6
|
||||
|
||||
|
@ -58,12 +58,12 @@ WORKDIR ../../qt5-install
|
|||
RUN find . -name \*.prl -exec sed -i -e '/^QMAKE_PRL_BUILD_DIR/d' {} \;
|
||||
|
||||
# Overwrite QtWebengine version to work around version conflicts
|
||||
RUN find . -name \Qt5WebEngine*Config.cmake -exec sed -i '' -e 's/5\.15\.17/5\.15\.14/g' {} \;
|
||||
RUN cp lib/libQt5WebEngine.so.5.15.17 lib/libQt5WebEngine.so.5.15.14
|
||||
RUN cp lib/libQt5WebEngineCore.so.5.15.17 lib/libQt5WebEngineCore.so.5.15.14
|
||||
RUN cp lib/libQt5WebEngineWidgets.so.5.15.17 lib/libQt5WebEngineWidgets.so.5.15.14
|
||||
RUN cp lib/libQt5Pdf.so.5.15.17 lib/libQt5Pdf.so.5.15.14
|
||||
RUN cp lib/libQt5PdfWidgets.so.5.15.17 lib/libQt5PdfWidgets.so.5.15.14
|
||||
RUN find . -name \Qt5WebEngine*Config.cmake -exec sed -i '' -e 's/5\.15\.19/5\.15\.16/g' {} \;
|
||||
RUN cp lib/libQt5WebEngine.so.5.15.19 lib/libQt5WebEngine.so.5.15.16
|
||||
RUN cp lib/libQt5WebEngineCore.so.5.15.19 lib/libQt5WebEngineCore.so.5.15.16
|
||||
RUN cp lib/libQt5WebEngineWidgets.so.5.15.19 lib/libQt5WebEngineWidgets.so.5.15.16
|
||||
RUN cp lib/libQt5Pdf.so.5.15.19 lib/libQt5Pdf.so.5.15.16
|
||||
RUN cp lib/libQt5PdfWidgets.so.5.15.19 lib/libQt5PdfWidgets.so.5.15.16
|
||||
|
||||
|
||||
COPY ./qt.conf ./bin/
|
||||
|
@ -71,4 +71,4 @@ COPY ./qt.conf ./bin/
|
|||
RUN cp ../qt5-build/config.summary ./
|
||||
|
||||
WORKDIR ..
|
||||
RUN XZ_OPT='-T0' tar -Jcvf qt5-install-5.15.14-2024.06.17-kde_570f5b2105df1ea052bec0d6dbf8a00137274371-ubuntu-20.04-amd64.tar.xz qt5-install
|
||||
RUN XZ_OPT='-T0' tar -Jcvf qt5-install-5.15.16-2024.12.14-kde_32be154325bfba3ad2ba8bf75dad702f3588e8d3-ubuntu-20.04-amd64.tar.xz qt5-install
|
||||
|
|
Loading…
Reference in a new issue