Merge branch 'overte-org:master' into Delete/onFirstRun

This commit is contained in:
Armored-Dragon 2024-08-31 20:48:38 +00:00 committed by GitHub
commit e8dae14a02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
122 changed files with 3455 additions and 1091 deletions

View file

@ -12,11 +12,147 @@ 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).
<!-- ## [Unreleased] 2023.07.2 -->
<!-- ## [2024.09.1] Unreleased -->
<!-- ## [2023.07.1] 2023.07.2 -->
## [2024.07.1] 2023.07.12
### Fixes
- Fix more warnings (PR1007)
- Fix new debug build warning (PR1013)
- Fix RPM packaging (PR1025)
- Temporary fix for some script messages not being transmitted (PR1024)
- Fix unhandled std::bad_weak_ptr (PR1037)
- Fix long messages in Entity script log (PR1029)
- Allow events from VR keyboard to overlay UI (PR1046)
- Fix Fedora 40 server packages. (PR1057)
- Fix crash in setCrashReporterEnabled (PR1065)
- Fix mtoon issue on GLES (PR1055)
- Fix GHA building hundreds of servers (PR1071)
- Fix broken upload paths for RPM distributions. (PR1072)
### Changes
- Text Entity Improvements (PR937)
- GitHub Action Runner auto-scaling (PR1021)
- Remove some external refrences (PR1026)
- Update from deprecated actions/checkout and actions/upload-artifact (PR1023)
- Update Ubuntu 20.04 amd64 Qt package (PR1032)
- Cut back on master builds. (PR1049)
- Increase default vertical FOV (PR1061)
- Always enable crash reporting. (PR1064)
- Update make-rpm-server to remove - characters. (PR1063)
- Update VCPKG on Windows, so it can find newer versions of Visual Studio. (PR1073)
### Additions
- Add a script to more easily build Debian and RPM server packages. (PR1011)
- Add Fedora 40 servers (PR1010)
- GitHub Actions server release builds (PR1022)
- Wiggly lasers (PR1014)
- Create Windows release builds. (PR1048)
### Removals
- Remove broken ccache macro (PR1018)
- Remove note about secure WebSockets not being supported. (PR1040)
- Remove RELEASE_NAME (PR1039)
- Remove hifiNeuron.dll (PR1075)
- Remove remnants of RELEASE_NAME. (PR1077)
## [2024.06.1] 2023.06.24
### Fixes
- Fix QNetworkRequest::FollowRedirectsAttribute deprecated warning (PR711)
- Fix luci (PR724)
- Fix setting external port and IP address for manual networking modes (PR746)
- particle billboarding is wrong in VR (PR747)
- Upgrade openexr (PR752)
- Fix OpenEXR on Windows (PR756)
- Upgrade Steamworks and fix for ninja build (PR755)
- Fixes for Oculus VR plugin (PR758)
- Fix Ninja builds with Crashpad enabled on Windows (PR765)
- Fix a bug in Entities.getEntityProperties (PR768)
- Fixed returnNothingOnEmptyPropertyFlags (PR770)
- ✨ "Update Existing Avatar" now properly updates the fst file (PR576)
- Fix the doppleganger position in the tutorial (PR781)
- Fix entity density not setting and not updating for motion states (PR819)
- Add keyboard modifiers to entity pointer events (PR815)
- 🐛 Fixed build on Windows (PR827)
- Fix recording API documentation not being built (PR829)
- Fix the display of Notifications (PR831)
- Fix prebuild.py code ordering to make --get-vcpkg-id and --get-vcpkg-path correctly in the repo root (PR836)
- Fixed avatar volume adjustment (PR841)
- Respect cull face during shadow pass (PR820)
- Fix Developer > UI > Show Overlays + Snap UI not hiding (PR823)
- Fixed blendshapes in gltf importer (PR840)
- Fix require behavior for modules (PR855)
- 🐛 Fixed avatar bounding box being inverted (PR866)
- Fix collisions on glTF avatars (PR867)
- Clean up GeometryCache and remove _glColor4f (PR845)
- Fix warnings as errors for MSVC (PR873)
- Fix invalid animation reference in assignment client (PR854)
- Fix previous commit for not loading textures on agent (PR893)
- conversionPenaltyScore should accumulate (PR935)
- Fix getEntityProperties for group properties + keylight direction (PR927)
- Move helper script engines to their own threads (PR853)
- Fix C++20 warnings (PR950)
- Fix access check in getSkeletonModelURLFromScript (PR955)
- SimplifiedUI adjustemnts (PR960)
- Fixed locale problems with cgltf.h (PR978)
- Fixed script signal proxy crashes (PR964)
- Fixed deadlocks in Recording API (PR959)
- Fix tests (PR991)
- Add missing dependencymanager call, fixes test crash (PR994)
- Skip packet capacity test when built in debug mode, as it triggers an assertion (PR993)
- Fix some warnings (PR1003)
- Fix Locker issue in RecordingScriptingInterface (PR1006)
### Changes
- Update Linux vcpkg to the same as the Windows version (PR751)
- Disable Oculus plugin on Visual Studio 2022 (PR754)
- Reorganize startup to allow more control over plugins (PR716)
- Script performance improvements (PR744)
- Re-enable building Oculus plugin on VS 2022 (PR761)
- Use response files on Ninja for long paths (PR764)
- Improvement in controller scripts performance (PR766)
- Update VCPKG for Linux aarch64 (PR807)
- Linux server gha update (PR812)
- glTF importer using cgltf library (PR835)
- 🔧 Disable building electron screenshare app on windows (PR864)
- Change the hash salt from Vircadia to Overte (PR869)
- Change vircadia launcher dir (PR870)
- Add Oculus to fullbody-enabled headsets list (PR882)
- Add Ubuntu 24.04 to server packaging (PR966)
- Improve network debugging messages to help with Conan PR (PR995)
- Send OpenGL errors to log on debug builds (PR998)
### Additions
- Add initial benchmarks for the script engine (PR710)
- Add more ram Options (PR763)
- Add VS22 cmake jumpstart script (PR773)
- MToon materials (PR805)
- Add a way to get VCPKG path and hash ID (PR813)
- Entity script logging for script editor (PR673)
- Create app: RenderWithZones Manager (PR806)
- Added WebP support for binary glTF (PR860)
- Support opaque (and black) particles (PR844)
- Create App: Tools tab: CSS&HTML adjustments (PR880)
- Create Application: Advanced Import functionality (PR877)
- Create App.: "Copy Dimensions" and "Paste Dimensions" (PR863)
- Create app: Entity List: "Copy ID" on menu and contextual menu. (PR865)
- Add qByteArray to script value conversion (PR868)
- Custom refresh rate profile (PR899)
- support VRMC_materials_mtoon and KHR_materials_unlit (PR936)
- Add very basic HTTP and HTTPS network tests (PR996)
### Removals
- Disable Neuron by default (PR753)
- Removing markdown from floof chat (PR769)
- Remove debug print with URL from ModelLoader (PR837)
- Remove legally problematic texture (PR851)
### Security
- Added simple protection for avatar URL (PR887)
- add canViewAssetURLs domain permissions (PR152)
<!-- ## [2023.06.1] 2023.06.12 -->
## [2023.11.1] 2023.11.24

View file

@ -148,22 +148,22 @@ endif()
# OVERTE_WARNINGS
#
# Here we add the ability to whitelist warnings we've determined we can't fix, or are safe to
# Here we add the ability to allowlist warnings we've determined we can't fix, or are safe to
# ignore for one reason or another. The way of doing so is compiler-specific, so we deal with
# the detection of that in cmake, and just pass it down to the code from here.
#
# We can also treat warnings as errors. Without the whitelist this will almost certainly lead
# We can also treat warnings as errors. Without the allowlist this will almost certainly lead
# to a build failure.
if(NOT DEFINED OVERTE_WARNINGS_WHITELIST)
set(OVERTE_WARNINGS_WHITELIST true CACHE BOOL "Whitelist some warnings we can't currently fix")
if(NOT DEFINED OVERTE_WARNINGS_ALLOWLIST)
set(OVERTE_WARNINGS_ALLOWLIST true CACHE BOOL "Allowlist some warnings we can't currently fix")
endif()
if(NOT DEFINED OVERTE_WARNINGS_AS_ERRORS)
set(OVERTE_WARNINGS_AS_ERRORS false CACHE BOOL "Count warnings as errors")
endif()
if(OVERTE_WARNINGS_WHITELIST)
if(OVERTE_WARNINGS_ALLOWLIST)
if (NOT WIN32)
set(CMAKE_PLATFORM_INFO_DIR "${CMAKE_CURRENT_BINARY_DIR}")
include(CMakeDetermineCXXCompiler)
@ -171,15 +171,15 @@ if(OVERTE_WARNINGS_WHITELIST)
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
message("GCC compiler detected, suppressing some unsolvable warnings.")
add_compile_definitions(OVERTE_WARNINGS_WHITELIST_GCC)
add_compile_definitions(OVERTE_WARNINGS_ALLOWLIST_GCC)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message("Clang compiler detected, suppressing some unsolvable warnings.")
add_compile_definitions(OVERTE_WARNINGS_WHITELIST_CLANG)
add_compile_definitions(OVERTE_WARNINGS_ALLOWLIST_CLANG)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "" AND WIN32))
message("Microsoft Visual Studio compiler detected, suppressing some unsolvable warnings.")
add_compile_definitions(OVERTE_WARNINGS_WHITELIST_MSVC)
add_compile_definitions(OVERTE_WARNINGS_ALLOWLIST_MSVC)
else()
message("We don't know yet how to whitelist warnings for ${CMAKE_CXX_COMPILER_ID}")
message("We don't know yet how to allowlist warnings for ${CMAKE_CXX_COMPILER_ID}")
endif()
endif()

View file

@ -1,6 +1,6 @@
Copyright (c) 2013-2019, High Fidelity, Inc.
Copyright (c) 2019-2021, Vircadia contributors.
Copyright (c) 2022-2023, Overte e.V.
Copyright (c) 2022-2024, Overte e.V.
All rights reserved.
https://overte.org

View file

