Merge branch 'master' into light_mod

This commit is contained in:
James B. Pollack 2015-12-14 10:13:09 -08:00
commit 0fa82a6449
10 changed files with 284 additions and 111 deletions

View file

@ -1,5 +1,7 @@
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file. Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file.
Interface can be built as 32 or 64 bit.
###Visual Studio 2013 ###Visual Studio 2013
You can use the Community or Professional editions of Visual Studio 2013. You can use the Community or Professional editions of Visual Studio 2013.
@ -25,25 +27,26 @@ We expect nmake.exe to be located at the following path.
###Qt ###Qt
You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version.
NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules.
* [Download the online installer](http://qt-project.org/downloads) * [Download the online installer](http://qt-project.org/downloads)
* When it asks you to select components, ONLY select the following: * When it asks you to select components, ONLY select one of the following, 32- or 64-bit to match your build preference:
* Qt > Qt 5.5.1 > **msvc2013 32-bit** * Qt > Qt 5.5.1 > **msvc2013 32-bit**
* Qt > Qt 5.5.1 > **msvc2013 64-bit**
* [Download the offline installer](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013-5.5.1.exe) * Download the offline installer, 32- or 64-bit to match your build preference:
* [32-bit](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013-5.5.1.exe)
* [64-bit](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013_64-5.5.1.exe)
Once Qt is installed, you need to manually configure the following: Once Qt is installed, you need to manually configure the following:
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.5.1\msvc2013\lib\cmake` directory. * Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.5.1\msvc2013\lib\cmake` or `Qt\5.5.1\msvc2013_64\lib\cmake` directory.
* You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New * You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New
###External Libraries ###External Libraries
As it stands, Hifi/Interface is a 32-bit application, so all libraries should also be 32-bit. All libraries should be 32- or 64-bit to match your build preference.
CMake will need to know where the headers and libraries for required external dependencies are. CMake will need to know where the headers and libraries for required external dependencies are.
We use CMake's `fixup_bundle` to find the DLLs all of our exectuable targets require, and then copy them beside the executable in a post-build step. If `fixup_bundle` is having problems finding a DLL, you can fix it manually on your end by adding the folder containing that DLL to your path. Let us know which DLL CMake had trouble finding, as it is possible a tweak to our CMake files is required. We use CMake's `fixup_bundle` to find the DLLs all of our executable targets require, and then copy them beside the executable in a post-build step. If `fixup_bundle` is having problems finding a DLL, you can fix it manually on your end by adding the folder containing that DLL to your path. Let us know which DLL CMake had trouble finding, as it is possible a tweak to our CMake files is required.
The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure:
@ -69,17 +72,23 @@ Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll
QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
QSslSocket: cannot resolve SSL_get0_next_proto_negotiated QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
To prevent these problems, install OpenSSL yourself. Download the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html): To prevent these problems, install OpenSSL yourself. Download one of the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html):
* Visual C++ 2008 Redistributables * Win32 OpenSSL v1.0.1q
* Win32 OpenSSL v1.0.1p * Win64 OpenSSL v1.0.1q
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
###Build High Fidelity using Visual Studio ###Build High Fidelity using Visual Studio
Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake.
For 32-bit builds:
cmake .. -G "Visual Studio 12" cmake .. -G "Visual Studio 12"
For 64-bit builds:
cmake .. -G "Visual Studio 12 Win64"
Open %HIFI_DIR%\build\hifi.sln and compile. Open %HIFI_DIR%\build\hifi.sln and compile.
###Running Interface ###Running Interface

View file

@ -37,6 +37,7 @@
#include <EntityScriptingInterface.h> // TODO: consider moving to scriptengine.h #include <EntityScriptingInterface.h> // TODO: consider moving to scriptengine.h
#include "avatars/ScriptableAvatar.h" #include "avatars/ScriptableAvatar.h"
#include "entities/AssignmentParentFinder.h"
#include "RecordingScriptingInterface.h" #include "RecordingScriptingInterface.h"
#include "AbstractAudioInterface.h" #include "AbstractAudioInterface.h"
@ -62,6 +63,8 @@ Agent::Agent(ReceivedMessage& message) :
connect(assetThread, &QThread::started, assetClient.data(), &AssetClient::init); connect(assetThread, &QThread::started, assetClient.data(), &AssetClient::init);
assetThread->start(); assetThread->start();
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
DependencyManager::set<ResourceCacheSharedItems>(); DependencyManager::set<ResourceCacheSharedItems>();
DependencyManager::set<SoundCache>(); DependencyManager::set<SoundCache>();
DependencyManager::set<AudioInjectorManager>(); DependencyManager::set<AudioInjectorManager>();
@ -284,6 +287,8 @@ void Agent::executeScript() {
entityScriptingInterface->setEntityTree(_entityViewer.getTree()); entityScriptingInterface->setEntityTree(_entityViewer.getTree());
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
// wire up our additional agent related processing to the update signal // wire up our additional agent related processing to the update signal
QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio); QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio);

