Archived
1
Fork 0

Add inspector

This commit is contained in:
Joshua Goins 2018-12-25 22:38:26 -05:00
parent 7f9f9702fc
commit 815910ac90
12 changed files with 341 additions and 3 deletions

View file

@ -1,6 +1,9 @@
set(INCLUDE_FILES
include/renderwindow.h
include/coloredit.h)
include/coloredit.h
include/context.h
include/vec3edit.h
include/collapsesection.h)
qt5_wrap_cpp(EDITOR_SRC ${INCLUDE_FILES})
@ -9,6 +12,8 @@ add_library(EditorCommon
src/renderwindow.cpp
src/editorstyle.cpp
src/coloredit.cpp
src/vec3edit.cpp
src/collapsesection.cpp
${EDITOR_SRC})
target_include_directories(EditorCommon PUBLIC include)
target_link_libraries(EditorCommon PRIVATE Engine Qt5::Widgets)

View file

@ -0,0 +1,28 @@
#pragma once
#include <QWidget>
class CollapseSection : public QWidget {
Q_OBJECT
public:
CollapseSection(QString label, bool closable = false);
signals:
void closeRequested();
protected:
void paintEvent(QPaintEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
private:
QString label;
bool closable;
QRect closeButtonRect;
bool closeButtonHovered = false;
bool collapsed = false;
QWidget* wrapper;
QLayout* layout;
};

View file

@ -1,11 +1,18 @@
#pragma once
#include <QObject>
class Renderer;
using EntityID = uint64_t;
struct Context {
class Context : public QObject {
Q_OBJECT
public:
Renderer* renderer;
std::vector<EntityID> selectedEntities;
signals:
void selectionChanged();
};

View file

@ -0,0 +1,23 @@
#pragma once
#include <QSpinBox>
#include <QWidget>
#include <glm/glm.hpp>
class Vector3Edit : public QWidget {
Q_OBJECT
public:
explicit Vector3Edit(glm::vec3& vec, QWidget* parent = nullptr);
~Vector3Edit();
signals:
void onValueChanged();
private:
struct {
QDoubleSpinBox *x, *y, *z;
} spinBoxes;
glm::vec3& vec;
QTimer* updateTimer;
};

View file

@ -0,0 +1,75 @@
#include "collapsesection.h"
#include <QPainter>
#include <QPaintEvent>
#include <QLayout>
#include <QApplication>
#include <QStyleOption>
#include <QDebug>
CollapseSection::CollapseSection(QString label, bool closable) : label(label), closable(closable) {
setContentsMargins(0, 25, 0, 0);
setMouseTracking(true);
}
void CollapseSection::paintEvent(QPaintEvent* event) {
QPainter painter(this);
painter.setPen(QColor(75, 75, 80));
painter.setBrush(QColor(50, 50, 55));
QRect r = event->rect().adjusted(1, 2, -1, 0);
r.setHeight(25);
painter.drawRect(r);
painter.setPen(Qt::white);
painter.drawText(event->rect().adjusted(6, 5, 0, 0), label);
if(closable) {
QStyleOption option;
option.rect.adjust(event->rect().width() - 20, 7, 0, 0);
option.rect.setHeight(16);
option.rect.setWidth(16);
option.state = QStyle::State_Active|QStyle::State_Enabled|QStyle::State_AutoRaise;
if(closeButtonHovered)
option.state |= QStyle::State_Raised | QStyle::State_MouseOver;
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &option, &painter, this);
}
}
void CollapseSection::mouseMoveEvent(QMouseEvent* event) {
if(closable) {
QRect r(width() - 20, 0, width(), 25); // close button
if(r.contains(mapFromGlobal(QCursor::pos())))
closeButtonHovered = true;
else
closeButtonHovered = false;
repaint();
}
}
void CollapseSection::mousePressEvent(QMouseEvent* event) {
QRect r(0, 0, width() - 20, 30); // header
if(r.contains(mapFromGlobal(QCursor::pos()))) {
if(!collapsed) {
setFixedHeight(30);
collapsed = true;
} else {
setFixedHeight(QWIDGETSIZE_MAX);
collapsed = false;
}
}
if(closable) {
QRect r(width() - 20, 0, width(), 25); // close button
if(r.contains(mapFromGlobal(QCursor::pos())))
emit closeRequested();
}
}

View file

@ -0,0 +1,58 @@
#include "vec3edit.h"
#include <QHBoxLayout>
#include <QTimer>
Vector3Edit::Vector3Edit(glm::vec3& vec, QWidget* parent) : QWidget(parent), vec(vec) {
QHBoxLayout* itemsLayout = new QHBoxLayout(this);
spinBoxes.x = new QDoubleSpinBox();
spinBoxes.y = new QDoubleSpinBox();
spinBoxes.z = new QDoubleSpinBox();
spinBoxes.x->setMinimum(-10000.0);
spinBoxes.x->setMaximum(10000.0);
spinBoxes.y->setMinimum(-10000.0);
spinBoxes.y->setMaximum(10000.0);
spinBoxes.z->setMinimum(-10000.0);
spinBoxes.z->setMaximum(10000.0);
itemsLayout->addWidget(spinBoxes.x);
itemsLayout->addWidget(spinBoxes.y);
itemsLayout->addWidget(spinBoxes.z);
spinBoxes.x->setValue(vec.x);
spinBoxes.y->setValue(vec.y);
spinBoxes.z->setValue(vec.z);
connect(spinBoxes.x, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this, &vec](double d) {
vec.x = d;
emit onValueChanged();
});
connect(spinBoxes.y, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this, &vec](double d) {
vec.y = d;
emit onValueChanged();
});
connect(spinBoxes.z, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this, &vec](double d) {
vec.z = d;
emit onValueChanged();
});
// TODO: find a better way to do this
updateTimer = new QTimer();
connect(updateTimer, &QTimer::timeout, [this, &vec]() {
if (vec.x != spinBoxes.x->value() || vec.y != spinBoxes.y->value() || vec.z != spinBoxes.z->value()) {
spinBoxes.x->setValue(vec.x);
spinBoxes.y->setValue(vec.y);
spinBoxes.z->setValue(vec.z);
}
});
updateTimer->start(1);
}
Vector3Edit::~Vector3Edit() {
updateTimer->stop();
}

