Global edits, edits use virtual function.

This commit is contained in:
Andrzej Kapolka 2014-02-12 20:00:07 -08:00
parent 5b207e4f8e
commit bb56e2847f
10 changed files with 381 additions and 175 deletions

View file

@ -3,20 +3,11 @@ macro(AUTO_MTC TARGET ROOT_DIR)
add_subdirectory(${ROOT_DIR}/tools/mtc ${ROOT_DIR}/tools/mtc)
endif (NOT TARGET mtc)
set(AUTOMTC_SRC ${TARGET}_automtc.cpp)
file(GLOB INCLUDE_FILES src/*.h)
add_custom_command(OUTPUT ${TARGET}_automtc.cpp COMMAND mtc -o ${TARGET}_automtc.cpp
${INCLUDE_FILES} DEPENDS mtc ${INCLUDE_FILES})
find_package(Qt5Core REQUIRED)
find_package(Qt5Script REQUIRED)
find_package(Qt5Widgets REQUIRED)
add_library(${TARGET}_automtc STATIC ${TARGET}_automtc.cpp)
qt5_use_modules(${TARGET}_automtc Core Script Widgets)
target_link_libraries(${TARGET} ${TARGET}_automtc)
add_custom_command(OUTPUT ${AUTOMTC_SRC} COMMAND mtc -o ${AUTOMTC_SRC} ${INCLUDE_FILES} DEPENDS mtc ${INCLUDE_FILES})
endmacro()

View file

@ -81,6 +81,9 @@ MetavoxelEditor::MetavoxelEditor() :
alignGridPosition();
centerGridPosition();
formLayout->addRow("Tool:", _toolBox = new QComboBox());
connect(_toolBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTool()));
_value = new QGroupBox();
_value->setTitle("Value");
topLayout->addWidget(_value);
@ -91,14 +94,20 @@ MetavoxelEditor::MetavoxelEditor() :
valueLayout->addWidget(_valueArea = new QScrollArea());
_valueArea->setWidgetResizable(true);
BoxSetTool* boxSetTool = new BoxSetTool(this);
topLayout->addWidget(boxSetTool);
_toolBox->addItem("Set Value (Box)", QVariant::fromValue(boxSetTool));
GlobalSetTool* globalSetTool = new GlobalSetTool(this);
topLayout->addWidget(globalSetTool);
_toolBox->addItem("Set Value (Global)", QVariant::fromValue(globalSetTool));
updateAttributes();
connect(Application::getInstance(), SIGNAL(renderingInWorldInterface()), SLOT(render()));
Application::getInstance()->getGLWidget()->installEventFilter(this);
resetState();
show();
if (_gridProgram.isLinked()) {
@ -109,43 +118,42 @@ MetavoxelEditor::MetavoxelEditor() :
_gridProgram.link();
}
bool MetavoxelEditor::eventFilter(QObject* watched, QEvent* event) {
switch (_state) {
case HOVERING_STATE:
if (event->type() == QEvent::MouseButtonPress && _startPosition != INVALID_VECTOR) {
_state = DRAGGING_STATE;
return true;
}
break;
QString MetavoxelEditor::getSelectedAttribute() const {
QList<QListWidgetItem*> selectedItems = _attributes->selectedItems();
return selectedItems.isEmpty() ? QString() : selectedItems.first()->text();
}
double MetavoxelEditor::getGridSpacing() const {
return pow(2.0, _gridSpacing->value());
}
double MetavoxelEditor::getGridPosition() const {
return _gridPosition->value();
}
glm::quat MetavoxelEditor::getGridRotation() const {
// for simplicity, we handle the other two planes by rotating them onto X/Y and performing computation there
switch (_gridPlane->currentIndex()) {
case GRID_PLANE_XY:
return glm::quat();
case DRAGGING_STATE:
if (event->type() == QEvent::MouseButtonRelease) {
_state = RAISING_STATE;
return true;
}
break;
case GRID_PLANE_XZ:
return glm::angleAxis(-90.0f, 1.0f, 0.0f, 0.0f);
case RAISING_STATE:
if (event->type() == QEvent::MouseButtonPress) {
if (_height != 0) {
// find the start and end corners in X/Y
float base = _gridPosition->value();
float top = base + _height;
glm::quat rotation = getGridRotation();
glm::vec3 start = rotation * glm::vec3(glm::min(_startPosition, _endPosition), glm::min(base, top));
float spacing = getGridSpacing();
glm::vec3 end = rotation * glm::vec3(glm::max(_startPosition, _endPosition) +
glm::vec2(spacing, spacing), glm::max(base, top));
// find the minimum and maximum extents after rotation
applyValue(glm::min(start, end), glm::max(start, end));
}
resetState();
return true;
}
break;
case GRID_PLANE_YZ:
default:
return glm::angleAxis(90.0f, 0.0f, 1.0f, 0.0f);
}
return false;
}
QVariant MetavoxelEditor::getValue() const {
QWidget* editor = _valueArea->widget();
return editor ? editor->metaObject()->userProperty().read(editor) : QVariant();
}
bool MetavoxelEditor::eventFilter(QObject* watched, QEvent* event) {
// pass along to the active tool
return getActiveTool()->eventFilter(watched, event);
}
void MetavoxelEditor::selectedAttributeChanged() {
@ -222,13 +230,15 @@ void MetavoxelEditor::alignGridPosition() {
_gridPosition->setValue(step * floor(_gridPosition->value() / step));
}
void MetavoxelEditor::render() {
QString selected = getSelectedAttribute();
if (selected.isNull()) {
resetState();
return;
void MetavoxelEditor::updateTool() {
for (int i = 0; i < _toolBox->count(); i++) {
_toolBox->itemData(i).value<QWidget*>()->setVisible(i == _toolBox->currentIndex());
}
}
const float GRID_BRIGHTNESS = 0.5f;
void MetavoxelEditor::render() {
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
@ -238,85 +248,22 @@ void MetavoxelEditor::render() {
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
glm::quat inverseRotation = glm::inverse(rotation);
glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin();
glm::vec3 rayDirection = inverseRotation * Application::getInstance()->getMouseRayDirection();
float spacing = getGridSpacing();
float position = _gridPosition->value();
if (_state == RAISING_STATE) {
// find the plane at the mouse position, orthogonal to the plane, facing the eye position
glLineWidth(4.0f);
glm::vec3 eyePosition = inverseRotation * Application::getInstance()->getViewFrustum()->getOffsetPosition();
glm::vec3 mousePoint = glm::vec3(_mousePosition, position);
glm::vec3 right = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), eyePosition - mousePoint);
glm::vec3 normal = glm::cross(right, glm::vec3(0.0f, 0.0f, 1.0f));
float divisor = glm::dot(normal, rayDirection);
if (fabs(divisor) > EPSILON) {
float distance = (glm::dot(normal, mousePoint) - glm::dot(normal, rayOrigin)) / divisor;
float projection = rayOrigin.z + distance * rayDirection.z;
_height = spacing * roundf(projection / spacing) - position;
}
} else if (fabs(rayDirection.z) > EPSILON) {
// find the intersection of the rotated mouse ray with the plane
float distance = (position - rayOrigin.z) / rayDirection.z;
_mousePosition = glm::vec2(rayOrigin + rayDirection * distance);
glm::vec2 snappedPosition = spacing * glm::floor(_mousePosition / spacing);
if (_state == HOVERING_STATE) {
_startPosition = _endPosition = snappedPosition;
glLineWidth(2.0f);
} else if (_state == DRAGGING_STATE) {
_endPosition = snappedPosition;
glLineWidth(4.0f);
}
} else {
// cancel any operation in progress
resetState();
}
const float GRID_BRIGHTNESS = 0.5f;
if (_startPosition != INVALID_VECTOR) {
glm::vec2 minimum = glm::min(_startPosition, _endPosition);
glm::vec2 maximum = glm::max(_startPosition, _endPosition);
glPushMatrix();
glTranslatef(minimum.x, minimum.y, position);
glScalef(maximum.x + spacing - minimum.x, maximum.y + spacing - minimum.y, _height);
glTranslatef(0.5f, 0.5f, 0.5f);
if (_state != HOVERING_STATE) {
const float BOX_ALPHA = 0.25f;
QColor color = getValue().value<QColor>();
if (color.isValid()) {
glColor4f(color.redF(), color.greenF(), color.blueF(), BOX_ALPHA);
} else {
glColor4f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS, BOX_ALPHA);
}
glEnable(GL_CULL_FACE);
glutSolidCube(1.0);
glDisable(GL_CULL_FACE);
}
glColor3f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS);
glutWireCube(1.0);
glPopMatrix();
} else {
glColor3f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS);
}
getActiveTool()->render();
glLineWidth(1.0f);
// center the grid around the camera position on the plane
glm::vec3 rotated = inverseRotation * Application::getInstance()->getCamera()->getPosition();
glm::vec3 rotated = glm::inverse(rotation) * Application::getInstance()->getCamera()->getPosition();
float spacing = getGridSpacing();
const int GRID_DIVISIONS = 300;
glTranslatef(spacing * (floorf(rotated.x / spacing) - GRID_DIVISIONS / 2),
spacing * (floorf(rotated.y / spacing) - GRID_DIVISIONS / 2), position);
spacing * (floorf(rotated.y / spacing) - GRID_DIVISIONS / 2), _gridPosition->value());
float scale = GRID_DIVISIONS * spacing;
glScalef(scale, scale, scale);
glColor3f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS);
_gridProgram.bind();
Application::getInstance()->getGeometryCache()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS);
@ -348,49 +295,173 @@ void MetavoxelEditor::updateAttributes(const QString& select) {
}
}
QString MetavoxelEditor::getSelectedAttribute() const {
QList<QListWidgetItem*> selectedItems = _attributes->selectedItems();
return selectedItems.isEmpty() ? QString() : selectedItems.first()->text();
MetavoxelTool* MetavoxelEditor::getActiveTool() const {
return static_cast<MetavoxelTool*>(_toolBox->itemData(_toolBox->currentIndex()).value<QObject*>());
}
double MetavoxelEditor::getGridSpacing() const {
return pow(2.0, _gridSpacing->value());
ProgramObject MetavoxelEditor::_gridProgram;
MetavoxelTool::MetavoxelTool(MetavoxelEditor* editor) :
_editor(editor) {
QVBoxLayout* layout = new QVBoxLayout();
setLayout(layout);
setVisible(false);
}
glm::quat MetavoxelEditor::getGridRotation() const {
// for simplicity, we handle the other two planes by rotating them onto X/Y and performing computation there
switch (_gridPlane->currentIndex()) {
case GRID_PLANE_XY:
return glm::quat();
void MetavoxelTool::render() {
// nothing by default
}
BoxSetTool::BoxSetTool(MetavoxelEditor* editor) :
MetavoxelTool(editor) {
resetState();
}
void BoxSetTool::render() {
QString selected = _editor->getSelectedAttribute();
if (selected.isNull()) {
resetState();
return;
}
glm::quat rotation = _editor->getGridRotation();
glm::quat inverseRotation = glm::inverse(rotation);
glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin();
glm::vec3 rayDirection = inverseRotation * Application::getInstance()->getMouseRayDirection();
float spacing = _editor->getGridSpacing();
float position = _editor->getGridPosition();
if (_state == RAISING_STATE) {
// find the plane at the mouse position, orthogonal to the plane, facing the eye position
glLineWidth(4.0f);
glm::vec3 eyePosition = inverseRotation * Application::getInstance()->getViewFrustum()->getOffsetPosition();
glm::vec3 mousePoint = glm::vec3(_mousePosition, position);
glm::vec3 right = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), eyePosition - mousePoint);
glm::vec3 normal = glm::cross(right, glm::vec3(0.0f, 0.0f, 1.0f));
float divisor = glm::dot(normal, rayDirection);
if (fabs(divisor) > EPSILON) {
float distance = (glm::dot(normal, mousePoint) - glm::dot(normal, rayOrigin)) / divisor;
float projection = rayOrigin.z + distance * rayDirection.z;
_height = spacing * roundf(projection / spacing) - position;
}
} else if (fabs(rayDirection.z) > EPSILON) {
// find the intersection of the rotated mouse ray with the plane
float distance = (position - rayOrigin.z) / rayDirection.z;
_mousePosition = glm::vec2(rayOrigin + rayDirection * distance);
glm::vec2 snappedPosition = spacing * glm::floor(_mousePosition / spacing);
if (_state == HOVERING_STATE) {
_startPosition = _endPosition = snappedPosition;
glLineWidth(2.0f);
case GRID_PLANE_XZ:
return glm::angleAxis(-90.0f, 1.0f, 0.0f, 0.0f);
case GRID_PLANE_YZ:
default:
return glm::angleAxis(90.0f, 0.0f, 1.0f, 0.0f);
} else if (_state == DRAGGING_STATE) {
_endPosition = snappedPosition;
glLineWidth(4.0f);
}
} else {
// cancel any operation in progress
resetState();
}
if (_startPosition != INVALID_VECTOR) {
glm::vec2 minimum = glm::min(_startPosition, _endPosition);
glm::vec2 maximum = glm::max(_startPosition, _endPosition);
glPushMatrix();
glTranslatef(minimum.x, minimum.y, position);
glScalef(maximum.x + spacing - minimum.x, maximum.y + spacing - minimum.y, _height);
glTranslatef(0.5f, 0.5f, 0.5f);
if (_state != HOVERING_STATE) {
const float BOX_ALPHA = 0.25f;
QColor color = _editor->getValue().value<QColor>();
if (color.isValid()) {
glColor4f(color.redF(), color.greenF(), color.blueF(), BOX_ALPHA);
} else {
glColor4f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS, BOX_ALPHA);
}
glEnable(GL_CULL_FACE);
glutSolidCube(1.0);
glDisable(GL_CULL_FACE);
}
glColor3f(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS);
glutWireCube(1.0);
glPopMatrix();
}
}
void MetavoxelEditor::resetState() {
bool BoxSetTool::eventFilter(QObject* watched, QEvent* event) {
switch (_state) {
case HOVERING_STATE:
if (event->type() == QEvent::MouseButtonPress && _startPosition != INVALID_VECTOR) {
_state = DRAGGING_STATE;
return true;
}
break;
case DRAGGING_STATE:
if (event->type() == QEvent::MouseButtonRelease) {
_state = RAISING_STATE;
return true;
}
break;
case RAISING_STATE:
if (event->type() == QEvent::MouseButtonPress) {
if (_height != 0) {
// find the start and end corners in X/Y
float base = _editor->getGridPosition();
float top = base + _height;
glm::quat rotation = _editor->getGridRotation();
glm::vec3 start = rotation * glm::vec3(glm::min(_startPosition, _endPosition), glm::min(base, top));
float spacing = _editor->getGridSpacing();
glm::vec3 end = rotation * glm::vec3(glm::max(_startPosition, _endPosition) +
glm::vec2(spacing, spacing), glm::max(base, top));
// find the minimum and maximum extents after rotation
applyValue(glm::min(start, end), glm::max(start, end));
}
resetState();
return true;
}
break;
}
return false;
}
void BoxSetTool::resetState() {
_state = HOVERING_STATE;
_startPosition = INVALID_VECTOR;
_height = 0.0f;
}
void MetavoxelEditor::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) {
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(getSelectedAttribute());
void BoxSetTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) {
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute());
if (!attribute) {
return;
}
OwnedAttributeValue value(attribute, attribute->createFromVariant(getValue()));
MetavoxelEditMessage edit = { { minimum, maximum }, getGridSpacing(), value };
Application::getInstance()->getMetavoxels()->applyEdit(edit);
OwnedAttributeValue value(attribute, attribute->createFromVariant(_editor->getValue()));
MetavoxelEditMessage message = { QVariant::fromValue(BoxSetEdit(Box(minimum, maximum),
_editor->getGridSpacing(), value)) };
Application::getInstance()->getMetavoxels()->applyEdit(message);
}
QVariant MetavoxelEditor::getValue() const {
QWidget* editor = _valueArea->widget();
return editor ? editor->metaObject()->userProperty().read(editor) : QVariant();
GlobalSetTool::GlobalSetTool(MetavoxelEditor* editor) :
MetavoxelTool(editor) {
QPushButton* button = new QPushButton("Apply");
layout()->addWidget(button);
connect(button, SIGNAL(clicked()), SLOT(apply()));
}
ProgramObject MetavoxelEditor::_gridProgram;
void GlobalSetTool::apply() {
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute());
if (!attribute) {
return;
}
OwnedAttributeValue value(attribute, attribute->createFromVariant(_editor->getValue()));
MetavoxelEditMessage message = { QVariant::fromValue(GlobalSetEdit(value)) };
Application::getInstance()->getMetavoxels()->applyEdit(message);
}

View file

@ -20,6 +20,8 @@ class QListWidget;
class QPushButton;
class QScrollArea;
class MetavoxelTool;
/// Allows editing metavoxels.
class MetavoxelEditor : public QDialog {
Q_OBJECT
@ -28,6 +30,14 @@ public:
MetavoxelEditor();
QString getSelectedAttribute() const;
double getGridSpacing() const;
double getGridPosition() const;
glm::quat getGridRotation() const;
QVariant getValue() const;
virtual bool eventFilter(QObject* watched, QEvent* event);
private slots:
@ -37,38 +47,84 @@ private slots:
void deleteSelectedAttribute();
void centerGridPosition();
void alignGridPosition();
void updateTool();
void render();
private:
void updateAttributes(const QString& select = QString());
QString getSelectedAttribute() const;
double getGridSpacing() const;
glm::quat getGridRotation() const;
void resetState();
void applyValue(const glm::vec3& minimum, const glm::vec3& maximum);
QVariant getValue() const;
void updateAttributes(const QString& select = QString());
MetavoxelTool* getActiveTool() const;
QListWidget* _attributes;
QPushButton* _deleteAttribute;
QComboBox* _gridPlane;
QDoubleSpinBox* _gridSpacing;
QDoubleSpinBox* _gridPosition;
QComboBox* _toolBox;
QGroupBox* _value;
QScrollArea* _valueArea;
static ProgramObject _gridProgram;
};
/// Base class for editor tools.
class MetavoxelTool : public QWidget {
Q_OBJECT
public:
MetavoxelTool(MetavoxelEditor* editor);
/// Renders the tool's interface, if any.
virtual void render();
protected:
MetavoxelEditor* _editor;
};
/// Allows setting the value of a region by dragging out a box.
class BoxSetTool : public MetavoxelTool {
Q_OBJECT
public:
BoxSetTool(MetavoxelEditor* editor);
virtual void render();
virtual bool eventFilter(QObject* watched, QEvent* event);
private:
void resetState();
void applyValue(const glm::vec3& minimum, const glm::vec3& maximum);
enum State { HOVERING_STATE, DRAGGING_STATE, RAISING_STATE };
State _state;
glm::vec2 _mousePosition; ///< the position of the mouse in rotated space
glm::vec2 _startPosition; ///< the first corner of the selection base
glm::vec2 _endPosition; ///< the second corner of the selection base
float _height; ///< the selection height
};
/// Allows setting the value across the entire space.
class GlobalSetTool : public MetavoxelTool {
Q_OBJECT
public:
static ProgramObject _gridProgram;
GlobalSetTool(MetavoxelEditor* editor);
private slots:
void apply();
};
#endif /* defined(__interface__MetavoxelEditor__) */

View file

@ -11,12 +11,12 @@ set(TARGET_NAME metavoxels)
find_package(Qt5Network REQUIRED)
find_package(Qt5Widgets REQUIRED)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
include(${MACRO_DIR}/AutoMTC.cmake)
auto_mtc(${TARGET_NAME} ${ROOT_DIR})
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME} ${AUTOMTC_SRC})
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
include(${MACRO_DIR}/IncludeGLM.cmake)

View file

@ -43,8 +43,7 @@ MetavoxelData& MetavoxelData::operator=(const MetavoxelData& other) {
Box MetavoxelData::getBounds() const {
float halfSize = _size * 0.5f;
Box bounds = { glm::vec3(-halfSize, -halfSize, -halfSize), glm::vec3(halfSize, halfSize, halfSize) };
return bounds;
return Box(glm::vec3(-halfSize, -halfSize, -halfSize), glm::vec3(halfSize, halfSize, halfSize));
}
void MetavoxelData::guide(MetavoxelVisitor& visitor) {

View file

@ -9,24 +9,35 @@
#include "MetavoxelData.h"
#include "MetavoxelMessages.h"
class EditVisitor : public MetavoxelVisitor {
void MetavoxelEditMessage::apply(MetavoxelData& data) const {
static_cast<const MetavoxelEdit*>(edit.data())->apply(data);
}
MetavoxelEdit::~MetavoxelEdit() {
}
BoxSetEdit::BoxSetEdit(const Box& region, float granularity, const OwnedAttributeValue& value) :
region(region), granularity(granularity), value(value) {
}
class BoxSetEditVisitor : public MetavoxelVisitor {
public:
EditVisitor(const MetavoxelEditMessage& edit);
BoxSetEditVisitor(const BoxSetEdit& edit);
virtual bool visit(MetavoxelInfo& info);
private:
const MetavoxelEditMessage& _edit;
const BoxSetEdit& _edit;
};
EditVisitor::EditVisitor(const MetavoxelEditMessage& edit) :
BoxSetEditVisitor::BoxSetEditVisitor(const BoxSetEdit& edit) :
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << edit.value.getAttribute()),
_edit(edit) {
}
bool EditVisitor::visit(MetavoxelInfo& info) {
bool BoxSetEditVisitor::visit(MetavoxelInfo& info) {
// find the intersection between volume and voxel
glm::vec3 minimum = glm::max(info.minimum, _edit.region.minimum);
glm::vec3 maximum = glm::min(info.minimum + glm::vec3(info.size, info.size, info.size), _edit.region.maximum);
@ -48,12 +59,44 @@ bool EditVisitor::visit(MetavoxelInfo& info) {
return true; // subdivide
}
void MetavoxelEditMessage::apply(MetavoxelData& data) const {
void BoxSetEdit::apply(MetavoxelData& data) const {
// expand to fit the entire edit
while (!data.getBounds().contains(region)) {
data.expand();
}
EditVisitor visitor(*this);
BoxSetEditVisitor visitor(*this);
data.guide(visitor);
}
GlobalSetEdit::GlobalSetEdit(const OwnedAttributeValue& value) :
value(value) {
}
class GlobalSetEditVisitor : public MetavoxelVisitor {
public:
GlobalSetEditVisitor(const GlobalSetEdit& edit);
virtual bool visit(MetavoxelInfo& info);
private:
const GlobalSetEdit& _edit;
};
GlobalSetEditVisitor::GlobalSetEditVisitor(const GlobalSetEdit& edit) :
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << edit.value.getAttribute()),
_edit(edit) {
}
bool GlobalSetEditVisitor::visit(MetavoxelInfo& info) {
info.outputValues[0] = _edit.value;
return false; // entirely contained
}
void GlobalSetEdit::apply(MetavoxelData& data) const {
GlobalSetEditVisitor visitor(*this);
data.guide(visitor);
}

View file

@ -67,13 +67,53 @@ class MetavoxelEditMessage {
public:
STREAM Box region;
STREAM float granularity;
STREAM OwnedAttributeValue value;
STREAM QVariant edit;
void apply(MetavoxelData& data) const;
};
DECLARE_STREAMABLE_METATYPE(MetavoxelEditMessage)
/// Abstract base class for edits.
class MetavoxelEdit {
public:
virtual ~MetavoxelEdit();
virtual void apply(MetavoxelData& data) const = 0;
};
/// An edit that sets the region within a box to a value.
class BoxSetEdit : public MetavoxelEdit {
STREAMABLE
public:
STREAM Box region;
STREAM float granularity;
STREAM OwnedAttributeValue value;
BoxSetEdit(const Box& region = Box(), float granularity = 0.0f,
const OwnedAttributeValue& value = OwnedAttributeValue());
virtual void apply(MetavoxelData& data) const;
};
DECLARE_STREAMABLE_METATYPE(BoxSetEdit)
/// An edit that sets the entire tree to a value.
class GlobalSetEdit : public MetavoxelEdit {
STREAMABLE
public:
STREAM OwnedAttributeValue value;
GlobalSetEdit(const OwnedAttributeValue& value = OwnedAttributeValue());
virtual void apply(MetavoxelData& data) const;
};
DECLARE_STREAMABLE_METATYPE(GlobalSetEdit)
#endif /* defined(__interface__MetavoxelMessages__) */

View file

@ -155,6 +155,10 @@ QByteArray signal(const char* signature) {
return signal.replace("dummyMethod()", signature);
}
Box::Box(const glm::vec3& minimum, const glm::vec3& maximum) :
minimum(minimum), maximum(maximum) {
}
bool Box::contains(const Box& other) const {
return other.minimum.x >= minimum.x && other.maximum.x <= maximum.x &&
other.minimum.y >= minimum.y && other.maximum.y <= maximum.y &&

View file

@ -46,6 +46,8 @@ public:
STREAM glm::vec3 minimum;
STREAM glm::vec3 maximum;
Box(const glm::vec3& minimum = glm::vec3(), const glm::vec3& maximum = glm::vec3());
bool contains(const Box& other) const;
};

View file

@ -12,12 +12,12 @@ find_package(Qt5Network REQUIRED)
find_package(Qt5Script REQUIRED)
find_package(Qt5Widgets REQUIRED)
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE)
include(${MACRO_DIR}/AutoMTC.cmake)
auto_mtc(${TARGET_NAME} ${ROOT_DIR})
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE ${AUTOMTC_SRC})
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
#include glm