Merge branch 'master' of https://github.com/highfidelity/hifi into blocks

This commit is contained in:
Elisa Lupin-Jimenez 2017-07-28 10:21:11 -07:00
commit 7ce31f3f69
24 changed files with 352 additions and 124 deletions

View file

@ -49,7 +49,7 @@
Var STR_CONTAINS_VAR_3 Var STR_CONTAINS_VAR_3
Var STR_CONTAINS_VAR_4 Var STR_CONTAINS_VAR_4
Var STR_RETURN_VAR Var STR_RETURN_VAR
Function StrContains Function StrContains
Exch $STR_NEEDLE Exch $STR_NEEDLE
Exch 1 Exch 1
@ -343,22 +343,29 @@ SectionEnd
;-------------------------------- ;--------------------------------
;Pages ;Pages
!insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
Page custom InstallTypesPage ReadInstallTypes
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
!insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_DIRECTORY
;Start Menu Folder Page Configuration ;Start Menu Folder Page Configuration
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
@CPACK_NSIS_PAGE_COMPONENTS@ @CPACK_NSIS_PAGE_COMPONENTS@
Page custom PostInstallOptionsPage ReadPostInstallOptions Page custom PostInstallOptionsPage ReadPostInstallOptions
!insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_INSTFILES
@ -442,6 +449,10 @@ Var CleanInstallCheckbox
Var CurrentOffset Var CurrentOffset
Var OffsetUnits Var OffsetUnits
Var CopyFromProductionCheckbox Var CopyFromProductionCheckbox
Var ExpressInstallRadioButton
Var CustomInstallRadioButton
Var InstallTypeDialog
Var Express
!macro SetPostInstallOption Checkbox OptionName Default !macro SetPostInstallOption Checkbox OptionName Default
; reads the value for the given post install option to the registry ; reads the value for the given post install option to the registry
@ -459,6 +470,60 @@ Var CopyFromProductionCheckbox
${EndIf} ${EndIf}
!macroend !macroend
Function InstallTypesPage
!insertmacro MUI_HEADER_TEXT "Choose Installation Type" "Express or Custom Install"
nsDialogs::Create 1018
Pop $InstallTypeDialog
${If} $InstallTypeDialog == error
Abort
${EndIf}
StrCpy $CurrentOffset 0
StrCpy $OffsetUnits u
StrCpy $Express "0"
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
${NSD_CreateRadioButton} 30% $CurrentOffset$OffsetUnits 100% 10u "Express Install (Recommended)"; $\nInstalls High Fidelity Interface and High Fidelity Sandbox"
pop $ExpressInstallRadioButton
${NSD_OnClick} $ExpressInstallRadioButton ChangeExpressLabel
IntOp $CurrentOffset $CurrentOffset + 15
${NSD_CreateRadiobutton} 30% $CurrentOffset$OffsetUnits 100% 10u "Custom Install (Advanced)"
pop $CustomInstallRadioButton
${NSD_OnClick} $CustomInstallRadioButton ChangeCustomLabel
${EndIf}
; Express Install selected by default
${NSD_Check} $ExpressInstallRadioButton
Call ChangeExpressLabel
nsDialogs::Show
FunctionEnd
Function ChangeExpressLabel
Push $R1
GetDlgItem $R1 $HWNDPARENT 1
SendMessage $R1 ${WM_SETTEXT} 0 "STR:Install"
Pop $R1
FunctionEnd
Function ChangeCustomLabel
Push $R1
GetDlgItem $R1 $HWNDPARENT 1
SendMessage $R1 ${WM_SETTEXT} 0 "STR:Next >"
Pop $R1
FunctionEnd
Function AbortFunction
; Check if Express is set, if so, abort the post install options page
Call HandleInstallTypes ; Sets Express if ExpressInstallRadioButton is checked and installs with defaults
StrCmp $Express "1" 0 end
Abort
end:
FunctionEnd
Function PostInstallOptionsPage Function PostInstallOptionsPage
!insertmacro MUI_HEADER_TEXT "Setup Options" "" !insertmacro MUI_HEADER_TEXT "Setup Options" ""
@ -549,9 +614,15 @@ Function PostInstallOptionsPage
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Copy settings and content from production install" ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Copy settings and content from production install"
Pop $CopyFromProductionCheckbox Pop $CopyFromProductionCheckbox
${NSD_SetState} $CopyFromProductionCheckbox ${BST_CHECKED} ${NSD_SetState} $CopyFromProductionCheckbox ${BST_UNCHECKED}
${EndIf} ${EndIf}
; Check if Express is set, if so, abort the post install options page
Call HandleInstallTypes ; Sets Express if ExpressInstallRadioButton is checked and installs with defaults
StrCmp $Express "1" 0 end
Abort
end:
nsDialogs::Show nsDialogs::Show
FunctionEnd FunctionEnd
@ -567,6 +638,16 @@ Var LaunchServerNowState
Var LaunchClientNowState Var LaunchClientNowState
Var CopyFromProductionState Var CopyFromProductionState
Var CleanInstallState Var CleanInstallState
Var ExpressInstallState
Var CustomInstallState
Function ReadInstallTypes
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
; check if the user asked for express/custom install
${NSD_GetState} $ExpressInstallRadioButton $ExpressInstallState
${NSD_GetState} $CustomInstallRadioButton $CustomInstallState
${EndIf}
FunctionEnd
Function ReadPostInstallOptions Function ReadPostInstallOptions
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
@ -603,6 +684,28 @@ Function ReadPostInstallOptions
${EndIf} ${EndIf}
FunctionEnd FunctionEnd
Function HandleInstallTypes
${If} $ExpressInstallState == ${BST_CHECKED}
StrCpy $Express "1"
; over ride custom checkboxes and select defaults
${NSD_SetState} $DesktopClientCheckbox ${BST_CHECKED}
${NSD_SetState} $ServerStartupCheckbox ${BST_CHECKED}
${NSD_SetState} $LaunchServerNowCheckbox ${BST_CHECKED}
${NSD_SetState} $LaunchClientNowCheckbox ${BST_CHECKED}
${If} @PR_BUILD@ == 1
${NSD_SetState} $CopyFromProductionCheckbox ${BST_UNCHECKED}
${EndIf}
; call ReadPostInstallOptions and HandlePostInstallOptions with defaults selected
Call ReadPostInstallOptions
Call HandlePostInstallOptions
${EndIf}
FunctionEnd
Function HandlePostInstallOptions Function HandlePostInstallOptions
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
; check if the user asked for a desktop shortcut to High Fidelity ; check if the user asked for a desktop shortcut to High Fidelity
@ -624,6 +727,7 @@ Function HandlePostInstallOptions
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO !insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf} ${EndIf}
; check if the user asked to have Sandbox launched every startup ; check if the user asked to have Sandbox launched every startup
${If} $ServerStartupState == ${BST_CHECKED} ${If} $ServerStartupState == ${BST_CHECKED}
; in case we added a shortcut in the global context, pull that now ; in case we added a shortcut in the global context, pull that now

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

