Merge pull request #8258 from AlexanderOtavka/edit-model-ui

Edit model dialog improvements
This commit is contained in:
Ryan Downe Karpf 2016-07-22 17:11:52 -07:00 committed by GitHub
commit 91714aaca6
15 changed files with 689 additions and 219 deletions

View file

@ -28,6 +28,7 @@ module.exports = {
"ModelCache": false, "ModelCache": false,
"MyAvatar": false, "MyAvatar": false,
"Overlays": false, "Overlays": false,
"OverlayWebWindow": false,
"Paths": false, "Paths": false,
"Quat": false, "Quat": false,
"Rates": false, "Rates": false,
@ -43,6 +44,7 @@ module.exports = {
"Toolbars": false, "Toolbars": false,
"Uuid": false, "Uuid": false,
"UndoStack": false, "UndoStack": false,
"UserActivityLogger": false,
"Vec3": false, "Vec3": false,
"WebSocket": false, "WebSocket": false,
"WebWindow": false, "WebWindow": false,
@ -56,6 +58,7 @@ module.exports = {
"comma-dangle": ["error", "never"], "comma-dangle": ["error", "never"],
"camelcase": ["error"], "camelcase": ["error"],
"curly": ["error", "all"], "curly": ["error", "all"],
"eqeqeq": ["error", "always"],
"indent": ["error", 4, { "SwitchCase": 1 }], "indent": ["error", 4, { "SwitchCase": 1 }],
"keyword-spacing": ["error", { "before": true, "after": true }], "keyword-spacing": ["error", { "before": true, "after": true }],
"max-len": ["error", 128, 4], "max-len": ["error", 128, 4],

View file

@ -65,6 +65,7 @@ Original.CheckBox {
colorScheme: checkBox.colorScheme colorScheme: checkBox.colorScheme
x: checkBox.boxSize / 2 x: checkBox.boxSize / 2
wrapMode: Text.Wrap wrapMode: Text.Wrap
enabled: checkBox.enabled
} }
} }
} }

View file

