diff --git a/examples/editModels.js b/examples/editModels.js index 9e1581e205..411c11de38 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1118,14 +1118,35 @@ function handeMenuEvent(menuItem){ } if (editModelID != -1) { print(" Edit Properties.... about to edit properties..."); - var propertyName = Window.prompt("Which property would you like to change?", "modelURL"); - var properties = Models.getModelProperties(editModelID); - var oldValue = properties[propertyName]; - var newValue = Window.prompt("New value for: " + propertyName, oldValue); - if (newValue != "") { - properties[propertyName] = newValue; - Models.editModel(editModelID, properties); - } + var array = new Array(); + var decimals = 3; + array.push({ label: "Model URL:", value: selectedModelProperties.modelURL }); + array.push({ label: "Animation URL:", value: selectedModelProperties.animationURL }); + array.push({ label: "X:", value: selectedModelProperties.position.x.toFixed(decimals) }); + array.push({ label: "Y:", value: selectedModelProperties.position.y.toFixed(decimals) }); + array.push({ label: "Z:", value: selectedModelProperties.position.z.toFixed(decimals) }); + var angles = Quat.safeEulerAngles(selectedModelProperties.modelRotation); + array.push({ label: "Pitch:", value: angles.x.toFixed(decimals) }); + array.push({ label: "Yaw:", value: angles.y.toFixed(decimals) }); + array.push({ label: "Roll:", value: angles.z.toFixed(decimals) }); + array.push({ label: "Scale:", value: 2 * selectedModelProperties.radius.toFixed(decimals) }); + + var propertyName = Window.form("Edit Properties", array); + modelSelected = false; + + selectedModelProperties.modelURL = array[0].value; + selectedModelProperties.animationURL = array[1].value; + selectedModelProperties.position.x = array[2].value; + selectedModelProperties.position.y = array[3].value; + selectedModelProperties.position.z = array[4].value; + angles.x = array[5].value; + angles.y = array[6].value; + angles.z = array[7].value; + selectedModelProperties.modelRotation = Quat.fromVec3Degrees(angles); + selectedModelProperties.radius = array[8].value / 2; + print(selectedModelProperties.radius); + + Models.editModel(selectedModelID, selectedModelProperties); } } tooltip.show(false); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index e10197d488..cdf039a183 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -10,9 +10,11 @@ // #include +#include #include #include #include +#include #include "Application.h" #include "Menu.h" @@ -24,6 +26,9 @@ WindowScriptingInterface* WindowScriptingInterface::getInstance() { return &sharedInstance; } +WindowScriptingInterface::WindowScriptingInterface() { +} + QScriptValue WindowScriptingInterface::alert(const QString& message) { QScriptValue retVal; QMetaObject::invokeMethod(this, "showAlert", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QScriptValue, retVal), Q_ARG(const QString&, message)); @@ -37,6 +42,14 @@ QScriptValue WindowScriptingInterface::confirm(const QString& message) { return retVal; } +QScriptValue WindowScriptingInterface::form(const QString& title, QScriptValue form) { + QScriptValue retVal; + QMetaObject::invokeMethod(this, "showForm", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QScriptValue, retVal), + Q_ARG(const QString&, title), Q_ARG(QScriptValue, form)); + return retVal; +} + QScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) { QScriptValue retVal; QMetaObject::invokeMethod(this, "showPrompt", Qt::BlockingQueuedConnection, @@ -69,6 +82,73 @@ QScriptValue WindowScriptingInterface::showConfirm(const QString& message) { return QScriptValue(response == QMessageBox::Yes); } +/// Display a form layout with an edit box +/// \param const QString& title title to display +/// \param const QScriptValue form to display (array containing labels and values) +/// \return QScriptValue result form (unchanged is dialog canceled) +QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptValue form) { + if (form.isArray() && form.property("length").toInt32() > 0) { + QDialog* editDialog = new QDialog(Application::getInstance()->getWindow()); + editDialog->setWindowTitle(title); + + QVBoxLayout* layout = new QVBoxLayout(); + editDialog->setLayout(layout); + + QScrollArea* area = new QScrollArea(); + layout->addWidget(area); + area->setWidgetResizable(true); + QWidget* container = new QWidget(); + QFormLayout* formLayout = new QFormLayout(); + container->setLayout(formLayout); + container->sizePolicy().setHorizontalStretch(1); + formLayout->setRowWrapPolicy(QFormLayout::DontWrapRows); + formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); + formLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop); + formLayout->setLabelAlignment(Qt::AlignLeft); + + area->setWidget(container); + + QVector edits; + for (int i = 0; i < form.property("length").toInt32(); ++i) { + QScriptValue item = form.property(i); + edits.push_back(new QLineEdit(item.property("value").toString())); + formLayout->addRow(item.property("label").toString(), edits.back()); + } + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok); + connect(buttons, SIGNAL(accepted()), editDialog, SLOT(accept())); + layout->addWidget(buttons); + + if (editDialog->exec() == QDialog::Accepted) { + for (int i = 0; i < form.property("length").toInt32(); ++i) { + QScriptValue item = form.property(i); + QScriptValue value = item.property("value"); + bool ok = true; + if (value.isNumber()) { + value = edits.at(i)->text().toDouble(&ok); + } else if (value.isString()) { + value = edits.at(i)->text(); + } else if (value.isBool()) { + if (edits.at(i)->text() == "true") { + value = true; + } else if (edits.at(i)->text() == "false") { + value = false; + } else { + ok = false; + } + } + if (ok) { + item.setProperty("value", value); + form.setProperty(i, item); + } + } + } + + delete editDialog; + } + + return form; +} + /// Display a prompt with a text box /// \param const QString& message message to display /// \param const QString& defaultText default text in the text box @@ -79,11 +159,11 @@ QScriptValue WindowScriptingInterface::showPrompt(const QString& message, const promptDialog.setLabelText(message); promptDialog.setTextValue(defaultText); promptDialog.setFixedSize(600, 200); - + if (promptDialog.exec() == QDialog::Accepted) { return QScriptValue(promptDialog.textValue()); } - + return QScriptValue::NullValue; } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index b97113af9c..7f84282543 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -20,7 +20,6 @@ class WindowScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(int innerWidth READ getInnerWidth) Q_PROPERTY(int innerHeight READ getInnerHeight) - WindowScriptingInterface() { }; public: static WindowScriptingInterface* getInstance(); int getInnerWidth(); @@ -29,14 +28,19 @@ public: public slots: QScriptValue alert(const QString& message = ""); QScriptValue confirm(const QString& message = ""); + QScriptValue form(const QString& title, QScriptValue array); QScriptValue prompt(const QString& message = "", const QString& defaultText = ""); QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); private slots: QScriptValue showAlert(const QString& message); QScriptValue showConfirm(const QString& message); + QScriptValue showForm(const QString& title, QScriptValue form); QScriptValue showPrompt(const QString& message, const QString& defaultText); QScriptValue showBrowse(const QString& title, const QString& directory, const QString& nameFilter); + +private: + WindowScriptingInterface(); }; #endif // hifi_WindowScriptingInterface_h