View file

@ -1,6 +1,7 @@
set(INCLUDE_FILES
include/mainwindow.h
include/hierarchy.h)
include/hierarchy.h
include/inspector.h)
qt5_wrap_cpp(EDITOR_SRC ${INCLUDE_FILES})
@ -8,6 +9,7 @@ add_executable(LevelEditor
src/main.cpp
src/mainwindow.cpp
src/hierarchy.cpp
src/inspector.cpp
${EDITOR_SRC})
target_include_directories(LevelEditor PRIVATE include)
target_link_libraries(LevelEditor Qt5::Widgets Engine ToolWindowManager EditorCommon)

View file

@ -0,0 +1,28 @@
#pragma once
#include <QWidget>
#include <QVBoxLayout>
struct Context;
struct InfoComponent;
struct TransformComponent;
struct MeshComponent;
class Inspector : public QWidget {
Q_OBJECT
public:
Inspector(Context& context, QWidget* parent = nullptr);
private:
void rebuild();
void addInfoInspector(InfoComponent* info);
void addTransformInspector(TransformComponent* transform);
void addMeshInspector(MeshComponent* mesh);
QVBoxLayout* layout = nullptr;
QList<QWidget*> sections;
Context& context;
};

View file

@ -13,6 +13,7 @@ public:
private:
void addSceneView();
void addHierarchy();
void addInspector();
Context& context;
ToolWindowManager* manager = nullptr;

View file

@ -24,6 +24,8 @@ Hierarchy::Hierarchy(Context& context, QWidget* parent) : QWidget(parent), conte
context.selectedEntities.push_back(entity);
}
emit context.selectionChanged();
});
listModel = new QStringListModel();

View file

