mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 10:30:05 +02:00
Compare commits
139 commits
Author | SHA1 | Date | |
---|---|---|---|
|
1ceeb39306 | ||
|
80c7b8f993 | ||
|
7b1bbb6b2d | ||
|
a2a1fca274 | ||
|
5ea07c8eb2 | ||
|
3be716cb05 | ||
|
cc20c37e05 | ||
|
e38f8bea34 | ||
|
3ca1d5f14b | ||
|
ae5c1d8d00 | ||
|
479b1aa6da | ||
|
385b33f6d2 | ||
|
dfe92064b9 | ||
|
e1f2551e30 | ||
|
7f4a489945 | ||
|
5cf56caf81 | ||
|
e98f08fa61 | ||
|
2e85e2e544 | ||
|
c39868e8f0 | ||
|
7ae59eb5dc | ||
|
86a71b589b | ||
|
45616a0db7 | ||
|
521d9d278f | ||
|
ca083aee9f | ||
|
c3595dc672 | ||
09e5a60c8b | |||
8badda8128 | |||
ec5aa9ff1d | |||
7bd436dd0d | |||
13a7ea356a | |||
bb8bac43ea | |||
1ba6026a85 | |||
4b9ddbc260 | |||
32fe7777e6 | |||
57864178c0 | |||
9ec0842dab | |||
7080067afc | |||
a18aee1c60 | |||
4e81908156 | |||
|
c541b64f66 | ||
|
dd01944bbf | ||
8661e8a858 | |||
fe6d76b935 | |||
9bdfc8344a | |||
|
f9ffccfe00 | ||
|
84b16f44aa | ||
|
9cb35541d3 | ||
|
fe550aa69f | ||
|
19144e492c | ||
|
46787eebf0 | ||
|
268de192f7 | ||
2010bb44e8 | |||
9f80c9de58 | |||
|
ed88ab5ecb | ||
|
74002b4738 | ||
|
58e84acd5f | ||
|
a58e188b5c | ||
|
8a770094bb | ||
|
f3cb4e2ca9 | ||
|
bf03847549 | ||
|
8bdc5bb4cf | ||
|
edb8cc55b4 | ||
|
022f1497c5 | ||
|
376cd078e5 | ||
|
b22f5fe4fe | ||
5aac93352c | |||
46a80fcfdb | |||
|
8f27a4bf2b | ||
95406c44c6 | |||
1887a82b4b | |||
e57874a2bd | |||
379db8b17c | |||
|
426df9dc94 | ||
|
b8a9881d41 | ||
|
750c5f20f6 | ||
|
a6646d8dff | ||
f1475e49ee | |||
|
c41c2deb77 | ||
|
cc8133bf08 | ||
|
7500a74e2b | ||
36b6010c08 | |||
edb3580520 | |||
65387adee8 | |||
d44ae7a961 | |||
bf601dfa6e | |||
5f0f03af0a | |||
7fdd4aef11 | |||
a0aae43386 | |||
076bd2dbee | |||
16530b2334 | |||
225578febe | |||
922ae918e9 | |||
aff59e5469 | |||
|
ef6f2737b6 | ||
|
74b9561afe | ||
9106746bc9 | |||
|
7734357398 | ||
|
3bc04c9c06 | ||
|
ca4dde4bb1 | ||
|
ff91b93ed8 | ||
|
9c823a8534 | ||
|
a509f84a42 | ||
|
f50101db8a | ||
854d80aace | |||
|
40761fb545 | ||
3d5afbdd31 | |||
c50a4f9cb8 | |||
|
65f55dd5fb | ||
|
2e7b19ea40 | ||
38caf617a2 | |||
ef4c99b027 | |||
58a7819fef | |||
03dbbb94c8 | |||
6f8f32d802 | |||
|
be95d324cc | ||
|
7c8044d27b | ||
|
e29549e711 | ||
|
ad3236ba37 | ||
|
0c868bd416 | ||
|
e27696802b | ||
|
8b35693701 | ||
|
94a229b9e7 | ||
|
6bee693d0c | ||
|
2f3aefc926 | ||
|
e802d0ec12 | ||
|
dac3006d8b | ||
|
4595d94bfe | ||
|
9acd1a93c1 | ||
634dc64f8f | |||
78978c7097 | |||
bd14f39f66 | |||
347987591f | |||
|
7b4c26be84 | ||
805cd78728 | |||
|
903984f427 | ||
|
3daa40087e | ||
cd8ad23dd1 | |||
93a243d095 | |||
|
f27263cc6a |
173 changed files with 5374 additions and 1488 deletions
29
.github/workflows/linux_server_build.yml
vendored
29
.github/workflows/linux_server_build.yml
vendored
|
@ -1,6 +1,6 @@
|
|||
# Copyright 2013-2019 High Fidelity, Inc.
|
||||
# Copyright 2020-2022 Vircadia contributors.
|
||||
# Copyright 2021-2023 Overte e.V.
|
||||
# Copyright 2021-2024 Overte e.V.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: Linux Server CI Build
|
||||
|
@ -65,6 +65,16 @@ jobs:
|
|||
arch: aarch64
|
||||
runner: linux_aarch64
|
||||
|
||||
- os: ubuntu-24.04
|
||||
image: docker.io/overte/overte-server-build:0.1.3-ubuntu-24.04-amd64
|
||||
arch: amd64
|
||||
runner: linux_amd64
|
||||
|
||||
- os: ubuntu-24.04
|
||||
image: docker.io/overte/overte-server-build:0.1.3-ubuntu-24.04-aarch64
|
||||
arch: aarch64
|
||||
runner: linux_aarch64
|
||||
|
||||
- os: fedora-38
|
||||
image: docker.io/overte/overte-server-build:0.1.3-fedora-38-amd64
|
||||
arch: amd64
|
||||
|
@ -75,15 +85,16 @@ jobs:
|
|||
arch: aarch64
|
||||
runner: linux_aarch64
|
||||
|
||||
- os: fedora-39
|
||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-39-amd64
|
||||
arch: amd64
|
||||
runner: linux_amd64
|
||||
# Packaging broken; See: https://github.com/overte-org/overte/issues/968
|
||||
#~ - os: fedora-39
|
||||
#~ image: docker.io/overte/overte-server-build:0.1.4-fedora-39-amd64
|
||||
#~ arch: amd64
|
||||
#~ runner: linux_amd64
|
||||
|
||||
- os: fedora-39
|
||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-39-aarch64
|
||||
arch: aarch64
|
||||
runner: linux_aarch64
|
||||
#~ - os: fedora-39
|
||||
#~ image: docker.io/overte/overte-server-build:0.1.4-fedora-39-aarch64
|
||||
#~ arch: aarch64
|
||||
#~ runner: linux_aarch64
|
||||
|
||||
- os: rockylinux-9
|
||||
image: docker.io/overte/overte-server-build:0.1.3-rockylinux-9-amd64
|
||||
|
|
|
@ -184,8 +184,13 @@ if(OVERTE_WARNINGS_WHITELIST)
|
|||
endif()
|
||||
|
||||
if(OVERTE_WARNINGS_AS_ERRORS)
|
||||
set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} -Werror")
|
||||
set(ENV{CFLAGS} "$ENV{CXXFLAGS} -Werror")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "" AND WIN32))
|
||||
set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} /WX")
|
||||
set(ENV{CFLAGS} "$ENV{CXXFLAGS} /WX")
|
||||
else()
|
||||
set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} -Werror")
|
||||
set(ENV{CFLAGS} "$ENV{CXXFLAGS} -Werror")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -252,9 +257,6 @@ else()
|
|||
endif()
|
||||
|
||||
set(SCREENSHARE 0)
|
||||
if (WIN32)
|
||||
set(SCREENSHARE 1)
|
||||
endif()
|
||||
if (APPLE AND NOT CLIENT_ONLY)
|
||||
# Don't include Screenshare in OSX client-only builds.
|
||||
set(SCREENSHARE 1)
|
||||
|
|
|
@ -109,7 +109,7 @@ public class PermissionChecker extends Activity {
|
|||
JSONObject obj = new JSONObject();
|
||||
try {
|
||||
obj.put("firstRun",false);
|
||||
obj.put("Avatar/fullAvatarURL", avatarPaths[which]);
|
||||
obj.put(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/Avatar/fullAvatarURL", avatarPaths[which]);
|
||||
File directory = new File(pathForJson);
|
||||
|
||||
if(!directory.exists()) directory.mkdirs();
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
class AgentScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar)
|
||||
Q_PROPERTY(bool isAvatar READ getIsAvatar WRITE setIsAvatar)
|
||||
Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound)
|
||||
Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream)
|
||||
Q_PROPERTY(bool isNoiseGateEnabled READ isNoiseGateEnabled WRITE setIsNoiseGateEnabled)
|
||||
|
@ -77,15 +77,15 @@ public slots:
|
|||
|
||||
/*@jsdoc
|
||||
* Checks whether the script is emulating an avatar.
|
||||
* @function Agent.isAvatar
|
||||
* @function Agent.getIsAvatar
|
||||
* @returns {boolean} <code>true</code> if the script is emulating an avatar, otherwise <code>false</code>.
|
||||
* @example <caption>Check whether the agent is emulating an avatar.</caption>
|
||||
* (function () {
|
||||
* print("Agent is avatar: " + Agent.isAvatar());
|
||||
* print("Agent is avatar: " + Agent.getIsAvatar());
|
||||
* print("Agent is avatar: " + Agent.isAvatar); // Same result.
|
||||
* }());
|
||||
*/
|
||||
bool isAvatar() const { return _agent->isAvatar(); }
|
||||
bool getIsAvatar() const { return _agent->isAvatar(); }
|
||||
|
||||
/*@jsdoc
|
||||
* Plays a sound from the position and with the orientation of the emulated avatar's head. No sound is played unless
|
||||
|
|
|
@ -30,8 +30,12 @@
|
|||
#include <NetworkingConstants.h>
|
||||
|
||||
|
||||
ScriptableAvatar::ScriptableAvatar(): _scriptEngine(newScriptEngine()) {
|
||||
ScriptableAvatar::ScriptableAvatar() {
|
||||
_clientTraitsHandler.reset(new ClientTraitsHandler(this));
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
qRegisterMetaType<HFMModel::Pointer>("HFMModel::Pointer");
|
||||
});
|
||||
}
|
||||
|
||||
QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
|
||||
|
@ -52,6 +56,7 @@ void ScriptableAvatar::startAnimation(const QString& url, float fps, float prior
|
|||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(url);
|
||||
_animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame, false);
|
||||
_maskedJoints = maskedJoints;
|
||||
_isAnimationRigValid = false;
|
||||
}
|
||||
|
||||
void ScriptableAvatar::stopAnimation() {
|
||||
|
@ -89,11 +94,12 @@ QStringList ScriptableAvatar::getJointNames() const {
|
|||
}
|
||||
|
||||
void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
_bind.reset();
|
||||
_animSkeleton.reset();
|
||||
_avatarAnimSkeleton.reset();
|
||||
_geometryResource.reset();
|
||||
|
||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||
updateJointMappings();
|
||||
_isRigValid = false;
|
||||
}
|
||||
|
||||
int ScriptableAvatar::sendAvatarDataPacket(bool sendAll) {
|
||||
|
@ -137,65 +143,87 @@ static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation,
|
|||
}
|
||||
|
||||
void ScriptableAvatar::update(float deltatime) {
|
||||
if (!_geometryResource && !_skeletonModelFilenameURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton.
|
||||
_geometryResource = DependencyManager::get<ModelCache>()->getGeometryResource(_skeletonModelFilenameURL);
|
||||
}
|
||||
|
||||
// Run animation
|
||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
|
||||
if (!_animSkeleton) {
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getHFMModel());
|
||||
}
|
||||
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
||||
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
||||
while (currentFrame >= _animationDetails.lastFrame) {
|
||||
currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame);
|
||||
Q_ASSERT(QThread::currentThread() == thread());
|
||||
if (_animation && _animation->isLoaded()) {
|
||||
Q_ASSERT(thread() == _animation->thread());
|
||||
auto frames = _animation->getFramesReference();
|
||||
if (frames.size() > 0 && _geometryResource && _geometryResource->isHFMModelLoaded()) {
|
||||
if (!_isRigValid) {
|
||||
_rig.reset(_geometryResource->getHFMModel());
|
||||
_isRigValid = true;
|
||||
}
|
||||
_animationDetails.currentFrame = currentFrame;
|
||||
|
||||
const QVector<HFMJoint>& modelJoints = _bind->getHFMModel().joints;
|
||||
QStringList animationJointNames = _animation->getJointNames();
|
||||
|
||||
const int nJoints = modelJoints.size();
|
||||
if (_jointData.size() != nJoints) {
|
||||
_jointData.resize(nJoints);
|
||||
if (!_isAnimationRigValid) {
|
||||
_animationRig.reset(_animation->getHFMModel());
|
||||
_isAnimationRigValid = true;
|
||||
}
|
||||
|
||||
const int frameCount = _animation->getFrames().size();
|
||||
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
||||
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||
const float frameFraction = glm::fract(currentFrame);
|
||||
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
||||
const float UNIT_SCALE = 0.01f;
|
||||
|
||||
for (int i = 0; i < animationJointNames.size(); i++) {
|
||||
const QString& name = animationJointNames[i];
|
||||
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
|
||||
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
||||
int mapping = _bind->getHFMModel().getJointIndex(name);
|
||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||
|
||||
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);
|
||||
AnimPose ceilPose = composeAnimPose(modelJoints[mapping], ceilFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);
|
||||
blend(1, &floorPose, &ceilPose, frameFraction, &poses[mapping]);
|
||||
}
|
||||
if (!_avatarAnimSkeleton) {
|
||||
_avatarAnimSkeleton = std::make_shared<AnimSkeleton>(_geometryResource->getHFMModel());
|
||||
}
|
||||
|
||||
std::vector<AnimPose> absPoses = poses;
|
||||
_animSkeleton->convertRelativePosesToAbsolute(absPoses);
|
||||
for (int i = 0; i < nJoints; i++) {
|
||||
JointData& data = _jointData[i];
|
||||
AnimPose& absPose = absPoses[i];
|
||||
if (data.rotation != absPose.rot()) {
|
||||
data.rotation = absPose.rot();
|
||||
data.rotationIsDefaultPose = false;
|
||||
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
||||
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
||||
while (currentFrame >= _animationDetails.lastFrame) {
|
||||
currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame);
|
||||
}
|
||||
AnimPose& relPose = poses[i];
|
||||
if (data.translation != relPose.trans()) {
|
||||
data.translation = relPose.trans();
|
||||
data.translationIsDefaultPose = false;
|
||||
}
|
||||
}
|
||||
_animationDetails.currentFrame = currentFrame;
|
||||
|
||||
} else {
|
||||
_animation.clear();
|
||||
const QVector<HFMJoint>& modelJoints = _geometryResource->getHFMModel().joints;
|
||||
QStringList animationJointNames = _animation->getJointNames();
|
||||
|
||||
const int nJoints = modelJoints.size();
|
||||
if (_jointData.size() != nJoints) {
|
||||
_jointData.resize(nJoints);
|
||||
}
|
||||
|
||||
const int frameCount = frames.size();
|
||||
const HFMAnimationFrame& floorFrame = frames.at((int)glm::floor(currentFrame) % frameCount);
|
||||
const HFMAnimationFrame& ceilFrame = frames.at((int)glm::ceil(currentFrame) % frameCount);
|
||||
const float frameFraction = glm::fract(currentFrame);
|
||||
std::vector<AnimPose> poses = _avatarAnimSkeleton->getRelativeDefaultPoses();
|
||||
|
||||
// TODO: this needs more testing, it's possible that we need not only scale but also rotation and translation
|
||||
// According to tests with unmatching avatar and animation armatures, sometimes bones are not rotated correctly.
|
||||
// Matching armatures already work very well now.
|
||||
const float UNIT_SCALE = _animationRig.GetScaleFactorGeometryToUnscaledRig() / _rig.GetScaleFactorGeometryToUnscaledRig();
|
||||
|
||||
for (int i = 0; i < animationJointNames.size(); i++) {
|
||||
const QString& name = animationJointNames[i];
|
||||
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
|
||||
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
||||
int mapping = _geometryResource->getHFMModel().getJointIndex(name);
|
||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i],
|
||||
floorFrame.translations[i] * UNIT_SCALE);
|
||||
AnimPose ceilPose = composeAnimPose(modelJoints[mapping], ceilFrame.rotations[i],
|
||||
ceilFrame.translations[i] * UNIT_SCALE);
|
||||
blend(1, &floorPose, &ceilPose, frameFraction, &poses[mapping]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<AnimPose> absPoses = poses;
|
||||
Q_ASSERT(_avatarAnimSkeleton != nullptr);
|
||||
_avatarAnimSkeleton->convertRelativePosesToAbsolute(absPoses);
|
||||
for (int i = 0; i < nJoints; i++) {
|
||||
JointData& data = _jointData[i];
|
||||
AnimPose& absPose = absPoses[i];
|
||||
if (data.rotation != absPose.rot()) {
|
||||
data.rotation = absPose.rot();
|
||||
data.rotationIsDefaultPose = false;
|
||||
}
|
||||
AnimPose& relPose = poses[i];
|
||||
if (data.translation != relPose.trans()) {
|
||||
data.translation = relPose.trans();
|
||||
data.translationIsDefaultPose = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
_animation.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,6 +273,7 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() {
|
|||
networkReply->deleteLater();
|
||||
return;
|
||||
}
|
||||
// TODO: this works only with .fst files currently, not directly with FBX and GLB models
|
||||
{
|
||||
QWriteLocker writeLock(&_jointDataLock);
|
||||
QByteArray line;
|
||||
|
@ -253,7 +282,7 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() {
|
|||
if (line.startsWith("filename")) {
|
||||
int filenameIndex = line.indexOf('=') + 1;
|
||||
if (filenameIndex > 0) {
|
||||
_skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed()));
|
||||
_skeletonModelFilenameURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed()));
|
||||
}
|
||||
}
|
||||
if (!line.startsWith("jointIndex")) {
|
||||
|
@ -315,7 +344,9 @@ AvatarEntityMap ScriptableAvatar::getAvatarEntityDataInternal(bool allProperties
|
|||
EntityItemProperties properties = entity->getProperties(desiredProperties);
|
||||
|
||||
QByteArray blob;
|
||||
EntityItemProperties::propertiesToBlob(*_scriptEngine, sessionID, properties, blob, allProperties);
|
||||
_helperScriptEngine.run( [&] {
|
||||
EntityItemProperties::propertiesToBlob(*_helperScriptEngine.get(), sessionID, properties, blob, allProperties);
|
||||
});
|
||||
data[id] = blob;
|
||||
}
|
||||
});
|
||||
|
@ -339,8 +370,12 @@ void ScriptableAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityDa
|
|||
while (dataItr != avatarEntityData.end()) {
|
||||
EntityItemProperties properties;
|
||||
const QByteArray& blob = dataItr.value();
|
||||
if (!blob.isNull() && EntityItemProperties::blobToProperties(*_scriptEngine, blob, properties)) {
|
||||
newProperties[dataItr.key()] = properties;
|
||||
if (!blob.isNull()) {
|
||||
_helperScriptEngine.run([&] {
|
||||
if (EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), blob, properties)) {
|
||||
newProperties[dataItr.key()] = properties;
|
||||
}
|
||||
});
|
||||
}
|
||||
++dataItr;
|
||||
}
|
||||
|
@ -419,9 +454,16 @@ void ScriptableAvatar::updateAvatarEntity(const QUuid& entityID, const QByteArra
|
|||
|
||||
EntityItemPointer entity;
|
||||
EntityItemProperties properties;
|
||||
if (!EntityItemProperties::blobToProperties(*_scriptEngine, entityData, properties)) {
|
||||
// entityData is corrupt
|
||||
return;
|
||||
{
|
||||
// TODO: checking how often this happens and what is the performance impact of having the script engine on separate thread
|
||||
// If it's happening often, a method to move HelperScriptEngine into the current thread would be a good idea
|
||||
bool result = _helperScriptEngine.runWithResult<bool> ( [&]() {
|
||||
return EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), entityData, properties);
|
||||
});
|
||||
if (!result) {
|
||||
// entityData is corrupt
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<QUuid, EntityItemPointer>::iterator itr = _entities.find(entityID);
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include <AvatarData.h>
|
||||
#include <ScriptEngine.h>
|
||||
#include <EntityItem.h>
|
||||
#include "model-networking/ModelCache.h"
|
||||
#include "Rig.h"
|
||||
#include <HelperScriptEngine.h>
|
||||
|
||||
/*@jsdoc
|
||||
* The <code>Avatar</code> API is used to manipulate scriptable avatars on the domain. This API is a subset of the
|
||||
|
@ -217,12 +220,16 @@ private:
|
|||
AnimationPointer _animation;
|
||||
AnimationDetails _animationDetails;
|
||||
QStringList _maskedJoints;
|
||||
AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies
|
||||
std::shared_ptr<AnimSkeleton> _animSkeleton;
|
||||
GeometryResource::Pointer _geometryResource;
|
||||
Rig _rig;
|
||||
bool _isRigValid{false};
|
||||
Rig _animationRig;
|
||||
bool _isAnimationRigValid{false};
|
||||
std::shared_ptr<AnimSkeleton> _avatarAnimSkeleton;
|
||||
QHash<QString, int> _fstJointIndices; ///< 1-based, since zero is returned for missing keys
|
||||
QStringList _fstJointNames; ///< in order of depth-first traversal
|
||||
QUrl _skeletonFBXURL;
|
||||
mutable ScriptEnginePointer _scriptEngine;
|
||||
QUrl _skeletonModelFilenameURL; // This contains URL from filename field in fst file
|
||||
mutable HelperScriptEngine _helperScriptEngine;
|
||||
std::map<QUuid, EntityItemPointer> _entities;
|
||||
|
||||
/// Loads the joint indices, names from the FST file (if any)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Source: hifi-client-deps
|
||||
Version: 0.1
|
||||
Description: Collected dependencies for High Fidelity applications
|
||||
Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr ((linux&!arm)|windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator, discord-rpc (!android)
|
||||
Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr ((linux&!arm)|windows), openxr-loader, quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator, discord-rpc (!android)
|
||||
|
|
34
cmake/ports/jsoncpp/portfile.cmake
Normal file
34
cmake/ports/jsoncpp/portfile.cmake
Normal file
|
@ -0,0 +1,34 @@
|
|||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO open-source-parsers/jsoncpp
|
||||
REF "${VERSION}"
|
||||
SHA512 1d06e044759b1e1a4cc4960189dd7e001a0a4389d7239a6d59295af995a553518e4e0337b4b4b817e70da5d9731a4c98655af90791b6287870b5ff8d73ad8873
|
||||
HEAD_REF master
|
||||
)
|
||||
|
||||
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" JSONCPP_STATIC)
|
||||
string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" STATIC_CRT)
|
||||
|
||||
vcpkg_cmake_configure(
|
||||
SOURCE_PATH "${SOURCE_PATH}"
|
||||
OPTIONS
|
||||
-DJSONCPP_WITH_CMAKE_PACKAGE=ON
|
||||
-DBUILD_STATIC_LIBS=${JSONCPP_STATIC}
|
||||
-DJSONCPP_STATIC_WINDOWS_RUNTIME=${STATIC_CRT}
|
||||
-DJSONCPP_WITH_PKGCONFIG_SUPPORT=ON
|
||||
-DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF
|
||||
-DJSONCPP_WITH_TESTS=OFF
|
||||
-DJSONCPP_WITH_EXAMPLE=OFF
|
||||
-DBUILD_OBJECT_LIBS=OFF
|
||||
)
|
||||
|
||||
vcpkg_cmake_install()
|
||||
|
||||
vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/jsoncpp)
|
||||
|
||||
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
|
||||
|
||||
vcpkg_copy_pdbs()
|
||||
vcpkg_fixup_pkgconfig()
|
||||
|
||||
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
|
18
cmake/ports/jsoncpp/vcpkg.json
Normal file
18
cmake/ports/jsoncpp/vcpkg.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "jsoncpp",
|
||||
"version": "1.9.5",
|
||||
"port-version": 4,
|
||||
"description": "JsonCpp is a C++ library that allows manipulating JSON values, including serialization and deserialization to and from strings. It can also preserve existing comment in unserialization/serialization steps, making it a convenient format to store user input files.",
|
||||
"homepage": "https://github.com/open-source-parsers/jsoncpp",
|
||||
"license": "MIT",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "vcpkg-cmake",
|
||||
"host": true
|
||||
},
|
||||
{
|
||||
"name": "vcpkg-cmake-config",
|
||||
"host": true
|
||||
}
|
||||
]
|
||||
}
|
8
cmake/ports/node/portfile.cmake
Executable file → Normal file
8
cmake/ports/node/portfile.cmake
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2023 Overte e.V.
|
||||
# Copyright 2023-2024 Overte e.V.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set(NODE_VERSION 18.14.2)
|
||||
|
@ -28,9 +28,9 @@ else ()
|
|||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO nodejs/node
|
||||
REF v18.16.1
|
||||
SHA512 cd2d7871a1a2aca8d800e0a501bd2836cbce076de750dcfc0b2bbe602c8a23705154bfb12faa3ff78e25ec753f419220742228569c281fa458987fb24f6d4d09
|
||||
HEAD_REF v18.16.1
|
||||
REF v18.20.2
|
||||
SHA512 10d3637c26274677d137f76bbb648d0e7851c994634a16c89858c3a13094a0692ea2cb9a787c6463c3001abd71dab0d83123127bc305171d097c48d21d691678
|
||||
HEAD_REF v18.20.2
|
||||
)
|
||||
# node cannot configure out of source, which VCPKG expects. So we copy the source to the configure directory.
|
||||
file(COPY ${SOURCE_PATH}/ DESTINATION "${CURRENT_BUILDTREES_DIR}")
|
||||
|
|
23
cmake/ports/openxr-loader/fix-jinja2.patch
Normal file
23
cmake/ports/openxr-loader/fix-jinja2.patch
Normal file
|
@ -0,0 +1,23 @@
|
|||
From d80c7dc3f4810fc49e4444590d39ef71e8a9b01c Mon Sep 17 00:00:00 2001
|
||||
From: Adam Johnson <AdamJohnso@gmail.com>
|
||||
Date: Sat, 19 Feb 2022 19:42:31 -0500
|
||||
Subject: [PATCH] Fix bad import in jinja2
|
||||
|
||||
---
|
||||
external/python/jinja2/utils.py | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/external/python/jinja2/utils.py b/external/python/jinja2/utils.py
|
||||
index db9c5d06..f198e3ef 100644
|
||||
--- a/external/python/jinja2/utils.py
|
||||
+++ b/external/python/jinja2/utils.py
|
||||
@@ -639,4 +639,8 @@ def __repr__(self):
|
||||
|
||||
|
||||
# Imported here because that's where it was in the past
|
||||
-from markupsafe import Markup, escape, soft_unicode
|
||||
+from markupsafe import Markup, escape
|
||||
+try:
|
||||
+ from markupsafe import soft_unicode
|
||||
+except ImportError:
|
||||
+ from markupsafe import soft_str as soft_unicode
|
30
cmake/ports/openxr-loader/fix-openxr-sdk-jsoncpp.patch
Normal file
30
cmake/ports/openxr-loader/fix-openxr-sdk-jsoncpp.patch
Normal file
|
@ -0,0 +1,30 @@
|
|||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index c75b145..386494c 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -89,7 +89,7 @@ if(NOT VULKAN_INCOMPATIBLE)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
-find_package(JsonCpp)
|
||||
+find_package(jsoncpp CONFIG REQUIRED)
|
||||
|
||||
### All options defined here
|
||||
option(BUILD_LOADER "Build loader" ON)
|
||||
diff --git a/src/loader/CMakeLists.txt b/src/loader/CMakeLists.txt
|
||||
index 6a88cf4..0821a3d 100644
|
||||
--- a/src/loader/CMakeLists.txt
|
||||
+++ b/src/loader/CMakeLists.txt
|
||||
@@ -68,7 +68,11 @@ add_library(openxr_loader ${LIBRARY_TYPE}
|
||||
${openxr_loader_RESOURCE_FILE}
|
||||
)
|
||||
if(BUILD_WITH_SYSTEM_JSONCPP)
|
||||
- target_link_libraries(openxr_loader PRIVATE JsonCpp::JsonCpp)
|
||||
+ if(BUILD_SHARED_LIBS)
|
||||
+ target_link_libraries(openxr_loader PRIVATE jsoncpp_lib)
|
||||
+ else()
|
||||
+ target_link_libraries(openxr_loader PRIVATE jsoncpp_static)
|
||||
+ endif()
|
||||
else()
|
||||
target_sources(openxr_loader
|
||||
PRIVATE
|
79
cmake/ports/openxr-loader/portfile.cmake
Normal file
79
cmake/ports/openxr-loader/portfile.cmake
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO KhronosGroup/OpenXR-SDK
|
||||
REF "release-${VERSION}"
|
||||
SHA512 6efc7596e707f95366dbcdbac9bd7d0c20735a2175b4edf56a9e8a112cf0ab8b664069fe942313164a37119032ddbf5671bc88ab5f276005dd36e4a4dabba1c7
|
||||
HEAD_REF master
|
||||
PATCHES
|
||||
fix-openxr-sdk-jsoncpp.patch
|
||||
)
|
||||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SDK_SOURCE_PATH
|
||||
REPO KhronosGroup/OpenXR-SDK-Source
|
||||
REF "release-${VERSION}"
|
||||
SHA512 04bdb0f16078209b5edd175a3396f70e1ceb8cfa382c65b8fda388e565480e3844daf68e0d987e72ed8c21d3148af0b41a2170911ec1660565887e0e5ae6d2bf
|
||||
HEAD_REF master
|
||||
PATCHES
|
||||
fix-openxr-sdk-jsoncpp.patch
|
||||
fix-jinja2.patch
|
||||
)
|
||||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH HPP_SOURCE_PATH
|
||||
REPO KhronosGroup/OpenXR-hpp
|
||||
REF 63db9919822f8af6f7bf7416ba6a015d4617202e
|
||||
SHA512 9e768f485d1631f8e74f35f028a64e2d64e33d362c53ae1c54427a10786e3befdd24089927319aa1a4b4c3e010247bd6cb3394bcee460c467c637ab6bc7bec90
|
||||
HEAD_REF master
|
||||
PATCHES
|
||||
python3_8_compatibility.patch
|
||||
)
|
||||
|
||||
# Weird behavior inside the OpenXR loader. On Windows they force shared libraries to use static crt, and
|
||||
# vice-versa. Might be better in future iterations to patch the CMakeLists.txt for OpenXR
|
||||
if (VCPKG_TARGET_IS_UWP OR VCPKG_TARGET_IS_WINDOWS)
|
||||
if(VCPKG_LIBRARY_LINKAGE STREQUAL static)
|
||||
set(DYNAMIC_LOADER OFF)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
else()
|
||||
set(DYNAMIC_LOADER ON)
|
||||
set(VCPKG_CRT_LINKAGE static)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
vcpkg_find_acquire_program(PYTHON3)
|
||||
|
||||
vcpkg_cmake_configure(
|
||||
SOURCE_PATH "${SOURCE_PATH}"
|
||||
OPTIONS
|
||||
-DBUILD_API_LAYERS=OFF
|
||||
-DBUILD_TESTS=OFF
|
||||
-DBUILD_CONFORMANCE_TESTS=OFF
|
||||
-DDYNAMIC_LOADER=${DYNAMIC_LOADER}
|
||||
-DPYTHON_EXECUTABLE="${PYTHON3}"
|
||||
-DBUILD_WITH_SYSTEM_JSONCPP=ON
|
||||
)
|
||||
|
||||
vcpkg_cmake_install()
|
||||
|
||||
# Generate the OpenXR C++ bindings
|
||||
set(ENV{OPENXR_REPO} "${SDK_SOURCE_PATH}")
|
||||
vcpkg_execute_required_process(
|
||||
COMMAND ${PYTHON3} "${HPP_SOURCE_PATH}/scripts/hpp_genxr.py" -quiet -registry "${SDK_SOURCE_PATH}/specification/registry/xr.xml" -o "${CURRENT_PACKAGES_DIR}/include/openxr"
|
||||
WORKING_DIRECTORY "${HPP_SOURCE_PATH}"
|
||||
LOGNAME "openxr-hpp"
|
||||
)
|
||||
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
vcpkg_cmake_config_fixup(PACKAGE_NAME OpenXR CONFIG_PATH cmake)
|
||||
else()
|
||||
vcpkg_cmake_config_fixup(PACKAGE_NAME OpenXR CONFIG_PATH lib/cmake/openxr)
|
||||
endif()
|
||||
|
||||
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
|
||||
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share")
|
||||
|
||||
vcpkg_fixup_pkgconfig()
|
||||
vcpkg_copy_pdbs()
|
||||
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
|
13
cmake/ports/openxr-loader/python3_8_compatibility.patch
Normal file
13
cmake/ports/openxr-loader/python3_8_compatibility.patch
Normal file
|
@ -0,0 +1,13 @@
|
|||
diff --git a/scripts/hpp_genxr.py b/scripts/hpp_genxr.py
|
||||
index ce419b0..23e1d3d 100644
|
||||
--- a/scripts/hpp_genxr.py
|
||||
+++ b/scripts/hpp_genxr.py
|
||||
@@ -36,7 +36,7 @@ from xrconventions import OpenXRConventions
|
||||
from data import EXCLUDED_EXTENSIONS
|
||||
|
||||
|
||||
-def makeREstring(strings: Iterable[str], default: typing.Optional[str] = None) -> str:
|
||||
+def makeREstring(strings, default: typing.Optional[str] = None) -> str:
|
||||
"""Turn a list of strings into a regexp string matching exactly those strings."""
|
||||
if strings or default is None:
|
||||
return f"^({'|'.join(re.escape(s) for s in strings)})$"
|
27
cmake/ports/openxr-loader/vcpkg.json
Normal file
27
cmake/ports/openxr-loader/vcpkg.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "openxr-loader",
|
||||
"version": "1.0.31",
|
||||
"description": "A royalty-free, open standard that provides high-performance access to Augmented Reality (AR) and Virtual Reality (VR)—collectively known as XR—platforms and devices",
|
||||
"homepage": "https://github.com/KhronosGroup/OpenXR-SDK",
|
||||
"license": "Apache-2.0",
|
||||
"supports": "!uwp & !osx",
|
||||
"dependencies": [
|
||||
"jsoncpp",
|
||||
{
|
||||
"name": "vcpkg-cmake",
|
||||
"host": true
|
||||
},
|
||||
{
|
||||
"name": "vcpkg-cmake-config",
|
||||
"host": true
|
||||
}
|
||||
],
|
||||
"features": {
|
||||
"vulkan": {
|
||||
"description": "Vulkan functionality for OpenXR",
|
||||
"dependencies": [
|
||||
"vulkan"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": 2.6,
|
||||
"version": 2.7,
|
||||
"settings": [
|
||||
{
|
||||
"name": "metaverse",
|
||||
|
@ -402,7 +402,7 @@
|
|||
},
|
||||
{
|
||||
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Avatar Entities</strong><br />Sets whether a user can use avatar entities on the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the “locked” property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain’s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li><li><strong>Replace Content</strong><br>Sets whether a user can replace entire content sets by wiping existing domain content.</li><li><strong>Get and Set Private User Data</strong><br>Sets whether a user can get and set the privateUserData entity property.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let’s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
|
||||
"span": 12
|
||||
"span": 11
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
|
@ -479,6 +479,13 @@
|
|||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"non-deletable-row-key": "permissions_id",
|
||||
|
@ -505,6 +512,7 @@
|
|||
"id_can_rez_tmp": true,
|
||||
"id_can_write_to_asset_server": true,
|
||||
"id_can_get_and_set_private_user_data": true,
|
||||
"id_can_view_asset_urls": true,
|
||||
"permissions_id": "localhost"
|
||||
},
|
||||
{
|
||||
|
@ -633,6 +641,13 @@
|
|||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -752,6 +767,13 @@
|
|||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -844,6 +866,13 @@
|
|||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -936,6 +965,13 @@
|
|||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1022,13 +1058,20 @@
|
|||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_get_and_set_private_user_data",
|
||||
"label": "Get and Set Private User Data",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
{
|
||||
"name": "id_can_get_and_set_private_user_data",
|
||||
"label": "Get and Set Private User Data",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -1120,6 +1163,13 @@
|
|||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "id_can_view_asset_urls",
|
||||
"label": "View Asset URLs",
|
||||
"type": "checkbox",
|
||||
"editable": true,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -353,6 +353,7 @@ void DomainGatekeeper::updateNodePermissions() {
|
|||
userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent;
|
||||
userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData;
|
||||
userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities;
|
||||
userPerms.permissions |= NodePermissions::Permission::canViewAssetURLs;
|
||||
} else {
|
||||
// at this point we don't have a sending socket for packets from this node - assume it is the active socket
|
||||
// or the public socket if we haven't activated a socket for the node yet
|
||||
|
@ -446,6 +447,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
|||
userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent;
|
||||
userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData;
|
||||
userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities;
|
||||
userPerms.permissions |= NodePermissions::Permission::canViewAssetURLs;
|
||||
newNode->setPermissions(userPerms);
|
||||
return newNode;
|
||||
}
|
||||
|
|
|
@ -547,6 +547,29 @@ void DomainServerSettingsManager::setupConfigMap(const QString& userConfigFilena
|
|||
|
||||
// No migration needed to version 2.6.
|
||||
|
||||
if (oldVersion < 2.7) {
|
||||
// Default values for new canViewAssetURLs permission.
|
||||
unpackPermissions();
|
||||
std::list<std::unordered_map<NodePermissionsKey, NodePermissionsPointer>> permissionsSets{
|
||||
_standardAgentPermissions.get(),
|
||||
_agentPermissions.get(),
|
||||
_ipPermissions.get(),
|
||||
_macPermissions.get(),
|
||||
_machineFingerprintPermissions.get(),
|
||||
_groupPermissions.get(),
|
||||
_groupForbiddens.get()
|
||||
};
|
||||
foreach (auto permissionsSet, permissionsSets) {
|
||||
for (auto entry : permissionsSet) {
|
||||
const auto& userKey = entry.first;
|
||||
if (permissionsSet[userKey]->can(NodePermissions::Permission::canConnectToDomain)) {
|
||||
permissionsSet[userKey]->set(NodePermissions::Permission::canViewAssetURLs);
|
||||
}
|
||||
}
|
||||
}
|
||||
packPermissions();
|
||||
}
|
||||
|
||||
// write the current description version to our settings
|
||||
*versionVariant = _descriptionVersion;
|
||||
|
||||
|
|
35
interface/resources/controllers/openxr_index.json
Normal file
35
interface/resources/controllers/openxr_index.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "OpenXR Index to Actions",
|
||||
"channels": [
|
||||
{ "from": "Index.LeftHand", "to": "Standard.LeftHand" },
|
||||
{ "from": "Index.RightHand", "to": "Standard.RightHand" },
|
||||
{ "from": "Index.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] },
|
||||
|
||||
{ "from": "Index.LeftPrimaryThumb", "to": "Actions.Down" },
|
||||
{ "from": "Index.LeftPrimaryThumbTouch", "to": "Standard.LeftPrimaryThumbTouch" },
|
||||
{ "from": "Index.LeftSecondaryThumb", "to": "Actions.ContextMenu" },
|
||||
{ "from": "Index.LeftSecondaryThumbTouch", "to": "Standard.LeftSecondaryThumbTouch" },
|
||||
|
||||
{ "from": "Index.RightPrimaryThumb", "to": "Actions.Up" },
|
||||
{ "from": "Index.RightPrimaryThumbTouch", "to": "Standard.RightPrimaryThumbTouch" },
|
||||
{ "from": "Index.RightSecondaryThumb", "to": "Actions.Sprint" },
|
||||
{ "from": "Index.RightSecondaryThumbTouch", "to": "Standard.RightSecondaryThumbTouch" },
|
||||
|
||||
{ "from": "Index.LY", "to": "Actions.TranslateZ", "filters": ["invert"] },
|
||||
{ "from": "Index.LX", "to": "Actions.TranslateX" },
|
||||
{ "from": "Index.RY", "to": "Standard.RY" },
|
||||
{ "from": "Index.RX", "to": "Standard.RX" },
|
||||
{ "from": "Index.LS", "to": "Standard.LS" },
|
||||
{ "from": "Index.RS", "to": "Actions.CycleCamera" },
|
||||
{ "from": "Index.LSTouch", "to": "Standard.LSTouch" },
|
||||
{ "from": "Index.RSTouch", "to": "Standard.RSTouch" },
|
||||
|
||||
{ "from": "Index.RT", "to": "Standard.RT" },
|
||||
{ "from": "Index.LT", "to": "Standard.LT" },
|
||||
{ "from": "Index.RTClick", "to": "Standard.RTClick" },
|
||||
{ "from": "Index.LTClick", "to": "Standard.LTClick" },
|
||||
|
||||
{ "from": "Index.LeftPrimaryIndexTouch", "to": "Standard.LeftPrimaryIndexTouch" },
|
||||
{ "from": "Index.RightPrimaryIndexTouch", "to": "Standard.RightPrimaryIndexTouch" }
|
||||
]
|
||||
}
|
|
@ -347,6 +347,10 @@ Flickable {
|
|||
text: "Real-Time"
|
||||
refreshRatePreset: 2 // RefreshRateProfile::REALTIME
|
||||
}
|
||||
ListElement {
|
||||
text: "Custom"
|
||||
refreshRatePreset: 3 // RefreshRateProfile::CUSTOM
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.ComboBox {
|
||||
|
@ -362,13 +366,7 @@ Flickable {
|
|||
currentIndex: -1
|
||||
|
||||
function refreshRefreshRateDropdownDisplay() {
|
||||
if (Performance.getRefreshRateProfile() === 0) {
|
||||
refreshRateDropdown.currentIndex = 0;
|
||||
} else if (Performance.getRefreshRateProfile() === 1) {
|
||||
refreshRateDropdown.currentIndex = 1;
|
||||
} else {
|
||||
refreshRateDropdown.currentIndex = 2;
|
||||
}
|
||||
refreshRateDropdown.currentIndex = Performance.getRefreshRateProfile();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -382,6 +380,180 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
Layout.topMargin: 32
|
||||
visible: refreshRateDropdown.currentIndex == 3
|
||||
|
||||
RowLayout {
|
||||
Layout.margins: 8
|
||||
|
||||
HifiControlsUit.SpinBox {
|
||||
id: refreshRateCustomFocusActive
|
||||
decimals: 0
|
||||
width: 160
|
||||
height: 32
|
||||
suffix: " FPS"
|
||||
label: "Focus Active"
|
||||
realFrom: 1
|
||||
realTo: 1000
|
||||
realStepSize: 15
|
||||
realValue: 60
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
property var loaded: false
|
||||
|
||||
Component.onCompleted: {
|
||||
realValue = Performance.getCustomRefreshRate(0)
|
||||
loaded = true
|
||||
}
|
||||
|
||||
onRealValueChanged: {
|
||||
if (loaded) {
|
||||
Performance.setCustomRefreshRate(0, realValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.SpinBox {
|
||||
id: refreshRateCustomFocusInactive
|
||||
decimals: 0
|
||||
width: 160
|
||||
height: 32
|
||||
suffix: " FPS"
|
||||
label: "Focus Inactive"
|
||||
realFrom: 1
|
||||
realTo: 1000
|
||||
realStepSize: 15
|
||||
realValue: 60
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
property var loaded: false
|
||||
|
||||
Component.onCompleted: {
|
||||
realValue = Performance.getCustomRefreshRate(1)
|
||||
loaded = true
|
||||
}
|
||||
|
||||
onRealValueChanged: {
|
||||
if (loaded) {
|
||||
Performance.setCustomRefreshRate(1, realValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.margins: 8
|
||||
|
||||
HifiControlsUit.SpinBox {
|
||||
id: refreshRateCustomUnfocus
|
||||
decimals: 0
|
||||
width: 160
|
||||
height: 32
|
||||
suffix: " FPS"
|
||||
label: "Unfocus"
|
||||
realFrom: 1
|
||||
realTo: 1000
|
||||
realStepSize: 15
|
||||
realValue: 60
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
property var loaded: false
|
||||
|
||||
Component.onCompleted: {
|
||||
realValue = Performance.getCustomRefreshRate(2)
|
||||
loaded = true
|
||||
}
|
||||
|
||||
onRealValueChanged: {
|
||||
if (loaded) {
|
||||
Performance.setCustomRefreshRate(2, realValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.SpinBox {
|
||||
id: refreshRateCustomMinimized
|
||||
decimals: 0
|
||||
width: 160
|
||||
height: 32
|
||||
suffix: " FPS"
|
||||
label: "Minimized"
|
||||
realFrom: 1
|
||||
realTo: 1000
|
||||
realStepSize: 1
|
||||
realValue: 60
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
property var loaded: false
|
||||
|
||||
Component.onCompleted: {
|
||||
realValue = Performance.getCustomRefreshRate(3)
|
||||
loaded = true
|
||||
}
|
||||
|
||||
onRealValueChanged: {
|
||||
if (loaded) {
|
||||
Performance.setCustomRefreshRate(3, realValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.margins: 8
|
||||
|
||||
HifiControlsUit.SpinBox {
|
||||
id: refreshRateCustomStartup
|
||||
decimals: 0
|
||||
width: 160
|
||||
height: 32
|
||||
suffix: " FPS"
|
||||
label: "Startup"
|
||||
realFrom: 1
|
||||
realTo: 1000
|
||||
realStepSize: 15
|
||||
realValue: 60
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
property var loaded: false
|
||||
|
||||
Component.onCompleted: {
|
||||
realValue = Performance.getCustomRefreshRate(4)
|
||||
loaded = true
|
||||
}
|
||||
|
||||
onRealValueChanged: {
|
||||
if (loaded) {
|
||||
Performance.setCustomRefreshRate(4, realValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.SpinBox {
|
||||
id: refreshRateCustomShutdown
|
||||
decimals: 0
|
||||
width: 160
|
||||
height: 32
|
||||
suffix: " FPS"
|
||||
label: "Shutdown"
|
||||
realFrom: 1
|
||||
realTo: 1000
|
||||
realStepSize: 15
|
||||
realValue: 60
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
property var loaded: false
|
||||
|
||||
Component.onCompleted: {
|
||||
realValue = Performance.getCustomRefreshRate(5)
|
||||
loaded = true
|
||||
}
|
||||
|
||||
onRealValueChanged: {
|
||||
if (loaded) {
|
||||
Performance.setCustomRefreshRate(5, realValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 35
|
||||
|
|
152
interface/resources/qml/hifi/dialogs/security/ScriptSecurity.qml
Normal file
152
interface/resources/qml/hifi/dialogs/security/ScriptSecurity.qml
Normal file
|
@ -0,0 +1,152 @@
|
|||
//
|
||||
// ScriptPermissions.cpp
|
||||
// libraries/script-engine/src/ScriptPermissions.cpp
|
||||
//
|
||||
// Created by dr Karol Suprynowicz on 2024/03/24.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Based on EntityScriptQMLWhitelist.qml
|
||||
// Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com
|
||||
// Copyright 2019 Kalila L.
|
||||
//
|
||||
// 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 script engines
|
||||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.12
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import controlsUit 1.0 as HiFiControls
|
||||
import PerformanceEnums 1.0
|
||||
import "../../../windows"
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: parentBody;
|
||||
|
||||
function getWhitelistAsText() {
|
||||
var whitelist = Settings.getValue("private/scriptPermissionGetAvatarURLSafeURLs");
|
||||
var arrayWhitelist = whitelist.replace(",", "\n");
|
||||
return arrayWhitelist;
|
||||
}
|
||||
|
||||
function setWhitelistAsText(whitelistText) {
|
||||
Settings.setValue("private/scriptPermissionGetAvatarURLSafeURLs", whitelistText.text);
|
||||
notificationText.text = "Whitelist saved.";
|
||||
}
|
||||
|
||||
function setAvatarProtection(enabled) {
|
||||
Settings.setValue("private/scriptPermissionGetAvatarURLEnable", enabled);
|
||||
console.info("Setting Protect Avatar URLs to:", enabled);
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
width: parent.width;
|
||||
height: 120;
|
||||
color: "#80010203";
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: titleText;
|
||||
text: "Protect Avatar URLs"
|
||||
// Text size
|
||||
size: 24;
|
||||
// Style
|
||||
color: "white";
|
||||
elide: Text.ElideRight;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 20;
|
||||
height: 60;
|
||||
|
||||
CheckBox {
|
||||
id: whitelistEnabled;
|
||||
|
||||
checked: Settings.getValue("private/scriptPermissionGetAvatarURLEnable", true);
|
||||
|
||||
anchors.right: parent.right;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 10;
|
||||
onToggled: {
|
||||
setAvatarProtection(whitelistEnabled.checked)
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Enabled"
|
||||
color: "white"
|
||||
font.pixelSize: 18;
|
||||
anchors.right: parent.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: textAreaRectangle;
|
||||
color: "black";
|
||||
width: parent.width;
|
||||
height: 250;
|
||||
anchors.top: titleText.bottom;
|
||||
|
||||
ScrollView {
|
||||
id: textAreaScrollView
|
||||
anchors.fill: parent;
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
contentWidth: parent.width
|
||||
contentHeight: parent.height
|
||||
clip: false;
|
||||
|
||||
TextArea {
|
||||
id: whitelistTextArea
|
||||
text: getWhitelistAsText();
|
||||
onTextChanged: notificationText.text = "";
|
||||
width: parent.width;
|
||||
height: parent.height;
|
||||
font.family: "Ubuntu";
|
||||
font.pointSize: 12;
|
||||
color: "white";
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: saveChanges
|
||||
anchors.topMargin: 5;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.rightMargin: 20;
|
||||
x: textAreaRectangle.x + textAreaRectangle.width - width - 15;
|
||||
y: textAreaRectangle.y + textAreaRectangle.height - height;
|
||||
contentItem: Text {
|
||||
text: saveChanges.text
|
||||
font.family: "Ubuntu";
|
||||
font.pointSize: 12;
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
color: "black"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
text: "Save Changes"
|
||||
onClicked: setWhitelistAsText(whitelistTextArea)
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: notificationText;
|
||||
text: ""
|
||||
// Text size
|
||||
size: 16;
|
||||
// Style
|
||||
color: "white";
|
||||
elide: Text.ElideLeft;
|
||||
// Anchors
|
||||
anchors.right: parent.left;
|
||||
anchors.rightMargin: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by Zach Fox on 2019-08-08
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -78,7 +79,7 @@ Item {
|
|||
temporaryText: "Viewing!"
|
||||
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://www.highfidelity.com/knowledge");
|
||||
Qt.openUrlExternally("https://overte.org/");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by Zach Fox on 2019-08-20
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -76,7 +77,7 @@ Item {
|
|||
temporaryText: "Opening browser..."
|
||||
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://www.highfidelity.com/knowledge/kb-tickets/new");
|
||||
Qt.openUrlExternally("https://overte.org/contact.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by Zach Fox on 2019-06-11
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -93,9 +94,9 @@ Flickable {
|
|||
width: parent.width
|
||||
height: 18
|
||||
labelTextOn: "Keep Old Menus (File, Edit, etc)"
|
||||
checked: Settings.getValue("simplifiedUI/keepMenus", false);
|
||||
checked: Settings.getValue("simplifiedUI/keepMenus", true);
|
||||
onClicked: {
|
||||
Settings.setValue("simplifiedUI/keepMenus", !Settings.getValue("simplifiedUI/keepMenus", false));
|
||||
Settings.setValue("simplifiedUI/keepMenus", !Settings.getValue("simplifiedUI/keepMenus", true));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by Zach Fox on 2019-05-06
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -175,7 +176,7 @@ Flickable {
|
|||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: performanceLow
|
||||
id: performanceLowPower
|
||||
text: "Low Power Quality" + (PlatformInfo.getTierProfiled() === PerformanceEnums.LOW_POWER ? " (Recommended)" : "")
|
||||
checked: Performance.getPerformancePreset() === PerformanceEnums.LOW_POWER
|
||||
onClicked: {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by Zach Fox on 2019-05-08
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
// Copyright 2024 Overte e.V.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -96,12 +97,11 @@ Original.Button {
|
|||
}
|
||||
}
|
||||
|
||||
contentItem: HifiStylesUit.FiraSansMedium {
|
||||
contentItem: Text {
|
||||
id: buttonText
|
||||
//topPadding: -2 // Necessary for proper alignment using Graphik Medium
|
||||
wrapMode: Text.Wrap
|
||||
color: enabled ? simplifiedUI.colors.controls.button.text.enabled : simplifiedUI.colors.controls.button.text.disabled
|
||||
size: simplifiedUI.sizes.controls.button.textSize
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: root.text
|
||||
|
|
|
@ -27,7 +27,7 @@ Item {
|
|||
width: parent.width
|
||||
|
||||
property string title: "Controls"
|
||||
property var openVRDevices: ["HTC Vive", "Valve Index", "Valve HMD", "Valve", "WindowsMR"]
|
||||
property var openVRDevices: ["HTC Vive", "Valve Index", "Valve HMD", "Valve", "WindowsMR", "Oculus"]
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
|
|
|
@ -3305,7 +3305,7 @@ void Application::initializeUi() {
|
|||
|
||||
// END PULL SAFEURLS FROM INTERFACE.JSON Settings
|
||||
|
||||
if (AUTHORIZED_EXTERNAL_QML_SOURCE.isParentOf(url)) {
|
||||
if (QUrl(NetworkingConstants::OVERTE_COMMUNITY_APPLICATIONS).isParentOf(url)) {
|
||||
return true;
|
||||
} else {
|
||||
for (const auto& str : safeURLS) {
|
||||
|
@ -6942,51 +6942,40 @@ void Application::updateRenderArgs(float deltaTime) {
|
|||
appRenderArgs._eyeToWorld = _myCamera.getTransform();
|
||||
appRenderArgs._isStereo = false;
|
||||
|
||||
{
|
||||
if (getActiveDisplayPlugin()->isStereo()) {
|
||||
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
||||
float ipdScale = hmdInterface->getIPDScale();
|
||||
|
||||
// scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly.
|
||||
ipdScale *= sensorToWorldScale;
|
||||
float ipdScale = hmdInterface->getIPDScale() * sensorToWorldScale;
|
||||
|
||||
auto baseProjection = appRenderArgs._renderArgs.getViewFrustum().getProjection();
|
||||
|
||||
if (getActiveDisplayPlugin()->isStereo()) {
|
||||
// Stereo modes will typically have a larger projection matrix overall,
|
||||
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
||||
// plugins will imply the combined projection for both eyes.
|
||||
//
|
||||
// This is properly implemented for the Oculus plugins, but for OpenVR
|
||||
// and Stereo displays I'm not sure how to get / calculate it, so we're
|
||||
// just relying on the left FOV in each case and hoping that the
|
||||
// overall culling margin of error doesn't cause popping in the
|
||||
// right eye. There are FIXMEs in the relevant plugins
|
||||
_myCamera.setProjection(getActiveDisplayPlugin()->getCullingProjection(baseProjection));
|
||||
appRenderArgs._isStereo = true;
|
||||
// Stereo modes will typically have a larger projection matrix overall,
|
||||
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
||||
// plugins will imply the combined projection for both eyes.
|
||||
//
|
||||
// This is properly implemented for the Oculus plugins, but for OpenVR
|
||||
// and Stereo displays I'm not sure how to get / calculate it, so we're
|
||||
// just relying on the left FOV in each case and hoping that the
|
||||
// overall culling margin of error doesn't cause popping in the
|
||||
// right eye. There are FIXMEs in the relevant plugins
|
||||
_myCamera.setProjection(getActiveDisplayPlugin()->getCullingProjection(baseProjection));
|
||||
appRenderArgs._isStereo = true;
|
||||
|
||||
auto& eyeOffsets = appRenderArgs._eyeOffsets;
|
||||
auto& eyeProjections = appRenderArgs._eyeProjections;
|
||||
auto& eyeOffsets = appRenderArgs._eyeOffsets;
|
||||
auto& eyeProjections = appRenderArgs._eyeProjections;
|
||||
|
||||
// FIXME we probably don't need to set the projection matrix every frame,
|
||||
// only when the display plugin changes (or in non-HMD modes when the user
|
||||
// changes the FOV manually, which right now I don't think they can.
|
||||
for_each_eye([&](Eye eye) {
|
||||
// For providing the stereo eye views, the HMD head pose has already been
|
||||
// applied to the avatar, so we need to get the difference between the head
|
||||
// pose applied to the avatar and the per eye pose, and use THAT as
|
||||
// the per-eye stereo matrix adjustment.
|
||||
mat4 eyeToHead = getActiveDisplayPlugin()->getEyeToHeadTransform(eye);
|
||||
// Grab the translation
|
||||
vec3 eyeOffset = glm::vec3(eyeToHead[3]);
|
||||
// Apply IPD scaling
|
||||
mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale);
|
||||
eyeOffsets[eye] = eyeOffsetTransform;
|
||||
eyeProjections[eye] = getActiveDisplayPlugin()->getEyeProjection(eye, baseProjection);
|
||||
});
|
||||
// FIXME we probably don't need to set the projection matrix every frame,
|
||||
// only when the display plugin changes (or in non-HMD modes when the user
|
||||
// changes the FOV manually, which right now I don't think they can.
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeOffsets[eye] = getActiveDisplayPlugin()->getEyeToHeadTransform(eye);
|
||||
// Apply IPD scaling
|
||||
eyeOffsets[eye][3][0] *= ipdScale;
|
||||
eyeProjections[eye] = getActiveDisplayPlugin()->getEyeProjection(eye, baseProjection);
|
||||
});
|
||||
|
||||
// Configure the type of display / stereo
|
||||
appRenderArgs._renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
|
||||
}
|
||||
// Configure the type of display / stereo
|
||||
appRenderArgs._renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
|
||||
}
|
||||
|
||||
appRenderArgs._renderArgs._stencilMaskMode = getActiveDisplayPlugin()->getStencilMaskMode();
|
||||
|
|
|
@ -41,6 +41,15 @@
|
|||
#include <QtQuick/QQuickWindow>
|
||||
#include <memory>
|
||||
#include "WarningsSuppression.h"
|
||||
#include "ScriptPermissions.h"
|
||||
|
||||
QVariantMap AvatarBookmarks::getBookmarks() {
|
||||
if (ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL)) {
|
||||
return _bookmarks;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void addAvatarEntities(const QVariantList& avatarEntities) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
@ -123,6 +132,12 @@ AvatarBookmarks::AvatarBookmarks() {
|
|||
}
|
||||
|
||||
void AvatarBookmarks::addBookmark(const QString& bookmarkName) {
|
||||
if (ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL)) {
|
||||
addBookmarkInternal(bookmarkName);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarBookmarks::addBookmarkInternal(const QString& bookmarkName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "addBookmark", Q_ARG(QString, bookmarkName));
|
||||
return;
|
||||
|
@ -134,6 +149,12 @@ void AvatarBookmarks::addBookmark(const QString& bookmarkName) {
|
|||
}
|
||||
|
||||
void AvatarBookmarks::saveBookmark(const QString& bookmarkName) {
|
||||
if (ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL)) {
|
||||
saveBookmarkInternal(bookmarkName);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarBookmarks::saveBookmarkInternal(const QString& bookmarkName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "saveBookmark", Q_ARG(QString, bookmarkName));
|
||||
return;
|
||||
|
@ -145,6 +166,12 @@ void AvatarBookmarks::saveBookmark(const QString& bookmarkName) {
|
|||
}
|
||||
|
||||
void AvatarBookmarks::removeBookmark(const QString& bookmarkName) {
|
||||
if (ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL)) {
|
||||
removeBookmarkInternal(bookmarkName);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarBookmarks::removeBookmarkInternal(const QString& bookmarkName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "removeBookmark", Q_ARG(QString, bookmarkName));
|
||||
return;
|
||||
|
@ -200,6 +227,12 @@ void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
|||
*/
|
||||
|
||||
void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
||||
if (ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL)) {
|
||||
loadBookmarkInternal(bookmarkName);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarBookmarks::loadBookmarkInternal(const QString& bookmarkName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
BLOCKING_INVOKE_METHOD(this, "loadBookmark", Q_ARG(QString, bookmarkName));
|
||||
return;
|
||||
|
@ -268,6 +301,15 @@ void AvatarBookmarks::readFromFile() {
|
|||
}
|
||||
|
||||
QVariantMap AvatarBookmarks::getBookmark(const QString &bookmarkName)
|
||||
{
|
||||
if (ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL)) {
|
||||
return getBookmarkInternal(bookmarkName);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap AvatarBookmarks::getBookmarkInternal(const QString &bookmarkName)
|
||||
{
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariantMap result;
|
||||
|
|
|
@ -100,7 +100,7 @@ public slots:
|
|||
* print("- " + key + " " + bookmarks[key].avatarUrl);
|
||||
* };
|
||||
*/
|
||||
QVariantMap getBookmarks() { return _bookmarks; }
|
||||
QVariantMap getBookmarks();
|
||||
|
||||
signals:
|
||||
/*@jsdoc
|
||||
|
@ -147,6 +147,11 @@ protected slots:
|
|||
void deleteBookmark() override;
|
||||
|
||||
private:
|
||||
QVariantMap getBookmarkInternal(const QString &bookmarkName);
|
||||
void addBookmarkInternal(const QString& bookmarkName);
|
||||
void saveBookmarkInternal(const QString& bookmarkName);
|
||||
void loadBookmarkInternal(const QString& bookmarkName);
|
||||
void removeBookmarkInternal(const QString& bookmarkName);
|
||||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
||||
|
|
|
@ -258,10 +258,11 @@ void CrashRecoveryHandler::handleCrash(CrashRecoveryHandler::Action action) {
|
|||
// Display name and avatar
|
||||
settings.beginGroup(AVATAR_GROUP);
|
||||
displayName = settings.value(DISPLAY_NAME_KEY).toString();
|
||||
fullAvatarURL = settings.value(FULL_AVATAR_URL_KEY).toUrl();
|
||||
fullAvatarModelName = settings.value(FULL_AVATAR_MODEL_NAME_KEY).toString();
|
||||
settings.endGroup();
|
||||
|
||||
fullAvatarURL = settings.value(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/" + AVATAR_GROUP + "/" + FULL_AVATAR_URL_KEY).toUrl();
|
||||
|
||||
// Tutorial complete
|
||||
tutorialComplete = settings.value(TUTORIAL_COMPLETE_FLAG_KEY).toBool();
|
||||
}
|
||||
|
@ -280,12 +281,12 @@ void CrashRecoveryHandler::handleCrash(CrashRecoveryHandler::Action action) {
|
|||
// Display name and avatar
|
||||
settings.beginGroup(AVATAR_GROUP);
|
||||
settings.setValue(DISPLAY_NAME_KEY, displayName);
|
||||
settings.setValue(FULL_AVATAR_URL_KEY, fullAvatarURL);
|
||||
settings.setValue(FULL_AVATAR_MODEL_NAME_KEY, fullAvatarModelName);
|
||||
settings.endGroup();
|
||||
|
||||
settings.setValue(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/" + AVATAR_GROUP + "/" + FULL_AVATAR_URL_KEY, fullAvatarURL);
|
||||
|
||||
// Tutorial complete
|
||||
settings.setValue(TUTORIAL_COMPLETE_FLAG_KEY, tutorialComplete);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,10 +49,10 @@ LODManager::LODManager() {
|
|||
const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.08f; // sec
|
||||
|
||||
// batchTIme is always contained in presentTime.
|
||||
// We favor using batchTime instead of presentTime as a representative value for rendering duration (on present thread)
|
||||
// We favor using batchTime instead of presentTime as a representative value for rendering duration (on present thread)
|
||||
// if batchTime + cushionTime < presentTime.
|
||||
// since we are shooting for fps around 60, 90Hz, the ideal frames are around 10ms
|
||||
// so we are picking a cushion time of 3ms
|
||||
// so we are picking a cushion time of 3ms
|
||||
const float LOD_BATCH_TO_PRESENT_CUSHION_TIME = 3.0f; // msec
|
||||
|
||||
void LODManager::setRenderTimes(float presentTime, float engineRunTime, float batchTime, float gpuTime) {
|
||||
|
@ -64,8 +64,8 @@ void LODManager::setRenderTimes(float presentTime, float engineRunTime, float ba
|
|||
}
|
||||
|
||||
void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||
std::lock_guard<std::mutex> { _automaticLODLock };
|
||||
|
||||
std::lock_guard<std::mutex> lock{ _automaticLODLock };
|
||||
|
||||
// The "render time" is the worse of:
|
||||
// - engineRunTime: Time spent in the render thread in the engine producing the gpu::Frame N
|
||||
// - batchTime: Time spent in the present thread processing the batches of gpu::Frame N+1
|
||||
|
@ -92,7 +92,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
|||
float smoothBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) ? realTimeDelta / (LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) : 1.0f;
|
||||
|
||||
//Evaluate the running averages for the render time
|
||||
// We must sanity check for the output average evaluated to be in a valid range to avoid issues
|
||||
// We must sanity check for the output average evaluated to be in a valid range to avoid issues
|
||||
_nowRenderTime = (1.0f - nowBlend) * _nowRenderTime + nowBlend * maxRenderTime; // msec
|
||||
_nowRenderTime = std::max(0.0f, std::min(_nowRenderTime, (float)MSECS_PER_SECOND));
|
||||
_smoothRenderTime = (1.0f - smoothBlend) * _smoothRenderTime + smoothBlend * maxRenderTime; // msec
|
||||
|
@ -112,7 +112,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
|||
// Current fps based on latest measurments
|
||||
float currentNowFPS = (float)MSECS_PER_SECOND / _nowRenderTime;
|
||||
float currentSmoothFPS = (float)MSECS_PER_SECOND / _smoothRenderTime;
|
||||
|
||||
|
||||
// Compute the Variance of the FPS signal (FPS - smouthFPS)^2
|
||||
// Also scale it by a percentage for fine tuning (default is 100%)
|
||||
float currentVarianceFPS = (currentSmoothFPS - currentNowFPS);
|
||||
|
@ -165,7 +165,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
|||
|
||||
// Compute the output of the PID and record intermediate results for tuning
|
||||
_pidOutputs.x = _pidCoefs.x * error; // Kp * error
|
||||
_pidOutputs.y = _pidCoefs.y * integral; // Ki * integral
|
||||
_pidOutputs.y = _pidCoefs.y * integral; // Ki * integral
|
||||
_pidOutputs.z = _pidCoefs.z * derivative; // Kd * derivative
|
||||
|
||||
auto output = _pidOutputs.x + _pidOutputs.y + _pidOutputs.z;
|
||||
|
@ -300,7 +300,7 @@ void LODManager::resetLODAdjust() {
|
|||
}
|
||||
|
||||
void LODManager::setAutomaticLODAdjust(bool value) {
|
||||
std::lock_guard<std::mutex> { _automaticLODLock };
|
||||
std::lock_guard<std::mutex> lock{ _automaticLODLock };
|
||||
_automaticLODAdjust = value;
|
||||
saveSettings();
|
||||
emit autoLODChanged();
|
||||
|
@ -399,7 +399,7 @@ void LODManager::loadSettings() {
|
|||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool() && firstRun.get()) {
|
||||
hmdQuality = WORLD_DETAIL_HIGH;
|
||||
}
|
||||
|
||||
|
||||
_automaticLODAdjust = automaticLODAdjust.get();
|
||||
_lodHalfAngle = lodHalfAngle.get();
|
||||
|
||||
|
@ -457,7 +457,7 @@ float LODManager::getLODTargetFPS() const {
|
|||
if (qApp->isHMDMode()) {
|
||||
lodTargetFPS = getHMDLODTargetFPS();
|
||||
}
|
||||
|
||||
|
||||
// if RefreshRate is slower than LOD target then it becomes the true LOD target
|
||||
if (lodTargetFPS > refreshRateFPS) {
|
||||
return refreshRateFPS;
|
||||
|
@ -476,7 +476,7 @@ void LODManager::setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMod
|
|||
setDesktopLODTargetFPS(desiredFPS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LODManager::setWorldDetailQuality(WorldDetailQuality quality) {
|
||||
setWorldDetailQuality(quality, qApp->isHMDMode());
|
||||
saveSettings();
|
||||
|
@ -492,7 +492,7 @@ ScriptValue worldDetailQualityToScriptValue(ScriptEngine* engine, const WorldDet
|
|||
}
|
||||
|
||||
bool worldDetailQualityFromScriptValue(const ScriptValue& object, WorldDetailQuality& worldDetailQuality) {
|
||||
worldDetailQuality =
|
||||
worldDetailQuality =
|
||||
static_cast<WorldDetailQuality>(std::min(std::max(object.toInt32(), (int)WORLD_DETAIL_LOW), (int)WORLD_DETAIL_HIGH));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -323,6 +323,19 @@ Menu::Menu() {
|
|||
}
|
||||
});
|
||||
|
||||
// Settings > Script Security
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::ScriptSecurity);
|
||||
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/ScriptSecurity.qml");
|
||||
|
||||
if (!hmd->getShouldShowTablet()) {
|
||||
hmd->toggleShouldShowTablet();
|
||||
}
|
||||
});
|
||||
|
||||
// Settings > Developer Menu
|
||||
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ namespace MenuOption {
|
|||
const QString RunTimingTests = "Run Timing Tests";
|
||||
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
|
||||
const QString EntityScriptQMLWhitelist = "Entity Script / QML Whitelist";
|
||||
const QString ScriptSecurity = "Script Security";
|
||||
const QString ShowTrackedObjects = "Show Tracked Objects";
|
||||
const QString SelfieCamera = "Selfie";
|
||||
const QString SendWrongDSConnectVersion = "Send wrong DS connect version";
|
||||
|
|
|
@ -48,12 +48,13 @@ static const int VR_TARGET_RATE = 90;
|
|||
* <tr><td><code>"Interactive"</code></td><td>Medium refresh rate, which is reduced when Interface doesn't have focus or is
|
||||
* minimized.</td></tr>
|
||||
* <tr><td><code>"Realtime"</code></td><td>High refresh rate, even when Interface doesn't have focus or is minimized.
|
||||
* <tr><td><code>"Custom"</code></td><td>Custom refresh rate for full control over the refresh rate in all states.
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} RefreshRateProfileName
|
||||
*/
|
||||
static const std::array<std::string, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILE_TO_STRING =
|
||||
{ { "Eco", "Interactive", "Realtime" } };
|
||||
{ { "Eco", "Interactive", "Realtime", "Custom" } };
|
||||
|
||||
/*@jsdoc
|
||||
* <p>Interface states that affect the refresh rate.</p>
|
||||
|
@ -94,7 +95,8 @@ static const std::array<std::string, RefreshRateManager::UXMode::UX_NUM> UX_MODE
|
|||
static const std::map<std::string, RefreshRateManager::RefreshRateProfile> REFRESH_RATE_PROFILE_FROM_STRING =
|
||||
{ { "Eco", RefreshRateManager::RefreshRateProfile::ECO },
|
||||
{ "Interactive", RefreshRateManager::RefreshRateProfile::INTERACTIVE },
|
||||
{ "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME } };
|
||||
{ "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME },
|
||||
{ "Custom", RefreshRateManager::RefreshRateProfile::CUSTOM } };
|
||||
|
||||
|
||||
// Porfile regimes are:
|
||||
|
@ -107,10 +109,12 @@ static const std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM>
|
|||
{ { 30, 20, 10, 2, 30, 30 } };
|
||||
|
||||
static const std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM> REALTIME_PROFILE =
|
||||
{ { 60, 60, 60, 2, 30, 30} };
|
||||
{ { 60, 60, 60, 2, 30, 30 } };
|
||||
|
||||
static const std::array<std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM>, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILES =
|
||||
{ { ECO_PROFILE, INTERACTIVE_PROFILE, REALTIME_PROFILE } };
|
||||
static const std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM> CUSTOM_PROFILE = REALTIME_PROFILE; // derived from settings and modified by scripts below
|
||||
|
||||
static std::array<std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM>, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILES =
|
||||
{ { ECO_PROFILE, INTERACTIVE_PROFILE, REALTIME_PROFILE, CUSTOM_PROFILE } };
|
||||
|
||||
|
||||
static const int INACTIVE_TIMER_LIMIT = 3000;
|
||||
|
@ -134,6 +138,10 @@ std::string RefreshRateManager::uxModeToString(RefreshRateManager::RefreshRateMa
|
|||
|
||||
RefreshRateManager::RefreshRateManager() {
|
||||
_refreshRateProfile = (RefreshRateManager::RefreshRateProfile) _refreshRateProfileSetting.get();
|
||||
for (size_t i = 0; i < _customRefreshRateSettings.size(); i++) {
|
||||
REFRESH_RATE_PROFILES[CUSTOM][i] = _customRefreshRateSettings[i].get();
|
||||
}
|
||||
|
||||
_inactiveTimer->setInterval(INACTIVE_TIMER_LIMIT);
|
||||
_inactiveTimer->setSingleShot(true);
|
||||
QObject::connect(_inactiveTimer.get(), &QTimer::timeout, [&] {
|
||||
|
@ -168,6 +176,25 @@ void RefreshRateManager::setRefreshRateProfile(RefreshRateManager::RefreshRatePr
|
|||
}
|
||||
}
|
||||
|
||||
int RefreshRateManager::getCustomRefreshRate(RefreshRateRegime regime) {
|
||||
if (isValidRefreshRateRegime(regime)) {
|
||||
return REFRESH_RATE_PROFILES[RefreshRateProfile::CUSTOM][regime];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RefreshRateManager::setCustomRefreshRate(RefreshRateRegime regime, int value) {
|
||||
value = std::max(value, 1);
|
||||
if (isValidRefreshRateRegime(regime)) {
|
||||
_refreshRateProfileSettingLock.withWriteLock([&] {
|
||||
REFRESH_RATE_PROFILES[RefreshRateProfile::CUSTOM][regime] = value;
|
||||
_customRefreshRateSettings[regime].set(value);
|
||||
});
|
||||
updateRefreshRateController();
|
||||
}
|
||||
}
|
||||
|
||||
RefreshRateManager::RefreshRateProfile RefreshRateManager::getRefreshRateProfile() const {
|
||||
RefreshRateManager::RefreshRateProfile profile = RefreshRateManager::RefreshRateProfile::REALTIME;
|
||||
|
||||
|
@ -191,7 +218,6 @@ void RefreshRateManager::setRefreshRateRegime(RefreshRateManager::RefreshRateReg
|
|||
_refreshRateRegime = refreshRateRegime;
|
||||
updateRefreshRateController();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RefreshRateManager::setUXMode(RefreshRateManager::UXMode uxMode) {
|
||||
|
|
|
@ -32,10 +32,11 @@ public:
|
|||
ECO = 0,
|
||||
INTERACTIVE,
|
||||
REALTIME,
|
||||
CUSTOM,
|
||||
PROFILE_NUM
|
||||
};
|
||||
Q_ENUM(RefreshRateProfile)
|
||||
static bool isValidRefreshRateProfile(RefreshRateProfile value) { return (value >= RefreshRateProfile::ECO && value <= RefreshRateProfile::REALTIME); }
|
||||
static bool isValidRefreshRateProfile(RefreshRateProfile value) { return (value >= 0 && value < RefreshRateProfile::PROFILE_NUM); }
|
||||
|
||||
/*@jsdoc
|
||||
* <p>Interface states that affect the refresh rate.</p>
|
||||
|
@ -106,6 +107,9 @@ public:
|
|||
// query the refresh rate target at the specified combination
|
||||
int queryRefreshRateTarget(RefreshRateProfile profile, RefreshRateRegime regime, UXMode uxMode) const;
|
||||
|
||||
int getCustomRefreshRate(RefreshRateRegime regime);
|
||||
void setCustomRefreshRate(RefreshRateRegime regime, int value);
|
||||
|
||||
void resetInactiveTimer();
|
||||
void toggleInactive();
|
||||
|
||||
|
@ -121,7 +125,15 @@ private:
|
|||
UXMode _uxMode { UXMode::DESKTOP };
|
||||
|
||||
mutable ReadWriteLockable _refreshRateProfileSettingLock;
|
||||
Setting::Handle<int> _refreshRateProfileSetting { "refreshRateProfile", RefreshRateProfile::INTERACTIVE };
|
||||
Setting::Handle<int> _refreshRateProfileSetting{ "refreshRateProfile", RefreshRateProfile::INTERACTIVE };
|
||||
std::array<Setting::Handle<int>, REGIME_NUM> _customRefreshRateSettings { {
|
||||
{ "customRefreshRateFocusActive", 60 },
|
||||
{ "customRefreshRateFocusInactive", 60 },
|
||||
{ "customRefreshRateUnfocus", 60 },
|
||||
{ "customRefreshRateMinimized", 2 },
|
||||
{ "customRefreshRateStartup", 30 },
|
||||
{ "customRefreshRateShutdown", 30 }
|
||||
} };
|
||||
|
||||
std::function<void(int)> _refreshRateOperator { nullptr };
|
||||
|
||||
|
|
|
@ -333,6 +333,14 @@ void AvatarDoctor::diagnoseTextures() {
|
|||
addTextureToList(material.occlusionTexture);
|
||||
addTextureToList(material.scatteringTexture);
|
||||
addTextureToList(material.lightmapTexture);
|
||||
|
||||
if (material.isMToonMaterial) {
|
||||
addTextureToList(material.shadeTexture);
|
||||
addTextureToList(material.shadingShiftTexture);
|
||||
addTextureToList(material.matcapTexture);
|
||||
addTextureToList(material.rimTexture);
|
||||
addTextureToList(material.uvAnimationTexture);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& materialMapping : model->getMaterialMapping()) {
|
||||
|
|
|
@ -136,6 +136,14 @@ AvatarProject* AvatarProject::createAvatarProject(const QString& projectsFolder,
|
|||
addTextureToList(material.occlusionTexture);
|
||||
addTextureToList(material.scatteringTexture);
|
||||
addTextureToList(material.lightmapTexture);
|
||||
|
||||
if (material.isMToonMaterial) {
|
||||
addTextureToList(material.shadeTexture);
|
||||
addTextureToList(material.shadingShiftTexture);
|
||||
addTextureToList(material.matcapTexture);
|
||||
addTextureToList(material.rimTexture);
|
||||
addTextureToList(material.uvAnimationTexture);
|
||||
}
|
||||
}
|
||||
|
||||
QDir textureDir(textureFolder.isEmpty() ? fbxInfo.absoluteDir() : textureFolder);
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "MovingEntitiesOperator.h"
|
||||
#include "SceneScriptingInterface.h"
|
||||
#include "WarningsSuppression.h"
|
||||
#include "ScriptPermissions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -226,7 +227,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
_yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed),
|
||||
_hmdYawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "hmdYawSpeed", _hmdYawSpeed),
|
||||
_pitchSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "pitchSpeed", _pitchSpeed),
|
||||
_fullAvatarURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarURL",
|
||||
_fullAvatarURLSetting(QStringList() << SETTINGS_FULL_PRIVATE_GROUP_NAME << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarURL",
|
||||
AvatarData::defaultFullAvatarModelUrl()),
|
||||
_fullAvatarModelNameSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarModelName", _fullAvatarModelName),
|
||||
_animGraphURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "animGraphURL", QUrl("")),
|
||||
|
@ -1739,10 +1740,11 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
|||
blobFailed = true; // blob doesn't exist
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
||||
if (!EntityItemProperties::blobToProperties(*_scriptEngine, itr.value(), properties)) {
|
||||
blobFailed = true; // blob is corrupt
|
||||
}
|
||||
_helperScriptEngine.run( [&] {
|
||||
if (!EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), itr.value(), properties)) {
|
||||
blobFailed = true; // blob is corrupt
|
||||
}
|
||||
});
|
||||
});
|
||||
if (blobFailed) {
|
||||
// remove from _cachedAvatarEntityBlobUpdatesToSkip just in case:
|
||||
|
@ -1775,10 +1777,11 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
|||
skip = true;
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
||||
if (!EntityItemProperties::blobToProperties(*_scriptEngine, itr.value(), properties)) {
|
||||
skip = true;
|
||||
}
|
||||
_helperScriptEngine.run( [&] {
|
||||
if (!EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), itr.value(), properties)) {
|
||||
skip = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (!skip && canRezAvatarEntites) {
|
||||
sanitizeAvatarEntityProperties(properties);
|
||||
|
@ -1883,10 +1886,9 @@ bool MyAvatar::updateStaleAvatarEntityBlobs() const {
|
|||
if (found) {
|
||||
++numFound;
|
||||
QByteArray blob;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
||||
EntityItemProperties::propertiesToBlob(*_scriptEngine, getID(), properties, blob);
|
||||
}
|
||||
_helperScriptEngine.run( [&] {
|
||||
EntityItemProperties::propertiesToBlob(*_helperScriptEngine.get(), getID(), properties, blob);
|
||||
});
|
||||
_avatarEntitiesLock.withWriteLock([&] {
|
||||
_cachedAvatarEntityBlobs[id] = blob;
|
||||
});
|
||||
|
@ -1947,10 +1949,9 @@ AvatarEntityMap MyAvatar::getAvatarEntityData() const {
|
|||
EntityItemProperties properties = entity->getProperties(desiredProperties);
|
||||
|
||||
QByteArray blob;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
||||
EntityItemProperties::propertiesToBlob(*_scriptEngine, getID(), properties, blob, true);
|
||||
}
|
||||
_helperScriptEngine.run( [&] {
|
||||
EntityItemProperties::propertiesToBlob(*_helperScriptEngine.get(), getID(), properties, blob, true);
|
||||
});
|
||||
|
||||
data[entityID] = blob;
|
||||
}
|
||||
|
@ -2092,9 +2093,6 @@ void MyAvatar::avatarEntityDataToJson(QJsonObject& root) const {
|
|||
}
|
||||
|
||||
void MyAvatar::loadData() {
|
||||
if (!_scriptEngine) {
|
||||
_scriptEngine = newScriptEngine();
|
||||
}
|
||||
getHead()->setBasePitch(_headPitchSetting.get());
|
||||
|
||||
_yawSpeed = _yawSpeedSetting.get(_yawSpeed);
|
||||
|
@ -2236,6 +2234,9 @@ AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString&
|
|||
return attachment;
|
||||
}
|
||||
|
||||
bool MyAvatar::isMyAvatarURLProtected() const {
|
||||
return !ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL);
|
||||
}
|
||||
|
||||
int MyAvatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||
qCDebug(interfaceapp) << "Error: ignoring update packet for MyAvatar"
|
||||
|
@ -2700,11 +2701,10 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() {
|
|||
QVariantMap avatarEntityData;
|
||||
avatarEntityData["id"] = entityID;
|
||||
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
||||
ScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine.get(), entityProperties);
|
||||
_helperScriptEngine.run( [&] {
|
||||
ScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_helperScriptEngine.get(), entityProperties);
|
||||
avatarEntityData["properties"] = scriptProperties.toVariant();
|
||||
}
|
||||
});
|
||||
avatarEntitiesData.append(QVariant(avatarEntityData));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <controllers/Pose.h>
|
||||
#include <controllers/Actions.h>
|
||||
#include <EntityItem.h>
|
||||
#include <HelperScriptEngine.h>
|
||||
#include <ThreadSafeValueCache.h>
|
||||
#include <Rig.h>
|
||||
#include <SettingHandle.h>
|
||||
|
@ -2683,6 +2684,7 @@ private:
|
|||
void setEnableDrawAverageFacing(bool drawAverage) { _drawAverageFacingEnabled = drawAverage; }
|
||||
bool getEnableDrawAverageFacing() const { return _drawAverageFacingEnabled; }
|
||||
virtual bool isMyAvatar() const override { return true; }
|
||||
virtual bool isMyAvatarURLProtected() const override;
|
||||
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
|
||||
virtual glm::vec3 getSkeletonPosition() const override;
|
||||
int _skeletonModelChangeCount { 0 };
|
||||
|
@ -3101,8 +3103,10 @@ private:
|
|||
mutable std::set<EntityItemID> _staleCachedAvatarEntityBlobs;
|
||||
//
|
||||
// keep a ScriptEngine around so we don't have to instantiate on the fly (these are very slow to create/delete)
|
||||
mutable std::mutex _scriptEngineLock;
|
||||
ScriptEnginePointer _scriptEngine { nullptr };
|
||||
// TODO: profile if it performs better when script engine is on avatar thread or on its own thread
|
||||
// Own thread is safer from deadlocks
|
||||
mutable HelperScriptEngine _helperScriptEngine;
|
||||
|
||||
bool _needToSaveAvatarEntitySettings { false };
|
||||
|
||||
bool _reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS] { false, false };
|
||||
|
|
|
@ -56,12 +56,22 @@ void PerformanceScriptingInterface::setRefreshRateProfile(RefreshRateProfile ref
|
|||
emit settingsChanged();
|
||||
}
|
||||
|
||||
void PerformanceScriptingInterface::setCustomRefreshRate(RefreshRateManager::RefreshRateRegime refreshRateRegime, int value)
|
||||
{
|
||||
qApp->getRefreshRateManager().setCustomRefreshRate(refreshRateRegime, value);
|
||||
emit settingsChanged();
|
||||
}
|
||||
|
||||
int PerformanceScriptingInterface::getCustomRefreshRate(RefreshRateManager::RefreshRateRegime refreshRateRegime) const {
|
||||
return qApp->getRefreshRateManager().getCustomRefreshRate(refreshRateRegime);
|
||||
}
|
||||
|
||||
PerformanceScriptingInterface::RefreshRateProfile PerformanceScriptingInterface::getRefreshRateProfile() const {
|
||||
return (PerformanceScriptingInterface::RefreshRateProfile)qApp->getRefreshRateManager().getRefreshRateProfile();
|
||||
}
|
||||
|
||||
QStringList PerformanceScriptingInterface::getRefreshRateProfileNames() const {
|
||||
static const QStringList refreshRateProfileNames = { "ECO", "INTERACTIVE", "REALTIME" };
|
||||
static const QStringList refreshRateProfileNames = { "ECO", "INTERACTIVE", "REALTIME", "CUSTOM" };
|
||||
return refreshRateProfileNames;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,22 @@ public slots:
|
|||
*/
|
||||
void setRefreshRateProfile(RefreshRateProfile refreshRateProfile);
|
||||
|
||||
/*@jsdoc
|
||||
* Sets a custom refresh rate.
|
||||
* @function Performance.setCustomRefreshRate
|
||||
* @param {RefreshRateRegime} refreshRateRegime - The refresh rate regime
|
||||
* @param {int} value - The value for the regime
|
||||
*/
|
||||
void setCustomRefreshRate(RefreshRateManager::RefreshRateRegime refreshRateRegime, int value);
|
||||
|
||||
/*@jsdoc
|
||||
* Gets the value for a specific RefreshRateRegime.
|
||||
* @function Performance.getCustomRefreshRate
|
||||
* @param {RefreshRateRegime} - The regime to get the value from
|
||||
* @returns {int} - The value from the specified regime
|
||||
*/
|
||||
int getCustomRefreshRate(RefreshRateManager::RefreshRateRegime regime) const;
|
||||
|
||||
/*@jsdoc
|
||||
* Gets the current refresh rate profile in use.
|
||||
* @function Performance.getRefreshRateProfile
|
||||
|
|
|
@ -21,6 +21,9 @@ SettingsScriptingInterface* SettingsScriptingInterface::getInstance() {
|
|||
}
|
||||
|
||||
QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
||||
if (_restrictPrivateValues && setting.startsWith(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/")) {
|
||||
return {""};
|
||||
}
|
||||
QVariant value = Setting::Handle<QVariant>(setting).get();
|
||||
if (!value.isValid()) {
|
||||
value = "";
|
||||
|
@ -29,6 +32,9 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
|||
}
|
||||
|
||||
QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVariant& defaultValue) {
|
||||
if (_restrictPrivateValues && setting.startsWith(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/")) {
|
||||
return {""};
|
||||
}
|
||||
QVariant value = Setting::Handle<QVariant>(setting, defaultValue).get();
|
||||
if (!value.isValid()) {
|
||||
value = "";
|
||||
|
@ -40,7 +46,7 @@ void SettingsScriptingInterface::setValue(const QString& setting, const QVariant
|
|||
if (getValue(setting) == value) {
|
||||
return;
|
||||
}
|
||||
if (setting.startsWith("private/")) {
|
||||
if (setting.startsWith("private/") || setting.startsWith(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/")) {
|
||||
if (_restrictPrivateValues) {
|
||||
qWarning() << "SettingsScriptingInterface::setValue -- restricted write: " << setting << value;
|
||||
return;
|
||||
|
|
|
@ -100,7 +100,8 @@ void setupPreferences() {
|
|||
QStringList refreshRateProfiles
|
||||
{ QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::ECO)),
|
||||
QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::INTERACTIVE)),
|
||||
QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::REALTIME)) };
|
||||
QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::REALTIME)),
|
||||
QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::CUSTOM)) };
|
||||
|
||||
preference->setItems(refreshRateProfiles);
|
||||
preferences->addPreference(preference);
|
||||
|
|
|
@ -281,7 +281,7 @@ if (APPLE)
|
|||
|
||||
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
||||
|
||||
set(DMG_SUBFOLDER_NAME "Vircadia")
|
||||
set(DMG_SUBFOLDER_NAME "Overte")
|
||||
set(ESCAPED_DMG_SUBFOLDER_NAME "")
|
||||
set(DMG_SUBFOLDER_ICON "${CMAKE_SOURCE_DIR}/cmake/installer/install-folder.rsrc")
|
||||
|
||||
|
|
|
@ -2106,6 +2106,14 @@ const QUrl& AvatarData::getSkeletonModelURL() const {
|
|||
}
|
||||
}
|
||||
|
||||
QString AvatarData::getSkeletonModelURLFromScript() const {
|
||||
if (isMyAvatar() && !isMyAvatarURLProtected()) {
|
||||
return _skeletonModelURL.toString();
|
||||
}
|
||||
|
||||
return QString();
|
||||
};
|
||||
|
||||
QByteArray AvatarData::packSkeletonData() const {
|
||||
// Send an avatar trait packet with the skeleton data before the mesh is loaded
|
||||
int avatarDataSize = 0;
|
||||
|
|
|
@ -610,6 +610,8 @@ public:
|
|||
AvatarData();
|
||||
virtual ~AvatarData();
|
||||
|
||||
virtual bool isMyAvatarURLProtected() const { return false; } // This needs to be here because both MyAvatar and AvatarData inherit from MyAvatar
|
||||
|
||||
static const QUrl& defaultFullAvatarModelUrl();
|
||||
|
||||
const QUuid getSessionUUID() const { return getID(); }
|
||||
|
@ -1355,7 +1357,7 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE virtual void detachAll(const QString& modelURL, const QString& jointName = QString());
|
||||
|
||||
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
|
||||
QString getSkeletonModelURLFromScript() const;
|
||||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||
|
||||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "ScriptAvatarData.h"
|
||||
|
||||
#include <NodeList.h>
|
||||
#include <ScriptEngineCast.h>
|
||||
#include <ScriptManager.h>
|
||||
|
||||
|
@ -204,7 +205,12 @@ bool ScriptAvatarData::getLookAtSnappingEnabled() const {
|
|||
//
|
||||
QString ScriptAvatarData::getSkeletonModelURLFromScript() const {
|
||||
if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) {
|
||||
return sharedAvatarData->getSkeletonModelURLFromScript();
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
if (sharedAvatarData->isMyAvatar() && !sharedAvatarData->isMyAvatarURLProtected() && nodeList->getThisNodeCanViewAssetURLs()) {
|
||||
return sharedAvatarData->getSkeletonModelURLFromScript();
|
||||
}
|
||||
|
||||
return QString();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ MaterialBaker::MaterialBaker(const QString& materialData, bool isURL, const QStr
|
|||
_isURL(isURL),
|
||||
_destinationPath(destinationPath),
|
||||
_bakedOutputDir(bakedOutputDir),
|
||||
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++)),
|
||||
_scriptEngine(newScriptEngine())
|
||||
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -214,16 +213,20 @@ void MaterialBaker::outputMaterial() {
|
|||
if (_materialResource->parsedMaterials.networkMaterials.size() == 1) {
|
||||
auto networkMaterial = _materialResource->parsedMaterials.networkMaterials.begin();
|
||||
auto scriptableMaterial = scriptable::ScriptableMaterial(networkMaterial->second);
|
||||
QVariant materialVariant =
|
||||
scriptable::scriptableMaterialToScriptValue(_scriptEngine.get(), scriptableMaterial).toVariant();
|
||||
json.insert("materials", QJsonDocument::fromVariant(materialVariant).object());
|
||||
_helperScriptEngine.run( [&] {
|
||||
QVariant materialVariant =
|
||||
scriptable::scriptableMaterialToScriptValue(_helperScriptEngine.get(), scriptableMaterial).toVariant();
|
||||
json.insert("materials", QJsonDocument::fromVariant(materialVariant).object());
|
||||
});
|
||||
} else {
|
||||
QJsonArray materialArray;
|
||||
for (auto networkMaterial : _materialResource->parsedMaterials.networkMaterials) {
|
||||
auto scriptableMaterial = scriptable::ScriptableMaterial(networkMaterial.second);
|
||||
QVariant materialVariant =
|
||||
scriptable::scriptableMaterialToScriptValue(_scriptEngine.get(), scriptableMaterial).toVariant();
|
||||
materialArray.append(QJsonDocument::fromVariant(materialVariant).object());
|
||||
_helperScriptEngine.run( [&] {
|
||||
QVariant materialVariant =
|
||||
scriptable::scriptableMaterialToScriptValue(_helperScriptEngine.get(), scriptableMaterial).toVariant();
|
||||
materialArray.append(QJsonDocument::fromVariant(materialVariant).object());
|
||||
});
|
||||
}
|
||||
json.insert("materials", materialArray);
|
||||
}
|
||||
|
@ -269,19 +272,32 @@ void MaterialBaker::setMaterials(const QHash<QString, hfm::Material>& materials,
|
|||
_materialResource = NetworkMaterialResourcePointer(new NetworkMaterialResource(), [](NetworkMaterialResource* ptr) { ptr->deleteLater(); });
|
||||
for (auto& material : materials) {
|
||||
_materialResource->parsedMaterials.names.push_back(material.name.toStdString());
|
||||
_materialResource->parsedMaterials.networkMaterials[material.name.toStdString()] = std::make_shared<NetworkMaterial>(material, baseURL);
|
||||
if (!material.isMToonMaterial) {
|
||||
_materialResource->parsedMaterials.networkMaterials[material.name.toStdString()] = std::make_shared<NetworkMaterial>(material, baseURL);
|
||||
} else {
|
||||
_materialResource->parsedMaterials.networkMaterials[material.name.toStdString()] = std::make_shared<NetworkMToonMaterial>(material, baseURL);
|
||||
}
|
||||
|
||||
// Store any embedded texture content
|
||||
addTexture(material.name, image::TextureUsage::NORMAL_TEXTURE, material.normalTexture);
|
||||
addTexture(material.name, image::TextureUsage::ALBEDO_TEXTURE, material.albedoTexture);
|
||||
addTexture(material.name, image::TextureUsage::GLOSS_TEXTURE, material.glossTexture);
|
||||
addTexture(material.name, image::TextureUsage::ROUGHNESS_TEXTURE, material.roughnessTexture);
|
||||
addTexture(material.name, image::TextureUsage::SPECULAR_TEXTURE, material.specularTexture);
|
||||
addTexture(material.name, image::TextureUsage::METALLIC_TEXTURE, material.metallicTexture);
|
||||
addTexture(material.name, image::TextureUsage::EMISSIVE_TEXTURE, material.emissiveTexture);
|
||||
addTexture(material.name, image::TextureUsage::OCCLUSION_TEXTURE, material.occlusionTexture);
|
||||
addTexture(material.name, image::TextureUsage::SCATTERING_TEXTURE, material.scatteringTexture);
|
||||
addTexture(material.name, image::TextureUsage::LIGHTMAP_TEXTURE, material.lightmapTexture);
|
||||
|
||||
if (!material.isMToonMaterial) {
|
||||
addTexture(material.name, image::TextureUsage::GLOSS_TEXTURE, material.glossTexture);
|
||||
addTexture(material.name, image::TextureUsage::ROUGHNESS_TEXTURE, material.roughnessTexture);
|
||||
addTexture(material.name, image::TextureUsage::SPECULAR_TEXTURE, material.specularTexture);
|
||||
addTexture(material.name, image::TextureUsage::METALLIC_TEXTURE, material.metallicTexture);
|
||||
addTexture(material.name, image::TextureUsage::OCCLUSION_TEXTURE, material.occlusionTexture);
|
||||
addTexture(material.name, image::TextureUsage::SCATTERING_TEXTURE, material.scatteringTexture);
|
||||
addTexture(material.name, image::TextureUsage::LIGHTMAP_TEXTURE, material.lightmapTexture);
|
||||
} else {
|
||||
addTexture(material.name, image::TextureUsage::ALBEDO_TEXTURE, material.shadeTexture);
|
||||
addTexture(material.name, image::TextureUsage::ROUGHNESS_TEXTURE, material.shadingShiftTexture);
|
||||
addTexture(material.name, image::TextureUsage::EMISSIVE_TEXTURE, material.matcapTexture);
|
||||
addTexture(material.name, image::TextureUsage::ALBEDO_TEXTURE, material.rimTexture);
|
||||
addTexture(material.name, image::TextureUsage::ROUGHNESS_TEXTURE, material.uvAnimationTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "TextureBaker.h"
|
||||
#include "baking/TextureFileNamer.h"
|
||||
|
||||
#include <HelperScriptEngine.h>
|
||||
#include <procedural/ProceduralMaterialCache.h>
|
||||
#include <ScriptEngine.h>
|
||||
|
||||
|
@ -72,7 +73,7 @@ private:
|
|||
QString _textureOutputDir;
|
||||
QString _bakedMaterialData;
|
||||
|
||||
ScriptEnginePointer _scriptEngine;
|
||||
HelperScriptEngine _helperScriptEngine;
|
||||
static std::function<QThread*()> _getNextOvenWorkerThreadOperator;
|
||||
TextureFileNamer _textureFileNamer;
|
||||
|
||||
|
|
|
@ -1195,9 +1195,9 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) {
|
|||
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8(), &error);
|
||||
// check validity of the document
|
||||
if (doc.isNull()) {
|
||||
qCDebug(controllers) << "Invalid JSON...\n";
|
||||
qCDebug(controllers) << error.errorString();
|
||||
qCDebug(controllers) << "JSON was:\n" << json << Qt::endl;
|
||||
qCCritical(controllers) << "Invalid JSON...\n";
|
||||
qCCritical(controllers) << error.errorString();
|
||||
qCCritical(controllers) << "JSON was:\n" << json << Qt::endl;
|
||||
return Mapping::Pointer();
|
||||
}
|
||||
|
||||
|
|
|
@ -743,6 +743,13 @@ void OpenGLDisplayPlugin::present(const std::shared_ptr<RefreshRateController>&
|
|||
}
|
||||
|
||||
gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory());
|
||||
|
||||
// Drop current frame after presenting it once.
|
||||
// This is required for the OpenXR frame cycle, since we call xrEndFrame after presenting.
|
||||
// xrEndFrame must not be called multiple times.
|
||||
if (_presentOnlyOnce) {
|
||||
_currentFrame.reset();
|
||||
}
|
||||
} else if (alwaysPresent()) {
|
||||
refreshRateController->clockEndTime();
|
||||
internalPresent();
|
||||
|
|
|
@ -201,4 +201,6 @@ protected:
|
|||
|
||||
QImage getScreenshot(float aspectRatio);
|
||||
QImage getSecondaryCameraScreenshot();
|
||||
|
||||
bool _presentOnlyOnce = false;
|
||||
};
|
||||
|
|
|
@ -56,16 +56,16 @@ QRect HmdDisplayPlugin::getRecommendedHUDRect() const {
|
|||
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
|
||||
}
|
||||
|
||||
glm::mat4 HmdDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
||||
return _eyeOffsets[eye];
|
||||
glm::mat4 HmdDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
|
||||
return _eyeOffsets[eye];
|
||||
}
|
||||
|
||||
glm::mat4 HmdDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
|
||||
return _eyeProjections[eye];
|
||||
glm::mat4 HmdDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
|
||||
return _eyeProjections[eye];
|
||||
}
|
||||
|
||||
glm::mat4 HmdDisplayPlugin::getCullingProjection(const glm::mat4& baseProjection) const {
|
||||
return _cullingProjection;
|
||||
glm::mat4 HmdDisplayPlugin::getCullingProjection(const glm::mat4& baseProjection) const {
|
||||
return _cullingProjection;
|
||||
}
|
||||
|
||||
glm::ivec4 HmdDisplayPlugin::eyeViewport(Eye eye) const {
|
||||
|
|
|
@ -337,21 +337,26 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
}
|
||||
|
||||
// Draw!
|
||||
DependencyManager::get<GeometryCache>()->renderSphere(batch);
|
||||
const uint32_t compactColor = 0xFFFFFFFF;
|
||||
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||
DependencyManager::get<GeometryCache>()->renderShape(batch, GeometryCache::Shape::Sphere, _colorBuffer);
|
||||
} else {
|
||||
auto proceduralDrawMaterial = std::static_pointer_cast<graphics::ProceduralMaterial>(drawMaterial);
|
||||
glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity());
|
||||
outColor = proceduralDrawMaterial->getColor(outColor);
|
||||
proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(),
|
||||
transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
|
||||
const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor));
|
||||
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireSphere(batch, outColor);
|
||||
DependencyManager::get<GeometryCache>()->renderWireShape(batch, GeometryCache::Shape::Sphere, _colorBuffer);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderSphere(batch, outColor);
|
||||
DependencyManager::get<GeometryCache>()->renderShape(batch, GeometryCache::Shape::Sphere, _colorBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
|
||||
args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->getShapeTriangleCount(GeometryCache::Shape::Sphere);
|
||||
}
|
||||
|
||||
void MaterialEntityRenderer::setCurrentMaterialName(const std::string& currentMaterialName) {
|
||||
|
|
|
@ -67,6 +67,7 @@ private:
|
|||
std::shared_ptr<NetworkMaterial> _appliedMaterial;
|
||||
std::string _currentMaterialName;
|
||||
|
||||
gpu::BufferPointer _colorBuffer { std::make_shared<gpu::Buffer>() };
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -21,23 +21,48 @@ using namespace render::entities;
|
|||
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER = 0;
|
||||
static gpu::Stream::FormatPointer _vertexFormat;
|
||||
static std::weak_ptr<gpu::Pipeline> _texturedPipeline;
|
||||
// forward, transparent, shadow, wireframe
|
||||
static std::map<std::tuple<bool, bool, bool, bool>, gpu::PipelinePointer> _pipelines;
|
||||
|
||||
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
|
||||
auto texturedPipeline = _texturedPipeline.lock();
|
||||
if (!texturedPipeline) {
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
if (_pipelines.empty()) {
|
||||
using namespace shader::entities_renderer::program;
|
||||
|
||||
auto program = gpu::Shader::createProgram(shader::entities_renderer::program::textured_particle);
|
||||
_texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state);
|
||||
// forward, translucent, shadow
|
||||
static const std::vector<std::tuple<bool, bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, false, textured_particle),
|
||||
std::make_tuple(true, false, false, textured_particle_forward),
|
||||
std::make_tuple(false, true, false, textured_particle_translucent),
|
||||
std::make_tuple(true, true, false, textured_particle_translucent_forward),
|
||||
std::make_tuple(false, false, true, textured_particle_shadow),
|
||||
// no such thing as shadow and forward/translucent
|
||||
};
|
||||
|
||||
for (auto& key : keys) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
bool transparent = std::get<1>(key);
|
||||
bool wireframe = i == 0;
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
|
||||
if (wireframe) {
|
||||
state->setFillMode(gpu::State::FILL_LINE);
|
||||
}
|
||||
|
||||
state->setDepthTest(true, !transparent, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
transparent ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);
|
||||
|
||||
auto program = gpu::Shader::createProgram(std::get<3>(key));
|
||||
_pipelines[std::make_tuple(std::get<0>(key), transparent, std::get<2>(key), wireframe)] = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<render::ShapePipeline>(texturedPipeline, nullptr, nullptr, nullptr);
|
||||
return std::make_shared<render::ShapePipeline>(_pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isTranslucent(),
|
||||
args->_renderMode == Args::RenderMode::SHADOW_RENDER_MODE, key.isWireframe())], nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
struct GpuParticle {
|
||||
|
@ -138,26 +163,25 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn
|
|||
_uniformBuffer.edit<ParticleUniforms>() = particleUniforms;
|
||||
}
|
||||
|
||||
ItemKey ParticleEffectEntityRenderer::getKey() {
|
||||
// FIXME: implement isTransparent() for particles and an opaque pipeline
|
||||
auto builder = ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||
|
||||
if (!_visible) {
|
||||
builder.withInvisible();
|
||||
}
|
||||
|
||||
if (_cullWithParent) {
|
||||
builder.withSubMetaCulled();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
bool ParticleEffectEntityRenderer::isTransparent() const {
|
||||
bool particleTransparent = _particleProperties.getColorStart().a < 1.0f || _particleProperties.getColorMiddle().a < 1.0f ||
|
||||
_particleProperties.getColorFinish().a < 1.0f || _particleProperties.getColorSpread().a > 0.0f ||
|
||||
_pulseProperties.getAlphaMode() != PulseMode::NONE || (_textureLoaded && _networkTexture && _networkTexture->getGPUTexture() &&
|
||||
_networkTexture->getGPUTexture()->getUsage().isAlpha() && !_networkTexture->getGPUTexture()->getUsage().isAlphaMask());
|
||||
return particleTransparent || Parent::isTransparent();
|
||||
}
|
||||
|
||||
ShapeKey ParticleEffectEntityRenderer::getShapeKey() {
|
||||
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).withTranslucent();
|
||||
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
|
||||
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ protected:
|
|||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
virtual ItemKey getKey() override;
|
||||
bool isTransparent() const override;
|
||||
virtual ShapeKey getShapeKey() override;
|
||||
virtual Item::Bound getBound(RenderArgs* args) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
|
|
@ -1719,21 +1719,28 @@ using namespace render;
|
|||
using namespace render::entities;
|
||||
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||
static std::map<std::tuple<bool, bool, bool>, ShapePipelinePointer> _pipelines;
|
||||
// forward, shadow, fade, wireframe
|
||||
static std::map<std::tuple<bool, bool, bool, bool>, ShapePipelinePointer> _pipelines;
|
||||
static gpu::Stream::FormatPointer _vertexFormat;
|
||||
|
||||
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
|
||||
// FIXME: custom pipelines like this don't handle shadows or renderLayers correctly
|
||||
|
||||
if (_pipelines.empty()) {
|
||||
using namespace shader::entities_renderer::program;
|
||||
|
||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward)
|
||||
// forward, shadow, fade
|
||||
static const std::vector<std::tuple<bool, bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, false, polyvox),
|
||||
std::make_tuple(true, false, false, polyvox_forward),
|
||||
std::make_tuple(false, true, false, polyvox_shadow),
|
||||
// no such thing as forward + shadow
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
, std::make_tuple(false, true, polyvox_fade), std::make_tuple(true, true, polyvox_forward_fade)
|
||||
std::make_tuple(false, false, true, polyvox_fade),
|
||||
std::make_tuple(false, true, true, polyvox_shadow_fade),
|
||||
// no such thing as forward + fade/shadow
|
||||
#else
|
||||
, std::make_tuple(false, true, polyvox), std::make_tuple(true, true, polyvox_forward)
|
||||
std::make_tuple(false, false, true, polyvox),
|
||||
std::make_tuple(false, true, true, polyvox_shadow),
|
||||
// no such thing as forward + fade/shadow
|
||||
#endif
|
||||
};
|
||||
for (auto& key : keys) {
|
||||
|
@ -1749,19 +1756,19 @@ ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const Sha
|
|||
state->setFillMode(gpu::State::FILL_LINE);
|
||||
}
|
||||
|
||||
auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
|
||||
if (std::get<1>(key)) {
|
||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr, nullptr, nullptr);
|
||||
auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<3>(key)), state);
|
||||
if (!std::get<2>(key)) {
|
||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), std::get<2>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr, nullptr, nullptr);
|
||||
} else {
|
||||
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr,
|
||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), std::get<2>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr,
|
||||
fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isFaded(), key.isWireframe())];
|
||||
return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, args->_renderMode == Args::RenderMode::SHADOW_RENDER_MODE, key.isFaded(), key.isWireframe())];
|
||||
}
|
||||
|
||||
PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
|
@ -1775,16 +1782,6 @@ PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) :
|
|||
_params = std::make_shared<gpu::Buffer>(sizeof(glm::vec4), nullptr);
|
||||
}
|
||||
|
||||
ItemKey PolyVoxEntityRenderer::getKey() {
|
||||
auto builder = ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||
|
||||
if (_cullWithParent) {
|
||||
builder.withSubMetaCulled();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
ShapeKey PolyVoxEntityRenderer::getShapeKey() {
|
||||
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
|
@ -1866,13 +1863,7 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) {
|
|||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setInputFormat(_vertexFormat);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0,
|
||||
sizeof(PolyVox::PositionMaterialNormal));
|
||||
|
||||
// TODO -- should we be setting this?
|
||||
// batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer,
|
||||
// 12,
|
||||
// sizeof(PolyVox::PositionMaterialNormal));
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0, sizeof(PolyVox::PositionMaterialNormal));
|
||||
batch.setIndexBuffer(gpu::UINT32, _mesh->getIndexBuffer()._buffer, 0);
|
||||
|
||||
for (size_t i = 0; i < _xyzTextures.size(); ++i) {
|
||||
|
|
|
@ -203,7 +203,6 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual ItemKey getKey() override;
|
||||
virtual ShapeKey getShapeKey() override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
|
|
|
@ -131,10 +131,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
});
|
||||
|
||||
const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor));
|
||||
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||
if (wireframe) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
geometryCache->renderWireShape(batch, geometryShape, _colorBuffer);
|
||||
} else {
|
||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
||||
geometryCache->renderShape(batch, geometryShape, _colorBuffer);
|
||||
}
|
||||
} else if (pipelineType == Pipeline::SIMPLE) {
|
||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
|
@ -149,10 +151,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
}
|
||||
} else {
|
||||
const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor));
|
||||
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||
if (wireframe) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
geometryCache->renderWireShape(batch, geometryShape, _colorBuffer);
|
||||
} else {
|
||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
||||
geometryCache->renderShape(batch, geometryShape, _colorBuffer);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -160,7 +164,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
geometryCache->renderShape(batch, geometryShape);
|
||||
const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor));
|
||||
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||
geometryCache->renderShape(batch, geometryShape, _colorBuffer);
|
||||
}
|
||||
|
||||
const auto triCount = geometryCache->getShapeTriangleCount(geometryShape);
|
||||
|
|
|
@ -42,6 +42,8 @@ private:
|
|||
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
|
||||
glm::vec3 _color { NAN };
|
||||
float _alpha { NAN };
|
||||
|
||||
gpu::BufferPointer _colorBuffer { std::make_shared<gpu::Buffer>() };
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DEFINES (translucent:f forward:f)/shadow:f
|
|
@ -15,8 +15,34 @@ LAYOUT(binding=0) uniform sampler2D colorMap;
|
|||
layout(location=0) in vec4 varColor;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
<@if HIFI_USE_FORWARD or HIFI_USE_SHADOW@>
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
<@else@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@endif@>
|
||||
|
||||
void main(void) {
|
||||
outFragColor = texture(colorMap, varTexcoord.xy) * varColor;
|
||||
vec4 albedo = texture(colorMap, varTexcoord.xy) * varColor;
|
||||
|
||||
<@if HIFI_USE_FORWARD or HIFI_USE_SHADOW@>
|
||||
<@if not HIFI_USE_TRANSLUCENT@>
|
||||
// to reduce texel flickering for floating point error we discard when alpha is "almost one"
|
||||
if (albedo.a < 0.999999) {
|
||||
discard;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if HIFI_USE_FORWARD@>
|
||||
_fragColor0 = albedo;
|
||||
<@else@>
|
||||
_fragColor0 = vec4(1.0);
|
||||
<@endif@>
|
||||
<@else@>
|
||||
vec3 NORMAL = vec3(1.0, 0.0, 0.0);
|
||||
<@if not HIFI_USE_TRANSLUCENT@>
|
||||
packDeferredFragmentUnlit(NORMAL, albedo.a, albedo.rgb);
|
||||
<@else@>
|
||||
packDeferredFragmentTranslucent(NORMAL, albedo.a, albedo.rgb, DEFAULT_ROUGHNESS);
|
||||
<@endif@>
|
||||
<@endif@>
|
||||
}
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
const float AmbientLightPropertyGroup::DEFAULT_AMBIENT_LIGHT_INTENSITY = 0.5f;
|
||||
|
||||
void AmbientLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
|
||||
ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, AmbientIntensity, ambientIntensity);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_LIGHT_URL, AmbientLight, ambientLight, AmbientURL, ambientURL);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_AMBIENT_LIGHT_URL, AmbientLight, ambientLight, AmbientURL, ambientURL);
|
||||
}
|
||||
|
||||
void AmbientLightPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
|
||||
|
|
|
@ -43,7 +43,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const AmbientLightPropertyGroup& other);
|
||||
|
|
|
@ -68,8 +68,10 @@ bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b
|
|||
* maintained when the animation stops playing, <code>false</code> if they aren't.
|
||||
*/
|
||||
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url);
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_ANIMATION_URL, Animation, animation, URL, url);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
||||
|
|
|
@ -37,7 +37,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const AnimationPropertyGroup& other);
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#include "EntityItemPropertiesMacros.h"
|
||||
|
||||
void BloomPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize);
|
||||
|
|
|
@ -44,7 +44,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const BloomPropertyGroup& other);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <Extents.h>
|
||||
#include <VariantMapToScriptValue.h>
|
||||
#include <ScriptValue.h>
|
||||
#include <PhysicsHelpers.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItem.h"
|
||||
|
@ -1566,6 +1567,8 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
return properties;
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
bool isMyOwnAvatarEntity = _entityHostType == entity::HostType::AVATAR && (_owningAvatarID == AVATAR_SELF_ID || _owningAvatarID == Physics::getSessionUUID());
|
||||
if (_idSet && (!pseudoPropertyFlagsActive || pseudoPropertyFlags.test(EntityPseudoPropertyFlag::ID))) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString());
|
||||
}
|
||||
|
@ -1615,7 +1618,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString());
|
||||
_grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
|
||||
// Physics
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DENSITY, density);
|
||||
|
@ -1634,7 +1637,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_COLLISION_MASK, collisionMask, collidesWith, getCollisionMaskAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DYNAMIC, dynamic);
|
||||
COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_DYNAMIC, dynamic, collisionsWillMove, getDynamic()); // legacy support
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_COLLISION_SOUND_URL, collisionSoundURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACTION_DATA, actionData);
|
||||
|
||||
// Cloning
|
||||
|
@ -1660,10 +1663,10 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
// Particles only
|
||||
if (_type == EntityTypes::ParticleEffect) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles);
|
||||
|
@ -1710,11 +1713,11 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
// Models only
|
||||
if (_type == EntityTypes::Model) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_MODEL_URL, modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_SCALE, modelScale);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations);
|
||||
|
@ -1724,7 +1727,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GROUP_CULLED, groupCulled);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BLENDSHAPE_COEFFICIENTS, blendshapeCoefficients);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USE_ORIGINAL_PIVOT, useOriginalPivot);
|
||||
_animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
}
|
||||
|
||||
// FIXME: Shouldn't provide a shapeType property for Box and Sphere entities.
|
||||
|
@ -1738,7 +1741,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
if (_type == EntityTypes::Box || _type == EntityTypes::Sphere || _type == EntityTypes::Shape) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHAPE, shape);
|
||||
}
|
||||
|
||||
|
@ -1754,7 +1757,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
|
||||
// Text only
|
||||
if (_type == EntityTypes::Text) {
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT, text);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight);
|
||||
|
@ -1777,17 +1780,17 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
// Zones only
|
||||
if (_type == EntityTypes::Zone) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
|
||||
_keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FILTER_URL, filterURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_FILTER_URL, filterURL);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString());
|
||||
|
@ -1802,11 +1805,11 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
if (_type == EntityTypes::Web) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_SOURCE_URL, sourceUrl);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DPI, dpi);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SCRIPT_URL, scriptURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_SCRIPT_URL, scriptURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_FPS, maxFPS);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_INPUT_MODE, inputMode, getInputModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, showKeyboardFocusHighlight);
|
||||
|
@ -1819,9 +1822,9 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_DATA, voxelData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_SURFACE_STYLE, voxelSurfaceStyle);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_X_TEXTURE_URL, xTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_TEXTURE_URL, yTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Z_TEXTURE_URL, zTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_X_TEXTURE_URL, xTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_Y_TEXTURE_URL, yTextureURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_Z_TEXTURE_URL, zTextureURL);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_X_N_NEIGHBOR_ID, xNNeighborID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_N_NEIGHBOR_ID, yNNeighborID);
|
||||
|
@ -1855,14 +1858,14 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
|
||||
// Materials
|
||||
if (_type == EntityTypes::Material) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_URL, materialURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_MATERIAL_URL, materialURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_MATERIAL_MAPPING_MODE, materialMappingMode, getMaterialMappingModeAsString());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_MATERIAL_NAME, parentMaterialName);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_POS, materialMappingPos);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_DATA, materialData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_MATERIAL_DATA, materialData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_REPEAT, materialRepeat);
|
||||
}
|
||||
|
||||
|
@ -1870,15 +1873,16 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
if (_type == EntityTypes::Image) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_IMAGE_URL, imageURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMISSIVE, emissive);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEEP_ASPECT_RATIO, keepAspectRatio);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SUB_IMAGE, subImage);
|
||||
|
||||
// Handle conversions to old 'textures' property from "imageURL"
|
||||
if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(PROP_IMAGE_URL)) &&
|
||||
if ((isMyOwnAvatarEntity || nodeList->getThisNodeCanViewAssetURLs()) &&
|
||||
((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(PROP_IMAGE_URL)) &&
|
||||
(!skipDefaults || defaultEntityProperties._imageURL != _imageURL)) {
|
||||
ScriptValue textures = engine->newObject();
|
||||
textures.setProperty("tex.picture", _imageURL);
|
||||
|
@ -1890,7 +1894,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
if (_type == EntityTypes::Grid) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GRID_FOLLOW_CAMERA, followCamera);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAJOR_GRID_EVERY, majorGridEvery);
|
||||
|
@ -1900,7 +1904,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
|||
// Gizmo only
|
||||
if (_type == EntityTypes::Gizmo) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_GIZMO_TYPE, gizmoType, getGizmoTypeAsString());
|
||||
_ring.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
||||
_ring.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||
}
|
||||
|
||||
/*@jsdoc
|
||||
|
@ -2549,7 +2553,7 @@ bool EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue&
|
|||
if (object.isString()) {
|
||||
EntityPropertyInfo propertyInfo;
|
||||
if (getPropertyInfo(object.toString(), propertyInfo)) {
|
||||
flags << propertyInfo.propertyEnum;
|
||||
flags << propertyInfo.propertyEnums;
|
||||
}
|
||||
}
|
||||
else if (object.isArray()) {
|
||||
|
@ -2558,7 +2562,7 @@ bool EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue&
|
|||
QString propertyName = object.property(i).toString();
|
||||
EntityPropertyInfo propertyInfo;
|
||||
if (getPropertyInfo(propertyName, propertyInfo)) {
|
||||
flags << propertyInfo.propertyEnum;
|
||||
flags << propertyInfo.propertyEnums;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2794,7 +2798,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
|
|||
{ // Keylight
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLight, keylight, Direction, direction);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows);
|
||||
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias, 0.0f, 1.0f);
|
||||
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 1.0f, 250.0f);
|
||||
|
@ -2943,14 +2947,14 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
|
|||
*/
|
||||
ScriptValue EntityPropertyInfoToScriptValue(ScriptEngine* engine, const EntityPropertyInfo& propertyInfo) {
|
||||
ScriptValue obj = engine->newObject();
|
||||
obj.setProperty("propertyEnum", propertyInfo.propertyEnum);
|
||||
obj.setProperty("propertyEnum", propertyInfo.propertyEnums.firstFlag());
|
||||
obj.setProperty("minimum", propertyInfo.minimum.toString());
|
||||
obj.setProperty("maximum", propertyInfo.maximum.toString());
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool EntityPropertyInfoFromScriptValue(const ScriptValue& object, EntityPropertyInfo& propertyInfo) {
|
||||
propertyInfo.propertyEnum = (EntityPropertyList)object.property("propertyEnum").toVariant().toUInt();
|
||||
propertyInfo.propertyEnums = (EntityPropertyList)object.property("propertyEnum").toVariant().toUInt();
|
||||
propertyInfo.minimum = object.property("minimum").toVariant();
|
||||
propertyInfo.maximum = object.property("maximum").toVariant();
|
||||
return true;
|
||||
|
|
|
@ -80,11 +80,11 @@ using u8vec3Color = glm::u8vec3;
|
|||
|
||||
struct EntityPropertyInfo {
|
||||
EntityPropertyInfo(EntityPropertyList propEnum) :
|
||||
propertyEnum(propEnum) {}
|
||||
propertyEnums(propEnum) {}
|
||||
EntityPropertyInfo(EntityPropertyList propEnum, QVariant min, QVariant max) :
|
||||
propertyEnum(propEnum), minimum(min), maximum(max) {}
|
||||
propertyEnums(propEnum), minimum(min), maximum(max) {}
|
||||
EntityPropertyInfo() = default;
|
||||
EntityPropertyList propertyEnum;
|
||||
EntityPropertyFlags propertyEnums;
|
||||
QVariant minimum;
|
||||
QVariant maximum;
|
||||
};
|
||||
|
|
|
@ -218,6 +218,37 @@ inline ScriptValue convertScriptValue(ScriptEngine* e, const AACube& v) { return
|
|||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(p, P) \
|
||||
if (((!returnNothingOnEmptyPropertyFlags && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
|
||||
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \
|
||||
if (isMyOwnAvatarEntity || nodeList->getThisNodeCanViewAssetURLs()) { \
|
||||
ScriptValue V = convertScriptValue(engine, _##P); \
|
||||
properties.setProperty(#P, V); \
|
||||
} else { \
|
||||
const QString emptyURL = ""; \
|
||||
ScriptValue V = convertScriptValue(engine, emptyURL); \
|
||||
properties.setProperty(#P, V); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(X, G, g, P, p) \
|
||||
if (((!returnNothingOnEmptyPropertyFlags && desiredProperties.isEmpty()) || desiredProperties.getHasProperty(X)) && \
|
||||
(!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P())) { \
|
||||
if (isMyOwnAvatarEntity || nodeList->getThisNodeCanViewAssetURLs()) { \
|
||||
ScriptValue groupProperties = properties.property(#g); \
|
||||
if (!groupProperties.isValid()) { \
|
||||
groupProperties = engine->newObject(); \
|
||||
} \
|
||||
ScriptValue V = convertScriptValue(engine, get##P()); \
|
||||
groupProperties.setProperty(#p, V); \
|
||||
properties.setProperty(#g, groupProperties); \
|
||||
} else { \
|
||||
const QString emptyURL = ""; \
|
||||
ScriptValue V = convertScriptValue(engine, emptyURL); \
|
||||
properties.setProperty(#P, V); \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef QVector<glm::vec3> qVectorVec3;
|
||||
typedef QVector<glm::quat> qVectorQuat;
|
||||
typedef QVector<bool> qVectorBool;
|
||||
|
@ -459,14 +490,16 @@ inline QRect QRect_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
|
|||
{ \
|
||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
|
||||
_propertyInfos[#g "." #n] = propertyInfo; \
|
||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||
_propertyInfos[#g].propertyEnums << P; \
|
||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||
}
|
||||
|
||||
#define ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(P, G, g, N, n, M, X) \
|
||||
{ \
|
||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
|
||||
_propertyInfos[#g "." #n] = propertyInfo; \
|
||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||
_propertyInfos[#g].propertyEnums << P; \
|
||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||
}
|
||||
|
||||
#define DEFINE_CORE(N, n, T, V) \
|
||||
|
|
|
@ -97,6 +97,7 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership
|
|||
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
|
||||
connect(nodeList.data(), &NodeList::canGetAndSetPrivateUserDataChanged, this, &EntityScriptingInterface::canGetAndSetPrivateUserDataChanged);
|
||||
connect(nodeList.data(), &NodeList::canRezAvatarEntitiesChanged, this, &EntityScriptingInterface::canRezAvatarEntitiesChanged);
|
||||
connect(nodeList.data(), &NodeList::canViewAssetURLsChanged, this, &EntityScriptingInterface::canViewAssetURLsChanged);
|
||||
|
||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod,
|
||||
|
@ -291,6 +292,11 @@ bool EntityScriptingInterface::canRezAvatarEntities() {
|
|||
return nodeList->getThisNodeCanRezAvatarEntities();
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::canViewAssetURLs() {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
return nodeList->getThisNodeCanViewAssetURLs();
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
|
||||
if (_entityTree) {
|
||||
disconnect(_entityTree.get(), &EntityTree::addingEntityPointer, this, &EntityScriptingInterface::onAddingEntity);
|
||||
|
|
|
@ -288,6 +288,14 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE bool canRezAvatarEntities();
|
||||
|
||||
/*@jsdoc
|
||||
* Checks whether or not the script can view asset URLs
|
||||
* @function Entities.canViewAssetURLs
|
||||
* @returns {boolean} <code>true</code> if the domain server will allow the script to view asset URLs,
|
||||
* otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool canViewAssetURLs();
|
||||
|
||||
/*@jsdoc
|
||||
* <p>How an entity is hosted and sent to others for display.</p>
|
||||
* <table>
|
||||
|
@ -2249,6 +2257,14 @@ signals:
|
|||
*/
|
||||
void canRezAvatarEntitiesChanged(bool canRezAvatarEntities);
|
||||
|
||||
/*@jsdoc
|
||||
* Triggered when your ability to view asset URLs is changed.
|
||||
* @function Entities.canViewAssetURLsChanged
|
||||
* @param {boolean} canViewAssetURLs - <code>true</code> if the script can view asset URLs,
|
||||
* <code>false</code> if it can't.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void canViewAssetURLsChanged(bool canViewAssetURLs);
|
||||
|
||||
/*@jsdoc
|
||||
* Triggered when a mouse button is clicked while the mouse cursor is on an entity, or a controller trigger is fully
|
||||
|
|
|
@ -2553,11 +2553,10 @@ bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElementPointer
|
|||
}
|
||||
entityDescription["DataVersion"] = _persistDataVersion;
|
||||
entityDescription["Id"] = _persistID;
|
||||
const std::lock_guard<std::mutex> scriptLock(scriptEngineMutex);
|
||||
RecurseOctreeToMapOperator theOperator(entityDescription, element, scriptEngine.get(), skipDefaultValues,
|
||||
skipThoseWithBadParents, _myAvatar);
|
||||
withReadLock([&] {
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
_helperScriptEngine.run( [&] {
|
||||
RecurseOctreeToMapOperator theOperator(entityDescription, element, _helperScriptEngine.get(), skipDefaultValues,
|
||||
skipThoseWithBadParents, _myAvatar);
|
||||
withReadLock([&] { recurseTreeWithOperator(&theOperator); });
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
@ -2728,11 +2727,10 @@ bool EntityTree::readFromMap(QVariantMap& map, const bool isImport) {
|
|||
}
|
||||
|
||||
EntityItemProperties properties;
|
||||
{
|
||||
const std::lock_guard<std::mutex> scriptLock(scriptEngineMutex);
|
||||
ScriptValue entityScriptValue = variantMapToScriptValue(entityMap, *scriptEngine);
|
||||
_helperScriptEngine.run( [&] {
|
||||
ScriptValue entityScriptValue = variantMapToScriptValue(entityMap, *_helperScriptEngine.get());
|
||||
EntityItemPropertiesFromScriptValueIgnoreReadOnly(entityScriptValue, properties);
|
||||
}
|
||||
});
|
||||
|
||||
EntityItemID entityItemID;
|
||||
if (entityMap.contains("id")) {
|
||||
|
@ -2881,13 +2879,12 @@ bool EntityTree::readFromMap(QVariantMap& map, const bool isImport) {
|
|||
}
|
||||
|
||||
bool EntityTree::writeToJSON(QString& jsonString, const OctreeElementPointer& element) {
|
||||
const std::lock_guard<std::mutex> scriptLock(scriptEngineMutex);
|
||||
RecurseOctreeToJSONOperator theOperator(element, scriptEngine.get(), jsonString);
|
||||
withReadLock([&] {
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
});
|
||||
_helperScriptEngine.run( [&] {
|
||||
RecurseOctreeToJSONOperator theOperator(element, _helperScriptEngine.get(), jsonString);
|
||||
withReadLock([&] { recurseTreeWithOperator(&theOperator); });
|
||||
|
||||
jsonString = theOperator.getJson();
|
||||
jsonString = theOperator.getJson();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QSet>
|
||||
#include <QVector>
|
||||
|
||||
#include <HelperScriptEngine.h>
|
||||
#include <Octree.h>
|
||||
#include <SpatialParentFinder.h>
|
||||
|
||||
|
@ -387,8 +388,7 @@ private:
|
|||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer);
|
||||
|
||||
// Script engine for writing entity tree data to and from JSON
|
||||
std::mutex scriptEngineMutex;
|
||||
ScriptEnginePointer scriptEngine{ newScriptEngine() };
|
||||
HelperScriptEngine _helperScriptEngine;
|
||||
};
|
||||
|
||||
void convertGrabUserDataToProperties(EntityItemProperties& properties);
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
void GrabPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_FOLLOWS_CONTROLLER, Grab, grab, GrabFollowsController, grabFollowsController);
|
||||
|
@ -36,7 +38,7 @@ void GrabPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProp
|
|||
EquippableRightPosition, equippableRightPosition);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_RIGHT_EQUIPPABLE_ROTATION_OFFSET, Grab, grab,
|
||||
EquippableRightRotation, equippableRightRotation);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_EQUIPPABLE_INDICATOR_URL, Grab, grab,
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_GRAB_EQUIPPABLE_INDICATOR_URL, Grab, grab,
|
||||
EquippableIndicatorURL, equippableIndicatorURL);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_EQUIPPABLE_INDICATOR_SCALE, Grab, grab,
|
||||
EquippableIndicatorScale, equippableIndicatorScale);
|
||||
|
|
|
@ -75,7 +75,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const GrabPropertyGroup& other);
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#include "EntityItemPropertiesMacros.h"
|
||||
|
||||
void HazePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_RANGE, Haze, haze, HazeRange, hazeRange);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_HAZE_COLOR, Haze, haze, HazeColor, hazeColor, u8vec3Color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_HAZE_GLARE_COLOR, Haze, haze, HazeGlareColor, hazeGlareColor, u8vec3Color);
|
||||
|
|
|
@ -80,7 +80,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const HazePropertyGroup& other);
|
||||
|
|
|
@ -28,7 +28,8 @@ const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_BIAS { 0.5f };
|
|||
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE { 40.0f };
|
||||
|
||||
void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color, u8vec3Color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const KeyLightPropertyGroup& other);
|
||||
|
|
|
@ -34,7 +34,8 @@ public:
|
|||
virtual ~PropertyGroup() = default;
|
||||
|
||||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const = 0;
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags, bool isMyOwnAvatarEntity) const = 0;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) = 0;
|
||||
virtual void debugDump() const { }
|
||||
virtual void listChangedProperties(QList<QString>& out) { }
|
||||
|
|
|
@ -60,8 +60,9 @@ void PulsePropertyGroup::setAlphaModeFromString(const QString& pulseMode) {
|
|||
}
|
||||
|
||||
void PulsePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_MIN, Pulse, pulse, Min, min);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_MAX, Pulse, pulse, Max, max);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_PERIOD, Pulse, pulse, Period, period);
|
||||
|
|
|
@ -44,7 +44,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const PulsePropertyGroup& other);
|
||||
|
|
|
@ -23,8 +23,9 @@ const float RingGizmoPropertyGroup::MIN_RADIUS = 0.0f;
|
|||
const float RingGizmoPropertyGroup::MAX_RADIUS = 0.5f;
|
||||
|
||||
void RingGizmoPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const {
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_START_ANGLE, Ring, ring, StartAngle, startAngle);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_END_ANGLE, Ring, ring, EndAngle, endAngle);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_INNER_RADIUS, Ring, ring, InnerRadius, innerRadius);
|
||||
|
|
|
@ -60,7 +60,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const RingGizmoPropertyGroup& other);
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
|
||||
const glm::u8vec3 SkyboxPropertyGroup::DEFAULT_COLOR = { 0, 0, 0 };
|
||||
|
||||
void SkyboxPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
||||
void SkyboxPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags, bool isMyOwnAvatarEntity) const {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color, u8vec3Color);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
|
||||
}
|
||||
|
||||
void SkyboxPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
|
||||
|
|
|
@ -43,7 +43,8 @@ public:
|
|||
// EntityItemProperty related helpers
|
||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||
ScriptEngine* engine, bool skipDefaults,
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const override;
|
||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||
bool isMyOwnAvatarEntity) const override;
|
||||
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||
|
||||
void merge(const SkyboxPropertyGroup& other);
|
||||
|
|
|
@ -100,8 +100,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
|||
(&::gpu::gl::GLBackend::do_glUniformMatrix3fv),
|
||||
(&::gpu::gl::GLBackend::do_glUniformMatrix4fv),
|
||||
|
||||
(&::gpu::gl::GLBackend::do_glColor4f),
|
||||
|
||||
(&::gpu::gl::GLBackend::do_pushProfileRange),
|
||||
(&::gpu::gl::GLBackend::do_popProfileRange),
|
||||
};
|
||||
|
@ -838,22 +836,6 @@ void GLBackend::do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) {
|
|||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) {
|
||||
|
||||
glm::vec4 newColor(
|
||||
batch._params[paramOffset + 3]._float,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
|
||||
if (_input._colorAttribute != newColor) {
|
||||
_input._colorAttribute = newColor;
|
||||
glVertexAttrib4fv(gpu::Stream::COLOR, &_input._colorAttribute.r);
|
||||
_input._hasColorAttribute = true;
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void GLBackend::releaseBuffer(GLuint id, Size size) const {
|
||||
Lock lock(_trashMutex);
|
||||
_currentFrameTrash.buffersTrash.push_back({ id, size });
|
||||
|
|
|
@ -241,8 +241,6 @@ public:
|
|||
virtual void do_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) final;
|
||||
virtual void do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) final;
|
||||
|
||||
virtual void do_glColor4f(const Batch& batch, size_t paramOffset) final;
|
||||
|
||||
// The State setters called by the GLState::Commands when a new state is assigned
|
||||
virtual void do_setStateFillMode(int32 mode) final;
|
||||
virtual void do_setStateCullMode(int32 mode) final;
|
||||
|
@ -350,8 +348,6 @@ protected:
|
|||
struct InputStageState {
|
||||
bool _invalidFormat { true };
|
||||
bool _lastUpdateStereoState { false };
|
||||
bool _hasColorAttribute { false };
|
||||
bool _hadColorAttribute { false };
|
||||
FormatReference _format { GPU_REFERENCE_INIT_VALUE };
|
||||
std::string _formatKey;
|
||||
|
||||
|
@ -368,8 +364,6 @@ protected:
|
|||
std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides;
|
||||
std::array<GLuint, MAX_NUM_INPUT_BUFFERS> _bufferVBOs;
|
||||
|
||||
glm::vec4 _colorAttribute { 1.0f };
|
||||
|
||||
BufferReference _indexBuffer;
|
||||
Offset _indexBufferOffset { 0 };
|
||||
Type _indexBufferType { UINT32 };
|
||||
|
|
|
@ -103,9 +103,6 @@ void GLBackend::resetInputStage() {
|
|||
reset(_input._format);
|
||||
_input._formatKey.clear();
|
||||
_input._invalidFormat = false;
|
||||
_input._hasColorAttribute = false;
|
||||
_input._hadColorAttribute = false;
|
||||
_input._colorAttribute = vec4(1.0f);
|
||||
_input._attributeActivation.reset();
|
||||
|
||||
for (uint32_t i = 0; i < _input._buffers.size(); i++) {
|
||||
|
@ -163,8 +160,6 @@ void GLBackend::updateInput() {
|
|||
#endif
|
||||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
bool hasColorAttribute = _input._hasColorAttribute;
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
|
@ -194,8 +189,6 @@ void GLBackend::updateInput() {
|
|||
|
||||
GLenum perLocationSize = attrib._element.getLocationSize();
|
||||
|
||||
hasColorAttribute |= slot == Stream::COLOR;
|
||||
|
||||
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
||||
GLuint attriNum = (GLuint)(slot + locNum);
|
||||
newActivation.set(attriNum);
|
||||
|
@ -226,12 +219,6 @@ void GLBackend::updateInput() {
|
|||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!hasColorAttribute && _input._hadColorAttribute) {
|
||||
// The previous input stage had a color attribute but this one doesn't, so reset the color to pure white.
|
||||
_input._colorAttribute = glm::vec4(1.0f);
|
||||
glVertexAttrib4fv(Stream::COLOR, &_input._colorAttribute.r);
|
||||
}
|
||||
}
|
||||
|
||||
// Manage Activation what was and what is expected now
|
||||
|
@ -253,9 +240,6 @@ void GLBackend::updateInput() {
|
|||
_stats._ISNumFormatChanges++;
|
||||
}
|
||||
|
||||
_input._hadColorAttribute = hasColorAttribute;
|
||||
_input._hasColorAttribute = false;
|
||||
|
||||
if (_input._invalidBuffers.any()) {
|
||||
auto vbo = _input._bufferVBOs.data();
|
||||
auto offset = _input._bufferOffsets.data();
|
||||
|
|
|
@ -33,8 +33,6 @@ void GL41Backend::updateInput() {
|
|||
#endif
|
||||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
bool hasColorAttribute = _input._hasColorAttribute;
|
||||
|
||||
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
||||
|
||||
auto format = acquire(_input._format);
|
||||
|
@ -110,8 +108,6 @@ void GL41Backend::updateInput() {
|
|||
uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]);
|
||||
GLboolean isNormalized = attrib._element.isNormalized();
|
||||
|
||||
hasColorAttribute |= slot == Stream::COLOR;
|
||||
|
||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||
if (attrib._element.isInteger()) {
|
||||
glVertexAttribIPointer(slot + (GLuint)locNum, count, type, stride,
|
||||
|
@ -131,17 +127,8 @@ void GL41Backend::updateInput() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasColorAttribute && _input._hadColorAttribute) {
|
||||
// The previous input stage had a color attribute but this one doesn't, so reset the color to pure white.
|
||||
_input._colorAttribute = glm::vec4(1.0f);
|
||||
glVertexAttrib4fv(Stream::COLOR, &_input._colorAttribute.r);
|
||||
}
|
||||
}
|
||||
// everything format related should be in sync now
|
||||
_input._invalidFormat = false;
|
||||
}
|
||||
|
||||
_input._hadColorAttribute = hasColorAttribute;
|
||||
_input._hasColorAttribute = false;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ void GL45Backend::updateInput() {
|
|||
#endif
|
||||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
bool hasColorAttribute = _input._hasColorAttribute;
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
|
@ -66,8 +64,6 @@ void GL45Backend::updateInput() {
|
|||
|
||||
GLenum perLocationSize = attrib._element.getLocationSize();
|
||||
|
||||
hasColorAttribute |= slot == Stream::COLOR;
|
||||
|
||||
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
||||
GLuint attriNum = (GLuint)(slot + locNum);
|
||||
newActivation.set(attriNum);
|
||||
|
@ -98,12 +94,6 @@ void GL45Backend::updateInput() {
|
|||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!hasColorAttribute && _input._hadColorAttribute) {
|
||||
// The previous input stage had a color attribute but this one doesn't, so reset the color to pure white.
|
||||
_input._colorAttribute = glm::vec4(1.0f);
|
||||
glVertexAttrib4fv(Stream::COLOR, &_input._colorAttribute.r);
|
||||
}
|
||||
}
|
||||
|
||||
// Manage Activation what was and what is expected now
|
||||
|
@ -125,9 +115,6 @@ void GL45Backend::updateInput() {
|
|||
_stats._ISNumFormatChanges++;
|
||||
}
|
||||
|
||||
_input._hadColorAttribute = hasColorAttribute;
|
||||
_input._hasColorAttribute = false;
|
||||
|
||||
if (_input._invalidBuffers.any()) {
|
||||
auto vbo = _input._bufferVBOs.data();
|
||||
auto offset = _input._bufferOffsets.data();
|
||||
|
|
|
@ -687,15 +687,6 @@ void Batch::_glUniformMatrix4fv(int32 location, int count, uint8 transpose, cons
|
|||
_params.emplace_back(location);
|
||||
}
|
||||
|
||||
void Batch::_glColor4f(float red, float green, float blue, float alpha) {
|
||||
ADD_COMMAND(glColor4f);
|
||||
|
||||
_params.emplace_back(alpha);
|
||||
_params.emplace_back(blue);
|
||||
_params.emplace_back(green);
|
||||
_params.emplace_back(red);
|
||||
}
|
||||
|
||||
void Batch::finishFrame(BufferUpdates& updates) {
|
||||
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ class QDebug;
|
|||
#define BATCH_PREALLOCATE_MIN 128
|
||||
namespace gpu {
|
||||
|
||||
// The named batch data provides a mechanism for accumulating data into buffers over the course
|
||||
// of many independent calls. For instance, two objects in the scene might both want to render
|
||||
// The named batch data provides a mechanism for accumulating data into buffers over the course
|
||||
// of many independent calls. For instance, two objects in the scene might both want to render
|
||||
// a simple box, but are otherwise unaware of each other. The common code that they call to render
|
||||
// the box can create buffers to store the rendering parameters for each box and register a function
|
||||
// that will be called with the accumulated buffer data when the batch commands are finally
|
||||
// the box can create buffers to store the rendering parameters for each box and register a function
|
||||
// that will be called with the accumulated buffer data when the batch commands are finally
|
||||
// executed against the backend
|
||||
|
||||
|
||||
|
@ -100,15 +100,15 @@ public:
|
|||
void clear();
|
||||
|
||||
// Batches may need to override the context level stereo settings
|
||||
// if they're performing framebuffer copy operations, like the
|
||||
// if they're performing framebuffer copy operations, like the
|
||||
// deferred lighting resolution mechanism
|
||||
void enableStereo(bool enable = true);
|
||||
bool isStereoEnabled() const;
|
||||
|
||||
// Stereo batches will pre-translate the view matrix, but this isn't
|
||||
// appropriate for skyboxes or other things intended to be drawn at
|
||||
// infinite distance, so provide a mechanism to render in stereo
|
||||
// without the pre-translation of the view.
|
||||
// Stereo batches will pre-translate the view matrix, but this isn't
|
||||
// appropriate for skyboxes or other things intended to be drawn at
|
||||
// infinite distance, so provide a mechanism to render in stereo
|
||||
// without the pre-translation of the view.
|
||||
void enableSkybox(bool enable = true);
|
||||
bool isSkyboxEnabled() const;
|
||||
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
// Indirect buffer is used by the multiDrawXXXIndirect calls
|
||||
// The indirect buffer contains the command descriptions to execute multiple drawcalls in a single call
|
||||
void setIndirectBuffer(const BufferPointer& buffer, Offset offset = 0, Offset stride = 0);
|
||||
|
||||
|
||||
// multi command desctription for multiDrawIndexedIndirect
|
||||
class DrawIndirectCommand {
|
||||
public:
|
||||
|
@ -248,7 +248,7 @@ public:
|
|||
void popProfileRange();
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
// For now, instead of calling the raw gl Call, use the equivalent call on the batch so the call is beeing recorded
|
||||
// THe implementation of these functions is in GLBackend.cpp
|
||||
|
@ -287,8 +287,6 @@ public:
|
|||
_glUniformMatrix3fv(location, 1, false, glm::value_ptr(v));
|
||||
}
|
||||
|
||||
void _glColor4f(float red, float green, float blue, float alpha);
|
||||
|
||||
// Maybe useful but shoudln't be public. Please convince me otherwise
|
||||
// Well porting to gles i need it...
|
||||
void runLambda(std::function<void()> f);
|
||||
|
@ -350,7 +348,7 @@ public:
|
|||
COMMAND_stopNamedCall,
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
COMMAND_glUniform1i,
|
||||
COMMAND_glUniform1f,
|
||||
|
@ -363,8 +361,6 @@ public:
|
|||
COMMAND_glUniformMatrix3fv,
|
||||
COMMAND_glUniformMatrix4fv,
|
||||
|
||||
COMMAND_glColor4f,
|
||||
|
||||
COMMAND_pushProfileRange,
|
||||
COMMAND_popProfileRange,
|
||||
|
||||
|
@ -381,7 +377,7 @@ public:
|
|||
union {
|
||||
#if (QT_POINTER_SIZE == 8)
|
||||
size_t _size;
|
||||
#endif
|
||||
#endif
|
||||
int32 _int;
|
||||
uint32 _uint;
|
||||
float _float;
|
||||
|
@ -389,7 +385,7 @@ public:
|
|||
};
|
||||
#if (QT_POINTER_SIZE == 8)
|
||||
Param(size_t val) : _size(val) {}
|
||||
#endif
|
||||
#endif
|
||||
Param(int32 val) : _int(val) {}
|
||||
Param(uint32 val) : _uint(val) {}
|
||||
Param(float val) : _float(val) {}
|
||||
|
@ -406,7 +402,7 @@ public:
|
|||
public:
|
||||
typedef T Data;
|
||||
Data _data;
|
||||
Cache<T>(const Data& data) : _data(data) {}
|
||||
Cache(const Data& data) : _data(data) {}
|
||||
static size_t _max;
|
||||
|
||||
class Vector {
|
||||
|
@ -573,7 +569,7 @@ private:
|
|||
|
||||
#else
|
||||
|
||||
#define PROFILE_RANGE_BATCH(batch, name)
|
||||
#define PROFILE_RANGE_BATCH(batch, name)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
Size getNumTypedElements() const { return getSize() / sizeof(T); };
|
||||
|
||||
const Byte* getData() const { return getSysmem().readData(); }
|
||||
|
||||
|
||||
// Resize the buffer
|
||||
// Keep previous data [0 to min(pSize, mSize)]
|
||||
Size resize(Size pSize);
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
// \return the number of bytes copied
|
||||
Size append(Size size, const Byte* data);
|
||||
|
||||
template <typename T>
|
||||
template <typename T>
|
||||
Size append(const T& t) {
|
||||
return append(sizeof(t), reinterpret_cast<const Byte*>(&t));
|
||||
}
|
||||
|
@ -110,10 +110,10 @@ public:
|
|||
|
||||
|
||||
const GPUObjectPointer gpuObject {};
|
||||
|
||||
|
||||
// Access the sysmem object, limited to ourselves and GPUObject derived classes
|
||||
const Sysmem& getSysmem() const { return _sysmem; }
|
||||
|
||||
|
||||
bool isDirty() const {
|
||||
return _pages(PageManager::DIRTY);
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ protected:
|
|||
// For use by the render thread to avoid the intermediate step of getUpdate/applyUpdate
|
||||
void flush() const;
|
||||
|
||||
// FIXME don't maintain a second buffer continuously. We should be able to apply updates
|
||||
// FIXME don't maintain a second buffer continuously. We should be able to apply updates
|
||||
// directly to the GL object and discard _renderSysmem and _renderPages
|
||||
mutable PageManager _renderPages;
|
||||
mutable Sysmem _renderSysmem;
|
||||
|
@ -292,7 +292,7 @@ public:
|
|||
// Direct memory access to the buffer contents is incompatible with the paging memory scheme
|
||||
template <typename T> Iterator<T> begin() { return Iterator<T>(&edit<T>(0), _stride); }
|
||||
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
|
||||
#else
|
||||
#else
|
||||
template <typename T> Iterator<const T> begin() const { return Iterator<const T>(&get<T>(), _stride); }
|
||||
template <typename T> Iterator<const T> end() const {
|
||||
// reimplement get<T> without bounds checking
|
||||
|
@ -378,7 +378,7 @@ public:
|
|||
return *(reinterpret_cast<T*> (_buffer->editData() + elementOffset));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class T> class StructBuffer : public gpu::BufferView {
|
||||
public:
|
||||
|
@ -387,8 +387,8 @@ public:
|
|||
U t;
|
||||
return std::make_shared<gpu::Buffer>(sizeof(U), (const gpu::Byte*) &t, sizeof(U));
|
||||
}
|
||||
~StructBuffer<T>() {};
|
||||
StructBuffer<T>() : gpu::BufferView(makeBuffer<T>()) {}
|
||||
~StructBuffer() {};
|
||||
StructBuffer() : gpu::BufferView(makeBuffer<T>()) {}
|
||||
|
||||
|
||||
T& edit() {
|
||||
|
|
|
@ -238,10 +238,14 @@ const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const
|
|||
Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const StereoState& _stereo, const Transform& xformView, Vec2 normalizedJitter) const {
|
||||
TransformCamera result = *this;
|
||||
Transform offsetTransform = xformView;
|
||||
if (!_stereo._skybox) {
|
||||
offsetTransform.postTranslate(-Vec3(_stereo._eyeViews[eye][3]));
|
||||
glm::vec3 eyePosition = extractTranslation(_stereo._eyeViews[eye]);
|
||||
glm::quat eyeOrientation = glmExtractRotation(_stereo._eyeViews[eye]);
|
||||
if (!_stereo._skybox)
|
||||
{
|
||||
offsetTransform.postRotate(eyeOrientation).postTranslate(eyePosition);
|
||||
} else {
|
||||
// FIXME: If "skybox" the ipd is set to 0 for now, let s try to propose a better solution for this in the future
|
||||
offsetTransform.postRotate(eyeOrientation);
|
||||
}
|
||||
result._projection = _stereo._eyeProjections[eye];
|
||||
normalizedJitter.x *= 2.0f;
|
||||
|
|
|
@ -201,8 +201,6 @@ constexpr const char* COMMAND_NAMES[] = {
|
|||
"glUniformMatrix3fv",
|
||||
"glUniformMatrix4fv",
|
||||
|
||||
"glColor4f",
|
||||
|
||||
"pushProfileRange",
|
||||
"popProfileRange",
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue