diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 65989b389e..d87a5f1cc9 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -413,6 +413,9 @@ void AvatarMixer::handleAvatarDataPacket(QSharedPointer message } void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer message, SharedNodePointer senderNode) { + auto nodeList = DependencyManager::get(); + nodeList->getOrCreateLinkedData(senderNode); + if (senderNode->getLinkedData()) { AvatarMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData()); if (nodeData != nullptr) { diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml deleted file mode 100644 index fec151d755..0000000000 --- a/interface/resources/qml/MarketplaceComboBox.qml +++ /dev/null @@ -1,103 +0,0 @@ -// -// MarketplaceComboBox.qml -// -// Created by Elisa Lupin-Jimenez on 3 Aug 2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtWebChannel 1.0 -import QtWebEngine 1.1 -import QtWebSockets 1.0 -import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel - -import "controls" -import "controls-uit" as Controls -import "styles" -import "styles-uit" - - -Rectangle { - HifiConstants { id: hifi } - id: marketplaceComboBox - anchors.fill: parent - color: hifi.colors.baseGrayShadow - property var currentUrl: "https://metaverse.highfidelity.com/marketplace" - - Controls.BaseWebView { - id: webview - url: currentUrl - anchors.top: switchMarketView.bottom - width: parent.width - height: parent.height - 40 - focus: true - - Timer { - id: zipTimer - running: false - repeat: false - interval: 1500 - property var handler; - onTriggered: handler(); - } - - property var autoCancel: 'var element = $("a.btn.cancel"); - element.click();' - - onNewViewRequested: { - var component = Qt.createComponent("Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView); - if (File.isZippedFbx(desktop.currentUrl)) { - zipTimer.handler = function() { - newWindow.destroy(); - runJavaScript(autoCancel); - } - zipTimer.start(); - } - } - - property var simpleDownload: 'var element = $("a.download-file"); - element.removeClass("download-file"); - element.removeAttr("download");' - - onLinkHovered: { - desktop.currentUrl = hoveredUrl; - // add an error message for non-fbx files - if (File.isZippedFbx(desktop.currentUrl)) { - runJavaScript(simpleDownload, function(){console.log("ran the JS");}); - } - - } - - } - - Controls.ComboBox { - id: switchMarketView - anchors.top: parent.top - anchors.right: parent.right - colorScheme: hifi.colorSchemes.dark - width: 200 - height: 40 - visible: true - model: ["Marketplace", "Clara.io"] - onCurrentIndexChanged: { - if (currentIndex === 0) { webview.url = "https://metaverse.highfidelity.com/marketplace"; } - if (currentIndex === 1) { webview.url = "https://clara.io/library"; } - } - - } - - Controls.Label { - id: switchMarketLabel - anchors.verticalCenter: switchMarketView.verticalCenter - anchors.right: switchMarketView.left - color: hifi.colors.white - text: "Explore interesting content from: " - } - -} \ No newline at end of file diff --git a/interface/resources/qml/Marketplaces.qml b/interface/resources/qml/Marketplaces.qml new file mode 100644 index 0000000000..70a20286d3 --- /dev/null +++ b/interface/resources/qml/Marketplaces.qml @@ -0,0 +1,167 @@ +// +// Marketplaces.qml +// +// Created by Elisa Lupin-Jimenez on 3 Aug 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtWebChannel 1.0 +import QtWebEngine 1.1 +import QtWebSockets 1.0 +import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel + +import "controls" +import "controls-uit" as Controls +import "styles" +import "styles-uit" + + +Rectangle { + HifiConstants { id: hifi } + id: marketplace + anchors.fill: parent + property var marketplacesUrl: "../../scripts/system/html/marketplaces.html" + property int statusBarHeight: 50 + property int statusMargin: 50 + property string standardMessage: "Check out other marketplaces." + property string claraMessage: "Choose a model and click Download -> Autodesk FBX." + property string claraError: "High Fidelity only supports Autodesk FBX models." + + Controls.BaseWebView { + id: webview + url: marketplacesUrl + anchors.top: marketplace.top + width: parent.width + height: parent.height - statusBarHeight + focus: true + + Timer { + id: zipTimer + running: false + repeat: false + interval: 1500 + property var handler; + onTriggered: handler(); + } + + Timer { + id: alertTimer + running: false + repeat: false + interval: 9000 + property var handler; + onTriggered: handler(); + } + + property var autoCancel: 'var element = $("a.btn.cancel"); + element.click();' + + property var simpleDownload: 'var element = $("a.download-file"); + element.removeClass("download-file"); + element.removeAttr("download");' + + function displayErrorStatus() { + alertTimer.handler = function() { + statusLabel.text = claraMessage; + statusBar.color = hifi.colors.blueHighlight; + statusIcon.text = hifi.glyphs.info; + } + alertTimer.start(); + } + + property var notFbxHandler: 'var element = $("a.btn.btn-primary.viewer-button.download-file") + element.click();' + + // this code is for removing other file types from Clara.io's download options + //property var checkFileType: "$('[data-extension]:not([data-extension=\"fbx\"])').parent().remove()" + + onLinkHovered: { + desktop.currentUrl = hoveredUrl; + //runJavaScript(checkFileType, function(){console.log("Remove filetypes JS injection");}); + if (File.isZippedFbx(desktop.currentUrl)) { + runJavaScript(simpleDownload, function(){console.log("Download JS injection");}); + return; + } + + if (File.isZipped(desktop.currentUrl)) { + statusLabel.text = claraError; + statusBar.color = hifi.colors.redHighlight; + statusIcon.text = hifi.glyphs.alert; + runJavaScript(notFbxHandler, displayErrorStatus()); + } + + } + + onLoadingChanged: { + if (File.isClaraLink(webview.url)) { + statusLabel.text = claraMessage; + } else { + statusLabel.text = standardMessage; + } + statusBar.color = hifi.colors.blueHighlight; + statusIcon.text = hifi.glyphs.info; + } + + onNewViewRequested: { + var component = Qt.createComponent("Browser.qml"); + var newWindow = component.createObject(desktop); + request.openIn(newWindow.webView); + if (File.isZippedFbx(desktop.currentUrl)) { + runJavaScript(autoCancel); + zipTimer.handler = function() { + newWindow.destroy(); + } + zipTimer.start(); + } + } + + } + + Rectangle { + id: statusBar + anchors.top: webview.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + color: hifi.colors.blueHighlight + + Controls.Button { + id: switchMarketView + anchors.right: parent.right + anchors.rightMargin: statusMargin + anchors.verticalCenter: parent.verticalCenter + width: 150 + text: "See all markets" + onClicked: { + webview.url = "../../scripts/system/html/marketplaces.html"; + statusLabel.text = standardMessage; + } + } + + Controls.Label { + id: statusLabel + anchors.verticalCenter: switchMarketView.verticalCenter + anchors.left: parent.left + anchors.leftMargin: statusMargin + color: hifi.colors.white + text: standardMessage + size: 18 + } + + HiFiGlyphs { + id: statusIcon + anchors.right: statusLabel.left + anchors.verticalCenter: statusLabel.verticalCenter + text: hifi.glyphs.info + color: hifi.colors.white + size: hifi.fontSizes.tableHeadingIcon + } + + } + +} \ No newline at end of file diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 180e5e1bcc..a0750c1f7f 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -59,6 +59,11 @@ Item { font.pixelSize: root.fontSize text: "Avatars: " + root.avatarCount } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Frame Rate: " + root.framerate.toFixed(2); + } Text { color: root.fontColor; font.pixelSize: root.fontSize diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9c44876e6e..d846a5c6d1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1685,7 +1685,6 @@ void Application::paintGL() { Finally clearFlag([this] { _inPaint = false; }); _frameCount++; - _frameCounter.increment(); auto lastPaintBegin = usecTimestampNow(); PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, (uint64_t)_frameCount); @@ -1922,6 +1921,7 @@ void Application::paintGL() { { PROFILE_RANGE(__FUNCTION__ "/pluginOutput"); PerformanceTimer perfTimer("pluginOutput"); + _frameCounter.increment(); displayPlugin->submitFrame(frame); } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 7fdf5cd57d..fbe272a562 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -117,10 +117,12 @@ void Stats::updateStats(bool force) { // we need to take one avatar out so we don't include ourselves STAT_UPDATE(avatarCount, avatarManager->size() - 1); STAT_UPDATE(serverCount, (int)nodeList->size()); - STAT_UPDATE(renderrate, qApp->getFps()); + STAT_UPDATE(framerate, qApp->getFps()); if (qApp->getActiveDisplayPlugin()) { - STAT_UPDATE(presentrate, qApp->getActiveDisplayPlugin()->presentRate()); - STAT_UPDATE(presentnewrate, qApp->getActiveDisplayPlugin()->newFramePresentRate()); + auto displayPlugin = qApp->getActiveDisplayPlugin(); + STAT_UPDATE(renderrate, displayPlugin->renderRate()); + STAT_UPDATE(presentrate, displayPlugin->presentRate()); + STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate()); STAT_UPDATE(presentdroprate, qApp->getActiveDisplayPlugin()->droppedFrameRate()); } else { STAT_UPDATE(presentrate, -1); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 4be2d88d9e..138f24cf19 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -32,8 +32,13 @@ class Stats : public QQuickItem { Q_PROPERTY(float audioPacketlossDownstream READ getAudioPacketLossDownstream) STATS_PROPERTY(int, serverCount, 0) + // How often the app is creating new gpu::Frames + STATS_PROPERTY(float, framerate, 0) + // How often the display plugin is executing a given frame STATS_PROPERTY(float, renderrate, 0) + // How often the display plugin is presenting to the device STATS_PROPERTY(float, presentrate, 0) + STATS_PROPERTY(float, presentnewrate, 0) STATS_PROPERTY(float, presentdroprate, 0) STATS_PROPERTY(int, simrate, 0) @@ -116,6 +121,7 @@ public slots: void forceUpdateStats() { updateStats(true); } signals: + void framerateChanged(); void expandedChanged(); void timingExpandedChanged(); void serverCountChanged(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 5ee097d355..4c683a27f8 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -475,32 +475,28 @@ bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { } void OpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) { - if (_lockCurrentTexture) { - return; - } - withNonPresentThreadLock([&] { _newFrameQueue.push(newFrame); }); } void OpenGLDisplayPlugin::updateFrameData() { + if (_lockCurrentTexture) { + return; + } withPresentThreadLock([&] { - gpu::FramePointer oldFrame = _currentFrame; - uint32_t skippedCount = 0; if (!_newFrameQueue.empty()) { // We're changing frames, so we can cleanup any GL resources that might have been used by the old frame _gpuContext->recycle(); } + if (_newFrameQueue.size() > 1) { + _droppedFrameRate.increment(_newFrameQueue.size() - 1); + } while (!_newFrameQueue.empty()) { _currentFrame = _newFrameQueue.front(); _newFrameQueue.pop(); _gpuContext->consumeFrameUpdates(_currentFrame); - if (_currentFrame && oldFrame) { - skippedCount += (_currentFrame->frameIndex - oldFrame->frameIndex) - 1; - } } - _droppedFrameRate.increment(skippedCount); }); } @@ -598,6 +594,7 @@ void OpenGLDisplayPlugin::internalPresent() { batch.draw(gpu::TRIANGLE_STRIP, 4); }); swapBuffers(); + _presentRate.increment(); } void OpenGLDisplayPlugin::present() { @@ -612,6 +609,13 @@ void OpenGLDisplayPlugin::present() { if (_currentFrame) { { + withPresentThreadLock([&] { + _renderRate.increment(); + if (_currentFrame != _lastFrame) { + _newFrameRate.increment(); + } + _lastFrame = _currentFrame; + }); // Execute the frame rendering commands PROFILE_RANGE_EX("execute", 0xff00ff00, (uint64_t)presentCount()) _gpuContext->executeFrame(_currentFrame); @@ -628,7 +632,6 @@ void OpenGLDisplayPlugin::present() { PROFILE_RANGE_EX("internalPresent", 0xff00ffff, (uint64_t)presentCount()) internalPresent(); } - _presentRate.increment(); } } @@ -637,17 +640,18 @@ float OpenGLDisplayPlugin::newFramePresentRate() const { } float OpenGLDisplayPlugin::droppedFrameRate() const { - float result; - withNonPresentThreadLock([&] { - result = _droppedFrameRate.rate(); - }); - return result; + return _droppedFrameRate.rate(); } float OpenGLDisplayPlugin::presentRate() const { return _presentRate.rate(); } +float OpenGLDisplayPlugin::renderRate() const { + return _renderRate.rate(); +} + + void OpenGLDisplayPlugin::swapBuffers() { static auto context = _container->getPrimaryWidget()->context(); context->swapBuffers(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 51b33c9bcd..afd8f7d45b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -62,6 +62,8 @@ public: float droppedFrameRate() const override; + float renderRate() const override; + bool beginFrameRender(uint32_t frameIndex) override; virtual bool wantVsync() const { return true; } @@ -109,8 +111,10 @@ protected: RateCounter<> _droppedFrameRate; RateCounter<> _newFrameRate; RateCounter<> _presentRate; + RateCounter<> _renderRate; gpu::FramePointer _currentFrame; + gpu::FramePointer _lastFrame; gpu::FramebufferPointer _compositeFramebuffer; gpu::PipelinePointer _overlayPipeline; gpu::PipelinePointer _simplePipeline; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp b/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp index 9b933cfb90..1d22ae7a52 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp @@ -104,7 +104,7 @@ bool GLTextureTransferHelper::processQueueItems(const Queue& messages) { QThread::usleep(1); result = glClientWaitSync(fence, 0, 0); } - glDeleteSync(package.fence); + glDeleteSync(fence); } object->_contentStamp = texturePointer->getDataStamp(); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 288cee3223..5111bda95f 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -178,6 +178,8 @@ public: virtual bool beginFrameRender(uint32_t frameIndex) { return true; } virtual float devicePixelRatio() { return 1.0f; } + // Rate at which we render frames + virtual float renderRate() const { return -1.0f; } // Rate at which we present to the display device virtual float presentRate() const { return -1.0f; } // Rate at which new frames are being presented to the display device diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index fa38e46d31..ad6a3cdf6f 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -65,13 +65,21 @@ bool FileScriptingInterface::isTempDir(QString tempDir) { folderName = "/" + testDir.section("/", -1); QString testContainer = testDir; testContainer.remove(folderName); - if (testContainer == tempContainer) return true; - return false; + return (testContainer == tempContainer); +} + +// checks whether the webview is displaying a Clara.io page for Marketplaces.qml +bool FileScriptingInterface::isClaraLink(QUrl url) { + return (url.toString().contains("clara.io") && !url.toString().contains("clara.io/signup")); } bool FileScriptingInterface::isZippedFbx(QUrl url) { - if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true; - return false; + return (url.toString().endsWith("fbx.zip")); +} + +// checks whether a user tries to download a file that is not in .fbx format +bool FileScriptingInterface::isZipped(QUrl url) { + return (url.toString().endsWith(".zip")); } // this function is not in use diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index dd6ca3225b..d9a100b293 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -25,6 +25,8 @@ public: public slots: bool isZippedFbx(QUrl url); + bool isZipped(QUrl url); + bool isClaraLink(QUrl url); QString convertUrlToPath(QUrl url); void runUnzip(QString path, QUrl url); QString getTempDir(); diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index f1cad94281..838a4121cd 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -139,6 +139,7 @@ void OculusDisplayPlugin::hmdPresent() { logWarning("Failed to present"); } } + _presentRate.increment(); } bool OculusDisplayPlugin::isHmdMounted() const { diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 76ca9abc79..4c4fcbbd37 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -174,6 +174,7 @@ public: vr::Texture_t texture{ (void*)oglplus::GetName(_framebuffer->color), vr::API_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &texture, &leftBounds); vr::VRCompositor()->Submit(vr::Eye_Right, &texture, &rightBounds); + _plugin._presentRate.increment(); PoseData nextRender, nextSim; nextRender.frameIndex = _plugin.presentCount(); vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount); @@ -192,7 +193,6 @@ public: nextRender.update(sensorResetMat); nextSim.update(sensorResetMat); - _plugin.withNonPresentThreadLock([&] { _nextRender = nextRender; _nextSim = nextSim; diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 98825c594d..f9cd32be46 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -37,49 +37,92 @@ var DEFAULT_SCRIPTS = [ // add a menu item for debugging var MENU_CATEGORY = "Developer"; var MENU_ITEM = "Debug defaultScripts.js"; -var debuggingDefaultScripts = false; + +var SETTINGS_KEY = '_debugDefaultScriptsIsChecked'; +var previousSetting = Settings.getValue(SETTINGS_KEY); + +if (previousSetting === '' || previousSetting === false || previousSetting === 'false') { + previousSetting = false; +} + +if (previousSetting === true || previousSetting === 'true') { + previousSetting = true; +} + + + if (Menu.menuExists(MENU_CATEGORY) && !Menu.menuItemExists(MENU_CATEGORY, MENU_ITEM)) { Menu.addMenuItem({ menuName: MENU_CATEGORY, menuItemName: MENU_ITEM, isCheckable: true, - isChecked: false, + isChecked: previousSetting, grouping: "Advanced" }); } -// start all scripts -if (Menu.isOptionChecked(MENU_ITEM)) { - // we're debugging individual default scripts - // so we load each into its own ScriptEngine instance - debuggingDefaultScripts = true; - for (var i in DEFAULT_SCRIPTS) { - Script.load(DEFAULT_SCRIPTS[i]); - } -} else { - // include all default scripts into this ScriptEngine +function runDefaultsTogether() { for (var j in DEFAULT_SCRIPTS) { Script.include(DEFAULT_SCRIPTS[j]); } } -function stopLoadedScripts() { - if (debuggingDefaultScripts) { - // remove debug script loads - var runningScripts = ScriptDiscoveryService.getRunning(); - for (var i in runningScripts) { - var scriptName = runningScripts[i].name; - for (var j in DEFAULT_SCRIPTS) { - if (DEFAULT_SCRIPTS[j].slice(-scriptName.length) === scriptName) { - ScriptDiscoveryService.stopScript(runningScripts[i].url); - } - } +function runDefaultsSeparately() { + for (var i in DEFAULT_SCRIPTS) { + Script.load(DEFAULT_SCRIPTS[i]); + } +} +// start all scripts +if (Menu.isOptionChecked(MENU_ITEM)) { + // we're debugging individual default scripts + // so we load each into its own ScriptEngine instance + debuggingDefaultScripts = true; + runDefaultsSeparately(); +} else { + // include all default scripts into this ScriptEngine + runDefaultsTogether(); +} + +function menuItemEvent(menuItem) { + if (menuItem == MENU_ITEM) { + + isChecked = Menu.isOptionChecked(MENU_ITEM); + if (isChecked === true) { + Settings.setValue(SETTINGS_KEY, true); + } else if (isChecked === false) { + Settings.setValue(SETTINGS_KEY, false); } - if (!Menu.isOptionChecked(MENU_ITEM)) { - Menu.removeMenuItem(MENU_CATEGORY, MENU_ITEM); + Window.alert('You must reload all scripts for this to take effect.') + } + + +} + + + +function stopLoadedScripts() { + // remove debug script loads + var runningScripts = ScriptDiscoveryService.getRunning(); + for (var i in runningScripts) { + var scriptName = runningScripts[i].name; + for (var j in DEFAULT_SCRIPTS) { + if (DEFAULT_SCRIPTS[j].slice(-scriptName.length) === scriptName) { + ScriptDiscoveryService.stopScript(runningScripts[i].url); + } } } } -Script.scriptEnding.connect(stopLoadedScripts); +function removeMenuItem() { + if (!Menu.isOptionChecked(MENU_ITEM)) { + Menu.removeMenuItem(MENU_CATEGORY, MENU_ITEM); + } +} + +Script.scriptEnding.connect(function() { + stopLoadedScripts(); + removeMenuItem(); +}); + +Menu.menuItemEvent.connect(menuItemEvent); \ No newline at end of file diff --git a/scripts/system/html/css/marketplaces.css b/scripts/system/html/css/marketplaces.css new file mode 100644 index 0000000000..734501f3fc --- /dev/null +++ b/scripts/system/html/css/marketplaces.css @@ -0,0 +1,98 @@ +/* +// +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ +body { + background: white; + padding: 0 0 0 0; + font-family:Raleway-SemiBold; +} +.marketplaces-container { + display: inline-block; + color: black; + width: 94%; + margin-left: 3%; + height: 100%; +} +.marketplaces-title { + margin-top: 45px; + margin-bottom: 20px; +} +.marketplaces-intro-text { + margin-bottom: 60px; +} +.marketplace-tile { + float:left; + width: 100%; +} +.marketplace-tile-first-column { + text-align: center; + float: left; + width: 33%; +} +.marketplace-tile-second-column { + float: left; + margin-left:4%; + width: 62%; +} +.exploreButton { + font-size: 16px !important; + width: 200px !important; + height: 45px !important; + margin-top: 20px; + margin-bottom: 30px; +} +.tile-divider { + width: 100%; + margin-left: 0%; + display: block; + height: 1px; + border: 0; + border-top: 1px solid lightgrey; + margin: 1em 0; + padding: 0; + margin-bottom: 30px; +} +.marketplace-tile-description { + margin-top: 15px; + margin-bottom: 30px; +} +.marketplace-tile-image { + margin-top:15px; + max-width: 256px; + height: 128px; + margin-bottom:60px; + -webkit-box-shadow: -1px 4px 16px 0px rgba(0, 0, 0, 0.48); + -moz-box-shadow: -1px 4px 16px 0px rgba(0, 0, 0, 0.48); + box-shadow: -1px 4px 16px 0px rgba(0, 0, 0, 0.48); +} +.marketplace-clara-steps { + padding-left: 15px; +} +.marketplace-clara-steps > li { + margin-top: 5px; +} +@media (max-width:768px) { + .marketplace-tile-first-column { + float: left; + width: 100%; + } + .marketplace-tile-second-column { + float: left; + width: 100%; + } + .exploreButton-holder { + width:100%; + text-align:center; + } + .tile-divider { + width: 100%; + margin-left: 0%; +} +.marketplace-tile-image{ + margin-bottom:15px; +} +} \ No newline at end of file diff --git a/scripts/system/html/img/clara-tile.png b/scripts/system/html/img/clara-tile.png new file mode 100644 index 0000000000..ae431dd510 Binary files /dev/null and b/scripts/system/html/img/clara-tile.png differ diff --git a/scripts/system/html/img/hifi-marketplace-tile.png b/scripts/system/html/img/hifi-marketplace-tile.png new file mode 100644 index 0000000000..9a95c081a0 Binary files /dev/null and b/scripts/system/html/img/hifi-marketplace-tile.png differ diff --git a/scripts/system/html/js/marketplaces.js b/scripts/system/html/js/marketplaces.js new file mode 100644 index 0000000000..a1b3847b3c --- /dev/null +++ b/scripts/system/html/js/marketplaces.js @@ -0,0 +1,12 @@ +function loaded() { +bindExploreButtons(); +} + +function bindExploreButtons() { + $('#exploreClaraMarketplace').on('click', function() { + window.location = "https://clara.io/library?public=true" + }) + $('#exploreHifiMarketplace').on('click', function() { + window.location = "http://www.highfidelity.com/marketplace" + }) +} \ No newline at end of file diff --git a/scripts/system/html/marketplaces.html b/scripts/system/html/marketplaces.html new file mode 100644 index 0000000000..ea85c7ec62 --- /dev/null +++ b/scripts/system/html/marketplaces.html @@ -0,0 +1,65 @@ + + + + Marketplaces + + + + + + + + + +
+

+ Marketplaces +

+
+

+ You can bring content into High Fidelity forom anywhere you want. Here are a few places that support direct import of content right now. If you'd like to suggest a Market to include here, let us know. +

+
+
+
+ +
+
+

This is the default High Fidelity marketplace. Viewing and downloading content from here is fully supported in Interface.

+
+
+
+
+
+
+
+ +
+
+

Clara.io has thousands of models available for importing into High Fidelity. Follow these steps for the best experience:

+
    +
  1. Create an account here or log in as an existing user.
  2. +
  3. Choose a model from the list and click Download -> Autodesk FBX.
  4. +
  5. After the file processes, click Download.
  6. +
  7. Add the model to your asset server, then find it from the list and choose Add To World.
  8. +
+
+ +
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/scripts/system/marketplaces/clara.js b/scripts/system/marketplaces/clara.js index 67c2d5503c..a04400497f 100644 --- a/scripts/system/marketplaces/clara.js +++ b/scripts/system/marketplaces/clara.js @@ -14,15 +14,15 @@ (function() { // BEGIN LOCAL_SCOPE var toolIconUrl = Script.resolvePath("../assets/images/tools/"); -var qml = Script.resolvePath("../../../resources/qml/MarketplaceComboBox.qml") +var qml = Script.resolvePath("../../../resources/qml/Marketplaces.qml") var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; var marketplaceWindow = new OverlayWindow({ title: "Marketplace", source: qml, - width: 900, - height: 700, + width: 1000, + height: 900, toolWindow: false, visible: false, });