More work on metavoxel editing.

This commit is contained in:
Andrzej Kapolka 2014-01-21 16:17:31 -08:00
parent d9589cd898
commit 5b4447d0b9
5 changed files with 186 additions and 1 deletions

View file

@ -1011,7 +1011,7 @@ void Menu::bandwidthDetails() {
}
void Menu::showMetavoxelEditor() {
if (_metavoxelEditorDialog.isNull()) {
if (!_metavoxelEditorDialog) {
_metavoxelEditorDialog = new MetavoxelEditorDialog();
}
_metavoxelEditorDialog->raise();

View file

@ -5,6 +5,16 @@
// Created by Andrzej Kapolka on 1/21/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QGroupBox>
#include <QLineEdit>
#include <QListWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <AttributeRegistry.h>
#include "Application.h"
#include "MetavoxelEditorDialog.h"
@ -13,6 +23,103 @@ MetavoxelEditorDialog::MetavoxelEditorDialog() :
setWindowTitle("Metavoxel Editor");
setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout* topLayout = new QVBoxLayout();
setLayout(topLayout);
QGroupBox* attributeGroup = new QGroupBox();
attributeGroup->setTitle("Attributes");
topLayout->addWidget(attributeGroup);
QVBoxLayout* attributeLayout = new QVBoxLayout();
attributeGroup->setLayout(attributeLayout);
attributeLayout->addWidget(_attributes = new QListWidget());
connect(_attributes, SIGNAL(itemSelectionChanged()), SLOT(updateValueEditor()));
QPushButton* newAttribute = new QPushButton("New...");
attributeLayout->addWidget(newAttribute);
connect(newAttribute, SIGNAL(clicked()), SLOT(createNewAttribute()));
_value = new QGroupBox();
_value->setTitle("Value");
topLayout->addWidget(_value);
QVBoxLayout* valueLayout = new QVBoxLayout();
_value->setLayout(valueLayout);
updateAttributes();
show();
}
void MetavoxelEditorDialog::updateValueEditor() {
QString selected = getSelectedAttribute();
if (selected.isNull()) {
_value->setVisible(false);
return;
}
_value->setVisible(true);
if (!_value->layout()->isEmpty()) {
delete _value->layout()->takeAt(0);
}
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(selected);
QWidget* editor = attribute->createEditor();
if (editor) {
_value->layout()->addWidget(editor);
}
}
void MetavoxelEditorDialog::createNewAttribute() {
QDialog dialog(this);
dialog.setWindowTitle("New Attribute");
QVBoxLayout layout;
dialog.setLayout(&layout);
QFormLayout form;
layout.addLayout(&form);
QLineEdit name;
form.addRow("Name:", &name);
QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog.connect(&buttons, SIGNAL(accepted()), SLOT(accept()));
dialog.connect(&buttons, SIGNAL(rejected()), SLOT(reject()));
layout.addWidget(&buttons);
if (!dialog.exec()) {
return;
}
QString nameText = name.text().trimmed();
AttributeRegistry::getInstance()->registerAttribute(new QRgbAttribute(nameText));
updateAttributes(nameText);
}
void MetavoxelEditorDialog::updateAttributes(const QString& select) {
// remember the selection in order to preserve it
QString selected = select.isNull() ? getSelectedAttribute() : select;
_attributes->clear();
// sort the names for consistent ordering
QList<QString> names = AttributeRegistry::getInstance()->getAttributes().keys();
qSort(names);
foreach (const QString& name, names) {
QListWidgetItem* item = new QListWidgetItem(name);
_attributes->addItem(item);
if (name == selected || selected.isNull()) {
item->setSelected(true);
selected = name;
}
}
}
QString MetavoxelEditorDialog::getSelectedAttribute() const {
QList<QListWidgetItem*> selectedItems = _attributes->selectedItems();
return selectedItems.isEmpty() ? QString() : selectedItems.first()->text();
}

View file

@ -11,6 +11,9 @@
#include <QDialog>
class QGroupBox;
class QListWidget;
/// Allows editing metavoxels.
class MetavoxelEditorDialog : public QDialog {
Q_OBJECT
@ -18,6 +21,19 @@ class MetavoxelEditorDialog : public QDialog {
public:
MetavoxelEditorDialog();
private slots:
void updateValueEditor();
void createNewAttribute();
private:
void updateAttributes(const QString& select = QString());
QString getSelectedAttribute() const;
QListWidget* _attributes;
QGroupBox* _value;
};
#endif /* defined(__interface__MetavoxelEditorDialog__) */

View file

@ -6,7 +6,10 @@
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include <QColorDialog>
#include <QPushButton>
#include <QScriptEngine>
#include <QVBoxLayout>
#include "AttributeRegistry.h"
#include "MetavoxelData.h"
@ -132,6 +135,31 @@ void* QRgbAttribute::createFromScript(const QScriptValue& value, QScriptEngine*
return encodeInline((QRgb)value.toUInt32());
}
QWidget* QRgbAttribute::createEditor(QWidget* parent) const {
QRgbEditor* editor = new QRgbEditor(parent);
editor->setColor(_defaultValue);
return editor;
}
QRgbEditor::QRgbEditor(QWidget* parent) : QWidget(parent) {
setLayout(new QVBoxLayout());
layout()->addWidget(_button = new QPushButton());
connect(_button, SIGNAL(clicked()), SLOT(selectColor()));
}
void QRgbEditor::setColor(int color) {
QString name = QColor::fromRgba(_color = color).name();
_button->setStyleSheet(QString("background: %1; color: %2").arg(name, QColor::fromRgb(~color).name()));
_button->setText(name);
}
void QRgbEditor::selectColor() {
QColor color = QColorDialog::getColor(QColor::fromRgba(_color), this, QString(), QColorDialog::ShowAlphaChannel);
if (color.isValid()) {
setColor(color.rgba());
}
}
PolymorphicData::~PolymorphicData() {
}

View file

@ -16,9 +16,11 @@
#include <QSharedData>
#include <QSharedPointer>
#include <QString>
#include <QWidget>
#include "Bitstream.h"
class QPushButton;
class QScriptContext;
class QScriptEngine;
class QScriptValue;
@ -52,6 +54,9 @@ public:
/// Retrieves an attribute by name.
AttributePointer getAttribute(const QString& name) const { return _attributes.value(name); }
/// Returns a reference to the attribute hash.
const QHash<QString, AttributePointer>& getAttributes() const { return _attributes; }
/// Returns a reference to the standard PolymorphicDataPointer "guide" attribute.
const AttributePointer& getGuideAttribute() const { return _guideAttribute; }
@ -153,6 +158,10 @@ public:
virtual void* getDefaultValue() const = 0;
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const { return create(); }
/// Creates a widget to use to edit values of this attribute, or returns NULL if the attribute isn't editable.
/// The widget should have a single "user" property that will be used to get/set the value.
virtual QWidget* createEditor(QWidget* parent = NULL) const { return NULL; }
};
/// A simple attribute class that stores its values inline.
@ -222,6 +231,31 @@ public:
virtual bool merge(void*& parent, void* children[]) const;
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const;
virtual QWidget* createEditor(QWidget* parent = NULL) const;
};
/// Editor for RGBA values.
class QRgbEditor : public QWidget {
Q_OBJECT
Q_PROPERTY(int color MEMBER _color WRITE setColor USER true)
public:
QRgbEditor(QWidget* parent);
public slots:
void setColor(int color);
private slots:
void selectColor();
private:
QPushButton* _button;
QRgb _color;
};
/// An attribute class that stores pointers to its values.