mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 19:41:20 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into feat/render-shape
This commit is contained in:
commit
801dde7950
66 changed files with 1444 additions and 1184 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include <ShutdownEventListener.h>
|
#include <ShutdownEventListener.h>
|
||||||
#include <SoundCache.h>
|
#include <SoundCache.h>
|
||||||
#include <ResourceScriptingInterface.h>
|
#include <ResourceScriptingInterface.h>
|
||||||
|
#include <ScriptEngines.h>
|
||||||
|
|
||||||
#include "AssignmentFactory.h"
|
#include "AssignmentFactory.h"
|
||||||
#include "AssignmentActionFactory.h"
|
#include "AssignmentActionFactory.h"
|
||||||
|
@ -53,6 +54,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
|
|
||||||
auto scriptableAvatar = DependencyManager::set<ScriptableAvatar>();
|
auto scriptableAvatar = DependencyManager::set<ScriptableAvatar>();
|
||||||
auto addressManager = DependencyManager::set<AddressManager>();
|
auto addressManager = DependencyManager::set<AddressManager>();
|
||||||
|
auto scriptEngines = DependencyManager::set<ScriptEngines>();
|
||||||
|
|
||||||
// create a NodeList as an unassigned client, must be after addressManager
|
// create a NodeList as an unassigned client, must be after addressManager
|
||||||
auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned, listenPort);
|
auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned, listenPort);
|
||||||
|
@ -174,6 +176,8 @@ AssignmentClient::~AssignmentClient() {
|
||||||
void AssignmentClient::aboutToQuit() {
|
void AssignmentClient::aboutToQuit() {
|
||||||
stopAssignmentClient();
|
stopAssignmentClient();
|
||||||
|
|
||||||
|
DependencyManager::destroy<ScriptEngines>();
|
||||||
|
|
||||||
// clear the log handler so that Qt doesn't call the destructor on LogHandler
|
// clear the log handler so that Qt doesn't call the destructor on LogHandler
|
||||||
qInstallMessageHandler(0);
|
qInstallMessageHandler(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,12 @@
|
||||||
|
|
||||||
SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& success) const {
|
SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID, bool& success) const {
|
||||||
SpatiallyNestableWeakPointer parent;
|
SpatiallyNestableWeakPointer parent;
|
||||||
|
|
||||||
|
if (parentID.isNull()) {
|
||||||
|
success = true;
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
// search entities
|
// search entities
|
||||||
parent = _tree->findEntityByEntityItemID(parentID);
|
parent = _tree->findEntityByEntityItemID(parentID);
|
||||||
if (parent.expired()) {
|
if (parent.expired()) {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
Script.load("away.js");
|
Script.load("away.js");
|
||||||
Script.load("progress.js");
|
Script.load("progress.js");
|
||||||
Script.load("edit.js");
|
Script.load("edit.js");
|
||||||
|
Script.load("marketplace.js");
|
||||||
Script.load("selectAudioDevice.js");
|
Script.load("selectAudioDevice.js");
|
||||||
Script.load("inspect.js");
|
Script.load("inspect.js");
|
||||||
Script.load("notifications.js");
|
Script.load("notifications.js");
|
||||||
|
|
|
@ -9,89 +9,118 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
Script.include("libraries/globals.js");
|
Script.include([
|
||||||
|
"libraries/toolBars.js",
|
||||||
|
]);
|
||||||
|
|
||||||
var directory = (function () {
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
|
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||||
|
|
||||||
var DIRECTORY_URL = "https://metaverse.highfidelity.com/directory",
|
var DIRECTORY_WINDOW_URL = "https://metaverse.highfidelity.com/directory";
|
||||||
directoryWindow,
|
var directoryWindow = new OverlayWebWindow({
|
||||||
DIRECTORY_BUTTON_URL = HIFI_PUBLIC_BUCKET + "images/tools/directory.svg",
|
title: 'directory',
|
||||||
BUTTON_WIDTH = 50,
|
source: "about:blank",
|
||||||
BUTTON_HEIGHT = 50,
|
width: 900,
|
||||||
BUTTON_ALPHA = 0.9,
|
height: 700,
|
||||||
BUTTON_MARGIN = 8,
|
visible: false
|
||||||
directoryButton,
|
});
|
||||||
EDIT_TOOLBAR_BUTTONS = 10, // Number of buttons in edit.js toolbar
|
|
||||||
viewport;
|
|
||||||
|
|
||||||
function updateButtonPosition() {
|
var toolHeight = 50;
|
||||||
Overlays.editOverlay(directoryButton, {
|
var toolWidth = 50;
|
||||||
x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN,
|
|
||||||
y: (viewport.y - (EDIT_TOOLBAR_BUTTONS + 1) * (BUTTON_HEIGHT + BUTTON_MARGIN) - BUTTON_MARGIN) / 2 - 1
|
|
||||||
|
function showDirectory() {
|
||||||
|
directoryWindow.setURL(DIRECTORY_WINDOW_URL);
|
||||||
|
directoryWindow.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideDirectory() {
|
||||||
|
directoryWindow.setVisible(false);
|
||||||
|
directoryWindow.setURL("about:blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleDirectory() {
|
||||||
|
if (directoryWindow.visible) {
|
||||||
|
hideDirectory();
|
||||||
|
} else {
|
||||||
|
showDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var toolBar = (function() {
|
||||||
|
var that = {},
|
||||||
|
toolBar,
|
||||||
|
browseDirectoryButton;
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
ToolBar.SPACING = 16;
|
||||||
|
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.directory.toolbar", function(windowDimensions, toolbar) {
|
||||||
|
return {
|
||||||
|
x: windowDimensions.x - 8 - toolbar.width,
|
||||||
|
y: 50
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
browseDirectoryButton = toolBar.addTool({
|
||||||
|
imageURL: toolIconUrl + "directory.svg",
|
||||||
|
width: toolWidth,
|
||||||
|
height: toolHeight,
|
||||||
|
alpha: 0.9,
|
||||||
|
visible: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
toolBar.showTool(browseDirectoryButton, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMousePressEvent(event) {
|
var browseDirectoryButtonDown = false;
|
||||||
var clickedOverlay;
|
that.mousePressEvent = function(event) {
|
||||||
|
var clickedOverlay,
|
||||||
|
url,
|
||||||
|
file;
|
||||||
|
|
||||||
clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
if (!event.isLeftButton) {
|
||||||
|
// if another mouse button than left is pressed ignore it
|
||||||
if (clickedOverlay === directoryButton) {
|
return false;
|
||||||
if (directoryWindow.url !== DIRECTORY_URL) {
|
|
||||||
directoryWindow.setURL(DIRECTORY_URL);
|
|
||||||
}
|
|
||||||
directoryWindow.setVisible(true);
|
|
||||||
directoryWindow.raise();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function onDomainChanged() {
|
clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
directoryWindow.setVisible(false);
|
x: event.x,
|
||||||
}
|
y: event.y
|
||||||
|
});
|
||||||
|
|
||||||
function onScriptUpdate() {
|
|
||||||
var oldViewport = viewport;
|
|
||||||
|
|
||||||
viewport = Controller.getViewportDimensions();
|
|
||||||
|
|
||||||
if (viewport.x !== oldViewport.x || viewport.y !== oldViewport.y) {
|
if (browseDirectoryButton === toolBar.clicked(clickedOverlay)) {
|
||||||
updateButtonPosition();
|
toggleDirectory();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
that.mouseReleaseEvent = function(event) {
|
||||||
|
var handled = false;
|
||||||
|
|
||||||
|
|
||||||
|
if (browseDirectoryButtonDown) {
|
||||||
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
newModelButtonDown = false;
|
||||||
|
browseDirectoryButtonDown = false;
|
||||||
|
|
||||||
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUp() {
|
that.cleanup = function() {
|
||||||
viewport = Controller.getViewportDimensions();
|
toolBar.cleanup();
|
||||||
|
};
|
||||||
|
|
||||||
directoryWindow = new OverlayWebWindow({
|
initialize();
|
||||||
title: 'Directory',
|
return that;
|
||||||
source: DIRECTORY_URL,
|
}());
|
||||||
width: 900,
|
|
||||||
height: 700,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
|
|
||||||
directoryButton = Overlays.addOverlay("image", {
|
Controller.mousePressEvent.connect(toolBar.mousePressEvent)
|
||||||
imageURL: DIRECTORY_BUTTON_URL,
|
Script.scriptEnding.connect(toolBar.cleanup);
|
||||||
width: BUTTON_WIDTH,
|
|
||||||
height: BUTTON_HEIGHT,
|
|
||||||
x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN,
|
|
||||||
y: BUTTON_MARGIN,
|
|
||||||
alpha: BUTTON_ALPHA,
|
|
||||||
visible: true
|
|
||||||
});
|
|
||||||
|
|
||||||
updateButtonPosition();
|
|
||||||
|
|
||||||
Controller.mousePressEvent.connect(onMousePressEvent);
|
|
||||||
Window.domainChanged.connect(onDomainChanged);
|
|
||||||
|
|
||||||
Script.update.connect(onScriptUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
function tearDown() {
|
|
||||||
Overlays.deleteOverlay(directoryButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
setUp();
|
|
||||||
Script.scriptEnding.connect(tearDown);
|
|
||||||
}());
|
|
||||||
|
|
|
@ -183,8 +183,7 @@ var toolBar = (function() {
|
||||||
newTextButton,
|
newTextButton,
|
||||||
newWebButton,
|
newWebButton,
|
||||||
newZoneButton,
|
newZoneButton,
|
||||||
newPolyVoxButton,
|
newPolyVoxButton;
|
||||||
browseMarketplaceButton;
|
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) {
|
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) {
|
||||||
|
@ -194,13 +193,7 @@ var toolBar = (function() {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
browseMarketplaceButton = toolBar.addTool({
|
|
||||||
imageURL: toolIconUrl + "marketplace.svg",
|
|
||||||
width: toolWidth,
|
|
||||||
height: toolHeight,
|
|
||||||
alpha: 0.9,
|
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
activeButton = toolBar.addTool({
|
activeButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "edit-status.svg",
|
imageURL: toolIconUrl + "edit-status.svg",
|
||||||
|
@ -415,7 +408,6 @@ var toolBar = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var newModelButtonDown = false;
|
var newModelButtonDown = false;
|
||||||
var browseMarketplaceButtonDown = false;
|
|
||||||
that.mousePressEvent = function(event) {
|
that.mousePressEvent = function(event) {
|
||||||
var clickedOverlay,
|
var clickedOverlay,
|
||||||
url,
|
url,
|
||||||
|
@ -443,11 +435,7 @@ var toolBar = (function() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
|
|
||||||
toggleMarketplace();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newCubeButton === toolBar.clicked(clickedOverlay)) {
|
if (newCubeButton === toolBar.clicked(clickedOverlay)) {
|
||||||
createNewEntity({
|
createNewEntity({
|
||||||
type: "Box",
|
type: "Box",
|
||||||
|
@ -652,22 +640,10 @@ var toolBar = (function() {
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
} else if (browseMarketplaceButtonDown) {
|
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({
|
|
||||||
x: event.x,
|
|
||||||
y: event.y
|
|
||||||
});
|
|
||||||
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
|
|
||||||
url = Window.s3Browse(".*(fbx|FBX|obj|OBJ)");
|
|
||||||
if (url !== null && url !== "") {
|
|
||||||
addModel(url);
|
|
||||||
}
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newModelButtonDown = false;
|
newModelButtonDown = false;
|
||||||
browseMarketplaceButtonDown = false;
|
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
131
examples/marketplace.js
Normal file
131
examples/marketplace.js
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
//
|
||||||
|
// marketplace.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Eric Levin on 8 Jan 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
|
||||||
|
//
|
||||||
|
|
||||||
|
Script.include([
|
||||||
|
"libraries/toolBars.js",
|
||||||
|
]);
|
||||||
|
|
||||||
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
|
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||||
|
|
||||||
|
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
|
||||||
|
var marketplaceWindow = new OverlayWebWindow({
|
||||||
|
title: 'Marketplace',
|
||||||
|
source: "about:blank",
|
||||||
|
width: 900,
|
||||||
|
height: 700,
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
|
||||||
|
var toolHeight = 50;
|
||||||
|
var toolWidth = 50;
|
||||||
|
|
||||||
|
|
||||||
|
function showMarketplace(marketplaceID) {
|
||||||
|
var url = MARKETPLACE_URL;
|
||||||
|
if (marketplaceID) {
|
||||||
|
url = url + "/items/" + marketplaceID;
|
||||||
|
}
|
||||||
|
print("setting marketplace URL to " + url);
|
||||||
|
marketplaceWindow.setURL(url);
|
||||||
|
marketplaceWindow.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideMarketplace() {
|
||||||
|
marketplaceWindow.setVisible(false);
|
||||||
|
marketplaceWindow.setURL("about:blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleMarketplace() {
|
||||||
|
if (marketplaceWindow.visible) {
|
||||||
|
hideMarketplace();
|
||||||
|
} else {
|
||||||
|
showMarketplace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var toolBar = (function() {
|
||||||
|
var that = {},
|
||||||
|
toolBar,
|
||||||
|
browseMarketplaceButton;
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
ToolBar.SPACING = 16;
|
||||||
|
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.marketplace.toolbar", function(windowDimensions, toolbar) {
|
||||||
|
return {
|
||||||
|
x: windowDimensions.x - 8 - toolbar.width,
|
||||||
|
y: 135
|
||||||
|
};
|
||||||
|
});
|
||||||
|
browseMarketplaceButton = toolBar.addTool({
|
||||||
|
imageURL: toolIconUrl + "marketplace.svg",
|
||||||
|
width: toolWidth,
|
||||||
|
height: toolHeight,
|
||||||
|
alpha: 0.9,
|
||||||
|
visible: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
toolBar.showTool(browseMarketplaceButton, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var browseMarketplaceButtonDown = false;
|
||||||
|
that.mousePressEvent = function(event) {
|
||||||
|
var clickedOverlay,
|
||||||
|
url,
|
||||||
|
file;
|
||||||
|
|
||||||
|
if (!event.isLeftButton) {
|
||||||
|
// if another mouse button than left is pressed ignore it
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
|
||||||
|
toggleMarketplace();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
that.mouseReleaseEvent = function(event) {
|
||||||
|
var handled = false;
|
||||||
|
|
||||||
|
|
||||||
|
if (browseMarketplaceButtonDown) {
|
||||||
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
newModelButtonDown = false;
|
||||||
|
browseMarketplaceButtonDown = false;
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
that.cleanup = function() {
|
||||||
|
toolBar.cleanup();
|
||||||
|
};
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
return that;
|
||||||
|
}());
|
||||||
|
|
||||||
|
Controller.mousePressEvent.connect(toolBar.mousePressEvent)
|
||||||
|
Script.scriptEnding.connect(toolBar.cleanup);
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- Copyright 2015 High Fidelity, Inc. -->
|
<!-- Copyright 2015 High Fidelity, Inc. -->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: white;
|
background: white;
|
||||||
width: 839px;
|
width: 100%;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@
|
||||||
function overrideBodyWidth() {
|
function overrideBodyWidth() {
|
||||||
document.body.style.width = "100%";
|
document.body.style.width = "100%";
|
||||||
<!-- Force reset layout after body resized-->
|
<!-- Force reset layout after body resized-->
|
||||||
container.style.width = "0";
|
<!-- container.style.width = "0"; -->
|
||||||
}
|
}
|
||||||
//]]></script>
|
//]]></script>
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,14 @@ DialogContainer {
|
||||||
property int maximumY: parent ? parent.height - height : 0
|
property int maximumY: parent ? parent.height - height : 0
|
||||||
|
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: dragRegion
|
||||||
|
visible: dragMouseArea.containsMouse
|
||||||
|
}
|
||||||
|
|
||||||
AddressBarDialog {
|
AddressBarDialog {
|
||||||
id: addressBarDialog
|
id: addressBarDialog
|
||||||
|
z: dragRegion.z + 1
|
||||||
implicitWidth: backgroundImage.width
|
implicitWidth: backgroundImage.width
|
||||||
implicitHeight: backgroundImage.height
|
implicitHeight: backgroundImage.height
|
||||||
|
|
||||||
|
@ -48,11 +53,13 @@ DialogContainer {
|
||||||
property int inputAreaStep: (height - inputAreaHeight) / 2
|
property int inputAreaStep: (height - inputAreaHeight) / 2
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
id: dragMouseArea
|
||||||
// Drag the icon
|
// Drag the icon
|
||||||
width: parent.height
|
width: parent.height
|
||||||
height: parent.height
|
height: parent.height
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
|
hoverEnabled: true
|
||||||
drag {
|
drag {
|
||||||
target: root
|
target: root
|
||||||
minimumX: -parent.inputAreaStep
|
minimumX: -parent.inputAreaStep
|
||||||
|
@ -61,6 +68,8 @@ DialogContainer {
|
||||||
maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0
|
maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
// Drag the input rectangle
|
// Drag the input rectangle
|
||||||
|
|
|
@ -51,6 +51,16 @@ Hifi.VrMenu {
|
||||||
VrMenuView {
|
VrMenuView {
|
||||||
property int menuDepth: root.models.length - 1
|
property int menuDepth: root.models.length - 1
|
||||||
model: root.models[menuDepth]
|
model: root.models[menuDepth]
|
||||||
|
|
||||||
|
function fit(position, size, maxposition) {
|
||||||
|
var padding = 8;
|
||||||
|
if (position < padding) {
|
||||||
|
position = padding;
|
||||||
|
} else if (position + size + padding > maxposition) {
|
||||||
|
position = maxposition - (size + padding);
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (menuDepth === 0) {
|
if (menuDepth === 0) {
|
||||||
|
@ -61,6 +71,8 @@ Hifi.VrMenu {
|
||||||
x = lastColumn.x + 64;
|
x = lastColumn.x + 64;
|
||||||
y = lastMousePosition.y - height / 2;
|
y = lastMousePosition.y - height / 2;
|
||||||
}
|
}
|
||||||
|
x = fit(x, width, parent.width);
|
||||||
|
y = fit(y, height, parent.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelected: {
|
onSelected: {
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
#include <RecordingScriptingInterface.h>
|
#include <RecordingScriptingInterface.h>
|
||||||
#include <ScriptCache.h>
|
#include <ScriptCache.h>
|
||||||
#include <SoundCache.h>
|
#include <SoundCache.h>
|
||||||
|
#include <ScriptEngines.h>
|
||||||
#include <TextureCache.h>
|
#include <TextureCache.h>
|
||||||
#include <Tooltip.h>
|
#include <Tooltip.h>
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
|
@ -319,6 +320,7 @@ bool setupEssentials(int& argc, char** argv) {
|
||||||
Setting::init();
|
Setting::init();
|
||||||
|
|
||||||
// Set dependencies
|
// Set dependencies
|
||||||
|
DependencyManager::set<ScriptEngines>();
|
||||||
DependencyManager::set<recording::Deck>();
|
DependencyManager::set<recording::Deck>();
|
||||||
DependencyManager::set<recording::Recorder>();
|
DependencyManager::set<recording::Recorder>();
|
||||||
DependencyManager::set<AddressManager>();
|
DependencyManager::set<AddressManager>();
|
||||||
|
@ -402,16 +404,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
_entityClipboard(new EntityTree()),
|
_entityClipboard(new EntityTree()),
|
||||||
_lastQueriedTime(usecTimestampNow()),
|
_lastQueriedTime(usecTimestampNow()),
|
||||||
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
||||||
_firstRun("firstRun", true),
|
|
||||||
_previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION),
|
|
||||||
_scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION),
|
|
||||||
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
|
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
|
||||||
_scaleMirror(1.0f),
|
_scaleMirror(1.0f),
|
||||||
_rotateMirror(0.0f),
|
_rotateMirror(0.0f),
|
||||||
_raiseMirror(0.0f),
|
_raiseMirror(0.0f),
|
||||||
_enableProcessOctreeThread(true),
|
_enableProcessOctreeThread(true),
|
||||||
_runningScriptsWidget(NULL),
|
|
||||||
_runningScriptsWidgetWasVisible(false),
|
|
||||||
_lastNackTime(usecTimestampNow()),
|
_lastNackTime(usecTimestampNow()),
|
||||||
_lastSendDownstreamAudioStats(usecTimestampNow()),
|
_lastSendDownstreamAudioStats(usecTimestampNow()),
|
||||||
_aboutToQuit(false),
|
_aboutToQuit(false),
|
||||||
|
@ -596,6 +593,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
|
connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
|
||||||
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
|
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
|
||||||
|
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
|
||||||
|
scriptEngines->registerScriptInitializer([this](ScriptEngine* engine){
|
||||||
|
registerScriptEngineWithApplicationServices(engine);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(scriptEngines, &ScriptEngines::scriptCountChanged, scriptEngines, [this] {
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
|
if (scriptEngines->getRunningScripts().isEmpty()) {
|
||||||
|
getMyAvatar()->clearScriptableSettings();
|
||||||
|
}
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] {
|
||||||
|
getEntities()->reloadEntityScripts();
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
connect(scriptEngines, &ScriptEngines::scriptLoadError,
|
||||||
|
scriptEngines, [](const QString& filename, const QString& error){
|
||||||
|
OffscreenUi::warning(nullptr, "Error Loading Script", filename + " failed to load.");
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSADATA WsaData;
|
WSADATA WsaData;
|
||||||
int wsaresult = WSAStartup(MAKEWORD(2, 2), &WsaData);
|
int wsaresult = WSAStartup(MAKEWORD(2, 2), &WsaData);
|
||||||
|
@ -678,9 +696,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
|
|
||||||
_overlays.init(); // do this before scripts load
|
_overlays.init(); // do this before scripts load
|
||||||
|
|
||||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
|
||||||
|
|
||||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(saveScripts()));
|
|
||||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
|
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
|
||||||
|
|
||||||
// hook up bandwidth estimator
|
// hook up bandwidth estimator
|
||||||
|
@ -847,18 +862,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice());
|
userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice());
|
||||||
userInputMapper->loadDefaultMapping(userInputMapper->getStandardDeviceID());
|
userInputMapper->loadDefaultMapping(userInputMapper->getStandardDeviceID());
|
||||||
|
|
||||||
// check first run...
|
// force the model the look at the correct directory (weird order of operations issue)
|
||||||
if (_firstRun.get()) {
|
scriptEngines->setScriptsLocation(scriptEngines->getScriptsLocation());
|
||||||
qCDebug(interfaceapp) << "This is a first run...";
|
// do this as late as possible so that all required subsystems are initialized
|
||||||
// clear the scripts, and set out script to our default scripts
|
scriptEngines->loadScripts();
|
||||||
clearScriptsBeforeRunning();
|
|
||||||
loadScript(DEFAULT_SCRIPTS_JS_URL);
|
|
||||||
|
|
||||||
_firstRun.set(false);
|
|
||||||
} else {
|
|
||||||
// do this as late as possible so that all required subsystems are initialized
|
|
||||||
loadScripts();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
||||||
|
@ -1017,7 +1024,9 @@ void Application::cleanupBeforeQuit() {
|
||||||
nodeList->getPacketReceiver().setShouldDropPackets(true);
|
nodeList->getPacketReceiver().setShouldDropPackets(true);
|
||||||
|
|
||||||
getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
|
getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
|
||||||
ScriptEngine::stopAllScripts(this); // stop all currently running global scripts
|
DependencyManager::get<ScriptEngines>()->saveScripts();
|
||||||
|
DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts
|
||||||
|
DependencyManager::destroy<ScriptEngines>();
|
||||||
|
|
||||||
// first stop all timers directly or by invokeMethod
|
// first stop all timers directly or by invokeMethod
|
||||||
// depending on what thread they run in
|
// depending on what thread they run in
|
||||||
|
@ -1192,8 +1201,9 @@ void Application::initializeUi() {
|
||||||
connect(engine, &QQmlEngine::quit, [] {
|
connect(engine, &QQmlEngine::quit, [] {
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
});
|
});
|
||||||
rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance());
|
|
||||||
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||||
|
rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance());
|
||||||
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
|
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
|
||||||
rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||||
rootContext->setContextProperty("MyAvatar", getMyAvatar());
|
rootContext->setContextProperty("MyAvatar", getMyAvatar());
|
||||||
|
@ -1220,6 +1230,7 @@ void Application::initializeUi() {
|
||||||
rootContext->setContextProperty("Menu", MenuScriptingInterface::getInstance());
|
rootContext->setContextProperty("Menu", MenuScriptingInterface::getInstance());
|
||||||
rootContext->setContextProperty("Stats", Stats::getInstance());
|
rootContext->setContextProperty("Stats", Stats::getInstance());
|
||||||
rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||||
|
rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||||
rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||||
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||||
rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||||
|
@ -1234,7 +1245,6 @@ void Application::initializeUi() {
|
||||||
rootContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
rootContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||||
rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||||
rootContext->setContextProperty("Render", DependencyManager::get<RenderScriptingInterface>().data());
|
rootContext->setContextProperty("Render", DependencyManager::get<RenderScriptingInterface>().data());
|
||||||
rootContext->setContextProperty("ScriptDiscoveryService", this->getRunningScriptsWidget());
|
|
||||||
|
|
||||||
_glWidget->installEventFilter(offscreenUi.data());
|
_glWidget->installEventFilter(offscreenUi.data());
|
||||||
VrMenu::load();
|
VrMenu::load();
|
||||||
|
@ -4164,48 +4174,6 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
|
||||||
void Application::packetSent(quint64 length) {
|
void Application::packetSent(quint64 length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString SETTINGS_KEY = "Settings";
|
|
||||||
|
|
||||||
void Application::loadScripts() {
|
|
||||||
// loads all saved scripts
|
|
||||||
Settings settings;
|
|
||||||
int size = settings.beginReadArray(SETTINGS_KEY);
|
|
||||||
for (int i = 0; i < size; ++i){
|
|
||||||
settings.setArrayIndex(i);
|
|
||||||
QString string = settings.value("script").toString();
|
|
||||||
if (!string.isEmpty()) {
|
|
||||||
loadScript(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::clearScriptsBeforeRunning() {
|
|
||||||
// clears all scripts from the settingsSettings settings;
|
|
||||||
Settings settings;
|
|
||||||
settings.beginWriteArray(SETTINGS_KEY);
|
|
||||||
settings.remove("");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::saveScripts() {
|
|
||||||
// Saves all currently running user-loaded scripts
|
|
||||||
Settings settings;
|
|
||||||
settings.beginWriteArray(SETTINGS_KEY);
|
|
||||||
settings.remove("");
|
|
||||||
|
|
||||||
QStringList runningScripts = getRunningScripts();
|
|
||||||
int i = 0;
|
|
||||||
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
|
|
||||||
if (getScriptEngine(*it)->isUserLoaded()) {
|
|
||||||
settings.setArrayIndex(i);
|
|
||||||
settings.setValue("script", *it);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) {
|
void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) {
|
||||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||||
// we can use the same ones from the application.
|
// we can use the same ones from the application.
|
||||||
|
@ -4232,11 +4200,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable);
|
scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable);
|
||||||
connect(scriptEngine, &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);
|
connect(scriptEngine, &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);
|
||||||
|
|
||||||
connect(scriptEngine, &ScriptEngine::finished, this, &Application::scriptFinished, Qt::DirectConnection);
|
|
||||||
|
|
||||||
connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool)));
|
|
||||||
connect(scriptEngine, SIGNAL(reloadScript(const QString&, bool)), this, SLOT(reloadScript(const QString&, bool)));
|
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
||||||
qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
|
qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
|
||||||
qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue,
|
qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue,
|
||||||
|
@ -4284,7 +4247,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
scriptEngine->registerGlobalObject("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||||
scriptEngine->registerGlobalObject("Render", DependencyManager::get<RenderScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("Render", DependencyManager::get<RenderScriptingInterface>().data());
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("ScriptDiscoveryService", this->getRunningScriptsWidget());
|
scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::canAcceptURL(const QString& urlString) const {
|
bool Application::canAcceptURL(const QString& urlString) const {
|
||||||
|
@ -4390,7 +4353,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
|
|
||||||
if (reply == QMessageBox::Yes) {
|
if (reply == QMessageBox::Yes) {
|
||||||
qCDebug(interfaceapp) << "Chose to run the script: " << scriptFilenameOrURL;
|
qCDebug(interfaceapp) << "Chose to run the script: " << scriptFilenameOrURL;
|
||||||
loadScript(scriptFilenameOrURL);
|
DependencyManager::get<ScriptEngines>()->loadScript(scriptFilenameOrURL);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "Declined to run the script: " << scriptFilenameOrURL;
|
qCDebug(interfaceapp) << "Declined to run the script: " << scriptFilenameOrURL;
|
||||||
}
|
}
|
||||||
|
@ -4563,186 +4526,6 @@ bool Application::displayAvatarAttachmentConfirmationDialog(const QString& name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
|
|
||||||
bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
|
|
||||||
|
|
||||||
if (isAboutToQuit()) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl scriptUrl(scriptFilename);
|
|
||||||
const QString& scriptURLString = scriptUrl.toString();
|
|
||||||
{
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
|
||||||
if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor
|
|
||||||
&& !_scriptEnginesHash[scriptURLString]->isFinished()) {
|
|
||||||
|
|
||||||
return _scriptEnginesHash[scriptURLString];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
|
|
||||||
scriptEngine->setUserLoaded(isUserLoaded);
|
|
||||||
|
|
||||||
if (scriptFilename.isNull()) {
|
|
||||||
// This appears to be the script engine used by the script widget's evaluation window before the file has been saved...
|
|
||||||
|
|
||||||
// this had better be the script editor (we should de-couple so somebody who thinks they are loading a script
|
|
||||||
// doesn't just get an empty script engine)
|
|
||||||
|
|
||||||
// we can complete setup now since there isn't a script we have to load
|
|
||||||
registerScriptEngineWithApplicationServices(scriptEngine);
|
|
||||||
scriptEngine->runInThread();
|
|
||||||
} else {
|
|
||||||
// connect to the appropriate signals of this script engine
|
|
||||||
connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded);
|
|
||||||
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError);
|
|
||||||
|
|
||||||
// get the script engine object to load the script at the designated script URL
|
|
||||||
scriptEngine->loadURL(scriptUrl, reload);
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore the main window's active state
|
|
||||||
if (activateMainWindow && !loadScriptFromEditor) {
|
|
||||||
_window->activateWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return scriptEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::reloadScript(const QString& scriptName, bool isUserLoaded) {
|
|
||||||
loadScript(scriptName, isUserLoaded, false, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - change to new version of ScriptCache loading notification
|
|
||||||
void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
|
|
||||||
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
|
|
||||||
|
|
||||||
{
|
|
||||||
QWriteLocker lock(&_scriptEnginesHashLock);
|
|
||||||
_scriptEnginesHash.insertMulti(scriptFilename, scriptEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
|
||||||
UserActivityLogger::getInstance().loadedScript(scriptFilename);
|
|
||||||
|
|
||||||
// register our application services and set it off on its own thread
|
|
||||||
registerScriptEngineWithApplicationServices(scriptEngine);
|
|
||||||
scriptEngine->runInThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - change to new version of ScriptCache loading notification
|
|
||||||
void Application::handleScriptLoadError(const QString& scriptFilename) {
|
|
||||||
qCDebug(interfaceapp) << "Application::loadScript(), script failed to load...";
|
|
||||||
OffscreenUi::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load.");
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList Application::getRunningScripts() {
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
|
||||||
return _scriptEnginesHash.keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptEngine* Application::getScriptEngine(const QString& scriptHash) {
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
|
||||||
return _scriptEnginesHash.value(scriptHash, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::scriptFinished(const QString& scriptName, ScriptEngine* engine) {
|
|
||||||
bool removed = false;
|
|
||||||
{
|
|
||||||
QWriteLocker lock(&_scriptEnginesHashLock);
|
|
||||||
const QString& scriptURLString = QUrl(scriptName).toString();
|
|
||||||
for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
|
|
||||||
if (it.value() == engine) {
|
|
||||||
_scriptEnginesHash.erase(it);
|
|
||||||
removed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (removed) {
|
|
||||||
postLambdaEvent([this, scriptName]() {
|
|
||||||
_runningScriptsWidget->scriptStopped(scriptName);
|
|
||||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::stopAllScripts(bool restart) {
|
|
||||||
{
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
|
||||||
|
|
||||||
if (restart) {
|
|
||||||
// Delete all running scripts from cache so that they are re-downloaded when they are restarted
|
|
||||||
auto scriptCache = DependencyManager::get<ScriptCache>();
|
|
||||||
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
|
||||||
it != _scriptEnginesHash.constEnd(); it++) {
|
|
||||||
if (!it.value()->isFinished()) {
|
|
||||||
scriptCache->deleteScript(it.key());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop and possibly restart all currently running scripts
|
|
||||||
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
|
||||||
it != _scriptEnginesHash.constEnd(); it++) {
|
|
||||||
if (it.value()->isFinished()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (restart && it.value()->isUserLoaded()) {
|
|
||||||
connect(it.value(), &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) {
|
|
||||||
reloadScript(scriptName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
QMetaObject::invokeMethod(it.value(), "stop");
|
|
||||||
//it.value()->stop();
|
|
||||||
qCDebug(interfaceapp) << "stopping script..." << it.key();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getMyAvatar()->clearScriptableSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Application::stopScript(const QString& scriptHash, bool restart) {
|
|
||||||
bool stoppedScript = false;
|
|
||||||
{
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
|
||||||
if (_scriptEnginesHash.contains(scriptHash)) {
|
|
||||||
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash];
|
|
||||||
if (restart) {
|
|
||||||
auto scriptCache = DependencyManager::get<ScriptCache>();
|
|
||||||
scriptCache->deleteScript(QUrl(scriptHash));
|
|
||||||
connect(scriptEngine, &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) {
|
|
||||||
reloadScript(scriptName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
scriptEngine->stop();
|
|
||||||
stoppedScript = true;
|
|
||||||
qCDebug(interfaceapp) << "stopping script..." << scriptHash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_scriptEnginesHash.empty()) {
|
|
||||||
getMyAvatar()->clearScriptableSettings();
|
|
||||||
}
|
|
||||||
return stoppedScript;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::reloadAllScripts() {
|
|
||||||
DependencyManager::get<ScriptCache>()->clearCache();
|
|
||||||
getEntities()->reloadEntityScripts();
|
|
||||||
stopAllScripts(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::reloadOneScript(const QString& scriptName) {
|
|
||||||
stopScript(scriptName, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::loadDefaultScripts() {
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
|
||||||
if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
|
|
||||||
loadScript(DEFAULT_SCRIPTS_JS_URL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::toggleRunningScriptsWidget() {
|
void Application::toggleRunningScriptsWidget() {
|
||||||
if (_runningScriptsWidget->isVisible()) {
|
if (_runningScriptsWidget->isVisible()) {
|
||||||
if (_runningScriptsWidget->hasFocus()) {
|
if (_runningScriptsWidget->hasFocus()) {
|
||||||
|
@ -4800,27 +4583,17 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject
|
||||||
qCDebug(interfaceapp) << "Destination wallet UUID for edit payments is" << voxelWalletUUID;
|
qCDebug(interfaceapp) << "Destination wallet UUID for edit payments is" << voxelWalletUUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Application::getPreviousScriptLocation() {
|
|
||||||
return _previousScriptLocation.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::setPreviousScriptLocation(const QString& previousScriptLocation) {
|
|
||||||
_previousScriptLocation.set(previousScriptLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::loadDialog() {
|
void Application::loadDialog() {
|
||||||
|
// To be migratd to QML
|
||||||
QString fileNameString = QFileDialog::getOpenFileName(_glWidget,
|
QString fileNameString = QFileDialog::getOpenFileName(
|
||||||
tr("Open Script"),
|
_glWidget, tr("Open Script"), "", tr("JavaScript Files (*.js)"));
|
||||||
getPreviousScriptLocation(),
|
|
||||||
tr("JavaScript Files (*.js)"));
|
|
||||||
if (!fileNameString.isEmpty()) {
|
if (!fileNameString.isEmpty()) {
|
||||||
setPreviousScriptLocation(fileNameString);
|
DependencyManager::get<ScriptEngines>()->loadScript(fileNameString);
|
||||||
loadScript(fileNameString);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadScriptURLDialog() {
|
void Application::loadScriptURLDialog() {
|
||||||
|
// To be migratd to QML
|
||||||
QInputDialog scriptURLDialog(getWindow());
|
QInputDialog scriptURLDialog(getWindow());
|
||||||
scriptURLDialog.setWindowTitle("Open and Run Script URL");
|
scriptURLDialog.setWindowTitle("Open and Run Script URL");
|
||||||
scriptURLDialog.setLabelText("Script:");
|
scriptURLDialog.setLabelText("Script:");
|
||||||
|
@ -4836,19 +4609,10 @@ void Application::loadScriptURLDialog() {
|
||||||
// the user input a new hostname, use that
|
// the user input a new hostname, use that
|
||||||
newScript = scriptURLDialog.textValue();
|
newScript = scriptURLDialog.textValue();
|
||||||
}
|
}
|
||||||
loadScript(newScript);
|
DependencyManager::get<ScriptEngines>()->loadScript(newScript);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Application::getScriptsLocation() {
|
|
||||||
return _scriptsLocationHandle.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::setScriptsLocation(const QString& scriptsLocation) {
|
|
||||||
_scriptsLocationHandle.set(scriptsLocation);
|
|
||||||
emit scriptLocationChanged(scriptsLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::toggleLogDialog() {
|
void Application::toggleLogDialog() {
|
||||||
if (! _logDialog) {
|
if (! _logDialog) {
|
||||||
_logDialog = new LogDialog(_glWidget, getLogger());
|
_logDialog = new LogDialog(_glWidget, getLogger());
|
||||||
|
@ -5063,8 +4827,23 @@ const DisplayPlugin* Application::getActiveDisplayPlugin() const {
|
||||||
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
|
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
|
||||||
auto menu = Menu::getInstance();
|
auto menu = Menu::getInstance();
|
||||||
QString name = displayPlugin->getName();
|
QString name = displayPlugin->getName();
|
||||||
|
auto grouping = displayPlugin->getGrouping();
|
||||||
|
QString groupingMenu { "" };
|
||||||
Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name));
|
Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name));
|
||||||
|
|
||||||
|
// assign the meny grouping based on plugin grouping
|
||||||
|
switch (grouping) {
|
||||||
|
case Plugin::ADVANCED:
|
||||||
|
groupingMenu = "Advanced";
|
||||||
|
break;
|
||||||
|
case Plugin::DEVELOPER:
|
||||||
|
groupingMenu = "Developer";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
groupingMenu = "Standard";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
static QActionGroup* displayPluginGroup = nullptr;
|
static QActionGroup* displayPluginGroup = nullptr;
|
||||||
if (!displayPluginGroup) {
|
if (!displayPluginGroup) {
|
||||||
displayPluginGroup = new QActionGroup(menu);
|
displayPluginGroup = new QActionGroup(menu);
|
||||||
|
@ -5073,7 +4852,9 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti
|
||||||
auto parent = menu->getMenu(MenuOption::OutputMenu);
|
auto parent = menu->getMenu(MenuOption::OutputMenu);
|
||||||
auto action = menu->addActionToQMenuAndActionHash(parent,
|
auto action = menu->addActionToQMenuAndActionHash(parent,
|
||||||
name, 0, qApp,
|
name, 0, qApp,
|
||||||
SLOT(updateDisplayMode()));
|
SLOT(updateDisplayMode()),
|
||||||
|
QAction::NoRole, UNSPECIFIED_POSITION, groupingMenu);
|
||||||
|
|
||||||
action->setCheckable(true);
|
action->setCheckable(true);
|
||||||
action->setChecked(active);
|
action->setChecked(active);
|
||||||
displayPluginGroup->addAction(action);
|
displayPluginGroup->addAction(action);
|
||||||
|
@ -5087,7 +4868,31 @@ void Application::updateDisplayMode() {
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
|
// first sort the plugins into groupings: standard, advanced, developer
|
||||||
|
DisplayPluginList standard;
|
||||||
|
DisplayPluginList advanced;
|
||||||
|
DisplayPluginList developer;
|
||||||
foreach(auto displayPlugin, displayPlugins) {
|
foreach(auto displayPlugin, displayPlugins) {
|
||||||
|
auto grouping = displayPlugin->getGrouping();
|
||||||
|
switch (grouping) {
|
||||||
|
case Plugin::ADVANCED:
|
||||||
|
advanced.push_back(displayPlugin);
|
||||||
|
break;
|
||||||
|
case Plugin::DEVELOPER:
|
||||||
|
developer.push_back(displayPlugin);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
standard.push_back(displayPlugin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// concactonate the groupings into a single list in the order: standard, advanced, developer
|
||||||
|
standard.insert(std::end(standard), std::begin(advanced), std::end(advanced));
|
||||||
|
standard.insert(std::end(standard), std::begin(developer), std::end(developer));
|
||||||
|
|
||||||
|
foreach(auto displayPlugin, standard) {
|
||||||
addDisplayPluginToMenu(displayPlugin, first);
|
addDisplayPluginToMenu(displayPlugin, first);
|
||||||
// This must be a queued connection to avoid a deadlock
|
// This must be a queued connection to avoid a deadlock
|
||||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender,
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender,
|
||||||
|
@ -5099,6 +4904,11 @@ void Application::updateDisplayMode() {
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// after all plugins have been added to the menu, add a seperator to the menu
|
||||||
|
auto menu = Menu::getInstance();
|
||||||
|
auto parent = menu->getMenu(MenuOption::OutputMenu);
|
||||||
|
parent->addSeparator();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -106,10 +106,6 @@ public:
|
||||||
|
|
||||||
void postLambdaEvent(std::function<void()> f);
|
void postLambdaEvent(std::function<void()> f);
|
||||||
|
|
||||||
void loadScripts();
|
|
||||||
QString getPreviousScriptLocation();
|
|
||||||
void setPreviousScriptLocation(const QString& previousScriptLocation);
|
|
||||||
void clearScriptsBeforeRunning();
|
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void initializeUi();
|
void initializeUi();
|
||||||
void paintGL();
|
void paintGL();
|
||||||
|
@ -197,9 +193,6 @@ public:
|
||||||
|
|
||||||
NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; }
|
NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; }
|
||||||
|
|
||||||
QStringList getRunningScripts();
|
|
||||||
ScriptEngine* getScriptEngine(const QString& scriptHash);
|
|
||||||
|
|
||||||
float getRenderResolutionScale() const;
|
float getRenderResolutionScale() const;
|
||||||
|
|
||||||
bool isAboutToQuit() const { return _aboutToQuit; }
|
bool isAboutToQuit() const { return _aboutToQuit; }
|
||||||
|
@ -213,13 +206,8 @@ public:
|
||||||
glm::mat4 getEyeProjection(int eye) const;
|
glm::mat4 getEyeProjection(int eye) const;
|
||||||
|
|
||||||
QRect getDesirableApplicationGeometry();
|
QRect getDesirableApplicationGeometry();
|
||||||
RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; }
|
|
||||||
|
|
||||||
Bookmarks* getBookmarks() const { return _bookmarks; }
|
Bookmarks* getBookmarks() const { return _bookmarks; }
|
||||||
|
|
||||||
QString getScriptsLocation();
|
|
||||||
void setScriptsLocation(const QString& scriptsLocation);
|
|
||||||
|
|
||||||
virtual bool canAcceptURL(const QString& url) const override;
|
virtual bool canAcceptURL(const QString& url) const override;
|
||||||
virtual bool acceptURL(const QString& url, bool defaultUpload = false) override;
|
virtual bool acceptURL(const QString& url, bool defaultUpload = false) override;
|
||||||
|
|
||||||
|
@ -241,8 +229,6 @@ public:
|
||||||
float getAverageSimsPerSecond();
|
float getAverageSimsPerSecond();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void scriptLocationChanged(const QString& newPath);
|
|
||||||
|
|
||||||
void svoImportRequested(const QString& url);
|
void svoImportRequested(const QString& url);
|
||||||
|
|
||||||
void checkBackgroundDownloads();
|
void checkBackgroundDownloads();
|
||||||
|
@ -263,14 +249,6 @@ public slots:
|
||||||
void loadDialog();
|
void loadDialog();
|
||||||
void loadScriptURLDialog();
|
void loadScriptURLDialog();
|
||||||
void toggleLogDialog();
|
void toggleLogDialog();
|
||||||
|
|
||||||
ScriptEngine* loadScript(const QString& scriptFilename = QString(), bool isUserLoaded = true,
|
|
||||||
bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
|
|
||||||
void stopAllScripts(bool restart = false);
|
|
||||||
bool stopScript(const QString& scriptHash, bool restart = false);
|
|
||||||
void reloadAllScripts();
|
|
||||||
void reloadOneScript(const QString& scriptName);
|
|
||||||
void loadDefaultScripts();
|
|
||||||
void toggleRunningScriptsWidget();
|
void toggleRunningScriptsWidget();
|
||||||
|
|
||||||
void showFriendsWindow();
|
void showFriendsWindow();
|
||||||
|
@ -313,9 +291,6 @@ private slots:
|
||||||
void idle(uint64_t now);
|
void idle(uint64_t now);
|
||||||
void aboutToQuit();
|
void aboutToQuit();
|
||||||
|
|
||||||
void handleScriptEngineLoaded(const QString& scriptFilename);
|
|
||||||
void handleScriptLoadError(const QString& scriptFilename);
|
|
||||||
|
|
||||||
void connectedToDomain(const QString& hostname);
|
void connectedToDomain(const QString& hostname);
|
||||||
|
|
||||||
void audioMuteToggled();
|
void audioMuteToggled();
|
||||||
|
@ -331,10 +306,6 @@ private slots:
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
void scriptFinished(const QString& scriptName, ScriptEngine* engine);
|
|
||||||
void saveScripts();
|
|
||||||
void reloadScript(const QString& scriptName, bool isUserLoaded = true);
|
|
||||||
|
|
||||||
bool acceptSnapshot(const QString& urlString);
|
bool acceptSnapshot(const QString& urlString);
|
||||||
bool askToSetAvatarUrl(const QString& url);
|
bool askToSetAvatarUrl(const QString& url);
|
||||||
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
||||||
|
@ -468,9 +439,6 @@ private:
|
||||||
Camera _mirrorCamera; // Cammera for mirror view
|
Camera _mirrorCamera; // Cammera for mirror view
|
||||||
QRect _mirrorViewRect;
|
QRect _mirrorViewRect;
|
||||||
|
|
||||||
Setting::Handle<bool> _firstRun;
|
|
||||||
Setting::Handle<QString> _previousScriptLocation;
|
|
||||||
Setting::Handle<QString> _scriptsLocationHandle;
|
|
||||||
Setting::Handle<float> _fieldOfView;
|
Setting::Handle<float> _fieldOfView;
|
||||||
|
|
||||||
float _scaleMirror;
|
float _scaleMirror;
|
||||||
|
@ -499,12 +467,7 @@ private:
|
||||||
|
|
||||||
TouchEvent _lastTouchEvent;
|
TouchEvent _lastTouchEvent;
|
||||||
|
|
||||||
QReadWriteLock _scriptEnginesHashLock;
|
RunningScriptsWidget* _runningScriptsWidget { nullptr };
|
||||||
RunningScriptsWidget* _runningScriptsWidget;
|
|
||||||
QHash<QString, ScriptEngine*> _scriptEnginesHash;
|
|
||||||
bool _runningScriptsWidgetWasVisible;
|
|
||||||
QString _scriptsLocation;
|
|
||||||
|
|
||||||
quint64 _lastNackTime;
|
quint64 _lastNackTime;
|
||||||
quint64 _lastSendDownstreamAudioStats;
|
quint64 _lastSendDownstreamAudioStats;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
#include <VrMenu.h>
|
#include <VrMenu.h>
|
||||||
|
#include <ScriptEngines.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
|
@ -114,13 +115,15 @@ Menu::Menu() {
|
||||||
Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()),
|
Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()),
|
||||||
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
|
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
|
||||||
|
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
// Edit > Stop All Scripts... [advanced]
|
// Edit > Stop All Scripts... [advanced]
|
||||||
addActionToQMenuAndActionHash(editMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()),
|
addActionToQMenuAndActionHash(editMenu, MenuOption::StopAllScripts, 0,
|
||||||
|
scriptEngines.data(), SLOT(stopAllScripts()),
|
||||||
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
|
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
|
||||||
|
|
||||||
// Edit > Reload All Scripts... [advanced]
|
// Edit > Reload All Scripts... [advanced]
|
||||||
addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
|
addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
|
||||||
qApp, SLOT(reloadAllScripts()),
|
scriptEngines.data(), SLOT(reloadAllScripts()),
|
||||||
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
|
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
|
||||||
|
|
||||||
// Edit > Scripts Editor... [advanced]
|
// Edit > Scripts Editor... [advanced]
|
||||||
|
|
|
@ -243,7 +243,7 @@ namespace MenuOption {
|
||||||
const QString OctreeStats = "Entity Statistics";
|
const QString OctreeStats = "Entity Statistics";
|
||||||
const QString OnePointCalibration = "1 Point Calibration";
|
const QString OnePointCalibration = "1 Point Calibration";
|
||||||
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
const QString OnlyDisplayTopTen = "Only Display Top Ten";
|
||||||
const QString OutputMenu = "Display>Mode";
|
const QString OutputMenu = "Display";
|
||||||
const QString PackageModel = "Package Model...";
|
const QString PackageModel = "Package Model...";
|
||||||
const QString Pair = "Pair";
|
const QString Pair = "Pair";
|
||||||
const QString PhysicsShowOwned = "Highlight Simulation Ownership";
|
const QString PhysicsShowOwned = "Highlight Simulation Ownership";
|
||||||
|
|
|
@ -79,9 +79,6 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
|
||||||
// what screens we're allowed on
|
// what screens we're allowed on
|
||||||
watchWindow(windowHandle());
|
watchWindow(windowHandle());
|
||||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||||
if (qApp->getRunningScriptsWidget()) {
|
|
||||||
watchWindow(qApp->getRunningScriptsWidget()->windowHandle());
|
|
||||||
}
|
|
||||||
if (qApp->getToolWindow()) {
|
if (qApp->getToolWindow()) {
|
||||||
watchWindow(qApp->getToolWindow()->windowHandle());
|
watchWindow(qApp->getToolWindow()->windowHandle());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
|
|
||||||
|
#include <ScriptEngines.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
@ -84,7 +85,7 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) {
|
||||||
|
|
||||||
// if scriptEngine is NULL then create one and keep track of it using _ownScriptEngine
|
// if scriptEngine is NULL then create one and keep track of it using _ownScriptEngine
|
||||||
_ownScriptEngine = scriptEngine == NULL;
|
_ownScriptEngine = scriptEngine == NULL;
|
||||||
_scriptEngine = _ownScriptEngine ? qApp->loadScript(QString(), false) : scriptEngine;
|
_scriptEngine = _ownScriptEngine ? DependencyManager::get<ScriptEngines>()->loadScript(QString(), false) : scriptEngine;
|
||||||
|
|
||||||
connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&)));
|
connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&)));
|
||||||
connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&)));
|
connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&)));
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <devices/DdeFaceTracker.h>
|
#include <devices/DdeFaceTracker.h>
|
||||||
#include <devices/Faceshift.h>
|
#include <devices/Faceshift.h>
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
|
#include <ScriptEngines.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "DialogsManager.h"
|
#include "DialogsManager.h"
|
||||||
|
@ -44,7 +45,9 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
|
||||||
|
|
||||||
connect(ui.buttonBrowseLocation, &QPushButton::clicked, this, &PreferencesDialog::openSnapshotLocationBrowser);
|
connect(ui.buttonBrowseLocation, &QPushButton::clicked, this, &PreferencesDialog::openSnapshotLocationBrowser);
|
||||||
connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser);
|
connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser);
|
||||||
connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, qApp, &Application::loadDefaultScripts);
|
connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, [] {
|
||||||
|
DependencyManager::get<ScriptEngines>()->loadDefaultScripts();
|
||||||
|
});
|
||||||
|
|
||||||
connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser);
|
connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser);
|
||||||
connect(ui.appearanceDescription, &QLineEdit::editingFinished, this, &PreferencesDialog::changeFullAvatarURL);
|
connect(ui.appearanceDescription, &QLineEdit::editingFinished, this, &PreferencesDialog::changeFullAvatarURL);
|
||||||
|
@ -171,7 +174,7 @@ void PreferencesDialog::loadPreferences() {
|
||||||
|
|
||||||
ui.snapshotLocationEdit->setText(Snapshot::snapshotsLocation.get());
|
ui.snapshotLocationEdit->setText(Snapshot::snapshotsLocation.get());
|
||||||
|
|
||||||
ui.scriptsLocationEdit->setText(qApp->getScriptsLocation());
|
ui.scriptsLocationEdit->setText(DependencyManager::get<ScriptEngines>()->getScriptsLocation());
|
||||||
|
|
||||||
ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
|
ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
|
||||||
ui.pupilDilationSlider->maximum());
|
ui.pupilDilationSlider->maximum());
|
||||||
|
@ -265,7 +268,7 @@ void PreferencesDialog::savePreferences() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ui.scriptsLocationEdit->text().isEmpty() && QDir(ui.scriptsLocationEdit->text()).exists()) {
|
if (!ui.scriptsLocationEdit->text().isEmpty() && QDir(ui.scriptsLocationEdit->text()).exists()) {
|
||||||
qApp->setScriptsLocation(ui.scriptsLocationEdit->text());
|
DependencyManager::get<ScriptEngines>()->setScriptsLocation(ui.scriptsLocationEdit->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
|
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
|
||||||
|
|
|
@ -22,8 +22,10 @@
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
#include <ScriptEngines.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "ScriptsModel.h"
|
#include "ScriptsModel.h"
|
||||||
#include "UIUtil.h"
|
#include "UIUtil.h"
|
||||||
|
@ -33,57 +35,55 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
|
||||||
Qt::WindowCloseButtonHint),
|
Qt::WindowCloseButtonHint),
|
||||||
ui(new Ui::RunningScriptsWidget),
|
ui(new Ui::RunningScriptsWidget),
|
||||||
_reloadSignalMapper(this),
|
_reloadSignalMapper(this),
|
||||||
_stopSignalMapper(this),
|
_stopSignalMapper(this) {
|
||||||
_scriptsModelFilter(this),
|
|
||||||
_scriptsModel(this) {
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, false);
|
setAttribute(Qt::WA_DeleteOnClose, false);
|
||||||
|
|
||||||
ui->filterLineEdit->installEventFilter(this);
|
ui->filterLineEdit->installEventFilter(this);
|
||||||
|
|
||||||
connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset,
|
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
|
||||||
|
connect(scriptEngines->scriptsModelFilter(), &QSortFilterProxyModel::modelReset,
|
||||||
this, &RunningScriptsWidget::selectFirstInList);
|
this, &RunningScriptsWidget::selectFirstInList);
|
||||||
|
|
||||||
// FIXME: menu isn't prepared at this point.
|
// FIXME: menu isn't prepared at this point.
|
||||||
//QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText);
|
//QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText);
|
||||||
//ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts.");
|
//ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts.");
|
||||||
|
ui->scriptTreeView->setModel(scriptEngines->scriptsModelFilter());
|
||||||
_scriptsModelFilter.setSourceModel(&_scriptsModel);
|
|
||||||
_scriptsModelFilter.sort(0, Qt::AscendingOrder);
|
|
||||||
_scriptsModelFilter.setDynamicSortFilter(true);
|
|
||||||
ui->scriptTreeView->setModel(&_scriptsModelFilter);
|
|
||||||
|
|
||||||
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter);
|
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter);
|
||||||
connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList);
|
connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList);
|
||||||
|
|
||||||
connect(ui->reloadAllButton, &QPushButton::clicked, qApp, &Application::reloadAllScripts);
|
connect(ui->reloadAllButton, &QPushButton::clicked, scriptEngines, &ScriptEngines::reloadAllScripts);
|
||||||
connect(ui->stopAllButton, &QPushButton::clicked, this, &RunningScriptsWidget::allScriptsStopped);
|
connect(ui->stopAllButton, &QPushButton::clicked, scriptEngines, &ScriptEngines::stopAllScripts);
|
||||||
connect(ui->loadScriptFromDiskButton, &QPushButton::clicked, qApp, &Application::loadDialog);
|
connect(ui->loadScriptFromDiskButton, &QPushButton::clicked, qApp, &Application::loadDialog);
|
||||||
connect(ui->loadScriptFromURLButton, &QPushButton::clicked, qApp, &Application::loadScriptURLDialog);
|
connect(ui->loadScriptFromURLButton, &QPushButton::clicked, qApp, &Application::loadScriptURLDialog);
|
||||||
connect(&_reloadSignalMapper, static_cast<void(QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped),
|
connect(&_reloadSignalMapper, static_cast<void(QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped),
|
||||||
qApp, &Application::reloadOneScript);
|
[scriptEngines](const QString& scriptName) { scriptEngines->stopScript(scriptName, true); });
|
||||||
|
|
||||||
connect(&_stopSignalMapper, static_cast<void(QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped),
|
connect(&_stopSignalMapper, static_cast<void(QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped),
|
||||||
[](const QString& script) { qApp->stopScript(script); });
|
[scriptEngines](const QString& scriptName) { scriptEngines->stopScript(scriptName); });
|
||||||
|
|
||||||
|
setRunningScripts(scriptEngines->getRunningScripts());
|
||||||
|
connect(scriptEngines, &ScriptEngines::scriptCountChanged, scriptEngines, [this, scriptEngines] {
|
||||||
|
setRunningScripts(scriptEngines->getRunningScripts());
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
UIUtil::scaleWidgetFontSizes(this);
|
UIUtil::scaleWidgetFontSizes(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunningScriptsWidget::~RunningScriptsWidget() {
|
RunningScriptsWidget::~RunningScriptsWidget() {
|
||||||
delete ui;
|
delete ui;
|
||||||
_scriptsModel.deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunningScriptsWidget::updateFileFilter(const QString& filter) {
|
void RunningScriptsWidget::updateFileFilter(const QString& filter) {
|
||||||
QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive);
|
QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive);
|
||||||
_scriptsModelFilter.setFilterRegExp(regex);
|
DependencyManager::get<ScriptEngines>()->scriptsModelFilter()->setFilterRegExp(regex);
|
||||||
selectFirstInList();
|
selectFirstInList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) {
|
void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) {
|
||||||
QVariant scriptFile = _scriptsModelFilter.data(index, ScriptsModel::ScriptPath);
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
qApp->loadScript(scriptFile.toString());
|
QVariant scriptFile = scriptEngines->scriptsModelFilter()->data(index, ScriptsModel::ScriptPath);
|
||||||
|
scriptEngines->loadScript(scriptFile.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunningScriptsWidget::loadSelectedScript() {
|
void RunningScriptsWidget::loadSelectedScript() {
|
||||||
|
@ -183,8 +183,9 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunningScriptsWidget::selectFirstInList() {
|
void RunningScriptsWidget::selectFirstInList() {
|
||||||
if (_scriptsModelFilter.rowCount() > 0) {
|
auto model = DependencyManager::get<ScriptEngines>()->scriptsModelFilter();
|
||||||
ui->scriptTreeView->setCurrentIndex(_scriptsModelFilter.index(0, 0));
|
if (model->rowCount() > 0) {
|
||||||
|
ui->scriptTreeView->setCurrentIndex(model->index(0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,90 +218,5 @@ void RunningScriptsWidget::keyPressEvent(QKeyEvent *keyEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunningScriptsWidget::allScriptsStopped() {
|
void RunningScriptsWidget::allScriptsStopped() {
|
||||||
qApp->stopAllScripts();
|
DependencyManager::get<ScriptEngines>()->stopAllScripts();
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList RunningScriptsWidget::getRunning() {
|
|
||||||
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
|
||||||
QVariantList result;
|
|
||||||
foreach(const QString& runningScript, qApp->getRunningScripts()) {
|
|
||||||
QUrl runningScriptURL = QUrl(runningScript);
|
|
||||||
if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
|
||||||
runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
|
||||||
}
|
|
||||||
QVariantMap resultNode;
|
|
||||||
resultNode.insert("name", runningScriptURL.fileName());
|
|
||||||
resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
|
||||||
// The path contains the exact path/URL of the script, which also is used in the stopScript function.
|
|
||||||
resultNode.insert("path", runningScript);
|
|
||||||
resultNode.insert("local", runningScriptURL.isLocalFile());
|
|
||||||
result.append(resultNode);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList RunningScriptsWidget::getPublic() {
|
|
||||||
return getPublicChildNodes(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList RunningScriptsWidget::getPublicChildNodes(TreeNodeFolder* parent) {
|
|
||||||
QVariantList result;
|
|
||||||
QList<TreeNodeBase*> treeNodes = qApp->getRunningScriptsWidget()->getScriptsModel()
|
|
||||||
->getFolderNodes(parent);
|
|
||||||
for (int i = 0; i < treeNodes.size(); i++) {
|
|
||||||
TreeNodeBase* node = treeNodes.at(i);
|
|
||||||
if (node->getType() == TREE_NODE_TYPE_FOLDER) {
|
|
||||||
TreeNodeFolder* folder = static_cast<TreeNodeFolder*>(node);
|
|
||||||
QVariantMap resultNode;
|
|
||||||
resultNode.insert("name", node->getName());
|
|
||||||
resultNode.insert("type", "folder");
|
|
||||||
resultNode.insert("children", getPublicChildNodes(folder));
|
|
||||||
result.append(resultNode);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TreeNodeScript* script = static_cast<TreeNodeScript*>(node);
|
|
||||||
if (script->getOrigin() == ScriptOrigin::SCRIPT_ORIGIN_LOCAL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QVariantMap resultNode;
|
|
||||||
resultNode.insert("name", node->getName());
|
|
||||||
resultNode.insert("type", "script");
|
|
||||||
resultNode.insert("url", script->getFullPath());
|
|
||||||
result.append(resultNode);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList RunningScriptsWidget::getLocal() {
|
|
||||||
QVariantList result;
|
|
||||||
QList<TreeNodeBase*> treeNodes = qApp->getRunningScriptsWidget()->getScriptsModel()
|
|
||||||
->getFolderNodes(NULL);
|
|
||||||
for (int i = 0; i < treeNodes.size(); i++) {
|
|
||||||
TreeNodeBase* node = treeNodes.at(i);
|
|
||||||
if (node->getType() != TREE_NODE_TYPE_SCRIPT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TreeNodeScript* script = static_cast<TreeNodeScript*>(node);
|
|
||||||
if (script->getOrigin() != ScriptOrigin::SCRIPT_ORIGIN_LOCAL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QVariantMap resultNode;
|
|
||||||
resultNode.insert("name", node->getName());
|
|
||||||
resultNode.insert("path", script->getFullPath());
|
|
||||||
result.append(resultNode);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunningScriptsWidget::stopScriptByName(const QString& name) {
|
|
||||||
foreach (const QString& runningScript, qApp->getRunningScripts()) {
|
|
||||||
if (QUrl(runningScript).fileName().toLower() == name.trimmed().toLower()) {
|
|
||||||
return qApp->stopScript(runningScript, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunningScriptsWidget::stopScript(const QString& name, bool restart) {
|
|
||||||
return qApp->stopScript(name, restart);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,24 +33,12 @@ public:
|
||||||
|
|
||||||
void setRunningScripts(const QStringList& list);
|
void setRunningScripts(const QStringList& list);
|
||||||
|
|
||||||
const ScriptsModel* getScriptsModel() { return &_scriptsModel; }
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void scriptStopped(const QString& scriptName);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool eventFilter(QObject* sender, QEvent* event);
|
virtual bool eventFilter(QObject* sender, QEvent* event);
|
||||||
|
|
||||||
virtual void keyPressEvent(QKeyEvent* event);
|
virtual void keyPressEvent(QKeyEvent* event);
|
||||||
virtual void showEvent(QShowEvent* event);
|
virtual void showEvent(QShowEvent* event);
|
||||||
|
|
||||||
public slots:
|
|
||||||
QVariantList getRunning();
|
|
||||||
QVariantList getPublic();
|
|
||||||
QVariantList getLocal();
|
|
||||||
bool stopScript(const QString& name, bool restart = false);
|
|
||||||
bool stopScriptByName(const QString& name);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void allScriptsStopped();
|
void allScriptsStopped();
|
||||||
void updateFileFilter(const QString& filter);
|
void updateFileFilter(const QString& filter);
|
||||||
|
@ -62,9 +50,6 @@ private:
|
||||||
Ui::RunningScriptsWidget* ui;
|
Ui::RunningScriptsWidget* ui;
|
||||||
QSignalMapper _reloadSignalMapper;
|
QSignalMapper _reloadSignalMapper;
|
||||||
QSignalMapper _stopSignalMapper;
|
QSignalMapper _stopSignalMapper;
|
||||||
ScriptsModelFilter _scriptsModelFilter;
|
|
||||||
ScriptsModel _scriptsModel;
|
|
||||||
|
|
||||||
QVariantList getPublicChildNodes(TreeNodeFolder* parent);
|
QVariantList getPublicChildNodes(TreeNodeFolder* parent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <ScriptEngines.h>
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
#include <OffscreenUi.h>
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
|
@ -101,17 +102,18 @@ bool ScriptEditorWidget::setRunning(bool run) {
|
||||||
disconnect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
|
disconnect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
if (run) {
|
if (run) {
|
||||||
const QString& scriptURLString = QUrl(_currentScript).toString();
|
const QString& scriptURLString = QUrl(_currentScript).toString();
|
||||||
// Reload script so that an out of date copy is not retrieved from the cache
|
// Reload script so that an out of date copy is not retrieved from the cache
|
||||||
_scriptEngine = qApp->loadScript(scriptURLString, true, true, false, true);
|
_scriptEngine = scriptEngines->loadScript(scriptURLString, true, true, false, true);
|
||||||
connect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged);
|
connect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged);
|
||||||
connect(_scriptEngine, &ScriptEngine::update, this, &ScriptEditorWidget::onScriptModified);
|
connect(_scriptEngine, &ScriptEngine::update, this, &ScriptEditorWidget::onScriptModified);
|
||||||
connect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
|
connect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
|
||||||
} else {
|
} else {
|
||||||
connect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
|
connect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
|
||||||
const QString& scriptURLString = QUrl(_currentScript).toString();
|
const QString& scriptURLString = QUrl(_currentScript).toString();
|
||||||
qApp->stopScript(scriptURLString);
|
scriptEngines->stopScript(scriptURLString);
|
||||||
_scriptEngine = NULL;
|
_scriptEngine = NULL;
|
||||||
}
|
}
|
||||||
_console->setScriptEngine(_scriptEngine);
|
_console->setScriptEngine(_scriptEngine);
|
||||||
|
@ -173,7 +175,7 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const QString& scriptURLString = QUrl(_currentScript).toString();
|
const QString& scriptURLString = QUrl(_currentScript).toString();
|
||||||
_scriptEngine = qApp->getScriptEngine(scriptURLString);
|
_scriptEngine = DependencyManager::get<ScriptEngines>()->getScriptEngine(scriptURLString);
|
||||||
if (_scriptEngine != NULL) {
|
if (_scriptEngine != NULL) {
|
||||||
connect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged);
|
connect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged);
|
||||||
connect(_scriptEngine, &ScriptEngine::update, this, &ScriptEditorWidget::onScriptModified);
|
connect(_scriptEngine, &ScriptEngine::update, this, &ScriptEditorWidget::onScriptModified);
|
||||||
|
@ -187,11 +189,12 @@ bool ScriptEditorWidget::save() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptEditorWidget::saveAs() {
|
bool ScriptEditorWidget::saveAs() {
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"),
|
QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"),
|
||||||
qApp->getPreviousScriptLocation(),
|
scriptEngines->getPreviousScriptLocation(),
|
||||||
tr("JavaScript Files (*.js)"));
|
tr("JavaScript Files (*.js)"));
|
||||||
if (!fileName.isEmpty()) {
|
if (!fileName.isEmpty()) {
|
||||||
qApp->setPreviousScriptLocation(fileName);
|
scriptEngines->setPreviousScriptLocation(fileName);
|
||||||
return saveFile(fileName);
|
return saveFile(fileName);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "ScriptEditorWidget.h"
|
#include "ScriptEditorWidget.h"
|
||||||
|
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
#include <QtCore/QSignalMapper>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QLayoutItem>
|
#include <QLayoutItem>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <ScriptEngines.h>
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "PathUtils.h"
|
#include "PathUtils.h"
|
||||||
|
|
||||||
|
@ -85,11 +87,12 @@ void ScriptEditorWindow::loadScriptMenu(const QString& scriptName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEditorWindow::loadScriptClicked() {
|
void ScriptEditorWindow::loadScriptClicked() {
|
||||||
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"),
|
QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"),
|
||||||
qApp->getPreviousScriptLocation(),
|
scriptEngines->getPreviousScriptLocation(),
|
||||||
tr("JavaScript Files (*.js)"));
|
tr("JavaScript Files (*.js)"));
|
||||||
if (!scriptName.isEmpty()) {
|
if (!scriptName.isEmpty()) {
|
||||||
qApp->setPreviousScriptLocation(scriptName);
|
scriptEngines->setPreviousScriptLocation(scriptName);
|
||||||
addScriptEditorWidget("loading...")->loadFile(scriptName);
|
addScriptEditorWidget("loading...")->loadFile(scriptName);
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}
|
}
|
||||||
|
@ -97,7 +100,7 @@ void ScriptEditorWindow::loadScriptClicked() {
|
||||||
|
|
||||||
void ScriptEditorWindow::loadMenuAboutToShow() {
|
void ScriptEditorWindow::loadMenuAboutToShow() {
|
||||||
_loadMenu->clear();
|
_loadMenu->clear();
|
||||||
QStringList runningScripts = qApp->getRunningScripts();
|
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();;
|
||||||
if (runningScripts.count() > 0) {
|
if (runningScripts.count() > 0) {
|
||||||
QSignalMapper* signalMapper = new QSignalMapper(this);
|
QSignalMapper* signalMapper = new QSignalMapper(this);
|
||||||
foreach (const QString& runningScript, runningScripts) {
|
foreach (const QString& runningScript, runningScripts) {
|
||||||
|
|
|
@ -15,14 +15,10 @@
|
||||||
|
|
||||||
#include <plugins/PluginContainer.h>
|
#include <plugins/PluginContainer.h>
|
||||||
|
|
||||||
const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display");
|
const QString Basic2DWindowOpenGLDisplayPlugin::NAME("Desktop");
|
||||||
|
|
||||||
static const QString FULLSCREEN = "Fullscreen";
|
static const QString FULLSCREEN = "Fullscreen";
|
||||||
|
|
||||||
const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Basic2DWindowOpenGLDisplayPlugin::activate() {
|
void Basic2DWindowOpenGLDisplayPlugin::activate() {
|
||||||
WindowOpenGLDisplayPlugin::activate();
|
WindowOpenGLDisplayPlugin::activate();
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual const QString & getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; }
|
virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; }
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,6 @@
|
||||||
|
|
||||||
const QString NullDisplayPlugin::NAME("NullDisplayPlugin");
|
const QString NullDisplayPlugin::NAME("NullDisplayPlugin");
|
||||||
|
|
||||||
const QString & NullDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::uvec2 NullDisplayPlugin::getRecommendedRenderSize() const {
|
glm::uvec2 NullDisplayPlugin::getRecommendedRenderSize() const {
|
||||||
return glm::uvec2(100, 100);
|
return glm::uvec2(100, 100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ class NullDisplayPlugin : public DisplayPlugin {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~NullDisplayPlugin() final {}
|
virtual ~NullDisplayPlugin() final {}
|
||||||
virtual const QString & getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
virtual grouping getGrouping() const override { return DEVELOPER; }
|
||||||
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,7 @@ void main() {
|
||||||
|
|
||||||
)FS";
|
)FS";
|
||||||
|
|
||||||
const QString InterleavedStereoDisplayPlugin::NAME("Interleaved Stereo Display");
|
const QString InterleavedStereoDisplayPlugin::NAME("3D TV - Interleaved");
|
||||||
|
|
||||||
const QString & InterleavedStereoDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() {
|
InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@ class InterleavedStereoDisplayPlugin : public StereoDisplayPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
InterleavedStereoDisplayPlugin();
|
InterleavedStereoDisplayPlugin();
|
||||||
virtual const QString & getName() const override;
|
|
||||||
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
virtual grouping getGrouping() const override { return ADVANCED; }
|
||||||
|
|
||||||
// initialize OpenGL context settings needed by the plugin
|
// initialize OpenGL context settings needed by the plugin
|
||||||
virtual void customizeContext() override;
|
virtual void customizeContext() override;
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
|
|
||||||
const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo");
|
const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo");
|
||||||
|
|
||||||
const QString & SideBySideStereoDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() {
|
SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SideBySideStereoDisplayPlugin();
|
SideBySideStereoDisplayPlugin();
|
||||||
virtual const QString& getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
virtual grouping getGrouping() const override { return ADVANCED; }
|
||||||
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override { return true; }
|
virtual bool isSupported() const override { return true; }
|
||||||
virtual bool isJointController() const override { return false; }
|
virtual bool isJointController() const override { return false; }
|
||||||
const QString& getName() const override { return NAME; }
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
||||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||||
|
|
|
@ -19,6 +19,11 @@ public:
|
||||||
/// \return human-readable name
|
/// \return human-readable name
|
||||||
virtual const QString& getName() const = 0;
|
virtual const QString& getName() const = 0;
|
||||||
|
|
||||||
|
typedef enum { STANDARD, ADVANCED, DEVELOPER } grouping;
|
||||||
|
|
||||||
|
/// \return human-readable grouping for the plugin, STANDARD, ADVANCED, or DEVELOPER
|
||||||
|
virtual grouping getGrouping() const { return STANDARD; }
|
||||||
|
|
||||||
/// \return string ID (not necessarily human-readable)
|
/// \return string ID (not necessarily human-readable)
|
||||||
virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; }
|
virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; }
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
AmbientOcclusion();
|
AmbientOcclusion();
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
typedef render::Job::Model<AmbientOcclusion> JobModel;
|
using JobModel = render::Task::Job::Model<AmbientOcclusion>;
|
||||||
|
|
||||||
const gpu::PipelinePointer& getOcclusionPipeline();
|
const gpu::PipelinePointer& getOcclusionPipeline();
|
||||||
const gpu::PipelinePointer& getHBlurPipeline();
|
const gpu::PipelinePointer& getHBlurPipeline();
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
Antialiasing();
|
Antialiasing();
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
typedef render::Job::Model<Antialiasing> JobModel;
|
using JobModel = render::Task::Job::Model<Antialiasing>;
|
||||||
|
|
||||||
const gpu::PipelinePointer& getAntialiasingPipeline();
|
const gpu::PipelinePointer& getAntialiasingPipeline();
|
||||||
const gpu::PipelinePointer& getBlendPipeline();
|
const gpu::PipelinePointer& getBlendPipeline();
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
class DebugDeferredBuffer {
|
class DebugDeferredBuffer {
|
||||||
public:
|
public:
|
||||||
using JobModel = render::Job::Model<DebugDeferredBuffer>;
|
using JobModel = render::Task::Job::Model<DebugDeferredBuffer>;
|
||||||
|
|
||||||
DebugDeferredBuffer();
|
DebugDeferredBuffer();
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
HitEffect();
|
HitEffect();
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
typedef render::Job::Model<HitEffect> JobModel;
|
using JobModel = render::Task::Job::Model<HitEffect>;
|
||||||
|
|
||||||
const gpu::PipelinePointer& getHitEffectPipeline();
|
const gpu::PipelinePointer& getHitEffectPipeline();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#include "RenderDeferredTask.h"
|
|
||||||
|
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
@ -24,10 +23,13 @@
|
||||||
#include "HitEffect.h"
|
#include "HitEffect.h"
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
|
|
||||||
|
#include "render/DrawTask.h"
|
||||||
#include "render/DrawStatus.h"
|
#include "render/DrawStatus.h"
|
||||||
#include "AmbientOcclusionEffect.h"
|
#include "AmbientOcclusionEffect.h"
|
||||||
#include "AntialiasingEffect.h"
|
#include "AntialiasingEffect.h"
|
||||||
|
|
||||||
|
#include "RenderDeferredTask.h"
|
||||||
|
|
||||||
#include "model_vert.h"
|
#include "model_vert.h"
|
||||||
#include "model_shadow_vert.h"
|
#include "model_shadow_vert.h"
|
||||||
#include "model_normal_map_vert.h"
|
#include "model_normal_map_vert.h"
|
||||||
|
@ -81,63 +83,61 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
|
||||||
initDeferredPipelines(*shapePlumber);
|
initDeferredPipelines(*shapePlumber);
|
||||||
|
|
||||||
// CPU only, create the list of renderedOpaques items
|
// CPU only, create the list of renderedOpaques items
|
||||||
_jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque",
|
addJob<FetchItems>("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) {
|
||||||
FetchItems([](const RenderContextPointer& context, int count) {
|
context->getItemsConfig().opaque.numFeed = count;
|
||||||
context->getItemsConfig().opaque.numFeed = count;
|
}));
|
||||||
})
|
addJob<CullItems<RenderDetails::OPAQUE_ITEM>>("CullOpaque", _jobs.back().getOutput());
|
||||||
)));
|
addJob<DepthSortItems>("DepthSortOpaque", _jobs.back().getOutput());
|
||||||
_jobs.push_back(Job(new CullItems<RenderDetails::OPAQUE_ITEM>::JobModel("CullOpaque", _jobs.back().getOutput())));
|
|
||||||
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput())));
|
|
||||||
auto& renderedOpaques = _jobs.back().getOutput();
|
auto& renderedOpaques = _jobs.back().getOutput();
|
||||||
|
|
||||||
// CPU only, create the list of renderedTransparents items
|
// CPU only, create the list of renderedTransparents items
|
||||||
_jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent",
|
addJob<FetchItems>("FetchTransparent", FetchItems(
|
||||||
FetchItems(ItemFilter::Builder::transparentShape().withoutLayered(),
|
ItemFilter::Builder::transparentShape().withoutLayered(),
|
||||||
[](const RenderContextPointer& context, int count) {
|
[](const RenderContextPointer& context, int count) {
|
||||||
context->getItemsConfig().transparent.numFeed = count;
|
context->getItemsConfig().transparent.numFeed = count;
|
||||||
})
|
}
|
||||||
)));
|
));
|
||||||
_jobs.push_back(Job(new CullItems<RenderDetails::TRANSLUCENT_ITEM>::JobModel("CullTransparent", _jobs.back().getOutput())));
|
addJob<CullItems<RenderDetails::TRANSLUCENT_ITEM>>("CullTransparent", _jobs.back().getOutput());
|
||||||
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false))));
|
addJob<DepthSortItems>("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false));
|
||||||
auto& renderedTransparents = _jobs.back().getOutput();
|
auto& renderedTransparents = _jobs.back().getOutput();
|
||||||
|
|
||||||
// GPU Jobs: Start preparing the deferred and lighting buffer
|
// GPU Jobs: Start preparing the deferred and lighting buffer
|
||||||
_jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred")));
|
addJob<PrepareDeferred>("PrepareDeferred");
|
||||||
|
|
||||||
// Render opaque objects in DeferredBuffer
|
// Render opaque objects in DeferredBuffer
|
||||||
_jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", renderedOpaques, DrawOpaqueDeferred(shapePlumber))));
|
addJob<DrawOpaqueDeferred>("DrawOpaqueDeferred", renderedOpaques, shapePlumber);
|
||||||
|
|
||||||
// Once opaque is all rendered create stencil background
|
// Once opaque is all rendered create stencil background
|
||||||
_jobs.push_back(Job(new DrawStencilDeferred::JobModel("DrawOpaqueStencil")));
|
addJob<DrawStencilDeferred>("DrawOpaqueStencil");
|
||||||
|
|
||||||
// Use Stencil and start drawing background in Lighting buffer
|
// Use Stencil and start drawing background in Lighting buffer
|
||||||
_jobs.push_back(Job(new DrawBackgroundDeferred::JobModel("DrawBackgroundDeferred")));
|
addJob<DrawBackgroundDeferred>("DrawBackgroundDeferred");
|
||||||
|
|
||||||
// Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now.
|
// Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now.
|
||||||
_jobs.push_back(Job(new DrawLight::JobModel("DrawLight")));
|
addJob<DrawLight>("DrawLight");
|
||||||
|
|
||||||
// DeferredBuffer is complete, now let's shade it into the LightingBuffer
|
// DeferredBuffer is complete, now let's shade it into the LightingBuffer
|
||||||
_jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred")));
|
addJob<RenderDeferred>("RenderDeferred");
|
||||||
|
|
||||||
// AO job, to be revisited
|
// AO job, to be revisited
|
||||||
_jobs.push_back(Job(new AmbientOcclusion::JobModel("AmbientOcclusion")));
|
addJob<AmbientOcclusion>("AmbientOcclusion");
|
||||||
_jobs.back().setEnabled(false);
|
_jobs.back().setEnabled(false);
|
||||||
_occlusionJobIndex = (int)_jobs.size() - 1;
|
_occlusionJobIndex = (int)_jobs.size() - 1;
|
||||||
|
|
||||||
// AA job to be revisited
|
// AA job to be revisited
|
||||||
_jobs.push_back(Job(new Antialiasing::JobModel("Antialiasing")));
|
addJob<Antialiasing>("Antialiasing");
|
||||||
_jobs.back().setEnabled(false);
|
_jobs.back().setEnabled(false);
|
||||||
_antialiasingJobIndex = (int)_jobs.size() - 1;
|
_antialiasingJobIndex = (int)_jobs.size() - 1;
|
||||||
|
|
||||||
// Render transparent objects forward in LigthingBuffer
|
// Render transparent objects forward in LigthingBuffer
|
||||||
_jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", renderedTransparents, DrawTransparentDeferred(shapePlumber))));
|
addJob<DrawTransparentDeferred>("DrawTransparentDeferred", renderedTransparents, shapePlumber);
|
||||||
|
|
||||||
// Lighting Buffer ready for tone mapping
|
// Lighting Buffer ready for tone mapping
|
||||||
_jobs.push_back(Job(new ToneMappingDeferred::JobModel("ToneMapping")));
|
addJob<ToneMappingDeferred>("ToneMapping");
|
||||||
_toneMappingJobIndex = (int)_jobs.size() - 1;
|
_toneMappingJobIndex = (int)_jobs.size() - 1;
|
||||||
|
|
||||||
// Debugging Deferred buffer job
|
// Debugging Deferred buffer job
|
||||||
_jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer")));
|
addJob<DebugDeferredBuffer>("DebugDeferredBuffer");
|
||||||
_jobs.back().setEnabled(false);
|
_jobs.back().setEnabled(false);
|
||||||
_drawDebugDeferredBufferIndex = (int)_jobs.size() - 1;
|
_drawDebugDeferredBufferIndex = (int)_jobs.size() - 1;
|
||||||
|
|
||||||
|
@ -146,21 +146,18 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
|
||||||
// Grab a texture map representing the different status icons and assign that to the drawStatsuJob
|
// Grab a texture map representing the different status icons and assign that to the drawStatsuJob
|
||||||
auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg";
|
auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg";
|
||||||
auto statusIconMap = DependencyManager::get<TextureCache>()->getImageTexture(iconMapPath);
|
auto statusIconMap = DependencyManager::get<TextureCache>()->getImageTexture(iconMapPath);
|
||||||
_jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap))));
|
addJob<DrawStatus>("DrawStatus", renderedOpaques, DrawStatus(statusIconMap));
|
||||||
_jobs.back().setEnabled(false);
|
_jobs.back().setEnabled(false);
|
||||||
_drawStatusJobIndex = (int)_jobs.size() - 1;
|
_drawStatusJobIndex = (int)_jobs.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D", DrawOverlay3D(shapePlumber))));
|
addJob<DrawOverlay3D>("DrawOverlay3D", shapePlumber);
|
||||||
|
|
||||||
_jobs.push_back(Job(new HitEffect::JobModel("HitEffect")));
|
addJob<HitEffect>("HitEffect");
|
||||||
_jobs.back().setEnabled(false);
|
_jobs.back().setEnabled(false);
|
||||||
_drawHitEffectJobIndex = (int)_jobs.size() -1;
|
_drawHitEffectJobIndex = (int)_jobs.size() -1;
|
||||||
|
|
||||||
_jobs.push_back(Job(new Blit::JobModel("Blit")));
|
addJob<Blit>("Blit");
|
||||||
}
|
|
||||||
|
|
||||||
RenderDeferredTask::~RenderDeferredTask() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
#ifndef hifi_RenderDeferredTask_h
|
#ifndef hifi_RenderDeferredTask_h
|
||||||
#define hifi_RenderDeferredTask_h
|
#define hifi_RenderDeferredTask_h
|
||||||
|
|
||||||
#include "render/DrawTask.h"
|
#include "render/Engine.h"
|
||||||
#include "render/ShapePipeline.h"
|
|
||||||
|
|
||||||
#include "gpu/Pipeline.h"
|
#include "gpu/Pipeline.h"
|
||||||
|
|
||||||
|
@ -23,14 +22,14 @@ class SetupDeferred {
|
||||||
public:
|
public:
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<SetupDeferred> JobModel;
|
using JobModel = render::Task::Job::Model<SetupDeferred>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrepareDeferred {
|
class PrepareDeferred {
|
||||||
public:
|
public:
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<PrepareDeferred> JobModel;
|
using JobModel = render::Task::Job::Model<PrepareDeferred>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class RenderDeferred {
|
||||||
public:
|
public:
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<RenderDeferred> JobModel;
|
using JobModel = render::Task::Job::Model<RenderDeferred>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ToneMappingDeferred {
|
class ToneMappingDeferred {
|
||||||
|
@ -47,7 +46,7 @@ public:
|
||||||
|
|
||||||
ToneMappingEffect _toneMappingEffect;
|
ToneMappingEffect _toneMappingEffect;
|
||||||
|
|
||||||
typedef render::Job::Model<ToneMappingDeferred> JobModel;
|
using JobModel = render::Task::Job::Model<ToneMappingDeferred>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrawOpaqueDeferred {
|
class DrawOpaqueDeferred {
|
||||||
|
@ -55,7 +54,7 @@ public:
|
||||||
DrawOpaqueDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
DrawOpaqueDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
|
||||||
|
|
||||||
typedef render::Job::ModelI<DrawOpaqueDeferred, render::ItemIDsBounds> JobModel;
|
using JobModel = render::Task::Job::ModelI<DrawOpaqueDeferred, render::ItemIDsBounds>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
render::ShapePlumberPointer _shapePlumber;
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
|
@ -66,7 +65,7 @@ public:
|
||||||
DrawTransparentDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
DrawTransparentDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
|
||||||
|
|
||||||
typedef render::Job::ModelI<DrawTransparentDeferred, render::ItemIDsBounds> JobModel;
|
using JobModel = render::Task::Job::ModelI<DrawTransparentDeferred, render::ItemIDsBounds>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
render::ShapePlumberPointer _shapePlumber;
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
|
@ -78,7 +77,7 @@ public:
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<DrawStencilDeferred> JobModel;
|
using JobModel = render::Task::Job::Model<DrawStencilDeferred>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||||
|
@ -88,7 +87,7 @@ class DrawBackgroundDeferred {
|
||||||
public:
|
public:
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<DrawBackgroundDeferred> JobModel;
|
using JobModel = render::Task::Job::Model<DrawBackgroundDeferred>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrawOverlay3D {
|
class DrawOverlay3D {
|
||||||
|
@ -98,7 +97,7 @@ public:
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<DrawOverlay3D> JobModel;
|
using JobModel = render::Task::Job::Model<DrawOverlay3D>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||||
|
@ -109,17 +108,14 @@ class Blit {
|
||||||
public:
|
public:
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef render::Job::Model<Blit> JobModel;
|
using JobModel = render::Task::Job::Model<Blit>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderDeferredTask : public render::Task {
|
class RenderDeferredTask : public render::Task {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RenderDeferredTask();
|
RenderDeferredTask();
|
||||||
~RenderDeferredTask();
|
|
||||||
|
|
||||||
render::Jobs _jobs;
|
|
||||||
|
|
||||||
int _drawDebugDeferredBufferIndex = -1;
|
int _drawDebugDeferredBufferIndex = -1;
|
||||||
int _drawStatusJobIndex = -1;
|
int _drawStatusJobIndex = -1;
|
||||||
int _drawHitEffectJobIndex = -1;
|
int _drawHitEffectJobIndex = -1;
|
||||||
|
|
32
libraries/render/src/render/Context.cpp
Normal file
32
libraries/render/src/render/Context.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// Context.cpp
|
||||||
|
// render/src/render
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 1/6/2015.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Context.h"
|
||||||
|
|
||||||
|
using namespace render;
|
||||||
|
|
||||||
|
RenderContext::RenderContext(ItemsConfig items, Tone tone, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode)
|
||||||
|
: _deferredDebugMode{ deferredDebugMode }, _deferredDebugSize{ deferredDebugSize },
|
||||||
|
_args{ nullptr },
|
||||||
|
_drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect },
|
||||||
|
_items{ items }, _tone{ tone }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned) {
|
||||||
|
_occlusionStatus = occlusion;
|
||||||
|
_fxaaStatus = fxaa;
|
||||||
|
|
||||||
|
if (showOwned) {
|
||||||
|
_drawStatus |= render::showNetworkStatusFlag;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
109
libraries/render/src/render/Context.h
Normal file
109
libraries/render/src/render/Context.h
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
//
|
||||||
|
// Context.h
|
||||||
|
// render/src/render
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 1/6/2015.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_render_Context_h
|
||||||
|
#define hifi_render_Context_h
|
||||||
|
|
||||||
|
#include "Scene.h"
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
|
||||||
|
class SceneContext {
|
||||||
|
public:
|
||||||
|
ScenePointer _scene;
|
||||||
|
|
||||||
|
SceneContext() {}
|
||||||
|
};
|
||||||
|
using SceneContextPointer = std::shared_ptr<SceneContext>;
|
||||||
|
|
||||||
|
// see examples/utilities/tools/renderEngineDebug.js
|
||||||
|
const int showDisplayStatusFlag = 1;
|
||||||
|
const int showNetworkStatusFlag = 2;
|
||||||
|
|
||||||
|
class RenderContext {
|
||||||
|
public:
|
||||||
|
class ItemsConfig {
|
||||||
|
public:
|
||||||
|
class Counter {
|
||||||
|
public:
|
||||||
|
Counter() {}
|
||||||
|
Counter(const Counter& counter) : maxDrawn { counter.maxDrawn } {}
|
||||||
|
|
||||||
|
void setCounts(const Counter& counter) {
|
||||||
|
numFeed = counter.numFeed;
|
||||||
|
numDrawn = counter.numDrawn;
|
||||||
|
};
|
||||||
|
|
||||||
|
int numFeed { 0 };
|
||||||
|
int numDrawn { 0 };
|
||||||
|
int maxDrawn { -1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
class State : public Counter {
|
||||||
|
public:
|
||||||
|
bool render { true };
|
||||||
|
bool cull { true };
|
||||||
|
bool sort { true };
|
||||||
|
|
||||||
|
Counter counter{};
|
||||||
|
};
|
||||||
|
|
||||||
|
ItemsConfig(State opaqueState, State transparentState, Counter overlay3DCounter)
|
||||||
|
: opaque{ opaqueState }, transparent{ transparentState }, overlay3D{ overlay3DCounter } {}
|
||||||
|
ItemsConfig() : ItemsConfig{ {}, {}, {} } {}
|
||||||
|
|
||||||
|
// TODO: If member count increases, store counters in a map instead of multiple members
|
||||||
|
State opaque{};
|
||||||
|
State transparent{};
|
||||||
|
Counter overlay3D{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Tone {
|
||||||
|
public:
|
||||||
|
int toneCurve = 1; // Means just Gamma 2.2 correction
|
||||||
|
float exposure = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderContext(ItemsConfig items, Tone tone, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode);
|
||||||
|
RenderContext() {}
|
||||||
|
|
||||||
|
void setArgs(RenderArgs* args) { _args = args; }
|
||||||
|
RenderArgs* getArgs() { return _args; }
|
||||||
|
ItemsConfig& getItemsConfig() { return _items; }
|
||||||
|
Tone& getTone() { return _tone; }
|
||||||
|
int getDrawStatus() { return _drawStatus; }
|
||||||
|
bool getDrawHitEffect() { return _drawHitEffect; }
|
||||||
|
bool getOcclusionStatus() { return _occlusionStatus; }
|
||||||
|
bool getFxaaStatus() { return _fxaaStatus; }
|
||||||
|
void setOptions(bool occlusion, bool fxaa, bool showOwned);
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
int _deferredDebugMode;
|
||||||
|
glm::vec4 _deferredDebugSize;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RenderArgs* _args;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
int _drawStatus; // bitflag
|
||||||
|
bool _drawHitEffect;
|
||||||
|
bool _occlusionStatus { false };
|
||||||
|
bool _fxaaStatus = { false };
|
||||||
|
|
||||||
|
ItemsConfig _items;
|
||||||
|
Tone _tone;
|
||||||
|
};
|
||||||
|
typedef std::shared_ptr<RenderContext> RenderContextPointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // hifi_render_Context_h
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace render {
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
||||||
|
|
||||||
typedef Job::ModelI<DrawStatus, ItemIDsBounds> JobModel;
|
using JobModel = Task::Job::ModelI<DrawStatus, ItemIDsBounds>;
|
||||||
|
|
||||||
const gpu::PipelinePointer getDrawItemBoundsPipeline();
|
const gpu::PipelinePointer getDrawItemBoundsPipeline();
|
||||||
const gpu::PipelinePointer getDrawItemStatusPipeline();
|
const gpu::PipelinePointer getDrawItemStatusPipeline();
|
||||||
|
|
|
@ -15,44 +15,12 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <RenderArgs.h>
|
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
DrawSceneTask::DrawSceneTask() : Task() {
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawSceneTask::~DrawSceneTask() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
// sanity checks
|
|
||||||
assert(sceneContext);
|
|
||||||
if (!sceneContext->_scene) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Is it possible that we render without a viewFrustum ?
|
|
||||||
if (!(renderContext->getArgs() && renderContext->getArgs()->_viewFrustum)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto job : _jobs) {
|
|
||||||
job.run(sceneContext, renderContext);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Job::~Job() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
|
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
|
||||||
assert(renderContext->getArgs());
|
assert(renderContext->getArgs());
|
||||||
assert(renderContext->getArgs()->_viewFrustum);
|
assert(renderContext->getArgs()->_viewFrustum);
|
||||||
|
@ -247,19 +215,6 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext
|
||||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||||
args->_batch = &batch;
|
args->_batch = &batch;
|
||||||
renderLights(sceneContext, renderContext, culledItems);
|
renderLights(sceneContext, renderContext, culledItems);
|
||||||
|
args->_batch = nullptr;
|
||||||
});
|
});
|
||||||
args->_batch = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) {
|
|
||||||
// Insert the itemID in every bucket where it filters true
|
|
||||||
for (auto& bucket : (*this)) {
|
|
||||||
if (bucket.first.test(key)) {
|
|
||||||
bucket.second.push_back(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemMaterialBucketMap::allocateStandardMaterialBuckets() {
|
|
||||||
(*this)[model::MaterialFilter::Builder::opaqueDiffuse()];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,216 +9,16 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef hifi_render_Task_h
|
#ifndef hifi_render_DrawTask_h
|
||||||
#define hifi_render_Task_h
|
#define hifi_render_DrawTask_h
|
||||||
|
|
||||||
#include "Engine.h"
|
#include "Engine.h"
|
||||||
#include "ShapePipeline.h"
|
#include "ShapePipeline.h"
|
||||||
#include "gpu/Batch.h"
|
#include "gpu/Batch.h"
|
||||||
#include <PerfStat.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
template <class T> void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
jobModel.run(sceneContext, renderContext);
|
|
||||||
}
|
|
||||||
template <class T, class I> void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) {
|
|
||||||
jobModel.run(sceneContext, renderContext, input);
|
|
||||||
}
|
|
||||||
template <class T, class O> void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) {
|
|
||||||
jobModel.run(sceneContext, renderContext, output);
|
|
||||||
}
|
|
||||||
template <class T, class I, class O> void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) {
|
|
||||||
jobModel.run(sceneContext, renderContext, input, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Job {
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Varying represent a varying piece of data
|
|
||||||
class Varying {
|
|
||||||
public:
|
|
||||||
|
|
||||||
Varying(const Varying& var): _concept(var._concept) {}
|
|
||||||
|
|
||||||
Varying() {}
|
|
||||||
template <class T>
|
|
||||||
Varying(const T& data) : _concept(std::make_shared<Job::Varying::Model<T>>(data)) {}
|
|
||||||
|
|
||||||
// Access the _data contained win the concept explicitely
|
|
||||||
template <class T> T& edit() { return std::static_pointer_cast<Model<T>>(_concept)->_data; }
|
|
||||||
template <class T> const T& get() const { return std::static_pointer_cast<const Model<T>>(_concept)->_data; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class Job;
|
|
||||||
|
|
||||||
std::vector<std::weak_ptr<Job>> _consumerJobs;
|
|
||||||
|
|
||||||
void addJobConsumer(const std::shared_ptr<Job>& job) {
|
|
||||||
_consumerJobs.push_back(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Concept {
|
|
||||||
public:
|
|
||||||
virtual ~Concept() = default;
|
|
||||||
};
|
|
||||||
template <class T> class Model : public Concept {
|
|
||||||
public:
|
|
||||||
typedef T Data;
|
|
||||||
Data _data;
|
|
||||||
Model(const Model& source): _data(source.data) {}
|
|
||||||
Model(const Data& data): _data(data) {}
|
|
||||||
virtual ~Model() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<Concept> _concept;
|
|
||||||
};
|
|
||||||
|
|
||||||
Job(const Job& other) : _concept(other._concept) {}
|
|
||||||
~Job();
|
|
||||||
|
|
||||||
bool isEnabled() const { return _concept->isEnabled(); }
|
|
||||||
void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); }
|
|
||||||
|
|
||||||
const std::string& getName() const { return _concept->getName(); }
|
|
||||||
const Varying getInput() const { return _concept->getInput(); }
|
|
||||||
const Varying getOutput() const { return _concept->getOutput(); }
|
|
||||||
|
|
||||||
template <class T> T& edit() {
|
|
||||||
auto theConcept = std::dynamic_pointer_cast<typename T::JobModel>(_concept);
|
|
||||||
assert(theConcept);
|
|
||||||
return theConcept->_data;
|
|
||||||
}
|
|
||||||
template <class T> const T& get() const {
|
|
||||||
auto theConcept = std::dynamic_pointer_cast<typename T::JobModel>(_concept);
|
|
||||||
assert(theConcept);
|
|
||||||
return theConcept->_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
PerformanceTimer perfTimer(getName().c_str());
|
|
||||||
PROFILE_RANGE(getName().c_str());
|
|
||||||
_concept->run(sceneContext, renderContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Concept {
|
|
||||||
std::string _name;
|
|
||||||
bool _isEnabled = true;
|
|
||||||
public:
|
|
||||||
Concept() : _name() {}
|
|
||||||
Concept(const std::string& name) : _name(name) {}
|
|
||||||
virtual ~Concept() = default;
|
|
||||||
|
|
||||||
void setName(const std::string& name) { _name = name; }
|
|
||||||
const std::string& getName() const { return _name; }
|
|
||||||
|
|
||||||
bool isEnabled() const { return _isEnabled; }
|
|
||||||
void setEnabled(bool isEnabled) { _isEnabled = isEnabled; }
|
|
||||||
|
|
||||||
virtual const Varying getInput() const { return Varying(); }
|
|
||||||
virtual const Varying getOutput() const { return Varying(); }
|
|
||||||
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Job(Concept* concept) : _concept(concept) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <class T> class Model : public Concept {
|
|
||||||
public:
|
|
||||||
typedef T Data;
|
|
||||||
|
|
||||||
Data _data;
|
|
||||||
|
|
||||||
Model() {}
|
|
||||||
Model(const std::string& name): Concept(name) {}
|
|
||||||
Model(Data data): _data(data) {}
|
|
||||||
Model(const std::string& name, Data data): Concept(name), _data(data) {}
|
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
if (isEnabled()) {
|
|
||||||
jobRun(_data, sceneContext, renderContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class I> class ModelI : public Concept {
|
|
||||||
public:
|
|
||||||
typedef T Data;
|
|
||||||
typedef I Input;
|
|
||||||
|
|
||||||
Data _data;
|
|
||||||
Varying _input;
|
|
||||||
|
|
||||||
const Varying getInput() const { return _input; }
|
|
||||||
|
|
||||||
ModelI(const std::string& name, const Varying& input, Data data = Data()) : Concept(name), _data(data), _input(input) {}
|
|
||||||
ModelI(const std::string& name, Data data): Concept(name), _data(data) {}
|
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
if (isEnabled()) {
|
|
||||||
jobRunI(_data, sceneContext, renderContext, _input.get<I>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class O> class ModelO : public Concept {
|
|
||||||
public:
|
|
||||||
typedef T Data;
|
|
||||||
typedef O Output;
|
|
||||||
|
|
||||||
Data _data;
|
|
||||||
Varying _output;
|
|
||||||
|
|
||||||
const Varying getOutput() const { return _output; }
|
|
||||||
|
|
||||||
ModelO(const std::string& name): Concept(name), _output(Output()) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelO(const std::string& name, Data data): Concept(name), _data(data), _output(Output()) {}
|
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
if (isEnabled()) {
|
|
||||||
jobRunO(_data, sceneContext, renderContext, _output.edit<O>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class I, class O> class ModelIO : public Concept {
|
|
||||||
public:
|
|
||||||
typedef T Data;
|
|
||||||
typedef I Input;
|
|
||||||
typedef O Output;
|
|
||||||
|
|
||||||
Data _data;
|
|
||||||
Varying _input;
|
|
||||||
Varying _output;
|
|
||||||
|
|
||||||
const Varying getInput() const { return _input; }
|
|
||||||
const Varying getOutput() const { return _output; }
|
|
||||||
|
|
||||||
ModelIO(const std::string& name, const Varying& input, Data data = Data()): Concept(name), _data(data), _input(input), _output(Output()) {}
|
|
||||||
ModelIO(const std::string& name, Data data, Output output): Concept(name), _data(data), _output(output) {}
|
|
||||||
|
|
||||||
void setInput(const Varying& input) { _input = input; }
|
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
|
||||||
if (isEnabled()) {
|
|
||||||
jobRunIO(_data, sceneContext, renderContext, _input.get<I>(), _output.edit<O>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<Concept> _concept;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::vector<Job> Jobs;
|
|
||||||
|
|
||||||
void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
||||||
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
||||||
void renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
void renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
||||||
|
@ -236,7 +36,7 @@ public:
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems);
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems);
|
||||||
|
|
||||||
typedef Job::ModelO<FetchItems, ItemIDsBounds> JobModel;
|
using JobModel = Task::Job::ModelO<FetchItems, ItemIDsBounds>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<RenderDetails::Type T = RenderDetails::Type::OTHER_ITEM>
|
template<RenderDetails::Type T = RenderDetails::Type::OTHER_ITEM>
|
||||||
|
@ -248,7 +48,8 @@ public:
|
||||||
renderContext->getArgs()->_details.pointTo(T);
|
renderContext->getArgs()->_details.pointTo(T);
|
||||||
render::cullItems(sceneContext, renderContext, inItems, outItems);
|
render::cullItems(sceneContext, renderContext, inItems, outItems);
|
||||||
}
|
}
|
||||||
typedef Job::ModelIO<CullItems, ItemIDsBounds, ItemIDsBounds> JobModel;
|
|
||||||
|
using JobModel = Task::Job::ModelIO<CullItems<T>, ItemIDsBounds, ItemIDsBounds>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DepthSortItems {
|
class DepthSortItems {
|
||||||
|
@ -259,43 +60,16 @@ public:
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
||||||
|
|
||||||
typedef Job::ModelIO<DepthSortItems, ItemIDsBounds, ItemIDsBounds> JobModel;
|
using JobModel = Task::Job::ModelIO<DepthSortItems, ItemIDsBounds, ItemIDsBounds>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrawLight {
|
class DrawLight {
|
||||||
public:
|
public:
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||||
|
|
||||||
typedef Job::Model<DrawLight> JobModel;
|
using JobModel = Task::Job::Model<DrawLight>;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrawSceneTask : public Task {
|
|
||||||
public:
|
|
||||||
|
|
||||||
DrawSceneTask();
|
|
||||||
~DrawSceneTask();
|
|
||||||
|
|
||||||
Jobs _jobs;
|
|
||||||
|
|
||||||
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// A map of ItemIDs allowing to create bucket lists of SHAPE type items which are filtered by their
|
|
||||||
// Material
|
|
||||||
class ItemMaterialBucketMap : public std::map<model::MaterialFilter, ItemIDs, model::MaterialFilter::Less> {
|
|
||||||
public:
|
|
||||||
|
|
||||||
ItemMaterialBucketMap() {}
|
|
||||||
|
|
||||||
void insert(const ItemID& id, const model::MaterialKey& key);
|
|
||||||
|
|
||||||
// standard builders allocating the main buckets
|
|
||||||
void allocateStandardMaterialBuckets();
|
|
||||||
};
|
|
||||||
void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_render_Task_h
|
#endif // hifi_render_DrawTask_h
|
||||||
|
|
|
@ -8,26 +8,11 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Engine.h"
|
#include "Engine.h"
|
||||||
|
|
||||||
#include "DrawTask.h"
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
RenderContext::RenderContext(ItemsConfig items, Tone tone, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode)
|
|
||||||
: _deferredDebugMode{ deferredDebugMode }, _deferredDebugSize{ deferredDebugSize },
|
|
||||||
_args{ nullptr },
|
|
||||||
_drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect },
|
|
||||||
_items{ items }, _tone{ tone } {}
|
|
||||||
|
|
||||||
void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned) {
|
|
||||||
_occlusionStatus = occlusion;
|
|
||||||
_fxaaStatus = fxaa;
|
|
||||||
|
|
||||||
if (showOwned) {
|
|
||||||
_drawStatus |= render::showNetworkStatusFlag;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Engine::Engine() :
|
Engine::Engine() :
|
||||||
_sceneContext(std::make_shared<SceneContext>()),
|
_sceneContext(std::make_shared<SceneContext>()),
|
||||||
_renderContext(std::make_shared<RenderContext>())
|
_renderContext(std::make_shared<RenderContext>())
|
||||||
|
@ -49,16 +34,8 @@ void Engine::addTask(const TaskPointer& task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::run() {
|
void Engine::run() {
|
||||||
|
// TODO: Tasks will need to be specified such that their data can feed into each other
|
||||||
for (auto task : _tasks) {
|
for (auto task : _tasks) {
|
||||||
task->run(_sceneContext, _renderContext);
|
task->run(_sceneContext, _renderContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::buildStandardTaskPipeline() {
|
|
||||||
if (!_tasks.empty()) {
|
|
||||||
_tasks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
addTask(std::make_shared<DrawSceneTask>());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -12,115 +12,11 @@
|
||||||
#ifndef hifi_render_Engine_h
|
#ifndef hifi_render_Engine_h
|
||||||
#define hifi_render_Engine_h
|
#define hifi_render_Engine_h
|
||||||
|
|
||||||
#include "Scene.h"
|
#include "Context.h"
|
||||||
|
#include "Task.h"
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
|
|
||||||
class SceneContext {
|
|
||||||
public:
|
|
||||||
ScenePointer _scene;
|
|
||||||
|
|
||||||
SceneContext() {}
|
|
||||||
};
|
|
||||||
using SceneContextPointer = std::shared_ptr<SceneContext>;
|
|
||||||
|
|
||||||
// see examples/utilities/tools/renderEngineDebug.js
|
|
||||||
const int showDisplayStatusFlag = 1;
|
|
||||||
const int showNetworkStatusFlag = 2;
|
|
||||||
|
|
||||||
|
|
||||||
class RenderContext {
|
|
||||||
public:
|
|
||||||
class ItemsConfig {
|
|
||||||
public:
|
|
||||||
class Counter {
|
|
||||||
public:
|
|
||||||
Counter() {};
|
|
||||||
Counter(const Counter& counter) {
|
|
||||||
numFeed = numDrawn = 0;
|
|
||||||
maxDrawn = counter.maxDrawn;
|
|
||||||
};
|
|
||||||
|
|
||||||
void setCounts(const Counter& counter) {
|
|
||||||
numFeed = counter.numFeed;
|
|
||||||
numDrawn = counter.numDrawn;
|
|
||||||
};
|
|
||||||
|
|
||||||
int numFeed = 0;
|
|
||||||
int numDrawn = 0;
|
|
||||||
int maxDrawn = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
class State : public Counter {
|
|
||||||
public:
|
|
||||||
bool render = true;
|
|
||||||
bool cull = true;
|
|
||||||
bool sort = true;
|
|
||||||
|
|
||||||
Counter counter{};
|
|
||||||
};
|
|
||||||
|
|
||||||
ItemsConfig(State opaqueState, State transparentState, Counter overlay3DCounter)
|
|
||||||
: opaque{ opaqueState }, transparent{ transparentState }, overlay3D{ overlay3DCounter } {}
|
|
||||||
ItemsConfig() : ItemsConfig{ {}, {}, {} } {}
|
|
||||||
|
|
||||||
// TODO: If member count increases, store counters in a map instead of multiple members
|
|
||||||
State opaque{};
|
|
||||||
State transparent{};
|
|
||||||
Counter overlay3D{};
|
|
||||||
};
|
|
||||||
|
|
||||||
class Tone {
|
|
||||||
public:
|
|
||||||
int toneCurve = 1; // Means just Gamma 2.2 correction
|
|
||||||
float exposure = 0.0;
|
|
||||||
};
|
|
||||||
|
|
||||||
RenderContext(ItemsConfig items, Tone tone, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode);
|
|
||||||
RenderContext() : RenderContext({}, {}, {}, {}, {}, {}) {};
|
|
||||||
|
|
||||||
void setArgs(RenderArgs* args) { _args = args; }
|
|
||||||
inline RenderArgs* getArgs() { return _args; }
|
|
||||||
inline ItemsConfig& getItemsConfig() { return _items; }
|
|
||||||
inline Tone& getTone() { return _tone; }
|
|
||||||
inline int getDrawStatus() { return _drawStatus; }
|
|
||||||
inline bool getDrawHitEffect() { return _drawHitEffect; }
|
|
||||||
inline bool getOcclusionStatus() { return _occlusionStatus; }
|
|
||||||
inline bool getFxaaStatus() { return _fxaaStatus; }
|
|
||||||
void setOptions(bool occlusion, bool fxaa, bool showOwned);
|
|
||||||
|
|
||||||
// Debugging
|
|
||||||
int _deferredDebugMode;
|
|
||||||
glm::vec4 _deferredDebugSize;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
RenderArgs* _args;
|
|
||||||
|
|
||||||
// Options
|
|
||||||
int _drawStatus; // bitflag
|
|
||||||
bool _drawHitEffect;
|
|
||||||
bool _occlusionStatus = false;
|
|
||||||
bool _fxaaStatus = false;
|
|
||||||
|
|
||||||
ItemsConfig _items;
|
|
||||||
Tone _tone;
|
|
||||||
};
|
|
||||||
typedef std::shared_ptr<RenderContext> RenderContextPointer;
|
|
||||||
|
|
||||||
// The base class for a task that runs on the SceneContext
|
|
||||||
class Task {
|
|
||||||
public:
|
|
||||||
Task() {}
|
|
||||||
~Task() {}
|
|
||||||
|
|
||||||
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
};
|
|
||||||
typedef std::shared_ptr<Task> TaskPointer;
|
|
||||||
typedef std::vector<TaskPointer> Tasks;
|
|
||||||
|
|
||||||
// The root of the tasks, the Engine, should not be known from the Tasks,
|
// The root of the tasks, the Engine, should not be known from the Tasks,
|
||||||
// The SceneContext is what navigates from the engine down to the Tasks
|
// The SceneContext is what navigates from the engine down to the Tasks
|
||||||
class Engine {
|
class Engine {
|
||||||
|
@ -142,11 +38,7 @@ public:
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
// standard pipeline of tasks
|
|
||||||
void buildStandardTaskPipeline();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Tasks _tasks;
|
Tasks _tasks;
|
||||||
|
|
||||||
SceneContextPointer _sceneContext;
|
SceneContextPointer _sceneContext;
|
||||||
|
@ -157,3 +49,4 @@ typedef std::shared_ptr<Engine> EnginePointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_render_Engine_h
|
#endif // hifi_render_Engine_h
|
||||||
|
|
||||||
|
|
227
libraries/render/src/render/Task.h
Normal file
227
libraries/render/src/render/Task.h
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
//
|
||||||
|
// Task.h
|
||||||
|
// render/src/render
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 1/6/2015.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_render_Task_h
|
||||||
|
#define hifi_render_Task_h
|
||||||
|
|
||||||
|
#include "Context.h"
|
||||||
|
|
||||||
|
#include "gpu/Batch.h"
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
|
||||||
|
// A varying piece of data, to be used as Job/Task I/O
|
||||||
|
// TODO: Task IO
|
||||||
|
class Varying {
|
||||||
|
public:
|
||||||
|
Varying() {}
|
||||||
|
Varying(const Varying& var) : _concept(var._concept) {}
|
||||||
|
template <class T> Varying(const T& data) : _concept(std::make_shared<Model<T>>(data)) {}
|
||||||
|
|
||||||
|
template <class T> T& edit() { return std::static_pointer_cast<Model<T>>(_concept)->_data; }
|
||||||
|
template <class T> const T& get() { return std::static_pointer_cast<const Model<T>>(_concept)->_data; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class Concept {
|
||||||
|
public:
|
||||||
|
virtual ~Concept() = default;
|
||||||
|
};
|
||||||
|
template <class T> class Model : public Concept {
|
||||||
|
public:
|
||||||
|
using Data = T;
|
||||||
|
|
||||||
|
Model(const Data& data) : _data(data) {}
|
||||||
|
virtual ~Model() = default;
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Concept> _concept;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: In c++17, use default classes of nullptr_t to combine these
|
||||||
|
template <class T> void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
jobModel.run(sceneContext, renderContext);
|
||||||
|
}
|
||||||
|
template <class T, class I> void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) {
|
||||||
|
jobModel.run(sceneContext, renderContext, input);
|
||||||
|
}
|
||||||
|
template <class T, class O> void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) {
|
||||||
|
jobModel.run(sceneContext, renderContext, output);
|
||||||
|
}
|
||||||
|
template <class T, class I, class O> void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) {
|
||||||
|
jobModel.run(sceneContext, renderContext, input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The base class for a task that runs on the SceneContext
|
||||||
|
class Task {
|
||||||
|
public:
|
||||||
|
// The guts of a task; tasks are composed of multiple Jobs that execute serially
|
||||||
|
class Job {
|
||||||
|
public:
|
||||||
|
friend class Task;
|
||||||
|
|
||||||
|
// The guts of a job; jobs are composed of a concept
|
||||||
|
class Concept {
|
||||||
|
public:
|
||||||
|
Concept() = default;
|
||||||
|
virtual ~Concept() = default;
|
||||||
|
|
||||||
|
bool isEnabled() const { return _isEnabled; }
|
||||||
|
void setEnabled(bool isEnabled) { _isEnabled = isEnabled; }
|
||||||
|
|
||||||
|
virtual const Varying getInput() const { return Varying(); }
|
||||||
|
virtual const Varying getOutput() const { return Varying(); }
|
||||||
|
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool _isEnabled = true;
|
||||||
|
};
|
||||||
|
using ConceptPointer = std::shared_ptr<Concept>;
|
||||||
|
|
||||||
|
|
||||||
|
template <class T> class Model : public Concept {
|
||||||
|
public:
|
||||||
|
typedef T Data;
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
|
||||||
|
Model() {}
|
||||||
|
Model(Data data): _data(data) {}
|
||||||
|
|
||||||
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
jobRun(_data, sceneContext, renderContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class I> class ModelI : public Concept {
|
||||||
|
public:
|
||||||
|
typedef T Data;
|
||||||
|
typedef I Input;
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
Varying _input;
|
||||||
|
|
||||||
|
const Varying getInput() const { return _input; }
|
||||||
|
|
||||||
|
ModelI(const Varying& input, Data data = Data()) : _data(data), _input(input) {}
|
||||||
|
ModelI(Data data) : _data(data) {}
|
||||||
|
|
||||||
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
jobRunI(_data, sceneContext, renderContext, _input.get<I>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class O> class ModelO : public Concept {
|
||||||
|
public:
|
||||||
|
typedef T Data;
|
||||||
|
typedef O Output;
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
Varying _output;
|
||||||
|
|
||||||
|
const Varying getOutput() const { return _output; }
|
||||||
|
|
||||||
|
ModelO(Data data) : _data(data), _output(Output()) {}
|
||||||
|
ModelO() : _output(Output()) {}
|
||||||
|
|
||||||
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
jobRunO(_data, sceneContext, renderContext, _output.edit<O>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class I, class O> class ModelIO : public Concept {
|
||||||
|
public:
|
||||||
|
typedef T Data;
|
||||||
|
typedef I Input;
|
||||||
|
typedef O Output;
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
Varying _input;
|
||||||
|
Varying _output;
|
||||||
|
|
||||||
|
const Varying getInput() const { return _input; }
|
||||||
|
const Varying getOutput() const { return _output; }
|
||||||
|
|
||||||
|
ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()) {}
|
||||||
|
ModelIO(Data data) : _data(data), _output(Output()) {}
|
||||||
|
|
||||||
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
jobRunIO(_data, sceneContext, renderContext, _input.get<I>(), _output.edit<O>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Job(ConceptPointer concept) : _concept(concept) {}
|
||||||
|
Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {}
|
||||||
|
|
||||||
|
bool isEnabled() const { return _concept->isEnabled(); }
|
||||||
|
void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); }
|
||||||
|
|
||||||
|
const Varying getInput() const { return _concept->getInput(); }
|
||||||
|
const Varying getOutput() const { return _concept->getOutput(); }
|
||||||
|
|
||||||
|
template <class T> T& edit() {
|
||||||
|
auto concept = std::static_pointer_cast<typename T::JobModel>(_concept);
|
||||||
|
assert(concept);
|
||||||
|
return concept->_data;
|
||||||
|
}
|
||||||
|
template <class T> const T& get() const {
|
||||||
|
auto concept = std::static_pointer_cast<typename T::JobModel>(_concept);
|
||||||
|
assert(concept);
|
||||||
|
return concept->_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
PerformanceTimer perfTimer(_name.c_str());
|
||||||
|
PROFILE_RANGE(_name.c_str());
|
||||||
|
|
||||||
|
_concept->run(sceneContext, renderContext);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
ConceptPointer _concept;
|
||||||
|
std::string _name = "";
|
||||||
|
|
||||||
|
};
|
||||||
|
using Jobs = std::vector<Job>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Task() = default;
|
||||||
|
virtual ~Task() = default;
|
||||||
|
|
||||||
|
// Queue a new job to the task; returns the job's index
|
||||||
|
template <class T, class... A> size_t addJob(std::string name, A&&... args) {
|
||||||
|
_jobs.emplace_back(name, std::make_shared<typename T::JobModel>(std::forward<A>(args)...));
|
||||||
|
return _jobs.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Job& getJob(size_t i) const { return _jobs.at(i); }
|
||||||
|
|
||||||
|
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Jobs _jobs;
|
||||||
|
};
|
||||||
|
typedef std::shared_ptr<Task> TaskPointer;
|
||||||
|
typedef std::vector<TaskPointer> Tasks;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // hifi_render_Task_h
|
|
@ -46,11 +46,13 @@
|
||||||
#include "TypedArrays.h"
|
#include "TypedArrays.h"
|
||||||
#include "XMLHttpRequestClass.h"
|
#include "XMLHttpRequestClass.h"
|
||||||
#include "WebSocketClass.h"
|
#include "WebSocketClass.h"
|
||||||
|
|
||||||
#include "RecordingScriptingInterface.h"
|
#include "RecordingScriptingInterface.h"
|
||||||
|
#include "ScriptEngines.h"
|
||||||
|
|
||||||
#include "MIDIEvent.h"
|
#include "MIDIEvent.h"
|
||||||
|
|
||||||
|
std::atomic<bool> ScriptEngine::_stoppingAllScripts { false };
|
||||||
|
|
||||||
static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3";
|
static const QString SCRIPT_EXCEPTION_FORMAT = "[UncaughtException] %1 in %2:%3";
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature)
|
Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature)
|
||||||
|
@ -132,9 +134,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
||||||
_fileNameString(fileNameString),
|
_fileNameString(fileNameString),
|
||||||
_arrayBufferClass(new ArrayBufferClass(this))
|
_arrayBufferClass(new ArrayBufferClass(this))
|
||||||
{
|
{
|
||||||
_allScriptsMutex.lock();
|
DependencyManager::get<ScriptEngines>()->addScriptEngine(this);
|
||||||
_allKnownScriptEngines.insert(this);
|
|
||||||
_allScriptsMutex.unlock();
|
|
||||||
|
|
||||||
connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) {
|
connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) {
|
||||||
hadUncaughtExceptions(*this, _fileNameString);
|
hadUncaughtExceptions(*this, _fileNameString);
|
||||||
|
@ -144,14 +144,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
||||||
ScriptEngine::~ScriptEngine() {
|
ScriptEngine::~ScriptEngine() {
|
||||||
qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename();
|
qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename();
|
||||||
|
|
||||||
// If we're not already in the middle of stopping all scripts, then we should remove ourselves
|
DependencyManager::get<ScriptEngines>()->removeScriptEngine(this);
|
||||||
// from the list of running scripts. We don't do this if we're in the process of stopping all scripts
|
|
||||||
// because that method removes scripts from its list as it iterates them
|
|
||||||
if (!_stoppingAllScripts) {
|
|
||||||
_allScriptsMutex.lock();
|
|
||||||
_allKnownScriptEngines.remove(this);
|
|
||||||
_allScriptsMutex.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::disconnectNonEssentialSignals() {
|
void ScriptEngine::disconnectNonEssentialSignals() {
|
||||||
|
@ -187,67 +180,6 @@ void ScriptEngine::runInThread() {
|
||||||
workerThread->start();
|
workerThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<ScriptEngine*> ScriptEngine::_allKnownScriptEngines;
|
|
||||||
QMutex ScriptEngine::_allScriptsMutex;
|
|
||||||
std::atomic<bool> ScriptEngine::_stoppingAllScripts { false };
|
|
||||||
|
|
||||||
void ScriptEngine::stopAllScripts(QObject* application) {
|
|
||||||
_allScriptsMutex.lock();
|
|
||||||
_stoppingAllScripts = true;
|
|
||||||
|
|
||||||
qCDebug(scriptengine) << "Stopping all scripts.... currently known scripts:" << _allKnownScriptEngines.size();
|
|
||||||
|
|
||||||
QMutableSetIterator<ScriptEngine*> i(_allKnownScriptEngines);
|
|
||||||
while (i.hasNext()) {
|
|
||||||
ScriptEngine* scriptEngine = i.next();
|
|
||||||
|
|
||||||
QString scriptName = scriptEngine->getFilename();
|
|
||||||
|
|
||||||
// NOTE: typically all script engines are running. But there's at least one known exception to this, the
|
|
||||||
// "entities sandbox" which is only used to evaluate entities scripts to test their validity before using
|
|
||||||
// them. We don't need to stop scripts that aren't running.
|
|
||||||
if (scriptEngine->isRunning()) {
|
|
||||||
|
|
||||||
// If the script is running, but still evaluating then we need to wait for its evaluation step to
|
|
||||||
// complete. After that we can handle the stop process appropriately
|
|
||||||
if (scriptEngine->evaluatePending()) {
|
|
||||||
while (scriptEngine->evaluatePending()) {
|
|
||||||
|
|
||||||
// This event loop allows any started, but not yet finished evaluate() calls to complete
|
|
||||||
// we need to let these complete so that we can be guaranteed that the script engine isn't
|
|
||||||
// in a partially setup state, which can confuse our shutdown unwinding.
|
|
||||||
QEventLoop loop;
|
|
||||||
QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit);
|
|
||||||
loop.exec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We disconnect any script engine signals from the application because we don't want to do any
|
|
||||||
// extra stopScript/loadScript processing that the Application normally does when scripts start
|
|
||||||
// and stop. We can safely short circuit this because we know we're in the "quitting" process
|
|
||||||
scriptEngine->disconnect(application);
|
|
||||||
|
|
||||||
// Calling stop on the script engine will set it's internal _isFinished state to true, and result
|
|
||||||
// in the ScriptEngine gracefully ending it's run() method.
|
|
||||||
scriptEngine->stop();
|
|
||||||
|
|
||||||
// We need to wait for the engine to be done running before we proceed, because we don't
|
|
||||||
// want any of the scripts final "scriptEnding()" or pending "update()" methods from accessing
|
|
||||||
// any application state after we leave this stopAllScripts() method
|
|
||||||
qCDebug(scriptengine) << "waiting on script:" << scriptName;
|
|
||||||
scriptEngine->waitTillDoneRunning();
|
|
||||||
qCDebug(scriptengine) << "done waiting on script:" << scriptName;
|
|
||||||
|
|
||||||
// If the script is stopped, we can remove it from our set
|
|
||||||
i.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_stoppingAllScripts = false;
|
|
||||||
_allScriptsMutex.unlock();
|
|
||||||
qCDebug(scriptengine) << "DONE Stopping all scripts....";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ScriptEngine::waitTillDoneRunning() {
|
void ScriptEngine::waitTillDoneRunning() {
|
||||||
// If the script never started running or finished running before we got here, we don't need to wait for it
|
// If the script never started running or finished running before we got here, we don't need to wait for it
|
||||||
if (_isRunning && _isThreaded) {
|
if (_isRunning && _isThreaded) {
|
||||||
|
|
|
@ -129,7 +129,6 @@ public:
|
||||||
bool isRunning() const { return _isRunning; } // used by ScriptWidget
|
bool isRunning() const { return _isRunning; } // used by ScriptWidget
|
||||||
|
|
||||||
void disconnectNonEssentialSignals();
|
void disconnectNonEssentialSignals();
|
||||||
static void stopAllScripts(QObject* application); // used by Application on shutdown
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// NOTE - These are the callback implementations for ScriptUser the get called by ScriptCache when the contents
|
// NOTE - These are the callback implementations for ScriptUser the get called by ScriptCache when the contents
|
||||||
|
@ -204,8 +203,7 @@ protected:
|
||||||
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs);
|
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs);
|
||||||
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success);
|
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success);
|
||||||
|
|
||||||
static QSet<ScriptEngine*> _allKnownScriptEngines;
|
friend class ScriptEngines;
|
||||||
static QMutex _allScriptsMutex;
|
|
||||||
static std::atomic<bool> _stoppingAllScripts;
|
static std::atomic<bool> _stoppingAllScripts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
435
libraries/script-engine/src/ScriptEngines.cpp
Normal file
435
libraries/script-engine/src/ScriptEngines.cpp
Normal file
|
@ -0,0 +1,435 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/01/08
|
||||||
|
// Copyright 2013-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
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ScriptEngines.h"
|
||||||
|
|
||||||
|
#include <QtCore/QStandardPaths>
|
||||||
|
#include <QtCore/QCoreApplication>
|
||||||
|
|
||||||
|
#include <SettingHandle.h>
|
||||||
|
#include <UserActivityLogger.h>
|
||||||
|
|
||||||
|
#include "ScriptEngine.h"
|
||||||
|
#include "ScriptEngineLogging.h"
|
||||||
|
|
||||||
|
#define __STR2__(x) #x
|
||||||
|
#define __STR1__(x) __STR2__(x)
|
||||||
|
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
|
#else
|
||||||
|
// Temporary fix to Qt bug: http://stackoverflow.com/questions/16194475
|
||||||
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/script.js");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ScriptsModel& getScriptsModel() {
|
||||||
|
static ScriptsModel scriptsModel;
|
||||||
|
return scriptsModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptEngines::ScriptEngines()
|
||||||
|
: _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION),
|
||||||
|
_previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION)
|
||||||
|
{
|
||||||
|
_scriptsModelFilter.setSourceModel(&_scriptsModel);
|
||||||
|
_scriptsModelFilter.sort(0, Qt::AscendingOrder);
|
||||||
|
_scriptsModelFilter.setDynamicSortFilter(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QObject* scriptsModel();
|
||||||
|
|
||||||
|
void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) {
|
||||||
|
_scriptInitializers.push_back(initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::addScriptEngine(ScriptEngine* engine) {
|
||||||
|
_allScriptsMutex.lock();
|
||||||
|
_allKnownScriptEngines.insert(engine);
|
||||||
|
_allScriptsMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::removeScriptEngine(ScriptEngine* engine) {
|
||||||
|
// If we're not already in the middle of stopping all scripts, then we should remove ourselves
|
||||||
|
// from the list of running scripts. We don't do this if we're in the process of stopping all scripts
|
||||||
|
// because that method removes scripts from its list as it iterates them
|
||||||
|
if (!_stoppingAllScripts) {
|
||||||
|
_allScriptsMutex.lock();
|
||||||
|
_allKnownScriptEngines.remove(engine);
|
||||||
|
_allScriptsMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::shutdownScripting() {
|
||||||
|
_allScriptsMutex.lock();
|
||||||
|
_stoppingAllScripts = true;
|
||||||
|
ScriptEngine::_stoppingAllScripts = true;
|
||||||
|
qCDebug(scriptengine) << "Stopping all scripts.... currently known scripts:" << _allKnownScriptEngines.size();
|
||||||
|
|
||||||
|
QMutableSetIterator<ScriptEngine*> i(_allKnownScriptEngines);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
ScriptEngine* scriptEngine = i.next();
|
||||||
|
QString scriptName = scriptEngine->getFilename();
|
||||||
|
|
||||||
|
// NOTE: typically all script engines are running. But there's at least one known exception to this, the
|
||||||
|
// "entities sandbox" which is only used to evaluate entities scripts to test their validity before using
|
||||||
|
// them. We don't need to stop scripts that aren't running.
|
||||||
|
if (scriptEngine->isRunning()) {
|
||||||
|
|
||||||
|
// If the script is running, but still evaluating then we need to wait for its evaluation step to
|
||||||
|
// complete. After that we can handle the stop process appropriately
|
||||||
|
if (scriptEngine->evaluatePending()) {
|
||||||
|
while (scriptEngine->evaluatePending()) {
|
||||||
|
|
||||||
|
// This event loop allows any started, but not yet finished evaluate() calls to complete
|
||||||
|
// we need to let these complete so that we can be guaranteed that the script engine isn't
|
||||||
|
// in a partially setup state, which can confuse our shutdown unwinding.
|
||||||
|
QEventLoop loop;
|
||||||
|
QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit);
|
||||||
|
loop.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We disconnect any script engine signals from the application because we don't want to do any
|
||||||
|
// extra stopScript/loadScript processing that the Application normally does when scripts start
|
||||||
|
// and stop. We can safely short circuit this because we know we're in the "quitting" process
|
||||||
|
scriptEngine->disconnect(this);
|
||||||
|
|
||||||
|
// Calling stop on the script engine will set it's internal _isFinished state to true, and result
|
||||||
|
// in the ScriptEngine gracefully ending it's run() method.
|
||||||
|
scriptEngine->stop();
|
||||||
|
|
||||||
|
// We need to wait for the engine to be done running before we proceed, because we don't
|
||||||
|
// want any of the scripts final "scriptEnding()" or pending "update()" methods from accessing
|
||||||
|
// any application state after we leave this stopAllScripts() method
|
||||||
|
qCDebug(scriptengine) << "waiting on script:" << scriptName;
|
||||||
|
scriptEngine->waitTillDoneRunning();
|
||||||
|
qCDebug(scriptengine) << "done waiting on script:" << scriptName;
|
||||||
|
|
||||||
|
// If the script is stopped, we can remove it from our set
|
||||||
|
i.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_stoppingAllScripts = false;
|
||||||
|
_allScriptsMutex.unlock();
|
||||||
|
qCDebug(scriptengine) << "DONE Stopping all scripts....";
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList getPublicChildNodes(TreeNodeFolder* parent) {
|
||||||
|
QVariantList result;
|
||||||
|
QList<TreeNodeBase*> treeNodes = getScriptsModel().getFolderNodes(parent);
|
||||||
|
for (int i = 0; i < treeNodes.size(); i++) {
|
||||||
|
TreeNodeBase* node = treeNodes.at(i);
|
||||||
|
if (node->getType() == TREE_NODE_TYPE_FOLDER) {
|
||||||
|
TreeNodeFolder* folder = static_cast<TreeNodeFolder*>(node);
|
||||||
|
QVariantMap resultNode;
|
||||||
|
resultNode.insert("name", node->getName());
|
||||||
|
resultNode.insert("type", "folder");
|
||||||
|
resultNode.insert("children", getPublicChildNodes(folder));
|
||||||
|
result.append(resultNode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TreeNodeScript* script = static_cast<TreeNodeScript*>(node);
|
||||||
|
if (script->getOrigin() == ScriptOrigin::SCRIPT_ORIGIN_LOCAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QVariantMap resultNode;
|
||||||
|
resultNode.insert("name", node->getName());
|
||||||
|
resultNode.insert("type", "script");
|
||||||
|
resultNode.insert("url", script->getFullPath());
|
||||||
|
result.append(resultNode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList ScriptEngines::getPublic() {
|
||||||
|
return getPublicChildNodes(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList ScriptEngines::getLocal() {
|
||||||
|
QVariantList result;
|
||||||
|
QList<TreeNodeBase*> treeNodes = getScriptsModel().getFolderNodes(NULL);
|
||||||
|
for (int i = 0; i < treeNodes.size(); i++) {
|
||||||
|
TreeNodeBase* node = treeNodes.at(i);
|
||||||
|
if (node->getType() != TREE_NODE_TYPE_SCRIPT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TreeNodeScript* script = static_cast<TreeNodeScript*>(node);
|
||||||
|
if (script->getOrigin() != ScriptOrigin::SCRIPT_ORIGIN_LOCAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QVariantMap resultNode;
|
||||||
|
resultNode.insert("name", node->getName());
|
||||||
|
resultNode.insert("path", script->getFullPath());
|
||||||
|
result.append(resultNode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList ScriptEngines::getRunning() {
|
||||||
|
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
||||||
|
QVariantList result;
|
||||||
|
auto runningScripts = getRunningScripts();
|
||||||
|
foreach(const QString& runningScript, runningScripts) {
|
||||||
|
QUrl runningScriptURL = QUrl(runningScript);
|
||||||
|
if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
||||||
|
runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
||||||
|
}
|
||||||
|
QVariantMap resultNode;
|
||||||
|
resultNode.insert("name", runningScriptURL.fileName());
|
||||||
|
resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
||||||
|
// The path contains the exact path/URL of the script, which also is used in the stopScript function.
|
||||||
|
resultNode.insert("path", runningScript);
|
||||||
|
resultNode.insert("local", runningScriptURL.isLocalFile());
|
||||||
|
result.append(resultNode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const QString SETTINGS_KEY = "Settings";
|
||||||
|
static const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
|
||||||
|
|
||||||
|
void ScriptEngines::loadDefaultScripts() {
|
||||||
|
loadScript(DEFAULT_SCRIPTS_JS_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::loadOneScript(const QString& scriptFilename) {
|
||||||
|
loadScript(scriptFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::loadScripts() {
|
||||||
|
// check first run...
|
||||||
|
if (_firstRun.get()) {
|
||||||
|
qCDebug(scriptengine) << "This is a first run...";
|
||||||
|
// clear the scripts, and set out script to our default scripts
|
||||||
|
clearScripts();
|
||||||
|
loadDefaultScripts();
|
||||||
|
_firstRun.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads all saved scripts
|
||||||
|
Settings settings;
|
||||||
|
int size = settings.beginReadArray(SETTINGS_KEY);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
QString string = settings.value("script").toString();
|
||||||
|
if (!string.isEmpty()) {
|
||||||
|
loadScript(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::clearScripts() {
|
||||||
|
// clears all scripts from the settingsSettings settings;
|
||||||
|
Settings settings;
|
||||||
|
settings.beginWriteArray(SETTINGS_KEY);
|
||||||
|
settings.remove("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::saveScripts() {
|
||||||
|
// Saves all currently running user-loaded scripts
|
||||||
|
Settings settings;
|
||||||
|
settings.beginWriteArray(SETTINGS_KEY);
|
||||||
|
settings.remove("");
|
||||||
|
|
||||||
|
QStringList runningScripts = getRunningScripts();
|
||||||
|
int i = 0;
|
||||||
|
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
|
||||||
|
if (getScriptEngine(*it)->isUserLoaded()) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
settings.setValue("script", *it);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ScriptEngines::getRunningScripts() {
|
||||||
|
QReadLocker lock(&_scriptEnginesHashLock);
|
||||||
|
return _scriptEnginesHash.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::stopAllScripts(bool restart) {
|
||||||
|
QReadLocker lock(&_scriptEnginesHashLock);
|
||||||
|
if (restart) {
|
||||||
|
// Delete all running scripts from cache so that they are re-downloaded when they are restarted
|
||||||
|
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||||
|
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
||||||
|
it != _scriptEnginesHash.constEnd(); it++) {
|
||||||
|
if (!it.value()->isFinished()) {
|
||||||
|
scriptCache->deleteScript(it.key());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop and possibly restart all currently running scripts
|
||||||
|
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
||||||
|
it != _scriptEnginesHash.constEnd(); it++) {
|
||||||
|
if (it.value()->isFinished()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (restart && it.value()->isUserLoaded()) {
|
||||||
|
connect(it.value(), &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) {
|
||||||
|
reloadScript(scriptName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
QMetaObject::invokeMethod(it.value(), "stop");
|
||||||
|
//it.value()->stop();
|
||||||
|
qCDebug(scriptengine) << "stopping script..." << it.key();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptEngines::stopScript(const QString& scriptHash, bool restart) {
|
||||||
|
bool stoppedScript = false;
|
||||||
|
{
|
||||||
|
QReadLocker lock(&_scriptEnginesHashLock);
|
||||||
|
if (_scriptEnginesHash.contains(scriptHash)) {
|
||||||
|
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash];
|
||||||
|
if (restart) {
|
||||||
|
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||||
|
scriptCache->deleteScript(QUrl(scriptHash));
|
||||||
|
connect(scriptEngine, &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) {
|
||||||
|
reloadScript(scriptName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
scriptEngine->stop();
|
||||||
|
stoppedScript = true;
|
||||||
|
qCDebug(scriptengine) << "stopping script..." << scriptHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stoppedScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptEngines::getScriptsLocation() const {
|
||||||
|
return _scriptsLocationHandle.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::setScriptsLocation(const QString& scriptsLocation) {
|
||||||
|
_scriptsLocationHandle.set(scriptsLocation);
|
||||||
|
_scriptsModel.updateScriptsLocation(scriptsLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::reloadAllScripts() {
|
||||||
|
DependencyManager::get<ScriptCache>()->clearCache();
|
||||||
|
emit scriptsReloading();
|
||||||
|
stopAllScripts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
|
||||||
|
if (thread() != QThread::currentThread()) {
|
||||||
|
ScriptEngine* result { nullptr };
|
||||||
|
QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result),
|
||||||
|
Q_ARG(QString, scriptFilename),
|
||||||
|
Q_ARG(bool, isUserLoaded),
|
||||||
|
Q_ARG(bool, loadScriptFromEditor),
|
||||||
|
Q_ARG(bool, activateMainWindow),
|
||||||
|
Q_ARG(bool, reload));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
QUrl scriptUrl(scriptFilename);
|
||||||
|
auto scriptEngine = getScriptEngine(scriptUrl.toString());
|
||||||
|
if (scriptEngine) {
|
||||||
|
return scriptEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptEngine = new ScriptEngine(NO_SCRIPT, "", true);
|
||||||
|
scriptEngine->setUserLoaded(isUserLoaded);
|
||||||
|
|
||||||
|
if (scriptFilename.isNull()) {
|
||||||
|
launchScriptEngine(scriptEngine);
|
||||||
|
} else {
|
||||||
|
// connect to the appropriate signals of this script engine
|
||||||
|
connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded);
|
||||||
|
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError);
|
||||||
|
|
||||||
|
// get the script engine object to load the script at the designated script URL
|
||||||
|
scriptEngine->loadURL(scriptUrl, reload);
|
||||||
|
}
|
||||||
|
|
||||||
|
return scriptEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptEngine* ScriptEngines::getScriptEngine(const QString& scriptHash) {
|
||||||
|
ScriptEngine* result = nullptr;
|
||||||
|
{
|
||||||
|
QReadLocker lock(&_scriptEnginesHashLock);
|
||||||
|
auto it = _scriptEnginesHash.find(scriptHash);
|
||||||
|
if (it != _scriptEnginesHash.end()) {
|
||||||
|
result = it.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME - change to new version of ScriptCache loading notification
|
||||||
|
void ScriptEngines::onScriptEngineLoaded(const QString& scriptFilename) {
|
||||||
|
UserActivityLogger::getInstance().loadedScript(scriptFilename);
|
||||||
|
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
|
||||||
|
|
||||||
|
launchScriptEngine(scriptEngine);
|
||||||
|
|
||||||
|
{
|
||||||
|
QWriteLocker lock(&_scriptEnginesHashLock);
|
||||||
|
_scriptEnginesHash.insertMulti(scriptFilename, scriptEngine);
|
||||||
|
}
|
||||||
|
emit scriptCountChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) {
|
||||||
|
connect(scriptEngine, &ScriptEngine::finished, this, &ScriptEngines::onScriptFinished, Qt::DirectConnection);
|
||||||
|
connect(scriptEngine, &ScriptEngine::loadScript, [&](const QString& scriptName, bool userLoaded) {
|
||||||
|
loadScript(scriptName, userLoaded);
|
||||||
|
});
|
||||||
|
connect(scriptEngine, &ScriptEngine::reloadScript, [&](const QString& scriptName, bool userLoaded) {
|
||||||
|
loadScript(scriptName, userLoaded, false, false, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// register our application services and set it off on its own thread
|
||||||
|
for (auto initializer : _scriptInitializers) {
|
||||||
|
initializer(scriptEngine);
|
||||||
|
}
|
||||||
|
scriptEngine->runInThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptEngines::onScriptFinished(const QString& scriptName, ScriptEngine* engine) {
|
||||||
|
bool removed = false;
|
||||||
|
{
|
||||||
|
QWriteLocker lock(&_scriptEnginesHashLock);
|
||||||
|
const QString& scriptURLString = QUrl(scriptName).toString();
|
||||||
|
for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
|
||||||
|
if (it.value() == engine) {
|
||||||
|
_scriptEnginesHash.erase(it);
|
||||||
|
removed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removed) {
|
||||||
|
emit scriptCountChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME - change to new version of ScriptCache loading notification
|
||||||
|
void ScriptEngines::onScriptEngineError(const QString& scriptFilename) {
|
||||||
|
qCDebug(scriptengine) << "Application::loadScript(), script failed to load...";
|
||||||
|
emit scriptLoadError(scriptFilename, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptEngines::getPreviousScriptLocation() const {
|
||||||
|
return _previousScriptLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngines::setPreviousScriptLocation(const QString& previousScriptLocation) {
|
||||||
|
_previousScriptLocation.set(previousScriptLocation);
|
||||||
|
}
|
103
libraries/script-engine/src/ScriptEngines.h
Normal file
103
libraries/script-engine/src/ScriptEngines.h
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/01/08
|
||||||
|
// Copyright 2013-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
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_ScriptEngines_h
|
||||||
|
#define hifi_ScriptEngines_h
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QMutex>
|
||||||
|
#include <QtCore/QReadWriteLock>
|
||||||
|
|
||||||
|
#include <SettingHandle.h>
|
||||||
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
|
#include "ScriptsModel.h"
|
||||||
|
#include "ScriptsModelFilter.h"
|
||||||
|
|
||||||
|
class ScriptEngine;
|
||||||
|
|
||||||
|
class ScriptEngines : public QObject, public Dependency {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(ScriptsModel* scriptsModel READ scriptsModel CONSTANT)
|
||||||
|
Q_PROPERTY(ScriptsModelFilter* scriptsModelFilter READ scriptsModelFilter CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
using ScriptInitializer = std::function<void(ScriptEngine*)>;
|
||||||
|
|
||||||
|
ScriptEngines();
|
||||||
|
void registerScriptInitializer(ScriptInitializer initializer);
|
||||||
|
|
||||||
|
void loadScripts();
|
||||||
|
void saveScripts();
|
||||||
|
void clearScripts();
|
||||||
|
|
||||||
|
QString getScriptsLocation() const;
|
||||||
|
void loadDefaultScripts();
|
||||||
|
void setScriptsLocation(const QString& scriptsLocation);
|
||||||
|
QStringList getRunningScripts();
|
||||||
|
ScriptEngine* getScriptEngine(const QString& scriptHash);
|
||||||
|
|
||||||
|
QString getPreviousScriptLocation() const;
|
||||||
|
void setPreviousScriptLocation(const QString& previousScriptLocation);
|
||||||
|
|
||||||
|
ScriptsModel* scriptsModel() { return &_scriptsModel; };
|
||||||
|
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
|
||||||
|
|
||||||
|
Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
|
||||||
|
Q_INVOKABLE ScriptEngine* loadScript(const QString& scriptFilename = QString(),
|
||||||
|
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
|
||||||
|
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
|
||||||
|
|
||||||
|
Q_INVOKABLE void reloadAllScripts();
|
||||||
|
Q_INVOKABLE void stopAllScripts(bool restart = false);
|
||||||
|
|
||||||
|
Q_INVOKABLE QVariantList getRunning();
|
||||||
|
Q_INVOKABLE QVariantList getPublic();
|
||||||
|
Q_INVOKABLE QVariantList getLocal();
|
||||||
|
|
||||||
|
// Called at shutdown time
|
||||||
|
void shutdownScripting();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void scriptCountChanged();
|
||||||
|
void scriptsReloading();
|
||||||
|
void scriptLoadError(const QString& filename, const QString& error);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void onScriptFinished(const QString& fileNameString, ScriptEngine* engine);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class ScriptEngine;
|
||||||
|
|
||||||
|
void reloadScript(const QString& scriptName) { loadScript(scriptName, true, false, false, true); }
|
||||||
|
void addScriptEngine(ScriptEngine* engine);
|
||||||
|
void removeScriptEngine(ScriptEngine* engine);
|
||||||
|
void onScriptEngineLoaded(const QString& scriptFilename);
|
||||||
|
void onScriptEngineError(const QString& scriptFilename);
|
||||||
|
void launchScriptEngine(ScriptEngine* engine);
|
||||||
|
|
||||||
|
|
||||||
|
Setting::Handle<bool> _firstRun { "firstRun", true };
|
||||||
|
QReadWriteLock _scriptEnginesHashLock;
|
||||||
|
QHash<QString, ScriptEngine*> _scriptEnginesHash;
|
||||||
|
QSet<ScriptEngine*> _allKnownScriptEngines;
|
||||||
|
QMutex _allScriptsMutex;
|
||||||
|
std::atomic<bool> _stoppingAllScripts { false };
|
||||||
|
std::list<ScriptInitializer> _scriptInitializers;
|
||||||
|
mutable Setting::Handle<QString> _scriptsLocationHandle;
|
||||||
|
mutable Setting::Handle<QString> _previousScriptLocation;
|
||||||
|
ScriptsModel _scriptsModel;
|
||||||
|
ScriptsModelFilter _scriptsModelFilter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_ScriptEngine_h
|
|
@ -1,7 +1,4 @@
|
||||||
//
|
//
|
||||||
// ScriptsModel.cpp
|
|
||||||
// interface/src
|
|
||||||
//
|
|
||||||
// Created by Ryan Huffman on 05/12/14.
|
// Created by Ryan Huffman on 05/12/14.
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
|
@ -11,17 +8,21 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "ScriptsModel.h"
|
||||||
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "ScriptEngine.h"
|
||||||
#include "Menu.h"
|
#include "ScriptEngines.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "ScriptEngineLogging.h"
|
||||||
|
#define __STR2__(x) #x
|
||||||
|
#define __STR1__(x) __STR2__(x)
|
||||||
|
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
|
||||||
|
|
||||||
#include "ScriptsModel.h"
|
|
||||||
|
|
||||||
static const QString S3_URL = "http://s3.amazonaws.com/hifi-public";
|
static const QString S3_URL = "http://s3.amazonaws.com/hifi-public";
|
||||||
static const QString PUBLIC_URL = "http://public.highfidelity.io";
|
static const QString PUBLIC_URL = "http://public.highfidelity.io";
|
||||||
|
@ -60,11 +61,8 @@ ScriptsModel::ScriptsModel(QObject* parent) :
|
||||||
_localDirectory.setFilter(QDir::Files | QDir::Readable);
|
_localDirectory.setFilter(QDir::Files | QDir::Readable);
|
||||||
_localDirectory.setNameFilters(QStringList("*.js"));
|
_localDirectory.setNameFilters(QStringList("*.js"));
|
||||||
|
|
||||||
updateScriptsLocation(qApp->getScriptsLocation());
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
|
|
||||||
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
|
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
|
||||||
connect(qApp, &Application::scriptLocationChanged, this, &ScriptsModel::updateScriptsLocation);
|
|
||||||
|
|
||||||
reloadLocalFiles();
|
reloadLocalFiles();
|
||||||
reloadRemoteFiles();
|
reloadRemoteFiles();
|
||||||
}
|
}
|
||||||
|
@ -182,7 +180,7 @@ void ScriptsModel::downloadFinished() {
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
finished = parseXML(data);
|
finished = parseXML(data);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "Error: Received no data when loading remote scripts";
|
qCDebug(scriptengine) << "Error: Received no data when loading remote scripts";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +229,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
if (xml.hasError()) {
|
if (xml.hasError()) {
|
||||||
qCDebug(interfaceapp) << "Error loading remote scripts: " << xml.errorString();
|
qCDebug(scriptengine) << "Error loading remote scripts: " << xml.errorString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ protected:
|
||||||
void rebuildTree();
|
void rebuildTree();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class ScriptEngines;
|
||||||
bool _loadingScripts;
|
bool _loadingScripts;
|
||||||
QDir _localDirectory;
|
QDir _localDirectory;
|
||||||
QFileSystemWatcher _fsWatcher;
|
QFileSystemWatcher _fsWatcher;
|
|
@ -104,8 +104,6 @@ public:
|
||||||
const Vec3& getScale() const;
|
const Vec3& getScale() const;
|
||||||
Transform& setScale(float scale);
|
Transform& setScale(float scale);
|
||||||
Transform& setScale(const Vec3& scale); // [new this] = [this.translation] * [this.rotation] * [scale]
|
Transform& setScale(const Vec3& scale); // [new this] = [this.translation] * [this.rotation] * [scale]
|
||||||
Transform& preScale(float scale);
|
|
||||||
Transform& preScale(const Vec3& scale);
|
|
||||||
Transform& postScale(float scale); // [new this] = [this] * [scale] equivalent to:glScale
|
Transform& postScale(float scale); // [new this] = [this] * [scale] equivalent to:glScale
|
||||||
Transform& postScale(const Vec3& scale); // [new this] = [this] * [scale] equivalent to:glScale
|
Transform& postScale(const Vec3& scale); // [new this] = [this] * [scale] equivalent to:glScale
|
||||||
|
|
||||||
|
@ -350,14 +348,6 @@ inline Transform& Transform::setScale(const Vec3& scale) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Transform& Transform::preScale(float scale) {
|
|
||||||
return setScale(getScale() * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Transform& Transform::preScale(const Vec3& scale) {
|
|
||||||
return setScale(getScale() * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Transform& Transform::postScale(float scale) {
|
inline Transform& Transform::postScale(float scale) {
|
||||||
if (!isValidScale(scale) || scale == 1.0f) {
|
if (!isValidScale(scale) || scale == 1.0f) {
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -376,6 +366,9 @@ inline Transform& Transform::postScale(const Vec3& scale) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
invalidCache();
|
invalidCache();
|
||||||
|
if ((scale.x != scale.y) || (scale.x != scale.z)) {
|
||||||
|
flagNonUniform();
|
||||||
|
}
|
||||||
if (isScaling()) {
|
if (isScaling()) {
|
||||||
_scale *= scale;
|
_scale *= scale;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual bool isJointController() const override { return true; }
|
virtual bool isJointController() const override { return true; }
|
||||||
const QString& getName() const override { return NAME; }
|
virtual const QString& getName() const override { return NAME; }
|
||||||
const QString& getID() const override { return NEURON_ID_STRING; }
|
const QString& getID() const override { return NEURON_ID_STRING; }
|
||||||
|
|
||||||
virtual void activate() override;
|
virtual void activate() override;
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual bool isJointController() const override { return false; }
|
virtual bool isJointController() const override { return false; }
|
||||||
const QString& getName() const override { return NAME; }
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
virtual void deinit() override;
|
virtual void deinit() override;
|
||||||
|
|
|
@ -29,8 +29,8 @@ public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual bool isJointController() const override { return true; }
|
virtual bool isJointController() const override { return true; }
|
||||||
const QString& getName() const override { return NAME; }
|
virtual const QString& getName() const override { return NAME; }
|
||||||
const QString& getID() const override { return HYDRA_ID_STRING; }
|
virtual const QString& getID() const override { return HYDRA_ID_STRING; }
|
||||||
|
|
||||||
virtual void activate() override;
|
virtual void activate() override;
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
|
|
|
@ -78,7 +78,6 @@ void OculusBaseDisplayPlugin::deinit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusBaseDisplayPlugin::activate() {
|
void OculusBaseDisplayPlugin::activate() {
|
||||||
WindowOpenGLDisplayPlugin::activate();
|
|
||||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
||||||
qFatal("Could not init OVR");
|
qFatal("Could not init OVR");
|
||||||
}
|
}
|
||||||
|
@ -87,6 +86,8 @@ void OculusBaseDisplayPlugin::activate() {
|
||||||
qFatal("Failed to acquire HMD");
|
qFatal("Failed to acquire HMD");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowOpenGLDisplayPlugin::activate();
|
||||||
|
|
||||||
_hmdDesc = ovr_GetHmdDesc(_session);
|
_hmdDesc = ovr_GetHmdDesc(_session);
|
||||||
|
|
||||||
_ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd);
|
_ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd);
|
||||||
|
|
|
@ -10,10 +10,6 @@
|
||||||
|
|
||||||
const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)");
|
const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)");
|
||||||
|
|
||||||
const QString & OculusDebugDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS");
|
static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS");
|
||||||
static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS");
|
static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS");
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
|
|
||||||
class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin {
|
class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
virtual const QString & getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
virtual grouping getGrouping() const override { return DEVELOPER; }
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -138,10 +138,6 @@ private:
|
||||||
|
|
||||||
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
||||||
|
|
||||||
const QString & OculusDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const QString MONO_PREVIEW = "Mono Preview";
|
static const QString MONO_PREVIEW = "Mono Preview";
|
||||||
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ const float TARGET_RATE_Oculus = 75.0f;
|
||||||
class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
virtual void activate() override;
|
virtual void activate() override;
|
||||||
virtual const QString & getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final;
|
virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final;
|
||||||
|
|
||||||
virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; }
|
virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; }
|
||||||
|
|
|
@ -26,11 +26,7 @@
|
||||||
|
|
||||||
using namespace oglplus;
|
using namespace oglplus;
|
||||||
|
|
||||||
const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift (0.5) (Simulated)");
|
const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift (0.5) (Legacy)");
|
||||||
|
|
||||||
const QString & OculusLegacyDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
|
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class OculusLegacyDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
OculusLegacyDisplayPlugin();
|
OculusLegacyDisplayPlugin();
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual const QString & getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual void activate() override;
|
virtual void activate() override;
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
|
|
|
@ -31,10 +31,6 @@ const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)");
|
||||||
|
|
||||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
||||||
|
|
||||||
const QString & OpenVrDisplayPlugin::getName() const {
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
static vr::IVRCompositor* _compositor{ nullptr };
|
static vr::IVRCompositor* _compositor{ nullptr };
|
||||||
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||||
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||||
|
|
|
@ -18,7 +18,7 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device p
|
||||||
class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual const QString & getName() const override;
|
virtual const QString& getName() const override { return NAME; }
|
||||||
virtual bool isHmd() const override { return true; }
|
virtual bool isHmd() const override { return true; }
|
||||||
|
|
||||||
virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; }
|
virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; }
|
||||||
|
|
|
@ -11,19 +11,21 @@
|
||||||
#include "TransformTests.h"
|
#include "TransformTests.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include <SharedLogging.h>
|
#include <SharedLogging.h>
|
||||||
#include <Transform.h>
|
|
||||||
|
|
||||||
#include "../QTestExtensions.h"
|
#include "../QTestExtensions.h"
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <Transform.h>
|
||||||
|
#include <StreamUtils.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
using namespace glm;
|
//using namespace glm;
|
||||||
|
|
||||||
const vec3 xAxis(1.0f, 0.0f, 0.0f);
|
const vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||||
const vec3 yAxis(0.0f, 1.0f, 0.0f);
|
const vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||||
const vec3 zAxis(0.0f, 0.0f, 1.0f);
|
const vec3 zAxis(0.0f, 0.0f, 1.0f);
|
||||||
const quat rot90 = angleAxis((float)M_PI / 2.0f, yAxis);
|
const quat rot90 = glm::angleAxis((float)M_PI / 2.0f, yAxis);
|
||||||
|
|
||||||
QTEST_MAIN(TransformTests)
|
QTEST_MAIN(TransformTests)
|
||||||
|
|
||||||
|
@ -71,19 +73,26 @@ void TransformTests::getInverseMatrix() {
|
||||||
vec4( 0.0f, 1.0f, 0.0f, 0.0f),
|
vec4( 0.0f, 1.0f, 0.0f, 0.0f),
|
||||||
vec4( 0.0f, 0.0f, 1.0f, 0.0f),
|
vec4( 0.0f, 0.0f, 1.0f, 0.0f),
|
||||||
vec4( 0.0f, 0.0f, 0.0f, 1.0f));
|
vec4( 0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
const mat4 result_a = inverse(m * mirrorX);
|
const mat4 result_a = glm::inverse(m * mirrorX);
|
||||||
|
|
||||||
Transform xform;
|
Transform xform;
|
||||||
xform.setTranslation(t);
|
xform.setTranslation(t);
|
||||||
xform.setRotation(rot90);
|
xform.setRotation(rot90);
|
||||||
|
|
||||||
//
|
|
||||||
// change postScale to preScale and the test will pass...
|
|
||||||
//
|
|
||||||
|
|
||||||
xform.postScale(vec3(-1.0f, 1.0f, 1.0f));
|
xform.postScale(vec3(-1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
mat4 result_b;
|
mat4 result_b;
|
||||||
xform.getInverseMatrix(result_b);
|
xform.getInverseMatrix(result_b);
|
||||||
|
|
||||||
QCOMPARE_WITH_ABS_ERROR(result_a, result_b, EPSILON);
|
// don't check elements directly, instead compare each axis transformed by the matrix.
|
||||||
|
auto xa = transformPoint(result_a, xAxis);
|
||||||
|
auto ya = transformPoint(result_a, yAxis);
|
||||||
|
auto za = transformPoint(result_a, zAxis);
|
||||||
|
|
||||||
|
auto xb = transformPoint(result_b, xAxis);
|
||||||
|
auto yb = transformPoint(result_b, yAxis);
|
||||||
|
auto zb = transformPoint(result_b, zAxis);
|
||||||
|
|
||||||
|
QCOMPARE_WITH_ABS_ERROR(xa, xb, EPSILON);
|
||||||
|
QCOMPARE_WITH_ABS_ERROR(ya, yb, EPSILON);
|
||||||
|
QCOMPARE_WITH_ABS_ERROR(za, zb, EPSILON);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue