ToolBar buttons to add and remove objects. (#18)
This commit is contained in:
parent
f40366cb8d
commit
ed604eb655
@ -48,6 +48,16 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent)
|
|||||||
&Qtk::ToolBox::updateFocus);
|
&Qtk::ToolBox::updateFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(ui_->actionDelete_Object,
|
||||||
|
&QAction::triggered,
|
||||||
|
this,
|
||||||
|
&MainWindow::deleteObject);
|
||||||
|
|
||||||
|
connect(ui_->actionLoad_Model,
|
||||||
|
&QAction::triggered,
|
||||||
|
this,
|
||||||
|
&MainWindow::loadObject);
|
||||||
|
|
||||||
// TODO: Fix / use MainWindow in Qt Designer to add these dock widgets.
|
// TODO: Fix / use MainWindow in Qt Designer to add these dock widgets.
|
||||||
// For now we will add them manually, but we should be able to do this in the
|
// For now we will add them manually, but we should be able to do this in the
|
||||||
// designer. At the moment if you edit the UI in designer the dock widget
|
// designer. At the moment if you edit the UI in designer the dock widget
|
||||||
@ -104,6 +114,26 @@ void MainWindow::refreshScene(const QString & sceneName)
|
|||||||
ui_->qtk__TreeView->updateView(getQtkWidget()->getScene());
|
ui_->qtk__TreeView->updateView(getQtkWidget()->getScene());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::deleteObject()
|
||||||
|
{
|
||||||
|
if (auto object = ui_->qtk__ToolBox->getObjectFocus(); object != Q_NULLPTR) {
|
||||||
|
auto scene = getQtkWidget()->getScene();
|
||||||
|
switch (object->getType()) {
|
||||||
|
case Qtk::Object::Type::QTK_MESH:
|
||||||
|
scene->removeObject(dynamic_cast<Qtk::MeshRenderer *>(object));
|
||||||
|
ui_->qtk__ToolBox->clearFocus();
|
||||||
|
break;
|
||||||
|
case Qtk::Object::Type::QTK_MODEL:
|
||||||
|
scene->removeObject(dynamic_cast<Qtk::Model *>(object));
|
||||||
|
ui_->qtk__ToolBox->clearFocus();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << "Failed to delete model with invalid type";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::setScene(Qtk::Scene * scene)
|
void MainWindow::setScene(Qtk::Scene * scene)
|
||||||
{
|
{
|
||||||
connect(scene,
|
connect(scene,
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QPlainTextEdit>
|
|
||||||
|
|
||||||
#include "designer-plugins/debugconsole.h"
|
#include "designer-plugins/debugconsole.h"
|
||||||
|
|
||||||
@ -144,6 +144,23 @@ class MainWindow : public QMainWindow
|
|||||||
*/
|
*/
|
||||||
void refreshScene(const QString & sceneName);
|
void refreshScene(const QString & sceneName);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a QFileDialog for selecting an object file to load into the scene.
|
||||||
|
*/
|
||||||
|
void loadObject()
|
||||||
|
{
|
||||||
|
const QUrl file = QFileDialog::getOpenFileName(
|
||||||
|
this, tr("Load Model"), QDir::homePath(), tr("Object Files (*.obj)"));
|
||||||
|
getQtkWidget()->getScene()->loadModel(file.fileName().replace(".obj", ""),
|
||||||
|
file.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the currently selected object from the scene.
|
||||||
|
*/
|
||||||
|
void deleteObject();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Private Members
|
* Private Members
|
||||||
|
@ -223,7 +223,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionLoad_Model">
|
<action name="actionLoad_Model">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset>
|
<iconset>
|
||||||
@ -238,7 +238,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionDelete_Object">
|
<action name="actionDelete_Object">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset>
|
<iconset>
|
||||||
|
@ -20,7 +20,7 @@ ToolBox::ToolBox(QWidget * parent) :
|
|||||||
QDockWidget(parent), objectDetails_(this), transformPanel_(this),
|
QDockWidget(parent), objectDetails_(this), transformPanel_(this),
|
||||||
scalePanel_(this), vertex_(this, "Vertex Shader:"),
|
scalePanel_(this), vertex_(this, "Vertex Shader:"),
|
||||||
fragment_(this, "Fragment Shader:"), properiesForm_(new QFormLayout),
|
fragment_(this, "Fragment Shader:"), properiesForm_(new QFormLayout),
|
||||||
shaderForm_(new QFormLayout), ui(new Ui::ToolBox)
|
shaderForm_(new QFormLayout), ui(new Ui::ToolBox), objectFocus_(Q_NULLPTR)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setMinimumWidth(350);
|
setMinimumWidth(350);
|
||||||
@ -44,10 +44,24 @@ void ToolBox::updateFocus(const QString & name)
|
|||||||
{
|
{
|
||||||
auto object =
|
auto object =
|
||||||
QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name);
|
QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name);
|
||||||
if (object != Q_NULLPTR) {
|
// If we can't find the object show a warning.
|
||||||
refreshProperties(object);
|
if (object == Q_NULLPTR) {
|
||||||
refreshShaders(object);
|
qDebug() << "Failed to find selected object: " << name
|
||||||
|
<< "; Clearing object panels.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We should still pass the nullptr here if we failed to find the object
|
||||||
|
// above.
|
||||||
|
objectFocus_ = object;
|
||||||
|
refreshProperties(object);
|
||||||
|
refreshShaders(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToolBox::clearFocus()
|
||||||
|
{
|
||||||
|
objectFocus_ = Q_NULLPTR;
|
||||||
|
refreshProperties(objectFocus_);
|
||||||
|
refreshShaders(objectFocus_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolBox::SpinBox3D::SpinBox3D(QWidget * parent, const char * l) :
|
ToolBox::SpinBox3D::SpinBox3D(QWidget * parent, const char * l) :
|
||||||
@ -70,6 +84,13 @@ void ToolBox::SpinBox::disconnect() const
|
|||||||
|
|
||||||
void ToolBox::TransformPanel::setObject(const Qtk::Object * object)
|
void ToolBox::TransformPanel::setObject(const Qtk::Object * object)
|
||||||
{
|
{
|
||||||
|
// Zero the panel contents if there is no object selected.
|
||||||
|
if (object == Q_NULLPTR) {
|
||||||
|
spinBox3D.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Reconnect translation panel controls to the new object.
|
// Reconnect translation panel controls to the new object.
|
||||||
const std::vector binds = {&Object::setTranslationX,
|
const std::vector binds = {&Object::setTranslationX,
|
||||||
&Object::setTranslationY,
|
&Object::setTranslationY,
|
||||||
@ -90,6 +111,12 @@ void ToolBox::TransformPanel::setObject(const Qtk::Object * object)
|
|||||||
|
|
||||||
void ToolBox::ScalePanel::setObject(const Qtk::Object * object)
|
void ToolBox::ScalePanel::setObject(const Qtk::Object * object)
|
||||||
{
|
{
|
||||||
|
// Zero the panel contents if there is no object selected.
|
||||||
|
if (object == Q_NULLPTR) {
|
||||||
|
spinBox3D.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Reconnect scale panel controls to the new object.
|
// Reconnect scale panel controls to the new object.
|
||||||
const std::vector binds = {
|
const std::vector binds = {
|
||||||
&Object::setScaleX, &Object::setScaleY, &Object::setScaleZ};
|
&Object::setScaleX, &Object::setScaleY, &Object::setScaleZ};
|
||||||
@ -123,8 +150,21 @@ void ToolBox::refreshProperties(const Object * object)
|
|||||||
|
|
||||||
void ToolBox::refreshShaders(const Object * object)
|
void ToolBox::refreshShaders(const Object * object)
|
||||||
{
|
{
|
||||||
|
// Zero the panel contents if there is no object selected.
|
||||||
|
if (object == Q_NULLPTR) {
|
||||||
|
vertex_.clear();
|
||||||
|
fragment_.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vertex_.path.setValue(object->getVertexShader().c_str());
|
vertex_.path.setValue(object->getVertexShader().c_str());
|
||||||
vertex_.editor->setText(object->getVertexShaderSourceCode().c_str());
|
vertex_.editor->setText(object->getVertexShaderSourceCode().c_str());
|
||||||
fragment_.path.setValue(object->getFragmentShader().c_str());
|
fragment_.path.setValue(object->getFragmentShader().c_str());
|
||||||
fragment_.editor->setText(object->getFragmentShaderSourceCode().c_str());
|
fragment_.editor->setText(object->getFragmentShaderSourceCode().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ToolBox::refresh(const Object * object)
|
||||||
|
{
|
||||||
|
refreshProperties(object);
|
||||||
|
refreshShaders(object);
|
||||||
|
}
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
#include "qtk/object.h"
|
||||||
|
|
||||||
#include "qtk/scene.h"
|
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -45,8 +45,13 @@ namespace Qtk
|
|||||||
|
|
||||||
void refreshShaders(const Object * object);
|
void refreshShaders(const Object * object);
|
||||||
|
|
||||||
|
void refresh(const Object * object);
|
||||||
|
|
||||||
void updateFocus(const QString & name);
|
void updateFocus(const QString & name);
|
||||||
|
|
||||||
|
[[nodiscard]] Object * getObjectFocus() const { return objectFocus_; }
|
||||||
|
|
||||||
|
void clearFocus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -65,9 +70,9 @@ namespace Qtk
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValue(const char * v) { value->setText(tr(v)); }
|
void setValue(const char * v) const { value->setText(tr(v)); }
|
||||||
|
|
||||||
void setItem(const char * l, const char * v)
|
void setItem(const char * l, const char * v) const
|
||||||
{
|
{
|
||||||
label->setText(tr(l));
|
label->setText(tr(l));
|
||||||
value->setText(tr(v));
|
value->setText(tr(v));
|
||||||
@ -84,8 +89,14 @@ namespace Qtk
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Refresh to display the new object's details
|
/// Refresh to display the new object's details
|
||||||
void setObject(const Qtk::Object * object)
|
void setObject(const Qtk::Object * object) const
|
||||||
{
|
{
|
||||||
|
// Zero contents if there is no object selected.
|
||||||
|
if (object == Q_NULLPTR) {
|
||||||
|
name.setValue("");
|
||||||
|
objectType.setValue("No object selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
name.setItem("Name:", object->getName().toStdString().c_str());
|
name.setItem("Name:", object->getName().toStdString().c_str());
|
||||||
objectType.setItem(
|
objectType.setItem(
|
||||||
"Type:",
|
"Type:",
|
||||||
@ -119,6 +130,15 @@ namespace Qtk
|
|||||||
/// Assigning a QWidget to a QLayout also ensures Qt will clean up.
|
/// Assigning a QWidget to a QLayout also ensures Qt will clean up.
|
||||||
explicit SpinBox3D(QWidget * parent, const char * l = "SpinBox3D:");
|
explicit SpinBox3D(QWidget * parent, const char * l = "SpinBox3D:");
|
||||||
|
|
||||||
|
/// Zero the SpinBox3D display.
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for (auto & field : fields) {
|
||||||
|
field->disconnect();
|
||||||
|
field->spinBox->setValue(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The main layout for the SpinBox3D widget.
|
/// The main layout for the SpinBox3D widget.
|
||||||
QHBoxLayout * layout;
|
QHBoxLayout * layout;
|
||||||
|
|
||||||
@ -176,6 +196,13 @@ namespace Qtk
|
|||||||
layout->addWidget(editor);
|
layout->addWidget(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Zero the ShaderView display.
|
||||||
|
void clear() const
|
||||||
|
{
|
||||||
|
path.setValue("");
|
||||||
|
editor->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
/// The main layout for the ShaderView widget.
|
/// The main layout for the ShaderView widget.
|
||||||
QVBoxLayout * layout;
|
QVBoxLayout * layout;
|
||||||
|
|
||||||
@ -190,6 +217,8 @@ namespace Qtk
|
|||||||
QFormLayout * properiesForm_;
|
QFormLayout * properiesForm_;
|
||||||
QFormLayout * shaderForm_;
|
QFormLayout * shaderForm_;
|
||||||
|
|
||||||
|
Object * objectFocus_ {};
|
||||||
|
|
||||||
Ui::ToolBox * ui;
|
Ui::ToolBox * ui;
|
||||||
};
|
};
|
||||||
} // namespace Qtk
|
} // namespace Qtk
|
||||||
|
@ -55,6 +55,34 @@ template <> Model * Scene::addObject(Model * object)
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> void Scene::removeObject(MeshRenderer * object)
|
||||||
|
{
|
||||||
|
auto it = std::find(mMeshes.begin(), mMeshes.end(), object);
|
||||||
|
if (it == mMeshes.end()) {
|
||||||
|
qDebug() << "[Scene::removeObject]: Failed to remove object: "
|
||||||
|
<< object->getName() << " (" << object << ")";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
--mObjectCount[object->getName()];
|
||||||
|
mMeshes.erase(it);
|
||||||
|
emit sceneUpdated(mSceneName);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> void Scene::removeObject(Model * object)
|
||||||
|
{
|
||||||
|
auto it = std::find(mModels.begin(), mModels.end(), object);
|
||||||
|
if (it == mModels.end()) {
|
||||||
|
qDebug() << "[Scene::removeObject]: Failed to remove object: "
|
||||||
|
<< object->getName() << " (" << object << ")";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
--mObjectCount[object->getName()];
|
||||||
|
mModels.erase(it);
|
||||||
|
emit sceneUpdated(mSceneName);
|
||||||
|
}
|
||||||
|
|
||||||
void Scene::draw()
|
void Scene::draw()
|
||||||
{
|
{
|
||||||
if (!mInit) {
|
if (!mInit) {
|
||||||
|
@ -85,16 +85,16 @@ namespace Qtk
|
|||||||
|
|
||||||
void loadModel(const QUrl & url)
|
void loadModel(const QUrl & url)
|
||||||
{
|
{
|
||||||
auto fileName = url.fileName().replace(".obj", "").toStdString();
|
auto fileName = url.fileName().replace(".obj", "");
|
||||||
auto filePath = url.toLocalFile().toStdString();
|
auto filePath = url.toLocalFile();
|
||||||
loadModel(fileName, filePath);
|
loadModel(fileName, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadModel(const std::string & name, const std::string & path)
|
void loadModel(const QString & name, const QString & path)
|
||||||
{
|
{
|
||||||
// Add the dropped model to the load queue.
|
// Add the dropped model to the load queue.
|
||||||
// This is consumed during rendering of the scene if not empty.
|
// This is consumed during rendering of the scene if not empty.
|
||||||
mModelLoadQueue.emplace(name, path);
|
mModelLoadQueue.emplace(name.toStdString(), path.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -182,8 +182,9 @@ namespace Qtk
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds objects to the scene.
|
* Adds objects to the scene.
|
||||||
* This template provides explicit specializations for valid types.
|
* This template provides explicit specializations for the valid types:
|
||||||
* Adding any object other than these types will cause errors.
|
* MeshRenderer, Model
|
||||||
|
* Any other object type will cause errors.
|
||||||
* TODO: Refactor to use Object base class container for scene objects.
|
* TODO: Refactor to use Object base class container for scene objects.
|
||||||
*
|
*
|
||||||
* If creating a new object type for a scene, it must inherit Qtk::Object
|
* If creating a new object type for a scene, it must inherit Qtk::Object
|
||||||
@ -194,6 +195,17 @@ namespace Qtk
|
|||||||
*/
|
*/
|
||||||
template <typename T> T * addObject(T * object);
|
template <typename T> T * addObject(T * object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an object from the scene.
|
||||||
|
* This template provides explicit specializations for the valid types:
|
||||||
|
* MeshRenderer, Model
|
||||||
|
* Any other object type will cause errors.
|
||||||
|
* TODO: Refactor to use Object base class container for scene objects.
|
||||||
|
*
|
||||||
|
* @param object Pointer to the object to remove from the scene.
|
||||||
|
*/
|
||||||
|
template <typename T> void removeObject(T * object);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name The name to use for this scene.
|
* @param name The name to use for this scene.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user