View file

@ -28,6 +28,7 @@ ScrollingWindow {
minSize: Qt.vector2d(200, 300) minSize: Qt.vector2d(200, 300)
property int colorScheme: hifi.colorSchemes.dark property int colorScheme: hifi.colorSchemes.dark
property int selectionMode: SelectionMode.ExtendedSelection
HifiConstants { id: hifi } HifiConstants { id: hifi }
@ -35,7 +36,8 @@ ScrollingWindow {
property var assetProxyModel: Assets.proxyModel; property var assetProxyModel: Assets.proxyModel;
property var assetMappingsModel: Assets.mappingModel; property var assetMappingsModel: Assets.mappingModel;
property var currentDirectory; property var currentDirectory;
property var selectedItems: treeView.selection.selectedIndexes.length;
Settings { Settings {
category: "Overlay.AssetServer" category: "Overlay.AssetServer"
property alias x: root.x property alias x: root.x
@ -48,7 +50,7 @@ ScrollingWindow {
assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError); assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError);
reload(); reload();
} }
function doDeleteFile(path) { function doDeleteFile(path) {
console.log("Deleting " + path); console.log("Deleting " + path);
@ -118,11 +120,23 @@ ScrollingWindow {
function canAddToWorld(path) { function canAddToWorld(path) {
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i]; var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i];
if (selectedItems > 1) {
return false;
}
return supportedExtensions.reduce(function(total, current) { return supportedExtensions.reduce(function(total, current) {
return total | new RegExp(current).test(path); return total | new RegExp(current).test(path);
}, false); }, false);
} }
function canRename() {
if (treeView.selection.hasSelection && selectedItems == 1) {
return true;
} else {
return false;
}
}
function clear() { function clear() {
Assets.mappingModel.clear(); Assets.mappingModel.clear();
@ -299,23 +313,37 @@ ScrollingWindow {
}); });
} }
function deleteFile(index) { function deleteFile(index) {
var path = [];
if (!index) { if (!index) {
index = treeView.selection.currentIndex; for (var i = 0; i < selectedItems; i++) {
treeView.selection.setCurrentIndex(treeView.selection.selectedIndexes[i], 0x100);
index = treeView.selection.currentIndex;
path[i] = assetProxyModel.data(index, 0x100);
}
} }
var path = assetProxyModel.data(index, 0x100);
if (!path) { if (!path) {
return; return;
} }
var modalMessage = "";
var items = selectedItems.toString();
var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101); var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101);
var typeString = isFolder ? 'folder' : 'file'; var typeString = isFolder ? 'folder' : 'file';
if (selectedItems > 1) {
modalMessage = "You are about to delete " + items + " items \nDo you want to continue?";
} else {
modalMessage = "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?";
}
var object = desktop.messageBox({ var object = desktop.messageBox({
icon: hifi.icons.question, icon: hifi.icons.question,
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No, buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
defaultButton: OriginalDialogs.StandardButton.Yes, defaultButton: OriginalDialogs.StandardButton.Yes,
title: "Delete", title: "Delete",
text: "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?" text: modalMessage
}); });
object.selected.connect(function(button) { object.selected.connect(function(button) {
if (button === OriginalDialogs.StandardButton.Yes) { if (button === OriginalDialogs.StandardButton.Yes) {
@ -455,20 +483,20 @@ ScrollingWindow {
color: hifi.buttons.black color: hifi.buttons.black
colorScheme: root.colorScheme colorScheme: root.colorScheme
width: 120 width: 120
enabled: canAddToWorld(assetProxyModel.data(treeView.selection.currentIndex, 0x100)) enabled: canAddToWorld(assetProxyModel.data(treeView.selection.currentIndex, 0x100))
onClicked: root.addToWorld() onClicked: root.addToWorld()
} }
HifiControls.Button { HifiControls.Button {
text: "Rename" text: "Rename"
color: hifi.buttons.black color: hifi.buttons.black
colorScheme: root.colorScheme colorScheme: root.colorScheme
width: 80 width: 80
onClicked: root.renameFile() onClicked: root.renameFile()
enabled: treeView.selection.hasSelection enabled: canRename()
} }
HifiControls.Button { HifiControls.Button {
@ -524,6 +552,7 @@ ScrollingWindow {
treeModel: assetProxyModel treeModel: assetProxyModel
canEdit: true canEdit: true
colorScheme: root.colorScheme colorScheme: root.colorScheme
selectionMode: SelectionMode.ExtendedSelection
modifyEl: renameEl modifyEl: renameEl

View file

@ -37,6 +37,7 @@ Rectangle {
property var assetProxyModel: Assets.proxyModel; property var assetProxyModel: Assets.proxyModel;
property var assetMappingsModel: Assets.mappingModel; property var assetMappingsModel: Assets.mappingModel;
property var currentDirectory; property var currentDirectory;
property var selectedItems: treeView.selection.selectedIndexes.length;
Settings { Settings {
category: "Overlay.AssetServer" category: "Overlay.AssetServer"
@ -119,11 +120,23 @@ Rectangle {
function canAddToWorld(path) { function canAddToWorld(path) {
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i]; var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i];
if (selectedItems > 1) {
return false;
}
return supportedExtensions.reduce(function(total, current) { return supportedExtensions.reduce(function(total, current) {
return total | new RegExp(current).test(path); return total | new RegExp(current).test(path);
}, false); }, false);
} }
function canRename() {
if (treeView.selection.hasSelection && selectedItems == 1) {
return true;
} else {
return false;
}
}
function clear() { function clear() {
Assets.mappingModel.clear(); Assets.mappingModel.clear();
@ -300,23 +313,37 @@ Rectangle {
}); });
} }
function deleteFile(index) { function deleteFile(index) {
var path = [];
if (!index) { if (!index) {
index = treeView.selection.currentIndex; for (var i = 0; i < selectedItems; i++) {
treeView.selection.setCurrentIndex(treeView.selection.selectedIndexes[i], 0x100);
index = treeView.selection.currentIndex;
path[i] = assetProxyModel.data(index, 0x100);
}
} }
var path = assetProxyModel.data(index, 0x100);
if (!path) { if (!path) {
return; return;
} }
var modalMessage = "";
var items = selectedItems.toString();
var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101); var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101);
var typeString = isFolder ? 'folder' : 'file'; var typeString = isFolder ? 'folder' : 'file';
if (selectedItems > 1) {
modalMessage = "You are about to delete " + items + " items \nDo you want to continue?";
} else {
modalMessage = "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?";
}
var object = tabletRoot.messageBox({ var object = tabletRoot.messageBox({
icon: hifi.icons.question, icon: hifi.icons.question,
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No, buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
defaultButton: OriginalDialogs.StandardButton.Yes, defaultButton: OriginalDialogs.StandardButton.Yes,
title: "Delete", title: "Delete",
text: "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?" text: modalMessage
}); });
object.selected.connect(function(button) { object.selected.connect(function(button) {
if (button === OriginalDialogs.StandardButton.Yes) { if (button === OriginalDialogs.StandardButton.Yes) {
@ -469,7 +496,7 @@ Rectangle {
width: 80 width: 80
onClicked: root.renameFile() onClicked: root.renameFile()
enabled: treeView.selection.hasSelection enabled: canRename()
} }
HifiControls.Button { HifiControls.Button {
@ -525,6 +552,7 @@ Rectangle {
treeModel: assetProxyModel treeModel: assetProxyModel
canEdit: true canEdit: true
colorScheme: root.colorScheme colorScheme: root.colorScheme
selectionMode: SelectionMode.ExtendedSelection
modifyEl: renameEl modifyEl: renameEl

View file

@ -624,6 +624,7 @@ const float DEFAULT_DESKTOP_TABLET_SCALE_PERCENT = 75.0f;
const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true; const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true;
const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false; const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false;
const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false; const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false;
const QString DEFAULT_CURSOR_NAME = "DEFAULT";
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) : Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) :
QApplication(argc, argv), QApplication(argc, argv),
@ -643,6 +644,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR), _hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR),
_preferAvatarFingerOverStylusSetting("preferAvatarFingerOverStylus", DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS), _preferAvatarFingerOverStylusSetting("preferAvatarFingerOverStylus", DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS),
_constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true), _constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true),
_preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME),
_scaleMirror(1.0f), _scaleMirror(1.0f),
_rotateMirror(0.0f), _rotateMirror(0.0f),
_raiseMirror(0.0f), _raiseMirror(0.0f),
@ -938,14 +940,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_glWidget->setFocusPolicy(Qt::StrongFocus); _glWidget->setFocusPolicy(Qt::StrongFocus);
_glWidget->setFocus(); _glWidget->setFocus();
#ifdef Q_OS_MAC showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get()));
auto cursorTarget = _window; // OSX doesn't seem to provide for hiding the cursor only on the GL widget
#else
// On windows and linux, hiding the top level cursor also means it's invisible when hovering over the
// window menu, which is a pain, so only hide it for the GL surface
auto cursorTarget = _glWidget;
#endif
cursorTarget->setCursor(Qt::BlankCursor);
// enable mouse tracking; otherwise, we only get drag events // enable mouse tracking; otherwise, we only get drag events
_glWidget->setMouseTracking(true); _glWidget->setMouseTracking(true);
@ -1743,9 +1738,16 @@ void Application::checkChangeCursor() {
} }
} }
void Application::showCursor(const QCursor& cursor) { void Application::showCursor(const Cursor::Icon& cursor) {
QMutexLocker locker(&_changeCursorLock); QMutexLocker locker(&_changeCursorLock);
_desiredCursor = cursor;
auto managedCursor = Cursor::Manager::instance().getCursor();
auto curIcon = managedCursor->getIcon();
if (curIcon != cursor) {
managedCursor->setIcon(cursor);
curIcon = cursor;
}
_desiredCursor = cursor == Cursor::Icon::SYSTEM ? Qt::ArrowCursor : Qt::BlankCursor;
_cursorNeedsChanging = true; _cursorNeedsChanging = true;
} }
@ -2166,9 +2168,11 @@ void Application::initializeUi() {
_window->setMenuBar(new Menu()); _window->setMenuBar(new Menu());
auto compositorHelper = DependencyManager::get<CompositorHelper>(); auto compositorHelper = DependencyManager::get<CompositorHelper>();
connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, [=] { connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] {
if (isHMDMode()) { if (isHMDMode()) {
showCursor(compositorHelper->getAllowMouseCapture() ? Qt::BlankCursor : Qt::ArrowCursor); showCursor(compositorHelper->getAllowMouseCapture() ?
Cursor::Manager::lookupIcon(_preferredCursor.get()) :
Cursor::Icon::SYSTEM);
} }
}); });
@ -2510,6 +2514,12 @@ void Application::setPreferAvatarFingerOverStylus(bool value) {
_preferAvatarFingerOverStylusSetting.set(value); _preferAvatarFingerOverStylusSetting.set(value);
} }
void Application::setPreferredCursor(const QString& cursorName) {
qCDebug(interfaceapp) << "setPreferredCursor" << cursorName;
_preferredCursor.set(cursorName.isEmpty() ? DEFAULT_CURSOR_NAME : cursorName);
showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get()));
}
void Application::setSettingConstrainToolbarPosition(bool setting) { void Application::setSettingConstrainToolbarPosition(bool setting) {
_constrainToolbarPosition.set(setting); _constrainToolbarPosition.set(setting);
DependencyManager::get<OffscreenUi>()->setConstrainToolbarToCenterX(setting); DependencyManager::get<OffscreenUi>()->setConstrainToolbarToCenterX(setting);
@ -3080,9 +3090,13 @@ void Application::keyPressEvent(QKeyEvent* event) {
auto cursor = Cursor::Manager::instance().getCursor(); auto cursor = Cursor::Manager::instance().getCursor();
auto curIcon = cursor->getIcon(); auto curIcon = cursor->getIcon();
if (curIcon == Cursor::Icon::DEFAULT) { if (curIcon == Cursor::Icon::DEFAULT) {
cursor->setIcon(Cursor::Icon::LINK); showCursor(Cursor::Icon::RETICLE);
} else if (curIcon == Cursor::Icon::RETICLE) {
showCursor(Cursor::Icon::SYSTEM);
} else if (curIcon == Cursor::Icon::SYSTEM) {
showCursor(Cursor::Icon::LINK);
} else { } else {
cursor->setIcon(Cursor::Icon::DEFAULT); showCursor(Cursor::Icon::DEFAULT);
} }
} else { } else {
resetSensors(true); resetSensors(true);

View file

@ -55,6 +55,7 @@
#include "BandwidthRecorder.h" #include "BandwidthRecorder.h"
#include "FancyCamera.h" #include "FancyCamera.h"
#include "ConnectionMonitor.h" #include "ConnectionMonitor.h"
#include "CursorManager.h"
#include "gpu/Context.h" #include "gpu/Context.h"
#include "Menu.h" #include "Menu.h"
#include "octree/OctreePacketProcessor.h" #include "octree/OctreePacketProcessor.h"
@ -165,7 +166,7 @@ public:
QSize getDeviceSize() const; QSize getDeviceSize() const;
bool hasFocus() const; bool hasFocus() const;
void showCursor(const QCursor& cursor); void showCursor(const Cursor::Icon& cursor);
bool isThrottleRendering() const; bool isThrottleRendering() const;
@ -400,6 +401,9 @@ public slots:
void loadDomainConnectionDialog(); void loadDomainConnectionDialog();
void showScriptLogs(); void showScriptLogs();
const QString getPreferredCursor() const { return _preferredCursor.get(); }
void setPreferredCursor(const QString& cursor);
private slots: private slots:
void showDesktop(); void showDesktop();
void clearDomainOctreeDetails(); void clearDomainOctreeDetails();
@ -567,6 +571,7 @@ private:
Setting::Handle<bool> _hmdTabletBecomesToolbarSetting; Setting::Handle<bool> _hmdTabletBecomesToolbarSetting;
Setting::Handle<bool> _preferAvatarFingerOverStylusSetting; Setting::Handle<bool> _preferAvatarFingerOverStylusSetting;
Setting::Handle<bool> _constrainToolbarPosition; Setting::Handle<bool> _constrainToolbarPosition;
Setting::Handle<QString> _preferredCursor;
float _scaleMirror; float _scaleMirror;
float _rotateMirror; float _rotateMirror;
@ -640,7 +645,7 @@ private:
void checkChangeCursor(); void checkChangeCursor();
mutable QMutex _changeCursorLock { QMutex::Recursive }; mutable QMutex _changeCursorLock { QMutex::Recursive };
QCursor _desiredCursor{ Qt::BlankCursor }; Qt::CursorShape _desiredCursor{ Qt::BlankCursor };
bool _cursorNeedsChanging { false }; bool _cursorNeedsChanging { false };
QThread* _deadlockWatchdogThread; QThread* _deadlockWatchdogThread;

View file

@ -613,7 +613,7 @@ void MyAvatar::simulate(float deltaTime) {
MovingEntitiesOperator moveOperator(entityTree); MovingEntitiesOperator moveOperator(entityTree);
forEachDescendant([&](SpatiallyNestablePointer object) { forEachDescendant([&](SpatiallyNestablePointer object) {
// if the queryBox has changed, tell the entity-server // if the queryBox has changed, tell the entity-server
if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) { if (object->getNestableType() == NestableType::Entity && object->checkAndMaybeUpdateQueryAACube()) {
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object); EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
bool success; bool success;
AACube newCube = entity->getQueryAACube(success); AACube newCube = entity->getQueryAACube(success);

View file

@ -106,6 +106,12 @@ void setupPreferences() {
auto setter = [](bool value) { qApp->setPreferAvatarFingerOverStylus(value); }; auto setter = [](bool value) { qApp->setPreferAvatarFingerOverStylus(value); };
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Avatar Finger Over Stylus", getter, setter)); preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Avatar Finger Over Stylus", getter, setter));
} }
{
static const QString RETICLE_ICON_NAME = { Cursor::Manager::getIconName(Cursor::Icon::RETICLE) };
auto getter = []()->bool { return qApp->getPreferredCursor() == RETICLE_ICON_NAME; };
auto setter = [](bool value) { qApp->setPreferredCursor(value ? RETICLE_ICON_NAME : QString()); };
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter));
}
// Snapshots // Snapshots
static const QString SNAPSHOTS { "Snapshots" }; static const QString SNAPSHOTS { "Snapshots" };

View file

@ -323,7 +323,7 @@ signals:
private: private:
void cleanupOverlaysToDelete(); void cleanupOverlaysToDelete();
mutable QMutex _mutex; mutable QMutex _mutex { QMutex::Recursive };
QMap<OverlayID, Overlay::Pointer> _overlaysHUD; QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
QMap<OverlayID, Overlay::Pointer> _overlaysWorld; QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
#if OVERLAY_PANELS #if OVERLAY_PANELS

View file

@ -1355,8 +1355,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy);
AACube saveQueryAACube = _queryAACube; AACube saveQueryAACube = _queryAACube;
checkAndAdjustQueryAACube(); if (checkAndMaybeUpdateQueryAACube() && saveQueryAACube != _queryAACube) {
if (saveQueryAACube != _queryAACube) {
somethingChanged = true; somethingChanged = true;
} }
@ -1424,26 +1423,20 @@ void EntityItem::setDimensions(const glm::vec3& value) {
/// ///
AACube EntityItem::getMaximumAACube(bool& success) const { AACube EntityItem::getMaximumAACube(bool& success) const {
if (_recalcMaxAACube) { if (_recalcMaxAACube) {
// * we know that the position is the center of rotation
glm::vec3 centerOfRotation = getPosition(success); // also where _registration point is glm::vec3 centerOfRotation = getPosition(success); // also where _registration point is
if (success) { if (success) {
_recalcMaxAACube = false; _recalcMaxAACube = false;
// * we know that the registration point is the center of rotation // we want to compute the furthestExtent that an entity can extend out from its "position"
// * we can calculate the length of the furthest extent from the registration point // to do this we compute the max of these two vec3s: registration and 1-registration
// as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint) // and then scale by dimensions
glm::vec3 dimensions = getDimensions(); glm::vec3 maxExtents = getDimensions() * glm::max(_registrationPoint, glm::vec3(1.0f) - _registrationPoint);
glm::vec3 registrationPoint = (dimensions * _registrationPoint);
glm::vec3 registrationRemainder = (dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint));
glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder);
// * we know that if you rotate in any direction you would create a sphere // there exists a sphere that contains maxExtents for all rotations
// that has a radius of the length of furthest extent from registration point float radius = glm::length(maxExtents);
float radius = glm::length(furthestExtentFromRegistration);
// * we know that the minimum bounding cube of this maximum possible sphere is // put a cube around the sphere
// (center - radius) to (center + radius) // TODO? replace _maxAACube with _boundingSphereRadius
glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius);
_maxAACube = AACube(minimumCorner, radius * 2.0f); _maxAACube = AACube(minimumCorner, radius * 2.0f);
} }
} else { } else {
@ -1635,6 +1628,8 @@ void EntityItem::updateDimensions(const glm::vec3& value) {
if (getDimensions() != value) { if (getDimensions() != value) {
setDimensions(value); setDimensions(value);
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
_queryAACubeSet = false;
dimensionsChanged();
} }
} }

View file

@ -2157,12 +2157,17 @@ QList<QString> EntityItemProperties::listChangedProperties() {
return out; return out;
} }
bool EntityItemProperties::parentDependentPropertyChanged() const { bool EntityItemProperties::transformChanged() const {
return localPositionChanged() || positionChanged() || return positionChanged() || rotationChanged() ||
localRotationChanged() || rotationChanged() || localPositionChanged() || localRotationChanged();
localVelocityChanged() || localAngularVelocityChanged();
} }
bool EntityItemProperties::parentRelatedPropertyChanged() const { bool EntityItemProperties::parentRelatedPropertyChanged() const {
return parentDependentPropertyChanged() || parentIDChanged() || parentJointIndexChanged(); return positionChanged() || rotationChanged() ||
localPositionChanged() || localRotationChanged() ||
parentIDChanged() || parentJointIndexChanged();
}
bool EntityItemProperties::queryAACubeRelatedPropertyChanged() const {
return parentRelatedPropertyChanged() || dimensionsChanged();
} }

View file

@ -86,8 +86,9 @@ public:
EntityPropertyFlags getChangedProperties() const; EntityPropertyFlags getChangedProperties() const;
bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret? bool transformChanged() const;
bool parentRelatedPropertyChanged() const; // parentDependentPropertyChanged or parentID or parentJointIndex bool parentRelatedPropertyChanged() const;
bool queryAACubeRelatedPropertyChanged() const;
AABox getAABox() const; AABox getAABox() const;

View file

@ -221,7 +221,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
_entityTree->withWriteLock([&] { _entityTree->withWriteLock([&] {
EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID);
if (entity) { if (entity) {
if (propertiesWithSimID.parentRelatedPropertyChanged()) { if (propertiesWithSimID.queryAACubeRelatedPropertyChanged()) {
// due to parenting, the server may not know where something is in world-space, so include the bounding cube. // due to parenting, the server may not know where something is in world-space, so include the bounding cube.
bool success; bool success;
AACube queryAACube = entity->getQueryAACube(success); AACube queryAACube = entity->getQueryAACube(success);
@ -435,7 +435,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
entity->rememberHasSimulationOwnershipBid(); entity->rememberHasSimulationOwnershipBid();
} }
} }
if (properties.parentRelatedPropertyChanged() && entity->computePuffedQueryAACube()) { if (properties.queryAACubeRelatedPropertyChanged()) {
properties.setQueryAACube(entity->getQueryAACube()); properties.setQueryAACube(entity->getQueryAACube());
} }
entity->setLastBroadcast(usecTimestampNow()); entity->setLastBroadcast(usecTimestampNow());
@ -445,7 +445,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
// if they've changed. // if they've changed.
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
if (descendant->getNestableType() == NestableType::Entity) { if (descendant->getNestableType() == NestableType::Entity) {
if (descendant->computePuffedQueryAACube()) { if (descendant->checkAndMaybeUpdateQueryAACube()) {
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant); EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
EntityItemProperties newQueryCubeProperties; EntityItemProperties newQueryCubeProperties;
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());

View file

@ -1675,6 +1675,7 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
addToNeedsParentFixupList(entity); addToNeedsParentFixupList(entity);
} }
entity->forceQueryAACubeUpdate(); entity->forceQueryAACubeUpdate();
entity->checkAndMaybeUpdateQueryAACube();
moveOperator.addEntityToMoveList(entity, entity->getQueryAACube()); moveOperator.addEntityToMoveList(entity, entity->getQueryAACube());
i++; i++;
} else { } else {
@ -1693,7 +1694,7 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
EntityItemPointer entity = localTree->findEntityByEntityItemID(newID); EntityItemPointer entity = localTree->findEntityByEntityItemID(newID);
if (entity) { if (entity) {
// queue the packet to send to the server // queue the packet to send to the server
entity->computePuffedQueryAACube(); entity->updateQueryAACube();
EntityItemProperties properties = entity->getProperties(); EntityItemProperties properties = entity->getProperties();
properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity
packetSender->queueEditEntityMessage(PacketType::EntityAdd, localTree, newID, properties); packetSender->queueEditEntityMessage(PacketType::EntityAdd, localTree, newID, properties);

View file

@ -136,7 +136,7 @@ void SimpleEntitySimulation::sortEntitiesThatMoved() {
SetOfEntities::iterator itemItr = _entitiesToSort.begin(); SetOfEntities::iterator itemItr = _entitiesToSort.begin();
while (itemItr != _entitiesToSort.end()) { while (itemItr != _entitiesToSort.end()) {
EntityItemPointer entity = *itemItr; EntityItemPointer entity = *itemItr;
entity->computePuffedQueryAACube(); entity->checkAndMaybeUpdateQueryAACube();
++itemItr; ++itemItr;
} }
EntitySimulation::sortEntitiesThatMoved(); EntitySimulation::sortEntitiesThatMoved();

View file

@ -484,11 +484,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
return false; return false;
} }
if (_entity->dynamicDataNeedsTransmit()) { if (_entity->dynamicDataNeedsTransmit() || _entity->queryAACubeNeedsUpdate()) {
return true;
}
if (_entity->queryAABoxNeedsUpdate()) {
return true; return true;
} }
@ -577,9 +573,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
properties.setActionData(_serverActionData); properties.setActionData(_serverActionData);
} }
if (properties.parentRelatedPropertyChanged() && _entity->computePuffedQueryAACube()) { if (properties.transformChanged()) {
// due to parenting, the server may not know where something is in world-space, so include the bounding cube. if (_entity->checkAndMaybeUpdateQueryAACube()) {
properties.setQueryAACube(_entity->getQueryAACube()); // due to parenting, the server may not know where something is in world-space, so include the bounding cube.
properties.setQueryAACube(_entity->getQueryAACube());
}
} }
// set the LastEdited of the properties but NOT the entity itself // set the LastEdited of the properties but NOT the entity itself
@ -643,7 +641,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
_entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { _entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
if (descendant->getNestableType() == NestableType::Entity) { if (descendant->getNestableType() == NestableType::Entity) {
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant); EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
if (descendant->computePuffedQueryAACube()) { if (descendant->checkAndMaybeUpdateQueryAACube()) {
EntityItemProperties newQueryCubeProperties; EntityItemProperties newQueryCubeProperties;
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
newQueryCubeProperties.setLastEdited(properties.getLastEdited()); newQueryCubeProperties.setLastEdited(properties.getLastEdited());

View file

@ -946,11 +946,35 @@ AACube SpatiallyNestable::getMaximumAACube(bool& success) const {
return AACube(getPosition(success) - glm::vec3(defaultAACubeSize / 2.0f), defaultAACubeSize); return AACube(getPosition(success) - glm::vec3(defaultAACubeSize / 2.0f), defaultAACubeSize);
} }
bool SpatiallyNestable::checkAndAdjustQueryAACube() { const float PARENTED_EXPANSION_FACTOR = 3.0f;
bool success;
bool SpatiallyNestable::checkAndMaybeUpdateQueryAACube() {
bool success = false;
AACube maxAACube = getMaximumAACube(success); AACube maxAACube = getMaximumAACube(success);
if (success && (!_queryAACubeSet || !_queryAACube.contains(maxAACube))) { if (success) {
setQueryAACube(maxAACube); // maybe update _queryAACube
if (!_queryAACubeSet || (_parentID.isNull() && _children.size() == 0) || !_queryAACube.contains(maxAACube)) {
if (_parentJointIndex != INVALID_JOINT_INDEX || _children.size() > 0 ) {
// make an expanded AACube centered on the object
float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale();
_queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale);
} else {
_queryAACube = maxAACube;
}
getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) {
bool childSuccess;
AACube descendantAACube = descendant->getQueryAACube(childSuccess);
if (childSuccess) {
if (_queryAACube.contains(descendantAACube)) {
return;
}
_queryAACube += descendantAACube.getMinimumPoint();
_queryAACube += descendantAACube.getMaximumPoint();
}
});
_queryAACubeSet = true;
}
} }
return success; return success;
} }
@ -961,46 +985,34 @@ void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) {
return; return;
} }
_queryAACube = queryAACube; _queryAACube = queryAACube;
if (queryAACube.getScale() > 0.0f) { _queryAACubeSet = true;
_queryAACubeSet = true;
}
} }
bool SpatiallyNestable::queryAABoxNeedsUpdate() const { bool SpatiallyNestable::queryAACubeNeedsUpdate() const {
bool success; if (!_queryAACubeSet) {
AACube currentAACube = getMaximumAACube(success); return true;
if (!success) {
qCDebug(shared) << "can't getMaximumAACube for" << getID();
return false;
} }
// make sure children are still in their boxes, also. // make sure children are still in their boxes, also.
bool childNeedsUpdate = false; bool childNeedsUpdate = false;
getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) { getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) {
if (!childNeedsUpdate && descendant->queryAABoxNeedsUpdate()) { if (!childNeedsUpdate && descendant->queryAACubeNeedsUpdate()) {
childNeedsUpdate = true; childNeedsUpdate = true;
} }
}); });
if (childNeedsUpdate) { return childNeedsUpdate;
return true;
}
if (_queryAACubeSet && _queryAACube.contains(currentAACube)) {
return false;
}
return true;
} }
bool SpatiallyNestable::computePuffedQueryAACube() { void SpatiallyNestable::updateQueryAACube() {
if (!queryAABoxNeedsUpdate()) {
return false;
}
bool success; bool success;
AACube currentAACube = getMaximumAACube(success); AACube maxAACube = getMaximumAACube(success);
// make an AACube with edges thrice as long and centered on the object if (_parentJointIndex != INVALID_JOINT_INDEX || _children.size() > 0 ) {
_queryAACube = AACube(currentAACube.getCorner() - glm::vec3(currentAACube.getScale()), currentAACube.getScale() * 3.0f); // make an expanded AACube centered on the object
_queryAACubeSet = true; float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale();
_queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale);
} else {
_queryAACube = maxAACube;
}
getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) { getThisPointer()->forEachDescendant([&](SpatiallyNestablePointer descendant) {
bool success; bool success;
@ -1013,8 +1025,7 @@ bool SpatiallyNestable::computePuffedQueryAACube() {
_queryAACube += descendantAACube.getMaximumPoint(); _queryAACube += descendantAACube.getMaximumPoint();
} }
}); });
_queryAACubeSet = true;
return true;
} }
AACube SpatiallyNestable::getQueryAACube(bool& success) const { AACube SpatiallyNestable::getQueryAACube(bool& success) const {

View file

@ -102,11 +102,11 @@ public:
virtual glm::vec3 getParentAngularVelocity(bool& success) const; virtual glm::vec3 getParentAngularVelocity(bool& success) const;
virtual AACube getMaximumAACube(bool& success) const; virtual AACube getMaximumAACube(bool& success) const;
virtual bool checkAndAdjustQueryAACube(); bool checkAndMaybeUpdateQueryAACube();
virtual bool computePuffedQueryAACube(); void updateQueryAACube();
virtual void setQueryAACube(const AACube& queryAACube); virtual void setQueryAACube(const AACube& queryAACube);
virtual bool queryAABoxNeedsUpdate() const; virtual bool queryAACubeNeedsUpdate() const;
void forceQueryAACubeUpdate() { _queryAACubeSet = false; } void forceQueryAACubeUpdate() { _queryAACubeSet = false; }
virtual AACube getQueryAACube(bool& success) const; virtual AACube getQueryAACube(bool& success) const;
virtual AACube getQueryAACube() const; virtual AACube getQueryAACube() const;
@ -197,7 +197,7 @@ protected:
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children; mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed
virtual void dimensionsChanged() { } // called when a this object's dimensions have changed virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed
virtual void parentDeleted() { } // called on children of a deleted parent virtual void parentDeleted() { } // called on children of a deleted parent
// _queryAACube is used to decide where something lives in the octree // _queryAACube is used to decide where something lives in the octree

View file

@ -31,12 +31,34 @@ namespace Cursor {
} }
}; };
static QMap<uint16_t, QString> ICONS; QMap<uint16_t, QString> Manager::ICON_NAMES {
{ Icon::SYSTEM, "SYSTEM", },
{ Icon::DEFAULT, "DEFAULT", },
{ Icon::LINK, "LINK", },
{ Icon::ARROW, "ARROW", },
{ Icon::RETICLE, "RETICLE", },
};
QMap<uint16_t, QString> Manager::ICONS;
static uint16_t _customIconId = Icon::USER_BASE; static uint16_t _customIconId = Icon::USER_BASE;
Manager::Manager() { Manager::Manager() {
ICONS[Icon::DEFAULT] = PathUtils::resourcesPath() + "images/arrow.png"; ICONS[Icon::SYSTEM] = PathUtils::resourcesPath() + "images/cursor-none.png";
ICONS[Icon::LINK] = PathUtils::resourcesPath() + "images/link.png"; ICONS[Icon::DEFAULT] = PathUtils::resourcesPath() + "images/cursor-arrow.png";
ICONS[Icon::LINK] = PathUtils::resourcesPath() + "images/cursor-link.png";
ICONS[Icon::ARROW] = PathUtils::resourcesPath() + "images/cursor-arrow.png";
ICONS[Icon::RETICLE] = PathUtils::resourcesPath() + "images/cursor-reticle.png";
}
Icon Manager::lookupIcon(const QString& name) {
for (const auto& kv : ICON_NAMES.toStdMap()) {
if (kv.second == name) {
return static_cast<Icon>(kv.first);
}
}
return Icon::DEFAULT;
}
const QString& Manager::getIconName(const Icon& icon) {
return ICON_NAMES.count(icon) ? ICON_NAMES[icon] : ICON_NAMES[Icon::DEFAULT];
} }
Manager& Manager::instance() { Manager& Manager::instance() {

View file

@ -18,16 +18,18 @@ namespace Cursor {
}; };
enum Icon { enum Icon {
SYSTEM,
DEFAULT, DEFAULT,
LINK, LINK,
GRAB, GRAB,
ARROW,
RETICLE,
// Add new system cursors here // Add new system cursors here
// User cursors will have ids over this value // User cursors will have ids over this value
USER_BASE = 0xFF, USER_BASE = 0xFF,
}; };
class Instance { class Instance {
public: public:
virtual Source getType() const = 0; virtual Source getType() const = 0;
@ -49,6 +51,11 @@ namespace Cursor {
uint16_t registerIcon(const QString& path); uint16_t registerIcon(const QString& path);
QList<uint16_t> registeredIcons() const; QList<uint16_t> registeredIcons() const;
const QString& getIconImage(uint16_t icon); const QString& getIconImage(uint16_t icon);
static QMap<uint16_t, QString> ICONS;
static QMap<uint16_t, QString> ICON_NAMES;
static Icon lookupIcon(const QString& name);
static const QString& getIconName(const Icon& icon);
private: private:
float _scale{ 1.0f }; float _scale{ 1.0f };
}; };

View file

@ -126,15 +126,17 @@ void OculusBaseDisplayPlugin::internalDeactivate() {
} }
bool OculusBaseDisplayPlugin::activateStandBySession() { bool OculusBaseDisplayPlugin::activateStandBySession() {
_session = acquireOculusSession();
if (!_session) { if (!_session) {
return false; _session = acquireOculusSession();
} }
return true; return _session;
} }
void OculusBaseDisplayPlugin::deactivateSession() { void OculusBaseDisplayPlugin::deactivateSession() {
releaseOculusSession(); // FIXME
_session = nullptr; // Switching to Qt 5.9 exposed a race condition or similar issue that caused a crash when putting on an Rift
// while already in VR mode. Commenting these out is a workaround.
//releaseOculusSession();
//_session = nullptr;
} }
void OculusBaseDisplayPlugin::updatePresentPose() { void OculusBaseDisplayPlugin::updatePresentPose() {
//mat4 sensorResetMat; //mat4 sensorResetMat;