mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 07:22:43 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into head-controller
This commit is contained in:
commit
d91b3700a7
22 changed files with 145 additions and 76 deletions
|
@ -170,20 +170,24 @@ Item {
|
|||
objectName: "loader"
|
||||
asynchronous: false
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
// Hook up callback for clara.io download from the marketplace.
|
||||
Connections {
|
||||
id: eventBridgeConnection
|
||||
target: null
|
||||
onWebEventReceived: {
|
||||
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (loader.item.hasOwnProperty("eventBridge")) {
|
||||
loader.item.eventBridge = eventBridge;
|
||||
|
||||
// Hook up callback for clara.io download from the marketplace.
|
||||
eventBridge.webEventReceived.connect(function (event) {
|
||||
if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||
ApplicationInterface.addAssetToWorldFromURL(event.slice(18));
|
||||
}
|
||||
});
|
||||
eventBridgeConnection.target = eventBridge
|
||||
}
|
||||
if (loader.item.hasOwnProperty("sendToScript")) {
|
||||
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
||||
|
|
|
@ -90,16 +90,21 @@ Windows.ScrollingWindow {
|
|||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
// Hook up callback for clara.io download from the marketplace.
|
||||
Connections {
|
||||
id: eventBridgeConnection
|
||||
target: null
|
||||
onWebEventReceived: {
|
||||
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (loader.item.hasOwnProperty("eventBridge")) {
|
||||
loader.item.eventBridge = eventBridge;
|
||||
|
||||
// Hook up callback for clara.io download from the marketplace.
|
||||
eventBridge.webEventReceived.connect(function (event) {
|
||||
if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||
ApplicationInterface.addAssetToWorldFromURL(event.slice(18));
|
||||
}
|
||||
});
|
||||
eventBridgeConnection.target = eventBridge
|
||||
}
|
||||
if (loader.item.hasOwnProperty("sendToScript")) {
|
||||
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
||||
|
|
|
@ -1459,6 +1459,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
updateSystemTabletMode();
|
||||
|
||||
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
|
||||
|
||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||
}
|
||||
|
||||
void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
|
||||
|
@ -1681,6 +1683,10 @@ Application::~Application() {
|
|||
|
||||
_physicsEngine->setCharacterController(nullptr);
|
||||
|
||||
// the _shapeManager should have zero references
|
||||
_shapeManager.collectGarbage();
|
||||
assert(_shapeManager.getNumShapes() == 0);
|
||||
|
||||
// shutdown render engine
|
||||
_main3DScene = nullptr;
|
||||
_renderEngine = nullptr;
|
||||
|
@ -4492,12 +4498,13 @@ void Application::update(float deltaTime) {
|
|||
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
PerformanceTimer perfTimer("handleOutgoingChanges");
|
||||
const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates();
|
||||
_entitySimulation->handleDeactivatedMotionStates(deactivations);
|
||||
|
||||
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();
|
||||
_entitySimulation->handleChangedMotionStates(outgoingChanges);
|
||||
avatarManager->handleChangedMotionStates(outgoingChanges);
|
||||
|
||||
const VectorOfMotionStates& deactivations = _physicsEngine->getDeactivatedMotionStates();
|
||||
_entitySimulation->handleDeactivatedMotionStates(deactivations);
|
||||
});
|
||||
|
||||
if (!_aboutToQuit) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <QStandardPaths>
|
||||
#include <PathUtils.h>
|
||||
#include <QUrl>
|
||||
#include <Gzip.h>
|
||||
|
||||
#include <BuildInfo.h>
|
||||
#include <GLMHelpers.h>
|
||||
|
@ -27,7 +28,7 @@
|
|||
|
||||
QString SAVE_DIRECTORY = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + BuildInfo::MODIFIED_ORGANIZATION + "/" + BuildInfo::INTERFACE_NAME + "/hifi-input-recordings/";
|
||||
QString FILE_PREFIX_NAME = "input-recording-";
|
||||
QString COMPRESS_EXTENSION = "json.gz";
|
||||
QString COMPRESS_EXTENSION = ".json.gz";
|
||||
namespace controller {
|
||||
|
||||
QJsonObject poseToJsonObject(const Pose pose) {
|
||||
|
@ -93,23 +94,26 @@ namespace controller {
|
|||
}
|
||||
|
||||
|
||||
void exportToFile(const QJsonObject& object) {
|
||||
void exportToFile(const QJsonObject& object, const QString& fileName) {
|
||||
if (!QDir(SAVE_DIRECTORY).exists()) {
|
||||
QDir().mkdir(SAVE_DIRECTORY);
|
||||
}
|
||||
|
||||
QString timeStamp = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
timeStamp.replace(":", "-");
|
||||
QString fileName = SAVE_DIRECTORY + FILE_PREFIX_NAME + timeStamp + COMPRESS_EXTENSION;
|
||||
qDebug() << fileName;
|
||||
|
||||
QFile saveFile (fileName);
|
||||
if (!saveFile.open(QIODevice::WriteOnly)) {
|
||||
qWarning() << "could not open file: " << fileName;
|
||||
return;
|
||||
}
|
||||
QJsonDocument saveData(object);
|
||||
QByteArray compressedData = qCompress(saveData.toJson(QJsonDocument::Compact));
|
||||
saveFile.write(compressedData);
|
||||
QByteArray jsonData = saveData.toJson(QJsonDocument::Indented);
|
||||
QByteArray jsonDataForFile;
|
||||
|
||||
if (!gzip(jsonData, jsonDataForFile, -1)) {
|
||||
qCritical("unable to gzip while saving to json.");
|
||||
return;
|
||||
}
|
||||
|
||||
saveFile.write(jsonDataForFile);
|
||||
saveFile.close();
|
||||
}
|
||||
|
||||
|
@ -121,8 +125,16 @@ namespace controller {
|
|||
status = false;
|
||||
return object;
|
||||
}
|
||||
QByteArray compressedData = qUncompress(openFile.readAll());
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(compressedData);
|
||||
QByteArray compressedData = openFile.readAll();
|
||||
QByteArray jsonData;
|
||||
|
||||
if (!gunzip(compressedData, jsonData)) {
|
||||
qCritical() << "json file not in gzip format: " << file;
|
||||
status = false;
|
||||
return object;
|
||||
}
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
|
||||
object = jsonDoc.object();
|
||||
status = true;
|
||||
openFile.close();
|
||||
|
@ -153,7 +165,7 @@ namespace controller {
|
|||
QJsonObject InputRecorder::recordDataToJson() {
|
||||
QJsonObject data;
|
||||
data["frameCount"] = _framesRecorded;
|
||||
data["version"] = "1.0";
|
||||
data["version"] = "0.0";
|
||||
|
||||
QJsonArray actionArrayList;
|
||||
QJsonArray poseArrayList;
|
||||
|
@ -187,7 +199,10 @@ namespace controller {
|
|||
|
||||
void InputRecorder::saveRecording() {
|
||||
QJsonObject jsonData = recordDataToJson();
|
||||
exportToFile(jsonData);
|
||||
QString timeStamp = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
timeStamp.replace(":", "-");
|
||||
QString fileName = SAVE_DIRECTORY + FILE_PREFIX_NAME + timeStamp + COMPRESS_EXTENSION;
|
||||
exportToFile(jsonData, fileName);
|
||||
}
|
||||
|
||||
void InputRecorder::loadRecording(const QString& path) {
|
||||
|
@ -202,10 +217,12 @@ namespace controller {
|
|||
QString filePath = urlPath.toLocalFile();
|
||||
QFileInfo info(filePath);
|
||||
QString extension = info.suffix();
|
||||
|
||||
if (extension != "gz") {
|
||||
qWarning() << "can not load file with exentsion of " << extension;
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
QJsonObject data = openFile(filePath, success);
|
||||
auto keyValue = data.find("version");
|
||||
|
@ -233,34 +250,7 @@ namespace controller {
|
|||
_poseStateList.push_back(_currentFramePoses);
|
||||
_currentFramePoses.clear();
|
||||
}
|
||||
} else if (success) {
|
||||
//convert recording to new reacording standard and rewrite file
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
_framesRecorded = data["frameCount"].toInt();
|
||||
QJsonArray actionArrayList = data["actionList"].toArray();
|
||||
QJsonArray poseArrayList = data["poseList"].toArray();
|
||||
|
||||
for (int actionIndex = 0; actionIndex < actionArrayList.size(); actionIndex++) {
|
||||
QJsonArray actionState = actionArrayList[actionIndex].toArray();
|
||||
for (int index = 0; index < actionState.size(); index++) {
|
||||
QString actionName = userInputMapper->getActionName(Action(index));
|
||||
_currentFrameActions[actionName] = actionState[index].toDouble();
|
||||
}
|
||||
_actionStateList.push_back(_currentFrameActions);
|
||||
_currentFrameActions.clear();
|
||||
}
|
||||
|
||||
for (int poseIndex = 0; poseIndex < poseArrayList.size(); poseIndex++) {
|
||||
QJsonArray poseState = poseArrayList[poseIndex].toArray();
|
||||
for (int index = 0; index < poseState.size(); index++) {
|
||||
QString actionName = userInputMapper->getActionName(Action(index));
|
||||
_currentFramePoses[actionName] = jsonObjectToPose(poseState[index].toObject());
|
||||
}
|
||||
_poseStateList.push_back(_currentFramePoses);
|
||||
_currentFramePoses.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -329,6 +329,16 @@ QString UserInputMapper::getActionName(Action action) const {
|
|||
return QString();
|
||||
}
|
||||
|
||||
QString UserInputMapper::getStandardPoseName(uint16_t pose) {
|
||||
Locker locker(_lock);
|
||||
for (auto posePair : getStandardInputs()) {
|
||||
if (posePair.first.channel == pose && posePair.first.getType() == ChannelType::POSE) {
|
||||
return posePair.second;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QVector<QString> UserInputMapper::getActionNames() const {
|
||||
Locker locker(_lock);
|
||||
QVector<QString> result;
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace controller {
|
|||
|
||||
QVector<Action> getAllActions() const;
|
||||
QString getActionName(Action action) const;
|
||||
QString getStandardPoseName(uint16_t pose);
|
||||
float getActionState(Action action) const { return _actionStates[toInt(action)]; }
|
||||
Pose getPoseState(Action action) const;
|
||||
int findAction(const QString& actionName) const;
|
||||
|
|
|
@ -36,9 +36,6 @@ void ActionEndpoint::apply(const Pose& value, const Pointer& source) {
|
|||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||
inputRecorder->setActionState(actionName, _currentPose);
|
||||
if (inputRecorder->isPlayingback()) {
|
||||
_currentPose = inputRecorder->getPoseState(actionName);
|
||||
}
|
||||
|
||||
if (!_currentPose.isValid()) {
|
||||
return;
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
#include "../Endpoint.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "../../InputRecorder.h"
|
||||
#include "../../UserInputMapper.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
class StandardEndpoint : public VirtualEndpoint {
|
||||
|
@ -40,6 +45,12 @@ public:
|
|||
|
||||
virtual Pose pose() override {
|
||||
_read = true;
|
||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||
if (inputRecorder->isPlayingback()) {
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
QString actionName = userInputMapper->getStandardPoseName(_input.getChannel());
|
||||
return inputRecorder->getPoseState(actionName);
|
||||
}
|
||||
return VirtualEndpoint::pose();
|
||||
}
|
||||
|
||||
|
|
|
@ -201,6 +201,13 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
|
|||
}
|
||||
}
|
||||
|
||||
void AccountManager::setSessionID(const QUuid& sessionID) {
|
||||
if (_sessionID != sessionID) {
|
||||
qCDebug(networking) << "Metaverse session ID changed to" << uuidStringWithoutCurlyBraces(sessionID);
|
||||
_sessionID = sessionID;
|
||||
}
|
||||
}
|
||||
|
||||
void AccountManager::sendRequest(const QString& path,
|
||||
AccountManagerAuth::Type authType,
|
||||
QNetworkAccessManager::Operation operation,
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
static QJsonObject dataObjectFromResponse(QNetworkReply& requestReply);
|
||||
|
||||
QUuid getSessionID() const { return _sessionID; }
|
||||
void setSessionID(const QUuid& sessionID) { _sessionID = sessionID; }
|
||||
void setSessionID(const QUuid& sessionID);
|
||||
|
||||
void setTemporaryDomain(const QUuid& domainID, const QString& key);
|
||||
const QString& getTemporaryDomainKey(const QUuid& domainID) { return _accountInfo.getTemporaryDomainKey(domainID); }
|
||||
|
|
|
@ -56,7 +56,7 @@ void UserActivityLoggerScriptingInterface::palAction(QString action, QString tar
|
|||
}
|
||||
|
||||
void UserActivityLoggerScriptingInterface::palOpened(float secondsOpened) {
|
||||
doLogAction("pal_opened", {
|
||||
doLogAction("pal_opened", {
|
||||
{ "seconds_opened", secondsOpened }
|
||||
});
|
||||
}
|
||||
|
@ -71,6 +71,14 @@ void UserActivityLoggerScriptingInterface::makeUserConnection(QString otherID, b
|
|||
doLogAction("makeUserConnection", payload);
|
||||
}
|
||||
|
||||
void UserActivityLoggerScriptingInterface::bubbleToggled(bool newValue) {
|
||||
doLogAction(newValue ? "bubbleOn" : "bubbleOff");
|
||||
}
|
||||
|
||||
void UserActivityLoggerScriptingInterface::bubbleActivated() {
|
||||
doLogAction("bubbleActivated");
|
||||
}
|
||||
|
||||
void UserActivityLoggerScriptingInterface::logAction(QString action, QVariantMap details) {
|
||||
doLogAction(action, QJsonObject::fromVariantMap(details));
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
Q_INVOKABLE void palAction(QString action, QString target);
|
||||
Q_INVOKABLE void palOpened(float secondsOpen);
|
||||
Q_INVOKABLE void makeUserConnection(QString otherUser, bool success, QString details = "");
|
||||
Q_INVOKABLE void bubbleToggled(bool newValue);
|
||||
Q_INVOKABLE void bubbleActivated();
|
||||
Q_INVOKABLE void logAction(QString action, QVariantMap details = QVariantMap{});
|
||||
private:
|
||||
void doLogAction(QString action, QJsonObject details = {});
|
||||
|
|
|
@ -114,6 +114,7 @@ void EntityMotionState::handleDeactivation() {
|
|||
|
||||
// virtual
|
||||
void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
assert(_entity);
|
||||
assert(entityTreeIsLocked());
|
||||
updateServerPhysicsVariables();
|
||||
ObjectMotionState::handleEasyChanges(flags);
|
||||
|
@ -170,6 +171,7 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
|
||||
// virtual
|
||||
bool EntityMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
assert(_entity);
|
||||
updateServerPhysicsVariables();
|
||||
return ObjectMotionState::handleHardAndEasyChanges(flags, engine);
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ void ObjectMotionState::setShape(const btCollisionShape* shape) {
|
|||
}
|
||||
|
||||
void ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
assert(_body && _shape);
|
||||
if (flags & Simulation::DIRTY_POSITION) {
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
btVector3 newPosition = glmToBullet(getObjectPosition());
|
||||
|
@ -282,6 +283,7 @@ void ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
}
|
||||
|
||||
bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
assert(_body && _shape);
|
||||
if (flags & Simulation::DIRTY_SHAPE) {
|
||||
// make sure the new shape is valid
|
||||
if (!isReadyToComputeShape()) {
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
static ShapeManager* getShapeManager();
|
||||
|
||||
ObjectMotionState(const btCollisionShape* shape);
|
||||
~ObjectMotionState();
|
||||
virtual ~ObjectMotionState();
|
||||
|
||||
virtual void handleEasyChanges(uint32_t& flags);
|
||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
||||
|
|
|
@ -130,7 +130,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
|
|||
}
|
||||
|
||||
// then remove the objects (aka MotionStates) from physics
|
||||
_physicsEngine->removeObjects(_physicalObjects);
|
||||
_physicsEngine->removeSetOfObjects(_physicalObjects);
|
||||
|
||||
// delete the MotionStates
|
||||
// TODO: after we invert the entities/physics lib dependencies we will let EntityItem delete
|
||||
|
|
|
@ -207,7 +207,7 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) {
|
|||
}
|
||||
|
||||
// Same as above, but takes a Set instead of a Vector. Should only be called during teardown.
|
||||
void PhysicsEngine::removeObjects(const SetOfMotionStates& objects) {
|
||||
void PhysicsEngine::removeSetOfObjects(const SetOfMotionStates& objects) {
|
||||
_contactMap.clear();
|
||||
for (auto object : objects) {
|
||||
btRigidBody* body = object->getRigidBody();
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
uint32_t getNumSubsteps();
|
||||
|
||||
void removeObjects(const VectorOfMotionStates& objects);
|
||||
void removeObjects(const SetOfMotionStates& objects); // only called during teardown
|
||||
void removeSetOfObjects(const SetOfMotionStates& objects); // only called during teardown
|
||||
|
||||
void addObjects(const VectorOfMotionStates& objects);
|
||||
VectorOfMotionStates changeObjects(const VectorOfMotionStates& objects);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
/* global Script, Users, Overlays, AvatarList, Controller, Camera, getControllerWorldLocation */
|
||||
/* global Script, Users, Overlays, AvatarList, Controller, Camera, getControllerWorldLocation, UserActivityLogger */
|
||||
|
||||
(function () { // BEGIN LOCAL_SCOPE
|
||||
var button;
|
||||
|
@ -76,6 +76,7 @@
|
|||
// Called from the C++ scripting interface to show the bubble overlay
|
||||
function enteredIgnoreRadius() {
|
||||
createOverlays();
|
||||
UserActivityLogger.bubbleActivated();
|
||||
}
|
||||
|
||||
// Used to set the state of the bubble HUD button
|
||||
|
@ -139,10 +140,14 @@
|
|||
}
|
||||
|
||||
// When the space bubble is toggled...
|
||||
function onBubbleToggled() {
|
||||
var bubbleActive = Users.getIgnoreRadiusEnabled();
|
||||
writeButtonProperties(bubbleActive);
|
||||
if (bubbleActive) {
|
||||
// NOTE: the c++ calls this with just the first param -- we added a second
|
||||
// just for not logging the initial state of the bubble when we startup.
|
||||
function onBubbleToggled(enabled, doNotLog) {
|
||||
writeButtonProperties(enabled);
|
||||
if (doNotLog !== true) {
|
||||
UserActivityLogger.bubbleToggled(enabled);
|
||||
}
|
||||
if (enabled) {
|
||||
createOverlays();
|
||||
} else {
|
||||
hideOverlays();
|
||||
|
@ -163,7 +168,7 @@
|
|||
sortOrder: 4
|
||||
});
|
||||
|
||||
onBubbleToggled();
|
||||
onBubbleToggled(Users.getIgnoreRadiusEnabled(), true); // pass in true so we don't log this initial one in the UserActivity table
|
||||
|
||||
button.clicked.connect(Users.toggleIgnoreRadius);
|
||||
Users.ignoreRadiusEnabledChanged.connect(onBubbleToggled);
|
||||
|
|
|
@ -2100,7 +2100,13 @@ function selectParticleEntity(entityID) {
|
|||
}
|
||||
|
||||
entityListTool.webView.webEventReceived.connect(function (data) {
|
||||
data = JSON.parse(data);
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch(e) {
|
||||
print("edit.js: Error parsing JSON: " + e.name + " data " + data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type === 'parent') {
|
||||
parentSelectedEntities();
|
||||
} else if(data.type === 'unparent') {
|
||||
|
|
|
@ -109,7 +109,13 @@ EntityListTool = function(opts) {
|
|||
};
|
||||
|
||||
webView.webEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch(e) {
|
||||
print("entityList.js: Error parsing JSON: " + e.name + " data " + data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type == "selectionUpdate") {
|
||||
var ids = data.entityIds;
|
||||
var entityIDs = [];
|
||||
|
|
|
@ -238,7 +238,13 @@ GridTool = function(opts) {
|
|||
});
|
||||
|
||||
webView.webEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch(e) {
|
||||
print("gridTool.js: Error parsing JSON: " + e.name + " data " + data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type == "init") {
|
||||
horizontalGrid.emitUpdate();
|
||||
} else if (data.type == "update") {
|
||||
|
|
Loading…
Reference in a new issue