@ -117,19 +117,22 @@ FocusScope {
function showList() { function showList() {
var r = desktop.mapFromItem(root, 0, 0, root.width, root.height); var r = desktop.mapFromItem(root, 0, 0, root.width, root.height);
listView.currentIndex = root.currentIndex var y = r.y + r.height;
scrollView.x = r.x; var bottom = y + scrollView.height;
scrollView.y = r.y + r.height;
var bottom = scrollView.y + scrollView.height;
if (bottom > desktop.height) { if (bottom > desktop.height) {
scrollView.y -= bottom - desktop.height + 8; y -= bottom - desktop.height + 8;
} }
scrollView.x = r.x;
scrollView.y = y;
popup.visible = true; popup.visible = true;
popup.forceActiveFocus(); popup.forceActiveFocus();
listView.currentIndex = root.currentIndex;
scrollView.hoverEnabled = true;
} }
function hideList() { function hideList() {
popup.visible = false; popup.visible = false;
scrollView.hoverEnabled = false;
} }
FocusScope { FocusScope {
@ -161,6 +164,7 @@ FocusScope {
id: scrollView id: scrollView
height: 480 height: 480
width: root.width + 4 width: root.width + 4
property bool hoverEnabled: false;
style: ScrollViewStyle { style: ScrollViewStyle {
decrementControl: Item { decrementControl: Item {
@ -193,7 +197,8 @@ FocusScope {
delegate: Rectangle { delegate: Rectangle {
width: root.width + 4 width: root.width + 4
height: popupText.implicitHeight * 1.4 height: popupText.implicitHeight * 1.4
color: popupHover.containsMouse ? hifi.colors.primaryHighlight : (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark) color: (listView.currentIndex === index) ? hifi.colors.primaryHighlight :
(isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
FiraSansSemiBold { FiraSansSemiBold {
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.textPadding anchors.leftMargin: hifi.dimensions.textPadding
@ -206,9 +211,9 @@ FocusScope {
MouseArea { MouseArea {
id: popupHover id: popupHover
anchors.fill: parent; anchors.fill: parent;
hoverEnabled: true hoverEnabled: scrollView.hoverEnabled;
onEntered: listView.currentIndex = index; onEntered: listView.currentIndex = index;
onClicked: popup.selectSpecificItem(index) onClicked: popup.selectSpecificItem(index);
} }
} }
} }

View file

@ -16,5 +16,6 @@ RalewaySemiBold {
property int colorScheme: hifi.colorSchemes.light property int colorScheme: hifi.colorSchemes.light
size: hifi.fontSizes.inputLabel size: hifi.fontSizes.inputLabel
color: colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText color: enabled ? (colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText)
: (colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight);
} }

View file

@ -456,6 +456,11 @@ FocusScope {
return inputDialogBuilder.createObject(desktop, properties); return inputDialogBuilder.createObject(desktop, properties);
} }
Component { id: customInputDialogBuilder; CustomQueryDialog { } }
function customInputDialog(properties) {
return customInputDialogBuilder.createObject(desktop, properties);
}
Component { id: fileDialogBuilder; FileDialog { } } Component { id: fileDialogBuilder; FileDialog { } }
function fileDialog(properties) { function fileDialog(properties) {
return fileDialogBuilder.createObject(desktop, properties); return fileDialogBuilder.createObject(desktop, properties);

View file

@ -0,0 +1,300 @@
//
// CustomQueryDialog.qml
//
// Created by Zander Otavka on 7/14/16
// 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
//
import QtQuick 2.5;
import QtQuick.Controls 1.4;
import QtQuick.Dialogs 1.2 as OriginalDialogs;
import "../controls-uit";
import "../styles-uit";
import "../windows";
ModalWindow {
id: root;
HifiConstants { id: hifi; }
implicitWidth: 640;
implicitHeight: 320;
visible: true;
signal selected(var result);
signal canceled();
property int icon: hifi.icons.none;
property string iconText: "";
property int iconSize: 35;
onIconChanged: updateIcon();
property var textInput;
property var comboBox;
property var checkBox;
onTextInputChanged: {
if (textInput && textInput.text !== undefined) {
textField.text = textInput.text;
}
}
onComboBoxChanged: {
if (comboBox && comboBox.index !== undefined) {
comboBoxField.currentIndex = comboBox.index;
}
}
onCheckBoxChanged: {
if (checkBox && checkBox.checked !== undefined) {
checkBoxField.checked = checkBox.checked;
}
}
property var warning: "";
property var result;
property var implicitCheckState: null;
property int titleWidth: 0;
onTitleWidthChanged: d.resize();
function updateIcon() {
if (!root) {
return;
}
iconText = hifi.glyphForIcon(root.icon);
}
function updateCheckbox() {
if (checkBox.disableForItems) {
var currentItemInDisableList = false;
for (var i in checkBox.disableForItems) {
if (comboBoxField.currentIndex === checkBox.disableForItems[i]) {
currentItemInDisableList = true;
break;
}
}
if (currentItemInDisableList) {
checkBoxField.enabled = false;
if (checkBox.checkStateOnDisable !== null && checkBox.checkStateOnDisable !== undefined) {
root.implicitCheckState = checkBoxField.checked;
checkBoxField.checked = checkBox.checkStateOnDisable;
}
root.warning = checkBox.warningOnDisable;
} else {
checkBoxField.enabled = true;
if (root.implicitCheckState !== null) {
checkBoxField.checked = root.implicitCheckState;
root.implicitCheckState = null;
}
root.warning = "";
}
}
}
Item {
clip: true;
width: pane.width;
height: pane.height;
anchors.margins: 0;
QtObject {
id: d;
readonly property int minWidth: 480;
readonly property int maxWdith: 1280;
readonly property int minHeight: 120;
readonly property int maxHeight: 720;
function resize() {
var targetWidth = Math.max(titleWidth, pane.width);
var targetHeight = (textField.visible ? textField.controlHeight + hifi.dimensions.contentSpacing.y : 0) +
(extraInputs.visible ? extraInputs.height + hifi.dimensions.contentSpacing.y : 0) +
(buttons.height + 3 * hifi.dimensions.contentSpacing.y);
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
root.height = (targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ?
d.maxHeight : targetHeight);
if (checkBoxField.visible && comboBoxField.visible) {
checkBoxField.width = extraInputs.width / 2;
comboBoxField.width = extraInputs.width / 2;
} else if (!checkBoxField.visible && comboBoxField.visible) {
comboBoxField.width = extraInputs.width;
}
}
}
Item {
anchors {
top: parent.top;
bottom: extraInputs.visible ? extraInputs.top : buttons.top;
left: parent.left;
right: parent.right;
margins: 0;
bottomMargin: hifi.dimensions.contentSpacing.y;
}
// FIXME make a text field type that can be bound to a history for autocompletion
TextField {
id: textField;
label: root.textInput.label;
focus: root.textInput ? true : false;
visible: root.textInput ? true : false;
anchors {
left: parent.left;
right: parent.right;
bottom: parent.bottom;
}
}
}
Item {
id: extraInputs;
visible: Boolean(root.checkBox || root.comboBox);
anchors {
left: parent.left;
right: parent.right;
bottom: buttons.top;
bottomMargin: hifi.dimensions.contentSpacing.y;
}
height: comboBoxField.controlHeight;
onHeightChanged: d.resize();
onWidthChanged: d.resize();
CheckBox {
id: checkBoxField;
text: root.checkBox.label;
focus: Boolean(root.checkBox);
visible: Boolean(root.checkBox);
anchors {
left: parent.left;
bottom: parent.bottom;
leftMargin: 6; // Magic number to align with warning icon
}
}
ComboBox {
id: comboBoxField;
label: root.comboBox.label;
focus: Boolean(root.comboBox);
visible: Boolean(root.comboBox);
anchors {
right: parent.right;
bottom: parent.bottom;
}
model: root.comboBox ? root.comboBox.items : [];
onCurrentTextChanged: updateCheckbox();
}
}
Row {
id: buttons;
focus: true;
spacing: hifi.dimensions.contentSpacing.x;
layoutDirection: Qt.RightToLeft;
onHeightChanged: d.resize();
onWidthChanged: {
d.resize();
resizeWarningText();
}
anchors {
bottom: parent.bottom;
left: parent.left;
right: parent.right;
bottomMargin: hifi.dimensions.contentSpacing.y;
}
function resizeWarningText() {
var rowWidth = buttons.width;
var buttonsWidth = acceptButton.width + cancelButton.width + hifi.dimensions.contentSpacing.x * 2;
var warningIconWidth = warningIcon.width + hifi.dimensions.contentSpacing.x;
warningText.width = rowWidth - buttonsWidth - warningIconWidth;
}
Button {
id: cancelButton;
action: cancelAction;
}
Button {
id: acceptButton;
action: acceptAction;
}
Text {
id: warningText;
visible: Boolean(root.warning);
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
maximumLineCount: 2;
}
HiFiGlyphs {
id: warningIcon;
visible: Boolean(root.warning);
text: hifi.glyphs.alert;
size: hifi.dimensions.controlLineHeight;
}
}
Action {
id: cancelAction;
text: qsTr("Cancel");
shortcut: Qt.Key_Escape;
onTriggered: {
root.result = null;
root.canceled();
root.destroy();
}
}
Action {
id: acceptAction;
text: qsTr("Add");
shortcut: Qt.Key_Return;
onTriggered: {
var result = {};
if (textInput) {
result.textInput = textField.text;
}
if (comboBox) {
result.comboBox = comboBoxField.currentIndex;
result.comboBoxText = comboBoxField.currentText;
}
if (checkBox) {
result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null;
}
root.result = JSON.stringify(result);
root.selected(root.result);
root.destroy();
}
}
}
Keys.onPressed: {
if (!visible) {
return;
}
switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
cancelAction.trigger();
event.accepted = true;
break;
case Qt.Key_Return:
case Qt.Key_Enter:
acceptAction.trigger();
event.accepted = true;
break;
}
}
Component.onCompleted: {
updateIcon();
d.resize();
textField.forceActiveFocus();
}
}

View file

@ -4715,6 +4715,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get<ToolbarScriptingInterface>().data()); scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get<ToolbarScriptingInterface>().data());
scriptEngine->registerGlobalObject("Window", DependencyManager::get<WindowScriptingInterface>().data()); scriptEngine->registerGlobalObject("Window", DependencyManager::get<WindowScriptingInterface>().data());
qScriptRegisterMetaType(scriptEngine, CustomPromptResultToScriptValue, CustomPromptResultFromScriptValue);
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
LocationScriptingInterface::locationSetter, "Window"); LocationScriptingInterface::locationSetter, "Window");
// register `location` on the global object. // register `location` on the global object.

View file

@ -29,6 +29,20 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation"; static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result) {
if (!result.value.isValid()) {
return QScriptValue::UndefinedValue;
}
Q_ASSERT(result.value.userType() == qMetaTypeId<QVariantMap>());
return engine->toScriptValue(result.value.toMap());
}
void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result) {
result.value = object.toVariant();
}
WindowScriptingInterface::WindowScriptingInterface() { WindowScriptingInterface::WindowScriptingInterface() {
const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler(); const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged); connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged);
@ -95,6 +109,14 @@ QScriptValue WindowScriptingInterface::prompt(const QString& message, const QStr
return ok ? QScriptValue(result) : QScriptValue::NullValue; return ok ? QScriptValue(result) : QScriptValue::NullValue;
} }
CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) {
CustomPromptResult result;
bool ok = false;
auto configMap = config.toMap();
result.value = OffscreenUi::getCustomInfo(OffscreenUi::ICON_NONE, "", configMap, &ok);
return ok ? result : CustomPromptResult();
}
QString fixupPathForMac(const QString& directory) { QString fixupPathForMac(const QString& directory) {
// On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus // On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus
// filename if the directory is valid. // filename if the directory is valid.

View file

@ -18,6 +18,18 @@
class WebWindowClass; class WebWindowClass;
class CustomPromptResult {
public:
QVariant value;
};
Q_DECLARE_METATYPE(CustomPromptResult);
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result);
void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result);
class WindowScriptingInterface : public QObject, public Dependency { class WindowScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int innerWidth READ getInnerWidth) Q_PROPERTY(int innerWidth READ getInnerWidth)
@ -38,6 +50,7 @@ public slots:
void alert(const QString& message = ""); void alert(const QString& message = "");
QScriptValue confirm(const QString& message = ""); QScriptValue confirm(const QString& message = "");
QScriptValue prompt(const QString& message = "", const QString& defaultText = ""); QScriptValue prompt(const QString& message = "", const QString& defaultText = "");
CustomPromptResult customPrompt(const QVariant& config);
QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
void copyToClipboard(const QString& text); void copyToClipboard(const QString& text);

View file

@ -700,11 +700,12 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
} }
info.setParams(type, dimensions, _compoundShapeURL); info.setParams(type, dimensions, _compoundShapeURL);
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
updateModelBounds();
// should never fall in here when model not fully loaded // should never fall in here when model not fully loaded
assert(_model && _model->isLoaded()); assert(_model && _model->isLoaded());
updateModelBounds();
_model->updateGeometry();
// compute meshPart local transforms // compute meshPart local transforms
QVector<glm::mat4> localTransforms; QVector<glm::mat4> localTransforms;
const FBXGeometry& fbxGeometry = _model->getFBXGeometry(); const FBXGeometry& fbxGeometry = _model->getFBXGeometry();

View file

@ -69,7 +69,6 @@ static const btVector3 _unitSphereDirections[NUM_UNIT_SPHERE_DIRECTIONS] = {
// util method // util method
btConvexHullShape* createConvexHull(const ShapeInfo::PointList& points) { btConvexHullShape* createConvexHull(const ShapeInfo::PointList& points) {
//std::cout << "adebug createConvexHull() points.size() = " << points.size() << std::endl; // adebug
assert(points.size() > 0); assert(points.size() > 0);
btConvexHullShape* hull = new btConvexHullShape(); btConvexHullShape* hull = new btConvexHullShape();
@ -241,7 +240,6 @@ void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) {
btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
btCollisionShape* shape = NULL; btCollisionShape* shape = NULL;
int type = info.getType(); int type = info.getType();
//std::cout << "adebug createShapeFromInfo() type = " << type << std::endl; // adebug
switch(type) { switch(type) {
case SHAPE_TYPE_BOX: { case SHAPE_TYPE_BOX: {
shape = new btBoxShape(glmToBullet(info.getHalfExtents())); shape = new btBoxShape(glmToBullet(info.getHalfExtents()));

View file

@ -84,6 +84,7 @@ public:
bool readyToAddToScene(RenderArgs* renderArgs = nullptr) const { bool readyToAddToScene(RenderArgs* renderArgs = nullptr) const {
return !_needsReload && isRenderable() && isActive(); return !_needsReload && isRenderable() && isActive();
} }
bool needsReload() const { return _needsReload; }
bool initWhenReady(render::ScenePointer scene); bool initWhenReady(render::ScenePointer scene);
bool addToScene(std::shared_ptr<render::Scene> scene, bool addToScene(std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges, render::PendingChanges& pendingChanges,
@ -232,6 +233,9 @@ public:
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } const glm::vec3& getRegistrationPoint() const { return _registrationPoint; }
// returns 'true' if needs fullUpdate after geometry change
bool updateGeometry();
protected: protected:
void setPupilDilation(float dilation) { _pupilDilation = dilation; } void setPupilDilation(float dilation) { _pupilDilation = dilation; }
@ -297,9 +301,6 @@ protected:
std::unordered_set<int> _cauterizeBoneSet; std::unordered_set<int> _cauterizeBoneSet;
bool _cauterizeBones; bool _cauterizeBones;
// returns 'true' if needs fullUpdate after geometry change
bool updateGeometry();
virtual void initJointStates(); virtual void initJointStates();
void setScaleInternal(const glm::vec3& scale); void setScaleInternal(const glm::vec3& scale);

View file

@ -343,6 +343,23 @@ QString OffscreenUi::getItem(const Icon icon, const QString& title, const QStrin
return result.toString(); return result.toString();
} }
QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok) {
if (ok) {
*ok = false;
}
QVariant result = DependencyManager::get<OffscreenUi>()->customInputDialog(icon, title, config);
if (result.isValid()) {
// We get a JSON encoded result, so we unpack it into a QVariant wrapping a QVariantMap
result = QVariant(QJsonDocument::fromJson(result.toString().toUtf8()).object().toVariantMap());
if (ok) {
*ok = true;
}
}
return result;
}
QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) { QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
QVariant result; QVariant result;
@ -358,6 +375,20 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q
return waitForInputDialogResult(createInputDialog(icon, title, label, current)); return waitForInputDialogResult(createInputDialog(icon, title, label, current));
} }
QVariant OffscreenUi::customInputDialog(const Icon icon, const QString& title, const QVariantMap& config) {
if (QThread::currentThread() != thread()) {
QVariant result;
QMetaObject::invokeMethod(this, "customInputDialog", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QVariant, result),
Q_ARG(Icon, icon),
Q_ARG(QString, title),
Q_ARG(QVariantMap, config));
return result;
}
return waitForInputDialogResult(createCustomInputDialog(icon, title, config));
}
void OffscreenUi::togglePinned() { void OffscreenUi::togglePinned() {
bool invokeResult = QMetaObject::invokeMethod(_desktop, "togglePinned"); bool invokeResult = QMetaObject::invokeMethod(_desktop, "togglePinned");
if (!invokeResult) { if (!invokeResult) {
@ -401,6 +432,23 @@ QQuickItem* OffscreenUi::createInputDialog(const Icon icon, const QString& title
return qvariant_cast<QQuickItem*>(result); return qvariant_cast<QQuickItem*>(result);
} }
QQuickItem* OffscreenUi::createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config) {
QVariantMap map = config;
map.insert("title", title);
map.insert("icon", icon);
QVariant result;
bool invokeResult = QMetaObject::invokeMethod(_desktop, "customInputDialog",
Q_RETURN_ARG(QVariant, result),
Q_ARG(QVariant, QVariant::fromValue(map)));
if (!invokeResult) {
qWarning() << "Failed to create custom message box";
return nullptr;
}
return qvariant_cast<QQuickItem*>(result);
}
QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) { QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) {
if (!inputDialog) { if (!inputDialog) {
return QVariant(); return QVariant();

View file

@ -122,7 +122,9 @@ public:
static QString getSaveFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0); static QString getSaveFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant()); Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
Q_INVOKABLE QVariant customInputDialog(const Icon icon, const QString& title, const QVariantMap& config);
QQuickItem* createInputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current); QQuickItem* createInputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current);
QQuickItem* createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config);
QVariant waitForInputDialogResult(QQuickItem* inputDialog); QVariant waitForInputDialogResult(QQuickItem* inputDialog);
// Compatibility with QInputDialog::getText // Compatibility with QInputDialog::getText
@ -140,6 +142,7 @@ public:
static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0); static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0);
static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0); static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0);
static QVariant getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok = 0);
unsigned int getMenuUserDataId() const; unsigned int getMenuUserDataId() const;

View file

@ -11,11 +11,13 @@
// 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
// //
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton";
var SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; var SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
var EDIT_TOOLBAR = "com.highfidelity.interface.toolbar.edit"; var EDIT_TOOLBAR = "com.highfidelity.interface.toolbar.edit";
/* globals SelectionDisplay, SelectionManager, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Toolbars,
progressDialog, tooltip, ParticleExplorerTool */
Script.include([ Script.include([
"libraries/stringHelpers.js", "libraries/stringHelpers.js",
"libraries/dataViewHelpers.js", "libraries/dataViewHelpers.js",
@ -29,7 +31,7 @@ Script.include([
"libraries/gridTool.js", "libraries/gridTool.js",
"libraries/entityList.js", "libraries/entityList.js",
"particle_explorer/particleExplorerTool.js", "particle_explorer/particleExplorerTool.js",
"libraries/lightOverlayManager.js", "libraries/lightOverlayManager.js"
]); ]);
var selectionDisplay = SelectionDisplay; var selectionDisplay = SelectionDisplay;
@ -39,13 +41,13 @@ var lightOverlayManager = new LightOverlayManager();
var cameraManager = new CameraManager(); var cameraManager = new CameraManager();
var grid = Grid(); var grid = new Grid();
gridTool = GridTool({ var gridTool = new GridTool({
horizontalGrid: grid horizontalGrid: grid
}); });
gridTool.setVisible(false); gridTool.setVisible(false);
var entityListTool = EntityListTool(); var entityListTool = new EntityListTool();
selectionManager.addEventListener(function () { selectionManager.addEventListener(function () {
selectionDisplay.updateHandles(); selectionDisplay.updateHandles();
@ -89,17 +91,16 @@ var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode";
// marketplace info, etc. not quite ready yet. // marketplace info, etc. not quite ready yet.
var SHOULD_SHOW_PROPERTY_MENU = false; var SHOULD_SHOW_PROPERTY_MENU = false;
var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain." var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain.";
var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain." var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain.";
var mode = 0; var mode = 0;
var isActive = false; var isActive = false;
IMPORTING_SVO_OVERLAY_WIDTH = 144; var IMPORTING_SVO_OVERLAY_WIDTH = 144;
IMPORTING_SVO_OVERLAY_HEIGHT = 30; var IMPORTING_SVO_OVERLAY_HEIGHT = 30;
IMPORTING_SVO_OVERLAY_MARGIN = 5; var IMPORTING_SVO_OVERLAY_MARGIN = 5;
IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34;
var importingSVOImageOverlay = Overlays.addOverlay("image", { var importingSVOImageOverlay = Overlays.addOverlay("image", {
imageURL: Script.resolvePath("assets") + "/images/hourglass.svg", imageURL: Script.resolvePath("assets") + "/images/hourglass.svg",
width: 20, width: 20,
@ -107,7 +108,7 @@ var importingSVOImageOverlay = Overlays.addOverlay("image", {
alpha: 1.0, alpha: 1.0,
x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH,
y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT,
visible: false, visible: false
}); });
var importingSVOTextOverlay = Overlays.addOverlay("text", { var importingSVOTextOverlay = Overlays.addOverlay("text", {
font: { font: {
@ -125,7 +126,7 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", {
blue: 80 blue: 80
}, },
backgroundAlpha: 0.7, backgroundAlpha: 0.7,
visible: false, visible: false
}); });
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
@ -177,7 +178,7 @@ var toolBar = (function() {
var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS; var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS;
var position = getPositionToCreateEntity(); var position = getPositionToCreateEntity();
var entityID = null; var entityID = null;
if (position != null) { if (position !== null && position !== undefined) {
position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions), position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions),
properties.position = position; properties.position = position;
entityID = Entities.addEntity(properties); entityID = Entities.addEntity(properties);
@ -204,7 +205,7 @@ var toolBar = (function() {
imageURL: imageUrl, imageURL: imageUrl,
buttonState: 1, buttonState: 1,
alpha: 0.9, alpha: 0.9,
visible: true, visible: true
}); });
if (handler) { if (handler) {
button.clicked.connect(function () { button.clicked.connect(function () {
@ -237,7 +238,7 @@ var toolBar = (function() {
alpha: 0.9, alpha: 0.9,
buttonState: 1, buttonState: 1,
hoverState: 3, hoverState: 3,
defaultState: 1, defaultState: 1
}); });
activeButton.clicked.connect(function () { activeButton.clicked.connect(function () {
that.setActive(!isActive); that.setActive(!isActive);
@ -250,13 +251,70 @@ var toolBar = (function() {
toolBar.writeProperty("shown", false); toolBar.writeProperty("shown", false);
addButton("newModelButton", "model-01.svg", function () { addButton("newModelButton", "model-01.svg", function () {
var url = Window.prompt("Model URL"); var SHAPE_TYPE_NONE = 0;
if (url !== null && url !== "") { var SHAPE_TYPE_SIMPLE_HULL = 1;
var SHAPE_TYPE_SIMPLE_COMPOUND = 2;
var SHAPE_TYPE_STATIC_MESH = 3;
var SHAPE_TYPES = [];
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH;
var DYNAMIC_DEFAULT = false;
var result = Window.customPrompt({
textInput: {
label: "Model URL"
},
comboBox: {
label: "Automatic Collisions",
index: SHAPE_TYPE_DEFAULT,
items: SHAPE_TYPES
},
checkBox: {
label: "Dynamic",
checked: DYNAMIC_DEFAULT,
disableForItems: [
SHAPE_TYPE_STATIC_MESH
],
checkStateOnDisable: false,
warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic"
}
});
if (result) {
var url = result.textInput;
var shapeType;
switch (result.comboBox) {
case SHAPE_TYPE_SIMPLE_HULL:
shapeType = "simple-hull";
break;
case SHAPE_TYPE_SIMPLE_COMPOUND:
shapeType = "simple-compound";
break;
case SHAPE_TYPE_STATIC_MESH:
shapeType = "static-mesh";
break;
default:
shapeType = "none";
}
var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT;
if (shapeType === "static-mesh" && dynamic) {
// The prompt should prevent this case
print("Error: model cannot be both static mesh and dynamic. This should never happen.");
} else if (url) {
createNewEntity({ createNewEntity({
type: "Model", type: "Model",
modelURL: url modelURL: url,
shapeType: shapeType,
dynamic: dynamic,
gravity: dynamic ? { x: 0, y: -10, z: 0 } : { x: 0, y: 0, z: 0 }
}); });
} }
}
}); });
addButton("newCubeButton", "cube-01.svg", function () { addButton("newCubeButton", "cube-01.svg", function () {
@ -298,7 +356,7 @@ var toolBar = (function() {
linearAttenuation: 0, linearAttenuation: 0,
quadraticAttenuation: 0, quadraticAttenuation: 0,
exponent: 0, exponent: 0,
cutoff: 180, // in degrees cutoff: 180 // in degrees
}); });
}); });
@ -333,7 +391,7 @@ var toolBar = (function() {
y: 0.9, y: 0.9,
z: 0.01 z: 0.01
}, },
sourceUrl: "https://highfidelity.com/", sourceUrl: "https://highfidelity.com/"
}); });
}); });
@ -344,7 +402,7 @@ var toolBar = (function() {
x: 10, x: 10,
y: 10, y: 10,
z: 10 z: 10
}, }
}); });
}); });
@ -352,7 +410,6 @@ var toolBar = (function() {
createNewEntity({ createNewEntity({
type: "ParticleEffect", type: "ParticleEffect",
isEmitting: true, isEmitting: true,
particleRadius: 0.1,
emitAcceleration: { emitAcceleration: {
x: 0, x: 0,
y: -1, y: -1,
@ -368,7 +425,7 @@ var toolBar = (function() {
particleRadius: 0.025, particleRadius: 0.025,
alphaFinish: 0, alphaFinish: 0,
emitRate: 100, emitRate: 100,
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png"
}); });
}); });
@ -380,7 +437,7 @@ var toolBar = (function() {
}; };
that.setActive = function (active) { that.setActive = function (active) {
if (active == isActive) { if (active === isActive) {
return; return;
} }
if (active && !Entities.canRez() && !Entities.canRezTmp()) { if (active && !Entities.canRez() && !Entities.canRezTmp()) {
@ -402,7 +459,6 @@ var toolBar = (function() {
selectionDisplay.triggerMapping.disable(); selectionDisplay.triggerMapping.disable();
} else { } else {
UserActivityLogger.enabledEdit(); UserActivityLogger.enabledEdit();
hasShownPropertiesTool = false;
entityListTool.setVisible(true); entityListTool.setVisible(true);
gridTool.setVisible(true); gridTool.setVisible(true);
grid.setEnabled(true); grid.setEnabled(true);
@ -431,8 +487,8 @@ var toolBar = (function() {
function isLocked(properties) { function isLocked(properties) {
// special case to lock the ground plane model in hq. // special case to lock the ground plane model in hq.
if (location.hostname == "hq.highfidelity.io" && if (location.hostname === "hq.highfidelity.io" &&
properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { properties.modelURL === HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") {
return true; return true;
} }
return false; return false;
@ -629,9 +685,10 @@ function mouseReleaseEvent(event) {
function mouseClickEvent(event) { function mouseClickEvent(event) {
var wantDebug = false; var wantDebug = false;
var result, properties;
if (isActive && event.isLeftButton) { if (isActive && event.isLeftButton) {
var result = findClickedEntity(event); result = findClickedEntity(event);
if (result === null) { if (result === null || result === undefined) {
if (!event.isShifted) { if (!event.isShifted) {
selectionManager.clearSelections(); selectionManager.clearSelections();
} }
@ -641,7 +698,7 @@ function mouseClickEvent(event) {
var pickRay = result.pickRay; var pickRay = result.pickRay;
var foundEntity = result.entityID; var foundEntity = result.entityID;
var properties = Entities.getEntityProperties(foundEntity); properties = Entities.getEntityProperties(foundEntity);
if (isLocked(properties)) { if (isLocked(properties)) {
if (wantDebug) { if (wantDebug) {
print("Model locked " + properties.id); print("Model locked " + properties.id);
@ -660,7 +717,7 @@ function mouseClickEvent(event) {
// x x - distance from A // x x - distance from A
// //
// |X-A| = (P-A).B // |X-A| = (P-A).B
// X == A + ((P-A).B)B // X === A + ((P-A).B)B
// d = |P-X| // d = |P-X|
var A = pickRay.origin; var A = pickRay.origin;
@ -668,16 +725,14 @@ function mouseClickEvent(event) {
var P = properties.position; var P = properties.position;
var x = Vec3.dot(Vec3.subtract(P, A), B); var x = Vec3.dot(Vec3.subtract(P, A), B);
var X = Vec3.sum(A, Vec3.multiply(B, x));
var d = Vec3.length(Vec3.subtract(P, X));
var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) *
180 / Math.PI;
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) &&
(allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
if (0 < x && sizeOK) { if (0 < x && sizeOK) {
entitySelected = true;
selectedEntityID = foundEntity; selectedEntityID = foundEntity;
orientation = MyAvatar.orientation; orientation = MyAvatar.orientation;
intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
@ -702,12 +757,12 @@ function mouseClickEvent(event) {
} }
} }
} else if (event.isRightButton) { } else if (event.isRightButton) {
var result = findClickedEntity(event); result = findClickedEntity(event);
if (result) { if (result) {
if (SHOULD_SHOW_PROPERTY_MENU !== true) { if (SHOULD_SHOW_PROPERTY_MENU !== true) {
return; return;
} }
var properties = Entities.getEntityProperties(result.entityID); properties = Entities.getEntityProperties(result.entityID);
if (properties.marketplaceID) { if (properties.marketplaceID) {
propertyMenu.marketplaceID = properties.marketplaceID; propertyMenu.marketplaceID = properties.marketplaceID;
propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace");
@ -833,7 +888,7 @@ function setupModelMenus() {
menuName: "Edit", menuName: "Edit",
menuItemName: MENU_AUTO_FOCUS_ON_SELECT, menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true", isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true",
grouping: "Advanced" grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
@ -841,7 +896,7 @@ function setupModelMenus() {
menuItemName: MENU_EASE_ON_FOCUS, menuItemName: MENU_EASE_ON_FOCUS,
afterItem: MENU_AUTO_FOCUS_ON_SELECT, afterItem: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true", isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true",
grouping: "Advanced" grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
@ -849,7 +904,7 @@ function setupModelMenus() {
menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
afterItem: MENU_EASE_ON_FOCUS, afterItem: MENU_EASE_ON_FOCUS,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true", isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) === "true",
grouping: "Advanced" grouping: "Advanced"
}); });
Menu.addMenuItem({ Menu.addMenuItem({
@ -857,7 +912,7 @@ function setupModelMenus() {
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
isCheckable: true, isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true", isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) === "true",
grouping: "Advanced" grouping: "Advanced"
}); });
@ -927,7 +982,9 @@ Script.update.connect(function(deltaTime) {
}); });
function insideBox(center, dimensions, point) { function insideBox(center, dimensions, point) {
return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) &&
(Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) &&
(Math.abs(point.z - center.z) <= (dimensions.z / 2.0));
} }
function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
@ -939,10 +996,10 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
if (!keepIfTouching) { if (!keepIfTouching) {
var isValid; var isValid;
if (selectionManager.localPosition === null) { if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) {
isValid = function (position) { isValid = function (position) {
return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position);
} };
} else { } else {
isValid = function (position) { isValid = function (position) {
var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation),
@ -953,7 +1010,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
y: 0, y: 0,
z: 0 z: 0
}, selectionManager.localDimensions, localPosition); }, selectionManager.localDimensions, localPosition);
} };
} }
for (var i = 0; i < entities.length; ++i) { for (var i = 0; i < entities.length; ++i) {
var properties = Entities.getEntityProperties(entities[i]); var properties = Entities.getEntityProperties(entities[i]);
@ -1019,19 +1076,19 @@ function toggleSelectedEntitiesVisible() {
} }
function handeMenuEvent(menuItem) { function handeMenuEvent(menuItem) {
if (menuItem == "Allow Selecting of Small Models") { if (menuItem === "Allow Selecting of Small Models") {
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
} else if (menuItem == "Allow Selecting of Large Models") { } else if (menuItem === "Allow Selecting of Large Models") {
allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models");
} else if (menuItem == "Allow Selecting of Lights") { } else if (menuItem === "Allow Selecting of Lights") {
Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
} else if (menuItem == "Delete") { } else if (menuItem === "Delete") {
deleteSelectedEntities(); deleteSelectedEntities();
} else if (menuItem == "Export Entities") { } else if (menuItem === "Export Entities") {
if (!selectionManager.hasSelection()) { if (!selectionManager.hasSelection()) {
Window.alert("No entities have been selected."); Window.alert("No entities have been selected.");
} else { } else {
var filename = Window.save("Select Where to Save", "", "*.json") var filename = Window.save("Select Where to Save", "", "*.json");
if (filename) { if (filename) {
var success = Clipboard.exportEntities(filename, selectionManager.selections); var success = Clipboard.exportEntities(filename, selectionManager.selections);
if (!success) { if (!success) {
@ -1039,10 +1096,10 @@ function handeMenuEvent(menuItem) {
} }
} }
} }
} else if (menuItem == "Import Entities" || menuItem == "Import Entities from URL") { } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") {
var importURL = null; var importURL = null;
if (menuItem == "Import Entities") { if (menuItem === "Import Entities") {
var fullPath = Window.browse("Select Model to Import", "", "*.json"); var fullPath = Window.browse("Select Model to Import", "", "*.json");
if (fullPath) { if (fullPath) {
importURL = "file:///" + fullPath; importURL = "file:///" + fullPath;
@ -1054,15 +1111,15 @@ function handeMenuEvent(menuItem) {
if (importURL) { if (importURL) {
importSVO(importURL); importSVO(importURL);
} }
} else if (menuItem == "Entity List...") { } else if (menuItem === "Entity List...") {
entityListTool.toggleVisible(); entityListTool.toggleVisible();
} else if (menuItem == "Select All Entities In Box") { } else if (menuItem === "Select All Entities In Box") {
selectAllEtitiesInCurrentSelectionBox(false); selectAllEtitiesInCurrentSelectionBox(false);
} else if (menuItem == "Select All Entities Touching Box") { } else if (menuItem === "Select All Entities Touching Box") {
selectAllEtitiesInCurrentSelectionBox(true); selectAllEtitiesInCurrentSelectionBox(true);
} else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) { } else if (menuItem === MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
} else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) { } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
} }
tooltip.show(false); tooltip.show(false);
@ -1081,8 +1138,11 @@ function getPositionToCreateEntity() {
var HALF_TREE_SCALE = 16384; var HALF_TREE_SCALE = 16384;
var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE; var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE ||
var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE; Math.abs(cameraPosition.z) > HALF_TREE_SCALE;
var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE ||
Math.abs(placementPosition.y) > HALF_TREE_SCALE ||
Math.abs(placementPosition.z) > HALF_TREE_SCALE;
if (cameraOutOfBounds && placementOutOfBounds) { if (cameraOutOfBounds && placementOutOfBounds) {
return null; return null;
@ -1096,7 +1156,7 @@ function getPositionToCreateEntity() {
} }
function importSVO(importURL) { function importSVO(importURL) {
print("Import URL requested: " + importURL) print("Import URL requested: " + importURL);
if (!Entities.canAdjustLocks()) { if (!Entities.canAdjustLocks()) {
Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG);
return; return;
@ -1121,7 +1181,7 @@ function importSVO(importURL) {
if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) {
position = getPositionToCreateEntity(); position = getPositionToCreateEntity();
} }
if (position != null) { if (position !== null && position !== undefined) {
var pastedEntityIDs = Clipboard.pasteEntities(position); var pastedEntityIDs = Clipboard.pasteEntities(position);
if (isActive) { if (isActive) {
@ -1158,13 +1218,13 @@ Controller.keyReleaseEvent.connect(function(event) {
cameraManager.keyReleaseEvent(event); cameraManager.keyReleaseEvent(event);
} }
// since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items
if (event.text == "BACKSPACE" || event.text == "DELETE") { if (event.text === "BACKSPACE" || event.text === "DELETE") {
deleteSelectedEntities(); deleteSelectedEntities();
} else if (event.text == "ESC") { } else if (event.text === "ESC") {
selectionManager.clearSelections(); selectionManager.clearSelections();
} else if (event.text == "TAB") { } else if (event.text === "TAB") {
selectionDisplay.toggleSpaceMode(); selectionDisplay.toggleSpaceMode();
} else if (event.text == "f") { } else if (event.text === "f") {
if (isActive) { if (isActive) {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
cameraManager.enable(); cameraManager.enable();
@ -1173,11 +1233,11 @@ Controller.keyReleaseEvent.connect(function(event) {
Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
} }
} }
} else if (event.text == '[') { } else if (event.text === '[') {
if (isActive) { if (isActive) {
cameraManager.enable(); cameraManager.enable();
} }
} else if (event.text == 'g') { } else if (event.text === 'g') {
if (isActive && selectionManager.hasSelection()) { if (isActive && selectionManager.hasSelection()) {
var newPosition = selectionManager.worldPosition; var newPosition = selectionManager.worldPosition;
newPosition = Vec3.subtract(newPosition, { newPosition = Vec3.subtract(newPosition, {
@ -1193,30 +1253,31 @@ Controller.keyReleaseEvent.connect(function(event) {
// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently // When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently
// possible to create an entity with a specific id, earlier undo commands to the deleted entity // possible to create an entity with a specific id, earlier undo commands to the deleted entity
// will fail if there isn't a way to find the new entity id. // will fail if there isn't a way to find the new entity id.
DELETED_ENTITY_MAP = {} var DELETED_ENTITY_MAP = {};
function applyEntityProperties(data) { function applyEntityProperties(data) {
var properties = data.setProperties; var properties = data.setProperties;
var selectedEntityIDs = []; var selectedEntityIDs = [];
for (var i = 0; i < properties.length; i++) { var i, entityID;
var entityID = properties[i].entityID; for (i = 0; i < properties.length; i++) {
entityID = properties[i].entityID;
if (DELETED_ENTITY_MAP[entityID] !== undefined) { if (DELETED_ENTITY_MAP[entityID] !== undefined) {
entityID = DELETED_ENTITY_MAP[entityID]; entityID = DELETED_ENTITY_MAP[entityID];
} }
Entities.editEntity(entityID, properties[i].properties); Entities.editEntity(entityID, properties[i].properties);
selectedEntityIDs.push(entityID); selectedEntityIDs.push(entityID);
} }
for (var i = 0; i < data.createEntities.length; i++) { for (i = 0; i < data.createEntities.length; i++) {
var entityID = data.createEntities[i].entityID; entityID = data.createEntities[i].entityID;
var properties = data.createEntities[i].properties; var entityProperties = data.createEntities[i].properties;
var newEntityID = Entities.addEntity(properties); var newEntityID = Entities.addEntity(entityProperties);
DELETED_ENTITY_MAP[entityID] = newEntityID; DELETED_ENTITY_MAP[entityID] = newEntityID;
if (data.selectCreated) { if (data.selectCreated) {
selectedEntityIDs.push(newEntityID); selectedEntityIDs.push(newEntityID);
} }
} }
for (var i = 0; i < data.deleteEntities.length; i++) { for (i = 0; i < data.deleteEntities.length; i++) {
var entityID = data.deleteEntities[i].entityID; entityID = data.deleteEntities[i].entityID;
if (DELETED_ENTITY_MAP[entityID] !== undefined) { if (DELETED_ENTITY_MAP[entityID] !== undefined) {
entityID = DELETED_ENTITY_MAP[entityID]; entityID = DELETED_ENTITY_MAP[entityID];
} }
@ -1224,7 +1285,7 @@ function applyEntityProperties(data) {
} }
selectionManager.setSelections(selectedEntityIDs); selectionManager.setSelections(selectedEntityIDs);
}; }
// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the // For currently selected entities, push a command to the UndoStack that uses the current entity properties for the
// redo command, and the saved properties for the undo command. Also, include create and delete entity data. // redo command, and the saved properties for the undo command. Also, include create and delete entity data.
@ -1233,13 +1294,13 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
setProperties: [], setProperties: [],
createEntities: deletedEntityData || [], createEntities: deletedEntityData || [],
deleteEntities: createdEntityData || [], deleteEntities: createdEntityData || [],
selectCreated: true, selectCreated: true
}; };
var redoData = { var redoData = {
setProperties: [], setProperties: [],
createEntities: createdEntityData || [], createEntities: createdEntityData || [],
deleteEntities: deletedEntityData || [], deleteEntities: deletedEntityData || [],
selectCreated: false, selectCreated: false
}; };
for (var i = 0; i < SelectionManager.selections.length; i++) { for (var i = 0; i < SelectionManager.selections.length; i++) {
var entityID = SelectionManager.selections[i]; var entityID = SelectionManager.selections[i];
@ -1253,22 +1314,22 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
properties: { properties: {
position: initialProperties.position, position: initialProperties.position,
rotation: initialProperties.rotation, rotation: initialProperties.rotation,
dimensions: initialProperties.dimensions, dimensions: initialProperties.dimensions
}, }
}); });
redoData.setProperties.push({ redoData.setProperties.push({
entityID: entityID, entityID: entityID,
properties: { properties: {
position: currentProperties.position, position: currentProperties.position,
rotation: currentProperties.rotation, rotation: currentProperties.rotation,
dimensions: currentProperties.dimensions, dimensions: currentProperties.dimensions
}, }
}); });
} }
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
} }
PropertiesTool = function(opts) { var PropertiesTool = function (opts) {
var that = {}; var that = {};
var url = Script.resolvePath('html/entityProperties.html'); var url = Script.resolvePath('html/entityProperties.html');
@ -1288,8 +1349,8 @@ PropertiesTool = function(opts) {
}; };
selectionManager.addEventListener(function () { selectionManager.addEventListener(function () {
data = { var data = {
type: 'update', type: 'update'
}; };
var selections = []; var selections = [];
for (var i = 0; i < selectionManager.selections.length; i++) { for (var i = 0; i < selectionManager.selections.length; i++) {
@ -1300,7 +1361,8 @@ PropertiesTool = function(opts) {
entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation);
} }
if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) {
entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES, Vec3.toPolar(entity.properties.keyLight.direction)); entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES,
Vec3.toPolar(entity.properties.keyLight.direction));
entity.properties.keyLight.direction.z = 0.0; entity.properties.keyLight.direction.z = 0.0;
} }
selections.push(entity); selections.push(entity);
@ -1311,18 +1373,19 @@ PropertiesTool = function(opts) {
webView.webEventReceived.connect(function (data) { webView.webEventReceived.connect(function (data) {
data = JSON.parse(data); data = JSON.parse(data);
if (data.type == "print") { var i, properties, dY, diff, newPosition;
if (data.type === "print") {
if (data.message) { if (data.message) {
print(data.message); print(data.message);
} }
} else if (data.type == "update") { } else if (data.type === "update") {
selectionManager.saveProperties(); selectionManager.saveProperties();
if (selectionManager.selections.length > 1) { if (selectionManager.selections.length > 1) {
properties = { properties = {
locked: data.properties.locked, locked: data.properties.locked,
visible: data.properties.visible, visible: data.properties.visible
}; };
for (var i = 0; i < selectionManager.selections.length; i++) { for (i = 0; i < selectionManager.selections.length; i++) {
Entities.editEntity(selectionManager.selections[i], properties); Entities.editEntity(selectionManager.selections[i], properties);
} }
} else { } else {
@ -1345,100 +1408,105 @@ PropertiesTool = function(opts) {
} }
if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) { if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) {
data.properties.keyLight.direction = Vec3.fromPolar( data.properties.keyLight.direction = Vec3.fromPolar(
data.properties.keyLight.direction.x * DEGREES_TO_RADIANS, data.properties.keyLight.direction.y * DEGREES_TO_RADIANS); data.properties.keyLight.direction.x * DEGREES_TO_RADIANS,
data.properties.keyLight.direction.y * DEGREES_TO_RADIANS
);
} }
Entities.editEntity(selectionManager.selections[0], data.properties); Entities.editEntity(selectionManager.selections[0], data.properties);
if (data.properties.name !== undefined || data.properties.modelURL !== undefined || data.properties.visible !== undefined || data.properties.locked !== undefined) { if (data.properties.name !== undefined || data.properties.modelURL !== undefined ||
data.properties.visible !== undefined || data.properties.locked !== undefined) {
entityListTool.sendUpdate(); entityListTool.sendUpdate();
} }
} }
pushCommandForSelections(); pushCommandForSelections();
selectionManager._update(); selectionManager._update();
} else if (data.type == "showMarketplace") { } else if (data.type === "showMarketplace") {
showMarketplace(); showMarketplace();
} else if (data.type == "action") { } else if (data.type === "action") {
if (data.action == "moveSelectionToGrid") { if (data.action === "moveSelectionToGrid") {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
selectionManager.saveProperties(); selectionManager.saveProperties();
var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2);
var diff = { diff = {
x: 0, x: 0,
y: dY, y: dY,
z: 0 z: 0
}; };
for (var i = 0; i < selectionManager.selections.length; i++) { for (i = 0; i < selectionManager.selections.length; i++) {
var properties = selectionManager.savedProperties[selectionManager.selections[i]]; properties = selectionManager.savedProperties[selectionManager.selections[i]];
var newPosition = Vec3.sum(properties.position, diff); newPosition = Vec3.sum(properties.position, diff);
Entities.editEntity(selectionManager.selections[i], { Entities.editEntity(selectionManager.selections[i], {
position: newPosition, position: newPosition
}); });
} }
pushCommandForSelections(); pushCommandForSelections();
selectionManager._update(); selectionManager._update();
} }
} else if (data.action == "moveAllToGrid") { } else if (data.action === "moveAllToGrid") {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
selectionManager.saveProperties(); selectionManager.saveProperties();
for (var i = 0; i < selectionManager.selections.length; i++) { for (i = 0; i < selectionManager.selections.length; i++) {
var properties = selectionManager.savedProperties[selectionManager.selections[i]]; properties = selectionManager.savedProperties[selectionManager.selections[i]];
var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2;
var dY = grid.getOrigin().y - bottomY; dY = grid.getOrigin().y - bottomY;
var diff = { diff = {
x: 0, x: 0,
y: dY, y: dY,
z: 0 z: 0
}; };
var newPosition = Vec3.sum(properties.position, diff); newPosition = Vec3.sum(properties.position, diff);
Entities.editEntity(selectionManager.selections[i], { Entities.editEntity(selectionManager.selections[i], {
position: newPosition, position: newPosition
}); });
} }
pushCommandForSelections(); pushCommandForSelections();
selectionManager._update(); selectionManager._update();
} }
} else if (data.action == "resetToNaturalDimensions") { } else if (data.action === "resetToNaturalDimensions") {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
selectionManager.saveProperties(); selectionManager.saveProperties();
for (var i = 0; i < selectionManager.selections.length; i++) { for (i = 0; i < selectionManager.selections.length; i++) {
var properties = selectionManager.savedProperties[selectionManager.selections[i]]; properties = selectionManager.savedProperties[selectionManager.selections[i]];
var naturalDimensions = properties.naturalDimensions; var naturalDimensions = properties.naturalDimensions;
// If any of the natural dimensions are not 0, resize // If any of the natural dimensions are not 0, resize
if (properties.type == "Model" && naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) { if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 &&
Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded."); naturalDimensions.z === 0) {
Window.alert("Cannot reset entity to its natural dimensions: Model URL" +
" is invalid or the model has not yet been loaded.");
} else { } else {
Entities.editEntity(selectionManager.selections[i], { Entities.editEntity(selectionManager.selections[i], {
dimensions: properties.naturalDimensions, dimensions: properties.naturalDimensions
}); });
} }
} }
pushCommandForSelections(); pushCommandForSelections();
selectionManager._update(); selectionManager._update();
} }
} else if (data.action == "previewCamera") { } else if (data.action === "previewCamera") {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
Camera.mode = "entity"; Camera.mode = "entity";
Camera.cameraEntity = selectionManager.selections[0]; Camera.cameraEntity = selectionManager.selections[0];
} }
} else if (data.action == "rescaleDimensions") { } else if (data.action === "rescaleDimensions") {
var multiplier = data.percentage / 100; var multiplier = data.percentage / 100;
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
selectionManager.saveProperties(); selectionManager.saveProperties();
for (var i = 0; i < selectionManager.selections.length; i++) { for (i = 0; i < selectionManager.selections.length; i++) {
var properties = selectionManager.savedProperties[selectionManager.selections[i]]; properties = selectionManager.savedProperties[selectionManager.selections[i]];
Entities.editEntity(selectionManager.selections[i], { Entities.editEntity(selectionManager.selections[i], {
dimensions: Vec3.multiply(multiplier, properties.dimensions), dimensions: Vec3.multiply(multiplier, properties.dimensions)
}); });
} }
pushCommandForSelections(); pushCommandForSelections();
selectionManager._update(); selectionManager._update();
} }
} else if (data.action == "reloadScript") { } else if (data.action === "reloadScript") {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
var timestamp = Date.now(); var timestamp = Date.now();
for (var i = 0; i < selectionManager.selections.length; i++) { for (i = 0; i < selectionManager.selections.length; i++) {
Entities.editEntity(selectionManager.selections[i], { Entities.editEntity(selectionManager.selections[i], {
scriptTimestamp: timestamp, scriptTimestamp: timestamp
}); });
} }
} }
@ -1449,7 +1517,7 @@ PropertiesTool = function(opts) {
return that; return that;
}; };
PopupMenu = function() { var PopupMenu = function () {
var self = this; var self = this;
var MENU_ITEM_HEIGHT = 21; var MENU_ITEM_HEIGHT = 21;
@ -1489,7 +1557,7 @@ PopupMenu = function() {
font: { font: {
size: 12 size: 12
}, },
visible: false, visible: false
}); });
overlays.push(id); overlays.push(id);
overlayInfo[id] = { overlayInfo[id] = {
@ -1508,7 +1576,7 @@ PopupMenu = function() {
for (var key in overlayInfo) { for (var key in overlayInfo) {
Overlays.editOverlay(key, { Overlays.editOverlay(key, {
x: x, x: x,
y: y, y: y
}); });
y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING;
} }
@ -1543,13 +1611,13 @@ PopupMenu = function() {
y: event.y y: event.y
}); });
if (!pressingOverlay) { if (!pressingOverlay) {
if (hoveringOverlay != null && overlay != hoveringOverlay) { if (hoveringOverlay !== null && hoveringOverlay !== null && overlay !== hoveringOverlay) {
Overlays.editOverlay(hoveringOverlay, { Overlays.editOverlay(hoveringOverlay, {
backgroundColor: upColor backgroundColor: upColor
}); });
hoveringOverlay = null; hoveringOverlay = null;
} }
if (overlay != hoveringOverlay && overlay in overlayInfo) { if (overlay !== hoveringOverlay && overlay in overlayInfo) {
Overlays.editOverlay(overlay, { Overlays.editOverlay(overlay, {
backgroundColor: overColor backgroundColor: overColor
}); });
@ -1564,8 +1632,8 @@ PopupMenu = function() {
x: event.x, x: event.x,
y: event.y y: event.y
}); });
if (pressingOverlay != null) { if (pressingOverlay !== null && pressingOverlay !== undefined) {
if (overlay == pressingOverlay) { if (overlay === pressingOverlay) {
self.onSelectMenuItem(overlayInfo[overlay].name); self.onSelectMenuItem(overlayInfo[overlay].name);
} }
Overlays.editOverlay(pressingOverlay, { Overlays.editOverlay(pressingOverlay, {
@ -1579,7 +1647,7 @@ PopupMenu = function() {
var visible = false; var visible = false;
self.setVisible = function (newVisible) { self.setVisible = function (newVisible) {
if (newVisible != visible) { if (newVisible !== visible) {
visible = newVisible; visible = newVisible;
for (var key in overlayInfo) { for (var key in overlayInfo) {
Overlays.editOverlay(key, { Overlays.editOverlay(key, {
@ -1587,13 +1655,13 @@ PopupMenu = function() {
}); });
} }
} }
} };
self.show = function () { self.show = function () {
self.setVisible(true); self.setVisible(true);
} };
self.hide = function () { self.hide = function () {
self.setVisible(false); self.setVisible(false);
} };
function cleanup() { function cleanup() {
for (var i = 0; i < overlays.length; i++) { for (var i = 0; i < overlays.length; i++) {
@ -1610,7 +1678,7 @@ PopupMenu = function() {
}; };
var propertyMenu = PopupMenu(); var propertyMenu = new PopupMenu();
propertyMenu.onSelectMenuItem = function (name) { propertyMenu.onSelectMenuItem = function (name) {
@ -1621,12 +1689,12 @@ propertyMenu.onSelectMenuItem = function(name) {
var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
propertiesTool = PropertiesTool(); var propertiesTool = new PropertiesTool();
var particleExplorerTool = ParticleExplorerTool(); var particleExplorerTool = new ParticleExplorerTool();
var selectedParticleEntity = 0; var selectedParticleEntity = 0;
entityListTool.webView.webEventReceived.connect(function (data) { entityListTool.webView.webEventReceived.connect(function (data) {
var data = JSON.parse(data); data = JSON.parse(data);
if (data.type == "selectionUpdate") { if (data.type === "selectionUpdate") {
var ids = data.entityIds; var ids = data.entityIds;
if (ids.length === 1) { if (ids.length === 1) {
if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") { if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") {
@ -1646,7 +1714,7 @@ entityListTool.webView.webEventReceived.connect(function(data) {
particleExplorerTool.setActiveParticleEntity(ids[0]); particleExplorerTool.setActiveParticleEntity(ids[0]);
particleExplorerTool.webView.webEventReceived.connect(function (data) { particleExplorerTool.webView.webEventReceived.connect(function (data) {
var data = JSON.parse(data); data = JSON.parse(data);
if (data.messageType === "page_loaded") { if (data.messageType === "page_loaded") {
particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData));
} }