View file

@ -1002,7 +1002,8 @@ function setupModelMenus() {
menuName: "Edit", menuName: "Edit",
menuItemName: "Models", menuItemName: "Models",
isSeparator: true, isSeparator: true,
beforeItem: "Physics" beforeItem: "Physics",
grouping: "Advanced"
}); });
if (!Menu.menuItemExists("Edit", "Delete")) { if (!Menu.menuItemExists("Edit", "Delete")) {
print("no delete... adding ours"); print("no delete... adding ours");
@ -1012,7 +1013,8 @@ function setupModelMenus() {
shortcutKeyEvent: { shortcutKeyEvent: {
text: "backspace" text: "backspace"
}, },
afterItem: "Models" afterItem: "Models",
grouping: "Advanced"
}); });
modelMenuAddedDelete = true; modelMenuAddedDelete = true;
} else { } else {
@ -1023,7 +1025,8 @@ function setupModelMenus() {
menuName: "Edit", menuName: "Edit",
menuItemName: "Entity List...", menuItemName: "Entity List...",
shortcutKey: "CTRL+META+L", shortcutKey: "CTRL+META+L",
afterItem: "Models" afterItem: "Models",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "Edit", menuName: "Edit",
@ -1031,7 +1034,8 @@ function setupModelMenus() {
shortcutKey: "CTRL+META+L", shortcutKey: "CTRL+META+L",
afterItem: "Entity List...", afterItem: "Entity List...",
isCheckable: true, isCheckable: true,
isChecked: true isChecked: true,
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "Edit", menuName: "Edit",
@ -1039,79 +1043,91 @@ function setupModelMenus() {
shortcutKey: "CTRL+META+S", shortcutKey: "CTRL+META+S",
afterItem: "Allow Selecting of Large Models", afterItem: "Allow Selecting of Large Models",
isCheckable: true, isCheckable: true,
isChecked: true isChecked: true,
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "Edit", menuName: "Edit",
menuItemName: "Allow Selecting of Lights", menuItemName: "Allow Selecting of Lights",
shortcutKey: "CTRL+SHIFT+META+L", shortcutKey: "CTRL+SHIFT+META+L",
afterItem: "Allow Selecting of Small Models", afterItem: "Allow Selecting of Small Models",
isCheckable: true isCheckable: true,
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "Edit", menuName: "Edit",
menuItemName: "Select All Entities In Box", menuItemName: "Select All Entities In Box",
shortcutKey: "CTRL+SHIFT+META+A", shortcutKey: "CTRL+SHIFT+META+A",
afterItem: "Allow Selecting of Lights" afterItem: "Allow Selecting of Lights",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "Edit", menuName: "Edit",
menuItemName: "Select All Entities Touching Box", menuItemName: "Select All Entities Touching Box",
shortcutKey: "CTRL+SHIFT+META+T", shortcutKey: "CTRL+SHIFT+META+T",
afterItem: "Select All Entities In Box" afterItem: "Select All Entities In Box",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "File", menuName: "File",
menuItemName: "Models", menuItemName: "Models",
isSeparator: true, isSeparator: true,
beforeItem: "Settings" beforeItem: "Settings",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "File", menuName: "File",
menuItemName: "Export Entities", menuItemName: "Export Entities",
shortcutKey: "CTRL+META+E", shortcutKey: "CTRL+META+E",
afterItem: "Models" afterItem: "Models",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "File", menuName: "File",
menuItemName: "Import Entities", menuItemName: "Import Entities",
shortcutKey: "CTRL+META+I", shortcutKey: "CTRL+META+I",
afterItem: "Export Entities" afterItem: "Export Entities",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "File", menuName: "File",
menuItemName: "Import Entities from URL", menuItemName: "Import Entities from URL",
shortcutKey: "CTRL+META+U", shortcutKey: "CTRL+META+U",
afterItem: "Import Entities" afterItem: "Import Entities",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "View", menuName: "Edit",
menuItemName: MENU_AUTO_FOCUS_ON_SELECT, menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true" isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "View", menuName: "Edit",
menuItemName: MENU_EASE_ON_FOCUS, menuItemName: MENU_EASE_ON_FOCUS,
afterItem: MENU_AUTO_FOCUS_ON_SELECT, afterItem: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "View", menuName: "Edit",
menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
afterItem: MENU_EASE_ON_FOCUS, afterItem: MENU_EASE_ON_FOCUS,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true" isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true",
grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
menuName: "View", menuName: "Edit",
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true" isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true",
grouping: "Advanced"
}); });
Entities.setLightsArePickable(false); Entities.setLightsArePickable(false);
@ -1138,10 +1154,10 @@ function cleanupModelMenus() {
Menu.removeMenuItem("File", "Import Entities"); Menu.removeMenuItem("File", "Import Entities");
Menu.removeMenuItem("File", "Import Entities from URL"); Menu.removeMenuItem("File", "Import Entities from URL");
Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT); Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE); Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
Menu.removeMenuItem("View", MENU_SHOW_ZONES_IN_EDIT_MODE); Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE);
} }
Script.scriptEnding.connect(function() { Script.scriptEnding.connect(function() {

View file

@ -47,8 +47,9 @@ Item {
} }
} }
implicitHeight: label.implicitHeight * 1.5 implicitHeight: source.visible ? label.implicitHeight * 1.5 : 0
implicitWidth: label.implicitWidth + label.height * 2.5 implicitWidth: label.implicitWidth + label.height * 2.5
visible: source.visible
Timer { Timer {
id: timer id: timer
@ -66,6 +67,7 @@ Item {
color: label.color color: label.color
text: checkText() text: checkText()
size: label.height size: label.height
visible: source.visible
font.pixelSize: size font.pixelSize: size
function checkText() { function checkText() {
if (!source || source.type != 1 || !source.checkable) { if (!source || source.type != 1 || !source.checkable) {
@ -89,6 +91,7 @@ Item {
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: source.enabled ? hifi.colors.text : hifi.colors.disabledText color: source.enabled ? hifi.colors.text : hifi.colors.disabledText
enabled: source.enabled && source.visible enabled: source.enabled && source.visible
visible: source.visible
function typedText() { function typedText() {
if (source) { if (source) {
switch (source.type) { switch (source.type) {
@ -109,7 +112,7 @@ Item {
x: listView.width - width - 4 x: listView.width - width - 4
size: label.height size: label.height
width: implicitWidth width: implicitWidth
visible: source.type == 2 visible: source.visible && (source.type == 2)
text: "\uF0DA" text: "\uF0DA"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: label.color color: label.color

View file

@ -68,16 +68,22 @@ Menu::Menu() {
dialogsManager.data(), &DialogsManager::toggleLoginDialog); dialogsManager.data(), &DialogsManager::toggleLoginDialog);
} }
addDisabledActionAndSeparator(fileMenu, "Scripts"); // File Menu > Scripts section -- "Advanced" grouping
addDisabledActionAndSeparator(fileMenu, "Scripts", UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O,
qApp, SLOT(loadDialog())); qApp, SLOT(loadDialog()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL, addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog())); Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()),
addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts())); QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R, addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
qApp, SLOT(reloadAllScripts())); qApp, SLOT(reloadAllScripts()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J, addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,
qApp, SLOT(toggleRunningScriptsWidget())); qApp, SLOT(toggleRunningScriptsWidget()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
auto addressManager = DependencyManager::get<AddressManager>(); auto addressManager = DependencyManager::get<AddressManager>();
@ -112,9 +118,11 @@ Menu::Menu() {
dialogsManager.data(), dialogsManager.data(),
SLOT(toggleAddressBar())); SLOT(toggleAddressBar()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0, addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0,
addressManager.data(), SLOT(copyAddress())); addressManager.data(), SLOT(copyAddress()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0, addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0,
addressManager.data(), SLOT(copyPath())); addressManager.data(), SLOT(copyPath()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, addActionToQMenuAndActionHash(fileMenu,
MenuOption::Quit, MenuOption::Quit,
@ -143,11 +151,13 @@ Menu::Menu() {
QAction::PreferencesRole); QAction::PreferencesRole);
addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0, addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0,
dialogsManager.data(), SLOT(editAttachments())); dialogsManager.data(), SLOT(editAttachments()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
MenuWrapper* toolsMenu = addMenu("Tools"); MenuWrapper* toolsMenu = addMenu("Tools");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S, addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S,
dialogsManager.data(), SLOT(showScriptEditor())); dialogsManager.data(), SLOT(showScriptEditor()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
#if defined(Q_OS_MAC) || defined(Q_OS_WIN) #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
auto speechRecognizer = DependencyManager::get<SpeechRecognizer>(); auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
@ -155,13 +165,16 @@ Menu::Menu() {
Qt::CTRL | Qt::SHIFT | Qt::Key_C, Qt::CTRL | Qt::SHIFT | Qt::Key_C,
speechRecognizer->getEnabled(), speechRecognizer->getEnabled(),
speechRecognizer.data(), speechRecognizer.data(),
SLOT(setEnabled(bool))); SLOT(setEnabled(bool)),
UNSPECIFIED_POSITION, "Advanced");
connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
#endif #endif
addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat,
0, // QML Qt::Key_Backslash, 0, // QML Qt::Key_Backslash,
dialogsManager.data(), SLOT(showIRCLink())); dialogsManager.data(), SLOT(showIRCLink()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::AddRemoveFriends, 0, addActionToQMenuAndActionHash(toolsMenu, MenuOption::AddRemoveFriends, 0,
qApp, SLOT(showFriendsWindow())); qApp, SLOT(showFriendsWindow()));
@ -193,22 +206,26 @@ Menu::Menu() {
MenuOption::ToolWindow, MenuOption::ToolWindow,
Qt::CTRL | Qt::ALT | Qt::Key_T, Qt::CTRL | Qt::ALT | Qt::Key_T,
dialogsManager.data(), dialogsManager.data(),
SLOT(toggleToolWindow())); SLOT(toggleToolWindow()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu, addActionToQMenuAndActionHash(toolsMenu,
MenuOption::Console, MenuOption::Console,
Qt::CTRL | Qt::ALT | Qt::Key_J, Qt::CTRL | Qt::ALT | Qt::Key_J,
DependencyManager::get<StandAloneJSConsole>().data(), DependencyManager::get<StandAloneJSConsole>().data(),
SLOT(toggleConsole())); SLOT(toggleConsole()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu, addActionToQMenuAndActionHash(toolsMenu,
MenuOption::ResetSensors, MenuOption::ResetSensors,
0, // QML Qt::Key_Apostrophe, 0, // QML Qt::Key_Apostrophe,
qApp, qApp,
SLOT(resetSensors())); SLOT(resetSensors()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0, addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0,
qApp, SLOT(packageModel())); qApp, SLOT(packageModel()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addMenu(DisplayPlugin::MENU_PATH()); addMenu(DisplayPlugin::MENU_PATH());
{ {
@ -220,7 +237,7 @@ Menu::Menu() {
MenuWrapper* avatarMenu = addMenu("Avatar"); MenuWrapper* avatarMenu = addMenu("Avatar");
QObject* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); QObject* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
MenuWrapper* inputModeMenu = addMenu(MenuOption::InputMenu); MenuWrapper* inputModeMenu = addMenu(MenuOption::InputMenu, "Advanced");
QActionGroup* inputModeGroup = new QActionGroup(inputModeMenu); QActionGroup* inputModeGroup = new QActionGroup(inputModeMenu);
inputModeGroup->setExclusive(false); inputModeGroup->setExclusive(false);
@ -241,17 +258,15 @@ Menu::Menu() {
avatar, avatar,
SLOT(resetSize())); SLOT(resetSize()));
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::KeyboardMotorControl, addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true,
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu())); NULL, NULL, UNSPECIFIED_POSITION, "Advanced");
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ScriptedMotorControl, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu())); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true,
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true); NULL, NULL, UNSPECIFIED_POSITION, "Advanced");
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true);
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()));
MenuWrapper* viewMenu = addMenu("View"); MenuWrapper* viewMenu = addMenu("View");
addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
MenuWrapper* cameraModeMenu = viewMenu->addMenu("Camera Mode"); MenuWrapper* cameraModeMenu = viewMenu->addMenu("Camera Mode");
QActionGroup* cameraModeGroup = new QActionGroup(cameraModeMenu); QActionGroup* cameraModeGroup = new QActionGroup(cameraModeMenu);
@ -275,30 +290,29 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror,
0, //QML Qt::SHIFT | Qt::Key_H, 0, //QML Qt::SHIFT | Qt::Key_H,
true); true);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror,
0, // QML Qt::Key_H,
false, qApp, SLOT(cameraMenuChanged()));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView,
0, false, qApp, SLOT(rotationModeChanged())); 0, false, qApp, SLOT(rotationModeChanged()),
UNSPECIFIED_POSITION, "Advanced");
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::WorldAxes, 0, false, NULL, NULL, UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, 0, false, NULL, NULL, UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::WorldAxes);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats);
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, addActionToQMenuAndActionHash(viewMenu, MenuOption::Log,
Qt::CTRL | Qt::SHIFT | Qt::Key_L, Qt::CTRL | Qt::SHIFT | Qt::Key_L,
qApp, SLOT(toggleLogDialog())); qApp, SLOT(toggleLogDialog()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::AudioNetworkStats, 0, addActionToQMenuAndActionHash(viewMenu, MenuOption::AudioNetworkStats, 0,
dialogsManager.data(), SLOT(audioStatsDetails())); dialogsManager.data(), SLOT(audioStatsDetails()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0,
dialogsManager.data(), SLOT(bandwidthDetails())); dialogsManager.data(), SLOT(bandwidthDetails()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0,
dialogsManager.data(), SLOT(octreeStatsDetails())); dialogsManager.data(), SLOT(octreeStatsDetails()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(viewMenu, "Advanced Menus", 0, false, this, SLOT(toggleAdvancedMenus()));
addCheckableActionToQMenuAndActionHash(viewMenu, "Developer Menus", 0, false, this, SLOT(toggleDeveloperMenus()));
MenuWrapper* developerMenu = addMenu("Developer"); MenuWrapper* developerMenu = addMenu("Developer", "Developer");
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere,
@ -447,9 +461,23 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true, addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true,
avatar, SLOT(setEnableMeshVisible(bool))); avatar, SLOT(setEnableMeshVisible(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::TurnWithHead, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::KeyboardMotorControl,
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ScriptedMotorControl, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableCharacterController, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false);
@ -573,6 +601,14 @@ Menu::Menu() {
#endif #endif
} }
void Menu::toggleAdvancedMenus() {
setGroupingIsVisible("Advanced", !getGroupingIsVisible("Advanced"));
}
void Menu::toggleDeveloperMenus() {
setGroupingIsVisible("Developer", !getGroupingIsVisible("Developer"));
}
void Menu::loadSettings() { void Menu::loadSettings() {
scanMenuBar(&Menu::loadAction); scanMenuBar(&Menu::loadAction);
} }
@ -610,23 +646,36 @@ void Menu::scanMenu(QMenu& menu, settingsAction modifySetting, Settings& setting
settings.endGroup(); settings.endGroup();
} }
void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, int menuItemLocation) { void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName,
int menuItemLocation, const QString& grouping) {
QAction* actionBefore = NULL; QAction* actionBefore = NULL;
QAction* separator;
QAction* separatorText;
if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
actionBefore = destinationMenu->actions()[menuItemLocation]; actionBefore = destinationMenu->actions()[menuItemLocation];
} }
if (actionBefore) { if (actionBefore) {
QAction* separator = new QAction("",destinationMenu); separator = new QAction("",destinationMenu);
destinationMenu->insertAction(actionBefore, separator); destinationMenu->insertAction(actionBefore, separator);
separator->setSeparator(true); separator->setSeparator(true);
QAction* separatorText = new QAction(actionName,destinationMenu); separatorText = new QAction(actionName,destinationMenu);
separatorText->setEnabled(false); separatorText->setEnabled(false);
destinationMenu->insertAction(actionBefore, separatorText); destinationMenu->insertAction(actionBefore, separatorText);
} else { } else {
destinationMenu->addSeparator(); separator = destinationMenu->addSeparator();
(destinationMenu->addAction(actionName))->setEnabled(false); separatorText = destinationMenu->addAction(actionName);
separatorText->setEnabled(false);
}
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << separator;
_groupingActions[grouping] << separatorText;
bool isVisible = getGroupingIsVisible(grouping);
separator->setVisible(isVisible);
separatorText->setVisible(isVisible);
} }
} }
@ -636,7 +685,8 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
const QObject* receiver, const QObject* receiver,
const char* member, const char* member,
QAction::MenuRole role, QAction::MenuRole role,
int menuItemLocation) { int menuItemLocation,
const QString& grouping) {
QAction* action = NULL; QAction* action = NULL;
QAction* actionBefore = NULL; QAction* actionBefore = NULL;
@ -664,6 +714,11 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
_actionHash.insert(actionName, action); _actionHash.insert(actionName, action);
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
return action; return action;
} }
@ -672,7 +727,8 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
const QString& actionName, const QString& actionName,
const QKeySequence& shortcut, const QKeySequence& shortcut,
QAction::MenuRole role, QAction::MenuRole role,
int menuItemLocation) { int menuItemLocation,
const QString& grouping) {
QAction* actionBefore = NULL; QAction* actionBefore = NULL;
if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
@ -699,6 +755,11 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
_actionHash.insert(action->text(), action); _actionHash.insert(action->text(), action);
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
return action; return action;
} }
@ -708,19 +769,29 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMe
const bool checked, const bool checked,
const QObject* receiver, const QObject* receiver,
const char* member, const char* member,
int menuItemLocation) { int menuItemLocation,
const QString& grouping) {
QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member, QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member,
QAction::NoRole, menuItemLocation); QAction::NoRole, menuItemLocation);
action->setCheckable(true); action->setCheckable(true);
action->setChecked(checked); action->setChecked(checked);
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
return action; return action;
} }
void Menu::removeAction(MenuWrapper* menu, const QString& actionName) { void Menu::removeAction(MenuWrapper* menu, const QString& actionName) {
menu->removeAction(_actionHash.value(actionName)); auto action = _actionHash.value(actionName);
menu->removeAction(action);
_actionHash.remove(actionName); _actionHash.remove(actionName);
for (auto& grouping : _groupingActions) {
grouping.remove(action);
}
} }
void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) { void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) {
@ -850,7 +921,7 @@ int Menu::positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPositi
} }
MenuWrapper* Menu::addMenu(const QString& menuName) { MenuWrapper* Menu::addMenu(const QString& menuName, const QString& grouping) {
QStringList menuTree = menuName.split(">"); QStringList menuTree = menuName.split(">");
MenuWrapper* addTo = NULL; MenuWrapper* addTo = NULL;
MenuWrapper* menu = NULL; MenuWrapper* menu = NULL;
@ -866,6 +937,14 @@ MenuWrapper* Menu::addMenu(const QString& menuName) {
addTo = menu; addTo = menu;
} }
if (isValidGrouping(grouping)) {
auto action = getMenuAction(menuName);
if (action) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
}
QMenuBar::repaint(); QMenuBar::repaint();
return menu; return menu;
} }
@ -897,7 +976,7 @@ bool Menu::menuExists(const QString& menuName) {
return false; return false;
} }
void Menu::addSeparator(const QString& menuName, const QString& separatorName) { void Menu::addSeparator(const QString& menuName, const QString& separatorName, const QString& grouping) {
MenuWrapper* menuObj = getMenu(menuName); MenuWrapper* menuObj = getMenu(menuName);
if (menuObj) { if (menuObj) {
addDisabledActionAndSeparator(menuObj, separatorName); addDisabledActionAndSeparator(menuObj, separatorName);
@ -952,15 +1031,16 @@ void Menu::addMenuItem(const MenuItemProperties& properties) {
QAction* menuItemAction = NULL; QAction* menuItemAction = NULL;
if (properties.isSeparator) { if (properties.isSeparator) {
addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition); addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition, properties.grouping);
} else if (properties.isCheckable) { } else if (properties.isCheckable) {
menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName, menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
properties.shortcutKeySequence, properties.isChecked, properties.shortcutKeySequence, properties.isChecked,
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition); MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
requestedPosition, properties.grouping);
} else { } else {
menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence, menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence,
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
QAction::NoRole, requestedPosition); QAction::NoRole, requestedPosition, properties.grouping);
} }
if (shortcut && menuItemAction) { if (shortcut && menuItemAction) {
connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger())); connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger()));
@ -975,7 +1055,7 @@ void Menu::removeMenuItem(const QString& menu, const QString& menuitem) {
removeAction(menuObj, menuitem); removeAction(menuObj, menuitem);
QMenuBar::repaint(); QMenuBar::repaint();
} }
}; }
bool Menu::menuItemExists(const QString& menu, const QString& menuitem) { bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
QAction* menuItemAction = _actionHash.value(menuitem); QAction* menuItemAction = _actionHash.value(menuitem);
@ -983,7 +1063,31 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
return (getMenu(menu) != NULL); return (getMenu(menu) != NULL);
} }
return false; return false;
}; }
bool Menu::getGroupingIsVisible(const QString& grouping) {
if (grouping.isEmpty() || grouping.isNull()) {
return true;
}
if (_groupingVisible.contains(grouping)) {
return _groupingVisible[grouping];
}
return false;
}
void Menu::setGroupingIsVisible(const QString& grouping, bool isVisible) {
// NOTE: Default grouping always visible
if (grouping.isEmpty() || grouping.isNull()) {
return;
}
_groupingVisible[grouping] = isVisible;
for (auto action: _groupingActions[grouping]) {
action->setVisible(isVisible);
}
QMenuBar::repaint();
}
MenuWrapper::MenuWrapper(QMenu* menu) : _realMenu(menu) { MenuWrapper::MenuWrapper(QMenu* menu) : _realMenu(menu) {
@ -1005,8 +1109,8 @@ void MenuWrapper::setEnabled(bool enabled) {
_realMenu->setEnabled(enabled); _realMenu->setEnabled(enabled);
} }
void MenuWrapper::addSeparator() { QAction* MenuWrapper::addSeparator() {
_realMenu->addSeparator(); return _realMenu->addSeparator();
} }
void MenuWrapper::addAction(QAction* action) { void MenuWrapper::addAction(QAction* action) {

View file

@ -30,7 +30,7 @@ public:
QList<QAction*> actions(); QList<QAction*> actions();
MenuWrapper* addMenu(const QString& menuName); MenuWrapper* addMenu(const QString& menuName);
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
void addSeparator(); QAction* addSeparator();
void addAction(QAction* action); void addAction(QAction* action);
QAction* addAction(const QString& menuName); QAction* addAction(const QString& menuName);
@ -74,28 +74,33 @@ public:
const QObject* receiver = NULL, const QObject* receiver = NULL,
const char* member = NULL, const char* member = NULL,
QAction::MenuRole role = QAction::NoRole, QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION); int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
QAction* addActionToQMenuAndActionHash(MenuWrapper* destinationMenu, QAction* addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
QAction* action, QAction* action,
const QString& actionName = QString(), const QString& actionName = QString(),
const QKeySequence& shortcut = 0, const QKeySequence& shortcut = 0,
QAction::MenuRole role = QAction::NoRole, QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION); int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
QAction* addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu, QAction* addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
const QString& actionName, const QString& actionName,
const QKeySequence& shortcut = 0, const QKeySequence& shortcut = 0,
const bool checked = false, const bool checked = false,
const QObject* receiver = NULL, const QObject* receiver = NULL,
const char* member = NULL, const char* member = NULL,
int menuItemLocation = UNSPECIFIED_POSITION); int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
void removeAction(MenuWrapper* menu, const QString& actionName); void removeAction(MenuWrapper* menu, const QString& actionName);
public slots: public slots:
MenuWrapper* addMenu(const QString& menuName); MenuWrapper* addMenu(const QString& menuName, const QString& grouping = QString());
void removeMenu(const QString& menuName); void removeMenu(const QString& menuName);
bool menuExists(const QString& menuName); bool menuExists(const QString& menuName);
void addSeparator(const QString& menuName, const QString& separatorName); void addSeparator(const QString& menuName, const QString& separatorName, const QString& grouping = QString());
void removeSeparator(const QString& menuName, const QString& separatorName); void removeSeparator(const QString& menuName, const QString& separatorName);
void addMenuItem(const MenuItemProperties& properties); void addMenuItem(const MenuItemProperties& properties);
void removeMenuItem(const QString& menuName, const QString& menuitem); void removeMenuItem(const QString& menuName, const QString& menuitem);
@ -103,6 +108,12 @@ public slots:
bool isOptionChecked(const QString& menuOption) const; bool isOptionChecked(const QString& menuOption) const;
void setIsOptionChecked(const QString& menuOption, bool isChecked); void setIsOptionChecked(const QString& menuOption, bool isChecked);
bool getGroupingIsVisible(const QString& grouping);
void setGroupingIsVisible(const QString& grouping, bool isVisible); /// NOTE: the "" grouping is always visible
void toggleDeveloperMenus();
void toggleAdvancedMenus();
private: private:
typedef void(*settingsAction)(Settings&, QAction&); typedef void(*settingsAction)(Settings&, QAction&);
static void loadAction(Settings& settings, QAction& action); static void loadAction(Settings& settings, QAction& action);
@ -111,8 +122,10 @@ private:
void scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings); void scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings);
/// helper method to have separators with labels that are also compatible with OS X /// helper method to have separators with labels that are also compatible with OS X
void addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, void addDisabledActionAndSeparator(MenuWrapper* destinationMenu,
int menuItemLocation = UNSPECIFIED_POSITION); const QString& actionName,
int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
QAction* getActionFromName(const QString& menuName, MenuWrapper* menu); QAction* getActionFromName(const QString& menuName, MenuWrapper* menu);
MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu); MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu);
@ -123,6 +136,10 @@ private:
int positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition); int positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition);
QHash<QString, QAction*> _actionHash; QHash<QString, QAction*> _actionHash;
bool isValidGrouping(const QString& grouping) const { return grouping == "Advanced" || grouping == "Developer"; }
QHash<QString, bool> _groupingVisible;
QHash<QString, QSet<QAction*>> _groupingActions;
}; };
namespace MenuOption { namespace MenuOption {

View file

@ -51,6 +51,14 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
static gpu::Stream::FormatPointer theFormat; static gpu::Stream::FormatPointer theFormat;
if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) { if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) {
if (!theBuffer) {
const float CLIP = 1.0f;
const glm::vec2 vertices[4] = { { -CLIP, -CLIP }, { CLIP, -CLIP }, { -CLIP, CLIP }, { CLIP, CLIP } };
theBuffer = std::make_shared<gpu::Buffer>(sizeof(vertices), (const gpu::Byte*) vertices);
theFormat = std::make_shared<gpu::Stream::Format>();
theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ));
}
glm::mat4 projMat; glm::mat4 projMat;
viewFrustum.evalProjectionMatrix(projMat); viewFrustum.evalProjectionMatrix(projMat);
@ -59,6 +67,8 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewTransform); batch.setViewTransform(viewTransform);
batch.setModelTransform(Transform()); // only for Mac batch.setModelTransform(Transform()); // only for Mac
batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8);
batch.setInputFormat(theFormat);
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
batch.setResourceTexture(0, skybox.getCubemap()); batch.setResourceTexture(0, skybox.getCubemap());

