mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blue
This commit is contained in:
commit
85fd1dcb5b
27 changed files with 3946 additions and 145 deletions
|
@ -14,11 +14,9 @@ Script.load("edit.js");
|
|||
Script.load("examples.js");
|
||||
Script.load("selectAudioDevice.js");
|
||||
Script.load("notifications.js");
|
||||
Script.load("users.js");
|
||||
Script.load("controllers/handControllerGrab.js");
|
||||
Script.load("controllers/squeezeHands.js");
|
||||
Script.load("grab.js");
|
||||
Script.load("directory.js");
|
||||
Script.load("dialTone.js");
|
||||
// Script.load("attachedEntitiesManager.js");
|
||||
Script.load("depthReticle.js");
|
||||
|
|
53
examples/libraries/jasmine/hifi-boot.js
Normal file
53
examples/libraries/jasmine/hifi-boot.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
(function() {
|
||||
function ConsoleReporter(options) {
|
||||
this.jasmineStarted = function (obj) {
|
||||
print("jasmineStarted: numSpecs = " + obj.totalSpecsDefined);
|
||||
};
|
||||
this.jasmineDone = function (obj) {
|
||||
print("jasmineDone");
|
||||
};
|
||||
this.suiteStarted = function(obj) {
|
||||
print("suiteStarted: \"" + obj.fullName + "\"");
|
||||
};
|
||||
this.suiteDone = function(obj) {
|
||||
print("suiteDone: \"" + obj.fullName + "\" " + obj.status);
|
||||
};
|
||||
this.specStarted = function(obj) {
|
||||
print("specStarted: \"" + obj.fullName + "\"");
|
||||
};
|
||||
this.specDone = function(obj) {
|
||||
print("specDone: \"" + obj.fullName + "\" " + obj.status);
|
||||
|
||||
var i, l = obj.failedExpectations.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
print(" " + obj.failedExpectations[i].message);
|
||||
}
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
setTimeout = Script.setTimeout;
|
||||
setInterval = Script.setInterval;
|
||||
clearTimeout = Script.clearTimeout;
|
||||
clearInterval = Script.clearInterval;
|
||||
|
||||
var jasmine = jasmineRequire.core(jasmineRequire);
|
||||
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
env.addReporter(new ConsoleReporter());
|
||||
|
||||
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
|
||||
extend(this, jasmineInterface);
|
||||
|
||||
function extend(destination, source) {
|
||||
for (var property in source) {
|
||||
destination[property] = source[property];
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
}());
|
||||
|
3458
examples/libraries/jasmine/jasmine.js
Normal file
3458
examples/libraries/jasmine/jasmine.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -355,20 +355,36 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
});
|
||||
}
|
||||
};
|
||||
that.windowDimensions = Controller.getViewportDimensions();
|
||||
|
||||
function clamp(value, min, max) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
that.windowDimensions = recommendedDimmensions; // Controller.getViewportDimensions();
|
||||
that.origin = { x: recommendedRect.x, y: recommendedRect.y };
|
||||
// Maybe fixme: Keeping the same percent of the window size isn't always the right thing.
|
||||
// For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen".
|
||||
// If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below.
|
||||
that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients.
|
||||
var fractionX = that.x / that.windowDimensions.x;
|
||||
var fractionY = that.y / that.windowDimensions.y;
|
||||
that.windowDimensions = newSize || Controller.getViewportDimensions();
|
||||
that.move(fractionX * that.windowDimensions.x, fractionY * that.windowDimensions.y);
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
var originRelativeX = (that.x - that.origin.x);
|
||||
var originRelativeY = (that.y - that.origin.y);
|
||||
var fractionX = clamp(originRelativeX / that.windowDimensions.x, 0, 1);
|
||||
var fractionY = clamp(originRelativeY / that.windowDimensions.y, 0, 1);
|
||||
that.windowDimensions = newSize || recommendedDimmensions;
|
||||
that.origin = { x: recommendedRect.x, y: recommendedRect.y };
|
||||
var newX = (fractionX * that.windowDimensions.x) + recommendedRect.x;
|
||||
var newY = (fractionY * that.windowDimensions.y) + recommendedRect.y;
|
||||
that.move(newX, newY);
|
||||
};
|
||||
if (optionalPersistenceKey) {
|
||||
this.fractionKey = optionalPersistenceKey + '.fraction';
|
||||
this.save = function () {
|
||||
var screenSize = Controller.getViewportDimensions();
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
if (screenSize.x > 0 && screenSize.y > 0) {
|
||||
// Guard against invalid screen size that can occur at shut-down.
|
||||
var fraction = {x: that.x / screenSize.x, y: that.y / screenSize.y};
|
||||
|
@ -411,7 +427,9 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y);
|
||||
};
|
||||
that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport.
|
||||
var currentWindowSize = Controller.getViewportDimensions();
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var currentWindowSize = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
|
||||
if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) {
|
||||
that.onResizeViewport(currentWindowSize);
|
||||
}
|
||||
|
@ -434,7 +452,8 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
}
|
||||
if (this.fractionKey || optionalInitialPositionFunction) {
|
||||
var savedFraction = JSON.parse(Settings.getValue(this.fractionKey) || '0'); // getValue can answer empty string
|
||||
var screenSize = Controller.getViewportDimensions();
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
if (savedFraction) {
|
||||
// If we have saved data, keep the toolbar at the same proportion of the screen width/height.
|
||||
that.move(savedFraction.x * screenSize.x, savedFraction.y * screenSize.y);
|
||||
|
|
59
examples/tests/avatarUnitTests.js
Normal file
59
examples/tests/avatarUnitTests.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
Script.include("../libraries/jasmine/jasmine.js");
|
||||
Script.include("../libraries/jasmine/hifi-boot.js");
|
||||
|
||||
// Art3mis
|
||||
var DEFAULT_AVATAR_URL = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/e76946cc-c272-4adf-9bb6-02cde0a4b57d/8fd984ea6fe1495147a3303f87fa6e23.fst?1460131758";
|
||||
|
||||
var ORIGIN = {x: 0, y: 0, z: 0};
|
||||
var ONE_HUNDRED = {x: 100, y: 100, z: 100};
|
||||
var ROT_IDENT = {x: 0, y: 0, z: 0, w: 1};
|
||||
|
||||
describe("MyAvatar", function () {
|
||||
|
||||
// reload the avatar from scratch before each test.
|
||||
beforeEach(function (done) {
|
||||
MyAvatar.skeletonModelURL = DEFAULT_AVATAR_URL;
|
||||
|
||||
// wait until we are finished loading
|
||||
var id = Script.setInterval(function () {
|
||||
if (MyAvatar.jointNames.length == 72) {
|
||||
// assume we are finished loading.
|
||||
Script.clearInterval(id);
|
||||
MyAvatar.position = ORIGIN;
|
||||
MyAvatar.orientation = ROT_IDENT;
|
||||
// give the avatar 1/2 a second to settle on the ground in the idle pose.
|
||||
Script.setTimeout(function () {
|
||||
done();
|
||||
}, 500);
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// makes the assumption that there is solid ground somewhat underneath the avatar.
|
||||
it("position and orientation getters", function () {
|
||||
var pos = MyAvatar.position;
|
||||
|
||||
expect(Math.abs(pos.x)).toBeLessThan(0.1);
|
||||
expect(Math.abs(pos.y)).toBeLessThan(1.0);
|
||||
expect(Math.abs(pos.z)).toBeLessThan(0.1);
|
||||
|
||||
var rot = MyAvatar.orientation;
|
||||
expect(Math.abs(rot.x)).toBeLessThan(0.01);
|
||||
expect(Math.abs(rot.y)).toBeLessThan(0.01);
|
||||
expect(Math.abs(rot.z)).toBeLessThan(0.01);
|
||||
expect(Math.abs(1 - rot.w)).toBeLessThan(0.01);
|
||||
});
|
||||
|
||||
it("position and orientation setters", function (done) {
|
||||
MyAvatar.position = ONE_HUNDRED;
|
||||
Script.setTimeout(function () {
|
||||
expect(Vec3.length(Vec3.subtract(MyAvatar.position, ONE_HUNDRED))).toBeLessThan(0.1);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
jasmine.getEnv().execute();
|
||||
|
|
@ -39,6 +39,7 @@ Column {
|
|||
"Shadow",
|
||||
"Pyramid Depth",
|
||||
"Ambient Occlusion",
|
||||
"Ambient Occlusion Blurred",
|
||||
"Custom Shader"
|
||||
]
|
||||
RadioButton {
|
||||
|
|
|
@ -178,9 +178,10 @@ Item {
|
|||
title: "Items"
|
||||
height: parent.evalEvenHeight()
|
||||
object: parent.drawOpaqueConfig
|
||||
|
||||
plots: [
|
||||
{
|
||||
object: Render.getConfig("DrawOpaqueDeferred"),
|
||||
object: parent.drawOpaqueConfig,
|
||||
prop: "numDrawn",
|
||||
label: "Opaques",
|
||||
color: "#1AC567"
|
||||
|
@ -198,7 +199,42 @@ Item {
|
|||
color: "#FED959"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
PlotPerf {
|
||||
title: "Timing"
|
||||
height: parent.evalEvenHeight()
|
||||
object: parent.drawOpaqueConfig
|
||||
valueUnit: "ms"
|
||||
valueScale: 1000
|
||||
valueNumDigits: "1"
|
||||
plots: [
|
||||
{
|
||||
object: Render.getConfig("DrawOpaqueDeferred"),
|
||||
prop: "cpuRunTime",
|
||||
label: "Opaques",
|
||||
color: "#1AC567"
|
||||
},
|
||||
{
|
||||
object: Render.getConfig("DrawTransparentDeferred"),
|
||||
prop: "cpuRunTime",
|
||||
label: "Translucents",
|
||||
color: "#00B4EF"
|
||||
},
|
||||
{
|
||||
object: Render.getConfig("RenderDeferred"),
|
||||
prop: "cpuRunTime",
|
||||
label: "Lighting",
|
||||
color: "#FED959"
|
||||
},
|
||||
{
|
||||
object: Render.getConfig("RenderDeferredTask"),
|
||||
prop: "cpuRunTime",
|
||||
label: "RenderFrame",
|
||||
color: "#E2334D"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ Hifi.AvatarInputs {
|
|||
readonly property int mirrorWidth: 265
|
||||
readonly property int iconSize: 24
|
||||
readonly property int iconPadding: 5
|
||||
|
||||
readonly property bool shouldReposition: true
|
||||
|
||||
Settings {
|
||||
category: "Overlay.AvatarInputs"
|
||||
|
|
|
@ -21,8 +21,11 @@ FocusScope {
|
|||
objectName: "desktop"
|
||||
anchors.fill: parent
|
||||
|
||||
onHeightChanged: d.repositionAll();
|
||||
onWidthChanged: d.repositionAll();
|
||||
property rect recommendedRect: rect(0,0,0,0);
|
||||
|
||||
onHeightChanged: d.handleSizeChanged();
|
||||
|
||||
onWidthChanged: d.handleSizeChanged();
|
||||
|
||||
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
||||
// when they're opened.
|
||||
|
@ -50,6 +53,20 @@ FocusScope {
|
|||
QtObject {
|
||||
id: d
|
||||
|
||||
function handleSizeChanged() {
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var newRecommendedRectJS = Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
|
||||
if (oldRecommendedRect != Qt.rect(0,0,0,0)
|
||||
&& oldRecommendedRect != newRecommendedRect) {
|
||||
d.repositionAll();
|
||||
}
|
||||
recommendedRect = newRecommendedRect;
|
||||
}
|
||||
|
||||
function findChild(item, name) {
|
||||
for (var i = 0; i < item.children.length; ++i) {
|
||||
if (item.children[i].objectName === name) {
|
||||
|
@ -202,12 +219,42 @@ FocusScope {
|
|||
// }
|
||||
}
|
||||
|
||||
function getRepositionChildren(predicate) {
|
||||
var currentWindows = [];
|
||||
if (!desktop) {
|
||||
console.log("Could not find desktop");
|
||||
return currentWindows;
|
||||
}
|
||||
|
||||
for (var i = 0; i < desktop.children.length; ++i) {
|
||||
var child = desktop.children[i];
|
||||
if (child.shouldReposition === true && (!predicate || predicate(child))) {
|
||||
currentWindows.push(child)
|
||||
}
|
||||
}
|
||||
return currentWindows;
|
||||
}
|
||||
|
||||
function repositionAll() {
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
reposition(windows[i]);
|
||||
var targetWindow = windows[i];
|
||||
if (targetWindow.visible) {
|
||||
repositionWindow(targetWindow, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
}
|
||||
|
||||
// also reposition the other children that aren't top level windows but want to be repositioned
|
||||
var otherChildren = d.getRepositionChildren();
|
||||
for (var i = 0; i < otherChildren.length; ++i) {
|
||||
var child = otherChildren[i];
|
||||
repositionWindow(child, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,38 +279,56 @@ FocusScope {
|
|||
targetWindow.focus = true;
|
||||
}
|
||||
|
||||
reposition(targetWindow);
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
|
||||
showDesktop();
|
||||
}
|
||||
|
||||
function reposition(item) {
|
||||
function repositionWindow(targetWindow, forceReposition,
|
||||
oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions) {
|
||||
|
||||
if (desktop.width === 0 || desktop.height === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
if (!targetWindow) {
|
||||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
var recommended = Controller.getRecommendedOverlayRect();
|
||||
var maxX = recommended.x + recommended.width;
|
||||
var maxY = recommended.y + recommended.height;
|
||||
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);
|
||||
// If the window is completely offscreen, reposition it
|
||||
if ((targetWindow.x > desktop.width || (targetWindow.x + targetWindow.width) < 0) ||
|
||||
(targetWindow.y > desktop.height || (targetWindow.y + targetWindow.height) < 0)) {
|
||||
|
||||
// if we asked to force reposition, or if the window is completely outside of the recommended rectangle, reposition it
|
||||
if (forceReposition || (targetWindow.x > maxX || (targetWindow.x + targetWindow.width) < recommended.x) ||
|
||||
(targetWindow.y > maxY || (targetWindow.y + targetWindow.height) < recommended.y)) {
|
||||
newPosition.x = -1
|
||||
newPosition.y = -1
|
||||
}
|
||||
|
||||
|
||||
if (newPosition.x === -1 && newPosition.y === -1) {
|
||||
// Set initial window position
|
||||
// var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y);
|
||||
// var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height);
|
||||
// newPosition = Utils.clampVector(newPosition, minPosition, maxPosition);
|
||||
// newPosition = Utils.randomPosition(minPosition, maxPosition);
|
||||
newPosition = Qt.vector2d(desktop.width / 2 - targetWindow.width / 2,
|
||||
desktop.height / 2 - targetWindow.height / 2);
|
||||
var originRelativeX = (targetWindow.x - oldRecommendedRect.x);
|
||||
var originRelativeY = (targetWindow.y - oldRecommendedRect.y);
|
||||
if (isNaN(originRelativeX)) {
|
||||
originRelativeX = 0;
|
||||
}
|
||||
if (isNaN(originRelativeY)) {
|
||||
originRelativeY = 0;
|
||||
}
|
||||
var fractionX = Utils.clamp(originRelativeX / oldRecommendedDimmensions.x, 0, 1);
|
||||
var fractionY = Utils.clamp(originRelativeY / oldRecommendedDimmensions.y, 0, 1);
|
||||
|
||||
var newX = (fractionX * newRecommendedDimmensions.x) + newRecommendedRect.x;
|
||||
var newY = (fractionY * newRecommendedDimmensions.y) + newRecommendedRect.y;
|
||||
|
||||
newPosition = Qt.vector2d(newX, newY);
|
||||
}
|
||||
targetWindow.x = newPosition.x;
|
||||
targetWindow.y = newPosition.y;
|
||||
|
|
|
@ -195,12 +195,7 @@ static const uint32_t INVALID_FRAME = UINT32_MAX;
|
|||
|
||||
static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation
|
||||
|
||||
#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
|
||||
|
||||
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
|
||||
|
||||
|
@ -2686,8 +2681,6 @@ void Application::idle(uint64_t now) {
|
|||
_overlayConductor.setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Overlays));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {
|
||||
|
@ -4899,19 +4892,44 @@ QRect Application::getRenderingGeometry() const {
|
|||
}
|
||||
|
||||
glm::uvec2 Application::getUiSize() const {
|
||||
return getActiveDisplayPlugin()->getRecommendedUiSize();
|
||||
static const uint MIN_SIZE = 1;
|
||||
glm::uvec2 result(MIN_SIZE);
|
||||
if (_displayPlugin) {
|
||||
result = getActiveDisplayPlugin()->getRecommendedUiSize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QRect Application::getRecommendedOverlayRect() const {
|
||||
auto uiSize = getUiSize();
|
||||
QRect result(0, 0, uiSize.x, uiSize.y);
|
||||
if (_displayPlugin) {
|
||||
result = getActiveDisplayPlugin()->getRecommendedOverlayRect();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QSize Application::getDeviceSize() const {
|
||||
return fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
|
||||
static const int MIN_SIZE = 1;
|
||||
QSize result(MIN_SIZE, MIN_SIZE);
|
||||
if (_displayPlugin) {
|
||||
result = fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Application::isThrottleRendering() const {
|
||||
return getActiveDisplayPlugin()->isThrottled();
|
||||
if (_displayPlugin) {
|
||||
return getActiveDisplayPlugin()->isThrottled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Application::hasFocus() const {
|
||||
return getActiveDisplayPlugin()->hasFocus();
|
||||
if (_displayPlugin) {
|
||||
return getActiveDisplayPlugin()->hasFocus();
|
||||
}
|
||||
return (QApplication::activeWindow() != nullptr);
|
||||
}
|
||||
|
||||
glm::vec2 Application::getViewportDimensions() const {
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
QRect getRenderingGeometry() const;
|
||||
|
||||
glm::uvec2 getUiSize() const;
|
||||
QRect getRecommendedOverlayRect() const;
|
||||
QSize getDeviceSize() const;
|
||||
bool hasFocus() const;
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <mutex>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <gpu/Context.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
|
@ -42,26 +41,11 @@ static const float TAU = 6.28318530717958f;
|
|||
//static const float MILKY_WAY_RATIO = 0.4f;
|
||||
static const char* UNIFORM_TIME_NAME = "iGlobalTime";
|
||||
|
||||
|
||||
|
||||
Stars::Stars() {
|
||||
}
|
||||
|
||||
Stars::~Stars() {
|
||||
}
|
||||
|
||||
// Produce a random float value between 0 and 1
|
||||
static float frand() {
|
||||
return (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
|
||||
// Produce a random radian value between 0 and 2 PI (TAU)
|
||||
/*
|
||||
static float rrand() {
|
||||
return frand() * TAU;
|
||||
}
|
||||
*/
|
||||
|
||||
// http://mathworld.wolfram.com/SpherePointPicking.html
|
||||
static vec2 randPolar() {
|
||||
vec2 result(frand(), frand());
|
||||
|
@ -115,59 +99,56 @@ struct StarVertex {
|
|||
vec4 colorAndSize;
|
||||
};
|
||||
|
||||
// FIXME star colors
|
||||
void Stars::render(RenderArgs* renderArgs, float alpha) {
|
||||
static gpu::BufferPointer vertexBuffer;
|
||||
static gpu::Stream::FormatPointer streamFormat;
|
||||
static gpu::Element positionElement, colorElement;
|
||||
static gpu::PipelinePointer _gridPipeline;
|
||||
static gpu::PipelinePointer _starsPipeline;
|
||||
static int32_t _timeSlot{ -1 };
|
||||
static std::once_flag once;
|
||||
static const int STARS_VERTICES_SLOT{ 0 };
|
||||
static const int STARS_COLOR_SLOT{ 1 };
|
||||
|
||||
const int VERTICES_SLOT = 0;
|
||||
const int COLOR_SLOT = 1;
|
||||
gpu::PipelinePointer Stars::_gridPipeline{};
|
||||
gpu::PipelinePointer Stars::_starsPipeline{};
|
||||
int32_t Stars::_timeSlot{ -1 };
|
||||
|
||||
std::call_once(once, [&] {
|
||||
{
|
||||
auto vs = gpu::Shader::createVertex(std::string(standardTransformPNTC_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(starsGrid_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
_timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME);
|
||||
if (_timeSlot == gpu::Shader::INVALID_LOCATION) {
|
||||
_timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME);
|
||||
}
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_gridPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
{
|
||||
auto vs = gpu::Shader::createVertex(std::string(stars_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(stars_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setAntialiasedLineEnable(true); // line smoothing also smooth points
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_starsPipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
void Stars::init() {
|
||||
if (!_gridPipeline) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(standardTransformPNTC_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(starsGrid_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
_timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME);
|
||||
if (_timeSlot == gpu::Shader::INVALID_LOCATION) {
|
||||
_timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME);
|
||||
}
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_gridPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
if (!_starsPipeline) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(stars_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(stars_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setAntialiasedLineEnable(true); // line smoothing also smooth points
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_starsPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
unsigned limit = STARFIELD_NUM_STARS;
|
||||
std::vector<StarVertex> points;
|
||||
points.resize(limit);
|
||||
|
||||
{ // generate stars
|
||||
QElapsedTimer startTime;
|
||||
startTime.start();
|
||||
|
||||
vertexBuffer.reset(new gpu::Buffer);
|
||||
|
||||
srand(STARFIELD_SEED);
|
||||
unsigned limit = STARFIELD_NUM_STARS;
|
||||
std::vector<StarVertex> points;
|
||||
points.resize(limit);
|
||||
for (size_t star = 0; star < limit; ++star) {
|
||||
points[star].position = vec4(fromPolar(randPolar()), 1);
|
||||
float size = frand() * 2.5f + 0.5f;
|
||||
|
@ -179,16 +160,32 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
|
|||
points[star].colorAndSize = vec4(color, size);
|
||||
}
|
||||
}
|
||||
|
||||
double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms
|
||||
qDebug() << "Total time to generate stars: " << timeDiff << " msec";
|
||||
}
|
||||
|
||||
gpu::Element positionElement, colorElement;
|
||||
const size_t VERTEX_STRIDE = sizeof(StarVertex);
|
||||
|
||||
vertexBuffer->append(VERTEX_STRIDE * limit, (const gpu::Byte*)&points[0]);
|
||||
streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, STARS_VERTICES_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, STARS_COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA));
|
||||
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
|
||||
colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
|
||||
|
||||
size_t offset = offsetof(StarVertex, position);
|
||||
positionView = gpu::BufferView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement);
|
||||
|
||||
offset = offsetof(StarVertex, colorAndSize);
|
||||
colorView = gpu::BufferView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, colorElement);
|
||||
}
|
||||
|
||||
// FIXME star colors
|
||||
void Stars::render(RenderArgs* renderArgs, float alpha) {
|
||||
std::call_once(once, [&]{ init(); });
|
||||
|
||||
vertexBuffer->append(sizeof(StarVertex) * limit, (const gpu::Byte*)&points[0]);
|
||||
streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA));
|
||||
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
|
||||
colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
|
||||
});
|
||||
|
||||
auto modelCache = DependencyManager::get<ModelCache>();
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
@ -210,17 +207,10 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
|
|||
batch._glUniform1f(_timeSlot, secs);
|
||||
geometryCache->renderCube(batch);
|
||||
|
||||
static const size_t VERTEX_STRIDE = sizeof(StarVertex);
|
||||
size_t offset = offsetof(StarVertex, position);
|
||||
gpu::BufferView posView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement);
|
||||
offset = offsetof(StarVertex, colorAndSize);
|
||||
gpu::BufferView colView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, colorElement);
|
||||
|
||||
// Render the stars
|
||||
batch.setPipeline(_starsPipeline);
|
||||
|
||||
batch.setInputFormat(streamFormat);
|
||||
batch.setInputBuffer(VERTICES_SLOT, posView);
|
||||
batch.setInputBuffer(COLOR_SLOT, colView);
|
||||
batch.setInputBuffer(STARS_VERTICES_SLOT, positionView);
|
||||
batch.setInputBuffer(STARS_COLOR_SLOT, colorView);
|
||||
batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS);
|
||||
}
|
||||
|
|
|
@ -12,21 +12,37 @@
|
|||
#ifndef hifi_Stars_h
|
||||
#define hifi_Stars_h
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
class RenderArgs;
|
||||
|
||||
// Starfield rendering component.
|
||||
class Stars {
|
||||
public:
|
||||
Stars();
|
||||
~Stars();
|
||||
Stars() = default;
|
||||
~Stars() = default;
|
||||
|
||||
Stars(Stars const&) = delete;
|
||||
Stars& operator=(Stars const&) = delete;
|
||||
|
||||
// Renders the starfield from a local viewer's perspective.
|
||||
// The parameters specifiy the field of view.
|
||||
void render(RenderArgs* args, float alpha);
|
||||
|
||||
private:
|
||||
// don't copy/assign
|
||||
Stars(Stars const&); // = delete;
|
||||
Stars& operator=(Stars const&); // delete;
|
||||
// Pipelines
|
||||
static gpu::PipelinePointer _gridPipeline;
|
||||
static gpu::PipelinePointer _starsPipeline;
|
||||
static int32_t _timeSlot;
|
||||
|
||||
// Buffers
|
||||
gpu::BufferPointer vertexBuffer;
|
||||
gpu::Stream::FormatPointer streamFormat;
|
||||
gpu::BufferView positionView;
|
||||
gpu::BufferView colorView;
|
||||
std::once_flag once;
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,11 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
|||
return qApp->getUiSize();
|
||||
}
|
||||
|
||||
QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
||||
auto rect = qApp->getRecommendedOverlayRect();
|
||||
return qRectToVariant(rect);
|
||||
}
|
||||
|
||||
controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
||||
// This is where we retrieve the Device Tracker category and then the sub tracker within it
|
||||
auto icIt = _inputControllers.find(0);
|
||||
|
|
|
@ -96,6 +96,7 @@ public slots:
|
|||
virtual void releaseJoystick(int joystickIndex);
|
||||
|
||||
virtual glm::vec2 getViewportDimensions() const;
|
||||
virtual QVariant getRecommendedOverlayRect() const;
|
||||
|
||||
/// Factory to create an InputController
|
||||
virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker);
|
||||
|
|
|
@ -34,6 +34,7 @@ static const float reticleSize = TWO_PI / 100.0f;
|
|||
static QString _tooltipId;
|
||||
|
||||
const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(3960, 1188); // ~10% more pixel density than old version, 72dx240d FOV
|
||||
const QRect CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT = QRect(956, 0, 2048, 1188); // don't include entire width only center 2048
|
||||
const float CompositorHelper::VIRTUAL_UI_ASPECT_RATIO = (float)VIRTUAL_SCREEN_SIZE.x / (float)VIRTUAL_SCREEN_SIZE.y;
|
||||
const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI * 3.0f / 2.0f, PI * 3.0f / 2.0f / VIRTUAL_UI_ASPECT_RATIO);
|
||||
const vec2 CompositorHelper::MOUSE_EXTENTS_ANGULAR_SIZE = vec2(PI * 2.0f, PI * 0.95f); // horizontal: full sphere, vertical: ~5deg from poles
|
||||
|
|
|
@ -42,6 +42,7 @@ class CompositorHelper : public QObject, public Dependency {
|
|||
Q_PROPERTY(bool reticleOverDesktop READ getReticleOverDesktop WRITE setReticleOverDesktop)
|
||||
public:
|
||||
static const uvec2 VIRTUAL_SCREEN_SIZE;
|
||||
static const QRect VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
|
||||
static const float VIRTUAL_UI_ASPECT_RATIO;
|
||||
static const vec2 VIRTUAL_UI_TARGET_FOV;
|
||||
static const vec2 MOUSE_EXTENTS_ANGULAR_SIZE;
|
||||
|
|
|
@ -34,6 +34,11 @@ glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const {
|
|||
return CompositorHelper::VIRTUAL_SCREEN_SIZE;
|
||||
}
|
||||
|
||||
QRect HmdDisplayPlugin::getRecommendedOverlayRect() const {
|
||||
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
|
||||
}
|
||||
|
||||
|
||||
bool HmdDisplayPlugin::internalActivate() {
|
||||
_monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW);
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final;
|
||||
bool isDisplayVisible() const override { return isHmdMounted(); }
|
||||
|
||||
QRect getRecommendedOverlayRect() const override final;
|
||||
|
||||
virtual glm::mat4 getHeadPose() const override;
|
||||
|
||||
|
||||
|
|
|
@ -105,6 +105,12 @@ public:
|
|||
return aspect(getRecommendedRenderSize());
|
||||
}
|
||||
|
||||
// The recommended bounds for primary overlay placement
|
||||
virtual QRect getRecommendedOverlayRect() const {
|
||||
auto recommendedSize = getRecommendedUiSize();
|
||||
return QRect(0, 0, recommendedSize.x, recommendedSize.y);
|
||||
}
|
||||
|
||||
// Stereo specific methods
|
||||
virtual glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
|
||||
return baseProjection;
|
||||
|
|
|
@ -90,6 +90,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
|
|||
|
||||
// Specular highlight from ambient
|
||||
vec3 direction = -reflect(fragEyeDir, fragNormal);
|
||||
|
||||
float levels = getLightAmbientMapNumMips(light);
|
||||
float lod = min(floor((roughness) * levels), levels);
|
||||
vec4 skyboxLight = evalSkyboxLight(direction, lod);
|
||||
|
|
|
@ -185,9 +185,6 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
|||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
config->setNumDrawn((int)inItems.size());
|
||||
emit config->numDrawnChanged();
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
|
@ -199,6 +196,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
|||
renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
|
||||
config->setNumDrawn((int)inItems.size());
|
||||
}
|
||||
|
||||
DrawOverlay3D::DrawOverlay3D(bool opaque) :
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
using JobModel = render::Job::Model<SetupDeferred>;
|
||||
};
|
||||
|
||||
|
||||
class PrepareDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
@ -29,32 +30,31 @@ public:
|
|||
using JobModel = render::Job::Model<PrepareDeferred>;
|
||||
};
|
||||
|
||||
|
||||
class RenderDeferred {
|
||||
public:
|
||||
using JobModel = render::Job::Model<RenderDeferred>;
|
||||
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
};
|
||||
|
||||
class DrawConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||
public:
|
||||
|
||||
int getNumDrawn() { return numDrawn; }
|
||||
void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); }
|
||||
int getNumDrawn() { return _numDrawn; }
|
||||
void setNumDrawn(int numDrawn) { _numDrawn = numDrawn; emit newStats(); }
|
||||
|
||||
int maxDrawn{ -1 };
|
||||
|
||||
signals:
|
||||
void numDrawnChanged();
|
||||
void newStats();
|
||||
void dirty();
|
||||
|
||||
protected:
|
||||
int numDrawn{ 0 };
|
||||
int _numDrawn{ 0 };
|
||||
};
|
||||
|
||||
class DrawDeferred {
|
||||
|
|
|
@ -127,6 +127,9 @@ protected:
|
|||
// A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled)
|
||||
class JobConfig : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(quint64 cpuRunTime READ getCPUTRunTime NOTIFY newStats())
|
||||
|
||||
quint64 _CPURunTime{ 0 };
|
||||
public:
|
||||
using Persistent = PersistentConfig<JobConfig>;
|
||||
|
||||
|
@ -151,11 +154,17 @@ public:
|
|||
Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); }
|
||||
Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); }
|
||||
|
||||
// Running Time measurement
|
||||
// The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated
|
||||
void setCPURunTime(quint64 ustime) { _CPURunTime = ustime; emit newStats(); }
|
||||
quint64 getCPUTRunTime() const { return _CPURunTime; }
|
||||
|
||||
public slots:
|
||||
void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); }
|
||||
|
||||
signals:
|
||||
void loaded();
|
||||
void newStats();
|
||||
};
|
||||
|
||||
class TaskConfig : public JobConfig {
|
||||
|
@ -223,7 +232,11 @@ public:
|
|||
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0;
|
||||
|
||||
protected:
|
||||
void setCPURunTime(quint64 ustime) { std::static_pointer_cast<Config>(_config)->setCPURunTime(ustime); }
|
||||
|
||||
QConfigPointer _config;
|
||||
|
||||
friend class Job;
|
||||
};
|
||||
using ConceptPointer = std::shared_ptr<Concept>;
|
||||
|
||||
|
@ -278,8 +291,11 @@ public:
|
|||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer(_name.c_str());
|
||||
PROFILE_RANGE(_name.c_str());
|
||||
auto start = usecTimestampNow();
|
||||
|
||||
_concept->run(sceneContext, renderContext);
|
||||
|
||||
_concept->setCPURunTime(usecTimestampNow() - start);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -22,12 +22,7 @@
|
|||
#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;
|
||||
|
|
|
@ -128,7 +128,7 @@ void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) {
|
|||
vec3.z = object.property("z").toVariant().toFloat();
|
||||
}
|
||||
|
||||
QVariant vec3toVariant(const glm::vec3 &vec3) {
|
||||
QVariant vec3toVariant(const glm::vec3& vec3) {
|
||||
if (vec3.x != vec3.x || vec3.y != vec3.y || vec3.z != vec3.z) {
|
||||
// if vec3 contains a NaN don't try to convert it
|
||||
return QVariant();
|
||||
|
@ -140,6 +140,18 @@ QVariant vec3toVariant(const glm::vec3 &vec3) {
|
|||
return result;
|
||||
}
|
||||
|
||||
QVariant vec4toVariant(const glm::vec4& vec4) {
|
||||
if (isNaN(vec4.x) || isNaN(vec4.y) || isNaN(vec4.z) || isNaN(vec4.w)) {
|
||||
// if vec4 contains a NaN don't try to convert it
|
||||
return QVariant();
|
||||
}
|
||||
QVariantMap result;
|
||||
result["x"] = vec4.x;
|
||||
result["y"] = vec4.y;
|
||||
result["z"] = vec4.z;
|
||||
result["w"] = vec4.w;
|
||||
return result;
|
||||
}
|
||||
|
||||
QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::vec3>& vector) {
|
||||
QScriptValue array = engine->newArray();
|
||||
|
@ -150,7 +162,7 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::
|
|||
}
|
||||
|
||||
|
||||
glm::vec3 vec3FromVariant(const QVariant &object, bool& valid) {
|
||||
glm::vec3 vec3FromVariant(const QVariant& object, bool& valid) {
|
||||
glm::vec3 v;
|
||||
valid = false;
|
||||
if (!object.isValid() || object.isNull()) {
|
||||
|
@ -189,12 +201,49 @@ glm::vec3 vec3FromVariant(const QVariant &object, bool& valid) {
|
|||
return v;
|
||||
}
|
||||
|
||||
glm::vec3 vec3FromVariant(const QVariant &object) {
|
||||
glm::vec3 vec3FromVariant(const QVariant& object) {
|
||||
bool valid = false;
|
||||
return vec3FromVariant(object, valid);
|
||||
}
|
||||
|
||||
QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) {
|
||||
glm::vec4 vec4FromVariant(const QVariant& object, bool& valid) {
|
||||
glm::vec4 v;
|
||||
valid = false;
|
||||
if (!object.isValid() || object.isNull()) {
|
||||
return v;
|
||||
} else if (object.canConvert<float>()) {
|
||||
v = glm::vec4(object.toFloat());
|
||||
valid = true;
|
||||
} else if (object.canConvert<QVector4D>()) {
|
||||
auto qvec4 = qvariant_cast<QVector4D>(object);
|
||||
v.x = qvec4.x();
|
||||
v.y = qvec4.y();
|
||||
v.z = qvec4.z();
|
||||
v.w = qvec4.w();
|
||||
valid = true;
|
||||
} else {
|
||||
auto map = object.toMap();
|
||||
auto x = map["x"];
|
||||
auto y = map["y"];
|
||||
auto z = map["z"];
|
||||
auto w = map["w"];
|
||||
if (x.canConvert<float>() && y.canConvert<float>() && z.canConvert<float>() && w.canConvert<float>()) {
|
||||
v.x = x.toFloat();
|
||||
v.y = y.toFloat();
|
||||
v.z = z.toFloat();
|
||||
v.w = w.toFloat();
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
glm::vec4 vec4FromVariant(const QVariant& object) {
|
||||
bool valid = false;
|
||||
return vec4FromVariant(object, valid);
|
||||
}
|
||||
|
||||
QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat& quat) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) {
|
||||
// if quat contains a NaN don't try to convert it
|
||||
|
@ -207,7 +256,7 @@ QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void quatFromScriptValue(const QScriptValue &object, glm::quat &quat) {
|
||||
void quatFromScriptValue(const QScriptValue& object, glm::quat &quat) {
|
||||
quat.x = object.property("x").toVariant().toFloat();
|
||||
quat.y = object.property("y").toVariant().toFloat();
|
||||
quat.z = object.property("z").toVariant().toFloat();
|
||||
|
@ -245,12 +294,12 @@ glm::quat quatFromVariant(const QVariant &object, bool& isValid) {
|
|||
return q;
|
||||
}
|
||||
|
||||
glm::quat quatFromVariant(const QVariant &object) {
|
||||
glm::quat quatFromVariant(const QVariant& object) {
|
||||
bool valid = false;
|
||||
return quatFromVariant(object, valid);
|
||||
}
|
||||
|
||||
QVariant quatToVariant(const glm::quat &quat) {
|
||||
QVariant quatToVariant(const glm::quat& quat) {
|
||||
if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z) {
|
||||
// if vec3 contains a NaN don't try to convert it
|
||||
return QVariant();
|
||||
|
|
|
@ -43,12 +43,15 @@ void mat4FromScriptValue(const QScriptValue& object, glm::mat4& mat4);
|
|||
// Vec4
|
||||
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4);
|
||||
void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4);
|
||||
QVariant vec4toVariant(const glm::vec4& vec4);
|
||||
glm::vec4 vec4FromVariant(const QVariant &object, bool& valid);
|
||||
glm::vec4 vec4FromVariant(const QVariant &object);
|
||||
|
||||
// Vec3
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
||||
void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||
|
||||
QVariant vec3toVariant(const glm::vec3 &vec3);
|
||||
QVariant vec3toVariant(const glm::vec3& vec3);
|
||||
glm::vec3 vec3FromVariant(const QVariant &object, bool& valid);
|
||||
glm::vec3 vec3FromVariant(const QVariant &object);
|
||||
|
||||
|
@ -71,9 +74,10 @@ glm::quat quatFromVariant(const QVariant &object);
|
|||
// Rect
|
||||
QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect);
|
||||
void qRectFromScriptValue(const QScriptValue& object, QRect& rect);
|
||||
|
||||
QVariant qRectToVariant(const QRect& rect);
|
||||
QRect qRectFromVariant(const QVariant& object, bool& isValid);
|
||||
QRect qRectFromVariant(const QVariant& object);
|
||||
QVariant qRectToVariant(const QRect& rect);
|
||||
|
||||
|
||||
// xColor
|
||||
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);
|
||||
|
|
Loading…
Reference in a new issue