@ -0,0 +1,96 @@
#include "inspector.h"
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include "context.h"
#include "ecs.h"
#include "worldmanager.h"
#include "vec3edit.h"
#include "collapsesection.h"
Inspector::Inspector(Context& context, QWidget* parent) : QWidget(parent), context(context) {
setWindowTitle("Inspector");
setWindowIcon(QIcon::fromTheme("edit-cut"));
layout = new QVBoxLayout();
layout->setAlignment(Qt::AlignTop);
layout->setSpacing(0);
setLayout(layout);
rebuild();
connect(&context, &Context::selectionChanged, this, &Inspector::rebuild);
}
void Inspector::rebuild() {
for(auto section : sections) {
layout->removeWidget(section);
delete section;
}
sections.clear();
if(context.selectedEntities.size() == 0)
return;
const auto& entity = context.selectedEntities[0];
InfoComponent* info = ECS::getComponent<InfoComponent>(entity);
if(info)
addInfoInspector(info);
TransformComponent* transform = ECS::getComponent<TransformComponent>(entity);
if(transform)
addTransformInspector(transform);
MeshComponent* mesh = ECS::getComponent<MeshComponent>(entity);
if(mesh)
addMeshInspector(mesh);
}
void Inspector::addInfoInspector(InfoComponent* info) {
CollapseSection* section = new CollapseSection("Info");
layout->addWidget(section);
sections.push_back(section);
QGridLayout* layout = new QGridLayout();
section->setLayout(layout);
QLabel* nameLabel = new QLabel("Name");
layout->addWidget(nameLabel);
QLineEdit* nameEdit = new QLineEdit();
nameEdit->setText(info->name.c_str());
connect(nameEdit, &QLineEdit::editingFinished, [info, nameEdit] {
info->name = nameEdit->text().toStdString();
});
layout->addWidget(nameEdit, 0, 1);
}
void Inspector::addTransformInspector(TransformComponent* transform) {
CollapseSection* section = new CollapseSection("Transform");
layout->addWidget(section);
sections.push_back(section);
QGridLayout* layout = new QGridLayout();
section->setLayout(layout);
QLabel* positionLabel = new QLabel("Position");
layout->addWidget(positionLabel);
Vector3Edit* positionEdit = new Vector3Edit(transform->position);
layout->addWidget(positionEdit, 0, 1);
}
void Inspector::addMeshInspector(MeshComponent* mesh) {
CollapseSection* section = new CollapseSection("Mesh", true);
layout->addWidget(section);
sections.push_back(section);
QGridLayout* layout = new QGridLayout();
section->setLayout(layout);
}

View file

@ -11,6 +11,7 @@
#include "renderwindow.h"
#include "renderer.h"
#include "hierarchy.h"
#include "inspector.h"
MainWindow::MainWindow(Context& context) : context(context) {
setWindowTitle("Level Editor");
@ -122,6 +123,11 @@ MainWindow::MainWindow(Context& context) : context(context) {
connect(addHierarchy, &QAction::triggered, this, &MainWindow::addHierarchy);
addHierarchy->setIcon(QIcon::fromTheme("view-sort-ascending"));
newViewMenu->addAction(addHierarchy);
QAction* addInspector = new QAction("Inspector");
connect(addInspector, &QAction::triggered, this, &MainWindow::addInspector);
addInspector->setIcon(QIcon::fromTheme("edit-cut"));
newViewMenu->addAction(addInspector);
}
mainMenuBar->addSeparator();
@ -138,6 +144,7 @@ MainWindow::MainWindow(Context& context) : context(context) {
addSceneView();
addHierarchy();
addInspector();
}
void MainWindow::addSceneView() {
@ -157,3 +164,9 @@ void MainWindow::addHierarchy() {
manager->addToolWindow(hierarchy, ToolWindowManager::AreaReference(ToolWindowManager::EmptySpace));
}
void MainWindow::addInspector() {
Inspector* inspector = new Inspector(context);
manager->addToolWindow(inspector, ToolWindowManager::AreaReference(ToolWindowManager::EmptySpace));
}