mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 12:13:28 +02:00
don't allow PC keyboard in HMD login/fix sign up password
This commit is contained in:
commit
037abd9b5e
112 changed files with 2573 additions and 1793 deletions
assignment-client/src
interface
resources
controllers
qml
src
libraries
audio-client/src
audio/src
avatars/src
display-plugins/src/display-plugins
entities/src
recording/src/recording
render-utils/src
AmbientOcclusionEffect.cppAmbientOcclusionEffect.hBloomEffect.cppDebugDeferredBuffer.hDeferredLightingEffect.cppDeferredLightingEffect.hLightStage.cppRenderShadowTask.cppRenderShadowTask.hToneMappingEffect.h
render/src/render
script-engine/src
shared/src
task/src/task
ui/src/ui
plugins/openvr/src
scripts
developer/utilities
lib/jet
render
system
|
@ -656,6 +656,8 @@ void Agent::queryAvatars() {
|
|||
ViewFrustum view;
|
||||
view.setPosition(scriptedAvatar->getWorldPosition());
|
||||
view.setOrientation(scriptedAvatar->getHeadOrientation());
|
||||
view.setProjection(DEFAULT_FIELD_OF_VIEW_DEGREES, DEFAULT_ASPECT_RATIO,
|
||||
DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP);
|
||||
view.calculate();
|
||||
ConicalViewFrustum conicalView { view };
|
||||
|
||||
|
@ -876,18 +878,30 @@ void Agent::aboutToFinish() {
|
|||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
|
||||
// destroy all other created dependencies
|
||||
DependencyManager::destroy<ScriptCache>();
|
||||
|
||||
DependencyManager::destroy<ResourceCacheSharedItems>();
|
||||
DependencyManager::destroy<SoundCacheScriptingInterface>();
|
||||
DependencyManager::destroy<SoundCache>();
|
||||
DependencyManager::destroy<AudioScriptingInterface>();
|
||||
|
||||
DependencyManager::destroy<RecordingScriptingInterface>();
|
||||
DependencyManager::destroy<AnimationCacheScriptingInterface>();
|
||||
DependencyManager::destroy<EntityScriptingInterface>();
|
||||
DependencyManager::destroy<ResourceScriptingInterface>();
|
||||
DependencyManager::destroy<UserActivityLoggerScriptingInterface>();
|
||||
|
||||
DependencyManager::destroy<ScriptCache>();
|
||||
DependencyManager::destroy<SoundCache>();
|
||||
DependencyManager::destroy<AnimationCache>();
|
||||
|
||||
DependencyManager::destroy<recording::Deck>();
|
||||
DependencyManager::destroy<recording::Recorder>();
|
||||
DependencyManager::destroy<recording::ClipCache>();
|
||||
|
||||
DependencyManager::destroy<AvatarHashMap>();
|
||||
DependencyManager::destroy<AssignmentParentFinder>();
|
||||
DependencyManager::destroy<MessagesClient>();
|
||||
DependencyManager::destroy<ResourceManager>();
|
||||
|
||||
DependencyManager::destroy<ResourceCacheSharedItems>();
|
||||
|
||||
// drop our shared pointer to the script engine, then ask ScriptEngines to shutdown scripting
|
||||
// this ensures that the ScriptEngine goes down before ScriptEngines
|
||||
_scriptEngine.clear();
|
||||
|
|
|
@ -129,17 +129,12 @@ void AssignmentClient::stopAssignmentClient() {
|
|||
QThread* currentAssignmentThread = _currentAssignment->thread();
|
||||
|
||||
// ask the current assignment to stop
|
||||
BLOCKING_INVOKE_METHOD(_currentAssignment, "stop");
|
||||
QMetaObject::invokeMethod(_currentAssignment, "stop");
|
||||
|
||||
// ask the current assignment to delete itself on its thread
|
||||
_currentAssignment->deleteLater();
|
||||
|
||||
// when this thread is destroyed we don't need to run our assignment complete method
|
||||
disconnect(currentAssignmentThread, &QThread::destroyed, this, &AssignmentClient::assignmentCompleted);
|
||||
|
||||
// wait on the thread from that assignment - it will be gone once the current assignment deletes
|
||||
currentAssignmentThread->quit();
|
||||
currentAssignmentThread->wait();
|
||||
auto PROCESS_EVENTS_INTERVAL_MS = 100;
|
||||
while (!currentAssignmentThread->wait(PROCESS_EVENTS_INTERVAL_MS)) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -337,6 +337,13 @@ void AudioMixerClientData::removeAgentAvatarAudioStream() {
|
|||
|
||||
if (it != _audioStreams.end()) {
|
||||
_audioStreams.erase(it);
|
||||
|
||||
// Clear mixing structures so that they get recreated with up to date
|
||||
// data if the stream comes back
|
||||
setHasReceivedFirstMix(false);
|
||||
_streams.skipped.clear();
|
||||
_streams.inactive.clear();
|
||||
_streams.active.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <GLMHelpers.h>
|
||||
|
||||
ScriptableAvatar::ScriptableAvatar() {
|
||||
_clientTraitsHandler = std::unique_ptr<ClientTraitsHandler>(new ClientTraitsHandler(this));
|
||||
_clientTraitsHandler.reset(new ClientTraitsHandler(this));
|
||||
}
|
||||
|
||||
QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
|
||||
|
|
|
@ -583,15 +583,29 @@ void EntityScriptServer::handleOctreePacket(QSharedPointer<ReceivedMessage> mess
|
|||
void EntityScriptServer::aboutToFinish() {
|
||||
shutdownScriptEngine();
|
||||
|
||||
DependencyManager::get<EntityScriptingInterface>()->setEntityTree(nullptr);
|
||||
DependencyManager::get<ResourceManager>()->cleanup();
|
||||
|
||||
DependencyManager::destroy<AudioScriptingInterface>();
|
||||
DependencyManager::destroy<SoundCacheScriptingInterface>();
|
||||
DependencyManager::destroy<ResourceScriptingInterface>();
|
||||
DependencyManager::destroy<EntityScriptingInterface>();
|
||||
|
||||
DependencyManager::destroy<SoundCache>();
|
||||
DependencyManager::destroy<ScriptCache>();
|
||||
|
||||
DependencyManager::destroy<ResourceManager>();
|
||||
DependencyManager::destroy<ResourceCacheSharedItems>();
|
||||
|
||||
DependencyManager::destroy<MessagesClient>();
|
||||
|
||||
DependencyManager::destroy<AssignmentDynamicFactory>();
|
||||
DependencyManager::destroy<AssignmentParentFinder>();
|
||||
DependencyManager::destroy<AvatarHashMap>();
|
||||
|
||||
DependencyManager::get<ResourceManager>()->cleanup();
|
||||
|
||||
DependencyManager::destroy<PluginManager>();
|
||||
|
||||
DependencyManager::destroy<ResourceScriptingInterface>();
|
||||
DependencyManager::destroy<EntityScriptingInterface>();
|
||||
|
||||
// cleanup the AudioInjectorManager (and any still running injectors)
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
|
|
78
interface/resources/controllers/standard_nomovement.json
Normal file
78
interface/resources/controllers/standard_nomovement.json
Normal file
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"name": "Standard to Action (No Movement)",
|
||||
"channels": [
|
||||
{ "from": "Standard.LT", "to": "Actions.LeftHandClick" },
|
||||
{ "from": "Standard.RT", "to": "Actions.RightHandClick" },
|
||||
|
||||
{ "from": "Standard.LeftHand", "to": "Actions.LeftHand" },
|
||||
{ "from": "Standard.LeftHandThumb1", "to": "Actions.LeftHandThumb1"},
|
||||
{ "from": "Standard.LeftHandThumb2", "to": "Actions.LeftHandThumb2"},
|
||||
{ "from": "Standard.LeftHandThumb3", "to": "Actions.LeftHandThumb3"},
|
||||
{ "from": "Standard.LeftHandThumb4", "to": "Actions.LeftHandThumb4"},
|
||||
{ "from": "Standard.LeftHandIndex1", "to": "Actions.LeftHandIndex1"},
|
||||
{ "from": "Standard.LeftHandIndex2", "to": "Actions.LeftHandIndex2"},
|
||||
{ "from": "Standard.LeftHandIndex3", "to": "Actions.LeftHandIndex3"},
|
||||
{ "from": "Standard.LeftHandIndex4", "to": "Actions.LeftHandIndex4"},
|
||||
{ "from": "Standard.LeftHandMiddle1", "to": "Actions.LeftHandMiddle1"},
|
||||
{ "from": "Standard.LeftHandMiddle2", "to": "Actions.LeftHandMiddle2"},
|
||||
{ "from": "Standard.LeftHandMiddle3", "to": "Actions.LeftHandMiddle3"},
|
||||
{ "from": "Standard.LeftHandMiddle4", "to": "Actions.LeftHandMiddle4"},
|
||||
{ "from": "Standard.LeftHandRing1", "to": "Actions.LeftHandRing1"},
|
||||
{ "from": "Standard.LeftHandRing2", "to": "Actions.LeftHandRing2"},
|
||||
{ "from": "Standard.LeftHandRing3", "to": "Actions.LeftHandRing3"},
|
||||
{ "from": "Standard.LeftHandRing4", "to": "Actions.LeftHandRing4"},
|
||||
{ "from": "Standard.LeftHandPinky1", "to": "Actions.LeftHandPinky1"},
|
||||
{ "from": "Standard.LeftHandPinky2", "to": "Actions.LeftHandPinky2"},
|
||||
{ "from": "Standard.LeftHandPinky3", "to": "Actions.LeftHandPinky3"},
|
||||
{ "from": "Standard.LeftHandPinky4", "to": "Actions.LeftHandPinky4"},
|
||||
|
||||
{ "from": "Standard.RightHand", "to": "Actions.RightHand" },
|
||||
{ "from": "Standard.RightHandThumb1", "to": "Actions.RightHandThumb1"},
|
||||
{ "from": "Standard.RightHandThumb2", "to": "Actions.RightHandThumb2"},
|
||||
{ "from": "Standard.RightHandThumb3", "to": "Actions.RightHandThumb3"},
|
||||
{ "from": "Standard.RightHandThumb4", "to": "Actions.RightHandThumb4"},
|
||||
{ "from": "Standard.RightHandIndex1", "to": "Actions.RightHandIndex1"},
|
||||
{ "from": "Standard.RightHandIndex2", "to": "Actions.RightHandIndex2"},
|
||||
{ "from": "Standard.RightHandIndex3", "to": "Actions.RightHandIndex3"},
|
||||
{ "from": "Standard.RightHandIndex4", "to": "Actions.RightHandIndex4"},
|
||||
{ "from": "Standard.RightHandMiddle1", "to": "Actions.RightHandMiddle1"},
|
||||
{ "from": "Standard.RightHandMiddle2", "to": "Actions.RightHandMiddle2"},
|
||||
{ "from": "Standard.RightHandMiddle3", "to": "Actions.RightHandMiddle3"},
|
||||
{ "from": "Standard.RightHandMiddle4", "to": "Actions.RightHandMiddle4"},
|
||||
{ "from": "Standard.RightHandRing1", "to": "Actions.RightHandRing1"},
|
||||
{ "from": "Standard.RightHandRing2", "to": "Actions.RightHandRing2"},
|
||||
{ "from": "Standard.RightHandRing3", "to": "Actions.RightHandRing3"},
|
||||
{ "from": "Standard.RightHandRing4", "to": "Actions.RightHandRing4"},
|
||||
{ "from": "Standard.RightHandPinky1", "to": "Actions.RightHandPinky1"},
|
||||
{ "from": "Standard.RightHandPinky2", "to": "Actions.RightHandPinky2"},
|
||||
{ "from": "Standard.RightHandPinky3", "to": "Actions.RightHandPinky3"},
|
||||
{ "from": "Standard.RightHandPinky4", "to": "Actions.RightHandPinky4"},
|
||||
|
||||
{ "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" },
|
||||
{ "from": "Standard.RightFoot", "to": "Actions.RightFoot" },
|
||||
|
||||
{ "from": "Standard.Hips", "to": "Actions.Hips" },
|
||||
{ "from": "Standard.Spine2", "to": "Actions.Spine2" },
|
||||
|
||||
{ "from": "Standard.Head", "to": "Actions.Head" },
|
||||
{ "from": "Standard.LeftArm", "to": "Actions.LeftArm" },
|
||||
{ "from": "Standard.RightArm", "to": "Actions.RightArm" },
|
||||
|
||||
{ "from": "Standard.TrackedObject00", "to" : "Actions.TrackedObject00" },
|
||||
{ "from": "Standard.TrackedObject01", "to" : "Actions.TrackedObject01" },
|
||||
{ "from": "Standard.TrackedObject02", "to" : "Actions.TrackedObject02" },
|
||||
{ "from": "Standard.TrackedObject03", "to" : "Actions.TrackedObject03" },
|
||||
{ "from": "Standard.TrackedObject04", "to" : "Actions.TrackedObject04" },
|
||||
{ "from": "Standard.TrackedObject05", "to" : "Actions.TrackedObject05" },
|
||||
{ "from": "Standard.TrackedObject06", "to" : "Actions.TrackedObject06" },
|
||||
{ "from": "Standard.TrackedObject07", "to" : "Actions.TrackedObject07" },
|
||||
{ "from": "Standard.TrackedObject08", "to" : "Actions.TrackedObject08" },
|
||||
{ "from": "Standard.TrackedObject09", "to" : "Actions.TrackedObject09" },
|
||||
{ "from": "Standard.TrackedObject10", "to" : "Actions.TrackedObject10" },
|
||||
{ "from": "Standard.TrackedObject11", "to" : "Actions.TrackedObject11" },
|
||||
{ "from": "Standard.TrackedObject12", "to" : "Actions.TrackedObject12" },
|
||||
{ "from": "Standard.TrackedObject13", "to" : "Actions.TrackedObject13" },
|
||||
{ "from": "Standard.TrackedObject14", "to" : "Actions.TrackedObject14" },
|
||||
{ "from": "Standard.TrackedObject15", "to" : "Actions.TrackedObject15" }
|
||||
]
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
//
|
||||
// LoginDialog.qml
|
||||
//
|
||||
// Created by Wayne Chen
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Created by David Rowe on 3 Jun 2015
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
@ -37,6 +36,8 @@ FocusScope {
|
|||
property string title: ""
|
||||
property string text: ""
|
||||
property int titleWidth: 0
|
||||
property alias bannerWidth: banner.width
|
||||
property alias bannerHeight: banner.height
|
||||
|
||||
function tryDestroy() {
|
||||
root.destroy()
|
||||
|
@ -51,10 +52,36 @@ FocusScope {
|
|||
}
|
||||
|
||||
Image {
|
||||
z: -10
|
||||
id: loginDialogBackground
|
||||
source: "LoginDialog/background.png"
|
||||
source: "LoginDialog/background.jpg"
|
||||
anchors.fill: parent
|
||||
z: -2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
z: -6
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.5
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
z: -5
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 0.18 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
|
@ -92,6 +119,6 @@ FocusScope {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,29 +56,6 @@ Item {
|
|||
anchors.fill: parent
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Rectangle {
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.9
|
||||
color: "black"
|
||||
}
|
||||
Item {
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
bottom: textContainer.top
|
||||
bottomMargin: 0.125 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: textContainer
|
||||
width: parent.width
|
||||
|
@ -131,7 +108,7 @@ Item {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
Component.onCompleted: {
|
||||
bodyText.text = root.isTablet ? qsTr("Please navigate to your default browser\nto recover your account.\nIf you are in a VR headset, please take it off.") :
|
||||
qsTr("Please navigate to your default browser to recover your account.\nIf you are in a VR headset, please take it off.");
|
||||
qsTr("Please navigate to your default browser to recover your account.\nIf you are in a VR headset,\nplease take it off.");
|
||||
bodyTextMetrics.text = bodyText.text;
|
||||
bodyText
|
||||
bodyText.anchors.leftMargin = (parent.width - bodyTextMetrics.width) / 2;
|
||||
|
|
|
@ -26,14 +26,15 @@ Item {
|
|||
readonly property int fontSize: 15
|
||||
readonly property bool fontBold: true
|
||||
|
||||
readonly property bool withSteam: withSteam
|
||||
property string errorString: errorString
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
// readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
readonly property int minWidthButton: 36
|
||||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.isTablet ? 1280 : root.width
|
||||
readonly property int minHeight: 120
|
||||
// readonly property int minHeightButton: !root.isTablet ? 56 : 42
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.isTablet ? 720 : root.height
|
||||
|
||||
|
@ -56,29 +57,6 @@ Item {
|
|||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Rectangle {
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.9
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 85
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: contentItem
|
||||
anchors.fill: parent
|
||||
|
@ -94,78 +72,42 @@ Item {
|
|||
// above buttons.
|
||||
anchors.topMargin: (parent.height - additionalTextContainer.height) / 2 - hifi.dimensions.contentSpacing.y - profileButton.height
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: (parent.width - loginErrorMessageTextMetrics.width) / 2;
|
||||
color: "red";
|
||||
font.family: "Cairo"
|
||||
font.pixelSize: 12
|
||||
text: ""
|
||||
font.family: completeProfileBody.fontFamily
|
||||
font.pixelSize: completeProfileBody.fontSize
|
||||
text: completeProfileBody.errorString
|
||||
visible: true
|
||||
}
|
||||
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: loggedInGlyph;
|
||||
text: hifi.glyphs.steamSquare;
|
||||
// color
|
||||
color: "white"
|
||||
// Size
|
||||
size: 78;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: (parent.width - loggedInGlyph.size) / 2;
|
||||
anchors.top: loginErrorMessage.bottom
|
||||
anchors.topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
visible: false;
|
||||
|
||||
}
|
||||
Item {
|
||||
id: buttons
|
||||
width: Math.max(banner.width, cancelContainer.width + profileButton.width)
|
||||
width: root.bannerWidth
|
||||
height: d.minHeightButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: (parent.height - additionalTextContainer.height) / 2 - hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - banner.width) / 2
|
||||
leftMargin: (parent.width - root.bannerWidth) / 2
|
||||
}
|
||||
Item {
|
||||
id: cancelContainer
|
||||
width: cancelText.width
|
||||
height: d.minHeightButton
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
}
|
||||
Text {
|
||||
id: cancelText
|
||||
text: qsTr("Cancel");
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
lineHeight: 1
|
||||
color: "white"
|
||||
font.family: completeProfileBody.fontFamily
|
||||
font.pixelSize: completeProfileBody.fontSize
|
||||
font.capitalization: Font.AllUppercase;
|
||||
font.bold: completeProfileBody.fontBold
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("CANCEL")
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
|
||||
fontFamily: completeProfileBody.fontFamily
|
||||
fontSize: completeProfileBody.fontSize
|
||||
fontBold: completeProfileBody.fontBold
|
||||
onClicked: {
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
MouseArea {
|
||||
id: cancelArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
}
|
||||
TextMetrics {
|
||||
id: profileButtonTextMetrics
|
||||
font: cancelText.font
|
||||
text: qsTr("CREATE YOUR PROFILE")
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: profileButton
|
||||
|
@ -173,7 +115,7 @@ Item {
|
|||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
width: Math.max(profileButtonTextMetrics.width + 2 * hifi.dimensions.contentSpacing.x, d.minWidthButton)
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
text: qsTr("Create your profile")
|
||||
|
@ -185,8 +127,6 @@ Item {
|
|||
onClicked: {
|
||||
loginErrorMessage.visible = false;
|
||||
loginDialog.createAccountFromSteam();
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader,
|
||||
"withSteam": true, "fromBody": "CompleteProfileBody" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +152,7 @@ Item {
|
|||
|
||||
onLinkActivated: {
|
||||
loginDialog.isLogIn = true;
|
||||
bodyLoader.setSource("SignInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "" });
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "", "linkSteam": true });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,11 +186,26 @@ Item {
|
|||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
onLinkActivated: loginDialog.openUrl(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleCreateCompleted: {
|
||||
console.log("Create Succeeded")
|
||||
|
||||
loginDialog.loginThroughSteam();
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "linkSteam": false });
|
||||
}
|
||||
onHandleCreateFailed: {
|
||||
console.log("Create Failed: " + error);
|
||||
|
||||
bodyLoader.setSource("UsernameCollisionBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
if (root.isTablet || root.isOverlay) {
|
||||
|
|
|
@ -35,6 +35,7 @@ Item {
|
|||
property bool punctuationMode: false
|
||||
|
||||
property bool withSteam: false
|
||||
property bool linkSteam: linkSteam
|
||||
property bool withOculus: false
|
||||
property string errorString: errorString
|
||||
|
||||
|
@ -44,7 +45,6 @@ Item {
|
|||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.isTablet ? 1280 : root.width
|
||||
readonly property int minHeight: 120
|
||||
// readonly property int minHeightButton: !root.isTablet ? 56 : 42
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.isTablet ? 720 : root.height
|
||||
|
||||
|
@ -65,7 +65,7 @@ Item {
|
|||
|
||||
function login() {
|
||||
loginDialog.login(emailField.text, passwordField.text);
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "fromBody": "" });
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "linkSteam": linkAccountBody.linkSteam });
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
@ -73,11 +73,19 @@ Item {
|
|||
loginDialog.isLogIn = true;
|
||||
loginErrorMessage.text = linkAccountBody.errorString;
|
||||
loginErrorMessage.visible = (linkAccountBody.errorString !== "");
|
||||
loginButton.text = "Log In";
|
||||
loginButton.text = !linkAccountBody.linkSteam ? "Log In" : "Link Account";
|
||||
loginButton.color = hifi.buttons.blue;
|
||||
emailField.placeholderText = "Username or Email";
|
||||
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
emailField.text = keepMeLoggedInCheckbox.checked ? savedUsername === "Unknown user" ? "" : savedUsername : "";
|
||||
if (linkAccountBody.linkSteam) {
|
||||
steamInfoText.anchors.top = passwordField.bottom;
|
||||
keepMeLoggedInCheckbox.anchors.top = steamInfoText.bottom;
|
||||
loginButton.width = (passwordField.width - hifi.dimensions.contentSpacing.x) / 2;
|
||||
loginButton.anchors.right = emailField.right;
|
||||
} else {
|
||||
loginButton.anchors.left = emailField.left;
|
||||
}
|
||||
loginContainer.visible = true;
|
||||
}
|
||||
|
||||
|
@ -88,36 +96,13 @@ Item {
|
|||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Rectangle {
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.9
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
bottom: loginContainer.top
|
||||
bottomMargin: 0.12 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: loginContainer
|
||||
width: emailField.width
|
||||
height: 0.45 * parent.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: bannerContainer.height + 0.25 * parent.height
|
||||
topMargin: root.bannerHeight + 0.25 * parent.height
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - emailField.width) / 2
|
||||
}
|
||||
|
@ -149,15 +134,15 @@ Item {
|
|||
|
||||
HifiControlsUit.TextField {
|
||||
id: emailField
|
||||
width: banner.width
|
||||
width: root.bannerWidth
|
||||
height: linkAccountBody.textFieldHeight
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: loginErrorMessage.height
|
||||
topMargin: errorContainer.height
|
||||
}
|
||||
placeholderText: "Username or Email"
|
||||
focus: true
|
||||
activeFocusOnPress: true
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
|
@ -181,14 +166,17 @@ Item {
|
|||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = !focus;
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControlsUit.TextField {
|
||||
id: passwordField
|
||||
width: banner.width
|
||||
width: root.bannerWidth
|
||||
height: linkAccountBody.textFieldHeight
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
placeholderText: "Password"
|
||||
activeFocusOnPress: true
|
||||
echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password
|
||||
|
@ -269,16 +257,30 @@ Item {
|
|||
}
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", Account.username);
|
||||
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
emailField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
||||
} else {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
width: (passwordField.width - hifi.dimensions.contentSpacing.x) / 2;
|
||||
height: d.minHeightButton
|
||||
text: qsTr("Cancel")
|
||||
fontFamily: linkAccountBody.fontFamily
|
||||
fontSize: linkAccountBody.fontSize
|
||||
fontBold: linkAccountBody.fontBold
|
||||
color: hifi.buttons.noneBorderlessWhite;
|
||||
visible: linkAccountBody.linkSteam
|
||||
anchors {
|
||||
top: keepMeLoggedInCheckbox.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
onClicked: {
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "errorString": "" });
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
|
@ -292,22 +294,38 @@ Item {
|
|||
anchors {
|
||||
top: keepMeLoggedInCheckbox.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: emailField.left
|
||||
}
|
||||
onClicked: {
|
||||
linkAccountBody.login()
|
||||
}
|
||||
}
|
||||
Text {
|
||||
id: steamInfoText
|
||||
visible: linkAccountBody.linkSteam
|
||||
anchors {
|
||||
top: loginButton.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: emailField.left
|
||||
}
|
||||
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
color: "white"
|
||||
text: qsTr("Your Steam account information will not be exposed to others.");
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
HifiStylesUit.ShortcutText {
|
||||
id: cantAccessText
|
||||
z: 10
|
||||
visible: !linkAccountBody.linkSteam
|
||||
anchors {
|
||||
top: loginButton.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: emailField.left
|
||||
}
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: 18
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
|
||||
text: "<a href='https://highfidelity.com/users/password/new'> Can't access your account?</a>"
|
||||
|
||||
|
@ -337,28 +355,33 @@ Item {
|
|||
buttonGlyph: hifi.glyphs.steamSquare
|
||||
buttonGlyphRightMargin: 10
|
||||
onClicked: {
|
||||
if (loginDialog.isOculusStoreRunning()) {
|
||||
linkAccountBody.withOculus = true;
|
||||
loginDialog.loginThroughSteam();
|
||||
} else if (loginDialog.isSteamRunning()) {
|
||||
// if (loginDialog.isOculusStoreRunning()) {
|
||||
// linkAccountBody.withOculus = true;
|
||||
// loginDialog.loginThroughSteam();
|
||||
// } else
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
linkAccountBody.withSteam = true;
|
||||
loginDialog.loginThroughSteam();
|
||||
}
|
||||
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader,
|
||||
"withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "fromBody": "LinkAccountBody" });
|
||||
"withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam });
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (loginDialog.isOculusStoreRunning()) {
|
||||
continueButton.text = qsTr("CONTINUE WITH OCULUS");
|
||||
continueButton.buttonGlyph = hifi.glyphs.oculus;
|
||||
} else if (loginDialog.isSteamRunning()) {
|
||||
if (linkAccountBody.linkSteam) {
|
||||
continueButton.visible = false;
|
||||
return;
|
||||
}
|
||||
// if (loginDialog.isOculusStoreRunning()) {
|
||||
// continueButton.text = qsTr("CONTINUE WITH OCULUS");
|
||||
// continueButton.buttonGlyph = hifi.glyphs.oculus;
|
||||
// } else
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
continueButton.text = qsTr("CONTINUE WITH STEAM");
|
||||
continueButton.buttonGlyph = hifi.glyphs.steamSquare;
|
||||
} else {
|
||||
continueButton.visible = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -366,10 +389,11 @@ Item {
|
|||
id: signUpContainer
|
||||
width: loginContainer.width
|
||||
height: signUpTextMetrics.height
|
||||
visible: !linkAccountBody.linkSteam
|
||||
anchors {
|
||||
left: loginContainer.left
|
||||
top: loginContainer.bottom
|
||||
// topMargin: 0.25 * parent.height
|
||||
topMargin: 0.05 * parent.height
|
||||
}
|
||||
TextMetrics {
|
||||
id: signUpTextMetrics
|
||||
|
@ -406,7 +430,7 @@ Item {
|
|||
onLinkActivated: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
bodyLoader.setSource("SignUpBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader,
|
||||
"errorString": "" });
|
||||
"errorString": "", "linkSteam": linkAccountBody.linkSteam });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -430,7 +454,7 @@ Item {
|
|||
fontFamily: linkAccountBody.fontFamily
|
||||
fontSize: linkAccountBody.fontSize
|
||||
fontBold: linkAccountBody.fontBold
|
||||
visible: loginDialog.getLoginDialogPoppedUp()
|
||||
visible: loginDialog.getLoginDialogPoppedUp() && !linkAccountBody.linkSteam;
|
||||
onClicked: {
|
||||
if (loginDialog.getLoginDialogPoppedUp()) {
|
||||
console.log("[ENCOURAGELOGINDIALOG]: user dismissed login screen")
|
||||
|
@ -445,6 +469,15 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onFocusEnabled: {
|
||||
Qt.callLater(function() {
|
||||
emailField.forceActiveFocus();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
root.keyboardEnabled = HMD.active;
|
||||
|
@ -466,10 +499,6 @@ Item {
|
|||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
linkAccountBody.login();
|
||||
break;
|
||||
case Qt.Key_Escape:
|
||||
event.accepted = true;
|
||||
root.tryDestroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ Item {
|
|||
property bool fontBold: true
|
||||
property bool withSteam: withSteam
|
||||
property bool withOculus: withOculus
|
||||
property string fromBody: fromBody
|
||||
property bool linkSteam: linkSteam
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
@ -68,16 +68,13 @@ Item {
|
|||
function init() {
|
||||
// For the process of logging in.
|
||||
loggingInText.wrapMode = Text.NoWrap;
|
||||
print("withSteam " + loggingInBody.withSteam);
|
||||
print("withOculus " + loggingInBody.withOculus);
|
||||
if (loggingInBody.withSteam) {
|
||||
loggingInGlyph.visible = true;
|
||||
loggingInText.text = "Logging in to Steam";
|
||||
loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2;
|
||||
|
||||
} else if (loggingInBody.withOculus) {
|
||||
loggingInGlyph.visible = true;
|
||||
loggingInGlyph.text = hifi.glyphs.oculus;
|
||||
loggingInGlyph.visible = true;
|
||||
loggingInText.text = "Logging in to Oculus";
|
||||
loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2;
|
||||
} else {
|
||||
|
@ -89,19 +86,20 @@ Item {
|
|||
}
|
||||
function loadingSuccess() {
|
||||
loggingInSpinner.visible = false;
|
||||
if (loggingInBody.linkSteam) {
|
||||
loggingInText.text = "Linking to Steam";
|
||||
loginDialog.linkSteam();
|
||||
return;
|
||||
}
|
||||
if (loggingInBody.withSteam) {
|
||||
// reset the flag.
|
||||
loggingInGlyph.visible = false;
|
||||
loggingInText.text = "You are now logged into Steam!"
|
||||
loggingInText.anchors.centerIn = loggingInHeader;
|
||||
loggingInText.anchors.bottom = loggingInHeader.bottom;
|
||||
loggingInText.text = "You are now logged into Steam!";
|
||||
loggedInGlyph.visible = true;
|
||||
} else if (loggingInBody.withOculus) {
|
||||
// reset the flag.
|
||||
loggingInGlyph.visible = false;
|
||||
loggingInText.text = "You are now logged into Oculus!"
|
||||
loggingInText.anchors.centerIn = loggingInHeader;
|
||||
loggingInText.anchors.bottom = loggingInHeader.bottom;
|
||||
loggingInText.text = "You are now logged into Oculus!";
|
||||
loggedInGlyph.text = hifi.glyphs.oculus;
|
||||
loggedInGlyph.visible = true;
|
||||
} else {
|
||||
|
@ -116,30 +114,6 @@ Item {
|
|||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Rectangle {
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.9
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 85
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: loggingInContainer
|
||||
width: parent.width
|
||||
|
@ -173,7 +147,7 @@ Item {
|
|||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
visible: loggingInBody.withSteam;
|
||||
visible: loggingInBody.withSteam || loggingInBody.withOculus;
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
|
@ -207,7 +181,7 @@ Item {
|
|||
}
|
||||
AnimatedImage {
|
||||
id: loggingInSpinner
|
||||
source: "../../icons/loader-snake-64-w.gif"
|
||||
source: "images/loader-snake-298-b.gif"
|
||||
width: 128
|
||||
height: width
|
||||
anchors.left: parent.left;
|
||||
|
@ -248,10 +222,19 @@ Item {
|
|||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleLinkCompleted: {
|
||||
console.log("Link Succeeded");
|
||||
loggingInBody.linkSteam = false;
|
||||
loggingInBody.loadingSuccess();
|
||||
}
|
||||
onHandleLinkFailed: {
|
||||
console.log("Link Failed: " + error);
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": true, "errorString": error });
|
||||
}
|
||||
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded")
|
||||
loadingSuccess();
|
||||
console.log("Login Succeeded");
|
||||
loggingInBody.loadingSuccess();
|
||||
}
|
||||
|
||||
onHandleLoginFailed: {
|
||||
|
@ -260,8 +243,8 @@ Item {
|
|||
var errorString = "";
|
||||
if (loggingInBody.withSteam) {
|
||||
loggingInGlyph.visible = false;
|
||||
errorString = "Your Steam authentication has failed. Please make sure you are logged into Steam and try again."
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString });
|
||||
errorString = "Your Steam authentication has failed. Please make sure you are logged into Steam and try again.";
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "errorString": errorString });
|
||||
} else if (loggingInBody.withOculus) {
|
||||
loggingInGlyph.visible = false;
|
||||
errorString = "Your Oculus authentication has failed. Please make sure you are logged into Oculus and try again."
|
||||
|
@ -269,11 +252,7 @@ Item {
|
|||
}
|
||||
else {
|
||||
errorString = "Username or password is incorrect.";
|
||||
if (loginDialog.isLogIn && loggingInBody.withSteam) {
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
} else {
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString });
|
||||
}
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// signUpBody.qml
|
||||
// SignUpBody.qml
|
||||
//
|
||||
// Created by Stephen Birarda on 7 Dec 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
|
@ -37,6 +37,7 @@ Item {
|
|||
onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
property string errorString: errorString
|
||||
property bool linkSteam: linkSteam
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
@ -44,7 +45,6 @@ Item {
|
|||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.isTablet ? 1280 : root.width
|
||||
readonly property int minHeight: 120
|
||||
// readonly property int minHeightButton: !root.isTablet ? 56 : 42
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.isTablet ? 720 : root.height
|
||||
|
||||
|
@ -64,22 +64,14 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
function login() {
|
||||
function signup() {
|
||||
loginDialog.signup(emailField.text, usernameField.text, passwordField.text);
|
||||
return;
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "fromBody": "" });
|
||||
}
|
||||
|
||||
function init() {
|
||||
// going to/from sign in/up dialog.
|
||||
loginDialog.isLogIn = false;
|
||||
loginErrorMessage.visible = (signUpBody.errorString !== "");
|
||||
if (signUpBody.errorString !== "") {
|
||||
loginErrorMessage.text = signUpBody.errorString;
|
||||
errorContainer.anchors.bottom = usernameField.top;
|
||||
errorContainer.anchors.bottomMargin = hifi.dimensions.contentSpacing.y;
|
||||
errorContainer.anchors.left = usernameField.left;
|
||||
}
|
||||
emailField.placeholderText = "Email";
|
||||
emailField.text = "";
|
||||
emailField.anchors.top = usernameField.bottom;
|
||||
|
@ -95,37 +87,13 @@ Item {
|
|||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Rectangle {
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.9
|
||||
color: "black"
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
bottom: loginContainer.top
|
||||
bottomMargin: 0.12 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: loginContainer
|
||||
width: usernameField.width
|
||||
height: parent.height - bannerContainer.height
|
||||
height: parent.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: bannerContainer.height + 0.25 * parent.height
|
||||
topMargin: root.bannerHeight + 0.25 * parent.height
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - usernameField.width) / 2
|
||||
}
|
||||
|
@ -133,7 +101,7 @@ Item {
|
|||
|
||||
Item {
|
||||
id: errorContainer
|
||||
width: loginErrorMessageTextMetrics.width
|
||||
width: parent.width
|
||||
height: loginErrorMessageTextMetrics.height
|
||||
anchors {
|
||||
bottom: usernameField.top;
|
||||
|
@ -147,6 +115,7 @@ Item {
|
|||
}
|
||||
Text {
|
||||
id: loginErrorMessage;
|
||||
width: root.bannerWidth
|
||||
color: "red";
|
||||
font.family: signUpBody.fontFamily
|
||||
font.pixelSize: 18
|
||||
|
@ -159,10 +128,11 @@ Item {
|
|||
|
||||
HifiControlsUit.TextField {
|
||||
id: usernameField
|
||||
width: banner.width
|
||||
width: root.bannerWidth
|
||||
height: signUpBody.textFieldHeight
|
||||
placeholderText: "Username"
|
||||
font.pixelSize: signUpBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: loginErrorMessage.height
|
||||
|
@ -191,25 +161,28 @@ Item {
|
|||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
}
|
||||
signUpBody.login();
|
||||
signUpBody.signup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = !focus;
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.TextField {
|
||||
id: emailField
|
||||
width: banner.width
|
||||
width: root.bannerWidth
|
||||
height: signUpBody.textFieldHeight
|
||||
anchors {
|
||||
top: parent.top
|
||||
}
|
||||
placeholderText: "Username or Email"
|
||||
font.pixelSize: signUpBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
activeFocusOnPress: true
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
|
@ -233,21 +206,24 @@ Item {
|
|||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
}
|
||||
signUpBody.login();
|
||||
signUpBody.signup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = !focus;
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControlsUit.TextField {
|
||||
id: passwordField
|
||||
width: banner.width
|
||||
width: root.bannerWidth
|
||||
height: signUpBody.textFieldHeight
|
||||
placeholderText: "Password"
|
||||
font.pixelSize: signUpBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
activeFocusOnPress: true
|
||||
echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password
|
||||
anchors {
|
||||
|
@ -316,7 +292,7 @@ Item {
|
|||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
}
|
||||
signUpBody.login();
|
||||
signUpBody.signup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -336,16 +312,12 @@ Item {
|
|||
}
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", Account.username);
|
||||
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
||||
} else {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,7 +341,7 @@ Item {
|
|||
fontSize: signUpBody.fontSize
|
||||
fontBold: signUpBody.fontBold
|
||||
onClicked: {
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": signUpBody.linkSteam });
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
|
@ -387,7 +359,7 @@ Item {
|
|||
}
|
||||
|
||||
onClicked: {
|
||||
signUpBody.login()
|
||||
signUpBody.signup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -433,7 +405,7 @@ Item {
|
|||
console.log("Sign Up Completed");
|
||||
|
||||
loginDialog.login(usernameField.text, passwordField.text);
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "fromBody": "" });
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "linkSteam": false });
|
||||
}
|
||||
onHandleSignupFailed: {
|
||||
console.log("Sign Up Failed")
|
||||
|
@ -442,6 +414,13 @@ Item {
|
|||
loginErrorMessage.visible = (errorStringEdited !== "");
|
||||
if (errorStringEdited !== "") {
|
||||
loginErrorMessage.text = errorStringEdited;
|
||||
loginErrorMessageTextMetrics.text = errorStringEdited;
|
||||
if (loginErrorMessageTextMetrics.width > 350 && root.isTablet) {
|
||||
loginErrorMessage.wrapMode = Text.WordWrap;
|
||||
loginErrorMessage.verticalAlignment = Text.AlignLeft;
|
||||
loginErrorMessage.horizontalAlignment = Text.AlignLeft;
|
||||
errorContainer.height = 2 * loginErrorMessageTextMetrics.height;
|
||||
}
|
||||
errorContainer.anchors.bottom = usernameField.top;
|
||||
errorContainer.anchors.left = usernameField.left;
|
||||
}
|
||||
|
|
|
@ -25,12 +25,9 @@ Item {
|
|||
readonly property int fontSize: 15
|
||||
readonly property bool fontBold: true
|
||||
|
||||
readonly property string errorString: errorString
|
||||
|
||||
function create() {
|
||||
mainTextContainer.visible = false
|
||||
loginDialog.createAccountFromSteam(textField.text)
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "fromBody": "UsernameCollisionBody" });
|
||||
loginDialog.createAccountFromSteam(textField.text);
|
||||
}
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
|
@ -45,7 +42,6 @@ Item {
|
|||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.isTablet ? 1280 : root.width
|
||||
readonly property int minHeight: 120
|
||||
// readonly property int minHeightButton: !root.isTablet ? 56 : 42
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.isTablet ? 720 : root.height
|
||||
|
||||
|
@ -70,30 +66,6 @@ Item {
|
|||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.9
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 85
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: mainTextContainerTextMetrics
|
||||
font: mainTextContainer.font
|
||||
|
@ -110,9 +82,9 @@ Item {
|
|||
}
|
||||
|
||||
font.family: usernameCollisionBody.fontFamily
|
||||
font.pixelSize: usernameCollisionBody.fontSize - 10
|
||||
font.pixelSize: usernameCollisionBody.fontSize
|
||||
font.bold: usernameCollisionBody.fontBold
|
||||
text: qsTr("Your Steam username is not available.")
|
||||
text: qsTr("Your Steam username is not available.");
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.redAccent
|
||||
lineHeight: 1
|
||||
|
@ -130,9 +102,10 @@ Item {
|
|||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
font.family: "Fira Sans"
|
||||
font.pixelSize: usernameCollisionBody.fontSize - 10
|
||||
font.pixelSize: usernameCollisionBody.fontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
font.bold: usernameCollisionBody.fontBold
|
||||
width: banner.width
|
||||
width: root.bannerWidth
|
||||
|
||||
placeholderText: "Choose your own"
|
||||
|
||||
|
@ -170,54 +143,33 @@ Item {
|
|||
|
||||
Item {
|
||||
id: buttons
|
||||
width: Math.max(banner.width, cancelContainer.width + profileButton.width)
|
||||
width: root.bannerWidth
|
||||
height: d.minHeightButton
|
||||
anchors {
|
||||
top: textField.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - banner.width) / 2
|
||||
leftMargin: (parent.width - root.bannerWidth) / 2
|
||||
}
|
||||
|
||||
Item {
|
||||
id: cancelContainer
|
||||
width: cancelText.width
|
||||
height: d.minHeightButton
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
}
|
||||
Text {
|
||||
id: cancelText
|
||||
text: qsTr("Cancel");
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
lineHeight: 1
|
||||
color: "white"
|
||||
font.family: usernameCollisionBody.fontFamily
|
||||
font.pixelSize: usernameCollisionBody.fontSize
|
||||
font.capitalization: Font.AllUppercase;
|
||||
font.bold: usernameCollisionBody.fontBold
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("CANCEL")
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
|
||||
fontFamily: usernameCollisionBody.fontFamily
|
||||
fontSize: usernameCollisionBody.fontSize
|
||||
fontBold: usernameCollisionBody.fontBold
|
||||
onClicked: {
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "" });
|
||||
}
|
||||
MouseArea {
|
||||
id: cancelArea
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
}
|
||||
}
|
||||
TextMetrics {
|
||||
id: profileButtonTextMetrics
|
||||
font: cancelText.font
|
||||
text: qsTr("CREATE YOUR PROFILE")
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: profileButton
|
||||
|
@ -225,7 +177,7 @@ Item {
|
|||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
width: Math.max(profileButtonTextMetrics.width + 2 * hifi.dimensions.contentSpacing.x, d.minWidthButton)
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
text: qsTr("Create your profile")
|
||||
|
@ -241,36 +193,18 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
//dont rise local keyboard
|
||||
keyboardEnabled = !root.isTablet && HMD.active;
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
if (root.isTablet || root.isOverlay) {
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
}
|
||||
|
||||
root.text = "";
|
||||
d.resize();
|
||||
textField.focus = true;
|
||||
if (usernameCollisionBody.errorString !== "") {
|
||||
mainTextContainer.visible = true;
|
||||
mainTextContainer.text = usernameCollisionBody.errorString;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleCreateCompleted: {
|
||||
console.log("Create Succeeded")
|
||||
console.log("Create Succeeded");
|
||||
loginDialog.loginThroughSteam();
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "fromBody": "UsernameCollisionBody" })
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "linkSteam": false })
|
||||
}
|
||||
onHandleCreateFailed: {
|
||||
console.log("Create Failed: " + error)
|
||||
|
||||
mainTextContainer.visible = true
|
||||
mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.")
|
||||
mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.");
|
||||
}
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded");
|
||||
|
|
BIN
interface/resources/qml/LoginDialog/background.jpg
Normal file
BIN
interface/resources/qml/LoginDialog/background.jpg
Normal file
Binary file not shown.
After ![]() (image error) Size: 315 KiB |
Binary file not shown.
Before ![]() (image error) Size: 22 KiB |
BIN
interface/resources/qml/LoginDialog/background_tablet.jpg
Normal file
BIN
interface/resources/qml/LoginDialog/background_tablet.jpg
Normal file
Binary file not shown.
After ![]() (image error) Size: 272 KiB |
Binary file not shown.
Before ![]() (image error) Size: 58 KiB |
Binary file not shown.
After ![]() (image error) Size: 281 KiB |
Binary file not shown.
Before ![]() (image error) Size: 49 KiB |
|
@ -36,6 +36,8 @@ FocusScope {
|
|||
property string title: ""
|
||||
property int titleWidth: 0
|
||||
property alias text: loginKeyboard.mirroredText
|
||||
property alias bannerWidth: banner.width
|
||||
property alias bannerHeight: banner.height
|
||||
|
||||
function tryDestroy() {
|
||||
root.destroy()
|
||||
|
@ -51,10 +53,36 @@ FocusScope {
|
|||
}
|
||||
|
||||
Image {
|
||||
z: -10
|
||||
id: loginDialogBackground
|
||||
source: "LoginDialog/background.png"
|
||||
source: "LoginDialog/background.jpg"
|
||||
anchors.fill: parent
|
||||
z: -2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
z: -6
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.5
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
z: -5
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 0.18 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
|
@ -121,6 +149,6 @@ FocusScope {
|
|||
|
||||
Component.onCompleted: {
|
||||
keyboardTimer.start();
|
||||
bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": ""});
|
||||
bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,20 +44,18 @@ Rectangle {
|
|||
|
||||
|
||||
onPasswordChanged: {
|
||||
var use3DKeyboard = (typeof MenuInterface === "undefined") ? false : MenuInterface.isOptionChecked("Use 3D Keyboard");
|
||||
var use3DKeyboard = (typeof KeyboardScriptingInterface === "undefined") ? false : KeyboardScriptingInterface.use3DKeyboard;
|
||||
if (use3DKeyboard) {
|
||||
KeyboardScriptingInterface.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
onRaisedChanged: {
|
||||
console.log("raising keyboard to " + raised);
|
||||
var use3DKeyboard = (typeof MenuInterface === "undefined") ? false : MenuInterface.isOptionChecked("Use 3D Keyboard");
|
||||
var use3DKeyboard = (typeof KeyboardScriptingInterface === "undefined") ? false : KeyboardScriptingInterface.use3DKeyboard;
|
||||
if (!use3DKeyboard) {
|
||||
keyboardBase.height = raised ? raisedHeight : 0;
|
||||
keyboardBase.visible = raised;
|
||||
} else {
|
||||
console.log("raising 3d keyboard to " + raised);
|
||||
KeyboardScriptingInterface.raised = raised;
|
||||
KeyboardScriptingInterface.password = raised ? password : false;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ TextField {
|
|||
property bool hasClearButton: false;
|
||||
property string leftPermanentGlyph: "";
|
||||
property string centerPlaceholderGlyph: "";
|
||||
property int styleRenderType: Text.NativeRendering
|
||||
|
||||
placeholderText: textField.placeholderText
|
||||
|
||||
|
@ -44,8 +45,8 @@ TextField {
|
|||
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
event.accepted = true;
|
||||
|
||||
// emit accepted signal manually
|
||||
|
@ -156,6 +157,7 @@ TextField {
|
|||
selectionColor: hifi.colors.primaryHighlight
|
||||
padding.left: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
renderType: textField.styleRenderType
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
|
|
|
@ -39,6 +39,8 @@ FocusScope {
|
|||
property alias text: loginKeyboard.mirroredText
|
||||
|
||||
property int titleWidth: 0
|
||||
property alias bannerWidth: banner.width
|
||||
property alias bannerHeight: banner.height
|
||||
property string iconText: hifi.glyphs.avatar
|
||||
property int iconSize: 35
|
||||
|
||||
|
@ -90,10 +92,36 @@ FocusScope {
|
|||
}
|
||||
|
||||
Image {
|
||||
z: -10
|
||||
id: loginDialogBackground
|
||||
source: "../LoginDialog/background.png"
|
||||
source: "../LoginDialog/background_tablet.jpg"
|
||||
anchors.fill: parent
|
||||
z: -2
|
||||
}
|
||||
|
||||
Item {
|
||||
z: -5
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 0.18 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
z: -6
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.5
|
||||
color: "black"
|
||||
}
|
||||
|
||||
HifiControlsUit.Keyboard {
|
||||
|
@ -143,7 +171,7 @@ FocusScope {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
keyboardTimer.start();
|
||||
bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
// LoginScreenDialog.qml
|
||||
//
|
||||
// Created by Wayne Chen on 2018/10/9
|
||||
// Copyright 2018 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 Hifi 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
import "qrc:///controls-uit" as HifiControlsUit
|
||||
import "qrc:///styles-uit" as HifiStylesUit
|
||||
|
||||
|
||||
LoginDialog {
|
||||
id: loginDialog
|
||||
|
||||
Loader {
|
||||
id: bodyLoader
|
||||
Item {
|
||||
|
||||
function login() {
|
||||
flavorText.visible = false
|
||||
mainTextContainer.visible = false
|
||||
toggleLoading(true)
|
||||
loginDialog.login(usernameField.text, passwordField.text)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginScreenDialog
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded, linking steam account")
|
||||
var poppedUp = Settings.getValue("loginDialogPoppedUp", false);
|
||||
if (poppedUp) {
|
||||
console.log("[ENCOURAGELOGINDIALOG]: logging in")
|
||||
var data = {
|
||||
"action": "user logged in"
|
||||
};
|
||||
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||
Settings.setValue("loginDialogPoppedUp", false);
|
||||
}
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
loginDialog.linkSteam()
|
||||
} else {
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
}
|
||||
onHandleLoginFailed: {
|
||||
console.log("Login Failed")
|
||||
var poppedUp = Settings.getValue("loginDialogPoppedUp", false);
|
||||
if (poppedUp) {
|
||||
console.log("[ENCOURAGELOGINDIALOG]: failed logging in")
|
||||
var data = {
|
||||
"action": "user failed logging in"
|
||||
};
|
||||
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||
Settings.setValue("loginDialogPoppedUp", false);
|
||||
}
|
||||
flavorText.visible = true
|
||||
mainTextContainer.visible = true
|
||||
toggleLoading(false)
|
||||
}
|
||||
onHandleLinkCompleted: {
|
||||
console.log("Link Succeeded")
|
||||
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
onHandleLinkFailed: {
|
||||
console.log("Link Failed")
|
||||
toggleLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -207,12 +207,12 @@ Flickable {
|
|||
width: 112
|
||||
label: "Y Offset"
|
||||
suffix: " cm"
|
||||
minimumValue: -10
|
||||
minimumValue: -50
|
||||
maximumValue: 50
|
||||
realStepSize: 1
|
||||
realValue: -5
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
sendConfigurationSettings();
|
||||
openVrConfiguration.forceActiveFocus();
|
||||
}
|
||||
|
@ -223,14 +223,14 @@ Flickable {
|
|||
id: headZOffset
|
||||
width: 112
|
||||
label: "Z Offset"
|
||||
minimumValue: -10
|
||||
minimumValue: -50
|
||||
maximumValue: 50
|
||||
realStepSize: 1
|
||||
decimals: 1
|
||||
suffix: " cm"
|
||||
realValue: -5
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
sendConfigurationSettings();
|
||||
openVrConfiguration.forceActiveFocus();
|
||||
}
|
||||
|
@ -319,11 +319,12 @@ Flickable {
|
|||
width: 112
|
||||
suffix: " cm"
|
||||
label: "Y Offset"
|
||||
minimumValue: -10
|
||||
minimumValue: -30
|
||||
maximumValue: 30
|
||||
realStepSize: 1
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
sendConfigurationSettings();
|
||||
openVrConfiguration.forceActiveFocus();
|
||||
}
|
||||
|
@ -335,12 +336,13 @@ Flickable {
|
|||
width: 112
|
||||
label: "Z Offset"
|
||||
suffix: " cm"
|
||||
minimumValue: -10
|
||||
minimumValue: -30
|
||||
maximumValue: 30
|
||||
realStepSize: 1
|
||||
decimals: 1
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
sendConfigurationSettings();
|
||||
openVrConfiguration.forceActiveFocus();
|
||||
}
|
||||
|
@ -574,7 +576,7 @@ Flickable {
|
|||
colorScheme: hifi.colorSchemes.dark
|
||||
realValue: 33.0
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
sendConfigurationSettings();
|
||||
openVrConfiguration.forceActiveFocus();
|
||||
}
|
||||
|
@ -592,7 +594,7 @@ Flickable {
|
|||
colorScheme: hifi.colorSchemes.dark
|
||||
realValue: 48
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
sendConfigurationSettings();
|
||||
openVrConfiguration.forceActiveFocus();
|
||||
}
|
||||
|
@ -771,7 +773,7 @@ Flickable {
|
|||
realStepSize: 1.0
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
onEditingFinished: {
|
||||
onRealValueChanged: {
|
||||
calibrationTimer.interval = realValue * 1000;
|
||||
openVrConfiguration.countDown = realValue;
|
||||
numberAnimation.duration = calibrationTimer.interval;
|
||||
|
@ -977,6 +979,13 @@ Flickable {
|
|||
var configurationType = settings["trackerConfiguration"];
|
||||
displayTrackerConfiguration(configurationType);
|
||||
|
||||
// default offset for user wearing puck on the center of their forehead.
|
||||
headYOffset.realValue = 4; // (cm), puck is above the head joint.
|
||||
headZOffset.realValue = 8; // (cm), puck is in front of the head joint.
|
||||
|
||||
// defaults for user wearing the pucks on the backs of their palms.
|
||||
handYOffset.realValue = 8; // (cm), puck is past the the hand joint. (set this to zero if puck is on the wrist)
|
||||
handZOffset.realValue = -4; // (cm), puck is on above hand joint.
|
||||
|
||||
var HmdHead = settings["HMDHead"];
|
||||
var viveController = settings["handController"];
|
||||
|
|
|
@ -61,7 +61,7 @@ Item {
|
|||
RalewaySemiBold {
|
||||
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
anchors.right: parent.right
|
||||
Layout.alignment: Qt.AlignRight
|
||||
font.pixelSize: 20
|
||||
color: "#afafaf"
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ Item {
|
|||
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
||||
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
||||
horizontalAlignment: Text.AlignRight
|
||||
anchors.right: parent.right
|
||||
Layout.alignment: Qt.AlignRight
|
||||
font.pixelSize: 20
|
||||
color: "#afafaf"
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@
|
|||
#include <FramebufferCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
#include <InfoView.h>
|
||||
#include <input-plugins/InputPlugin.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
|
@ -122,8 +121,6 @@
|
|||
#include <plugins/SteamClientPlugin.h>
|
||||
#include <plugins/InputConfiguration.h>
|
||||
#include <RecordingScriptingInterface.h>
|
||||
#include <UpdateSceneTask.h>
|
||||
#include <RenderViewTask.h>
|
||||
#include <render/EngineStats.h>
|
||||
#include <SecondaryCamera.h>
|
||||
#include <ResourceCache.h>
|
||||
|
@ -264,54 +261,7 @@ extern "C" {
|
|||
#include "AndroidHelper.h"
|
||||
#endif
|
||||
|
||||
enum ApplicationEvent {
|
||||
// Execute a lambda function
|
||||
Lambda = QEvent::User + 1,
|
||||
// Trigger the next render
|
||||
Render,
|
||||
// Trigger the next idle
|
||||
Idle,
|
||||
};
|
||||
|
||||
class RenderEventHandler : public QObject {
|
||||
using Parent = QObject;
|
||||
Q_OBJECT
|
||||
public:
|
||||
RenderEventHandler() {
|
||||
// Transfer to a new thread
|
||||
moveToNewNamedThread(this, "RenderThread", [](QThread* renderThread) {
|
||||
hifi::qt::addBlockingForbiddenThread("Render", renderThread);
|
||||
qApp->_lastTimeRendered.start();
|
||||
}, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority);
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize() {
|
||||
setObjectName("Render");
|
||||
PROFILE_SET_THREAD_NAME("Render");
|
||||
setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
|
||||
}
|
||||
|
||||
void render() {
|
||||
if (qApp->shouldPaint()) {
|
||||
qApp->paintGL();
|
||||
}
|
||||
}
|
||||
|
||||
bool event(QEvent* event) override {
|
||||
switch ((int)event->type()) {
|
||||
case ApplicationEvent::Render:
|
||||
render();
|
||||
qApp->_pendingRenderEvent.store(false);
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Parent::event(event);
|
||||
}
|
||||
};
|
||||
|
||||
#include "graphics/RenderEventHandler.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse")
|
||||
|
||||
|
@ -374,8 +324,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI
|
|||
static const int ENTITY_SERVER_ADDED_TIMEOUT = 5000;
|
||||
static const int ENTITY_SERVER_CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
static const uint32_t INVALID_FRAME = UINT32_MAX;
|
||||
|
||||
static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entities before physics enabled
|
||||
|
||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
|
@ -385,6 +333,10 @@ Setting::Handle<int> maxOctreePacketsPerSecond{"maxOctreePPS", DEFAULT_MAX_OCTRE
|
|||
Setting::Handle<bool> loginDialogPoppedUp{"loginDialogPoppedUp", false};
|
||||
static const QUrl OVERLAY_LOGIN_DIALOG_URL(PathUtils::qmlUrl("OverlayLoginDialog.qml"));
|
||||
|
||||
static const QString STANDARD_TO_ACTION_MAPPING_NAME = "Standard to Action";
|
||||
static const QString NO_MOVEMENT_MAPPING_NAME = "Standard to Action (No Movement)";
|
||||
static const QString NO_MOVEMENT_MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/standard_nomovement.json";
|
||||
|
||||
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
|
||||
static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
|
||||
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
||||
|
@ -1813,6 +1765,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice());
|
||||
}
|
||||
|
||||
QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
|
||||
_defaultScriptsLocation = getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str());
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
|
||||
|
@ -1834,8 +1789,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() {
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
// Do not show login dialog if requested not to on the command line
|
||||
QString hifiNoLoginCommandLineKey = QString("--").append(HIFI_NO_LOGIN_COMMAND_LINE_KEY);
|
||||
int index = arguments().indexOf(hifiNoLoginCommandLineKey);
|
||||
if (index != -1) {
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
return;
|
||||
}
|
||||
|
||||
// only for non-android. QML is ready to be shown at this time.
|
||||
showLoginScreen();
|
||||
#else
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
#endif
|
||||
});
|
||||
|
||||
|
@ -2071,7 +2036,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
|
||||
properties["render_rate"] = _renderLoopCounter.rate();
|
||||
properties["render_rate"] = getRenderLoopRate();
|
||||
properties["target_render_rate"] = getTargetRenderFrameRate();
|
||||
properties["present_rate"] = displayPlugin->presentRate();
|
||||
properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate();
|
||||
|
@ -2360,7 +2325,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
DependencyManager::get<Keyboard>()->createKeyboard();
|
||||
|
||||
_pendingIdleEvent = false;
|
||||
_pendingRenderEvent = false;
|
||||
_graphicsEngine.startup();
|
||||
|
||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||
|
||||
|
@ -2369,17 +2334,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground);
|
||||
connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground);
|
||||
AndroidHelper::instance().notifyLoadComplete();
|
||||
#else
|
||||
#if !defined(DISABLE_QML)
|
||||
// Do not show login dialog if requested not to on the command line
|
||||
const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "--no-login-suggestion";
|
||||
int index = arguments().indexOf(HIFI_NO_LOGIN_COMMAND_LINE_KEY);
|
||||
if (index == -1) {
|
||||
// request not found
|
||||
pauseUntilLoginDetermined();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
pauseUntilLoginDetermined();
|
||||
}
|
||||
|
||||
void Application::updateVerboseLogging() {
|
||||
|
@ -2544,6 +2500,8 @@ void Application::cleanupBeforeQuit() {
|
|||
QString webengineRemoteDebugging = QProcessEnvironment::systemEnvironment().value("QTWEBENGINE_REMOTE_DEBUGGING", "false");
|
||||
qCDebug(interfaceapp) << "QTWEBENGINE_REMOTE_DEBUGGING =" << webengineRemoteDebugging;
|
||||
|
||||
DependencyManager::prepareToExit();
|
||||
|
||||
if (tracing::enabled()) {
|
||||
auto tracer = DependencyManager::get<tracing::Tracer>();
|
||||
tracer->stopTracing();
|
||||
|
@ -2612,11 +2570,6 @@ void Application::cleanupBeforeQuit() {
|
|||
|
||||
// Cleanup all overlays after the scripts, as scripts might add more
|
||||
_overlays.cleanupAllOverlays();
|
||||
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
|
||||
// removal of the items.
|
||||
// See https://highfidelity.fogbugz.com/f/cases/5328
|
||||
_main3DScene->enqueueFrame(); // flush all the transactions
|
||||
_main3DScene->processTransactionQueue(); // process and apply deletions
|
||||
|
||||
// first stop all timers directly or by invokeMethod
|
||||
// depending on what thread they run in
|
||||
|
@ -2631,7 +2584,6 @@ void Application::cleanupBeforeQuit() {
|
|||
}
|
||||
|
||||
_window->saveGeometry();
|
||||
_gpuContext->shutdown();
|
||||
|
||||
// Destroy third party processes after scripts have finished using them.
|
||||
#ifdef HAVE_DDE
|
||||
|
@ -2656,6 +2608,7 @@ void Application::cleanupBeforeQuit() {
|
|||
|
||||
// destroy Audio so it and its threads have a chance to go down safely
|
||||
// this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "stop");
|
||||
DependencyManager::destroy<AudioClient>();
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<AudioScriptingInterface>();
|
||||
|
@ -2688,10 +2641,9 @@ Application::~Application() {
|
|||
_shapeManager.collectGarbage();
|
||||
assert(_shapeManager.getNumShapes() == 0);
|
||||
|
||||
// shutdown render engine
|
||||
_main3DScene = nullptr;
|
||||
_renderEngine = nullptr;
|
||||
|
||||
// shutdown graphics engine
|
||||
_graphicsEngine.shutdown();
|
||||
|
||||
_gameWorkload.shutdown();
|
||||
|
||||
DependencyManager::destroy<Preferences>();
|
||||
|
@ -2747,10 +2699,8 @@ Application::~Application() {
|
|||
// quit the thread used by the closure event sender
|
||||
closeEventSender->thread()->quit();
|
||||
|
||||
// Can't log to file passed this point, FileLogger about to be deleted
|
||||
// Can't log to file past this point, FileLogger about to be deleted
|
||||
qInstallMessageHandler(LogHandler::verboseMessageHandler);
|
||||
|
||||
_renderEventHandler->deleteLater();
|
||||
}
|
||||
|
||||
void Application::initializeGL() {
|
||||
|
@ -2840,26 +2790,13 @@ void Application::initializeGL() {
|
|||
#endif
|
||||
|
||||
|
||||
_renderEventHandler = new RenderEventHandler();
|
||||
|
||||
// Build an offscreen GL context for the main thread.
|
||||
_glWidget->makeCurrent();
|
||||
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
_glWidget->swapBuffers();
|
||||
|
||||
|
||||
// Create the GPU backend
|
||||
|
||||
// Requires the window context, because that's what's used in the actual rendering
|
||||
// and the GPU backend will make things like the VAO which cannot be shared across
|
||||
// contexts
|
||||
_glWidget->makeCurrent();
|
||||
gpu::Context::init<gpu::gl::GLBackend>();
|
||||
_glWidget->makeCurrent();
|
||||
_gpuContext = std::make_shared<gpu::Context>();
|
||||
|
||||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||
_graphicsEngine.initializeGPU(_glWidget);
|
||||
}
|
||||
|
||||
static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" };
|
||||
|
@ -2873,7 +2810,7 @@ void Application::initializeDisplayPlugins() {
|
|||
// Once time initialization code
|
||||
DisplayPluginPointer targetDisplayPlugin;
|
||||
foreach(auto displayPlugin, displayPlugins) {
|
||||
displayPlugin->setContext(_gpuContext);
|
||||
displayPlugin->setContext(_graphicsEngine.getGPUContext());
|
||||
if (displayPlugin->getName() == lastActiveDisplayPluginName) {
|
||||
targetDisplayPlugin = displayPlugin;
|
||||
}
|
||||
|
@ -2943,18 +2880,7 @@ void Application::initializeDisplayPlugins() {
|
|||
void Application::initializeRenderEngine() {
|
||||
// FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
|
||||
DeadlockWatchdogThread::withPause([&] {
|
||||
// Set up the render engine
|
||||
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
||||
#ifndef Q_OS_ANDROID
|
||||
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !DISABLE_DEFERRED);
|
||||
#endif
|
||||
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !DISABLE_DEFERRED, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||
_renderEngine->load();
|
||||
_renderEngine->registerScene(_main3DScene);
|
||||
|
||||
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
||||
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
||||
_graphicsEngine.initializeRender(DISABLE_DEFERRED);
|
||||
DependencyManager::get<Keyboard>()->registerKeyboardHighlighting();
|
||||
});
|
||||
}
|
||||
|
@ -2965,6 +2891,7 @@ static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, in
|
|||
#endif
|
||||
|
||||
void Application::showLoginScreen() {
|
||||
#if !defined(DISABLE_QML)
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
if (!accountManager->isLoggedIn()) {
|
||||
|
@ -2983,6 +2910,9 @@ void Application::showLoginScreen() {
|
|||
}
|
||||
_loginDialogPoppedUp = !accountManager->isLoggedIn();
|
||||
loginDialogPoppedUp.set(_loginDialogPoppedUp);
|
||||
#else
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::initializeUi() {
|
||||
|
@ -3176,7 +3106,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
|
||||
surfaceContext->setContextProperty("FrameTimings", &_graphicsEngine._frameTimingsScriptingInterface);
|
||||
surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this));
|
||||
|
||||
surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE);
|
||||
|
@ -3225,7 +3155,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
|
||||
surfaceContext->setContextProperty("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get());
|
||||
surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get());
|
||||
surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
|
||||
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
|
@ -3513,7 +3443,7 @@ void Application::resizeGL() {
|
|||
|
||||
auto renderResolutionScale = getRenderResolutionScale();
|
||||
if (displayPlugin->getRenderResolutionScale() != renderResolutionScale) {
|
||||
auto renderConfig = _renderEngine->getConfiguration();
|
||||
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
|
||||
assert(renderConfig);
|
||||
auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
|
||||
assert(mainView);
|
||||
|
@ -3763,8 +3693,8 @@ void Application::onPresent(quint32 frameCount) {
|
|||
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
||||
}
|
||||
expected = false;
|
||||
if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) {
|
||||
postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
|
||||
if (_graphicsEngine.checkPendingRenderEvent() && !isAboutToQuit()) {
|
||||
postEvent(_graphicsEngine._renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3859,7 +3789,7 @@ bool Application::event(QEvent* event) {
|
|||
}
|
||||
|
||||
// Allow focused Entities and Overlays to handle keyboard input
|
||||
if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event)) {
|
||||
if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event) && !qApp->getLoginDialogPoppedUp()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3972,6 +3902,10 @@ bool Application::eventFilter(QObject* object, QEvent* event) {
|
|||
static bool _altPressed{ false };
|
||||
|
||||
void Application::keyPressEvent(QKeyEvent* event) {
|
||||
if (isHMDMode() && qApp->getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_altPressed = event->key() == Qt::Key_Alt;
|
||||
|
||||
if (!event->isAutoRepeat()) {
|
||||
|
@ -4215,6 +4149,10 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
}
|
||||
|
||||
void Application::keyReleaseEvent(QKeyEvent* event) {
|
||||
if (isHMDMode() && qApp->getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event->isAutoRepeat()) {
|
||||
_keysPressed.remove(event->key());
|
||||
}
|
||||
|
@ -4579,39 +4517,6 @@ bool Application::acceptSnapshot(const QString& urlString) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static uint32_t _renderedFrameIndex { INVALID_FRAME };
|
||||
|
||||
bool Application::shouldPaint() const {
|
||||
if (_aboutToQuit || _window->isMinimized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto displayPlugin = getActiveDisplayPlugin();
|
||||
|
||||
#ifdef DEBUG_PAINT_DELAY
|
||||
static uint64_t paintDelaySamples{ 0 };
|
||||
static uint64_t paintDelayUsecs{ 0 };
|
||||
|
||||
paintDelayUsecs += displayPlugin->getPaintDelayUsecs();
|
||||
|
||||
static const int PAINT_DELAY_THROTTLE = 1000;
|
||||
if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) {
|
||||
qCDebug(interfaceapp).nospace() <<
|
||||
"Paint delay (" << paintDelaySamples << " samples): " <<
|
||||
(float)paintDelaySamples / paintDelayUsecs << "us";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Throttle if requested
|
||||
if (displayPlugin->isThrottled() && (_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sync up the _renderedFrameIndex
|
||||
_renderedFrameIndex = displayPlugin->presentCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <Windows.h>
|
||||
#include <TCHAR.h>
|
||||
|
@ -4865,26 +4770,13 @@ void Application::idle() {
|
|||
if (displayPlugin) {
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate());
|
||||
}
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", uint32_t, ResourceCache::getLoadingRequestCount());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, getRenderLoopRate());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", uint32_t, ResourceCache::getLoadingRequests().length());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", uint32_t, ResourceCache::getPendingRequestCount());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
|
||||
auto renderConfig = _renderEngine->getConfiguration();
|
||||
PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_gpuContext->getFrameTimerGPUAverage());
|
||||
auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer");
|
||||
auto linearDepth = renderConfig->getConfig("LinearDepth");
|
||||
auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry");
|
||||
auto renderDeferred = renderConfig->getConfig("RenderDeferred");
|
||||
auto toneAndPostRangeTimer = renderConfig->getConfig("ToneAndPostRangeTimer");
|
||||
|
||||
PROFILE_COUNTER(render_detail, "gpuTimes", {
|
||||
{ "OpaqueRangeTimer", opaqueRangeTimer ? opaqueRangeTimer->property("gpuRunTime") : 0 },
|
||||
{ "LinearDepth", linearDepth ? linearDepth->property("gpuRunTime") : 0 },
|
||||
{ "SurfaceGeometry", surfaceGeometry ? surfaceGeometry->property("gpuRunTime") : 0 },
|
||||
{ "RenderDeferred", renderDeferred ? renderDeferred->property("gpuRunTime") : 0 },
|
||||
{ "ToneAndPostRangeTimer", toneAndPostRangeTimer ? toneAndPostRangeTimer->property("gpuRunTime") : 0 }
|
||||
});
|
||||
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
|
||||
PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage());
|
||||
|
||||
PROFILE_RANGE(app, __FUNCTION__);
|
||||
|
||||
|
@ -5258,9 +5150,6 @@ void Application::init() {
|
|||
#if !defined(DISABLE_QML)
|
||||
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
||||
#endif
|
||||
if (!DISABLE_DEFERRED) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->init();
|
||||
}
|
||||
DependencyManager::get<AvatarManager>()->init();
|
||||
|
||||
_timerStart.start();
|
||||
|
@ -5329,7 +5218,7 @@ void Application::init() {
|
|||
}
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
_gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene, _entitySimulation);
|
||||
_gameWorkload.startup(getEntities()->getWorkloadSpace(), _graphicsEngine.getRenderScene(), _entitySimulation);
|
||||
_entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace());
|
||||
}
|
||||
|
||||
|
@ -5340,7 +5229,14 @@ void Application::pauseUntilLoginDetermined() {
|
|||
}
|
||||
|
||||
getMyAvatar()->setEnableMeshVisible(false);
|
||||
_controllerScriptingInterface->disableMapping("Standard to Action");
|
||||
_controllerScriptingInterface->disableMapping(STANDARD_TO_ACTION_MAPPING_NAME);
|
||||
|
||||
{
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
if (userInputMapper->loadMapping(NO_MOVEMENT_MAPPING_JSON)) {
|
||||
_controllerScriptingInterface->enableMapping(NO_MOVEMENT_MAPPING_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
const auto& nodeList = DependencyManager::get<NodeList>();
|
||||
// save interstitial mode setting until resuming.
|
||||
|
@ -5371,7 +5267,7 @@ void Application::resumeAfterLoginDialogActionTaken() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!isHMDMode()) {
|
||||
if (!isHMDMode() && getDesktopTabletBecomesToolbarSetting()) {
|
||||
auto toolbar = DependencyManager::get<ToolbarScriptingInterface>()->getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
toolbar->writeProperty("visible", true);
|
||||
} else {
|
||||
|
@ -5381,8 +5277,13 @@ void Application::resumeAfterLoginDialogActionTaken() {
|
|||
|
||||
updateSystemTabletMode();
|
||||
|
||||
{
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->unloadMapping(NO_MOVEMENT_MAPPING_JSON);
|
||||
_controllerScriptingInterface->disableMapping(NO_MOVEMENT_MAPPING_NAME);
|
||||
}
|
||||
getMyAvatar()->setEnableMeshVisible(true);
|
||||
_controllerScriptingInterface->enableMapping("Standard to Action");
|
||||
_controllerScriptingInterface->enableMapping(STANDARD_TO_ACTION_MAPPING_NAME);
|
||||
|
||||
const auto& nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->getDomainHandler().setInterstitialModeEnabled(_interstitialModeEnabled);
|
||||
|
@ -5391,7 +5292,12 @@ void Application::resumeAfterLoginDialogActionTaken() {
|
|||
// this will force the model the look at the correct directory (weird order of operations issue)
|
||||
scriptEngines->reloadLocalFiles();
|
||||
|
||||
scriptEngines->loadScripts();
|
||||
if (!_defaultScriptsLocation.exists()) {
|
||||
scriptEngines->loadDefaultScripts();
|
||||
scriptEngines->defaultScriptsLocationOverridden(true);
|
||||
} else {
|
||||
scriptEngines->loadScripts();
|
||||
}
|
||||
}
|
||||
|
||||
if (_firstRun.get()) {
|
||||
|
@ -5466,7 +5372,7 @@ void Application::updateLOD(float deltaTime) const {
|
|||
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
||||
if (!isThrottleRendering()) {
|
||||
float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
|
||||
float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
|
||||
float engineRunTime = (float)(_graphicsEngine.getRenderEngine()->getConfiguration().get()->getCPURunTime());
|
||||
float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
|
||||
float batchTime = getGPUContext()->getFrameTimerBatchAverage();
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
@ -5846,6 +5752,9 @@ void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
|
|||
_keyboardFocusHighlight->setVisible(false);
|
||||
}
|
||||
}
|
||||
if (overlayID == _loginDialogOverlayID) {
|
||||
emit loginDialogFocusEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5867,7 +5776,7 @@ void Application::updateSecondaryCameraViewFrustum() {
|
|||
// camera should be.
|
||||
|
||||
// Code based on SecondaryCameraJob
|
||||
auto renderConfig = _renderEngine->getConfiguration();
|
||||
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
|
||||
assert(renderConfig);
|
||||
auto camera = dynamic_cast<SecondaryCameraJobConfig*>(renderConfig->getConfig("SecondaryCamera"));
|
||||
|
||||
|
@ -5936,7 +5845,7 @@ void Application::updateSecondaryCameraViewFrustum() {
|
|||
static bool domainLoadingInProgress = false;
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1);
|
||||
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_graphicsEngine._renderFrameCount + 1);
|
||||
|
||||
if (_aboutToQuit) {
|
||||
return;
|
||||
|
@ -6355,7 +6264,7 @@ void Application::update(float deltaTime) {
|
|||
// TODO: Fix this by modeling the way the secondary camera works on how the main camera works
|
||||
// ie. Use a camera object stored in the game logic and informs the Engine on where the secondary
|
||||
// camera should be.
|
||||
updateSecondaryCameraViewFrustum();
|
||||
// updateSecondaryCameraViewFrustum();
|
||||
}
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
@ -6431,13 +6340,6 @@ void Application::update(float deltaTime) {
|
|||
|
||||
updateRenderArgs(deltaTime);
|
||||
|
||||
// HACK
|
||||
// load the view frustum
|
||||
// FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||
// Then we can move this logic into the Avatar::simulate call.
|
||||
myAvatar->preDisplaySide(&_appRenderArgs._renderArgs);
|
||||
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("AnimDebugDraw");
|
||||
AnimDebugDraw::getInstance().update();
|
||||
|
@ -6448,10 +6350,15 @@ void Application::update(float deltaTime) {
|
|||
PerformanceTimer perfTimer("enqueueFrame");
|
||||
getMain3DScene()->enqueueFrame();
|
||||
}
|
||||
|
||||
// If the display plugin is inactive then the frames won't be processed so process them here.
|
||||
if (!getActiveDisplayPlugin()->isActive()) {
|
||||
getMain3DScene()->processTransactionQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateRenderArgs(float deltaTime) {
|
||||
editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) {
|
||||
_graphicsEngine.editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) {
|
||||
PerformanceTimer perfTimer("editRenderArgs");
|
||||
appRenderArgs._headPose = getHMDSensorPose();
|
||||
|
||||
|
@ -6480,7 +6387,7 @@ void Application::updateRenderArgs(float deltaTime) {
|
|||
_viewFrustum.setProjection(adjustedProjection);
|
||||
_viewFrustum.calculate();
|
||||
}
|
||||
appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(),
|
||||
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
appRenderArgs._renderArgs._scene = getMain3DScene();
|
||||
|
@ -6565,6 +6472,13 @@ void Application::updateRenderArgs(float deltaTime) {
|
|||
QMutexLocker viewLocker(&_viewMutex);
|
||||
appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum);
|
||||
}
|
||||
|
||||
|
||||
// HACK
|
||||
// load the view frustum
|
||||
// FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||
// Then we can move this logic into the Avatar::simulate call.
|
||||
myAvatar->preDisplaySide(&appRenderArgs._renderArgs);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -7168,7 +7082,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
||||
|
||||
scriptEngine->registerGlobalObject("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get());
|
||||
scriptEngine->registerGlobalObject("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get());
|
||||
scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get());
|
||||
|
||||
GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data());
|
||||
|
@ -8741,6 +8655,7 @@ void Application::createLoginDialogOverlay() {
|
|||
overlays.editOverlay(keyboard->getAnchorID(), properties);
|
||||
keyboard->setResetKeyboardPositionOnRaise(false);
|
||||
}
|
||||
setKeyboardFocusOverlay(_loginDialogOverlayID);
|
||||
getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false);
|
||||
getApplicationCompositor().getReticleInterface()->setVisible(false);
|
||||
if (!_loginStateManager.isSetUp()) {
|
||||
|
@ -8749,11 +8664,13 @@ void Application::createLoginDialogOverlay() {
|
|||
}
|
||||
|
||||
void Application::updateLoginDialogOverlayPosition() {
|
||||
auto overlayPosition = getOverlays().getProperty(_loginDialogOverlayID, "position");
|
||||
const float LOOK_AWAY_THRESHOLD_ANGLE = 40.0f;
|
||||
auto& overlays = getOverlays();
|
||||
auto overlayPosition = overlays.getProperty(_loginDialogOverlayID, "position");
|
||||
auto overlayPositionVec = vec3FromVariant(overlayPosition.value);
|
||||
auto cameraPositionVec = _myCamera.getPosition();
|
||||
auto cameraOrientation = _myCamera.getOrientation();
|
||||
cameraOrientation = cancelOutRollAndPitch(cameraOrientation);
|
||||
cameraOrientation = cancelOutRoll(cameraOrientation);
|
||||
auto headLookVec = (cameraOrientation * Vectors::FRONT);
|
||||
auto overlayToHeadVec = overlayPositionVec - cameraPositionVec;
|
||||
auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI);
|
||||
|
@ -8762,12 +8679,12 @@ void Application::updateLoginDialogOverlayPosition() {
|
|||
auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * -0.1f);
|
||||
auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180;
|
||||
|
||||
if (pointAngle > 40.0f) {
|
||||
if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE) {
|
||||
QVariantMap properties {
|
||||
{"position", vec3toVariant(newOverlayPositionVec)},
|
||||
{"orientation", quatToVariant(newOverlayOrientation)}
|
||||
};
|
||||
getOverlays().editOverlay(_loginDialogOverlayID, properties);
|
||||
overlays.editOverlay(_loginDialogOverlayID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,11 +71,11 @@
|
|||
#include "ui/overlays/Overlays.h"
|
||||
|
||||
#include "workload/GameWorkload.h"
|
||||
#include "graphics/GraphicsEngine.h"
|
||||
|
||||
#include <procedural/ProceduralSkybox.h>
|
||||
#include <graphics/Skybox.h>
|
||||
#include <ModelScriptingInterface.h>
|
||||
#include "FrameTimingsScriptingInterface.h"
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
|
@ -98,6 +98,8 @@ static const UINT UWM_SHOW_APPLICATION =
|
|||
#endif
|
||||
|
||||
static const QString RUNNING_MARKER_FILENAME = "Interface.running";
|
||||
static const QString SCRIPTS_SWITCH = "scripts";
|
||||
static const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "no-login-suggestion";
|
||||
|
||||
class Application;
|
||||
#if defined(qApp)
|
||||
|
@ -153,7 +155,6 @@ public:
|
|||
void updateSecondaryCameraViewFrustum();
|
||||
|
||||
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
||||
void paintGL();
|
||||
void resizeGL();
|
||||
|
||||
bool event(QEvent* event) override;
|
||||
|
@ -203,8 +204,8 @@ public:
|
|||
|
||||
Overlays& getOverlays() { return _overlays; }
|
||||
|
||||
size_t getRenderFrameCount() const { return _renderFrameCount; }
|
||||
float getRenderLoopRate() const { return _renderLoopCounter.rate(); }
|
||||
size_t getRenderFrameCount() const { return _graphicsEngine.getRenderFrameCount(); }
|
||||
float getRenderLoopRate() const { return _graphicsEngine.getRenderLoopRate(); }
|
||||
float getNumCollisionObjects() const;
|
||||
float getTargetRenderFrameRate() const; // frames/second
|
||||
|
||||
|
@ -275,10 +276,10 @@ public:
|
|||
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
|
||||
int getMaxOctreePacketsPerSecond() const;
|
||||
|
||||
render::ScenePointer getMain3DScene() override { return _main3DScene; }
|
||||
const render::ScenePointer& getMain3DScene() const { return _main3DScene; }
|
||||
render::EnginePointer getRenderEngine() override { return _renderEngine; }
|
||||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||
render::ScenePointer getMain3DScene() override { return _graphicsEngine.getRenderScene(); }
|
||||
render::EnginePointer getRenderEngine() override { return _graphicsEngine.getRenderEngine(); }
|
||||
gpu::ContextPointer getGPUContext() const { return _graphicsEngine.getGPUContext(); }
|
||||
|
||||
|
||||
const GameWorkload& getGameWorkload() const { return _gameWorkload; }
|
||||
|
||||
|
@ -344,6 +345,8 @@ signals:
|
|||
|
||||
void interstitialModeChanged(bool isInInterstitialMode);
|
||||
|
||||
void loginDialogFocusEnabled();
|
||||
|
||||
void miniTabletEnabledChanged(bool enabled);
|
||||
|
||||
public slots:
|
||||
|
@ -526,7 +529,6 @@ private:
|
|||
bool handleFileOpenEvent(QFileOpenEvent* event);
|
||||
void cleanupBeforeQuit();
|
||||
|
||||
bool shouldPaint() const;
|
||||
void idle();
|
||||
void update(float deltaTime);
|
||||
|
||||
|
@ -546,8 +548,6 @@ private:
|
|||
|
||||
void initializeAcceptedFiles();
|
||||
|
||||
void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/);
|
||||
|
||||
bool importJSONFromURL(const QString& urlString);
|
||||
bool importSVOFromURL(const QString& urlString);
|
||||
bool importFromZIP(const QString& filePath);
|
||||
|
@ -597,18 +597,12 @@ private:
|
|||
|
||||
bool _activatingDisplayPlugin { false };
|
||||
|
||||
uint32_t _renderFrameCount { 0 };
|
||||
|
||||
// Frame Rate Measurement
|
||||
RateCounter<500> _renderLoopCounter;
|
||||
RateCounter<500> _gameLoopCounter;
|
||||
|
||||
FrameTimingsScriptingInterface _frameTimingsScriptingInterface;
|
||||
|
||||
QTimer _minimizedWindowTimer;
|
||||
QElapsedTimer _timerStart;
|
||||
QElapsedTimer _lastTimeUpdated;
|
||||
QElapsedTimer _lastTimeRendered;
|
||||
|
||||
int _minimumGPUTextureMemSizeStabilityCount { 30 };
|
||||
|
||||
|
@ -672,6 +666,7 @@ private:
|
|||
ControllerScriptingInterface* _controllerScriptingInterface{ nullptr };
|
||||
QPointer<LogDialog> _logDialog;
|
||||
QPointer<EntityScriptServerLogDialog> _entityScriptServerLogDialog;
|
||||
QDir _defaultScriptsLocation;
|
||||
|
||||
FileLogger* _logger;
|
||||
|
||||
|
@ -703,29 +698,9 @@ private:
|
|||
|
||||
quint64 _lastFaceTrackerUpdate;
|
||||
|
||||
render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
||||
render::EnginePointer _renderEngine{ new render::RenderEngine() };
|
||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||
|
||||
GameWorkload _gameWorkload;
|
||||
|
||||
mutable QMutex _renderArgsMutex{ QMutex::Recursive };
|
||||
struct AppRenderArgs {
|
||||
render::Args _renderArgs;
|
||||
glm::mat4 _eyeToWorld;
|
||||
glm::mat4 _view;
|
||||
glm::mat4 _eyeOffsets[2];
|
||||
glm::mat4 _eyeProjections[2];
|
||||
glm::mat4 _headPose;
|
||||
glm::mat4 _sensorToWorld;
|
||||
float _sensorToWorldScale { 1.0f };
|
||||
bool _isStereo{ false };
|
||||
};
|
||||
AppRenderArgs _appRenderArgs;
|
||||
|
||||
|
||||
using RenderArgsEditor = std::function <void (AppRenderArgs&)>;
|
||||
void editRenderArgs(RenderArgsEditor editor);
|
||||
GraphicsEngine _graphicsEngine;
|
||||
void updateRenderArgs(float deltaTime);
|
||||
|
||||
|
||||
|
@ -771,8 +746,6 @@ private:
|
|||
|
||||
bool _keyboardDeviceHasFocus { true };
|
||||
|
||||
QString _returnFromFullScreenMirrorTo;
|
||||
|
||||
ConnectionMonitor _connectionMonitor;
|
||||
|
||||
QTimer _addAssetToWorldResizeTimer;
|
||||
|
@ -806,12 +779,8 @@ private:
|
|||
|
||||
QUrl _avatarOverrideUrl;
|
||||
bool _saveAvatarOverrideUrl { false };
|
||||
QObject* _renderEventHandler{ nullptr };
|
||||
|
||||
friend class RenderEventHandler;
|
||||
|
||||
std::atomic<bool> _pendingIdleEvent { true };
|
||||
std::atomic<bool> _pendingRenderEvent { true };
|
||||
|
||||
bool quitWhenFinished { false };
|
||||
|
||||
|
|
|
@ -19,220 +19,207 @@
|
|||
#include "Util.h"
|
||||
|
||||
|
||||
// Statically provided display and input plugins
|
||||
extern DisplayPluginList getDisplayPlugins();
|
||||
|
||||
void Application::editRenderArgs(RenderArgsEditor editor) {
|
||||
QMutexLocker renderLocker(&_renderArgsMutex);
|
||||
editor(_appRenderArgs);
|
||||
|
||||
}
|
||||
|
||||
void Application::paintGL() {
|
||||
// Some plugins process message events, allowing paintGL to be called reentrantly.
|
||||
|
||||
_renderFrameCount++;
|
||||
_lastTimeRendered.start();
|
||||
|
||||
auto lastPaintBegin = usecTimestampNow();
|
||||
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
|
||||
PerformanceTimer perfTimer("paintGL");
|
||||
|
||||
if (nullptr == _displayPlugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayPluginPointer displayPlugin;
|
||||
{
|
||||
PROFILE_RANGE(render, "/getActiveDisplayPlugin");
|
||||
displayPlugin = getActiveDisplayPlugin();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/pluginBeginFrameRender");
|
||||
// If a display plugin loses it's underlying support, it
|
||||
// needs to be able to signal us to not use it
|
||||
if (!displayPlugin->beginFrameRender(_renderFrameCount)) {
|
||||
QMetaObject::invokeMethod(this, "updateDisplayMode");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RenderArgs renderArgs;
|
||||
glm::mat4 HMDSensorPose;
|
||||
glm::mat4 eyeToWorld;
|
||||
glm::mat4 sensorToWorld;
|
||||
|
||||
bool isStereo;
|
||||
glm::mat4 stereoEyeOffsets[2];
|
||||
glm::mat4 stereoEyeProjections[2];
|
||||
|
||||
{
|
||||
QMutexLocker viewLocker(&_renderArgsMutex);
|
||||
renderArgs = _appRenderArgs._renderArgs;
|
||||
|
||||
// don't render if there is no context.
|
||||
if (!_appRenderArgs._renderArgs._context) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMDSensorPose = _appRenderArgs._headPose;
|
||||
eyeToWorld = _appRenderArgs._eyeToWorld;
|
||||
sensorToWorld = _appRenderArgs._sensorToWorld;
|
||||
isStereo = _appRenderArgs._isStereo;
|
||||
for_each_eye([&](Eye eye) {
|
||||
stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye];
|
||||
stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye];
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/gpuContextReset");
|
||||
_gpuContext->beginFrame(_appRenderArgs._view, HMDSensorPose);
|
||||
// Reset the gpu::Context Stages
|
||||
// Back to the default framebuffer;
|
||||
gpu::doInBatch("Application_render::gpuContextReset", _gpuContext, [&](gpu::Batch& batch) {
|
||||
batch.resetStages();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/renderOverlay");
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
// NOTE: There is no batch associated with this renderArgs
|
||||
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
||||
renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize());
|
||||
_applicationOverlay.renderOverlay(&renderArgs);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/updateCompositor");
|
||||
getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer finalFramebuffer;
|
||||
QSize finalFramebufferSize;
|
||||
{
|
||||
PROFILE_RANGE(render, "/getOutputFramebuffer");
|
||||
// Primary rendering pass
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
finalFramebufferSize = framebufferCache->getFrameBufferSize();
|
||||
// Final framebuffer that will be handed to the display-plugin
|
||||
finalFramebuffer = framebufferCache->getFramebuffer();
|
||||
}
|
||||
|
||||
{
|
||||
if (isStereo) {
|
||||
renderArgs._context->enableStereo(true);
|
||||
renderArgs._context->setStereoProjections(stereoEyeProjections);
|
||||
renderArgs._context->setStereoViews(stereoEyeOffsets);
|
||||
}
|
||||
|
||||
renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
||||
renderArgs._hudTexture = _applicationOverlay.getOverlayTexture();
|
||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
runRenderFrame(&renderArgs);
|
||||
}
|
||||
|
||||
auto frame = _gpuContext->endFrame();
|
||||
frame->frameIndex = _renderFrameCount;
|
||||
frame->framebuffer = finalFramebuffer;
|
||||
frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
|
||||
auto frameBufferCache = DependencyManager::get<FramebufferCache>();
|
||||
if (frameBufferCache) {
|
||||
frameBufferCache->releaseFramebuffer(framebuffer);
|
||||
}
|
||||
};
|
||||
// deliver final scene rendering commands to the display plugin
|
||||
{
|
||||
PROFILE_RANGE(render, "/pluginOutput");
|
||||
PerformanceTimer perfTimer("pluginOutput");
|
||||
_renderLoopCounter.increment();
|
||||
displayPlugin->submitFrame(frame);
|
||||
}
|
||||
|
||||
// Reset the framebuffer and stereo state
|
||||
renderArgs._blitFramebuffer.reset();
|
||||
renderArgs._context->enableStereo(false);
|
||||
|
||||
#if !defined(DISABLE_QML)
|
||||
{
|
||||
auto stats = Stats::getInstance();
|
||||
if (stats) {
|
||||
stats->setRenderDetails(renderArgs._details);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;
|
||||
_frameTimingsScriptingInterface.addValue(lastPaintDuration);
|
||||
}
|
||||
//void Application::paintGL() {
|
||||
// // Some plugins process message events, allowing paintGL to be called reentrantly.
|
||||
//
|
||||
// _renderFrameCount++;
|
||||
// // SG: Moved into the RenderEventHandler
|
||||
// //_lastTimeRendered.start();
|
||||
//
|
||||
// auto lastPaintBegin = usecTimestampNow();
|
||||
// PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
|
||||
// PerformanceTimer perfTimer("paintGL");
|
||||
//
|
||||
// if (nullptr == _displayPlugin) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// DisplayPluginPointer displayPlugin;
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/getActiveDisplayPlugin");
|
||||
// displayPlugin = getActiveDisplayPlugin();
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/pluginBeginFrameRender");
|
||||
// // If a display plugin loses it's underlying support, it
|
||||
// // needs to be able to signal us to not use it
|
||||
// if (!displayPlugin->beginFrameRender(_renderFrameCount)) {
|
||||
// QMetaObject::invokeMethod(this, "updateDisplayMode");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// RenderArgs renderArgs;
|
||||
// glm::mat4 HMDSensorPose;
|
||||
// glm::mat4 eyeToWorld;
|
||||
// glm::mat4 sensorToWorld;
|
||||
//
|
||||
// bool isStereo;
|
||||
// glm::mat4 stereoEyeOffsets[2];
|
||||
// glm::mat4 stereoEyeProjections[2];
|
||||
//
|
||||
// {
|
||||
// QMutexLocker viewLocker(&_renderArgsMutex);
|
||||
// renderArgs = _appRenderArgs._renderArgs;
|
||||
//
|
||||
// // don't render if there is no context.
|
||||
// if (!_appRenderArgs._renderArgs._context) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// HMDSensorPose = _appRenderArgs._headPose;
|
||||
// eyeToWorld = _appRenderArgs._eyeToWorld;
|
||||
// sensorToWorld = _appRenderArgs._sensorToWorld;
|
||||
// isStereo = _appRenderArgs._isStereo;
|
||||
// for_each_eye([&](Eye eye) {
|
||||
// stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye];
|
||||
// stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye];
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/gpuContextReset");
|
||||
// _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose);
|
||||
// // Reset the gpu::Context Stages
|
||||
// // Back to the default framebuffer;
|
||||
// gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) {
|
||||
// batch.resetStages();
|
||||
// });
|
||||
// }
|
||||
//
|
||||
//
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/renderOverlay");
|
||||
// PerformanceTimer perfTimer("renderOverlay");
|
||||
// // NOTE: There is no batch associated with this renderArgs
|
||||
// // the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
||||
// renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize() * getRenderResolutionScale());
|
||||
// _applicationOverlay.renderOverlay(&renderArgs);
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/updateCompositor");
|
||||
// getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld);
|
||||
// }
|
||||
//
|
||||
// gpu::FramebufferPointer finalFramebuffer;
|
||||
// QSize finalFramebufferSize;
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/getOutputFramebuffer");
|
||||
// // Primary rendering pass
|
||||
// auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
// finalFramebufferSize = framebufferCache->getFrameBufferSize();
|
||||
// // Final framebuffer that will be handled to the display-plugin
|
||||
// finalFramebuffer = framebufferCache->getFramebuffer();
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// if (isStereo) {
|
||||
// renderArgs._context->enableStereo(true);
|
||||
// renderArgs._context->setStereoProjections(stereoEyeProjections);
|
||||
// renderArgs._context->setStereoViews(stereoEyeOffsets);
|
||||
// }
|
||||
//
|
||||
// renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
||||
// renderArgs._hudTexture = _applicationOverlay.getOverlayTexture();
|
||||
// renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
// _graphicsEngine.render_runRenderFrame(&renderArgs);
|
||||
// }
|
||||
//
|
||||
// auto frame = _graphicsEngine.getGPUContext()->endFrame();
|
||||
// frame->frameIndex = _renderFrameCount;
|
||||
// frame->framebuffer = finalFramebuffer;
|
||||
// frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
|
||||
// auto frameBufferCache = DependencyManager::get<FramebufferCache>();
|
||||
// if (frameBufferCache) {
|
||||
// frameBufferCache->releaseFramebuffer(framebuffer);
|
||||
// }
|
||||
// };
|
||||
// // deliver final scene rendering commands to the display plugin
|
||||
// {
|
||||
// PROFILE_RANGE(render, "/pluginOutput");
|
||||
// PerformanceTimer perfTimer("pluginOutput");
|
||||
// _renderLoopCounter.increment();
|
||||
// displayPlugin->submitFrame(frame);
|
||||
// }
|
||||
//
|
||||
// // Reset the framebuffer and stereo state
|
||||
// renderArgs._blitFramebuffer.reset();
|
||||
// renderArgs._context->enableStereo(false);
|
||||
//
|
||||
// {
|
||||
// Stats::getInstance()->setRenderDetails(renderArgs._details);
|
||||
// }
|
||||
//
|
||||
// uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;
|
||||
// _frameTimingsScriptingInterface.addValue(lastPaintDuration);
|
||||
//}
|
||||
|
||||
|
||||
// WorldBox Render Data & rendering functions
|
||||
|
||||
class WorldBoxRenderData {
|
||||
public:
|
||||
typedef render::Payload<WorldBoxRenderData> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
int _val = 0;
|
||||
static render::ItemID _item; // unique WorldBoxRenderData
|
||||
};
|
||||
|
||||
render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
||||
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
||||
PerformanceTimer perfTimer("worldBox");
|
||||
|
||||
auto& batch = *args->_batch;
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
renderWorldBox(args, batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::runRenderFrame(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("display");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
|
||||
|
||||
// The pending changes collecting the changes here
|
||||
render::Transaction transaction;
|
||||
|
||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
||||
// render models...
|
||||
PerformanceTimer perfTimer("entities");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::runRenderFrame() ... entities...");
|
||||
|
||||
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
|
||||
|
||||
renderArgs->_debugFlags = renderDebugFlags;
|
||||
}
|
||||
|
||||
// Make sure the WorldBox is in the scene
|
||||
// For the record, this one RenderItem is the first one we created and added to the scene.
|
||||
// We could move that code elsewhere but you know...
|
||||
if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
||||
auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
|
||||
auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
||||
|
||||
WorldBoxRenderData::_item = _main3DScene->allocateID();
|
||||
|
||||
transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
|
||||
_main3DScene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("EngineRun");
|
||||
_renderEngine->getRenderContext()->args = renderArgs;
|
||||
_renderEngine->run();
|
||||
}
|
||||
}
|
||||
//
|
||||
//class WorldBoxRenderData {
|
||||
//public:
|
||||
// typedef render::Payload<WorldBoxRenderData> Payload;
|
||||
// typedef Payload::DataPointer Pointer;
|
||||
//
|
||||
// int _val = 0;
|
||||
// static render::ItemID _item; // unique WorldBoxRenderData
|
||||
//};
|
||||
//
|
||||
//render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
||||
//
|
||||
//namespace render {
|
||||
// template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
||||
// template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
||||
// template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
||||
// if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
||||
// PerformanceTimer perfTimer("worldBox");
|
||||
//
|
||||
// auto& batch = *args->_batch;
|
||||
// DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
// renderWorldBox(args, batch);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//void Application::runRenderFrame(RenderArgs* renderArgs) {
|
||||
// PROFILE_RANGE(render, __FUNCTION__);
|
||||
// PerformanceTimer perfTimer("display");
|
||||
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
|
||||
//
|
||||
// // The pending changes collecting the changes here
|
||||
// render::Transaction transaction;
|
||||
//
|
||||
// if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
||||
// // render models...
|
||||
// PerformanceTimer perfTimer("entities");
|
||||
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
// "Application::runRenderFrame() ... entities...");
|
||||
//
|
||||
// RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
|
||||
//
|
||||
// renderArgs->_debugFlags = renderDebugFlags;
|
||||
// }
|
||||
//
|
||||
// // Make sure the WorldBox is in the scene
|
||||
// // For the record, this one RenderItem is the first one we created and added to the scene.
|
||||
// // We could move that code elsewhere but you know...
|
||||
// if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
||||
// auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
|
||||
// auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
||||
//
|
||||
// WorldBoxRenderData::_item = _main3DScene->allocateID();
|
||||
//
|
||||
// transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
|
||||
// _main3DScene->enqueueTransaction(transaction);
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// PerformanceTimer perfTimer("EngineRun");
|
||||
// _renderEngine->getRenderContext()->args = renderArgs;
|
||||
// _renderEngine->run();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
|
|
@ -247,25 +247,35 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
|
|||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
||||
|
||||
QScriptEngine scriptEngine;
|
||||
QVariantList wearableEntities;
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
auto avatarEntities = myAvatar->getAvatarEntityData();
|
||||
for (auto entityID : avatarEntities.keys()) {
|
||||
auto entity = entityTree->findEntityByID(entityID);
|
||||
if (!entity || !isWearableEntity(entity)) {
|
||||
continue;
|
||||
|
||||
if (entityTree) {
|
||||
QScriptEngine scriptEngine;
|
||||
auto avatarEntities = myAvatar->getAvatarEntityData();
|
||||
for (auto entityID : avatarEntities.keys()) {
|
||||
auto entity = entityTree->findEntityByID(entityID);
|
||||
if (!entity || !isWearableEntity(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariantMap avatarEntityData;
|
||||
|
||||
EncodeBitstreamParams params;
|
||||
auto desiredProperties = entity->getEntityProperties(params);
|
||||
desiredProperties += PROP_LOCAL_POSITION;
|
||||
desiredProperties += PROP_LOCAL_ROTATION;
|
||||
desiredProperties -= PROP_JOINT_ROTATIONS_SET;
|
||||
desiredProperties -= PROP_JOINT_ROTATIONS;
|
||||
desiredProperties -= PROP_JOINT_TRANSLATIONS_SET;
|
||||
desiredProperties -= PROP_JOINT_TRANSLATIONS;
|
||||
|
||||
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
|
||||
QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties);
|
||||
avatarEntityData["properties"] = scriptProperties.toVariant();
|
||||
wearableEntities.append(QVariant(avatarEntityData));
|
||||
}
|
||||
QVariantMap avatarEntityData;
|
||||
EncodeBitstreamParams params;
|
||||
auto desiredProperties = entity->getEntityProperties(params);
|
||||
desiredProperties += PROP_LOCAL_POSITION;
|
||||
desiredProperties += PROP_LOCAL_ROTATION;
|
||||
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
|
||||
QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties);
|
||||
avatarEntityData["properties"] = scriptProperties.toVariant();
|
||||
wearableEntities.append(QVariant(avatarEntityData));
|
||||
}
|
||||
bookmark.insert(ENTRY_AVATAR_ENTITIES, wearableEntities);
|
||||
return bookmark;
|
||||
|
|
|
@ -368,8 +368,6 @@ Menu::Menu() {
|
|||
qApp->setHmdTabletBecomesToolbarSetting(action->isChecked());
|
||||
});
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::Use3DKeyboard, 0, true);
|
||||
|
||||
// Developer > Render >>>
|
||||
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace MenuOption {
|
|||
const QString FrameTimer = "Show Timer";
|
||||
const QString FullscreenMirror = "Mirror";
|
||||
const QString Help = "Help...";
|
||||
const QString HomeLocation = "Home";
|
||||
const QString HomeLocation = "Home ";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IndependentMode = "Independent Mode";
|
||||
const QString ActionMotorControl = "Enable Default Motor Control";
|
||||
|
@ -213,7 +213,6 @@ namespace MenuOption {
|
|||
const QString TurnWithHead = "Turn using Head";
|
||||
const QString UseAudioForMouth = "Use Audio for Mouth";
|
||||
const QString UseCamera = "Use Camera";
|
||||
const QString Use3DKeyboard = "Use 3D Keyboard";
|
||||
const QString VelocityFilter = "Velocity Filter";
|
||||
const QString VisibleToEveryone = "Everyone";
|
||||
const QString VisibleToFriends = "Friends";
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <QStandardPaths>
|
||||
|
||||
static const QString AVATAR_HEAD_AND_BODY_STRING = "Avatar Body with Head";
|
||||
static const QString AVATAR_ATTACHEMENT_STRING = "Avatar Attachment";
|
||||
static const QString ENTITY_MODEL_STRING = "Entity Model";
|
||||
|
||||
ModelSelector::ModelSelector() {
|
||||
|
|
|
@ -171,7 +171,7 @@ void SecondaryCameraJobConfig::setOrientation(glm::quat orient) {
|
|||
}
|
||||
|
||||
void SecondaryCameraJobConfig::enableSecondaryCameraRenderConfigs(bool enabled) {
|
||||
qApp->getRenderEngine()->getConfiguration()->getConfig<SecondaryCameraRenderTask>()->setEnabled(enabled);
|
||||
qApp->getRenderEngine()->getConfiguration()->getConfig<SecondaryCameraRenderTask>("SecondaryCameraJob")->setEnabled(enabled);
|
||||
setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
@ -187,11 +187,13 @@ public:
|
|||
|
||||
void run(const render::RenderContextPointer& renderContext, const RenderArgsPointer& cachedArgs) {
|
||||
auto args = renderContext->args;
|
||||
if (cachedArgs) {
|
||||
args->_blitFramebuffer = cachedArgs->_blitFramebuffer;
|
||||
args->_viewport = cachedArgs->_viewport;
|
||||
args->popViewFrustum();
|
||||
args->_displayMode = cachedArgs->_displayMode;
|
||||
args->_renderMode = cachedArgs->_renderMode;
|
||||
}
|
||||
args->popViewFrustum();
|
||||
|
||||
gpu::doInBatch("EndSecondaryCameraFrame::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.restoreContextStereo();
|
||||
|
|
|
@ -36,114 +36,6 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
// Show center of world
|
||||
static const glm::vec3 RED(1.0f, 0.0f, 0.0f);
|
||||
static const glm::vec3 GREEN(0.0f, 1.0f, 0.0f);
|
||||
static const glm::vec3 BLUE(0.0f, 0.0f, 1.0f);
|
||||
static const glm::vec3 GREY(0.5f, 0.5f, 0.5f);
|
||||
static const glm::vec4 GREY4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
static const glm::vec4 DASHED_RED(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
static const glm::vec4 DASHED_GREEN(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
static const glm::vec4 DASHED_BLUE(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
static const float DASH_LENGTH = 1.0f;
|
||||
static const float GAP_LENGTH = 1.0f;
|
||||
auto transform = Transform{};
|
||||
static std::array<int, 18> geometryIds;
|
||||
static std::once_flag initGeometryIds;
|
||||
std::call_once(initGeometryIds, [&] {
|
||||
for (size_t i = 0; i < geometryIds.size(); ++i) {
|
||||
geometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
});
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), RED, geometryIds[0]);
|
||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-HALF_TREE_SCALE, 0.0f, 0.0f), DASHED_RED,
|
||||
DASH_LENGTH, GAP_LENGTH, geometryIds[1]);
|
||||
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), GREEN, geometryIds[2]);
|
||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -HALF_TREE_SCALE, 0.0f), DASHED_GREEN,
|
||||
DASH_LENGTH, GAP_LENGTH, geometryIds[3]);
|
||||
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), BLUE, geometryIds[4]);
|
||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -HALF_TREE_SCALE), DASHED_BLUE,
|
||||
DASH_LENGTH, GAP_LENGTH, geometryIds[5]);
|
||||
|
||||
// X center boundaries
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[6]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[7]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[8]);
|
||||
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[9]);
|
||||
|
||||
// Z center boundaries
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[10]);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), GREY,
|
||||
geometryIds[11]);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[12]);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[13]);
|
||||
|
||||
// Center boundaries
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||
glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[14]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||
glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), GREY,
|
||||
geometryIds[15]);
|
||||
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[16]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE),
|
||||
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[17]);
|
||||
|
||||
|
||||
geometryCache->renderWireCubeInstance(args, batch, GREY4);
|
||||
|
||||
// Draw meter markers along the 3 axis to help with measuring things
|
||||
const float MARKER_DISTANCE = 1.0f;
|
||||
const float MARKER_RADIUS = 0.05f;
|
||||
|
||||
transform = Transform().setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, GREEN);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, BLUE);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, GREY);
|
||||
}
|
||||
|
||||
// Do some basic timing tests and report the results
|
||||
void runTimingTests() {
|
||||
// How long does it take to make a call to get the time?
|
||||
|
|
|
@ -15,14 +15,9 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
#include <render/Forward.h>
|
||||
|
||||
class ShapeEntityItem;
|
||||
class ShapeInfo;
|
||||
|
||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
||||
|
||||
void runTimingTests();
|
||||
void runUnitTests();
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
_flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD),
|
||||
_avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0)
|
||||
{
|
||||
_clientTraitsHandler = std::unique_ptr<ClientTraitsHandler>(new ClientTraitsHandler(this));
|
||||
_clientTraitsHandler.reset(new ClientTraitsHandler(this));
|
||||
|
||||
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||
_headData = new MyHead(this);
|
||||
|
|
301
interface/src/graphics/GraphicsEngine.cpp
Normal file
301
interface/src/graphics/GraphicsEngine.cpp
Normal file
|
@ -0,0 +1,301 @@
|
|||
//
|
||||
// GraphicsEngine.cpp
|
||||
//
|
||||
// Created by Sam Gateau on 29/6/2018.
|
||||
// Copyright 2018 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
|
||||
//
|
||||
#include "GraphicsEngine.h"
|
||||
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
|
||||
#include "WorldBox.h"
|
||||
#include "LODManager.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <TextureCache.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include <UpdateSceneTask.h>
|
||||
#include <RenderViewTask.h>
|
||||
#include <SecondaryCamera.h>
|
||||
|
||||
#include "RenderEventHandler.h"
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
#include <display-plugins/DisplayPlugin.h>
|
||||
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include <QMetaObject>
|
||||
#include "ui/Stats.h"
|
||||
#include "Application.h"
|
||||
|
||||
GraphicsEngine::GraphicsEngine() {
|
||||
}
|
||||
|
||||
GraphicsEngine::~GraphicsEngine() {
|
||||
}
|
||||
|
||||
void GraphicsEngine::initializeGPU(GLWidget* glwidget) {
|
||||
|
||||
_renderEventHandler = new RenderEventHandler(
|
||||
[this]() { return this->shouldPaint(); },
|
||||
[this]() { this->render_performFrame(); }
|
||||
);
|
||||
|
||||
// Requires the window context, because that's what's used in the actual rendering
|
||||
// and the GPU backend will make things like the VAO which cannot be shared across
|
||||
// contexts
|
||||
glwidget->makeCurrent();
|
||||
gpu::Context::init<gpu::gl::GLBackend>();
|
||||
glwidget->makeCurrent();
|
||||
_gpuContext = std::make_shared<gpu::Context>();
|
||||
|
||||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||
}
|
||||
|
||||
void GraphicsEngine::initializeRender(bool disableDeferred) {
|
||||
|
||||
// Set up the render engine
|
||||
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
||||
#ifndef Q_OS_ANDROID
|
||||
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !disableDeferred);
|
||||
#endif
|
||||
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||
_renderEngine->load();
|
||||
_renderEngine->registerScene(_renderScene);
|
||||
|
||||
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
||||
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
||||
}
|
||||
|
||||
void GraphicsEngine::startup() {
|
||||
static_cast<RenderEventHandler*>(_renderEventHandler)->resumeThread();
|
||||
}
|
||||
|
||||
void GraphicsEngine::shutdown() {
|
||||
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
|
||||
// removal of the items.
|
||||
// See https://highfidelity.fogbugz.com/f/cases/5328
|
||||
_renderScene->enqueueFrame(); // flush all the transactions
|
||||
_renderScene->processTransactionQueue(); // process and apply deletions
|
||||
|
||||
_gpuContext->shutdown();
|
||||
|
||||
|
||||
// shutdown render engine
|
||||
_renderScene = nullptr;
|
||||
_renderEngine = nullptr;
|
||||
|
||||
_renderEventHandler->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("render");
|
||||
|
||||
// Make sure the WorldBox is in the scene
|
||||
// For the record, this one RenderItem is the first one we created and added to the scene.
|
||||
// We could move that code elsewhere but you know...
|
||||
if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
||||
render::Transaction transaction;
|
||||
auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
|
||||
auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
||||
|
||||
WorldBoxRenderData::_item = _renderScene->allocateID();
|
||||
|
||||
transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
|
||||
_renderScene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
{
|
||||
_renderEngine->getRenderContext()->args = renderArgs;
|
||||
_renderEngine->run();
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned int THROTTLED_SIM_FRAMERATE = 15;
|
||||
static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
|
||||
|
||||
|
||||
|
||||
|
||||
bool GraphicsEngine::shouldPaint() const {
|
||||
|
||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
|
||||
#ifdef DEBUG_PAINT_DELAY
|
||||
static uint64_t paintDelaySamples{ 0 };
|
||||
static uint64_t paintDelayUsecs{ 0 };
|
||||
|
||||
paintDelayUsecs += displayPlugin->getPaintDelayUsecs();
|
||||
|
||||
static const int PAINT_DELAY_THROTTLE = 1000;
|
||||
if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) {
|
||||
qCDebug(interfaceapp).nospace() <<
|
||||
"Paint delay (" << paintDelaySamples << " samples): " <<
|
||||
(float)paintDelaySamples / paintDelayUsecs << "us";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Throttle if requested
|
||||
//if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||
if ( displayPlugin->isThrottled() &&
|
||||
(static_cast<RenderEventHandler*>(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GraphicsEngine::checkPendingRenderEvent() {
|
||||
bool expected = false;
|
||||
return (_renderEventHandler && static_cast<RenderEventHandler*>(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GraphicsEngine::render_performFrame() {
|
||||
// Some plugins process message events, allowing paintGL to be called reentrantly.
|
||||
|
||||
_renderFrameCount++;
|
||||
|
||||
auto lastPaintBegin = usecTimestampNow();
|
||||
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
|
||||
PerformanceTimer perfTimer("paintGL");
|
||||
|
||||
DisplayPluginPointer displayPlugin;
|
||||
{
|
||||
PROFILE_RANGE(render, "/getActiveDisplayPlugin");
|
||||
displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/pluginBeginFrameRender");
|
||||
// If a display plugin loses it's underlying support, it
|
||||
// needs to be able to signal us to not use it
|
||||
if (!displayPlugin->beginFrameRender(_renderFrameCount)) {
|
||||
QMetaObject::invokeMethod(qApp, "updateDisplayMode");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RenderArgs renderArgs;
|
||||
glm::mat4 HMDSensorPose;
|
||||
glm::mat4 eyeToWorld;
|
||||
glm::mat4 sensorToWorld;
|
||||
|
||||
bool isStereo;
|
||||
glm::mat4 stereoEyeOffsets[2];
|
||||
glm::mat4 stereoEyeProjections[2];
|
||||
|
||||
{
|
||||
QMutexLocker viewLocker(&_renderArgsMutex);
|
||||
renderArgs = _appRenderArgs._renderArgs;
|
||||
|
||||
// don't render if there is no context.
|
||||
if (!_appRenderArgs._renderArgs._context) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMDSensorPose = _appRenderArgs._headPose;
|
||||
eyeToWorld = _appRenderArgs._eyeToWorld;
|
||||
sensorToWorld = _appRenderArgs._sensorToWorld;
|
||||
isStereo = _appRenderArgs._isStereo;
|
||||
for_each_eye([&](Eye eye) {
|
||||
stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye];
|
||||
stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye];
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/gpuContextReset");
|
||||
getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose);
|
||||
// Reset the gpu::Context Stages
|
||||
// Back to the default framebuffer;
|
||||
gpu::doInBatch("Application_render::gpuContextReset", getGPUContext(), [&](gpu::Batch& batch) {
|
||||
batch.resetStages();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/renderOverlay");
|
||||
PerformanceTimer perfTimer("renderOverlay");
|
||||
// NOTE: There is no batch associated with this renderArgs
|
||||
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
||||
renderArgs._viewport = glm::ivec4(0, 0, qApp->getDeviceSize());
|
||||
qApp->getApplicationOverlay().renderOverlay(&renderArgs);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render, "/updateCompositor");
|
||||
qApp->getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer finalFramebuffer;
|
||||
QSize finalFramebufferSize;
|
||||
{
|
||||
PROFILE_RANGE(render, "/getOutputFramebuffer");
|
||||
// Primary rendering pass
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
finalFramebufferSize = framebufferCache->getFrameBufferSize();
|
||||
// Final framebuffer that will be handled to the display-plugin
|
||||
finalFramebuffer = framebufferCache->getFramebuffer();
|
||||
}
|
||||
|
||||
{
|
||||
if (isStereo) {
|
||||
renderArgs._context->enableStereo(true);
|
||||
renderArgs._context->setStereoProjections(stereoEyeProjections);
|
||||
renderArgs._context->setStereoViews(stereoEyeOffsets);
|
||||
}
|
||||
|
||||
renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
||||
renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture();
|
||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
render_runRenderFrame(&renderArgs);
|
||||
}
|
||||
|
||||
auto frame = getGPUContext()->endFrame();
|
||||
frame->frameIndex = _renderFrameCount;
|
||||
frame->framebuffer = finalFramebuffer;
|
||||
frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
|
||||
auto frameBufferCache = DependencyManager::get<FramebufferCache>();
|
||||
if (frameBufferCache) {
|
||||
frameBufferCache->releaseFramebuffer(framebuffer);
|
||||
}
|
||||
};
|
||||
// deliver final scene rendering commands to the display plugin
|
||||
{
|
||||
PROFILE_RANGE(render, "/pluginOutput");
|
||||
PerformanceTimer perfTimer("pluginOutput");
|
||||
_renderLoopCounter.increment();
|
||||
displayPlugin->submitFrame(frame);
|
||||
}
|
||||
|
||||
// Reset the framebuffer and stereo state
|
||||
renderArgs._blitFramebuffer.reset();
|
||||
renderArgs._context->enableStereo(false);
|
||||
|
||||
{
|
||||
auto stats = Stats::getInstance();
|
||||
if (stats) {
|
||||
stats->setRenderDetails(renderArgs._details);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;
|
||||
_frameTimingsScriptingInterface.addValue(lastPaintDuration);
|
||||
}
|
||||
|
||||
|
||||
void GraphicsEngine::editRenderArgs(RenderArgsEditor editor) {
|
||||
QMutexLocker renderLocker(&_renderArgsMutex);
|
||||
editor(_appRenderArgs);
|
||||
}
|
90
interface/src/graphics/GraphicsEngine.h
Normal file
90
interface/src/graphics/GraphicsEngine.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// GraphicsEngine.h
|
||||
//
|
||||
// Created by Sam Gateau on 29/6/2018.
|
||||
// Copyright 2018 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
|
||||
//
|
||||
#ifndef hifi_GraphicsEngine_h
|
||||
#define hifi_GraphicsEngine_h
|
||||
|
||||
#include <gl/OffscreenGLCanvas.h>
|
||||
#include <gl/GLWidget.h>
|
||||
#include <qmutex.h>
|
||||
|
||||
#include <render/Engine.h>
|
||||
|
||||
#include <OctreeConstants.h>
|
||||
#include <shared/RateCounter.h>
|
||||
|
||||
#include "FrameTimingsScriptingInterface.h"
|
||||
|
||||
|
||||
struct AppRenderArgs {
|
||||
render::Args _renderArgs;
|
||||
glm::mat4 _eyeToWorld;
|
||||
glm::mat4 _view;
|
||||
glm::mat4 _eyeOffsets[2];
|
||||
glm::mat4 _eyeProjections[2];
|
||||
glm::mat4 _headPose;
|
||||
glm::mat4 _sensorToWorld;
|
||||
float _sensorToWorldScale{ 1.0f };
|
||||
bool _isStereo{ false };
|
||||
};
|
||||
|
||||
using RenderArgsEditor = std::function <void(AppRenderArgs&)>;
|
||||
|
||||
|
||||
class GraphicsEngine {
|
||||
public:
|
||||
GraphicsEngine();
|
||||
~GraphicsEngine();
|
||||
|
||||
void initializeGPU(GLWidget*);
|
||||
void initializeRender(bool disableDeferred);
|
||||
void startup();
|
||||
void shutdown();
|
||||
|
||||
render::ScenePointer getRenderScene() const { return _renderScene; }
|
||||
render::EnginePointer getRenderEngine() const { return _renderEngine; }
|
||||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||
|
||||
// Same as the one in application
|
||||
bool shouldPaint() const;
|
||||
bool checkPendingRenderEvent();
|
||||
|
||||
size_t getRenderFrameCount() const { return _renderFrameCount; }
|
||||
float getRenderLoopRate() const { return _renderLoopCounter.rate(); }
|
||||
|
||||
// Feed GRaphics Engine with new frame configuration
|
||||
void editRenderArgs(RenderArgsEditor editor);
|
||||
|
||||
private:
|
||||
// Thread specific calls
|
||||
void render_performFrame();
|
||||
void render_runRenderFrame(RenderArgs* renderArgs);
|
||||
|
||||
protected:
|
||||
|
||||
mutable QMutex _renderArgsMutex{ QMutex::Recursive };
|
||||
AppRenderArgs _appRenderArgs;
|
||||
|
||||
RateCounter<500> _renderLoopCounter;
|
||||
|
||||
uint32_t _renderFrameCount{ 0 };
|
||||
render::ScenePointer _renderScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
||||
render::EnginePointer _renderEngine{ new render::RenderEngine() };
|
||||
|
||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||
|
||||
QObject* _renderEventHandler{ nullptr };
|
||||
friend class RenderEventHandler;
|
||||
|
||||
FrameTimingsScriptingInterface _frameTimingsScriptingInterface;
|
||||
|
||||
friend class Application;
|
||||
};
|
||||
|
||||
#endif // hifi_GraphicsEngine_h
|
58
interface/src/graphics/RenderEventHandler.cpp
Normal file
58
interface/src/graphics/RenderEventHandler.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// RenderEventHandler.cpp
|
||||
//
|
||||
// Created by Bradley Austin Davis on 29/6/2018.
|
||||
// Copyright 2018 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
|
||||
//
|
||||
#include "RenderEventHandler.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "CrashHandler.h"
|
||||
|
||||
RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCall) :
|
||||
_checkCall(checkCall),
|
||||
_renderCall(renderCall)
|
||||
{
|
||||
// Transfer to a new thread
|
||||
moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) {
|
||||
hifi::qt::addBlockingForbiddenThread("Render", renderThread);
|
||||
_lastTimeRendered.start();
|
||||
}, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority);
|
||||
}
|
||||
|
||||
void RenderEventHandler::initialize() {
|
||||
setObjectName("Render");
|
||||
PROFILE_SET_THREAD_NAME("Render");
|
||||
setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
|
||||
}
|
||||
|
||||
void RenderEventHandler::resumeThread() {
|
||||
_pendingRenderEvent = false;
|
||||
}
|
||||
|
||||
void RenderEventHandler::render() {
|
||||
if (_checkCall()) {
|
||||
_lastTimeRendered.start();
|
||||
_renderCall();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderEventHandler::event(QEvent* event) {
|
||||
switch ((int)event->type()) {
|
||||
case ApplicationEvent::Render:
|
||||
render();
|
||||
_pendingRenderEvent.store(false);
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Parent::event(event);
|
||||
}
|
||||
|
52
interface/src/graphics/RenderEventHandler.h
Normal file
52
interface/src/graphics/RenderEventHandler.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// RenderEventHandler.h
|
||||
//
|
||||
// Created by Bradley Austin Davis on 29/6/2018.
|
||||
// Copyright 2018 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
|
||||
//
|
||||
#ifndef hifi_RenderEventHandler_h
|
||||
#define hifi_RenderEventHandler_h
|
||||
|
||||
#include <QEvent>
|
||||
#include <QElapsedTimer>
|
||||
#include "gl/OffscreenGLCanvas.h"
|
||||
|
||||
enum ApplicationEvent {
|
||||
// Execute a lambda function
|
||||
Lambda = QEvent::User + 1,
|
||||
// Trigger the next render
|
||||
Render,
|
||||
// Trigger the next idle
|
||||
Idle,
|
||||
};
|
||||
|
||||
class RenderEventHandler : public QObject {
|
||||
using Parent = QObject;
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
using CheckCall = std::function <bool()>;
|
||||
using RenderCall = std::function <void()>;
|
||||
|
||||
CheckCall _checkCall;
|
||||
RenderCall _renderCall;
|
||||
|
||||
RenderEventHandler(CheckCall checkCall, RenderCall renderCall);
|
||||
|
||||
QElapsedTimer _lastTimeRendered;
|
||||
std::atomic<bool> _pendingRenderEvent{ true };
|
||||
|
||||
void resumeThread();
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
void render();
|
||||
|
||||
bool event(QEvent* event) override;
|
||||
};
|
||||
|
||||
#endif // #include hifi_RenderEventHandler_h
|
138
interface/src/graphics/WorldBox.cpp
Normal file
138
interface/src/graphics/WorldBox.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
//
|
||||
// WorldBox.cpp
|
||||
//
|
||||
// Created by Sam Gateau on 01/07/2018.
|
||||
// Copyright 2018 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
|
||||
//
|
||||
#include "WorldBox.h"
|
||||
|
||||
#include "OctreeConstants.h"
|
||||
|
||||
render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
||||
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
||||
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
||||
PerformanceTimer perfTimer("worldBox");
|
||||
|
||||
auto& batch = *args->_batch;
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
WorldBoxRenderData::renderWorldBox(args, batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldBoxRenderData::renderWorldBox(RenderArgs* args, gpu::Batch& batch) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
// Show center of world
|
||||
static const glm::vec3 RED(1.0f, 0.0f, 0.0f);
|
||||
static const glm::vec3 GREEN(0.0f, 1.0f, 0.0f);
|
||||
static const glm::vec3 BLUE(0.0f, 0.0f, 1.0f);
|
||||
static const glm::vec3 GREY(0.5f, 0.5f, 0.5f);
|
||||
static const glm::vec4 GREY4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
static const glm::vec4 DASHED_RED(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
static const glm::vec4 DASHED_GREEN(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
static const glm::vec4 DASHED_BLUE(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
static const float DASH_LENGTH = 1.0f;
|
||||
static const float GAP_LENGTH = 1.0f;
|
||||
auto transform = Transform{};
|
||||
static std::array<int, 18> geometryIds;
|
||||
static std::once_flag initGeometryIds;
|
||||
std::call_once(initGeometryIds, [&] {
|
||||
for (size_t i = 0; i < geometryIds.size(); ++i) {
|
||||
geometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
});
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), RED, geometryIds[0]);
|
||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-HALF_TREE_SCALE, 0.0f, 0.0f), DASHED_RED,
|
||||
DASH_LENGTH, GAP_LENGTH, geometryIds[1]);
|
||||
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), GREEN, geometryIds[2]);
|
||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -HALF_TREE_SCALE, 0.0f), DASHED_GREEN,
|
||||
DASH_LENGTH, GAP_LENGTH, geometryIds[3]);
|
||||
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), BLUE, geometryIds[4]);
|
||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -HALF_TREE_SCALE), DASHED_BLUE,
|
||||
DASH_LENGTH, GAP_LENGTH, geometryIds[5]);
|
||||
|
||||
// X center boundaries
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[6]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[7]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[8]);
|
||||
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||
geometryIds[9]);
|
||||
|
||||
// Z center boundaries
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[10]);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), GREY,
|
||||
geometryIds[11]);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[12]);
|
||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE),
|
||||
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[13]);
|
||||
|
||||
// Center boundaries
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||
glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[14]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||
glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), GREY,
|
||||
geometryIds[15]);
|
||||
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[16]);
|
||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE),
|
||||
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||
geometryIds[17]);
|
||||
|
||||
|
||||
geometryCache->renderWireCubeInstance(args, batch, GREY4);
|
||||
|
||||
// Draw meter markers along the 3 axis to help with measuring things
|
||||
const float MARKER_DISTANCE = 1.0f;
|
||||
const float MARKER_RADIUS = 0.05f;
|
||||
|
||||
transform = Transform().setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, GREEN);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, BLUE);
|
||||
|
||||
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
||||
batch.setModelTransform(transform);
|
||||
geometryCache->renderSolidSphereInstance(args, batch, GREY);
|
||||
}
|
||||
|
43
interface/src/graphics/WorldBox.h
Normal file
43
interface/src/graphics/WorldBox.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// WorldBox.h
|
||||
//
|
||||
// Created by Sam Gateau on 01/07/2018.
|
||||
// Copyright 2018 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
|
||||
//
|
||||
#ifndef hifi_WorldBox_h
|
||||
#define hifi_WorldBox_h
|
||||
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
#include <render/Forward.h>
|
||||
|
||||
#include <render/Item.h>
|
||||
#include <GeometryCache.h>
|
||||
#include "Menu.h"
|
||||
|
||||
|
||||
|
||||
class WorldBoxRenderData {
|
||||
public:
|
||||
typedef render::Payload<WorldBoxRenderData> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
int _val = 0;
|
||||
static render::ItemID _item; // unique WorldBoxRenderData
|
||||
|
||||
|
||||
|
||||
static void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
||||
};
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff);
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff);
|
||||
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args);
|
||||
}
|
||||
|
||||
#endif // hifi_WorldBox_h
|
|
@ -72,6 +72,7 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
|
||||
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
|
||||
QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache <dir>", "dir");
|
||||
QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts <path>", "path");
|
||||
|
||||
parser.addOption(urlOption);
|
||||
parser.addOption(noUpdaterOption);
|
||||
|
@ -79,6 +80,7 @@ int main(int argc, const char* argv[]) {
|
|||
parser.addOption(runServerOption);
|
||||
parser.addOption(serverContentPathOption);
|
||||
parser.addOption(overrideAppLocalDataPathOption);
|
||||
parser.addOption(overrideScriptsPathOption);
|
||||
parser.addOption(allowMultipleInstancesOption);
|
||||
|
||||
if (!parser.parse(arguments)) {
|
||||
|
@ -165,6 +167,15 @@ int main(int argc, const char* argv[]) {
|
|||
if (allowMultipleInstances) {
|
||||
instanceMightBeRunning = false;
|
||||
}
|
||||
// this needs to be done here in main, as the mechanism for setting the
|
||||
// scripts directory appears not to work. See the bug report
|
||||
// https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine
|
||||
if (parser.isSet(overrideScriptsPathOption)) {
|
||||
QDir scriptsPath(parser.value(overrideScriptsPathOption));
|
||||
if (scriptsPath.exists()) {
|
||||
PathUtils::defaultScriptsLocation(scriptsPath.path());
|
||||
}
|
||||
}
|
||||
|
||||
if (instanceMightBeRunning) {
|
||||
// Try to connect and send message to existing interface instance
|
||||
|
|
|
@ -32,3 +32,7 @@ void KeyboardScriptingInterface::setPassword(bool password) {
|
|||
void KeyboardScriptingInterface::loadKeyboardFile(const QString& keyboardFile) {
|
||||
DependencyManager::get<Keyboard>()->loadKeyboardFile(keyboardFile);
|
||||
}
|
||||
|
||||
bool KeyboardScriptingInterface::getUse3DKeyboard() {
|
||||
return DependencyManager::get<Keyboard>()->getUse3DKeyboard();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ class KeyboardScriptingInterface : public QObject, public Dependency {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(bool raised READ isRaised WRITE setRaised)
|
||||
Q_PROPERTY(bool password READ isPassword WRITE setPassword)
|
||||
Q_PROPERTY(bool use3DKeyboard READ getUse3DKeyboard);
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void loadKeyboardFile(const QString& string);
|
||||
|
@ -41,5 +42,7 @@ private:
|
|||
|
||||
bool isPassword();
|
||||
void setPassword(bool password);
|
||||
|
||||
bool getUse3DKeyboard();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -55,8 +55,6 @@ ApplicationOverlay::~ApplicationOverlay() {
|
|||
// Renders the overlays either to a texture or to the screen
|
||||
void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
|
||||
|
||||
buildFramebufferObject();
|
||||
|
||||
if (!_overlayFramebuffer) {
|
||||
|
|
|
@ -241,6 +241,17 @@ void Keyboard::registerKeyboardHighlighting() {
|
|||
selection->enableListToScene(KEY_PRESSED_HIGHLIGHT);
|
||||
}
|
||||
|
||||
bool Keyboard::getUse3DKeyboard() const {
|
||||
return _use3DKeyboardLock.resultWithReadLock<bool>([&] {
|
||||
return _use3DKeyboard.get();
|
||||
});
|
||||
}
|
||||
|
||||
void Keyboard::setUse3DKeyboard(bool use) {
|
||||
_use3DKeyboardLock.withWriteLock([&] {
|
||||
_use3DKeyboard.set(use);
|
||||
});
|
||||
}
|
||||
|
||||
void Keyboard::createKeyboard() {
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <Sound.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
#include <SettingHandle.h>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
|
@ -93,11 +94,12 @@ public:
|
|||
void registerKeyboardHighlighting();
|
||||
bool isRaised() const;
|
||||
void setRaised(bool raised);
|
||||
|
||||
void setResetKeyboardPositionOnRaise(bool reset);
|
||||
bool isPassword() const;
|
||||
void setPassword(bool password);
|
||||
|
||||
void setResetKeyboardPositionOnRaise(bool reset);
|
||||
bool getUse3DKeyboard() const;
|
||||
void setUse3DKeyboard(bool use);
|
||||
|
||||
void loadKeyboardFile(const QString& keyboardFile);
|
||||
QVector<OverlayID> getKeysID();
|
||||
|
@ -147,6 +149,9 @@ private:
|
|||
SharedSoundPointer _keySound { nullptr };
|
||||
std::shared_ptr<QTimer> _layerSwitchTimer { std::make_shared<QTimer>() };
|
||||
|
||||
mutable ReadWriteLockable _use3DKeyboardLock;
|
||||
Setting::Handle<bool> _use3DKeyboard { "use3DKeyboard", true };
|
||||
|
||||
QString _typedCharacters;
|
||||
TextDisplay _textDisplay;
|
||||
Anchor _anchor;
|
||||
|
|
|
@ -42,8 +42,9 @@ LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {
|
|||
this, &LoginDialog::handleLoginCompleted);
|
||||
connect(accountManager.data(), &AccountManager::loginFailed,
|
||||
this, &LoginDialog::handleLoginFailed);
|
||||
#endif
|
||||
connect(qApp, SIGNAL(loginDialogFocusEnabled()), this, SLOT(onFocusEnabled()));
|
||||
connect(this, SIGNAL(dismissedLoginDialog()), qApp, SLOT(onDismissedLoginDialog()));
|
||||
#endif
|
||||
}
|
||||
|
||||
LoginDialog::~LoginDialog() {
|
||||
|
@ -121,6 +122,25 @@ void LoginDialog::login(const QString& username, const QString& password) const
|
|||
DependencyManager::get<AccountManager>()->requestAccessToken(username, password);
|
||||
}
|
||||
|
||||
void LoginDialog::loginThroughOculus() {
|
||||
qDebug() << "Attempting to login through Oculus";
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
steamClient->requestTicket([this](Ticket ticket) {
|
||||
if (ticket.isNull()) {
|
||||
emit handleLoginFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
DependencyManager::get<AccountManager>()->requestAccessTokenWithSteam(ticket);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LoginDialog::linkOculus() {
|
||||
qDebug() << "Attempting to link Oculus account";
|
||||
|
||||
}
|
||||
|
||||
void LoginDialog::loginThroughSteam() {
|
||||
qDebug() << "Attempting to login through Steam";
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
|
@ -288,3 +308,8 @@ void LoginDialog::signupFailed(QNetworkReply* reply) {
|
|||
emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
void LoginDialog::onFocusEnabled() {
|
||||
forceActiveFocus();
|
||||
emit focusEnabled();
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ signals:
|
|||
// occurs upon dismissing the encouraging log in.
|
||||
void dismissedLoginDialog();
|
||||
|
||||
void focusEnabled();
|
||||
|
||||
public slots:
|
||||
void linkCompleted(QNetworkReply* reply);
|
||||
void linkFailed(QNetworkReply* reply);
|
||||
|
@ -58,6 +60,8 @@ public slots:
|
|||
void signupCompleted(QNetworkReply* reply);
|
||||
void signupFailed(QNetworkReply* reply);
|
||||
|
||||
void onFocusEnabled();
|
||||
|
||||
protected slots:
|
||||
Q_INVOKABLE void dismissLoginDialog();
|
||||
|
||||
|
@ -65,6 +69,8 @@ protected slots:
|
|||
Q_INVOKABLE bool isOculusStoreRunning() const;
|
||||
|
||||
Q_INVOKABLE void login(const QString& username, const QString& password) const;
|
||||
Q_INVOKABLE void loginThroughOculus();
|
||||
Q_INVOKABLE void linkOculus();
|
||||
Q_INVOKABLE void loginThroughSteam();
|
||||
Q_INVOKABLE void linkSteam();
|
||||
Q_INVOKABLE void createAccountFromSteam(QString username = QString());
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Snapshot.h"
|
||||
#include "SnapshotAnimated.h"
|
||||
#include "UserActivityLogger.h"
|
||||
#include "ui/Keyboard.h"
|
||||
|
||||
void setupPreferences() {
|
||||
auto preferences = DependencyManager::get<Preferences>();
|
||||
|
@ -119,6 +120,12 @@ void setupPreferences() {
|
|||
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter));
|
||||
}
|
||||
|
||||
{
|
||||
auto getter = []()->bool { return DependencyManager::get<Keyboard>()->getUse3DKeyboard(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<Keyboard>()->setUse3DKeyboard(value); };
|
||||
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use Virtual Keyboard", getter, setter));
|
||||
}
|
||||
|
||||
{
|
||||
auto getter = []()->bool { return qApp->getMiniTabletEnabled(); };
|
||||
auto setter = [](bool value) { qApp->setMiniTabletEnabled(value); };
|
||||
|
|
|
@ -302,7 +302,6 @@ void AudioClient::customDeleter() {
|
|||
#if defined(Q_OS_ANDROID)
|
||||
_shouldRestartInputSetup = false;
|
||||
#endif
|
||||
stop();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include <xmmintrin.h>
|
||||
// convert float to int using round-to-nearest
|
||||
FORCEINLINE static int32_t floatToInt(float x) {
|
||||
return _mm_cvt_ss2si(_mm_load_ss(&x));
|
||||
return _mm_cvt_ss2si(_mm_set_ss(x));
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -150,7 +150,7 @@ static const int IEEE754_EXPN_BIAS = 127;
|
|||
//
|
||||
// Peak detection and -log2(x) for float input (mono)
|
||||
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
|
||||
// x > 2^LOG2_HEADROOM undefined
|
||||
// x > 2^LOG2_HEADROOM returns 0
|
||||
//
|
||||
FORCEINLINE static int32_t peaklog2(float* input) {
|
||||
|
||||
|
@ -161,12 +161,12 @@ FORCEINLINE static int32_t peaklog2(float* input) {
|
|||
uint32_t peak = u & IEEE754_FABS_MASK;
|
||||
|
||||
// split into e and x - 1.0
|
||||
int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
return 0x7fffffff;
|
||||
// saturate when e > 31 or e < 0
|
||||
if ((uint32_t)e > 31) {
|
||||
return 0x7fffffff & ~(e >> 31);
|
||||
}
|
||||
|
||||
int k = x >> (31 - LOG2_TABBITS);
|
||||
|
@ -186,7 +186,7 @@ FORCEINLINE static int32_t peaklog2(float* input) {
|
|||
//
|
||||
// Peak detection and -log2(x) for float input (stereo)
|
||||
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
|
||||
// x > 2^LOG2_HEADROOM undefined
|
||||
// x > 2^LOG2_HEADROOM returns 0
|
||||
//
|
||||
FORCEINLINE static int32_t peaklog2(float* input0, float* input1) {
|
||||
|
||||
|
@ -200,12 +200,12 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1) {
|
|||
uint32_t peak = MAX(u0, u1);
|
||||
|
||||
// split into e and x - 1.0
|
||||
int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
return 0x7fffffff;
|
||||
// saturate when e > 31 or e < 0
|
||||
if ((uint32_t)e > 31) {
|
||||
return 0x7fffffff & ~(e >> 31);
|
||||
}
|
||||
|
||||
int k = x >> (31 - LOG2_TABBITS);
|
||||
|
@ -225,7 +225,7 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1) {
|
|||
//
|
||||
// Peak detection and -log2(x) for float input (quad)
|
||||
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
|
||||
// x > 2^LOG2_HEADROOM undefined
|
||||
// x > 2^LOG2_HEADROOM returns 0
|
||||
//
|
||||
FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) {
|
||||
|
||||
|
@ -243,12 +243,12 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2,
|
|||
uint32_t peak = MAX(MAX(u0, u1), MAX(u2, u3));
|
||||
|
||||
// split into e and x - 1.0
|
||||
int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
return 0x7fffffff;
|
||||
// saturate when e > 31 or e < 0
|
||||
if ((uint32_t)e > 31) {
|
||||
return 0x7fffffff & ~(e >> 31);
|
||||
}
|
||||
|
||||
int k = x >> (31 - LOG2_TABBITS);
|
||||
|
|
|
@ -447,9 +447,9 @@ AudioInjectorPointer AudioInjector::playSound(SharedSoundPointer sound, const A
|
|||
using AudioConstants::AudioSample;
|
||||
using AudioConstants::SAMPLE_RATE;
|
||||
const int standardRate = SAMPLE_RATE;
|
||||
// limit to 4 octaves
|
||||
const int pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f);
|
||||
const int resampledRate = SAMPLE_RATE / pitch;
|
||||
// limit pitch to 4 octaves
|
||||
const float pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f);
|
||||
const int resampledRate = glm::round(SAMPLE_RATE / pitch);
|
||||
|
||||
auto audioData = sound->getAudioData();
|
||||
auto numChannels = audioData->getNumChannels();
|
||||
|
@ -499,9 +499,9 @@ AudioInjectorPointer AudioInjector::playSound(AudioDataPointer audioData, const
|
|||
using AudioConstants::AudioSample;
|
||||
using AudioConstants::SAMPLE_RATE;
|
||||
const int standardRate = SAMPLE_RATE;
|
||||
// limit to 4 octaves
|
||||
const int pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f);
|
||||
const int resampledRate = SAMPLE_RATE / pitch;
|
||||
// limit pitch to 4 octaves
|
||||
const float pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f);
|
||||
const int resampledRate = glm::round(SAMPLE_RATE / pitch);
|
||||
|
||||
auto numChannels = audioData->getNumChannels();
|
||||
auto numFrames = audioData->getNumFrames();
|
||||
|
|
|
@ -1490,7 +1490,7 @@ protected:
|
|||
bool _isClientAvatar { false };
|
||||
|
||||
// null unless MyAvatar or ScriptableAvatar sending traits data to mixer
|
||||
std::unique_ptr<ClientTraitsHandler> _clientTraitsHandler;
|
||||
std::unique_ptr<ClientTraitsHandler, LaterDeleter> _clientTraitsHandler;
|
||||
|
||||
template <typename T, typename F>
|
||||
T readLockWithNamedJointIndex(const QString& name, const T& defaultValue, F f) const {
|
||||
|
|
|
@ -22,7 +22,7 @@ ClientTraitsHandler::ClientTraitsHandler(AvatarData* owningAvatar) :
|
|||
_owningAvatar(owningAvatar)
|
||||
{
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
QObject::connect(nodeList.data(), &NodeList::nodeAdded, [this](SharedNodePointer addedNode){
|
||||
QObject::connect(nodeList.data(), &NodeList::nodeAdded, this, [this](SharedNodePointer addedNode) {
|
||||
if (addedNode->getType() == NodeType::AvatarMixer) {
|
||||
resetForNewMixer();
|
||||
}
|
||||
|
|
|
@ -534,18 +534,26 @@ void OpenGLDisplayPlugin::updateFrameData() {
|
|||
}
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> OpenGLDisplayPlugin::getHUDOperator() {
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
|
||||
if (_hudPipeline && hudTexture) {
|
||||
auto hudPipeline = _hudPipeline;
|
||||
auto hudMirrorPipeline = _mirrorHUDPipeline;
|
||||
auto hudStereo = isStereo();
|
||||
auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize();
|
||||
std::array<glm::ivec4, 2> hudEyeViewports;
|
||||
for_each_eye([&](Eye eye) {
|
||||
hudEyeViewports[eye] = eyeViewport(eye);
|
||||
});
|
||||
return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
|
||||
if (hudPipeline && hudTexture) {
|
||||
batch.enableStereo(false);
|
||||
batch.setPipeline(mirror ? _mirrorHUDPipeline : _hudPipeline);
|
||||
batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline);
|
||||
batch.setResourceTexture(0, hudTexture);
|
||||
if (isStereo()) {
|
||||
if (hudStereo) {
|
||||
for_each_eye([&](Eye eye) {
|
||||
batch.setViewportTransform(eyeViewport(eye));
|
||||
batch.setViewportTransform(hudEyeViewports[eye]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
} else {
|
||||
batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize()));
|
||||
batch.setViewportTransform(ivec4(uvec2(0), hudCompositeFramebufferSize));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -420,18 +420,26 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
|
|||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
|
||||
updatePipeline();
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
|
||||
if (pipeline && hudTexture) {
|
||||
batch.setPipeline(pipeline);
|
||||
|
||||
batch.setInputFormat(format);
|
||||
gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element);
|
||||
gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element);
|
||||
auto hudPipeline = pipeline;
|
||||
auto hudFormat = format;
|
||||
auto hudVertices = vertices;
|
||||
auto hudIndices = indices;
|
||||
auto hudUniformBuffer = uniformsBuffer;
|
||||
auto hudUniforms = uniforms;
|
||||
auto hudIndexCount = indexCount;
|
||||
return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
|
||||
if (hudPipeline && hudTexture) {
|
||||
batch.setPipeline(hudPipeline);
|
||||
|
||||
batch.setInputFormat(hudFormat);
|
||||
gpu::BufferView posView(hudVertices, VERTEX_OFFSET, hudVertices->getSize(), VERTEX_STRIDE, hudFormat->getAttributes().at(gpu::Stream::POSITION)._element);
|
||||
gpu::BufferView uvView(hudVertices, TEXTURE_OFFSET, hudVertices->getSize(), VERTEX_STRIDE, hudFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, posView);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView);
|
||||
batch.setIndexBuffer(gpu::UINT16, indices, 0);
|
||||
uniformsBuffer->setSubData(0, uniforms);
|
||||
batch.setUniformBuffer(0, uniformsBuffer);
|
||||
batch.setIndexBuffer(gpu::UINT16, hudIndices, 0);
|
||||
hudUniformBuffer->setSubData(0, hudUniforms);
|
||||
batch.setUniformBuffer(0, hudUniformBuffer);
|
||||
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
glm::mat4 modelTransform = compositorHelper->getUiTransform();
|
||||
|
@ -441,7 +449,7 @@ std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDis
|
|||
batch.setModelTransform(modelTransform);
|
||||
batch.setResourceTexture(0, hudTexture);
|
||||
|
||||
batch.drawIndexed(gpu::TRIANGLES, indexCount);
|
||||
batch.drawIndexed(gpu::TRIANGLES, hudIndexCount);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -486,6 +486,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
|||
|
||||
propertiesWithSimID.setLastEditedBy(sessionID);
|
||||
|
||||
propertiesWithSimID.setActionData(QByteArray());
|
||||
|
||||
bool scalesWithParent = propertiesWithSimID.getScalesWithParent();
|
||||
|
||||
propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent);
|
||||
|
@ -830,6 +832,8 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
properties.setClientOnly(entity->getClientOnly());
|
||||
properties.setOwningAvatarID(entity->getOwningAvatarID());
|
||||
|
||||
properties.setActionData(entity->getDynamicData());
|
||||
|
||||
// make sure the properties has a type, so that the encode can know which properties to include
|
||||
properties.setType(entity->getType());
|
||||
|
||||
|
|
|
@ -180,9 +180,7 @@ void Deck::processFrames() {
|
|||
#ifdef WANT_RECORDING_DEBUG
|
||||
qCDebug(recordingLog) << "Setting timer for next processing " << nextInterval;
|
||||
#endif
|
||||
_timer.singleShot(nextInterval, [this] {
|
||||
processFrames();
|
||||
});
|
||||
_timer.singleShot(nextInterval, this, &Deck::processFrames);
|
||||
}
|
||||
|
||||
void Deck::removeClip(const ClipConstPointer& clip) {
|
||||
|
|
|
@ -303,7 +303,7 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() {
|
|||
}
|
||||
|
||||
void AmbientOcclusionEffect::configure(const Config& config) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(config.enabled);
|
||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(config.isEnabled());
|
||||
|
||||
bool shouldUpdateBlurs = false;
|
||||
bool shouldUpdateTechnique = false;
|
||||
|
|
|
@ -78,7 +78,6 @@ using AmbientOcclusionFramebufferPointer = std::shared_ptr<AmbientOcclusionFrame
|
|||
|
||||
class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty)
|
||||
Q_PROPERTY(bool horizonBased MEMBER horizonBased NOTIFY dirty)
|
||||
Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty)
|
||||
Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
|
||||
|
|
|
@ -282,7 +282,7 @@ void BloomEffect::configure(const Config& config) {
|
|||
for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) {
|
||||
blurName.back() = '0' + i;
|
||||
auto blurConfig = config.getConfig<render::BlurGaussian>(blurName);
|
||||
blurConfig->setProperty("filterScale", 1.0f);
|
||||
blurConfig->filterScale = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
class DebugDeferredBufferConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled)
|
||||
Q_PROPERTY(int mode MEMBER mode WRITE setMode)
|
||||
Q_PROPERTY(glm::vec4 size MEMBER size NOTIFY dirty)
|
||||
public:
|
||||
|
|
|
@ -606,11 +606,16 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex
|
|||
}
|
||||
}
|
||||
|
||||
RenderDeferred::RenderDeferred(bool renderShadows):
|
||||
_renderShadows(renderShadows)
|
||||
{
|
||||
DependencyManager::get<DeferredLightingEffect>()->init();
|
||||
}
|
||||
|
||||
void RenderDeferred::configure(const Config& config) {
|
||||
}
|
||||
|
||||
void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
PROFILE_RANGE(render, "DeferredLighting");
|
||||
|
||||
auto deferredTransform = inputs.get0();
|
||||
auto deferredFramebuffer = inputs.get1();
|
||||
|
|
|
@ -189,8 +189,7 @@ public:
|
|||
using Config = RenderDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
||||
|
||||
RenderDeferred() {}
|
||||
RenderDeferred(bool renderShadows) : _renderShadows(renderShadows) {}
|
||||
RenderDeferred(bool renderShadows = false);
|
||||
|
||||
void configure(const Config& config);
|
||||
|
||||
|
|
|
@ -444,10 +444,12 @@ LightStageSetup::LightStageSetup() {
|
|||
}
|
||||
|
||||
void LightStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(LightStage::getName());
|
||||
if (!stage) {
|
||||
stage = std::make_shared<LightStage>();
|
||||
renderContext->_scene->resetStage(LightStage::getName(), stage);
|
||||
if (renderContext->_scene) {
|
||||
auto stage = renderContext->_scene->getStage(LightStage::getName());
|
||||
if (!stage) {
|
||||
stage = std::make_shared<LightStage>();
|
||||
renderContext->_scene->resetStage(LightStage::getName(), stage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ using namespace render;
|
|||
extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
||||
|
||||
void RenderShadowTask::configure(const Config& configuration) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->setShadowMapEnabled(configuration.enabled);
|
||||
DependencyManager::get<DeferredLightingEffect>()->setShadowMapEnabled(configuration.isEnabled());
|
||||
// This is a task, so must still propogate configure() to its Jobs
|
||||
// Task::configure(configuration);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ protected:
|
|||
|
||||
class RenderShadowTaskConfig : public render::Task::Config::Persistent {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty)
|
||||
public:
|
||||
RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {}
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ private:
|
|||
|
||||
class ToneMappingConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled)
|
||||
Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure);
|
||||
Q_PROPERTY(int curve MEMBER curve WRITE setCurve);
|
||||
public:
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
namespace render {
|
||||
class DrawSceneOctreeConfig : public Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
|
||||
Q_PROPERTY(bool showVisibleCells READ getShowVisibleCells WRITE setShowVisibleCells NOTIFY dirty())
|
||||
Q_PROPERTY(bool showEmptyCells READ getShowEmptyCells WRITE setShowEmptyCells NOTIFY dirty())
|
||||
Q_PROPERTY(int numAllocatedCells READ getNumAllocatedCells)
|
||||
|
@ -77,7 +76,6 @@ namespace render {
|
|||
|
||||
class DrawItemSelectionConfig : public Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
|
||||
Q_PROPERTY(bool showInsideItems READ getShowInsideItems WRITE setShowInsideItems NOTIFY dirty())
|
||||
Q_PROPERTY(bool showInsideSubcellItems READ getShowInsideSubcellItems WRITE setShowInsideSubcellItems NOTIFY dirty())
|
||||
Q_PROPERTY(bool showPartialItems READ getShowPartialItems WRITE setShowPartialItems NOTIFY dirty())
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
using namespace render;
|
||||
|
||||
void DrawStatusConfig::dirtyHelper() {
|
||||
enabled = showNetwork || showDisplay;
|
||||
_isEnabled = showNetwork || showDisplay;
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -319,10 +319,6 @@ void ScriptEngines::loadScripts() {
|
|||
|
||||
// loads all saved scripts
|
||||
auto runningScripts = runningScriptsHandle.get();
|
||||
if (runningScripts.empty()) {
|
||||
loadDefaultScripts();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto script : runningScripts) {
|
||||
auto string = script.toString();
|
||||
|
|
|
@ -74,6 +74,9 @@ public:
|
|||
#endif
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
static void prepareToExit() { manager()._exiting = true; }
|
||||
|
||||
private:
|
||||
static DependencyManager& manager();
|
||||
|
||||
|
@ -84,6 +87,8 @@ private:
|
|||
|
||||
QHash<size_t, QSharedPointer<Dependency>> _instanceHash;
|
||||
QHash<size_t, size_t> _inheritanceHash;
|
||||
|
||||
bool _exiting { false };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -95,9 +100,17 @@ QSharedPointer<T> DependencyManager::get() {
|
|||
instance = qSharedPointerCast<T>(manager().safeGet(hashCode));
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
// debug builds...
|
||||
if (instance.isNull()) {
|
||||
qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name();
|
||||
}
|
||||
#else
|
||||
// for non-debug builds, don't print "No instance available" during shutdown, because
|
||||
// the act of printing this often causes crashes (because the LogHandler has-been/is-being
|
||||
// deleted).
|
||||
if (!manager()._exiting && instance.isNull()) {
|
||||
qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,13 @@ void doEvery(quint64& lastReportUsecs, quint64 secs, F lamdba) {
|
|||
// Maximum accuracy in msecs
|
||||
float secTimestampNow();
|
||||
|
||||
// Custom deleter for QObjects that calls deleteLater
|
||||
struct LaterDeleter {
|
||||
void operator()(QObject* ptr) {
|
||||
ptr->deleteLater();
|
||||
}
|
||||
};
|
||||
|
||||
float randFloat();
|
||||
int randIntInRange (int min, int max);
|
||||
float randFloatInRange (float min,float max);
|
||||
|
|
|
@ -18,6 +18,17 @@
|
|||
|
||||
using namespace task;
|
||||
|
||||
JobConfig::~JobConfig() {
|
||||
|
||||
}
|
||||
|
||||
void JobConfig::setEnabled(bool enable) {
|
||||
if (_isEnabled != enable) {
|
||||
_isEnabled = enable;
|
||||
emit dirtyEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
void JobConfig::setPresetList(const QJsonObject& object) {
|
||||
for (auto it = object.begin(); it != object.end(); it++) {
|
||||
JobConfig* child = findChild<JobConfig*>(it.key(), Qt::FindDirectChildrenOnly);
|
||||
|
@ -68,3 +79,57 @@ void TaskConfig::refresh() {
|
|||
_task->applyConfiguration();
|
||||
}
|
||||
|
||||
TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const {
|
||||
TaskConfig* root = const_cast<TaskConfig*> (this);
|
||||
|
||||
std::list<std::string> tokens;
|
||||
std::size_t pos = 0, sepPos;
|
||||
while ((sepPos = jobPath.find_first_of('.', pos)) != std::string::npos) {
|
||||
std::string token = jobPath.substr(pos, sepPos - pos);
|
||||
if (!token.empty()) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
pos = sepPos + 1;
|
||||
}
|
||||
{
|
||||
std::string token = jobPath.substr(pos, sepPos - pos);
|
||||
if (!token.empty()) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.empty()) {
|
||||
return root;
|
||||
}
|
||||
else {
|
||||
while (tokens.size() > 1) {
|
||||
auto taskName = tokens.front();
|
||||
tokens.pop_front();
|
||||
root = root->findChild<TaskConfig*>((taskName.empty() ? QString() : QString(taskName.c_str())));
|
||||
if (!root) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
jobName = tokens.front();
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const {
|
||||
std::string jobName;
|
||||
auto root = getRootConfig(jobPath, jobName);
|
||||
|
||||
if (!root) {
|
||||
return nullptr;
|
||||
}
|
||||
if (jobName.empty()) {
|
||||
return root;
|
||||
} else {
|
||||
|
||||
auto found = root->findChild<JobConfig*>((jobName.empty() ? QString() : QString(jobName.c_str())));
|
||||
if (!found) {
|
||||
return nullptr;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,12 +50,10 @@ public:
|
|||
_default = toJsonValue(*this).toObject().toVariantMap();
|
||||
|
||||
_presets.unite(list.toVariantMap());
|
||||
if (C::alwaysEnabled || C::enabled) {
|
||||
if (C::isEnabled()) {
|
||||
_presets.insert(DEFAULT, _default);
|
||||
}
|
||||
if (!C::alwaysEnabled) {
|
||||
_presets.insert(NONE, QVariantMap{{ "enabled", false }});
|
||||
}
|
||||
_presets.insert(NONE, QVariantMap{{ "enabled", false }});
|
||||
|
||||
auto preset = _preset.get();
|
||||
if (preset != _preset.getDefault() && _presets.contains(preset)) {
|
||||
|
@ -92,17 +90,21 @@ class JobConfig : public QObject {
|
|||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled())
|
||||
|
||||
double _msCPURunTime{ 0.0 };
|
||||
|
||||
protected:
|
||||
friend class TaskConfig;
|
||||
|
||||
bool _isEnabled{ true };
|
||||
|
||||
public:
|
||||
using Persistent = PersistentConfig<JobConfig>;
|
||||
|
||||
JobConfig() = default;
|
||||
JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {}
|
||||
JobConfig(bool enabled): _isEnabled{ enabled } {}
|
||||
~JobConfig();
|
||||
|
||||
bool isEnabled() { return alwaysEnabled || enabled; }
|
||||
void setEnabled(bool enable) { enabled = alwaysEnabled || enable; emit dirtyEnabled(); }
|
||||
|
||||
bool alwaysEnabled{ true };
|
||||
bool enabled{ true };
|
||||
bool isEnabled() const { return _isEnabled; }
|
||||
void setEnabled(bool enable);
|
||||
|
||||
virtual void setPresetList(const QJsonObject& object);
|
||||
|
||||
|
@ -200,6 +202,7 @@ public:
|
|||
*/
|
||||
class TaskConfig : public JobConfig {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using Persistent = PersistentConfig<TaskConfig>;
|
||||
|
||||
|
@ -221,27 +224,13 @@ public:
|
|||
//
|
||||
// getter for qml integration, prefer the templated getter
|
||||
Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig<TConfigProxy>(name.toStdString()); }
|
||||
|
||||
// getter for cpp (strictly typed), prefer this getter
|
||||
template <class T> typename T::Config* getConfig(std::string job = "") const {
|
||||
const TaskConfig* root = this;
|
||||
QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string
|
||||
auto tokens = path.split('.', QString::SkipEmptyParts);
|
||||
TaskConfig* getRootConfig(const std::string& jobPath, std::string& jobName) const;
|
||||
JobConfig* getJobConfig(const std::string& jobPath) const;
|
||||
|
||||
if (tokens.empty()) {
|
||||
tokens.push_back(QString());
|
||||
}
|
||||
else {
|
||||
while (tokens.size() > 1) {
|
||||
auto name = tokens.front();
|
||||
tokens.pop_front();
|
||||
root = QObject::findChild<TaskConfig*>(name);
|
||||
if (!root) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return root->findChild<typename T::Config*>(tokens.front());
|
||||
template <class T> typename T::Config* getConfig(std::string jobPath = "") const {
|
||||
return dynamic_cast<typename T::Config*>(getJobConfig(jobPath));
|
||||
}
|
||||
|
||||
Q_INVOKABLE bool isTask() const override { return true; }
|
||||
|
|
|
@ -164,7 +164,7 @@ public:
|
|||
|
||||
void run(const ContextPointer& jobContext) override {
|
||||
jobContext->jobConfig = std::static_pointer_cast<Config>(Concept::_config);
|
||||
if (jobContext->jobConfig->alwaysEnabled || jobContext->jobConfig->isEnabled()) {
|
||||
if (jobContext->jobConfig->isEnabled()) {
|
||||
jobRun(_data, jobContext, _input.get<I>(), _output.edit<O>());
|
||||
}
|
||||
jobContext->jobConfig.reset();
|
||||
|
@ -340,7 +340,7 @@ public:
|
|||
|
||||
void run(const ContextPointer& jobContext) override {
|
||||
auto config = std::static_pointer_cast<C>(Concept::_config);
|
||||
if (config->alwaysEnabled || config->enabled) {
|
||||
if (config->isEnabled()) {
|
||||
for (auto job : TaskConcept::_jobs) {
|
||||
job.run(jobContext);
|
||||
if (jobContext->taskFlow.doAbortTask()) {
|
||||
|
|
|
@ -149,6 +149,11 @@ protected:
|
|||
int findPositionOfMenuItem(MenuWrapper* menu, const QString& searchMenuItem);
|
||||
int positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition);
|
||||
|
||||
// There is a design flaw here -- _actionHash is system-wide and hashes the names of menu-items to their
|
||||
// QActions. The path (parent submenu name etc) isn't included in the hash key. This generally works,
|
||||
// but we add "Home" twice -- once for "go home" and once for "set startup location to home". Anytime
|
||||
// a user bookmarks a place and gives it a name like an existing menu-item, something will go wrong.
|
||||
// TODO: change the js api to require the full path when referring to a specific menu item.
|
||||
QHash<QString, QAction*> _actionHash;
|
||||
|
||||
bool isValidGrouping(const QString& grouping) const { return grouping == "Advanced" || grouping == "Developer"; }
|
||||
|
|
|
@ -892,7 +892,7 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHead
|
|||
glm::vec3 x = glm::normalize(glm::cross(Vectors::UNIT_Y, forward));
|
||||
glm::vec3 z = glm::normalize(glm::cross(x, Vectors::UNIT_Y));
|
||||
glm::mat3 centerEyeRotMat(x, Vectors::UNIT_Y, z);
|
||||
glm::vec3 centerEyeTrans = headPuckPose.translation + centerEyeRotMat * glm::vec3(0.0f, _headPuckYOffset, _headPuckZOffset);
|
||||
glm::vec3 centerEyeTrans = headPuckPose.translation + centerEyeRotMat * -glm::vec3(0.0f, _headPuckYOffset, _headPuckZOffset);
|
||||
|
||||
glm::mat4 E_s(glm::vec4(centerEyeRotMat[0], 0.0f),
|
||||
glm::vec4(centerEyeRotMat[1], 0.0f),
|
||||
|
@ -1056,7 +1056,7 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef
|
|||
float hapticTime = strength * MAX_HAPTIC_TIME;
|
||||
if (hapticTime < duration * 1000.0f) {
|
||||
_system->TriggerHapticPulse(deviceIndex, 0, hapticTime);
|
||||
}
|
||||
}
|
||||
|
||||
float remainingHapticTime = duration - (hapticTime / 1000.0f + deltaTime * 1000.0f); // in milliseconds
|
||||
if (leftHand) {
|
||||
|
@ -1077,23 +1077,20 @@ void ViveControllerManager::InputDevice::calibrateLeftHand(const glm::mat4& defa
|
|||
}
|
||||
|
||||
// This allows the user to not have to match the t-pose exactly. We assume that the y facing of the hand lies in the plane of the puck.
|
||||
// Where the plane of the puck is defined by the the local z-axis of the puck, which is facing out of the vive logo/power button.
|
||||
// Where the plane of the puck is defined by the the local z-axis of the puck, which is pointing out of the camera mount on the bottom of the puck.
|
||||
glm::vec3 zPrime = handPoseZAxis;
|
||||
glm::vec3 xPrime = glm::normalize(glm::cross(referenceHandYAxis, handPoseZAxis));
|
||||
glm::vec3 yPrime = glm::normalize(glm::cross(zPrime, xPrime));
|
||||
glm::mat4 newHandMat = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f),
|
||||
glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset);
|
||||
glm::quat initialRotation = handPose.getRotation();
|
||||
glm::quat finalRotation = glmExtractRotation(newHandMat);
|
||||
|
||||
glm::quat rotationOffset = glm::inverse(initialRotation) * finalRotation;
|
||||
|
||||
glm::mat4 offsetMat = createMatFromQuatAndPos(rotationOffset, translationOffset);
|
||||
glm::quat initialRot = handPose.getRotation();
|
||||
glm::quat postOffsetRot = glm::inverse(initialRot) * glmExtractRotation(newHandMat);
|
||||
glm::vec3 postOffsetTrans = postOffsetRot * -glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset);
|
||||
glm::mat4 postOffsetMat = createMatFromQuatAndPos(postOffsetRot, postOffsetTrans);
|
||||
|
||||
_jointToPuckMap[controller::LEFT_HAND] = handPair.first;
|
||||
_pucksPostOffset[handPair.first] = offsetMat;
|
||||
_pucksPostOffset[handPair.first] = postOffsetMat;
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::calibrateRightHand(const glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, PuckPosePair& handPair) {
|
||||
|
@ -1113,16 +1110,13 @@ void ViveControllerManager::InputDevice::calibrateRightHand(const glm::mat4& def
|
|||
glm::mat4 newHandMat = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f),
|
||||
glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset);
|
||||
glm::quat initialRotation = handPose.getRotation();
|
||||
glm::quat finalRotation = glmExtractRotation(newHandMat);
|
||||
|
||||
glm::quat rotationOffset = glm::inverse(initialRotation) * finalRotation;
|
||||
|
||||
glm::mat4 offsetMat = createMatFromQuatAndPos(rotationOffset, translationOffset);
|
||||
glm::quat initialRot = handPose.getRotation();
|
||||
glm::quat postOffsetRot = glm::inverse(initialRot) * glmExtractRotation(newHandMat);
|
||||
glm::vec3 postOffsetTrans = postOffsetRot * -glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset);
|
||||
glm::mat4 postOffsetMat = createMatFromQuatAndPos(postOffsetRot, postOffsetTrans);
|
||||
|
||||
_jointToPuckMap[controller::RIGHT_HAND] = handPair.first;
|
||||
_pucksPostOffset[handPair.first] = offsetMat;
|
||||
_pucksPostOffset[handPair.first] = postOffsetMat;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -73,6 +73,121 @@ function job_print_functor(printout, showProps, maxDepth) {
|
|||
}
|
||||
}
|
||||
|
||||
// Use this function to create a functor that will build a tree datastructure of the Job visited
|
||||
|
||||
function job_tree_model_array_functor(jobTreeArray, newNodeFunctor) {
|
||||
var jobsRoot;
|
||||
var numJobs = 0;
|
||||
var jobTreePath = []
|
||||
if (newNodeFunctor === undefined) newNodeFunctor = function (node) {}
|
||||
|
||||
return function (job, depth, index) {
|
||||
var id = numJobs
|
||||
var newItem = {"name": job.objectName, "level": depth, "index": index, "id": id, "subNode": [], "path": ""}
|
||||
if (depth == 0) {
|
||||
newNodeFunctor(newItem)
|
||||
jobTreeArray.push(newItem)
|
||||
numJobs++
|
||||
jobsRoot = jobTreeArray[0].subNode;
|
||||
} else {
|
||||
if (jobTreePath.length < depth) {
|
||||
var node = jobsRoot;
|
||||
var path;
|
||||
for (var n = 0; n < jobTreePath.length; n++) {
|
||||
newItem.path += (n > 0 ? "." : "") + node[jobTreePath[n]].name
|
||||
node = node[jobTreePath[n]].subNode
|
||||
}
|
||||
|
||||
newNodeFunctor(newItem)
|
||||
node.push((newItem))
|
||||
numJobs++
|
||||
jobTreePath.push(0);
|
||||
} else if (jobTreePath.length >= depth) {
|
||||
var node = jobsRoot;
|
||||
for (var n = 0; n < (depth - 1); n++) {
|
||||
newItem.path += (n > 0 ? "." : "") + node[jobTreePath[n]].name
|
||||
node = node[jobTreePath[n]].subNode
|
||||
}
|
||||
|
||||
newNodeFunctor(newItem)
|
||||
node.push((newItem))
|
||||
numJobs++
|
||||
jobTreePath[depth-1] = index;
|
||||
while (jobTreePath.length > depth) {
|
||||
jobTreePath.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function job_tree_model_functor(jobTreeModel, maxLevel, newNodeFunctor) {
|
||||
var jobsRoot;
|
||||
var numJobs = 0;
|
||||
var jobTreePath = []
|
||||
if (newNodeFunctor === undefined) newNodeFunctor = function (node) {}
|
||||
|
||||
return function (job, depth, index) {
|
||||
var id = numJobs
|
||||
var newItem = {"name": job.objectName, "level": depth, "index": index, "id": id, "subNode": [], "path": "", "init": (depth < maxLevel), "ud": {}}
|
||||
if (depth == 0) {
|
||||
newNodeFunctor(newItem)
|
||||
jobTreeModel.append(newItem)
|
||||
numJobs++
|
||||
jobsRoot = jobTreeModel.get(0).subNode;
|
||||
} else {
|
||||
if (jobTreePath.length < depth) {
|
||||
var node = jobsRoot;
|
||||
var path;
|
||||
for (var n = 0; n < jobTreePath.length; n++) {
|
||||
newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name
|
||||
node = node.get(jobTreePath[n]).subNode
|
||||
}
|
||||
|
||||
newNodeFunctor(newItem)
|
||||
node.append((newItem))
|
||||
numJobs++
|
||||
jobTreePath.push(0);
|
||||
} else if (jobTreePath.length >= depth) {
|
||||
var node = jobsRoot;
|
||||
for (var n = 0; n < (depth - 1); n++) {
|
||||
newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name
|
||||
node = node.get(jobTreePath[n]).subNode
|
||||
}
|
||||
|
||||
newNodeFunctor(newItem)
|
||||
node.append((newItem))
|
||||
numJobs++
|
||||
jobTreePath[depth-1] = index;
|
||||
while (jobTreePath.length > depth) {
|
||||
jobTreePath.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Traverse the jobTreenode data structure created above
|
||||
function job_traverseTreeNode(root, functor, depth) {
|
||||
if (root.subNode.length) {
|
||||
depth++;
|
||||
for (var i = 0; i <root.subNode.length; i++) {
|
||||
var sub = root.subNode[i];
|
||||
if (functor(sub, depth, i)) {
|
||||
job_traverseTreeNode(sub, functor, depth, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function job_traverseTreeNodeRoot(root, functor) {
|
||||
if (functor(root, 0, 0)) {
|
||||
job_traverseTreeNode(root, functor, 0)
|
||||
}
|
||||
}
|
||||
// Expose functions for regular js including this files through the 'Jet' object
|
||||
/*Jet = {}
|
||||
Jet.task_traverse = task_traverse
|
||||
|
|
|
@ -19,56 +19,23 @@ import "../jet.js" as Jet
|
|||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi;}
|
||||
color: hifi.colors.baseGray;
|
||||
color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8);
|
||||
id: root;
|
||||
|
||||
property var rootConfig : Workload
|
||||
property var myArray : []
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
var message = ""
|
||||
var maxDepth = 3;
|
||||
|
||||
var jobTreePath = []
|
||||
var jobsRoot;
|
||||
|
||||
var functor = function (job, depth, index) {
|
||||
var newItem = {"name": job.objectName, "level": depth, "index": index, "subNode": [], "init": depth < maxDepth, "path": ""}
|
||||
if (depth == 0) {
|
||||
jobsModel.append(newItem)
|
||||
jobsRoot = jobsModel.get(0).subNode;
|
||||
} else {
|
||||
if (jobTreePath.length < depth) {
|
||||
var node = jobsRoot;
|
||||
var path;
|
||||
for (var n = 0; n < jobTreePath.length; n++) {
|
||||
newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name
|
||||
node = node.get(jobTreePath[n]).subNode
|
||||
}
|
||||
node.append(newItem)
|
||||
jobTreePath.push(0);
|
||||
} else if (jobTreePath.length >= depth) {
|
||||
var node = jobsRoot;
|
||||
for (var n = 0; n < (depth - 1); n++) {
|
||||
newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name
|
||||
node = node.get(jobTreePath[n]).subNode
|
||||
}
|
||||
node.append(newItem)
|
||||
jobTreePath[depth-1] = index;
|
||||
while (jobTreePath.length > depth) {
|
||||
jobTreePath.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var functor = Jet.job_tree_model_functor(jobsModel, 3, function(node) {
|
||||
node["cpuT"] = 0.0
|
||||
})
|
||||
Jet.task_traverseTree(rootConfig, functor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ListModel {
|
||||
id: jobsModel
|
||||
property var engineJobItemModel : []
|
||||
}
|
||||
|
||||
Component {
|
||||
|
@ -77,30 +44,46 @@ Rectangle {
|
|||
id: objRecursiveColumn
|
||||
clip: true
|
||||
visible: model.init
|
||||
|
||||
MouseArea {
|
||||
width: objRow.implicitWidth
|
||||
height: objRow.implicitHeight
|
||||
onDoubleClicked: {
|
||||
for(var i = 1; i < parent.children.length - 1; ++i) {
|
||||
parent.children[i].visible = !parent.children[i].visible
|
||||
}
|
||||
|
||||
function switchFold() {
|
||||
for(var i = 1; i < children.length - 1; ++i) {
|
||||
children[i].visible = !children[i].visible
|
||||
}
|
||||
Row {
|
||||
id: objRow
|
||||
Item {
|
||||
height: 1
|
||||
width: model.level * 15
|
||||
}
|
||||
|
||||
Row {
|
||||
id: objRow
|
||||
Item {
|
||||
height: 1
|
||||
width: model.level * 15
|
||||
}
|
||||
|
||||
HifiControls.CheckBox {
|
||||
id: objCheck
|
||||
property var config: root.rootConfig.getConfig(model.path + "." + model.name);
|
||||
text: " "
|
||||
checked: root.rootConfig.getConfig(model.path + "." + model.name).enabled
|
||||
onCheckedChanged: { root.rootConfig.getConfig(model.path + "." + model.name).enabled = checked }
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
width: objLabel.implicitWidth
|
||||
height: objLabel.implicitHeight
|
||||
onDoubleClicked: {
|
||||
parent.parent.switchFold()
|
||||
}
|
||||
HifiControls.CheckBox {
|
||||
property var config: root.rootConfig.getConfig(model.path + "." + model.name);
|
||||
|
||||
HifiControls.Label {
|
||||
id: objLabel
|
||||
colorScheme: (root.rootConfig.getConfig(model.path + "." + model.name) ? hifi.colorSchemes.dark : hifi.colorSchemes.light)
|
||||
text: (objRecursiveColumn.children.length > 2 ?
|
||||
objRecursiveColumn.children[1].visible ?
|
||||
qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(2)
|
||||
checked: config.enabled
|
||||
qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name
|
||||
+ " id=" + model.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: subNode
|
||||
delegate: objRecursiveDelegate
|
||||
|
|
265
scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml
Normal file
265
scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml
Normal file
|
@ -0,0 +1,265 @@
|
|||
//
|
||||
// jet/TaskTimeFrameView.qml
|
||||
//
|
||||
// Created by Sam Gateau, 2018/06/15
|
||||
// Copyright 2018 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.7
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "qrc:///qml/styles-uit"
|
||||
import "qrc:///qml/controls-uit" as HifiControls
|
||||
|
||||
import "../jet.js" as Jet
|
||||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi;}
|
||||
color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8);
|
||||
id: root;
|
||||
|
||||
property var rootConfig : Workload
|
||||
|
||||
property var jobsTree
|
||||
property var jobsArray
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!jobsTree) { jobsTree = new Array(); }
|
||||
if (!jobsArray) { jobsArray = new Array(); }
|
||||
|
||||
var tfunctor = Jet.job_tree_model_array_functor(jobsTree, function(node) {
|
||||
var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level, "name": node.name }
|
||||
jobsArray.push(job)
|
||||
})
|
||||
Jet.task_traverseTree(rootConfig, tfunctor);
|
||||
|
||||
for (var j = 0; j <jobsArray.length; j++) {
|
||||
jobsArray[j].cpuT = Render.getConfig(jobsArray[j].fullpath).cpuRunTime
|
||||
// print("job" + j + ": " + jobsArray[j].cpuT)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component.onDestruction: {
|
||||
myCanvasTimer.stop();
|
||||
console.log("stopping timer!!!!");
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: myCanvasTimer
|
||||
interval: 100; running: true; repeat: true
|
||||
onTriggered: pullFreshValues()
|
||||
}
|
||||
|
||||
function pullFreshValues() {
|
||||
|
||||
for (var j = 0; j <jobsArray.length; j++) {
|
||||
jobsArray[j].cpuT = Render.getConfig(jobsArray[j].fullpath).cpuRunTime
|
||||
// jobsArray[j].cpuT = root.rootConfig.getConfig(jobsArray[j].fullpath).cpuRunTime
|
||||
}
|
||||
mycanvas.requestPaint()
|
||||
}
|
||||
|
||||
|
||||
property var frameScale : 10
|
||||
Row {
|
||||
id: myHeaderRow
|
||||
anchors.top:parent.top
|
||||
anchors.left:parent.left
|
||||
anchors.right:parent.right
|
||||
|
||||
|
||||
HifiControls.Button {
|
||||
id: myTimerPlayPause
|
||||
text: (myCanvasTimer.running ? "||" : "|>")
|
||||
height: 24
|
||||
width: 24
|
||||
onClicked: {
|
||||
print("list of highlight styles")
|
||||
myCanvasTimer.running = !myCanvasTimer.running
|
||||
}
|
||||
}
|
||||
}
|
||||
Canvas {
|
||||
id: mycanvas
|
||||
anchors.top:myHeaderRow.bottom
|
||||
anchors.bottom:parent.bottom
|
||||
anchors.left:parent.left
|
||||
anchors.right:parent.right
|
||||
|
||||
property var frameDuration: 10
|
||||
property var frameViewBegin: 0
|
||||
property var frameViewRange: width
|
||||
|
||||
function reset() {
|
||||
frameViewBegin = 0
|
||||
frameViewRange = width
|
||||
}
|
||||
|
||||
function checkView() {
|
||||
if (frameViewBegin > width * 0.9) {
|
||||
frameViewBegin = width * 0.9
|
||||
} else if (frameViewBegin + frameViewRange < width * 0.1) {
|
||||
frameViewBegin = width * 0.1 -frameViewRange
|
||||
}
|
||||
}
|
||||
|
||||
function drag(deltaX) {
|
||||
frameViewBegin -= deltaX
|
||||
checkView()
|
||||
}
|
||||
|
||||
function pivotScale(pivotX, deltaX) {
|
||||
var newRange = frameViewRange + 2 * deltaX
|
||||
if (newRange <= 1) {
|
||||
newRange = 2;
|
||||
}
|
||||
frameViewBegin = pivotX - frameViewRange * (pivotX - frameViewBegin) / newRange
|
||||
frameViewRange = newRange
|
||||
print( "pivot= " + pivotX + " deltaX= " + (deltaX))
|
||||
checkView()
|
||||
}
|
||||
|
||||
|
||||
onPaint: {
|
||||
// print("mycanvasOnPaint " + jobsArray.length)
|
||||
var lineHeight = 12;
|
||||
|
||||
function getXFromTime(t) {
|
||||
return (t / mycanvas.frameDuration) * mycanvas.frameViewRange - (mycanvas.frameViewBegin)
|
||||
}
|
||||
function getWFromDuration(d) {
|
||||
return (d / mycanvas.frameDuration) * mycanvas.frameViewRange
|
||||
}
|
||||
function displayBackground(ctx) {
|
||||
ctx.fillStyle = Qt.rgba(0, 0, 0, root.backgroundOpacity);
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
|
||||
ctx.strokeStyle= "grey";
|
||||
ctx.lineWidth="2";
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, lineHeight + 1);
|
||||
ctx.lineTo(width, lineHeight + 1);
|
||||
ctx.moveTo(0, height);
|
||||
ctx.lineTo(width, height);
|
||||
|
||||
var x0 = getXFromTime(0)
|
||||
ctx.moveTo(x0, 0);
|
||||
ctx.lineTo(x0, height);
|
||||
|
||||
x0 = getXFromTime(5)
|
||||
ctx.moveTo(x0, 0);
|
||||
ctx.lineTo(x0, height);
|
||||
|
||||
x0 = getXFromTime(10)
|
||||
ctx.moveTo(x0, 0);
|
||||
ctx.lineTo(x0, height);
|
||||
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawJob(ctx, depth, index, duration, timeOffset) {
|
||||
//print(root.jobsArray[index].cpuT)
|
||||
ctx.fillStyle = ( depth % 2 ? ( index % 2 ? "blue" : "yellow") : ( index % 2 ? "green" : "red"))
|
||||
ctx.fillRect(getXFromTime(timeOffset), lineHeight * 2 * depth,getWFromDuration(duration), lineHeight);
|
||||
|
||||
if (depth,getWFromDuration(duration) >= width * 0.1) {
|
||||
ctx.fillStyle = "grey";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText( root.jobsArray[index].name, getXFromTime(timeOffset + duration * 0.5), lineHeight * 2 * depth);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.font="12px Verdana";
|
||||
|
||||
displayBackground(ctx);
|
||||
if (jobsArray.length > 0) {
|
||||
mycanvas.frameDuration = Math.max(jobsArray[0].cpuT, 1)
|
||||
var rangeStack =new Array()
|
||||
rangeStack.push( { "b": 0.0, "e": mycanvas.frameDuration } )
|
||||
|
||||
drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0)
|
||||
|
||||
for (var i = 1; i <jobsArray.length; i++) {
|
||||
var lastDepth = rangeStack.length - 1;
|
||||
var depth = jobsArray[i].depth;
|
||||
var timeOffset = 0.0
|
||||
var duration = jobsArray[i].cpuT;
|
||||
|
||||
if (depth > lastDepth) {
|
||||
timeOffset = rangeStack[lastDepth].b
|
||||
while(rangeStack.length <= depth) {
|
||||
rangeStack.push( { "b": timeOffset, "e": timeOffset + duration } )
|
||||
}
|
||||
|
||||
} else {
|
||||
if (depth < lastDepth) {
|
||||
while(rangeStack.length != (depth + 1)) {
|
||||
rangeStack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
timeOffset = rangeStack[depth].e
|
||||
rangeStack[depth].b = timeOffset
|
||||
rangeStack[depth].e = timeOffset + duration
|
||||
}
|
||||
if (duration > 0.0) {
|
||||
drawJob(ctx, depth, i, duration, timeOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: hitbox
|
||||
anchors.fill: mycanvas
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
property var pivotX
|
||||
property var dragPos
|
||||
onPressed: {
|
||||
dragPos = { "x":mouse.x, "y":mouse.y }
|
||||
pivotX = mouse.x
|
||||
}
|
||||
onPositionChanged: {
|
||||
if (dragPos !== undefined) {
|
||||
var delta = mouse.x - dragPos.x
|
||||
|
||||
if (mouse.buttons & Qt.LeftButton) {
|
||||
mycanvas.drag(delta)
|
||||
}
|
||||
|
||||
if (mouse.buttons & Qt.RightButton) {
|
||||
mycanvas.pivotScale(pivotX, delta)
|
||||
}
|
||||
|
||||
dragPos.x = mouse.x
|
||||
dragPos.y = mouse.y
|
||||
mycanvas.requestPaint()
|
||||
}
|
||||
}
|
||||
onReleased: {
|
||||
dragPos = undefined
|
||||
}
|
||||
|
||||
onWheel: {
|
||||
mycanvas.pivotScale(wheel.x, mycanvas.frameViewRange * 0.02 * (wheel.angleDelta.y / 120.0))
|
||||
mycanvas.requestPaint()
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
mycanvas.reset()
|
||||
mycanvas.requestPaint()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
TaskList 1.0 TaskList.qml
|
||||
TaskViewList 1.0 TaskViewList.qml
|
||||
TaskTimeFrameView 1.0 TaskTimeFrameView.qml
|
||||
|
|
|
@ -1,13 +1,57 @@
|
|||
function openEngineTaskView() {
|
||||
// Set up the qml ui
|
||||
var qml = Script.resolvePath('engineInspector.qml');
|
||||
var window = new OverlayWindow({
|
||||
title: 'Render Engine',
|
||||
source: qml,
|
||||
width: 300,
|
||||
height: 400
|
||||
(function() {
|
||||
var TABLET_BUTTON_NAME = "Inspector";
|
||||
var QMLAPP_URL = Script.resolvePath("./engineInspector.qml");
|
||||
var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg");
|
||||
var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg");
|
||||
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var button = tablet.addButton({
|
||||
text: TABLET_BUTTON_NAME,
|
||||
icon: ICON_URL,
|
||||
activeIcon: ACTIVE_ICON_URL
|
||||
});
|
||||
window.setPosition(200, 50);
|
||||
//window.closed.connect(function() { Script.stop(); });
|
||||
}
|
||||
openEngineTaskView();
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
killWindow()
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
});
|
||||
|
||||
button.clicked.connect(onClicked);
|
||||
|
||||
var onScreen = false;
|
||||
var window;
|
||||
|
||||
function onClicked() {
|
||||
if (onScreen) {
|
||||
killWindow()
|
||||
} else {
|
||||
createWindow()
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
var qml = Script.resolvePath(QMLAPP_URL);
|
||||
window = new OverlayWindow({
|
||||
title: 'Render Engine Inspector',
|
||||
source: qml,
|
||||
width: 250,
|
||||
height: 500
|
||||
});
|
||||
window.setPosition(200, 50);
|
||||
window.closed.connect(killWindow);
|
||||
onScreen = true
|
||||
button.editProperties({isActive: true});
|
||||
}
|
||||
|
||||
function killWindow() {
|
||||
if (window !== undefined) {
|
||||
window.closed.disconnect(killWindow);
|
||||
window.close()
|
||||
window = undefined
|
||||
}
|
||||
onScreen = false
|
||||
button.editProperties({isActive: false})
|
||||
}
|
||||
}());
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// deferredLighting.qml
|
||||
// EngineInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 6/6/2016
|
||||
// Created by Sam Gateau on 06/07/2018
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -18,13 +18,13 @@ import "../lib/jet/qml" as Jet
|
|||
|
||||
Item {
|
||||
HifiConstants { id: hifi;}
|
||||
id: render;
|
||||
id: root;
|
||||
anchors.fill: parent
|
||||
|
||||
property var mainViewTask: Render.getConfig("RenderMainView")
|
||||
property var rootConfig: Render.getConfig("")
|
||||
|
||||
Jet.TaskListView {
|
||||
rootConfig: Render
|
||||
anchors.fill: render
|
||||
rootConfig: root.rootConfig
|
||||
anchors.fill: root
|
||||
}
|
||||
}
|
59
scripts/developer/utilities/render/engineProfiler.js
Normal file
59
scripts/developer/utilities/render/engineProfiler.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
|
||||
(function() {
|
||||
var TABLET_BUTTON_NAME = "Profiler";
|
||||
var QMLAPP_URL = Script.resolvePath("./engineProfiler.qml");
|
||||
var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg");
|
||||
var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg");
|
||||
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var button = tablet.addButton({
|
||||
text: TABLET_BUTTON_NAME,
|
||||
icon: ICON_URL,
|
||||
activeIcon: ACTIVE_ICON_URL
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
killWindow()
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
});
|
||||
|
||||
button.clicked.connect(onClicked);
|
||||
|
||||
var onScreen = false;
|
||||
var window;
|
||||
|
||||
function onClicked() {
|
||||
if (onScreen) {
|
||||
killWindow()
|
||||
} else {
|
||||
createWindow()
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
var qml = Script.resolvePath(QMLAPP_URL);
|
||||
window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), {
|
||||
title: 'Render Engine Profiler',
|
||||
flags: Desktop.ALWAYS_ON_TOP,
|
||||
presentationMode: Desktop.PresentationMode.NATIVE,
|
||||
size: {x: 500, y: 100}
|
||||
});
|
||||
window.setPosition(200, 50);
|
||||
window.closed.connect(killWindow);
|
||||
onScreen = true
|
||||
button.editProperties({isActive: true});
|
||||
}
|
||||
|
||||
function killWindow() {
|
||||
if (window !== undefined) {
|
||||
window.closed.disconnect(killWindow);
|
||||
window.close()
|
||||
window = undefined
|
||||
}
|
||||
onScreen = false
|
||||
button.editProperties({isActive: false})
|
||||
}
|
||||
}());
|
||||
|
31
scripts/developer/utilities/render/engineProfiler.qml
Normal file
31
scripts/developer/utilities/render/engineProfiler.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// EngineProfiler.qml
|
||||
//
|
||||
// Created by Sam Gateau on 06/07/2018
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "qrc:///qml/styles-uit"
|
||||
import "qrc:///qml/controls-uit" as HifiControls
|
||||
|
||||
import "../lib/jet/qml" as Jet
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi;}
|
||||
id: root;
|
||||
anchors.fill: parent
|
||||
|
||||
property var rootConfig: Render.getConfig("")
|
||||
|
||||
|
||||
Jet.TaskTimeFrameView {
|
||||
rootConfig: root.rootConfig
|
||||
anchors.fill: root
|
||||
}
|
||||
}
|
|
@ -615,7 +615,9 @@ function notificationPollCallbackHistory(historyArray) {
|
|||
ui.notificationDisplayBanner(message);
|
||||
} else {
|
||||
for (var i = 0; i < notificationCount; i++) {
|
||||
message = '"' + (historyArray[i].message) + '" ' +
|
||||
var historyMessage = historyArray[i].message;
|
||||
var sanitizedHistoryMessage = historyMessage.replace(/<\/?[^>]+(>|$)/g, "");
|
||||
message = '"' + sanitizedHistoryMessage + '" ' +
|
||||
"Open INVENTORY to see all activity.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
|
|
|
@ -129,9 +129,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
return getControllerWorldLocation(Controller.Standard.RightHand, true);
|
||||
};
|
||||
|
||||
Selection.enableListHighlight(DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE);
|
||||
Selection.enableListToScene(DISPATCHER_HOVERING_LIST);
|
||||
|
||||
this.updateTimings = function () {
|
||||
_this.intervalCount++;
|
||||
var thisInterval = Date.now();
|
||||
|
@ -525,7 +522,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
Controller.disableMapping(MAPPING_NAME);
|
||||
_this.pointerManager.removePointers();
|
||||
Pointers.removePointer(this.mouseRayPick);
|
||||
Selection.disableListHighlight(DISPATCHER_HOVERING_LIST);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -459,13 +459,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
this.dropGestureReset();
|
||||
this.clearEquipHaptics();
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
var message = {
|
||||
hand: this.hand,
|
||||
entityID: this.targetEntityID
|
||||
};
|
||||
|
||||
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||
var grabbedProperties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES);
|
||||
var grabData = getGrabbableData(grabbedProperties);
|
||||
|
||||
|
|
|
@ -84,7 +84,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.entityWithContextOverlay = false;
|
||||
this.contextOverlayTimer = false;
|
||||
this.locked = false;
|
||||
this.highlightedEntity = null;
|
||||
this.reticleMinX = MARGIN;
|
||||
this.reticleMaxX = null;
|
||||
this.reticleMinY = MARGIN;
|
||||
|
@ -410,9 +409,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
|
||||
(this.notPointingAtEntity(controllerData) && Window.isPhysicsEnabled()) || this.targetIsNull()) {
|
||||
this.endFarGrabAction();
|
||||
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||
this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
this.restoreIgnoredEntities();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
@ -466,9 +462,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
var entityID = rayPickInfo.objectID;
|
||||
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||
this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES);
|
||||
if (targetProps.href !== "") {
|
||||
AddressManager.handleLookupString(targetProps.href);
|
||||
|
@ -513,66 +506,43 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.startFarGrabAction(controllerData, targetProps);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var targetEntityID = rayPickInfo.objectID;
|
||||
if (this.highlightedEntity !== targetEntityID) {
|
||||
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||
this.highlightedEntity);
|
||||
var selectionTargetProps = Entities.getEntityProperties(targetEntityID, DISPATCHER_PROPERTIES);
|
||||
} else if (!this.entityWithContextOverlay) {
|
||||
var _this = this;
|
||||
|
||||
var selectionTargetObject = new TargetObject(targetEntityID, selectionTargetProps);
|
||||
selectionTargetObject.parentProps = getEntityParents(selectionTargetProps);
|
||||
var selectionTargetEntity = selectionTargetObject.getTargetEntity();
|
||||
|
||||
if (entityIsGrabbable(selectionTargetEntity.props) ||
|
||||
entityIsGrabbable(selectionTargetObject.entityProps)) {
|
||||
|
||||
Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", rayPickInfo.objectID);
|
||||
if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) {
|
||||
if (_this.contextOverlayTimer) {
|
||||
Script.clearTimeout(_this.contextOverlayTimer);
|
||||
}
|
||||
this.highlightedEntity = rayPickInfo.objectID;
|
||||
_this.contextOverlayTimer = false;
|
||||
_this.potentialEntityWithContextOverlay = rayPickInfo.objectID;
|
||||
}
|
||||
|
||||
if (!this.entityWithContextOverlay) {
|
||||
var _this = this;
|
||||
|
||||
if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) {
|
||||
if (_this.contextOverlayTimer) {
|
||||
Script.clearTimeout(_this.contextOverlayTimer);
|
||||
if (!_this.contextOverlayTimer) {
|
||||
_this.contextOverlayTimer = Script.setTimeout(function () {
|
||||
if (!_this.entityWithContextOverlay &&
|
||||
_this.contextOverlayTimer &&
|
||||
_this.potentialEntityWithContextOverlay === rayPickInfo.objectID) {
|
||||
var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES);
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: _this.hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID,
|
||||
rayPickInfo.intersection, props),
|
||||
pos3D: rayPickInfo.intersection,
|
||||
normal: rayPickInfo.surfaceNormal,
|
||||
direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal),
|
||||
button: "Secondary"
|
||||
};
|
||||
if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) {
|
||||
_this.entityWithContextOverlay = rayPickInfo.objectID;
|
||||
}
|
||||
}
|
||||
_this.contextOverlayTimer = false;
|
||||
_this.potentialEntityWithContextOverlay = rayPickInfo.objectID;
|
||||
}
|
||||
|
||||
if (!_this.contextOverlayTimer) {
|
||||
_this.contextOverlayTimer = Script.setTimeout(function () {
|
||||
if (!_this.entityWithContextOverlay &&
|
||||
_this.contextOverlayTimer &&
|
||||
_this.potentialEntityWithContextOverlay === rayPickInfo.objectID) {
|
||||
var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES);
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: _this.hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID,
|
||||
rayPickInfo.intersection, props),
|
||||
pos3D: rayPickInfo.intersection,
|
||||
normal: rayPickInfo.surfaceNormal,
|
||||
direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal),
|
||||
button: "Secondary"
|
||||
};
|
||||
if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) {
|
||||
_this.entityWithContextOverlay = rayPickInfo.objectID;
|
||||
}
|
||||
}
|
||||
_this.contextOverlayTimer = false;
|
||||
}, 500);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
} else if (this.distanceRotating) {
|
||||
this.distanceRotate(otherFarGrabModule);
|
||||
} else if (this.highlightedEntity) {
|
||||
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
}
|
||||
}
|
||||
return this.exitIfDisabled(controllerData);
|
||||
|
|
|
@ -61,6 +61,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.reticleMinY = MARGIN;
|
||||
this.reticleMaxY = 0;
|
||||
this.lastUnexpectedChildrenCheckTime = 0;
|
||||
this.endedGrab = 0;
|
||||
this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms
|
||||
|
||||
var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX
|
||||
|
||||
|
@ -144,7 +146,12 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
// compute the mass for the purpose of energy and how quickly to move object
|
||||
this.mass = this.getMass(grabbedProperties.dimensions, grabbedProperties.density);
|
||||
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
// Debounce haptic pules. Can occur as near grab controller module vacillates between being ready or not due to
|
||||
// changing positions and floating point rounding.
|
||||
if (Date.now() - this.endedGrab > this.MIN_HAPTIC_PULSE_INTERVAL) {
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
}
|
||||
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
var message = {
|
||||
hand: this.hand,
|
||||
|
@ -256,7 +263,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.endFarParentGrab = function (controllerData) {
|
||||
this.hapticTargetID = null;
|
||||
this.endedGrab = Date.now();
|
||||
// var endProps = controllerData.nearbyEntityPropertiesByID[this.targetEntityID];
|
||||
var endProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES);
|
||||
if (this.thisFarGrabJointIsParent(endProps)) {
|
||||
|
@ -410,11 +417,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (targetEntity) {
|
||||
var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES);
|
||||
if (entityIsGrabbable(gtProps)) {
|
||||
// give haptic feedback
|
||||
if (gtProps.id !== this.hapticTargetID) {
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
this.hapticTargetID = gtProps.id;
|
||||
}
|
||||
// if we've attempted to grab a child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, gtProps);
|
||||
if (entityIsGrabbable(groupRootProps)) {
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
//
|
||||
// highlightNearbyEntities.js
|
||||
//
|
||||
// Created by Dante Ruiz 2018-4-10
|
||||
// Copyright 2017 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
|
||||
|
||||
|
||||
/* global Script, MyAvatar, entityIsCloneable, Messages, print */
|
||||
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
||||
function differenceInArrays(firstArray, secondArray) {
|
||||
var differenceArray = firstArray.filter(function(element) {
|
||||
return secondArray.indexOf(element) < 0;
|
||||
});
|
||||
|
||||
return differenceArray;
|
||||
}
|
||||
|
||||
function HighlightNearbyEntities(hand) {
|
||||
this.hand = hand;
|
||||
this.otherHand = hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND :
|
||||
dispatcherUtils.RIGHT_HAND;
|
||||
this.highlightedEntities = [];
|
||||
|
||||
this.parameters = dispatcherUtils.makeDispatcherModuleParameters(
|
||||
480,
|
||||
this.hand === dispatcherUtils.RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
|
||||
this.isGrabable = function(controllerData, props) {
|
||||
var canGrabEntity = false;
|
||||
if (dispatcherUtils.entityIsGrabbable(props) || entityIsCloneable(props)) {
|
||||
// if we've attempted to grab a child, roll up to the root of the tree
|
||||
var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props);
|
||||
canGrabEntity = true;
|
||||
if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) {
|
||||
canGrabEntity = false;
|
||||
}
|
||||
}
|
||||
return canGrabEntity;
|
||||
};
|
||||
|
||||
this.clearAll = function() {
|
||||
this.highlightedEntities.forEach(function(entity) {
|
||||
dispatcherUtils.unhighlightTargetEntity(entity);
|
||||
});
|
||||
};
|
||||
|
||||
this.hasHyperLink = function(props) {
|
||||
return (props.href !== "" && props.href !== undefined);
|
||||
};
|
||||
|
||||
this.removeEntityFromHighlightList = function(entityID) {
|
||||
var index = this.highlightedEntities.indexOf(entityID);
|
||||
if (index > -1) {
|
||||
this.highlightedEntities.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
this.getOtherModule = function() {
|
||||
var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftHighlightNearbyEntities :
|
||||
rightHighlightNearbyEntities;
|
||||
return otherModule;
|
||||
};
|
||||
|
||||
this.getOtherHandHighlightedEntities = function() {
|
||||
return this.getOtherModule().highlightedEntities;
|
||||
};
|
||||
|
||||
this.highlightEntities = function(controllerData) {
|
||||
var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand];
|
||||
var otherHandHighlightedEntities = this.getOtherHandHighlightedEntities();
|
||||
var newHighlightedEntities = [];
|
||||
var sensorScaleFactor = MyAvatar.sensorToWorldScale;
|
||||
for (var i = 0; i < nearbyEntitiesProperties.length; i++) {
|
||||
var props = nearbyEntitiesProperties[i];
|
||||
if (props.distance > dispatcherUtils.NEAR_GRAB_RADIUS * sensorScaleFactor) {
|
||||
continue;
|
||||
}
|
||||
if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) {
|
||||
dispatcherUtils.highlightTargetEntity(props.id);
|
||||
if (newHighlightedEntities.indexOf(props.id) < 0) {
|
||||
newHighlightedEntities.push(props.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unhighlightEntities = differenceInArrays(this.highlightedEntities, newHighlightedEntities);
|
||||
|
||||
unhighlightEntities.forEach(function(entityID) {
|
||||
if (otherHandHighlightedEntities.indexOf(entityID) < 0 ) {
|
||||
dispatcherUtils.unhighlightTargetEntity(entityID);
|
||||
}
|
||||
});
|
||||
this.highlightedEntities = newHighlightedEntities;
|
||||
};
|
||||
|
||||
this.isReady = function(controllerData) {
|
||||
this.highlightEntities(controllerData);
|
||||
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function(controllerData) {
|
||||
return this.isReady(controllerData);
|
||||
};
|
||||
}
|
||||
|
||||
var handleMessage = function(channel, message, sender) {
|
||||
var data;
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
if (channel === 'Hifi-unhighlight-entity') {
|
||||
try {
|
||||
data = JSON.parse(message);
|
||||
var hand = data.hand;
|
||||
if (hand === dispatcherUtils.LEFT_HAND) {
|
||||
leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID);
|
||||
} else if (hand === dispatcherUtils.RIGHT_HAND) {
|
||||
rightHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID);
|
||||
}
|
||||
} catch (e) {
|
||||
print("highlightNearbyEntities -- Failed to parse message: " + JSON.stringify(message));
|
||||
}
|
||||
} else if (channel === 'Hifi-unhighlight-all') {
|
||||
leftHighlightNearbyEntities.clearAll();
|
||||
rightHighlightNearbyEntities.clearAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
var leftHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.LEFT_HAND);
|
||||
var rightHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.RIGHT_HAND);
|
||||
|
||||
dispatcherUtils.enableDispatcherModule("LeftHighlightNearbyEntities", leftHighlightNearbyEntities);
|
||||
dispatcherUtils.enableDispatcherModule("RightHighlightNearbyEntities", rightHighlightNearbyEntities);
|
||||
|
||||
function cleanup() {
|
||||
dispatcherUtils.disableDispatcherModule("LeftHighlightNearbyEntities");
|
||||
dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities");
|
||||
}
|
||||
Messages.subscribe('Hifi-unhighlight-entity');
|
||||
Messages.subscribe('Hifi-unhighlight-all');
|
||||
Messages.messageReceived.connect(handleMessage);
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
|
@ -1,104 +0,0 @@
|
|||
//
|
||||
// mouseHighlightEntities.js
|
||||
//
|
||||
// scripts/system/controllers/controllerModules/
|
||||
//
|
||||
// Created by Dante Ruiz 2018-4-11
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
/* jslint bitwise: true */
|
||||
|
||||
/* global Script, print, Entities, Messages, Picks, HMD, MyAvatar, isInEditMode, DISPATCHER_PROPERTIES */
|
||||
|
||||
|
||||
(function() {
|
||||
Script.include("/~/system/libraries/utils.js");
|
||||
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
||||
function MouseHighlightEntities() {
|
||||
this.highlightedEntity = null;
|
||||
this.grabbedEntity = null;
|
||||
|
||||
this.parameters = dispatcherUtils.makeDispatcherModuleParameters(
|
||||
5,
|
||||
["mouse"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.setGrabbedEntity = function(entity) {
|
||||
this.grabbedEntity = entity;
|
||||
this.highlightedEntity = null;
|
||||
};
|
||||
|
||||
this.isReady = function(controllerData) {
|
||||
if (HMD.active) {
|
||||
if (this.highlightedEntity) {
|
||||
dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
}
|
||||
} else if (!this.grabbedEntity && !isInEditMode()) {
|
||||
var pickResult = controllerData.mouseRayPick;
|
||||
if (pickResult.type === Picks.INTERSECTED_ENTITY) {
|
||||
var targetEntityID = pickResult.objectID;
|
||||
|
||||
if (this.highlightedEntity !== targetEntityID) {
|
||||
var targetProps = Entities.getEntityProperties(targetEntityID, DISPATCHER_PROPERTIES);
|
||||
|
||||
if (this.highlightedEntity) {
|
||||
dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
}
|
||||
|
||||
if (dispatcherUtils.entityIsGrabbable(targetProps)) {
|
||||
// highlight entity
|
||||
dispatcherUtils.highlightTargetEntity(targetEntityID);
|
||||
this.highlightedEntity = targetEntityID;
|
||||
}
|
||||
}
|
||||
} else if (this.highlightedEntity) {
|
||||
dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
}
|
||||
}
|
||||
|
||||
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function(controllerData) {
|
||||
return this.isReady(controllerData);
|
||||
};
|
||||
}
|
||||
|
||||
var mouseHighlightEntities = new MouseHighlightEntities();
|
||||
dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities);
|
||||
|
||||
var handleMessage = function(channel, message, sender) {
|
||||
var data;
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
if (channel === 'Hifi-Object-Manipulation') {
|
||||
try {
|
||||
data = JSON.parse(message);
|
||||
if (data.action === 'grab') {
|
||||
var grabbedEntity = data.grabbedEntity;
|
||||
mouseHighlightEntities.setGrabbedEntity(grabbedEntity);
|
||||
} else if (data.action === 'release') {
|
||||
mouseHighlightEntities.setGrabbedEntity(null);
|
||||
}
|
||||
} catch (e) {
|
||||
print("Warning: mouseHighlightEntities -- error parsing Hifi-Object-Manipulation: " + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function cleanup() {
|
||||
dispatcherUtils.disableDispatcherModule("MouseHighlightEntities");
|
||||
}
|
||||
Messages.subscribe('Hifi-Object-Manipulation');
|
||||
Messages.messageReceived.connect(handleMessage);
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
})();
|
|
@ -24,7 +24,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
this.hand = hand;
|
||||
this.targetEntityID = null;
|
||||
this.actionID = null; // action this script created...
|
||||
this.hapticTargetID = null;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
500,
|
||||
|
@ -115,13 +114,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args);
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
var message = {
|
||||
hand: this.hand,
|
||||
entityID: this.targetEntityID
|
||||
};
|
||||
|
||||
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||
};
|
||||
|
||||
// this is for when the action is going to time-out
|
||||
|
@ -171,10 +163,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
break;
|
||||
}
|
||||
if (entityIsGrabbable(props) || entityIsCloneable(props)) {
|
||||
if (props.id !== this.hapticTargetID) {
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
this.hapticTargetID = props.id;
|
||||
}
|
||||
if (!entityIsCloneable(props)) {
|
||||
// if we've attempted to grab a non-cloneable child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, props);
|
||||
|
@ -206,7 +194,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
return makeRunningValues(true, [this.targetEntityID], []);
|
||||
}
|
||||
} else {
|
||||
this.hapticTargetID = null;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
};
|
||||
|
@ -216,7 +203,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE &&
|
||||
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
|
||||
this.endNearGrabAction();
|
||||
this.hapticTargetID = null;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS,
|
||||
findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH,
|
||||
HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME,
|
||||
TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity,
|
||||
TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, NEAR_GRAB_DISTANCE,
|
||||
distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES
|
||||
*/
|
||||
|
||||
|
@ -24,15 +24,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
// XXX this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true;
|
||||
// XXX this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC;
|
||||
|
||||
// this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378
|
||||
var GRAB_POINT_SPHERE_OFFSET = { x: 0.04, y: 0.13, z: 0.039 }; // x = upward, y = forward, z = lateral
|
||||
|
||||
function getGrabOffset(handController) {
|
||||
var offset = getGrabPointSphereOffset(handController, true);
|
||||
offset.y = -offset.y;
|
||||
return Vec3.multiply(MyAvatar.sensorToWorldScale, offset);
|
||||
}
|
||||
|
||||
function NearParentingGrabEntity(hand) {
|
||||
this.hand = hand;
|
||||
this.targetEntityID = null;
|
||||
|
@ -40,12 +31,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.previousParentID = {};
|
||||
this.previousParentJointIndex = {};
|
||||
this.previouslyUnhooked = {};
|
||||
this.hapticTargetID = null;
|
||||
this.lastUnequipCheckTime = 0;
|
||||
this.autoUnequipCounter = 0;
|
||||
this.lastUnexpectedChildrenCheckTime = 0;
|
||||
this.robbed = false;
|
||||
this.highlightedEntity = null;
|
||||
this.cloneAllowed = true;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
|
@ -95,14 +84,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.startNearParentingGrabEntity = function (controllerData, targetProps) {
|
||||
var grabData = getGrabbableData(targetProps);
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
this.highlightedEntity = null;
|
||||
var message = {
|
||||
hand: this.hand,
|
||||
entityID: this.targetEntityID
|
||||
};
|
||||
|
||||
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||
var handJointIndex;
|
||||
if (grabData.grabFollowsController) {
|
||||
handJointIndex = getControllerJointIndex(this.hand);
|
||||
|
@ -146,7 +128,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.endNearParentingGrabEntity = function (controllerData) {
|
||||
this.hapticTargetID = null;
|
||||
var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID];
|
||||
if (this.thisHandIsParent(props) && !this.robbed) {
|
||||
Entities.editEntity(this.targetEntityID, {
|
||||
|
@ -164,8 +145,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
this.highlightedEntity = null;
|
||||
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
this.robbed = false;
|
||||
|
@ -178,8 +158,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.lastUnequipCheckTime = now;
|
||||
if (props.parentID === MyAvatar.SELF_ID) {
|
||||
var tearAwayDistance = TEAR_AWAY_DISTANCE * MyAvatar.sensorToWorldScale;
|
||||
var controllerIndex = (this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand);
|
||||
var controllerGrabOffset = getGrabOffset(controllerIndex);
|
||||
var controllerIndex =
|
||||
this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||
var controllerGrabOffset = getGrabPointSphereOffset(controllerIndex, true);
|
||||
controllerGrabOffset = Vec3.multiply(-MyAvatar.sensorToWorldScale, controllerGrabOffset);
|
||||
var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props, controllerGrabOffset);
|
||||
if (distance > tearAwayDistance) {
|
||||
this.autoUnequipCounter++;
|
||||
|
@ -242,21 +224,18 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
// nearbyEntityProperties is already sorted by length from controller
|
||||
var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand];
|
||||
var sensorScaleFactor = MyAvatar.sensorToWorldScale;
|
||||
var nearGrabDistance = NEAR_GRAB_DISTANCE * sensorScaleFactor;
|
||||
var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor;
|
||||
for (var i = 0; i < nearbyEntityProperties.length; i++) {
|
||||
var props = nearbyEntityProperties[i];
|
||||
var handPosition = controllerData.controllerLocations[this.hand].position;
|
||||
var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props);
|
||||
var distance = Vec3.distance(handPosition, props.position);
|
||||
if ((dist > TEAR_AWAY_DISTANCE) ||
|
||||
(distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) {
|
||||
var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position.
|
||||
var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props);
|
||||
var distance = Vec3.distance(grabPosition, props.position);
|
||||
if ((dist > nearGrabDistance) ||
|
||||
(distance > nearGrabRadius)) { // Only smallish entities can be near grabbed.
|
||||
continue;
|
||||
}
|
||||
if (entityIsGrabbable(props) || entityIsCloneable(props)) {
|
||||
// give haptic feedback
|
||||
if (props.id !== this.hapticTargetID) {
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
this.hapticTargetID = props.id;
|
||||
}
|
||||
if (!entityIsCloneable(props)) {
|
||||
// if we've attempted to grab a non-cloneable child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, props);
|
||||
|
@ -290,16 +269,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it
|
||||
} else {
|
||||
this.targetEntityID = targetProps.id;
|
||||
this.highlightedEntity = this.targetEntityID;
|
||||
highlightTargetEntity(this.targetEntityID);
|
||||
return makeRunningValues(true, [this.targetEntityID], []);
|
||||
}
|
||||
} else {
|
||||
if (this.highlightedEntity) {
|
||||
unhighlightTargetEntity(this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
}
|
||||
this.hapticTargetID = null;
|
||||
this.robbed = false;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
@ -316,11 +288,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID];
|
||||
if (!props) {
|
||||
// entity was deleted
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
this.highlightedEntity = null;
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
this.hapticTargetID = null;
|
||||
this.robbed = false;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
@ -335,12 +304,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args);
|
||||
} else {
|
||||
// still searching / highlighting
|
||||
// still searching
|
||||
var readiness = this.isReady(controllerData);
|
||||
if (!readiness.active) {
|
||||
this.robbed = false;
|
||||
unhighlightTargetEntity(this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
return readiness;
|
||||
}
|
||||
if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
/* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData,
|
||||
Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS, unhighlightTargetEntity
|
||||
Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -55,7 +55,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
this.startNearTrigger = function (controllerData) {
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args);
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
};
|
||||
|
||||
this.continueNearTrigger = function (controllerData) {
|
||||
|
|
|
@ -35,9 +35,7 @@ var CONTOLLER_SCRIPTS = [
|
|||
"controllerModules/hudOverlayPointer.js",
|
||||
"controllerModules/mouseHMD.js",
|
||||
"controllerModules/scaleEntity.js",
|
||||
"controllerModules/highlightNearbyEntities.js",
|
||||
"controllerModules/nearGrabHyperLinkEntity.js",
|
||||
"controllerModules/mouseHighlightEntities.js",
|
||||
"controllerModules/nearTabletHighlight.js"
|
||||
];
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue