Compare commits
	
		
			10 Commits
		
	
	
		
			d827d02a15
			...
			8eaebee2c6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8eaebee2c6 | |||
| 48598de9c8 | |||
| 6218928e15 | |||
| 034d0a8b4e | |||
| dc94d0a130 | |||
| 3d4df2eb76 | |||
| 6528e872e5 | |||
| 5984763d43 | |||
| 95fd1e9977 | |||
| 3cad213a8e | 
@ -57,7 +57,7 @@ endif()
 | 
			
		||||
# Allow add_subdirectory on this project to use target ALIAS if available.
 | 
			
		||||
# If this example project is opened standalone we will use find_package.
 | 
			
		||||
if(NOT TARGET Qtk::qtk)
 | 
			
		||||
  find_package(Qtk 0.2 REQUIRED)
 | 
			
		||||
  find_package(Qtk 0.3 REQUIRED)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
find_package(Qt6 COMPONENTS Core Widgets OpenGLWidgets REQUIRED)
 | 
			
		||||
@ -100,4 +100,4 @@ if((Qt6_VERSION VERSION_GREATER_EQUAL "6.3.0" AND (WIN32 OR APPLE))
 | 
			
		||||
  install(SCRIPT ${QTK_EXAMPLE_DEPLOY_SCRIPT} COMPONENT qtk_example)
 | 
			
		||||
elseif(NOT Qtk_IS_TOP_LEVEL)
 | 
			
		||||
  message(WARNING "[Qtk] Installation is only supported on Qt >=6.5.\n")
 | 
			
		||||
endif()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
@ -222,6 +222,9 @@
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionLoad_Model">
 | 
			
		||||
   <property name="enabled">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="icon">
 | 
			
		||||
    <iconset>
 | 
			
		||||
     <normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/solid/cube.svg</normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/solid/cube.svg</iconset>
 | 
			
		||||
@ -234,6 +237,9 @@
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionDelete_Object">
 | 
			
		||||
   <property name="enabled">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="icon">
 | 
			
		||||
    <iconset>
 | 
			
		||||
     <normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/trash-can.svg</normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/trash-can.svg</iconset>
 | 
			
		||||
 | 
			
		||||
@ -485,13 +485,7 @@ void QtkScene::update()
 | 
			
		||||
  // Helper lambda to set the light position used by GLSL shaders on the model.
 | 
			
		||||
  // TODO: This could be a helper function on the Model class.
 | 
			
		||||
  auto setLightPosition = [](const std::string & lightName, Model * model) {
 | 
			
		||||
    if (auto light = Model::getInstance(lightName.c_str()); light) {
 | 
			
		||||
      QVector3D position = light->getTransform().getTranslation();
 | 
			
		||||
      model->setUniform("uLight.position", position);
 | 
			
		||||
    } else {
 | 
			
		||||
      qDebug() << "[QtkScene] Failed to set light position: "
 | 
			
		||||
               << lightName.c_str();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  QMatrix4x4 posMatrix;
 | 
			
		||||
 | 
			
		||||
@ -16,20 +16,94 @@
 | 
			
		||||
 | 
			
		||||
using namespace Qtk;
 | 
			
		||||
 | 
			
		||||
ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), ui(new Ui::ToolBox)
 | 
			
		||||
ToolBox::ToolBox(QWidget * parent) :
 | 
			
		||||
    QDockWidget(parent), objectDetails_(this), transformPanel_(this),
 | 
			
		||||
    scalePanel_(this), vertex_(this, "Vertex Shader:"),
 | 
			
		||||
    fragment_(this, "Fragment Shader:"), properiesForm_(new QFormLayout),
 | 
			
		||||
    shaderForm_(new QFormLayout), ui(new Ui::ToolBox)
 | 
			
		||||
{
 | 
			
		||||
  ui->setupUi(this);
 | 
			
		||||
  setMinimumWidth(350);
 | 
			
		||||
 | 
			
		||||
  // Object Properties.
 | 
			
		||||
  ui->page_properties->setLayout(properiesForm_);
 | 
			
		||||
  properiesForm_->addRow(objectDetails_.name.label, objectDetails_.name.value);
 | 
			
		||||
  properiesForm_->addRow(objectDetails_.objectType.label,
 | 
			
		||||
                         objectDetails_.objectType.value);
 | 
			
		||||
  properiesForm_->addRow(reinterpret_cast<QWidget *>(&transformPanel_));
 | 
			
		||||
  properiesForm_->addRow(reinterpret_cast<QWidget *>(&scalePanel_));
 | 
			
		||||
  ui->toolBox->setCurrentWidget(ui->page_properties);
 | 
			
		||||
 | 
			
		||||
  // Shader views.
 | 
			
		||||
  ui->page_shaders->setLayout(shaderForm_);
 | 
			
		||||
  shaderForm_->addRow(reinterpret_cast<QWidget *>(&vertex_));
 | 
			
		||||
  shaderForm_->addRow(reinterpret_cast<QWidget *>(&fragment_));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::updateFocus(const QString & name)
 | 
			
		||||
{
 | 
			
		||||
  auto object =
 | 
			
		||||
      Qtk::QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name);
 | 
			
		||||
      QtkWidget::mWidgetManager.get_widget()->getScene()->getObject(name);
 | 
			
		||||
  if (object != Q_NULLPTR) {
 | 
			
		||||
    removePages();
 | 
			
		||||
    createPageProperties(object);
 | 
			
		||||
    createPageShader(object);
 | 
			
		||||
    refreshProperties(object);
 | 
			
		||||
    refreshShaders(object);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ToolBox::SpinBox3D::SpinBox3D(QWidget * parent, const char * l) :
 | 
			
		||||
    QWidget(parent), layout(new QHBoxLayout(this)), label(new QLabel(tr(l)))
 | 
			
		||||
{
 | 
			
		||||
  // The layout owns the widget and will clean it up on destruction.
 | 
			
		||||
  layout->addWidget(label);
 | 
			
		||||
  for (const auto & f : fields) {
 | 
			
		||||
    layout->addWidget(f->spinBox);
 | 
			
		||||
    f->spinBox->setMinimum(std::numeric_limits<double>::lowest());
 | 
			
		||||
    f->spinBox->setSingleStep(0.1);
 | 
			
		||||
    f->spinBox->setFixedWidth(75);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::SpinBox::disconnect() const
 | 
			
		||||
{
 | 
			
		||||
  Object::disconnect(connection);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::TransformPanel::setObject(const Qtk::Object * object)
 | 
			
		||||
{
 | 
			
		||||
  // Reconnect translation panel controls to the new object.
 | 
			
		||||
  const std::vector binds = {&Object::setTranslationX,
 | 
			
		||||
                             &Object::setTranslationY,
 | 
			
		||||
                             &Object::setTranslationZ};
 | 
			
		||||
  for (size_t i = 0; i < spinBox3D.fields.size(); i++) {
 | 
			
		||||
    auto * f = spinBox3D.fields[i];
 | 
			
		||||
    // Disconnect before changing spin box value.
 | 
			
		||||
    f->disconnect();
 | 
			
		||||
 | 
			
		||||
    // Set the values in the spin box to the object's current X,Y,Z
 | 
			
		||||
    f->spinBox->setValue(object->getTransform().getTranslation()[i]);
 | 
			
		||||
 | 
			
		||||
    // Reconnect to bind spin box value to the new object's position.
 | 
			
		||||
    f->connection =
 | 
			
		||||
        connect(f->spinBox, &QDoubleSpinBox::valueChanged, object, binds[i]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::ScalePanel::setObject(const Qtk::Object * object)
 | 
			
		||||
{
 | 
			
		||||
  // Reconnect scale panel controls to the new object.
 | 
			
		||||
  const std::vector binds = {
 | 
			
		||||
      &Object::setScaleX, &Object::setScaleY, &Object::setScaleZ};
 | 
			
		||||
  for (size_t i = 0; i < spinBox3D.fields.size(); i++) {
 | 
			
		||||
    auto * f = spinBox3D.fields[i];
 | 
			
		||||
    // Disconnect before changing spin box value.
 | 
			
		||||
    f->disconnect();
 | 
			
		||||
 | 
			
		||||
    // Set the values in the spin box to the object's current X,Y,Z
 | 
			
		||||
    f->spinBox->setValue(object->getTransform().getScale()[i]);
 | 
			
		||||
 | 
			
		||||
    // Reconnect to bind spin box value to the new object's scale.
 | 
			
		||||
    f->connection =
 | 
			
		||||
        connect(f->spinBox, &QDoubleSpinBox::valueChanged, object, binds[i]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,110 +112,19 @@ ToolBox::~ToolBox()
 | 
			
		||||
  delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::removePages()
 | 
			
		||||
void ToolBox::refreshProperties(const Object * object)
 | 
			
		||||
{
 | 
			
		||||
  // Remove all existing pages.
 | 
			
		||||
  for (size_t i = 0; i < ui->toolBox->count(); i++) {
 | 
			
		||||
    delete ui->toolBox->widget(i);
 | 
			
		||||
    ui->toolBox->removeItem(i);
 | 
			
		||||
  }
 | 
			
		||||
  // Refresh to show the new object's details.
 | 
			
		||||
  objectDetails_.setObject(object);
 | 
			
		||||
  // Reconnect transform panel controls to the new object.
 | 
			
		||||
  transformPanel_.setObject(object);
 | 
			
		||||
  scalePanel_.setObject(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::createPageProperties(const Object * object)
 | 
			
		||||
void ToolBox::refreshShaders(const Object * object)
 | 
			
		||||
{
 | 
			
		||||
  auto transform = object->getTransform();
 | 
			
		||||
  auto type = object->getType();
 | 
			
		||||
  auto * widget = new QWidget;
 | 
			
		||||
  ui->toolBox->addItem(widget, "Properties");
 | 
			
		||||
  ui->toolBox->setCurrentWidget(widget);
 | 
			
		||||
 | 
			
		||||
  auto * layout = new QFormLayout;
 | 
			
		||||
  layout->addRow(new QLabel(tr("Name:")),
 | 
			
		||||
                 new QLabel(object->getName().c_str()));
 | 
			
		||||
 | 
			
		||||
  layout->addRow(new QLabel(tr("Type:")),
 | 
			
		||||
                 new QLabel(type == Object::Type::QTK_MESH ? "Mesh" : "Model"));
 | 
			
		||||
 | 
			
		||||
  auto rowLayout = new QHBoxLayout;
 | 
			
		||||
  rowLayout->addWidget(new QLabel(tr("Translation:")));
 | 
			
		||||
  int minWidth = 75;
 | 
			
		||||
  for (size_t i = 0; i < 3; i++) {
 | 
			
		||||
    auto spinBox = new QDoubleSpinBox;
 | 
			
		||||
    spinBox->setMinimum(std::numeric_limits<double>::lowest());
 | 
			
		||||
    spinBox->setSingleStep(0.1);
 | 
			
		||||
    spinBox->setValue(transform.getTranslation()[i]);
 | 
			
		||||
    spinBox->setFixedWidth(minWidth);
 | 
			
		||||
    rowLayout->addWidget(spinBox);
 | 
			
		||||
 | 
			
		||||
    if (i == 0) {
 | 
			
		||||
      connect(spinBox,
 | 
			
		||||
              &QDoubleSpinBox::valueChanged,
 | 
			
		||||
              object,
 | 
			
		||||
              &Object::setTranslationX);
 | 
			
		||||
    } else if (i == 1) {
 | 
			
		||||
      connect(spinBox,
 | 
			
		||||
              &QDoubleSpinBox::valueChanged,
 | 
			
		||||
              object,
 | 
			
		||||
              &Object::setTranslationY);
 | 
			
		||||
    } else if (i == 2) {
 | 
			
		||||
      connect(spinBox,
 | 
			
		||||
              &QDoubleSpinBox::valueChanged,
 | 
			
		||||
              object,
 | 
			
		||||
              &Object::setTranslationZ);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  layout->addRow(rowLayout);
 | 
			
		||||
 | 
			
		||||
  rowLayout = new QHBoxLayout;
 | 
			
		||||
  rowLayout->addWidget(new QLabel(tr("Scale:")));
 | 
			
		||||
  for (size_t i = 0; i < 3; i++) {
 | 
			
		||||
    auto spinBox = new QDoubleSpinBox;
 | 
			
		||||
    spinBox->setMinimum(std::numeric_limits<double>::lowest());
 | 
			
		||||
    spinBox->setSingleStep(0.1);
 | 
			
		||||
    spinBox->setValue(transform.getScale()[i]);
 | 
			
		||||
    spinBox->setFixedWidth(minWidth);
 | 
			
		||||
    rowLayout->addWidget(spinBox);
 | 
			
		||||
 | 
			
		||||
    if (i == 0) {
 | 
			
		||||
      connect(
 | 
			
		||||
          spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleX);
 | 
			
		||||
    } else if (i == 1) {
 | 
			
		||||
      connect(
 | 
			
		||||
          spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleY);
 | 
			
		||||
    } else if (i == 2) {
 | 
			
		||||
      connect(
 | 
			
		||||
          spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleZ);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  layout->addRow(rowLayout);
 | 
			
		||||
  widget->setLayout(layout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ToolBox::createPageShader(const Object * object)
 | 
			
		||||
{
 | 
			
		||||
  // Shaders page.
 | 
			
		||||
  auto widget = new QWidget;
 | 
			
		||||
  ui->toolBox->addItem(widget, "Shaders");
 | 
			
		||||
  auto mainLayout = new QFormLayout;
 | 
			
		||||
  auto rowLayout = new QHBoxLayout;
 | 
			
		||||
  rowLayout->addWidget(new QLabel("Vertex Shader:"));
 | 
			
		||||
  rowLayout->addWidget(new QLabel(object->getVertexShader().c_str()));
 | 
			
		||||
  mainLayout->addRow(rowLayout);
 | 
			
		||||
 | 
			
		||||
  auto shaderView = new QTextEdit;
 | 
			
		||||
  shaderView->setReadOnly(true);
 | 
			
		||||
  shaderView->setText(object->getVertexShaderSourceCode().c_str());
 | 
			
		||||
  mainLayout->addRow(shaderView);
 | 
			
		||||
 | 
			
		||||
  rowLayout = new QHBoxLayout;
 | 
			
		||||
  rowLayout->addWidget(new QLabel("Fragment Shader:"));
 | 
			
		||||
  rowLayout->addWidget(new QLabel(object->getFragmentShader().c_str()));
 | 
			
		||||
  mainLayout->addRow(rowLayout);
 | 
			
		||||
 | 
			
		||||
  shaderView = new QTextEdit;
 | 
			
		||||
  shaderView->setReadOnly(true);
 | 
			
		||||
  shaderView->setText(object->getFragmentShaderSourceCode().c_str());
 | 
			
		||||
  mainLayout->addRow(shaderView);
 | 
			
		||||
 | 
			
		||||
  widget->setLayout(mainLayout);
 | 
			
		||||
  vertex_.path.setItem(object->getVertexShader().c_str());
 | 
			
		||||
  vertex_.editor->setText(object->getVertexShaderSourceCode().c_str());
 | 
			
		||||
  fragment_.path.setItem(object->getFragmentShader().c_str());
 | 
			
		||||
  fragment_.editor->setText(object->getFragmentShaderSourceCode().c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,10 @@
 | 
			
		||||
#include <QDesignerExportWidget>
 | 
			
		||||
#include <QDockWidget>
 | 
			
		||||
#include <QDoubleSpinBox>
 | 
			
		||||
#include <QGroupBox>
 | 
			
		||||
#include <QFormLayout>
 | 
			
		||||
#include <QHBoxLayout>
 | 
			
		||||
#include <QLabel>
 | 
			
		||||
#include <QTextEdit>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "qtk/scene.h"
 | 
			
		||||
@ -25,7 +28,7 @@ namespace Ui
 | 
			
		||||
 | 
			
		||||
namespace Qtk
 | 
			
		||||
{
 | 
			
		||||
  class ToolBox : public QDockWidget
 | 
			
		||||
  class ToolBox final : public QDockWidget
 | 
			
		||||
  {
 | 
			
		||||
      Q_OBJECT
 | 
			
		||||
 | 
			
		||||
@ -38,11 +41,9 @@ namespace Qtk
 | 
			
		||||
 | 
			
		||||
      ~ToolBox();
 | 
			
		||||
 | 
			
		||||
      void removePages();
 | 
			
		||||
      void refreshProperties(const Object * object);
 | 
			
		||||
 | 
			
		||||
      void createPageProperties(const Object * object);
 | 
			
		||||
 | 
			
		||||
      void createPageShader(const Object * object);
 | 
			
		||||
      void refreshShaders(const Object * object);
 | 
			
		||||
 | 
			
		||||
      void updateFocus(const QString & name);
 | 
			
		||||
 | 
			
		||||
@ -52,6 +53,144 @@ namespace Qtk
 | 
			
		||||
       * Private Members
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /// Displays details on the object.
 | 
			
		||||
      struct ObjectDetails {
 | 
			
		||||
          /// Single item containing a label and value.
 | 
			
		||||
          struct Item {
 | 
			
		||||
              explicit Item(QWidget * parent,
 | 
			
		||||
                            const char * l = "Item:",
 | 
			
		||||
                            const char * v = "") :
 | 
			
		||||
                  label(new QLabel(tr(l), parent)),
 | 
			
		||||
                  value(new QLabel(tr(v), parent))
 | 
			
		||||
              {
 | 
			
		||||
                value->setText(v);
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              void setItem(const QString & v) { setItem(label->text(), v); }
 | 
			
		||||
 | 
			
		||||
              void setItem(const QString & l, const QString & v)
 | 
			
		||||
              {
 | 
			
		||||
                label->setText(l);
 | 
			
		||||
                value->setText(v);
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              QLabel * label;
 | 
			
		||||
              QLabel * value;
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          /// We pass the parent widget so that Qt handles releasing memory.
 | 
			
		||||
          explicit ObjectDetails(QWidget * parent) :
 | 
			
		||||
              name(parent, "Name:"), objectType(parent, "ObjectType:")
 | 
			
		||||
          {
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          /// Refresh to display the new object's details
 | 
			
		||||
          void setObject(const Qtk::Object * object)
 | 
			
		||||
          {
 | 
			
		||||
            name.setItem(tr("Name:"), object->getName());
 | 
			
		||||
            objectType.setItem(
 | 
			
		||||
                tr("Type:"),
 | 
			
		||||
                object->getType() == Object::QTK_MESH ? "Mesh" : "Model");
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          Item name, objectType;
 | 
			
		||||
      };
 | 
			
		||||
      ObjectDetails objectDetails_;
 | 
			
		||||
 | 
			
		||||
      /// Structure to associate a QSpinBox with a connection.
 | 
			
		||||
      struct SpinBox {
 | 
			
		||||
          /**
 | 
			
		||||
           * Default constructor passes no parent to the QSpinBox.
 | 
			
		||||
           * It must be added to a layout for Qt to clean up the resources.
 | 
			
		||||
           */
 | 
			
		||||
          SpinBox() : spinBox(new QDoubleSpinBox) {}
 | 
			
		||||
 | 
			
		||||
          /// Disconnect the associated connection.
 | 
			
		||||
          void disconnect() const;
 | 
			
		||||
 | 
			
		||||
          QDoubleSpinBox * spinBox;
 | 
			
		||||
          QMetaObject::Connection connection;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      /// Spinbox with 3 fields and a single label.
 | 
			
		||||
      class SpinBox3D final : QWidget
 | 
			
		||||
      {
 | 
			
		||||
        public:
 | 
			
		||||
          /// We pass a parent to ensure Qt will clean up resources.
 | 
			
		||||
          /// Assigning a QWidget to a QLayout also ensures Qt will clean up.
 | 
			
		||||
          explicit SpinBox3D(QWidget * parent, const char * l = "SpinBox3D:");
 | 
			
		||||
 | 
			
		||||
          /// The main layout for the SpinBox3D widget.
 | 
			
		||||
          QHBoxLayout * layout {this};
 | 
			
		||||
 | 
			
		||||
          /// Label for the SpinBox3D.
 | 
			
		||||
          QLabel * label;
 | 
			
		||||
 | 
			
		||||
          /// SpinBox and a connection for each field.
 | 
			
		||||
          SpinBox x, y, z;
 | 
			
		||||
          /// Array for iterating over fields.
 | 
			
		||||
          std::array<SpinBox *, 3> fields {&x, &y, &z};
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      /// Initialize the transform panel and configure QObject connections.
 | 
			
		||||
      struct TransformPanel {
 | 
			
		||||
          explicit TransformPanel(QWidget * parent) :
 | 
			
		||||
              spinBox3D(parent, "Transform:")
 | 
			
		||||
          {
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          /// Reconnect QObject connections and spin box values in UI.
 | 
			
		||||
          void setObject(const Qtk::Object * object);
 | 
			
		||||
 | 
			
		||||
          SpinBox3D spinBox3D;
 | 
			
		||||
      };
 | 
			
		||||
      TransformPanel transformPanel_;
 | 
			
		||||
 | 
			
		||||
      /// Initialize the scale panel and configure QObject connections.
 | 
			
		||||
      struct ScalePanel {
 | 
			
		||||
          explicit ScalePanel(QWidget * parent) : spinBox3D(parent, "Scale:") {}
 | 
			
		||||
 | 
			
		||||
          /// Reconnect QObject connections and spin box values in UI.
 | 
			
		||||
          void setObject(const Qtk::Object * object);
 | 
			
		||||
 | 
			
		||||
          SpinBox3D spinBox3D;
 | 
			
		||||
      };
 | 
			
		||||
      ScalePanel scalePanel_;
 | 
			
		||||
 | 
			
		||||
      /// Displays shader name, path, and read-only text view.
 | 
			
		||||
      class ShaderView final : QWidget
 | 
			
		||||
      {
 | 
			
		||||
        public:
 | 
			
		||||
          explicit ShaderView(QWidget * parent = nullptr,
 | 
			
		||||
                              const char * l = "ShaderView:") :
 | 
			
		||||
              layout(new QVBoxLayout(this)), path(parent, l),
 | 
			
		||||
              editor(new QTextEdit(parent))
 | 
			
		||||
          {
 | 
			
		||||
            // Create a child horizontal layout for shader name and file path.
 | 
			
		||||
            auto * pathLayout = new QHBoxLayout;
 | 
			
		||||
            pathLayout->addWidget(path.label);
 | 
			
		||||
            pathLayout->addWidget(path.value);
 | 
			
		||||
            layout->addLayout(pathLayout);
 | 
			
		||||
 | 
			
		||||
            // Add the read-only text editor widget to the main layout.
 | 
			
		||||
            editor->setReadOnly(true);
 | 
			
		||||
            layout->addWidget(editor);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          /// The main layout for the ShaderView widget.
 | 
			
		||||
          QVBoxLayout * layout;
 | 
			
		||||
 | 
			
		||||
          /// Shader name and path on disk.
 | 
			
		||||
          ObjectDetails::Item path;
 | 
			
		||||
 | 
			
		||||
          /// Read-only (for now) display of the shader source code.
 | 
			
		||||
          QTextEdit * editor;
 | 
			
		||||
      };
 | 
			
		||||
      ShaderView vertex_, fragment_;
 | 
			
		||||
 | 
			
		||||
      QFormLayout * properiesForm_;
 | 
			
		||||
      QFormLayout * shaderForm_;
 | 
			
		||||
 | 
			
		||||
      Ui::ToolBox * ui;
 | 
			
		||||
  };
 | 
			
		||||
}  // namespace Qtk
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ void Qtk::TreeView::updateView(const Qtk::Scene * scene)
 | 
			
		||||
  mSceneName = scene->getSceneName();
 | 
			
		||||
  auto objects = scene->getObjects();
 | 
			
		||||
  for (const auto & object : objects) {
 | 
			
		||||
    QStringList list(QStringList(QString(object->getName().c_str())));
 | 
			
		||||
    QStringList list(QStringList(QString(object->getName())));
 | 
			
		||||
    ui->treeWidget->insertTopLevelItem(0, new QTreeWidgetItem(list));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) :
 | 
			
		||||
 | 
			
		||||
MeshRenderer::~MeshRenderer()
 | 
			
		||||
{
 | 
			
		||||
  sInstances.remove(mName.c_str());
 | 
			
		||||
  sInstances.remove(mName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
@ -56,8 +56,19 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Model::setLightPosition(const QString & lightName, const char * uniform)
 | 
			
		||||
{
 | 
			
		||||
  if (auto light = MeshRenderer::getInstance(lightName); light) {
 | 
			
		||||
    QVector3D position = light->getTransform().getTranslation();
 | 
			
		||||
    setUniform(uniform, position);
 | 
			
		||||
  } else {
 | 
			
		||||
    qDebug() << "[QtkScene] Failed to set " << mName
 | 
			
		||||
             << "light position: " << lightName;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Static function to access ModelManager for getting Models by name
 | 
			
		||||
Model * Qtk::Model::getInstance(const char * name)
 | 
			
		||||
Model * Model::getInstance(const char * name)
 | 
			
		||||
{
 | 
			
		||||
  return mManager[name];
 | 
			
		||||
}
 | 
			
		||||
@ -102,7 +113,7 @@ void Model::loadModel(const std::string & path)
 | 
			
		||||
  sortModelMeshes();
 | 
			
		||||
 | 
			
		||||
  // Object finished loading, insert it into ModelManager
 | 
			
		||||
  mManager.insert(getName().c_str(), this);
 | 
			
		||||
  mManager.insert(getName(), this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Model::processNode(aiNode * node, const aiScene * scene)
 | 
			
		||||
@ -261,13 +272,11 @@ ModelMesh::Textures Model::loadMaterialTextures(aiMaterial * mat,
 | 
			
		||||
 | 
			
		||||
void Model::sortModelMeshes()
 | 
			
		||||
{
 | 
			
		||||
  auto cameraPos = Scene::getCamera().getTransform();
 | 
			
		||||
  auto cameraPos = Scene::getCamera().getTransform().getTranslation();
 | 
			
		||||
  auto cameraDistance = [&cameraPos](const ModelMesh & a, const ModelMesh & b) {
 | 
			
		||||
    // Sort by the first vertex position in the model
 | 
			
		||||
    return (cameraPos.getTranslation().distanceToPoint(
 | 
			
		||||
               a.mVertices[0].mPosition))
 | 
			
		||||
           < (cameraPos.getTranslation().distanceToPoint(
 | 
			
		||||
               b.mVertices[0].mPosition));
 | 
			
		||||
    return cameraPos.distanceToPoint(a.mVertices[0].mPosition)
 | 
			
		||||
           < cameraPos.distanceToPoint(b.mVertices[0].mPosition);
 | 
			
		||||
  };
 | 
			
		||||
  std::sort(mMeshes.begin(), mMeshes.end(), cameraDistance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -63,7 +63,7 @@ namespace Qtk
 | 
			
		||||
        loadModel(mModelPath);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      inline ~Model() override { mManager.remove(getName().c_str()); }
 | 
			
		||||
      inline ~Model() override { mManager.remove(getName()); }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Methods
 | 
			
		||||
@ -113,6 +113,14 @@ namespace Qtk
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Sets the position of a light used in GLSL unfiroms.
 | 
			
		||||
       *
 | 
			
		||||
       * @param lightName Object name of the light
 | 
			
		||||
       */
 | 
			
		||||
      void setLightPosition(const QString & lightName,
 | 
			
		||||
                            const char * uniform = "uLight.position");
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Accessors
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
@ -100,7 +100,7 @@ namespace Qtk
 | 
			
		||||
        return mShape.mVertices;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline std::string getName() const { return mName; }
 | 
			
		||||
      [[nodiscard]] inline QString getName() const { return mName; }
 | 
			
		||||
 | 
			
		||||
      [[nodiscard]] inline const Type & getType() const { return mType; }
 | 
			
		||||
 | 
			
		||||
@ -143,7 +143,7 @@ namespace Qtk
 | 
			
		||||
       * Setters
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      virtual inline void setName(const std::string & name) { mName = name; }
 | 
			
		||||
      virtual inline void setName(const QString & name) { mName = name; }
 | 
			
		||||
 | 
			
		||||
      virtual inline void setColors(const Colors & value)
 | 
			
		||||
      {
 | 
			
		||||
@ -244,6 +244,21 @@ namespace Qtk
 | 
			
		||||
        mProgram.release();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Public Static Methods
 | 
			
		||||
       ************************************************************************/
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Helper to disconnect a QObject connection, only if it's valid.
 | 
			
		||||
       * If the connection is valid and we fail to disconnect log a message.
 | 
			
		||||
       */
 | 
			
		||||
      static void disconnect(const QMetaObject::Connection & con)
 | 
			
		||||
      {
 | 
			
		||||
        if (con && !QObject::disconnect(con)) {
 | 
			
		||||
          qDebug() << "[Qtk] Failed to disconnect valid connection: " << con;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      /*************************************************************************
 | 
			
		||||
       * Private Members
 | 
			
		||||
@ -255,7 +270,7 @@ namespace Qtk
 | 
			
		||||
      Transform3D mTransform;
 | 
			
		||||
      Shape mShape;
 | 
			
		||||
      Texture mTexture;
 | 
			
		||||
      std::string mName;
 | 
			
		||||
      QString mName;
 | 
			
		||||
      bool mBound;
 | 
			
		||||
      Type mType = QTK_OBJECT;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -103,7 +103,7 @@ std::vector<Object *> Scene::getObjects() const
 | 
			
		||||
Object * Scene::getObject(const QString & name) const
 | 
			
		||||
{
 | 
			
		||||
  for (const auto & object : getObjects()) {
 | 
			
		||||
    if (object->getName() == name.toStdString()) {
 | 
			
		||||
    if (object->getName() == name) {
 | 
			
		||||
      return object;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -121,6 +121,6 @@ void Scene::initSceneObjectName(Object * object)
 | 
			
		||||
  // If the object name exists make it unique.
 | 
			
		||||
  auto count = ++mObjectCount[object->getName()];
 | 
			
		||||
  if (count > 1) {
 | 
			
		||||
    object->setName(object->getName() + " (" + std::to_string(count) + ")");
 | 
			
		||||
    object->setName(object->getName() + " (" + QString::number(count) + ")");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -120,9 +120,7 @@ namespace Qtk
 | 
			
		||||
       */
 | 
			
		||||
      [[nodiscard]] uint64_t getObjectCount(const QString & name)
 | 
			
		||||
      {
 | 
			
		||||
        return mObjectCount.count(name.toStdString())
 | 
			
		||||
                   ? mObjectCount[name.toStdString()]
 | 
			
		||||
                   : 0;
 | 
			
		||||
        return mObjectCount.count(name) ? mObjectCount[name] : 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
@ -248,7 +246,7 @@ namespace Qtk
 | 
			
		||||
      /* MeshRenderers used simple geometry. */
 | 
			
		||||
      std::vector<MeshRenderer *> mMeshes {};
 | 
			
		||||
      /* Track count of objects with same initial name. */
 | 
			
		||||
      std::unordered_map<std::string, uint64_t> mObjectCount;
 | 
			
		||||
      std::unordered_map<QString, uint64_t> mObjectCount;
 | 
			
		||||
  };
 | 
			
		||||
}  // namespace Qtk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user