@ -277,14 +277,14 @@ void AudioMixer::sendStatsPacket() {
#ifdef DEBUG_EVENT_QUEUE
QJsonObject qtStats;
_slavePool.queueStats(qtStats);
_workerPool.queueStats(qtStats);
statsObject["audio_thread_event_queue"] = qtStats;
#endif
// general stats
statsObject["useDynamicJitterBuffers"] = _numStaticJitterFrames == DISABLE_STATIC_JITTER_FRAMES;
statsObject["threads"] = _slavePool.numThreads();
statsObject["threads"] = _workerPool.numThreads();
statsObject["trailing_mix_ratio"] = _trailingMixRatio;
statsObject["throttling_ratio"] = _throttlingRatio;
@ -433,15 +433,15 @@ void AudioMixer::start() {
auto frameTimer = _frameTiming.timer();
// process (node-isolated) audio packets across slave threads
// process (node-isolated) audio packets across worker threads
{
auto packetsTimer = _packetsTiming.timer();
// first clear the concurrent vector of added streams that the slaves will add to when they process packets
// first clear the concurrent vector of added streams that the workers will add to when they process packets
_workerSharedData.addedStreams.clear();
nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
_slavePool.processPackets(cbegin, cend);
_workerPool.processPackets(cbegin, cend);
});
}
@ -463,15 +463,15 @@ void AudioMixer::start() {
numToRetain = nodeList->size() * (1.0f - _throttlingRatio);
}
nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
// mix across slave threads
// mix across worker threads
auto mixTimer = _mixTiming.timer();
_slavePool.mix(cbegin, cend, frame, numToRetain);
_workerPool.mix(cbegin, cend, frame, numToRetain);
});
// gather stats
_slavePool.each([&](AudioMixerSlave& slave) {
_stats.accumulate(slave.stats);
slave.stats.reset();
_workerPool.each([&](AudioMixerWorker& worker) {
_stats.accumulate(worker.stats);
worker.stats.reset();
});
++frame;
@ -573,7 +573,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
const QString NUM_THREADS = "num_threads";
int numThreads = audioThreadingGroupObject[NUM_THREADS].toString().toInt(&ok);
if (ok) {
_slavePool.setNumThreads(numThreads);
_workerPool.setNumThreads(numThreads);
}
}

View file

@ -23,7 +23,7 @@
#include <plugins/Forward.h>
#include "AudioMixerStats.h"
#include "AudioMixerSlavePool.h"
#include "AudioMixerWorkerPool.h"
class PositionalAudioStream;
class AvatarAudioStream;
@ -107,7 +107,7 @@ private:
int _numStatFrames { 0 };
AudioMixerStats _stats;
AudioMixerSlavePool _slavePool { _workerSharedData };
AudioMixerWorkerPool _workerPool { _workerSharedData };
class Timer {
public:
@ -153,7 +153,7 @@ private:
float _throttleStartTarget = 0.9f;
float _throttleBackoffTarget = 0.44f;
AudioMixerSlave::SharedData _workerSharedData;
AudioMixerWorker::SharedData _workerSharedData;
};
#endif // hifi_AudioMixer_h

View file

@ -201,9 +201,9 @@ void AudioMixerClientData::parsePerAvatarGainSet(ReceivedMessage& message, const
float gain = unpackFloatGainFromByte(packedGain);
if (avatarUUID.isNull()) {
// set the MASTER avatar gain
setMasterAvatarGain(gain);
qCDebug(audio) << "Setting MASTER avatar gain for" << uuid << "to" << gain;
// set the PRIMARY avatar gain
setPrimaryAvatarGain(gain);
qCDebug(audio) << "Setting PRIMARY avatar gain for" << uuid << "to" << gain;
} else {
// set the per-source avatar gain
setGainForAvatar(avatarUUID, gain);
@ -218,8 +218,8 @@ void AudioMixerClientData::parseInjectorGainSet(ReceivedMessage& message, const
message.readPrimitive(&packedGain);
float gain = unpackFloatGainFromByte(packedGain);
setMasterInjectorGain(gain);
qCDebug(audio) << "Setting MASTER injector gain for" << uuid << "to" << gain;
setPrimaryInjectorGain(gain);
qCDebug(audio) << "Setting PRIMARY injector gain for" << uuid << "to" << gain;
}
bool setGainInStreams(const QUuid &nodeID, float gain, std::vector<AudioMixerClientData::MixableStream> &streamVector) {

View file

@ -86,10 +86,10 @@ public:
// uses randomization to have the AudioMixer send a stats packet to this node around every second
bool shouldSendStats(int frameNumber);
float getMasterAvatarGain() const { return _masterAvatarGain; }
void setMasterAvatarGain(float gain) { _masterAvatarGain = gain; }
float getMasterInjectorGain() const { return _masterInjectorGain; }
void setMasterInjectorGain(float gain) { _masterInjectorGain = gain; }
float getPrimaryAvatarGain() const { return _primaryAvatarGain; }
void setPrimaryAvatarGain(float gain) { _primaryAvatarGain = gain; }
float getPrimaryInjectorGain() const { return _primaryInjectorGain; }
void setPrimaryInjectorGain(float gain) { _primaryInjectorGain = gain; }
AudioLimiter audioLimiter;
@ -140,11 +140,11 @@ public:
Streams& getStreams() { return _streams; }
// thread-safe, called from AudioMixerSlave(s) while processing ignore packets for other nodes
// thread-safe, called from AudioMixerWorker(s) while processing ignore packets for other nodes
void ignoredByNode(QUuid nodeID);
void unignoredByNode(QUuid nodeID);
// start of methods called non-concurrently from single AudioMixerSlave mixing for the owning node
// start of methods called non-concurrently from single AudioMixerWorker mixing for the owning node
const Node::IgnoredNodeIDs& getNewIgnoredNodeIDs() const { return _newIgnoredNodeIDs; }
const Node::IgnoredNodeIDs& getNewUnignoredNodeIDs() const { return _newUnignoredNodeIDs; }
@ -163,7 +163,7 @@ public:
bool getHasReceivedFirstMix() const { return _hasReceivedFirstMix; }
void setHasReceivedFirstMix(bool hasReceivedFirstMix) { _hasReceivedFirstMix = hasReceivedFirstMix; }
// end of methods called non-concurrently from single AudioMixerSlave
// end of methods called non-concurrently from single AudioMixerWorker
signals:
void injectorStreamFinished(const QUuid& streamID);
@ -194,8 +194,8 @@ private:
int _frameToSendStats { 0 };
float _masterAvatarGain { 1.0f }; // per-listener mixing gain, applied only to avatars
float _masterInjectorGain { 1.0f }; // per-listener mixing gain, applied only to injectors
float _primaryAvatarGain { 1.0f }; // per-listener mixing gain, applied only to avatars
float _primaryInjectorGain { 1.0f }; // per-listener mixing gain, applied only to injectors
CodecPluginPointer _codec;
QString _selectedCodecName;

View file

@ -1,5 +1,5 @@
//
// AudioMixerSlave.cpp
// AudioMixerWorker.cpp
// assignment-client/src/audio
//
// Created by Zach Pomerantz on 11/22/16.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AudioMixerSlave.h"
#include "AudioMixerWorker.h"
#include <algorithm>
@ -50,12 +50,12 @@ void sendEnvironmentPacket(const SharedNodePointer& node, AudioMixerClientData&
// mix helpers
inline float approximateGain(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd);
inline float computeGain(float masterAvatarGain, float masterInjectorGain, const AvatarAudioStream& listeningNodeStream,
inline float computeGain(float primaryAvatarGain, float primaryInjectorGain, const AvatarAudioStream& listeningNodeStream,
const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition, float distance);
inline float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
const glm::vec3& relativePosition);
void AudioMixerSlave::processPackets(const SharedNodePointer& node) {
void AudioMixerWorker::processPackets(const SharedNodePointer& node) {
AudioMixerClientData* data = (AudioMixerClientData*)node->getLinkedData();
if (data) {
// process packets and collect the number of streams available for this frame
@ -63,14 +63,14 @@ void AudioMixerSlave::processPackets(const SharedNodePointer& node) {
}
}
void AudioMixerSlave::configureMix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) {
void AudioMixerWorker::configureMix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) {
_begin = begin;
_end = end;
_frame = frame;
_numToRetain = numToRetain;
}
void AudioMixerSlave::mix(const SharedNodePointer& node) {
void AudioMixerWorker::mix(const SharedNodePointer& node) {
// check that the node is valid
AudioMixerClientData* data = (AudioMixerClientData*)node->getLinkedData();
if (data == nullptr) {
@ -178,7 +178,7 @@ private:
};
void AudioMixerSlave::addStreams(Node& listener, AudioMixerClientData& listenerData) {
void AudioMixerWorker::addStreams(Node& listener, AudioMixerClientData& listenerData) {
auto& ignoredNodeIDs = listener.getIgnoredNodeIDs();
auto& ignoringNodeIDs = listenerData.getIgnoringNodeIDs();
@ -229,7 +229,7 @@ void AudioMixerSlave::addStreams(Node& listener, AudioMixerClientData& listenerD
}
}
bool shouldBeRemoved(const MixableStream& stream, const AudioMixerSlave::SharedData& sharedData) {
bool shouldBeRemoved(const MixableStream& stream, const AudioMixerWorker::SharedData& sharedData) {
return (contains(sharedData.removedNodes, stream.nodeStreamID.nodeLocalID) ||
contains(sharedData.removedStreams, stream.nodeStreamID));
};
@ -306,7 +306,7 @@ float approximateVolume(const MixableStream& stream, const AvatarAudioStream* li
return stream.positionalStream->getLastPopOutputTrailingLoudness() * gain;
};
bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
bool AudioMixerWorker::prepareMix(const SharedNodePointer& listener) {
AvatarAudioStream* listenerAudioStream = static_cast<AudioMixerClientData*>(listener->getLinkedData())->getAvatarAudioStream();
AudioMixerClientData* listenerData = static_cast<AudioMixerClientData*>(listener->getLinkedData());
@ -338,8 +338,8 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
}
if (!isThrottling) {
updateHRTFParameters(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(),
listenerData->getMasterInjectorGain());
updateHRTFParameters(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(),
listenerData->getPrimaryInjectorGain());
}
return false;
});
@ -363,8 +363,8 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
}
if (!isThrottling) {
updateHRTFParameters(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(),
listenerData->getMasterInjectorGain());
updateHRTFParameters(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(),
listenerData->getPrimaryInjectorGain());
}
return false;
});
@ -387,7 +387,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
return true;
}
addStream(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(), listenerData->getMasterInjectorGain(),
addStream(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(), listenerData->getPrimaryInjectorGain(),
isSoloing);
if (shouldBeInactive(stream)) {
@ -423,7 +423,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
return true;
}
addStream(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(), listenerData->getMasterInjectorGain(),
addStream(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(), listenerData->getPrimaryInjectorGain(),
isSoloing);
if (shouldBeInactive(stream)) {
@ -489,10 +489,10 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
return hasAudio;
}
void AudioMixerSlave::addStream(AudioMixerClientData::MixableStream& mixableStream,
void AudioMixerWorker::addStream(AudioMixerClientData::MixableStream& mixableStream,
AvatarAudioStream& listeningNodeStream,
float masterAvatarGain,
float masterInjectorGain,
float primaryAvatarGain,
float primaryInjectorGain,
bool isSoloing) {
++stats.totalMixes;
@ -505,8 +505,8 @@ void AudioMixerSlave::addStream(AudioMixerClientData::MixableStream& mixableStre
float distance = glm::max(glm::length(relativePosition), EPSILON);
float gain = isEcho ? 1.0f
: (isSoloing ? masterAvatarGain
: computeGain(masterAvatarGain, masterInjectorGain, listeningNodeStream, *streamToAdd,
: (isSoloing ? primaryAvatarGain
: computeGain(primaryAvatarGain, primaryInjectorGain, listeningNodeStream, *streamToAdd,
relativePosition, distance));
float azimuth = isEcho ? 0.0f : computeAzimuth(listeningNodeStream, listeningNodeStream, relativePosition);
@ -575,10 +575,10 @@ void AudioMixerSlave::addStream(AudioMixerClientData::MixableStream& mixableStre
}
}
void AudioMixerSlave::updateHRTFParameters(AudioMixerClientData::MixableStream& mixableStream,
void AudioMixerWorker::updateHRTFParameters(AudioMixerClientData::MixableStream& mixableStream,
AvatarAudioStream& listeningNodeStream,
float masterAvatarGain,
float masterInjectorGain) {
float primaryAvatarGain,
float primaryInjectorGain) {
auto streamToAdd = mixableStream.positionalStream;
// check if this is a server echo of a source back to itself
@ -587,7 +587,7 @@ void AudioMixerSlave::updateHRTFParameters(AudioMixerClientData::MixableStream&
glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream.getPosition();
float distance = glm::max(glm::length(relativePosition), EPSILON);
float gain = isEcho ? 1.0f : computeGain(masterAvatarGain, masterInjectorGain, listeningNodeStream, *streamToAdd,
float gain = isEcho ? 1.0f : computeGain(primaryAvatarGain, primaryInjectorGain, listeningNodeStream, *streamToAdd,
relativePosition, distance);
float azimuth = isEcho ? 0.0f : computeAzimuth(listeningNodeStream, listeningNodeStream, relativePosition);
@ -596,7 +596,7 @@ void AudioMixerSlave::updateHRTFParameters(AudioMixerClientData::MixableStream&
++stats.hrtfUpdates;
}
void AudioMixerSlave::resetHRTFState(AudioMixerClientData::MixableStream& mixableStream) {
void AudioMixerWorker::resetHRTFState(AudioMixerClientData::MixableStream& mixableStream) {
mixableStream.hrtf->reset();
++stats.hrtfResets;
}
@ -713,7 +713,7 @@ float approximateGain(const AvatarAudioStream& listeningNodeStream, const Positi
// injector: apply attenuation
if (streamToAdd.getType() == PositionalAudioStream::Injector) {
gain *= reinterpret_cast<const InjectedAudioStream*>(&streamToAdd)->getAttenuationRatio();
// injector: skip master gain
// injector: skip primary gain
}
// avatar: skip attenuation - it is too costly to approximate
@ -723,11 +723,11 @@ float approximateGain(const AvatarAudioStream& listeningNodeStream, const Positi
float distance = glm::length(relativePosition);
return gain / distance;
// avatar: skip master gain
// avatar: skip primary gain
}
float computeGain(float masterAvatarGain,
float masterInjectorGain,
float computeGain(float primaryAvatarGain,
float primaryInjectorGain,
const AvatarAudioStream& listeningNodeStream,
const PositionalAudioStream& streamToAdd,
const glm::vec3& relativePosition,
@ -737,8 +737,8 @@ float computeGain(float masterAvatarGain,
// injector: apply attenuation
if (streamToAdd.getType() == PositionalAudioStream::Injector) {
gain *= reinterpret_cast<const InjectedAudioStream*>(&streamToAdd)->getAttenuationRatio();
// apply master gain
gain *= masterInjectorGain;
// apply primary gain
gain *= primaryInjectorGain;
// avatar: apply fixed off-axis attenuation to make them quieter as they turn away
} else if (streamToAdd.getType() == PositionalAudioStream::Microphone) {
@ -754,8 +754,8 @@ float computeGain(float masterAvatarGain,
gain *= offAxisCoefficient;
// apply master gain
gain *= masterAvatarGain;
// apply primary gain
gain *= primaryAvatarGain;
}
auto& audioZones = AudioMixer::getAudioZones();

View file

@ -1,5 +1,5 @@
//
// AudioMixerSlave.h
// AudioMixerWorker.h
// assignment-client/src/audio
//
// Created by Zach Pomerantz on 11/22/16.
@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AudioMixerSlave_h
#define hifi_AudioMixerSlave_h
#ifndef hifi_AudioMixerWorker_h
#define hifi_AudioMixerWorker_h
#if !defined(Q_MOC_RUN)
// Work around https://bugreports.qt.io/browse/QTBUG-80990
@ -31,7 +31,7 @@
class AvatarAudioStream;
class AudioHRTF;
class AudioMixerSlave {
class AudioMixerWorker {
public:
using ConstIter = NodeList::const_iterator;
@ -41,7 +41,7 @@ public:
std::vector<NodeIDStreamID> removedStreams;
};
AudioMixerSlave(SharedData& sharedData) : _sharedData(sharedData) {};
AudioMixerWorker(SharedData& sharedData) : _sharedData(sharedData) {};
// process packets for a given node (requires no configuration)
void processPackets(const SharedNodePointer& node);
@ -60,13 +60,13 @@ private:
bool prepareMix(const SharedNodePointer& listener);
void addStream(AudioMixerClientData::MixableStream& mixableStream,
AvatarAudioStream& listeningNodeStream,
float masterAvatarGain,
float masterInjectorGain,
float primaryAvatarGain,
float primaryInjectorGain,
bool isSoloing);
void updateHRTFParameters(AudioMixerClientData::MixableStream& mixableStream,
AvatarAudioStream& listeningNodeStream,
float masterAvatarGain,
float masterInjectorGain);
float primaryAvatarGain,
float primaryInjectorGain);
void resetHRTFState(AudioMixerClientData::MixableStream& mixableStream);
void addStreams(Node& listener, AudioMixerClientData& listenerData);
@ -84,4 +84,4 @@ private:
SharedData& _sharedData;
};
#endif // hifi_AudioMixerSlave_h
#endif // hifi_AudioMixerWorker_h

View file

@ -1,5 +1,5 @@
//
// AudioMixerSlavePool.cpp
// AudioMixerWorkerPool.cpp
// assignment-client/src/audio
//
// Created by Zach Pomerantz on 11/16/2016.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AudioMixerSlavePool.h"
#include "AudioMixerWorkerPool.h"
#include <QObject>
@ -18,7 +18,7 @@
#include <ThreadHelpers.h>
void AudioMixerSlaveThread::run() {
void AudioMixerWorkerThread::run() {
while (true) {
wait();
@ -36,10 +36,10 @@ void AudioMixerSlaveThread::run() {
}
}
void AudioMixerSlaveThread::wait() {
void AudioMixerWorkerThread::wait() {
{
Lock lock(_pool._mutex);
_pool._slaveCondition.wait(lock, [&] {
_pool._workerCondition.wait(lock, [&] {
assert(_pool._numStarted <= _pool._numThreads);
return _pool._numStarted != _pool._numThreads;
});
@ -52,7 +52,7 @@ void AudioMixerSlaveThread::wait() {
_function = _pool._function;
}
void AudioMixerSlaveThread::notify(bool stopping) {
void AudioMixerWorkerThread::notify(bool stopping) {
{
Lock lock(_pool._mutex);
assert(_pool._numFinished < _pool._numThreads);
@ -64,26 +64,26 @@ void AudioMixerSlaveThread::notify(bool stopping) {
_pool._poolCondition.notify_one();
}
bool AudioMixerSlaveThread::try_pop(SharedNodePointer& node) {
bool AudioMixerWorkerThread::try_pop(SharedNodePointer& node) {
return _pool._queue.try_pop(node);
}
void AudioMixerSlavePool::processPackets(ConstIter begin, ConstIter end) {
_function = &AudioMixerSlave::processPackets;
_configure = [](AudioMixerSlave& slave) {};
void AudioMixerWorkerPool::processPackets(ConstIter begin, ConstIter end) {
_function = &AudioMixerWorker::processPackets;
_configure = [](AudioMixerWorker& worker) {};
run(begin, end);
}
void AudioMixerSlavePool::mix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) {
_function = &AudioMixerSlave::mix;
_configure = [=](AudioMixerSlave& slave) {
slave.configureMix(_begin, _end, frame, numToRetain);
void AudioMixerWorkerPool::mix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) {
_function = &AudioMixerWorker::mix;
_configure = [=](AudioMixerWorker& worker) {
worker.configureMix(_begin, _end, frame, numToRetain);
};
run(begin, end);
}
void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) {
void AudioMixerWorkerPool::run(ConstIter begin, ConstIter end) {
_begin = begin;
_end = end;
@ -97,7 +97,7 @@ void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) {
// run
_numStarted = _numFinished = 0;
_slaveCondition.notify_all();
_workerCondition.notify_all();
// wait
_poolCondition.wait(lock, [&] {
@ -111,17 +111,17 @@ void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) {
assert(_queue.empty());
}
void AudioMixerSlavePool::each(std::function<void(AudioMixerSlave& slave)> functor) {
for (auto& slave : _slaves) {
functor(*slave.get());
void AudioMixerWorkerPool::each(std::function<void(AudioMixerWorker& worker)> functor) {
for (auto& worker : _workers) {
functor(*worker.get());
}
}
#ifdef DEBUG_EVENT_QUEUE
void AudioMixerSlavePool::queueStats(QJsonObject& stats) {
void AudioMixerWorkerPool::queueStats(QJsonObject& stats) {
unsigned i = 0;
for (auto& slave : _slaves) {
int queueSize = ::hifi::qt::getEventQueueSize(slave.get());
for (auto& worker : _workers) {
int queueSize = ::hifi::qt::getEventQueueSize(worker.get());
QString queueName = QString("audio_thread_event_queue_%1").arg(i);
stats[queueName] = queueSize;
@ -130,7 +130,7 @@ void AudioMixerSlavePool::queueStats(QJsonObject& stats) {
}
#endif // DEBUG_EVENT_QUEUE
void AudioMixerSlavePool::setNumThreads(int numThreads) {
void AudioMixerWorkerPool::setNumThreads(int numThreads) {
// clamp to allowed size
{
int maxThreads = QThread::idealThreadCount();
@ -150,36 +150,36 @@ void AudioMixerSlavePool::setNumThreads(int numThreads) {
resize(numThreads);
}
void AudioMixerSlavePool::resize(int numThreads) {
assert(_numThreads == (int)_slaves.size());
void AudioMixerWorkerPool::resize(int numThreads) {
assert(_numThreads == (int)_workers.size());
qDebug("%s: set %d threads (was %d)", __FUNCTION__, numThreads, _numThreads);
Lock lock(_mutex);
if (numThreads > _numThreads) {
// start new slaves
// start new workers
for (int i = 0; i < numThreads - _numThreads; ++i) {
auto slave = new AudioMixerSlaveThread(*this, _workerSharedData);
QObject::connect(slave, &QThread::started, [] { setThreadName("AudioMixerSlaveThread"); });
slave->start();
_slaves.emplace_back(slave);
auto worker = new AudioMixerWorkerThread(*this, _workerSharedData);
QObject::connect(worker, &QThread::started, [] { setThreadName("AudioMixerWorkerThread"); });
worker->start();
_workers.emplace_back(worker);
}
} else if (numThreads < _numThreads) {
auto extraBegin = _slaves.begin() + numThreads;
auto extraBegin = _workers.begin() + numThreads;
// mark slaves to stop...
auto slave = extraBegin;
while (slave != _slaves.end()) {
(*slave)->_stop = true;
++slave;
// mark workers to stop...
auto worker = extraBegin;
while (worker != _workers.end()) {
(*worker)->_stop = true;
++worker;
}
// ...cycle them until they do stop...
_numStopped = 0;
while (_numStopped != (_numThreads - numThreads)) {
_numStarted = _numFinished = _numStopped;
_slaveCondition.notify_all();
_workerCondition.notify_all();
_poolCondition.wait(lock, [&] {
assert(_numFinished <= _numThreads);
return _numFinished == _numThreads;
@ -187,18 +187,18 @@ void AudioMixerSlavePool::resize(int numThreads) {
}
// ...wait for threads to finish...
slave = extraBegin;
while (slave != _slaves.end()) {
QThread* thread = reinterpret_cast<QThread*>(slave->get());
worker = extraBegin;
while (worker != _workers.end()) {
QThread* thread = reinterpret_cast<QThread*>(worker->get());
static const int MAX_THREAD_WAIT_TIME = 10;
thread->wait(MAX_THREAD_WAIT_TIME);
++slave;
++worker;
}
// ...and erase them
_slaves.erase(extraBegin, _slaves.end());
_workers.erase(extraBegin, _workers.end());
}
_numThreads = _numStarted = _numFinished = numThreads;
assert(_numThreads == (int)_slaves.size());
assert(_numThreads == (int)_workers.size());
}

View file

@ -1,5 +1,5 @@
//
// AudioMixerSlavePool.h
// AudioMixerWorkerPool.h
// assignment-client/src/audio
//
// Created by Zach Pomerantz on 11/16/2016.
@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AudioMixerSlavePool_h
#define hifi_AudioMixerSlavePool_h
#ifndef hifi_AudioMixerWorkerPool_h
#define hifi_AudioMixerWorkerPool_h
#include <condition_variable>
#include <mutex>
@ -20,37 +20,37 @@
#include <shared/QtHelpers.h>
#include <TBBHelpers.h>
#include "AudioMixerSlave.h"
#include "AudioMixerWorker.h"
class AudioMixerSlavePool;
class AudioMixerWorkerPool;
class AudioMixerSlaveThread : public QThread, public AudioMixerSlave {
class AudioMixerWorkerThread : public QThread, public AudioMixerWorker {
Q_OBJECT
using ConstIter = NodeList::const_iterator;
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
public:
AudioMixerSlaveThread(AudioMixerSlavePool& pool, AudioMixerSlave::SharedData& sharedData)
: AudioMixerSlave(sharedData), _pool(pool) {}
AudioMixerWorkerThread(AudioMixerWorkerPool& pool, AudioMixerWorker::SharedData& sharedData)
: AudioMixerWorker(sharedData), _pool(pool) {}
void run() override final;
private:
friend class AudioMixerSlavePool;
friend class AudioMixerWorkerPool;
void wait();
void notify(bool stopping);
bool try_pop(SharedNodePointer& node);
AudioMixerSlavePool& _pool;
void (AudioMixerSlave::*_function)(const SharedNodePointer& node) { nullptr };
AudioMixerWorkerPool& _pool;
void (AudioMixerWorker::*_function)(const SharedNodePointer& node) { nullptr };
bool _stop { false };
};
// Slave pool for audio mixers
// AudioMixerSlavePool is not thread-safe! It should be instantiated and used from a single thread.
class AudioMixerSlavePool {
// Worker pool for audio mixers
// AudioMixerWorkerPool is not thread-safe! It should be instantiated and used from a single thread.
class AudioMixerWorkerPool {
using Queue = tbb::concurrent_queue<SharedNodePointer>;
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
@ -59,18 +59,18 @@ class AudioMixerSlavePool {
public:
using ConstIter = NodeList::const_iterator;
AudioMixerSlavePool(AudioMixerSlave::SharedData& sharedData, int numThreads = QThread::idealThreadCount())
AudioMixerWorkerPool(AudioMixerWorker::SharedData& sharedData, int numThreads = QThread::idealThreadCount())
: _workerSharedData(sharedData) { setNumThreads(numThreads); }
~AudioMixerSlavePool() { resize(0); }
~AudioMixerWorkerPool() { resize(0); }
// process packets on slave threads
// process packets on worker threads
void processPackets(ConstIter begin, ConstIter end);
// mix on slave threads
// mix on worker threads
void mix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain);
// iterate over all slaves
void each(std::function<void(AudioMixerSlave& slave)> functor);
// iterate over all workers
void each(std::function<void(AudioMixerWorker& worker)> functor);
#ifdef DEBUG_EVENT_QUEUE
void queueStats(QJsonObject& stats);
@ -83,18 +83,18 @@ private:
void run(ConstIter begin, ConstIter end);
void resize(int numThreads);
std::vector<std::unique_ptr<AudioMixerSlaveThread>> _slaves;
std::vector<std::unique_ptr<AudioMixerWorkerThread>> _workers;
friend void AudioMixerSlaveThread::wait();
friend void AudioMixerSlaveThread::notify(bool stopping);
friend bool AudioMixerSlaveThread::try_pop(SharedNodePointer& node);
friend void AudioMixerWorkerThread::wait();
friend void AudioMixerWorkerThread::notify(bool stopping);
friend bool AudioMixerWorkerThread::try_pop(SharedNodePointer& node);
// synchronization state
Mutex _mutex;
ConditionVariable _slaveCondition;
ConditionVariable _workerCondition;
ConditionVariable _poolCondition;
void (AudioMixerSlave::*_function)(const SharedNodePointer& node);
std::function<void(AudioMixerSlave&)> _configure;
void (AudioMixerWorker::*_function)(const SharedNodePointer& node);
std::function<void(AudioMixerWorker&)> _configure;
int _numThreads { 0 };
int _numStarted { 0 }; // guarded by _mutex
int _numFinished { 0 }; // guarded by _mutex
@ -105,7 +105,7 @@ private:
ConstIter _begin;
ConstIter _end;
AudioMixerSlave::SharedData& _workerSharedData;
AudioMixerWorker::SharedData& _workerSharedData;
};
#endif // hifi_AudioMixerSlavePool_h
#endif // hifi_AudioMixerWorkerPool_h

View file

@ -60,7 +60,7 @@ bool AvatarMixer::SessionDisplayName::operator<(const SessionDisplayName& rhs) c
AvatarMixer::AvatarMixer(ReceivedMessage& message) :
ThreadedAssignment(message),
_slavePool(&_slaveSharedData)
_workerPool(&_workerSharedData)
{
DependencyManager::registerInheritance<EntityDynamicFactoryInterface, AssignmentDynamicFactory>();
DependencyManager::set<AssignmentDynamicFactory>();
@ -297,7 +297,7 @@ void AvatarMixer::start() {
auto end = usecTimestampNow();
_processQueuedAvatarDataPacketsLockWaitElapsedTime += (end - start);
_slavePool.processIncomingPackets(cbegin, cend);
_workerPool.processIncomingPackets(cbegin, cend);
}, &lockWait, &nodeTransform, &functor);
auto end = usecTimestampNow();
_processQueuedAvatarDataPacketsElapsedTime += (end - start);
@ -333,7 +333,7 @@ void AvatarMixer::start() {
auto start = usecTimestampNow();
nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
auto start = usecTimestampNow();
_slavePool.broadcastAvatarData(cbegin, cend, _lastFrameTimestamp, _maxKbpsPerNode, _throttlingRatio);
_workerPool.broadcastAvatarData(cbegin, cend, _lastFrameTimestamp, _maxKbpsPerNode, _throttlingRatio);
auto end = usecTimestampNow();
_broadcastAvatarDataInner += (end - start);
}, &lockWait, &nodeTransform, &functor);
@ -761,14 +761,14 @@ void AvatarMixer::sendStatsPacket() {
QJsonObject statsObject;
statsObject["broadcast_loop_rate"] = _loopRate.rate();
statsObject["threads"] = _slavePool.numThreads();
statsObject["threads"] = _workerPool.numThreads();
statsObject["trailing_mix_ratio"] = _trailingMixRatio;
statsObject["throttling_ratio"] = _throttlingRatio;
#ifdef DEBUG_EVENT_QUEUE
QJsonObject qtStats;
_slavePool.queueStats(qtStats);
_workerPool.queueStats(qtStats);
statsObject["avatar_thread_event_queue"] = qtStats;
#endif
@ -821,41 +821,41 @@ void AvatarMixer::sendStatsPacket() {
statsObject["parallelTasks"] = parallelTasks;
AvatarMixerSlaveStats aggregateStats;
AvatarMixerWorkerStats aggregateStats;
// gather stats
_slavePool.each([&](AvatarMixerSlave& slave) {
AvatarMixerSlaveStats stats;
slave.harvestStats(stats);
_workerPool.each([&](AvatarMixerWorker& worker) {
AvatarMixerWorkerStats stats;
worker.harvestStats(stats);
aggregateStats += stats;
});
QJsonObject slavesAggregatObject;
QJsonObject workersAggregatObject;
slavesAggregatObject["received_1_nodesProcessed"] = TIGHT_LOOP_STAT(aggregateStats.nodesProcessed);
workersAggregatObject["received_1_nodesProcessed"] = TIGHT_LOOP_STAT(aggregateStats.nodesProcessed);
slavesAggregatObject["sent_1_nodesBroadcastedTo"] = TIGHT_LOOP_STAT(aggregateStats.nodesBroadcastedTo);
workersAggregatObject["sent_1_nodesBroadcastedTo"] = TIGHT_LOOP_STAT(aggregateStats.nodesBroadcastedTo);
float averageNodes = ((float)aggregateStats.nodesBroadcastedTo / (float)tightLoopFrames);
float averageOthersIncluded = averageNodes ? aggregateStats.numOthersIncluded / averageNodes : 0.0f;
slavesAggregatObject["sent_2_averageOthersIncluded"] = TIGHT_LOOP_STAT(averageOthersIncluded);
workersAggregatObject["sent_2_averageOthersIncluded"] = TIGHT_LOOP_STAT(averageOthersIncluded);
float averageOverBudgetAvatars = averageNodes ? aggregateStats.overBudgetAvatars / averageNodes : 0.0f;
slavesAggregatObject["sent_3_averageOverBudgetAvatars"] = TIGHT_LOOP_STAT(averageOverBudgetAvatars);
slavesAggregatObject["sent_4_averageDataBytes"] = TIGHT_LOOP_STAT(aggregateStats.numDataBytesSent);
slavesAggregatObject["sent_5_averageTraitsBytes"] = TIGHT_LOOP_STAT(aggregateStats.numTraitsBytesSent);
slavesAggregatObject["sent_6_averageIdentityBytes"] = TIGHT_LOOP_STAT(aggregateStats.numIdentityBytesSent);
slavesAggregatObject["sent_7_averageHeroAvatars"] = TIGHT_LOOP_STAT(aggregateStats.numHeroesIncluded);
workersAggregatObject["sent_3_averageOverBudgetAvatars"] = TIGHT_LOOP_STAT(averageOverBudgetAvatars);
workersAggregatObject["sent_4_averageDataBytes"] = TIGHT_LOOP_STAT(aggregateStats.numDataBytesSent);
workersAggregatObject["sent_5_averageTraitsBytes"] = TIGHT_LOOP_STAT(aggregateStats.numTraitsBytesSent);
workersAggregatObject["sent_6_averageIdentityBytes"] = TIGHT_LOOP_STAT(aggregateStats.numIdentityBytesSent);
workersAggregatObject["sent_7_averageHeroAvatars"] = TIGHT_LOOP_STAT(aggregateStats.numHeroesIncluded);
slavesAggregatObject["timing_1_processIncomingPackets"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.processIncomingPacketsElapsedTime);
slavesAggregatObject["timing_2_ignoreCalculation"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.ignoreCalculationElapsedTime);
slavesAggregatObject["timing_3_toByteArray"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.toByteArrayElapsedTime);
slavesAggregatObject["timing_4_avatarDataPacking"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.avatarDataPackingElapsedTime);
slavesAggregatObject["timing_5_packetSending"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.packetSendingElapsedTime);
slavesAggregatObject["timing_6_jobElapsedTime"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.jobElapsedTime);
workersAggregatObject["timing_1_processIncomingPackets"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.processIncomingPacketsElapsedTime);
workersAggregatObject["timing_2_ignoreCalculation"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.ignoreCalculationElapsedTime);
workersAggregatObject["timing_3_toByteArray"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.toByteArrayElapsedTime);
workersAggregatObject["timing_4_avatarDataPacking"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.avatarDataPackingElapsedTime);
workersAggregatObject["timing_5_packetSending"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.packetSendingElapsedTime);
workersAggregatObject["timing_6_jobElapsedTime"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.jobElapsedTime);
statsObject["slaves_aggregate (per frame)"] = slavesAggregatObject;
statsObject["workers_aggregate (per frame)"] = workersAggregatObject;
_handleViewFrustumPacketElapsedTime = 0;
_handleAvatarIdentityPacketElapsedTime = 0;
@ -1016,9 +1016,9 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
numThreads = 1;
}
qCDebug(avatars) << "Avatar mixer will use specified number of threads:" << numThreads;
_slavePool.setNumThreads(numThreads);
_workerPool.setNumThreads(numThreads);
} else {
qCDebug(avatars) << "Avatar mixer will automatically determine number of threads to use. Using:" << _slavePool.numThreads() << "threads.";
qCDebug(avatars) << "Avatar mixer will automatically determine number of threads to use. Using:" << _workerPool.numThreads() << "threads.";
}
{
@ -1035,7 +1035,7 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
static const QString PRIORITY_FRACTION_KEY = "priority_fraction";
if (avatarMixerGroupObject.contains(PRIORITY_FRACTION_KEY)) {
float priorityFraction = float(avatarMixerGroupObject[PRIORITY_FRACTION_KEY].toDouble());
_slavePool.setPriorityReservedFraction(std::min(std::max(0.0f, priorityFraction), 1.0f));
_workerPool.setPriorityReservedFraction(std::min(std::max(0.0f, priorityFraction), 1.0f));
qCDebug(avatars) << "Avatar mixer reserving" << priorityFraction << "of bandwidth for priority avatars";
}
}
@ -1058,23 +1058,23 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
qCDebug(avatars) << "This domain requires a minimum avatar height of" << _domainMinimumHeight
<< "and a maximum avatar height of" << _domainMaximumHeight;
static const QString AVATAR_WHITELIST_OPTION = "avatar_whitelist";
_slaveSharedData.skeletonURLWhitelist = avatarMixerGroupObject[AVATAR_WHITELIST_OPTION]
static const QString AVATAR_ALLOWLIST_OPTION = "avatar_allowlist";
_workerSharedData.skeletonURLAllowlist = avatarMixerGroupObject[AVATAR_ALLOWLIST_OPTION]
.toString().split(',', Qt::KeepEmptyParts);
static const QString REPLACEMENT_AVATAR_OPTION = "replacement_avatar";
_slaveSharedData.skeletonReplacementURL = avatarMixerGroupObject[REPLACEMENT_AVATAR_OPTION]
_workerSharedData.skeletonReplacementURL = avatarMixerGroupObject[REPLACEMENT_AVATAR_OPTION]
.toString();
if (_slaveSharedData.skeletonURLWhitelist.count() == 1 && _slaveSharedData.skeletonURLWhitelist[0].isEmpty()) {
if (_workerSharedData.skeletonURLAllowlist.count() == 1 && _workerSharedData.skeletonURLAllowlist[0].isEmpty()) {
// KeepEmptyParts above will parse "," as ["", ""] (which is ok), but "" as [""] (which is not ok).
_slaveSharedData.skeletonURLWhitelist.clear();
_workerSharedData.skeletonURLAllowlist.clear();
}
if (_slaveSharedData.skeletonURLWhitelist.isEmpty()) {
if (_workerSharedData.skeletonURLAllowlist.isEmpty()) {
qCDebug(avatars) << "All avatars are allowed.";
} else {
qCDebug(avatars) << "Avatars other than" << _slaveSharedData.skeletonURLWhitelist << "will be replaced by" << (_slaveSharedData.skeletonReplacementURL.isEmpty() ? "default" : _slaveSharedData.skeletonReplacementURL.toString());
qCDebug(avatars) << "Avatars other than" << _workerSharedData.skeletonURLAllowlist << "will be replaced by" << (_workerSharedData.skeletonReplacementURL.isEmpty() ? "default" : _workerSharedData.skeletonReplacementURL.toString());
}
}
@ -1099,7 +1099,7 @@ void AvatarMixer::setupEntityQuery() {
priorityZoneQuery["name"] = true; // Handy for debugging.
_entityViewer.getOctreeQuery().setJSONParameters(priorityZoneQuery);
_slaveSharedData.entityTree = entityTree;
_workerSharedData.entityTree = entityTree;
}
void AvatarMixer::handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {

View file

@ -26,7 +26,7 @@
#include "../entities/EntityTreeHeadlessViewer.h"
#include "AvatarMixerClientData.h"
#include "AvatarMixerSlavePool.h"
#include "AvatarMixerWorkerPool.h"
/// Handles assignments of type AvatarMixer - distribution of avatar data to various clients
class AvatarMixer : public ThreadedAssignment {
@ -153,8 +153,8 @@ private:
RateCounter<> _loopRate; // this is the rate that the main thread tight loop runs
AvatarMixerSlavePool _slavePool;
SlaveSharedData _slaveSharedData;
AvatarMixerWorkerPool _workerPool;
WorkerSharedData _workerSharedData;
};
#endif // hifi_AvatarMixer_h

View file

@ -21,7 +21,7 @@
#include "AvatarLogging.h"
#include "AvatarMixerSlave.h"
#include "AvatarMixerWorker.h"
AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID, Node::LocalID nodeLocalID) : NodeData(nodeID, nodeLocalID) {
// in case somebody calls getSessionUUID on the AvatarData instance, make sure it has the right ID
@ -52,7 +52,7 @@ void AvatarMixerClientData::queuePacket(QSharedPointer<ReceivedMessage> message,
_packetQueue.push(message);
}
int AvatarMixerClientData::processPackets(const SlaveSharedData& slaveSharedData) {
int AvatarMixerClientData::processPackets(const WorkerSharedData& workerSharedData) {
int packetsProcessed = 0;
SharedNodePointer node = _packetQueue.node;
assert(_packetQueue.empty() || node);
@ -65,10 +65,10 @@ int AvatarMixerClientData::processPackets(const SlaveSharedData& slaveSharedData
switch (packet->getType()) {
case PacketType::AvatarData:
parseData(*packet, slaveSharedData);
parseData(*packet, workerSharedData);
break;
case PacketType::SetAvatarTraits:
processSetTraitsMessage(*packet, slaveSharedData, *node);
processSetTraitsMessage(*packet, workerSharedData, *node);
break;
case PacketType::BulkAvatarTraitsAck:
processBulkAvatarTraitsAckMessage(*packet);
@ -127,7 +127,7 @@ struct FindContainingZone {
} // namespace
int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveSharedData& slaveSharedData) {
int AvatarMixerClientData::parseData(ReceivedMessage& message, const WorkerSharedData& workerSharedData) {
// pull the sequence number from the data first
uint16_t sequenceNumber;
@ -150,7 +150,7 @@ int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveShared
auto newPosition = _avatar->getClientGlobalPosition();
if (newPosition != oldPosition || _avatar->getNeedsHeroCheck()) {
EntityTree& entityTree = *slaveSharedData.entityTree;
EntityTree& entityTree = *workerSharedData.entityTree;
FindContainingZone findContainingZone{ newPosition };
entityTree.recurseTreeWithOperation(&FindContainingZone::operation, &findContainingZone);
bool currentlyHasPriority = findContainingZone.isInPriorityZone;
@ -176,7 +176,7 @@ int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveShared
}
void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
const SlaveSharedData& slaveSharedData,
const WorkerSharedData& workerSharedData,
Node& sendingNode) {
// Trying to read more bytes than available, bail
if (message.getBytesLeftToRead() < qint64(sizeof(AvatarTraits::TraitVersion))) {
@ -221,8 +221,8 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
_avatar->processTrait(traitType, message.read(traitSize));
_lastReceivedTraitVersions[traitType] = packetTraitVersion;
if (traitType == AvatarTraits::SkeletonModelURL) {
// special handling for skeleton model URL, since we need to make sure it is in the whitelist
checkSkeletonURLAgainstWhitelist(slaveSharedData, sendingNode, packetTraitVersion);
// special handling for skeleton model URL, since we need to make sure it is in the allowlist
checkSkeletonURLAgainstAllowlist(workerSharedData, sendingNode, packetTraitVersion);
}
anyTraitsChanged = true;
@ -366,36 +366,36 @@ void AvatarMixerClientData::processBulkAvatarTraitsAckMessage(ReceivedMessage& m
}
}
void AvatarMixerClientData::checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData,
void AvatarMixerClientData::checkSkeletonURLAgainstAllowlist(const WorkerSharedData& workerSharedData,
Node& sendingNode,
AvatarTraits::TraitVersion traitVersion) {
const auto& whitelist = slaveSharedData.skeletonURLWhitelist;
const auto& allowlist = workerSharedData.skeletonURLAllowlist;
if (!whitelist.isEmpty()) {
bool inWhitelist = false;
if (!allowlist.isEmpty()) {
bool inAllowlist = false;
auto avatarURL = _avatar->getSkeletonModelURL();
// The avatar is in the whitelist if:
// 1. The avatar's URL's host matches one of the hosts of the URLs in the whitelist AND
// 2. The avatar's URL's path starts with the path of that same URL in the whitelist
for (const auto& whiteListedPrefix : whitelist) {
auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix);
// check if this script URL matches the whitelist domain and, optionally, is beneath the path
if (avatarURL.host().compare(whiteListURL.host(), Qt::CaseInsensitive) == 0 &&
avatarURL.path().startsWith(whiteListURL.path(), Qt::CaseInsensitive)) {
inWhitelist = true;
// The avatar is in the allowlist if:
// 1. The avatar's URL's host matches one of the hosts of the URLs in the allowlist AND
// 2. The avatar's URL's path starts with the path of that same URL in the allowlist
for (const auto& allowListedPrefix : allowlist) {
auto allowListURL = QUrl::fromUserInput(allowListedPrefix);
// check if this script URL matches the allowlist domain and, optionally, is beneath the path
if (avatarURL.host().compare(allowListURL.host(), Qt::CaseInsensitive) == 0 &&
avatarURL.path().startsWith(allowListURL.path(), Qt::CaseInsensitive)) {
inAllowlist = true;
break;
}
}
if (!inWhitelist) {
if (!inAllowlist) {
// make sure we're not unecessarily overriding the default avatar with the default avatar
if (_avatar->getWireSafeSkeletonModelURL() != slaveSharedData.skeletonReplacementURL) {
if (_avatar->getWireSafeSkeletonModelURL() != workerSharedData.skeletonReplacementURL) {
// we need to change this avatar's skeleton URL, and send them a traits packet informing them of the change
qDebug() << "Overwriting avatar URL" << _avatar->getWireSafeSkeletonModelURL() << "to replacement"
<< slaveSharedData.skeletonReplacementURL << "for" << sendingNode.getUUID();
_avatar->setSkeletonModelURL(slaveSharedData.skeletonReplacementURL);
<< workerSharedData.skeletonReplacementURL << "for" << sendingNode.getUUID();
_avatar->setSkeletonModelURL(workerSharedData.skeletonReplacementURL);
auto packet = NLPacket::create(PacketType::SetAvatarTraits, -1, true);

View file

@ -36,7 +36,7 @@ const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps";
const QString OUTBOUND_AVATAR_TRAITS_STATS_KEY = "outbound_av_traits_kbps";
const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps";
struct SlaveSharedData;
struct WorkerSharedData;
class AvatarMixerClientData : public NodeData {
Q_OBJECT
@ -47,7 +47,7 @@ public:
using PerNodeTraitVersions = std::unordered_map<Node::LocalID, AvatarTraits::TraitVersions>;
using NodeData::parseData; // Avoid clang warning about hiding.
int parseData(ReceivedMessage& message, const SlaveSharedData& SlaveSharedData);
int parseData(ReceivedMessage& message, const WorkerSharedData& WorkerSharedData);
MixerAvatar& getAvatar() { return *_avatar; }
const MixerAvatar& getAvatar() const { return *_avatar; }
const MixerAvatar* getConstAvatarData() const { return _avatar.get(); }
@ -130,12 +130,12 @@ public:
QVector<JointData>& getLastOtherAvatarSentJoints(NLPacket::LocalID otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
int processPackets(const WorkerSharedData& workerSharedData); // returns number of packets processed
void processSetTraitsMessage(ReceivedMessage& message, const SlaveSharedData& slaveSharedData, Node& sendingNode);
void processSetTraitsMessage(ReceivedMessage& message, const WorkerSharedData& workerSharedData, Node& sendingNode);
void emulateDeleteEntitiesTraitsMessage(const QList<QUuid>& avatarEntityIDs);
void processBulkAvatarTraitsAckMessage(ReceivedMessage& message);
void checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData, Node& sendingNode,
void checkSkeletonURLAgainstAllowlist(const WorkerSharedData& workerSharedData, Node& sendingNode,
AvatarTraits::TraitVersion traitVersion);
using TraitsCheckTimestamp = std::chrono::steady_clock::time_point;

View file

@ -1,5 +1,5 @@
//
// AvatarMixerSlave.cpp
// AvatarMixerWorker.cpp
// assignment-client/src/avatar
//
// Created by Brad Hefta-Gaub on 2/14/2017.
@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AvatarMixerSlave.h"
#include "AvatarMixerWorker.h"
#include <algorithm>
#include <random>
@ -36,12 +36,12 @@
namespace chrono = std::chrono;
void AvatarMixerSlave::configure(ConstIter begin, ConstIter end) {
void AvatarMixerWorker::configure(ConstIter begin, ConstIter end) {
_begin = begin;
_end = end;
}
void AvatarMixerSlave::configureBroadcast(ConstIter begin, ConstIter end,
void AvatarMixerWorker::configureBroadcast(ConstIter begin, ConstIter end,
p_high_resolution_clock::time_point lastFrameTimestamp,
float maxKbpsPerNode, float throttlingRatio,
float priorityReservedFraction) {
@ -53,13 +53,13 @@ void AvatarMixerSlave::configureBroadcast(ConstIter begin, ConstIter end,
_avatarHeroFraction = priorityReservedFraction;
}
void AvatarMixerSlave::harvestStats(AvatarMixerSlaveStats& stats) {
void AvatarMixerWorker::harvestStats(AvatarMixerWorkerStats& stats) {
stats = _stats;
_stats.reset();
}
void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
void AvatarMixerWorker::processIncomingPackets(const SharedNodePointer& node) {
auto start = usecTimestampNow();
auto nodeData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData());
if (nodeData) {
@ -70,7 +70,7 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
_stats.processIncomingPacketsElapsedTime += (end - start);
}
int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
int AvatarMixerWorker::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
if (destinationNode.getType() == NodeType::Agent && !destinationNode.isUpstream()) {
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
@ -83,7 +83,7 @@ int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarM
}
}
qint64 AvatarMixerSlave::addTraitsNodeHeader(AvatarMixerClientData* listeningNodeData,
qint64 AvatarMixerWorker::addTraitsNodeHeader(AvatarMixerClientData* listeningNodeData,
const AvatarMixerClientData* sendingNodeData,
NLPacketList& traitsPacketList,
qint64 bytesWritten) {
@ -98,7 +98,7 @@ qint64 AvatarMixerSlave::addTraitsNodeHeader(AvatarMixerClientData* listeningNod
return bytesWritten;
}
qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
qint64 AvatarMixerWorker::addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
const AvatarMixerClientData* sendingNodeData,
NLPacketList& traitsPacketList) {
@ -245,7 +245,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
return bytesWritten;
}
int AvatarMixerSlave::sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
int AvatarMixerWorker::sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
if (AvatarMixer::shouldReplicateTo(agentNode, destinationNode)) {
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(true);
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
@ -262,7 +262,7 @@ int AvatarMixerSlave::sendReplicatedIdentityPacket(const Node& agentNode, const
static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45;
void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) {
void AvatarMixerWorker::broadcastAvatarData(const SharedNodePointer& node) {
quint64 start = usecTimestampNow();
if ((node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) && node->getLinkedData() && node->getActiveSocket() && !node->isUpstream()) {
@ -311,7 +311,7 @@ namespace {
} // Close anonymous namespace.
void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) {
void AvatarMixerWorker::broadcastAvatarDataToAgent(const SharedNodePointer& node) {
const Node* destinationNode = node.data();
auto nodeList = DependencyManager::get<NodeList>();
@ -680,7 +680,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
uint64_t REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US = 5 * 1000 * 1000;
void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node) {
void AvatarMixerWorker::broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node) {
_stats.downstreamMixersBroadcastedTo++;
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());

View file

@ -1,5 +1,5 @@
//
// AvatarMixerSlave.h
// AvatarMixerWorker.h
// assignment-client/src/avatar
//
// Created by Brad Hefta-Gaub on 2/14/2017.
@ -9,14 +9,14 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AvatarMixerSlave_h
#define hifi_AvatarMixerSlave_h
#ifndef hifi_AvatarMixerWorker_h
#define hifi_AvatarMixerWorker_h
#include <NodeList.h>
class AvatarMixerClientData;
class AvatarMixerSlaveStats {
class AvatarMixerWorkerStats {
public:
int nodesProcessed { 0 };
int packetsProcessed { 0 };
@ -67,7 +67,7 @@ public:
jobElapsedTime = 0;
}
AvatarMixerSlaveStats& operator+=(const AvatarMixerSlaveStats& rhs) {
AvatarMixerWorkerStats& operator+=(const AvatarMixerWorkerStats& rhs) {
nodesProcessed += rhs.nodesProcessed;
packetsProcessed += rhs.packetsProcessed;
processIncomingPacketsElapsedTime += rhs.processIncomingPacketsElapsedTime;
@ -96,15 +96,15 @@ public:
class EntityTree;
using EntityTreePointer = std::shared_ptr<EntityTree>;
struct SlaveSharedData {
QStringList skeletonURLWhitelist;
struct WorkerSharedData {
QStringList skeletonURLAllowlist;
QUrl skeletonReplacementURL;
EntityTreePointer entityTree;
};
class AvatarMixerSlave {
class AvatarMixerWorker {
public:
AvatarMixerSlave(SlaveSharedData* sharedData) : _sharedData(sharedData) {};
AvatarMixerWorker(WorkerSharedData* sharedData) : _sharedData(sharedData) {};
using ConstIter = NodeList::const_iterator;
void configure(ConstIter begin, ConstIter end);
@ -116,7 +116,7 @@ public:
void processIncomingPackets(const SharedNodePointer& node);
void broadcastAvatarData(const SharedNodePointer& node);
void harvestStats(AvatarMixerSlaveStats& stats);
void harvestStats(AvatarMixerWorkerStats& stats);
private:
int sendIdentityPacket(NLPacketList& packet, const AvatarMixerClientData* nodeData, const Node& destinationNode);
@ -143,8 +143,8 @@ private:
float _throttlingRatio { 0.0f };
float _avatarHeroFraction { 0.4f };
AvatarMixerSlaveStats _stats;
SlaveSharedData* _sharedData;
AvatarMixerWorkerStats _stats;
WorkerSharedData* _sharedData;
};
#endif // hifi_AvatarMixerSlave_h
#endif // hifi_AvatarMixerWorker_h

View file

@ -1,5 +1,5 @@
//
// AvatarMixerSlavePool.cpp
// AvatarMixerWorkerPool.cpp
// assignment-client/src/avatar
//
// Created by Brad Hefta-Gaub on 2/14/2017.
@ -9,12 +9,12 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AvatarMixerSlavePool.h"
#include "AvatarMixerWorkerPool.h"
#include <assert.h>
#include <algorithm>
void AvatarMixerSlaveThread::run() {
void AvatarMixerWorkerThread::run() {
while (true) {
wait();
@ -32,10 +32,10 @@ void AvatarMixerSlaveThread::run() {
}
}
void AvatarMixerSlaveThread::wait() {
void AvatarMixerWorkerThread::wait() {
{
Lock lock(_pool._mutex);
_pool._slaveCondition.wait(lock, [&] {
_pool._workerCondition.wait(lock, [&] {
assert(_pool._numStarted <= _pool._numThreads);
return _pool._numStarted != _pool._numThreads;
});
@ -47,7 +47,7 @@ void AvatarMixerSlaveThread::wait() {
_function = _pool._function;
}
void AvatarMixerSlaveThread::notify(bool stopping) {
void AvatarMixerWorkerThread::notify(bool stopping) {
{
Lock lock(_pool._mutex);
assert(_pool._numFinished < _pool._numThreads);
@ -59,30 +59,30 @@ void AvatarMixerSlaveThread::notify(bool stopping) {
_pool._poolCondition.notify_one();
}
bool AvatarMixerSlaveThread::try_pop(SharedNodePointer& node) {
bool AvatarMixerWorkerThread::try_pop(SharedNodePointer& node) {
return _pool._queue.try_pop(node);
}
void AvatarMixerSlavePool::processIncomingPackets(ConstIter begin, ConstIter end) {
_function = &AvatarMixerSlave::processIncomingPackets;
_configure = [=](AvatarMixerSlave& slave) {
slave.configure(begin, end);
void AvatarMixerWorkerPool::processIncomingPackets(ConstIter begin, ConstIter end) {
_function = &AvatarMixerWorker::processIncomingPackets;
_configure = [=](AvatarMixerWorker& worker) {
worker.configure(begin, end);
};
run(begin, end);
}
void AvatarMixerSlavePool::broadcastAvatarData(ConstIter begin, ConstIter end,
void AvatarMixerWorkerPool::broadcastAvatarData(ConstIter begin, ConstIter end,
p_high_resolution_clock::time_point lastFrameTimestamp,
float maxKbpsPerNode, float throttlingRatio) {
_function = &AvatarMixerSlave::broadcastAvatarData;
_configure = [=](AvatarMixerSlave& slave) {
slave.configureBroadcast(begin, end, lastFrameTimestamp, maxKbpsPerNode, throttlingRatio,
_function = &AvatarMixerWorker::broadcastAvatarData;
_configure = [=](AvatarMixerWorker& worker) {
worker.configureBroadcast(begin, end, lastFrameTimestamp, maxKbpsPerNode, throttlingRatio,
_priorityReservedFraction);
};
run(begin, end);
}
void AvatarMixerSlavePool::run(ConstIter begin, ConstIter end) {
void AvatarMixerWorkerPool::run(ConstIter begin, ConstIter end) {
_begin = begin;
_end = end;
@ -96,7 +96,7 @@ void AvatarMixerSlavePool::run(ConstIter begin, ConstIter end) {
// run
_numStarted = _numFinished = 0;
_slaveCondition.notify_all();
_workerCondition.notify_all();
// wait
_poolCondition.wait(lock, [&] {
@ -111,17 +111,17 @@ void AvatarMixerSlavePool::run(ConstIter begin, ConstIter end) {
}
void AvatarMixerSlavePool::each(std::function<void(AvatarMixerSlave& slave)> functor) {
for (auto& slave : _slaves) {
functor(*slave.get());
void AvatarMixerWorkerPool::each(std::function<void(AvatarMixerWorker& worker)> functor) {
for (auto& worker : _workers) {
functor(*worker.get());
}
}
#ifdef DEBUG_EVENT_QUEUE
void AvatarMixerSlavePool::queueStats(QJsonObject& stats) {
void AvatarMixerWorkerPool::queueStats(QJsonObject& stats) {
unsigned i = 0;
for (auto& slave : _slaves) {
int queueSize = ::hifi::qt::getEventQueueSize(slave.get());
for (auto& worker : _workers) {
int queueSize = ::hifi::qt::getEventQueueSize(worker.get());
QString queueName = QString("avatar_thread_event_queue_%1").arg(i);
stats[queueName] = queueSize;
@ -130,7 +130,7 @@ void AvatarMixerSlavePool::queueStats(QJsonObject& stats) {
}
#endif // DEBUG_EVENT_QUEUE
void AvatarMixerSlavePool::setNumThreads(int numThreads) {
void AvatarMixerWorkerPool::setNumThreads(int numThreads) {
// clamp to allowed size
{
int maxThreads = QThread::idealThreadCount();
@ -150,35 +150,35 @@ void AvatarMixerSlavePool::setNumThreads(int numThreads) {
resize(numThreads);
}
void AvatarMixerSlavePool::resize(int numThreads) {
assert(_numThreads == (int)_slaves.size());
void AvatarMixerWorkerPool::resize(int numThreads) {
assert(_numThreads == (int)_workers.size());
qDebug("%s: set %d threads (was %d)", __FUNCTION__, numThreads, _numThreads);
Lock lock(_mutex);
if (numThreads > _numThreads) {
// start new slaves
// start new workers
for (int i = 0; i < numThreads - _numThreads; ++i) {
auto slave = new AvatarMixerSlaveThread(*this, _slaveSharedData);
slave->start();
_slaves.emplace_back(slave);
auto worker = new AvatarMixerWorkerThread(*this, _workerSharedData);
worker->start();
_workers.emplace_back(worker);
}
} else if (numThreads < _numThreads) {
auto extraBegin = _slaves.begin() + numThreads;
auto extraBegin = _workers.begin() + numThreads;
// mark slaves to stop...
auto slave = extraBegin;
while (slave != _slaves.end()) {
(*slave)->_stop = true;
++slave;
// mark workers to stop...
auto worker = extraBegin;
while (worker != _workers.end()) {
(*worker)->_stop = true;
++worker;
}
// ...cycle them until they do stop...
_numStopped = 0;
while (_numStopped != (_numThreads - numThreads)) {
_numStarted = _numFinished = _numStopped;
_slaveCondition.notify_all();
_workerCondition.notify_all();
_poolCondition.wait(lock, [&] {
assert(_numFinished <= _numThreads);
return _numFinished == _numThreads;
@ -186,18 +186,18 @@ void AvatarMixerSlavePool::resize(int numThreads) {
}
// ...wait for threads to finish...
slave = extraBegin;
while (slave != _slaves.end()) {
QThread* thread = reinterpret_cast<QThread*>(slave->get());
worker = extraBegin;
while (worker != _workers.end()) {
QThread* thread = reinterpret_cast<QThread*>(worker->get());
static const int MAX_THREAD_WAIT_TIME = 10;
thread->wait(MAX_THREAD_WAIT_TIME);
++slave;
++worker;
}
// ...and erase them
_slaves.erase(extraBegin, _slaves.end());
_workers.erase(extraBegin, _workers.end());
}
_numThreads = _numStarted = _numFinished = numThreads;
assert(_numThreads == (int)_slaves.size());
assert(_numThreads == (int)_workers.size());
}

View file

@ -1,5 +1,5 @@
//
// AvatarMixerSlavePool.h
// AvatarMixerWorkerPool.h
// assignment-client/src/avatar
//
// Created by Brad Hefta-Gaub on 2/14/2017.
@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AvatarMixerSlavePool_h
#define hifi_AvatarMixerSlavePool_h
#ifndef hifi_AvatarMixerWorkerPool_h
#define hifi_AvatarMixerWorkerPool_h
#include <condition_variable>
#include <mutex>
@ -22,38 +22,38 @@
#include <NodeList.h>
#include <shared/QtHelpers.h>
#include "AvatarMixerSlave.h"
#include "AvatarMixerWorker.h"
class AvatarMixerSlavePool;
class AvatarMixerWorkerPool;
class AvatarMixerSlaveThread : public QThread, public AvatarMixerSlave {
class AvatarMixerWorkerThread : public QThread, public AvatarMixerWorker {
Q_OBJECT
using ConstIter = NodeList::const_iterator;
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
public:
AvatarMixerSlaveThread(AvatarMixerSlavePool& pool, SlaveSharedData* slaveSharedData) :
AvatarMixerSlave(slaveSharedData), _pool(pool) {};
AvatarMixerWorkerThread(AvatarMixerWorkerPool& pool, WorkerSharedData* workerSharedData) :
AvatarMixerWorker(workerSharedData), _pool(pool) {};
void run() override final;
private:
friend class AvatarMixerSlavePool;
friend class AvatarMixerWorkerPool;
void wait();
void notify(bool stopping);
bool try_pop(SharedNodePointer& node);
AvatarMixerSlavePool& _pool;
void (AvatarMixerSlave::*_function)(const SharedNodePointer& node) { nullptr };
AvatarMixerWorkerPool& _pool;
void (AvatarMixerWorker::*_function)(const SharedNodePointer& node) { nullptr };
bool _stop { false };
};
// Slave pool for avatar mixers
// AvatarMixerSlavePool is not thread-safe! It should be instantiated and used from a single thread.
class AvatarMixerSlavePool {
// Worker pool for avatar mixers
// AvatarMixerWorkerPool is not thread-safe! It should be instantiated and used from a single thread.
class AvatarMixerWorkerPool {
using Queue = tbb::concurrent_queue<SharedNodePointer>;
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
@ -62,17 +62,17 @@ class AvatarMixerSlavePool {
public:
using ConstIter = NodeList::const_iterator;
AvatarMixerSlavePool(SlaveSharedData* slaveSharedData, int numThreads = QThread::idealThreadCount()) :
_slaveSharedData(slaveSharedData) { setNumThreads(numThreads); }
~AvatarMixerSlavePool() { resize(0); }
AvatarMixerWorkerPool(WorkerSharedData* workerSharedData, int numThreads = QThread::idealThreadCount()) :
_workerSharedData(workerSharedData) { setNumThreads(numThreads); }
~AvatarMixerWorkerPool() { resize(0); }
// Jobs the slave pool can do...
// Jobs the worker pool can do...
void processIncomingPackets(ConstIter begin, ConstIter end);
void broadcastAvatarData(ConstIter begin, ConstIter end,
p_high_resolution_clock::time_point lastFrameTimestamp, float maxKbpsPerNode, float throttlingRatio);
// iterate over all slaves
void each(std::function<void(AvatarMixerSlave& slave)> functor);
// iterate over all workers
void each(std::function<void(AvatarMixerWorker& worker)> functor);
#ifdef DEBUG_EVENT_QUEUE
void queueStats(QJsonObject& stats);
@ -88,18 +88,18 @@ private:
void run(ConstIter begin, ConstIter end);
void resize(int numThreads);
std::vector<std::unique_ptr<AvatarMixerSlaveThread>> _slaves;
std::vector<std::unique_ptr<AvatarMixerWorkerThread>> _workers;
friend void AvatarMixerSlaveThread::wait();
friend void AvatarMixerSlaveThread::notify(bool stopping);
friend bool AvatarMixerSlaveThread::try_pop(SharedNodePointer& node);
friend void AvatarMixerWorkerThread::wait();
friend void AvatarMixerWorkerThread::notify(bool stopping);
friend bool AvatarMixerWorkerThread::try_pop(SharedNodePointer& node);
// synchronization state
Mutex _mutex;
ConditionVariable _slaveCondition;
ConditionVariable _workerCondition;
ConditionVariable _poolCondition;
void (AvatarMixerSlave::*_function)(const SharedNodePointer& node);
std::function<void(AvatarMixerSlave&)> _configure;
void (AvatarMixerWorker::*_function)(const SharedNodePointer& node);
std::function<void(AvatarMixerWorker&)> _configure;
// Set from Domain Settings:
float _priorityReservedFraction { 0.4f };
@ -114,7 +114,7 @@ private:
ConstIter _begin;
ConstIter _end;
SlaveSharedData* _slaveSharedData;
WorkerSharedData* _workerSharedData;
};
#endif // hifi_AvatarMixerSlavePool_h
#endif // hifi_AvatarMixerWorkerPool_h

View file

@ -320,11 +320,11 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
tree->setWantEditLogging(wantEditLogging);
tree->setWantTerseEditLogging(wantTerseEditLogging);
QString entityScriptSourceWhitelist;
if (readOptionString("entityScriptSourceWhitelist", settingsSectionObject, entityScriptSourceWhitelist)) {
tree->setEntityScriptSourceWhitelist(entityScriptSourceWhitelist);
QString entityScriptSourceAllowlist;
if (readOptionString("entityScriptSourceAllowlist", settingsSectionObject, entityScriptSourceAllowlist)) {
tree->setEntityScriptSourceAllowlist(entityScriptSourceAllowlist);
} else {
tree->setEntityScriptSourceWhitelist("");
tree->setEntityScriptSourceAllowlist("");
}
auto entityEditFilters = DependencyManager::get<EntityEditFilters>();

View file

@ -26,7 +26,7 @@ macro(SET_PACKAGING_PARAMETERS)
set_from_env(STABLE_BUILD STABLE_BUILD 0)
set_from_env(PRELOADED_STARTUP_LOCATION PRELOADED_STARTUP_LOCATION "")
set_from_env(PRELOADED_SCRIPT_WHITELIST PRELOADED_SCRIPT_WHITELIST "")
set_from_env(PRELOADED_SCRIPT_ALLOWLIST PRELOADED_SCRIPT_ALLOWLIST "")
set_from_env(BYPASS_SIGNING BYPASS_SIGNING 0)

View file

@ -29,7 +29,7 @@ namespace BuildInfo {
const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@";
const QString BUILD_TIME = "@BUILD_TIME@";
const QString PRELOADED_STARTUP_LOCATION = "@PRELOADED_STARTUP_LOCATION@";
const QString PRELOADED_SCRIPT_WHITELIST = "@PRELOADED_SCRIPT_WHITELIST@";
const QString PRELOADED_SCRIPT_ALLOWLIST = "@PRELOADED_SCRIPT_ALLOWLIST@";
enum BuildType {
Dev,

View file

@ -178,7 +178,7 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin
}
// If this user is a known member of a domain group, give them the implied permissions.
// Do before processing verifiedUsername in case user is logged into the Directory Services and is a member of a blacklist group.
// Do before processing verifiedUsername in case user is logged into the Directory Services and is a member of a blocklist group.
if (!verifiedDomainUserName.isEmpty()) {
auto userGroups = _domainGroupMemberships[verifiedDomainUserName];
foreach (QString userGroup, userGroups) {
@ -277,8 +277,8 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin
}
}
// if this user is a known member of a blacklist group, remove the implied permissions
foreach (QUuid groupID, _server->_settingsManager.getBlacklistGroupIDs()) {
// if this user is a known member of a blocklist group, remove the implied permissions
foreach (QUuid groupID, _server->_settingsManager.getBlocklistGroupIDs()) {
QUuid rankID = _server->_settingsManager.isGroupMember(verifiedUsername, groupID);
if (rankID != QUuid()) {
QUuid rankID = _server->_settingsManager.isGroupMember(verifiedUsername, groupID);
@ -287,7 +287,7 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin
GroupRank rank = _server->_settingsManager.getGroupRank(groupID, rankID);
#ifdef WANT_DEBUG
qDebug() << "| user-permissions: user is in blacklist group:" << groupID << " rank:" << rank.name
qDebug() << "| user-permissions: user is in blocklist group:" << groupID << " rank:" << rank.name
<< "so:" << userPerms;
#endif
}
@ -299,20 +299,20 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin
userPerms.setVerifiedUserName(verifiedUsername);
}
// If this user is a known member of an domain group that is blacklisted, remove the implied permissions.
// If this user is a known member of an domain group that is blocklisted, remove the implied permissions.
if (!verifiedDomainUserName.isEmpty()) {
auto userGroups = _domainGroupMemberships[verifiedDomainUserName];
foreach(QString userGroup, userGroups) {
// A domain group is signified by a leading special character, "@".
// Multiple domain groups may be specified in one domain server setting as a comma- and/or space-separated lists of
// domain group names. For example, "@silver @Gold, @platinum".
auto domainGroups = _server->_settingsManager.getDomainServerBlacklistGroupNames()
auto domainGroups = _server->_settingsManager.getDomainServerBlocklistGroupNames()
.filter(QRegularExpression("^(.*[\\s,])?" + QRegularExpression::escape(userGroup) + "([\\s,].*)?$",
QRegularExpression::CaseInsensitiveOption));
foreach(QString domainGroup, domainGroups) {
userPerms &= ~_server->_settingsManager.getForbiddensForGroup(domainGroup, QUuid());
#ifdef WANT_DEBUG
qDebug() << "| user-permissions: domain user is in blacklist group:" << domainGroup << "so:" << userPerms;
qDebug() << "| user-permissions: domain user is in blocklist group:" << domainGroup << "so:" << userPerms;
#endif
}
}
@ -1027,7 +1027,7 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) {
QJsonObject json;
QSet<QString> groupIDSet;
foreach (QUuid groupID, _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlacklistGroupIDs()) {
foreach (QUuid groupID, _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlocklistGroupIDs()) {
groupIDSet += groupID.toString().mid(1,36);
}

View file

@ -341,17 +341,17 @@ DomainServer::DomainServer(int argc, char* argv[]) :
connect(&_settingsManager, &DomainServerSettingsManager::updateNodePermissions, [this] { _metadata->securityChanged(true); });
qDebug() << "domain-server is running";
static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist";
static const QString AC_SUBNET_ALLOWLIST_SETTING_PATH = "security.ac_subnet_allowlist";
static const Subnet LOCALHOST { QHostAddress("127.0.0.1"), 32 };
_acSubnetWhitelist = { LOCALHOST };
_acSubnetAllowlist = { LOCALHOST };
auto whitelist = _settingsManager.valueOrDefaultValueForKeyPath(AC_SUBNET_WHITELIST_SETTING_PATH).toStringList();
for (auto& subnet : whitelist) {
auto allowlist = _settingsManager.valueOrDefaultValueForKeyPath(AC_SUBNET_ALLOWLIST_SETTING_PATH).toStringList();
for (auto& subnet : allowlist) {
auto netmaskParts = subnet.trimmed().split("/");
if (netmaskParts.size() > 2) {
qDebug() << "Ignoring subnet in whitelist, malformed: " << subnet;
qDebug() << "Ignoring subnet in allowlist, malformed: " << subnet;
continue;
}
@ -363,7 +363,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
bool ok;
netmask = netmaskParts[1].toInt(&ok);
if (!ok) {
qDebug() << "Ignoring subnet in whitelist, bad netmask: " << subnet;
qDebug() << "Ignoring subnet in allowlist, bad netmask: " << subnet;
continue;
}
}
@ -371,10 +371,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
auto ip = QHostAddress(netmaskParts[0]);
if (!ip.isNull()) {
qDebug() << "Adding AC whitelist subnet: " << subnet << " -> " << (ip.toString() + "/" + QString::number(netmask));
_acSubnetWhitelist.push_back({ ip , netmask });
qDebug() << "Adding AC allowlist subnet: " << subnet << " -> " << (ip.toString() + "/" + QString::number(netmask));
_acSubnetAllowlist.push_back({ ip , netmask });
} else {
qDebug() << "Ignoring subnet in whitelist, invalid ip portion: " << subnet;
qDebug() << "Ignoring subnet in allowlist, invalid ip portion: " << subnet;
}
}
@ -1502,8 +1502,8 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer<ReceivedMessage
return senderAddr.isInSubnet(mask);
};
auto it = find_if(_acSubnetWhitelist.begin(), _acSubnetWhitelist.end(), isHostAddressInSubnet);
if (it == _acSubnetWhitelist.end()) {
auto it = find_if(_acSubnetAllowlist.begin(), _acSubnetAllowlist.end(), isHostAddressInSubnet);
if (it == _acSubnetAllowlist.end()) {
HIFI_FDEBUG("Received an assignment connect request from a disallowed ip address:"
<< senderAddr.toString());
return;

View file

@ -251,7 +251,7 @@ private:
QString operationToString(const QNetworkAccessManager::Operation &op);
SubnetList _acSubnetWhitelist;
SubnetList _acSubnetAllowlist;
std::vector<QString> _replicatedUsernames;

View file

@ -172,20 +172,20 @@ static const QMap<QString, DomainServerExporter::MetricType> TYPE_MAP {
{ "avatar_mixer_single_core_tasks_process_events" , DomainServerExporter::MetricType::Counter },
{ "avatar_mixer_single_core_tasks_queue_incoming_packet" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_single_core_tasks_send_stats" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_received_1_nodes_processed" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_1_nodes_broadcasted_to" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_2_average_others_included" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_3_average_over_budget_avatars" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_4_average_data_bytes" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_5_average_traits_bytes" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_6_average_identity_bytes" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_sent_7_average_hero_avatars" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_timing_1_process_incoming_packets" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_timing_2_ignore_calculation" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_timing_3_to_byte_array" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_timing_4_avatar_data_packing" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_timing_5_packet_sending" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_slaves_aggregate_per_frame_timing_6_job_elapsed_time" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_received_1_nodes_processed" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_1_nodes_broadcasted_to" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_2_average_others_included" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_3_average_over_budget_avatars" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_4_average_data_bytes" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_5_average_traits_bytes" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_6_average_identity_bytes" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_sent_7_average_hero_avatars" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_timing_1_process_incoming_packets" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_timing_2_ignore_calculation" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_timing_3_to_byte_array" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_timing_4_avatar_data_packing" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_timing_5_packet_sending" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_workers_aggregate_per_frame_timing_6_job_elapsed_time" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_threads" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_throttling_ratio" , DomainServerExporter::MetricType::Gauge },
{ "avatar_mixer_trailing_mix_ratio" , DomainServerExporter::MetricType::Gauge },
@ -254,9 +254,9 @@ static const QMap<QString, DomainServerExporter::MetricType> TYPE_MAP {
//
// For numeric values with an unit, instead of trying to parse it, the stats will just need to
// have a second copy of the metric added, with the value expressed as a number, with the original
// being blacklisted here.
// being blocklisted here.
static const QSet<QString> BLACKLIST = {
static const QSet<QString> BLOCKLIST = {
"asset_server_connection_stats_last_heard", // Timestamp as a string
"asset_server_username", // Username
"audio_mixer_listeners_jitter_downstream_avg_gap", // Number as string with unit name, alternative added
@ -379,7 +379,7 @@ void DomainServerExporter::generateMetricsFromJson(QTextStream& stream,
continue;
}
if (BLACKLIST.contains(metricName)) {
if (BLOCKLIST.contains(metricName)) {
continue;
}

View file

@ -688,7 +688,7 @@ void DomainServerSettingsManager::packPermissions() {
// save settings for groups
packPermissionsForMap("permissions", _groupPermissions, GROUP_PERMISSIONS_KEYPATH);
// save settings for blacklist groups
// save settings for blocklist groups
packPermissionsForMap("permissions", _groupForbiddens, GROUP_FORBIDDENS_KEYPATH);
persistToFile();
@ -869,7 +869,7 @@ bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() {
}
}
QList<QUuid> forbiddenGroupIDs = getBlacklistGroupIDs();
QList<QUuid> forbiddenGroupIDs = getBlocklistGroupIDs();
foreach (QUuid groupID, forbiddenGroupIDs) {
QString groupName = _groupNames[groupID];
QHash<QUuid, GroupRank>& ranksForGroup = _groupRanks[groupID];
@ -1743,7 +1743,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
QJsonObject postedObject(postedSettingsObject);
static const QString SECURITY_ROOT_KEY = "security";
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
static const QString AC_SUBNET_ALLOWLIST_KEY = "ac_subnet_allowlist";
static const QString BROADCASTING_KEY = "broadcasting";
static const QString WIZARD_KEY = "wizard";
static const QString DESCRIPTION_ROOT_KEY = "descriptors";
@ -1863,7 +1863,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY &&
rootKey != DESCRIPTION_ROOT_KEY && rootKey != WIZARD_KEY) ||
settingKey == AC_SUBNET_WHITELIST_KEY) {
settingKey == AC_SUBNET_ALLOWLIST_KEY) {
needRestart = true;
}
} else {
@ -2038,7 +2038,7 @@ void DomainServerSettingsManager::apiRefreshGroupInformation() {
}
if (_groupIDs.contains(lowerGroupName)) {
// we already know about this one. recall setGroupID in case the group has been
// added to another section (the same group is found in both groups and blacklists).
// added to another section (the same group is found in both groups and blocklists).
changed = setGroupID(groupName, _groupIDs[lowerGroupName]);
continue;
}
@ -2245,7 +2245,7 @@ QList<QUuid> DomainServerSettingsManager::getGroupIDs() {
return result.values();
}
QList<QUuid> DomainServerSettingsManager::getBlacklistGroupIDs() {
QList<QUuid> DomainServerSettingsManager::getBlocklistGroupIDs() {
QSet<QUuid> result;
foreach (NodePermissionsKey groupKey, _groupForbiddens.keys()) {
if (_groupForbiddens[groupKey]->isGroup()) {
@ -2264,7 +2264,7 @@ QStringList DomainServerSettingsManager::getDomainServerGroupNames() {
return result.values();
}
QStringList DomainServerSettingsManager::getDomainServerBlacklistGroupNames() {
QStringList DomainServerSettingsManager::getDomainServerBlocklistGroupNames() {
// All names as listed in the domain server settings; not necessarily Directory Services groups.
QSet<QString> result;
foreach (NodePermissionsKey groupKey, _groupForbiddens.keys()) {

View file

@ -135,10 +135,10 @@ public:
GroupRank getGroupRank(QUuid groupID, QUuid rankID) { return _groupRanks[groupID][rankID]; }
QList<QUuid> getGroupIDs();
QList<QUuid> getBlacklistGroupIDs();
QList<QUuid> getBlocklistGroupIDs();
QStringList getDomainServerGroupNames();
QStringList getDomainServerBlacklistGroupNames();
QStringList getDomainServerBlocklistGroupNames();
// these are used to locally cache the result of calling "/api/v1/groups/.../is_member/..." on Directory Services api
void clearGroupMemberships(const QString& name) { _groupMembership[name.toLower()].clear(); }

View file

@ -4,6 +4,7 @@
// Created by Wayne Chen on 10/18/18
// Copyright 2018 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
@ -377,13 +378,13 @@ Item {
}
}
function onHandleLoginCompleted(): {
function onHandleLoginCompleted() {
console.log("Login Succeeded");
loggingInBody.loadingSuccess();
}
function onHandleLoginFailed() {
console.log("Login Failed")
console.log("Login Failed");
loggingInSpinner.visible = false;
loggingInGlyph.visible = false;
var errorString = "";

View file

@ -354,7 +354,7 @@ Rectangle {
font: avatarGainSliderText.font
}
RalewayRegular {
// The slider for my card is special, it controls the master gain
// The slider for my card is special, it controls the primary gain
id: avatarGainSliderText;
text: "People volume";
size: 16;
@ -645,7 +645,7 @@ Rectangle {
font: noiseReductionThresholdSliderText.font
}
RalewayRegular {
// The slider for my card is special, it controls the master gain
// The slider for my card is special, it controls the primary gain
id: noiseReductionThresholdSliderText;
text: "Audio input threshold";
size: 16;

View file

@ -1,5 +1,5 @@
//
// EntityScriptQMLWhitelist.qml
// EntityScriptQMLAllowlist.qml
// interface/resources/qml/hifi/dialogs/security
//
// Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com
@ -8,7 +8,7 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Security Settings for the Entity Script QML Whitelist
// Security Settings for the Entity Script QML Allowlist
import Hifi 1.0 as Hifi
import QtQuick 2.8
@ -23,25 +23,25 @@ import "../../../windows"
Rectangle {
id: parentBody;
function getWhitelistAsText() {
var whitelist = Settings.getValue("private/settingsSafeURLS");
var arrayWhitelist = whitelist.split(",").join("\n");
return arrayWhitelist;
function getAllowlistAsText() {
var allowlist = Settings.getValue("private/settingsSafeURLS");
var arrayAllowlist = allowlist.split(",").join("\n");
return arrayAllowlist;
}
function setWhitelistAsText(whitelistText) {
Settings.setValue("private/settingsSafeURLS", whitelistText.text);
function setAllowlistAsText(allowlistText) {
Settings.setValue("private/settingsSafeURLS", allowlistText.text);
var originalSetString = whitelistText.text;
var originalSetString = allowlistText.text;
var originalSet = originalSetString.split(' ').join('');
var check = Settings.getValue("private/settingsSafeURLS");
var arrayCheck = check.split(",").join("\n");
setWhitelistSuccess(arrayCheck === originalSet);
setAllowlistSuccess(arrayCheck === originalSet);
}
function setWhitelistSuccess(success) {
function setAllowlistSuccess(success) {
if (success) {
notificationText.text = "Successfully saved settings.";
} else {
@ -49,20 +49,20 @@ Rectangle {
}
}
function toggleWhitelist(enabled) {
Settings.setValue("private/whitelistEnabled", enabled);
console.info("Toggling Whitelist to:", enabled);
function toggleAllowlist(enabled) {
Settings.setValue("private/allowlistEnabled", enabled);
console.info("Toggling Allowlist to:", enabled);
}
function initCheckbox() {
var check = Settings.getValue("private/whitelistEnabled", false);
var check = Settings.getValue("private/allowlistEnabled", false);
if (check) {
whitelistEnabled.toggle();
allowlistEnabled.toggle();
}
}
anchors.fill: parent
width: parent.width;
height: 120;
@ -70,7 +70,7 @@ Rectangle {
HifiStylesUit.RalewayRegular {
id: titleText;
text: "Entity Script / QML Whitelist"
text: "Entity Script / QML Allowlist"
// Text size
size: 24;
// Style
@ -89,13 +89,13 @@ Rectangle {
initCheckbox();
}
id: whitelistEnabled;
id: allowlistEnabled;
anchors.right: parent.right;
anchors.top: parent.top;
anchors.topMargin: 10;
onToggled: {
toggleWhitelist(whitelistEnabled.checked)
toggleAllowlist(allowlistEnabled.checked)
}
Label {
@ -115,7 +115,7 @@ Rectangle {
width: parent.width;
height: 250;
anchors.top: titleText.bottom;
ScrollView {
id: textAreaScrollView
anchors.fill: parent;
@ -126,8 +126,8 @@ Rectangle {
clip: false;
TextArea {
id: whitelistTextArea
text: getWhitelistAsText();
id: allowlistTextArea
text: getAllowlistAsText();
onTextChanged: notificationText.text = "";
width: parent.width;
height: parent.height;
@ -136,7 +136,7 @@ Rectangle {
color: "white";
}
}
Button {
id: saveChanges
anchors.topMargin: 5;
@ -155,8 +155,8 @@ Rectangle {
elide: Text.ElideRight
}
text: "Save Changes"
onClicked: setWhitelistAsText(whitelistTextArea)
onClicked: setAllowlistAsText(allowlistTextArea)
HifiStylesUit.RalewayRegular {
id: notificationText;
text: ""
@ -170,15 +170,15 @@ Rectangle {
anchors.rightMargin: 10;
}
}
HifiStylesUit.RalewayRegular {
id: descriptionText;
text:
"The whitelist checks scripts and QML as they are loaded.<br/>
text:
"The allowlist checks scripts and QML as they are loaded.<br/>
Therefore, if a script is cached or has no reason to load again,<br/>
removing it from the whitelist will have no effect until<br/>
removing it from the allowlist will have no effect until<br/>
it is reloaded.<br/>
Separate your whitelisted domains by line, not commas. e.g.
Separate your allowlisted domains by line, not commas. e.g.
<blockquote>
<b>https://google.com/</b><br/>
<b>hifi://the-spot/</b><br/>
@ -186,7 +186,7 @@ Rectangle {
<b>https://mydomain.here/</b>
</blockquote>
Ensure there are no spaces or whitespace.<br/><br/>
For QML files, you can only whitelist each file individually<br/>
For QML files, you can only allowlist each file individually<br/>
ending with '.qml'."
// Text size
size: 16;

View file

@ -5,7 +5,7 @@
// Created by dr Karol Suprynowicz on 2024/03/24.
// Copyright 2024 Overte e.V.
//
// Based on EntityScriptQMLWhitelist.qml
// Based on EntityScriptQMLAllowlist.qml
// Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com
// Copyright 2019 Kalila L.
//
@ -27,15 +27,15 @@ import "../../../windows"
Rectangle {
id: parentBody;
function getWhitelistAsText() {
var whitelist = Settings.getValue("private/scriptPermissionGetAvatarURLSafeURLs");
var arrayWhitelist = whitelist.replace(",", "\n");
return arrayWhitelist;
function getAllowlistAsText() {
var allowlist = Settings.getValue("private/scriptPermissionGetAvatarURLSafeURLs");
var arrayAllowlist = allowlist.replace(",", "\n");
return arrayAllowlist;
}
function setWhitelistAsText(whitelistText) {
Settings.setValue("private/scriptPermissionGetAvatarURLSafeURLs", whitelistText.text);
notificationText.text = "Whitelist saved.";
function setAllowlistAsText(allowlistText) {
Settings.setValue("private/scriptPermissionGetAvatarURLSafeURLs", allowlistText.text);
notificationText.text = "Allowlist saved.";
}
function setAvatarProtection(enabled) {
@ -65,7 +65,7 @@ Rectangle {
height: 60;
CheckBox {
id: whitelistEnabled;
id: allowlistEnabled;
checked: Settings.getValue("private/scriptPermissionGetAvatarURLEnable", true);
@ -73,7 +73,7 @@ Rectangle {
anchors.top: parent.top;
anchors.topMargin: 10;
onToggled: {
setAvatarProtection(whitelistEnabled.checked)
setAvatarProtection(allowlistEnabled.checked)
}
Label {
@ -104,8 +104,8 @@ Rectangle {
clip: false;
TextArea {
id: whitelistTextArea
text: getWhitelistAsText();
id: allowlistTextArea
text: getAllowlistAsText();
onTextChanged: notificationText.text = "";
width: parent.width;
height: parent.height;
@ -133,7 +133,7 @@ Rectangle {
elide: Text.ElideRight
}
text: "Save Changes"
onClicked: setWhitelistAsText(whitelistTextArea)
onClicked: setAllowlistAsText(allowlistTextArea)
HifiStylesUit.RalewayRegular {
id: notificationText;

View file

@ -211,7 +211,7 @@ Flickable {
wrapMode: Text.Wrap
Component.onCompleted: {
var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU()));
var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getPrimaryGPU()));
var gpuModel = gpu.model;
if (!gpuModel || gpuModel.length === 0) {
gpuModel = "Unknown";
@ -336,7 +336,7 @@ Flickable {
textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n";
textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n";
var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU()));
var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getPrimaryGPU()));
var gpuModel = gpu.model;
if (!gpuModel || gpuModel.length === 0) {
gpuModel = "Unknown";

View file

@ -0,0 +1,30 @@
vec3 getErrorColor() {
vec3 positionWS = iWorldOrientation * (_positionMS.xyz * iWorldScale) + iWorldPosition;
float checkSize = 0.1;
vec3 edges = round(mod(positionWS, vec3(checkSize)) / checkSize);
float checkerboard = mod(edges.x + edges.y + edges.z, 2.0);
return mix(vec3(1, 0, 1), vec3(0.0), checkerboard);
}
// version 1
vec3 getProceduralColor() {
return getErrorColor();
}
// version 2
float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) {
diffuse = getErrorColor();
return 1.0;
}
// version 3
float getProceduralFragment(inout ProceduralFragment data) {
data.emissive = getErrorColor();
return 1.0;
}
// version 4
float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition data) {
data.emissive = getErrorColor();
return 1.0;
}

View file

@ -0,0 +1,7 @@
vec3 getSkyboxColor() {
vec3 normal = normalize(_normal);
float checkSize = 0.1;
vec3 edges = round(mod(normal, vec3(checkSize)) / checkSize);
float checkerboard = mod(edges.x + edges.y + edges.z, 2.0);
return mix(vec3(1, 0, 1), vec3(0.0), checkerboard);
}

View file

@ -3293,9 +3293,9 @@ void Application::initializeUi() {
{
auto defaultUrlValidator = OffscreenQmlSurface::getUrlValidator();
auto newValidator = [=](const QUrl& url) -> bool {
QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]";
QString allowlistPrefix = "[ALLOWLIST ENTITY SCRIPTS]";
QList<QString> safeURLS = { "" };
safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
safeURLS += qEnvironmentVariable("EXTRA_ALLOWLIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
// PULL SAFEURLS FROM INTERFACE.JSON Settings
@ -3332,7 +3332,7 @@ void Application::initializeUi() {
QmlContextCallback platformInfoCallback = [](QQmlContext* context) {
context->setContextProperty("PlatformInfo", new PlatformInfoScriptingInterface());
};
OffscreenQmlSurface::addWhitelistContextHandler({
OffscreenQmlSurface::addAllowlistContextHandler({
QUrl{ "hifi/tablet/TabletAddressDialog.qml" },
QUrl{ "hifi/Card.qml" },
QUrl{ "hifi/Pal.qml" },
@ -3342,7 +3342,7 @@ void Application::initializeUi() {
QmlContextCallback ttsCallback = [](QQmlContext* context) {
context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
};
OffscreenQmlSurface::addWhitelistContextHandler({
OffscreenQmlSurface::addAllowlistContextHandler({
QUrl{ "hifi/tts/TTS.qml" }
}, ttsCallback);
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");

View file

@ -46,6 +46,7 @@
#include "avatar/AvatarManager.h"
#include "avatar/AvatarPackager.h"
#include "AvatarBookmarks.h"
#include <display-plugins/OpenGLDisplayPlugin.h>
#include "DomainAccountManager.h"
#include "MainWindow.h"
#include "render/DrawStatus.h"
@ -310,13 +311,13 @@ Menu::Menu() {
}
});
// Settings > Entity Script / QML Whitelist
action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script / QML Whitelist");
// Settings > Entity Script / QML Allowlist
action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script / QML Allowlist");
connect(action, &QAction::triggered, [] {
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
auto hmd = DependencyManager::get<HMDScriptingInterface>();
tablet->pushOntoStack("hifi/dialogs/security/EntityScriptQMLWhitelist.qml");
tablet->pushOntoStack("hifi/dialogs/security/EntityScriptQMLAllowlist.qml");
if (!hmd->getShouldShowTablet()) {
hmd->toggleShouldShowTablet();
@ -540,7 +541,7 @@ Menu::Menu() {
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false);
connect(action, &QAction::triggered, [action] {
ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked();
Procedural::enableProceduralShaders = action->isChecked();
});
{
@ -549,6 +550,13 @@ Menu::Menu() {
drawStatusConfig, SLOT(setShowFade(bool)));
}
{
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ExtraLinearTosRGBConversion, 0, OpenGLDisplayPlugin::getExtraLinearToSRGBConversion());
connect(action, &QAction::triggered, [action] {
OpenGLDisplayPlugin::setExtraLinearToSRGBConversion(action->isChecked());
});
}
// Developer > Assets >>>
// Menu item is not currently needed but code should be kept in case it proves useful again at some stage.
//#define WANT_ASSET_MIGRATION

View file

@ -189,7 +189,7 @@ namespace MenuOption {
const QString RunningScripts = "Running Scripts...";
const QString RunTimingTests = "Run Timing Tests";
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
const QString EntityScriptQMLWhitelist = "Entity Script / QML Whitelist";
const QString EntityScriptQMLAllowlist = "Entity Script / QML Allowlist";
const QString ScriptSecurity = "Script Security";
const QString ShowTrackedObjects = "Show Tracked Objects";
const QString SelfieCamera = "Selfie";
@ -237,7 +237,8 @@ namespace MenuOption {
const QString ComputeBlendshapes = "Compute Blendshapes";
const QString HighlightTransitions = "Highlight Transitions";
const QString MaterialProceduralShaders = "Enable Procedural Materials";
}
const QString ExtraLinearTosRGBConversion = "Extra Linear to sRGB Conversion";
}
#endif // hifi_Menu_h

View file

@ -75,13 +75,13 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
// Ugly case that prevent us to run deferred everywhere...
bool isDeferredCapable = platform::Profiler::isRenderMethodDeferredCapable();
auto masterDisplay = platform::getDisplay(platform::getMasterDisplay());
auto primaryDisplay = platform::getDisplay(platform::getPrimaryDisplay());
// eval recommended PPI and Scale
float recommendedPpiScale = 1.0f;
const float RECOMMENDED_PPI[] = { 200.0f, 200.0f, 120.f, 160.f, 250.f};
if (!masterDisplay.empty() && masterDisplay.count(platform::keys::display::ppi)) {
float ppi = masterDisplay[platform::keys::display::ppi];
if (!primaryDisplay.empty() && primaryDisplay.count(platform::keys::display::ppi)) {
float ppi = primaryDisplay[platform::keys::display::ppi];
// only scale if the actual ppi is higher than the recommended ppi
if (ppi > RECOMMENDED_PPI[preset]) {
// make sure the scale is no less than a quarter

View file

@ -97,7 +97,7 @@ int main(int argc, const char* argv[]) {
);
QCommandLineOption protocolVersionOption(
"protocolVersion",
"Writes the protocol version base64 signature to a file?",
"Writes the protocol version base64 signature to a file",
"path"
);
QCommandLineOption noUpdaterOption(
@ -275,10 +275,18 @@ int main(int argc, const char* argv[]) {
"abortAfterInit",
"Debug option. Aborts after initialization, right before the program starts running the event loop."
);
QCommandLineOption getProtocolVersionHashOption(
"getProtocolVersionHash",
"Debug option. Returns the network protocol version MD5 hash."
);
QCommandLineOption getProtocolVersionDataOption(
"getProtocolVersionData",
"Debug option. Returns the network protocol detailed data in JSON."
);
// "--qmljsdebugger", which appears in output from "--help-all".
// Those below don't seem to be optional.
// --ignore-gpu-blacklist
// --ignore-gpu-blocklist
// --suppress-settings-reset
@ -321,6 +329,8 @@ int main(int argc, const char* argv[]) {
parser.addOption(abortAfterStartupOption);
parser.addOption(abortAfterInitOption);
parser.addOption(getPluginsOption);
parser.addOption(getProtocolVersionHashOption);
parser.addOption(getProtocolVersionDataOption);
QString applicationPath;
@ -455,6 +465,34 @@ int main(int argc, const char* argv[]) {
return 1;
}
}
if (parser.isSet(getProtocolVersionHashOption)) {
std::cout << protocolVersionsSignatureHex().toStdString() << std::endl;
return 0;
}
if (parser.isSet(getProtocolVersionDataOption)) {
auto protocolMap = protocolVersionsSignatureMap();
QMetaEnum packetMetaEnum = QMetaEnum::fromType<PacketTypeEnum::Value>();
QJsonArray packetTypesList;
auto keyList = protocolMap.keys();
std::sort(keyList.begin(), keyList.end()); // Sort by numeric value
for(const auto packet : keyList) {
QJsonObject data;
int intValue = static_cast<int>(packet);
QString keyName = packetMetaEnum.valueToKey(intValue);
data["name"] = keyName;
data["value"] = intValue;
data["version"] = versionForPacketType(packet);
packetTypesList.append(data);
}
std::cout << QJsonDocument(packetTypesList).toJson().toStdString() << std::endl;
return 0;
}
static const QString APPLICATION_CONFIG_FILENAME = "config.json";
QDir applicationDir(applicationPath);

View file

@ -408,9 +408,9 @@ CollisionRegion CollisionPick::getMathematicalPick() const {
void CollisionPick::filterIntersections(std::vector<ContactTestResult>& intersections) const {
const QVector<QUuid>& ignoreItems = getIgnoreItems();
const QVector<QUuid>& includeItems = getIncludeItems();
bool isWhitelist = !includeItems.empty();
bool isAllowlist = !includeItems.empty();
if (!isWhitelist && ignoreItems.empty()) {
if (!isAllowlist && ignoreItems.empty()) {
return;
}
@ -420,7 +420,7 @@ void CollisionPick::filterIntersections(std::vector<ContactTestResult>& intersec
for (int i = 0; i < n; i++) {
auto& intersection = intersections[i];
const QUuid& id = intersection.foundID;
if (!ignoreItems.contains(id) && (!isWhitelist || includeItems.contains(id))) {
if (!ignoreItems.contains(id) && (!isAllowlist || includeItems.contains(id))) {
filteredIntersections.push_back(intersection);
}
}

View file

@ -533,7 +533,7 @@ void Audio::setAvatarGain(float gain) {
}
withWriteLock([&] {
// ask the NodeList to set the master avatar gain
// ask the NodeList to set the primary avatar gain
DependencyManager::get<NodeList>()->setAvatarGain(QUuid(), gain);
});

View file

@ -182,8 +182,8 @@ bool PlatformInfoScriptingInterface::isStandalone() {
int PlatformInfoScriptingInterface::getNumCPUs() {
return platform::getNumCPUs();
}
int PlatformInfoScriptingInterface::getMasterCPU() {
return platform::getMasterCPU();
int PlatformInfoScriptingInterface::getPrimaryCPU() {
return platform::getPrimaryCPU();
}
QString PlatformInfoScriptingInterface::getCPU(int index) {
auto desc = platform::getCPU(index);
@ -193,8 +193,8 @@ QString PlatformInfoScriptingInterface::getCPU(int index) {
int PlatformInfoScriptingInterface::getNumGPUs() {
return platform::getNumGPUs();
}
int PlatformInfoScriptingInterface::getMasterGPU() {
return platform::getMasterGPU();
int PlatformInfoScriptingInterface::getPrimaryGPU() {
return platform::getPrimaryGPU();
}
QString PlatformInfoScriptingInterface::getGPU(int index) {
auto desc = platform::getGPU(index);
@ -204,8 +204,8 @@ QString PlatformInfoScriptingInterface::getGPU(int index) {
int PlatformInfoScriptingInterface::getNumDisplays() {
return platform::getNumDisplays();
}
int PlatformInfoScriptingInterface::getMasterDisplay() {
return platform::getMasterDisplay();
int PlatformInfoScriptingInterface::getPrimaryDisplay() {
return platform::getPrimaryDisplay();
}
QString PlatformInfoScriptingInterface::getDisplay(int index) {
auto desc = platform::getDisplay(index);

View file

@ -106,8 +106,8 @@ public slots:
* @function PlatformInfo.getGraphicsCardType
* @returns {string} The model of the graphics card currently being used.
* @deprecated This function is deprecated and will be removed.
* Use <code>JSON.parse({@link PlatformInfo.getGPU|PlatformInfo.getGPU(}
* {@link PlatformInfo.getMasterGPU|PlatformInfo.getMasterGPU() )}).model</code>
* Use <code>JSON.parse({@link PlatformInfo.getGPU|PlatformInfo.getGPU(}
* {@link PlatformInfo.getPrimaryGPU|PlatformInfo.getPrimaryGPU() )}).model</code>
* instead.
*/
QString getGraphicsCardType();
@ -149,11 +149,11 @@ public slots:
int getNumCPUs();
/*@jsdoc
* Gets the index number of the master CPU.
* @function PlatformInfo.getMasterCPU
* @returns {number} The index of the master CPU.
* Gets the index number of the primary CPU.
* @function PlatformInfo.getPrimaryCPU
* @returns {number} The index of the primary CPU.
*/
int getMasterCPU();
int getPrimaryCPU();
/*@jsdoc
* Gets the platform description of a CPU.
@ -178,11 +178,11 @@ public slots:
int getNumGPUs();
/*@jsdoc
* Gets the index number of the master GPU.
* @function PlatformInfo.getMasterGPU
* @returns {number} The index of the master GPU.
* Gets the index number of the primary GPU.
* @function PlatformInfo.getPrimaryGPU
* @returns {number} The index of the primary GPU.
*/
int getMasterGPU();
int getPrimaryGPU();
/*@jsdoc
* Gets the platform description of a GPU.
@ -207,11 +207,11 @@ public slots:
int getNumDisplays();
/*@jsdoc
* Gets the index number of the master display.
* @function PlatformInfo.getMasterDisplay
* @returns {number} The index of the master display.
* Gets the index number of the primary display.
* @function PlatformInfo.getPrimaryDisplay
* @returns {number} The index of the primary display.
*/
int getMasterDisplay();
int getPrimaryDisplay();
/*@jsdoc
* Gets the platform description of a display.

View file

@ -221,8 +221,8 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
Application::setupQmlSurface(quickView->rootContext(), true);
//add any whitelisted callbacks
OffscreenUi::applyWhiteList(sourceUrl, quickView->rootContext());
//add any allowlisted callbacks
OffscreenUi::applyAllowList(sourceUrl, quickView->rootContext());
/*@jsdoc
* Configures how a <code>NATIVE</code> window is displayed.

View file

@ -538,7 +538,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
}
}
} else if (targetType == IKTarget::Type::HmdHead) {
// An HmdHead target slaves the orientation of the end-effector by distributing rotation
// An HmdHead target workers the orientation of the end-effector by distributing rotation
// deltas up the hierarchy. Its target position is enforced later (by shifting the hips).
deltaRotation = target.getRotation() * glm::inverse(tipOrientation);
const float ANGLE_DISTRIBUTION_FACTOR = 0.45f;

View file

@ -71,11 +71,11 @@ public:
using IgnoreBox = AABox;
// called from single AudioMixerSlave while processing packets for node
// called from single AudioMixerWorker while processing packets for node
void enableIgnoreBox();
void disableIgnoreBox() { _isIgnoreBoxEnabled = false; }
// thread-safe, called from AudioMixerSlave(s) while preparing mixes
// thread-safe, called from AudioMixerWorker(s) while preparing mixes
bool isIgnoreBoxEnabled() const { return _isIgnoreBoxEnabled; }
const IgnoreBox& getIgnoreBox() const { return _ignoreBox; }

View file

@ -4417,9 +4417,9 @@ bs_new ()
bs = (Bit_stream_struc *) calloc(1, sizeof(Bit_stream_struc));
g_return_val_if_fail (bs != NULL, NULL);
bs->master.cur_bit = 8;
bs->master.size = 0;
bs->master.cur_used = 0;
bs->primary.cur_bit = 8;
bs->primary.size = 0;
bs->primary.cur_used = 0;
bs->read.cur_bit = 8;
bs->read.size = 0;
bs->read.cur_used = 0;
@ -4443,11 +4443,11 @@ bs_set_data (Bit_stream_struc * bs, const guint8 * data, gsize size)
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (size != 0, FALSE);
bs->master.data = data;
bs->master.cur_byte = (guint8 *) data;
bs->master.size = size;
bs->master.bitpos = 0;
bs->master.cur_used = 0;
bs->primary.data = data;
bs->primary.cur_byte = (guint8 *) data;
bs->primary.size = size;
bs->primary.bitpos = 0;
bs->primary.cur_used = 0;
bs_reset (bs);
return TRUE;
}
@ -4494,7 +4494,7 @@ bs_eat (Bit_stream_struc * bs, BSReader * read, guint32 Nbits)
}
}
/* Advance the master position by Nbits */
/* Advance the primary position by Nbits */
void
bs_consume (Bit_stream_struc * bs, guint32 Nbits)
{
@ -4503,7 +4503,7 @@ bs_consume (Bit_stream_struc * bs, guint32 Nbits)
GST_DEBUG ("%d Consumed %d bits to end at %" G_GUINT64_FORMAT,
n++, Nbits, bs_pos (bs) + Nbits);
#endif
bs_eat (bs, &bs->master, Nbits);
bs_eat (bs, &bs->primary, Nbits);
}
/* Advance the read position by Nbits */

View file

@ -197,10 +197,10 @@ typedef struct BSReader
typedef struct Bit_stream_struc
{
BSReader master; /* Master tracking position, advanced
BSReader primary; /* Primary tracking position, advanced
* by bs_consume() */
BSReader read; /* Current read position, set back to the
* master by bs_reset() */
* primary by bs_reset() */
} Bit_stream_struc;
/* Create and initialise a new bitstream reader */
@ -209,25 +209,25 @@ Bit_stream_struc *bs_new ();
/* Release a bitstream reader */
void bs_free (Bit_stream_struc * bs);
/* Reset the current read position to the master position */
/* Reset the current read position to the primary position */
static inline void
bs_reset (Bit_stream_struc * bs)
{
memcpy (&bs->read, &bs->master, sizeof (BSReader));
memcpy (&bs->read, &bs->primary, sizeof (BSReader));
}
/* Reset master and read states */
/* Reset primary and read states */
static inline void
bs_flush (Bit_stream_struc * bs)
{
g_return_if_fail (bs != NULL);
bs->master.cur_bit = 8;
bs->master.size = 0;
bs->master.cur_used = 0;
bs->master.cur_byte = NULL;
bs->master.data = NULL;
bs->master.bitpos = 0;
bs->primary.cur_bit = 8;
bs->primary.size = 0;
bs->primary.cur_used = 0;
bs->primary.cur_byte = NULL;
bs->primary.data = NULL;
bs->primary.bitpos = 0;
bs_reset (bs);
}
@ -235,7 +235,7 @@ bs_flush (Bit_stream_struc * bs)
/* Set data as the stream for processing */
gboolean bs_set_data (Bit_stream_struc * bs, const guint8 * data, gsize size);
/* Advance the master position by Nbits */
/* Advance the primary position by Nbits */
void bs_consume (Bit_stream_struc * bs, guint32 Nbits);
/* Number of bits available for reading */
@ -253,14 +253,14 @@ void bs_skipbits (Bit_stream_struc * bs, guint32 N);
/* give number of consumed bytes */
static inline gsize bs_get_consumed (Bit_stream_struc * bs)
{
return bs->master.cur_used;
return bs->primary.cur_used;
}
/* Current bitstream position in bits */
static inline guint64
bs_pos (Bit_stream_struc * bs)
{
return bs->master.bitpos;
return bs->primary.bitpos;
}
/* Current read bitstream position in bits */

View file

@ -1704,7 +1704,7 @@ protected:
void unpackSkeletonModelURL(const QByteArray& data);
void unpackSkeletonData(const QByteArray& data);
// isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "master"
// isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "primary"
// Audio Mixer that the replicated avatar is connected to.
bool _isReplicated{ false };

View file

@ -112,14 +112,6 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() {
return Parent::internalActivate();
}
gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline() {
#if defined(Q_OS_ANDROID)
return _linearToSRGBPipeline;
#else
return _drawTexturePipeline;
#endif
}
void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
#if defined(Q_OS_ANDROID)
auto& virtualPadManager = VirtualPad::Manager::instance();

View file

@ -37,8 +37,6 @@ public:
virtual void pluginUpdate() override {};
virtual gpu::PipelinePointer getRenderTexturePipeline() override;
protected:
mutable bool _isThrottled = false;

View file

@ -32,6 +32,7 @@
#include <gl/GLEscrow.h>
#include <gl/Context.h>
#include <gl/OffscreenGLCanvas.h>
#include <gl/GLHelpers.h>
#include <gpu/Texture.h>
#include <gpu/FrameIO.h>
@ -57,6 +58,8 @@ using namespace shader::gpu::program;
extern QThread* RENDER_THREAD;
Setting::Handle<bool> OpenGLDisplayPlugin::_extraLinearToSRGBConversionSetting("extraLinearToSRGBConversion", false);
class PresentThread : public QThread, public Dependency {
using Mutex = std::mutex;
using Condition = std::condition_variable;
@ -956,5 +959,16 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
}
gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() {
return _drawTexturePipeline;
#ifdef USE_GLES
if (!_extraLinearToSRGBConversionSetting.isSet()) {
const gl::ContextInfo &contextInfo = gl::ContextInfo::get();
_extraLinearToSRGBConversionSetting.set(std::find(contextInfo.extensions.cbegin(), contextInfo.extensions.cend(), "GL_EXT_framebuffer_sRGB") == contextInfo.extensions.cend());
}
#endif
if (getExtraLinearToSRGBConversion()) {
return _linearToSRGBPipeline;
} else {
return _drawTexturePipeline;
}
}

View file

@ -18,6 +18,7 @@
#include <QtGui/QImage>
#include <GLMHelpers.h>
#include <SettingHandle.h>
#include <SimpleMovingAverage.h>
#include <shared/RateCounter.h>
@ -86,6 +87,9 @@ public:
QOpenGLFramebufferObject* target,
GLsync* fenceSync) override;
static void setExtraLinearToSRGBConversion(bool value) { _extraLinearToSRGBConversionSetting.set(value); }
static bool getExtraLinearToSRGBConversion() { return _extraLinearToSRGBConversionSetting.get(); };
protected:
friend class PresentThread;
@ -201,4 +205,7 @@ protected:
QImage getScreenshot(float aspectRatio);
QImage getSecondaryCameraScreenshot();
private:
static Setting::Handle<bool> _extraLinearToSRGBConversionSetting;
};

View file

@ -65,8 +65,8 @@ EntityTree::~EntityTree() {
//eraseAllOctreeElements(false); // KEEP THIS
}
void EntityTree::setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist) {
_entityScriptSourceWhitelist = entityScriptSourceWhitelist.split(',', Qt::SkipEmptyParts);
void EntityTree::setEntityScriptSourceAllowlist(const QString& entityScriptSourceAllowlist) {
_entityScriptSourceAllowlist = entityScriptSourceAllowlist.split(',', Qt::SkipEmptyParts);
}
@ -1411,17 +1411,17 @@ void EntityTree::bumpTimestamp(EntityItemProperties& properties) { //fixme put c
properties.setLastEdited(properties.getLastEdited() + LAST_EDITED_SERVERSIDE_BUMP);
}
bool EntityTree::isScriptInWhitelist(const QString& scriptProperty) {
bool EntityTree::isScriptInAllowlist(const QString& scriptProperty) {
// grab a URL representation of the entity script so we can check the host for this script
auto entityScriptURL = QUrl::fromUserInput(scriptProperty);
for (const auto& whiteListedPrefix : _entityScriptSourceWhitelist) {
auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix);
for (const auto& allowListedPrefix : _entityScriptSourceAllowlist) {
auto allowListURL = QUrl::fromUserInput(allowListedPrefix);
// check if this script URL matches the whitelist domain and, optionally, is beneath the path
if (entityScriptURL.host().compare(whiteListURL.host(), Qt::CaseInsensitive) == 0 &&
entityScriptURL.path().startsWith(whiteListURL.path(), Qt::CaseInsensitive)) {
// check if this script URL matches the allowlist domain and, optionally, is beneath the path
if (entityScriptURL.host().compare(allowListURL.host(), Qt::CaseInsensitive) == 0 &&
entityScriptURL.path().startsWith(allowListURL.path(), Qt::CaseInsensitive)) {
return true;
}
}
@ -1504,18 +1504,18 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
}
}
if (validEditPacket && !_entityScriptSourceWhitelist.isEmpty()) {
if (validEditPacket && !_entityScriptSourceAllowlist.isEmpty()) {
bool wasDeletedBecauseOfClientScript = false;
// check the client entity script to make sure its URL is in the whitelist
// check the client entity script to make sure its URL is in the allowlist
if (!properties.getScript().isEmpty()) {
bool clientScriptPassedWhitelist = isScriptInWhitelist(properties.getScript());
bool clientScriptPassedAllowlist = isScriptInAllowlist(properties.getScript());
if (!clientScriptPassedWhitelist) {
if (!clientScriptPassedAllowlist) {
if (wantEditLogging()) {
qCDebug(entities) << "User [" << senderNode->getUUID()
<< "] attempting to set entity script not on whitelist, edit rejected";
<< "] attempting to set entity script not on allowlist, edit rejected";
}
// If this was an add, we also want to tell the client that sent this edit that the entity was not added.
@ -1530,20 +1530,20 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
}
}
// check all server entity scripts to make sure their URLs are in the whitelist
// check all server entity scripts to make sure their URLs are in the allowlist
if (!properties.getServerScripts().isEmpty()) {
bool serverScriptPassedWhitelist = isScriptInWhitelist(properties.getServerScripts());
bool serverScriptPassedAllowlist = isScriptInAllowlist(properties.getServerScripts());
if (!serverScriptPassedWhitelist) {
if (!serverScriptPassedAllowlist) {
if (wantEditLogging()) {
qCDebug(entities) << "User [" << senderNode->getUUID()
<< "] attempting to set server entity script not on whitelist, edit rejected";
<< "] attempting to set server entity script not on allowlist, edit rejected";
}
// If this was an add, we also want to tell the client that sent this edit that the entity was not added.
if (isAdd) {
// Make sure we didn't already need to send back a delete because the client script failed
// the whitelist check
// the allowlist check
if (!wasDeletedBecauseOfClientScript) {
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);

View file

@ -63,7 +63,7 @@ public:
void setEntityMaxTmpLifetime(float maxTmpEntityLifetime) { _maxTmpEntityLifetime = maxTmpEntityLifetime; }
void setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist);
void setEntityScriptSourceAllowlist(const QString& entityScriptSourceAllowlist);
/// Implements our type specific root element factory
virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL) override;
@ -300,7 +300,7 @@ protected:
void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode);
bool isScriptInWhitelist(const QString& scriptURL);
bool isScriptInAllowlist(const QString& scriptURL);
QReadWriteLock _newlyCreatedHooksLock;
QVector<NewlyCreatedEntityHook*> _newlyCreatedHooks;
@ -363,7 +363,7 @@ protected:
bool filterProperties(const EntityItemPointer& existingEntity, EntityItemProperties& propertiesIn, EntityItemProperties& propertiesOut, bool& wasChanged, FilterType filterType) const;
bool _hasEntityEditFilter{ false };
QStringList _entityScriptSourceWhitelist;
QStringList _entityScriptSourceAllowlist;
MovingEntitiesOperator _entityMover;
QHash<EntityItemID, EntityItemPointer> _entitiesToAdd;

View file

@ -126,7 +126,7 @@ protected:
const Shaders _shaders;
// The type of the shader, the master key
// The type of the shader, the primary key
const Type _type;
// Number of attempts to compile the shader

View file

@ -405,7 +405,7 @@ public:
Stamp getDataStamp() const { return _storage->getStamp(); }
// The theoretical size in bytes of data stored in the texture
// For the master (level) first level of mip
// For the primary (level) first level of mip
Size getSize() const override { return _size; }
// Size and format

View file

@ -4,7 +4,7 @@
//
// Created by Stephen Birarda on 2/18/2014.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
// Copyright 2023-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
@ -696,7 +696,8 @@ void AccountManager::setAccessTokens(const QString& response) {
if (!rootObject.contains("access_token") || !rootObject.contains("expires_in")
|| !rootObject.contains("token_type")) {
// TODO: error handling - malformed token response
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
qCWarning(networking) << "Error setting access token. Received a response for password grant that is missing one or more expected values.";
qCWarning(networking) << "Response:" << QJsonDocument(rootObject).toJson(QJsonDocument::Compact);
} else {
// clear the path from the response URL so we have the right root URL for this access token
QUrl rootURL = rootObject.contains("url") ? rootObject["url"].toString() : _authURL;
@ -714,7 +715,7 @@ void AccountManager::setAccessTokens(const QString& response) {
}
} else {
// TODO: error handling
qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString();
qCWarning(networking) << "Error in response for password grant -" << rootObject["error"].toString();
emit loginFailed();
}
}
@ -731,7 +732,8 @@ void AccountManager::requestAccessTokenFinished() {
if (!rootObject.contains("access_token") || !rootObject.contains("expires_in")
|| !rootObject.contains("token_type")) {
// TODO: error handling - malformed token response
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
qCWarning(networking) << "Error requesting access token. Received a response for password grant that is missing one or more expected values.";
qCWarning(networking) << "Response:" << QJsonDocument(rootObject).toJson(QJsonDocument::Compact);
} else {
// clear the path from the response URL so we have the right root URL for this access token
QUrl rootURL = requestReply->url();
@ -750,7 +752,7 @@ void AccountManager::requestAccessTokenFinished() {
}
} else {
// TODO: error handling
qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString();
qCWarning(networking) << "Error in response for password grant -" << rootObject["error"].toString();
emit loginFailed();
}
}

View file

@ -1250,7 +1250,7 @@ void NodeList::setAvatarGain(const QUuid& nodeID, float gain) {
setAvatarGainPacket->writePrimitive(packFloatGainToByte(fastExp2f(gain / 6.02059991f)));
if (nodeID.isNull()) {
qCDebug(networking) << "Sending Set MASTER Avatar Gain packet with Gain:" << gain;
qCDebug(networking) << "Sending Set PRIMARY Avatar Gain packet with Gain:" << gain;
sendPacket(std::move(setAvatarGainPacket), *audioMixer);

View file

@ -137,7 +137,7 @@ void UserActivityLogger::changedDomain(QString domainURL) {
}
void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceName) {
static QStringList DEVICE_BLACKLIST = {
static QStringList DEVICE_BLOCKLIST = {
"Desktop",
"NullDisplayPlugin",
"3D TV - Side by Side Stereo",
@ -145,7 +145,7 @@ void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceNam
"Keyboard/Mouse"
};
if (DEVICE_BLACKLIST.contains(deviceName) || deviceName.isEmpty()) {
if (DEVICE_BLOCKLIST.contains(deviceName) || deviceName.isEmpty()) {
return;
}

View file

@ -130,6 +130,10 @@ void sendWrongProtocolVersionsSignature(bool sendWrongVersion) {
static QByteArray protocolVersionSignature;
static QString protocolVersionSignatureBase64;
static QString protocolVersionSignatureHex;
static QMap<PacketType, uint8_t> protocolVersionMap;
static void ensureProtocolVersionsSignature() {
static std::once_flag once;
std::call_once(once, [&] {
@ -139,12 +143,14 @@ static void ensureProtocolVersionsSignature() {
stream << numberOfProtocols;
for (uint8_t packetType = 0; packetType < numberOfProtocols; packetType++) {
uint8_t packetTypeVersion = static_cast<uint8_t>(versionForPacketType(static_cast<PacketType>(packetType)));
protocolVersionMap[static_cast<PacketType>(packetType)] = packetTypeVersion;
stream << packetTypeVersion;
}
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData(buffer);
protocolVersionSignature = hash.result();
protocolVersionSignatureBase64 = protocolVersionSignature.toBase64();
protocolVersionSignatureHex = protocolVersionSignature.toHex(0);
});
}
QByteArray protocolVersionsSignature() {
@ -161,3 +167,13 @@ QString protocolVersionsSignatureBase64() {
ensureProtocolVersionsSignature();
return protocolVersionSignatureBase64;
}
QString protocolVersionsSignatureHex() {
ensureProtocolVersionsSignature();
return protocolVersionSignatureHex;
}
QMap<PacketType, uint8_t> protocolVersionsSignatureMap() {
ensureProtocolVersionsSignature();
return protocolVersionMap;
}

View file

@ -31,8 +31,15 @@ class PacketTypeEnum {
Q_GADGET
Q_ENUMS(Value)
public:
// If adding a new packet packetType, you can replace one marked usable or add at the end.
// This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t
/**
* @brief Packet type identifier
*
* Identifies the type of packet being sent.
*
* @note If adding a new packet packetType, you can replace one marked usable or add at the end.
* @note This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t
*/
enum class Value : uint8_t {
Unknown,
DomainConnectRequestPending,
@ -143,6 +150,8 @@ public:
NUM_PACKET_TYPE
};
Q_ENUM(Value)
const static QHash<PacketTypeEnum::Value, PacketTypeEnum::Value> getReplicatedPacketMapping() {
const static QHash<PacketTypeEnum::Value, PacketTypeEnum::Value> REPLICATED_PACKET_MAPPING {
{ PacketTypeEnum::Value::MicrophoneAudioNoEcho, PacketTypeEnum::Value::ReplicatedMicrophoneAudioNoEcho },
@ -219,10 +228,60 @@ const int NUM_BYTES_MD5_HASH = 16;
// NOTE: There is a max limit of 255, hopefully we have a better way to manage this by then.
typedef uint8_t PacketVersion;
/**
* @brief Returns the version number of the given packet type
*
* If the implementation of a packet type is modified in an incompatible way, the implementation
* of this function needs to be modified to return an incremented value.
*
* This is used to determine whether the protocol is compatible between client and server.
*
* @note Version is limited to a max of 255.
*
* @param packetType Type of packet
* @return PacketVersion Version
*/
PacketVersion versionForPacketType(PacketType packetType);
QByteArray protocolVersionsSignature(); /// returns a unique signature for all the current protocols
/**
* @brief Returns a unique signature for all the current protocols
*
* This computes a MD5 hash that expresses the state of the protocol's specification. The calculation
* is done in ensureProtocolVersionsSignature and accounts for the following:
*
* * Number of known packet types
* * versionForPacketType(type) for each packet type.
*
* There's no provision for backwards compatibility, anything that changes this calculation is a protocol break.
*
* @return QByteArray MD5 digest as a byte array
*/
QByteArray protocolVersionsSignature();
/***
* @brief Returns a unique signature for all the current protocols
*
* Same as protocolVersionsSignature(), in base64.
*/
QString protocolVersionsSignatureBase64();
/***
* @brief Returns a unique signature for all the current protocols
*
* Same as protocolVersionsSignature(), in hex;
*/
QString protocolVersionsSignatureHex();
/***
* @brief Returns the data used to compute the protocol version
*
* The key is the packet type. The value is the version for that packet type.
*
* Used for aiding in development.
*/
QMap<PacketType, uint8_t> protocolVersionsSignatureMap();
#if (PR_BUILD || DEV_BUILD)
void sendWrongProtocolVersionsSignature(bool sendWrongVersion); /// for debugging version negotiation
#endif
@ -428,4 +487,5 @@ enum class AvatarQueryVersion : PacketVersion {
ConicalFrustums = 22
};
#endif // hifi_PacketHeaders_h

View file

@ -655,7 +655,7 @@ uint8_t EntityMotionState::getSimulationPriority() const {
return _entity->getSimulationPriority();
}
void EntityMotionState::slaveBidPriority() {
void EntityMotionState::workerBidPriority() {
_bumpedPriority = glm::max(_bumpedPriority, _entity->getSimulationPriority());
}

View file

@ -111,7 +111,7 @@ protected:
void updateServerPhysicsVariables();
bool remoteSimulationOutOfSync(uint32_t simulationStep);
void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity
void workerBidPriority(); // computeNewBidPriority() with value stored in _entity
void clearObjectVelocities() const;

View file

@ -602,7 +602,7 @@ void PhysicalEntitySimulation::sendOwnershipBids(uint32_t numSubsteps) {
// in the EntityMotionState::_serverFoo variables (please see comments in EntityMotionState.h)
// therefore we need to immediately send an update so that the values stored are what we're
// "telling" the server rather than what we've been "hearing" from the server.
_bids[i]->slaveBidPriority();
_bids[i]->workerBidPriority();
_bids[i]->sendUpdate(_entityPacketSender, numSubsteps);
addOwnership(_bids[i]);

View file

@ -21,15 +21,15 @@ bool enumeratePlatform();
int getNumCPUs();
json getCPU(int index);
int getMasterCPU();
int getPrimaryCPU();
int getNumGPUs();
json getGPU(int index);
int getMasterGPU();
int getPrimaryGPU();
int getNumDisplays();
json getDisplay(int index);
int getMasterDisplay();
int getPrimaryDisplay();
json getMemory();

View file

@ -20,7 +20,7 @@ namespace platform { namespace keys{
extern const char* model;
extern const char* clockSpeed;
extern const char* numCores;
extern const char* isMaster;
extern const char* isPrimary;
}
namespace gpu {
extern const char* vendor;
@ -32,7 +32,7 @@ namespace platform { namespace keys{
extern const char* videoMemory;
extern const char* driver;
extern const char* displays;
extern const char* isMaster;
extern const char* isPrimary;
}
namespace graphicsAPI {
extern const char* name;
@ -90,7 +90,7 @@ namespace platform { namespace keys{
extern const char* modeRefreshrate;
extern const char* modeWidth;
extern const char* modeHeight;
extern const char* isMaster;
extern const char* isPrimary;
}
namespace memory {
extern const char* memTotal;

View file

@ -32,9 +32,9 @@ Profiler::Tier Profiler::profilePlatform() {
return platformTier;
}
// Not filtered yet, let s try to make sense of the master cpu and master gpu info
auto cpuInfo = platform::getCPU(platform::getMasterCPU());
auto gpuInfo = platform::getGPU(platform::getMasterGPU());
// Not filtered yet, let's try to make sense of the primary cpu and primary gpu info
auto cpuInfo = platform::getCPU(platform::getPrimaryCPU());
auto gpuInfo = platform::getGPU(platform::getPrimaryGPU());
if (filterOnProcessors(computerInfo, cpuInfo, gpuInfo, platformTier)) {
return platformTier;
}
@ -62,7 +62,7 @@ bool filterOnComputerMACOS(const platform::json& computer, Profiler::Tier& tier)
// The simple rule for mac is
// if it s an intel gpu then LOW
// else go mid
auto gpu = platform::getGPU(platform::getMasterGPU());
auto gpu = platform::getGPU(platform::getPrimaryGPU());
if (gpu.count(keys::gpu::vendor)) {
std::string gpuVendor = gpu[keys::gpu::vendor].get<std::string>();

View file

@ -67,7 +67,7 @@ void MACOSInstance::enumerateGpusAndDisplays() {
auto displaySizeHeightInches = displaySize.height * MM_TO_IN;
auto displayBounds = CGDisplayBounds(displayID);
auto displayMaster =CGDisplayIsMain(displayID);
auto displayPrimary =CGDisplayIsMain(displayID);
auto displayUnit =CGDisplayUnitNumber(displayID);
auto displayModel =CGDisplayModelNumber(displayID);
@ -112,8 +112,8 @@ void MACOSInstance::enumerateGpusAndDisplays() {
// refreshrate
display[keys::display::modeRefreshrate] = displayRefreshrate;
// Master display ?
display[keys::display::isMaster] = (displayMaster ? true : false);
// Primary display ?
display[keys::display::isPrimary] = (displayPrimary ? true : false);
// Macos specific
display["macos_unit"] = displayUnit;

View file

@ -30,7 +30,7 @@ namespace platform { namespace keys {
* @property {string} vendor - The CPU vendor (e.g., <code>"Intel"</code> or <code>"AMD"</code>).
* @property {string} model - The CPU model.
* @property {number} numCores - The number of logical cores.
* @property {boolean} isMaster - <code>true</code> if the CPU is the "master" or primary CPU, <code>false</code> or
* @property {boolean} isPrimary - <code>true</code> if the CPU is the primary CPU, <code>false</code> or
* <code>undefined</code> if it isn't.
*/
namespace cpu {
@ -41,7 +41,7 @@ namespace platform { namespace keys {
const char* model = "model";
const char* clockSpeed = "clockSpeed"; // FIXME: Not used.
const char* numCores = "numCores";
const char* isMaster = "isMaster";
const char* isPrimary = "isPrimary";
}
/*@jsdoc
@ -53,7 +53,7 @@ namespace platform { namespace keys {
* @property {number} videoMemory - The size of the GPU's video memory, in MB.
* @property {number[]} displays - The index numbers of the displays currently being driven by the GPU. An empty array if
* the GPU is currently not driving any displays.
* @property {boolean} isMaster - <code>true</code> if the GPU is the "master" or primary GPU, <code>false</code> or
* @property {boolean} isPrimary - <code>true</code> if the GPU is the primary GPU, <code>false</code> or
* <code>undefined</code> if it isn't.
*/
namespace gpu {
@ -66,7 +66,7 @@ namespace platform { namespace keys {
const char* videoMemory = "videoMemory";
const char* driver = "driver";
const char* displays = "displays";
const char* isMaster = "isMaster";
const char* isPrimary = "isPrimary";
}
/*@jsdoc
@ -175,7 +175,7 @@ namespace platform { namespace keys {
* @property {number} modeRefreshrate - The refresh rate of the current display mode, in Hz.
* @property {number} modeWidth - The width of the current display mode, in pixels.
* @property {number} modeHeight - The height of the current display mode, in pixels.
* @property {boolean} isMaster - <code>true</code> if the GPU is the "master" or primary display, <code>false</code> or
* @property {boolean} isPrimary - <code>true</code> if the GPU is the primary display, <code>false</code> or
* <code>undefined</code> if it isn't.
*/
namespace display {
@ -193,7 +193,7 @@ namespace platform { namespace keys {
const char* modeRefreshrate = "modeRefreshrate";
const char* modeWidth = "modeWidth";
const char* modeHeight = "modeHeight";
const char* isMaster = "isMaster";
const char* isPrimary = "isPrimary";
}
/*@jsdoc
@ -300,8 +300,8 @@ json platform::getCPU(int index) {
return _instance->getCPU(index);
}
int platform::getMasterCPU() {
return _instance->getMasterCPU();
int platform::getPrimaryCPU() {
return _instance->getPrimaryCPU();
}
int platform::getNumGPUs() {
@ -312,8 +312,8 @@ json platform::getGPU(int index) {
return _instance->getGPU(index);
}
int platform::getMasterGPU() {
return _instance->getMasterGPU();
int platform::getPrimaryGPU() {
return _instance->getPrimaryGPU();
}
int platform::getNumDisplays() {
@ -324,8 +324,8 @@ json platform::getDisplay(int index) {
return _instance->getDisplay(index);
}
int platform::getMasterDisplay() {
return _instance->getMasterDisplay();
int platform::getPrimaryDisplay() {
return _instance->getPrimaryDisplay();
}
json platform::getMemory() {

View file

@ -41,8 +41,8 @@ bool Instance::enumeratePlatform() {
enumerateNics();
enumerateGraphicsApis();
// eval the master index for each platform scopes
updateMasterIndices();
// eval the primary index for each platform scopes
updatePrimaryIndices();
// And profile the platform and put the tier in "computer"
_computer[keys::computer::profileTier] = Profiler::TierNames[Profiler::profilePlatform()];
@ -50,54 +50,54 @@ bool Instance::enumeratePlatform() {
return true;
}
void Instance::updateMasterIndices() {
void Instance::updatePrimaryIndices() {
// We assume a single CPU at the moment:
{
if (!_cpus.empty()) {
_masterCPU = 0;
_cpus[0][keys::cpu::isMaster] = true;
_primaryCPU = 0;
_cpus[0][keys::cpu::isPrimary] = true;
} else {
_masterCPU = NOT_FOUND;
_primaryCPU = NOT_FOUND;
}
}
// Go through the displays list
{
_masterDisplay = NOT_FOUND;
_primaryDisplay = NOT_FOUND;
for (int i = 0; i < (int) _displays.size(); ++i) {
const auto& display = _displays[i];
if (display.count(keys::display::isMaster)) {
if (display[keys::display::isMaster].get<bool>()) {
_masterDisplay = i;
if (display.count(keys::display::isPrimary)) {
if (display[keys::display::isPrimary].get<bool>()) {
_primaryDisplay = i;
break;
}
}
}
// NO master display found, return the first one or NOT_FOUND if no display
if (_masterDisplay == NOT_FOUND) {
// NO primary display found, return the first one or NOT_FOUND if no display
if (_primaryDisplay == NOT_FOUND) {
if (!_displays.empty()) {
_masterDisplay = 0;
_displays[0][keys::display::isMaster] = true;
_primaryDisplay = 0;
_displays[0][keys::display::isPrimary] = true;
}
}
}
// From the master display decide the master gpu
// From the primary display decide the primary gpu
{
_masterGPU = NOT_FOUND;
if (_masterDisplay != NOT_FOUND) {
const auto& display = _displays[_masterDisplay];
// FInd the GPU index of the master display
_primaryGPU = NOT_FOUND;
if (_primaryDisplay != NOT_FOUND) {
const auto& display = _displays[_primaryDisplay];
// FInd the GPU index of the primary display
if (display.count(keys::display::gpu)) {
_masterGPU = display[keys::display::gpu];
_gpus[_masterGPU][keys::gpu::isMaster] = true;
_primaryGPU = display[keys::display::gpu];
_gpus[_primaryGPU][keys::gpu::isPrimary] = true;
}
}
// NO master GPU found from master display, bummer, return the first one or NOT_FOUND if no display
if (_masterGPU == NOT_FOUND) {
// NO primary GPU found from primary display, bummer, return the first one or NOT_FOUND if no display
if (_primaryGPU == NOT_FOUND) {
if (!_gpus.empty()) {
_masterGPU = 0;
_gpus[0][keys::gpu::isMaster] = true;
_primaryGPU = 0;
_gpus[0][keys::gpu::isPrimary] = true;
}
}
}

View file

@ -23,15 +23,15 @@ public:
int getNumCPUs() { return (int)_cpus.size(); }
json getCPU(int index);
int getMasterCPU() const { return _masterCPU; }
int getPrimaryCPU() const { return _primaryCPU; }
int getNumGPUs() { return (int)_gpus.size(); }
json getGPU(int index);
int getMasterGPU() const { return _masterGPU; }
int getPrimaryGPU() const { return _primaryGPU; }
int getNumDisplays() { return (int)_displays.size(); }
json getDisplay(int index);
int getMasterDisplay() const { return _masterDisplay; }
int getPrimaryDisplay() const { return _primaryDisplay; }
json getMemory() { return _memory; }
@ -62,12 +62,12 @@ protected:
json _memory;
json _computer;
int _masterCPU{ -1 };
int _masterGPU{ -1 };
int _masterDisplay{ -1 };
int _primaryCPU{ -1 };
int _primaryGPU{ -1 };
int _primaryDisplay{ -1 };
// Traverse the cpus, gpus and displays to update the "master" index in each domain
void updateMasterIndices();
// Traverse the cpus, gpus and displays to update the "primary" index in each domain
void updatePrimaryIndices();
};

View file

@ -167,8 +167,8 @@ void WINInstance::enumerateGpusAndDisplays() {
// refreshrate
display[keys::display::modeRefreshrate] = devMode.dmDisplayFrequency;;
// Master display ?
display[keys::display::isMaster] = (bool) (monitorInfo.dwFlags & MONITORINFOF_PRIMARY);
// Primary display ?
display[keys::display::isPrimary] = (bool) (monitorInfo.dwFlags & MONITORINFOF_PRIMARY);
// Add the display index to the list of displays of the gpu
displayIndices.push_back((int) _displays.size());

View file

@ -28,6 +28,8 @@
Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural")
bool Procedural::enableProceduralShaders = false;
// User-data parsing constants
static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity";
static const QString VERTEX_URL_KEY = "vertexShaderURL";
@ -377,6 +379,27 @@ void Procedural::prepare(gpu::Batch& batch,
_proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState);
// Error fallback: pink checkerboard
if (_errorFallbackFragmentSource.isEmpty()) {
QFile file(_errorFallbackFragmentPath);
file.open(QIODevice::ReadOnly);
_errorFallbackFragmentSource = QTextStream(&file).readAll();
}
vertexSource.replacements.erase(PROCEDURAL_BLOCK);
fragmentSource.replacements[PROCEDURAL_BLOCK] = _errorFallbackFragmentSource.toStdString();
gpu::ShaderPointer errorVertexShader = gpu::Shader::createVertex(vertexSource);
gpu::ShaderPointer errorFragmentShader = gpu::Shader::createPixel(fragmentSource);
gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(errorVertexShader, errorFragmentShader);
_errorPipelines[key] = gpu::Pipeline::create(errorProgram, _opaqueState);
// Disabled fallback: nothing
vertexSource.replacements.erase(PROCEDURAL_BLOCK);
fragmentSource.replacements.erase(PROCEDURAL_BLOCK);
gpu::ShaderPointer disabledVertexShader = gpu::Shader::createVertex(vertexSource);
gpu::ShaderPointer disabledFragmentShader = gpu::Shader::createPixel(fragmentSource);
gpu::ShaderPointer disabledProgram = gpu::Shader::createProgram(disabledVertexShader, disabledFragmentShader);
_disabledPipelines[key] = gpu::Pipeline::create(disabledProgram, _opaqueState);
_lastCompile = usecTimestampNow();
if (_firstCompile == 0) {
_firstCompile = _lastCompile;
@ -385,8 +408,15 @@ void Procedural::prepare(gpu::Batch& batch,
recompiledShader = true;
}
gpu::PipelinePointer finalPipeline = recompiledShader ? _proceduralPipelines[key] : pipeline->second;
if (!enableProceduralShaders) {
finalPipeline = _disabledPipelines[key];
} else if (!finalPipeline || finalPipeline->getProgram()->compilationHasFailed()) {
finalPipeline = _errorPipelines[key];
}
// FIXME: need to handle forward rendering
batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second);
batch.setPipeline(finalPipeline);
bool recreateUniforms = _shaderDirty || _uniformsDirty || recompiledShader || _prevKey != key;
if (recreateUniforms) {
@ -533,4 +563,6 @@ void graphics::ProceduralMaterial::initializeProcedural() {
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
_procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural);
_procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent);
_procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorShader.frag").path();
}

View file

@ -124,12 +124,16 @@ public:
gpu::Shader::Source _opaqueFragmentSource;
gpu::Shader::Source _transparentFragmentSource;
QString _errorFallbackFragmentPath;
gpu::StatePointer _opaqueState { std::make_shared<gpu::State>() };
gpu::StatePointer _transparentState { std::make_shared<gpu::State>() };
static std::function<void(gpu::StatePointer)> opaqueStencil;
static std::function<void(gpu::StatePointer)> transparentStencil;
static bool enableProceduralShaders;
protected:
// DO NOT TOUCH
// We have to pack these in a particular way to match the ProceduralCommon.slh
@ -176,11 +180,15 @@ protected:
bool _shaderDirty { true };
bool _uniformsDirty { true };
QString _errorFallbackFragmentSource;
// Rendering objects
UniformLambdas _uniforms;
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _proceduralPipelines;
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _errorPipelines;
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _disabledPipelines;
StandardInputs _standardInputs;
gpu::BufferPointer _standardInputsBuffer;

View file

@ -22,6 +22,8 @@ ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _crea
_procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox);
_procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox);
_procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorSkyboxShader.frag").path();
_procedural.setDoesFade(false);
// Adjust the pipeline state for background using the stencil test

View file

@ -25,8 +25,6 @@
using namespace render;
bool ModelMeshPartPayload::enableMaterialProceduralShaders = false;
ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex,
const Transform& transform, const uint64_t& created) :
_meshIndex(meshIndex),
@ -345,9 +343,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
}
if (_shapeKey.hasOwnPipeline()) {
if (!(enableMaterialProceduralShaders)) {
return;
}
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(_drawMaterials.top().material);
auto& schema = _drawMaterials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity);

View file

@ -68,8 +68,6 @@ public:
void setBlendshapeBuffer(const std::unordered_map<int, gpu::BufferPointer>& blendshapeBuffers, const QVector<int>& blendedMeshSizes);
static bool enableMaterialProceduralShaders;
private:
void initCache(const ModelPointer& model, int shapeID);

View file

@ -183,7 +183,7 @@ void Transaction::clear() {
Scene::Scene(glm::vec3 origin, float size) :
_masterSpatialTree(origin, size)
_primarySpatialTree(origin, size)
{
_items.push_back(Item()); // add the itemID #0 to nothing
}
@ -306,10 +306,10 @@ void Scene::resetItems(const Transaction::Resets& transactions) {
// Update the item's container
assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none());
if (newKey.isSpatial()) {
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), itemId, newKey);
auto newCell = _primarySpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), itemId, newKey);
item.resetCell(newCell, newKey.isSmall());
} else {
_masterNonspatialSet.insert(itemId);
_primaryNonspatialSet.insert(itemId);
}
}
}
@ -323,9 +323,9 @@ void Scene::removeItems(const Transaction::Removes& transactions) {
// Remove the item
if (oldKey.isSpatial()) {
_masterSpatialTree.removeItem(oldCell, oldKey, removedID);
_primarySpatialTree.removeItem(oldCell, oldKey, removedID);
} else {
_masterNonspatialSet.erase(removedID);
_primaryNonspatialSet.erase(removedID);
}
// Remove the transition to prevent updating it for nothing
@ -362,20 +362,20 @@ void Scene::updateItems(const Transaction::Updates& transactions) {
// Update the item's container
if (oldKey.isSpatial() == newKey.isSpatial()) {
if (newKey.isSpatial()) {
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey);
auto newCell = _primarySpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey);
item.resetCell(newCell, newKey.isSmall());
}
} else {
if (newKey.isSpatial()) {
_masterNonspatialSet.erase(updateID);
_primaryNonspatialSet.erase(updateID);
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey);
auto newCell = _primarySpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey);
item.resetCell(newCell, newKey.isSmall());
} else {
_masterSpatialTree.removeItem(oldCell, oldKey, updateID);
_primarySpatialTree.removeItem(oldCell, oldKey, updateID);
item.resetCell();
_masterNonspatialSet.insert(updateID);
_primaryNonspatialSet.insert(updateID);
}
}
}

View file

@ -185,10 +185,10 @@ public:
const Item getItemSafe(const ItemID& id) const { if (isAllocatedID(id)) { return _items[id]; } else { return Item(); } }
// Access the spatialized items
const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
const ItemSpatialTree& getSpatialTree() const { return _primarySpatialTree; }
// Access non-spatialized items (layered objects, backgrounds)
const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; }
const ItemIDSet& getNonspatialSet() const { return _primaryNonspatialSet; }
// Access a particular Stage (empty if doesn't exist)
// Thread safe
@ -226,8 +226,8 @@ protected:
// database of items is protected for editing by a mutex
std::mutex _itemsMutex;
Item::Vector _items;
ItemSpatialTree _masterSpatialTree;
ItemIDSet _masterNonspatialSet;
ItemSpatialTree _primarySpatialTree;
ItemIDSet _primaryNonspatialSet;
void resetItems(const Transaction::Resets& transactions);
void resetTransitionFinishedOperator(const Transaction::TransitionFinishedOperators& transactions);

View file

@ -19,21 +19,21 @@ void ScriptGatekeeper::initialize() {
return;
}
QVariant rawCurrentWhitelistValues = Setting::Handle<QVariant>(SCRIPT_WHITELIST_ENTRIES_KEY).get();
QString settingsSafeValues = rawCurrentWhitelistValues.toString();
QVariant rawCurrentAllowlistValues = Setting::Handle<QVariant>(SCRIPT_ALLOWLIST_ENTRIES_KEY).get();
QString settingsSafeValues = rawCurrentAllowlistValues.toString();
Setting::Handle<bool> whitelistEnabled { SCRIPT_WHITELIST_ENABLED_KEY, false };
Setting::Handle<bool> allowlistEnabled { SCRIPT_ALLOWLIST_ENABLED_KEY, false };
Setting::Handle<bool> isFirstRun { Settings::firstRun, true };
QString preloadedVal = BuildInfo::PRELOADED_SCRIPT_WHITELIST;
QString preloadedVal = BuildInfo::PRELOADED_SCRIPT_ALLOWLIST;
if (settingsSafeValues.isEmpty() && !preloadedVal.isEmpty() && isFirstRun.get()) {
// We assume that the whitelist should be enabled if a preloaded whitelist is attached, so we activate it if it's not already active.
if (!whitelistEnabled.get()) {
whitelistEnabled.set(true);
// We assume that the allowlist should be enabled if a preloaded allowlist is attached, so we activate it if it's not already active.
if (!allowlistEnabled.get()) {
allowlistEnabled.set(true);
}
Setting::Handle<QVariant>(SCRIPT_WHITELIST_ENTRIES_KEY).set(preloadedVal);
Setting::Handle<QVariant>(SCRIPT_ALLOWLIST_ENTRIES_KEY).set(preloadedVal);
}
_initialized = true;

View file

@ -17,14 +17,14 @@
#include <QtCore/QObject>
/// Manages script whitelisting in a domain
/// Manages script allowlisting in a domain
class ScriptGatekeeper : public QObject {
Q_OBJECT
public:
void initialize();
QString SCRIPT_WHITELIST_ENABLED_KEY{ "private/whitelistEnabled" };
QString SCRIPT_WHITELIST_ENTRIES_KEY{ "private/settingsSafeURLS" };
QString SCRIPT_ALLOWLIST_ENABLED_KEY{ "private/allowlistEnabled" };
QString SCRIPT_ALLOWLIST_ENTRIES_KEY{ "private/settingsSafeURLS" };
private:
bool _initialized { false };

View file

@ -2192,17 +2192,17 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
exception = testConstructor;
}
} else {
// ENTITY SCRIPT WHITELIST STARTS HERE
// ENTITY SCRIPT ALLOWLIST STARTS HERE
auto nodeList = DependencyManager::get<NodeList>();
bool passList = false; // assume unsafe
QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]";
QString allowlistPrefix = "[ALLOWLIST ENTITY SCRIPTS]";
QList<QString> safeURLPrefixes = { "file:///", "atp:", "cache:" };
safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
safeURLPrefixes += qEnvironmentVariable("EXTRA_ALLOWLIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
// Entity Script Whitelist toggle check.
Setting::Handle<bool> whitelistEnabled {"private/whitelistEnabled", false };
// Entity Script Allowlist toggle check.
Setting::Handle<bool> allowlistEnabled {"private/allowlistEnabled", false };
if (!whitelistEnabled.get()) {
if (!allowlistEnabled.get()) {
passList = true;
}
@ -2212,39 +2212,39 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
safeURLPrefixes += settingsSafeURLS;
// END Pull SAFEURLS from the Interface.JSON settings.
// Get current domain whitelist bypass, in case an entire domain is whitelisted.
// Get current domain allowlist bypass, in case an entire domain is allowlisted.
QString currentDomain = DependencyManager::get<AddressManager>()->getDomainURL().host();
QString domainSafeIP = nodeList->getDomainHandler().getHostname();
QString domainSafeURL = URL_SCHEME_OVERTE + "://" + currentDomain;
for (const auto& str : safeURLPrefixes) {
if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) {
qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed, entire domain is whitelisted. Current Domain Host: "
qCDebug(scriptengine) << allowlistPrefix << "Allowlist Bypassed, entire domain is allowlisted. Current Domain Host: "
<< nodeList->getDomainHandler().getHostname()
<< "Current Domain: " << currentDomain;
passList = true;
}
}
// END bypass whitelist based on current domain.
// END bypass allowlist based on current domain.
// Start processing scripts through the whitelist.
if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage whitelist.
// Start processing scripts through the allowlist.
if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage allowlist.
passList = true;
} else if (!passList) { // If waved through, do not engage whitelist.
} else if (!passList) { // If waved through, do not engage allowlist.
for (const auto& str : safeURLPrefixes) {
qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
qCDebug(scriptengine) << allowlistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
<< scriptOrURL.startsWith(str);
if (!str.isEmpty() && scriptOrURL.startsWith(str)) {
passList = true;
qCDebug(scriptengine) << whitelistPrefix << "Script approved.";
qCDebug(scriptengine) << allowlistPrefix << "Script approved.";
break; // Bail early since we found a match.
}
}
}
// END processing of scripts through the whitelist.
// END processing of scripts through the allowlist.
if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown.
qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL;
qCDebug(scriptengine) << allowlistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL;
exception = _engine->makeError(_engine->newValue("UNSAFE_ENTITY_SCRIPTS == 0"));
} else {
QTimer timeout;
@ -2267,7 +2267,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
exception = testConstructor;
}
}
// ENTITY SCRIPT WHITELIST ENDS HERE, uncomment below for original full disabling.
// ENTITY SCRIPT ALLOWLIST ENDS HERE, uncomment below for original full disabling.
// qCDebug(scriptengine) << "(disabled entity script)" << entityID.toString() << scriptOrURL;
// exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0");
@ -2303,17 +2303,17 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
return; // done processing script
}*/
// ENTITY SCRIPT WHITELIST STARTS HERE
// ENTITY SCRIPT ALLOWLIST STARTS HERE
auto nodeList = DependencyManager::get<NodeList>();
bool passList = false; // assume unsafe
QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]";
QString allowlistPrefix = "[ALLOWLIST ENTITY SCRIPTS]";
QList<QString> safeURLPrefixes = { "file:///", "atp:", "cache:" };
safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
safeURLPrefixes += qEnvironmentVariable("EXTRA_ALLOWLIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts);
// Entity Script Whitelist toggle check.
Setting::Handle<bool> whitelistEnabled {"private/whitelistEnabled", false };
// Entity Script Allowlist toggle check.
Setting::Handle<bool> allowlistEnabled {"private/allowlistEnabled", false };
if (!whitelistEnabled.get()) {
if (!allowlistEnabled.get()) {
passList = true;
}
@ -2323,40 +2323,40 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
safeURLPrefixes += settingsSafeURLS;
// END Pull SAFEURLS from the Interface.JSON settings.
// Get current domain whitelist bypass, in case an entire domain is whitelisted.
// Get current domain allowlist bypass, in case an entire domain is allowlisted.
QString currentDomain = DependencyManager::get<AddressManager>()->getDomainURL().host();
QString domainSafeIP = nodeList->getDomainHandler().getHostname();
QString domainSafeURL = URL_SCHEME_OVERTE + "://" + currentDomain;
for (const auto& str : safeURLPrefixes) {
if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) {
qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed, entire domain is whitelisted. Current Domain Host: "
qCDebug(scriptengine) << allowlistPrefix << "Allowlist Bypassed, entire domain is allowlisted. Current Domain Host: "
<< nodeList->getDomainHandler().getHostname()
<< "Current Domain: " << currentDomain;
passList = true;
}
}
// END bypass whitelist based on current domain.
// END bypass allowlist based on current domain.
// Start processing scripts through the whitelist.
if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage whitelist.
// Start processing scripts through the allowlist.
if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage allowlist.
passList = true;
} else if (!passList) { // If waved through, do not engage whitelist.
} else if (!passList) { // If waved through, do not engage allowlist.
for (const auto& str : safeURLPrefixes) {
qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
qCDebug(scriptengine) << allowlistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN"
<< scriptOrURL.startsWith(str);
if (!str.isEmpty() && scriptOrURL.startsWith(str)) {
passList = true;
qCDebug(scriptengine) << whitelistPrefix << "Script approved.";
qCDebug(scriptengine) << allowlistPrefix << "Script approved.";
break; // Bail early since we found a match.
}
}
}
// END processing of scripts through the whitelist.
// END processing of scripts through the allowlist.
ScriptValue exception;
if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown.
qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL;
qCDebug(scriptengine) << allowlistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL;
exception = _engine->makeError(_engine->newValue("UNSAFE_ENTITY_SCRIPTS == 0"));
}
@ -2369,7 +2369,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
emit unhandledException(scriptRuntimeException);
return;
}
// ENTITY SCRIPT WHITELIST ENDS HERE, uncomment below for original full disabling.
// ENTITY SCRIPT ALLOWLIST ENDS HERE, uncomment below for original full disabling.
// qCDebug(scriptengine) << "(disabled entity script)" << entityID.toString() << scriptOrURL;
// exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0");

View file

@ -110,17 +110,17 @@ public slots:
bool getPersonalMuteStatus(const QUuid& nodeID);
/*@jsdoc
* Sets an avatar's gain (volume) for you and you only, or sets the master gain.
* Sets an avatar's gain (volume) for you and you only, or sets the primary gain.
* @function Users.setAvatarGain
* @param {Uuid} nodeID - The session ID of the avatar to set the gain for, or <code>null</code> to set the master gain.
* @param {Uuid} nodeID - The session ID of the avatar to set the gain for, or <code>null</code> to set the primary gain.
* @param {number} gain - The gain to set, in dB.
*/
void setAvatarGain(const QUuid& nodeID, float gain);
/*@jsdoc
* Gets an avatar's gain (volume) for you and you only, or gets the master gain.
* Gets an avatar's gain (volume) for you and you only, or gets the primary gain.
* @function Users.getAvatarGain
* @param {Uuid} nodeID - The session ID of the avatar to get the gain for, or <code>null</code> to get the master gain.
* @param {Uuid} nodeID - The session ID of the avatar to get the gain for, or <code>null</code> to get the primary gain.
* @returns {number} The gain, in dB.
*/
float getAvatarGain(const QUuid& nodeID);

View file

@ -854,11 +854,11 @@ void printSystemInformation() {
qCDebug(shared) << "Environment Variables";
// List of env variables to include in the log. For privacy reasons we don't send all env variables.
const QStringList envWhitelist = {
const QStringList envAllowlist = {
"QTWEBENGINE_REMOTE_DEBUGGING"
};
auto envVariables = QProcessEnvironment::systemEnvironment();
for (auto& env : envWhitelist)
for (auto& env : envAllowlist)
{
qCDebug(shared).noquote().nospace() << "\t" <<
(envVariables.contains(env) ? " = " + envVariables.value(env) : " NOT FOUND");

View file

@ -19,7 +19,7 @@
*/
#ifdef OVERTE_WARNINGS_WHITELIST_GCC
#ifdef OVERTE_WARNINGS_ALLOWLIST_GCC
#define OVERTE_IGNORE_DEPRECATED_BEGIN \
_Pragma("GCC diagnostic push") \
@ -27,7 +27,7 @@
#define OVERTE_IGNORE_DEPRECATED_END _Pragma("GCC diagnostic pop")
#elif OVERTE_WARNINGS_WHITELIST_CLANG
#elif OVERTE_WARNINGS_ALLOWLIST_CLANG
#define OVERTE_IGNORE_DEPRECATED_BEGIN \
_Pragma("clang diagnostic push") \
@ -35,7 +35,7 @@
#define OVERTE_IGNORE_DEPRECATED_END _Pragma("clang diagnostic pop")
#elif OVERTE_WARNINGS_WHITELIST_MSVC
#elif OVERTE_WARNINGS_ALLOWLIST_MSVC
#define OVERTE_IGNORE_DEPRECATED_BEGIN \
_Pragma("warning(push)") \

View file

@ -63,11 +63,11 @@
namespace hifi { namespace qml { namespace offscreen {
class OffscreenQmlWhitelist : public Dependency, private ReadWriteLockable {
class OffscreenQmlAllowlist : public Dependency, private ReadWriteLockable {
SINGLETON_DEPENDENCY
public:
void addWhitelistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback) {
void addAllowlistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback) {
withWriteLock([&] {
for (auto url : urls) {
if (url.isRelative()) {
@ -93,11 +93,11 @@ private:
QHash<QUrl, QList<QmlContextCallback>> _callbacks;
};
QSharedPointer<OffscreenQmlWhitelist> getQmlWhitelist() {
QSharedPointer<OffscreenQmlAllowlist> getQmlAllowlist() {
static std::once_flag once;
std::call_once(once, [&] { DependencyManager::set<OffscreenQmlWhitelist>(); });
std::call_once(once, [&] { DependencyManager::set<OffscreenQmlAllowlist>(); });
return DependencyManager::get<OffscreenQmlWhitelist>();
return DependencyManager::get<OffscreenQmlAllowlist>();
}
// Class to handle changing QML audio output device using another thread
@ -292,9 +292,9 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) {
engine->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
}
void OffscreenQmlSurface::addWhitelistContextHandler(const std::initializer_list<QUrl>& urls,
void OffscreenQmlSurface::addAllowlistContextHandler(const std::initializer_list<QUrl>& urls,
const QmlContextCallback& callback) {
getQmlWhitelist()->addWhitelistContextHandler(urls, callback);
getQmlAllowlist()->addAllowlistContextHandler(urls, callback);
}
void OffscreenQmlSurface::onRootContextCreated(QQmlContext* qmlContext) {
@ -319,17 +319,17 @@ void OffscreenQmlSurface::onRootContextCreated(QQmlContext* qmlContext) {
#endif
}
void OffscreenQmlSurface::applyWhiteList(const QUrl& url, QQmlContext* context) {
QList<QmlContextCallback> callbacks = getQmlWhitelist()->getCallbacksForUrl(url);
void OffscreenQmlSurface::applyAllowList(const QUrl& url, QQmlContext* context) {
QList<QmlContextCallback> callbacks = getQmlAllowlist()->getCallbacksForUrl(url);
for(const auto& callback : callbacks){
callback(context);
}
}
QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, QQuickItem* parent, bool forceNewContext) {
// Get any whitelist functionality
QList<QmlContextCallback> callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource);
// If we have whitelisted content, we must load a new context
// Get any allowlist functionality
QList<QmlContextCallback> callbacks = getQmlAllowlist()->getCallbacksForUrl(qmlSource);
// If we have allowlisted content, we must load a new context
forceNewContext |= !callbacks.empty();
QQmlContext* targetContext = Parent::contextForUrl(qmlSource, parent, forceNewContext);

View file

@ -28,9 +28,9 @@ class OffscreenQmlSurface : public hifi::qml::OffscreenSurface {
public:
~OffscreenQmlSurface();
static void addWhitelistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback);
static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); };
static void applyWhiteList(const QUrl& url,QQmlContext* context);
static void addAllowlistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback);
static void addAllowlistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addAllowlistContextHandler({ { url } }, callback); };
static void applyAllowList(const QUrl& url,QQmlContext* context);
bool isFocusText() const { return _focusText; }
bool getCleaned() { return _isCleaned; }

View file

@ -54,7 +54,7 @@ namespace {
return false;
}
// We can potentially add whitelisting logic or development environment variables that
// We can potentially add allowlisting logic or development environment variables that
// will allow people to override this setting on a per-client basis here.
QString targetFilePath = QFileInfo(requestUrl.toLocalFile()).canonicalFilePath();

View file

@ -487,13 +487,17 @@ Rectangle {
var last_item_index = channel.count - 1;
var last_item = channel.get(last_item_index);
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;
}
// 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;
// }
last_message_user = username;
last_message_time = new Date();
@ -510,7 +514,7 @@ Rectangle {
mess = mess.replace(arrow, "&lt;");
var link = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
mess = mess.replace(link, (match) => {return "<a onclick='Window.openUrl("+match+")' href='" + match + "'>" + match + "</a> <a onclick='Window.openUrl("+match+")'>⮺</a>"});
mess = mess.replace(link, (match) => {return `<a style="color:#4EBAFD" onclick='Window.openUrl("+match+")' href='` + match + `'>` + match + `</a> <a onclick='Window.openUrl(`+match+`)'></a>`});
var newline = /\n/gi;
mess = mess.replace(newline, "<br>");

View file

@ -36,8 +36,8 @@ var pickID = Picks.createPick(PickType.Ray, {
filter: PICK_FILTERS,
enabled: true,
});
var blacklist = [ overlayID ]; // exclude hover text from ray pick results
Picks.setIgnoreItems(pickID, blacklist);
var blocklist = [ overlayID ]; // exclude hover text from ray pick results
Picks.setIgnoreItems(pickID, blocklist);
Script.scriptEnding.connect(function() {
Picks.removePick(pickID);
});

View file

@ -56,7 +56,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
this.veryhighVarianceCount = 0;
this.orderedPluginNames = [];
this.tabletID = null;
this.blacklist = [];
this.blocklist = [];
this.pointerManager = new PointerManager();
this.grabSphereOverlays = [null, null];
this.targetIDs = {};
@ -169,8 +169,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
this.setIgnorePointerItems = function() {
if (HMD.tabletID && HMD.tabletID !== this.tabletID) {
this.tabletID = HMD.tabletID;
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist);
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist);
Pointers.setIgnoreItems(_this.leftPointer, _this.blocklist);
Pointers.setIgnoreItems(_this.rightPointer, _this.blocklist);
}
};
@ -547,19 +547,19 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
}
};
this.leftBlacklistTabletIDs = [];
this.rightBlacklistTabletIDs = [];
this.leftBlocklistTabletIDs = [];
this.rightBlocklistTabletIDs = [];
this.setLeftBlacklist = function () {
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat(_this.leftBlacklistTabletIDs));
this.setLeftBlocklist = function () {
Pointers.setIgnoreItems(_this.leftPointer, _this.blocklist.concat(_this.leftBlocklistTabletIDs));
};
this.setRightBlacklist = function () {
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat(_this.rightBlacklistTabletIDs));
this.setRightBlocklist = function () {
Pointers.setIgnoreItems(_this.rightPointer, _this.blocklist.concat(_this.rightBlocklistTabletIDs));
};
this.setBlacklist = function() {
_this.setLeftBlacklist();
_this.setRightBlacklist();
this.setBlocklist = function() {
_this.setLeftBlocklist();
_this.setRightBlocklist();
};
var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
@ -634,34 +634,34 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
var message;
if (sender === MyAvatar.sessionUUID) {
try {
if (channel === 'Hifi-Hand-RayPick-Blacklist') {
if (channel === 'Hifi-Hand-RayPick-Blocklist') {
message = JSON.parse(data);
var action = message.action;
var id = message.id;
var index = _this.blacklist.indexOf(id);
var index = _this.blocklist.indexOf(id);
if (action === 'add' && index === -1) {
_this.blacklist.push(id);
_this.setBlacklist();
_this.blocklist.push(id);
_this.setBlocklist();
}
if (action === 'remove') {
if (index > -1) {
_this.blacklist.splice(index, 1);
_this.setBlacklist();
_this.blocklist.splice(index, 1);
_this.setBlocklist();
}
}
if (action === "tablet") {
var tabletIDs = message.blacklist ?
var tabletIDs = message.blocklist ?
[HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID] :
[];
if (message.hand === LEFT_HAND) {
_this.leftBlacklistTabletIDs = tabletIDs;
_this.setLeftBlacklist();
_this.leftBlocklistTabletIDs = tabletIDs;
_this.setLeftBlocklist();
} else {
_this.rightBlacklistTabletIDs = tabletIDs;
_this.setRightBlacklist();
_this.rightBlocklistTabletIDs = tabletIDs;
_this.setRightBlocklist();
}
}
}
@ -737,7 +737,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
Entities.mousePressOnEntity.connect(mousePress);
var controllerDispatcher = new ControllerDispatcher();
Messages.subscribe('Hifi-Hand-RayPick-Blacklist');
Messages.subscribe('Hifi-Hand-RayPick-Blocklist');
Messages.messageReceived.connect(controllerDispatcher.handleMessage);
Picks.handLaserDelayChanged.connect(controllerDispatcher.handLaserDelayChanged);

View file

@ -299,7 +299,7 @@ Script.include("/~/system/libraries/controllers.js");
action: 'remove',
id: this.ignoredEntities[i]
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data));
}
this.ignoredEntities = [];
};
@ -394,7 +394,7 @@ Script.include("/~/system/libraries/controllers.js");
action: 'add',
id: intersection.objectID
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data));
this.ignoredEntities.push(intersection.objectID);
}
}

View file

@ -229,7 +229,7 @@ Script.include("/~/system/libraries/utils.js");
enableDispatcherModule("RightHandInEditMode", rightHandInEditMode);
var INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status";
var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist";
var HAND_RAYPICK_BLOCKLIST_CHANNEL = "Hifi-Hand-RayPick-Blocklist";
this.handleMessage = function (channel, data, sender) {
if (channel === INEDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) {
var message;
@ -247,10 +247,10 @@ Script.include("/~/system/libraries/utils.js");
} else {
rightHandInEditMode.isEditing = message.editing;
}
Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({
Messages.sendLocalMessage(HAND_RAYPICK_BLOCKLIST_CHANNEL, JSON.stringify({
action: "tablet",
hand: message.hand,
blacklist: message.editing
blocklist: message.editing
}));
break;
}

View file

@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
enableDispatcherModule("RightHandInVREditMode", rightHandInVREditMode);
var INVREDIT_STATUS_CHANNEL = "Hifi-InVREdit-Status";
var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist";
var HAND_RAYPICK_BLOCKLIST_CHANNEL = "Hifi-Hand-RayPick-Blocklist";
this.handleMessage = function (channel, data, sender) {
if (channel === INVREDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) {
var message;
@ -168,10 +168,10 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
} else {
rightHandInVREditMode.isEditing = message.editing;
}
Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({
Messages.sendLocalMessage(HAND_RAYPICK_BLOCKLIST_CHANNEL, JSON.stringify({
action: "tablet",
hand: message.hand,
blacklist: message.editing
blocklist: message.editing
}));
break;
}

View file

@ -113,7 +113,7 @@ Script.include("/~/system/libraries/controllers.js");
action: 'add',
id: objectID
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data));
this.ignoredObjects.push(objectID);
}
} else if (intersection.type === Picks.INTERSECTED_ENTITY) {
@ -122,7 +122,7 @@ Script.include("/~/system/libraries/controllers.js");
action: 'add',
id: objectID
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data));
this.ignoredObjects.push(objectID);
}
}
@ -134,7 +134,7 @@ Script.include("/~/system/libraries/controllers.js");
action: 'remove',
id: this.ignoredObjects[index]
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data));
}
this.ignoredObjects = [];

View file

@ -58,7 +58,7 @@ function runDefaultsTogether() {
function runDefaultsSeparately() {
for (var i in CONTOLLER_SCRIPTS) {
if (CONTOLLER_SCRIPTS.hasOwnProperty(i)) {
print("loading " + CONTOLLER_SCRIPTS[j]);
print("loading " + CONTOLLER_SCRIPTS[i]);
Script.load(CONTOLLER_SCRIPTS[i]);
}
}

View file

@ -31,6 +31,7 @@
// Program ----
function onMouseLookChanged(newMouseLook) {
disableMouseLook();
mouseLookEnabled = newMouseLook;
}
@ -38,8 +39,6 @@
// Toggle using the m key
if (event.text.toLowerCase() === "m") {
if (Camera.captureMouse) {
mouseLookActive = false;
Settings.setValue("mouselook-active", false);
disableMouseLook();
} else {
mouseLookActive = true;
@ -82,12 +81,16 @@
if (hmdActive) return;
if (tablet.tabletShown) return;
if (overlayActive) return;
if (!mouseLookEnabled) return; // Mouse look disabled via setting
if (!mouseLookActive) return; // Mouse look disabled via the hotkey
Camera.captureMouse = true;
}
function disableMouseLook() {
mouseLookActive = false;
Settings.setValue("mouselook-active", false);
Camera.captureMouse = false;
}

View file

@ -5,7 +5,7 @@
// Created by Ryan Huffman on 13 Nov 2014
// Copyright 2014 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2022 Overte e.V.
// Copyright 2022-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
@ -63,131 +63,298 @@
</table>
</div>
<div id="uiMaterialAssistant" style="display: none;">
<div id="uiMaterialAssistant-sidewalk">
<div id="uiMaterialAssistant-formContainer">
<div id="uiMaterialAssistant-headerContainer">
<div style="width: 85%; text-align: left;"><font class="uiMaterialAssistant-title">MATERIAL DATA</font></div>
<div style="width: 15%; text-align: right;"><span id="uiMaterialAssistant-closeButton">&#10006;</span></div>
</div>
<div class="uiMaterialAssistant-group">
<font class="uiMaterialAssistant-label">Name:&nbsp;</font>
<input name = "ma-name" id = "ma-name" type = "text" class="uiMaterialAssistant-input" style= "width: 90%;">
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-albedo-isActive"></button>
<font class="uiMaterialAssistant-label">Albedo (Color): </font>
<div id="ma-albedo-colorPicker" class="uiMaterialAssistant-color-picker"></div>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-albedoMap-isActive"></button>
<font class="uiMaterialAssistant-label">Albedo Map (RGB) URL: </font>
<input name = "ma-albedoMap" id = "ma-albedoMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">The Albedo (Color) can be used to tint the texture of the Albedo Map.</font>
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-metallic-isActive"></button>
<font class="uiMaterialAssistant-label">Metallic: </font>
<input class="uiMaterialAssistant-input" name = "ma-metallic" id = "ma-metallic" readonly type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="1" max="1000" value="1" class="uiMaterialAssistant-slider" name = "ma-metallic-slider" id = "ma-metallic-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 15%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Nonmetal</font></div>
<div style="width: 15%; text-align: left;"><font class = "uiMaterialAssistant-Explain">| Hair</font></div>
<div style="width: 60%; text-align: left;"><font class = "uiMaterialAssistant-Explain">| Chitin</font></div>
<div style="width: 10%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Metal &gt;|</font></div>
</div><br>
<font class="uiMaterialAssistant-label">Metallic Map (Grayscale) URL: </font>
<input name = "ma-metallicMap" id = "ma-metallicMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-roughness-isActive"></button>
<font class="uiMaterialAssistant-label">Roughness:</font>
<input name = "ma-roughness" id = "ma-roughness" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-roughness-slider" id = "ma-roughness-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 50%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Glossy, polished, lustrous</font></div>
<div style="width: 50%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Unpolished, mat, rough &gt;|</font></div>
</div><br>
<font class="uiMaterialAssistant-label">Roughness Map (Grayscale) URL: </font>
<input name = "ma-roughnessMap" id = "ma-roughnessMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-normalMap-isActive"></button>
<font class="uiMaterialAssistant-label">Normal Map URL: </font>
<input name = "ma-normalMap" id = "ma-normalMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-opacity-isActive"></button>
<font class="uiMaterialAssistant-label">Opacity: </font>
<input name = "ma-opacity" id = "ma-opacity" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-opacity-slider" id = "ma-opacity-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 50%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Transparent</font></div>
<div style="width: 50%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Opaque &gt;|</font></div>
<div id="uiMaterialAssistant-headerContainer">
<div style="width: 85%; text-align: left;"><font class="uiMaterialAssistant-title">MATERIAL DATA</font></div>
<div style="width: 15%; text-align: right;"><span id="uiMaterialAssistant-closeButton">&#10006;&nbsp;&nbsp;</span></div>
</div>
<div id="uiMaterialAssistant-scrollable">
<div id="uiMaterialAssistant-sidewalk">
<div id="uiMaterialAssistant-formContainer">
<div class="uiMaterialAssistant-group">
<font class="uiMaterialAssistant-label">Name:&nbsp;</font>
<input name = "ma-name" id = "ma-name" type = "text" class="uiMaterialAssistant-input" style= "width: 90%;">
</div>
<br>
<font class="uiMaterialAssistant-label">Opacity Map Mode:</font><br><br>
<input type="radio" class="uiMaterialAssistant-radio" checked name = "ma-opacityMapMode" id = "ma-opacityMapMode-dont" value = "OPACITY_MAP_OPAQUE"> Do not used&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-opacityMapMode" id = "ma-opacityMapMode-mask" value = "OPACITY_MAP_MASK"> Cut off mask&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-opacityMapMode" id = "ma-opacityMapMode-blend" value = "OPACITY_MAP_BLEND"> Blend<br>
<font class="uiMaterialAssistant-Explain"><br>Note: For an opacity map, the alpha layer of the Albedo Map will be used.<br>
'Blend' mode will used the alpha value to determine the opacity of a pixel.<br>
'Cut off mask' mode will use the 'Cut off threshold' to determine if a pixel will be opaque or transparent, based on the alpha value from the map.</font><br><br>
<font class="uiMaterialAssistant-label">Cut Off Threshold: </font>
<input name = "ma-opacityCutoff" id = "ma-opacityCutoff" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-opacityCutoff-slider" id = "ma-opacityCutoff-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 50%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Transparent</font></div>
<div style="width: 50%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Opaque &gt;|</font></div>
<div class="uiMaterialAssistant-group">
<font class="uiMaterialAssistant-label">Model: </font><br><br>
<input type="radio" class="uiMaterialAssistant-radio" checked name = "ma-Model" id = "ma-Model-hifi_pbr" value = "hifi_pbr"> PBR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-Model" id = "ma-Model-vrm_mtoon" value = "vrm_mtoon"> MToon&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-Model" id = "ma-Model-hifi_shader_simple" value = "hifi_shader_simple"> Shader (Simple)<br>
</div>
</div>
<div class="uiMaterialAssistant-group">
<div style="width: 100%; display: flex;">
<div style="width: 70%; text-align: left;">
<button class="uiMaterialAssistant-active" id="ma-emissive-isActive"></button>
<font class="uiMaterialAssistant-label">Emissive: </font>
<div id="ma-emissive-colorPicker" class="uiMaterialAssistant-color-picker"></div>
<div class="uiMaterialAssistant-group">
<div id="maContainerAlbedo">
<button class="uiMaterialAssistant-active" id="ma-albedo-isActive"></button>
<font class="uiMaterialAssistant-label">Albedo (Color): </font>
<div id="ma-albedo-colorPicker" class="uiMaterialAssistant-color-picker"></div>
</div>
<div style="width: 30%; text-align: left;">
<input type="checkbox" class="uiMaterialAssistant-checkbox" name = "ma-unlit" id = "ma-unlit">
<font class="uiMaterialAssistant-label">Unlit</font>
<br><br>
<div id="maContainerAlbedoMap">
<button class="uiMaterialAssistant-active" id="ma-albedoMap-isActive"></button>
<font class="uiMaterialAssistant-label">Albedo Map (RGB) URL: </font>
<input name = "ma-albedoMap" id = "ma-albedoMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">The Albedo (Color) can be used to tint the texture of the Albedo Map.</font>
</div>
</div>
<font class="uiMaterialAssistant-label">Bloom Factor:</font>
<input name = "ma-bloom" id = "ma-bloom" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="100" max="900" value="100" class="uiMaterialAssistant-slider" name = "ma-bloom-slider" id = "ma-bloom-slider"><br>
<font class="uiMaterialAssistant-label">Emissive Map (RGB) URL:</font>
<input name = "ma-emissiveMap" id = "ma-emissiveMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<div class="uiMaterialAssistant-group" id="maContainerMetallic">
<button class="uiMaterialAssistant-active" id="ma-metallic-isActive"></button>
<font class="uiMaterialAssistant-label">Metallic: </font>
<input class="uiMaterialAssistant-input" name = "ma-metallic" id = "ma-metallic" readonly type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="1" max="1000" value="1" class="uiMaterialAssistant-slider" name = "ma-metallic-slider" id = "ma-metallic-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 15%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Nonmetal</font></div>
<div style="width: 15%; text-align: left;"><font class = "uiMaterialAssistant-Explain">| Hair</font></div>
<div style="width: 60%; text-align: left;"><font class = "uiMaterialAssistant-Explain">| Chitin</font></div>
<div style="width: 10%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Metal &gt;|</font></div>
</div><br>
<font class="uiMaterialAssistant-label">Metallic Map (Red channel) URL: </font>
<input name = "ma-metallicMap" id = "ma-metallicMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<div style="display: flex;">
<div style="text-align: left;"><input type="checkbox" class="uiMaterialAssistant-checkbox" name = "ma-useSpecular" id = "ma-useSpecular"></div>
<div style="text-align: left; padding: 3px;"><font class="uiMaterialAssistant-label"> Instead, use Specular Map </font></div>
</div>
</div>
<div class="uiMaterialAssistant-group" id="maContainerRoughness">
<button class="uiMaterialAssistant-active" id="ma-roughness-isActive"></button>
<font class="uiMaterialAssistant-label">Roughness:</font>
<input name = "ma-roughness" id = "ma-roughness" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-roughness-slider" id = "ma-roughness-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 50%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Glossy, polished, lustrous</font></div>
<div style="width: 50%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Unpolished, mat, rough &gt;|</font></div>
</div><br>
<font class="uiMaterialAssistant-label">Roughness Map (Red channel) URL: </font>
<input name = "ma-roughnessMap" id = "ma-roughnessMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<div style="display: flex;">
<div style="text-align: left;"><input type="checkbox" class="uiMaterialAssistant-checkbox" name = "ma-useGloss" id = "ma-useGloss"></div>
<div style="text-align: left; padding: 3px;"><font class="uiMaterialAssistant-label"> Instead, use Gloss Map </font></div>
</div>
</div>
<div class="uiMaterialAssistant-group" id="maContainerNormalMap">
<button class="uiMaterialAssistant-active" id="ma-normalMap-isActive"></button>
<font class="uiMaterialAssistant-label">Normal Map URL: </font>
<input name = "ma-normalMap" id = "ma-normalMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<div style="display: flex;">
<div style="text-align: left;"><input type="checkbox" class="uiMaterialAssistant-checkbox" name = "ma-useBump" id = "ma-useBump"></div>
<div style="text-align: left; padding: 3px;"><font class="uiMaterialAssistant-label"> Instead, use Bump Map </font></div>
</div>
</div>
<div class="uiMaterialAssistant-group">
<div id="maContainerOpacity">
<button class="uiMaterialAssistant-active" id="ma-opacity-isActive"></button>
<font class="uiMaterialAssistant-label">Opacity: </font>
<input name = "ma-opacity" id = "ma-opacity" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-opacity-slider" id = "ma-opacity-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 50%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Transparent</font></div>
<div style="width: 50%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Opaque &gt;|</font></div>
</div>
</div>
<br>
<div id="maContainerOpacityMap">
<font class="uiMaterialAssistant-label">Opacity Map Mode:</font><br><br>
<input type="radio" class="uiMaterialAssistant-radio" checked name = "ma-opacityMapMode" id = "ma-opacityMapMode-dont" value = "OPACITY_MAP_OPAQUE"> Not used&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-opacityMapMode" id = "ma-opacityMapMode-mask" value = "OPACITY_MAP_MASK"> Cut off mask&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-opacityMapMode" id = "ma-opacityMapMode-blend" value = "OPACITY_MAP_BLEND"> Blend<br>
<font class="uiMaterialAssistant-Explain"><br>Note: For an opacity map, the alpha layer of the Albedo Map will be used.<br>
'Blend' mode will used the alpha value to determine the opacity of a pixel.<br>
'Cut off mask' mode will use the 'Cut off threshold' to determine if a pixel will be opaque or transparent, based on the alpha value from the map.</font><br><br>
<font class="uiMaterialAssistant-label">Cut Off Threshold: </font>
<input name = "ma-opacityCutoff" id = "ma-opacityCutoff" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-opacityCutoff-slider" id = "ma-opacityCutoff-slider"><br>
<div style="width: 100%; display: flex;">
<div style="width: 50%; text-align: left;"><font class = "uiMaterialAssistant-Explain">|&lt; Transparent</font></div>
<div style="width: 50%; text-align: right;"><font class = "uiMaterialAssistant-Explain">Opaque &gt;|</font></div>
</div>
</div>
</div>
<div class="uiMaterialAssistant-group" id = "maContainerEmissive">
<div style="width: 100%; display: flex;">
<div style="width: 65%; text-align: left;">
<button class="uiMaterialAssistant-active" id="ma-emissive-isActive"></button>
<font class="uiMaterialAssistant-label">Emissive: </font>
<div id="ma-emissive-colorPicker" class="uiMaterialAssistant-color-picker"></div>
</div>
<div style="width: 35%; text-align: left;">
<div id = "maContainerUnlit">
<div style="display: flex;">
<div style="text-align: left;"><input type="checkbox" class="uiMaterialAssistant-checkbox" name = "ma-unlit" id = "ma-unlit"></div>
<div style="text-align: left; padding: 3px;"><font class="uiMaterialAssistant-label"> Unlit</font></div>
</div>
</div>
</div>
</div>
<font class="uiMaterialAssistant-label">Bloom Factor:</font>
<input name = "ma-bloom" id = "ma-bloom" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="100" max="900" value="100" class="uiMaterialAssistant-slider" name = "ma-bloom-slider" id = "ma-bloom-slider"><br>
<div id = "maContainerEmissiveMap">
<font class="uiMaterialAssistant-label">Emissive Map (RGB) URL:</font>
<input name = "ma-emissiveMap" id = "ma-emissiveMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
</div>
</div>
<div class="uiMaterialAssistant-group" id="maContainerScattering">
<button class="uiMaterialAssistant-active" id="ma-scattering-isActive"></button>
<font class="uiMaterialAssistant-label">Scattering: </font>
<input name = "ma-scattering" id = "ma-scattering" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-scattering-slider" id = "ma-scattering-slider"><br>
<font class="uiMaterialAssistant-label">Scattering Map (Red channel) URL: </font>
<input name = "ma-scatteringMap" id = "ma-scatteringMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<font class="uiMaterialAssistant-Explain">Scattering or Scattering Map won't be effective without the presence of a Normal/Bump Map.</font>
</div>
<div class="uiMaterialAssistant-group" id="maContainerOcclusionMap">
<button class="uiMaterialAssistant-active" id="ma-occlusionMap-isActive"></button>
<font class="uiMaterialAssistant-label">Occlusion Map (Red channel) URL: </font>
<input name = "ma-occlusionMap" id = "ma-occlusionMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<font class="uiMaterialAssistant-Explain">Note: 'Occlusion Map' and 'Light Map' are using a separated UV Map.</font>
</div>
<div class="uiMaterialAssistant-group" id="maContainerLightMap">
<button class="uiMaterialAssistant-active" id="ma-lightMap-isActive"></button>
<font class="uiMaterialAssistant-label">Light Map (Red channel) URL: </font>
<input name = "ma-lightMap" id = "ma-lightMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
<font class="uiMaterialAssistant-Explain">Note: 'Light Map' and 'Occlusion Map' are using a separated UV Map.</font>
</div>
<div id="maContainerMtoon">
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-shade-isActive"></button>
<font class="uiMaterialAssistant-label">Shade (Color): </font>
<div id="ma-shade-colorPicker" class="uiMaterialAssistant-color-picker"></div>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-shadeMap-isActive"></button>
<font class="uiMaterialAssistant-label">Shade Map (RGB) URL: </font>
<input name = "ma-shadeMap" id = "ma-shadeMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">The Shade (Color) can be used to tint the texture of the Shade Map.</font>
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-matcap-isActive"></button>
<font class="uiMaterialAssistant-label">Matcap (Color): </font>
<div id="ma-matcap-colorPicker" class="uiMaterialAssistant-color-picker"></div>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-matcapMap-isActive"></button>
<font class="uiMaterialAssistant-label">Matcap Map (RGB) URL: </font>
<input name = "ma-matcapMap" id = "ma-matcapMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">The Matcap (Color) can be used to tint the texture of the Matcap Map.</font>
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-shadingShift-isActive"></button>
<font class="uiMaterialAssistant-label">Shading Shift: </font>
<input name = "ma-shadingShift" id = "ma-shadingShift" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-shadingShift-slider" id = "ma-shadingShift-slider">
<br><br>
<button class="uiMaterialAssistant-active" id="ma-shadingShiftMap-isActive"></button>
<font class="uiMaterialAssistant-label">Shading Shift Map (Red Channel) URL: </font>
<input name = "ma-shadingShiftMap" id = "ma-shadingShiftMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">The Shading Shift value can be used to multiply the effect of the Shading Shift Map. Shading Shift Map can be RGB texture, but it will only used the "red" channel.</font>
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-shadingToony-isActive"></button>
<font class="uiMaterialAssistant-label">Shading Toony: </font>
<input name = "ma-shadingToony" id = "ma-shadingToony" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-shadingToony-slider" id = "ma-shadingToony-slider">
<font class="uiMaterialAssistant-Explain">&nbsp;</font>
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-parametricRim-isActive"></button>
<font class="uiMaterialAssistant-label">Parametric Rim (Color): </font>
<div id="ma-parametricRim-colorPicker" class="uiMaterialAssistant-color-picker"></div>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-parametricRimFresnelPower-isActive"></button>
<font class="uiMaterialAssistant-label">Parametric Rim Fresnel Power: </font>
<input name = "ma-parametricRimFresnelPower" id = "ma-parametricRimFresnelPower" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="20000" value="0" class="uiMaterialAssistant-slider" name = "ma-parametricRimFresnelPower-slider" id = "ma-parametricRimFresnelPower-slider">
<font class="uiMaterialAssistant-Explain">&nbsp;</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-parametricRimLift-isActive"></button>
<font class="uiMaterialAssistant-label">Parametric Rim Lift Factor: </font>
<input name = "ma-parametricRimLift" id = "ma-parametricRimLift" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="-10000" max="10000" value="0" class="uiMaterialAssistant-slider" name = "ma-parametricRimLift-slider" id = "ma-parametricRimLift-slider">
<font class="uiMaterialAssistant-Explain">&nbsp;</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-rimMap-isActive"></button>
<font class="uiMaterialAssistant-label">Rim Map (RGB) URL: </font>
<input name = "ma-rimMap" id = "ma-rimMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">&nbsp;</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-rimLightingMix-isActive"></button>
<font class="uiMaterialAssistant-label">Rim Lighting Mix: </font>
<input name = "ma-rimLightingMix" id = "ma-rimLightingMix" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-rimLightingMix-slider" id = "ma-rimLightingMix-slider">
<font class="uiMaterialAssistant-Explain">How much to mix between the rim color and normal lighting.</font>
</div>
<!-- ############ Not supported yet, but the code is ready (commented) ##########################################################
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-outlineWidthMode-isActive"></button>
<font class="uiMaterialAssistant-label">Outline Width Mode : </font><br><br>
<input type="radio" class="uiMaterialAssistant-radio" checked name = "ma-outlineWidthMode" id = "ma-outlineWidthMode-none" value = "none"> None&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-outlineWidthMode" id = "ma-outlineWidthMode-world" value = "worldCoordinates"> World Coordinates&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-outlineWidthMode" id = "ma-outlineWidthMode-screen" value = "screenCoordinates"> Screen Coordinates<br>
<font class="uiMaterialAssistant-Explain">'World Coordinates' will render an outline with a constant world size, i.e. its apparent size depends on distance.
'Screen Coordinates' will render an outline with a constant screen size, i.e. its apparent size remains constant.</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-outlineWidth-isActive"></button>
<font class="uiMaterialAssistant-label">Outline Width: </font>
<input name = "ma-outlineWidth" id = "ma-outlineWidth" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-outlineWidth-slider" id = "ma-outlineWidth-slider">
<font class="uiMaterialAssistant-Explain">The width of the outline, in meters if the mode is 'World Coordinates', or a ratio of the screen height if the Mode is 'Screen Coordinates'.</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-outline-isActive"></button>
<font class="uiMaterialAssistant-label">Outline (Color): </font>
<div id="ma-outline-colorPicker" class="uiMaterialAssistant-color-picker"></div>
</div>
############################################################################################################ -->
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-uvAnimationMaskMap-isActive"></button>
<font class="uiMaterialAssistant-label">UV Animation Mask Map (Blue Channel) URL: </font>
<input name = "ma-uvAnimationMaskMap" id = "ma-uvAnimationMaskMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;"><br>
<font class="uiMaterialAssistant-Explain">UV Animation Mask Map can be RGB texture, but it will only used the "blue" channel.</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-uvAnimationScrollXSpeed-isActive"></button>
<font class="uiMaterialAssistant-label">UV Animation Scroll X Speed: </font>
<input name = "ma-uvAnimationScrollXSpeed" id = "ma-uvAnimationScrollXSpeed" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="-3000" max="3000" value="0" class="uiMaterialAssistant-slider" name = "ma-uvAnimationScrollXSpeed-slider" id = "ma-uvAnimationScrollXSpeed-slider">
<font class="uiMaterialAssistant-Explain">The speed of the UV scrolling animation in the X dimension, in UV units per second.</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-uvAnimationScrollYSpeed-isActive"></button>
<font class="uiMaterialAssistant-label">UV Animation Scroll Y Speed: </font>
<input name = "ma-uvAnimationScrollYSpeed" id = "ma-uvAnimationScrollYSpeed" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="-3000" max="3000" value="0" class="uiMaterialAssistant-slider" name = "ma-uvAnimationScrollYSpeed-slider" id = "ma-uvAnimationScrollYSpeed-slider">
<font class="uiMaterialAssistant-Explain">The speed of the UV scrolling animation in the Y dimension, in UV units per second.</font>
<br><br>
<button class="uiMaterialAssistant-active" id="ma-uvAnimationRotationSpeed-isActive"></button>
<font class="uiMaterialAssistant-label">UV Animation Rotation Speed: </font>
<input name = "ma-uvAnimationRotationSpeed" id = "ma-uvAnimationRotationSpeed" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="-10000" max="10000" value="0" class="uiMaterialAssistant-slider" name = "ma-uvAnimationRotationSpeed-slider" id = "ma-uvAnimationRotationSpeed-slider">
<font class="uiMaterialAssistant-Explain">The speed of the UV scrolling rotation around the center (0.5 UV, 0.5 UV), in radians per second.</font>
</div>
</div>
<div id="maContainerShaderSimple">
<div class="uiMaterialAssistant-group">
<font class="uiMaterialAssistant-label">Procedural (json):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font>
<button class="uiMaterialAssistant-smallButton" id= "ma-addProceduralTemplate">Use Basic Template</button>
<textarea name = "ma-procedural" id = "ma-procedural" class="uiMaterialAssistant-textarea"></textarea><br>
<font class="uiMaterialAssistant-Explain">&nbsp;</font>
</div>
</div>
<div class="uiMaterialAssistant-group">
<font class="uiMaterialAssistant-label">Material displayed on surface: </font><br><br>
<input type="radio" class="uiMaterialAssistant-radio" checked name = "ma-cullFaceMode" id = "ma-cullFaceMode-back" value = "CULL_BACK"> Outside&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-cullFaceMode" id = "ma-cullFaceMode-front" value = "CULL_FRONT"> Inside&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-cullFaceMode" id = "ma-cullFaceMode-none" value = "CULL_NONE"> Both<br>
</div>
<br><br><br><br><br>
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-scattering-isActive"></button>
<font class="uiMaterialAssistant-label">Scattering: </font>
<input name = "ma-scattering" id = "ma-scattering" readonly class="uiMaterialAssistant-input" type = "text" size = "5"><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="uiMaterialAssistant-slider" name = "ma-scattering-slider" id = "ma-scattering-slider"><br>
<font class="uiMaterialAssistant-label">Scattering Map (Grayscale) URL: </font>
<input name = "ma-scatteringMap" id = "ma-scatteringMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
</div>
<div class="uiMaterialAssistant-group">
<button class="uiMaterialAssistant-active" id="ma-occlusionMap-isActive"></button>
<font class="uiMaterialAssistant-label">Occlusion Map (Grayscale) URL: </font>
<input name = "ma-occlusionMap" id = "ma-occlusionMap" class="uiMaterialAssistant-input" type = "text" style= "width:100%;">
</div>
<div class="uiMaterialAssistant-group">
<font class="uiMaterialAssistant-label">Material displayed on surface: </font><br><br>
<input type="radio" class="uiMaterialAssistant-radio" checked name = "ma-cullFaceMode" id = "ma-cullFaceMode-back" value = "CULL_BACK"> Outside&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-cullFaceMode" id = "ma-cullFaceMode-front" value = "CULL_FRONT"> Inside&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" class="uiMaterialAssistant-radio" name = "ma-cullFaceMode" id = "ma-cullFaceMode-none" value = "CULL_NONE"> Both<br>
</div>
<br><br><br><br><br>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show more