mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 18:47:28 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into feat/avatarTools/avatarDoctor
This commit is contained in:
commit
74ce98a075
393 changed files with 5850 additions and 10313 deletions
|
@ -81,6 +81,25 @@ if (ANDROID)
|
|||
set(GLES_OPTION ON)
|
||||
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
||||
add_definitions(-DHIFI_ANDROID_APP=\"${HIFI_ANDROID_APP}\")
|
||||
if (
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questInterface") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questFramePlayer") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "framePlayer")
|
||||
)
|
||||
# We know the quest hardware has this extension, so we can force the use of instanced stereo
|
||||
add_definitions(-DHAVE_EXT_clip_cull_distance)
|
||||
# We can also use multiview stereo techniques
|
||||
add_definitions(-DHAVE_OVR_multiview2)
|
||||
add_definitions(-DHAVE_OVR_multiview)
|
||||
# We can also use our own foveated textures
|
||||
add_definitions(-DHAVE_QCOM_texture_foveated)
|
||||
|
||||
# if set, the application itself or some library it depends on MUST implement
|
||||
# `DisplayPluginList getDisplayPlugins()` and `InputPluginList getInputPlugins()`
|
||||
add_definitions(-DCUSTOM_INPUT_PLUGINS)
|
||||
add_definitions(-DCUSTOM_DISPLAY_PLUGINS)
|
||||
set(PLATFORM_PLUGIN_LIBRARIES oculusMobile oculusMobilePlugin)
|
||||
endif()
|
||||
else ()
|
||||
set(PLATFORM_QT_COMPONENTS WebEngine Xml)
|
||||
endif ()
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
import com.android.builder.core.BuilderConstants
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile project.hasProperty("HIFI_ANDROID_KEYSTORE") ? file(HIFI_ANDROID_KEYSTORE) : null
|
||||
storePassword project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") ? HIFI_ANDROID_KEYSTORE_PASSWORD : ''
|
||||
keyAlias project.hasProperty("HIFI_ANDROID_KEY_ALIAS") ? HIFI_ANDROID_KEY_ALIAS : ''
|
||||
keyPassword project.hasProperty("HIFI_ANDROID_KEY_PASSWORD") ? HIFI_ANDROID_KEY_PASSWORD : ''
|
||||
}
|
||||
}
|
||||
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "io.highfidelity.frameplayer"
|
||||
|
@ -32,19 +25,17 @@ android {
|
|||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
externalNativeBuild.cmake.path '../../../CMakeLists.txt'
|
||||
|
||||
variantFilter { variant ->
|
||||
def build = variant.buildType.name
|
||||
if (build == BuilderConstants.RELEASE) {
|
||||
variant.setIgnore(true)
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild.cmake.path '../../../CMakeLists.txt'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: '../../libraries/qt/libs')
|
||||
//implementation project(':oculus')
|
||||
implementation project(':qt')
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -54,6 +55,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
public static final String DOMAIN_URL = "url";
|
||||
public static final String EXTRA_GOTO_USERNAME = "gotousername";
|
||||
private static final String TAG = "Interface";
|
||||
public static final String EXTRA_ARGS = "args";
|
||||
private static final int WEB_DRAWER_RIGHT_MARGIN = 262;
|
||||
private static final int WEB_DRAWER_BOTTOM_MARGIN = 150;
|
||||
private static final int NORMAL_DPI = 160;
|
||||
|
@ -78,6 +80,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
|
||||
private boolean nativeEnterBackgroundCallEnqueued = false;
|
||||
private SlidingDrawer mWebSlidingDrawer;
|
||||
private boolean mStartInDomain;
|
||||
// private GvrApi gvrApi;
|
||||
// Opaque native pointer to the Application C++ object.
|
||||
// This object is owned by the InterfaceActivity instance and passed to the native methods.
|
||||
|
@ -93,8 +96,14 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.isLoading = true;
|
||||
Intent intent = getIntent();
|
||||
if (intent.hasExtra(DOMAIN_URL) && !intent.getStringExtra(DOMAIN_URL).isEmpty()) {
|
||||
if (intent.hasExtra(DOMAIN_URL) && !TextUtils.isEmpty(intent.getStringExtra(DOMAIN_URL))) {
|
||||
intent.putExtra("applicationArguments", "--url " + intent.getStringExtra(DOMAIN_URL));
|
||||
} else if (intent.hasExtra(EXTRA_ARGS)) {
|
||||
String args = intent.getStringExtra(EXTRA_ARGS);
|
||||
if (!TextUtils.isEmpty(args)) {
|
||||
mStartInDomain = true;
|
||||
intent.putExtra("applicationArguments", args);
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
@ -125,7 +134,10 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
getActionBar().hide();
|
||||
}
|
||||
});
|
||||
startActivity(new Intent(this, SplashActivity.class));
|
||||
Intent splashIntent = new Intent(this, SplashActivity.class);
|
||||
splashIntent.putExtra(SplashActivity.EXTRA_START_IN_DOMAIN, mStartInDomain);
|
||||
startActivity(splashIntent);
|
||||
|
||||
mVibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
|
||||
headsetStateReceiver = new HeadsetStateReceiver();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.pm.PackageManager;
|
|||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -27,9 +28,14 @@ public class PermissionChecker extends Activity {
|
|||
private static final boolean CHOOSE_AVATAR_ON_STARTUP = false;
|
||||
private static final String TAG = "Interface";
|
||||
|
||||
private static final String EXTRA_ARGS = "args";
|
||||
private String mArgs;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mArgs =(getIntent().getStringExtra(EXTRA_ARGS));
|
||||
|
||||
Intent myIntent = new Intent(this, BreakpadUploaderService.class);
|
||||
startService(myIntent);
|
||||
if (CHOOSE_AVATAR_ON_STARTUP) {
|
||||
|
@ -76,6 +82,11 @@ public class PermissionChecker extends Activity {
|
|||
|
||||
private void launchActivityWithPermissions(){
|
||||
Intent i = new Intent(this, InterfaceActivity.class);
|
||||
|
||||
if (!TextUtils.isEmpty(mArgs)) {
|
||||
i.putExtra(EXTRA_ARGS, mArgs);
|
||||
}
|
||||
|
||||
startActivity(i);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ import android.view.View;
|
|||
|
||||
public class SplashActivity extends Activity {
|
||||
|
||||
public static final String EXTRA_START_IN_DOMAIN = "start-in-domain";
|
||||
private boolean mStartInDomain;
|
||||
|
||||
private native void registerLoadCompleteListener();
|
||||
|
||||
@Override
|
||||
|
@ -36,13 +39,27 @@ public class SplashActivity extends Activity {
|
|||
}
|
||||
|
||||
public void onAppLoadedComplete() {
|
||||
if (HifiUtils.getInstance().isUserLoggedIn()) {
|
||||
startActivity(new Intent(this, MainActivity.class));
|
||||
} else {
|
||||
Intent menuIntent = new Intent(this, LoginMenuActivity.class);
|
||||
menuIntent.putExtra(LoginMenuActivity.EXTRA_FINISH_ON_BACK, true);
|
||||
startActivity(menuIntent);
|
||||
if (!mStartInDomain) {
|
||||
if (HifiUtils.getInstance().isUserLoggedIn()) {
|
||||
startActivity(new Intent(this, MainActivity.class));
|
||||
} else {
|
||||
Intent menuIntent = new Intent(this, LoginMenuActivity.class);
|
||||
menuIntent.putExtra(LoginMenuActivity.EXTRA_FINISH_ON_BACK, true);
|
||||
startActivity(menuIntent);
|
||||
}
|
||||
}
|
||||
SplashActivity.this.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(EXTRA_START_IN_DOMAIN, mStartInDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mStartInDomain = savedInstanceState.getBoolean(EXTRA_START_IN_DOMAIN, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
import com.android.builder.core.BuilderConstants
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile project.hasProperty("HIFI_ANDROID_KEYSTORE") ? file(HIFI_ANDROID_KEYSTORE) : null
|
||||
storePassword project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") ? HIFI_ANDROID_KEYSTORE_PASSWORD : ''
|
||||
keyAlias project.hasProperty("HIFI_ANDROID_KEY_ALIAS") ? HIFI_ANDROID_KEY_ALIAS : ''
|
||||
keyPassword project.hasProperty("HIFI_ANDROID_KEY_PASSWORD") ? HIFI_ANDROID_KEY_PASSWORD : ''
|
||||
}
|
||||
}
|
||||
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "io.highfidelity.frameplayer"
|
||||
|
@ -33,15 +26,14 @@ android {
|
|||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
externalNativeBuild.cmake.path '../../../CMakeLists.txt'
|
||||
|
||||
variantFilter { variant ->
|
||||
def build = variant.buildType.name
|
||||
if (build == BuilderConstants.RELEASE) {
|
||||
variant.setIgnore(true)
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild.cmake.path '../../../CMakeLists.txt'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -650,6 +650,8 @@ public class QtActivity extends Activity {
|
|||
if (!keepInterfaceRunning) {
|
||||
QtApplication.invokeDelegate();
|
||||
}
|
||||
QtNative.terminateQt();
|
||||
QtNative.setActivity(null,null);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -14,7 +14,7 @@ link_hifi_libraries(
|
|||
audio avatars octree gpu graphics shaders fbx hfm entities
|
||||
networking animation recording shared script-engine embedded-webserver
|
||||
controllers physics plugins midi image
|
||||
model-networking ktx shaders
|
||||
material-networking model-networking ktx shaders
|
||||
)
|
||||
|
||||
add_dependencies(${TARGET_NAME} oven)
|
||||
|
|
|
@ -111,7 +111,7 @@ bool EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
|
|||
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||
newView.lodScaleFactor = powf(2.0f, lodLevelOffset);
|
||||
|
||||
startNewTraversal(newView, root);
|
||||
startNewTraversal(newView, root, isFullScene);
|
||||
|
||||
// When the viewFrustum changed the sort order may be incorrect, so we re-sort
|
||||
// and also use the opportunity to cull anything no longer in view
|
||||
|
@ -220,9 +220,10 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil
|
|||
return hasNewChild || hasNewDescendants;
|
||||
}
|
||||
|
||||
void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) {
|
||||
void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root,
|
||||
bool forceFirstPass) {
|
||||
|
||||
DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root);
|
||||
DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, forceFirstPass);
|
||||
// there are three types of traversal:
|
||||
//
|
||||
// (1) FirstTime = at login --> find everything in view
|
||||
|
|
|
@ -42,7 +42,7 @@ private:
|
|||
bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
|
||||
bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
|
||||
|
||||
void startNewTraversal(const DiffTraversal::View& viewFrustum, EntityTreeElementPointer root);
|
||||
void startNewTraversal(const DiffTraversal::View& viewFrustum, EntityTreeElementPointer root, bool forceFirstPass = false);
|
||||
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override;
|
||||
|
||||
void preDistributionProcessing() override;
|
||||
|
|
|
@ -324,12 +324,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
if (isFullScene) {
|
||||
// we're forcing a full scene, clear the force in OctreeQueryNode so we don't force it next time again
|
||||
nodeData->setShouldForceFullScene(false);
|
||||
} else {
|
||||
// we aren't forcing a full scene, check if something else suggests we should
|
||||
isFullScene = nodeData->haveJSONParametersChanged() ||
|
||||
(nodeData->hasConicalViews() &&
|
||||
(nodeData->getViewFrustumJustStoppedChanging() ||
|
||||
nodeData->hasLodChanged()));
|
||||
}
|
||||
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
|
|
|
@ -300,6 +300,8 @@ Var substringResult
|
|||
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags
|
||||
;Checking lowest bit:
|
||||
IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED}
|
||||
!insertmacro LoadVar ${SecName}_was_installed
|
||||
IntOp $AR_SecFlags $AR_SecFlags | $R0
|
||||
IntCmp $AR_SecFlags 1 "leave_${SecName}"
|
||||
;Section is not selected:
|
||||
|
||||
|
@ -478,18 +480,6 @@ Var GAClientID
|
|||
;--------------------------------
|
||||
; Installation types
|
||||
|
||||
Section "-Previous Install Cleanup"
|
||||
; Remove the resources folder so we don't end up including removed QML files
|
||||
RMDir /r "$INSTDIR\resources"
|
||||
|
||||
; delete old assignment-client and domain-server so they're no longer present
|
||||
; in client only installs.
|
||||
Delete "$INSTDIR\@DS_EXEC_NAME@"
|
||||
Delete "$INSTDIR\@AC_EXEC_NAME@"
|
||||
|
||||
; delete interface so it's not there for server-only installs
|
||||
Delete "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
||||
SectionEnd
|
||||
|
||||
@CPACK_NSIS_INSTALLATION_TYPES@
|
||||
|
||||
|
|
|
@ -205,13 +205,16 @@ endif()
|
|||
# link required hifi libraries
|
||||
link_hifi_libraries(
|
||||
shared workload task octree ktx gpu gl procedural graphics graphics-scripting render
|
||||
pointers
|
||||
recording hfm fbx networking model-networking model-baker entities avatars trackers
|
||||
pointers recording hfm fbx networking material-networking
|
||||
model-networking model-baker entities avatars trackers
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer avatars-renderer ui qml auto-updater midi
|
||||
controllers plugins image trackers
|
||||
ui-plugins display-plugins input-plugins
|
||||
# Platform specific GL libraries
|
||||
${PLATFORM_GL_BACKEND}
|
||||
# Plaform specific input & display plugin libraries
|
||||
${PLATFORM_PLUGIN_LIBRARIES}
|
||||
shaders
|
||||
)
|
||||
|
||||
|
@ -330,7 +333,11 @@ if (APPLE)
|
|||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/fonts"
|
||||
"${RESOURCES_DEV_DIR}/fonts"
|
||||
# add redirect json to macOS builds.
|
||||
#copy serverless for android
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/serverless"
|
||||
"${RESOURCES_DEV_DIR}/serverless"
|
||||
# add redirect json to macOS builds.
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||
"${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json"
|
||||
"${RESOURCES_DEV_DIR}/serverless/redirect.json"
|
||||
|
|
BIN
interface/resources/images/whitePixel.png
Normal file
BIN
interface/resources/images/whitePixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 155 B |
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Web3DOverlay.qml
|
||||
// Web3DSurface.qml
|
||||
//
|
||||
// Created by Gabriel Calero & Cristian Duarte on Jun 22, 2018
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
|
|
|
@ -1,275 +0,0 @@
|
|||
import QtQuick 2.5
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.5
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import "qrc:////qml//windows"
|
||||
|
||||
ScrollingWindow {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
//HifiStyles.HifiConstants { id: hifistyles }
|
||||
title: "Browser"
|
||||
resizable: true
|
||||
destroyOnHidden: true
|
||||
width: 800
|
||||
height: 600
|
||||
property variant permissionsBar: {'securityOrigin':'none','feature':'none'}
|
||||
property alias url: webview.url
|
||||
property alias webView: webview
|
||||
|
||||
signal loadingChanged(int status)
|
||||
|
||||
x: 100
|
||||
y: 100
|
||||
|
||||
Component.onCompleted: {
|
||||
focus = true
|
||||
shown = true
|
||||
addressBar.text = webview.url
|
||||
}
|
||||
|
||||
function setProfile(profile) {
|
||||
webview.profile = profile;
|
||||
}
|
||||
|
||||
function showPermissionsBar(){
|
||||
permissionsContainer.visible=true;
|
||||
}
|
||||
|
||||
function hidePermissionsBar(){
|
||||
permissionsContainer.visible=false;
|
||||
}
|
||||
|
||||
function allowPermissions(){
|
||||
webview.grantFeaturePermission(permissionsBar.securityOrigin, permissionsBar.feature, true);
|
||||
hidePermissionsBar();
|
||||
}
|
||||
|
||||
function setAutoAdd(auto) {
|
||||
desktop.setAutoAdd(auto);
|
||||
}
|
||||
|
||||
Item {
|
||||
id:item
|
||||
width: pane.contentWidth
|
||||
implicitHeight: pane.scrollHeight
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
spacing: 4
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
HiFiGlyphs {
|
||||
id: back;
|
||||
enabled: webview.canGoBack;
|
||||
text: hifi.glyphs.backward
|
||||
color: enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
size: 48
|
||||
MouseArea { anchors.fill: parent; onClicked: webview.goBack() }
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: forward;
|
||||
enabled: webview.canGoForward;
|
||||
text: hifi.glyphs.forward
|
||||
color: enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
size: 48
|
||||
MouseArea { anchors.fill: parent; onClicked: webview.goForward() }
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: reload;
|
||||
enabled: webview.canGoForward;
|
||||
text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload
|
||||
color: enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
size: 48
|
||||
MouseArea { anchors.fill: parent; onClicked: webview.goForward() }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: border
|
||||
height: 48
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.left: buttons.right
|
||||
anchors.leftMargin: 8
|
||||
|
||||
Item {
|
||||
id: barIcon
|
||||
width: parent.height
|
||||
height: parent.height
|
||||
Image {
|
||||
source: webview.icon;
|
||||
x: (parent.height - height) / 2
|
||||
y: (parent.width - width) / 2
|
||||
sourceSize: Qt.size(width, height);
|
||||
verticalAlignment: Image.AlignVCenter;
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: addressBar
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.left: barIcon.right
|
||||
anchors.leftMargin: 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
focus: true
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
placeholderText: "Enter URL"
|
||||
Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i")
|
||||
Keys.onPressed: {
|
||||
switch(event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
if (text.indexOf("http") != 0) {
|
||||
text = "http://" + text;
|
||||
}
|
||||
root.hidePermissionsBar();
|
||||
root.keyboardRaised = false;
|
||||
webview.url = text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id:permissionsContainer
|
||||
visible:false
|
||||
color: "#000000"
|
||||
width: parent.width
|
||||
anchors.top: buttons.bottom
|
||||
height:40
|
||||
z:100
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: "black" }
|
||||
GradientStop { position: 1.0; color: "grey" }
|
||||
}
|
||||
|
||||
RalewayLight {
|
||||
id: permissionsInfo
|
||||
anchors.right:permissionsRow.left
|
||||
anchors.rightMargin: 32
|
||||
anchors.topMargin:8
|
||||
anchors.top:parent.top
|
||||
text: "This site wants to use your microphone/camera"
|
||||
size: 18
|
||||
color: hifi.colors.white
|
||||
}
|
||||
|
||||
Row {
|
||||
id: permissionsRow
|
||||
spacing: 4
|
||||
anchors.top:parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.right: parent.right
|
||||
visible: true
|
||||
z:101
|
||||
|
||||
Button {
|
||||
id:allow
|
||||
text: "Allow"
|
||||
color: hifi.buttons.blue
|
||||
colorScheme: root.colorScheme
|
||||
width: 120
|
||||
enabled: true
|
||||
onClicked: root.allowPermissions();
|
||||
z:101
|
||||
}
|
||||
|
||||
Button {
|
||||
id:block
|
||||
text: "Block"
|
||||
color: hifi.buttons.red
|
||||
colorScheme: root.colorScheme
|
||||
width: 120
|
||||
enabled: true
|
||||
onClicked: root.hidePermissionsBar();
|
||||
z:101
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebView {
|
||||
id: webview
|
||||
url: "https://highfidelity.com/"
|
||||
profile: FileTypeProfile;
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// Detect when may want to raise and lower keyboard.
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ]
|
||||
|
||||
anchors.top: buttons.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
if (feature == 2) { // QWebEnginePage::MediaAudioCapture
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
} else {
|
||||
permissionsBar.securityOrigin = securityOrigin;
|
||||
permissionsBar.feature = feature;
|
||||
root.showPermissionsBar();
|
||||
}
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
if (loadRequest.status === WebEngineView.LoadSucceededStatus) {
|
||||
addressBar.text = loadRequest.url
|
||||
}
|
||||
root.loadingChanged(loadRequest.status);
|
||||
}
|
||||
|
||||
onWindowCloseRequested: {
|
||||
root.destroy();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
desktop.initWebviewProfileHandlers(webview.profile);
|
||||
}
|
||||
}
|
||||
|
||||
} // item
|
||||
|
||||
|
||||
Keys.onPressed: {
|
||||
switch(event.key) {
|
||||
case Qt.Key_L:
|
||||
if (event.modifiers == Qt.ControlModifier) {
|
||||
event.accepted = true
|
||||
addressBar.selectAll()
|
||||
addressBar.forceActiveFocus()
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // dialog
|
58
interface/resources/qml/+webengine/BrowserWebView.qml
Normal file
58
interface/resources/qml/+webengine/BrowserWebView.qml
Normal file
|
@ -0,0 +1,58 @@
|
|||
import QtQuick 2.5
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.5
|
||||
|
||||
import controlsUit 1.0
|
||||
|
||||
WebView {
|
||||
id: webview
|
||||
url: "https://highfidelity.com/"
|
||||
profile: FileTypeProfile;
|
||||
|
||||
property var parentRoot: null
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// Detect when may want to raise and lower keyboard.
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ]
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
if (feature == 2) { // QWebEnginePage::MediaAudioCapture
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
} else {
|
||||
permissionsBar.securityOrigin = securityOrigin;
|
||||
permissionsBar.feature = feature;
|
||||
parentRoot.showPermissionsBar();
|
||||
}
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
if (loadRequest.status === WebEngineView.LoadSucceededStatus) {
|
||||
addressBar.text = loadRequest.url
|
||||
}
|
||||
parentRoot.loadingChanged(loadRequest.status);
|
||||
}
|
||||
|
||||
onWindowCloseRequested: {
|
||||
parentRoot.destroy();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
desktop.initWebviewProfileHandlers(webview.profile);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// InfoView.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 27 Apr 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
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import Hifi 1.0 as Hifi
|
||||
|
||||
import controlsUit 1.0
|
||||
import "qrc:////qml//windows" as Windows
|
||||
|
||||
Windows.ScrollingWindow {
|
||||
id: root
|
||||
width: 800
|
||||
height: 800
|
||||
resizable: true
|
||||
|
||||
Hifi.InfoView {
|
||||
id: infoView
|
||||
width: pane.contentWidth
|
||||
implicitHeight: pane.scrollHeight
|
||||
|
||||
WebView {
|
||||
id: webview
|
||||
objectName: "WebView"
|
||||
anchors.fill: parent
|
||||
url: infoView.url
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
centerWindow(root);
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
centerWindow(root);
|
||||
}
|
||||
}
|
||||
|
||||
function centerWindow() {
|
||||
desktop.centerOnVisible(root);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
//
|
||||
// QmlWebWindow.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 17 Dec 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
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
|
||||
import "qrc:////qml//windows" as Windows
|
||||
import controlsUit 1.0 as Controls
|
||||
import stylesUit 1.0
|
||||
|
||||
Windows.ScrollingWindow {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
title: "WebWindow"
|
||||
resizable: true
|
||||
shown: false
|
||||
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
||||
destroyOnCloseButton: false
|
||||
property alias source: webview.url
|
||||
property alias scriptUrl: webview.userScriptUrl
|
||||
|
||||
// This is for JS/QML communication, which is unused in a WebWindow,
|
||||
// but not having this here results in spurious warnings about a
|
||||
// missing signal
|
||||
signal sendToScript(var message);
|
||||
|
||||
signal moved(vector2d position);
|
||||
signal resized(size size);
|
||||
|
||||
function notifyMoved() {
|
||||
moved(Qt.vector2d(x, y));
|
||||
}
|
||||
|
||||
function notifyResized() {
|
||||
resized(Qt.size(width, height));
|
||||
}
|
||||
|
||||
onXChanged: notifyMoved();
|
||||
onYChanged: notifyMoved();
|
||||
|
||||
onWidthChanged: notifyResized();
|
||||
onHeightChanged: notifyResized();
|
||||
|
||||
onShownChanged: {
|
||||
keyboardEnabled = HMD.active;
|
||||
}
|
||||
|
||||
Item {
|
||||
width: pane.contentWidth
|
||||
implicitHeight: pane.scrollHeight
|
||||
|
||||
Controls.WebView {
|
||||
id: webview
|
||||
url: "about:blank"
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// Detect when may want to raise and lower keyboard.
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// User script.
|
||||
WebEngineScript {
|
||||
id: userScript
|
||||
sourceUrl: webview.userScriptUrl
|
||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||
|
||||
function onWebEventReceived(event) {
|
||||
if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||
ApplicationInterface.addAssetToWorldFromURL(event.slice(18));
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
eventBridge.webEventReceived.connect(onWebEventReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
interface/resources/qml/+webengine/QmlWebWindowView.qml
Normal file
53
interface/resources/qml/+webengine/QmlWebWindowView.qml
Normal file
|
@ -0,0 +1,53 @@
|
|||
import QtQuick 2.5
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
|
||||
import controlsUit 1.0 as Controls
|
||||
import stylesUit 1.0
|
||||
Controls.WebView {
|
||||
id: webview
|
||||
url: "about:blank"
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// Detect when may want to raise and lower keyboard.
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// User script.
|
||||
WebEngineScript {
|
||||
id: userScript
|
||||
sourceUrl: webview.userScriptUrl
|
||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||
|
||||
function onWebEventReceived(event) {
|
||||
if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||
ApplicationInterface.addAssetToWorldFromURL(event.slice(18));
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
eventBridge.webEventReceived.connect(onWebEventReceived);
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
import QtQuick 2.5
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
|
||||
import "windows"
|
||||
import "."
|
||||
|
||||
ScrollingWindow {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
//HifiStyles.HifiConstants { id: hifistyles }
|
||||
|
||||
title: "Browser"
|
||||
resizable: true
|
||||
destroyOnHidden: true
|
||||
|
@ -30,6 +29,7 @@ ScrollingWindow {
|
|||
}
|
||||
|
||||
function setProfile(profile) {
|
||||
webview.profile = profile;
|
||||
}
|
||||
|
||||
function showPermissionsBar(){
|
||||
|
@ -41,6 +41,7 @@ ScrollingWindow {
|
|||
}
|
||||
|
||||
function allowPermissions(){
|
||||
webview.grantFeaturePermission(permissionsBar.securityOrigin, permissionsBar.feature, true);
|
||||
hidePermissionsBar();
|
||||
}
|
||||
|
||||
|
@ -198,10 +199,15 @@ ScrollingWindow {
|
|||
}
|
||||
}
|
||||
|
||||
ProxyWebView {
|
||||
BrowserWebView {
|
||||
id: webview
|
||||
anchors.centerIn: parent
|
||||
url: "https://highfidelity.com/"
|
||||
parentRoot: root
|
||||
|
||||
anchors.top: buttons.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
} // item
|
||||
|
|
8
interface/resources/qml/BrowserWebView.qml
Normal file
8
interface/resources/qml/BrowserWebView.qml
Normal file
|
@ -0,0 +1,8 @@
|
|||
import QtQuick 2.5
|
||||
import controlsUit 1.0
|
||||
|
||||
ProxyWebView {
|
||||
property var parentRoot: null
|
||||
|
||||
function grantFeaturePermission(origin, feature) {}
|
||||
}
|
|
@ -24,7 +24,7 @@ Windows.ScrollingWindow {
|
|||
width: pane.contentWidth
|
||||
implicitHeight: pane.scrollHeight
|
||||
|
||||
ProxyWebView {
|
||||
BaseWebView {
|
||||
id: webview
|
||||
objectName: "WebView"
|
||||
anchors.fill: parent
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import QtQuick 2.5
|
||||
|
||||
import "windows" as Windows
|
||||
import "."
|
||||
import controlsUit 1.0 as Controls
|
||||
import stylesUit 1.0
|
||||
|
||||
|
@ -55,12 +56,8 @@ Windows.ScrollingWindow {
|
|||
width: pane.contentWidth
|
||||
implicitHeight: pane.scrollHeight
|
||||
|
||||
Controls.WebView {
|
||||
QmlWebWindowView {
|
||||
id: webview
|
||||
url: "about:blank"
|
||||
property string userScriptUrl: ""
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
5
interface/resources/qml/QmlWebWindowView.qml
Normal file
5
interface/resources/qml/QmlWebWindowView.qml
Normal file
|
@ -0,0 +1,5 @@
|
|||
import QtQuick 2.5
|
||||
import controlsUit 1.0
|
||||
|
||||
BaseWebView {
|
||||
}
|
|
@ -129,11 +129,11 @@ Item {
|
|||
}
|
||||
StatText {
|
||||
visible: root.expanded
|
||||
text: "Intersection calls: Entities/Overlays/Avatars/HUD\n " +
|
||||
"Styluses:\t" + root.stylusPicksUpdated.x + "/" + root.stylusPicksUpdated.y + "/" + root.stylusPicksUpdated.z + "/" + root.stylusPicksUpdated.w + "\n " +
|
||||
"Rays:\t" + root.rayPicksUpdated.x + "/" + root.rayPicksUpdated.y + "/" + root.rayPicksUpdated.z + "/" + root.rayPicksUpdated.w + "\n " +
|
||||
"Parabolas:\t" + root.parabolaPicksUpdated.x + "/" + root.parabolaPicksUpdated.y + "/" + root.parabolaPicksUpdated.z + "/" + root.parabolaPicksUpdated.w + "\n " +
|
||||
"Colliders:\t" + root.collisionPicksUpdated.x + "/" + root.collisionPicksUpdated.y + "/" + root.collisionPicksUpdated.z + "/" + root.collisionPicksUpdated.w
|
||||
text: "Intersection calls: Entities/Avatars/HUD\n " +
|
||||
"Styluses:\t" + root.stylusPicksUpdated.x + "/" + root.stylusPicksUpdated.y + "/" + root.stylusPicksUpdated.z + "\n " +
|
||||
"Rays:\t" + root.rayPicksUpdated.x + "/" + root.rayPicksUpdated.y + "/" + root.rayPicksUpdated.z + "\n " +
|
||||
"Parabolas:\t" + root.parabolaPicksUpdated.x + "/" + root.parabolaPicksUpdated.y + "/" + root.parabolaPicksUpdated.z + "\n " +
|
||||
"Colliders:\t" + root.collisionPicksUpdated.x + "/" + root.collisionPicksUpdated.y + "/" + root.collisionPicksUpdated.z
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Web3DOverlay.qml
|
||||
// Web3DSurface.qml
|
||||
//
|
||||
// Created by David Rowe on 16 Dec 2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
|
|
|
@ -18,6 +18,7 @@ Rectangle {
|
|||
|
||||
property bool safeLoading: false
|
||||
property bool loadingLatched: false
|
||||
property bool loading: false
|
||||
property var loadingRequest: null
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ Rectangle {
|
|||
property var activeTab: "nearbyTab";
|
||||
property bool currentlyEditingDisplayName: false
|
||||
property bool punctuationMode: false;
|
||||
property double loudSortTime: 0.0;
|
||||
readonly property double kLOUD_SORT_PERIOD_MS: 1000.0;
|
||||
|
||||
HifiConstants { id: hifi; }
|
||||
RootHttpRequest { id: http; }
|
||||
|
@ -1247,6 +1249,11 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (nearbyTable.sortIndicatorColumn == 0 && Date.now() - pal.loudSortTime >= pal.kLOUD_SORT_PERIOD_MS) {
|
||||
// Current sort by loudness so re-sort.
|
||||
sortModel();
|
||||
pal.loudSortTime = Date.now();
|
||||
}
|
||||
break;
|
||||
case 'clearLocalQMLData':
|
||||
ignored = {};
|
||||
|
|
|
@ -21,7 +21,7 @@ Rectangle {
|
|||
HifiControlsUit.Keyboard {
|
||||
id: keyboard
|
||||
z: 1000
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised && HMD.active
|
||||
numeric: parent.punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
|
|
@ -607,7 +607,7 @@ Rectangle {
|
|||
} else if (msg.method === "showTrashLightbox") {
|
||||
lightboxPopup.titleText = "Send \"" + msg.itemName + "\" to Trash";
|
||||
lightboxPopup.bodyText = "Sending this item to the Trash means you will no longer own this item " +
|
||||
"and it will be inaccessible to you from Purchases.\n\nThis action cannot be undone.";
|
||||
"and it will be inaccessible to you from Inventory.\n\nThis action cannot be undone.";
|
||||
lightboxPopup.button1text = "CANCEL";
|
||||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import QtQuick 2.0
|
||||
import QtWebEngine 1.5
|
||||
import "../../controls" as Controls
|
||||
|
||||
Controls.TabletWebView {
|
||||
profile: WebEngineProfile { httpUserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"}
|
||||
}
|
|
@ -2,7 +2,6 @@ import QtQuick 2.0
|
|||
import "../../controls" as Controls
|
||||
|
||||
Controls.TabletWebView {
|
||||
profile: WebEngineProfile { httpUserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
*
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {string} buildDate
|
||||
* @property {string} buildVersion
|
||||
* @property {string} qtVersion
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
#include <MessagesClient.h>
|
||||
#include <hfm/ModelFormatRegistry.h>
|
||||
#include <model-networking/ModelCacheScriptingInterface.h>
|
||||
#include <model-networking/TextureCacheScriptingInterface.h>
|
||||
#include <material-networking/TextureCacheScriptingInterface.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <NetworkingConstants.h>
|
||||
|
@ -152,8 +152,9 @@
|
|||
#include <trackers/EyeTracker.h>
|
||||
#include <avatars-renderer/ScriptAvatar.h>
|
||||
#include <RenderableEntityItem.h>
|
||||
#include <RenderableTextEntityItem.h>
|
||||
#include <RenderableWebEntityItem.h>
|
||||
#include <model-networking/MaterialCache.h>
|
||||
#include <material-networking/MaterialCache.h>
|
||||
#include "recording/ClipCache.h"
|
||||
|
||||
#include "AudioClient.h"
|
||||
|
@ -198,15 +199,12 @@
|
|||
#include "ui/AvatarInputs.h"
|
||||
#include "ui/DialogsManager.h"
|
||||
#include "ui/LoginDialog.h"
|
||||
#include "ui/overlays/Cube3DOverlay.h"
|
||||
#include "ui/overlays/Web3DOverlay.h"
|
||||
#include "ui/Snapshot.h"
|
||||
#include "ui/SnapshotAnimated.h"
|
||||
#include "ui/StandAloneJSConsole.h"
|
||||
#include "ui/Stats.h"
|
||||
#include "ui/AnimStats.h"
|
||||
#include "ui/UpdateDialog.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "ui/DomainConnectionModel.h"
|
||||
#include "ui/Keyboard.h"
|
||||
#include "Util.h"
|
||||
|
@ -351,6 +349,8 @@ static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
|
|||
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||
static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn";
|
||||
|
||||
static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt";
|
||||
#endif
|
||||
|
@ -603,8 +603,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
__android_log_write(ANDROID_LOG_FATAL,"Interface",local);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
qApp->getLogger()->addMessage(qPrintable(logMessage));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,7 +623,7 @@ public:
|
|||
case NestableType::Entity:
|
||||
return getEntityModelProvider(static_cast<EntityItemID>(uuid));
|
||||
case NestableType::Overlay:
|
||||
return getOverlayModelProvider(static_cast<OverlayID>(uuid));
|
||||
return nullptr;
|
||||
case NestableType::Avatar:
|
||||
return getAvatarModelProvider(uuid);
|
||||
}
|
||||
|
@ -646,22 +647,6 @@ private:
|
|||
return provider;
|
||||
}
|
||||
|
||||
scriptable::ModelProviderPointer getOverlayModelProvider(OverlayID overlayID) {
|
||||
scriptable::ModelProviderPointer provider;
|
||||
auto &overlays = qApp->getOverlays();
|
||||
if (auto overlay = overlays.getOverlay(overlayID)) {
|
||||
if (auto base3d = std::dynamic_pointer_cast<Base3DOverlay>(overlay)) {
|
||||
provider = std::dynamic_pointer_cast<scriptable::ModelProvider>(base3d);
|
||||
provider->modelProviderType = NestableType::Overlay;
|
||||
} else {
|
||||
qCWarning(interfaceapp) << "no renderer for overlay ID" << overlayID.toString();
|
||||
}
|
||||
} else {
|
||||
qCWarning(interfaceapp) << "overlay not found" << overlayID.toString();
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
|
||||
scriptable::ModelProviderPointer getAvatarModelProvider(QUuid sessionUUID) {
|
||||
scriptable::ModelProviderPointer provider;
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
@ -946,9 +931,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
// FIXME move to header, or better yet, design some kind of UI manager
|
||||
// to take care of highlighting keyboard focused items, rather than
|
||||
// continuing to overburden Application.cpp
|
||||
std::shared_ptr<Cube3DOverlay> _keyboardFocusHighlight{ nullptr };
|
||||
OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID };
|
||||
|
||||
QUuid _keyboardFocusHighlightID;
|
||||
|
||||
OffscreenGLCanvas* _qmlShareContext { nullptr };
|
||||
|
||||
|
@ -989,7 +972,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
QApplication(argc, argv),
|
||||
_window(new MainWindow(desktop())),
|
||||
_sessionRunTimer(startupTimer),
|
||||
#ifndef Q_OS_ANDROID
|
||||
_logger(new FileLogger(this)),
|
||||
#endif
|
||||
_previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)),
|
||||
_entitySimulation(new PhysicalEntitySimulation()),
|
||||
_physicsEngine(new PhysicsEngine(Vectors::ZERO)),
|
||||
|
@ -1123,7 +1108,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
}
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
_logger->setSessionID(accountManager->getSessionID());
|
||||
#endif
|
||||
|
||||
setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());
|
||||
setCrashAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId()));
|
||||
|
@ -1215,9 +1202,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
if (tabletScriptingInterface) {
|
||||
tabletScriptingInterface->setQmlTabletRoot(SYSTEM_TABLET, nullptr);
|
||||
}
|
||||
getOverlays().deleteOverlay(getTabletScreenID());
|
||||
getOverlays().deleteOverlay(getTabletHomeButtonID());
|
||||
getOverlays().deleteOverlay(getTabletFrameID());
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
entityScriptingInterface->deleteEntity(getTabletScreenID());
|
||||
entityScriptingInterface->deleteEntity(getTabletHomeButtonID());
|
||||
entityScriptingInterface->deleteEntity(getTabletFrameID());
|
||||
_failedToConnectToEntityServer = false;
|
||||
});
|
||||
|
||||
|
@ -1307,10 +1295,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
if (isHMDMode()) {
|
||||
emit loginDialogFocusDisabled();
|
||||
dialogsManager->hideLoginDialog();
|
||||
createLoginDialogOverlay();
|
||||
createLoginDialog();
|
||||
} else {
|
||||
getOverlays().deleteOverlay(_loginDialogOverlayID);
|
||||
_loginDialogOverlayID = OverlayID();
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_loginDialogID);
|
||||
_loginDialogID = QUuid();
|
||||
_loginStateManager.tearDown();
|
||||
dialogsManager->showLoginDialog();
|
||||
emit loginDialogFocusEnabled();
|
||||
|
@ -1901,25 +1889,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
SpacemouseManager::getInstance().init();
|
||||
#endif
|
||||
|
||||
// If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity,
|
||||
[this](const EntityItemID& entityItemID, const PointerEvent& event) {
|
||||
// If the user clicks on an object, we will check that it's a web surface, and if so, set the focus to it
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
auto keyboardFocusOperator = [this](const QUuid& id, const PointerEvent& event) {
|
||||
if (event.shouldFocus()) {
|
||||
if (getEntities()->wantsKeyboardFocus(entityItemID)) {
|
||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||
setKeyboardFocusEntity(entityItemID);
|
||||
} else {
|
||||
auto keyboard = DependencyManager::get<Keyboard>();
|
||||
if (getEntities()->wantsKeyboardFocus(id)) {
|
||||
setKeyboardFocusEntity(id);
|
||||
} else if (!keyboard->containsID(id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus
|
||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, keyboardFocusOperator);
|
||||
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, keyboardFocusOperator);
|
||||
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityItemID) {
|
||||
if (entityItemID == _keyboardFocusedEntity.get()) {
|
||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
}
|
||||
});
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
||||
if (_aboutToQuit) {
|
||||
|
@ -1979,33 +1969,25 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
return false;
|
||||
});
|
||||
|
||||
EntityTree::setAddMaterialToOverlayOperator([this](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
||||
auto overlay = _overlays.getOverlay(overlayID);
|
||||
if (overlay) {
|
||||
overlay->addMaterial(material, parentMaterialName);
|
||||
return true;
|
||||
EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* {
|
||||
auto entities = getEntities();
|
||||
if (auto entity = entities->renderableForEntityId(id)) {
|
||||
return qobject_cast<QObject*>(entity.get());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
EntityTree::setRemoveMaterialFromOverlayOperator([this](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
||||
auto overlay = _overlays.getOverlay(overlayID);
|
||||
if (overlay) {
|
||||
overlay->removeMaterial(material, parentMaterialName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
// Keyboard focus handling for Web overlays.
|
||||
auto overlays = &(qApp->getOverlays());
|
||||
connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) {
|
||||
if (overlayID == _keyboardFocusedOverlay.get()) {
|
||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||
EntityTree::setTextSizeOperator([this](const QUuid& id, const QString& text) {
|
||||
auto entities = getEntities();
|
||||
if (auto entity = entities->renderableForEntityId(id)) {
|
||||
if (auto renderable = std::dynamic_pointer_cast<render::entities::TextEntityRenderer>(entity)) {
|
||||
return renderable->textSize(text);
|
||||
}
|
||||
}
|
||||
return QSizeF(0.0f, 0.0f);
|
||||
});
|
||||
|
||||
connect(this, &Application::aboutToQuit, [this]() {
|
||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
});
|
||||
|
||||
|
@ -2326,8 +2308,30 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
|
||||
});
|
||||
|
||||
EntityTreeRenderer::setGetAvatarUpOperator([] {
|
||||
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
|
||||
EntityItem::setBillboardRotationOperator([this](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode) {
|
||||
if (billboardMode == BillboardMode::YAW) {
|
||||
//rotate about vertical to face the camera
|
||||
ViewFrustum frustum;
|
||||
copyViewFrustum(frustum);
|
||||
glm::vec3 dPosition = frustum.getPosition() - position;
|
||||
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
|
||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
||||
return glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
||||
} else if (billboardMode == BillboardMode::FULL) {
|
||||
ViewFrustum frustum;
|
||||
copyViewFrustum(frustum);
|
||||
glm::vec3 cameraPos = frustum.getPosition();
|
||||
// use the referencial from the avatar, y isn't always up
|
||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
|
||||
// check to see if glm::lookAt will work / using glm::lookAt variable name
|
||||
glm::highp_vec3 s(glm::cross(position - cameraPos, avatarUP));
|
||||
|
||||
// make sure s is not NaN for any component
|
||||
if (glm::length2(s) > 0.0f) {
|
||||
return glm::conjugate(glm::toQuat(glm::lookAt(cameraPos, position, avatarUP)));
|
||||
}
|
||||
}
|
||||
return rotation;
|
||||
});
|
||||
|
||||
render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
|
||||
|
@ -2353,7 +2357,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
});
|
||||
});
|
||||
auto rootItemLoadedFunctor = [webSurface, url, isTablet] {
|
||||
Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == OVERLAY_LOGIN_DIALOG.toString());
|
||||
Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == LOGIN_DIALOG.toString());
|
||||
};
|
||||
if (webSurface->getRootItem()) {
|
||||
rootItemLoadedFunctor();
|
||||
|
@ -2372,7 +2376,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// Fix for crash in QtWebEngineCore when rapidly switching domains
|
||||
// Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
|
||||
if (rootItem) {
|
||||
if (rootItem && !cachedWebSurface) {
|
||||
// stop loading
|
||||
QMetaObject::invokeMethod(rootItem, "stop");
|
||||
}
|
||||
|
@ -2401,6 +2405,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
});
|
||||
|
||||
// Preload Tablet sounds
|
||||
DependencyManager::get<EntityScriptingInterface>()->setEntityTree(qApp->getEntities()->getTree());
|
||||
DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
|
||||
DependencyManager::get<Keyboard>()->createKeyboard();
|
||||
|
||||
|
@ -2608,11 +2613,10 @@ void Application::cleanupBeforeQuit() {
|
|||
_applicationStateDevice.reset();
|
||||
|
||||
{
|
||||
if (_keyboardFocusHighlightID != UNKNOWN_OVERLAY_ID) {
|
||||
getOverlays().deleteOverlay(_keyboardFocusHighlightID);
|
||||
_keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID;
|
||||
if (_keyboardFocusHighlightID != UNKNOWN_ENTITY_ID) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_keyboardFocusHighlightID);
|
||||
_keyboardFocusHighlightID = UNKNOWN_ENTITY_ID;
|
||||
}
|
||||
_keyboardFocusHighlight = nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -3116,7 +3120,7 @@ void Application::initializeUi() {
|
|||
});
|
||||
|
||||
#if !defined(DISABLE_QML)
|
||||
// Pre-create a couple of Web3D overlays to speed up tablet UI
|
||||
// Pre-create a couple of offscreen surfaces to speed up tablet UI
|
||||
auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
|
||||
offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) {
|
||||
if (rootObject == TabletScriptingInterface::QML) {
|
||||
|
@ -3837,8 +3841,8 @@ static inline bool isKeyEvent(QEvent::Type type) {
|
|||
return type == QEvent::KeyPress || type == QEvent::KeyRelease;
|
||||
}
|
||||
|
||||
bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) {
|
||||
if (!_keyboardFocusedEntity.get().isInvalidID()) {
|
||||
bool Application::handleKeyEventForFocusedEntity(QEvent* event) {
|
||||
if (_keyboardFocusedEntity.get() != UNKNOWN_ENTITY_ID) {
|
||||
switch (event->type()) {
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
|
@ -3859,28 +3863,6 @@ bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) {
|
||||
switch (event->type()) {
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease: {
|
||||
// Only Web overlays can have focus.
|
||||
auto overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
|
||||
if (overlay && overlay->getEventHandler()) {
|
||||
event->setAccepted(false);
|
||||
QCoreApplication::sendEvent(overlay->getEventHandler(), event);
|
||||
if (event->isAccepted()) {
|
||||
_lastAcceptedKeyPress = usecTimestampNow();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3923,8 +3905,8 @@ bool Application::event(QEvent* event) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Allow focused Entities and Overlays to handle keyboard input
|
||||
if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event)) {
|
||||
// Allow focused Entities to handle keyboard input
|
||||
if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntity(event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4405,9 +4387,9 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
|||
buttons, event->modifiers());
|
||||
|
||||
if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||
|
||||
getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_OVERLAY_ID) {
|
||||
getOverlays().mouseMoveEvent(&mappedEvent);
|
||||
getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) {
|
||||
getEntities()->mouseMoveEvent(&mappedEvent);
|
||||
getOverlays().mouseMoveEvent(&mappedEvent);
|
||||
}
|
||||
|
||||
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts
|
||||
|
@ -4439,15 +4421,16 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
#else
|
||||
QPointF transformedPos;
|
||||
#endif
|
||||
QMouseEvent mappedEvent(event->type(),
|
||||
transformedPos,
|
||||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
|
||||
getOverlays().mousePressEvent(&mappedEvent);
|
||||
QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers());
|
||||
std::pair<float, QUuid> entityResult;
|
||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
||||
getEntities()->mousePressEvent(&mappedEvent);
|
||||
entityResult = getEntities()->mousePressEvent(&mappedEvent);
|
||||
}
|
||||
std::pair<float, QUuid> overlayResult = getOverlays().mousePressEvent(&mappedEvent);
|
||||
|
||||
QUuid focusedEntity = entityResult.first < overlayResult.first ? entityResult.second : overlayResult.second;
|
||||
setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(focusedEntity) ? focusedEntity : UNKNOWN_ENTITY_ID);
|
||||
|
||||
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
|
||||
|
||||
|
@ -4487,10 +4470,10 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) {
|
|||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
|
||||
getOverlays().mouseDoublePressEvent(&mappedEvent);
|
||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
||||
getEntities()->mouseDoublePressEvent(&mappedEvent);
|
||||
}
|
||||
getOverlays().mouseDoublePressEvent(&mappedEvent);
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface->isMouseCaptured()) {
|
||||
|
@ -4514,8 +4497,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
|
|||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
|
||||
getOverlays().mouseReleaseEvent(&mappedEvent);
|
||||
getEntities()->mouseReleaseEvent(&mappedEvent);
|
||||
getOverlays().mouseReleaseEvent(&mappedEvent);
|
||||
|
||||
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
|
||||
|
||||
|
@ -4963,7 +4946,11 @@ void Application::idle() {
|
|||
// Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing
|
||||
// details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing
|
||||
// details normally.
|
||||
#ifdef Q_OS_ANDROID
|
||||
bool showWarnings = false;
|
||||
#else
|
||||
bool showWarnings = getLogger()->extraDebugging();
|
||||
#endif
|
||||
PerformanceWarning warn(showWarnings, "idle()");
|
||||
|
||||
{
|
||||
|
@ -4977,31 +4964,19 @@ void Application::idle() {
|
|||
update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS));
|
||||
}
|
||||
|
||||
|
||||
// Update focus highlight for entity or overlay.
|
||||
{
|
||||
if (!_keyboardFocusedEntity.get().isInvalidID() || _keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) {
|
||||
{ // Update keyboard focus highlight
|
||||
if (!_keyboardFocusedEntity.get().isInvalidID()) {
|
||||
const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus
|
||||
quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress;
|
||||
if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) {
|
||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||
} else {
|
||||
// update position of highlight overlay
|
||||
if (!_keyboardFocusedEntity.get().isInvalidID()) {
|
||||
auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get());
|
||||
if (entity && _keyboardFocusHighlight) {
|
||||
_keyboardFocusHighlight->setWorldOrientation(entity->getWorldOrientation());
|
||||
_keyboardFocusHighlight->setWorldPosition(entity->getWorldPosition());
|
||||
}
|
||||
} else {
|
||||
// Only Web overlays can have focus.
|
||||
auto overlay =
|
||||
std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
|
||||
if (overlay && _keyboardFocusHighlight) {
|
||||
_keyboardFocusHighlight->setWorldOrientation(overlay->getWorldOrientation());
|
||||
_keyboardFocusHighlight->setWorldPosition(overlay->getWorldPosition());
|
||||
}
|
||||
if (auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get())) {
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(entity->getWorldPosition());
|
||||
properties.setRotation(entity->getWorldOrientation());
|
||||
properties.setDimensions(entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_keyboardFocusHighlightID, properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5799,118 +5774,80 @@ void Application::rotationModeChanged() const {
|
|||
}
|
||||
|
||||
void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) {
|
||||
// Create focus
|
||||
if (qApp->getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) {
|
||||
_keyboardFocusHighlight = std::make_shared<Cube3DOverlay>();
|
||||
_keyboardFocusHighlight->setAlpha(1.0f);
|
||||
_keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 });
|
||||
_keyboardFocusHighlight->setIsSolid(false);
|
||||
_keyboardFocusHighlight->setPulseMin(0.5);
|
||||
_keyboardFocusHighlight->setPulseMax(1.0);
|
||||
_keyboardFocusHighlight->setColorPulse(1.0);
|
||||
_keyboardFocusHighlight->setIgnorePickIntersection(true);
|
||||
_keyboardFocusHighlight->setDrawInFront(false);
|
||||
_keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight);
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (_keyboardFocusHighlightID == UNKNOWN_ENTITY_ID || !entityScriptingInterface->isAddedEntity(_keyboardFocusHighlightID)) {
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Box);
|
||||
properties.setAlpha(1.0f);
|
||||
properties.setColor({ 0xFF, 0xEF, 0x00 });
|
||||
properties.setPrimitiveMode(PrimitiveMode::LINES);
|
||||
properties.getPulse().setMin(0.5);
|
||||
properties.getPulse().setMax(1.0f);
|
||||
properties.getPulse().setColorMode(PulseMode::IN_PHASE);
|
||||
properties.setIgnorePickIntersection(true);
|
||||
_keyboardFocusHighlightID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
}
|
||||
|
||||
// Position focus
|
||||
_keyboardFocusHighlight->setWorldOrientation(rotation);
|
||||
_keyboardFocusHighlight->setWorldPosition(position);
|
||||
_keyboardFocusHighlight->setDimensions(dimensions);
|
||||
_keyboardFocusHighlight->setVisible(true);
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(position);
|
||||
properties.setRotation(rotation);
|
||||
properties.setDimensions(dimensions);
|
||||
properties.setVisible(true);
|
||||
entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties);
|
||||
}
|
||||
|
||||
QUuid Application::getKeyboardFocusEntity() const {
|
||||
return _keyboardFocusedEntity.get();
|
||||
}
|
||||
|
||||
static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
|
||||
|
||||
void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {
|
||||
if (qApp->getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
if (_keyboardFocusedEntity.get() != entityItemID) {
|
||||
_keyboardFocusedEntity.set(entityItemID);
|
||||
|
||||
if (_keyboardFocusHighlight && _keyboardFocusedOverlay.get() == UNKNOWN_OVERLAY_ID) {
|
||||
_keyboardFocusHighlight->setVisible(false);
|
||||
}
|
||||
|
||||
if (entityItemID == UNKNOWN_ENTITY_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
auto properties = entityScriptingInterface->getEntityProperties(entityItemID);
|
||||
if (!properties.getLocked() && properties.getVisible()) {
|
||||
|
||||
auto entities = getEntities();
|
||||
auto entityId = _keyboardFocusedEntity.get();
|
||||
if (entities->wantsKeyboardFocus(entityId)) {
|
||||
entities->setProxyWindow(entityId, _window->windowHandle());
|
||||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->pluginFocusOutEvent();
|
||||
}
|
||||
_lastAcceptedKeyPress = usecTimestampNow();
|
||||
|
||||
auto entity = getEntities()->getEntity(entityId);
|
||||
if (entity) {
|
||||
setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
|
||||
entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OverlayID Application::getKeyboardFocusOverlay() {
|
||||
return _keyboardFocusedOverlay.get();
|
||||
}
|
||||
|
||||
void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
|
||||
if (overlayID != _keyboardFocusedOverlay.get()) {
|
||||
if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) {
|
||||
if (overlayID == _loginDialogOverlayID) {
|
||||
void Application::setKeyboardFocusEntity(const QUuid& id) {
|
||||
if (_keyboardFocusedEntity.get() != id) {
|
||||
if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) {
|
||||
if (id == _loginDialogID) {
|
||||
emit loginDialogFocusEnabled();
|
||||
} else {
|
||||
// that's the only overlay we want in focus;
|
||||
// that's the only entity we want in focus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_keyboardFocusedOverlay.set(overlayID);
|
||||
_keyboardFocusedEntity.set(id);
|
||||
|
||||
if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) {
|
||||
_keyboardFocusHighlight->setVisible(false);
|
||||
}
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (id != UNKNOWN_ENTITY_ID) {
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_VISIBLE;
|
||||
desiredProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT;
|
||||
auto properties = entityScriptingInterface->getEntityProperties(id);
|
||||
if (properties.getVisible()) {
|
||||
auto entities = getEntities();
|
||||
auto entityId = _keyboardFocusedEntity.get();
|
||||
if (entities->wantsKeyboardFocus(entityId)) {
|
||||
entities->setProxyWindow(entityId, _window->windowHandle());
|
||||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->pluginFocusOutEvent();
|
||||
}
|
||||
_lastAcceptedKeyPress = usecTimestampNow();
|
||||
|
||||
if (overlayID == UNKNOWN_OVERLAY_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto overlayType = getOverlays().getOverlayType(overlayID);
|
||||
auto isVisible = getOverlays().getProperty(overlayID, "visible").value.toBool();
|
||||
if (overlayType == Web3DOverlay::TYPE && isVisible) {
|
||||
auto overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(overlayID));
|
||||
overlay->setProxyWindow(_window->windowHandle());
|
||||
|
||||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->pluginFocusOutEvent();
|
||||
}
|
||||
_lastAcceptedKeyPress = usecTimestampNow();
|
||||
|
||||
if (overlay->getProperty("showKeyboardFocusHighlight").toBool()) {
|
||||
auto size = overlay->getSize() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR;
|
||||
const float OVERLAY_DEPTH = 0.0105f;
|
||||
setKeyboardFocusHighlight(overlay->getWorldPosition(), overlay->getWorldOrientation(), glm::vec3(size.x, size.y, OVERLAY_DEPTH));
|
||||
} else if (_keyboardFocusHighlight) {
|
||||
_keyboardFocusHighlight->setVisible(false);
|
||||
if (properties.getShowKeyboardFocusHighlight()) {
|
||||
if (auto entity = entities->getEntity(entityId)) {
|
||||
setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
|
||||
entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(false);
|
||||
entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6287,6 +6224,19 @@ void Application::update(float deltaTime) {
|
|||
auto grabManager = DependencyManager::get<GrabManager>();
|
||||
grabManager->simulateGrabs();
|
||||
|
||||
// TODO: break these out into distinct perfTimers when they prove interesting
|
||||
{
|
||||
PROFILE_RANGE(app, "PickManager");
|
||||
PerformanceTimer perfTimer("pickManager");
|
||||
DependencyManager::get<PickManager>()->update();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(app, "PointerManager");
|
||||
PerformanceTimer perfTimer("pointerManager");
|
||||
DependencyManager::get<PointerManager>()->update();
|
||||
}
|
||||
|
||||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
||||
{
|
||||
|
@ -6300,40 +6250,57 @@ void Application::update(float deltaTime) {
|
|||
PROFILE_RANGE(simulation_physics, "PrePhysics");
|
||||
PerformanceTimer perfTimer("prePhysics)");
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "RemoveEntities");
|
||||
const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics();
|
||||
_physicsEngine->removeObjects(motionStates);
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size());
|
||||
_physicsEngine->removeObjects(motionStates);
|
||||
}
|
||||
_entitySimulation->deleteObjectsRemovedFromPhysics();
|
||||
}
|
||||
|
||||
VectorOfMotionStates motionStates;
|
||||
getEntities()->getTree()->withReadLock([&] {
|
||||
_entitySimulation->getObjectsToAddToPhysics(motionStates);
|
||||
_physicsEngine->addObjects(motionStates);
|
||||
|
||||
});
|
||||
getEntities()->getTree()->withReadLock([&] {
|
||||
_entitySimulation->getObjectsToChange(motionStates);
|
||||
VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
|
||||
_entitySimulation->setObjectsToChange(stillNeedChange);
|
||||
});
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "AddEntities");
|
||||
VectorOfMotionStates motionStates;
|
||||
getEntities()->getTree()->withReadLock([&] {
|
||||
_entitySimulation->getObjectsToAddToPhysics(motionStates);
|
||||
PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size());
|
||||
_physicsEngine->addObjects(motionStates);
|
||||
});
|
||||
}
|
||||
{
|
||||
VectorOfMotionStates motionStates;
|
||||
PROFILE_RANGE(simulation_physics, "ChangeEntities");
|
||||
getEntities()->getTree()->withReadLock([&] {
|
||||
_entitySimulation->getObjectsToChange(motionStates);
|
||||
VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
|
||||
_entitySimulation->setObjectsToChange(stillNeedChange);
|
||||
});
|
||||
}
|
||||
|
||||
_entitySimulation->applyDynamicChanges();
|
||||
|
||||
t1 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
PhysicsEngine::Transaction transaction;
|
||||
avatarManager->buildPhysicsTransaction(transaction);
|
||||
_physicsEngine->processTransaction(transaction);
|
||||
avatarManager->handleProcessedPhysicsTransaction(transaction);
|
||||
myAvatar->getCharacterController()->buildPhysicsTransaction(transaction);
|
||||
_physicsEngine->processTransaction(transaction);
|
||||
myAvatar->getCharacterController()->handleProcessedPhysicsTransaction(transaction);
|
||||
myAvatar->prepareForPhysicsSimulation();
|
||||
_physicsEngine->enableGlobalContactAddedCallback(myAvatar->isFlying());
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "Avatars");
|
||||
PhysicsEngine::Transaction transaction;
|
||||
avatarManager->buildPhysicsTransaction(transaction);
|
||||
_physicsEngine->processTransaction(transaction);
|
||||
avatarManager->handleProcessedPhysicsTransaction(transaction);
|
||||
myAvatar->getCharacterController()->buildPhysicsTransaction(transaction);
|
||||
_physicsEngine->processTransaction(transaction);
|
||||
myAvatar->getCharacterController()->handleProcessedPhysicsTransaction(transaction);
|
||||
myAvatar->prepareForPhysicsSimulation();
|
||||
_physicsEngine->enableGlobalContactAddedCallback(myAvatar->isFlying());
|
||||
}
|
||||
|
||||
_physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) {
|
||||
dynamic->prepareForPhysicsSimulation();
|
||||
});
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "PrepareActions");
|
||||
_physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) {
|
||||
dynamic->prepareForPhysicsSimulation();
|
||||
});
|
||||
}
|
||||
}
|
||||
auto t2 = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
|
@ -6436,22 +6403,9 @@ void Application::update(float deltaTime) {
|
|||
|
||||
updateLOD(deltaTime);
|
||||
|
||||
if (!_loginDialogOverlayID.isNull()) {
|
||||
_loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogOverlayID);
|
||||
updateLoginDialogOverlayPosition();
|
||||
}
|
||||
|
||||
// TODO: break these out into distinct perfTimers when they prove interesting
|
||||
{
|
||||
PROFILE_RANGE(app, "PickManager");
|
||||
PerformanceTimer perfTimer("pickManager");
|
||||
DependencyManager::get<PickManager>()->update();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(app, "PointerManager");
|
||||
PerformanceTimer perfTimer("pointerManager");
|
||||
DependencyManager::get<PointerManager>()->update();
|
||||
if (!_loginDialogID.isNull()) {
|
||||
_loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogID);
|
||||
updateLoginDialogPosition();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -7217,7 +7171,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);
|
||||
|
||||
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
|
||||
qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue,
|
||||
RayToOverlayIntersectionResultFromScriptValue);
|
||||
|
||||
|
@ -7334,8 +7287,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||
|
||||
registerInteractiveWindowMetaType(scriptEngine.data());
|
||||
|
||||
auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();
|
||||
|
@ -8306,7 +8257,7 @@ void Application::toggleLogDialog() {
|
|||
bool keepOnTop =_keepLogWindowOnTop.get();
|
||||
#ifdef Q_OS_WIN
|
||||
_logDialog = new LogDialog(keepOnTop ? qApp->getWindow() : nullptr, getLogger());
|
||||
#else
|
||||
#elif !defined(Q_OS_ANDROID)
|
||||
_logDialog = new LogDialog(nullptr, getLogger());
|
||||
|
||||
if (keepOnTop) {
|
||||
|
@ -8857,45 +8808,47 @@ void Application::setShowBulletConstraintLimits(bool value) {
|
|||
_physicsEngine->setShowBulletConstraintLimits(value);
|
||||
}
|
||||
|
||||
void Application::createLoginDialogOverlay() {
|
||||
const glm::vec2 LOGIN_OVERLAY_DIMENSIONS{ 0.89f, 0.5f };
|
||||
const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
void Application::createLoginDialog() {
|
||||
const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f };
|
||||
const auto OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
auto cameraPosition = _myCamera.getPosition();
|
||||
auto cameraOrientation = _myCamera.getOrientation();
|
||||
auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;
|
||||
auto headLookVec = (cameraOrientation * Vectors::FRONT);
|
||||
// DEFAULT_DPI / tablet scale percentage
|
||||
const float OVERLAY_DPI = 31.0f / (75.0f / 100.0f);
|
||||
auto offset = headLookVec * OVERLAY_OFFSET.x;
|
||||
auto overlayPosition = (cameraPosition + offset) + (upVec * OVERLAY_OFFSET.y);
|
||||
QVariantMap overlayProperties = {
|
||||
{ "name", "LoginDialogOverlay" },
|
||||
{ "url", OVERLAY_LOGIN_DIALOG },
|
||||
{ "position", vec3toVariant(overlayPosition) },
|
||||
{ "orientation", quatToVariant(cameraOrientation) },
|
||||
{ "isSolid", true },
|
||||
{ "grabbable", false },
|
||||
{ "ignorePickIntersection", false },
|
||||
{ "alpha", 1.0 },
|
||||
{ "dimensions", vec2ToVariant(LOGIN_OVERLAY_DIMENSIONS)},
|
||||
{ "dpi", OVERLAY_DPI },
|
||||
{ "visible", true }
|
||||
};
|
||||
auto& overlays = getOverlays();
|
||||
_loginDialogOverlayID = overlays.addOverlay("web3d", overlayProperties);
|
||||
auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID));
|
||||
const float DPI = 31.0f / (75.0f / 100.0f);
|
||||
auto offset = headLookVec * OFFSET.x;
|
||||
auto position = (cameraPosition + offset) + (upVec * OFFSET.y);
|
||||
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Web);
|
||||
properties.setName("LoginDialogEntity");
|
||||
properties.setSourceUrl(LOGIN_DIALOG.toString());
|
||||
properties.setPosition(position);
|
||||
properties.setRotation(cameraOrientation);
|
||||
properties.setDimensions(LOGIN_DIMENSIONS);
|
||||
properties.setPrimitiveMode(PrimitiveMode::SOLID);
|
||||
properties.getGrab().setGrabbable(false);
|
||||
properties.setIgnorePickIntersection(false);
|
||||
properties.setAlpha(1.0f);
|
||||
properties.setDPI(DPI);
|
||||
properties.setVisible(true);
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
_loginDialogID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
|
||||
auto keyboard = DependencyManager::get<Keyboard>().data();
|
||||
if (!keyboard->getAnchorID().isNull() && !_loginDialogOverlayID.isNull()) {
|
||||
const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f);
|
||||
if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) {
|
||||
auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
|
||||
QVariantMap properties {
|
||||
{ "position", vec3toVariant(overlayPosition + keyboardLocalOffset) },
|
||||
{ "orientation", quatToVariant(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION) },
|
||||
};
|
||||
overlays.editOverlay(keyboard->getAnchorID(), properties);
|
||||
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(position + keyboardLocalOffset);
|
||||
properties.setRotation(cameraOrientation * Quaternions::Y_180);
|
||||
|
||||
entityScriptingInterface->editEntity(keyboard->getAnchorID(), properties);
|
||||
keyboard->setResetKeyboardPositionOnRaise(false);
|
||||
}
|
||||
setKeyboardFocusOverlay(_loginDialogOverlayID);
|
||||
setKeyboardFocusEntity(_loginDialogID);
|
||||
emit loginDialogFocusEnabled();
|
||||
getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false);
|
||||
getApplicationCompositor().getReticleInterface()->setVisible(false);
|
||||
|
@ -8904,38 +8857,43 @@ void Application::createLoginDialogOverlay() {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::updateLoginDialogOverlayPosition() {
|
||||
void Application::updateLoginDialogPosition() {
|
||||
const float LOOK_AWAY_THRESHOLD_ANGLE = 70.0f;
|
||||
const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
auto& overlays = getOverlays();
|
||||
auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID));
|
||||
auto overlayPositionVec = loginOverlay->getWorldPosition();
|
||||
const auto OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_POSITION;
|
||||
auto properties = entityScriptingInterface->getEntityProperties(_loginDialogID, desiredProperties);
|
||||
auto positionVec = properties.getPosition();
|
||||
auto cameraPositionVec = _myCamera.getPosition();
|
||||
auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation());
|
||||
auto headLookVec = (cameraOrientation * Vectors::FRONT);
|
||||
auto overlayToHeadVec = overlayPositionVec - cameraPositionVec;
|
||||
auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI);
|
||||
auto entityToHeadVec = positionVec - cameraPositionVec;
|
||||
auto pointAngle = (glm::acos(glm::dot(glm::normalize(entityToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI);
|
||||
auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;
|
||||
auto offset = headLookVec * OVERLAY_OFFSET.x;
|
||||
auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * OVERLAY_OFFSET.y);
|
||||
auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180;
|
||||
auto offset = headLookVec * OFFSET.x;
|
||||
auto newPositionVec = (cameraPositionVec + offset) + (upVec * OFFSET.y);
|
||||
|
||||
bool overlayOutOfBounds = glm::distance(overlayPositionVec, cameraPositionVec) > 1.0f;
|
||||
bool outOfBounds = glm::distance(positionVec, cameraPositionVec) > 1.0f;
|
||||
|
||||
if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || overlayOutOfBounds) {
|
||||
QVariantMap properties {
|
||||
{"position", vec3toVariant(newOverlayPositionVec)},
|
||||
{"orientation", quatToVariant(newOverlayOrientation)}
|
||||
};
|
||||
overlays.editOverlay(_loginDialogOverlayID, properties);
|
||||
const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f);
|
||||
auto keyboardLocalOffset = newOverlayOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
|
||||
QVariantMap keyboardProperties {
|
||||
{ "position", vec3toVariant(newOverlayPositionVec + keyboardLocalOffset) },
|
||||
{ "orientation", quatToVariant(newOverlayOrientation * KEYBOARD_LOCAL_ORIENTATION) },
|
||||
};
|
||||
auto keyboard = DependencyManager::get<Keyboard>().data();
|
||||
overlays.editOverlay(keyboard->getAnchorID(), keyboardProperties);
|
||||
if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || outOfBounds) {
|
||||
{
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(newPositionVec);
|
||||
properties.setRotation(cameraOrientation);
|
||||
entityScriptingInterface->editEntity(_loginDialogID, properties);
|
||||
}
|
||||
|
||||
{
|
||||
glm::vec3 keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
|
||||
glm::quat keyboardOrientation = cameraOrientation * glm::quat(glm::radians(glm::vec3(-30.0f, 180.0f, 0.0f)));
|
||||
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(newPositionVec + keyboardLocalOffset);
|
||||
properties.setRotation(keyboardOrientation);
|
||||
entityScriptingInterface->editEntity(DependencyManager::get<Keyboard>()->getAnchorID(), properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8952,10 +8910,9 @@ void Application::onDismissedLoginDialog() {
|
|||
loginDialogPoppedUp.set(false);
|
||||
auto keyboard = DependencyManager::get<Keyboard>().data();
|
||||
keyboard->setResetKeyboardPositionOnRaise(true);
|
||||
if (!_loginDialogOverlayID.isNull()) {
|
||||
// deleting overlay.
|
||||
getOverlays().deleteOverlay(_loginDialogOverlayID);
|
||||
_loginDialogOverlayID = OverlayID();
|
||||
if (!_loginDialogID.isNull()) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_loginDialogID);
|
||||
_loginDialogID = QUuid();
|
||||
_loginStateManager.tearDown();
|
||||
}
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
|
@ -9121,12 +9078,12 @@ void Application::updateSystemTabletMode() {
|
|||
}
|
||||
}
|
||||
|
||||
OverlayID Application::getTabletScreenID() const {
|
||||
QUuid Application::getTabletScreenID() const {
|
||||
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||
return HMD->getCurrentTabletScreenID();
|
||||
}
|
||||
|
||||
OverlayID Application::getTabletHomeButtonID() const {
|
||||
QUuid Application::getTabletHomeButtonID() const {
|
||||
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||
return HMD->getCurrentHomeButtonID();
|
||||
}
|
||||
|
@ -9137,7 +9094,7 @@ QUuid Application::getTabletFrameID() const {
|
|||
}
|
||||
|
||||
QVector<QUuid> Application::getTabletIDs() const {
|
||||
// Most important overlays first.
|
||||
// Most important first.
|
||||
QVector<QUuid> result;
|
||||
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||
result << HMD->getCurrentTabletScreenID();
|
||||
|
|
|
@ -251,7 +251,9 @@ public:
|
|||
|
||||
void setActiveDisplayPlugin(const QString& pluginName);
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
FileLogger* getLogger() const { return _logger; }
|
||||
#endif
|
||||
|
||||
float getRenderResolutionScale() const;
|
||||
|
||||
|
@ -299,10 +301,10 @@ public:
|
|||
|
||||
void shareSnapshot(const QString& filename, const QUrl& href = QUrl(""));
|
||||
|
||||
OverlayID getTabletScreenID() const;
|
||||
OverlayID getTabletHomeButtonID() const;
|
||||
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
||||
QVector<QUuid> getTabletIDs() const; // In order of most important IDs first.
|
||||
QUuid getTabletScreenID() const;
|
||||
QUuid getTabletHomeButtonID() const;
|
||||
QUuid getTabletFrameID() const;
|
||||
QVector<QUuid> getTabletIDs() const;
|
||||
|
||||
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
||||
void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; }
|
||||
|
@ -325,8 +327,8 @@ public:
|
|||
void setOtherAvatarsReplicaCount(int count) { DependencyManager::get<AvatarHashMap>()->setReplicaCount(count); }
|
||||
|
||||
bool getLoginDialogPoppedUp() const { return _loginDialogPoppedUp; }
|
||||
void createLoginDialogOverlay();
|
||||
void updateLoginDialogOverlayPosition();
|
||||
void createLoginDialog();
|
||||
void updateLoginDialogPosition();
|
||||
|
||||
// Check if a headset is connected
|
||||
bool hasRiftControllers();
|
||||
|
@ -440,10 +442,7 @@ public slots:
|
|||
void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions);
|
||||
|
||||
QUuid getKeyboardFocusEntity() const; // thread-safe
|
||||
void setKeyboardFocusEntity(const EntityItemID& entityItemID);
|
||||
|
||||
OverlayID getKeyboardFocusOverlay();
|
||||
void setKeyboardFocusOverlay(const OverlayID& overlayID);
|
||||
void setKeyboardFocusEntity(const QUuid& id);
|
||||
|
||||
void addAssetToWorldMessageClose();
|
||||
|
||||
|
@ -534,7 +533,7 @@ private:
|
|||
void init();
|
||||
void pauseUntilLoginDetermined();
|
||||
void resumeAfterLoginDialogActionTaken();
|
||||
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
|
||||
bool handleKeyEventForFocusedEntity(QEvent* event);
|
||||
bool handleFileOpenEvent(QFileOpenEvent* event);
|
||||
void cleanupBeforeQuit();
|
||||
|
||||
|
@ -599,7 +598,9 @@ private:
|
|||
|
||||
bool _aboutToQuit { false };
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
FileLogger* _logger { nullptr };
|
||||
#endif
|
||||
|
||||
bool _previousSessionCrashed;
|
||||
|
||||
|
@ -706,7 +707,7 @@ private:
|
|||
QString _previousAvatarSkeletonModel;
|
||||
float _previousAvatarTargetScale;
|
||||
CameraMode _previousCameraMode;
|
||||
OverlayID _loginDialogOverlayID;
|
||||
QUuid _loginDialogID;
|
||||
LoginStateManager _loginStateManager;
|
||||
|
||||
quint64 _lastFaceTrackerUpdate;
|
||||
|
@ -724,7 +725,6 @@ private:
|
|||
DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface();
|
||||
|
||||
ThreadSafeValueCache<EntityItemID> _keyboardFocusedEntity;
|
||||
ThreadSafeValueCache<OverlayID> _keyboardFocusedOverlay;
|
||||
quint64 _lastAcceptedKeyPress = 0;
|
||||
bool _isForeground = true; // starts out assumed to be in foreground
|
||||
bool _isGLInitialized { false };
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -50,15 +50,6 @@ SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& s
|
|||
return avatarManager->getMyAvatar();
|
||||
}
|
||||
|
||||
// search overlays
|
||||
auto& overlays = qApp->getOverlays();
|
||||
auto overlay = overlays.getOverlay(parentID);
|
||||
parent = std::dynamic_pointer_cast<SpatiallyNestable>(overlay); // this will return nullptr for non-3d overlays
|
||||
if (!parent.expired()) {
|
||||
success = true;
|
||||
return parent;
|
||||
}
|
||||
|
||||
success = false;
|
||||
return parent;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ class AABox;
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} presentTime <em>Read-only.</em>
|
||||
* @property {number} engineRunTime <em>Read-only.</em>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* @hifi-client-entity
|
||||
* @hifi-interface
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
class LocationBookmarks : public Bookmarks, public Dependency {
|
||||
|
|
|
@ -170,7 +170,7 @@ void LoginStateManager::setUp() {
|
|||
const unsigned int leftHand = 0;
|
||||
QVariantMap leftPointerProperties {
|
||||
{ "joint", "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND" },
|
||||
{ "filter", PickScriptingInterface::PICK_OVERLAYS() },
|
||||
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
|
||||
{ "triggers", leftPointerTriggerProperties },
|
||||
{ "posOffset", vec3toVariant(grabPointSphereOffsetLeft + malletOffset) },
|
||||
{ "hover", true },
|
||||
|
@ -197,7 +197,7 @@ void LoginStateManager::setUp() {
|
|||
rightPointerTriggerProperties = QList<QVariant>({rtClick1, rtClick2});
|
||||
QVariantMap rightPointerProperties{
|
||||
{ "joint", "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" },
|
||||
{ "filter", PickScriptingInterface::PICK_OVERLAYS() },
|
||||
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
|
||||
{ "triggers", rightPointerTriggerProperties },
|
||||
{ "posOffset", vec3toVariant(grabPointSphereOffsetRight + malletOffset) },
|
||||
{ "hover", true },
|
||||
|
@ -212,7 +212,7 @@ void LoginStateManager::setUp() {
|
|||
pointers->enablePointer(_rightLoginPointerID);
|
||||
}
|
||||
|
||||
void LoginStateManager::update(const QString dominantHand, const QUuid loginOverlayID) {
|
||||
void LoginStateManager::update(const QString& dominantHand, const QUuid& loginEntityID) {
|
||||
if (!isSetUp()) {
|
||||
return;
|
||||
}
|
||||
|
@ -224,8 +224,8 @@ void LoginStateManager::update(const QString dominantHand, const QUuid loginOver
|
|||
if (pointers && raypicks) {
|
||||
const auto rightObjectID = raypicks->getPrevRayPickResult(_rightLoginPointerID)["objectID"].toUuid();
|
||||
const auto leftObjectID = raypicks->getPrevRayPickResult(_leftLoginPointerID)["objectID"].toUuid();
|
||||
const QString leftMode = (leftObjectID.isNull() || leftObjectID != loginOverlayID) ? "" : "full";
|
||||
const QString rightMode = (rightObjectID.isNull() || rightObjectID != loginOverlayID) ? "" : "full";
|
||||
const QString leftMode = (leftObjectID.isNull() || leftObjectID != loginEntityID) ? "" : "full";
|
||||
const QString rightMode = (rightObjectID.isNull() || rightObjectID != loginEntityID) ? "" : "full";
|
||||
pointers->setRenderState(_leftLoginPointerID, leftMode);
|
||||
pointers->setRenderState(_rightLoginPointerID, rightMode);
|
||||
if (_dominantHand == "left" && !leftObjectID.isNull()) {
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void update(const QString dominantHand, const QUuid loginOverlayID);
|
||||
void update(const QString& dominantHand, const QUuid& loginObjectID);
|
||||
|
||||
bool isSetUp() const { return (_leftLoginPointerID > PointerEvent::INVALID_POINTER_ID) && (_rightLoginPointerID > PointerEvent::INVALID_POINTER_ID); }
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
class SpeechRecognizer : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -31,6 +31,7 @@ class AudioScope : public QObject, public Dependency {
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} scopeInput <em>Read-only.</em>
|
||||
* @property {number} scopeOutputLeft <em>Read-only.</em>
|
||||
|
|
|
@ -569,7 +569,7 @@ void AvatarActionHold::lateAvatarUpdate(const AnimPose& prePhysicsRoomPose, cons
|
|||
}
|
||||
|
||||
btTransform worldTrans = rigidBody->getWorldTransform();
|
||||
AnimPose worldBodyPose(1.0f, bulletToGLM(worldTrans.getRotation()), bulletToGLM(worldTrans.getOrigin()));
|
||||
AnimPose worldBodyPose(glm::vec3(1), bulletToGLM(worldTrans.getRotation()), bulletToGLM(worldTrans.getOrigin()));
|
||||
|
||||
// transform the body transform into sensor space with the prePhysics sensor-to-world matrix.
|
||||
// then transform it back into world uisng the postAvatarUpdate sensor-to-world matrix.
|
||||
|
|
|
@ -46,6 +46,7 @@ using SortedAvatar = std::pair<float, std::shared_ptr<Avatar>>;
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @borrows AvatarList.getAvatarIdentifiers as getAvatarIdentifiers
|
||||
* @borrows AvatarList.getAvatarsInRange as getAvatarsInRange
|
||||
|
|
|
@ -2980,7 +2980,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
auto animSkeleton = _skeletonModel->getRig().getAnimSkeleton();
|
||||
|
||||
// the rig is in the skeletonModel frame
|
||||
AnimPose xform(1.0f, _skeletonModel->getRotation(), _skeletonModel->getTranslation());
|
||||
AnimPose xform(glm::vec3(1), _skeletonModel->getRotation(), _skeletonModel->getTranslation());
|
||||
|
||||
if (_enableDebugDrawDefaultPose && animSkeleton) {
|
||||
glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f);
|
||||
|
@ -3025,7 +3025,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
updateHoldActions(_prePhysicsRoomPose, postUpdateRoomPose);
|
||||
|
||||
if (_enableDebugDrawDetailedCollision) {
|
||||
AnimPose rigToWorldPose(1.0f, getWorldOrientation() * Quaternions::Y_180, getWorldPosition());
|
||||
AnimPose rigToWorldPose(glm::vec3(1.0f), getWorldOrientation() * Quaternions::Y_180, getWorldPosition());
|
||||
const int NUM_DEBUG_COLORS = 8;
|
||||
const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = {
|
||||
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
|
@ -4821,7 +4821,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
|||
swingTwistDecomposition(hipsinWorldSpace, avatarUpWorld, resultingSwingInWorld, resultingTwistInWorld);
|
||||
|
||||
// remove scale present from sensorToWorldMatrix
|
||||
followWorldPose.scale() = 1.0f;
|
||||
followWorldPose.scale() = glm::vec3(1.0f);
|
||||
|
||||
if (isActive(Rotation)) {
|
||||
//use the hmd reading for the hips follow
|
||||
|
@ -5313,3 +5313,15 @@ void MyAvatar::releaseGrab(const QUuid& grabID) {
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const {
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
if (entityTree) {
|
||||
entityTree->withWriteLock([&] {
|
||||
// force an update packet
|
||||
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, entityID, properties);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ class MyAvatar : public Avatar {
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {Vec3} qmlPosition - A synonym for <code>position</code> for use by QML.
|
||||
* @property {boolean} shouldRenderLocally=true - If <code>true</code> then your avatar is rendered for you in Interface,
|
||||
|
@ -137,7 +138,7 @@ class MyAvatar : public Avatar {
|
|||
* your avatar when rolling your HMD in degrees per second.
|
||||
* @property {number} userHeight=1.75 - The height of the user in sensor space.
|
||||
* @property {number} userEyeHeight=1.65 - The estimated height of the user's eyes in sensor space. <em>Read-only.</em>
|
||||
* @property {Uuid} SELF_ID - UUID representing "my avatar". Only use for local-only entities and overlays in situations
|
||||
* @property {Uuid} SELF_ID - UUID representing "my avatar". Only use for local-only entities in situations
|
||||
* where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain). Note: Likely to be deprecated.
|
||||
* <em>Read-only.</em>
|
||||
* @property {number} walkSpeed
|
||||
|
@ -1883,6 +1884,7 @@ private:
|
|||
bool didTeleport();
|
||||
bool getIsAway() const { return _isAway; }
|
||||
void setAway(bool value);
|
||||
void sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const override;
|
||||
|
||||
std::mutex _pinnedJointsMutex;
|
||||
std::vector<int> _pinnedJoints;
|
||||
|
|
|
@ -41,7 +41,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
|||
if (myAvatar->isJointPinned(hipsIndex)) {
|
||||
Transform avatarTransform = myAvatar->getTransform();
|
||||
AnimPose result = AnimPose(worldToSensorMat * avatarTransform.getMatrix() * Matrices::Y_180);
|
||||
result.scale() = 1.0f;
|
||||
result.scale() = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
Rig::ControllerParameters params;
|
||||
|
||||
AnimPose avatarToRigPose(1.0f, Quaternions::Y_180, glm::vec3(0.0f));
|
||||
AnimPose avatarToRigPose(glm::vec3(1.0f), Quaternions::Y_180, glm::vec3(0.0f));
|
||||
|
||||
glm::mat4 rigToAvatarMatrix = Matrices::Y_180;
|
||||
glm::mat4 avatarToWorldMatrix = createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition());
|
||||
|
@ -127,7 +127,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
// preMult 180 is necessary to convert from avatar to rig coordinates.
|
||||
// postMult 180 is necessary to convert head from -z forward to z forward.
|
||||
glm::quat headRot = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180;
|
||||
params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(1.0f, headRot, glm::vec3(0.0f));
|
||||
params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(glm::vec3(1.0f), headRot, glm::vec3(0.0f));
|
||||
params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,44 +55,47 @@ OtherAvatar::~OtherAvatar() {
|
|||
|
||||
void OtherAvatar::removeOrb() {
|
||||
if (!_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_otherAvatarOrbMeshPlaceholderID);
|
||||
_otherAvatarOrbMeshPlaceholderID = UNKNOWN_OVERLAY_ID;
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_otherAvatarOrbMeshPlaceholderID);
|
||||
_otherAvatarOrbMeshPlaceholderID = UNKNOWN_ENTITY_ID;
|
||||
}
|
||||
}
|
||||
|
||||
void OtherAvatar::updateOrbPosition() {
|
||||
if (_otherAvatarOrbMeshPlaceholder != nullptr) {
|
||||
_otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition());
|
||||
if (_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||
_otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder);
|
||||
}
|
||||
if (_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(getHead()->getPosition());
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
void OtherAvatar::createOrb() {
|
||||
if (_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||
_otherAvatarOrbMeshPlaceholder = std::make_shared<Sphere3DOverlay>();
|
||||
_otherAvatarOrbMeshPlaceholder->setAlpha(1.0f);
|
||||
_otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus));
|
||||
_otherAvatarOrbMeshPlaceholder->setIsSolid(false);
|
||||
_otherAvatarOrbMeshPlaceholder->setPulseMin(0.5);
|
||||
_otherAvatarOrbMeshPlaceholder->setPulseMax(1.0);
|
||||
_otherAvatarOrbMeshPlaceholder->setColorPulse(1.0);
|
||||
_otherAvatarOrbMeshPlaceholder->setIgnorePickIntersection(true);
|
||||
_otherAvatarOrbMeshPlaceholder->setDrawInFront(false);
|
||||
_otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder);
|
||||
// Position focus
|
||||
_otherAvatarOrbMeshPlaceholder->setWorldOrientation(glm::quat(0.0f, 0.0f, 0.0f, 1.0));
|
||||
_otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition());
|
||||
_otherAvatarOrbMeshPlaceholder->setDimensions(glm::vec3(0.5f, 0.5f, 0.5f));
|
||||
_otherAvatarOrbMeshPlaceholder->setVisible(true);
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Sphere);
|
||||
properties.setAlpha(1.0f);
|
||||
properties.setColor(getLoadingOrbColor(_loadingStatus));
|
||||
properties.setPrimitiveMode(PrimitiveMode::LINES);
|
||||
properties.getPulse().setMin(0.5f);
|
||||
properties.getPulse().setMax(1.0f);
|
||||
properties.getPulse().setColorMode(PulseMode::IN_PHASE);
|
||||
properties.setIgnorePickIntersection(true);
|
||||
|
||||
properties.setPosition(getHead()->getPosition());
|
||||
properties.setRotation(glm::quat(0.0f, 0.0f, 0.0f, 1.0));
|
||||
properties.setDimensions(glm::vec3(0.5f, 0.5f, 0.5f));
|
||||
properties.setVisible(true);
|
||||
|
||||
_otherAvatarOrbMeshPlaceholderID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
void OtherAvatar::indicateLoadingStatus(LoadingStatus loadingStatus) {
|
||||
Avatar::indicateLoadingStatus(loadingStatus);
|
||||
if (_otherAvatarOrbMeshPlaceholder) {
|
||||
_otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus));
|
||||
|
||||
if (_otherAvatarOrbMeshPlaceholderID != UNKNOWN_ENTITY_ID) {
|
||||
EntityItemProperties properties;
|
||||
properties.setColor(getLoadingOrbColor(_loadingStatus));
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,6 +450,10 @@ void OtherAvatar::handleChangedAvatarEntityData() {
|
|||
EntityItemProperties properties;
|
||||
int32_t bytesLeftToRead = data.size();
|
||||
unsigned char* dataAt = (unsigned char*)(data.data());
|
||||
// FIXME: This function will cause unintented changes in SpaillyNestable
|
||||
// E.g overriding the ID index of an exisiting entity to temporary entity
|
||||
// in the following map QHash<QUuid, SpatiallyNestableWeakPointer> _children;
|
||||
// Andrew Meadows will address this issue
|
||||
if (!properties.constructFromBuffer(dataAt, bytesLeftToRead)) {
|
||||
// properties are corrupt
|
||||
continue;
|
||||
|
@ -489,6 +496,17 @@ void OtherAvatar::handleChangedAvatarEntityData() {
|
|||
bool success = true;
|
||||
if (entity) {
|
||||
QUuid oldParentID = entity->getParentID();
|
||||
|
||||
// Since has overwrtiiten the back pointer
|
||||
// from the parent children map (see comment for function call above),
|
||||
// we need to for reset the back pointer in the map correctly by setting the parentID, but
|
||||
// since the parentID of the entity has not changed we first need to set it some ither ID,
|
||||
// then set the the original ID for the changes to take effect
|
||||
// TODO: This is a horrible hack and once properties.constructFromBuffer no longer causes
|
||||
// side effects...remove the following three lines
|
||||
const QUuid NULL_ID = QUuid("{00000000-0000-0000-0000-000000000005}");
|
||||
entity->setParentID(NULL_ID);
|
||||
entity->setParentID(oldParentID);
|
||||
if (entityTree->updateEntity(entityID, properties)) {
|
||||
entity->updateLastEditedFromRemote();
|
||||
} else {
|
||||
|
@ -510,6 +528,11 @@ void OtherAvatar::handleChangedAvatarEntityData() {
|
|||
}
|
||||
}
|
||||
stateItr.value().success = success;
|
||||
if (success) {
|
||||
stateItr.value().hash = newHash;
|
||||
} else {
|
||||
stateItr.value().hash = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AvatarEntityIDs recentlyRemovedAvatarEntities = getAndClearRecentlyRemovedIDs();
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#include <workload/Space.h>
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "ui/overlays/Sphere3DOverlay.h"
|
||||
|
||||
class AvatarManager;
|
||||
class AvatarMotionState;
|
||||
|
@ -76,9 +74,18 @@ protected:
|
|||
void onAddAttachedAvatarEntity(const QUuid& id);
|
||||
void onRemoveAttachedAvatarEntity(const QUuid& id);
|
||||
|
||||
class AvatarEntityDataHash {
|
||||
public:
|
||||
AvatarEntityDataHash(uint32_t h) : hash(h) {};
|
||||
uint32_t hash { 0 };
|
||||
bool success { false };
|
||||
};
|
||||
|
||||
using MapOfAvatarEntityDataHashes = QMap<QUuid, AvatarEntityDataHash>;
|
||||
MapOfAvatarEntityDataHashes _avatarEntityDataHashes;
|
||||
|
||||
std::vector<QUuid> _attachedAvatarEntities;
|
||||
std::shared_ptr<Sphere3DOverlay> _otherAvatarOrbMeshPlaceholder { nullptr };
|
||||
OverlayID _otherAvatarOrbMeshPlaceholderID { UNKNOWN_OVERLAY_ID };
|
||||
QUuid _otherAvatarOrbMeshPlaceholderID;
|
||||
AvatarMotionState* _motionState { nullptr };
|
||||
std::vector<DetailedMotionState*> _detailedMotionStates;
|
||||
int32_t _spaceIndex { -1 };
|
||||
|
|
|
@ -194,7 +194,6 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
|
|||
_calibrationCount(0),
|
||||
_calibrationValues(),
|
||||
_calibrationBillboard(NULL),
|
||||
_calibrationBillboardID(UNKNOWN_OVERLAY_ID),
|
||||
_calibrationMessage(QString()),
|
||||
_isCalibrated(false)
|
||||
{
|
||||
|
@ -616,10 +615,6 @@ void DdeFaceTracker::setEyeClosingThreshold(float eyeClosingThreshold) {
|
|||
|
||||
static const int CALIBRATION_BILLBOARD_WIDTH = 300;
|
||||
static const int CALIBRATION_BILLBOARD_HEIGHT = 120;
|
||||
static const int CALIBRATION_BILLBOARD_TOP_MARGIN = 30;
|
||||
static const int CALIBRATION_BILLBOARD_LEFT_MARGIN = 30;
|
||||
static const int CALIBRATION_BILLBOARD_FONT_SIZE = 16;
|
||||
static const float CALIBRATION_BILLBOARD_ALPHA = 0.5f;
|
||||
static QString CALIBRATION_INSTRUCTION_MESSAGE = "Hold still to calibrate camera";
|
||||
|
||||
void DdeFaceTracker::calibrate() {
|
||||
|
@ -634,12 +629,8 @@ void DdeFaceTracker::calibrate() {
|
|||
_calibrationCount = 0;
|
||||
_calibrationMessage = CALIBRATION_INSTRUCTION_MESSAGE + "\n\n";
|
||||
|
||||
// FIXME: this overlay probably doesn't work anymore
|
||||
_calibrationBillboard = new TextOverlay();
|
||||
_calibrationBillboard->setTopMargin(CALIBRATION_BILLBOARD_TOP_MARGIN);
|
||||
_calibrationBillboard->setLeftMargin(CALIBRATION_BILLBOARD_LEFT_MARGIN);
|
||||
_calibrationBillboard->setFontSize(CALIBRATION_BILLBOARD_FONT_SIZE);
|
||||
_calibrationBillboard->setText(CALIBRATION_INSTRUCTION_MESSAGE);
|
||||
_calibrationBillboard->setAlpha(CALIBRATION_BILLBOARD_ALPHA);
|
||||
glm::vec2 viewport = qApp->getCanvasSize();
|
||||
_calibrationBillboard->setX((viewport.x - CALIBRATION_BILLBOARD_WIDTH) / 2);
|
||||
_calibrationBillboard->setY((viewport.y - CALIBRATION_BILLBOARD_HEIGHT) / 2);
|
||||
|
@ -659,10 +650,10 @@ void DdeFaceTracker::addCalibrationDatum() {
|
|||
int samplesLeft = CALIBRATION_SAMPLES - _calibrationCount;
|
||||
if (samplesLeft % LARGE_TICK_INTERVAL == 0) {
|
||||
_calibrationMessage += QString::number(samplesLeft / LARGE_TICK_INTERVAL);
|
||||
_calibrationBillboard->setText(_calibrationMessage);
|
||||
// FIXME: set overlay text
|
||||
} else if (samplesLeft % SMALL_TICK_INTERVAL == 0) {
|
||||
_calibrationMessage += ".";
|
||||
_calibrationBillboard->setText(_calibrationMessage);
|
||||
// FIXME: set overlay text
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
class DdeFaceTracker : public FaceTracker, public Dependency {
|
||||
|
@ -168,7 +169,7 @@ private:
|
|||
int _calibrationCount;
|
||||
QVector<float> _calibrationValues;
|
||||
TextOverlay* _calibrationBillboard;
|
||||
OverlayID _calibrationBillboardID;
|
||||
QUuid _calibrationBillboardID;
|
||||
QString _calibrationMessage;
|
||||
bool _isCalibrated;
|
||||
void addCalibrationDatum();
|
||||
|
|
|
@ -38,11 +38,13 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"OctreePacketProcessor::processPacket()");
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
const int WAY_BEHIND = 300;
|
||||
|
||||
if (packetsToProcessCount() > WAY_BEHIND && qApp->getLogger()->extraDebugging()) {
|
||||
qDebug("OctreePacketProcessor::processPacket() packets to process=%d", packetsToProcessCount());
|
||||
}
|
||||
#endif
|
||||
|
||||
bool wasStatsPacket = false;
|
||||
|
||||
|
|
|
@ -409,10 +409,6 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi
|
|||
return std::make_shared<CollisionPickResult>(pick, entityIntersections, std::vector<ContactTestResult>());
|
||||
}
|
||||
|
||||
PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) {
|
||||
return std::make_shared<CollisionPickResult>(pick, std::vector<ContactTestResult>(), std::vector<ContactTestResult>());
|
||||
}
|
||||
|
||||
PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pick) {
|
||||
if (!pick.loaded) {
|
||||
// Cannot compute result
|
||||
|
|
|
@ -54,7 +54,6 @@ public:
|
|||
return std::make_shared<CollisionPickResult>(pickVariant, std::vector<ContactTestResult>(), std::vector<ContactTestResult>());
|
||||
}
|
||||
PickResultPointer getEntityIntersection(const CollisionRegion& pick) override;
|
||||
PickResultPointer getOverlayIntersection(const CollisionRegion& pick) override;
|
||||
PickResultPointer getAvatarIntersection(const CollisionRegion& pick) override;
|
||||
PickResultPointer getHUDIntersection(const CollisionRegion& pick) override;
|
||||
Transform getResultTransform() const override;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "PickManager.h"
|
||||
#include "RayPick.h"
|
||||
|
||||
#include "PolyLineEntityItem.h"
|
||||
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
|
||||
const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalTime, bool centerEndY, bool lockEnd,
|
||||
bool distanceScaleEnd, bool scaleWithParent, bool enabled) :
|
||||
|
@ -28,7 +30,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
|
|||
void LaserPointer::editRenderStatePath(const std::string& state, const QVariant& pathProps) {
|
||||
auto renderState = std::static_pointer_cast<RenderState>(_renderStates[state]);
|
||||
if (renderState) {
|
||||
updateRenderStateOverlay(renderState->getPathID(), pathProps);
|
||||
updateRenderState(renderState->getPathID(), pathProps);
|
||||
QVariant lineWidth = pathProps.toMap()["lineWidth"];
|
||||
if (lineWidth.isValid()) {
|
||||
renderState->setLineWidth(lineWidth.toFloat());
|
||||
|
@ -121,48 +123,62 @@ void LaserPointer::setVisualPickResultInternal(PickResultPointer pickResult, Int
|
|||
}
|
||||
}
|
||||
|
||||
LaserPointer::RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) :
|
||||
LaserPointer::RenderState::RenderState(const QUuid& startID, const QUuid& pathID, const QUuid& endID) :
|
||||
StartEndRenderState(startID, endID), _pathID(pathID)
|
||||
{
|
||||
if (!_pathID.isNull()) {
|
||||
_pathIgnoreRays = qApp->getOverlays().getProperty(_pathID, "ignorePickIntersection").value.toBool();
|
||||
_lineWidth = qApp->getOverlays().getProperty(_pathID, "lineWidth").value.toFloat();
|
||||
if (!getPathID().isNull()) {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
{
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_IGNORE_PICK_INTERSECTION;
|
||||
_pathIgnorePicks = entityScriptingInterface->getEntityProperties(getPathID(), desiredProperties).getIgnorePickIntersection();
|
||||
}
|
||||
{
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_STROKE_WIDTHS;
|
||||
auto widths = entityScriptingInterface->getEntityProperties(getPathID(), desiredProperties).getStrokeWidths();
|
||||
_lineWidth = widths.length() == 0 ? PolyLineEntityItem::DEFAULT_LINE_WIDTH : widths[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointer::RenderState::cleanup() {
|
||||
StartEndRenderState::cleanup();
|
||||
if (!_pathID.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_pathID);
|
||||
if (!getPathID().isNull()) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(getPathID());
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointer::RenderState::disable() {
|
||||
StartEndRenderState::disable();
|
||||
if (!getPathID().isNull()) {
|
||||
QVariantMap pathProps;
|
||||
pathProps.insert("visible", false);
|
||||
pathProps.insert("ignorePickIntersection", true);
|
||||
qApp->getOverlays().editOverlay(getPathID(), pathProps);
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(false);
|
||||
properties.setIgnorePickIntersection(true);
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(getPathID(), properties);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
|
||||
StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
|
||||
QVariant endVariant = vec3toVariant(end);
|
||||
if (!getPathID().isNull()) {
|
||||
QVariantMap pathProps;
|
||||
pathProps.insert("start", vec3toVariant(origin));
|
||||
pathProps.insert("end", endVariant);
|
||||
pathProps.insert("visible", true);
|
||||
pathProps.insert("ignorePickIntersection", doesPathIgnoreRays());
|
||||
pathProps.insert("lineWidth", getLineWidth() * parentScale);
|
||||
qApp->getOverlays().editOverlay(getPathID(), pathProps);
|
||||
EntityItemProperties properties;
|
||||
QVector<glm::vec3> points;
|
||||
points.append(glm::vec3(0.0f));
|
||||
points.append(end - origin);
|
||||
properties.setPosition(origin);
|
||||
properties.setLinePoints(points);
|
||||
properties.setVisible(true);
|
||||
properties.setIgnorePickIntersection(doesPathIgnorePicks());
|
||||
QVector<float> widths;
|
||||
widths.append(getLineWidth() * parentScale);
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(getPathID(), properties);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<StartEndRenderState> LaserPointer::buildRenderState(const QVariantMap& propMap) {
|
||||
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
|
||||
QUuid startID;
|
||||
if (propMap["start"].isValid()) {
|
||||
QVariantMap startMap = propMap["start"].toMap();
|
||||
|
@ -232,9 +248,8 @@ PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const P
|
|||
glm::vec3 LaserPointer::findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction) {
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
case LOCAL_ENTITY:
|
||||
return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction);
|
||||
case OVERLAY:
|
||||
return RayPick::intersectRayWithOverlayXYPlane(pickedObject.objectID, origin, direction);
|
||||
default:
|
||||
return glm::vec3(NAN);
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ public:
|
|||
class RenderState : public StartEndRenderState {
|
||||
public:
|
||||
RenderState() {}
|
||||
RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID);
|
||||
RenderState(const QUuid& startID, const QUuid& pathID, const QUuid& endID);
|
||||
|
||||
const OverlayID& getPathID() const { return _pathID; }
|
||||
const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; }
|
||||
const QUuid& getPathID() const { return _pathID; }
|
||||
const bool& doesPathIgnorePicks() const { return _pathIgnorePicks; }
|
||||
|
||||
void setLineWidth(float width) { _lineWidth = width; }
|
||||
float getLineWidth() const { return _lineWidth; }
|
||||
|
@ -33,9 +33,9 @@ public:
|
|||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
|
||||
|
||||
private:
|
||||
OverlayID _pathID;
|
||||
bool _pathIgnoreRays;
|
||||
QUuid _pathID;
|
||||
|
||||
bool _pathIgnorePicks;
|
||||
float _lineWidth;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class LaserPointerScriptingInterface : public QObject, public Dependency {
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
public:
|
||||
|
||||
|
@ -111,10 +112,10 @@ public:
|
|||
* @function LaserPointers.setLockEndUUID
|
||||
* @param {number} id
|
||||
* @param {Uuid} itemID
|
||||
* @param {boolean} isOverlay
|
||||
* @param {boolean} isAvatar
|
||||
* @param {Mat4} [offsetMat]
|
||||
*/
|
||||
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay, offsetMat); }
|
||||
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); }
|
||||
|
||||
|
||||
/**jsdoc
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "Application.h"
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "PickScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "DependencyManager.h"
|
||||
|
@ -68,20 +67,15 @@ PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick)
|
|||
DependencyManager::get<EntityScriptingInterface>()->evalParabolaIntersectionVector(pick, searchFilter,
|
||||
getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
|
||||
if (entityRes.intersects) {
|
||||
return std::make_shared<ParabolaPickResult>(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.parabolicDistance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo);
|
||||
}
|
||||
}
|
||||
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
|
||||
}
|
||||
|
||||
PickResultPointer ParabolaPick::getOverlayIntersection(const PickParabola& pick) {
|
||||
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
|
||||
bool precisionPicking = !(getFilter().isCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
ParabolaToOverlayIntersectionResult overlayRes =
|
||||
qApp->getOverlays().findParabolaIntersectionVector(pick, precisionPicking,
|
||||
getIncludeItemsAs<OverlayID>(), getIgnoreItemsAs<OverlayID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (overlayRes.intersects) {
|
||||
return std::make_shared<ParabolaPickResult>(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.parabolicDistance, overlayRes.intersection, pick, overlayRes.surfaceNormal, overlayRes.extraInfo);
|
||||
IntersectionType type = IntersectionType::ENTITY;
|
||||
if (getFilter().doesPickLocalEntities()) {
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_ENTITY_HOST_TYPE;
|
||||
if (DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
|
||||
type = IntersectionType::LOCAL_ENTITY;
|
||||
}
|
||||
}
|
||||
return std::make_shared<ParabolaPickResult>(type, entityRes.entityID, entityRes.distance, entityRes.parabolicDistance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo);
|
||||
}
|
||||
}
|
||||
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <Pick.h>
|
||||
|
||||
class EntityItemID;
|
||||
class OverlayID;
|
||||
|
||||
class ParabolaPickResult : public PickResult {
|
||||
public:
|
||||
|
@ -80,7 +79,6 @@ public:
|
|||
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); }
|
||||
PickResultPointer getEntityIntersection(const PickParabola& pick) override;
|
||||
PickResultPointer getOverlayIntersection(const PickParabola& pick) override;
|
||||
PickResultPointer getAvatarIntersection(const PickParabola& pick) override;
|
||||
PickResultPointer getHUDIntersection(const PickParabola& pick) override;
|
||||
Transform getResultTransform() const override;
|
||||
|
|
|
@ -149,7 +149,7 @@ void ParabolaPointer::setVisualPickResultInternal(PickResultPointer pickResult,
|
|||
}
|
||||
}
|
||||
|
||||
ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth,
|
||||
ParabolaPointer::RenderState::RenderState(const QUuid& startID, const QUuid& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth,
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled) :
|
||||
StartEndRenderState(startID, endID)
|
||||
{
|
||||
|
@ -230,6 +230,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
|
|||
}
|
||||
|
||||
std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVariantMap& propMap) {
|
||||
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
|
||||
QUuid startID;
|
||||
if (propMap["start"].isValid()) {
|
||||
QVariantMap startMap = propMap["start"].toMap();
|
||||
|
@ -321,9 +322,8 @@ glm::vec3 ParabolaPointer::findIntersection(const PickedObject& pickedObject, co
|
|||
// TODO: implement
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
case LOCAL_ENTITY:
|
||||
//return ParabolaPick::intersectParabolaWithEntityXYPlane(pickedObject.objectID, origin, velocity, acceleration);
|
||||
case OVERLAY:
|
||||
//return ParabolaPick::intersectParabolaWithOverlayXYPlane(pickedObject.objectID, origin, velocity, acceleration);
|
||||
default:
|
||||
return glm::vec3(NAN);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "PathPointer.h"
|
||||
|
||||
#include <render/Item.h>
|
||||
|
||||
class ParabolaPointer : public PathPointer {
|
||||
using Parent = PathPointer;
|
||||
public:
|
||||
|
@ -79,7 +81,7 @@ public:
|
|||
};
|
||||
|
||||
RenderState() {}
|
||||
RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float parentScale,
|
||||
RenderState(const QUuid& startID, const QUuid& endID, const glm::vec3& pathColor, float pathAlpha, float parentScale,
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled);
|
||||
|
||||
void setPathWidth(float width) { _pathWidth = width; }
|
||||
|
|
|
@ -73,10 +73,10 @@ void PathPointer::setLength(float length) {
|
|||
});
|
||||
}
|
||||
|
||||
void PathPointer::setLockEndUUID(const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat) {
|
||||
void PathPointer::setLockEndUUID(const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat) {
|
||||
withWriteLock([&] {
|
||||
_lockEndObject.id = objectID;
|
||||
_lockEndObject.isOverlay = isOverlay;
|
||||
_lockEndObject.isAvatar = isAvatar;
|
||||
_lockEndObject.offsetMat = offsetMat;
|
||||
});
|
||||
}
|
||||
|
@ -97,12 +97,8 @@ PickResultPointer PathPointer::getVisualPickResult(const PickResultPointer& pick
|
|||
glm::quat rot;
|
||||
glm::vec3 dim;
|
||||
glm::vec3 registrationPoint;
|
||||
if (_lockEndObject.isOverlay) {
|
||||
pos = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "position").value);
|
||||
rot = quatFromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "rotation").value);
|
||||
dim = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "dimensions").value);
|
||||
registrationPoint = glm::vec3(0.5f);
|
||||
} else {
|
||||
// TODO: use isAvatar
|
||||
{
|
||||
EntityItemProperties props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(_lockEndObject.id);
|
||||
glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition());
|
||||
glm::mat4 finalPosAndRotMat = entityMat * _lockEndObject.offsetMat;
|
||||
|
@ -117,7 +113,7 @@ PickResultPointer PathPointer::getVisualPickResult(const PickResultPointer& pick
|
|||
distance = glm::distance(origin, endVec);
|
||||
glm::vec3 normalizedDirection = glm::normalize(direction);
|
||||
|
||||
type = _lockEndObject.isOverlay ? IntersectionType::OVERLAY : IntersectionType::ENTITY;
|
||||
type = IntersectionType::ENTITY;
|
||||
id = _lockEndObject.id;
|
||||
intersection = endVec;
|
||||
surfaceNormal = -normalizedDirection;
|
||||
|
@ -126,8 +122,6 @@ PickResultPointer PathPointer::getVisualPickResult(const PickResultPointer& pick
|
|||
id = getPickedObjectID(pickResult);
|
||||
if (type == IntersectionType::ENTITY) {
|
||||
endVec = DependencyManager::get<EntityScriptingInterface>()->getEntityTransform(id)[3];
|
||||
} else if (type == IntersectionType::OVERLAY) {
|
||||
endVec = vec3FromVariant(qApp->getOverlays().getProperty(id, "position").value);
|
||||
} else if (type == IntersectionType::AVATAR) {
|
||||
endVec = DependencyManager::get<AvatarHashMap>()->getAvatar(id)->getPosition();
|
||||
}
|
||||
|
@ -184,8 +178,8 @@ void PathPointer::editRenderState(const std::string& state, const QVariant& star
|
|||
withWriteLock([&] {
|
||||
auto renderState = _renderStates.find(state);
|
||||
if (renderState != _renderStates.end()) {
|
||||
updateRenderStateOverlay(renderState->second->getStartID(), startProps);
|
||||
updateRenderStateOverlay(renderState->second->getEndID(), endProps);
|
||||
updateRenderState(renderState->second->getStartID(), startProps);
|
||||
updateRenderState(renderState->second->getEndID(), endProps);
|
||||
QVariant startDim = startProps.toMap()["dimensions"];
|
||||
if (startDim.isValid()) {
|
||||
renderState->second->setStartDim(vec3FromVariant(startDim));
|
||||
|
@ -204,7 +198,8 @@ void PathPointer::editRenderState(const std::string& state, const QVariant& star
|
|||
});
|
||||
}
|
||||
|
||||
void PathPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) {
|
||||
void PathPointer::updateRenderState(const QUuid& id, const QVariant& props) {
|
||||
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
|
||||
if (!id.isNull() && props.isValid()) {
|
||||
QVariantMap propMap = props.toMap();
|
||||
propMap.remove("visible");
|
||||
|
@ -249,65 +244,79 @@ Pointer::Buttons PathPointer::getPressedButtons(const PickResultPointer& pickRes
|
|||
return toReturn;
|
||||
}
|
||||
|
||||
StartEndRenderState::StartEndRenderState(const OverlayID& startID, const OverlayID& endID) :
|
||||
StartEndRenderState::StartEndRenderState(const QUuid& startID, const QUuid& endID) :
|
||||
_startID(startID), _endID(endID) {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (!_startID.isNull()) {
|
||||
_startDim = vec3FromVariant(qApp->getOverlays().getProperty(_startID, "dimensions").value);
|
||||
_startIgnoreRays = qApp->getOverlays().getProperty(_startID, "ignorePickIntersection").value.toBool();
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_DIMENSIONS;
|
||||
desiredProperties += PROP_IGNORE_PICK_INTERSECTION;
|
||||
auto properties = entityScriptingInterface->getEntityProperties(_startID, desiredProperties);
|
||||
_startDim = properties.getDimensions();
|
||||
_startIgnorePicks = properties.getIgnorePickIntersection();
|
||||
}
|
||||
if (!_endID.isNull()) {
|
||||
_endDim = vec3FromVariant(qApp->getOverlays().getProperty(_endID, "dimensions").value);
|
||||
_endRot = quatFromVariant(qApp->getOverlays().getProperty(_endID, "rotation").value);
|
||||
_endIgnoreRays = qApp->getOverlays().getProperty(_endID, "ignorePickIntersection").value.toBool();
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_DIMENSIONS;
|
||||
desiredProperties += PROP_ROTATION;
|
||||
desiredProperties += PROP_IGNORE_PICK_INTERSECTION;
|
||||
auto properties = entityScriptingInterface->getEntityProperties(_endID, desiredProperties);
|
||||
_endDim = properties.getDimensions();
|
||||
_endRot = properties.getRotation();
|
||||
_endIgnorePicks = properties.getIgnorePickIntersection();
|
||||
}
|
||||
}
|
||||
|
||||
void StartEndRenderState::cleanup() {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (!_startID.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_startID);
|
||||
entityScriptingInterface->deleteEntity(_startID);
|
||||
}
|
||||
if (!_endID.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_endID);
|
||||
entityScriptingInterface->deleteEntity(_endID);
|
||||
}
|
||||
}
|
||||
|
||||
void StartEndRenderState::disable() {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (!getStartID().isNull()) {
|
||||
QVariantMap startProps;
|
||||
startProps.insert("visible", false);
|
||||
startProps.insert("ignorePickIntersection", true);
|
||||
qApp->getOverlays().editOverlay(getStartID(), startProps);
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(false);
|
||||
properties.setIgnorePickIntersection(true);
|
||||
entityScriptingInterface->editEntity(getStartID(), properties);
|
||||
}
|
||||
if (!getEndID().isNull()) {
|
||||
QVariantMap endProps;
|
||||
endProps.insert("visible", false);
|
||||
endProps.insert("ignorePickIntersection", true);
|
||||
qApp->getOverlays().editOverlay(getEndID(), endProps);
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(false);
|
||||
properties.setIgnorePickIntersection(true);
|
||||
entityScriptingInterface->editEntity(getEndID(), properties);
|
||||
}
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (!getStartID().isNull()) {
|
||||
QVariantMap startProps;
|
||||
startProps.insert("position", vec3toVariant(origin));
|
||||
startProps.insert("visible", true);
|
||||
startProps.insert("dimensions", vec3toVariant(getStartDim() * parentScale));
|
||||
startProps.insert("ignorePickIntersection", doesStartIgnoreRays());
|
||||
qApp->getOverlays().editOverlay(getStartID(), startProps);
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(origin);
|
||||
properties.setVisible(true);
|
||||
properties.setDimensions(getStartDim() * parentScale);
|
||||
properties.setIgnorePickIntersection(doesStartIgnorePicks());
|
||||
entityScriptingInterface->editEntity(getStartID(), properties);
|
||||
}
|
||||
|
||||
if (!getEndID().isNull()) {
|
||||
QVariantMap endProps;
|
||||
glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(getEndID(), "dimensions").value);
|
||||
EntityItemProperties properties;
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_DIMENSIONS;
|
||||
glm::vec3 dim;
|
||||
if (distanceScaleEnd) {
|
||||
dim = getEndDim() * glm::distance(origin, end);
|
||||
endProps.insert("dimensions", vec3toVariant(dim));
|
||||
} else {
|
||||
dim = getEndDim() * parentScale;
|
||||
endProps.insert("dimensions", vec3toVariant(dim));
|
||||
}
|
||||
properties.setDimensions(dim);
|
||||
|
||||
glm::quat normalQuat = Quat().lookAtSimple(Vectors::ZERO, surfaceNormal);
|
||||
normalQuat = normalQuat * glm::quat(glm::vec3(-M_PI_2, 0, 0));
|
||||
|
@ -343,11 +352,11 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end,
|
|||
_avgEndRot = rotation;
|
||||
}
|
||||
}
|
||||
endProps.insert("position", vec3toVariant(position));
|
||||
endProps.insert("rotation", quatToVariant(rotation));
|
||||
endProps.insert("visible", true);
|
||||
endProps.insert("ignorePickIntersection", doesEndIgnoreRays());
|
||||
qApp->getOverlays().editOverlay(getEndID(), endProps);
|
||||
properties.setPosition(position);
|
||||
properties.setRotation(rotation);
|
||||
properties.setVisible(true);
|
||||
properties.setIgnorePickIntersection(doesEndIgnorePicks());
|
||||
entityScriptingInterface->editEntity(getEndID(), properties);
|
||||
}
|
||||
_enabled = true;
|
||||
}
|
||||
|
@ -355,9 +364,8 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end,
|
|||
glm::vec2 PathPointer::findPos2D(const PickedObject& pickedObject, const glm::vec3& origin) {
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
case LOCAL_ENTITY:
|
||||
return RayPick::projectOntoEntityXYPlane(pickedObject.objectID, origin);
|
||||
case OVERLAY:
|
||||
return RayPick::projectOntoOverlayXYPlane(pickedObject.objectID, origin);
|
||||
case HUD:
|
||||
return DependencyManager::get<PickManager>()->calculatePos2DFromHUD(origin);
|
||||
default:
|
||||
|
|
|
@ -12,27 +12,25 @@
|
|||
#include <QString>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
#include <Pointer.h>
|
||||
#include <Pick.h>
|
||||
|
||||
struct LockEndObject {
|
||||
QUuid id { QUuid() };
|
||||
bool isOverlay { false };
|
||||
bool isAvatar { false };
|
||||
glm::mat4 offsetMat { glm::mat4() };
|
||||
};
|
||||
|
||||
class StartEndRenderState {
|
||||
public:
|
||||
StartEndRenderState() {}
|
||||
StartEndRenderState(const OverlayID& startID, const OverlayID& endID);
|
||||
StartEndRenderState(const QUuid& startID, const QUuid& endID);
|
||||
virtual ~StartEndRenderState() = default;
|
||||
|
||||
const OverlayID& getStartID() const { return _startID; }
|
||||
const OverlayID& getEndID() const { return _endID; }
|
||||
const bool& doesStartIgnoreRays() const { return _startIgnoreRays; }
|
||||
const bool& doesEndIgnoreRays() const { return _endIgnoreRays; }
|
||||
const QUuid& getStartID() const { return _startID; }
|
||||
const QUuid& getEndID() const { return _endID; }
|
||||
const bool& doesStartIgnorePicks() const { return _startIgnorePicks; }
|
||||
const bool& doesEndIgnorePicks() const { return _endIgnorePicks; }
|
||||
|
||||
void setStartDim(const glm::vec3& startDim) { _startDim = startDim; }
|
||||
const glm::vec3& getStartDim() const { return _startDim; }
|
||||
|
@ -51,10 +49,10 @@ public:
|
|||
bool isEnabled() const { return _enabled; }
|
||||
|
||||
protected:
|
||||
OverlayID _startID;
|
||||
OverlayID _endID;
|
||||
bool _startIgnoreRays;
|
||||
bool _endIgnoreRays;
|
||||
QUuid _startID;
|
||||
QUuid _endID;
|
||||
bool _startIgnorePicks;
|
||||
bool _endIgnorePicks;
|
||||
|
||||
glm::vec3 _startDim;
|
||||
glm::vec3 _endDim;
|
||||
|
@ -78,11 +76,11 @@ public:
|
|||
virtual ~PathPointer();
|
||||
|
||||
void setRenderState(const std::string& state) override;
|
||||
// You cannot use editRenderState to change the type of any part of the pointer. You can only edit the properties of the existing overlays.
|
||||
// You cannot use editRenderState to change the type of any part of the pointer. You can only edit the properties of the existing parts.
|
||||
void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) override;
|
||||
|
||||
void setLength(float length) override;
|
||||
void setLockEndUUID(const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) override;
|
||||
void setLockEndUUID(const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) override;
|
||||
|
||||
void updateVisuals(const PickResultPointer& prevRayPickResult) override;
|
||||
|
||||
|
@ -119,7 +117,7 @@ protected:
|
|||
bool shouldHover(const PickResultPointer& pickResult) override { return _currentRenderState != ""; }
|
||||
bool shouldTrigger(const PickResultPointer& pickResult) override { return _currentRenderState != ""; }
|
||||
|
||||
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
|
||||
void updateRenderState(const QUuid& id, const QVariant& props);
|
||||
virtual void editRenderStatePath(const std::string& state, const QVariant& pathProps) = 0;
|
||||
|
||||
PickedObject getHoveredObject(const PickResultPointer& pickResult) override;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "avatar/AvatarManager.h"
|
||||
#include "NestableTransformNode.h"
|
||||
#include "avatars-renderer/AvatarTransformNode.h"
|
||||
#include "ui/overlays/OverlayTransformNode.h"
|
||||
#include "EntityTransformNode.h"
|
||||
|
||||
#include <ScriptEngine.h>
|
||||
|
@ -61,7 +60,7 @@ PickFilter getPickFilter(unsigned int filter) {
|
|||
* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results.
|
||||
* @property {number} [filter=0] The filter for this Pick to use, constructed using filter flags combined using bitwise OR.
|
||||
* @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or a pick.
|
||||
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
|
||||
* @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Ray Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral
|
||||
|
@ -161,7 +160,7 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties
|
|||
* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results.
|
||||
* @property {number} [filter=0] The filter for this Pick to use, constructed using filter flags combined using bitwise OR.
|
||||
* @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or a pick.
|
||||
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
|
||||
* @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Parabola Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral
|
||||
|
@ -264,7 +263,7 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
|
|||
* The depth is measured in world space, but will scale with the parent if defined.
|
||||
* @property {CollisionMask} [collisionGroup=8] - The type of object this collision pick collides as. Objects whose collision masks overlap with the pick's collision group
|
||||
* will be considered colliding with the pick.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or a pick.
|
||||
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
|
||||
* @property {boolean} [scaleWithParent=true] If true, the collision pick's dimensions and threshold will adjust according to the scale of the parent.
|
||||
|
@ -415,8 +414,6 @@ void PickScriptingInterface::setParentTransform(std::shared_ptr<PickQuery> pick,
|
|||
NestableType nestableType = sharedNestablePointer->getNestableType();
|
||||
if (nestableType == NestableType::Avatar) {
|
||||
pick->parentTransform = std::make_shared<AvatarTransformNode>(std::static_pointer_cast<Avatar>(sharedNestablePointer), parentJointIndex);
|
||||
} else if (nestableType == NestableType::Overlay) {
|
||||
pick->parentTransform = std::make_shared<OverlayTransformNode>(std::static_pointer_cast<Base3DOverlay>(sharedNestablePointer), parentJointIndex);
|
||||
} else if (nestableType == NestableType::Entity) {
|
||||
pick->parentTransform = std::make_shared<EntityTransformNode>(std::static_pointer_cast<EntityItem>(sharedNestablePointer), parentJointIndex);
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} PICK_ENTITIES A filter flag. Include domain and avatar entities when intersecting. <em>Read-only.</em>. Deprecated.
|
||||
* @property {number} PICK_OVERLAYS A filter flag. Include local entities when intersecting. <em>Read-only.</em>. Deprecated.
|
||||
|
@ -46,7 +47,8 @@
|
|||
*
|
||||
* @property {number} INTERSECTED_NONE An intersection type. Intersected nothing with the given filter flags. <em>Read-only.</em>
|
||||
* @property {number} INTERSECTED_ENTITY An intersection type. Intersected an entity. <em>Read-only.</em>
|
||||
* @property {number} INTERSECTED_OVERLAY An intersection type. Intersected an overlay. <em>Read-only.</em>
|
||||
* @property {number} INTERSECTED_LOCAL_ENTITY An intersection type. Intersected a local entity.</em>
|
||||
* @property {number} INTERSECTED_OVERLAY An intersection type. Intersected an entity (3D Overlays no longer exist). <em>Read-only.</em>
|
||||
* @property {number} INTERSECTED_AVATAR An intersection type. Intersected an avatar. <em>Read-only.</em>
|
||||
* @property {number} INTERSECTED_HUD An intersection type. Intersected the HUD sphere. <em>Read-only.</em>
|
||||
* @property {number} perFrameTimeBudget - The max number of usec to spend per frame updating Pick results.
|
||||
|
@ -76,6 +78,7 @@ class PickScriptingInterface : public QObject, public Dependency {
|
|||
|
||||
Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT)
|
||||
|
@ -211,7 +214,7 @@ public:
|
|||
Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking);
|
||||
|
||||
/**jsdoc
|
||||
* Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to ignore during intersection. Not used by Stylus Picks.
|
||||
* Sets a list of Entity IDs and/or Avatar IDs to ignore during intersection. Not used by Stylus Picks.
|
||||
* @function Picks.setIgnoreItems
|
||||
* @param {number} uid The ID of the Pick, as returned by {@link Picks.createPick}.
|
||||
* @param {Uuid[]} ignoreItems A list of IDs to ignore.
|
||||
|
@ -219,7 +222,7 @@ public:
|
|||
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems);
|
||||
|
||||
/**jsdoc
|
||||
* Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus
|
||||
* Sets a list of Entity IDs and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus
|
||||
* Picks <b>only</b> intersect with objects in their include list.
|
||||
* @function Picks.setIncludeItems
|
||||
* @param {number} uid The ID of the Pick, as returned by {@link Picks.createPick}.
|
||||
|
@ -348,7 +351,13 @@ public slots:
|
|||
* @function Picks.INTERSECTED_OVERLAY
|
||||
* @returns {number}
|
||||
*/
|
||||
static constexpr unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; }
|
||||
static constexpr unsigned int INTERSECTED_LOCAL_ENTITY() { return IntersectionType::LOCAL_ENTITY; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Picks.INTERSECTED_OVERLAY
|
||||
* @returns {number}
|
||||
*/
|
||||
static constexpr unsigned int INTERSECTED_OVERLAY() { return INTERSECTED_LOCAL_ENTITY(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Picks.INTERSECTED_AVATAR
|
||||
|
|
|
@ -99,7 +99,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
|
|||
}
|
||||
}
|
||||
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<StylusPointer>(properties, StylusPointer::buildStylusOverlay(propertyMap), hover, enabled, modelPositionOffset,
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<StylusPointer>(properties, StylusPointer::buildStylus(propertyMap), hover, enabled, modelPositionOffset,
|
||||
modelRotationOffset, modelDimensions));
|
||||
}
|
||||
|
||||
|
@ -116,15 +116,15 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
|
|||
*
|
||||
* @typedef {object} Pointers.RayPointerRenderState
|
||||
* @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState}
|
||||
* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the beginning of the Ray Pointer,
|
||||
* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Ray Pointer,
|
||||
* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a <code>type</code> field).
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise.
|
||||
* @property {Overlays.OverlayProperties|QUuid} [path] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the path of the Ray Pointer,
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise.
|
||||
* @property {Overlays.OverlayProperties|QUuid} [path] When using {@link Pointers.createPointer}, an optionally defined object to represent the path of the Ray Pointer,
|
||||
* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a <code>type</code> field), which <b>must</b> be <code>"line3d"</code>.
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise.
|
||||
* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the end of the Ray Pointer,
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise.
|
||||
* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Ray Pointer,
|
||||
* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a <code>type</code> field).
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise.
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise.
|
||||
*/
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick.
|
||||
|
@ -271,14 +271,14 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
|||
*
|
||||
* @typedef {object} Pointers.ParabolaPointerRenderState
|
||||
* @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState}
|
||||
* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the beginning of the Parabola Pointer,
|
||||
* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Parabola Pointer,
|
||||
* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a <code>type</code> field).
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise.
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise.
|
||||
* @property {Pointers.ParabolaProperties} [path] When using {@link Pointers.createPointer}, the optionally defined rendering properties of the parabolic path defined by the Parabola Pointer.
|
||||
* Not defined in {@link Pointers.getPointerProperties}.
|
||||
* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the end of the Parabola Pointer,
|
||||
* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Parabola Pointer,
|
||||
* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a <code>type</code> field).
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise.
|
||||
* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise.
|
||||
*/
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick.
|
||||
|
|
|
@ -16,12 +16,13 @@
|
|||
|
||||
/**jsdoc
|
||||
* The Pointers API lets you create and manage objects for repeatedly calculating intersections in different ways, as well as the visual representation of those objects.
|
||||
* Pointers can also be configured to automatically generate {@link PointerEvent}s on {@link Entities} and {@link Overlays}.
|
||||
* Pointers can also be configured to automatically generate {@link PointerEvent}s on {@link Entities}.
|
||||
*
|
||||
* @namespace Pointers
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
class PointerScriptingInterface : public QObject, public Dependency {
|
||||
|
@ -39,7 +40,7 @@ public:
|
|||
* @typedef {object} Pointers.Trigger
|
||||
* @property {Controller.Standard|Controller.Actions|function} action This can be a built-in Controller action, like Controller.Standard.LTClick, or a function that evaluates to >= 1.0 when you want to trigger <code>button</code>.
|
||||
* @property {string} button Which button to trigger. "Primary", "Secondary", "Tertiary", and "Focus" are currently supported. Only "Primary" will trigger clicks on web surfaces. If "Focus" is triggered,
|
||||
* it will try to set the entity or overlay focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None".
|
||||
* it will try to set the entity focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None".
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
|
@ -153,7 +154,7 @@ public:
|
|||
Q_INVOKABLE void setLength(unsigned int uid, float length) const { DependencyManager::get<PointerManager>()->setLength(uid, length); }
|
||||
|
||||
/**jsdoc
|
||||
* Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to ignore during intersection. Not used by Stylus Pointers.
|
||||
* Sets a list of Entity IDs and/or Avatar IDs to ignore during intersection. Not used by Stylus Pointers.
|
||||
* @function Pointers.setIgnoreItems
|
||||
* @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}.
|
||||
* @param {Uuid[]} ignoreItems A list of IDs to ignore.
|
||||
|
@ -161,7 +162,7 @@ public:
|
|||
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const;
|
||||
|
||||
/**jsdoc
|
||||
* Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus
|
||||
* Sets a list of Entity IDs and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus
|
||||
* Pointers <b>only</b> intersect with objects in their include list.
|
||||
* @function Pointers.setIncludeItems
|
||||
* @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}.
|
||||
|
@ -171,15 +172,15 @@ public:
|
|||
|
||||
|
||||
/**jsdoc
|
||||
* Lock a Pointer onto a specific object (overlay, entity, or avatar). Optionally, provide an offset in object-space, otherwise the Pointer will lock on to the center of the object.
|
||||
* Lock a Pointer onto a specific object (entity or avatar). Optionally, provide an offset in object-space, otherwise the Pointer will lock on to the center of the object.
|
||||
* Not used by Stylus Pointers.
|
||||
* @function Pointers.setLockEndUUID
|
||||
* @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}.
|
||||
* @param {Uuid} objectID The ID of the object to which to lock on.
|
||||
* @param {boolean} isOverlay False for entities or avatars, true for overlays
|
||||
* @param {boolean} isAvatar False for entities, true for avatars
|
||||
* @param {Mat4} [offsetMat] The offset matrix to use if you do not want to lock on to the center of the object.
|
||||
*/
|
||||
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay, offsetMat); }
|
||||
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); }
|
||||
|
||||
|
||||
/**jsdoc
|
||||
|
@ -211,7 +212,7 @@ public:
|
|||
* @function Pointers.getPointerProperties
|
||||
* @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}.
|
||||
* @returns {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} The information about the Pointer.
|
||||
* Currently only includes renderStates and defaultRenderStates with associated overlay IDs.
|
||||
* Currently only includes renderStates and defaultRenderStates with associated entity IDs.
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const;
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "DependencyManager.h"
|
||||
|
@ -37,19 +36,15 @@ PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
|||
DependencyManager::get<EntityScriptingInterface>()->evalRayIntersectionVector(pick, searchFilter,
|
||||
getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
|
||||
if (entityRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) {
|
||||
bool precisionPicking = !(getFilter().isCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
RayToOverlayIntersectionResult overlayRes =
|
||||
qApp->getOverlays().findRayIntersectionVector(pick, precisionPicking,
|
||||
getIncludeItemsAs<OverlayID>(), getIgnoreItemsAs<OverlayID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (overlayRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, pick, overlayRes.surfaceNormal, overlayRes.extraInfo);
|
||||
IntersectionType type = IntersectionType::ENTITY;
|
||||
if (getFilter().doesPickLocalEntities()) {
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_ENTITY_HOST_TYPE;
|
||||
if (DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
|
||||
type = IntersectionType::LOCAL_ENTITY;
|
||||
}
|
||||
}
|
||||
return std::make_shared<RayPickResult>(type, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
|
@ -89,12 +84,6 @@ glm::vec3 RayPick::intersectRayWithXYPlane(const glm::vec3& origin, const glm::v
|
|||
return origin + t * direction;
|
||||
}
|
||||
|
||||
glm::vec3 RayPick::intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction) {
|
||||
glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value);
|
||||
glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value);
|
||||
return intersectRayWithXYPlane(origin, direction, position, rotation, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT);
|
||||
}
|
||||
|
||||
glm::vec3 RayPick::intersectRayWithEntityXYPlane(const QUuid& entityID, const glm::vec3& origin, const glm::vec3& direction) {
|
||||
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
return intersectRayWithXYPlane(origin, direction, props.getPosition(), props.getRotation(), props.getRegistrationPoint());
|
||||
|
@ -113,15 +102,12 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3
|
|||
return pos2D;
|
||||
}
|
||||
|
||||
glm::vec2 RayPick::projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos, bool unNormalized) {
|
||||
glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value);
|
||||
glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value);
|
||||
glm::vec3 dimensions = glm::vec3(vec2FromVariant(qApp->getOverlays().getProperty(overlayID, "dimensions").value), 0.01f);
|
||||
|
||||
return projectOntoXYPlane(worldPos, position, rotation, dimensions, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT, unNormalized);
|
||||
}
|
||||
|
||||
glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) {
|
||||
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_POSITION;
|
||||
desiredProperties += PROP_ROTATION;
|
||||
desiredProperties += PROP_DIMENSIONS;
|
||||
desiredProperties += PROP_REGISTRATION_POINT;
|
||||
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID, desiredProperties);
|
||||
return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <Pick.h>
|
||||
|
||||
class EntityItemID;
|
||||
class OverlayID;
|
||||
|
||||
class RayPickResult : public PickResult {
|
||||
public:
|
||||
|
@ -78,16 +77,13 @@ public:
|
|||
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<RayPickResult>(pickVariant); }
|
||||
PickResultPointer getEntityIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getOverlayIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getAvatarIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getHUDIntersection(const PickRay& pick) override;
|
||||
Transform getResultTransform() const override;
|
||||
|
||||
// These are helper functions for projecting and intersecting rays
|
||||
static glm::vec3 intersectRayWithEntityXYPlane(const QUuid& entityID, const glm::vec3& origin, const glm::vec3& direction);
|
||||
static glm::vec3 intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction);
|
||||
static glm::vec2 projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized = true);
|
||||
static glm::vec2 projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos, bool unNormalized = true);
|
||||
|
||||
private:
|
||||
static glm::vec3 intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat& rotation, const glm::vec3& registration);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} PICK_ENTITIES <em>Read-only.</em>
|
||||
* @property {number} PICK_OVERLAYS <em>Read-only.</em>
|
||||
|
@ -53,6 +54,7 @@ class RayPickScriptingInterface : public QObject, public Dependency {
|
|||
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT)
|
||||
|
@ -202,7 +204,13 @@ public slots:
|
|||
* @function RayPick.INTERSECTED_OVERLAY
|
||||
* @returns {number}
|
||||
*/
|
||||
static unsigned int INTERSECTED_OVERLAY() { return PickScriptingInterface::INTERSECTED_OVERLAY(); }
|
||||
static unsigned int INTERSECTED_LOCAL_ENTITY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function RayPick.INTERSECTED_OVERLAY
|
||||
* @returns {number}
|
||||
*/
|
||||
static unsigned int INTERSECTED_OVERLAY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function RayPick.INTERSECTED_AVATAR
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "ui/overlays/Base3DOverlay.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include <DependencyManager.h>
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
@ -20,6 +18,8 @@
|
|||
#include <controllers/StandardControls.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
|
||||
#include <EntityTreeElement.h>
|
||||
|
||||
using namespace bilateral;
|
||||
float StylusPick::WEB_STYLUS_LENGTH = 0.2f;
|
||||
|
||||
|
@ -148,7 +148,7 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!entity->getVisible() && !getFilter().doesPickInvisible()) {
|
||||
if (!EntityTreeElement::checkFilterSettings(entity, getFilter())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -161,47 +161,15 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) {
|
|||
|
||||
glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(target, intersection, false);
|
||||
if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) {
|
||||
results.push_back(StylusPickResult(IntersectionType::ENTITY, target, distance, intersection, pick, normal));
|
||||
}
|
||||
}
|
||||
|
||||
StylusPickResult nearestTarget(pick.toVariantMap());
|
||||
for (const auto& result : results) {
|
||||
if (result.distance < nearestTarget.distance) {
|
||||
nearestTarget = result;
|
||||
}
|
||||
}
|
||||
return std::make_shared<StylusPickResult>(nearestTarget);
|
||||
}
|
||||
|
||||
PickResultPointer StylusPick::getOverlayIntersection(const StylusTip& pick) {
|
||||
std::vector<StylusPickResult> results;
|
||||
for (const auto& target : getIncludeItems()) {
|
||||
if (target.isNull()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto overlay = qApp->getOverlays().getOverlay(target);
|
||||
// Don't interact with non-3D or invalid overlays
|
||||
if (!overlay || !overlay->is3D()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!overlay->getVisible() && !getFilter().doesPickInvisible()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto overlay3D = std::static_pointer_cast<Base3DOverlay>(overlay);
|
||||
const auto overlayRotation = overlay3D->getWorldOrientation();
|
||||
const auto overlayPosition = overlay3D->getWorldPosition();
|
||||
|
||||
glm::vec3 normal = overlayRotation * Vectors::UNIT_Z;
|
||||
float distance = glm::dot(pick.position - overlayPosition, normal);
|
||||
glm::vec3 intersection = pick.position - (normal * distance);
|
||||
|
||||
glm::vec2 pos2D = RayPick::projectOntoOverlayXYPlane(target, intersection, false);
|
||||
if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) {
|
||||
results.push_back(StylusPickResult(IntersectionType::OVERLAY, target, distance, intersection, pick, normal));
|
||||
IntersectionType type = IntersectionType::ENTITY;
|
||||
if (getFilter().doesPickLocalEntities()) {
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_ENTITY_HOST_TYPE;
|
||||
if (DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(target, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
|
||||
type = IntersectionType::LOCAL_ENTITY;
|
||||
}
|
||||
}
|
||||
results.push_back(StylusPickResult(type, target, distance, intersection, pick, normal));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ public:
|
|||
StylusTip getMathematicalPick() const override;
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override;
|
||||
PickResultPointer getEntityIntersection(const StylusTip& pick) override;
|
||||
PickResultPointer getOverlayIntersection(const StylusTip& pick) override;
|
||||
PickResultPointer getAvatarIntersection(const StylusTip& pick) override;
|
||||
PickResultPointer getHUDIntersection(const StylusTip& pick) override;
|
||||
Transform getResultTransform() const override;
|
||||
|
|
|
@ -27,10 +27,10 @@ static const float TOUCH_HYSTERESIS = 0.001f;
|
|||
|
||||
static const QString DEFAULT_STYLUS_MODEL_URL = PathUtils::resourcesUrl() + "/meshes/tablet-stylus-fat.fbx";
|
||||
|
||||
StylusPointer::StylusPointer(const QVariant& props, const OverlayID& stylusOverlay, bool hover, bool enabled,
|
||||
StylusPointer::StylusPointer(const QVariant& props, const QUuid& stylus, bool hover, bool enabled,
|
||||
const glm::vec3& modelPositionOffset, const glm::quat& modelRotationOffset, const glm::vec3& modelDimensions) :
|
||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createStylusPick(props), enabled, hover),
|
||||
_stylusOverlay(stylusOverlay),
|
||||
_stylus(stylus),
|
||||
_modelPositionOffset(modelPositionOffset),
|
||||
_modelDimensions(modelDimensions),
|
||||
_modelRotationOffset(modelRotationOffset)
|
||||
|
@ -38,13 +38,14 @@ StylusPointer::StylusPointer(const QVariant& props, const OverlayID& stylusOverl
|
|||
}
|
||||
|
||||
StylusPointer::~StylusPointer() {
|
||||
if (!_stylusOverlay.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_stylusOverlay);
|
||||
if (!_stylus.isNull()) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(_stylus);
|
||||
}
|
||||
}
|
||||
|
||||
OverlayID StylusPointer::buildStylusOverlay(const QVariantMap& properties) {
|
||||
QVariantMap overlayProperties;
|
||||
QUuid StylusPointer::buildStylus(const QVariantMap& properties) {
|
||||
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
|
||||
QVariantMap propertiesMap;
|
||||
|
||||
QString modelUrl = DEFAULT_STYLUS_MODEL_URL;
|
||||
|
||||
|
@ -56,15 +57,15 @@ OverlayID StylusPointer::buildStylusOverlay(const QVariantMap& properties) {
|
|||
}
|
||||
}
|
||||
// TODO: make these configurable per pointer
|
||||
overlayProperties["name"] = "stylus";
|
||||
overlayProperties["url"] = modelUrl;
|
||||
overlayProperties["loadPriority"] = 10.0f;
|
||||
overlayProperties["solid"] = true;
|
||||
overlayProperties["visible"] = false;
|
||||
overlayProperties["ignorePickIntersection"] = true;
|
||||
overlayProperties["drawInFront"] = false;
|
||||
propertiesMap["name"] = "stylus";
|
||||
propertiesMap["url"] = modelUrl;
|
||||
propertiesMap["loadPriority"] = 10.0f;
|
||||
propertiesMap["solid"] = true;
|
||||
propertiesMap["visible"] = false;
|
||||
propertiesMap["ignorePickIntersection"] = true;
|
||||
propertiesMap["drawInFront"] = false;
|
||||
|
||||
return qApp->getOverlays().addOverlay("model", overlayProperties);
|
||||
return qApp->getOverlays().addOverlay("model", propertiesMap);
|
||||
}
|
||||
|
||||
void StylusPointer::updateVisuals(const PickResultPointer& pickResult) {
|
||||
|
@ -83,25 +84,25 @@ void StylusPointer::updateVisuals(const PickResultPointer& pickResult) {
|
|||
}
|
||||
|
||||
void StylusPointer::show(const StylusTip& tip) {
|
||||
if (!_stylusOverlay.isNull()) {
|
||||
QVariantMap props;
|
||||
if (!_stylus.isNull()) {
|
||||
auto modelOrientation = tip.orientation * _modelRotationOffset;
|
||||
auto sensorToWorldScale = DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
||||
auto modelPositionOffset = modelOrientation * (_modelPositionOffset * sensorToWorldScale);
|
||||
props["position"] = vec3toVariant(tip.position + modelPositionOffset);
|
||||
props["rotation"] = quatToVariant(modelOrientation);
|
||||
props["dimensions"] = vec3toVariant(sensorToWorldScale * _modelDimensions);
|
||||
props["visible"] = true;
|
||||
qApp->getOverlays().editOverlay(_stylusOverlay, props);
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(tip.position + modelPositionOffset);
|
||||
properties.setRotation(modelOrientation);
|
||||
properties.setDimensions(sensorToWorldScale * _modelDimensions);
|
||||
properties.setVisible(true);
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_stylus, properties);
|
||||
}
|
||||
_showing = true;
|
||||
}
|
||||
|
||||
void StylusPointer::hide() {
|
||||
if (!_stylusOverlay.isNull()) {
|
||||
QVariantMap props;
|
||||
props.insert("visible", false);
|
||||
qApp->getOverlays().editOverlay(_stylusOverlay, props);
|
||||
if (!_stylus.isNull()) {
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(false);
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_stylus, properties);
|
||||
}
|
||||
_showing = false;
|
||||
}
|
||||
|
@ -234,9 +235,8 @@ QVariantMap StylusPointer::toVariantMap() const {
|
|||
glm::vec3 StylusPointer::findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction) {
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
case LOCAL_ENTITY:
|
||||
return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction);
|
||||
case OVERLAY:
|
||||
return RayPick::intersectRayWithOverlayXYPlane(pickedObject.objectID, origin, direction);
|
||||
default:
|
||||
return glm::vec3(NAN);
|
||||
}
|
||||
|
@ -245,9 +245,8 @@ glm::vec3 StylusPointer::findIntersection(const PickedObject& pickedObject, cons
|
|||
glm::vec2 StylusPointer::findPos2D(const PickedObject& pickedObject, const glm::vec3& origin) {
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
case LOCAL_ENTITY:
|
||||
return RayPick::projectOntoEntityXYPlane(pickedObject.objectID, origin);
|
||||
case OVERLAY:
|
||||
return RayPick::projectOntoOverlayXYPlane(pickedObject.objectID, origin);
|
||||
case HUD:
|
||||
return DependencyManager::get<PickManager>()->calculatePos2DFromHUD(origin);
|
||||
default:
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include <shared/Bilateral.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
#include "StylusPick.h"
|
||||
|
||||
class StylusPointer : public Pointer {
|
||||
|
@ -21,7 +19,7 @@ class StylusPointer : public Pointer {
|
|||
using Ptr = std::shared_ptr<StylusPointer>;
|
||||
|
||||
public:
|
||||
StylusPointer(const QVariant& props, const OverlayID& stylusOverlay, bool hover, bool enabled,
|
||||
StylusPointer(const QVariant& props, const QUuid& stylus, bool hover, bool enabled,
|
||||
const glm::vec3& modelPositionOffset, const glm::quat& modelRotationOffset, const glm::vec3& modelDimensions);
|
||||
~StylusPointer();
|
||||
|
||||
|
@ -36,7 +34,7 @@ public:
|
|||
|
||||
QVariantMap toVariantMap() const override;
|
||||
|
||||
static OverlayID buildStylusOverlay(const QVariantMap& properties);
|
||||
static QUuid buildStylus(const QVariantMap& properties);
|
||||
|
||||
protected:
|
||||
PickedObject getHoveredObject(const PickResultPointer& pickResult) override;
|
||||
|
@ -74,7 +72,7 @@ private:
|
|||
|
||||
RenderState _renderState { EVENTS_ON };
|
||||
|
||||
const OverlayID _stylusOverlay;
|
||||
QUuid _stylus;
|
||||
|
||||
static bool isWithinBounds(float distance, float min, float max, float hysteresis);
|
||||
static glm::vec3 findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction);
|
||||
|
|
|
@ -42,6 +42,7 @@ class AccountServicesScriptingInterface : public QObject {
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @namespace AccountServices
|
||||
* @property {string} username <em>Read-only.</em>
|
||||
|
|
|
@ -32,6 +32,7 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
* @hifi-server-entity
|
||||
* @hifi-assignment-client
|
||||
*
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
class ClipboardScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -199,6 +199,7 @@ class ScriptEngine;
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end
|
||||
* points in a {@link RouteObject} mapping. A synonym for <code>Controller.Hardware.Actions</code>.
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
*
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} width
|
||||
* @property {number} height
|
||||
* @property {number} ALWAYS_ON_TOP - InteractiveWindow flag for always showing a window on top
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
class GooglePolyScriptingInterface : public QObject, public Dependency {
|
||||
|
|
|
@ -31,6 +31,7 @@ class QScriptEngine;
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise
|
||||
* {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
|
||||
|
@ -53,12 +54,12 @@ class QScriptEngine;
|
|||
* @property {boolean} tabletContextualMode - <code>true</code> if the tablet has been opened in contextual mode, otherwise
|
||||
* <code>false</code>. In contextual mode, the tablet has been opened at a specific world position and orientation rather
|
||||
* than at a position and orientation relative to the user. <em>Read-only.</em>
|
||||
* @property {Uuid} tabletID - The UUID of the tablet body model overlay.
|
||||
* @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay.
|
||||
* @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay.
|
||||
* @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight overlay.
|
||||
* @property {Uuid} miniTabletID - The UUID of the mini tablet's body model overlay. <code>null</code> if not in HMD mode.
|
||||
* @property {Uuid} miniTabletScreenID - The UUID of the mini tablet's screen overlay. <code>null</code> if not in HMD mode.
|
||||
* @property {Uuid} tabletID - The UUID of the tablet body model entity.
|
||||
* @property {Uuid} tabletScreenID - The UUID of the tablet's screen entity.
|
||||
* @property {Uuid} homeButtonID - The UUID of the tablet's "home" button entity.
|
||||
* @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight entity.
|
||||
* @property {Uuid} miniTabletID - The UUID of the mini tablet's body model entity. <code>null</code> if not in HMD mode.
|
||||
* @property {Uuid} miniTabletScreenID - The UUID of the mini tablet's screen entity. <code>null</code> if not in HMD mode.
|
||||
* @property {number} miniTabletHand - The hand that the mini tablet is displayed on: <code>0</code> for left hand,
|
||||
* <code>1</code> for right hand, <code>-1</code> if not in HMD mode.
|
||||
* @property {bool} miniTabletEnabled=true - <code>true</code> if the mini tablet is enabled to be displayed, otherwise
|
||||
|
|
|
@ -64,6 +64,6 @@ bool KeyboardScriptingInterface::getPreferMalletsOverLasers() const {
|
|||
return DependencyManager::get<Keyboard>()->getPreferMalletsOverLasers();
|
||||
}
|
||||
|
||||
bool KeyboardScriptingInterface::containsID(OverlayID overlayID) const {
|
||||
return DependencyManager::get<Keyboard>()->containsID(overlayID);
|
||||
bool KeyboardScriptingInterface::containsID(const QUuid& id) const {
|
||||
return DependencyManager::get<Keyboard>()->containsID(id);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <QtCore/QUuid>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
/**jsdoc
|
||||
* The Keyboard API provides facilities to use 3D Physical keyboard.
|
||||
|
@ -24,6 +23,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {bool} raised - <code>true</code> If the keyboard is visible <code>false</code> otherwise
|
||||
* @property {bool} password - <code>true</code> Will show * instead of characters in the text display <code>false</code> otherwise
|
||||
|
@ -46,7 +46,7 @@ public:
|
|||
Q_INVOKABLE void disableRightMallet();
|
||||
Q_INVOKABLE void setLeftHandLaser(unsigned int leftHandLaser);
|
||||
Q_INVOKABLE void setRightHandLaser(unsigned int rightHandLaser);
|
||||
Q_INVOKABLE bool containsID(OverlayID overlayID) const;
|
||||
Q_INVOKABLE bool containsID(const QUuid& overlayID) const;
|
||||
private:
|
||||
bool getPreferMalletsOverLasers() const;
|
||||
bool isRaised() const;
|
||||
|
|
|
@ -35,6 +35,7 @@ class MenuItemProperties;
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,19 +40,6 @@ bool GameplayObjects::removeFromGameplayObjects(const EntityItemID& entityID) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GameplayObjects::addToGameplayObjects(const OverlayID& overlayID) {
|
||||
containsData = true;
|
||||
if (std::find(_overlayIDs.begin(), _overlayIDs.end(), overlayID) == _overlayIDs.end()) {
|
||||
_overlayIDs.push_back(overlayID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool GameplayObjects::removeFromGameplayObjects(const OverlayID& overlayID) {
|
||||
_overlayIDs.erase(std::remove(_overlayIDs.begin(), _overlayIDs.end(), overlayID), _overlayIDs.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SelectionScriptingInterface::SelectionScriptingInterface() {
|
||||
}
|
||||
|
||||
|
@ -64,7 +51,6 @@ SelectionScriptingInterface::SelectionScriptingInterface() {
|
|||
* <tbody>
|
||||
* <tr><td><code>"avatar"</code></td><td></td></tr>
|
||||
* <tr><td><code>"entity"</code></td><td></td></tr>
|
||||
* <tr><td><code>"overlay"</code></td><td></td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Selection.ItemType
|
||||
|
@ -72,20 +58,16 @@ SelectionScriptingInterface::SelectionScriptingInterface() {
|
|||
bool SelectionScriptingInterface::addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
|
||||
if (itemType == "avatar") {
|
||||
return addToGameplayObjects(listName, (QUuid)id);
|
||||
} else if (itemType == "entity") {
|
||||
} else if (itemType == "entity" || itemType == "overlay") {
|
||||
return addToGameplayObjects(listName, (EntityItemID)id);
|
||||
} else if (itemType == "overlay") {
|
||||
return addToGameplayObjects(listName, (OverlayID)id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool SelectionScriptingInterface::removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
|
||||
if (itemType == "avatar") {
|
||||
return removeFromGameplayObjects(listName, (QUuid)id);
|
||||
} else if (itemType == "entity") {
|
||||
} else if (itemType == "entity" || itemType == "overlay") {
|
||||
return removeFromGameplayObjects(listName, (EntityItemID)id);
|
||||
} else if (itemType == "overlay") {
|
||||
return removeFromGameplayObjects(listName, (OverlayID)id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -253,12 +235,6 @@ void SelectionScriptingInterface::printList(const QString& listName) {
|
|||
qDebug() << j << ';';
|
||||
}
|
||||
qDebug() << "";
|
||||
|
||||
qDebug() << "Overlay IDs:";
|
||||
for (auto k : (*currentList).getOverlayIDs()) {
|
||||
qDebug() << k << ';';
|
||||
}
|
||||
qDebug() << "";
|
||||
}
|
||||
else {
|
||||
qDebug() << "List named " << listName << " empty";
|
||||
|
@ -272,7 +248,6 @@ void SelectionScriptingInterface::printList(const QString& listName) {
|
|||
* @typedef {object} Selection.SelectedItemsList
|
||||
* @property {Uuid[]} avatars - The IDs of the avatars in the selection.
|
||||
* @property {Uuid[]} entities - The IDs of the entities in the selection.
|
||||
* @property {Uuid[]} overlays - The IDs of the overlays in the selection.
|
||||
*/
|
||||
QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const {
|
||||
QReadLocker lock(&_selectionListsLock);
|
||||
|
@ -281,7 +256,6 @@ QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& lis
|
|||
if (currentList != _selectedItemsListMap.end()) {
|
||||
QList<QVariant> avatarIDs;
|
||||
QList<QVariant> entityIDs;
|
||||
QList<QVariant> overlayIDs;
|
||||
|
||||
if ((*currentList).getContainsData()) {
|
||||
if (!(*currentList).getAvatarIDs().empty()) {
|
||||
|
@ -294,15 +268,9 @@ QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& lis
|
|||
entityIDs.push_back((QUuid)j );
|
||||
}
|
||||
}
|
||||
if (!(*currentList).getOverlayIDs().empty()) {
|
||||
for (auto j : (*currentList).getOverlayIDs()) {
|
||||
overlayIDs.push_back((QUuid)j);
|
||||
}
|
||||
}
|
||||
}
|
||||
list["avatars"] = (avatarIDs);
|
||||
list["entities"] = (entityIDs);
|
||||
list["overlays"] = (overlayIDs);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -379,7 +347,6 @@ void SelectionToSceneHandler::updateSceneFromSelectedList() {
|
|||
render::ItemIDs finalList;
|
||||
render::ItemID currentID;
|
||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
auto& overlays = qApp->getOverlays();
|
||||
|
||||
for (QUuid& currentAvatarID : thisList.getAvatarIDs()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(DependencyManager::get<AvatarManager>()->getAvatarBySessionID(currentAvatarID));
|
||||
|
@ -398,16 +365,6 @@ void SelectionToSceneHandler::updateSceneFromSelectedList() {
|
|||
}
|
||||
}
|
||||
|
||||
for (OverlayID& currentOverlayID : thisList.getOverlayIDs()) {
|
||||
auto overlay = overlays.getOverlay(currentOverlayID);
|
||||
if (overlay != NULL) {
|
||||
currentID = overlay->getRenderItemID();
|
||||
if (currentID != render::Item::INVALID_ITEM_ID) {
|
||||
finalList.push_back(currentID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render::Selection selection(_listName.toStdString(), finalList);
|
||||
transaction.resetSelection(selection);
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <AbstractViewStateInterface.h>
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <render/HighlightStyle.h>
|
||||
|
||||
|
@ -37,15 +36,10 @@ public:
|
|||
bool addToGameplayObjects(const EntityItemID& entityID);
|
||||
bool removeFromGameplayObjects(const EntityItemID& entityID);
|
||||
|
||||
std::vector<OverlayID> getOverlayIDs() const { return _overlayIDs; }
|
||||
bool addToGameplayObjects(const OverlayID& overlayID);
|
||||
bool removeFromGameplayObjects(const OverlayID& overlayID);
|
||||
|
||||
private:
|
||||
bool containsData { false };
|
||||
std::vector<QUuid> _avatarIDs;
|
||||
std::vector<EntityItemID> _entityIDs;
|
||||
std::vector<OverlayID> _overlayIDs;
|
||||
};
|
||||
|
||||
|
||||
|
@ -83,11 +77,12 @@ protected:
|
|||
};
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Selection</code> API provides a means of grouping together avatars, entities, and overlays in named lists.
|
||||
* The <code>Selection</code> API provides a means of grouping together avatars and entities in named lists.
|
||||
* @namespace Selection
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @example <caption>Outline an entity when it is grabbed by a controller.</caption>
|
||||
* // Create a box and copy the following text into the entity's "Script URL" field.
|
||||
|
@ -174,14 +169,14 @@ public:
|
|||
Q_INVOKABLE bool clearSelectedItemsList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Print out the list of avatars, entities, and overlays in a selection to the <em>debug log</em> (not the script log).
|
||||
* Print out the list of avatars and entities in a selection to the <em>debug log</em> (not the script log).
|
||||
* @function Selection.printList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
*/
|
||||
Q_INVOKABLE void printList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Get the list of avatars, entities, and overlays stored in a selection list.
|
||||
* Get the list of avatars and entities stored in a selection list.
|
||||
* @function Selection.getSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
class SettingsScriptingInterface : public QObject {
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} walletStatus
|
||||
* @property {bool} limitedCommerce
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other
|
||||
* chrome), in pixels. <em>Read-only.</em>
|
||||
|
|
|
@ -90,7 +90,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(app, __FUNCTION__);
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
|
||||
if (!_uiTexture) {
|
||||
_uiTexture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
|
||||
|
@ -119,7 +119,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(app, __FUNCTION__);
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -134,9 +134,7 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) {
|
|||
batch.resetViewTransform();
|
||||
|
||||
// Render all of the Script based "HUD" aka 2D overlays.
|
||||
// note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the
|
||||
// cameral controls for the edit.js
|
||||
qApp->getOverlays().renderHUD(renderArgs);
|
||||
qApp->getOverlays().render(renderArgs);
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderArgs) {
|
||||
|
@ -178,7 +176,7 @@ static const auto DEFAULT_SAMPLER = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LI
|
|||
static const auto DEPTH_FORMAT = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
|
||||
|
||||
void ApplicationOverlay::buildFramebufferObject() {
|
||||
PROFILE_RANGE(app, __FUNCTION__);
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
|
||||
auto uiSize = glm::uvec2(qApp->getUiSize());
|
||||
if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) {
|
||||
|
|
|
@ -29,6 +29,7 @@ class AvatarInputs : public QObject {
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {boolean} cameraEnabled <em>Read-only.</em>
|
||||
* @property {boolean} cameraMuted <em>Read-only.</em>
|
||||
|
|
|
@ -57,7 +57,7 @@ void DialogsManager::showAddressBar() {
|
|||
if (!hmd->getShouldShowTablet()) {
|
||||
hmd->openTablet();
|
||||
}
|
||||
qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID());
|
||||
qApp->setKeyboardFocusEntity(hmd->getCurrentTabletScreenID());
|
||||
setAddressBarVisible(true);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ void DialogsManager::hideAddressBar() {
|
|||
tablet->gotoHomeScreen();
|
||||
hmd->closeTablet();
|
||||
}
|
||||
qApp->setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||
qApp->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
setAddressBarVisible(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,6 @@
|
|||
#include <RegisteredMetaTypes.h>
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
#include "ui/overlays/ModelOverlay.h"
|
||||
#include "ui/overlays/Cube3DOverlay.h"
|
||||
#include "ui/overlays/Text3DOverlay.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
@ -120,21 +115,21 @@ std::pair<glm::vec3, glm::quat> calculateKeyboardPositionAndOrientation() {
|
|||
float sensorToWorldScale = myAvatar->getSensorToWorldScale();
|
||||
QUuid tabletID = hmd->getCurrentTabletFrameID();
|
||||
if (!tabletID.isNull() && hmd->getShouldShowTablet()) {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto tabletOverlay = std::dynamic_pointer_cast<Base3DOverlay>(overlays.getOverlay(tabletID));
|
||||
if (tabletOverlay) {
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||
bool landscapeMode = tablet->getLandscape();
|
||||
glm::vec3 keyboardOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_OFFSET : KEYBOARD_TABLET_OFFSET;
|
||||
glm::vec3 keyboardDegreesOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_DEGREES_OFFSET : KEYBOARD_TABLET_DEGREES_OFFSET;
|
||||
glm::vec3 tabletWorldPosition = tabletOverlay->getWorldPosition();
|
||||
glm::quat tabletWorldOrientation = tabletOverlay->getWorldOrientation();
|
||||
glm::vec3 scaledKeyboardTabletOffset = keyboardOffset * sensorToWorldScale;
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_POSITION;
|
||||
desiredProperties += PROP_ROTATION;
|
||||
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(tabletID, desiredProperties);
|
||||
|
||||
keyboardLocation.first = tabletWorldPosition + (tabletWorldOrientation * scaledKeyboardTabletOffset);
|
||||
keyboardLocation.second = tabletWorldOrientation * glm::quat(glm::radians(keyboardDegreesOffset));
|
||||
}
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||
bool landscapeMode = tablet->getLandscape();
|
||||
glm::vec3 keyboardOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_OFFSET : KEYBOARD_TABLET_OFFSET;
|
||||
glm::vec3 keyboardDegreesOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_DEGREES_OFFSET : KEYBOARD_TABLET_DEGREES_OFFSET;
|
||||
glm::vec3 tabletWorldPosition = properties.getPosition();
|
||||
glm::quat tabletWorldOrientation = properties.getRotation();
|
||||
glm::vec3 scaledKeyboardTabletOffset = keyboardOffset * sensorToWorldScale;
|
||||
|
||||
keyboardLocation.first = tabletWorldPosition + (tabletWorldOrientation * scaledKeyboardTabletOffset);
|
||||
keyboardLocation.second = tabletWorldOrientation * glm::quat(glm::radians(keyboardDegreesOffset));
|
||||
} else {
|
||||
glm::vec3 avatarWorldPosition = myAvatar->getWorldPosition();
|
||||
glm::quat avatarWorldOrientation = myAvatar->getWorldOrientation();
|
||||
|
@ -148,31 +143,27 @@ std::pair<glm::vec3, glm::quat> calculateKeyboardPositionAndOrientation() {
|
|||
}
|
||||
|
||||
void Key::saveDimensionsAndLocalPosition() {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto model3DOverlay = std::dynamic_pointer_cast<ModelOverlay>(overlays.getOverlay(_keyID));
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_LOCAL_POSITION;
|
||||
desiredProperties += PROP_DIMENSIONS;
|
||||
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(_keyID, desiredProperties);
|
||||
|
||||
if (model3DOverlay) {
|
||||
_originalLocalPosition = model3DOverlay->getLocalPosition();
|
||||
_originalDimensions = model3DOverlay->getDimensions();
|
||||
_currentLocalPosition = _originalLocalPosition;
|
||||
}
|
||||
_originalLocalPosition = properties.getLocalPosition();
|
||||
_originalDimensions = properties.getDimensions();
|
||||
_currentLocalPosition = _originalLocalPosition;
|
||||
_originalDimensionsAndLocalPositionSaved = true;
|
||||
}
|
||||
|
||||
void Key::scaleKey(float sensorToWorldScale) {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto model3DOverlay = std::dynamic_pointer_cast<ModelOverlay>(overlays.getOverlay(_keyID));
|
||||
|
||||
if (model3DOverlay) {
|
||||
if (_originalDimensionsAndLocalPositionSaved) {
|
||||
glm::vec3 scaledLocalPosition = _originalLocalPosition * sensorToWorldScale;
|
||||
glm::vec3 scaledDimensions = _originalDimensions * sensorToWorldScale;
|
||||
_currentLocalPosition = scaledLocalPosition;
|
||||
|
||||
QVariantMap properties {
|
||||
{ "dimensions", vec3toVariant(scaledDimensions) },
|
||||
{ "localPosition", vec3toVariant(scaledLocalPosition) }
|
||||
};
|
||||
|
||||
overlays.editOverlay(_keyID, properties);
|
||||
EntityItemProperties properties;
|
||||
properties.setDimensions(scaledDimensions);
|
||||
properties.setLocalPosition(scaledLocalPosition);
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_keyID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,6 +232,18 @@ void Keyboard::registerKeyboardHighlighting() {
|
|||
selection->enableListToScene(KEY_PRESSED_HIGHLIGHT);
|
||||
}
|
||||
|
||||
void Keyboard::disableSelectionLists() {
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
selection->disableListHighlight(KEY_HOVER_HIGHLIGHT);
|
||||
selection->disableListHighlight(KEY_PRESSED_HIGHLIGHT);
|
||||
}
|
||||
|
||||
void Keyboard::enableSelectionLists() {
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
selection->enableListHighlight(KEY_HOVER_HIGHLIGHT, KEY_HOVERING_STYLE);
|
||||
selection->enableListHighlight(KEY_PRESSED_HIGHLIGHT, KEY_PRESSING_STYLE);
|
||||
}
|
||||
|
||||
bool Keyboard::getUse3DKeyboard() const {
|
||||
return _use3DKeyboardLock.resultWithReadLock<bool>([&] {
|
||||
return _use3DKeyboard.get();
|
||||
|
@ -262,21 +265,21 @@ void Keyboard::createKeyboard() {
|
|||
|
||||
QVariantMap leftStylusProperties {
|
||||
{ "hand", LEFT_HAND_CONTROLLER_INDEX },
|
||||
{ "filter", PickScriptingInterface::PICK_OVERLAYS() },
|
||||
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
|
||||
{ "model", modelProperties },
|
||||
{ "tipOffset", vec3toVariant(MALLET_TIP_OFFSET) }
|
||||
};
|
||||
|
||||
QVariantMap rightStylusProperties {
|
||||
{ "hand", RIGHT_HAND_CONTROLLER_INDEX },
|
||||
{ "filter", PickScriptingInterface::PICK_OVERLAYS() },
|
||||
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
|
||||
{ "model", modelProperties },
|
||||
{ "tipOffset", vec3toVariant(MALLET_TIP_OFFSET) }
|
||||
};
|
||||
|
||||
_leftHandStylus = pointerManager->addPointer(std::make_shared<StylusPointer>(leftStylusProperties, StylusPointer::buildStylusOverlay(leftStylusProperties), true, true,
|
||||
_leftHandStylus = pointerManager->addPointer(std::make_shared<StylusPointer>(leftStylusProperties, StylusPointer::buildStylus(leftStylusProperties), true, true,
|
||||
MALLET_POSITION_OFFSET, MALLET_ROTATION_OFFSET, MALLET_MODEL_DIMENSIONS));
|
||||
_rightHandStylus = pointerManager->addPointer(std::make_shared<StylusPointer>(rightStylusProperties, StylusPointer::buildStylusOverlay(rightStylusProperties), true, true,
|
||||
_rightHandStylus = pointerManager->addPointer(std::make_shared<StylusPointer>(rightStylusProperties, StylusPointer::buildStylus(rightStylusProperties), true, true,
|
||||
MALLET_POSITION_OFFSET, MALLET_ROTATION_OFFSET, MALLET_MODEL_DIMENSIONS));
|
||||
|
||||
pointerManager->disablePointer(_rightHandStylus);
|
||||
|
@ -300,6 +303,7 @@ void Keyboard::setRaised(bool raised) {
|
|||
raiseKeyboardAnchor(raised);
|
||||
raiseKeyboard(raised);
|
||||
raised ? enableStylus() : disableStylus();
|
||||
raised ? enableSelectionLists() : disableSelectionLists();
|
||||
withWriteLock([&] {
|
||||
_raised = raised;
|
||||
_layerIndex = 0;
|
||||
|
@ -312,93 +316,65 @@ void Keyboard::setRaised(bool raised) {
|
|||
}
|
||||
|
||||
void Keyboard::updateTextDisplay() {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
float sensorToWorldScale = myAvatar->getSensorToWorldScale();
|
||||
float textWidth = (float) overlays.textSize(_textDisplay.overlayID, _typedCharacters).width();
|
||||
float textWidth = (float)entityScriptingInterface->textSize(_textDisplay.entityID, _typedCharacters).width();
|
||||
|
||||
glm::vec3 scaledDimensions = _textDisplay.dimensions;
|
||||
scaledDimensions *= sensorToWorldScale;
|
||||
float leftMargin = (scaledDimensions.x / 2);
|
||||
scaledDimensions.x += textWidth;
|
||||
scaledDimensions.y *= 1.25f;
|
||||
|
||||
|
||||
QVariantMap textDisplayProperties {
|
||||
{ "dimensions", vec3toVariant(scaledDimensions) },
|
||||
{ "leftMargin", leftMargin },
|
||||
{ "text", _typedCharacters },
|
||||
{ "lineHeight", (_textDisplay.lineHeight * sensorToWorldScale) }
|
||||
};
|
||||
|
||||
overlays.editOverlay(_textDisplay.overlayID, textDisplayProperties);
|
||||
EntityItemProperties properties;
|
||||
properties.setDimensions(scaledDimensions);
|
||||
properties.setLeftMargin(leftMargin);
|
||||
properties.setText(_typedCharacters);
|
||||
properties.setLineHeight(_textDisplay.lineHeight * sensorToWorldScale);
|
||||
entityScriptingInterface->editEntity(_textDisplay.entityID, properties);
|
||||
}
|
||||
|
||||
void Keyboard::raiseKeyboardAnchor(bool raise) const {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
OverlayID anchorOverlayID = _anchor.overlayID;
|
||||
auto anchorOverlay = std::dynamic_pointer_cast<Cube3DOverlay>(overlays.getOverlay(anchorOverlayID));
|
||||
if (anchorOverlay) {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(raise);
|
||||
|
||||
entityScriptingInterface->editEntity(_textDisplay.entityID, properties);
|
||||
entityScriptingInterface->editEntity(_backPlate.entityID, properties);
|
||||
|
||||
if (_resetKeyboardPositionOnRaise) {
|
||||
std::pair<glm::vec3, glm::quat> keyboardLocation = calculateKeyboardPositionAndOrientation();
|
||||
if (_resetKeyboardPositionOnRaise) {
|
||||
anchorOverlay->setWorldPosition(keyboardLocation.first);
|
||||
anchorOverlay->setWorldOrientation(keyboardLocation.second);
|
||||
}
|
||||
anchorOverlay->setVisible(raise);
|
||||
|
||||
QVariantMap textDisplayProperties {
|
||||
{ "visible", raise }
|
||||
};
|
||||
|
||||
overlays.editOverlay(_textDisplay.overlayID, textDisplayProperties);
|
||||
|
||||
auto backPlateOverlay = std::dynamic_pointer_cast<Cube3DOverlay>(overlays.getOverlay(_backPlate.overlayID));
|
||||
|
||||
if (backPlateOverlay) {
|
||||
backPlateOverlay->setVisible(raise);
|
||||
}
|
||||
properties.setPosition(keyboardLocation.first);
|
||||
properties.setRotation(keyboardLocation.second);
|
||||
}
|
||||
entityScriptingInterface->editEntity(_anchor.entityID, properties);
|
||||
}
|
||||
|
||||
void Keyboard::scaleKeyboard(float sensorToWorldScale) {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
||||
glm::vec3 scaledDimensions = _anchor.originalDimensions * sensorToWorldScale;
|
||||
auto volume3DOverlay = std::dynamic_pointer_cast<Volume3DOverlay>(overlays.getOverlay(_anchor.overlayID));
|
||||
|
||||
if (volume3DOverlay) {
|
||||
volume3DOverlay->setDimensions(scaledDimensions);
|
||||
{
|
||||
EntityItemProperties properties;
|
||||
properties.setLocalPosition(_backPlate.localPosition * sensorToWorldScale);
|
||||
properties.setDimensions(_backPlate.dimensions * sensorToWorldScale);
|
||||
entityScriptingInterface->editEntity(_backPlate.entityID, properties);
|
||||
}
|
||||
|
||||
for (auto& keyboardLayer: _keyboardLayers) {
|
||||
for (auto& keyboardLayer : _keyboardLayers) {
|
||||
for (auto iter = keyboardLayer.begin(); iter != keyboardLayer.end(); iter++) {
|
||||
iter.value().scaleKey(sensorToWorldScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 scaledLocalPosition = _textDisplay.localPosition * sensorToWorldScale;
|
||||
glm::vec3 textDisplayScaledDimensions = _textDisplay.dimensions * sensorToWorldScale;
|
||||
|
||||
QVariantMap textDisplayProperties {
|
||||
{ "localPosition", vec3toVariant(scaledLocalPosition) },
|
||||
{ "dimensions", vec3toVariant(textDisplayScaledDimensions) },
|
||||
{ "lineHeight", (_textDisplay.lineHeight * sensorToWorldScale) }
|
||||
};
|
||||
|
||||
overlays.editOverlay(_textDisplay.overlayID, textDisplayProperties);
|
||||
|
||||
|
||||
glm::vec3 backPlateScaledDimensions = _backPlate.dimensions * sensorToWorldScale;
|
||||
glm::vec3 backPlateScaledLocalPosition = _backPlate.localPosition * sensorToWorldScale;
|
||||
|
||||
QVariantMap backPlateProperties {
|
||||
{ "localPosition", vec3toVariant(backPlateScaledLocalPosition) },
|
||||
{ "dimensions", vec3toVariant(backPlateScaledDimensions) }
|
||||
};
|
||||
|
||||
overlays.editOverlay(_backPlate.overlayID, backPlateProperties);
|
||||
{
|
||||
EntityItemProperties properties;
|
||||
properties.setLocalPosition(_textDisplay.localPosition * sensorToWorldScale);
|
||||
properties.setDimensions(_textDisplay.dimensions * sensorToWorldScale);
|
||||
properties.setLineHeight(_textDisplay.lineHeight * sensorToWorldScale);
|
||||
entityScriptingInterface->editEntity(_textDisplay.entityID, properties);
|
||||
}
|
||||
}
|
||||
|
||||
void Keyboard::startLayerSwitchTimer() {
|
||||
|
@ -419,13 +395,12 @@ void Keyboard::raiseKeyboard(bool raise) const {
|
|||
if (_keyboardLayers.empty()) {
|
||||
return;
|
||||
}
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
|
||||
const auto& keyboardLayer = _keyboardLayers[_layerIndex];
|
||||
EntityItemProperties properties;
|
||||
properties.setVisible(raise);
|
||||
for (auto iter = keyboardLayer.begin(); iter != keyboardLayer.end(); iter++) {
|
||||
auto base3DOverlay = std::dynamic_pointer_cast<Base3DOverlay>(overlays.getOverlay(iter.key()));
|
||||
if (base3DOverlay) {
|
||||
base3DOverlay->setVisible(raise);
|
||||
}
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(iter.key(), properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,19 +440,15 @@ bool Keyboard::getPreferMalletsOverLasers() const {
|
|||
}
|
||||
|
||||
void Keyboard::switchToLayer(int layerIndex) {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
if (layerIndex >= 0 && layerIndex < (int)_keyboardLayers.size()) {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_POSITION;
|
||||
desiredProperties += PROP_ROTATION;
|
||||
auto oldProperties = entityScriptingInterface->getEntityProperties(_anchor.entityID, desiredProperties);
|
||||
|
||||
OverlayID currentAnchorOverlayID = _anchor.overlayID;
|
||||
|
||||
glm::vec3 currentOverlayPosition;
|
||||
glm::quat currentOverlayOrientation;
|
||||
|
||||
auto currentAnchorOverlay = std::dynamic_pointer_cast<Cube3DOverlay>(overlays.getOverlay(currentAnchorOverlayID));
|
||||
if (currentAnchorOverlay) {
|
||||
currentOverlayPosition = currentAnchorOverlay->getWorldPosition();
|
||||
currentOverlayOrientation = currentAnchorOverlay->getWorldOrientation();
|
||||
}
|
||||
glm::vec3 currentPosition = oldProperties.getPosition();
|
||||
glm::quat currentOrientation = oldProperties.getRotation();
|
||||
|
||||
raiseKeyboardAnchor(false);
|
||||
raiseKeyboard(false);
|
||||
|
@ -487,19 +458,17 @@ void Keyboard::switchToLayer(int layerIndex) {
|
|||
raiseKeyboardAnchor(true);
|
||||
raiseKeyboard(true);
|
||||
|
||||
OverlayID newAnchorOverlayID = _anchor.overlayID;
|
||||
auto newAnchorOverlay = std::dynamic_pointer_cast<Cube3DOverlay>(overlays.getOverlay(newAnchorOverlayID));
|
||||
if (newAnchorOverlay) {
|
||||
newAnchorOverlay->setWorldPosition(currentOverlayPosition);
|
||||
newAnchorOverlay->setWorldOrientation(currentOverlayOrientation);
|
||||
}
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(currentPosition);
|
||||
properties.setRotation(currentOrientation);
|
||||
entityScriptingInterface->editEntity(_anchor.entityID, properties);
|
||||
|
||||
startLayerSwitchTimer();
|
||||
}
|
||||
}
|
||||
|
||||
bool Keyboard::shouldProcessOverlayAndPointerEvent(const PointerEvent& event, const OverlayID& overlayID) const {
|
||||
return (shouldProcessPointerEvent(event) && shouldProcessOverlay(overlayID));
|
||||
bool Keyboard::shouldProcessEntityAndPointerEvent(const PointerEvent& event) const {
|
||||
return (shouldProcessPointerEvent(event) && shouldProcessEntity());
|
||||
}
|
||||
|
||||
bool Keyboard::shouldProcessPointerEvent(const PointerEvent& event) const {
|
||||
|
@ -510,14 +479,14 @@ bool Keyboard::shouldProcessPointerEvent(const PointerEvent& event) const {
|
|||
return ((isStylusEvent && preferMalletsOverLasers) || (isLaserEvent && !preferMalletsOverLasers));
|
||||
}
|
||||
|
||||
void Keyboard::handleTriggerBegin(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
void Keyboard::handleTriggerBegin(const QUuid& id, const PointerEvent& event) {
|
||||
auto buttonType = event.getButton();
|
||||
if (!shouldProcessOverlayAndPointerEvent(event, overlayID) || buttonType != PointerEvent::PrimaryButton) {
|
||||
if (!shouldProcessEntityAndPointerEvent(event) || buttonType != PointerEvent::PrimaryButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& keyboardLayer = _keyboardLayers[_layerIndex];
|
||||
auto search = keyboardLayer.find(overlayID);
|
||||
auto search = keyboardLayer.find(id);
|
||||
|
||||
if (search == keyboardLayer.end()) {
|
||||
return;
|
||||
|
@ -533,13 +502,9 @@ void Keyboard::handleTriggerBegin(const OverlayID& overlayID, const PointerEvent
|
|||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->triggerHapticPulse(PULSE_STRENGTH, PULSE_DURATION, handIndex);
|
||||
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto base3DOverlay = std::dynamic_pointer_cast<Base3DOverlay>(overlays.getOverlay(overlayID));
|
||||
|
||||
glm::vec3 keyWorldPosition;
|
||||
if (base3DOverlay) {
|
||||
keyWorldPosition = base3DOverlay->getWorldPosition();
|
||||
}
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_POSITION;
|
||||
glm::vec3 keyWorldPosition = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getPosition();
|
||||
|
||||
AudioInjectorOptions audioOptions;
|
||||
audioOptions.localOnly = true;
|
||||
|
@ -601,7 +566,7 @@ void Keyboard::handleTriggerBegin(const OverlayID& overlayID, const PointerEvent
|
|||
key.startTimer(KEY_PRESS_TIMEOUT_MS);
|
||||
}
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
selection->addToSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "overlay", overlayID);
|
||||
selection->addToSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "entity", id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,25 +582,23 @@ void Keyboard::setRightHandLaser(unsigned int rightHandLaser) {
|
|||
});
|
||||
}
|
||||
|
||||
void Keyboard::handleTriggerEnd(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) {
|
||||
void Keyboard::handleTriggerEnd(const QUuid& id, const PointerEvent& event) {
|
||||
if (!shouldProcessEntityAndPointerEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& keyboardLayer = _keyboardLayers[_layerIndex];
|
||||
auto search = keyboardLayer.find(overlayID);
|
||||
auto search = keyboardLayer.find(id);
|
||||
|
||||
if (search == keyboardLayer.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Key& key = search.value();;
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto base3DOverlay = std::dynamic_pointer_cast<Base3DOverlay>(overlays.getOverlay(overlayID));
|
||||
Key& key = search.value();
|
||||
|
||||
if (base3DOverlay) {
|
||||
base3DOverlay->setLocalPosition(key.getCurrentLocalPosition());
|
||||
}
|
||||
EntityItemProperties properties;
|
||||
properties.setLocalPosition(key.getCurrentLocalPosition());
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(id, properties);
|
||||
|
||||
key.setIsPressed(false);
|
||||
if (key.timerFinished() && getPreferMalletsOverLasers()) {
|
||||
|
@ -643,78 +606,79 @@ void Keyboard::handleTriggerEnd(const OverlayID& overlayID, const PointerEvent&
|
|||
}
|
||||
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
selection->removeFromSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "overlay", overlayID);
|
||||
selection->removeFromSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "entity", id);
|
||||
}
|
||||
|
||||
void Keyboard::handleTriggerContinue(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) {
|
||||
void Keyboard::handleTriggerContinue(const QUuid& id, const PointerEvent& event) {
|
||||
if (!shouldProcessEntityAndPointerEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& keyboardLayer = _keyboardLayers[_layerIndex];
|
||||
auto search = keyboardLayer.find(overlayID);
|
||||
auto search = keyboardLayer.find(id);
|
||||
|
||||
if (search == keyboardLayer.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Key& key = search.value();
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
|
||||
if (!key.isPressed() && getPreferMalletsOverLasers()) {
|
||||
auto base3DOverlay = std::dynamic_pointer_cast<Base3DOverlay>(overlays.getOverlay(overlayID));
|
||||
unsigned int pointerID = event.getID();
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
auto pickResult = pointerManager->getPrevPickResult(pointerID);
|
||||
auto stylusPickResult = std::dynamic_pointer_cast<StylusPickResult>(pickResult);
|
||||
float distance = stylusPickResult->distance;
|
||||
|
||||
if (base3DOverlay) {
|
||||
unsigned int pointerID = event.getID();
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
auto pickResult = pointerManager->getPrevPickResult(pointerID);
|
||||
auto stylusPickResult = std::dynamic_pointer_cast<StylusPickResult>(pickResult);
|
||||
float distance = stylusPickResult->distance;
|
||||
static const float PENETRATION_THRESHOLD = 0.025f;
|
||||
if (distance < PENETRATION_THRESHOLD) {
|
||||
static const float Z_OFFSET = 0.002f;
|
||||
|
||||
static const float PENATRATION_THRESHOLD = 0.025f;
|
||||
if (distance < PENATRATION_THRESHOLD) {
|
||||
static const float Z_OFFSET = 0.002f;
|
||||
glm::quat overlayOrientation = base3DOverlay->getWorldOrientation();
|
||||
glm::vec3 overlayYAxis = overlayOrientation * Z_AXIS;
|
||||
glm::vec3 overlayYOffset = overlayYAxis * Z_OFFSET;
|
||||
glm::vec3 localPosition = key.getCurrentLocalPosition() - overlayYOffset;
|
||||
base3DOverlay->setLocalPosition(localPosition);
|
||||
key.setIsPressed(true);
|
||||
}
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_ROTATION;
|
||||
glm::quat orientation = entityScriptingInterface->getEntityProperties(id, desiredProperties).getRotation();
|
||||
glm::vec3 yAxis = orientation * Z_AXIS;
|
||||
glm::vec3 yOffset = yAxis * Z_OFFSET;
|
||||
glm::vec3 localPosition = key.getCurrentLocalPosition() - yOffset;
|
||||
|
||||
EntityItemProperties properties;
|
||||
properties.setLocalPosition(localPosition);
|
||||
entityScriptingInterface->editEntity(id, properties);
|
||||
key.setIsPressed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Keyboard::handleHoverBegin(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) {
|
||||
void Keyboard::handleHoverBegin(const QUuid& id, const PointerEvent& event) {
|
||||
if (!shouldProcessEntityAndPointerEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& keyboardLayer = _keyboardLayers[_layerIndex];
|
||||
auto search = keyboardLayer.find(overlayID);
|
||||
auto search = keyboardLayer.find(id);
|
||||
|
||||
if (search == keyboardLayer.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
selection->addToSelectedItemsList(KEY_HOVER_HIGHLIGHT, "overlay", overlayID);
|
||||
selection->addToSelectedItemsList(KEY_HOVER_HIGHLIGHT, "entity", id);
|
||||
}
|
||||
|
||||
void Keyboard::handleHoverEnd(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) {
|
||||
void Keyboard::handleHoverEnd(const QUuid& id, const PointerEvent& event) {
|
||||
if (!shouldProcessEntityAndPointerEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& keyboardLayer = _keyboardLayers[_layerIndex];
|
||||
auto search = keyboardLayer.find(overlayID);
|
||||
auto search = keyboardLayer.find(id);
|
||||
|
||||
if (search == keyboardLayer.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
selection->removeFromSelectedItemsList(KEY_HOVER_HIGHLIGHT, "overlay", overlayID);
|
||||
selection->removeFromSelectedItemsList(KEY_HOVER_HIGHLIGHT, "entity", id);
|
||||
}
|
||||
|
||||
void Keyboard::disableStylus() {
|
||||
|
@ -752,7 +716,6 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
}
|
||||
|
||||
clearKeyboardKeys();
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
auto requestData = request->getData();
|
||||
|
||||
QVector<QUuid> includeItems;
|
||||
|
@ -776,54 +739,60 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
return;
|
||||
}
|
||||
|
||||
QVariantMap anchorProperties {
|
||||
{ "name", "KeyboardAnchor"},
|
||||
{ "isSolid", true },
|
||||
{ "visible", false },
|
||||
{ "grabbable", true },
|
||||
{ "ignorePickIntersection", false },
|
||||
{ "dimensions", anchorObject["dimensions"].toVariant() },
|
||||
{ "position", anchorObject["position"].toVariant() },
|
||||
{ "orientation", anchorObject["rotation"].toVariant() }
|
||||
};
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
{
|
||||
glm::vec3 dimensions = vec3FromVariant(anchorObject["dimensions"].toVariant());
|
||||
|
||||
glm::vec3 dimensions = vec3FromVariant(anchorObject["dimensions"].toVariant());
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Box);
|
||||
properties.setName("KeyboardAnchor");
|
||||
properties.setVisible(false);
|
||||
properties.getGrab().setGrabbable(true);
|
||||
properties.setIgnorePickIntersection(false);
|
||||
properties.setDimensions(dimensions);
|
||||
properties.setPosition(vec3FromVariant(anchorObject["position"].toVariant()));
|
||||
properties.setRotation(quatFromVariant(anchorObject["rotation"].toVariant()));
|
||||
|
||||
Anchor anchor;
|
||||
anchor.overlayID = overlays.addOverlay("cube", anchorProperties);
|
||||
anchor.originalDimensions = dimensions;
|
||||
_anchor = anchor;
|
||||
Anchor anchor;
|
||||
anchor.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
anchor.originalDimensions = dimensions;
|
||||
_anchor = anchor;
|
||||
}
|
||||
|
||||
QJsonObject backPlateObject = jsonObject["backPlate"].toObject();
|
||||
{
|
||||
QJsonObject backPlateObject = jsonObject["backPlate"].toObject();
|
||||
glm::vec3 position = vec3FromVariant(backPlateObject["position"].toVariant());
|
||||
glm::vec3 dimensions = vec3FromVariant(backPlateObject["dimensions"].toVariant());
|
||||
glm::quat rotation = quatFromVariant(backPlateObject["rotation"].toVariant());
|
||||
|
||||
QVariantMap backPlateProperties {
|
||||
{ "name", "backPlate"},
|
||||
{ "isSolid", true },
|
||||
{ "visible", true },
|
||||
{ "grabbable", false },
|
||||
{ "alpha", 0.0 },
|
||||
{ "ignoreRayIntersection", false},
|
||||
{ "dimensions", backPlateObject["dimensions"].toVariant() },
|
||||
{ "position", backPlateObject["position"].toVariant() },
|
||||
{ "orientation", backPlateObject["rotation"].toVariant() },
|
||||
{ "parentID", _anchor.overlayID }
|
||||
};
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Box);
|
||||
properties.setName("Keyboard-BackPlate");
|
||||
properties.setVisible(true);
|
||||
properties.getGrab().setGrabbable(false);
|
||||
properties.setAlpha(0.0f);
|
||||
properties.setIgnorePickIntersection(false);
|
||||
properties.setDimensions(dimensions);
|
||||
properties.setPosition(position);
|
||||
properties.setRotation(rotation);
|
||||
properties.setParentID(_anchor.entityID);
|
||||
|
||||
BackPlate backPlate;
|
||||
backPlate.overlayID = overlays.addOverlay("cube", backPlateProperties);
|
||||
backPlate.dimensions = vec3FromVariant(backPlateObject["dimensions"].toVariant());
|
||||
backPlate.localPosition = vec3FromVariant(overlays.getProperty(backPlate.overlayID, "localPosition").value);
|
||||
_backPlate = backPlate;
|
||||
BackPlate backPlate;
|
||||
backPlate.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
backPlate.dimensions = dimensions;
|
||||
glm::quat anchorEntityInverseWorldOrientation = glm::inverse(rotation);
|
||||
glm::vec3 anchorEntityLocalTranslation = anchorEntityInverseWorldOrientation * -position;
|
||||
backPlate.localPosition = (anchorEntityInverseWorldOrientation * position) + anchorEntityLocalTranslation;
|
||||
_backPlate = backPlate;
|
||||
}
|
||||
|
||||
const QJsonArray& keyboardLayers = jsonObject["layers"].toArray();
|
||||
int keyboardLayerCount = keyboardLayers.size();
|
||||
_keyboardLayers.reserve(keyboardLayerCount);
|
||||
|
||||
|
||||
for (int keyboardLayerIndex = 0; keyboardLayerIndex < keyboardLayerCount; keyboardLayerIndex++) {
|
||||
const QJsonValue& keyboardLayer = keyboardLayers[keyboardLayerIndex].toArray();
|
||||
|
||||
QHash<OverlayID, Key> keyboardLayerKeys;
|
||||
QHash<QUuid, Key> keyboardLayerKeys;
|
||||
foreach (const QJsonValue& keyboardKeyValue, keyboardLayer.toArray()) {
|
||||
|
||||
QVariantMap textureMap;
|
||||
|
@ -841,20 +810,18 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
QString modelUrl = keyboardKeyValue["modelURL"].toString();
|
||||
QString url = (useResourcePath ? (resourcePath + modelUrl) : modelUrl);
|
||||
|
||||
QVariantMap properties {
|
||||
{ "dimensions", keyboardKeyValue["dimensions"].toVariant() },
|
||||
{ "position", keyboardKeyValue["position"].toVariant() },
|
||||
{ "visible", false },
|
||||
{ "isSolid", true },
|
||||
{ "emissive", true },
|
||||
{ "parentID", _anchor.overlayID },
|
||||
{ "url", url },
|
||||
{ "textures", textureMap },
|
||||
{ "grabbable", false },
|
||||
{ "localOrientation", keyboardKeyValue["localOrientation"].toVariant() }
|
||||
};
|
||||
|
||||
OverlayID overlayID = overlays.addOverlay("model", properties);
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Model);
|
||||
properties.setDimensions(vec3FromVariant(keyboardKeyValue["dimensions"].toVariant()));
|
||||
properties.setPosition(vec3FromVariant(keyboardKeyValue["position"].toVariant()));
|
||||
properties.setVisible(false);
|
||||
properties.setEmissive(true);
|
||||
properties.setParentID(_anchor.entityID);
|
||||
properties.setModelURL(url);
|
||||
properties.setTextures(QString(QJsonDocument::fromVariant(textureMap).toJson()));
|
||||
properties.getGrab().setGrabbable(false);
|
||||
properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant()));
|
||||
QUuid id = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
|
||||
QString keyType = keyboardKeyValue["type"].toString();
|
||||
QString keyString = keyboardKeyValue["key"].toString();
|
||||
|
@ -869,48 +836,54 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
key.setSwitchToLayerIndex(switchToLayer);
|
||||
}
|
||||
}
|
||||
key.setID(overlayID);
|
||||
key.setID(id);
|
||||
key.setKeyString(keyString);
|
||||
key.saveDimensionsAndLocalPosition();
|
||||
|
||||
includeItems.append(key.getID());
|
||||
_itemsToIgnore.append(key.getID());
|
||||
keyboardLayerKeys.insert(overlayID, key);
|
||||
_itemsToIgnore.insert(key.getID());
|
||||
keyboardLayerKeys.insert(id, key);
|
||||
}
|
||||
|
||||
_keyboardLayers.push_back(keyboardLayerKeys);
|
||||
|
||||
}
|
||||
|
||||
TextDisplay textDisplay;
|
||||
QJsonObject displayTextObject = jsonObject["textDisplay"].toObject();
|
||||
{
|
||||
QJsonObject displayTextObject = jsonObject["textDisplay"].toObject();
|
||||
glm::vec3 dimensions = vec3FromVariant(displayTextObject["dimensions"].toVariant());
|
||||
glm::vec3 localPosition = vec3FromVariant(displayTextObject["localPosition"].toVariant());
|
||||
float lineHeight = (float)displayTextObject["lineHeight"].toDouble();
|
||||
|
||||
QVariantMap displayTextProperties {
|
||||
{ "dimensions", displayTextObject["dimensions"].toVariant() },
|
||||
{ "localPosition", displayTextObject["localPosition"].toVariant() },
|
||||
{ "localOrientation", displayTextObject["localOrientation"].toVariant() },
|
||||
{ "leftMargin", displayTextObject["leftMargin"].toVariant() },
|
||||
{ "rightMargin", displayTextObject["rightMargin"].toVariant() },
|
||||
{ "topMargin", displayTextObject["topMargin"].toVariant() },
|
||||
{ "bottomMargin", displayTextObject["bottomMargin"].toVariant() },
|
||||
{ "lineHeight", displayTextObject["lineHeight"].toVariant() },
|
||||
{ "visible", false },
|
||||
{ "emissive", true },
|
||||
{ "grabbable", false },
|
||||
{ "text", ""},
|
||||
{ "parentID", _anchor.overlayID }
|
||||
};
|
||||
EntityItemProperties properties;
|
||||
properties.setType(EntityTypes::Text);
|
||||
properties.setDimensions(dimensions);
|
||||
properties.setLocalPosition(localPosition);
|
||||
properties.setLocalRotation(quatFromVariant(displayTextObject["localOrientation"].toVariant()));
|
||||
properties.setLeftMargin((float)displayTextObject["leftMargin"].toDouble());
|
||||
properties.setRightMargin((float)displayTextObject["rightMargin"].toDouble());
|
||||
properties.setTopMargin((float)displayTextObject["topMargin"].toDouble());
|
||||
properties.setBottomMargin((float)displayTextObject["bottomMargin"].toDouble());
|
||||
properties.setLineHeight((float)displayTextObject["lineHeight"].toDouble());
|
||||
properties.setVisible(false);
|
||||
properties.setEmissive(true);
|
||||
properties.getGrab().setGrabbable(false);
|
||||
properties.setText("");
|
||||
properties.setTextAlpha(1.0f);
|
||||
properties.setBackgroundAlpha(0.7f);
|
||||
properties.setParentID(_anchor.entityID);
|
||||
|
||||
textDisplay.overlayID = overlays.addOverlay("text3d", displayTextProperties);
|
||||
textDisplay.localPosition = vec3FromVariant(displayTextObject["localPosition"].toVariant());
|
||||
textDisplay.dimensions = vec3FromVariant(displayTextObject["dimensions"].toVariant());
|
||||
textDisplay.lineHeight = (float) displayTextObject["lineHeight"].toDouble();
|
||||
|
||||
_textDisplay = textDisplay;
|
||||
TextDisplay textDisplay;
|
||||
textDisplay.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL);
|
||||
textDisplay.localPosition = localPosition;
|
||||
textDisplay.dimensions = dimensions;
|
||||
textDisplay.lineHeight = lineHeight;
|
||||
_textDisplay = textDisplay;
|
||||
}
|
||||
|
||||
_ignoreItemsLock.withWriteLock([&] {
|
||||
_itemsToIgnore.append(_textDisplay.overlayID);
|
||||
_itemsToIgnore.append(_anchor.overlayID);
|
||||
_itemsToIgnore.insert(_textDisplay.entityID);
|
||||
_itemsToIgnore.insert(_anchor.entityID);
|
||||
});
|
||||
_layerIndex = 0;
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
|
@ -922,34 +895,33 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
}
|
||||
|
||||
|
||||
OverlayID Keyboard::getAnchorID() {
|
||||
return _ignoreItemsLock.resultWithReadLock<OverlayID>([&] {
|
||||
return _anchor.overlayID;
|
||||
QUuid Keyboard::getAnchorID() {
|
||||
return _ignoreItemsLock.resultWithReadLock<QUuid>([&] {
|
||||
return _anchor.entityID;
|
||||
});
|
||||
}
|
||||
|
||||
bool Keyboard::shouldProcessOverlay(const OverlayID& overlayID) const {
|
||||
return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished() && overlayID != _backPlate.overlayID);
|
||||
bool Keyboard::shouldProcessEntity() const {
|
||||
return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished());
|
||||
}
|
||||
|
||||
QVector<OverlayID> Keyboard::getKeysID() {
|
||||
return _ignoreItemsLock.resultWithReadLock<QVector<OverlayID>>([&] {
|
||||
QSet<QUuid> Keyboard::getKeyIDs() {
|
||||
return _ignoreItemsLock.resultWithReadLock<QSet<QUuid>>([&] {
|
||||
return _itemsToIgnore;
|
||||
});
|
||||
}
|
||||
|
||||
void Keyboard::clearKeyboardKeys() {
|
||||
Overlays& overlays = qApp->getOverlays();
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
for (const auto& keyboardLayer: _keyboardLayers) {
|
||||
for (auto iter = keyboardLayer.begin(); iter != keyboardLayer.end(); iter++) {
|
||||
overlays.deleteOverlay(iter.key());
|
||||
entityScriptingInterface->deleteEntity(iter.key());
|
||||
}
|
||||
}
|
||||
|
||||
overlays.deleteOverlay(_anchor.overlayID);
|
||||
overlays.deleteOverlay(_textDisplay.overlayID);
|
||||
overlays.deleteOverlay(_backPlate.overlayID);
|
||||
entityScriptingInterface->deleteEntity(_anchor.entityID);
|
||||
entityScriptingInterface->deleteEntity(_textDisplay.entityID);
|
||||
entityScriptingInterface->deleteEntity(_backPlate.entityID);
|
||||
|
||||
_keyboardLayers.clear();
|
||||
|
||||
|
@ -989,8 +961,8 @@ void Keyboard::disableRightMallet() {
|
|||
pointerManager->disablePointer(_rightHandStylus);
|
||||
}
|
||||
|
||||
bool Keyboard::containsID(OverlayID overlayID) const {
|
||||
bool Keyboard::containsID(const QUuid& id) const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _itemsToIgnore.contains(overlayID) || _backPlate.overlayID == overlayID;
|
||||
return _itemsToIgnore.contains(id) || _backPlate.entityID == id;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include <shared/ReadWriteLockable.h>
|
||||
#include <SettingHandle.h>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
class PointerEvent;
|
||||
|
||||
|
||||
|
@ -47,8 +45,8 @@ public:
|
|||
|
||||
static Key::Type getKeyTypeFromString(const QString& keyTypeString);
|
||||
|
||||
OverlayID getID() const { return _keyID; }
|
||||
void setID(OverlayID overlayID) { _keyID = overlayID; }
|
||||
QUuid getID() const { return _keyID; }
|
||||
void setID(const QUuid& id) { _keyID = id; }
|
||||
|
||||
void startTimer(int time);
|
||||
bool timerFinished();
|
||||
|
@ -77,12 +75,13 @@ private:
|
|||
int _switchToLayer { 0 };
|
||||
bool _pressed { false };
|
||||
|
||||
OverlayID _keyID;
|
||||
QUuid _keyID;
|
||||
QString _keyString;
|
||||
|
||||
glm::vec3 _originalLocalPosition;
|
||||
glm::vec3 _originalDimensions;
|
||||
glm::vec3 _currentLocalPosition;
|
||||
bool _originalDimensionsAndLocalPositionSaved { false };
|
||||
|
||||
std::shared_ptr<QTimer> _timer { std::make_shared<QTimer>() };
|
||||
};
|
||||
|
@ -111,35 +110,35 @@ public:
|
|||
|
||||
bool getUse3DKeyboard() const;
|
||||
void setUse3DKeyboard(bool use);
|
||||
bool containsID(OverlayID overlayID) const;
|
||||
bool containsID(const QUuid& id) const;
|
||||
|
||||
void loadKeyboardFile(const QString& keyboardFile);
|
||||
QVector<OverlayID> getKeysID();
|
||||
OverlayID getAnchorID();
|
||||
QSet<QUuid> getKeyIDs();
|
||||
QUuid getAnchorID();
|
||||
|
||||
public slots:
|
||||
void handleTriggerBegin(const OverlayID& overlayID, const PointerEvent& event);
|
||||
void handleTriggerEnd(const OverlayID& overlayID, const PointerEvent& event);
|
||||
void handleTriggerContinue(const OverlayID& overlayID, const PointerEvent& event);
|
||||
void handleHoverBegin(const OverlayID& overlayID, const PointerEvent& event);
|
||||
void handleHoverEnd(const OverlayID& overlayID, const PointerEvent& event);
|
||||
void handleTriggerBegin(const QUuid& id, const PointerEvent& event);
|
||||
void handleTriggerEnd(const QUuid& id, const PointerEvent& event);
|
||||
void handleTriggerContinue(const QUuid& id, const PointerEvent& event);
|
||||
void handleHoverBegin(const QUuid& id, const PointerEvent& event);
|
||||
void handleHoverEnd(const QUuid& id, const PointerEvent& event);
|
||||
void scaleKeyboard(float sensorToWorldScale);
|
||||
|
||||
private:
|
||||
struct Anchor {
|
||||
OverlayID overlayID;
|
||||
QUuid entityID;
|
||||
glm::vec3 originalDimensions;
|
||||
};
|
||||
|
||||
struct BackPlate {
|
||||
OverlayID overlayID;
|
||||
QUuid entityID;
|
||||
glm::vec3 dimensions;
|
||||
glm::vec3 localPosition;
|
||||
};
|
||||
|
||||
struct TextDisplay {
|
||||
float lineHeight;
|
||||
OverlayID overlayID;
|
||||
QUuid entityID;
|
||||
glm::vec3 localPosition;
|
||||
glm::vec3 dimensions;
|
||||
};
|
||||
|
@ -148,14 +147,16 @@ private:
|
|||
void raiseKeyboardAnchor(bool raise) const;
|
||||
void enableStylus();
|
||||
void disableStylus();
|
||||
void enableSelectionLists();
|
||||
void disableSelectionLists();
|
||||
|
||||
void setLayerIndex(int layerIndex);
|
||||
void clearKeyboardKeys();
|
||||
void switchToLayer(int layerIndex);
|
||||
void updateTextDisplay();
|
||||
bool shouldProcessOverlayAndPointerEvent(const PointerEvent& event, const OverlayID& overlayID) const;
|
||||
bool shouldProcessEntityAndPointerEvent(const PointerEvent& event) const;
|
||||
bool shouldProcessPointerEvent(const PointerEvent& event) const;
|
||||
bool shouldProcessOverlay(const OverlayID& overlayID) const;
|
||||
bool shouldProcessEntity() const;
|
||||
|
||||
void startLayerSwitchTimer();
|
||||
bool isLayerSwitchTimerFinished() const;
|
||||
|
@ -184,8 +185,8 @@ private:
|
|||
Anchor _anchor;
|
||||
BackPlate _backPlate;
|
||||
|
||||
QVector<OverlayID> _itemsToIgnore;
|
||||
std::vector<QHash<OverlayID, Key>> _keyboardLayers;
|
||||
QSet<QUuid> _itemsToIgnore;
|
||||
std::vector<QHash<QUuid, Key>> _keyboardLayers;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
HIFI_QML_DEF(LoginDialog)
|
||||
|
||||
static const QUrl TABLET_LOGIN_DIALOG_URL("dialogs/TabletLoginDialog.qml");
|
||||
const QUrl OVERLAY_LOGIN_DIALOG = PathUtils::qmlUrl("OverlayLoginDialog.qml");
|
||||
const QUrl LOGIN_DIALOG = PathUtils::qmlUrl("OverlayLoginDialog.qml");
|
||||
|
||||
LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
@ -71,7 +71,7 @@ void LoginDialog::showWithSelection() {
|
|||
if (!qApp->getLoginDialogPoppedUp()) {
|
||||
tablet->initialScreen(TABLET_LOGIN_DIALOG_URL);
|
||||
} else {
|
||||
qApp->createLoginDialogOverlay();
|
||||
qApp->createLoginDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
class QNetworkReply;
|
||||
|
||||
extern const QUrl OVERLAY_LOGIN_DIALOG;
|
||||
extern const QUrl LOGIN_DIALOG;
|
||||
|
||||
class LoginDialog : public OffscreenQmlDialog {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -42,6 +42,7 @@ private:
|
|||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*/
|
||||
|
||||
class Snapshot : public QObject, public Dependency {
|
||||
|
|
|
@ -158,7 +158,7 @@ void Stats::updateStats(bool force) {
|
|||
STAT_UPDATE(rayPicksCount, totalPicks[PickQuery::Ray]);
|
||||
STAT_UPDATE(parabolaPicksCount, totalPicks[PickQuery::Parabola]);
|
||||
STAT_UPDATE(collisionPicksCount, totalPicks[PickQuery::Collision]);
|
||||
std::vector<QVector4D> updatedPicks = pickManager->getUpdatedPickCounts();
|
||||
std::vector<QVector3D> updatedPicks = pickManager->getUpdatedPickCounts();
|
||||
STAT_UPDATE(stylusPicksUpdated, updatedPicks[PickQuery::Stylus]);
|
||||
STAT_UPDATE(rayPicksUpdated, updatedPicks[PickQuery::Ray]);
|
||||
STAT_UPDATE(parabolaPicksUpdated, updatedPicks[PickQuery::Parabola]);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue