mirror of
https://github.com/lubosz/overte.git
synced 2025-07-24 18:54:11 +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 2013-2019 High Fidelity, Inc.
|
||||||
# Copyright 2020-2022 Vircadia contributors.
|
# Copyright 2020-2022 Vircadia contributors.
|
||||||
# Copyright 2021-2023 Overte e.V.
|
# Copyright 2021-2024 Overte e.V.
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
name: Linux Server CI Build
|
name: Linux Server CI Build
|
||||||
|
@ -65,6 +65,16 @@ jobs:
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
runner: linux_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
|
- os: fedora-38
|
||||||
image: docker.io/overte/overte-server-build:0.1.3-fedora-38-amd64
|
image: docker.io/overte/overte-server-build:0.1.3-fedora-38-amd64
|
||||||
arch: amd64
|
arch: amd64
|
||||||
|
@ -75,15 +85,16 @@ jobs:
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
runner: linux_aarch64
|
runner: linux_aarch64
|
||||||
|
|
||||||
- os: fedora-39
|
# Packaging broken; See: https://github.com/overte-org/overte/issues/968
|
||||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-39-amd64
|
#~ - os: fedora-39
|
||||||
arch: amd64
|
#~ image: docker.io/overte/overte-server-build:0.1.4-fedora-39-amd64
|
||||||
runner: linux_amd64
|
#~ arch: amd64
|
||||||
|
#~ runner: linux_amd64
|
||||||
|
|
||||||
- os: fedora-39
|
#~ - os: fedora-39
|
||||||
image: docker.io/overte/overte-server-build:0.1.4-fedora-39-aarch64
|
#~ image: docker.io/overte/overte-server-build:0.1.4-fedora-39-aarch64
|
||||||
arch: aarch64
|
#~ arch: aarch64
|
||||||
runner: linux_aarch64
|
#~ runner: linux_aarch64
|
||||||
|
|
||||||
- os: rockylinux-9
|
- os: rockylinux-9
|
||||||
image: docker.io/overte/overte-server-build:0.1.3-rockylinux-9-amd64
|
image: docker.io/overte/overte-server-build:0.1.3-rockylinux-9-amd64
|
||||||
|
|
|
@ -184,9 +184,14 @@ if(OVERTE_WARNINGS_WHITELIST)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(OVERTE_WARNINGS_AS_ERRORS)
|
if(OVERTE_WARNINGS_AS_ERRORS)
|
||||||
|
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{CXXFLAGS} "$ENV{CXXFLAGS} -Werror")
|
||||||
set(ENV{CFLAGS} "$ENV{CXXFLAGS} -Werror")
|
set(ENV{CFLAGS} "$ENV{CXXFLAGS} -Werror")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if (HIFI_ANDROID)
|
if (HIFI_ANDROID)
|
||||||
|
@ -252,9 +257,6 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SCREENSHARE 0)
|
set(SCREENSHARE 0)
|
||||||
if (WIN32)
|
|
||||||
set(SCREENSHARE 1)
|
|
||||||
endif()
|
|
||||||
if (APPLE AND NOT CLIENT_ONLY)
|
if (APPLE AND NOT CLIENT_ONLY)
|
||||||
# Don't include Screenshare in OSX client-only builds.
|
# Don't include Screenshare in OSX client-only builds.
|
||||||
set(SCREENSHARE 1)
|
set(SCREENSHARE 1)
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class PermissionChecker extends Activity {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
try {
|
try {
|
||||||
obj.put("firstRun",false);
|
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);
|
File directory = new File(pathForJson);
|
||||||
|
|
||||||
if(!directory.exists()) directory.mkdirs();
|
if(!directory.exists()) directory.mkdirs();
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
*/
|
*/
|
||||||
class AgentScriptingInterface : public QObject {
|
class AgentScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
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 isPlayingAvatarSound READ isPlayingAvatarSound)
|
||||||
Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream)
|
Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream)
|
||||||
Q_PROPERTY(bool isNoiseGateEnabled READ isNoiseGateEnabled WRITE setIsNoiseGateEnabled)
|
Q_PROPERTY(bool isNoiseGateEnabled READ isNoiseGateEnabled WRITE setIsNoiseGateEnabled)
|
||||||
|
@ -77,15 +77,15 @@ public slots:
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* Checks whether the script is emulating an avatar.
|
* 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>.
|
* @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>
|
* @example <caption>Check whether the agent is emulating an avatar.</caption>
|
||||||
* (function () {
|
* (function () {
|
||||||
* print("Agent is avatar: " + Agent.isAvatar());
|
* print("Agent is avatar: " + Agent.getIsAvatar());
|
||||||
* print("Agent is avatar: " + Agent.isAvatar); // Same result.
|
* print("Agent is avatar: " + Agent.isAvatar); // Same result.
|
||||||
* }());
|
* }());
|
||||||
*/
|
*/
|
||||||
bool isAvatar() const { return _agent->isAvatar(); }
|
bool getIsAvatar() const { return _agent->isAvatar(); }
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* Plays a sound from the position and with the orientation of the emulated avatar's head. No sound is played unless
|
* 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>
|
#include <NetworkingConstants.h>
|
||||||
|
|
||||||
|
|
||||||
ScriptableAvatar::ScriptableAvatar(): _scriptEngine(newScriptEngine()) {
|
ScriptableAvatar::ScriptableAvatar() {
|
||||||
_clientTraitsHandler.reset(new ClientTraitsHandler(this));
|
_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) {
|
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);
|
_animation = DependencyManager::get<AnimationCache>()->getAnimation(url);
|
||||||
_animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame, false);
|
_animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame, false);
|
||||||
_maskedJoints = maskedJoints;
|
_maskedJoints = maskedJoints;
|
||||||
|
_isAnimationRigValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptableAvatar::stopAnimation() {
|
void ScriptableAvatar::stopAnimation() {
|
||||||
|
@ -89,11 +94,12 @@ QStringList ScriptableAvatar::getJointNames() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
_bind.reset();
|
_avatarAnimSkeleton.reset();
|
||||||
_animSkeleton.reset();
|
_geometryResource.reset();
|
||||||
|
|
||||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||||
updateJointMappings();
|
updateJointMappings();
|
||||||
|
_isRigValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ScriptableAvatar::sendAvatarDataPacket(bool sendAll) {
|
int ScriptableAvatar::sendAvatarDataPacket(bool sendAll) {
|
||||||
|
@ -137,10 +143,26 @@ static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptableAvatar::update(float deltatime) {
|
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
|
// Run animation
|
||||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
|
Q_ASSERT(QThread::currentThread() == thread());
|
||||||
if (!_animSkeleton) {
|
if (_animation && _animation->isLoaded()) {
|
||||||
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getHFMModel());
|
Q_ASSERT(thread() == _animation->thread());
|
||||||
|
auto frames = _animation->getFramesReference();
|
||||||
|
if (frames.size() > 0 && _geometryResource && _geometryResource->isHFMModelLoaded()) {
|
||||||
|
if (!_isRigValid) {
|
||||||
|
_rig.reset(_geometryResource->getHFMModel());
|
||||||
|
_isRigValid = true;
|
||||||
|
}
|
||||||
|
if (!_isAnimationRigValid) {
|
||||||
|
_animationRig.reset(_animation->getHFMModel());
|
||||||
|
_isAnimationRigValid = true;
|
||||||
|
}
|
||||||
|
if (!_avatarAnimSkeleton) {
|
||||||
|
_avatarAnimSkeleton = std::make_shared<AnimSkeleton>(_geometryResource->getHFMModel());
|
||||||
}
|
}
|
||||||
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
||||||
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
||||||
|
@ -149,7 +171,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
}
|
}
|
||||||
_animationDetails.currentFrame = currentFrame;
|
_animationDetails.currentFrame = currentFrame;
|
||||||
|
|
||||||
const QVector<HFMJoint>& modelJoints = _bind->getHFMModel().joints;
|
const QVector<HFMJoint>& modelJoints = _geometryResource->getHFMModel().joints;
|
||||||
QStringList animationJointNames = _animation->getJointNames();
|
QStringList animationJointNames = _animation->getJointNames();
|
||||||
|
|
||||||
const int nJoints = modelJoints.size();
|
const int nJoints = modelJoints.size();
|
||||||
|
@ -157,29 +179,34 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
_jointData.resize(nJoints);
|
_jointData.resize(nJoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int frameCount = _animation->getFrames().size();
|
const int frameCount = frames.size();
|
||||||
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
const HFMAnimationFrame& floorFrame = frames.at((int)glm::floor(currentFrame) % frameCount);
|
||||||
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
const HFMAnimationFrame& ceilFrame = frames.at((int)glm::ceil(currentFrame) % frameCount);
|
||||||
const float frameFraction = glm::fract(currentFrame);
|
const float frameFraction = glm::fract(currentFrame);
|
||||||
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
std::vector<AnimPose> poses = _avatarAnimSkeleton->getRelativeDefaultPoses();
|
||||||
|
|
||||||
const float UNIT_SCALE = 0.01f;
|
// 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++) {
|
for (int i = 0; i < animationJointNames.size(); i++) {
|
||||||
const QString& name = animationJointNames[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
|
// 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).
|
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
||||||
int mapping = _bind->getHFMModel().getJointIndex(name);
|
int mapping = _geometryResource->getHFMModel().getJointIndex(name);
|
||||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||||
|
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i],
|
||||||
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);
|
floorFrame.translations[i] * UNIT_SCALE);
|
||||||
AnimPose ceilPose = composeAnimPose(modelJoints[mapping], ceilFrame.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]);
|
blend(1, &floorPose, &ceilPose, frameFraction, &poses[mapping]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AnimPose> absPoses = poses;
|
std::vector<AnimPose> absPoses = poses;
|
||||||
_animSkeleton->convertRelativePosesToAbsolute(absPoses);
|
Q_ASSERT(_avatarAnimSkeleton != nullptr);
|
||||||
|
_avatarAnimSkeleton->convertRelativePosesToAbsolute(absPoses);
|
||||||
for (int i = 0; i < nJoints; i++) {
|
for (int i = 0; i < nJoints; i++) {
|
||||||
JointData& data = _jointData[i];
|
JointData& data = _jointData[i];
|
||||||
AnimPose& absPose = absPoses[i];
|
AnimPose& absPose = absPoses[i];
|
||||||
|
@ -198,6 +225,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
_animation.clear();
|
_animation.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
quint64 dt = now - _lastSendAvatarDataTime;
|
quint64 dt = now - _lastSendAvatarDataTime;
|
||||||
|
@ -245,6 +273,7 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() {
|
||||||
networkReply->deleteLater();
|
networkReply->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// TODO: this works only with .fst files currently, not directly with FBX and GLB models
|
||||||
{
|
{
|
||||||
QWriteLocker writeLock(&_jointDataLock);
|
QWriteLocker writeLock(&_jointDataLock);
|
||||||
QByteArray line;
|
QByteArray line;
|
||||||
|
@ -253,7 +282,7 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() {
|
||||||
if (line.startsWith("filename")) {
|
if (line.startsWith("filename")) {
|
||||||
int filenameIndex = line.indexOf('=') + 1;
|
int filenameIndex = line.indexOf('=') + 1;
|
||||||
if (filenameIndex > 0) {
|
if (filenameIndex > 0) {
|
||||||
_skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed()));
|
_skeletonModelFilenameURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!line.startsWith("jointIndex")) {
|
if (!line.startsWith("jointIndex")) {
|
||||||
|
@ -315,7 +344,9 @@ AvatarEntityMap ScriptableAvatar::getAvatarEntityDataInternal(bool allProperties
|
||||||
EntityItemProperties properties = entity->getProperties(desiredProperties);
|
EntityItemProperties properties = entity->getProperties(desiredProperties);
|
||||||
|
|
||||||
QByteArray blob;
|
QByteArray blob;
|
||||||
EntityItemProperties::propertiesToBlob(*_scriptEngine, sessionID, properties, blob, allProperties);
|
_helperScriptEngine.run( [&] {
|
||||||
|
EntityItemProperties::propertiesToBlob(*_helperScriptEngine.get(), sessionID, properties, blob, allProperties);
|
||||||
|
});
|
||||||
data[id] = blob;
|
data[id] = blob;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -339,9 +370,13 @@ void ScriptableAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityDa
|
||||||
while (dataItr != avatarEntityData.end()) {
|
while (dataItr != avatarEntityData.end()) {
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
const QByteArray& blob = dataItr.value();
|
const QByteArray& blob = dataItr.value();
|
||||||
if (!blob.isNull() && EntityItemProperties::blobToProperties(*_scriptEngine, blob, properties)) {
|
if (!blob.isNull()) {
|
||||||
|
_helperScriptEngine.run([&] {
|
||||||
|
if (EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), blob, properties)) {
|
||||||
newProperties[dataItr.key()] = properties;
|
newProperties[dataItr.key()] = properties;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
++dataItr;
|
++dataItr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,10 +454,17 @@ void ScriptableAvatar::updateAvatarEntity(const QUuid& entityID, const QByteArra
|
||||||
|
|
||||||
EntityItemPointer entity;
|
EntityItemPointer entity;
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
if (!EntityItemProperties::blobToProperties(*_scriptEngine, entityData, properties)) {
|
{
|
||||||
|
// 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
|
// entityData is corrupt
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::map<QUuid, EntityItemPointer>::iterator itr = _entities.find(entityID);
|
std::map<QUuid, EntityItemPointer>::iterator itr = _entities.find(entityID);
|
||||||
if (itr == _entities.end()) {
|
if (itr == _entities.end()) {
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
#include <EntityItem.h>
|
#include <EntityItem.h>
|
||||||
|
#include "model-networking/ModelCache.h"
|
||||||
|
#include "Rig.h"
|
||||||
|
#include <HelperScriptEngine.h>
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* The <code>Avatar</code> API is used to manipulate scriptable avatars on the domain. This API is a subset of the
|
* 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;
|
AnimationPointer _animation;
|
||||||
AnimationDetails _animationDetails;
|
AnimationDetails _animationDetails;
|
||||||
QStringList _maskedJoints;
|
QStringList _maskedJoints;
|
||||||
AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies
|
GeometryResource::Pointer _geometryResource;
|
||||||
std::shared_ptr<AnimSkeleton> _animSkeleton;
|
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
|
QHash<QString, int> _fstJointIndices; ///< 1-based, since zero is returned for missing keys
|
||||||
QStringList _fstJointNames; ///< in order of depth-first traversal
|
QStringList _fstJointNames; ///< in order of depth-first traversal
|
||||||
QUrl _skeletonFBXURL;
|
QUrl _skeletonModelFilenameURL; // This contains URL from filename field in fst file
|
||||||
mutable ScriptEnginePointer _scriptEngine;
|
mutable HelperScriptEngine _helperScriptEngine;
|
||||||
std::map<QUuid, EntityItemPointer> _entities;
|
std::map<QUuid, EntityItemPointer> _entities;
|
||||||
|
|
||||||
/// Loads the joint indices, names from the FST file (if any)
|
/// Loads the joint indices, names from the FST file (if any)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Source: hifi-client-deps
|
Source: hifi-client-deps
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Description: Collected dependencies for High Fidelity applications
|
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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
set(NODE_VERSION 18.14.2)
|
set(NODE_VERSION 18.14.2)
|
||||||
|
@ -28,9 +28,9 @@ else ()
|
||||||
vcpkg_from_github(
|
vcpkg_from_github(
|
||||||
OUT_SOURCE_PATH SOURCE_PATH
|
OUT_SOURCE_PATH SOURCE_PATH
|
||||||
REPO nodejs/node
|
REPO nodejs/node
|
||||||
REF v18.16.1
|
REF v18.20.2
|
||||||
SHA512 cd2d7871a1a2aca8d800e0a501bd2836cbce076de750dcfc0b2bbe602c8a23705154bfb12faa3ff78e25ec753f419220742228569c281fa458987fb24f6d4d09
|
SHA512 10d3637c26274677d137f76bbb648d0e7851c994634a16c89858c3a13094a0692ea2cb9a787c6463c3001abd71dab0d83123127bc305171d097c48d21d691678
|
||||||
HEAD_REF v18.16.1
|
HEAD_REF v18.20.2
|
||||||
)
|
)
|
||||||
# node cannot configure out of source, which VCPKG expects. So we copy the source to the configure directory.
|
# 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}")
|
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": [
|
"settings": [
|
||||||
{
|
{
|
||||||
"name": "metaverse",
|
"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>",
|
"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": [
|
"columns": [
|
||||||
|
@ -479,6 +479,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id_can_view_asset_urls",
|
||||||
|
"label": "View Asset URLs",
|
||||||
|
"type": "checkbox",
|
||||||
|
"editable": true,
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"non-deletable-row-key": "permissions_id",
|
"non-deletable-row-key": "permissions_id",
|
||||||
|
@ -505,6 +512,7 @@
|
||||||
"id_can_rez_tmp": true,
|
"id_can_rez_tmp": true,
|
||||||
"id_can_write_to_asset_server": true,
|
"id_can_write_to_asset_server": true,
|
||||||
"id_can_get_and_set_private_user_data": true,
|
"id_can_get_and_set_private_user_data": true,
|
||||||
|
"id_can_view_asset_urls": true,
|
||||||
"permissions_id": "localhost"
|
"permissions_id": "localhost"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -633,6 +641,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id_can_view_asset_urls",
|
||||||
|
"label": "View Asset URLs",
|
||||||
|
"type": "checkbox",
|
||||||
|
"editable": true,
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -752,6 +767,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id_can_view_asset_urls",
|
||||||
|
"label": "View Asset URLs",
|
||||||
|
"type": "checkbox",
|
||||||
|
"editable": true,
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -844,6 +866,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id_can_view_asset_urls",
|
||||||
|
"label": "View Asset URLs",
|
||||||
|
"type": "checkbox",
|
||||||
|
"editable": true,
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -936,6 +965,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id_can_view_asset_urls",
|
||||||
|
"label": "View Asset URLs",
|
||||||
|
"type": "checkbox",
|
||||||
|
"editable": true,
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1028,6 +1064,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id_can_view_asset_urls",
|
||||||
|
"label": "View Asset URLs",
|
||||||
|
"type": "checkbox",
|
||||||
|
"editable": true,
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1120,6 +1163,13 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"default": false
|
"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::canReplaceDomainContent;
|
||||||
userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData;
|
userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData;
|
||||||
userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities;
|
userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities;
|
||||||
|
userPerms.permissions |= NodePermissions::Permission::canViewAssetURLs;
|
||||||
} else {
|
} else {
|
||||||
// at this point we don't have a sending socket for packets from this node - assume it is the active socket
|
// 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
|
// 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::canReplaceDomainContent;
|
||||||
userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData;
|
userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData;
|
||||||
userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities;
|
userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities;
|
||||||
|
userPerms.permissions |= NodePermissions::Permission::canViewAssetURLs;
|
||||||
newNode->setPermissions(userPerms);
|
newNode->setPermissions(userPerms);
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -547,6 +547,29 @@ void DomainServerSettingsManager::setupConfigMap(const QString& userConfigFilena
|
||||||
|
|
||||||
// No migration needed to version 2.6.
|
// 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
|
// write the current description version to our settings
|
||||||
*versionVariant = _descriptionVersion;
|
*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"
|
text: "Real-Time"
|
||||||
refreshRatePreset: 2 // RefreshRateProfile::REALTIME
|
refreshRatePreset: 2 // RefreshRateProfile::REALTIME
|
||||||
}
|
}
|
||||||
|
ListElement {
|
||||||
|
text: "Custom"
|
||||||
|
refreshRatePreset: 3 // RefreshRateProfile::CUSTOM
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControlsUit.ComboBox {
|
HifiControlsUit.ComboBox {
|
||||||
|
@ -362,13 +366,7 @@ Flickable {
|
||||||
currentIndex: -1
|
currentIndex: -1
|
||||||
|
|
||||||
function refreshRefreshRateDropdownDisplay() {
|
function refreshRefreshRateDropdownDisplay() {
|
||||||
if (Performance.getRefreshRateProfile() === 0) {
|
refreshRateDropdown.currentIndex = Performance.getRefreshRateProfile();
|
||||||
refreshRateDropdown.currentIndex = 0;
|
|
||||||
} else if (Performance.getRefreshRateProfile() === 1) {
|
|
||||||
refreshRateDropdown.currentIndex = 1;
|
|
||||||
} else {
|
|
||||||
refreshRateDropdown.currentIndex = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
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 {
|
Item {
|
||||||
Layout.preferredWidth: parent.width
|
Layout.preferredWidth: parent.width
|
||||||
Layout.preferredHeight: 35
|
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
|
// Created by Zach Fox on 2019-08-08
|
||||||
// Copyright 2019 High Fidelity, Inc.
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
// Copyright 2024 Overte e.V.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -78,7 +79,7 @@ Item {
|
||||||
temporaryText: "Viewing!"
|
temporaryText: "Viewing!"
|
||||||
|
|
||||||
onClicked: {
|
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
|
// Created by Zach Fox on 2019-08-20
|
||||||
// Copyright 2019 High Fidelity, Inc.
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
// Copyright 2024 Overte e.V.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -76,7 +77,7 @@ Item {
|
||||||
temporaryText: "Opening browser..."
|
temporaryText: "Opening browser..."
|
||||||
|
|
||||||
onClicked: {
|
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
|
// Created by Zach Fox on 2019-06-11
|
||||||
// Copyright 2019 High Fidelity, Inc.
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
// Copyright 2024 Overte e.V.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -93,9 +94,9 @@ Flickable {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 18
|
height: 18
|
||||||
labelTextOn: "Keep Old Menus (File, Edit, etc)"
|
labelTextOn: "Keep Old Menus (File, Edit, etc)"
|
||||||
checked: Settings.getValue("simplifiedUI/keepMenus", false);
|
checked: Settings.getValue("simplifiedUI/keepMenus", true);
|
||||||
onClicked: {
|
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
|
// Created by Zach Fox on 2019-05-06
|
||||||
// Copyright 2019 High Fidelity, Inc.
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
// Copyright 2024 Overte e.V.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// 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
|
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||||
|
|
||||||
SimplifiedControls.RadioButton {
|
SimplifiedControls.RadioButton {
|
||||||
id: performanceLow
|
id: performanceLowPower
|
||||||
text: "Low Power Quality" + (PlatformInfo.getTierProfiled() === PerformanceEnums.LOW_POWER ? " (Recommended)" : "")
|
text: "Low Power Quality" + (PlatformInfo.getTierProfiled() === PerformanceEnums.LOW_POWER ? " (Recommended)" : "")
|
||||||
checked: Performance.getPerformancePreset() === PerformanceEnums.LOW_POWER
|
checked: Performance.getPerformancePreset() === PerformanceEnums.LOW_POWER
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
//
|
//
|
||||||
// Created by Zach Fox on 2019-05-08
|
// Created by Zach Fox on 2019-05-08
|
||||||
// Copyright 2019 High Fidelity, Inc.
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
// Copyright 2024 Overte e.V.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// 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
|
id: buttonText
|
||||||
//topPadding: -2 // Necessary for proper alignment using Graphik Medium
|
//topPadding: -2 // Necessary for proper alignment using Graphik Medium
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
color: enabled ? simplifiedUI.colors.controls.button.text.enabled : simplifiedUI.colors.controls.button.text.disabled
|
color: enabled ? simplifiedUI.colors.controls.button.text.enabled : simplifiedUI.colors.controls.button.text.disabled
|
||||||
size: simplifiedUI.sizes.controls.button.textSize
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: root.text
|
text: root.text
|
||||||
|
|
|
@ -27,7 +27,7 @@ Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
property string title: "Controls"
|
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 }
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
|
|
|
@ -3305,7 +3305,7 @@ void Application::initializeUi() {
|
||||||
|
|
||||||
// END PULL SAFEURLS FROM INTERFACE.JSON Settings
|
// END PULL SAFEURLS FROM INTERFACE.JSON Settings
|
||||||
|
|
||||||
if (AUTHORIZED_EXTERNAL_QML_SOURCE.isParentOf(url)) {
|
if (QUrl(NetworkingConstants::OVERTE_COMMUNITY_APPLICATIONS).isParentOf(url)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
for (const auto& str : safeURLS) {
|
for (const auto& str : safeURLS) {
|
||||||
|
@ -6942,16 +6942,13 @@ void Application::updateRenderArgs(float deltaTime) {
|
||||||
appRenderArgs._eyeToWorld = _myCamera.getTransform();
|
appRenderArgs._eyeToWorld = _myCamera.getTransform();
|
||||||
appRenderArgs._isStereo = false;
|
appRenderArgs._isStereo = false;
|
||||||
|
|
||||||
{
|
if (getActiveDisplayPlugin()->isStereo()) {
|
||||||
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
||||||
float ipdScale = hmdInterface->getIPDScale();
|
|
||||||
|
|
||||||
// scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly.
|
// 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();
|
auto baseProjection = appRenderArgs._renderArgs.getViewFrustum().getProjection();
|
||||||
|
|
||||||
if (getActiveDisplayPlugin()->isStereo()) {
|
|
||||||
// Stereo modes will typically have a larger projection matrix overall,
|
// Stereo modes will typically have a larger projection matrix overall,
|
||||||
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
||||||
// plugins will imply the combined projection for both eyes.
|
// plugins will imply the combined projection for both eyes.
|
||||||
|
@ -6971,23 +6968,15 @@ void Application::updateRenderArgs(float deltaTime) {
|
||||||
// only when the display plugin changes (or in non-HMD modes when the user
|
// 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.
|
// changes the FOV manually, which right now I don't think they can.
|
||||||
for_each_eye([&](Eye eye) {
|
for_each_eye([&](Eye eye) {
|
||||||
// For providing the stereo eye views, the HMD head pose has already been
|
eyeOffsets[eye] = getActiveDisplayPlugin()->getEyeToHeadTransform(eye);
|
||||||
// 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
|
// Apply IPD scaling
|
||||||
mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale);
|
eyeOffsets[eye][3][0] *= ipdScale;
|
||||||
eyeOffsets[eye] = eyeOffsetTransform;
|
|
||||||
eyeProjections[eye] = getActiveDisplayPlugin()->getEyeProjection(eye, baseProjection);
|
eyeProjections[eye] = getActiveDisplayPlugin()->getEyeProjection(eye, baseProjection);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure the type of display / stereo
|
// Configure the type of display / stereo
|
||||||
appRenderArgs._renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
|
appRenderArgs._renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
appRenderArgs._renderArgs._stencilMaskMode = getActiveDisplayPlugin()->getStencilMaskMode();
|
appRenderArgs._renderArgs._stencilMaskMode = getActiveDisplayPlugin()->getStencilMaskMode();
|
||||||
if (appRenderArgs._renderArgs._stencilMaskMode == StencilMaskMode::MESH) {
|
if (appRenderArgs._renderArgs._stencilMaskMode == StencilMaskMode::MESH) {
|
||||||
|
|
|
@ -41,6 +41,15 @@
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "WarningsSuppression.h"
|
#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) {
|
void addAvatarEntities(const QVariantList& avatarEntities) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
@ -123,6 +132,12 @@ AvatarBookmarks::AvatarBookmarks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::addBookmark(const QString& bookmarkName) {
|
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()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
BLOCKING_INVOKE_METHOD(this, "addBookmark", Q_ARG(QString, bookmarkName));
|
BLOCKING_INVOKE_METHOD(this, "addBookmark", Q_ARG(QString, bookmarkName));
|
||||||
return;
|
return;
|
||||||
|
@ -134,6 +149,12 @@ void AvatarBookmarks::addBookmark(const QString& bookmarkName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::saveBookmark(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()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
BLOCKING_INVOKE_METHOD(this, "saveBookmark", Q_ARG(QString, bookmarkName));
|
BLOCKING_INVOKE_METHOD(this, "saveBookmark", Q_ARG(QString, bookmarkName));
|
||||||
return;
|
return;
|
||||||
|
@ -145,6 +166,12 @@ void AvatarBookmarks::saveBookmark(const QString& bookmarkName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::removeBookmark(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()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
BLOCKING_INVOKE_METHOD(this, "removeBookmark", Q_ARG(QString, bookmarkName));
|
BLOCKING_INVOKE_METHOD(this, "removeBookmark", Q_ARG(QString, bookmarkName));
|
||||||
return;
|
return;
|
||||||
|
@ -200,6 +227,12 @@ void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
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()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
BLOCKING_INVOKE_METHOD(this, "loadBookmark", Q_ARG(QString, bookmarkName));
|
BLOCKING_INVOKE_METHOD(this, "loadBookmark", Q_ARG(QString, bookmarkName));
|
||||||
return;
|
return;
|
||||||
|
@ -268,6 +301,15 @@ void AvatarBookmarks::readFromFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap AvatarBookmarks::getBookmark(const QString &bookmarkName)
|
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()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVariantMap result;
|
QVariantMap result;
|
||||||
|
|
|
@ -100,7 +100,7 @@ public slots:
|
||||||
* print("- " + key + " " + bookmarks[key].avatarUrl);
|
* print("- " + key + " " + bookmarks[key].avatarUrl);
|
||||||
* };
|
* };
|
||||||
*/
|
*/
|
||||||
QVariantMap getBookmarks() { return _bookmarks; }
|
QVariantMap getBookmarks();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
|
@ -147,6 +147,11 @@ protected slots:
|
||||||
void deleteBookmark() override;
|
void deleteBookmark() override;
|
||||||
|
|
||||||
private:
|
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 AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||||
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||||
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
||||||
|
|
|
@ -258,10 +258,11 @@ void CrashRecoveryHandler::handleCrash(CrashRecoveryHandler::Action action) {
|
||||||
// Display name and avatar
|
// Display name and avatar
|
||||||
settings.beginGroup(AVATAR_GROUP);
|
settings.beginGroup(AVATAR_GROUP);
|
||||||
displayName = settings.value(DISPLAY_NAME_KEY).toString();
|
displayName = settings.value(DISPLAY_NAME_KEY).toString();
|
||||||
fullAvatarURL = settings.value(FULL_AVATAR_URL_KEY).toUrl();
|
|
||||||
fullAvatarModelName = settings.value(FULL_AVATAR_MODEL_NAME_KEY).toString();
|
fullAvatarModelName = settings.value(FULL_AVATAR_MODEL_NAME_KEY).toString();
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
|
fullAvatarURL = settings.value(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/" + AVATAR_GROUP + "/" + FULL_AVATAR_URL_KEY).toUrl();
|
||||||
|
|
||||||
// Tutorial complete
|
// Tutorial complete
|
||||||
tutorialComplete = settings.value(TUTORIAL_COMPLETE_FLAG_KEY).toBool();
|
tutorialComplete = settings.value(TUTORIAL_COMPLETE_FLAG_KEY).toBool();
|
||||||
}
|
}
|
||||||
|
@ -280,12 +281,12 @@ void CrashRecoveryHandler::handleCrash(CrashRecoveryHandler::Action action) {
|
||||||
// Display name and avatar
|
// Display name and avatar
|
||||||
settings.beginGroup(AVATAR_GROUP);
|
settings.beginGroup(AVATAR_GROUP);
|
||||||
settings.setValue(DISPLAY_NAME_KEY, displayName);
|
settings.setValue(DISPLAY_NAME_KEY, displayName);
|
||||||
settings.setValue(FULL_AVATAR_URL_KEY, fullAvatarURL);
|
|
||||||
settings.setValue(FULL_AVATAR_MODEL_NAME_KEY, fullAvatarModelName);
|
settings.setValue(FULL_AVATAR_MODEL_NAME_KEY, fullAvatarModelName);
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
|
settings.setValue(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/" + AVATAR_GROUP + "/" + FULL_AVATAR_URL_KEY, fullAvatarURL);
|
||||||
|
|
||||||
// Tutorial complete
|
// Tutorial complete
|
||||||
settings.setValue(TUTORIAL_COMPLETE_FLAG_KEY, tutorialComplete);
|
settings.setValue(TUTORIAL_COMPLETE_FLAG_KEY, tutorialComplete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ void LODManager::setRenderTimes(float presentTime, float engineRunTime, float ba
|
||||||
}
|
}
|
||||||
|
|
||||||
void LODManager::autoAdjustLOD(float realTimeDelta) {
|
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:
|
// The "render time" is the worse of:
|
||||||
// - engineRunTime: Time spent in the render thread in the engine producing the gpu::Frame N
|
// - engineRunTime: Time spent in the render thread in the engine producing the gpu::Frame N
|
||||||
|
@ -300,7 +300,7 @@ void LODManager::resetLODAdjust() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LODManager::setAutomaticLODAdjust(bool value) {
|
void LODManager::setAutomaticLODAdjust(bool value) {
|
||||||
std::lock_guard<std::mutex> { _automaticLODLock };
|
std::lock_guard<std::mutex> lock{ _automaticLODLock };
|
||||||
_automaticLODAdjust = value;
|
_automaticLODAdjust = value;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
emit autoLODChanged();
|
emit autoLODChanged();
|
||||||
|
|
|
@ -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
|
// Settings > Developer Menu
|
||||||
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
||||||
|
|
||||||
|
|
|
@ -190,6 +190,7 @@ namespace MenuOption {
|
||||||
const QString RunTimingTests = "Run Timing Tests";
|
const QString RunTimingTests = "Run Timing Tests";
|
||||||
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
|
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
|
||||||
const QString EntityScriptQMLWhitelist = "Entity Script / QML Whitelist";
|
const QString EntityScriptQMLWhitelist = "Entity Script / QML Whitelist";
|
||||||
|
const QString ScriptSecurity = "Script Security";
|
||||||
const QString ShowTrackedObjects = "Show Tracked Objects";
|
const QString ShowTrackedObjects = "Show Tracked Objects";
|
||||||
const QString SelfieCamera = "Selfie";
|
const QString SelfieCamera = "Selfie";
|
||||||
const QString SendWrongDSConnectVersion = "Send wrong DS connect version";
|
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
|
* <tr><td><code>"Interactive"</code></td><td>Medium refresh rate, which is reduced when Interface doesn't have focus or is
|
||||||
* minimized.</td></tr>
|
* 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>"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>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
* @typedef {string} RefreshRateProfileName
|
* @typedef {string} RefreshRateProfileName
|
||||||
*/
|
*/
|
||||||
static const std::array<std::string, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILE_TO_STRING =
|
static const std::array<std::string, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILE_TO_STRING =
|
||||||
{ { "Eco", "Interactive", "Realtime" } };
|
{ { "Eco", "Interactive", "Realtime", "Custom" } };
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* <p>Interface states that affect the refresh rate.</p>
|
* <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 =
|
static const std::map<std::string, RefreshRateManager::RefreshRateProfile> REFRESH_RATE_PROFILE_FROM_STRING =
|
||||||
{ { "Eco", RefreshRateManager::RefreshRateProfile::ECO },
|
{ { "Eco", RefreshRateManager::RefreshRateProfile::ECO },
|
||||||
{ "Interactive", RefreshRateManager::RefreshRateProfile::INTERACTIVE },
|
{ "Interactive", RefreshRateManager::RefreshRateProfile::INTERACTIVE },
|
||||||
{ "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME } };
|
{ "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME },
|
||||||
|
{ "Custom", RefreshRateManager::RefreshRateProfile::CUSTOM } };
|
||||||
|
|
||||||
|
|
||||||
// Porfile regimes are:
|
// Porfile regimes are:
|
||||||
|
@ -109,8 +111,10 @@ static const std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM>
|
||||||
static const std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM> REALTIME_PROFILE =
|
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 =
|
static const std::array<int, RefreshRateManager::RefreshRateRegime::REGIME_NUM> CUSTOM_PROFILE = REALTIME_PROFILE; // derived from settings and modified by scripts below
|
||||||
{ { ECO_PROFILE, INTERACTIVE_PROFILE, REALTIME_PROFILE } };
|
|
||||||
|
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;
|
static const int INACTIVE_TIMER_LIMIT = 3000;
|
||||||
|
@ -134,6 +138,10 @@ std::string RefreshRateManager::uxModeToString(RefreshRateManager::RefreshRateMa
|
||||||
|
|
||||||
RefreshRateManager::RefreshRateManager() {
|
RefreshRateManager::RefreshRateManager() {
|
||||||
_refreshRateProfile = (RefreshRateManager::RefreshRateProfile) _refreshRateProfileSetting.get();
|
_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->setInterval(INACTIVE_TIMER_LIMIT);
|
||||||
_inactiveTimer->setSingleShot(true);
|
_inactiveTimer->setSingleShot(true);
|
||||||
QObject::connect(_inactiveTimer.get(), &QTimer::timeout, [&] {
|
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 RefreshRateManager::getRefreshRateProfile() const {
|
||||||
RefreshRateManager::RefreshRateProfile profile = RefreshRateManager::RefreshRateProfile::REALTIME;
|
RefreshRateManager::RefreshRateProfile profile = RefreshRateManager::RefreshRateProfile::REALTIME;
|
||||||
|
|
||||||
|
@ -191,7 +218,6 @@ void RefreshRateManager::setRefreshRateRegime(RefreshRateManager::RefreshRateReg
|
||||||
_refreshRateRegime = refreshRateRegime;
|
_refreshRateRegime = refreshRateRegime;
|
||||||
updateRefreshRateController();
|
updateRefreshRateController();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefreshRateManager::setUXMode(RefreshRateManager::UXMode uxMode) {
|
void RefreshRateManager::setUXMode(RefreshRateManager::UXMode uxMode) {
|
||||||
|
|
|
@ -32,10 +32,11 @@ public:
|
||||||
ECO = 0,
|
ECO = 0,
|
||||||
INTERACTIVE,
|
INTERACTIVE,
|
||||||
REALTIME,
|
REALTIME,
|
||||||
|
CUSTOM,
|
||||||
PROFILE_NUM
|
PROFILE_NUM
|
||||||
};
|
};
|
||||||
Q_ENUM(RefreshRateProfile)
|
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
|
/*@jsdoc
|
||||||
* <p>Interface states that affect the refresh rate.</p>
|
* <p>Interface states that affect the refresh rate.</p>
|
||||||
|
@ -106,6 +107,9 @@ public:
|
||||||
// query the refresh rate target at the specified combination
|
// query the refresh rate target at the specified combination
|
||||||
int queryRefreshRateTarget(RefreshRateProfile profile, RefreshRateRegime regime, UXMode uxMode) const;
|
int queryRefreshRateTarget(RefreshRateProfile profile, RefreshRateRegime regime, UXMode uxMode) const;
|
||||||
|
|
||||||
|
int getCustomRefreshRate(RefreshRateRegime regime);
|
||||||
|
void setCustomRefreshRate(RefreshRateRegime regime, int value);
|
||||||
|
|
||||||
void resetInactiveTimer();
|
void resetInactiveTimer();
|
||||||
void toggleInactive();
|
void toggleInactive();
|
||||||
|
|
||||||
|
@ -122,6 +126,14 @@ private:
|
||||||
|
|
||||||
mutable ReadWriteLockable _refreshRateProfileSettingLock;
|
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 };
|
std::function<void(int)> _refreshRateOperator { nullptr };
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,14 @@ void AvatarDoctor::diagnoseTextures() {
|
||||||
addTextureToList(material.occlusionTexture);
|
addTextureToList(material.occlusionTexture);
|
||||||
addTextureToList(material.scatteringTexture);
|
addTextureToList(material.scatteringTexture);
|
||||||
addTextureToList(material.lightmapTexture);
|
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()) {
|
for (const auto& materialMapping : model->getMaterialMapping()) {
|
||||||
|
|
|
@ -136,6 +136,14 @@ AvatarProject* AvatarProject::createAvatarProject(const QString& projectsFolder,
|
||||||
addTextureToList(material.occlusionTexture);
|
addTextureToList(material.occlusionTexture);
|
||||||
addTextureToList(material.scatteringTexture);
|
addTextureToList(material.scatteringTexture);
|
||||||
addTextureToList(material.lightmapTexture);
|
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);
|
QDir textureDir(textureFolder.isEmpty() ? fbxInfo.absoluteDir() : textureFolder);
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
#include "MovingEntitiesOperator.h"
|
#include "MovingEntitiesOperator.h"
|
||||||
#include "SceneScriptingInterface.h"
|
#include "SceneScriptingInterface.h"
|
||||||
#include "WarningsSuppression.h"
|
#include "WarningsSuppression.h"
|
||||||
|
#include "ScriptPermissions.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -226,7 +227,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
||||||
_yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed),
|
_yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed),
|
||||||
_hmdYawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "hmdYawSpeed", _hmdYawSpeed),
|
_hmdYawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "hmdYawSpeed", _hmdYawSpeed),
|
||||||
_pitchSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "pitchSpeed", _pitchSpeed),
|
_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()),
|
AvatarData::defaultFullAvatarModelUrl()),
|
||||||
_fullAvatarModelNameSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarModelName", _fullAvatarModelName),
|
_fullAvatarModelNameSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarModelName", _fullAvatarModelName),
|
||||||
_animGraphURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "animGraphURL", QUrl("")),
|
_animGraphURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "animGraphURL", QUrl("")),
|
||||||
|
@ -1739,11 +1740,12 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
||||||
blobFailed = true; // blob doesn't exist
|
blobFailed = true; // blob doesn't exist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
_helperScriptEngine.run( [&] {
|
||||||
if (!EntityItemProperties::blobToProperties(*_scriptEngine, itr.value(), properties)) {
|
if (!EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), itr.value(), properties)) {
|
||||||
blobFailed = true; // blob is corrupt
|
blobFailed = true; // blob is corrupt
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
if (blobFailed) {
|
if (blobFailed) {
|
||||||
// remove from _cachedAvatarEntityBlobUpdatesToSkip just in case:
|
// remove from _cachedAvatarEntityBlobUpdatesToSkip just in case:
|
||||||
// avoids a resource leak when blob updates to be skipped are never actually skipped
|
// avoids a resource leak when blob updates to be skipped are never actually skipped
|
||||||
|
@ -1775,11 +1777,12 @@ void MyAvatar::handleChangedAvatarEntityData() {
|
||||||
skip = true;
|
skip = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
_helperScriptEngine.run( [&] {
|
||||||
if (!EntityItemProperties::blobToProperties(*_scriptEngine, itr.value(), properties)) {
|
if (!EntityItemProperties::blobToProperties(*_helperScriptEngine.get(), itr.value(), properties)) {
|
||||||
skip = true;
|
skip = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
if (!skip && canRezAvatarEntites) {
|
if (!skip && canRezAvatarEntites) {
|
||||||
sanitizeAvatarEntityProperties(properties);
|
sanitizeAvatarEntityProperties(properties);
|
||||||
entityTree->withWriteLock([&] {
|
entityTree->withWriteLock([&] {
|
||||||
|
@ -1883,10 +1886,9 @@ bool MyAvatar::updateStaleAvatarEntityBlobs() const {
|
||||||
if (found) {
|
if (found) {
|
||||||
++numFound;
|
++numFound;
|
||||||
QByteArray blob;
|
QByteArray blob;
|
||||||
{
|
_helperScriptEngine.run( [&] {
|
||||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
EntityItemProperties::propertiesToBlob(*_helperScriptEngine.get(), getID(), properties, blob);
|
||||||
EntityItemProperties::propertiesToBlob(*_scriptEngine, getID(), properties, blob);
|
});
|
||||||
}
|
|
||||||
_avatarEntitiesLock.withWriteLock([&] {
|
_avatarEntitiesLock.withWriteLock([&] {
|
||||||
_cachedAvatarEntityBlobs[id] = blob;
|
_cachedAvatarEntityBlobs[id] = blob;
|
||||||
});
|
});
|
||||||
|
@ -1947,10 +1949,9 @@ AvatarEntityMap MyAvatar::getAvatarEntityData() const {
|
||||||
EntityItemProperties properties = entity->getProperties(desiredProperties);
|
EntityItemProperties properties = entity->getProperties(desiredProperties);
|
||||||
|
|
||||||
QByteArray blob;
|
QByteArray blob;
|
||||||
{
|
_helperScriptEngine.run( [&] {
|
||||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
EntityItemProperties::propertiesToBlob(*_helperScriptEngine.get(), getID(), properties, blob, true);
|
||||||
EntityItemProperties::propertiesToBlob(*_scriptEngine, getID(), properties, blob, true);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
data[entityID] = blob;
|
data[entityID] = blob;
|
||||||
}
|
}
|
||||||
|
@ -2092,9 +2093,6 @@ void MyAvatar::avatarEntityDataToJson(QJsonObject& root) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::loadData() {
|
void MyAvatar::loadData() {
|
||||||
if (!_scriptEngine) {
|
|
||||||
_scriptEngine = newScriptEngine();
|
|
||||||
}
|
|
||||||
getHead()->setBasePitch(_headPitchSetting.get());
|
getHead()->setBasePitch(_headPitchSetting.get());
|
||||||
|
|
||||||
_yawSpeed = _yawSpeedSetting.get(_yawSpeed);
|
_yawSpeed = _yawSpeedSetting.get(_yawSpeed);
|
||||||
|
@ -2236,6 +2234,9 @@ AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString&
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::isMyAvatarURLProtected() const {
|
||||||
|
return !ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL);
|
||||||
|
}
|
||||||
|
|
||||||
int MyAvatar::parseDataFromBuffer(const QByteArray& buffer) {
|
int MyAvatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
qCDebug(interfaceapp) << "Error: ignoring update packet for MyAvatar"
|
qCDebug(interfaceapp) << "Error: ignoring update packet for MyAvatar"
|
||||||
|
@ -2700,11 +2701,10 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() {
|
||||||
QVariantMap avatarEntityData;
|
QVariantMap avatarEntityData;
|
||||||
avatarEntityData["id"] = entityID;
|
avatarEntityData["id"] = entityID;
|
||||||
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
|
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
|
||||||
{
|
_helperScriptEngine.run( [&] {
|
||||||
std::lock_guard<std::mutex> guard(_scriptEngineLock);
|
ScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_helperScriptEngine.get(), entityProperties);
|
||||||
ScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine.get(), entityProperties);
|
|
||||||
avatarEntityData["properties"] = scriptProperties.toVariant();
|
avatarEntityData["properties"] = scriptProperties.toVariant();
|
||||||
}
|
});
|
||||||
avatarEntitiesData.append(QVariant(avatarEntityData));
|
avatarEntitiesData.append(QVariant(avatarEntityData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <controllers/Pose.h>
|
#include <controllers/Pose.h>
|
||||||
#include <controllers/Actions.h>
|
#include <controllers/Actions.h>
|
||||||
#include <EntityItem.h>
|
#include <EntityItem.h>
|
||||||
|
#include <HelperScriptEngine.h>
|
||||||
#include <ThreadSafeValueCache.h>
|
#include <ThreadSafeValueCache.h>
|
||||||
#include <Rig.h>
|
#include <Rig.h>
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
|
@ -2683,6 +2684,7 @@ private:
|
||||||
void setEnableDrawAverageFacing(bool drawAverage) { _drawAverageFacingEnabled = drawAverage; }
|
void setEnableDrawAverageFacing(bool drawAverage) { _drawAverageFacingEnabled = drawAverage; }
|
||||||
bool getEnableDrawAverageFacing() const { return _drawAverageFacingEnabled; }
|
bool getEnableDrawAverageFacing() const { return _drawAverageFacingEnabled; }
|
||||||
virtual bool isMyAvatar() const override { return true; }
|
virtual bool isMyAvatar() const override { return true; }
|
||||||
|
virtual bool isMyAvatarURLProtected() const override;
|
||||||
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
|
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
|
||||||
virtual glm::vec3 getSkeletonPosition() const override;
|
virtual glm::vec3 getSkeletonPosition() const override;
|
||||||
int _skeletonModelChangeCount { 0 };
|
int _skeletonModelChangeCount { 0 };
|
||||||
|
@ -3101,8 +3103,10 @@ private:
|
||||||
mutable std::set<EntityItemID> _staleCachedAvatarEntityBlobs;
|
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)
|
// 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;
|
// TODO: profile if it performs better when script engine is on avatar thread or on its own thread
|
||||||
ScriptEnginePointer _scriptEngine { nullptr };
|
// Own thread is safer from deadlocks
|
||||||
|
mutable HelperScriptEngine _helperScriptEngine;
|
||||||
|
|
||||||
bool _needToSaveAvatarEntitySettings { false };
|
bool _needToSaveAvatarEntitySettings { false };
|
||||||
|
|
||||||
bool _reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS] { false, false };
|
bool _reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS] { false, false };
|
||||||
|
|
|
@ -56,12 +56,22 @@ void PerformanceScriptingInterface::setRefreshRateProfile(RefreshRateProfile ref
|
||||||
emit settingsChanged();
|
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 {
|
PerformanceScriptingInterface::RefreshRateProfile PerformanceScriptingInterface::getRefreshRateProfile() const {
|
||||||
return (PerformanceScriptingInterface::RefreshRateProfile)qApp->getRefreshRateManager().getRefreshRateProfile();
|
return (PerformanceScriptingInterface::RefreshRateProfile)qApp->getRefreshRateManager().getRefreshRateProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList PerformanceScriptingInterface::getRefreshRateProfileNames() const {
|
QStringList PerformanceScriptingInterface::getRefreshRateProfileNames() const {
|
||||||
static const QStringList refreshRateProfileNames = { "ECO", "INTERACTIVE", "REALTIME" };
|
static const QStringList refreshRateProfileNames = { "ECO", "INTERACTIVE", "REALTIME", "CUSTOM" };
|
||||||
return refreshRateProfileNames;
|
return refreshRateProfileNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,22 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void setRefreshRateProfile(RefreshRateProfile refreshRateProfile);
|
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
|
/*@jsdoc
|
||||||
* Gets the current refresh rate profile in use.
|
* Gets the current refresh rate profile in use.
|
||||||
* @function Performance.getRefreshRateProfile
|
* @function Performance.getRefreshRateProfile
|
||||||
|
|
|
@ -21,6 +21,9 @@ SettingsScriptingInterface* SettingsScriptingInterface::getInstance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
||||||
|
if (_restrictPrivateValues && setting.startsWith(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/")) {
|
||||||
|
return {""};
|
||||||
|
}
|
||||||
QVariant value = Setting::Handle<QVariant>(setting).get();
|
QVariant value = Setting::Handle<QVariant>(setting).get();
|
||||||
if (!value.isValid()) {
|
if (!value.isValid()) {
|
||||||
value = "";
|
value = "";
|
||||||
|
@ -29,6 +32,9 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVariant& defaultValue) {
|
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();
|
QVariant value = Setting::Handle<QVariant>(setting, defaultValue).get();
|
||||||
if (!value.isValid()) {
|
if (!value.isValid()) {
|
||||||
value = "";
|
value = "";
|
||||||
|
@ -40,7 +46,7 @@ void SettingsScriptingInterface::setValue(const QString& setting, const QVariant
|
||||||
if (getValue(setting) == value) {
|
if (getValue(setting) == value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (setting.startsWith("private/")) {
|
if (setting.startsWith("private/") || setting.startsWith(SETTINGS_FULL_PRIVATE_GROUP_NAME + "/")) {
|
||||||
if (_restrictPrivateValues) {
|
if (_restrictPrivateValues) {
|
||||||
qWarning() << "SettingsScriptingInterface::setValue -- restricted write: " << setting << value;
|
qWarning() << "SettingsScriptingInterface::setValue -- restricted write: " << setting << value;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -100,7 +100,8 @@ void setupPreferences() {
|
||||||
QStringList refreshRateProfiles
|
QStringList refreshRateProfiles
|
||||||
{ QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::ECO)),
|
{ QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::ECO)),
|
||||||
QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::INTERACTIVE)),
|
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);
|
preference->setItems(refreshRateProfiles);
|
||||||
preferences->addPreference(preference);
|
preferences->addPreference(preference);
|
||||||
|
|
|
@ -281,7 +281,7 @@ if (APPLE)
|
||||||
|
|
||||||
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
||||||
|
|
||||||
set(DMG_SUBFOLDER_NAME "Vircadia")
|
set(DMG_SUBFOLDER_NAME "Overte")
|
||||||
set(ESCAPED_DMG_SUBFOLDER_NAME "")
|
set(ESCAPED_DMG_SUBFOLDER_NAME "")
|
||||||
set(DMG_SUBFOLDER_ICON "${CMAKE_SOURCE_DIR}/cmake/installer/install-folder.rsrc")
|
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 {
|
QByteArray AvatarData::packSkeletonData() const {
|
||||||
// Send an avatar trait packet with the skeleton data before the mesh is loaded
|
// Send an avatar trait packet with the skeleton data before the mesh is loaded
|
||||||
int avatarDataSize = 0;
|
int avatarDataSize = 0;
|
||||||
|
|
|
@ -610,6 +610,8 @@ public:
|
||||||
AvatarData();
|
AvatarData();
|
||||||
virtual ~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();
|
static const QUrl& defaultFullAvatarModelUrl();
|
||||||
|
|
||||||
const QUuid getSessionUUID() const { return getID(); }
|
const QUuid getSessionUUID() const { return getID(); }
|
||||||
|
@ -1355,7 +1357,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE virtual void detachAll(const QString& modelURL, const QString& jointName = QString());
|
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 setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||||
|
|
||||||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "ScriptAvatarData.h"
|
#include "ScriptAvatarData.h"
|
||||||
|
|
||||||
|
#include <NodeList.h>
|
||||||
#include <ScriptEngineCast.h>
|
#include <ScriptEngineCast.h>
|
||||||
#include <ScriptManager.h>
|
#include <ScriptManager.h>
|
||||||
|
|
||||||
|
@ -204,7 +205,12 @@ bool ScriptAvatarData::getLookAtSnappingEnabled() const {
|
||||||
//
|
//
|
||||||
QString ScriptAvatarData::getSkeletonModelURLFromScript() const {
|
QString ScriptAvatarData::getSkeletonModelURLFromScript() const {
|
||||||
if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) {
|
if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
if (sharedAvatarData->isMyAvatar() && !sharedAvatarData->isMyAvatarURLProtected() && nodeList->getThisNodeCanViewAssetURLs()) {
|
||||||
return sharedAvatarData->getSkeletonModelURLFromScript();
|
return sharedAvatarData->getSkeletonModelURLFromScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
} else {
|
} else {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,7 @@ MaterialBaker::MaterialBaker(const QString& materialData, bool isURL, const QStr
|
||||||
_isURL(isURL),
|
_isURL(isURL),
|
||||||
_destinationPath(destinationPath),
|
_destinationPath(destinationPath),
|
||||||
_bakedOutputDir(bakedOutputDir),
|
_bakedOutputDir(bakedOutputDir),
|
||||||
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++)),
|
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++))
|
||||||
_scriptEngine(newScriptEngine())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,16 +213,20 @@ void MaterialBaker::outputMaterial() {
|
||||||
if (_materialResource->parsedMaterials.networkMaterials.size() == 1) {
|
if (_materialResource->parsedMaterials.networkMaterials.size() == 1) {
|
||||||
auto networkMaterial = _materialResource->parsedMaterials.networkMaterials.begin();
|
auto networkMaterial = _materialResource->parsedMaterials.networkMaterials.begin();
|
||||||
auto scriptableMaterial = scriptable::ScriptableMaterial(networkMaterial->second);
|
auto scriptableMaterial = scriptable::ScriptableMaterial(networkMaterial->second);
|
||||||
|
_helperScriptEngine.run( [&] {
|
||||||
QVariant materialVariant =
|
QVariant materialVariant =
|
||||||
scriptable::scriptableMaterialToScriptValue(_scriptEngine.get(), scriptableMaterial).toVariant();
|
scriptable::scriptableMaterialToScriptValue(_helperScriptEngine.get(), scriptableMaterial).toVariant();
|
||||||
json.insert("materials", QJsonDocument::fromVariant(materialVariant).object());
|
json.insert("materials", QJsonDocument::fromVariant(materialVariant).object());
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
QJsonArray materialArray;
|
QJsonArray materialArray;
|
||||||
for (auto networkMaterial : _materialResource->parsedMaterials.networkMaterials) {
|
for (auto networkMaterial : _materialResource->parsedMaterials.networkMaterials) {
|
||||||
auto scriptableMaterial = scriptable::ScriptableMaterial(networkMaterial.second);
|
auto scriptableMaterial = scriptable::ScriptableMaterial(networkMaterial.second);
|
||||||
|
_helperScriptEngine.run( [&] {
|
||||||
QVariant materialVariant =
|
QVariant materialVariant =
|
||||||
scriptable::scriptableMaterialToScriptValue(_scriptEngine.get(), scriptableMaterial).toVariant();
|
scriptable::scriptableMaterialToScriptValue(_helperScriptEngine.get(), scriptableMaterial).toVariant();
|
||||||
materialArray.append(QJsonDocument::fromVariant(materialVariant).object());
|
materialArray.append(QJsonDocument::fromVariant(materialVariant).object());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
json.insert("materials", materialArray);
|
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(); });
|
_materialResource = NetworkMaterialResourcePointer(new NetworkMaterialResource(), [](NetworkMaterialResource* ptr) { ptr->deleteLater(); });
|
||||||
for (auto& material : materials) {
|
for (auto& material : materials) {
|
||||||
_materialResource->parsedMaterials.names.push_back(material.name.toStdString());
|
_materialResource->parsedMaterials.names.push_back(material.name.toStdString());
|
||||||
|
if (!material.isMToonMaterial) {
|
||||||
_materialResource->parsedMaterials.networkMaterials[material.name.toStdString()] = std::make_shared<NetworkMaterial>(material, baseURL);
|
_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
|
// Store any embedded texture content
|
||||||
addTexture(material.name, image::TextureUsage::NORMAL_TEXTURE, material.normalTexture);
|
addTexture(material.name, image::TextureUsage::NORMAL_TEXTURE, material.normalTexture);
|
||||||
addTexture(material.name, image::TextureUsage::ALBEDO_TEXTURE, material.albedoTexture);
|
addTexture(material.name, image::TextureUsage::ALBEDO_TEXTURE, material.albedoTexture);
|
||||||
|
addTexture(material.name, image::TextureUsage::EMISSIVE_TEXTURE, material.emissiveTexture);
|
||||||
|
|
||||||
|
if (!material.isMToonMaterial) {
|
||||||
addTexture(material.name, image::TextureUsage::GLOSS_TEXTURE, material.glossTexture);
|
addTexture(material.name, image::TextureUsage::GLOSS_TEXTURE, material.glossTexture);
|
||||||
addTexture(material.name, image::TextureUsage::ROUGHNESS_TEXTURE, material.roughnessTexture);
|
addTexture(material.name, image::TextureUsage::ROUGHNESS_TEXTURE, material.roughnessTexture);
|
||||||
addTexture(material.name, image::TextureUsage::SPECULAR_TEXTURE, material.specularTexture);
|
addTexture(material.name, image::TextureUsage::SPECULAR_TEXTURE, material.specularTexture);
|
||||||
addTexture(material.name, image::TextureUsage::METALLIC_TEXTURE, material.metallicTexture);
|
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::OCCLUSION_TEXTURE, material.occlusionTexture);
|
||||||
addTexture(material.name, image::TextureUsage::SCATTERING_TEXTURE, material.scatteringTexture);
|
addTexture(material.name, image::TextureUsage::SCATTERING_TEXTURE, material.scatteringTexture);
|
||||||
addTexture(material.name, image::TextureUsage::LIGHTMAP_TEXTURE, material.lightmapTexture);
|
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 "TextureBaker.h"
|
||||||
#include "baking/TextureFileNamer.h"
|
#include "baking/TextureFileNamer.h"
|
||||||
|
|
||||||
|
#include <HelperScriptEngine.h>
|
||||||
#include <procedural/ProceduralMaterialCache.h>
|
#include <procedural/ProceduralMaterialCache.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ private:
|
||||||
QString _textureOutputDir;
|
QString _textureOutputDir;
|
||||||
QString _bakedMaterialData;
|
QString _bakedMaterialData;
|
||||||
|
|
||||||
ScriptEnginePointer _scriptEngine;
|
HelperScriptEngine _helperScriptEngine;
|
||||||
static std::function<QThread*()> _getNextOvenWorkerThreadOperator;
|
static std::function<QThread*()> _getNextOvenWorkerThreadOperator;
|
||||||
TextureFileNamer _textureFileNamer;
|
TextureFileNamer _textureFileNamer;
|
||||||
|
|
||||||
|
|
|
@ -1195,9 +1195,9 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) {
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8(), &error);
|
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8(), &error);
|
||||||
// check validity of the document
|
// check validity of the document
|
||||||
if (doc.isNull()) {
|
if (doc.isNull()) {
|
||||||
qCDebug(controllers) << "Invalid JSON...\n";
|
qCCritical(controllers) << "Invalid JSON...\n";
|
||||||
qCDebug(controllers) << error.errorString();
|
qCCritical(controllers) << error.errorString();
|
||||||
qCDebug(controllers) << "JSON was:\n" << json << Qt::endl;
|
qCCritical(controllers) << "JSON was:\n" << json << Qt::endl;
|
||||||
return Mapping::Pointer();
|
return Mapping::Pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -743,6 +743,13 @@ void OpenGLDisplayPlugin::present(const std::shared_ptr<RefreshRateController>&
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory());
|
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()) {
|
} else if (alwaysPresent()) {
|
||||||
refreshRateController->clockEndTime();
|
refreshRateController->clockEndTime();
|
||||||
internalPresent();
|
internalPresent();
|
||||||
|
|
|
@ -201,4 +201,6 @@ protected:
|
||||||
|
|
||||||
QImage getScreenshot(float aspectRatio);
|
QImage getScreenshot(float aspectRatio);
|
||||||
QImage getSecondaryCameraScreenshot();
|
QImage getSecondaryCameraScreenshot();
|
||||||
|
|
||||||
|
bool _presentOnlyOnce = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -337,21 +337,26 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw!
|
// 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 {
|
} else {
|
||||||
auto proceduralDrawMaterial = std::static_pointer_cast<graphics::ProceduralMaterial>(drawMaterial);
|
auto proceduralDrawMaterial = std::static_pointer_cast<graphics::ProceduralMaterial>(drawMaterial);
|
||||||
glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity());
|
glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity());
|
||||||
outColor = proceduralDrawMaterial->getColor(outColor);
|
outColor = proceduralDrawMaterial->getColor(outColor);
|
||||||
proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(),
|
proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(),
|
||||||
transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
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) {
|
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 {
|
} 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) {
|
void MaterialEntityRenderer::setCurrentMaterialName(const std::string& currentMaterialName) {
|
||||||
|
|
|
@ -67,6 +67,7 @@ private:
|
||||||
std::shared_ptr<NetworkMaterial> _appliedMaterial;
|
std::shared_ptr<NetworkMaterial> _appliedMaterial;
|
||||||
std::string _currentMaterialName;
|
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 uint8_t CUSTOM_PIPELINE_NUMBER = 0;
|
||||||
static gpu::Stream::FormatPointer _vertexFormat;
|
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) {
|
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
|
||||||
auto texturedPipeline = _texturedPipeline.lock();
|
if (_pipelines.empty()) {
|
||||||
if (!texturedPipeline) {
|
using namespace shader::entities_renderer::program;
|
||||||
|
|
||||||
|
// 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>();
|
auto state = std::make_shared<gpu::State>();
|
||||||
state->setCullMode(gpu::State::CULL_BACK);
|
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);
|
|
||||||
|
|
||||||
auto program = gpu::Shader::createProgram(shader::entities_renderer::program::textured_particle);
|
if (wireframe) {
|
||||||
_texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state);
|
state->setFillMode(gpu::State::FILL_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<render::ShapePipeline>(texturedPipeline, nullptr, nullptr, nullptr);
|
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>(_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 {
|
struct GpuParticle {
|
||||||
|
@ -138,26 +163,25 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn
|
||||||
_uniformBuffer.edit<ParticleUniforms>() = particleUniforms;
|
_uniformBuffer.edit<ParticleUniforms>() = particleUniforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKey ParticleEffectEntityRenderer::getKey() {
|
bool ParticleEffectEntityRenderer::isTransparent() const {
|
||||||
// FIXME: implement isTransparent() for particles and an opaque pipeline
|
bool particleTransparent = _particleProperties.getColorStart().a < 1.0f || _particleProperties.getColorMiddle().a < 1.0f ||
|
||||||
auto builder = ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
_particleProperties.getColorFinish().a < 1.0f || _particleProperties.getColorSpread().a > 0.0f ||
|
||||||
|
_pulseProperties.getAlphaMode() != PulseMode::NONE || (_textureLoaded && _networkTexture && _networkTexture->getGPUTexture() &&
|
||||||
if (!_visible) {
|
_networkTexture->getGPUTexture()->getUsage().isAlpha() && !_networkTexture->getGPUTexture()->getUsage().isAlphaMask());
|
||||||
builder.withInvisible();
|
return particleTransparent || Parent::isTransparent();
|
||||||
}
|
|
||||||
|
|
||||||
if (_cullWithParent) {
|
|
||||||
builder.withSubMetaCulled();
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapeKey ParticleEffectEntityRenderer::getShapeKey() {
|
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) {
|
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||||
builder.withWireframe();
|
builder.withWireframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ protected:
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||||
|
|
||||||
virtual ItemKey getKey() override;
|
bool isTransparent() const override;
|
||||||
virtual ShapeKey getShapeKey() override;
|
virtual ShapeKey getShapeKey() override;
|
||||||
virtual Item::Bound getBound(RenderArgs* args) override;
|
virtual Item::Bound getBound(RenderArgs* args) override;
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
|
|
|
@ -1719,21 +1719,28 @@ using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
|
||||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
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;
|
static gpu::Stream::FormatPointer _vertexFormat;
|
||||||
|
|
||||||
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
|
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()) {
|
if (_pipelines.empty()) {
|
||||||
using namespace shader::entities_renderer::program;
|
using namespace shader::entities_renderer::program;
|
||||||
|
|
||||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
// forward, shadow, fade
|
||||||
std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward)
|
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
|
#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
|
#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
|
#endif
|
||||||
};
|
};
|
||||||
for (auto& key : keys) {
|
for (auto& key : keys) {
|
||||||
|
@ -1749,19 +1756,19 @@ ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const Sha
|
||||||
state->setFillMode(gpu::State::FILL_LINE);
|
state->setFillMode(gpu::State::FILL_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
|
auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<3>(key)), state);
|
||||||
if (std::get<1>(key)) {
|
if (!std::get<2>(key)) {
|
||||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr, nullptr, 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, nullptr, nullptr);
|
||||||
} else {
|
} else {
|
||||||
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
|
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());
|
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) {
|
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);
|
_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() {
|
ShapeKey PolyVoxEntityRenderer::getShapeKey() {
|
||||||
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
|
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
|
||||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||||
|
@ -1866,13 +1863,7 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) {
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
batch.setInputFormat(_vertexFormat);
|
batch.setInputFormat(_vertexFormat);
|
||||||
batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0,
|
batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0, sizeof(PolyVox::PositionMaterialNormal));
|
||||||
sizeof(PolyVox::PositionMaterialNormal));
|
|
||||||
|
|
||||||
// TODO -- should we be setting this?
|
|
||||||
// batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer,
|
|
||||||
// 12,
|
|
||||||
// sizeof(PolyVox::PositionMaterialNormal));
|
|
||||||
batch.setIndexBuffer(gpu::UINT32, _mesh->getIndexBuffer()._buffer, 0);
|
batch.setIndexBuffer(gpu::UINT32, _mesh->getIndexBuffer()._buffer, 0);
|
||||||
|
|
||||||
for (size_t i = 0; i < _xyzTextures.size(); ++i) {
|
for (size_t i = 0; i < _xyzTextures.size(); ++i) {
|
||||||
|
|
|
@ -203,7 +203,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ItemKey getKey() override;
|
|
||||||
virtual ShapeKey getShapeKey() override;
|
virtual ShapeKey getShapeKey() override;
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) 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));
|
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) {
|
if (wireframe) {
|
||||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
geometryCache->renderWireShape(batch, geometryShape, _colorBuffer);
|
||||||
} else {
|
} else {
|
||||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
geometryCache->renderShape(batch, geometryShape, _colorBuffer);
|
||||||
}
|
}
|
||||||
} else if (pipelineType == Pipeline::SIMPLE) {
|
} else if (pipelineType == Pipeline::SIMPLE) {
|
||||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
// 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);
|
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor));
|
||||||
|
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||||
if (wireframe) {
|
if (wireframe) {
|
||||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
geometryCache->renderWireShape(batch, geometryShape, _colorBuffer);
|
||||||
} else {
|
} else {
|
||||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
geometryCache->renderShape(batch, geometryShape, _colorBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -160,7 +164,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
args->_details._materialSwitches++;
|
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);
|
const auto triCount = geometryCache->getShapeTriangleCount(geometryShape);
|
||||||
|
|
|
@ -42,6 +42,8 @@ private:
|
||||||
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
|
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
|
||||||
glm::vec3 _color { NAN };
|
glm::vec3 _color { NAN };
|
||||||
float _alpha { 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=0) in vec4 varColor;
|
||||||
layout(location=1) in vec2 varTexcoord;
|
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) {
|
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;
|
const float AmbientLightPropertyGroup::DEFAULT_AMBIENT_LIGHT_INTENSITY = 0.5f;
|
||||||
|
|
||||||
void AmbientLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
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_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) {
|
void AmbientLightPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
|
||||||
|
|
|
@ -43,7 +43,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const AmbientLightPropertyGroup& other);
|
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.
|
* maintained when the animation stops playing, <code>false</code> if they aren't.
|
||||||
*/
|
*/
|
||||||
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
||||||
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url);
|
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_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_FPS, Animation, animation, FPS, fps);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
||||||
|
|
|
@ -37,7 +37,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const AnimationPropertyGroup& other);
|
void merge(const AnimationPropertyGroup& other);
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
#include "EntityItemPropertiesMacros.h"
|
#include "EntityItemPropertiesMacros.h"
|
||||||
|
|
||||||
void BloomPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
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_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize);
|
||||||
|
|
|
@ -44,7 +44,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const BloomPropertyGroup& other);
|
void merge(const BloomPropertyGroup& other);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <Extents.h>
|
#include <Extents.h>
|
||||||
#include <VariantMapToScriptValue.h>
|
#include <VariantMapToScriptValue.h>
|
||||||
#include <ScriptValue.h>
|
#include <ScriptValue.h>
|
||||||
|
#include <PhysicsHelpers.h>
|
||||||
|
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
|
@ -1566,6 +1567,8 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
return properties;
|
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))) {
|
if (_idSet && (!pseudoPropertyFlagsActive || pseudoPropertyFlags.test(EntityPseudoPropertyFlag::ID))) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString());
|
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_IGNORE_PICK_INTERSECTION, ignorePickIntersection);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString());
|
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
|
// Physics
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DENSITY, density);
|
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_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_COLLISION_MASK, collisionMask, collidesWith, getCollisionMaskAsString());
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DYNAMIC, dynamic);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DYNAMIC, dynamic);
|
||||||
COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_DYNAMIC, dynamic, collisionsWillMove, getDynamic()); // legacy support
|
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);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACTION_DATA, actionData);
|
||||||
|
|
||||||
// Cloning
|
// Cloning
|
||||||
|
@ -1660,10 +1663,10 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
// Particles only
|
// Particles only
|
||||||
if (_type == EntityTypes::ParticleEffect) {
|
if (_type == EntityTypes::ParticleEffect) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
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_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
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_TEXTURES, textures);
|
||||||
|
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles);
|
||||||
|
@ -1710,11 +1713,11 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
// Models only
|
// Models only
|
||||||
if (_type == EntityTypes::Model) {
|
if (_type == EntityTypes::Model) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
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_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
|
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_MODEL_SCALE, modelScale);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations);
|
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_GROUP_CULLED, groupCulled);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BLENDSHAPE_COEFFICIENTS, blendshapeCoefficients);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BLENDSHAPE_COEFFICIENTS, blendshapeCoefficients);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USE_ORIGINAL_PIVOT, useOriginalPivot);
|
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.
|
// 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) {
|
if (_type == EntityTypes::Box || _type == EntityTypes::Sphere || _type == EntityTypes::Shape) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
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);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHAPE, shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1754,7 +1757,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
|
|
||||||
// Text only
|
// Text only
|
||||||
if (_type == EntityTypes::Text) {
|
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_TEXT, text);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight);
|
||||||
|
@ -1777,17 +1780,17 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
// Zones only
|
// Zones only
|
||||||
if (_type == EntityTypes::Zone) {
|
if (_type == EntityTypes::Zone) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString());
|
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);
|
_keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||||
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||||
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||||
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||||
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags);
|
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
|
||||||
|
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
|
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_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString());
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString());
|
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) {
|
if (_type == EntityTypes::Web) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
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_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(PROP_MAX_FPS, maxFPS);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_INPUT_MODE, inputMode, getInputModeAsString());
|
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_INPUT_MODE, inputMode, getInputModeAsString());
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, showKeyboardFocusHighlight);
|
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_VOLUME_SIZE, voxelVolumeSize);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_DATA, voxelData);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_DATA, voxelData);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_SURFACE_STYLE, voxelSurfaceStyle);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VOXEL_SURFACE_STYLE, voxelSurfaceStyle);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_X_TEXTURE_URL, xTextureURL);
|
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_X_TEXTURE_URL, xTextureURL);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_TEXTURE_URL, yTextureURL);
|
COPY_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_Y_TEXTURE_URL, yTextureURL);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Z_TEXTURE_URL, zTextureURL);
|
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_X_N_NEIGHBOR_ID, xNNeighborID);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_N_NEIGHBOR_ID, yNNeighborID);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Y_N_NEIGHBOR_ID, yNNeighborID);
|
||||||
|
@ -1855,14 +1858,14 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
|
|
||||||
// Materials
|
// Materials
|
||||||
if (_type == EntityTypes::Material) {
|
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_GETTER(PROP_MATERIAL_MAPPING_MODE, materialMappingMode, getMaterialMappingModeAsString());
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_MATERIAL_NAME, parentMaterialName);
|
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_POS, materialMappingPos);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
|
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);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_REPEAT, materialRepeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1870,15 +1873,16 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
if (_type == EntityTypes::Image) {
|
if (_type == EntityTypes::Image) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
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_EMISSIVE, emissive);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEEP_ASPECT_RATIO, keepAspectRatio);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEEP_ASPECT_RATIO, keepAspectRatio);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SUB_IMAGE, subImage);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SUB_IMAGE, subImage);
|
||||||
|
|
||||||
// Handle conversions to old 'textures' property from "imageURL"
|
// 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)) {
|
(!skipDefaults || defaultEntityProperties._imageURL != _imageURL)) {
|
||||||
ScriptValue textures = engine->newObject();
|
ScriptValue textures = engine->newObject();
|
||||||
textures.setProperty("tex.picture", _imageURL);
|
textures.setProperty("tex.picture", _imageURL);
|
||||||
|
@ -1890,7 +1894,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
if (_type == EntityTypes::Grid) {
|
if (_type == EntityTypes::Grid) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
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_GRID_FOLLOW_CAMERA, followCamera);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAJOR_GRID_EVERY, majorGridEvery);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAJOR_GRID_EVERY, majorGridEvery);
|
||||||
|
@ -1900,7 +1904,7 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
|
||||||
// Gizmo only
|
// Gizmo only
|
||||||
if (_type == EntityTypes::Gizmo) {
|
if (_type == EntityTypes::Gizmo) {
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_GIZMO_TYPE, gizmoType, getGizmoTypeAsString());
|
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
|
/*@jsdoc
|
||||||
|
@ -2549,7 +2553,7 @@ bool EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue&
|
||||||
if (object.isString()) {
|
if (object.isString()) {
|
||||||
EntityPropertyInfo propertyInfo;
|
EntityPropertyInfo propertyInfo;
|
||||||
if (getPropertyInfo(object.toString(), propertyInfo)) {
|
if (getPropertyInfo(object.toString(), propertyInfo)) {
|
||||||
flags << propertyInfo.propertyEnum;
|
flags << propertyInfo.propertyEnums;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (object.isArray()) {
|
else if (object.isArray()) {
|
||||||
|
@ -2558,7 +2562,7 @@ bool EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue&
|
||||||
QString propertyName = object.property(i).toString();
|
QString propertyName = object.property(i).toString();
|
||||||
EntityPropertyInfo propertyInfo;
|
EntityPropertyInfo propertyInfo;
|
||||||
if (getPropertyInfo(propertyName, propertyInfo)) {
|
if (getPropertyInfo(propertyName, propertyInfo)) {
|
||||||
flags << propertyInfo.propertyEnum;
|
flags << propertyInfo.propertyEnums;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2794,7 +2798,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
|
||||||
{ // Keylight
|
{ // Keylight
|
||||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color);
|
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_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(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_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);
|
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 EntityPropertyInfoToScriptValue(ScriptEngine* engine, const EntityPropertyInfo& propertyInfo) {
|
||||||
ScriptValue obj = engine->newObject();
|
ScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("propertyEnum", propertyInfo.propertyEnum);
|
obj.setProperty("propertyEnum", propertyInfo.propertyEnums.firstFlag());
|
||||||
obj.setProperty("minimum", propertyInfo.minimum.toString());
|
obj.setProperty("minimum", propertyInfo.minimum.toString());
|
||||||
obj.setProperty("maximum", propertyInfo.maximum.toString());
|
obj.setProperty("maximum", propertyInfo.maximum.toString());
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityPropertyInfoFromScriptValue(const ScriptValue& object, EntityPropertyInfo& propertyInfo) {
|
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.minimum = object.property("minimum").toVariant();
|
||||||
propertyInfo.maximum = object.property("maximum").toVariant();
|
propertyInfo.maximum = object.property("maximum").toVariant();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -80,11 +80,11 @@ using u8vec3Color = glm::u8vec3;
|
||||||
|
|
||||||
struct EntityPropertyInfo {
|
struct EntityPropertyInfo {
|
||||||
EntityPropertyInfo(EntityPropertyList propEnum) :
|
EntityPropertyInfo(EntityPropertyList propEnum) :
|
||||||
propertyEnum(propEnum) {}
|
propertyEnums(propEnum) {}
|
||||||
EntityPropertyInfo(EntityPropertyList propEnum, QVariant min, QVariant max) :
|
EntityPropertyInfo(EntityPropertyList propEnum, QVariant min, QVariant max) :
|
||||||
propertyEnum(propEnum), minimum(min), maximum(max) {}
|
propertyEnums(propEnum), minimum(min), maximum(max) {}
|
||||||
EntityPropertyInfo() = default;
|
EntityPropertyInfo() = default;
|
||||||
EntityPropertyList propertyEnum;
|
EntityPropertyFlags propertyEnums;
|
||||||
QVariant minimum;
|
QVariant minimum;
|
||||||
QVariant maximum;
|
QVariant maximum;
|
||||||
};
|
};
|
||||||
|
|
|
@ -218,6 +218,37 @@ inline ScriptValue convertScriptValue(ScriptEngine* e, const AACube& v) { return
|
||||||
properties.setProperty(#P, V); \
|
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::vec3> qVectorVec3;
|
||||||
typedef QVector<glm::quat> qVectorQuat;
|
typedef QVector<glm::quat> qVectorQuat;
|
||||||
typedef QVector<bool> qVectorBool;
|
typedef QVector<bool> qVectorBool;
|
||||||
|
@ -459,6 +490,7 @@ inline QRect QRect_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
|
||||||
{ \
|
{ \
|
||||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
|
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
|
||||||
_propertyInfos[#g "." #n] = propertyInfo; \
|
_propertyInfos[#g "." #n] = propertyInfo; \
|
||||||
|
_propertyInfos[#g].propertyEnums << P; \
|
||||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,6 +498,7 @@ inline QRect QRect_convertFromScriptValue(const ScriptValue& v, bool& isValid) {
|
||||||
{ \
|
{ \
|
||||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
|
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
|
||||||
_propertyInfos[#g "." #n] = propertyInfo; \
|
_propertyInfos[#g "." #n] = propertyInfo; \
|
||||||
|
_propertyInfos[#g].propertyEnums << P; \
|
||||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership
|
||||||
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
|
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
|
||||||
connect(nodeList.data(), &NodeList::canGetAndSetPrivateUserDataChanged, this, &EntityScriptingInterface::canGetAndSetPrivateUserDataChanged);
|
connect(nodeList.data(), &NodeList::canGetAndSetPrivateUserDataChanged, this, &EntityScriptingInterface::canGetAndSetPrivateUserDataChanged);
|
||||||
connect(nodeList.data(), &NodeList::canRezAvatarEntitiesChanged, this, &EntityScriptingInterface::canRezAvatarEntitiesChanged);
|
connect(nodeList.data(), &NodeList::canRezAvatarEntitiesChanged, this, &EntityScriptingInterface::canRezAvatarEntitiesChanged);
|
||||||
|
connect(nodeList.data(), &NodeList::canViewAssetURLsChanged, this, &EntityScriptingInterface::canViewAssetURLsChanged);
|
||||||
|
|
||||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod,
|
packetReceiver.registerListener(PacketType::EntityScriptCallMethod,
|
||||||
|
@ -291,6 +292,11 @@ bool EntityScriptingInterface::canRezAvatarEntities() {
|
||||||
return nodeList->getThisNodeCanRezAvatarEntities();
|
return nodeList->getThisNodeCanRezAvatarEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityScriptingInterface::canViewAssetURLs() {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
return nodeList->getThisNodeCanViewAssetURLs();
|
||||||
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
|
void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
|
||||||
if (_entityTree) {
|
if (_entityTree) {
|
||||||
disconnect(_entityTree.get(), &EntityTree::addingEntityPointer, this, &EntityScriptingInterface::onAddingEntity);
|
disconnect(_entityTree.get(), &EntityTree::addingEntityPointer, this, &EntityScriptingInterface::onAddingEntity);
|
||||||
|
|
|
@ -288,6 +288,14 @@ public slots:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool canRezAvatarEntities();
|
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
|
/*@jsdoc
|
||||||
* <p>How an entity is hosted and sent to others for display.</p>
|
* <p>How an entity is hosted and sent to others for display.</p>
|
||||||
* <table>
|
* <table>
|
||||||
|
@ -2249,6 +2257,14 @@ signals:
|
||||||
*/
|
*/
|
||||||
void canRezAvatarEntitiesChanged(bool canRezAvatarEntities);
|
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
|
/*@jsdoc
|
||||||
* Triggered when a mouse button is clicked while the mouse cursor is on an entity, or a controller trigger is fully
|
* 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["DataVersion"] = _persistDataVersion;
|
||||||
entityDescription["Id"] = _persistID;
|
entityDescription["Id"] = _persistID;
|
||||||
const std::lock_guard<std::mutex> scriptLock(scriptEngineMutex);
|
_helperScriptEngine.run( [&] {
|
||||||
RecurseOctreeToMapOperator theOperator(entityDescription, element, scriptEngine.get(), skipDefaultValues,
|
RecurseOctreeToMapOperator theOperator(entityDescription, element, _helperScriptEngine.get(), skipDefaultValues,
|
||||||
skipThoseWithBadParents, _myAvatar);
|
skipThoseWithBadParents, _myAvatar);
|
||||||
withReadLock([&] {
|
withReadLock([&] { recurseTreeWithOperator(&theOperator); });
|
||||||
recurseTreeWithOperator(&theOperator);
|
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2728,11 +2727,10 @@ bool EntityTree::readFromMap(QVariantMap& map, const bool isImport) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
{
|
_helperScriptEngine.run( [&] {
|
||||||
const std::lock_guard<std::mutex> scriptLock(scriptEngineMutex);
|
ScriptValue entityScriptValue = variantMapToScriptValue(entityMap, *_helperScriptEngine.get());
|
||||||
ScriptValue entityScriptValue = variantMapToScriptValue(entityMap, *scriptEngine);
|
|
||||||
EntityItemPropertiesFromScriptValueIgnoreReadOnly(entityScriptValue, properties);
|
EntityItemPropertiesFromScriptValueIgnoreReadOnly(entityScriptValue, properties);
|
||||||
}
|
});
|
||||||
|
|
||||||
EntityItemID entityItemID;
|
EntityItemID entityItemID;
|
||||||
if (entityMap.contains("id")) {
|
if (entityMap.contains("id")) {
|
||||||
|
@ -2881,13 +2879,12 @@ bool EntityTree::readFromMap(QVariantMap& map, const bool isImport) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTree::writeToJSON(QString& jsonString, const OctreeElementPointer& element) {
|
bool EntityTree::writeToJSON(QString& jsonString, const OctreeElementPointer& element) {
|
||||||
const std::lock_guard<std::mutex> scriptLock(scriptEngineMutex);
|
_helperScriptEngine.run( [&] {
|
||||||
RecurseOctreeToJSONOperator theOperator(element, scriptEngine.get(), jsonString);
|
RecurseOctreeToJSONOperator theOperator(element, _helperScriptEngine.get(), jsonString);
|
||||||
withReadLock([&] {
|
withReadLock([&] { recurseTreeWithOperator(&theOperator); });
|
||||||
recurseTreeWithOperator(&theOperator);
|
|
||||||
});
|
|
||||||
|
|
||||||
jsonString = theOperator.getJson();
|
jsonString = theOperator.getJson();
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
#include <HelperScriptEngine.h>
|
||||||
#include <Octree.h>
|
#include <Octree.h>
|
||||||
#include <SpatialParentFinder.h>
|
#include <SpatialParentFinder.h>
|
||||||
|
|
||||||
|
@ -387,8 +388,7 @@ private:
|
||||||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer);
|
MovingEntitiesOperator& moveOperator, bool force, bool tellServer);
|
||||||
|
|
||||||
// Script engine for writing entity tree data to and from JSON
|
// Script engine for writing entity tree data to and from JSON
|
||||||
std::mutex scriptEngineMutex;
|
HelperScriptEngine _helperScriptEngine;
|
||||||
ScriptEnginePointer scriptEngine{ newScriptEngine() };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void convertGrabUserDataToProperties(EntityItemProperties& properties);
|
void convertGrabUserDataToProperties(EntityItemProperties& properties);
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
void GrabPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
void GrabPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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_GRABBABLE, Grab, grab, Grabbable, grabbable);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic);
|
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);
|
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);
|
EquippableRightPosition, equippableRightPosition);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_RIGHT_EQUIPPABLE_ROTATION_OFFSET, Grab, grab,
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_RIGHT_EQUIPPABLE_ROTATION_OFFSET, Grab, grab,
|
||||||
EquippableRightRotation, equippableRightRotation);
|
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);
|
EquippableIndicatorURL, equippableIndicatorURL);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_EQUIPPABLE_INDICATOR_SCALE, Grab, grab,
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_EQUIPPABLE_INDICATOR_SCALE, Grab, grab,
|
||||||
EquippableIndicatorScale, equippableIndicatorScale);
|
EquippableIndicatorScale, equippableIndicatorScale);
|
||||||
|
|
|
@ -75,7 +75,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const GrabPropertyGroup& other);
|
void merge(const GrabPropertyGroup& other);
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
#include "EntityItemPropertiesMacros.h"
|
#include "EntityItemPropertiesMacros.h"
|
||||||
|
|
||||||
void HazePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
|
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(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_COLOR, Haze, haze, HazeColor, hazeColor, u8vec3Color);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_HAZE_GLARE_COLOR, Haze, haze, HazeGlareColor, hazeGlareColor, u8vec3Color);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_HAZE_GLARE_COLOR, Haze, haze, HazeGlareColor, hazeGlareColor, u8vec3Color);
|
||||||
|
|
|
@ -80,7 +80,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const HazePropertyGroup& other);
|
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 };
|
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE { 40.0f };
|
||||||
|
|
||||||
void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
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_TYPED(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color, u8vec3Color);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
||||||
|
|
|
@ -50,7 +50,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const KeyLightPropertyGroup& other);
|
void merge(const KeyLightPropertyGroup& other);
|
||||||
|
|
|
@ -34,7 +34,8 @@ public:
|
||||||
virtual ~PropertyGroup() = default;
|
virtual ~PropertyGroup() = default;
|
||||||
|
|
||||||
// EntityItemProperty related helpers
|
// 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 copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) = 0;
|
||||||
virtual void debugDump() const { }
|
virtual void debugDump() const { }
|
||||||
virtual void listChangedProperties(QList<QString>& out) { }
|
virtual void listChangedProperties(QList<QString>& out) { }
|
||||||
|
|
|
@ -61,7 +61,8 @@ void PulsePropertyGroup::setAlphaModeFromString(const QString& pulseMode) {
|
||||||
|
|
||||||
void PulsePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
void PulsePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
ScriptEngine* engine, bool skipDefaults,
|
||||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
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_MIN, Pulse, pulse, Min, min);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_MAX, Pulse, pulse, Max, max);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_MAX, Pulse, pulse, Max, max);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_PERIOD, Pulse, pulse, Period, period);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_PERIOD, Pulse, pulse, Period, period);
|
||||||
|
|
|
@ -44,7 +44,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const PulsePropertyGroup& other);
|
void merge(const PulsePropertyGroup& other);
|
||||||
|
|
|
@ -24,7 +24,8 @@ const float RingGizmoPropertyGroup::MAX_RADIUS = 0.5f;
|
||||||
|
|
||||||
void RingGizmoPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
void RingGizmoPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
ScriptEngine* engine, bool skipDefaults,
|
||||||
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags) const {
|
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_START_ANGLE, Ring, ring, StartAngle, startAngle);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_END_ANGLE, Ring, ring, EndAngle, endAngle);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_END_ANGLE, Ring, ring, EndAngle, endAngle);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_INNER_RADIUS, Ring, ring, InnerRadius, innerRadius);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_INNER_RADIUS, Ring, ring, InnerRadius, innerRadius);
|
||||||
|
|
|
@ -60,7 +60,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const RingGizmoPropertyGroup& other);
|
void merge(const RingGizmoPropertyGroup& other);
|
||||||
|
|
|
@ -20,9 +20,11 @@
|
||||||
|
|
||||||
const glm::u8vec3 SkyboxPropertyGroup::DEFAULT_COLOR = { 0, 0, 0 };
|
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_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) {
|
void SkyboxPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
|
||||||
|
|
|
@ -43,7 +43,8 @@ public:
|
||||||
// EntityItemProperty related helpers
|
// EntityItemProperty related helpers
|
||||||
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
|
||||||
ScriptEngine* engine, bool skipDefaults,
|
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;
|
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
|
||||||
|
|
||||||
void merge(const SkyboxPropertyGroup& other);
|
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_glUniformMatrix3fv),
|
||||||
(&::gpu::gl::GLBackend::do_glUniformMatrix4fv),
|
(&::gpu::gl::GLBackend::do_glUniformMatrix4fv),
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_glColor4f),
|
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_pushProfileRange),
|
(&::gpu::gl::GLBackend::do_pushProfileRange),
|
||||||
(&::gpu::gl::GLBackend::do_popProfileRange),
|
(&::gpu::gl::GLBackend::do_popProfileRange),
|
||||||
};
|
};
|
||||||
|
@ -838,22 +836,6 @@ void GLBackend::do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) {
|
||||||
(void)CHECK_GL_ERROR();
|
(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 {
|
void GLBackend::releaseBuffer(GLuint id, Size size) const {
|
||||||
Lock lock(_trashMutex);
|
Lock lock(_trashMutex);
|
||||||
_currentFrameTrash.buffersTrash.push_back({ id, size });
|
_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_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_glUniformMatrix4fv(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
|
// The State setters called by the GLState::Commands when a new state is assigned
|
||||||
virtual void do_setStateFillMode(int32 mode) final;
|
virtual void do_setStateFillMode(int32 mode) final;
|
||||||
virtual void do_setStateCullMode(int32 mode) final;
|
virtual void do_setStateCullMode(int32 mode) final;
|
||||||
|
@ -350,8 +348,6 @@ protected:
|
||||||
struct InputStageState {
|
struct InputStageState {
|
||||||
bool _invalidFormat { true };
|
bool _invalidFormat { true };
|
||||||
bool _lastUpdateStereoState { false };
|
bool _lastUpdateStereoState { false };
|
||||||
bool _hasColorAttribute { false };
|
|
||||||
bool _hadColorAttribute { false };
|
|
||||||
FormatReference _format { GPU_REFERENCE_INIT_VALUE };
|
FormatReference _format { GPU_REFERENCE_INIT_VALUE };
|
||||||
std::string _formatKey;
|
std::string _formatKey;
|
||||||
|
|
||||||
|
@ -368,8 +364,6 @@ protected:
|
||||||
std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides;
|
std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides;
|
||||||
std::array<GLuint, MAX_NUM_INPUT_BUFFERS> _bufferVBOs;
|
std::array<GLuint, MAX_NUM_INPUT_BUFFERS> _bufferVBOs;
|
||||||
|
|
||||||
glm::vec4 _colorAttribute { 1.0f };
|
|
||||||
|
|
||||||
BufferReference _indexBuffer;
|
BufferReference _indexBuffer;
|
||||||
Offset _indexBufferOffset { 0 };
|
Offset _indexBufferOffset { 0 };
|
||||||
Type _indexBufferType { UINT32 };
|
Type _indexBufferType { UINT32 };
|
||||||
|
|
|
@ -103,9 +103,6 @@ void GLBackend::resetInputStage() {
|
||||||
reset(_input._format);
|
reset(_input._format);
|
||||||
_input._formatKey.clear();
|
_input._formatKey.clear();
|
||||||
_input._invalidFormat = false;
|
_input._invalidFormat = false;
|
||||||
_input._hasColorAttribute = false;
|
|
||||||
_input._hadColorAttribute = false;
|
|
||||||
_input._colorAttribute = vec4(1.0f);
|
|
||||||
_input._attributeActivation.reset();
|
_input._attributeActivation.reset();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < _input._buffers.size(); i++) {
|
for (uint32_t i = 0; i < _input._buffers.size(); i++) {
|
||||||
|
@ -163,8 +160,6 @@ void GLBackend::updateInput() {
|
||||||
#endif
|
#endif
|
||||||
_input._lastUpdateStereoState = isStereoNow;
|
_input._lastUpdateStereoState = isStereoNow;
|
||||||
|
|
||||||
bool hasColorAttribute = _input._hasColorAttribute;
|
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
if (_input._invalidFormat) {
|
||||||
InputStageState::ActivationCache newActivation;
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
@ -194,8 +189,6 @@ void GLBackend::updateInput() {
|
||||||
|
|
||||||
GLenum perLocationSize = attrib._element.getLocationSize();
|
GLenum perLocationSize = attrib._element.getLocationSize();
|
||||||
|
|
||||||
hasColorAttribute |= slot == Stream::COLOR;
|
|
||||||
|
|
||||||
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
GLuint attriNum = (GLuint)(slot + locNum);
|
GLuint attriNum = (GLuint)(slot + locNum);
|
||||||
newActivation.set(attriNum);
|
newActivation.set(attriNum);
|
||||||
|
@ -226,12 +219,6 @@ void GLBackend::updateInput() {
|
||||||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||||
#endif
|
#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
|
// Manage Activation what was and what is expected now
|
||||||
|
@ -253,9 +240,6 @@ void GLBackend::updateInput() {
|
||||||
_stats._ISNumFormatChanges++;
|
_stats._ISNumFormatChanges++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_input._hadColorAttribute = hasColorAttribute;
|
|
||||||
_input._hasColorAttribute = false;
|
|
||||||
|
|
||||||
if (_input._invalidBuffers.any()) {
|
if (_input._invalidBuffers.any()) {
|
||||||
auto vbo = _input._bufferVBOs.data();
|
auto vbo = _input._bufferVBOs.data();
|
||||||
auto offset = _input._bufferOffsets.data();
|
auto offset = _input._bufferOffsets.data();
|
||||||
|
|
|
@ -33,8 +33,6 @@ void GL41Backend::updateInput() {
|
||||||
#endif
|
#endif
|
||||||
_input._lastUpdateStereoState = isStereoNow;
|
_input._lastUpdateStereoState = isStereoNow;
|
||||||
|
|
||||||
bool hasColorAttribute = _input._hasColorAttribute;
|
|
||||||
|
|
||||||
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
||||||
|
|
||||||
auto format = acquire(_input._format);
|
auto format = acquire(_input._format);
|
||||||
|
@ -110,8 +108,6 @@ void GL41Backend::updateInput() {
|
||||||
uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]);
|
uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]);
|
||||||
GLboolean isNormalized = attrib._element.isNormalized();
|
GLboolean isNormalized = attrib._element.isNormalized();
|
||||||
|
|
||||||
hasColorAttribute |= slot == Stream::COLOR;
|
|
||||||
|
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
if (attrib._element.isInteger()) {
|
if (attrib._element.isInteger()) {
|
||||||
glVertexAttribIPointer(slot + (GLuint)locNum, count, type, stride,
|
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
|
// everything format related should be in sync now
|
||||||
_input._invalidFormat = false;
|
_input._invalidFormat = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_input._hadColorAttribute = hasColorAttribute;
|
|
||||||
_input._hasColorAttribute = false;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,6 @@ void GL45Backend::updateInput() {
|
||||||
#endif
|
#endif
|
||||||
_input._lastUpdateStereoState = isStereoNow;
|
_input._lastUpdateStereoState = isStereoNow;
|
||||||
|
|
||||||
bool hasColorAttribute = _input._hasColorAttribute;
|
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
if (_input._invalidFormat) {
|
||||||
InputStageState::ActivationCache newActivation;
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
@ -66,8 +64,6 @@ void GL45Backend::updateInput() {
|
||||||
|
|
||||||
GLenum perLocationSize = attrib._element.getLocationSize();
|
GLenum perLocationSize = attrib._element.getLocationSize();
|
||||||
|
|
||||||
hasColorAttribute |= slot == Stream::COLOR;
|
|
||||||
|
|
||||||
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
GLuint attriNum = (GLuint)(slot + locNum);
|
GLuint attriNum = (GLuint)(slot + locNum);
|
||||||
newActivation.set(attriNum);
|
newActivation.set(attriNum);
|
||||||
|
@ -98,12 +94,6 @@ void GL45Backend::updateInput() {
|
||||||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||||
#endif
|
#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
|
// Manage Activation what was and what is expected now
|
||||||
|
@ -125,9 +115,6 @@ void GL45Backend::updateInput() {
|
||||||
_stats._ISNumFormatChanges++;
|
_stats._ISNumFormatChanges++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_input._hadColorAttribute = hasColorAttribute;
|
|
||||||
_input._hasColorAttribute = false;
|
|
||||||
|
|
||||||
if (_input._invalidBuffers.any()) {
|
if (_input._invalidBuffers.any()) {
|
||||||
auto vbo = _input._bufferVBOs.data();
|
auto vbo = _input._bufferVBOs.data();
|
||||||
auto offset = _input._bufferOffsets.data();
|
auto offset = _input._bufferOffsets.data();
|
||||||
|
|
|
@ -687,15 +687,6 @@ void Batch::_glUniformMatrix4fv(int32 location, int count, uint8 transpose, cons
|
||||||
_params.emplace_back(location);
|
_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) {
|
void Batch::finishFrame(BufferUpdates& updates) {
|
||||||
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
|
|
||||||
|
|
|
@ -287,8 +287,6 @@ public:
|
||||||
_glUniformMatrix3fv(location, 1, false, glm::value_ptr(v));
|
_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
|
// Maybe useful but shoudln't be public. Please convince me otherwise
|
||||||
// Well porting to gles i need it...
|
// Well porting to gles i need it...
|
||||||
void runLambda(std::function<void()> f);
|
void runLambda(std::function<void()> f);
|
||||||
|
@ -363,8 +361,6 @@ public:
|
||||||
COMMAND_glUniformMatrix3fv,
|
COMMAND_glUniformMatrix3fv,
|
||||||
COMMAND_glUniformMatrix4fv,
|
COMMAND_glUniformMatrix4fv,
|
||||||
|
|
||||||
COMMAND_glColor4f,
|
|
||||||
|
|
||||||
COMMAND_pushProfileRange,
|
COMMAND_pushProfileRange,
|
||||||
COMMAND_popProfileRange,
|
COMMAND_popProfileRange,
|
||||||
|
|
||||||
|
@ -406,7 +402,7 @@ public:
|
||||||
public:
|
public:
|
||||||
typedef T Data;
|
typedef T Data;
|
||||||
Data _data;
|
Data _data;
|
||||||
Cache<T>(const Data& data) : _data(data) {}
|
Cache(const Data& data) : _data(data) {}
|
||||||
static size_t _max;
|
static size_t _max;
|
||||||
|
|
||||||
class Vector {
|
class Vector {
|
||||||
|
|
|
@ -387,8 +387,8 @@ public:
|
||||||
U t;
|
U t;
|
||||||
return std::make_shared<gpu::Buffer>(sizeof(U), (const gpu::Byte*) &t, sizeof(U));
|
return std::make_shared<gpu::Buffer>(sizeof(U), (const gpu::Byte*) &t, sizeof(U));
|
||||||
}
|
}
|
||||||
~StructBuffer<T>() {};
|
~StructBuffer() {};
|
||||||
StructBuffer<T>() : gpu::BufferView(makeBuffer<T>()) {}
|
StructBuffer() : gpu::BufferView(makeBuffer<T>()) {}
|
||||||
|
|
||||||
|
|
||||||
T& edit() {
|
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 {
|
Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const StereoState& _stereo, const Transform& xformView, Vec2 normalizedJitter) const {
|
||||||
TransformCamera result = *this;
|
TransformCamera result = *this;
|
||||||
Transform offsetTransform = xformView;
|
Transform offsetTransform = xformView;
|
||||||
if (!_stereo._skybox) {
|
glm::vec3 eyePosition = extractTranslation(_stereo._eyeViews[eye]);
|
||||||
offsetTransform.postTranslate(-Vec3(_stereo._eyeViews[eye][3]));
|
glm::quat eyeOrientation = glmExtractRotation(_stereo._eyeViews[eye]);
|
||||||
|
if (!_stereo._skybox)
|
||||||
|
{
|
||||||
|
offsetTransform.postRotate(eyeOrientation).postTranslate(eyePosition);
|
||||||
} else {
|
} 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
|
// 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];
|
result._projection = _stereo._eyeProjections[eye];
|
||||||
normalizedJitter.x *= 2.0f;
|
normalizedJitter.x *= 2.0f;
|
||||||
|
|
|
@ -201,8 +201,6 @@ constexpr const char* COMMAND_NAMES[] = {
|
||||||
"glUniformMatrix3fv",
|
"glUniformMatrix3fv",
|
||||||
"glUniformMatrix4fv",
|
"glUniformMatrix4fv",
|
||||||
|
|
||||||
"glColor4f",
|
|
||||||
|
|
||||||
"pushProfileRange",
|
"pushProfileRange",
|
||||||
"popProfileRange",
|
"popProfileRange",
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@ Mesh::Mesh() :
|
||||||
_vertexBuffer(gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)),
|
_vertexBuffer(gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)),
|
||||||
_indexBuffer(gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::INDEX)),
|
_indexBuffer(gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::INDEX)),
|
||||||
_partBuffer(gpu::Element(gpu::VEC4, gpu::UINT32, gpu::PART)) {
|
_partBuffer(gpu::Element(gpu::VEC4, gpu::UINT32, gpu::PART)) {
|
||||||
|
const uint32_t compactColor = 0xFFFFFFFF;
|
||||||
|
_colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::Mesh(const Mesh& mesh) :
|
Mesh::Mesh(const Mesh& mesh) :
|
||||||
|
@ -26,7 +28,8 @@ Mesh::Mesh(const Mesh& mesh) :
|
||||||
_vertexBuffer(mesh._vertexBuffer),
|
_vertexBuffer(mesh._vertexBuffer),
|
||||||
_attributeBuffers(mesh._attributeBuffers),
|
_attributeBuffers(mesh._attributeBuffers),
|
||||||
_indexBuffer(mesh._indexBuffer),
|
_indexBuffer(mesh._indexBuffer),
|
||||||
_partBuffer(mesh._partBuffer) {
|
_partBuffer(mesh._partBuffer),
|
||||||
|
_colorBuffer(mesh._colorBuffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::~Mesh() {
|
Mesh::~Mesh() {
|
||||||
|
@ -39,6 +42,13 @@ void Mesh::setVertexFormatAndStream(const gpu::Stream::FormatPointer& vf, const
|
||||||
auto attrib = _vertexFormat->getAttribute(gpu::Stream::POSITION);
|
auto attrib = _vertexFormat->getAttribute(gpu::Stream::POSITION);
|
||||||
_vertexBuffer = BufferView(vbs->getBuffers()[attrib._channel], vbs->getOffsets()[attrib._channel], vbs->getBuffers()[attrib._channel]->getSize(),
|
_vertexBuffer = BufferView(vbs->getBuffers()[attrib._channel], vbs->getOffsets()[attrib._channel], vbs->getBuffers()[attrib._channel]->getSize(),
|
||||||
(gpu::uint16) vbs->getStrides()[attrib._channel], attrib._element);
|
(gpu::uint16) vbs->getStrides()[attrib._channel], attrib._element);
|
||||||
|
|
||||||
|
// We require meshes to have a color attribute. If they don't, we default to white.
|
||||||
|
if (!_vertexFormat->hasAttribute(gpu::Stream::COLOR)) {
|
||||||
|
int channelNum = _vertexStream.getNumBuffers();
|
||||||
|
_vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE);
|
||||||
|
_vertexStream.addBuffer(_colorBuffer, 0, _vertexFormat->getChannels().at(channelNum)._stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::setVertexBuffer(const BufferView& buffer) {
|
void Mesh::setVertexBuffer(const BufferView& buffer) {
|
||||||
|
@ -98,6 +108,12 @@ void Mesh::evalVertexStream() {
|
||||||
_vertexStream.addBuffer(view._buffer, view._offset, stride);
|
_vertexStream.addBuffer(view._buffer, view._offset, stride);
|
||||||
channelNum++;
|
channelNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We require meshes to have a color attribute. If they don't, we default to white.
|
||||||
|
if (!_vertexFormat->hasAttribute(gpu::Stream::COLOR)) {
|
||||||
|
_vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE);
|
||||||
|
_vertexStream.addBuffer(_colorBuffer, 0, _vertexFormat->getChannels().at(channelNum)._stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::setIndexBuffer(const BufferView& buffer) {
|
void Mesh::setIndexBuffer(const BufferView& buffer) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue