mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-16 21:48:44 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into migrateEditFiles
This commit is contained in:
commit
feaea12b24
21 changed files with 461 additions and 124 deletions
|
@ -33,7 +33,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
|
||||||
|
|
||||||
Download and install the latest version of CMake 3.9.
|
Download and install the latest version of CMake 3.9.
|
||||||
|
|
||||||
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.9 Version page](https://cmake.org/files/v3.9/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
|
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
|
||||||
|
|
||||||
### Step 3. Create VCPKG environment variable
|
### Step 3. Create VCPKG environment variable
|
||||||
In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.
|
In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.
|
||||||
|
|
|
@ -739,6 +739,10 @@ void DomainServer::setupNodeListAndAssignments() {
|
||||||
|
|
||||||
connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded);
|
connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded);
|
||||||
connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
|
connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
|
||||||
|
connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, this,
|
||||||
|
[this](const HifiSockAddr& localSockAddr) {
|
||||||
|
DependencyManager::get<LimitedNodeList>()->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, localSockAddr.getPort());
|
||||||
|
});
|
||||||
|
|
||||||
// register as the packet receiver for the types we want
|
// register as the packet receiver for the types we want
|
||||||
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
|
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
|
||||||
|
|
|
@ -94,6 +94,7 @@ Item {
|
||||||
text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName
|
text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName
|
||||||
maximumLength: 256
|
maximumLength: 256
|
||||||
clip: true
|
clip: true
|
||||||
|
selectByMouse: true
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
if (MyAvatar.displayName !== text) {
|
if (MyAvatar.displayName !== text) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import "./audio" as AudioSettings
|
||||||
import "./general" as GeneralSettings
|
import "./general" as GeneralSettings
|
||||||
import "./vr" as VrSettings
|
import "./vr" as VrSettings
|
||||||
import "./dev" as DevSettings
|
import "./dev" as DevSettings
|
||||||
|
import "./about" as AboutSettings
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
property string activeTabView: "generalTabView"
|
property string activeTabView: "generalTabView"
|
||||||
|
@ -76,6 +77,10 @@ Rectangle {
|
||||||
tabTitle: "VR"
|
tabTitle: "VR"
|
||||||
tabViewName: "vrTabView"
|
tabViewName: "vrTabView"
|
||||||
}
|
}
|
||||||
|
ListElement {
|
||||||
|
tabTitle: "About"
|
||||||
|
tabViewName: "aboutTabView"
|
||||||
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
tabTitle: "Dev"
|
tabTitle: "Dev"
|
||||||
tabViewName: "devTabView"
|
tabViewName: "devTabView"
|
||||||
|
@ -103,7 +108,7 @@ Rectangle {
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled)
|
visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled)
|
||||||
|
|
||||||
width: tabTitleText.paintedWidth + 64
|
width: tabTitleText.paintedWidth + 32
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
HifiStylesUit.GraphikRegular {
|
HifiStylesUit.GraphikRegular {
|
||||||
|
@ -163,6 +168,12 @@ Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AboutSettings.About {
|
||||||
|
id: aboutTabViewContainer
|
||||||
|
visible: activeTabView === "aboutTabView"
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
SimplifiedControls.VerticalScrollBar {
|
SimplifiedControls.VerticalScrollBar {
|
||||||
parent: {
|
parent: {
|
||||||
if (activeTabView === "generalTabView") {
|
if (activeTabView === "generalTabView") {
|
||||||
|
@ -173,6 +184,8 @@ Rectangle {
|
||||||
vrTabViewContainer
|
vrTabViewContainer
|
||||||
} else if (activeTabView === "devTabView") {
|
} else if (activeTabView === "devTabView") {
|
||||||
devTabViewContainer
|
devTabViewContainer
|
||||||
|
} else if (activeTabView === "aboutTabView") {
|
||||||
|
aboutTabViewContainer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
//
|
||||||
|
// About.qml
|
||||||
|
//
|
||||||
|
// Created by Zach Fox on 2019-06-18
|
||||||
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import "../../simplifiedConstants" as SimplifiedConstants
|
||||||
|
import "../../simplifiedControls" as SimplifiedControls
|
||||||
|
import stylesUit 1.0 as HifiStylesUit
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: root
|
||||||
|
contentWidth: parent.width
|
||||||
|
contentHeight: aboutColumnLayout.height
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
root.contentX = 0;
|
||||||
|
root.contentY = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SimplifiedConstants.SimplifiedConstants {
|
||||||
|
id: simplifiedUI
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: aboutColumnLayout
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 26
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 26
|
||||||
|
anchors.top: parent.top
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: "images/logo.png"
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.preferredWidth: 200
|
||||||
|
Layout.preferredHeight: 150
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
mipmap: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: platformInfoContainer
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Layout.bottomMargin: 24
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikSemiBold {
|
||||||
|
text: "Version " + Window.checkVersion()
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikSemiBold {
|
||||||
|
text: "Platform Info"
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
Layout.topMargin: 8
|
||||||
|
Layout.bottomMargin: 8
|
||||||
|
height: paintedHeight
|
||||||
|
size: 22
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>Computer Vendor/Model:</b>"
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var computer = JSON.parse(PlatformInfo.getComputer());
|
||||||
|
var computerVendor = computer.vendor;
|
||||||
|
if (computerVendor.length === 0) {
|
||||||
|
computerVendor = "Unknown";
|
||||||
|
}
|
||||||
|
var computerModel = computer.model;
|
||||||
|
if (computerModel.length === 0) {
|
||||||
|
computerModel = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
text = "<b>Computer Vendor/Model:</b> " + computerVendor + "/" + computerModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>Profiled Platform Tier:</b> " + PlatformInfo.getTierProfiled()
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>OS Type:</b> " + PlatformInfo.getOperatingSystemType()
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>CPU:</b> " + PlatformInfo.getCPUBrand()
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b># CPUs:</b> " + PlatformInfo.getNumCPUs()
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b># CPU Cores:</b> " + PlatformInfo.getNumLogicalCores()
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>RAM:</b> " + PlatformInfo.getTotalSystemMemoryMB() + " MB"
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>GPU:</b> " + PlatformInfo.getGraphicsCardType()
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.GraphikRegular {
|
||||||
|
text: "<b>VR Hand Controllers:</b> " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"))
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
height: paintedHeight
|
||||||
|
size: 16
|
||||||
|
color: simplifiedUI.colors.text.white
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
SimplifiedControls.Button {
|
||||||
|
Layout.topMargin: 8
|
||||||
|
width: 200
|
||||||
|
height: 32
|
||||||
|
text: "Copy to Clipboard"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
Window.copyToClipboard(root.buildPlatformInfoTextToCopy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPlatformInfoTextToCopy() {
|
||||||
|
var textToCopy = "**About Interface**\n";
|
||||||
|
textToCopy += "Interface Version: " + Window.checkVersion() + "\n";
|
||||||
|
textToCopy += "\n**Platform Info**\n";
|
||||||
|
|
||||||
|
var computer = JSON.parse(PlatformInfo.getComputer());
|
||||||
|
var computerVendor = computer.vendor;
|
||||||
|
if (computerVendor.length === 0) {
|
||||||
|
computerVendor = "Unknown";
|
||||||
|
}
|
||||||
|
var computerModel = computer.model;
|
||||||
|
if (computerModel.length === 0) {
|
||||||
|
computerModel = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n";
|
||||||
|
textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n";
|
||||||
|
textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n";
|
||||||
|
textToCopy += "CPU: " + PlatformInfo.getCPUBrand() + "\n";
|
||||||
|
textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n";
|
||||||
|
textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n";
|
||||||
|
textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n";
|
||||||
|
textToCopy += "GPU: " + PlatformInfo.getGraphicsCardType() + "\n";
|
||||||
|
textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"));
|
||||||
|
|
||||||
|
return textToCopy;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -1416,6 +1416,10 @@ void MyAvatar::setEnableDebugDrawAnimPose(bool isEnabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setDebugDrawAnimPoseName(QString poseName) {
|
||||||
|
_debugDrawAnimPoseName.set(poseName);
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
|
void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
|
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
@ -3086,15 +3090,26 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enableDebugDrawAnimPose && animSkeleton) {
|
if (_enableDebugDrawAnimPose && animSkeleton) {
|
||||||
// build absolute AnimPoseVec from rig
|
|
||||||
AnimPoseVec absPoses;
|
AnimPoseVec absPoses;
|
||||||
const Rig& rig = _skeletonModel->getRig();
|
const Rig& rig = _skeletonModel->getRig();
|
||||||
|
const glm::vec4 CYAN(0.1f, 0.6f, 0.6f, 1.0f);
|
||||||
|
|
||||||
|
QString name = _debugDrawAnimPoseName.get();
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
// build absolute AnimPoseVec from rig transforms. i.e. the same that are used for rendering.
|
||||||
absPoses.reserve(rig.getJointStateCount());
|
absPoses.reserve(rig.getJointStateCount());
|
||||||
for (int i = 0; i < rig.getJointStateCount(); i++) {
|
for (int i = 0; i < rig.getJointStateCount(); i++) {
|
||||||
absPoses.push_back(AnimPose(rig.getJointTransform(i)));
|
absPoses.push_back(AnimPose(rig.getJointTransform(i)));
|
||||||
}
|
}
|
||||||
glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f);
|
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN);
|
||||||
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, cyan);
|
} else {
|
||||||
|
AnimNode::ConstPointer node = rig.findAnimNodeByName(name);
|
||||||
|
if (node) {
|
||||||
|
rig.buildAbsoluteRigPoses(node->getPoses(), absPoses);
|
||||||
|
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2018,12 +2018,20 @@ public slots:
|
||||||
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Displays animation debug graphics.
|
* Displays animation debug graphics. By default it shows the animation poses used for rendering.
|
||||||
|
* However, the property MyAvatar.setDebugDrawAnimPoseName can be used to draw a specific animation node.
|
||||||
* @function MyAvatar.setEnableDebugDrawAnimPose
|
* @function MyAvatar.setEnableDebugDrawAnimPose
|
||||||
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
|
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
|
||||||
*/
|
*/
|
||||||
void setEnableDebugDrawAnimPose(bool isEnabled);
|
void setEnableDebugDrawAnimPose(bool isEnabled);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* If set it determines which animation debug graphics to draw, when MyAvatar.setEnableDebugDrawAnimPose is set to true.
|
||||||
|
* @function MyAvatar.setDebugDrawAnimPoseName
|
||||||
|
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
|
||||||
|
*/
|
||||||
|
void setDebugDrawAnimPoseName(QString poseName);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Displays position debug graphics.
|
* Displays position debug graphics.
|
||||||
* @function MyAvatar.setEnableDebugDrawPosition
|
* @function MyAvatar.setEnableDebugDrawPosition
|
||||||
|
@ -2666,6 +2674,8 @@ private:
|
||||||
bool _enableDebugDrawIKChains { false };
|
bool _enableDebugDrawIKChains { false };
|
||||||
bool _enableDebugDrawDetailedCollision { false };
|
bool _enableDebugDrawDetailedCollision { false };
|
||||||
|
|
||||||
|
ThreadSafeValueCache<QString> _debugDrawAnimPoseName;
|
||||||
|
|
||||||
mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state?
|
mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state?
|
||||||
|
|
||||||
AudioListenerMode _audioListenerMode;
|
AudioListenerMode _audioListenerMode;
|
||||||
|
|
|
@ -10,10 +10,13 @@
|
||||||
|
|
||||||
#include "AnimClip.h"
|
#include "AnimClip.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "GLMHelpers.h"
|
#include "GLMHelpers.h"
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
#include "AnimUtil.h"
|
#include "AnimUtil.h"
|
||||||
|
|
||||||
|
|
||||||
AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) :
|
AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) :
|
||||||
AnimNode(AnimNode::Type::Clip, id),
|
AnimNode(AnimNode::Type::Clip, id),
|
||||||
_startFrame(startFrame),
|
_startFrame(startFrame),
|
||||||
|
@ -107,6 +110,19 @@ static std::vector<int> buildJointIndexMap(const AnimSkeleton& dstSkeleton, cons
|
||||||
return jointIndexMap;
|
return jointIndexMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_CUSTOM_ASSERT
|
||||||
|
#undef ASSERT
|
||||||
|
#define ASSERT(x) \
|
||||||
|
do { \
|
||||||
|
if (!(x)) { \
|
||||||
|
int* bad_ptr = 0; \
|
||||||
|
*bad_ptr = 0x0badf00d; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define ASSERT assert
|
||||||
|
#endif
|
||||||
|
|
||||||
void AnimClip::copyFromNetworkAnim() {
|
void AnimClip::copyFromNetworkAnim() {
|
||||||
assert(_networkAnim && _networkAnim->isLoaded() && _skeleton);
|
assert(_networkAnim && _networkAnim->isLoaded() && _skeleton);
|
||||||
_anim.clear();
|
_anim.clear();
|
||||||
|
@ -165,11 +181,14 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
|
|
||||||
for (int frame = 0; frame < animFrameCount; frame++) {
|
for (int frame = 0; frame < animFrameCount; frame++) {
|
||||||
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
||||||
|
ASSERT(frame >= 0 && frame < (int)animModel.animationFrames.size());
|
||||||
|
|
||||||
// extract the full rotations from the animFrame (including pre and post rotations from the animModel).
|
// extract the full rotations from the animFrame (including pre and post rotations from the animModel).
|
||||||
std::vector<glm::quat> animRotations;
|
std::vector<glm::quat> animRotations;
|
||||||
animRotations.reserve(animJointCount);
|
animRotations.reserve(animJointCount);
|
||||||
for (int i = 0; i < animJointCount; i++) {
|
for (int i = 0; i < animJointCount; i++) {
|
||||||
|
ASSERT(i >= 0 && i < (int)animModel.joints.size());
|
||||||
|
ASSERT(i >= 0 && i < (int)animFrame.rotations.size());
|
||||||
animRotations.push_back(animModel.joints[i].preRotation * animFrame.rotations[i] * animModel.joints[i].postRotation);
|
animRotations.push_back(animModel.joints[i].preRotation * animFrame.rotations[i] * animModel.joints[i].postRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,10 +199,12 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
std::vector<glm::quat> avatarRotations;
|
std::vector<glm::quat> avatarRotations;
|
||||||
avatarRotations.reserve(avatarJointCount);
|
avatarRotations.reserve(avatarJointCount);
|
||||||
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
||||||
|
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size());
|
||||||
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
||||||
if (animJointIndex >= 0) {
|
if (animJointIndex >= 0) {
|
||||||
// This joint is in both animation and avatar.
|
// This joint is in both animation and avatar.
|
||||||
// Set the absolute rotation directly
|
// Set the absolute rotation directly
|
||||||
|
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animRotations.size());
|
||||||
avatarRotations.push_back(animRotations[animJointIndex]);
|
avatarRotations.push_back(animRotations[animJointIndex]);
|
||||||
} else {
|
} else {
|
||||||
// This joint is NOT in the animation at all.
|
// This joint is NOT in the animation at all.
|
||||||
|
@ -192,6 +213,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
glm::quat avatarParentAbsoluteRot;
|
glm::quat avatarParentAbsoluteRot;
|
||||||
int avatarParentJointIndex = avatarSkeleton->getParentIndex(avatarJointIndex);
|
int avatarParentJointIndex = avatarSkeleton->getParentIndex(avatarJointIndex);
|
||||||
if (avatarParentJointIndex >= 0) {
|
if (avatarParentJointIndex >= 0) {
|
||||||
|
ASSERT(avatarParentJointIndex >= 0 && avatarParentJointIndex < (int)avatarRotations.size());
|
||||||
avatarParentAbsoluteRot = avatarRotations[avatarParentJointIndex];
|
avatarParentAbsoluteRot = avatarRotations[avatarParentJointIndex];
|
||||||
}
|
}
|
||||||
avatarRotations.push_back(avatarParentAbsoluteRot * avatarRelativeDefaultRot);
|
avatarRotations.push_back(avatarParentAbsoluteRot * avatarRelativeDefaultRot);
|
||||||
|
@ -201,6 +223,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
// convert avatar rotations into relative frame
|
// convert avatar rotations into relative frame
|
||||||
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
||||||
|
|
||||||
|
ASSERT(frame >= 0 && frame < (int)_anim.size());
|
||||||
_anim[frame].reserve(avatarJointCount);
|
_anim[frame].reserve(avatarJointCount);
|
||||||
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
||||||
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
||||||
|
@ -209,12 +232,15 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
glm::vec3 relativeScale = avatarDefaultPose.scale();
|
glm::vec3 relativeScale = avatarDefaultPose.scale();
|
||||||
|
|
||||||
glm::vec3 relativeTranslation;
|
glm::vec3 relativeTranslation;
|
||||||
|
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size());
|
||||||
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
||||||
if (animJointIndex >= 0) {
|
if (animJointIndex >= 0) {
|
||||||
// This joint is in both animation and avatar.
|
// This joint is in both animation and avatar.
|
||||||
|
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animFrame.translations.size());
|
||||||
const glm::vec3& animTrans = animFrame.translations[animJointIndex];
|
const glm::vec3& animTrans = animFrame.translations[animJointIndex];
|
||||||
|
|
||||||
// retarget translation from animation to avatar
|
// retarget translation from animation to avatar
|
||||||
|
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animModel.animationFrames[0].translations.size());
|
||||||
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
|
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
|
||||||
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,6 +250,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// build the final pose
|
// build the final pose
|
||||||
|
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarRotations.size());
|
||||||
_anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation));
|
_anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,8 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AnimPoseVec& getPoses() const { return getPosesInternal(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void setCurrentFrameInternal(float frame) {}
|
virtual void setCurrentFrameInternal(float frame) {}
|
||||||
|
|
|
@ -2232,6 +2232,14 @@ void Rig::initAnimGraph(const QUrl& url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimNode::ConstPointer Rig::findAnimNodeByName(const QString& name) const {
|
||||||
|
if (_animNode) {
|
||||||
|
return _animNode->findByName(name);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
|
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
|
||||||
if (_animSkeleton && _rootJointIndex >= 0) {
|
if (_animSkeleton && _rootJointIndex >= 0) {
|
||||||
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans();
|
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans();
|
||||||
|
@ -2258,7 +2266,7 @@ void Rig::applyOverridePoses() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const {
|
||||||
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
||||||
if (!_animSkeleton) {
|
if (!_animSkeleton) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -196,6 +196,7 @@ public:
|
||||||
void initAnimGraph(const QUrl& url);
|
void initAnimGraph(const QUrl& url);
|
||||||
|
|
||||||
AnimNode::ConstPointer getAnimNode() const { return _animNode; }
|
AnimNode::ConstPointer getAnimNode() const { return _animNode; }
|
||||||
|
AnimNode::ConstPointer findAnimNodeByName(const QString& name) const;
|
||||||
AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
|
AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
|
||||||
QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList);
|
QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList);
|
||||||
void removeAnimationStateHandler(QScriptValue handler);
|
void removeAnimationStateHandler(QScriptValue handler);
|
||||||
|
@ -243,7 +244,7 @@ public:
|
||||||
Flow& getFlow() { return _internalFlow; }
|
Flow& getFlow() { return _internalFlow; }
|
||||||
|
|
||||||
float getUnscaledEyeHeight() const;
|
float getUnscaledEyeHeight() const;
|
||||||
|
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onLoadComplete();
|
void onLoadComplete();
|
||||||
|
@ -252,7 +253,6 @@ protected:
|
||||||
bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); }
|
bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); }
|
||||||
void updateAnimationStateHandlers();
|
void updateAnimationStateHandlers();
|
||||||
void applyOverridePoses();
|
void applyOverridePoses();
|
||||||
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut);
|
|
||||||
|
|
||||||
void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
|
void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
|
||||||
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||||
|
|
|
@ -35,16 +35,6 @@ static const double SQRT2 = 1.41421356237309504880;
|
||||||
static const double FIXQ31 = 2147483648.0;
|
static const double FIXQ31 = 2147483648.0;
|
||||||
static const double FIXQ32 = 4294967296.0;
|
static const double FIXQ32 = 4294967296.0;
|
||||||
|
|
||||||
// Round an integer to the next power-of-two, at compile time.
|
|
||||||
// VS2013 does not support constexpr so macros are used instead.
|
|
||||||
#define SETBITS0(x) (x)
|
|
||||||
#define SETBITS1(x) (SETBITS0(x) | (SETBITS0(x) >> 1))
|
|
||||||
#define SETBITS2(x) (SETBITS1(x) | (SETBITS1(x) >> 2))
|
|
||||||
#define SETBITS3(x) (SETBITS2(x) | (SETBITS2(x) >> 4))
|
|
||||||
#define SETBITS4(x) (SETBITS3(x) | (SETBITS3(x) >> 8))
|
|
||||||
#define SETBITS5(x) (SETBITS4(x) | (SETBITS4(x) >> 16))
|
|
||||||
#define NEXTPOW2(x) (SETBITS5((x) - 1) + 1)
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allpass delay modulation
|
// Allpass delay modulation
|
||||||
//
|
//
|
||||||
|
@ -111,6 +101,18 @@ static const int M_AP19 = 113;
|
||||||
static const int M_AP20 = 107;
|
static const int M_AP20 = 107;
|
||||||
static const int M_AP21 = 127;
|
static const int M_AP21 = 127;
|
||||||
|
|
||||||
|
// Round an integer to the next power-of-two, at compile time
|
||||||
|
constexpr uint32_t NEXTPOW2(uint32_t n) {
|
||||||
|
n -= 1;
|
||||||
|
n |= (n >> 1);
|
||||||
|
n |= (n >> 2);
|
||||||
|
n |= (n >> 4);
|
||||||
|
n |= (n >> 8);
|
||||||
|
n |= (n >> 16);
|
||||||
|
n += 1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Filter design tools using analog-matched response.
|
// Filter design tools using analog-matched response.
|
||||||
// All filter types approximate the s-plane response, including cutoff > Nyquist.
|
// All filter types approximate the s-plane response, including cutoff > Nyquist.
|
||||||
|
@ -1796,6 +1798,18 @@ void AudioReverb::render(float** inputs, float** outputs, int numFrames) {
|
||||||
|
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
|
||||||
|
// unaligned load/store without undefined behavior
|
||||||
|
static inline __m128i mm_loadu_si32(void const* mem_addr) {
|
||||||
|
int32_t temp;
|
||||||
|
memcpy(&temp, mem_addr, sizeof(int32_t));
|
||||||
|
return _mm_cvtsi32_si128(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mm_storeu_si32(void* mem_addr, __m128i a) {
|
||||||
|
int32_t temp = _mm_cvtsi128_si32(a);
|
||||||
|
memcpy(mem_addr, &temp, sizeof(int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
// convert int16_t to float, deinterleave stereo
|
// convert int16_t to float, deinterleave stereo
|
||||||
void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
||||||
__m128 scale = _mm_set1_ps(1/32768.0f);
|
__m128 scale = _mm_set1_ps(1/32768.0f);
|
||||||
|
@ -1816,7 +1830,7 @@ void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFra
|
||||||
_mm_storeu_ps(&outputs[1][i], f1);
|
_mm_storeu_ps(&outputs[1][i], f1);
|
||||||
}
|
}
|
||||||
for (; i < numFrames; i++) {
|
for (; i < numFrames; i++) {
|
||||||
__m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]);
|
__m128i a0 = mm_loadu_si32((__m128i*)&input[2*i]);
|
||||||
__m128i a1 = a0;
|
__m128i a1 = a0;
|
||||||
|
|
||||||
// deinterleave and sign-extend
|
// deinterleave and sign-extend
|
||||||
|
@ -1887,7 +1901,7 @@ void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames)
|
||||||
|
|
||||||
// interleave
|
// interleave
|
||||||
a0 = _mm_unpacklo_epi16(a0, a1);
|
a0 = _mm_unpacklo_epi16(a0, a1);
|
||||||
*(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0);
|
mm_storeu_si32((__m128i*)&output[2*i], a0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -793,6 +793,18 @@ int AudioSRC::multirateFilter4(const float* input0, const float* input1, const f
|
||||||
|
|
||||||
#include <emmintrin.h> // SSE2
|
#include <emmintrin.h> // SSE2
|
||||||
|
|
||||||
|
// unaligned load/store without undefined behavior
|
||||||
|
static inline __m128i mm_loadu_si32(void const* mem_addr) {
|
||||||
|
int32_t temp;
|
||||||
|
memcpy(&temp, mem_addr, sizeof(int32_t));
|
||||||
|
return _mm_cvtsi32_si128(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mm_storeu_si32(void* mem_addr, __m128i a) {
|
||||||
|
int32_t temp = _mm_cvtsi128_si32(a);
|
||||||
|
memcpy(mem_addr, &temp, sizeof(int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
// convert int16_t to float, deinterleave stereo
|
// convert int16_t to float, deinterleave stereo
|
||||||
void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
||||||
__m128 scale = _mm_set1_ps(1/32768.0f);
|
__m128 scale = _mm_set1_ps(1/32768.0f);
|
||||||
|
@ -839,7 +851,7 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames
|
||||||
_mm_storeu_ps(&outputs[1][i], f1);
|
_mm_storeu_ps(&outputs[1][i], f1);
|
||||||
}
|
}
|
||||||
for (; i < numFrames; i++) {
|
for (; i < numFrames; i++) {
|
||||||
__m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]);
|
__m128i a0 = mm_loadu_si32((__m128i*)&input[2*i]);
|
||||||
__m128i a1 = a0;
|
__m128i a1 = a0;
|
||||||
|
|
||||||
// deinterleave and sign-extend
|
// deinterleave and sign-extend
|
||||||
|
@ -878,9 +890,9 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames
|
||||||
_mm_storeu_ps(&outputs[3][i], _mm_shuffle_ps(f1, f3, _MM_SHUFFLE(3,1,3,1)));
|
_mm_storeu_ps(&outputs[3][i], _mm_shuffle_ps(f1, f3, _MM_SHUFFLE(3,1,3,1)));
|
||||||
}
|
}
|
||||||
for (; i < numFrames; i++) {
|
for (; i < numFrames; i++) {
|
||||||
__m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+0]);
|
__m128i a0 = mm_loadu_si32((__m128i*)&input[4*i+0]);
|
||||||
__m128i a1 = a0;
|
__m128i a1 = a0;
|
||||||
__m128i a2 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+2]);
|
__m128i a2 = mm_loadu_si32((__m128i*)&input[4*i+2]);
|
||||||
__m128i a3 = a2;
|
__m128i a3 = a2;
|
||||||
|
|
||||||
// deinterleave and sign-extend
|
// deinterleave and sign-extend
|
||||||
|
@ -986,7 +998,7 @@ void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) {
|
||||||
|
|
||||||
// interleave
|
// interleave
|
||||||
a0 = _mm_unpacklo_epi16(a0, a1);
|
a0 = _mm_unpacklo_epi16(a0, a1);
|
||||||
*(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0);
|
mm_storeu_si32((__m128i*)&output[2*i], a0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (_numChannels == 4) {
|
} else if (_numChannels == 4) {
|
||||||
|
|
|
@ -996,7 +996,7 @@ void LimitedNodeList::sendSTUNRequest() {
|
||||||
const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10;
|
const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10;
|
||||||
|
|
||||||
if (!_hasCompletedInitialSTUN) {
|
if (!_hasCompletedInitialSTUN) {
|
||||||
qCDebug(networking) << "Sending intial stun request to" << STUN_SERVER_HOSTNAME;
|
qCDebug(networking) << "Sending initial stun request to" << STUN_SERVER_HOSTNAME;
|
||||||
|
|
||||||
if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) {
|
if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) {
|
||||||
// we're still trying to do our initial STUN we're over the fail threshold
|
// we're still trying to do our initial STUN we're over the fail threshold
|
||||||
|
@ -1185,7 +1185,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
|
||||||
|
|
||||||
// We now setup a timer here to fire every so often to check that our IP address has not changed.
|
// We now setup a timer here to fire every so often to check that our IP address has not changed.
|
||||||
// Or, if we failed - if will check if we can eventually get a public socket
|
// Or, if we failed - if will check if we can eventually get a public socket
|
||||||
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
|
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 10 * 1000;
|
||||||
|
|
||||||
QTimer* stunOccasionalTimer = new QTimer { this };
|
QTimer* stunOccasionalTimer = new QTimer { this };
|
||||||
connect(stunOccasionalTimer, &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
|
connect(stunOccasionalTimer, &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
|
||||||
|
@ -1243,15 +1243,22 @@ void LimitedNodeList::errorTestingLocalSocket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
|
void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
|
||||||
if (sockAddr != _localSockAddr) {
|
if (sockAddr.getAddress() != _localSockAddr.getAddress()) {
|
||||||
|
|
||||||
if (_localSockAddr.isNull()) {
|
if (_localSockAddr.isNull()) {
|
||||||
qCInfo(networking) << "Local socket is" << sockAddr;
|
qCInfo(networking) << "Local socket is" << sockAddr;
|
||||||
|
_localSockAddr = sockAddr;
|
||||||
} else {
|
} else {
|
||||||
qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
|
qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
|
||||||
|
_localSockAddr = sockAddr;
|
||||||
|
if (_hasTCPCheckedLocalSocket) { // Force a port change for NAT:
|
||||||
|
reset();
|
||||||
|
_nodeSocket.rebind(0);
|
||||||
|
_localSockAddr.setPort(_nodeSocket.localPort());
|
||||||
|
qCInfo(networking) << "Local port changed to" << _localSockAddr.getPort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_localSockAddr = sockAddr;
|
|
||||||
emit localSockAddrChanged(_localSockAddr);
|
emit localSockAddrChanged(_localSockAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ using namespace udt;
|
||||||
|
|
||||||
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
|
_udpSocket(parent),
|
||||||
_readyReadBackupTimer(new QTimer(this)),
|
_readyReadBackupTimer(new QTimer(this)),
|
||||||
_shouldChangeSocketOptions(shouldChangeSocketOptions)
|
_shouldChangeSocketOptions(shouldChangeSocketOptions)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +51,7 @@ Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::bind(const QHostAddress& address, quint16 port) {
|
void Socket::bind(const QHostAddress& address, quint16 port) {
|
||||||
|
|
||||||
_udpSocket.bind(address, port);
|
_udpSocket.bind(address, port);
|
||||||
|
|
||||||
if (_shouldChangeSocketOptions) {
|
if (_shouldChangeSocketOptions) {
|
||||||
|
@ -75,7 +77,7 @@ void Socket::rebind() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::rebind(quint16 localPort) {
|
void Socket::rebind(quint16 localPort) {
|
||||||
_udpSocket.close();
|
_udpSocket.abort();
|
||||||
bind(QHostAddress::AnyIPv4, localPort);
|
bind(QHostAddress::AnyIPv4, localPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness
|
||||||
_fragColor0 = vec4(albedo, mix(packShadedMetallic(metallic), packScatteringMetallic(metallic), check));
|
_fragColor0 = vec4(albedo, mix(packShadedMetallic(metallic), packScatteringMetallic(metallic), check));
|
||||||
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
||||||
_fragColor2 = vec4(mix(emissive, vec3(scattering), check), occlusion);
|
_fragColor2 = vec4(mix(emissive, vec3(scattering), check), occlusion);
|
||||||
|
|
||||||
_fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);
|
_fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +48,6 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r
|
||||||
_fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));
|
_fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));
|
||||||
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
||||||
_fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);
|
_fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0);
|
||||||
|
|
||||||
_fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);
|
_fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +57,7 @@ void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {
|
||||||
}
|
}
|
||||||
_fragColor0 = vec4(color, packUnlit());
|
_fragColor0 = vec4(color, packUnlit());
|
||||||
_fragColor1 = vec4(packNormal(normal), 1.0);
|
_fragColor1 = vec4(packNormal(normal), 1.0);
|
||||||
// _fragColor2 = vec4(vec3(0.0), 1.0);
|
_fragColor2 = vec4(vec3(0.0), 1.0);
|
||||||
_fragColor3 = vec4(color, 1.0);
|
_fragColor3 = vec4(color, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +67,8 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, floa
|
||||||
}
|
}
|
||||||
_fragColor0 = vec4(albedo.rgb, alpha);
|
_fragColor0 = vec4(albedo.rgb, alpha);
|
||||||
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
||||||
|
_fragColor2 = vec4(vec3(0.0), 1.0);
|
||||||
|
_fragColor3 = vec4(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
|
@ -41,33 +41,17 @@ namespace gr {
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
struct LightLocations {
|
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& program);
|
||||||
bool shadowTransform{ false };
|
|
||||||
void initialize(const gpu::ShaderPointer& program) {
|
|
||||||
shadowTransform = program->getReflection().validUniformBuffer(ru::Buffer::ShadowParams);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
|
|
||||||
|
|
||||||
void DeferredLightingEffect::init() {
|
void DeferredLightingEffect::init() {
|
||||||
_directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
|
loadLightProgram(shader::render_utils::program::directional_ambient_light, false, _directionalAmbientSphereLight);
|
||||||
_directionalSkyboxLightLocations = std::make_shared<LightLocations>();
|
loadLightProgram(shader::render_utils::program::directional_skybox_light, false, _directionalSkyboxLight);
|
||||||
|
|
||||||
_directionalAmbientSphereLightShadowLocations = std::make_shared<LightLocations>();
|
loadLightProgram(shader::render_utils::program::directional_ambient_light_shadow, false, _directionalAmbientSphereLightShadow);
|
||||||
_directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>();
|
loadLightProgram(shader::render_utils::program::directional_skybox_light_shadow, false, _directionalSkyboxLightShadow);
|
||||||
|
|
||||||
_localLightLocations = std::make_shared<LightLocations>();
|
loadLightProgram(shader::render_utils::program::local_lights_shading, true, _localLight);
|
||||||
_localLightOutlineLocations = std::make_shared<LightLocations>();
|
loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline);
|
||||||
|
|
||||||
loadLightProgram(shader::render_utils::program::directional_ambient_light, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);
|
|
||||||
loadLightProgram(shader::render_utils::program::directional_skybox_light, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
|
|
||||||
|
|
||||||
loadLightProgram(shader::render_utils::program::directional_ambient_light_shadow, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations);
|
|
||||||
loadLightProgram(shader::render_utils::program::directional_skybox_light_shadow, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
|
|
||||||
|
|
||||||
loadLightProgram(shader::render_utils::program::local_lights_shading, true, _localLight, _localLightLocations);
|
|
||||||
loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline, _localLightOutlineLocations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: figure out how to move lightFrame into a varying in GeometryCache and RenderPipelines
|
// FIXME: figure out how to move lightFrame into a varying in GeometryCache and RenderPipelines
|
||||||
|
@ -123,15 +107,9 @@ void DeferredLightingEffect::unsetLocalLightsBatch(gpu::Batch& batch) {
|
||||||
batch.setUniformBuffer(ru::Buffer::LightClusterFrustumGrid, nullptr);
|
batch.setUniformBuffer(ru::Buffer::LightClusterFrustumGrid, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gpu::ShaderPointer makeLightProgram(int programId, LightLocationsPtr& locations) {
|
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& pipeline) {
|
||||||
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(programId);
|
gpu::ShaderPointer program = gpu::Shader::createProgram(programId);
|
||||||
locations->initialize(program);
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
|
|
||||||
|
|
||||||
gpu::ShaderPointer program = makeLightProgram(programId, locations);
|
|
||||||
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
auto state = std::make_shared<gpu::State>();
|
||||||
state->setColorWriteMask(true, true, true, false);
|
state->setColorWriteMask(true, true, true, false);
|
||||||
|
@ -456,7 +434,6 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
|
|
||||||
// Setup the global directional pass pipeline
|
// Setup the global directional pass pipeline
|
||||||
auto program = deferredLightingEffect->_directionalSkyboxLight;
|
auto program = deferredLightingEffect->_directionalSkyboxLight;
|
||||||
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
|
||||||
{
|
{
|
||||||
if (keyLightCastShadows) {
|
if (keyLightCastShadows) {
|
||||||
|
|
||||||
|
@ -464,20 +441,16 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
// otherwise use the ambient sphere version
|
// otherwise use the ambient sphere version
|
||||||
if (hasAmbientMap) {
|
if (hasAmbientMap) {
|
||||||
program = deferredLightingEffect->_directionalSkyboxLightShadow;
|
program = deferredLightingEffect->_directionalSkyboxLightShadow;
|
||||||
locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations;
|
|
||||||
} else {
|
} else {
|
||||||
program = deferredLightingEffect->_directionalAmbientSphereLightShadow;
|
program = deferredLightingEffect->_directionalAmbientSphereLightShadow;
|
||||||
locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the keylight has an ambient Map then use the Skybox version of the pass
|
// If the keylight has an ambient Map then use the Skybox version of the pass
|
||||||
// otherwise use the ambient sphere version
|
// otherwise use the ambient sphere version
|
||||||
if (hasAmbientMap) {
|
if (hasAmbientMap) {
|
||||||
program = deferredLightingEffect->_directionalSkyboxLight;
|
program = deferredLightingEffect->_directionalSkyboxLight;
|
||||||
locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
|
||||||
} else {
|
} else {
|
||||||
program = deferredLightingEffect->_directionalAmbientSphereLight;
|
program = deferredLightingEffect->_directionalAmbientSphereLight;
|
||||||
locations = deferredLightingEffect->_directionalAmbientSphereLightLocations;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,6 @@
|
||||||
#include "SubsurfaceScattering.h"
|
#include "SubsurfaceScattering.h"
|
||||||
#include "AmbientOcclusionEffect.h"
|
#include "AmbientOcclusionEffect.h"
|
||||||
|
|
||||||
|
|
||||||
struct LightLocations;
|
|
||||||
using LightLocationsPtr = std::shared_ptr<LightLocations>;
|
|
||||||
|
|
||||||
// THis is where we currently accumulate the local lights, let s change that sooner than later
|
// THis is where we currently accumulate the local lights, let s change that sooner than later
|
||||||
class DeferredLightingEffect : public Dependency {
|
class DeferredLightingEffect : public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
@ -72,15 +68,6 @@ private:
|
||||||
gpu::PipelinePointer _localLight;
|
gpu::PipelinePointer _localLight;
|
||||||
gpu::PipelinePointer _localLightOutline;
|
gpu::PipelinePointer _localLightOutline;
|
||||||
|
|
||||||
LightLocationsPtr _directionalSkyboxLightLocations;
|
|
||||||
LightLocationsPtr _directionalAmbientSphereLightLocations;
|
|
||||||
|
|
||||||
LightLocationsPtr _directionalSkyboxLightShadowLocations;
|
|
||||||
LightLocationsPtr _directionalAmbientSphereLightShadowLocations;
|
|
||||||
|
|
||||||
LightLocationsPtr _localLightLocations;
|
|
||||||
LightLocationsPtr _localLightOutlineLocations;
|
|
||||||
|
|
||||||
friend class LightClusteringPass;
|
friend class LightClusteringPass;
|
||||||
friend class RenderDeferredSetup;
|
friend class RenderDeferredSetup;
|
||||||
friend class RenderDeferredLocals;
|
friend class RenderDeferredLocals;
|
||||||
|
|
|
@ -18,7 +18,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
const float depth = 1.0;
|
const float depth = 1.0;
|
||||||
const vec4 UNIT_QUAD[4] = vec4[4](
|
const mat4 UNIT_QUAD = mat4(
|
||||||
vec4(-1.0, -1.0, depth, 1.0),
|
vec4(-1.0, -1.0, depth, 1.0),
|
||||||
vec4(1.0, -1.0, depth, 1.0),
|
vec4(1.0, -1.0, depth, 1.0),
|
||||||
vec4(-1.0, 1.0, depth, 1.0),
|
vec4(-1.0, 1.0, depth, 1.0),
|
||||||
|
@ -26,7 +26,7 @@ void main(void) {
|
||||||
);
|
);
|
||||||
vec4 pos = UNIT_QUAD[gl_VertexID];
|
vec4 pos = UNIT_QUAD[gl_VertexID];
|
||||||
|
|
||||||
_texCoord01.xy = (pos.xy + 1.0) * 0.5;
|
_texCoord01 = vec4((pos.xy + 1.0) * 0.5, 0.0, 0.0);
|
||||||
|
|
||||||
gl_Position = pos;
|
gl_Position = pos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,48 +115,39 @@ protected:
|
||||||
const Lambda _triggerHandler;
|
const Lambda _triggerHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BoolPreference : public Preference {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool value READ getValue WRITE setValue NOTIFY valueChanged)
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class TypedPreference : public Preference {
|
|
||||||
public:
|
public:
|
||||||
using Getter = std::function<T()>;
|
using Getter = std::function<bool()>;
|
||||||
using Setter = std::function<void(const T&)>;
|
using Setter = std::function<void(const bool&)>;
|
||||||
|
|
||||||
TypedPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
BoolPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||||
: Preference(category, name), _getter(getter), _setter(setter) { }
|
: Preference(category, name), _getter(getter), _setter(setter) { }
|
||||||
|
|
||||||
T getValue() const { return _value; }
|
bool getValue() const { return _value; }
|
||||||
void setValue(const T& value) { if (_value != value) { _value = value; emitValueChanged(); } }
|
void setValue(const bool& value) { if (_value != value) { _value = value; emitValueChanged(); } }
|
||||||
void load() override { _value = _getter(); }
|
void load() override { _value = _getter(); }
|
||||||
void save() const override {
|
void save() const override {
|
||||||
T oldValue = _getter();
|
bool oldValue = _getter();
|
||||||
if (_value != oldValue) {
|
if (_value != oldValue) {
|
||||||
_setter(_value);
|
_setter(_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
T _value;
|
|
||||||
const Getter _getter;
|
|
||||||
const Setter _setter;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BoolPreference : public TypedPreference<bool> {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(bool value READ getValue WRITE setValue NOTIFY valueChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
BoolPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
|
||||||
: TypedPreference(category, name, getter, setter) { }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void valueChanged();
|
void valueChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool _value;
|
||||||
|
const Getter _getter;
|
||||||
|
const Setter _setter;
|
||||||
|
|
||||||
void emitValueChanged() override { emit valueChanged(); }
|
void emitValueChanged() override { emit valueChanged(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class FloatPreference : public TypedPreference<float> {
|
class FloatPreference : public Preference {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
|
Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
|
||||||
Q_PROPERTY(float min READ getMin CONSTANT)
|
Q_PROPERTY(float min READ getMin CONSTANT)
|
||||||
|
@ -165,8 +156,21 @@ class FloatPreference : public TypedPreference<float> {
|
||||||
Q_PROPERTY(float decimals READ getDecimals CONSTANT)
|
Q_PROPERTY(float decimals READ getDecimals CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Getter = std::function<float()>;
|
||||||
|
using Setter = std::function<void(const float&)>;
|
||||||
|
|
||||||
FloatPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
FloatPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||||
: TypedPreference(category, name, getter, setter) { }
|
: Preference(category, name), _getter(getter), _setter(setter) { }
|
||||||
|
|
||||||
|
float getValue() const { return _value; }
|
||||||
|
void setValue(const float& value) { if (_value != value) { _value = value; emitValueChanged(); } }
|
||||||
|
void load() override { _value = _getter(); }
|
||||||
|
void save() const override {
|
||||||
|
float oldValue = _getter();
|
||||||
|
if (_value != oldValue) {
|
||||||
|
_setter(_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float getMin() const { return _min; }
|
float getMin() const { return _min; }
|
||||||
void setMin(float min) { _min = min; };
|
void setMin(float min) { _min = min; };
|
||||||
|
@ -186,14 +190,17 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
void emitValueChanged() override { emit valueChanged(); }
|
void emitValueChanged() override { emit valueChanged(); }
|
||||||
|
|
||||||
|
float _value;
|
||||||
|
const Getter _getter;
|
||||||
|
const Setter _setter;
|
||||||
|
|
||||||
float _decimals { 0 };
|
float _decimals { 0 };
|
||||||
float _min { 0 };
|
float _min { 0 };
|
||||||
float _max { 1 };
|
float _max { 1 };
|
||||||
float _step { 0.1f };
|
float _step { 0.1f };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IntPreference : public Preference {
|
||||||
class IntPreference : public TypedPreference<int> {
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
|
Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
|
||||||
Q_PROPERTY(float min READ getMin CONSTANT)
|
Q_PROPERTY(float min READ getMin CONSTANT)
|
||||||
|
@ -202,8 +209,21 @@ class IntPreference : public TypedPreference<int> {
|
||||||
Q_PROPERTY(int decimals READ getDecimals CONSTANT)
|
Q_PROPERTY(int decimals READ getDecimals CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Getter = std::function<int()>;
|
||||||
|
using Setter = std::function<void(const int&)>;
|
||||||
|
|
||||||
IntPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
IntPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||||
: TypedPreference(category, name, getter, setter) { }
|
: Preference(category, name), _getter(getter), _setter(setter) { }
|
||||||
|
|
||||||
|
int getValue() const { return _value; }
|
||||||
|
void setValue(const int& value) { if (_value != value) { _value = value; emitValueChanged(); } }
|
||||||
|
void load() override { _value = _getter(); }
|
||||||
|
void save() const override {
|
||||||
|
int oldValue = _getter();
|
||||||
|
if (_value != oldValue) {
|
||||||
|
_setter(_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float getMin() const { return _min; }
|
float getMin() const { return _min; }
|
||||||
void setMin(float min) { _min = min; };
|
void setMin(float min) { _min = min; };
|
||||||
|
@ -221,6 +241,10 @@ signals:
|
||||||
void valueChanged();
|
void valueChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int _value;
|
||||||
|
const Getter _getter;
|
||||||
|
const Setter _setter;
|
||||||
|
|
||||||
void emitValueChanged() override { emit valueChanged(); }
|
void emitValueChanged() override { emit valueChanged(); }
|
||||||
|
|
||||||
int _min { std::numeric_limits<int>::min() };
|
int _min { std::numeric_limits<int>::min() };
|
||||||
|
@ -229,19 +253,37 @@ protected:
|
||||||
int _decimals { 0 };
|
int _decimals { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringPreference : public TypedPreference<QString> {
|
class StringPreference : public Preference {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged)
|
Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Getter = std::function<QString()>;
|
||||||
|
using Setter = std::function<void(const QString&)>;
|
||||||
|
|
||||||
StringPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
StringPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||||
: TypedPreference(category, name, getter, setter) { }
|
: Preference(category, name), _getter(getter), _setter(setter) { }
|
||||||
|
|
||||||
|
|
||||||
|
QString getValue() const { return _value; }
|
||||||
|
void setValue(const QString& value) { if (_value != value) { _value = value; emitValueChanged(); } }
|
||||||
|
void load() override { _value = _getter(); }
|
||||||
|
void save() const override {
|
||||||
|
QString oldValue = _getter();
|
||||||
|
if (_value != oldValue) {
|
||||||
|
_setter(_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void valueChanged();
|
void valueChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void emitValueChanged() override { emit valueChanged(); }
|
void emitValueChanged() override { emit valueChanged(); }
|
||||||
|
|
||||||
|
QString _value;
|
||||||
|
const Getter _getter;
|
||||||
|
const Setter _setter;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SliderPreference : public FloatPreference {
|
class SliderPreference : public FloatPreference {
|
||||||
|
@ -342,6 +384,9 @@ class CheckPreference : public BoolPreference {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool indented READ getIndented CONSTANT)
|
Q_PROPERTY(bool indented READ getIndented CONSTANT)
|
||||||
public:
|
public:
|
||||||
|
using Getter = std::function<bool()>;
|
||||||
|
using Setter = std::function<void(const bool&)>;
|
||||||
|
|
||||||
CheckPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
CheckPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||||
: BoolPreference(category, name, getter, setter) { }
|
: BoolPreference(category, name, getter, setter) { }
|
||||||
Type getType() override { return Checkbox; }
|
Type getType() override { return Checkbox; }
|
||||||
|
|
Loading…
Reference in a new issue