mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 05:23:33 +02:00
Merge branch 'master' into 21872-b
This commit is contained in:
commit
f571e90ef5
35 changed files with 313 additions and 310 deletions
|
@ -7,6 +7,9 @@
|
||||||
//
|
//
|
||||||
// Sends messages over the EventBridge when text input is required.
|
// Sends messages over the EventBridge when text input is required.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/* global document, window, console, setTimeout, setInterval, EventBridge */
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var POLL_FREQUENCY = 500; // ms
|
var POLL_FREQUENCY = 500; // ms
|
||||||
var MAX_WARNINGS = 3;
|
var MAX_WARNINGS = 3;
|
||||||
|
@ -37,22 +40,24 @@
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function shouldSetNumeric() {
|
function shouldSetNumeric() {
|
||||||
return document.activeElement.type === "number";
|
return document.activeElement.type === "number";
|
||||||
};
|
}
|
||||||
|
|
||||||
function scheduleBringToView(timeout) {
|
function scheduleBringToView(timeout) {
|
||||||
|
setTimeout(function () {
|
||||||
var timer = setTimeout(function () {
|
// If the element is not visible because the keyboard has been raised over the top of it, scroll it up into view.
|
||||||
clearTimeout(timer);
|
// If the element is not visible because the keyboard raising has moved it off screen, scroll it down into view.
|
||||||
|
|
||||||
var elementRect = document.activeElement.getBoundingClientRect();
|
var elementRect = document.activeElement.getBoundingClientRect();
|
||||||
var absoluteElementTop = elementRect.top + window.scrollY;
|
var VISUAL_MARGIN = 3;
|
||||||
var middle = absoluteElementTop - (window.innerHeight / 2);
|
var delta = elementRect.y + elementRect.height + VISUAL_MARGIN - window.innerHeight;
|
||||||
|
if (delta > 0) {
|
||||||
window.scrollTo(0, middle);
|
window.scrollBy(0, delta);
|
||||||
|
} else if (elementRect.y < VISUAL_MARGIN) {
|
||||||
|
window.scrollBy(0, elementRect.y - VISUAL_MARGIN);
|
||||||
|
}
|
||||||
}, timeout);
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,11 +67,13 @@
|
||||||
var passwordField = shouldSetPasswordField();
|
var passwordField = shouldSetPasswordField();
|
||||||
|
|
||||||
if (isWindowFocused &&
|
if (isWindowFocused &&
|
||||||
(keyboardRaised !== window.isKeyboardRaised || numericKeyboard !== window.isNumericKeyboard || passwordField !== window.isPasswordField)) {
|
(keyboardRaised !== window.isKeyboardRaised || numericKeyboard !== window.isNumericKeyboard
|
||||||
|
|| passwordField !== window.isPasswordField)) {
|
||||||
|
|
||||||
if (typeof EventBridge !== "undefined" && EventBridge !== null) {
|
if (typeof EventBridge !== "undefined" && EventBridge !== null) {
|
||||||
EventBridge.emitWebEvent(
|
EventBridge.emitWebEvent(
|
||||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "") + (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
|
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "")
|
||||||
|
+ (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (numWarnings < MAX_WARNINGS) {
|
if (numWarnings < MAX_WARNINGS) {
|
||||||
|
|
|
@ -49,6 +49,7 @@ Item {
|
||||||
property string upgradeTitle;
|
property string upgradeTitle;
|
||||||
property bool updateAvailable: root.upgradeUrl !== "" && !root.isShowingMyItems;
|
property bool updateAvailable: root.upgradeUrl !== "" && !root.isShowingMyItems;
|
||||||
property bool isShowingMyItems;
|
property bool isShowingMyItems;
|
||||||
|
property bool valid;
|
||||||
|
|
||||||
property string originalStatusText;
|
property string originalStatusText;
|
||||||
property string originalStatusColor;
|
property string originalStatusColor;
|
||||||
|
@ -239,6 +240,7 @@ Item {
|
||||||
width: 62;
|
width: 62;
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
item.enabled = root.valid;
|
||||||
item.buttonGlyphText = hifi.glyphs.gift;
|
item.buttonGlyphText = hifi.glyphs.gift;
|
||||||
item.buttonText = "Gift";
|
item.buttonText = "Gift";
|
||||||
item.buttonClicked = function() {
|
item.buttonClicked = function() {
|
||||||
|
@ -463,7 +465,7 @@ Item {
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: statusContainer;
|
id: statusContainer;
|
||||||
visible: root.purchaseStatus === "pending" || root.purchaseStatus === "invalidated" || root.numberSold > -1;
|
visible: root.purchaseStatus === "pending" || !root.valid || root.numberSold > -1;
|
||||||
anchors.left: itemName.left;
|
anchors.left: itemName.left;
|
||||||
anchors.right: itemName.right;
|
anchors.right: itemName.right;
|
||||||
anchors.top: itemName.bottom;
|
anchors.top: itemName.bottom;
|
||||||
|
@ -480,7 +482,7 @@ Item {
|
||||||
text: {
|
text: {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
"PENDING..."
|
"PENDING..."
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
"INVALIDATED"
|
"INVALIDATED"
|
||||||
} else if (root.numberSold > -1) {
|
} else if (root.numberSold > -1) {
|
||||||
("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "\u221e" : root.limitedRun))
|
("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "\u221e" : root.limitedRun))
|
||||||
|
@ -492,7 +494,7 @@ Item {
|
||||||
color: {
|
color: {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
hifi.colors.blueAccent
|
hifi.colors.blueAccent
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
hifi.colors.redAccent
|
hifi.colors.redAccent
|
||||||
} else {
|
} else {
|
||||||
hifi.colors.baseGray
|
hifi.colors.baseGray
|
||||||
|
@ -506,7 +508,7 @@ Item {
|
||||||
text: {
|
text: {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
hifi.glyphs.question
|
hifi.glyphs.question
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
hifi.glyphs.question
|
hifi.glyphs.question
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
@ -523,7 +525,7 @@ Item {
|
||||||
color: {
|
color: {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
hifi.colors.blueAccent
|
hifi.colors.blueAccent
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
hifi.colors.redAccent
|
hifi.colors.redAccent
|
||||||
} else {
|
} else {
|
||||||
hifi.colors.baseGray
|
hifi.colors.baseGray
|
||||||
|
@ -538,7 +540,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
sendToPurchases({method: 'showPendingLightbox'});
|
sendToPurchases({method: 'showPendingLightbox'});
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
sendToPurchases({method: 'showInvalidatedLightbox'});
|
sendToPurchases({method: 'showInvalidatedLightbox'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -546,7 +548,7 @@ Item {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
statusText.color = hifi.colors.blueHighlight;
|
statusText.color = hifi.colors.blueHighlight;
|
||||||
statusIcon.color = hifi.colors.blueHighlight;
|
statusIcon.color = hifi.colors.blueHighlight;
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
statusText.color = hifi.colors.redAccent;
|
statusText.color = hifi.colors.redAccent;
|
||||||
statusIcon.color = hifi.colors.redAccent;
|
statusIcon.color = hifi.colors.redAccent;
|
||||||
}
|
}
|
||||||
|
@ -555,7 +557,7 @@ Item {
|
||||||
if (root.purchaseStatus === "pending") {
|
if (root.purchaseStatus === "pending") {
|
||||||
statusText.color = hifi.colors.blueAccent;
|
statusText.color = hifi.colors.blueAccent;
|
||||||
statusIcon.color = hifi.colors.blueAccent;
|
statusIcon.color = hifi.colors.blueAccent;
|
||||||
} else if (root.purchaseStatus === "invalidated") {
|
} else if (!root.valid) {
|
||||||
statusText.color = hifi.colors.redHighlight;
|
statusText.color = hifi.colors.redHighlight;
|
||||||
statusIcon.color = hifi.colors.redHighlight;
|
statusIcon.color = hifi.colors.redHighlight;
|
||||||
}
|
}
|
||||||
|
@ -645,8 +647,8 @@ Item {
|
||||||
width: 160;
|
width: 160;
|
||||||
height: 40;
|
height: 40;
|
||||||
enabled: root.hasPermissionToRezThis &&
|
enabled: root.hasPermissionToRezThis &&
|
||||||
root.purchaseStatus !== "invalidated" &&
|
MyAvatar.skeletonModelURL !== root.itemHref &&
|
||||||
MyAvatar.skeletonModelURL !== root.itemHref;
|
root.valid;
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
|
|
|
@ -616,6 +616,7 @@ Rectangle {
|
||||||
upgradeTitle: model.upgrade_title;
|
upgradeTitle: model.upgrade_title;
|
||||||
itemType: model.itemType;
|
itemType: model.itemType;
|
||||||
isShowingMyItems: root.isShowingMyItems;
|
isShowingMyItems: root.isShowingMyItems;
|
||||||
|
valid: model.valid;
|
||||||
anchors.topMargin: 10;
|
anchors.topMargin: 10;
|
||||||
anchors.bottomMargin: 10;
|
anchors.bottomMargin: 10;
|
||||||
|
|
||||||
|
@ -995,10 +996,6 @@ Rectangle {
|
||||||
|
|
||||||
for (var i = 0; i < purchasesModel.count; i++) {
|
for (var i = 0; i < purchasesModel.count; i++) {
|
||||||
if (purchasesModel.get(i).title.toLowerCase().indexOf(filterBar.text.toLowerCase()) !== -1) {
|
if (purchasesModel.get(i).title.toLowerCase().indexOf(filterBar.text.toLowerCase()) !== -1) {
|
||||||
if (!purchasesModel.get(i).valid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (purchasesModel.get(i).status !== "confirmed" && !root.isShowingMyItems) {
|
if (purchasesModel.get(i).status !== "confirmed" && !root.isShowingMyItems) {
|
||||||
tempPurchasesModel.insert(0, purchasesModel.get(i));
|
tempPurchasesModel.insert(0, purchasesModel.get(i));
|
||||||
} else if ((root.isShowingMyItems && purchasesModel.get(i).edition_number === "0") ||
|
} else if ((root.isShowingMyItems && purchasesModel.get(i).edition_number === "0") ||
|
||||||
|
@ -1055,10 +1052,6 @@ Rectangle {
|
||||||
var currentId;
|
var currentId;
|
||||||
for (var i = 0; i < tempPurchasesModel.count; i++) {
|
for (var i = 0; i < tempPurchasesModel.count; i++) {
|
||||||
currentId = tempPurchasesModel.get(i).id;
|
currentId = tempPurchasesModel.get(i).id;
|
||||||
|
|
||||||
if (!purchasesModel.get(i).valid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
filteredPurchasesModel.append(tempPurchasesModel.get(i));
|
filteredPurchasesModel.append(tempPurchasesModel.get(i));
|
||||||
filteredPurchasesModel.setProperty(i, 'cardBackVisible', false);
|
filteredPurchasesModel.setProperty(i, 'cardBackVisible', false);
|
||||||
filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1));
|
filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1));
|
||||||
|
|
|
@ -735,9 +735,9 @@ extern InputPluginList getInputPlugins();
|
||||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||||
|
|
||||||
// Parameters used for running tests from teh command line
|
// Parameters used for running tests from teh command line
|
||||||
const QString TEST_SCRIPT_COMMAND { "--testScript" };
|
const QString TEST_SCRIPT_COMMAND{ "--testScript" };
|
||||||
const QString TEST_QUIT_WHEN_FINISHED_OPTION { "quitWhenFinished" };
|
const QString TEST_QUIT_WHEN_FINISHED_OPTION{ "quitWhenFinished" };
|
||||||
const QString TEST_SNAPSHOT_LOCATION_COMMAND { "--testSnapshotLocation" };
|
const QString TEST_RESULTS_LOCATION_COMMAND{ "--testResultsLocation" };
|
||||||
|
|
||||||
bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
const char** constArgv = const_cast<const char**>(argv);
|
const char** constArgv = const_cast<const char**>(argv);
|
||||||
|
@ -1015,7 +1015,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
// If the URL scheme is http(s) or ftp, then use as is, else - treat it as a local file
|
// If the URL scheme is http(s) or ftp, then use as is, else - treat it as a local file
|
||||||
// This is done so as not break previous command line scripts
|
// This is done so as not break previous command line scripts
|
||||||
if (testScriptPath.left(URL_SCHEME_HTTP.length()) == URL_SCHEME_HTTP || testScriptPath.left(URL_SCHEME_FTP.length()) == URL_SCHEME_FTP) {
|
if (testScriptPath.left(URL_SCHEME_HTTP.length()) == URL_SCHEME_HTTP ||
|
||||||
|
testScriptPath.left(URL_SCHEME_FTP.length()) == URL_SCHEME_FTP) {
|
||||||
|
|
||||||
setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath));
|
setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath));
|
||||||
} else if (QFileInfo(testScriptPath).exists()) {
|
} else if (QFileInfo(testScriptPath).exists()) {
|
||||||
setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath));
|
setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath));
|
||||||
|
@ -1025,12 +1027,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED_OPTION) {
|
if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED_OPTION) {
|
||||||
quitWhenFinished = true;
|
quitWhenFinished = true;
|
||||||
}
|
}
|
||||||
} else if (args.at(i) == TEST_SNAPSHOT_LOCATION_COMMAND) {
|
} else if (args.at(i) == TEST_RESULTS_LOCATION_COMMAND) {
|
||||||
// Set test snapshot location only if it is a writeable directory
|
// Set test snapshot location only if it is a writeable directory
|
||||||
QString pathname(args.at(i + 1));
|
QString path(args.at(i + 1));
|
||||||
QFileInfo fileInfo(pathname);
|
|
||||||
|
QFileInfo fileInfo(path);
|
||||||
if (fileInfo.isDir() && fileInfo.isWritable()) {
|
if (fileInfo.isDir() && fileInfo.isWritable()) {
|
||||||
testSnapshotLocation = pathname;
|
TestScriptingInterface::getInstance()->setTestResultsLocation(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7588,7 +7591,9 @@ void Application::loadAvatarBrowser() const {
|
||||||
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) {
|
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) {
|
||||||
postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] {
|
postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] {
|
||||||
// Get a screenshot and save it
|
// Get a screenshot and save it
|
||||||
QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, testSnapshotLocation);
|
QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename,
|
||||||
|
TestScriptingInterface::getInstance()->getTestResultsLocation());
|
||||||
|
|
||||||
// If we're not doing an animated snapshot as well...
|
// If we're not doing an animated snapshot as well...
|
||||||
if (!includeAnimated) {
|
if (!includeAnimated) {
|
||||||
// Tell the dependency manager that the capture of the still snapshot has taken place.
|
// Tell the dependency manager that the capture of the still snapshot has taken place.
|
||||||
|
@ -7602,7 +7607,9 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa
|
||||||
|
|
||||||
void Application::takeSecondaryCameraSnapshot(const QString& filename) {
|
void Application::takeSecondaryCameraSnapshot(const QString& filename) {
|
||||||
postLambdaEvent([filename, this] {
|
postLambdaEvent([filename, this] {
|
||||||
QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename, testSnapshotLocation);
|
QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename,
|
||||||
|
TestScriptingInterface::getInstance()->getTestResultsLocation());
|
||||||
|
|
||||||
emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true);
|
emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,7 +419,6 @@ public slots:
|
||||||
void updateVerboseLogging();
|
void updateVerboseLogging();
|
||||||
Q_INVOKABLE void openAndroidActivity(const QString& activityName);
|
Q_INVOKABLE void openAndroidActivity(const QString& activityName);
|
||||||
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onDesktopRootItemCreated(QQuickItem* qmlContext);
|
void onDesktopRootItemCreated(QQuickItem* qmlContext);
|
||||||
void onDesktopRootContextCreated(QQmlContext* qmlContext);
|
void onDesktopRootContextCreated(QQmlContext* qmlContext);
|
||||||
|
@ -753,7 +752,6 @@ private:
|
||||||
std::atomic<bool> _pendingIdleEvent { true };
|
std::atomic<bool> _pendingIdleEvent { true };
|
||||||
std::atomic<bool> _pendingRenderEvent { true };
|
std::atomic<bool> _pendingRenderEvent { true };
|
||||||
|
|
||||||
QString testSnapshotLocation;
|
|
||||||
bool quitWhenFinished { false };
|
bool quitWhenFinished { false };
|
||||||
};
|
};
|
||||||
#endif // hifi_Application_h
|
#endif // hifi_Application_h
|
||||||
|
|
|
@ -70,7 +70,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
// Note: we MUST clamp the blend to 1.0 for stability
|
// Note: we MUST clamp the blend to 1.0 for stability
|
||||||
float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
|
float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
|
||||||
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec
|
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec
|
||||||
if (!_automaticLODAdjust) {
|
if (!_automaticLODAdjust || _avgRenderTime == 0.0f) {
|
||||||
// early exit
|
// early exit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,6 @@ namespace MenuOption {
|
||||||
const QString ShowOtherLookAtVectors = "Show Other Eye Vectors";
|
const QString ShowOtherLookAtVectors = "Show Other Eye Vectors";
|
||||||
const QString EnableLookAtSnapping = "Enable LookAt Snapping";
|
const QString EnableLookAtSnapping = "Enable LookAt Snapping";
|
||||||
const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats";
|
const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats";
|
||||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode";
|
|
||||||
const QString SimulateEyeTracking = "Simulate";
|
const QString SimulateEyeTracking = "Simulate";
|
||||||
const QString SMIEyeTracking = "SMI Eye Tracking";
|
const QString SMIEyeTracking = "SMI Eye Tracking";
|
||||||
const QString SparseTextureManagement = "Enable Sparse Texture Management";
|
const QString SparseTextureManagement = "Enable Sparse Texture Management";
|
||||||
|
|
|
@ -160,3 +160,29 @@ void TestScriptingInterface::clearCaches() {
|
||||||
qApp->reloadResourceCaches();
|
qApp->reloadResourceCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes a JSON object from javascript to a file
|
||||||
|
void TestScriptingInterface::saveObject(QVariant variant, const QString& filename) {
|
||||||
|
if (_testResultsLocation.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument jsonDocument;
|
||||||
|
jsonDocument = QJsonDocument::fromVariant(variant);
|
||||||
|
if (jsonDocument.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray jsonData = jsonDocument.toJson();
|
||||||
|
|
||||||
|
// Append trailing slash if needed
|
||||||
|
if (_testResultsLocation.right(1) != "/") {
|
||||||
|
_testResultsLocation += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString filepath = QDir::cleanPath(_testResultsLocation + filename);
|
||||||
|
QFile file(filepath);
|
||||||
|
|
||||||
|
file.open(QFile::WriteOnly);
|
||||||
|
file.write(jsonData);
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,10 @@ class QScriptValue;
|
||||||
class TestScriptingInterface : public QObject {
|
class TestScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setTestResultsLocation(const QString path) { _testResultsLocation = path; }
|
||||||
|
const QString& getTestResultsLocation() { return _testResultsLocation; };
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
static TestScriptingInterface* getInstance();
|
static TestScriptingInterface* getInstance();
|
||||||
|
|
||||||
|
@ -46,7 +50,6 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void waitIdle();
|
void waitIdle();
|
||||||
|
|
||||||
|
|
||||||
bool waitForConnection(qint64 maxWaitMs = 10000);
|
bool waitForConnection(qint64 maxWaitMs = 10000);
|
||||||
|
|
||||||
void wait(int milliseconds);
|
void wait(int milliseconds);
|
||||||
|
@ -83,8 +86,14 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void clearCaches();
|
void clearCaches();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Save a JSON object to a file in the test results location
|
||||||
|
*/
|
||||||
|
void saveObject(QVariant v, const QString& filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool waitForCondition(qint64 maxWaitMs, std::function<bool()> condition);
|
bool waitForCondition(qint64 maxWaitMs, std::function<bool()> condition);
|
||||||
|
QString _testResultsLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_TestScriptingInterface_h
|
#endif // hifi_TestScriptingInterface_h
|
||||||
|
|
|
@ -481,8 +481,8 @@ public slots:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Gets the status of server entity script attached to an entity
|
* Gets the status of server entity script attached to an entity
|
||||||
* @function Entities.getServerScriptStatus
|
* @function Entities.getServerScriptStatus
|
||||||
* @property {Uuid} entityID - The ID of the entity to get the server entity script status for.
|
* @param {Uuid} entityID - The ID of the entity to get the server entity script status for.
|
||||||
* @property {Entities~getServerScriptStatusCallback} callback - The function to call upon completion.
|
* @param {Entities~getServerScriptStatusCallback} callback - The function to call upon completion.
|
||||||
* @returns {boolean} <code>true</code> always.
|
* @returns {boolean} <code>true</code> always.
|
||||||
*/
|
*/
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -731,7 +731,9 @@ void EntityMotionState::measureBodyAcceleration() {
|
||||||
// hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt
|
// hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt
|
||||||
glm::vec3 velocity = getBodyLinearVelocityGTSigma();
|
glm::vec3 velocity = getBodyLinearVelocityGTSigma();
|
||||||
|
|
||||||
_measuredAcceleration = (velocity / powf(1.0f - _body->getLinearDamping(), dt) - _lastVelocity) * invDt;
|
const float MIN_DAMPING_FACTOR = 0.01f;
|
||||||
|
float invDampingAttenuationFactor = 1.0f / glm::max(powf(1.0f - _body->getLinearDamping(), dt), MIN_DAMPING_FACTOR);
|
||||||
|
_measuredAcceleration = (velocity * invDampingAttenuationFactor - _lastVelocity) * invDt;
|
||||||
_lastVelocity = velocity;
|
_lastVelocity = velocity;
|
||||||
if (numSubsteps > PHYSICS_ENGINE_MAX_NUM_SUBSTEPS) {
|
if (numSubsteps > PHYSICS_ENGINE_MAX_NUM_SUBSTEPS) {
|
||||||
// we fall in here when _lastMeasureStep is old: the body has just become active
|
// we fall in here when _lastMeasureStep is old: the body has just become active
|
||||||
|
|
|
@ -149,9 +149,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
|
||||||
batch.setStateScissorRect(viewport);
|
batch.setStateScissorRect(viewport);
|
||||||
|
|
||||||
batch.setFramebuffer(fbo);
|
batch.setFramebuffer(fbo);
|
||||||
batch.clearFramebuffer(
|
batch.clearDepthFramebuffer(1.0, false);
|
||||||
gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH,
|
|
||||||
vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true);
|
|
||||||
|
|
||||||
glm::mat4 projMat;
|
glm::mat4 projMat;
|
||||||
Transform viewMat;
|
Transform viewMat;
|
||||||
|
@ -232,12 +230,11 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
||||||
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Outputs>(2);
|
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Outputs>(2);
|
||||||
// Fetch and cull the items from the scene
|
// Fetch and cull the items from the scene
|
||||||
|
|
||||||
// Enable models to not cast shadows (otherwise, models will always cast shadows)
|
static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
|
||||||
static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster();
|
|
||||||
|
|
||||||
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying();
|
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying();
|
||||||
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
||||||
const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying();
|
const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
|
||||||
const auto shadowItems = task.addJob<FetchSpatialSelection>("FetchShadowSelection", selectionInputs);
|
const auto shadowItems = task.addJob<FetchSpatialSelection>("FetchShadowSelection", selectionInputs);
|
||||||
|
|
||||||
// Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not
|
// Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not
|
||||||
|
@ -261,21 +258,22 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
||||||
char jobName[64];
|
char jobName[64];
|
||||||
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
||||||
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, i, _cullFunctor, tagBits, tagMask);
|
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, i, _cullFunctor, tagBits, tagMask);
|
||||||
const auto shadowFilter = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(0);
|
const auto shadowRenderFilter = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(0);
|
||||||
|
const auto shadowBoundsFilter = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(1);
|
||||||
auto antiFrustum = render::Varying(ViewFrustumPointer());
|
auto antiFrustum = render::Varying(ViewFrustumPointer());
|
||||||
cascadeFrustums[i] = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(1);
|
cascadeFrustums[i] = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(2);
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
antiFrustum = cascadeFrustums[i - 2];
|
antiFrustum = cascadeFrustums[i - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// CPU jobs: finer grained culling
|
// CPU jobs: finer grained culling
|
||||||
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter, antiFrustum).asVarying();
|
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowRenderFilter, shadowBoundsFilter, antiFrustum).asVarying();
|
||||||
const auto culledShadowItemsAndBounds = task.addJob<CullShapeBounds>("CullShadowCascade", cullInputs, shadowCullFunctor, RenderDetails::SHADOW);
|
const auto culledShadowItemsAndBounds = task.addJob<CullShapeBounds>("CullShadowCascade", cullInputs, shadowCullFunctor, RenderDetails::SHADOW);
|
||||||
|
|
||||||
// GPU jobs: Render to shadow map
|
// GPU jobs: Render to shadow map
|
||||||
sprintf(jobName, "RenderShadowMap%d", i);
|
sprintf(jobName, "RenderShadowMap%d", i);
|
||||||
task.addJob<RenderShadowMap>(jobName, culledShadowItemsAndBounds, shapePlumber, i);
|
task.addJob<RenderShadowMap>(jobName, culledShadowItemsAndBounds, shapePlumber, i);
|
||||||
task.addJob<RenderShadowCascadeTeardown>("ShadowCascadeTeardown", shadowFilter);
|
task.addJob<RenderShadowCascadeTeardown>("ShadowCascadeTeardown", shadowRenderFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
task.addJob<RenderShadowTeardown>("ShadowTeardown", setupOutput);
|
task.addJob<RenderShadowTeardown>("ShadowTeardown", setupOutput);
|
||||||
|
@ -406,7 +404,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
||||||
|
|
||||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||||
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
||||||
output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster();
|
auto baseFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask);
|
||||||
|
// Second item filter is to filter items to keep in shadow frustum computation (here we need to keep shadow receivers)
|
||||||
|
output.edit1() = baseFilter;
|
||||||
|
// First item filter is to filter items to render in shadow map (so only keep casters)
|
||||||
|
output.edit0() = baseFilter.withShadowCaster();
|
||||||
|
|
||||||
// Set the keylight render args
|
// Set the keylight render args
|
||||||
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
||||||
|
@ -419,10 +421,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
||||||
texelSize *= minTexelCount;
|
texelSize *= minTexelCount;
|
||||||
_cullFunctor._minSquareSize = texelSize * texelSize;
|
_cullFunctor._minSquareSize = texelSize * texelSize;
|
||||||
|
|
||||||
output.edit1() = cascadeFrustum;
|
output.edit2() = cascadeFrustum;
|
||||||
} else {
|
} else {
|
||||||
output.edit0() = ItemFilter::Builder::nothing();
|
output.edit0() = ItemFilter::Builder::nothing();
|
||||||
output.edit1() = ViewFrustumPointer();
|
output.edit1() = ItemFilter::Builder::nothing();
|
||||||
|
output.edit2() = ViewFrustumPointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ private:
|
||||||
|
|
||||||
class RenderShadowCascadeSetup {
|
class RenderShadowCascadeSetup {
|
||||||
public:
|
public:
|
||||||
using Outputs = render::VaryingSet2<render::ItemFilter, ViewFrustumPointer>;
|
using Outputs = render::VaryingSet3<render::ItemFilter, render::ItemFilter, ViewFrustumPointer>;
|
||||||
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
||||||
|
|
||||||
RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) :
|
RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) :
|
||||||
|
|
|
@ -368,17 +368,19 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
const auto& inShapes = inputs.get0();
|
const auto& inShapes = inputs.get0();
|
||||||
const auto& filter = inputs.get1();
|
const auto& cullFilter = inputs.get1();
|
||||||
const auto& antiFrustum = inputs.get2();
|
const auto& boundsFilter = inputs.get2();
|
||||||
|
const auto& antiFrustum = inputs.get3();
|
||||||
auto& outShapes = outputs.edit0();
|
auto& outShapes = outputs.edit0();
|
||||||
auto& outBounds = outputs.edit1();
|
auto& outBounds = outputs.edit1();
|
||||||
|
|
||||||
outShapes.clear();
|
outShapes.clear();
|
||||||
outBounds = AABox();
|
outBounds = AABox();
|
||||||
|
|
||||||
if (!filter.selectsNothing()) {
|
if (!cullFilter.selectsNothing() || !boundsFilter.selectsNothing()) {
|
||||||
auto& details = args->_details.edit(_detailType);
|
auto& details = args->_details.edit(_detailType);
|
||||||
Test test(_cullFunctor, args, details, antiFrustum);
|
Test test(_cullFunctor, args, details, antiFrustum);
|
||||||
|
auto scene = args->_scene;
|
||||||
|
|
||||||
for (auto& inItems : inShapes) {
|
for (auto& inItems : inShapes) {
|
||||||
auto key = inItems.first;
|
auto key = inItems.first;
|
||||||
|
@ -393,18 +395,28 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input
|
||||||
if (antiFrustum == nullptr) {
|
if (antiFrustum == nullptr) {
|
||||||
for (auto& item : inItems.second) {
|
for (auto& item : inItems.second) {
|
||||||
if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound)) {
|
if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound)) {
|
||||||
|
const auto shapeKey = scene->getItem(item.id).getKey();
|
||||||
|
if (cullFilter.test(shapeKey)) {
|
||||||
outItems->second.emplace_back(item);
|
outItems->second.emplace_back(item);
|
||||||
|
}
|
||||||
|
if (boundsFilter.test(shapeKey)) {
|
||||||
outBounds += item.bound;
|
outBounds += item.bound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto& item : inItems.second) {
|
for (auto& item : inItems.second) {
|
||||||
if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound) && test.antiFrustumTest(item.bound)) {
|
if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound) && test.antiFrustumTest(item.bound)) {
|
||||||
|
const auto shapeKey = scene->getItem(item.id).getKey();
|
||||||
|
if (cullFilter.test(shapeKey)) {
|
||||||
outItems->second.emplace_back(item);
|
outItems->second.emplace_back(item);
|
||||||
|
}
|
||||||
|
if (boundsFilter.test(shapeKey)) {
|
||||||
outBounds += item.bound;
|
outBounds += item.bound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
details._rendered += (int)outItems->second.size();
|
details._rendered += (int)outItems->second.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace render {
|
||||||
|
|
||||||
class CullShapeBounds {
|
class CullShapeBounds {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet3<ShapeBounds, ItemFilter, ViewFrustumPointer>;
|
using Inputs = render::VaryingSet4<ShapeBounds, ItemFilter, ItemFilter, ViewFrustumPointer>;
|
||||||
using Outputs = render::VaryingSet2<ShapeBounds, AABox>;
|
using Outputs = render::VaryingSet2<ShapeBounds, AABox>;
|
||||||
using JobModel = Job::ModelIO<CullShapeBounds, Inputs, Outputs>;
|
using JobModel = Job::ModelIO<CullShapeBounds, Inputs, Outputs>;
|
||||||
|
|
||||||
|
|
|
@ -186,36 +186,36 @@ public:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.deleteAsset
|
* @function Assets.deleteAsset
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback = ""]
|
* @param {} [callback = ""]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void deleteAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void deleteAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.resolveAsset
|
* @function Assets.resolveAsset
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback = ""]
|
* @param {} [callback = ""]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void resolveAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void resolveAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.decompressData
|
* @function Assets.decompressData
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback = ""]
|
* @param {} [callback = ""]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void decompressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void decompressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.compressData
|
* @function Assets.compressData
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback = ""]
|
* @param {} [callback = ""]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void compressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void compressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
@ -229,7 +229,7 @@ public:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.canWriteCacheValue
|
* @function Assets.canWriteCacheValue
|
||||||
* @property {string} url
|
* @param {string} url
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -237,8 +237,8 @@ public:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.getCacheStatus
|
* @function Assets.getCacheStatus
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback=undefined]
|
* @param {} [callback=undefined]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void getCacheStatus(QScriptValue scope, QScriptValue callback = QScriptValue()) {
|
Q_INVOKABLE void getCacheStatus(QScriptValue scope, QScriptValue callback = QScriptValue()) {
|
||||||
|
@ -247,38 +247,38 @@ public:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.queryCacheMeta
|
* @function Assets.queryCacheMeta
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback=undefined]
|
* @param {} [callback=undefined]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void queryCacheMeta(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void queryCacheMeta(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.loadFromCache
|
* @function Assets.loadFromCache
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback=undefined]
|
* @param {} [callback=undefined]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void loadFromCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void loadFromCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.saveToCache
|
* @function Assets.saveToCache
|
||||||
* @property {} options
|
* @param {} options
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback=undefined]
|
* @param {} [callback=undefined]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void saveToCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
Q_INVOKABLE void saveToCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function Assets.saveToCache
|
* @function Assets.saveToCache
|
||||||
* @property {} url
|
* @param {} url
|
||||||
* @property {} data
|
* @param {} data
|
||||||
* @property {} metadata
|
* @param {} metadata
|
||||||
* @property {} scope
|
* @param {} scope
|
||||||
* @property {} [callback=undefined]
|
* @param {} [callback=undefined]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Q_INVOKABLE void saveToCache(const QUrl& url, const QByteArray& data, const QVariantMap& metadata,
|
Q_INVOKABLE void saveToCache(const QUrl& url, const QByteArray& data, const QVariantMap& metadata,
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||||
|
|
||||||
const char* StandingHMDSensorMode { "Standing HMD Sensor Mode" }; // this probably shouldn't be hardcoded here
|
|
||||||
const char* OpenVrThreadedSubmit { "OpenVR Threaded Submit" }; // this probably shouldn't be hardcoded here
|
const char* OpenVrThreadedSubmit { "OpenVR Threaded Submit" }; // this probably shouldn't be hardcoded here
|
||||||
|
|
||||||
PoseData _nextRenderPoseData;
|
PoseData _nextRenderPoseData;
|
||||||
|
@ -451,7 +450,6 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit;
|
qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit;
|
||||||
|
|
||||||
_openVrDisplayActive = true;
|
_openVrDisplayActive = true;
|
||||||
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
|
||||||
_system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
|
_system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
|
||||||
// Recommended render target size is per-eye, so double the X size for
|
// Recommended render target size is per-eye, so double the X size for
|
||||||
// left + right eyes
|
// left + right eyes
|
||||||
|
@ -507,7 +505,6 @@ void OpenVrDisplayPlugin::internalDeactivate() {
|
||||||
Parent::internalDeactivate();
|
Parent::internalDeactivate();
|
||||||
|
|
||||||
_openVrDisplayActive = false;
|
_openVrDisplayActive = false;
|
||||||
_container->setIsOptionChecked(StandingHMDSensorMode, false);
|
|
||||||
if (_system) {
|
if (_system) {
|
||||||
// TODO: Invalidate poses. It's fine if someone else sets these shared values, but we're about to stop updating them, and
|
// TODO: Invalidate poses. It's fine if someone else sets these shared values, but we're about to stop updating them, and
|
||||||
// we don't want ViveControllerManager to consider old values to be valid.
|
// we don't want ViveControllerManager to consider old values to be valid.
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
|
||||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, Camera,
|
||||||
getControllerJointIndex, enableDispatcherModule, disableDispatcherModule,
|
getControllerJointIndex, enableDispatcherModule, disableDispatcherModule, entityIsFarGrabbedByOther,
|
||||||
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
|
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
|
||||||
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable,
|
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable,
|
||||||
cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid, unhighlightTargetEntity
|
cloneEntity, DISPATCHER_PROPERTIES, Uuid, unhighlightTargetEntity, isInEditMode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/Xform.js");
|
Script.include("/~/system/libraries/Xform.js");
|
||||||
|
@ -828,7 +828,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
};
|
};
|
||||||
|
|
||||||
var onKeyPress = function(event) {
|
var onKeyPress = function(event) {
|
||||||
if (event.text === UNEQUIP_KEY) {
|
if (event.text.toLowerCase() === UNEQUIP_KEY) {
|
||||||
if (rightEquipEntity.targetEntityID) {
|
if (rightEquipEntity.targetEntityID) {
|
||||||
rightEquipEntity.endEquipEntity();
|
rightEquipEntity.endEquipEntity();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
||||||
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
|
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
|
||||||
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity,
|
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity,
|
||||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, unhighlightTargetEntity
|
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, unhighlightTargetEntity, Uuid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
|
|
@ -7,12 +7,8 @@
|
||||||
// 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
|
||||||
|
|
||||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
/* global Script, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule,
|
||||||
getControllerJointIndex, getGrabbableData, enableDispatcherModule, disableDispatcherModule,
|
makeDispatcherModuleParameters, makeRunningValues, TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, BUMPER_ON_VALUE, AddressManager
|
||||||
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
|
||||||
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
|
|
||||||
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity,
|
|
||||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, AddressManager
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS,
|
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS,
|
||||||
findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH,
|
findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH,
|
||||||
HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME,
|
HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME,
|
||||||
TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Selection, DISPATCHER_HOVERING_LIST, Uuid,
|
TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity
|
||||||
highlightTargetEntity, unhighlightTargetEntity
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -43,11 +42,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
[],
|
[],
|
||||||
100);
|
100);
|
||||||
|
|
||||||
|
|
||||||
// XXX does handJointIndex change if the avatar changes?
|
|
||||||
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
|
||||||
this.controllerJointIndex = getControllerJointIndex(this.hand);
|
|
||||||
|
|
||||||
this.thisHandIsParent = function(props) {
|
this.thisHandIsParent = function(props) {
|
||||||
if (!props) {
|
if (!props) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -62,8 +56,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var controllerJointIndex = this.controllerJointIndex;
|
if (props.parentJointIndex === getControllerJointIndex(this.hand)) {
|
||||||
if (props.parentJointIndex === controllerJointIndex) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +95,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
// } else {
|
// } else {
|
||||||
// handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
// handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||||
// }
|
// }
|
||||||
handJointIndex = this.controllerJointIndex;
|
handJointIndex = getControllerJointIndex(this.hand);
|
||||||
|
|
||||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
Entities.callEntityMethod(targetProps.id, "startNearGrab", args);
|
Entities.callEntityMethod(targetProps.id, "startNearGrab", args);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
/* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex,
|
/* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex,
|
||||||
enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
||||||
makeDispatcherModuleParameters, Overlays, makeRunningValues, Vec3, resizeTablet, getTabletWidthFromSettings,
|
makeDispatcherModuleParameters, Overlays, makeRunningValues, Vec3, resizeTablet, getTabletWidthFromSettings,
|
||||||
NEAR_GRAB_RADIUS
|
NEAR_GRAB_RADIUS, HMD, Uuid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -37,7 +37,6 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
|
|
||||||
// XXX does handJointIndex change if the avatar changes?
|
// XXX does handJointIndex change if the avatar changes?
|
||||||
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||||
this.controllerJointIndex = getControllerJointIndex(this.hand);
|
|
||||||
|
|
||||||
this.getOtherModule = function() {
|
this.getOtherModule = function() {
|
||||||
return (this.hand === RIGHT_HAND) ? leftNearParentingGrabOverlay : rightNearParentingGrabOverlay;
|
return (this.hand === RIGHT_HAND) ? leftNearParentingGrabOverlay : rightNearParentingGrabOverlay;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
/* jslint bitwise: true */
|
/* jslint bitwise: true */
|
||||||
|
|
||||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex,
|
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
||||||
enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Vec3,
|
enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Vec3,
|
||||||
HMD, Uuid, AvatarList, Picks, Pointers, PickType
|
HMD, Uuid, AvatarList, Picks, Pointers, PickType
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
||||||
<script type="text/javascript" src="js/spinButtons.js"></script>
|
<script type="text/javascript" src="js/spinButtons.js"></script>
|
||||||
<script type="text/javascript" src="js/keyboardControl.js"></script>
|
|
||||||
<script type="text/javascript" src="js/entityList.js"></script>
|
<script type="text/javascript" src="js/entityList.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body onload='loaded();'>
|
<body onload='loaded();'>
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
||||||
<script type="text/javascript" src="js/spinButtons.js"></script>
|
<script type="text/javascript" src="js/spinButtons.js"></script>
|
||||||
<script type="text/javascript" src="js/keyboardControl.js"></script>
|
|
||||||
<script type="text/javascript" src="js/entityProperties.js"></script>
|
<script type="text/javascript" src="js/entityProperties.js"></script>
|
||||||
<script src="js/jsoneditor.min.js"></script>
|
<script src="js/jsoneditor.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
||||||
<script type="text/javascript" src="js/spinButtons.js"></script>
|
<script type="text/javascript" src="js/spinButtons.js"></script>
|
||||||
<script type="text/javascript" src="js/keyboardControl.js"></script>
|
|
||||||
<script type="text/javascript" src="js/gridControls.js"></script>
|
<script type="text/javascript" src="js/gridControls.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body onload='loaded();'>
|
<body onload='loaded();'>
|
||||||
|
|
|
@ -444,8 +444,6 @@ function loaded() {
|
||||||
|
|
||||||
augmentSpinButtons();
|
augmentSpinButtons();
|
||||||
|
|
||||||
setUpKeyboardControl();
|
|
||||||
|
|
||||||
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
||||||
document.addEventListener("contextmenu", function (event) {
|
document.addEventListener("contextmenu", function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
/* global alert, augmentSpinButtons, clearTimeout, console, document, Element, EventBridge,
|
/* global alert, augmentSpinButtons, clearTimeout, console, document, Element, EventBridge,
|
||||||
HifiEntityUI, JSONEditor, openEventBridge, setUpKeyboardControl, setTimeout, window, _ $ */
|
HifiEntityUI, JSONEditor, openEventBridge, setTimeout, window, _ $ */
|
||||||
|
|
||||||
var PI = 3.14159265358979;
|
var PI = 3.14159265358979;
|
||||||
var DEGREES_TO_RADIANS = PI / 180.0;
|
var DEGREES_TO_RADIANS = PI / 180.0;
|
||||||
|
@ -2157,8 +2157,6 @@ function loaded() {
|
||||||
|
|
||||||
augmentSpinButtons();
|
augmentSpinButtons();
|
||||||
|
|
||||||
setUpKeyboardControl();
|
|
||||||
|
|
||||||
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
||||||
document.addEventListener("contextmenu", function(event) {
|
document.addEventListener("contextmenu", function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -129,8 +129,6 @@ function loaded() {
|
||||||
|
|
||||||
augmentSpinButtons();
|
augmentSpinButtons();
|
||||||
|
|
||||||
setUpKeyboardControl();
|
|
||||||
|
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
||||||
});
|
});
|
||||||
document.addEventListener("keydown", function (keyDown) {
|
document.addEventListener("keydown", function (keyDown) {
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
//
|
|
||||||
// keyboardControl.js
|
|
||||||
//
|
|
||||||
// Created by David Rowe on 28 Sep 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
|
|
||||||
//
|
|
||||||
|
|
||||||
function setUpKeyboardControl() {
|
|
||||||
|
|
||||||
var lowerTimer = null;
|
|
||||||
var isRaised = false;
|
|
||||||
var KEYBOARD_HEIGHT = 200;
|
|
||||||
|
|
||||||
function raiseKeyboard() {
|
|
||||||
window.isKeyboardRaised = true;
|
|
||||||
window.isNumericKeyboard = this.type === "number";
|
|
||||||
|
|
||||||
if (lowerTimer !== null) {
|
|
||||||
clearTimeout(lowerTimer);
|
|
||||||
lowerTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventBridge.emitWebEvent("_RAISE_KEYBOARD" + (this.type === "number" ? "_NUMERIC" : ""));
|
|
||||||
|
|
||||||
if (!isRaised) {
|
|
||||||
var delta = this.getBoundingClientRect().bottom + 10 - (document.body.clientHeight - KEYBOARD_HEIGHT);
|
|
||||||
if (delta > 0) {
|
|
||||||
setTimeout(function () {
|
|
||||||
document.body.scrollTop += delta;
|
|
||||||
}, 500); // Allow time for keyboard to be raised in QML.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isRaised = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doLowerKeyboard() {
|
|
||||||
window.isKeyboardRaised = false;
|
|
||||||
window.isNumericKeyboard = false;
|
|
||||||
|
|
||||||
EventBridge.emitWebEvent("_LOWER_KEYBOARD");
|
|
||||||
lowerTimer = null;
|
|
||||||
isRaised = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function lowerKeyboard() {
|
|
||||||
// Delay lowering keyboard a little in case immediately raise it again.
|
|
||||||
if (lowerTimer === null) {
|
|
||||||
lowerTimer = setTimeout(doLowerKeyboard, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function documentBlur() {
|
|
||||||
// Action any pending Lower keyboard event immediately upon leaving document window so that they don't interfere with
|
|
||||||
// other Entities Editor tab.
|
|
||||||
if (lowerTimer !== null) {
|
|
||||||
clearTimeout(lowerTimer);
|
|
||||||
doLowerKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var inputs = document.querySelectorAll("input[type=text], input[type=password], input[type=number], textarea");
|
|
||||||
for (var i = 0, length = inputs.length; i < length; i++) {
|
|
||||||
inputs[i].addEventListener("focus", raiseKeyboard);
|
|
||||||
inputs[i].addEventListener("blur", lowerKeyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("blur", documentBlur);
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* global module, Camera, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays, Xform,
|
/* global module, Camera, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays, Xform,
|
||||||
Selection,
|
Selection, Uuid,
|
||||||
MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, FORBIDDEN_GRAB_TYPES:true,
|
MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, FORBIDDEN_GRAB_TYPES:true,
|
||||||
HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true,
|
HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true,
|
||||||
DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true,
|
DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true,
|
||||||
|
@ -34,11 +34,12 @@
|
||||||
getGrabbableData:true,
|
getGrabbableData:true,
|
||||||
entityIsGrabbable:true,
|
entityIsGrabbable:true,
|
||||||
entityIsDistanceGrabbable:true,
|
entityIsDistanceGrabbable:true,
|
||||||
|
getControllerJointIndexCacheTime:true,
|
||||||
|
getControllerJointIndexCache:true,
|
||||||
getControllerJointIndex:true,
|
getControllerJointIndex:true,
|
||||||
propsArePhysical:true,
|
propsArePhysical:true,
|
||||||
controllerDispatcherPluginsNeedSort:true,
|
controllerDispatcherPluginsNeedSort:true,
|
||||||
projectOntoXYPlane:true,
|
projectOntoXYPlane:true,
|
||||||
getChildrenProps:true,
|
|
||||||
projectOntoEntityXYPlane:true,
|
projectOntoEntityXYPlane:true,
|
||||||
projectOntoOverlayXYPlane:true,
|
projectOntoOverlayXYPlane:true,
|
||||||
makeLaserLockInfo:true,
|
makeLaserLockInfo:true,
|
||||||
|
@ -53,6 +54,8 @@
|
||||||
TEAR_AWAY_COUNT:true,
|
TEAR_AWAY_COUNT:true,
|
||||||
TEAR_AWAY_CHECK_TIME:true,
|
TEAR_AWAY_CHECK_TIME:true,
|
||||||
distanceBetweenPointAndEntityBoundingBox:true,
|
distanceBetweenPointAndEntityBoundingBox:true,
|
||||||
|
entityIsEquipped:true,
|
||||||
|
entityIsFarGrabbedByOther:true,
|
||||||
highlightTargetEntity:true,
|
highlightTargetEntity:true,
|
||||||
clearHighlightedEntities:true,
|
clearHighlightedEntities:true,
|
||||||
unhighlightTargetEntity:true
|
unhighlightTargetEntity:true
|
||||||
|
@ -265,7 +268,14 @@ entityIsDistanceGrabbable = function(props) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getControllerJointIndexCacheTime = [0, 0];
|
||||||
|
getControllerJointIndexCache = [-1, -1];
|
||||||
|
|
||||||
getControllerJointIndex = function (hand) {
|
getControllerJointIndex = function (hand) {
|
||||||
|
var GET_CONTROLLERJOINTINDEX_CACHE_REFRESH_TIME = 3000; // msecs
|
||||||
|
|
||||||
|
var now = Date.now();
|
||||||
|
if (now - getControllerJointIndexCacheTime[hand] > GET_CONTROLLERJOINTINDEX_CACHE_REFRESH_TIME) {
|
||||||
if (HMD.isHandControllerAvailable()) {
|
if (HMD.isHandControllerAvailable()) {
|
||||||
var controllerJointIndex = -1;
|
var controllerJointIndex = -1;
|
||||||
if (Camera.mode === "first person") {
|
if (Camera.mode === "first person") {
|
||||||
|
@ -278,8 +288,13 @@ getControllerJointIndex = function (hand) {
|
||||||
"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND");
|
"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getControllerJointIndexCacheTime[hand] = now;
|
||||||
|
getControllerJointIndexCache[hand] = controllerJointIndex;
|
||||||
return controllerJointIndex;
|
return controllerJointIndex;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return getControllerJointIndexCache[hand];
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
|
|
||||||
Script.include("/~/system/libraries/WebTablet.js");
|
Script.include("/~/system/libraries/WebTablet.js");
|
||||||
Script.include("/~/system/libraries/gridTool.js");
|
Script.include("/~/system/libraries/gridTool.js");
|
||||||
|
Script.include("/~/system/libraries/connectionUtils.js");
|
||||||
|
|
||||||
var METAVERSE_SERVER_URL = Account.metaverseServerURL;
|
var METAVERSE_SERVER_URL = Account.metaverseServerURL;
|
||||||
var MARKETPLACE_URL = METAVERSE_SERVER_URL + "/marketplace";
|
var MARKETPLACE_URL = METAVERSE_SERVER_URL + "/marketplace";
|
||||||
|
|
|
@ -251,6 +251,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'refresh': // old name for refreshNearby
|
||||||
case 'refreshNearby':
|
case 'refreshNearby':
|
||||||
data = {};
|
data = {};
|
||||||
ExtendedOverlay.some(function (overlay) { // capture the audio data
|
ExtendedOverlay.some(function (overlay) { // capture the audio data
|
||||||
|
@ -743,10 +744,13 @@ function receiveMessage(channel, messageString, senderID) {
|
||||||
var message = JSON.parse(messageString);
|
var message = JSON.parse(messageString);
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
case 'select':
|
case 'select':
|
||||||
|
if (!onPalScreen) {
|
||||||
|
tablet.loadQMLSource(PAL_QML_SOURCE);
|
||||||
|
Script.setTimeout(function () { sendToQml(message); }, 1000);
|
||||||
|
} else {
|
||||||
sendToQml(message); // Accepts objects, not just strings.
|
sendToQml(message); // Accepts objects, not just strings.
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
print('Unrecognized PAL message', messageString);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,40 +175,39 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::startTestsEvaluation(const QString& testFolder) {
|
void Test::startTestsEvaluation(const QString& testFolder) {
|
||||||
QString pathToTestResultsDirectory;
|
|
||||||
if (testFolder.isNull()) {
|
|
||||||
// Get list of JPEG images in folder, sorted by name
|
// Get list of JPEG images in folder, sorted by name
|
||||||
pathToTestResultsDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = snapshotDirectory;
|
||||||
} else {
|
|
||||||
pathToTestResultsDirectory = testFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pathToTestResultsDirectory == QString()) {
|
snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images",
|
||||||
|
previousSelection, QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (snapshotDirectory == "") {
|
||||||
|
snapshotDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit if test results folder could not be created
|
// Quit if test results folder could not be created
|
||||||
if (!createTestResultsFolderPath(pathToTestResultsDirectory)) {
|
if (!createTestResultsFolderPath(snapshotDirectory)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before any processing - all images are converted to PNGs, as this is the format stored on GitHub
|
// Before any processing - all images are converted to PNGs, as this is the format stored on GitHub
|
||||||
QStringList sortedSnapshotFilenames = createListOfAll_imagesInDirectory("jpg", pathToTestResultsDirectory);
|
QStringList sortedSnapshotFilenames = createListOfAll_imagesInDirectory("jpg", snapshotDirectory);
|
||||||
foreach(QString filename, sortedSnapshotFilenames) {
|
foreach(QString filename, sortedSnapshotFilenames) {
|
||||||
QStringList stringParts = filename.split(".");
|
QStringList stringParts = filename.split(".");
|
||||||
copyJPGtoPNG(
|
copyJPGtoPNG(snapshotDirectory + "/" + stringParts[0] + ".jpg",
|
||||||
pathToTestResultsDirectory + "/" + stringParts[0] + ".jpg",
|
snapshotDirectory + "/" + stringParts[0] + ".png"
|
||||||
pathToTestResultsDirectory + "/" + stringParts[0] + ".png"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
QFile::remove(pathToTestResultsDirectory + "/" + stringParts[0] + ".jpg");
|
QFile::remove(snapshotDirectory + "/" + stringParts[0] + ".jpg");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create two lists. The first is the test results, the second is the expected images
|
// Create two lists. The first is the test results, the second is the expected images
|
||||||
// The expected images are represented as a URL to enable download from GitHub
|
// The expected images are represented as a URL to enable download from GitHub
|
||||||
// Images that are in the wrong format are ignored.
|
// Images that are in the wrong format are ignored.
|
||||||
|
|
||||||
QStringList sortedTestResultsFilenames = createListOfAll_imagesInDirectory("png", pathToTestResultsDirectory);
|
QStringList sortedTestResultsFilenames = createListOfAll_imagesInDirectory("png", snapshotDirectory);
|
||||||
QStringList expectedImagesURLs;
|
QStringList expectedImagesURLs;
|
||||||
|
|
||||||
resultImagesFullFilenames.clear();
|
resultImagesFullFilenames.clear();
|
||||||
|
@ -216,7 +215,7 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
||||||
expectedImagesFullFilenames.clear();
|
expectedImagesFullFilenames.clear();
|
||||||
|
|
||||||
foreach(QString currentFilename, sortedTestResultsFilenames) {
|
foreach(QString currentFilename, sortedTestResultsFilenames) {
|
||||||
QString fullCurrentFilename = pathToTestResultsDirectory + "/" + currentFilename;
|
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
||||||
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
||||||
resultImagesFullFilenames << fullCurrentFilename;
|
resultImagesFullFilenames << fullCurrentFilename;
|
||||||
|
|
||||||
|
@ -236,11 +235,11 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
||||||
QString expectedImageFilename = currentFilename.replace("/", "_").replace(".", "_EI.");
|
QString expectedImageFilename = currentFilename.replace("/", "_").replace(".", "_EI.");
|
||||||
|
|
||||||
expectedImagesFilenames << expectedImageFilename;
|
expectedImagesFilenames << expectedImageFilename;
|
||||||
expectedImagesFullFilenames << pathToTestResultsDirectory + "/" + expectedImageFilename;
|
expectedImagesFullFilenames << snapshotDirectory + "/" + expectedImageFilename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
autoTester->downloadImages(expectedImagesURLs, pathToTestResultsDirectory, expectedImagesFilenames);
|
autoTester->downloadImages(expectedImagesURLs, snapshotDirectory, expectedImagesFilenames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) {
|
void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) {
|
||||||
|
@ -303,25 +302,39 @@ void Test::importTest(QTextStream& textStream, const QString& testPathname) {
|
||||||
// This script will run all text.js scripts in every applicable sub-folder
|
// This script will run all text.js scripts in every applicable sub-folder
|
||||||
void Test::createRecursiveScript() {
|
void Test::createRecursiveScript() {
|
||||||
// Select folder to start recursing from
|
// Select folder to start recursing from
|
||||||
QString topLevelDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder that will contain the top level test script", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = testDirectory;
|
||||||
if (topLevelDirectory == "") {
|
|
||||||
|
testDirectory =
|
||||||
|
QFileDialog::getExistingDirectory(nullptr, "Please select folder that will contain the top level test script",
|
||||||
|
previousSelection, QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createRecursiveScript(topLevelDirectory, true);
|
createRecursiveScript(testDirectory, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method creates a `testRecursive.js` script in every sub-folder.
|
// This method creates a `testRecursive.js` script in every sub-folder.
|
||||||
void Test::createAllRecursiveScripts() {
|
void Test::createAllRecursiveScripts() {
|
||||||
// Select folder to start recursing from
|
// Select folder to start recursing from
|
||||||
QString topLevelDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the recursive scripts", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = testDirectory;
|
||||||
if (topLevelDirectory == "") {
|
|
||||||
|
testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the recursive scripts",
|
||||||
|
previousSelection,
|
||||||
|
QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createRecursiveScript(topLevelDirectory, false);
|
createRecursiveScript(testDirectory, false);
|
||||||
|
|
||||||
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
QDirIterator it(testDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString directory = it.next();
|
QString directory = it.next();
|
||||||
|
|
||||||
|
@ -427,29 +440,42 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact
|
||||||
void Test::createTest() {
|
void Test::createTest() {
|
||||||
// Rename files sequentially, as ExpectedResult_00000.jpeg, ExpectedResult_00001.jpg and so on
|
// Rename files sequentially, as ExpectedResult_00000.jpeg, ExpectedResult_00001.jpg and so on
|
||||||
// Any existing expected result images will be deleted
|
// Any existing expected result images will be deleted
|
||||||
QString imageSourceDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = snapshotDirectory;
|
||||||
if (imageSourceDirectory == "") {
|
|
||||||
|
snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images",
|
||||||
|
previousSelection,
|
||||||
|
QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (snapshotDirectory == "") {
|
||||||
|
snapshotDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString imageDestinationDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder to save the test images", ".", QFileDialog::ShowDirsOnly);
|
previousSelection = testDirectory;
|
||||||
if (imageDestinationDirectory == "") {
|
|
||||||
|
QString testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder to save the test images",
|
||||||
|
previousSelection, QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("jpg", imageSourceDirectory);
|
QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("jpg", snapshotDirectory);
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
const int maxImages = pow(10, NUM_DIGITS);
|
const int maxImages = pow(10, NUM_DIGITS);
|
||||||
foreach (QString currentFilename, sortedImageFilenames) {
|
foreach (QString currentFilename, sortedImageFilenames) {
|
||||||
QString fullCurrentFilename = imageSourceDirectory + "/" + currentFilename;
|
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
||||||
if (isInSnapshotFilenameFormat("jpg", currentFilename)) {
|
if (isInSnapshotFilenameFormat("jpg", currentFilename)) {
|
||||||
if (i >= maxImages) {
|
if (i >= maxImages) {
|
||||||
QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported");
|
QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
QString newFilename = "ExpectedImage_" + QString::number(i - 1).rightJustified(5, '0') + ".png";
|
QString newFilename = "ExpectedImage_" + QString::number(i - 1).rightJustified(5, '0') + ".png";
|
||||||
QString fullNewFileName = imageDestinationDirectory + "/" + newFilename;
|
QString fullNewFileName = testDirectory + "/" + newFilename;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
copyJPGtoPNG(fullCurrentFilename, fullNewFileName);
|
copyJPGtoPNG(fullCurrentFilename, fullNewFileName);
|
||||||
|
@ -489,31 +515,6 @@ ExtractedText Test::getTestScriptLines(QString testFileName) {
|
||||||
QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString + "\\," + ws + ownPath + "\\," + ws + functionParameter + ws + "{" + ".*");
|
QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString + "\\," + ws + ownPath + "\\," + ws + functionParameter + ws + "{" + ".*");
|
||||||
QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle);
|
QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle);
|
||||||
|
|
||||||
// Assert platform checks that test is running on the correct OS
|
|
||||||
const QString functionAssertPlatform(ws + "autoTester" + ws + "\\." + ws + "assertPlatform");
|
|
||||||
const QString regexAssertPlatform(ws + functionAssertPlatform + ws + "\\(" + ws + quotedString + ".*");
|
|
||||||
const QRegularExpression lineAssertPlatform = QRegularExpression(regexAssertPlatform);
|
|
||||||
|
|
||||||
// Assert display checks that test is running on the correct display
|
|
||||||
const QString functionAssertDisplay(ws + "autoTester" + ws + "\\." + ws + "assertDisplay");
|
|
||||||
const QString regexAssertDisplay(ws + functionAssertDisplay + ws + "\\(" + ws + quotedString + ".*");
|
|
||||||
const QRegularExpression lineAssertDisplay = QRegularExpression(regexAssertDisplay);
|
|
||||||
|
|
||||||
// Assert CPU checks that test is running on the correct type of CPU
|
|
||||||
const QString functionAssertCPU(ws + "autoTester" + ws + "\\." + ws + "assertCPU");
|
|
||||||
const QString regexAssertCPU(ws + functionAssertCPU + ws + "\\(" + ws + quotedString + ".*");
|
|
||||||
const QRegularExpression lineAssertCPU = QRegularExpression(regexAssertCPU);
|
|
||||||
|
|
||||||
// Assert GPU checks that test is running on the correct type of GPU
|
|
||||||
const QString functionAssertGPU(ws + "autoTester" + ws + "\\." + ws + "assertGPU");
|
|
||||||
const QString regexAssertGPU(ws + functionAssertGPU + ws + "\\(" + ws + quotedString + ".*");
|
|
||||||
const QRegularExpression lineAssertGPU = QRegularExpression(regexAssertGPU);
|
|
||||||
|
|
||||||
// Assert the correct amount of memory
|
|
||||||
const QString functionAssertPhysicalMemoryGB(ws + "autoTester" + ws + "\\." + ws + "assertPhysicalMemoryGB");
|
|
||||||
const QString regexAssertPhysicalMemoryGB(ws + functionAssertPhysicalMemoryGB + ws + "\\(" + ws + quotedString + ".*");
|
|
||||||
const QRegularExpression lineAssertPhysicalMemoryGB = QRegularExpression(regexAssertPhysicalMemoryGB);
|
|
||||||
|
|
||||||
|
|
||||||
// Each step is either of the following forms:
|
// Each step is either of the following forms:
|
||||||
// autoTester.addStepSnapshot("Take snapshot"...
|
// autoTester.addStepSnapshot("Take snapshot"...
|
||||||
|
@ -523,7 +524,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) {
|
||||||
const QRegularExpression lineStepSnapshot = QRegularExpression(regexStepSnapshot);
|
const QRegularExpression lineStepSnapshot = QRegularExpression(regexStepSnapshot);
|
||||||
|
|
||||||
const QString functionAddStepName(ws + "autoTester" + ws + "\\." + ws + "addStep");
|
const QString functionAddStepName(ws + "autoTester" + ws + "\\." + ws + "addStep");
|
||||||
const QString regexStep(ws + functionAddStepName + ws + "\\(" + ws + quotedString + ws + "\\)" + ".*");
|
const QString regexStep(ws + functionAddStepName + ws + "\\(" + ws + quotedString + ".*");
|
||||||
const QRegularExpression lineStep = QRegularExpression(regexStep);
|
const QRegularExpression lineStep = QRegularExpression(regexStep);
|
||||||
|
|
||||||
while (!line.isNull()) {
|
while (!line.isNull()) {
|
||||||
|
@ -531,7 +532,6 @@ ExtractedText Test::getTestScriptLines(QString testFileName) {
|
||||||
if (lineContainingTitle.match(line).hasMatch()) {
|
if (lineContainingTitle.match(line).hasMatch()) {
|
||||||
QStringList tokens = line.split('"');
|
QStringList tokens = line.split('"');
|
||||||
relevantTextFromTest.title = tokens[1];
|
relevantTextFromTest.title = tokens[1];
|
||||||
|
|
||||||
} else if (lineStepSnapshot.match(line).hasMatch()) {
|
} else if (lineStepSnapshot.match(line).hasMatch()) {
|
||||||
QStringList tokens = line.split('"');
|
QStringList tokens = line.split('"');
|
||||||
QString nameOfStep = tokens[1];
|
QString nameOfStep = tokens[1];
|
||||||
|
@ -561,29 +561,43 @@ ExtractedText Test::getTestScriptLines(QString testFileName) {
|
||||||
// The folder selected must contain a script named "test.js", the file produced is named "test.md"
|
// The folder selected must contain a script named "test.js", the file produced is named "test.md"
|
||||||
void Test::createMDFile() {
|
void Test::createMDFile() {
|
||||||
// Folder selection
|
// Folder selection
|
||||||
QString testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = testDirectory;
|
||||||
|
|
||||||
|
testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test", previousSelection,
|
||||||
|
QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
if (testDirectory == "") {
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createMDFile(testDirectory);
|
createMDFile(testDirectory);
|
||||||
|
|
||||||
|
QMessageBox::information(0, "Success", "MD file has been created");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::createAllMDFiles() {
|
void Test::createAllMDFiles() {
|
||||||
// Select folder to start recursing from
|
// Select folder to start recursing from
|
||||||
QString topLevelDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the MD files", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = testDirectory;
|
||||||
if (topLevelDirectory == "") {
|
|
||||||
|
testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the MD files",
|
||||||
|
previousSelection, QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First test if top-level folder has a test.js file
|
// First test if top-level folder has a test.js file
|
||||||
const QString testPathname{ topLevelDirectory + "/" + TEST_FILENAME };
|
const QString testPathname { testDirectory + "/" + TEST_FILENAME };
|
||||||
QFileInfo fileInfo(testPathname);
|
QFileInfo fileInfo(testPathname);
|
||||||
if (fileInfo.exists()) {
|
if (fileInfo.exists()) {
|
||||||
createMDFile(topLevelDirectory);
|
createMDFile(testDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
QDirIterator it(testDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString directory = it.next();
|
QString directory = it.next();
|
||||||
|
|
||||||
|
@ -638,31 +652,33 @@ void Test::createMDFile(const QString& testDirectory) {
|
||||||
stream << "## Steps\n";
|
stream << "## Steps\n";
|
||||||
stream << "Press space bar to advance step by step\n\n";
|
stream << "Press space bar to advance step by step\n\n";
|
||||||
|
|
||||||
// Note that snapshots of step n are taken in step n+1
|
|
||||||
// (this implies that if the LAST step requests a snapshot then this will not work - caveat emptor)
|
|
||||||
int snapShotIndex { 0 };
|
int snapShotIndex { 0 };
|
||||||
for (size_t i = 0; i < testScriptLines.stepList.size(); ++i) {
|
for (size_t i = 0; i < testScriptLines.stepList.size(); ++i) {
|
||||||
stream << "### Step " << QString::number(i + 1) << "\n";
|
stream << "### Step " << QString::number(i + 1) << "\n";
|
||||||
stream << "- " << testScriptLines.stepList[i]->text << "\n";
|
stream << "- " << testScriptLines.stepList[i]->text << "\n";
|
||||||
if ((i + 1 < testScriptLines.stepList.size()) && testScriptLines.stepList[i + 1]->takeSnapshot) {
|
if ((i + 1 < testScriptLines.stepList.size()) && testScriptLines.stepList[i]->takeSnapshot) {
|
||||||
stream << "- .rightJustified(5, '0') << ".png)\n";
|
stream << "- .rightJustified(5, '0') << ".png)\n";
|
||||||
++snapShotIndex;
|
++snapShotIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mdFile.close();
|
mdFile.close();
|
||||||
|
|
||||||
QMessageBox::information(0, "Success", "Test MD file " + mdFilename + " has been created");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::createTestsOutline() {
|
void Test::createTestsOutline() {
|
||||||
QString testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", ".", QFileDialog::ShowDirsOnly);
|
QString previousSelection = testDirectory;
|
||||||
if (testsRootDirectory == "") {
|
|
||||||
|
testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", previousSelection,
|
||||||
|
QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString testsOutlineFilename { "testsOutline.md" };
|
const QString testsOutlineFilename { "testsOutline.md" };
|
||||||
QString mdFilename(testsRootDirectory + "/" + testsOutlineFilename);
|
QString mdFilename(testDirectory + "/" + testsOutlineFilename);
|
||||||
QFile mdFile(mdFilename);
|
QFile mdFile(mdFilename);
|
||||||
if (!mdFile.open(QIODevice::WriteOnly)) {
|
if (!mdFile.open(QIODevice::WriteOnly)) {
|
||||||
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename);
|
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename);
|
||||||
|
@ -676,10 +692,10 @@ void Test::createTestsOutline() {
|
||||||
stream << "Directories with an appended (*) have an automatic test\n\n";
|
stream << "Directories with an appended (*) have an automatic test\n\n";
|
||||||
|
|
||||||
// We need to know our current depth, as this isn't given by QDirIterator
|
// We need to know our current depth, as this isn't given by QDirIterator
|
||||||
int rootDepth { testsRootDirectory.count('/') };
|
int rootDepth { testDirectory.count('/') };
|
||||||
|
|
||||||
// Each test is shown as the folder name linking to the matching GitHub URL, and the path to the associated test.md file
|
// Each test is shown as the folder name linking to the matching GitHub URL, and the path to the associated test.md file
|
||||||
QDirIterator it(testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
QDirIterator it(testDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString directory = it.next();
|
QString directory = it.next();
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,12 @@ private:
|
||||||
const int NUM_DIGITS { 5 };
|
const int NUM_DIGITS { 5 };
|
||||||
const QString EXPECTED_IMAGE_PREFIX { "ExpectedImage_" };
|
const QString EXPECTED_IMAGE_PREFIX { "ExpectedImage_" };
|
||||||
|
|
||||||
|
// We have two directories to work with.
|
||||||
|
// The first is the directory containing the test we are working with
|
||||||
|
// The second contains the snapshots taken for test runs that need to be evaluated
|
||||||
|
QString testDirectory;
|
||||||
|
QString snapshotDirectory;
|
||||||
|
|
||||||
QStringList expectedImagesFilenames;
|
QStringList expectedImagesFilenames;
|
||||||
QStringList expectedImagesFullFilenames;
|
QStringList expectedImagesFullFilenames;
|
||||||
QStringList resultImagesFullFilenames;
|
QStringList resultImagesFullFilenames;
|
||||||
|
|
Loading…
Reference in a new issue