diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js
index 1e9051d717..bdd80df9ec 100644
--- a/domain-server/resources/web/js/settings.js
+++ b/domain-server/resources/web/js/settings.js
@@ -667,7 +667,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
modal_body = "
Choose the High Fidelity domain you want this domain-server to represent.
This will set your domain ID on the settings page.
"
domain_select = $("")
_.each(data.data.domains, function(domain){
- domain_select.append("")
+ domain_select.append("");
})
modal_body += "" + domain_select[0].outerHTML
modal_buttons["success"] = {
diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js
index 1f613adf3b..e3450b708e 100644
--- a/examples/controllers/hydra/gun.js
+++ b/examples/controllers/hydra/gun.js
@@ -16,6 +16,27 @@
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
+var RED = { red: 255, green: 0, blue: 0 };
+var LASER_WIDTH = 2;
+
+var pointer = [];
+pointer.push(Overlays.addOverlay("line3d", {
+ start: { x: 0, y: 0, z: 0 },
+ end: { x: 0, y: 0, z: 0 },
+ color: RED,
+ alpha: 1,
+ visible: true,
+ lineWidth: LASER_WIDTH
+}));
+pointer.push(Overlays.addOverlay("line3d", {
+ start: { x: 0, y: 0, z: 0 },
+ end: { x: 0, y: 0, z: 0 },
+ color: RED,
+ alpha: 1,
+ visible: true,
+ lineWidth: LASER_WIDTH
+}));
+
function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}
@@ -26,7 +47,7 @@ var yawFromMouse = 0;
var pitchFromMouse = 0;
var isMouseDown = false;
-var BULLET_VELOCITY = 20.0;
+var BULLET_VELOCITY = 5.0;
var MIN_THROWER_DELAY = 1000;
var MAX_THROWER_DELAY = 1000;
var LEFT_BUTTON_3 = 3;
@@ -106,8 +127,6 @@ if (showScore) {
});
}
-
-
function printVector(string, vector) {
print(string + " " + vector.x + ", " + vector.y + ", " + vector.z);
}
@@ -115,7 +134,7 @@ function printVector(string, vector) {
function shootBullet(position, velocity) {
var BULLET_SIZE = 0.07;
var BULLET_LIFETIME = 10.0;
- var BULLET_GRAVITY = -0.02;
+ var BULLET_GRAVITY = 0.0;
bulletID = Entities.addEntity(
{ type: "Sphere",
position: position,
@@ -124,6 +143,8 @@ function shootBullet(position, velocity) {
velocity: velocity,
lifetime: BULLET_LIFETIME,
gravity: { x: 0, y: BULLET_GRAVITY, z: 0 },
+ damping: 0.01,
+ density: 5000,
ignoreCollisions: false,
collisionsWillMove: true
});
@@ -146,11 +167,11 @@ function shootBullet(position, velocity) {
function shootTarget() {
var TARGET_SIZE = 0.50;
- var TARGET_GRAVITY = -0.25;
+ var TARGET_GRAVITY = 0.0;
var TARGET_LIFETIME = 300.0;
- var TARGET_UP_VELOCITY = 0.5;
- var TARGET_FWD_VELOCITY = 1.0;
- var DISTANCE_TO_LAUNCH_FROM = 3.0;
+ var TARGET_UP_VELOCITY = 0.0;
+ var TARGET_FWD_VELOCITY = 0.0;
+ var DISTANCE_TO_LAUNCH_FROM = 5.0;
var ANGLE_RANGE_FOR_LAUNCH = 20.0;
var camera = Camera.getPosition();
//printVector("camera", camera);
@@ -166,13 +187,14 @@ function shootTarget() {
targetID = Entities.addEntity(
{ type: "Box",
position: newPosition,
- dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE },
- color: { red: 0, green: 200, blue: 200 },
- //angularVelocity: { x: 1, y: 0, z: 0 },
+ dimensions: { x: TARGET_SIZE * (0.5 + Math.random()), y: TARGET_SIZE * (0.5 + Math.random()), z: TARGET_SIZE * (0.5 + Math.random()) / 4.0 },
+ color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 },
velocity: velocity,
gravity: { x: 0, y: TARGET_GRAVITY, z: 0 },
lifetime: TARGET_LIFETIME,
- damping: 0.0001,
+ rotation: Camera.getOrientation(),
+ damping: 0.1,
+ density: 100.0,
collisionsWillMove: true });
// Record start time
@@ -183,8 +205,6 @@ function shootTarget() {
Audio.playSound(targetLaunchSound, audioOptions);
}
-
-
function entityCollisionWithEntity(entity1, entity2, collision) {
if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) &&
@@ -212,7 +232,7 @@ function keyPressEvent(event) {
if (event.text == "t") {
var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY;
Script.setTimeout(shootTarget, time);
- } else if (event.text == ".") {
+ } else if ((event.text == ".") || (event.text == "SPACE")) {
shootFromMouse();
} else if (event.text == "r") {
playLoadSound();
@@ -254,7 +274,7 @@ function takeFiringPose() {
}
}
-//MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(-0, -160, -79), 0.20);
+MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(-0, -160, -79), 0.20);
MyAvatar.attach(gunModel, "LeftHand", {x:-0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(0, 0, 79), 0.20);
// Give a bit of time to load before playing sound
@@ -262,7 +282,6 @@ Script.setTimeout(playLoadSound, 2000);
function update(deltaTime) {
if (bulletID && !bulletID.isKnownID) {
- print("Trying to identify bullet");
bulletID = Entities.identifyEntity(bulletID);
}
if (targetID && !targetID.isKnownID) {
@@ -304,15 +323,6 @@ function update(deltaTime) {
}
}
- // Check hydra controller for launch button press
- if (!isLaunchButtonPressed && Controller.isButtonPressed(LEFT_BUTTON_3)) {
- isLaunchButtonPressed = true;
- var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY;
- Script.setTimeout(shootTarget, time);
- } else if (isLaunchButtonPressed && !Controller.isButtonPressed(LEFT_BUTTON_3)) {
- isLaunchButtonPressed = false;
-
- }
// check for trigger press
@@ -335,14 +345,21 @@ function update(deltaTime) {
shootABullet = true;
}
}
+ var palmController = t * controllersPerTrigger;
+ var palmPosition = Controller.getSpatialControlPosition(palmController);
+ var fingerTipController = palmController + 1;
+ var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController);
+ var laserTip = Vec3.sum(Vec3.multiply(100.0, Vec3.subtract(fingerTipPosition, palmPosition)), palmPosition);
+
+ // Update Lasers
+ Overlays.editOverlay(pointer[t], {
+ start: palmPosition,
+ end: laserTip,
+ alpha: 1
+ });
if (shootABullet) {
- var palmController = t * controllersPerTrigger;
- var palmPosition = Controller.getSpatialControlPosition(palmController);
-
- var fingerTipController = palmController + 1;
- var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController);
-
+
var palmToFingerTipVector =
{ x: (fingerTipPosition.x - palmPosition.x),
y: (fingerTipPosition.y - palmPosition.y),
@@ -361,20 +378,8 @@ function update(deltaTime) {
}
}
-function mousePressEvent(event) {
- isMouseDown = true;
- lastX = event.x;
- lastY = event.y;
-
- if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === offButton) {
- Script.stop();
- } else {
- shootFromMouse();
- }
-}
-
function shootFromMouse() {
- var DISTANCE_FROM_CAMERA = 2.0;
+ var DISTANCE_FROM_CAMERA = 1.0;
var camera = Camera.getPosition();
var forwardVector = Quat.getFront(Camera.getOrientation());
var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
@@ -402,6 +407,8 @@ function mouseMoveEvent(event) {
function scriptEnding() {
Overlays.deleteOverlay(reticle);
Overlays.deleteOverlay(offButton);
+ Overlays.deleteOverlay(pointer[0]);
+ Overlays.deleteOverlay(pointer[1]);
Overlays.deleteOverlay(text);
MyAvatar.detachOne(gunModel);
clearPose();
@@ -410,7 +417,6 @@ function scriptEnding() {
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
Script.scriptEnding.connect(scriptEnding);
Script.update.connect(update);
-Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.keyPressEvent.connect(keyPressEvent);
diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js
index cdb8e76c65..a14958dd23 100644
--- a/examples/defaultScripts.js
+++ b/examples/defaultScripts.js
@@ -11,7 +11,7 @@
Script.load("lookWithTouch.js");
Script.load("editEntities.js");
Script.load("selectAudioDevice.js");
-Script.load("hydraMove.js");
+Script.load("controllers/hydra/hydraMove.js");
Script.load("headMove.js");
Script.load("inspect.js");
Script.load("lobby.js");
diff --git a/examples/lobby.js b/examples/lobby.js
index 636f0a95f1..fcac7a490b 100644
--- a/examples/lobby.js
+++ b/examples/lobby.js
@@ -165,8 +165,7 @@ function changeLobbyTextures() {
for (var j = 0; j < NUM_PANELS; j++) {
var panelIndex = placeIndexToPanelIndex(j);
- textureProp["textures"]["file" + panelIndex] = HIFI_PUBLIC_BUCKET + "images/places/"
- + places[j].id + "/hifi-place-" + places[j].id + "_640x360.jpg";
+ textureProp["textures"]["file" + panelIndex] = places[j].previews.lobby;
};
Overlays.editOverlay(panelWall, textureProp);
diff --git a/interface/src/ScriptsModel.cpp b/interface/src/ScriptsModel.cpp
index 41ce16c229..b09762b73c 100644
--- a/interface/src/ScriptsModel.cpp
+++ b/interface/src/ScriptsModel.cpp
@@ -31,20 +31,30 @@ static const QString IS_TRUNCATED_NAME = "IsTruncated";
static const QString CONTAINER_NAME = "Contents";
static const QString KEY_NAME = "Key";
-ScriptItem::ScriptItem(const QString& filename, const QString& fullPath) :
- _filename(filename),
- _fullPath(fullPath) {
+TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type) :
+ _parent(parent),
+ _name(name),
+ _type(type) {
+};
+
+TreeNodeScript::TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin) :
+ TreeNodeBase(NULL, localPath.split("/").last(), TREE_NODE_TYPE_SCRIPT),
+ _localPath(localPath),
+ _fullPath(fullPath),
+ _origin(origin) {
+};
+
+TreeNodeFolder::TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent) :
+ TreeNodeBase(parent, foldername, TREE_NODE_TYPE_FOLDER) {
};
ScriptsModel::ScriptsModel(QObject* parent) :
- QAbstractListModel(parent),
+ QAbstractItemModel(parent),
_loadingScripts(false),
_localDirectory(),
_fsWatcher(),
- _localFiles(),
- _remoteFiles()
+ _treeNodes()
{
-
_localDirectory.setFilter(QDir::Files | QDir::Readable);
_localDirectory.setNameFilters(QStringList("*.js"));
@@ -57,31 +67,61 @@ ScriptsModel::ScriptsModel(QObject* parent) :
reloadRemoteFiles();
}
-QVariant ScriptsModel::data(const QModelIndex& index, int role) const {
- const QList* files = NULL;
- int row = 0;
- bool isLocal = index.row() < _localFiles.size();
- if (isLocal) {
- files = &_localFiles;
- row = index.row();
- } else {
- files = &_remoteFiles;
- row = index.row() - _localFiles.size();
- }
+ScriptsModel::~ScriptsModel() {
+ for (int i = _treeNodes.size() - 1; i >= 0; i--) {
+ delete _treeNodes.at(i);
+ }
+ _treeNodes.clear();
+}
- if (role == Qt::DisplayRole) {
- return QVariant((*files)[row]->getFilename() + (isLocal ? " (local)" : ""));
- } else if (role == ScriptPath) {
- return QVariant((*files)[row]->getFullPath());
+TreeNodeBase* ScriptsModel::getTreeNodeFromIndex(const QModelIndex& index) const {
+ if (index.isValid()) {
+ return static_cast(index.internalPointer());
+ }
+ return NULL;
+}
+
+QModelIndex ScriptsModel::index(int row, int column, const QModelIndex& parent) const {
+ if (row < 0 || column < 0) {
+ return QModelIndex();
+ }
+ return createIndex(row, column, getFolderNodes(static_cast(getTreeNodeFromIndex(parent))).at(row));
+}
+
+QModelIndex ScriptsModel::parent(const QModelIndex& child) const {
+ TreeNodeFolder* parent = (static_cast(child.internalPointer()))->getParent();
+ if (!parent) {
+ return QModelIndex();
+ }
+ TreeNodeFolder* grandParent = parent->getParent();
+ int row = getFolderNodes(grandParent).indexOf(parent);
+ return createIndex(row, 0, parent);
+}
+
+QVariant ScriptsModel::data(const QModelIndex& index, int role) const {
+ TreeNodeBase* node = getTreeNodeFromIndex(index);
+ if (node->getType() == TREE_NODE_TYPE_SCRIPT) {
+ TreeNodeScript* script = static_cast(node);
+ if (role == Qt::DisplayRole) {
+ return QVariant(script->getName() + (script->getOrigin() == SCRIPT_ORIGIN_LOCAL ? " (local)" : ""));
+ } else if (role == ScriptPath) {
+ return QVariant(script->getFullPath());
+ }
+ } else if (node->getType() == TREE_NODE_TYPE_FOLDER) {
+ TreeNodeFolder* folder = static_cast(node);
+ if (role == Qt::DisplayRole) {
+ return QVariant(folder->getName());
+ }
}
return QVariant();
}
int ScriptsModel::rowCount(const QModelIndex& parent) const {
- if (parent.isValid()) {
- return 0;
- }
- return _localFiles.length() + _remoteFiles.length();
+ return getFolderNodes(static_cast(getTreeNodeFromIndex(parent))).count();
+}
+
+int ScriptsModel::columnCount(const QModelIndex& parent) const {
+ return 1;
}
void ScriptsModel::updateScriptsLocation(const QString& newPath) {
@@ -93,7 +133,7 @@ void ScriptsModel::updateScriptsLocation(const QString& newPath) {
if (!_localDirectory.absolutePath().isEmpty()) {
_fsWatcher.addPath(_localDirectory.absolutePath());
}
- }
+ }
reloadLocalFiles();
}
@@ -101,8 +141,14 @@ void ScriptsModel::updateScriptsLocation(const QString& newPath) {
void ScriptsModel::reloadRemoteFiles() {
if (!_loadingScripts) {
_loadingScripts = true;
- while (!_remoteFiles.isEmpty()) {
- delete _remoteFiles.takeFirst();
+ for (int i = _treeNodes.size() - 1; i >= 0; i--) {
+ TreeNodeBase* node = _treeNodes.at(i);
+ if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
+ static_cast(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE)
+ {
+ delete node;
+ _treeNodes.removeAt(i);
+ }
}
requestRemoteFiles();
}
@@ -121,7 +167,6 @@ void ScriptsModel::requestRemoteFiles(QString marker) {
QNetworkRequest request(url);
QNetworkReply* reply = networkAccessManager.get(request);
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
-
}
void ScriptsModel::downloadFinished() {
@@ -170,7 +215,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
xml.readNext();
lastKey = xml.text().toString();
if (jsRegex.exactMatch(xml.text().toString())) {
- _remoteFiles.append(new ScriptItem(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey));
+ _treeNodes.append(new TreeNodeScript(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey, SCRIPT_ORIGIN_REMOTE));
}
}
xml.readNext();
@@ -178,7 +223,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
}
xml.readNext();
}
-
+ rebuildTree();
endResetModel();
// Error handling
@@ -198,8 +243,14 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
void ScriptsModel::reloadLocalFiles() {
beginResetModel();
- while (!_localFiles.isEmpty()) {
- delete _localFiles.takeFirst();
+ for (int i = _treeNodes.size() - 1; i >= 0; i--) {
+ TreeNodeBase* node = _treeNodes.at(i);
+ if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
+ static_cast(node)->getOrigin() == SCRIPT_ORIGIN_LOCAL)
+ {
+ delete node;
+ _treeNodes.removeAt(i);
+ }
}
_localDirectory.refresh();
@@ -207,8 +258,53 @@ void ScriptsModel::reloadLocalFiles() {
const QFileInfoList localFiles = _localDirectory.entryInfoList();
for (int i = 0; i < localFiles.size(); i++) {
QFileInfo file = localFiles[i];
- _localFiles.append(new ScriptItem(file.fileName(), file.absoluteFilePath()));
+ _treeNodes.append(new TreeNodeScript(file.fileName(), file.absoluteFilePath(), SCRIPT_ORIGIN_LOCAL));
}
-
+ rebuildTree();
endResetModel();
}
+
+void ScriptsModel::rebuildTree() {
+ for (int i = _treeNodes.size() - 1; i >= 0; i--) {
+ if (_treeNodes.at(i)->getType() == TREE_NODE_TYPE_FOLDER) {
+ delete _treeNodes.at(i);
+ _treeNodes.removeAt(i);
+ }
+ }
+ QHash folders;
+ for (int i = 0; i < _treeNodes.size(); i++) {
+ TreeNodeBase* node = _treeNodes.at(i);
+ if (node->getType() == TREE_NODE_TYPE_SCRIPT) {
+ TreeNodeScript* script = static_cast(node);
+ TreeNodeFolder* parent = NULL;
+ QString hash;
+ QStringList pathList = script->getLocalPath().split(tr("/"));
+ pathList.removeLast();
+ QStringList::const_iterator pathIterator;
+ for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) {
+ hash.append(*pathIterator + "/");
+ if (!folders.contains(hash)) {
+ folders[hash] = new TreeNodeFolder(*pathIterator, parent);
+ }
+ parent = folders[hash];
+ }
+ script->setParent(parent);
+ }
+ }
+ QHash::const_iterator folderIterator;
+ for (folderIterator = folders.constBegin(); folderIterator != folders.constEnd(); ++folderIterator) {
+ _treeNodes.append(*folderIterator);
+ }
+ folders.clear();
+}
+
+QList ScriptsModel::getFolderNodes(TreeNodeFolder* parent) const {
+ QList result;
+ for (int i = 0; i < _treeNodes.size(); i++) {
+ TreeNodeBase* node = _treeNodes.at(i);
+ if (node->getParent() == parent) {
+ result.append(node);
+ }
+ }
+ return result;
+}
diff --git a/interface/src/ScriptsModel.h b/interface/src/ScriptsModel.h
index ca72a8d8f4..914a197201 100644
--- a/interface/src/ScriptsModel.h
+++ b/interface/src/ScriptsModel.h
@@ -12,30 +12,69 @@
#ifndef hifi_ScriptsModel_h
#define hifi_ScriptsModel_h
-#include
+#include
#include
#include
#include
-class ScriptItem {
-public:
- ScriptItem(const QString& filename, const QString& fullPath);
+class TreeNodeFolder;
- const QString& getFilename() { return _filename; };
- const QString& getFullPath() { return _fullPath; };
-
-private:
- QString _filename;
- QString _fullPath;
+enum ScriptOrigin {
+ SCRIPT_ORIGIN_LOCAL,
+ SCRIPT_ORIGIN_REMOTE
};
-class ScriptsModel : public QAbstractListModel {
+enum TreeNodeType {
+ TREE_NODE_TYPE_SCRIPT,
+ TREE_NODE_TYPE_FOLDER
+};
+
+class TreeNodeBase {
+public:
+ TreeNodeFolder* getParent() const { return _parent; }
+ void setParent(TreeNodeFolder* parent) { _parent = parent; }
+ TreeNodeType getType() { return _type; }
+ const QString& getName() { return _name; };
+
+private:
+ TreeNodeFolder* _parent;
+ TreeNodeType _type;
+
+protected:
+ QString _name;
+ TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type);
+};
+
+class TreeNodeScript : public TreeNodeBase {
+public:
+ TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin);
+ const QString& getLocalPath() { return _localPath; }
+ const QString& getFullPath() { return _fullPath; };
+ const ScriptOrigin getOrigin() { return _origin; };
+
+private:
+ QString _localPath;
+ QString _fullPath;
+ ScriptOrigin _origin;
+};
+
+class TreeNodeFolder : public TreeNodeBase {
+public:
+ TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent);
+};
+
+class ScriptsModel : public QAbstractItemModel {
Q_OBJECT
public:
ScriptsModel(QObject* parent = NULL);
-
- virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
- virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ ~ScriptsModel();
+ QModelIndex index(int row, int column, const QModelIndex& parent) const;
+ QModelIndex parent(const QModelIndex& child) const;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const;
+ QList getFolderNodes(TreeNodeFolder* parent) const;
enum Role {
ScriptPath = Qt::UserRole,
@@ -50,13 +89,13 @@ protected slots:
protected:
void requestRemoteFiles(QString marker = QString());
bool parseXML(QByteArray xmlFile);
+ void rebuildTree();
private:
bool _loadingScripts;
QDir _localDirectory;
QFileSystemWatcher _fsWatcher;
- QList _localFiles;
- QList _remoteFiles;
+ QList _treeNodes;
};
#endif // hifi_ScriptsModel_h
diff --git a/interface/src/ScriptsModelFilter.cpp b/interface/src/ScriptsModelFilter.cpp
new file mode 100644
index 0000000000..1879e547c0
--- /dev/null
+++ b/interface/src/ScriptsModelFilter.cpp
@@ -0,0 +1,44 @@
+//
+// ScriptsModelFilter.cpp
+// interface/src
+//
+// Created by Thijs Wenker on 01/11/15.
+// Copyright 2015 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#include "ScriptsModelFilter.h"
+
+ScriptsModelFilter::ScriptsModelFilter(QObject *parent) :
+ QSortFilterProxyModel(parent) {
+}
+
+bool ScriptsModelFilter::lessThan(const QModelIndex& left, const QModelIndex& right) const {
+ ScriptsModel* scriptsModel = static_cast(sourceModel());
+ TreeNodeBase* leftNode = scriptsModel->getTreeNodeFromIndex(left);
+ TreeNodeBase* rightNode = scriptsModel->getTreeNodeFromIndex(right);
+ if (leftNode->getType() != rightNode->getType()) {
+ return leftNode->getType() == TREE_NODE_TYPE_FOLDER;
+ }
+ return leftNode->getName() < rightNode->getName();
+}
+
+bool ScriptsModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
+ if (!filterRegExp().isEmpty()) {
+ ScriptsModel* scriptsModel = static_cast(sourceModel());
+ TreeNodeBase* node = scriptsModel->getFolderNodes(
+ static_cast(scriptsModel->getTreeNodeFromIndex(sourceParent))).at(sourceRow);
+ QModelIndex sourceIndex = sourceModel()->index(sourceRow, this->filterKeyColumn(), sourceParent);
+ if (node->getType() == TREE_NODE_TYPE_FOLDER) {
+ int rows = scriptsModel->rowCount(sourceIndex);
+ for (int i = 0; i < rows; i++) {
+ if (filterAcceptsRow(i, sourceIndex)) {
+ return true;
+ }
+ }
+ }
+ }
+ return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
+}
diff --git a/interface/src/ScriptsModelFilter.h b/interface/src/ScriptsModelFilter.h
new file mode 100644
index 0000000000..7b7cdd974e
--- /dev/null
+++ b/interface/src/ScriptsModelFilter.h
@@ -0,0 +1,27 @@
+//
+// ScriptsModelFilter.h
+// interface/src
+//
+// Created by Thijs Wenker on 01/11/15.
+// Copyright 2015 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_ScriptsModelFilter_h
+#define hifi_ScriptsModelFilter_h
+
+#include "ScriptsModel.h"
+#include
+
+class ScriptsModelFilter : public QSortFilterProxyModel {
+ Q_OBJECT
+public:
+ ScriptsModelFilter(QObject *parent = NULL);
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const;
+ bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
+};
+
+#endif // hifi_ScriptsModelFilter_h
diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp
index 57c0532777..4346d813bb 100644
--- a/interface/src/ui/RunningScriptsWidget.cpp
+++ b/interface/src/ui/RunningScriptsWidget.cpp
@@ -33,7 +33,7 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
Qt::WindowCloseButtonHint),
ui(new Ui::RunningScriptsWidget),
_signalMapper(this),
- _proxyModel(this),
+ _scriptsModelFilter(this),
_scriptsModel(this) {
ui->setupUi(this);
@@ -41,46 +41,49 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
ui->filterLineEdit->installEventFilter(this);
- connect(&_proxyModel, &QSortFilterProxyModel::modelReset,
+ connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset,
this, &RunningScriptsWidget::selectFirstInList);
QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText);
ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts.");
- _proxyModel.setSourceModel(&_scriptsModel);
- _proxyModel.sort(0, Qt::AscendingOrder);
- _proxyModel.setDynamicSortFilter(true);
- ui->scriptListView->setModel(&_proxyModel);
+ _scriptsModelFilter.setSourceModel(&_scriptsModel);
+ _scriptsModelFilter.sort(0, Qt::AscendingOrder);
+ _scriptsModelFilter.setDynamicSortFilter(true);
+ ui->scriptTreeView->setModel(&_scriptsModelFilter);
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter);
- connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList);
+ connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList);
connect(ui->reloadAllButton, &QPushButton::clicked,
Application::getInstance(), &Application::reloadAllScripts);
connect(ui->stopAllButton, &QPushButton::clicked,
this, &RunningScriptsWidget::allScriptsStopped);
- connect(ui->loadScriptButton, &QPushButton::clicked,
+ connect(ui->loadScriptFromDiskButton, &QPushButton::clicked,
Application::getInstance(), &Application::loadDialog);
+ connect(ui->loadScriptFromURLButton, &QPushButton::clicked,
+ Application::getInstance(), &Application::loadScriptURLDialog);
connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
}
RunningScriptsWidget::~RunningScriptsWidget() {
delete ui;
+ _scriptsModel.deleteLater();
}
void RunningScriptsWidget::updateFileFilter(const QString& filter) {
QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive);
- _proxyModel.setFilterRegExp(regex);
+ _scriptsModelFilter.setFilterRegExp(regex);
selectFirstInList();
}
void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) {
- QVariant scriptFile = _proxyModel.data(index, ScriptsModel::ScriptPath);
+ QVariant scriptFile = _scriptsModelFilter.data(index, ScriptsModel::ScriptPath);
Application::getInstance()->loadScript(scriptFile.toString());
}
void RunningScriptsWidget::loadSelectedScript() {
- QModelIndex selectedIndex = ui->scriptListView->currentIndex();
+ QModelIndex selectedIndex = ui->scriptTreeView->currentIndex();
if (selectedIndex.isValid()) {
loadScriptFromList(selectedIndex);
}
@@ -165,8 +168,8 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) {
}
void RunningScriptsWidget::selectFirstInList() {
- if (_proxyModel.rowCount() > 0) {
- ui->scriptListView->setCurrentIndex(_proxyModel.index(0, 0));
+ if (_scriptsModelFilter.rowCount() > 0) {
+ ui->scriptTreeView->setCurrentIndex(_scriptsModelFilter.index(0, 0));
}
}
@@ -177,7 +180,7 @@ bool RunningScriptsWidget::eventFilter(QObject* sender, QEvent* event) {
}
QKeyEvent* keyEvent = static_cast(event);
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
- QModelIndex selectedIndex = ui->scriptListView->currentIndex();
+ QModelIndex selectedIndex = ui->scriptTreeView->currentIndex();
if (selectedIndex.isValid()) {
loadScriptFromList(selectedIndex);
}
diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h
index 69833a890b..3ec5590dee 100644
--- a/interface/src/ui/RunningScriptsWidget.h
+++ b/interface/src/ui/RunningScriptsWidget.h
@@ -18,6 +18,7 @@
#include
#include "ScriptsModel.h"
+#include "ScriptsModelFilter.h"
#include "ScriptsTableWidget.h"
namespace Ui {
@@ -54,7 +55,7 @@ private slots:
private:
Ui::RunningScriptsWidget* ui;
QSignalMapper _signalMapper;
- QSortFilterProxyModel _proxyModel;
+ ScriptsModelFilter _scriptsModelFilter;
ScriptsModel _scriptsModel;
ScriptsTableWidget* _recentlyLoadedScriptsTable;
QStringList _recentlyLoadedScripts;
diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui
index b70200e9f2..3d7db5064a 100644
--- a/interface/ui/runningScriptsWidget.ui
+++ b/interface/ui/runningScriptsWidget.ui
@@ -245,8 +245,8 @@ font: bold 16px;
0
0
- 328
- 18
+ 334
+ 20
@@ -373,7 +373,7 @@ font: bold 16px;
font: bold 16px;
- Scripts
+ Load Scripts
@@ -391,9 +391,16 @@ font: bold 16px;
-
-
+
- Load script
+ from URL
+
+
+
+ -
+
+
+ from Disk
@@ -429,7 +436,7 @@ font: bold 16px;
-
-
+
0
@@ -442,6 +449,12 @@ font: bold 16px;
Qt::ScrollBarAlwaysOff
+
+ true
+
+
+ false
+