View file

@ -95,6 +95,7 @@ void menuItemPropertiesFromScriptValue(const QScriptValue& object, MenuItemPrope
} }
properties.beforeItem = object.property("beforeItem").toVariant().toString(); properties.beforeItem = object.property("beforeItem").toVariant().toString();
properties.afterItem = object.property("afterItem").toVariant().toString(); properties.afterItem = object.property("afterItem").toVariant().toString();
properties.grouping = object.property("grouping").toVariant().toString();
} }

View file

@ -43,6 +43,8 @@ public:
bool isCheckable; bool isCheckable;
bool isChecked; bool isChecked;
bool isSeparator; bool isSeparator;
QString grouping; /// Either: "", "Advanced", or "Developer"
}; };
Q_DECLARE_METATYPE(MenuItemProperties) Q_DECLARE_METATYPE(MenuItemProperties)
QScriptValue menuItemPropertiesToScriptValue(QScriptEngine* engine, const MenuItemProperties& props); QScriptValue menuItemPropertiesToScriptValue(QScriptEngine* engine, const MenuItemProperties& props);

View file

@ -95,6 +95,14 @@ void VrMenu::setRootMenu(QObject* rootMenu) {
_rootMenu = rootMenu; _rootMenu = rootMenu;
} }
void updateQmlItemFromAction(QObject* target, QAction* source) {
target->setProperty("checkable", source->isCheckable());
target->setProperty("enabled", source->isEnabled());
target->setProperty("text", source->text());
target->setProperty("checked", source->isChecked());
target->setProperty("visible", source->isVisible());
}
void VrMenu::addMenu(QMenu* menu) { void VrMenu::addMenu(QMenu* menu) {
Q_ASSERT(!MenuUserData::forObject(menu)); Q_ASSERT(!MenuUserData::forObject(menu));
QObject* parent = menu->parent(); QObject* parent = menu->parent();
@ -119,14 +127,12 @@ void VrMenu::addMenu(QMenu* menu) {
// Bind the QML and Widget together // Bind the QML and Widget together
new MenuUserData(menu, result); new MenuUserData(menu, result);
} auto menuAction = menu->menuAction();
updateQmlItemFromAction(result, menuAction);
QObject::connect(menuAction, &QAction::changed, [=] {
updateQmlItemFromAction(result, menuAction);
});
void updateQmlItemFromAction(QObject* target, QAction* source) {
target->setProperty("checkable", source->isCheckable());
target->setProperty("enabled", source->isEnabled());
target->setProperty("visible", source->isVisible());
target->setProperty("text", source->text());
target->setProperty("checked", source->isChecked());
} }
void bindActionToQmlAction(QObject* qmlAction, QAction* action) { void bindActionToQmlAction(QObject* qmlAction, QAction* action) {