Apply webkit style clang format on code base

master
Jeremy HU 2022-10-18 20:35:04 +11:00
parent 73f0404c2e
commit 57b1a802f3
213 changed files with 7933 additions and 8534 deletions

View File

@ -1,22 +1,22 @@
#include <QOpenGLFunctions>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QOpenGLFunctions>
#include "about_widget.h"
#include "version.h"
#include "model_widget.h"
#include "version.h"
AboutWidget::AboutWidget()
{
QTextEdit *versionInfoLabel = new QTextEdit;
QTextEdit* versionInfoLabel = new QTextEdit;
versionInfoLabel->setText(QString("%1 %2 (version: %3 build: %4 %5)\nopengl: %6 shader: %7 core: %8").arg(APP_NAME).arg(APP_HUMAN_VER).arg(APP_VER).arg(__DATE__).arg(__TIME__).arg(ModelWidget::m_openGLVersion).arg(ModelWidget::m_openGLShadingLanguageVersion).arg(ModelWidget::m_openGLIsCoreProfile ? "true" : "false"));
versionInfoLabel->setReadOnly(true);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addWidget(versionInfoLabel);
setLayout(mainLayout);
setFixedSize(QSize(350, 100));
setWindowTitle(applicationTitle(tr("About")));
}

View File

@ -3,8 +3,7 @@
#include <QDialog>
class AboutWidget : public QDialog
{
class AboutWidget : public QDialog {
Q_OBJECT
public:
AboutWidget();

View File

@ -1,9 +1,9 @@
#include <QtGlobal>
#include <QMatrix4x4>
#include <QDebug>
#include <cmath>
#include <QtMath>
#include "ccd_ik_resolver.h"
#include <QDebug>
#include <QMatrix4x4>
#include <QtGlobal>
#include <QtMath>
#include <cmath>
CcdIkSolver::CcdIkSolver()
{
@ -15,9 +15,9 @@ void CcdIkSolver::setSolveFrom(int fromNodeIndex)
}
void CcdIkSolver::setNodeHingeConstraint(int nodeIndex,
const QVector3D &axis, double minLimitDegrees, double maxLimitDegrees)
const QVector3D& axis, double minLimitDegrees, double maxLimitDegrees)
{
auto &node = m_nodes[nodeIndex];
auto& node = m_nodes[nodeIndex];
node.axis = axis;
node.minLimitDegrees = minLimitDegrees;
node.maxLimitDegrees = maxLimitDegrees;
@ -33,7 +33,7 @@ void CcdIkSolver::setDistanceThreshod(float threshold)
m_distanceThreshold2 = threshold * threshold;
}
int CcdIkSolver::addNodeInOrder(const QVector3D &position)
int CcdIkSolver::addNodeInOrder(const QVector3D& position)
{
CcdIkNode node;
node.position = position;
@ -42,13 +42,13 @@ int CcdIkSolver::addNodeInOrder(const QVector3D &position)
return nodeCount;
}
void CcdIkSolver::solveTo(const QVector3D &position)
void CcdIkSolver::solveTo(const QVector3D& position)
{
//qDebug() << "solveTo:" << position;
m_destination = position;
float lastDistance2 = 0;
for (int i = 0; i < m_maxRound; i++) {
const auto &endEffector = m_nodes[m_nodes.size() - 1];
const auto& endEffector = m_nodes[m_nodes.size() - 1];
float distance2 = (endEffector.position - m_destination).lengthSquared();
//qDebug() << "Round:" << i << " distance2:" << distance2;
if (distance2 <= m_distanceThreshold2)
@ -60,7 +60,7 @@ void CcdIkSolver::solveTo(const QVector3D &position)
}
}
const QVector3D &CcdIkSolver::getNodeSolvedPosition(int index)
const QVector3D& CcdIkSolver::getNodeSolvedPosition(int index)
{
Q_ASSERT(index >= 0 && index < (int)m_nodes.size());
return m_nodes[index].position;
@ -82,18 +82,18 @@ float CcdIkSolver::angleInRangle360BetweenTwoVectors(QVector3D a, QVector3D b, Q
void CcdIkSolver::iterate()
{
auto rotateChildren = [&](const QQuaternion &quaternion, int i) {
const auto &origin = m_nodes[i];
auto rotateChildren = [&](const QQuaternion& quaternion, int i) {
const auto& origin = m_nodes[i];
for (size_t j = i + 1; j <= m_nodes.size() - 1; j++) {
auto &next = m_nodes[j];
auto& next = m_nodes[j];
const auto offset = next.position - origin.position;
next.position = origin.position + quaternion.rotatedVector(offset);
}
};
for (int i = m_nodes.size() - 2; i >= m_fromNodeIndex; i--) {
const auto &origin = m_nodes[i];
const auto &endEffector = m_nodes[m_nodes.size() - 1];
const auto& origin = m_nodes[i];
const auto& endEffector = m_nodes[m_nodes.size() - 1];
QVector3D from = (endEffector.position - origin.position).normalized();
QVector3D to = (m_destination - origin.position).normalized();
auto quaternion = QQuaternion::rotationTo(from, to);
@ -111,12 +111,10 @@ void CcdIkSolver::iterate()
int childIndex = i + 1;
if (childIndex >= m_nodes.size())
continue;
const auto &parent = m_nodes[parentIndex];
const auto &child = m_nodes[childIndex];
QVector3D angleFrom = (QVector3D(0.0, parent.position.y(), parent.position.z()) -
QVector3D(0.0, origin.position.y(), origin.position.z())).normalized();
QVector3D angleTo = (QVector3D(0.0, child.position.y(), child.position.z()) -
QVector3D(0.0, origin.position.y(), origin.position.z())).normalized();
const auto& parent = m_nodes[parentIndex];
const auto& child = m_nodes[childIndex];
QVector3D angleFrom = (QVector3D(0.0, parent.position.y(), parent.position.z()) - QVector3D(0.0, origin.position.y(), origin.position.z())).normalized();
QVector3D angleTo = (QVector3D(0.0, child.position.y(), child.position.z()) - QVector3D(0.0, origin.position.y(), origin.position.z())).normalized();
float degrees = angleInRangle360BetweenTwoVectors(angleFrom, angleTo, QVector3D(1.0, 0.0, 0.0));
if (degrees < origin.minLimitDegrees) {
auto quaternion = QQuaternion::fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), origin.minLimitDegrees - degrees);

View File

@ -1,31 +1,30 @@
#ifndef DUST3D_APPLICATION_CCD_IK_SOLVER_H_
#define DUST3D_APPLICATION_CCD_IK_SOLVER_H_
#include <vector>
#include <QVector3D>
#include <QQuaternion>
#include <QVector3D>
#include <vector>
struct CcdIkNode
{
struct CcdIkNode {
QVector3D position;
QVector3D axis;
double minLimitDegrees;
double maxLimitDegrees;
};
class CcdIkSolver
{
class CcdIkSolver {
public:
CcdIkSolver();
void setMaxRound(int maxRound);
void setDistanceThreshod(float threshold);
int addNodeInOrder(const QVector3D &position);
void solveTo(const QVector3D &position);
const QVector3D &getNodeSolvedPosition(int index);
int addNodeInOrder(const QVector3D& position);
void solveTo(const QVector3D& position);
const QVector3D& getNodeSolvedPosition(int index);
int getNodeCount();
void setNodeHingeConstraint(int nodeIndex,
const QVector3D &axis, double minLimitDegrees, double maxLimitDegrees);
const QVector3D& axis, double minLimitDegrees, double maxLimitDegrees);
void setSolveFrom(int fromNodeIndex);
private:
float angleInRangle360BetweenTwoVectors(QVector3D a, QVector3D b, QVector3D planeNormal);
void iterate();

View File

@ -1,13 +1,13 @@
#include <QAbstractListModel>
#include <dust3d/base/debug.h>
#include "component_list_model.h"
#include "document.h"
#include <QAbstractListModel>
#include <dust3d/base/debug.h>
ComponentListModel::ComponentListModel(const Document *document, QObject *parent):
QAbstractListModel(parent),
m_document(document)
ComponentListModel::ComponentListModel(const Document* document, QObject* parent)
: QAbstractListModel(parent)
, m_document(document)
{
connect(m_document, &Document::componentPreviewPixmapChanged, [this](const dust3d::Uuid &componentId) {
connect(m_document, &Document::componentPreviewPixmapChanged, [this](const dust3d::Uuid& componentId) {
auto findIndex = this->m_componentIdToIndexMap.find(componentId);
if (findIndex != this->m_componentIdToIndexMap.end()) {
//dust3dDebug << "dataChanged:" << findIndex->second.row();
@ -18,7 +18,7 @@ ComponentListModel::ComponentListModel(const Document *document, QObject *parent
this->setListingComponentId(dust3d::Uuid());
this->reload();
});
connect(m_document, &Document::componentChildrenChanged, [this](const dust3d::Uuid &componentId) {
connect(m_document, &Document::componentChildrenChanged, [this](const dust3d::Uuid& componentId) {
if (componentId != this->listingComponentId())
return;
this->reload();
@ -29,7 +29,7 @@ void ComponentListModel::reload()
{
beginResetModel();
m_componentIdToIndexMap.clear();
const SkeletonComponent *listingComponent = m_document->findComponent(m_listingComponentId);
const SkeletonComponent* listingComponent = m_document->findComponent(m_listingComponentId);
if (nullptr != listingComponent) {
for (int i = 0; i < (int)listingComponent->childrenIds.size(); ++i) {
m_componentIdToIndexMap[listingComponent->childrenIds[i]] = createIndex(i, 0);
@ -39,7 +39,7 @@ void ComponentListModel::reload()
emit layoutChanged();
}
QModelIndex ComponentListModel::componentIdToIndex(const dust3d::Uuid &componentId) const
QModelIndex ComponentListModel::componentIdToIndex(const dust3d::Uuid& componentId) const
{
auto findIndex = m_componentIdToIndexMap.find(componentId);
if (findIndex == m_componentIdToIndexMap.end())
@ -47,34 +47,34 @@ QModelIndex ComponentListModel::componentIdToIndex(const dust3d::Uuid &component
return findIndex->second;
}
int ComponentListModel::rowCount(const QModelIndex &parent) const
int ComponentListModel::rowCount(const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
const SkeletonComponent *listingComponent = m_document->findComponent(m_listingComponentId);
const SkeletonComponent* listingComponent = m_document->findComponent(m_listingComponentId);
if (nullptr == listingComponent)
return 0;
return (int)listingComponent->childrenIds.size();
}
int ComponentListModel::columnCount(const QModelIndex &parent) const
int ComponentListModel::columnCount(const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
return 1;
}
const SkeletonComponent *ComponentListModel::modelIndexToComponent(const QModelIndex &index) const
const SkeletonComponent* ComponentListModel::modelIndexToComponent(const QModelIndex& index) const
{
const SkeletonComponent *listingComponent = m_document->findComponent(m_listingComponentId);
const SkeletonComponent* listingComponent = m_document->findComponent(m_listingComponentId);
if (nullptr == listingComponent)
return nullptr;
if (index.row() >= (int)listingComponent->childrenIds.size()) {
dust3dDebug << "Component list row is out of range, size:" << listingComponent->childrenIds.size() << "row:" << index.row();
return nullptr;
}
const auto &componentId = listingComponent->childrenIds[index.row()];
const SkeletonComponent *component = m_document->findComponent(componentId);
const auto& componentId = listingComponent->childrenIds[index.row()];
const SkeletonComponent* component = m_document->findComponent(componentId);
if (nullptr == component) {
dust3dDebug << "Component not found:" << componentId.toString();
return nullptr;
@ -82,50 +82,48 @@ const SkeletonComponent *ComponentListModel::modelIndexToComponent(const QModelI
return component;
}
const dust3d::Uuid ComponentListModel::modelIndexToComponentId(const QModelIndex &index) const
const dust3d::Uuid ComponentListModel::modelIndexToComponentId(const QModelIndex& index) const
{
const SkeletonComponent *listingComponent = m_document->findComponent(m_listingComponentId);
const SkeletonComponent* listingComponent = m_document->findComponent(m_listingComponentId);
if (nullptr == listingComponent)
return dust3d::Uuid();
if (index.row() >= (int)listingComponent->childrenIds.size()) {
dust3dDebug << "Component list row is out of range, size:" << listingComponent->childrenIds.size() << "row:" << index.row();
return dust3d::Uuid();
}
const auto &componentId = listingComponent->childrenIds[index.row()];
const auto& componentId = listingComponent->childrenIds[index.row()];
return componentId;
}
QVariant ComponentListModel::data(const QModelIndex &index, int role) const
QVariant ComponentListModel::data(const QModelIndex& index, int role) const
{
switch (role) {
case Qt::ToolTipRole: {
const SkeletonComponent *component = modelIndexToComponent(index);
if (nullptr != component) {
return component->name;
}
const SkeletonComponent* component = modelIndexToComponent(index);
if (nullptr != component) {
return component->name;
}
break;
} break;
case Qt::DecorationRole: {
const SkeletonComponent *component = modelIndexToComponent(index);
if (nullptr != component) {
if (0 == component->previewPixmap.width()) {
static QPixmap s_emptyPixmap;
if (0 == s_emptyPixmap.width()) {
QImage image((int)Theme::partPreviewImageSize, (int)Theme::partPreviewImageSize, QImage::Format_ARGB32);
image.fill(Qt::transparent);
s_emptyPixmap = QPixmap::fromImage(image);
}
return s_emptyPixmap;
const SkeletonComponent* component = modelIndexToComponent(index);
if (nullptr != component) {
if (0 == component->previewPixmap.width()) {
static QPixmap s_emptyPixmap;
if (0 == s_emptyPixmap.width()) {
QImage image((int)Theme::partPreviewImageSize, (int)Theme::partPreviewImageSize, QImage::Format_ARGB32);
image.fill(Qt::transparent);
s_emptyPixmap = QPixmap::fromImage(image);
}
return component->previewPixmap;
return s_emptyPixmap;
}
return component->previewPixmap;
}
break;
} break;
}
return QVariant();
}
void ComponentListModel::setListingComponentId(const dust3d::Uuid &componentId)
void ComponentListModel::setListingComponentId(const dust3d::Uuid& componentId)
{
if (m_listingComponentId == componentId)
return;

View File

@ -1,32 +1,33 @@
#ifndef DUST3D_APPLICATION_COMPONENT_LIST_MODEL_H_
#define DUST3D_APPLICATION_COMPONENT_LIST_MODEL_H_
#include <unordered_map>
#include <dust3d/base/uuid.h>
#include <QAbstractListModel>
#include <dust3d/base/uuid.h>
#include <unordered_map>
class Document;
class SkeletonComponent;
class ComponentListModel: public QAbstractListModel
{
class ComponentListModel : public QAbstractListModel {
Q_OBJECT
signals:
void listingComponentChanged(const dust3d::Uuid &componentId);
void listingComponentChanged(const dust3d::Uuid& componentId);
public:
ComponentListModel(const Document *document, QObject *parent=nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
const SkeletonComponent *modelIndexToComponent(const QModelIndex &index) const;
QModelIndex componentIdToIndex(const dust3d::Uuid &componentId) const;
const dust3d::Uuid modelIndexToComponentId(const QModelIndex &index) const;
ComponentListModel(const Document* document, QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role) const;
const SkeletonComponent* modelIndexToComponent(const QModelIndex& index) const;
QModelIndex componentIdToIndex(const dust3d::Uuid& componentId) const;
const dust3d::Uuid modelIndexToComponentId(const QModelIndex& index) const;
const dust3d::Uuid listingComponentId() const;
public slots:
void setListingComponentId(const dust3d::Uuid &componentId);
void setListingComponentId(const dust3d::Uuid& componentId);
void reload();
private:
const Document *m_document = nullptr;
const Document* m_document = nullptr;
dust3d::Uuid m_listingComponentId;
std::unordered_map<dust3d::Uuid, QModelIndex> m_componentIdToIndexMap;
};

View File

@ -1,23 +1,23 @@
#include <memory>
#include "component_preview_grid_widget.h"
#include "component_list_model.h"
#include "document.h"
#include <memory>
ComponentPreviewGridWidget::ComponentPreviewGridWidget(Document *document, QWidget *parent):
PreviewGridView(parent),
m_document(document)
ComponentPreviewGridWidget::ComponentPreviewGridWidget(Document* document, QWidget* parent)
: PreviewGridView(parent)
, m_document(document)
{
m_componentListModel = std::make_unique<ComponentListModel>(m_document);
setModel(m_componentListModel.get());
connect(this, &ComponentPreviewGridWidget::doubleClicked, [this](const QModelIndex &index) {
const SkeletonComponent *component = this->componentListModel()->modelIndexToComponent(index);
connect(this, &ComponentPreviewGridWidget::doubleClicked, [this](const QModelIndex& index) {
const SkeletonComponent* component = this->componentListModel()->modelIndexToComponent(index);
if (nullptr == component)
return;
if (component->childrenIds.empty()) {
std::vector<dust3d::Uuid> partIds;
this->m_document->collectComponentDescendantParts(component->id, partIds);
for (const auto &partId: partIds)
for (const auto& partId : partIds)
emit this->selectPartOnCanvas(partId);
} else {
this->componentListModel()->setListingComponentId(component->id);
@ -25,17 +25,17 @@ ComponentPreviewGridWidget::ComponentPreviewGridWidget(Document *document, QWidg
});
}
ComponentListModel *ComponentPreviewGridWidget::componentListModel()
ComponentListModel* ComponentPreviewGridWidget::componentListModel()
{
return m_componentListModel.get();
}
std::vector<const SkeletonComponent *> ComponentPreviewGridWidget::getSelectedComponents() const
std::vector<const SkeletonComponent*> ComponentPreviewGridWidget::getSelectedComponents() const
{
std::vector<const SkeletonComponent *> components;
std::vector<const SkeletonComponent*> components;
QModelIndexList selected = selectionModel()->selectedIndexes();
for (const auto &it: selected) {
const auto &component = m_componentListModel->modelIndexToComponent(it);
for (const auto& it : selected) {
const auto& component = m_componentListModel->modelIndexToComponent(it);
if (nullptr == component)
continue;
components.push_back(component);
@ -47,8 +47,8 @@ std::vector<dust3d::Uuid> ComponentPreviewGridWidget::getSelectedComponentIds()
{
std::vector<dust3d::Uuid> componentIds;
QModelIndexList selected = selectionModel()->selectedIndexes();
for (const auto &it: selected) {
const auto &componentId = m_componentListModel->modelIndexToComponentId(it);
for (const auto& it : selected) {
const auto& componentId = m_componentListModel->modelIndexToComponentId(it);
if (componentId.isNull())
continue;
componentIds.push_back(componentId);
@ -60,7 +60,7 @@ std::vector<dust3d::Uuid> ComponentPreviewGridWidget::getSelectedPartIds() const
{
auto selectedComponents = getSelectedComponents();
std::vector<dust3d::Uuid> partIds;
for (const auto &component: selectedComponents) {
for (const auto& component : selectedComponents) {
if (component->linkToPartId.isNull())
continue;
partIds.push_back(component->linkToPartId);

View File

@ -1,30 +1,31 @@
#ifndef DUST3D_APPLICATION_COMPONENT_PREVIEW_GRID_WIDGET_H_
#define DUST3D_APPLICATION_COMPONENT_PREVIEW_GRID_WIDGET_H_
#include <memory>
#include <dust3d/base/uuid.h>
#include <QAbstractListModel>
#include "preview_grid_view.h"
#include "component_list_model.h"
#include "preview_grid_view.h"
#include <QAbstractListModel>
#include <dust3d/base/uuid.h>
#include <memory>
class Document;
class SkeletonComponent;
class ComponentPreviewGridWidget: public PreviewGridView
{
class ComponentPreviewGridWidget : public PreviewGridView {
Q_OBJECT
signals:
void unselectAllOnCanvas();
void selectPartOnCanvas(const dust3d::Uuid &partId);
void selectPartOnCanvas(const dust3d::Uuid& partId);
public:
ComponentPreviewGridWidget(Document *document, QWidget *parent=nullptr);
ComponentListModel *componentListModel();
std::vector<const SkeletonComponent *> getSelectedComponents() const;
ComponentPreviewGridWidget(Document* document, QWidget* parent = nullptr);
ComponentListModel* componentListModel();
std::vector<const SkeletonComponent*> getSelectedComponents() const;
std::vector<dust3d::Uuid> getSelectedComponentIds() const;
std::vector<dust3d::Uuid> getSelectedPartIds() const;
private:
std::unique_ptr<ComponentListModel> m_componentListModel;
Document *m_document = nullptr;
Document* m_document = nullptr;
};
#endif

View File

@ -1,7 +1,7 @@
#include <dust3d/base/debug.h>
#include <QPainter>
#include "theme.h"
#include "component_preview_images_decorator.h"
#include "theme.h"
#include <QPainter>
#include <dust3d/base/debug.h>
ComponentPreviewImagesDecorator::ComponentPreviewImagesDecorator(std::unique_ptr<std::vector<PreviewInput>> previewInputs)
{
@ -21,7 +21,7 @@ void ComponentPreviewImagesDecorator::decorate()
m_resultImages = std::make_unique<std::unordered_map<dust3d::Uuid, std::unique_ptr<QImage>>>();
QPointF iconOffset(Theme::previewIconMargin, 0);
for (auto &it: *m_previewInputs) {
for (auto& it : *m_previewInputs) {
if (it.isDirectory) {
QPainter painter(it.image.get());
painter.setRenderHints(QPainter::Antialiasing);

View File

@ -1,17 +1,15 @@
#ifndef DUST3D_APPLICATION_COMPONENT_PREVIEW_IMAGES_DECORATOR_H_
#define DUST3D_APPLICATION_COMPONENT_PREVIEW_IMAGES_DECORATOR_H_
#include <QImage>
#include <dust3d/base/uuid.h>
#include <memory>
#include <unordered_map>
#include <dust3d/base/uuid.h>
#include <QImage>
class ComponentPreviewImagesDecorator: public QObject
{
class ComponentPreviewImagesDecorator : public QObject {
Q_OBJECT
public:
struct PreviewInput
{
struct PreviewInput {
dust3d::Uuid id;
std::unique_ptr<QImage> image;
bool isDirectory = false;
@ -23,6 +21,7 @@ signals:
void finished();
public slots:
void process();
private:
std::unique_ptr<std::vector<PreviewInput>> m_previewInputs;
std::unique_ptr<std::unordered_map<dust3d::Uuid, std::unique_ptr<QImage>>> m_resultImages;

View File

@ -1,96 +1,96 @@
#include <unordered_set>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include "component_property_widget.h"
#include "document.h"
#include "float_number_widget.h"
#include "theme.h"
#include <QColorDialog>
#include <QGroupBox>
#include "component_property_widget.h"
#include "float_number_widget.h"
#include "document.h"
#include "theme.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QVBoxLayout>
#include <unordered_set>
ComponentPropertyWidget::ComponentPropertyWidget(Document *document,
const std::vector<dust3d::Uuid> &componentIds,
QWidget *parent):
QWidget(parent),
m_document(document),
m_componentIds(componentIds)
ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
const std::vector<dust3d::Uuid>& componentIds,
QWidget* parent)
: QWidget(parent)
, m_document(document)
, m_componentIds(componentIds)
{
preparePartIds();
m_color = lastColor();
QPushButton *colorPreviewArea = new QPushButton;
QPushButton* colorPreviewArea = new QPushButton;
colorPreviewArea->setStyleSheet("QPushButton {background-color: " + m_color.name() + "; border-radius: 0;}");
colorPreviewArea->setFixedSize(Theme::toolIconSize * 1.8, Theme::toolIconSize);
QPushButton *colorPickerButton = new QPushButton(QChar(fa::eyedropper));
QPushButton* colorPickerButton = new QPushButton(QChar(fa::eyedropper));
Theme::initIconButton(colorPickerButton);
connect(colorPickerButton, &QPushButton::clicked, this, &ComponentPropertyWidget::showColorDialog);
QHBoxLayout *colorLayout = new QHBoxLayout;
QHBoxLayout* colorLayout = new QHBoxLayout;
colorLayout->addWidget(colorPreviewArea);
colorLayout->addWidget(colorPickerButton);
colorLayout->addStretch();
colorLayout->setSizeConstraint(QLayout::SetFixedSize);
QGroupBox *deformGroupBox = nullptr;
QGroupBox* deformGroupBox = nullptr;
if (nullptr != m_part) {
FloatNumberWidget *thicknessWidget = new FloatNumberWidget;
FloatNumberWidget* thicknessWidget = new FloatNumberWidget;
thicknessWidget->setItemName(tr("Thickness"));
thicknessWidget->setRange(0, 2);
thicknessWidget->setValue(m_part->deformThickness);
connect(thicknessWidget, &FloatNumberWidget::valueChanged, [=](float value) {
emit setPartDeformThickness(m_partId, value);
emit groupOperationAdded();
});
FloatNumberWidget *widthWidget = new FloatNumberWidget;
FloatNumberWidget* widthWidget = new FloatNumberWidget;
widthWidget->setItemName(tr("Width"));
widthWidget->setRange(0, 2);
widthWidget->setValue(m_part->deformWidth);
connect(widthWidget, &FloatNumberWidget::valueChanged, [=](float value) {
emit setPartDeformWidth(m_partId, value);
emit groupOperationAdded();
});
QPushButton *thicknessEraser = new QPushButton(QChar(fa::eraser));
QPushButton* thicknessEraser = new QPushButton(QChar(fa::eraser));
Theme::initIconButton(thicknessEraser);
connect(thicknessEraser, &QPushButton::clicked, [=]() {
thicknessWidget->setValue(1.0);
emit groupOperationAdded();
});
QPushButton *widthEraser = new QPushButton(QChar(fa::eraser));
QPushButton* widthEraser = new QPushButton(QChar(fa::eraser));
Theme::initIconButton(widthEraser);
connect(widthEraser, &QPushButton::clicked, [=]() {
widthWidget->setValue(1.0);
emit groupOperationAdded();
});
QVBoxLayout *deformLayout = new QVBoxLayout;
QHBoxLayout *thicknessLayout = new QHBoxLayout;
QHBoxLayout *widthLayout = new QHBoxLayout;
QVBoxLayout* deformLayout = new QVBoxLayout;
QHBoxLayout* thicknessLayout = new QHBoxLayout;
QHBoxLayout* widthLayout = new QHBoxLayout;
thicknessLayout->addWidget(thicknessEraser);
thicknessLayout->addWidget(thicknessWidget);
widthLayout->addWidget(widthEraser);
widthLayout->addWidget(widthWidget);
QCheckBox *deformUnifyStateBox = new QCheckBox();
QCheckBox* deformUnifyStateBox = new QCheckBox();
Theme::initCheckbox(deformUnifyStateBox);
deformUnifyStateBox->setText(tr("Unified"));
deformUnifyStateBox->setChecked(m_part->deformUnified);
connect(deformUnifyStateBox, &QCheckBox::stateChanged, this, [=]() {
emit setPartDeformUnified(m_partId, deformUnifyStateBox->isChecked());
emit groupOperationAdded();
});
QHBoxLayout *deformUnifyLayout = new QHBoxLayout;
QHBoxLayout* deformUnifyLayout = new QHBoxLayout;
deformUnifyLayout->addStretch();
deformUnifyLayout->addWidget(deformUnifyStateBox);
@ -102,85 +102,85 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document *document,
deformGroupBox->setLayout(deformLayout);
}
QGroupBox *cutFaceGroupBox = nullptr;
QGroupBox* cutFaceGroupBox = nullptr;
if (nullptr != m_part) {
FloatNumberWidget *rotationWidget = new FloatNumberWidget;
FloatNumberWidget* rotationWidget = new FloatNumberWidget;
rotationWidget->setItemName(tr("Rotation"));
rotationWidget->setRange(-1, 1);
rotationWidget->setValue(m_part->cutRotation);
connect(rotationWidget, &FloatNumberWidget::valueChanged, [=](float value) {
emit setPartCutRotation(m_partId, value);
emit groupOperationAdded();
});
QPushButton *rotationEraser = new QPushButton(QChar(fa::eraser));
QPushButton* rotationEraser = new QPushButton(QChar(fa::eraser));
Theme::initIconButton(rotationEraser);
connect(rotationEraser, &QPushButton::clicked, [=]() {
rotationWidget->setValue(0.0);
emit groupOperationAdded();
});
QPushButton *rotationMinus5Button = new QPushButton(QChar(fa::rotateleft));
QPushButton* rotationMinus5Button = new QPushButton(QChar(fa::rotateleft));
Theme::initIconButton(rotationMinus5Button);
connect(rotationMinus5Button, &QPushButton::clicked, [=]() {
rotationWidget->setValue(-0.5);
emit groupOperationAdded();
});
QPushButton *rotation5Button = new QPushButton(QChar(fa::rotateright));
QPushButton* rotation5Button = new QPushButton(QChar(fa::rotateright));
Theme::initIconButton(rotation5Button);
connect(rotation5Button, &QPushButton::clicked, [=]() {
rotationWidget->setValue(0.5);
emit groupOperationAdded();
});
QHBoxLayout *rotationLayout = new QHBoxLayout;
QHBoxLayout* rotationLayout = new QHBoxLayout;
rotationLayout->addWidget(rotationEraser);
rotationLayout->addWidget(rotationWidget);
rotationLayout->addWidget(rotationMinus5Button);
rotationLayout->addWidget(rotation5Button);
QCheckBox *subdivStateBox = new QCheckBox();
QCheckBox* subdivStateBox = new QCheckBox();
Theme::initCheckbox(subdivStateBox);
subdivStateBox->setText(tr("Subdivided"));
subdivStateBox->setChecked(m_part->subdived);
connect(subdivStateBox, &QCheckBox::stateChanged, this, [=]() {
emit setPartSubdivState(m_partId, subdivStateBox->isChecked());
emit groupOperationAdded();
});
QCheckBox *chamferStateBox = new QCheckBox();
QCheckBox* chamferStateBox = new QCheckBox();
Theme::initCheckbox(chamferStateBox);
chamferStateBox->setText(tr("Chamfered"));
chamferStateBox->setChecked(m_part->chamfered);
connect(chamferStateBox, &QCheckBox::stateChanged, this, [=]() {
emit setPartChamferState(m_partId, chamferStateBox->isChecked());
emit groupOperationAdded();
});
QCheckBox *roundEndStateBox = new QCheckBox();
QCheckBox* roundEndStateBox = new QCheckBox();
Theme::initCheckbox(roundEndStateBox);
roundEndStateBox->setText(tr("Round end"));
roundEndStateBox->setChecked(m_part->rounded);
connect(roundEndStateBox, &QCheckBox::stateChanged, this, [=]() {
emit setPartRoundState(m_partId, roundEndStateBox->isChecked());
emit groupOperationAdded();
});
QHBoxLayout *optionsLayout = new QHBoxLayout;
QHBoxLayout* optionsLayout = new QHBoxLayout;
optionsLayout->addStretch();
optionsLayout->addWidget(roundEndStateBox);
optionsLayout->addWidget(chamferStateBox);
optionsLayout->addWidget(subdivStateBox);
QVBoxLayout *cutFaceLayout = new QVBoxLayout;
QVBoxLayout* cutFaceLayout = new QVBoxLayout;
cutFaceLayout->addLayout(rotationLayout);
cutFaceLayout->addLayout(optionsLayout);
@ -188,7 +188,7 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document *document,
cutFaceGroupBox->setLayout(cutFaceLayout);
}
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addLayout(colorLayout);
if (nullptr != deformGroupBox)
mainLayout->addWidget(deformGroupBox);
@ -216,10 +216,10 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document *document,
void ComponentPropertyWidget::preparePartIds()
{
std::unordered_set<dust3d::Uuid> addedPartIdSet;
for (const auto &componentId: m_componentIds) {
for (const auto& componentId : m_componentIds) {
std::vector<dust3d::Uuid> partIds;
m_document->collectComponentDescendantParts(componentId, partIds);
for (const auto &it: partIds) {
for (const auto& it : partIds) {
if (addedPartIdSet.insert(it).second)
m_partIds.emplace_back(it);
}
@ -234,18 +234,18 @@ void ComponentPropertyWidget::preparePartIds()
QColor ComponentPropertyWidget::lastColor()
{
QColor color = Qt::white;
std::map<QString, int> colorMap;
for (const auto &partId: m_partIds) {
const SkeletonPart *part = m_document->findPart(partId);
std::map<QString, int> colorMap;
for (const auto& partId : m_partIds) {
const SkeletonPart* part = m_document->findPart(partId);
if (nullptr == part)
continue;
colorMap[part->color.name()]++;
}
if (!colorMap.empty()) {
color = std::max_element(colorMap.begin(), colorMap.end(),
[](const std::map<QString, int>::value_type &a, const std::map<QString, int>::value_type &b) {
return a.second < b.second;
})->first;
color = std::max_element(colorMap.begin(), colorMap.end(),
[](const std::map<QString, int>::value_type& a, const std::map<QString, int>::value_type& b) {
return a.second < b.second;
})->first;
}
return color;
}
@ -258,7 +258,7 @@ void ComponentPropertyWidget::showColorDialog()
if (!color.isValid())
return;
for (const auto &partId: m_partIds) {
for (const auto& partId : m_partIds) {
emit setPartColorState(partId, true, color);
}
emit groupOperationAdded();

View File

@ -1,39 +1,40 @@
#ifndef DUST3D_APPLICATION_COMPONENT_PROPERTY_WIDGET_H_
#define DUST3D_APPLICATION_COMPONENT_PROPERTY_WIDGET_H_
#include <dust3d/base/uuid.h>
#include <QWidget>
#include <dust3d/base/uuid.h>
class Document;
class SkeletonPart;
class ComponentPropertyWidget: public QWidget
{
class ComponentPropertyWidget : public QWidget {
Q_OBJECT
signals:
void beginColorPicking();
void endColorPicking();
void setPartColorState(const dust3d::Uuid &partId, bool hasColor, const QColor &color);
void setPartDeformThickness(const dust3d::Uuid &partId, float thickness);
void setPartDeformWidth(const dust3d::Uuid &partId, float width);
void setPartDeformUnified(const dust3d::Uuid &partId, bool unified);
void setPartSubdivState(const dust3d::Uuid &partId, bool subdived);
void setPartChamferState(const dust3d::Uuid &partId, bool chamfered);
void setPartRoundState(const dust3d::Uuid &partId, bool rounded);
void setPartCutRotation(const dust3d::Uuid &partId, float cutRotation);
void setPartColorState(const dust3d::Uuid& partId, bool hasColor, const QColor& color);
void setPartDeformThickness(const dust3d::Uuid& partId, float thickness);
void setPartDeformWidth(const dust3d::Uuid& partId, float width);
void setPartDeformUnified(const dust3d::Uuid& partId, bool unified);
void setPartSubdivState(const dust3d::Uuid& partId, bool subdived);
void setPartChamferState(const dust3d::Uuid& partId, bool chamfered);
void setPartRoundState(const dust3d::Uuid& partId, bool rounded);
void setPartCutRotation(const dust3d::Uuid& partId, float cutRotation);
void groupOperationAdded();
public:
ComponentPropertyWidget(Document *document,
const std::vector<dust3d::Uuid> &componentIds,
QWidget *parent=nullptr);
ComponentPropertyWidget(Document* document,
const std::vector<dust3d::Uuid>& componentIds,
QWidget* parent = nullptr);
public slots:
void showColorDialog();
private:
Document *m_document = nullptr;
Document* m_document = nullptr;
std::vector<dust3d::Uuid> m_componentIds;
std::vector<dust3d::Uuid> m_partIds;
dust3d::Uuid m_partId;
const SkeletonPart *m_part = nullptr;
const SkeletonPart* m_part = nullptr;
QColor m_color;
QColor lastColor();
void preparePartIds();

View File

@ -1,15 +1,15 @@
#include <QPainter>
#include <QPainterPath>
#include "cut_face_preview.h"
#include "theme.h"
#include <QPainter>
#include <QPainterPath>
static std::map<int, QImage *> g_standardCutFaceMap;
static std::map<int, QImage*> g_standardCutFaceMap;
QImage *buildCutFaceTemplatePreviewImage(const std::vector<dust3d::Vector2> &cutTemplate)
QImage* buildCutFaceTemplatePreviewImage(const std::vector<dust3d::Vector2>& cutTemplate)
{
QImage *image = new QImage(Theme::partPreviewImageSize, Theme::partPreviewImageSize, QImage::Format_ARGB32);
QImage* image = new QImage(Theme::partPreviewImageSize, Theme::partPreviewImageSize, QImage::Format_ARGB32);
image->fill(Qt::transparent);
if (cutTemplate.empty())
return image;
@ -17,41 +17,41 @@ QImage *buildCutFaceTemplatePreviewImage(const std::vector<dust3d::Vector2> &cut
painter.begin(image);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
QPen pen(Theme::red, 2);
painter.setPen(pen);
QBrush brush;
brush.setColor(Theme::white);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);
const float scale = 0.7f;
QPolygon polygon;
for (size_t i = 0; i <= cutTemplate.size(); ++i) {
const auto &it = cutTemplate[i % cutTemplate.size()];
polygon.append(QPoint((it.x() * scale + 1.0) * 0.5 * Theme::partPreviewImageSize,
const auto& it = cutTemplate[i % cutTemplate.size()];
polygon.append(QPoint((it.x() * scale + 1.0) * 0.5 * Theme::partPreviewImageSize,
(it.y() * scale + 1.0) * 0.5 * Theme::partPreviewImageSize));
}
QPainterPath path;
path.addPolygon(polygon);
painter.fillPath(path, brush);
painter.drawPath(path);
painter.end();
return image;
}
const QImage *cutFacePreviewImage(dust3d::CutFace cutFace)
const QImage* cutFacePreviewImage(dust3d::CutFace cutFace)
{
auto findItem = g_standardCutFaceMap.find((int)cutFace);
if (findItem != g_standardCutFaceMap.end())
return findItem->second;
std::vector<dust3d::Vector2> cutTemplate = dust3d::CutFaceToPoints(cutFace);
QImage *image = buildCutFaceTemplatePreviewImage(cutTemplate);
g_standardCutFaceMap.insert({(int)cutFace, image});
QImage* image = buildCutFaceTemplatePreviewImage(cutTemplate);
g_standardCutFaceMap.insert({ (int)cutFace, image });
return image;
}

View File

@ -4,7 +4,7 @@
#include <QImage>
#include <dust3d/base/cut_face.h>
QImage *buildCutFaceTemplatePreviewImage(const std::vector<dust3d::Vector2> &cutTemplate);
const QImage *cutFacePreviewImage(dust3d::CutFace cutFace);
QImage* buildCutFaceTemplatePreviewImage(const std::vector<dust3d::Vector2>& cutTemplate);
const QImage* cutFacePreviewImage(dust3d::CutFace cutFace);
#endif

View File

@ -1,10 +1,10 @@
#include <QtGlobal>
#include <QFile>
#include <QDebug>
#include <QtEndian>
#include <QByteArray>
#include <QOpenGLPixelTransferOptions>
#include "dds_file.h"
#include <QByteArray>
#include <QDebug>
#include <QFile>
#include <QOpenGLPixelTransferOptions>
#include <QtEndian>
#include <QtGlobal>
#ifndef _WIN32
typedef quint32 DWORD;
@ -37,20 +37,20 @@ typedef enum {
} DDS_CAPS2_FLAGS;
typedef struct {
DWORD dwSize;
DWORD dwFlags;
DWORD dwHeight;
DWORD dwWidth;
DWORD dwPitchOrLinearSize;
DWORD dwDepth;
DWORD dwMipMapCount;
DWORD dwReserved1[11];
DWORD dwSize;
DWORD dwFlags;
DWORD dwHeight;
DWORD dwWidth;
DWORD dwPitchOrLinearSize;
DWORD dwDepth;
DWORD dwMipMapCount;
DWORD dwReserved1[11];
DDS_PIXELFORMAT ddspf;
DWORD dwCaps;
DWORD dwCaps2;
DWORD dwCaps3;
DWORD dwCaps4;
DWORD dwReserved2;
DWORD dwCaps;
DWORD dwCaps2;
DWORD dwCaps3;
DWORD dwCaps4;
DWORD dwReserved2;
} DDS_HEADER;
typedef enum {
@ -176,9 +176,9 @@ typedef enum {
DXGI_FORMAT_FORCE_UINT
} DXGI_FORMAT;
static const char *DxgiFormatToString(DXGI_FORMAT dxgiFormat)
static const char* DxgiFormatToString(DXGI_FORMAT dxgiFormat)
{
static const char *names[] = {
static const char* names[] = {
"DXGI_FORMAT_UNKNOWN",
"DXGI_FORMAT_R32G32B32A32_TYPELESS",
"DXGI_FORMAT_R32G32B32A32_FLOAT",
@ -314,9 +314,9 @@ typedef enum {
D3D10_RESOURCE_DIMENSION_TEXTURE3D
} D3D10_RESOURCE_DIMENSION;
static const char *ResourceDimensionToString(D3D10_RESOURCE_DIMENSION resourceDimension)
static const char* ResourceDimensionToString(D3D10_RESOURCE_DIMENSION resourceDimension)
{
static const char *names[] = {
static const char* names[] = {
"D3D10_RESOURCE_DIMENSION_UNKNOWN",
"D3D10_RESOURCE_DIMENSION_BUFFER",
"D3D10_RESOURCE_DIMENSION_TEXTURE1D",
@ -337,9 +337,9 @@ typedef enum {
D3D10_RESOURCE_MISC_GDI_COMPATIBLE
} D3D10_RESOURCE_MISC_FLAG;
static const char *MiscFlagToString(UINT miscFlag)
static const char* MiscFlagToString(UINT miscFlag)
{
static const char *names[] = {
static const char* names[] = {
"D3D10_RESOURCE_MISC_GENERATE_MIPS",
"D3D10_RESOURCE_MISC_SHARED",
"D3D10_RESOURCE_MISC_TEXTURECUBE",
@ -353,76 +353,76 @@ static const char *MiscFlagToString(UINT miscFlag)
}
typedef struct {
DXGI_FORMAT dxgiFormat;
DXGI_FORMAT dxgiFormat;
D3D10_RESOURCE_DIMENSION resourceDimension;
UINT miscFlag;
UINT arraySize;
UINT miscFlags2;
UINT miscFlag;
UINT arraySize;
UINT miscFlags2;
} DDS_HEADER_DXT10;
typedef struct {
DWORD dwMagic;
DDS_HEADER header;
DDS_HEADER_DXT10 header10;
DWORD dwMagic;
DDS_HEADER header;
DDS_HEADER_DXT10 header10;
} DDS_FILE_HEADER;
DdsFileReader::DdsFileReader(const QString &filename) :
m_filename(filename)
{
DdsFileReader::DdsFileReader(const QString& filename)
: m_filename(filename)
{
}
std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> DdsFileReader::createOpenGLTextures()
{
QFile file(m_filename);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Open" << m_filename << "failed";
return nullptr;
}
DDS_FILE_HEADER fileHeader;
if (sizeof(fileHeader) != file.read((char *)&fileHeader, sizeof(fileHeader))) {
if (sizeof(fileHeader) != file.read((char*)&fileHeader, sizeof(fileHeader))) {
qDebug() << "Read DDS file hader failed";
return nullptr;
}
if (0x20534444 != qFromLittleEndian<quint32>(&fileHeader.dwMagic)) {
qDebug() << "Not a DDS file";
return nullptr;
}
if (0x30315844 != qFromLittleEndian<quint32>(&fileHeader.header.ddspf.dwFourCC)) {
qDebug() << "Unsupported DDS file, expected DX10 file";
return nullptr;
}
auto caps2 = qFromLittleEndian<quint32>(&fileHeader.header.dwCaps2);
if (!(DDSCAPS2_CUBEMAP & caps2)) {
qDebug() << "Unsupported DDS file, expected CUBEMAP file";
return nullptr;
}
//qDebug() << "Start anyalize DDS file...";
int width = qFromLittleEndian<quint32>(&fileHeader.header.dwWidth);
int height = qFromLittleEndian<quint32>(&fileHeader.header.dwHeight);
//qDebug() << "DDS size:" << width << "X" << height;
//auto pitchOrLinearSize = qFromLittleEndian<quint32>(&fileHeader.header.dwPitchOrLinearSize);
//qDebug() << "DDS pitch or linear size:" << pitchOrLinearSize;
auto arraySize = qFromLittleEndian<quint32>(&fileHeader.header10.arraySize);
//qDebug() << "DDS array size:" << arraySize;
auto mipMapCount = qFromLittleEndian<quint32>(&fileHeader.header.dwMipMapCount);
//qDebug() << "DDS mip map count:" << mipMapCount;
DXGI_FORMAT dxgiFormat = (DXGI_FORMAT)qFromLittleEndian<quint32>(&fileHeader.header10.dxgiFormat);
//qDebug() << "DDS dxgi format:" << DxgiFormatToString(dxgiFormat);
//qDebug() << "DDS resource dimension:" << ResourceDimensionToString((D3D10_RESOURCE_DIMENSION)qFromLittleEndian<quint32>(&fileHeader.header10.resourceDimension));
//qDebug() << "DDS misc flag:" << MiscFlagToString((UINT)qFromLittleEndian<quint32>(&fileHeader.header10.miscFlag));
quint32 faces = 0;
if (DDSCAPS2_CUBEMAP_POSITIVEX & caps2) {
//qDebug() << "DDS found +x";
@ -448,20 +448,20 @@ std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> DdsFileReader::cre
//qDebug() << "DDS found -z";
++faces;
}
if (6 != faces) {
qDebug() << "Unsupported DDS file, expected six faces";
return nullptr;
}
if (1 != arraySize) {
qDebug() << "Unsupported DDS file, expected one layer";
return nullptr;
}
if (DXGI_FORMAT_R16G16B16A16_FLOAT != dxgiFormat) {
qDebug() << "Unsupported DDS file, expected dxgi format: DXGI_FORMAT_R16G16B16A16_FLOAT";
return nullptr;
return nullptr;
}
int components = 8;
int oneFaceSize = 0;
@ -479,7 +479,7 @@ std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> DdsFileReader::cre
}
int depth = 1;
auto textures = std::make_unique<std::vector<std::unique_ptr<QOpenGLTexture>>>();
textures->resize(6);
@ -488,7 +488,7 @@ std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> DdsFileReader::cre
for (quint32 face = 0; face < faces; ++face) {
for (quint32 level = 0; level < mipMapCount; ++level) {
if (0 == layer && 0 == level) {
QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
QOpenGLTexture* texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
texture->setMinificationFilter(QOpenGLTexture::NearestMipMapNearest);
texture->setMagnificationFilter(QOpenGLTexture::Nearest);
texture->setFormat(QOpenGLTexture::RGBA16F);
@ -504,58 +504,58 @@ std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> DdsFileReader::cre
return std::move(textures);
}
QOpenGLTexture *DdsFileReader::createOpenGLTexture()
QOpenGLTexture* DdsFileReader::createOpenGLTexture()
{
QFile file(m_filename);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Open" << m_filename << "failed";
return nullptr;
}
DDS_FILE_HEADER fileHeader;
if (sizeof(fileHeader) != file.read((char *)&fileHeader, sizeof(fileHeader))) {
if (sizeof(fileHeader) != file.read((char*)&fileHeader, sizeof(fileHeader))) {
qDebug() << "Read DDS file hader failed";
return nullptr;
}
if (0x20534444 != qFromLittleEndian<quint32>(&fileHeader.dwMagic)) {
qDebug() << "Not a DDS file";
return nullptr;
}
if (0x30315844 != qFromLittleEndian<quint32>(&fileHeader.header.ddspf.dwFourCC)) {
qDebug() << "Unsupported DDS file, expected DX10 file";
return nullptr;
}
auto caps2 = qFromLittleEndian<quint32>(&fileHeader.header.dwCaps2);
if (!(DDSCAPS2_CUBEMAP & caps2)) {
qDebug() << "Unsupported DDS file, expected CUBEMAP file";
return nullptr;
}
//qDebug() << "Start anyalize DDS file...";
int width = qFromLittleEndian<quint32>(&fileHeader.header.dwWidth);
int height = qFromLittleEndian<quint32>(&fileHeader.header.dwHeight);
//qDebug() << "DDS size:" << width << "X" << height;
//auto pitchOrLinearSize = qFromLittleEndian<quint32>(&fileHeader.header.dwPitchOrLinearSize);
//qDebug() << "DDS pitch or linear size:" << pitchOrLinearSize;
auto arraySize = qFromLittleEndian<quint32>(&fileHeader.header10.arraySize);
//qDebug() << "DDS array size:" << arraySize;
auto mipMapCount = qFromLittleEndian<quint32>(&fileHeader.header.dwMipMapCount);
//qDebug() << "DDS mip map count:" << mipMapCount;
DXGI_FORMAT dxgiFormat = (DXGI_FORMAT)qFromLittleEndian<quint32>(&fileHeader.header10.dxgiFormat);
//qDebug() << "DDS dxgi format:" << DxgiFormatToString(dxgiFormat);
//qDebug() << "DDS resource dimension:" << ResourceDimensionToString((D3D10_RESOURCE_DIMENSION)qFromLittleEndian<quint32>(&fileHeader.header10.resourceDimension));
//qDebug() << "DDS misc flag:" << MiscFlagToString((UINT)qFromLittleEndian<quint32>(&fileHeader.header10.miscFlag));
quint32 faces = 0;
if (DDSCAPS2_CUBEMAP_POSITIVEX & caps2) {
//qDebug() << "DDS found +x";
@ -581,20 +581,20 @@ QOpenGLTexture *DdsFileReader::createOpenGLTexture()
//qDebug() << "DDS found -z";
++faces;
}
if (6 != faces) {
qDebug() << "Unsupported DDS file, expected six faces";
return nullptr;
}
if (1 != arraySize) {
qDebug() << "Unsupported DDS file, expected one layer";
return nullptr;
}
if (DXGI_FORMAT_R16G16B16A16_FLOAT != dxgiFormat) {
qDebug() << "Unsupported DDS file, expected dxgi format: DXGI_FORMAT_R16G16B16A16_FLOAT";
return nullptr;
return nullptr;
}
int components = 8;
int oneFaceSize = 0;
@ -610,9 +610,9 @@ QOpenGLTexture *DdsFileReader::createOpenGLTexture()
qDebug() << "DDS file invalid, expected total size:" << totalSize << "read size:" << data.size();
return nullptr;
}
int depth = 1;
QOpenGLTexture* texture = new QOpenGLTexture(QOpenGLTexture::TargetCubeMap);
texture->setFormat(QOpenGLTexture::RGBA16F);
texture->setSize(width, height, depth);
@ -620,37 +620,37 @@ QOpenGLTexture *DdsFileReader::createOpenGLTexture()
texture->setMipBaseLevel(0);
texture->setMipMaxLevel(mipMapCount - 1);
texture->setMipLevels(mipMapCount);
if (!texture->create()) {
qDebug() << "QOpenGLTexture::create failed";
delete texture;
return nullptr;
}
texture->allocateStorage();
if (!texture->isStorageAllocated()) {
qDebug() << "QOpenGLTexture::isStorageAllocated false";
delete texture;
return nullptr;
}
uint64_t dataOffset = 0;
for (quint32 layer = 0; layer < arraySize; ++layer) {
for (quint32 face = 0; face < faces; ++face) {
for (quint32 level = 0; level < mipMapCount; ++level) {
QOpenGLPixelTransferOptions uploadOptions;
uploadOptions.setAlignment(1);
texture->setData(level,
layer,
static_cast<QOpenGLTexture::CubeMapFace>(QOpenGLTexture::CubeMapPositiveX + face),
QOpenGLTexture::RGBA,
QOpenGLTexture::Float16,
data.constData() + dataOffset,
texture->setData(level,
layer,
static_cast<QOpenGLTexture::CubeMapFace>(QOpenGLTexture::CubeMapPositiveX + face),
QOpenGLTexture::RGBA,
QOpenGLTexture::Float16,
data.constData() + dataOffset,
&uploadOptions);
dataOffset += calculateOneFaceSizeAtLevel(level);
}
}
}
return texture;
}

View File

@ -1,16 +1,16 @@
#ifndef DUST3D_APPLICATION_DDS_FILE_H_
#define DUST3D_APPLICATION_DDS_FILE_H_
#include <memory>
#include <QString>
#include <QOpenGLTexture>
#include <QString>
#include <memory>
class DdsFileReader
{
class DdsFileReader {
public:
DdsFileReader(const QString &filename);
QOpenGLTexture *createOpenGLTexture();
DdsFileReader(const QString& filename);
QOpenGLTexture* createOpenGLTexture();
std::unique_ptr<std::vector<std::unique_ptr<QOpenGLTexture>>> createOpenGLTextures();
private:
QString m_filename;
};

View File

@ -1,13 +1,13 @@
#include "debug.h"
QDebug operator<<(QDebug debug, const dust3d::Uuid &uuid)
QDebug operator<<(QDebug debug, const dust3d::Uuid& uuid)
{
QDebugStateSaver stateSaver(debug);
debug.nospace() << uuid.toString().c_str();
return debug;
}
QDebug operator<<(QDebug debug, const std::string &string)
QDebug operator<<(QDebug debug, const std::string& string)
{
QDebugStateSaver stateSaver(debug);
debug.nospace() << string.c_str();

View File

@ -4,7 +4,7 @@
#include <QDebug>
#include <dust3d/base/uuid.h>
QDebug operator<<(QDebug debug, const dust3d::Uuid &uuid);
QDebug operator<<(QDebug debug, const std::string &string);
QDebug operator<<(QDebug debug, const dust3d::Uuid& uuid);
QDebug operator<<(QDebug debug, const std::string& string);
#endif

View File

@ -1,34 +1,34 @@
#include <QFileDialog>
#include <QDebug>
#include <QThread>
#include <QGuiApplication>
#include <QClipboard>
#include <QMimeData>
#include <QApplication>
#include <QVector3D>
#include <functional>
#include <QtCore/qbuffer.h>
#include <QElapsedTimer>
#include <queue>
#include <dust3d/base/snapshot_xml.h>
#include <dust3d/base/texture_type.h>
#include "document.h"
#include "image_forever.h"
#include "material_previews_generator.h"
#include "mesh_generator.h"
#include "mesh_result_post_processor.h"
#include "texture_generator.h"
#include "material_previews_generator.h"
#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QElapsedTimer>
#include <QFileDialog>
#include <QGuiApplication>
#include <QMimeData>
#include <QThread>
#include <QVector3D>
#include <QtCore/qbuffer.h>
#include <dust3d/base/snapshot_xml.h>
#include <dust3d/base/texture_type.h>
#include <functional>
#include <queue>
unsigned long Document::m_maxSnapshot = 1000;
Document::Document() :
SkeletonDocument()
Document::Document()
: SkeletonDocument()
{
}
Document::~Document()
{
delete (dust3d::MeshGenerator::GeneratedCacheContext *)m_generatedCacheContext;
delete (dust3d::MeshGenerator::GeneratedCacheContext*)m_generatedCacheContext;
delete m_resultMesh;
delete m_postProcessedObject;
delete textureImage;
@ -55,7 +55,7 @@ bool Document::originSettled() const
return !qFuzzyIsNull(getOriginX()) && !qFuzzyIsNull(getOriginY()) && !qFuzzyIsNull(getOriginZ());
}
const Material *Document::findMaterial(dust3d::Uuid materialId) const
const Material* Document::findMaterial(dust3d::Uuid materialId) const
{
auto it = materialMap.find(materialId);
if (it == materialMap.end())
@ -104,8 +104,7 @@ void Document::setNodeCutFaceLinkedId(dust3d::Uuid nodeId, dust3d::Uuid linkedId
qDebug() << "Node not found:" << nodeId;
return;
}
if (node->second.cutFace == dust3d::CutFace::UserDefined &&
node->second.cutFaceLinkedId == linkedId)
if (node->second.cutFace == dust3d::CutFace::UserDefined && node->second.cutFaceLinkedId == linkedId)
return;
node->second.setCutFaceLinkedId(linkedId);
auto part = partMap.find(node->second.partId);
@ -132,7 +131,7 @@ void Document::clearNodeCutFaceSettings(dust3d::Uuid nodeId)
emit skeletonChanged();
}
void Document::updateTurnaround(const QImage &image)
void Document::updateTurnaround(const QImage& image)
{
turnaround = image;
turnaroundPngByteArray.clear();
@ -149,47 +148,47 @@ void Document::clearTurnaround()
emit turnaroundChanged();
}
void Document::updateTextureImage(QImage *image)
void Document::updateTextureImage(QImage* image)
{
delete textureImageByteArray;
textureImageByteArray = nullptr;
delete textureImage;
textureImage = image;
}
void Document::updateTextureNormalImage(QImage *image)
void Document::updateTextureNormalImage(QImage* image)
{
delete textureNormalImageByteArray;
textureNormalImageByteArray = nullptr;
delete textureNormalImage;
textureNormalImage = image;
}
void Document::updateTextureMetalnessImage(QImage *image)
void Document::updateTextureMetalnessImage(QImage* image)
{
delete textureMetalnessImageByteArray;
textureMetalnessImageByteArray = nullptr;
delete textureMetalnessImage;
textureMetalnessImage = image;
}
void Document::updateTextureRoughnessImage(QImage *image)
void Document::updateTextureRoughnessImage(QImage* image)
{
delete textureRoughnessImageByteArray;
textureRoughnessImageByteArray = nullptr;
delete textureRoughnessImage;
textureRoughnessImage = image;
}
void Document::updateTextureAmbientOcclusionImage(QImage *image)
void Document::updateTextureAmbientOcclusionImage(QImage* image)
{
delete textureAmbientOcclusionImageByteArray;
textureAmbientOcclusionImageByteArray = nullptr;
delete textureAmbientOcclusionImage;
textureAmbientOcclusionImage = image;
}
@ -198,28 +197,27 @@ void Document::setEditMode(SkeletonDocumentEditMode mode)
{
if (editMode == mode)
return;
editMode = mode;
emit editModeChanged();
}
void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uuid> &limitNodeIds,
void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uuid>& limitNodeIds,
DocumentToSnapshotFor forWhat,
const std::set<dust3d::Uuid> &limitMaterialIds) const
const std::set<dust3d::Uuid>& limitMaterialIds) const
{
if (DocumentToSnapshotFor::Document == forWhat ||
DocumentToSnapshotFor::Nodes == forWhat) {
if (DocumentToSnapshotFor::Document == forWhat || DocumentToSnapshotFor::Nodes == forWhat) {
std::set<dust3d::Uuid> limitPartIds;
std::set<dust3d::Uuid> limitComponentIds;
for (const auto &nodeId: limitNodeIds) {
const SkeletonNode *node = findNode(nodeId);
for (const auto& nodeId : limitNodeIds) {
const SkeletonNode* node = findNode(nodeId);
if (!node)
continue;
const SkeletonPart *part = findPart(node->partId);
const SkeletonPart* part = findPart(node->partId);
if (!part)
continue;
limitPartIds.insert(node->partId);
const SkeletonComponent *component = findComponent(part->componentId);
const SkeletonComponent* component = findComponent(part->componentId);
while (component) {
limitComponentIds.insert(component->id);
if (component->id.isNull())
@ -227,7 +225,7 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
component = findComponent(component->parentId);
}
}
for (const auto &partIt : partMap) {
for (const auto& partIt : partMap) {
if (!limitPartIds.empty() && limitPartIds.find(partIt.first) == limitPartIds.end())
continue;
std::map<std::string, std::string> part;
@ -281,7 +279,7 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
part["smooth"] = "true";
snapshot->parts[part["id"]] = part;
}
for (const auto &nodeIt: nodeMap) {
for (const auto& nodeIt : nodeMap) {
if (!limitNodeIds.empty() && limitNodeIds.find(nodeIt.first) == limitNodeIds.end())
continue;
std::map<std::string, std::string> node;
@ -305,12 +303,10 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
node["name"] = nodeIt.second.name.toUtf8().constData();
snapshot->nodes[node["id"]] = node;
}
for (const auto &edgeIt: edgeMap) {
for (const auto& edgeIt : edgeMap) {
if (edgeIt.second.nodeIds.size() != 2)
continue;
if (!limitNodeIds.empty() &&
(limitNodeIds.find(edgeIt.second.nodeIds[0]) == limitNodeIds.end() ||
limitNodeIds.find(edgeIt.second.nodeIds[1]) == limitNodeIds.end()))
if (!limitNodeIds.empty() && (limitNodeIds.find(edgeIt.second.nodeIds[0]) == limitNodeIds.end() || limitNodeIds.find(edgeIt.second.nodeIds[1]) == limitNodeIds.end()))
continue;
std::map<std::string, std::string> edge;
edge["id"] = edgeIt.second.id.toString();
@ -321,7 +317,7 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
edge["name"] = edgeIt.second.name.toUtf8().constData();
snapshot->edges[edge["id"]] = edge;
}
for (const auto &componentIt: componentMap) {
for (const auto& componentIt : componentMap) {
if (!limitComponentIds.empty() && limitComponentIds.find(componentIt.first) == limitComponentIds.end())
continue;
std::map<std::string, std::string> component;
@ -332,7 +328,7 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
component["combineMode"] = CombineModeToString(componentIt.second.combineMode);
component["__dirty"] = componentIt.second.dirty ? "true" : "false";
std::vector<std::string> childIdList;
for (const auto &childId: componentIt.second.childrenIds) {
for (const auto& childId : componentIt.second.childrenIds) {
childIdList.push_back(childId.toString());
}
std::string children = dust3d::String::join(childIdList, ",");
@ -349,7 +345,7 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
}
if (limitComponentIds.empty() || limitComponentIds.find(dust3d::Uuid()) != limitComponentIds.end()) {
std::vector<std::string> childIdList;
for (const auto &childId: rootComponent.childrenIds) {
for (const auto& childId : rootComponent.childrenIds) {
childIdList.push_back(childId.toString());
}
std::string children = dust3d::String::join(childIdList, ",");
@ -357,9 +353,8 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
snapshot->rootComponent["children"] = children;
}
}
if (DocumentToSnapshotFor::Document == forWhat ||
DocumentToSnapshotFor::Materials == forWhat) {
for (const auto &materialId: materialIdList) {
if (DocumentToSnapshotFor::Document == forWhat || DocumentToSnapshotFor::Materials == forWhat) {
for (const auto& materialId : materialIdList) {
if (!limitMaterialIds.empty() && limitMaterialIds.find(materialId) == limitMaterialIds.end())
continue;
auto findMaterialResult = materialMap.find(materialId);
@ -367,16 +362,16 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
qDebug() << "Find material failed:" << materialId;
continue;
}
auto &materialIt = *findMaterialResult;
auto& materialIt = *findMaterialResult;
std::map<std::string, std::string> material;
material["id"] = materialIt.second.id.toString();
material["type"] = "MetalRoughness";
if (!materialIt.second.name.isEmpty())
material["name"] = materialIt.second.name.toUtf8().constData();
std::vector<std::pair<std::map<std::string, std::string>, std::vector<std::map<std::string, std::string>>>> layers;
for (const auto &layer: materialIt.second.layers) {
for (const auto& layer : materialIt.second.layers) {
std::vector<std::map<std::string, std::string>> maps;
for (const auto &mapItem: layer.maps) {
for (const auto& mapItem : layer.maps) {
std::map<std::string, std::string> textureMap;
textureMap["for"] = TextureTypeToString(mapItem.forWhat);
textureMap["linkDataType"] = "imageId";
@ -386,7 +381,7 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
std::map<std::string, std::string> layerAttributes;
if (!qFuzzyCompare((float)layer.tileScale, (float)1.0))
layerAttributes["tileScale"] = std::to_string(layer.tileScale);
layers.push_back({layerAttributes, maps});
layers.push_back({ layerAttributes, maps });
}
snapshot->materials.push_back(std::make_pair(material, layers));
}
@ -400,34 +395,31 @@ void Document::toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uui
}
}
void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSource source)
void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSource source)
{
bool isOriginChanged = false;
if (SnapshotSource::Paste != source &&
SnapshotSource::Import != source) {
const auto &originXit = snapshot.canvas.find("originX");
const auto &originYit = snapshot.canvas.find("originY");
const auto &originZit = snapshot.canvas.find("originZ");
if (originXit != snapshot.canvas.end() &&
originYit != snapshot.canvas.end() &&
originZit != snapshot.canvas.end()) {
if (SnapshotSource::Paste != source && SnapshotSource::Import != source) {
const auto& originXit = snapshot.canvas.find("originX");
const auto& originYit = snapshot.canvas.find("originY");
const auto& originZit = snapshot.canvas.find("originZ");
if (originXit != snapshot.canvas.end() && originYit != snapshot.canvas.end() && originZit != snapshot.canvas.end()) {
setOriginX(dust3d::String::toFloat(originXit->second));
setOriginY(dust3d::String::toFloat(originYit->second));
setOriginZ(dust3d::String::toFloat(originZit->second));
isOriginChanged = true;
}
}
std::set<dust3d::Uuid> newAddedNodeIds;
std::set<dust3d::Uuid> newAddedEdgeIds;
std::set<dust3d::Uuid> newAddedPartIds;
std::set<dust3d::Uuid> newAddedComponentIds;
std::set<dust3d::Uuid> inversePartIds;
std::map<dust3d::Uuid, dust3d::Uuid> oldNewIdMap;
for (const auto &materialIt: snapshot.materials) {
const auto &materialAttributes = materialIt.first;
for (const auto& materialIt : snapshot.materials) {
const auto& materialAttributes = materialIt.first;
auto materialType = dust3d::String::valueOrEmpty(materialAttributes, "type");
if ("MetalRoughness" != materialType) {
qDebug() << "Unsupported material type:" << materialType;
@ -437,15 +429,15 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
dust3d::Uuid newMaterialId = SnapshotSource::Import == source ? oldMaterialId : dust3d::Uuid::createUuid();
oldNewIdMap[oldMaterialId] = newMaterialId;
if (materialMap.end() == materialMap.find(newMaterialId)) {
auto &newMaterial = materialMap[newMaterialId];
auto& newMaterial = materialMap[newMaterialId];
newMaterial.id = newMaterialId;
newMaterial.name = dust3d::String::valueOrEmpty(materialAttributes, "name").c_str();
for (const auto &layerIt: materialIt.second) {
for (const auto& layerIt : materialIt.second) {
MaterialLayer layer;
auto findTileScale = layerIt.first.find("tileScale");
if (findTileScale != layerIt.first.end())
layer.tileScale = dust3d::String::toFloat(findTileScale->second);
for (const auto &mapItem: layerIt.second) {
for (const auto& mapItem : layerIt.second) {
auto textureTypeString = dust3d::String::valueOrEmpty(mapItem, "for");
auto textureType = dust3d::TextureTypeFromString(textureTypeString.c_str());
if (dust3d::TextureType::None == textureType) {
@ -470,13 +462,13 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
}
}
std::map<dust3d::Uuid, dust3d::Uuid> cutFaceLinkedIdModifyMap;
for (const auto &partKv: snapshot.parts) {
for (const auto& partKv : snapshot.parts) {
const auto newUuid = dust3d::Uuid::createUuid();
SkeletonPart &part = partMap[newUuid];
SkeletonPart& part = partMap[newUuid];
part.id = newUuid;
oldNewIdMap[dust3d::Uuid(partKv.first)] = part.id;
part.name = dust3d::String::valueOrEmpty(partKv.second, "name").c_str();
const auto &visibleIt = partKv.second.find("visible");
const auto& visibleIt = partKv.second.find("visible");
if (visibleIt != partKv.second.end()) {
part.visible = dust3d::String::isTrue(visibleIt->second);
} else {
@ -490,56 +482,56 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
part.rounded = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "rounded"));
part.chamfered = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "chamfered"));
part.target = dust3d::PartTargetFromString(dust3d::String::valueOrEmpty(partKv.second, "target").c_str());
const auto &cutRotationIt = partKv.second.find("cutRotation");
const auto& cutRotationIt = partKv.second.find("cutRotation");
if (cutRotationIt != partKv.second.end())
part.setCutRotation(dust3d::String::toFloat(cutRotationIt->second));
const auto &cutFaceIt = partKv.second.find("cutFace");
const auto& cutFaceIt = partKv.second.find("cutFace");
if (cutFaceIt != partKv.second.end()) {
dust3d::Uuid cutFaceLinkedId = dust3d::Uuid(cutFaceIt->second);
if (cutFaceLinkedId.isNull()) {
part.setCutFace(dust3d::CutFaceFromString(cutFaceIt->second.c_str()));
} else {
part.setCutFaceLinkedId(cutFaceLinkedId);
cutFaceLinkedIdModifyMap.insert({part.id, cutFaceLinkedId});
cutFaceLinkedIdModifyMap.insert({ part.id, cutFaceLinkedId });
}
}
if (dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "inverse")))
inversePartIds.insert(part.id);
const auto &colorIt = partKv.second.find("color");
const auto& colorIt = partKv.second.find("color");
if (colorIt != partKv.second.end()) {
part.color = QColor(colorIt->second.c_str());
part.hasColor = true;
}
const auto &colorSolubilityIt = partKv.second.find("colorSolubility");
const auto& colorSolubilityIt = partKv.second.find("colorSolubility");
if (colorSolubilityIt != partKv.second.end())
part.colorSolubility = dust3d::String::toFloat(colorSolubilityIt->second);
const auto &metalnessIt = partKv.second.find("metallic");
const auto& metalnessIt = partKv.second.find("metallic");
if (metalnessIt != partKv.second.end())
part.metalness = dust3d::String::toFloat(metalnessIt->second);
const auto &roughnessIt = partKv.second.find("roughness");
const auto& roughnessIt = partKv.second.find("roughness");
if (roughnessIt != partKv.second.end())
part.roughness = dust3d::String::toFloat(roughnessIt->second);
const auto &deformThicknessIt = partKv.second.find("deformThickness");
const auto& deformThicknessIt = partKv.second.find("deformThickness");
if (deformThicknessIt != partKv.second.end())
part.setDeformThickness(dust3d::String::toFloat(deformThicknessIt->second));
const auto &deformWidthIt = partKv.second.find("deformWidth");
const auto& deformWidthIt = partKv.second.find("deformWidth");
if (deformWidthIt != partKv.second.end())
part.setDeformWidth(dust3d::String::toFloat(deformWidthIt->second));
const auto &deformUnifiedIt = partKv.second.find("deformUnified");
const auto& deformUnifiedIt = partKv.second.find("deformUnified");
if (deformUnifiedIt != partKv.second.end())
part.deformUnified = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "deformUnified"));
const auto &hollowThicknessIt = partKv.second.find("hollowThickness");
const auto& hollowThicknessIt = partKv.second.find("hollowThickness");
if (hollowThicknessIt != partKv.second.end())
part.hollowThickness = dust3d::String::toFloat(hollowThicknessIt->second);
const auto &materialIdIt = partKv.second.find("materialId");
const auto& materialIdIt = partKv.second.find("materialId");
if (materialIdIt != partKv.second.end())
part.materialId = oldNewIdMap[dust3d::Uuid(materialIdIt->second)];
part.countershaded = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "countershaded"));
part.smooth = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "smooth"));
newAddedPartIds.insert(part.id);
}
for (const auto &it: cutFaceLinkedIdModifyMap) {
SkeletonPart &part = partMap[it.first];
for (const auto& it : cutFaceLinkedIdModifyMap) {
SkeletonPart& part = partMap[it.first];
auto findNewLinkedId = oldNewIdMap.find(it.second);
if (findNewLinkedId == oldNewIdMap.end()) {
if (partMap.find(it.second) == partMap.end()) {
@ -549,12 +541,8 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
part.setCutFaceLinkedId(findNewLinkedId->second);
}
}
for (const auto &nodeKv: snapshot.nodes) {
if (nodeKv.second.find("radius") == nodeKv.second.end() ||
nodeKv.second.find("x") == nodeKv.second.end() ||
nodeKv.second.find("y") == nodeKv.second.end() ||
nodeKv.second.find("z") == nodeKv.second.end() ||
nodeKv.second.find("partId") == nodeKv.second.end())
for (const auto& nodeKv : snapshot.nodes) {
if (nodeKv.second.find("radius") == nodeKv.second.end() || nodeKv.second.find("x") == nodeKv.second.end() || nodeKv.second.find("y") == nodeKv.second.end() || nodeKv.second.find("z") == nodeKv.second.end() || nodeKv.second.find("partId") == nodeKv.second.end())
continue;
dust3d::Uuid oldNodeId = dust3d::Uuid(nodeKv.first);
SkeletonNode node(nodeMap.find(oldNodeId) == nodeMap.end() ? oldNodeId : dust3d::Uuid::createUuid());
@ -565,10 +553,10 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
node.setY(dust3d::String::toFloat(dust3d::String::valueOrEmpty(nodeKv.second, "y")));
node.setZ(dust3d::String::toFloat(dust3d::String::valueOrEmpty(nodeKv.second, "z")));
node.partId = oldNewIdMap[dust3d::Uuid(dust3d::String::valueOrEmpty(nodeKv.second, "partId"))];
const auto &cutRotationIt = nodeKv.second.find("cutRotation");
const auto& cutRotationIt = nodeKv.second.find("cutRotation");
if (cutRotationIt != nodeKv.second.end())
node.setCutRotation(dust3d::String::toFloat(cutRotationIt->second));
const auto &cutFaceIt = nodeKv.second.find("cutFace");
const auto& cutFaceIt = nodeKv.second.find("cutFace");
if (cutFaceIt != nodeKv.second.end()) {
dust3d::Uuid cutFaceLinkedId = dust3d::Uuid(cutFaceIt->second);
if (cutFaceLinkedId.isNull()) {
@ -588,10 +576,8 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
nodeMap[node.id] = node;
newAddedNodeIds.insert(node.id);
}
for (const auto &edgeKv: snapshot.edges) {
if (edgeKv.second.find("from") == edgeKv.second.end() ||
edgeKv.second.find("to") == edgeKv.second.end() ||
edgeKv.second.find("partId") == edgeKv.second.end())
for (const auto& edgeKv : snapshot.edges) {
if (edgeKv.second.find("from") == edgeKv.second.end() || edgeKv.second.find("to") == edgeKv.second.end() || edgeKv.second.find("partId") == edgeKv.second.end())
continue;
dust3d::Uuid oldEdgeId = dust3d::Uuid(edgeKv.first);
SkeletonEdge edge(edgeMap.find(oldEdgeId) == edgeMap.end() ? oldEdgeId : dust3d::Uuid::createUuid());
@ -613,12 +599,12 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
edgeMap[edge.id] = edge;
newAddedEdgeIds.insert(edge.id);
}
for (const auto &nodeIt: nodeMap) {
for (const auto& nodeIt : nodeMap) {
if (newAddedNodeIds.find(nodeIt.first) == newAddedNodeIds.end())
continue;
partMap[nodeIt.second.partId].nodeIds.push_back(nodeIt.first);
}
for (const auto &componentKv: snapshot.components) {
for (const auto& componentKv : snapshot.components) {
QString linkData = dust3d::String::valueOrEmpty(componentKv.second, "linkData").c_str();
QString linkDataType = dust3d::String::valueOrEmpty(componentKv.second, "linkDataType").c_str();
SkeletonComponent component(dust3d::Uuid(), linkData, linkDataType);
@ -642,9 +628,9 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
componentMap.emplace(component.id, std::move(component));
newAddedComponentIds.insert(component.id);
}
const auto &rootComponentChildren = snapshot.rootComponent.find("children");
const auto& rootComponentChildren = snapshot.rootComponent.find("children");
if (rootComponentChildren != snapshot.rootComponent.end()) {
for (const auto &childId: dust3d::String::split(rootComponentChildren->second, ',')) {
for (const auto& childId : dust3d::String::split(rootComponentChildren->second, ',')) {
if (childId.empty())
continue;
dust3d::Uuid componentId = oldNewIdMap[dust3d::Uuid(childId)];
@ -654,11 +640,11 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
rootComponent.addChild(componentId);
}
}
for (const auto &componentKv: snapshot.components) {
for (const auto& componentKv : snapshot.components) {
dust3d::Uuid componentId = oldNewIdMap[dust3d::Uuid(componentKv.first)];
if (componentMap.find(componentId) == componentMap.end())
continue;
for (const auto &childId: dust3d::String::split(dust3d::String::valueOrEmpty(componentKv.second, "children"), ',')) {
for (const auto& childId : dust3d::String::split(dust3d::String::valueOrEmpty(componentKv.second, "children"), ',')) {
if (childId.empty())
continue;
dust3d::Uuid childComponentId = oldNewIdMap[dust3d::Uuid(childId)];
@ -669,34 +655,34 @@ void Document::addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSo
componentMap[childComponentId].parentId = componentId;
}
}
for (const auto &nodeIt: newAddedNodeIds) {
for (const auto& nodeIt : newAddedNodeIds) {
emit nodeAdded(nodeIt);
}
for (const auto &edgeIt: newAddedEdgeIds) {
for (const auto& edgeIt : newAddedEdgeIds) {
emit edgeAdded(edgeIt);
}
for (const auto &partIt : newAddedPartIds) {
for (const auto& partIt : newAddedPartIds) {
emit partAdded(partIt);
}
emit componentChildrenChanged(dust3d::Uuid());
if (isOriginChanged)
emit originChanged();
emit skeletonChanged();
for (const auto &partIt : newAddedPartIds) {
for (const auto& partIt : newAddedPartIds) {
emit partVisibleStateChanged(partIt);
}
emit uncheckAll();
for (const auto &nodeIt: newAddedNodeIds) {
for (const auto& nodeIt : newAddedNodeIds) {
emit checkNode(nodeIt);
}
for (const auto &edgeIt: newAddedEdgeIds) {
for (const auto& edgeIt : newAddedEdgeIds) {
emit checkEdge(edgeIt);
}
if (!snapshot.materials.empty())
emit materialListChanged();
}
@ -722,22 +708,22 @@ void Document::reset()
emit skeletonChanged();
}
void Document::fromSnapshot(const dust3d::Snapshot &snapshot)
void Document::fromSnapshot(const dust3d::Snapshot& snapshot)
{
reset();
addFromSnapshot(snapshot, SnapshotSource::Unknown);
emit uncheckAll();
}
ModelMesh *Document::takeResultMesh()
ModelMesh* Document::takeResultMesh()
{
if (nullptr == m_resultMesh)
return nullptr;
ModelMesh *resultMesh = new ModelMesh(*m_resultMesh);
ModelMesh* resultMesh = new ModelMesh(*m_resultMesh);
return resultMesh;
}
MonochromeMesh *Document::takeWireframeMesh()
MonochromeMesh* Document::takeWireframeMesh()
{
if (nullptr == m_wireframeMesh)
return nullptr;
@ -749,51 +735,51 @@ bool Document::isMeshGenerationSucceed()
return m_isMeshGenerationSucceed;
}
ModelMesh *Document::takeResultTextureMesh()
ModelMesh* Document::takeResultTextureMesh()
{
if (nullptr == m_resultTextureMesh)
return nullptr;
ModelMesh *resultTextureMesh = new ModelMesh(*m_resultTextureMesh);
ModelMesh* resultTextureMesh = new ModelMesh(*m_resultTextureMesh);
return resultTextureMesh;
}
void Document::meshReady()
{
ModelMesh *resultMesh = m_meshGenerator->takeResultMesh();
ModelMesh* resultMesh = m_meshGenerator->takeResultMesh();
m_wireframeMesh.reset(m_meshGenerator->takeWireframeMesh());
dust3d::Object *object = m_meshGenerator->takeObject();
dust3d::Object* object = m_meshGenerator->takeObject();
bool isSuccessful = m_meshGenerator->isSuccessful();
std::unique_ptr<std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>> componentPreviewMeshes;
componentPreviewMeshes.reset(m_meshGenerator->takeComponentPreviewMeshes());
bool componentPreviewsChanged = componentPreviewMeshes && !componentPreviewMeshes->empty();
if (componentPreviewsChanged) {
for (auto &it: *componentPreviewMeshes) {
for (auto& it : *componentPreviewMeshes) {
setComponentPreviewMesh(it.first, std::move(it.second));
}
emit resultComponentPreviewMeshesChanged();
}
delete m_resultMesh;
m_resultMesh = resultMesh;
m_isMeshGenerationSucceed = isSuccessful;
delete m_currentObject;
m_currentObject = object;
if (nullptr == m_resultMesh) {
qDebug() << "Result mesh is null";
}
delete m_meshGenerator;
m_meshGenerator = nullptr;
qDebug() << "Mesh generation done";
m_isPostProcessResultObsolete = true;
emit resultMeshChanged();
if (m_isResultMeshObsolete) {
generateMesh();
}
@ -843,18 +829,18 @@ void Document::generateMesh()
m_isResultMeshObsolete = true;
return;
}
emit meshGenerating();
qDebug() << "Mesh generating..";
settleOrigin();
m_isResultMeshObsolete = false;
QThread *thread = new QThread;
dust3d::Snapshot *snapshot = new dust3d::Snapshot;
QThread* thread = new QThread;
dust3d::Snapshot* snapshot = new dust3d::Snapshot;
toSnapshot(snapshot);
resetDirtyFlags();
m_meshGenerator = new MeshGenerator(snapshot);
@ -862,7 +848,7 @@ void Document::generateMesh()
m_meshGenerator->setDefaultPartColor(dust3d::Color::createWhite());
if (nullptr == m_generatedCacheContext)
m_generatedCacheContext = new MeshGenerator::GeneratedCacheContext;
m_meshGenerator->setGeneratedCacheContext((dust3d::MeshGenerator::GeneratedCacheContext *)m_generatedCacheContext);
m_meshGenerator->setGeneratedCacheContext((dust3d::MeshGenerator::GeneratedCacheContext*)m_generatedCacheContext);
if (!m_smoothNormal) {
m_meshGenerator->setSmoothShadingThresholdAngleDegrees(0);
}
@ -880,16 +866,16 @@ void Document::generateTexture()
m_isTextureObsolete = true;
return;
}
qDebug() << "Texture guide generating..";
emit textureGenerating();
m_isTextureObsolete = false;
dust3d::Snapshot *snapshot = new dust3d::Snapshot;
dust3d::Snapshot* snapshot = new dust3d::Snapshot;
toSnapshot(snapshot);
QThread *thread = new QThread;
QThread* thread = new QThread;
m_textureGenerator = new TextureGenerator(*m_postProcessedObject, snapshot);
m_textureGenerator->moveToThread(thread);
connect(thread, &QThread::started, m_textureGenerator, &TextureGenerator::process);
@ -906,21 +892,21 @@ void Document::textureReady()
updateTextureMetalnessImage(m_textureGenerator->takeResultTextureMetalnessImage());
updateTextureRoughnessImage(m_textureGenerator->takeResultTextureRoughnessImage());
updateTextureAmbientOcclusionImage(m_textureGenerator->takeResultTextureAmbientOcclusionImage());
delete m_resultTextureMesh;
m_resultTextureMesh = m_textureGenerator->takeResultMesh();
m_postProcessedObject->alphaEnabled = m_textureGenerator->hasTransparencySettings();
m_textureImageUpdateVersion++;
delete m_textureGenerator;
m_textureGenerator = nullptr;
qDebug() << "Texture guide generation done";
emit resultTextureChanged();
if (m_isTextureObsolete) {
generateTexture();
} else {
@ -945,7 +931,7 @@ void Document::postProcess()
qDebug() << "Post processing..";
emit postProcessing();
QThread *thread = new QThread;
QThread* thread = new QThread;
m_postProcessor = new MeshResultPostProcessor(*m_currentObject);
m_postProcessor->moveToThread(thread);
connect(thread, &QThread::started, m_postProcessor, &MeshResultPostProcessor::process);
@ -972,7 +958,7 @@ void Document::postProcessedMeshResultReady()
}
}
const dust3d::Object &Document::currentPostProcessedObject() const
const dust3d::Object& Document::currentPostProcessedObject() const
{
return *m_postProcessedObject;
}
@ -1007,7 +993,7 @@ void Document::setPartSubdivState(dust3d::Uuid partId, bool subdived)
emit skeletonChanged();
}
void Document::resolveSnapshotBoundingBox(const dust3d::Snapshot &snapshot, QRectF *mainProfile, QRectF *sideProfile)
void Document::resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile)
{
float left = 0;
bool leftFirstTime = true;
@ -1021,7 +1007,7 @@ void Document::resolveSnapshotBoundingBox(const dust3d::Snapshot &snapshot, QRec
bool zLeftFirstTime = true;
float zRight = 0;
bool zRightFirstTime = true;
for (const auto &nodeIt: snapshot.nodes) {
for (const auto& nodeIt : snapshot.nodes) {
float radius = dust3d::String::toFloat(dust3d::String::valueOrEmpty(nodeIt.second, "radius"));
float x = dust3d::String::toFloat(dust3d::String::valueOrEmpty(nodeIt.second, "x"));
float y = dust3d::String::toFloat(dust3d::String::valueOrEmpty(nodeIt.second, "y"));
@ -1330,8 +1316,7 @@ void Document::setPartCutFaceLinkedId(dust3d::Uuid partId, dust3d::Uuid linkedId
qDebug() << "Part not found:" << partId;
return;
}
if (part->second.cutFace == dust3d::CutFace::UserDefined &&
part->second.cutFaceLinkedId == linkedId)
if (part->second.cutFace == dust3d::CutFace::UserDefined && part->second.cutFaceLinkedId == linkedId)
return;
part->second.setCutFaceLinkedId(linkedId);
part->second.dirty = true;
@ -1370,7 +1355,7 @@ void Document::undo()
return;
m_redoItems.push_back(m_undoItems.back());
m_undoItems.pop_back();
const auto &item = m_undoItems.back();
const auto& item = m_undoItems.back();
fromSnapshot(item.snapshot);
qDebug() << "Undo/Redo items:" << m_undoItems.size() << m_redoItems.size();
}
@ -1380,7 +1365,7 @@ void Document::redo()
if (m_redoItems.empty())
return;
m_undoItems.push_back(m_redoItems.back());
const auto &item = m_redoItems.back();
const auto& item = m_redoItems.back();
fromSnapshot(item.snapshot);
m_redoItems.pop_back();
qDebug() << "Undo/Redo items:" << m_undoItems.size() << m_redoItems.size();
@ -1394,12 +1379,12 @@ void Document::clearHistories()
void Document::paste()
{
const QClipboard *clipboard = QApplication::clipboard();
const QMimeData *mimeData = clipboard->mimeData();
const QClipboard* clipboard = QApplication::clipboard();
const QMimeData* mimeData = clipboard->mimeData();
if (mimeData->hasText()) {
dust3d::Snapshot snapshot;
std::string text = mimeData->text().toUtf8().constData();
loadSnapshotFromXmlString(&snapshot, (char *)text.c_str());
loadSnapshotFromXmlString(&snapshot, (char*)text.c_str());
addFromSnapshot(snapshot, SnapshotSource::Paste);
saveSnapshot();
}
@ -1407,8 +1392,8 @@ void Document::paste()
bool Document::hasPastableNodesInClipboard() const
{
const QClipboard *clipboard = QApplication::clipboard();
const QMimeData *mimeData = clipboard->mimeData();
const QClipboard* clipboard = QApplication::clipboard();
const QMimeData* mimeData = clipboard->mimeData();
if (mimeData->hasText()) {
if (-1 != mimeData->text().indexOf("<node "))
return true;
@ -1418,8 +1403,8 @@ bool Document::hasPastableNodesInClipboard() const
bool Document::hasPastableMaterialsInClipboard() const
{
const QClipboard *clipboard = QApplication::clipboard();
const QMimeData *mimeData = clipboard->mimeData();
const QClipboard* clipboard = QApplication::clipboard();
const QMimeData* mimeData = clipboard->mimeData();
if (mimeData->hasText()) {
if (-1 != mimeData->text().indexOf("<material "))
return true;
@ -1439,7 +1424,7 @@ bool Document::redoable() const
bool Document::isNodeEditable(dust3d::Uuid nodeId) const
{
const SkeletonNode *node = findNode(nodeId);
const SkeletonNode* node = findNode(nodeId);
if (!node) {
qDebug() << "Node id not found:" << nodeId;
return false;
@ -1449,7 +1434,7 @@ bool Document::isNodeEditable(dust3d::Uuid nodeId) const
bool Document::isEdgeEditable(dust3d::Uuid edgeId) const
{
const SkeletonEdge *edge = findEdge(edgeId);
const SkeletonEdge* edge = findEdge(edgeId);
if (!edge) {
qDebug() << "Edge id not found:" << edgeId;
return false;
@ -1459,16 +1444,12 @@ bool Document::isEdgeEditable(dust3d::Uuid edgeId) const
bool Document::isExportReady() const
{
if (m_meshGenerator ||
m_textureGenerator ||
m_postProcessor)
if (m_meshGenerator || m_textureGenerator || m_postProcessor)
return false;
if (m_isResultMeshObsolete ||
m_isTextureObsolete ||
m_isPostProcessResultObsolete)
if (m_isResultMeshObsolete || m_isTextureObsolete || m_isPostProcessResultObsolete)
return false;
return true;
}
@ -1485,17 +1466,17 @@ void Document::addMaterial(dust3d::Uuid materialId, QString name, std::vector<Ma
qDebug() << "Material already exist:" << materialId;
return;
}
dust3d::Uuid newMaterialId = materialId;
auto &material = materialMap[newMaterialId];
auto& material = materialMap[newMaterialId];
material.id = newMaterialId;
material.name = name;
material.layers = layers;
material.dirty = true;
materialIdList.push_back(newMaterialId);
emit materialAdded(newMaterialId);
emit materialListChanged();
emit optionsChanged();
@ -1510,7 +1491,7 @@ void Document::removeMaterial(dust3d::Uuid materialId)
}
materialIdList.erase(std::remove(materialIdList.begin(), materialIdList.end(), materialId), materialIdList.end());
materialMap.erase(findMaterialResult);
emit materialListChanged();
emit materialRemoved(materialId);
emit optionsChanged();
@ -1539,7 +1520,7 @@ void Document::renameMaterial(dust3d::Uuid materialId, QString name)
}
if (findMaterialResult->second.name == name)
return;
findMaterialResult->second.name = name;
emit materialNameChanged(materialId);
emit materialListChanged();
@ -1552,10 +1533,10 @@ void Document::generateMaterialPreviews()
return;
}
QThread *thread = new QThread;
QThread* thread = new QThread;
m_materialPreviewsGenerator = new MaterialPreviewsGenerator();
bool hasDirtyMaterial = false;
for (auto &materialIt: materialMap) {
for (auto& materialIt : materialMap) {
if (!materialIt.second.dirty)
continue;
m_materialPreviewsGenerator->addMaterial(materialIt.first, materialIt.second.layers);
@ -1568,9 +1549,9 @@ void Document::generateMaterialPreviews()
delete thread;
return;
}
qDebug() << "Material previews generating..";
m_materialPreviewsGenerator->moveToThread(thread);
connect(thread, &QThread::started, m_materialPreviewsGenerator, &MaterialPreviewsGenerator::process);
connect(m_materialPreviewsGenerator, &MaterialPreviewsGenerator::finished, this, &Document::materialPreviewsReady);
@ -1581,10 +1562,10 @@ void Document::generateMaterialPreviews()
void Document::materialPreviewsReady()
{
for (const auto &materialId: m_materialPreviewsGenerator->generatedPreviewMaterialIds()) {
for (const auto& materialId : m_materialPreviewsGenerator->generatedPreviewMaterialIds()) {
auto material = materialMap.find(materialId);
if (material != materialMap.end()) {
ModelMesh *resultPartPreviewMesh = m_materialPreviewsGenerator->takePreview(materialId);
ModelMesh* resultPartPreviewMesh = m_materialPreviewsGenerator->takePreview(materialId);
material->second.updatePreviewMesh(resultPartPreviewMesh);
emit materialPreviewChanged(materialId);
}
@ -1592,9 +1573,9 @@ void Document::materialPreviewsReady()
delete m_materialPreviewsGenerator;
m_materialPreviewsGenerator = nullptr;
qDebug() << "Material previews generation done";
generateMaterialPreviews();
}
@ -1619,18 +1600,18 @@ void Document::copyNodes(std::set<dust3d::Uuid> nodeIdSet) const
toSnapshot(&snapshot, nodeIdSet, DocumentToSnapshotFor::Nodes);
std::string snapshotXml;
dust3d::saveSnapshotToXmlString(snapshot, snapshotXml);
QClipboard *clipboard = QApplication::clipboard();
QClipboard* clipboard = QApplication::clipboard();
clipboard->setText(snapshotXml.c_str());
}
void Document::collectCutFaceList(std::vector<QString> &cutFaces) const
void Document::collectCutFaceList(std::vector<QString>& cutFaces) const
{
cutFaces.clear();
std::vector<dust3d::Uuid> cutFacePartIdList;
std::set<dust3d::Uuid> cutFacePartIds;
for (const auto &it: partMap) {
for (const auto& it : partMap) {
if (dust3d::PartTarget::CutFace == it.second.target) {
if (cutFacePartIds.find(it.first) != cutFacePartIds.end())
continue;
@ -1644,16 +1625,16 @@ void Document::collectCutFaceList(std::vector<QString> &cutFaces) const
cutFacePartIdList.push_back(it.second.cutFaceLinkedId);
}
}
// Sort cut face by center.x of front view
std::map<dust3d::Uuid, float> centerOffsetMap;
for (const auto &partId: cutFacePartIdList) {
const SkeletonPart *part = findPart(partId);
for (const auto& partId : cutFacePartIdList) {
const SkeletonPart* part = findPart(partId);
if (nullptr == part)
continue;
float offsetSum = 0;
for (const auto &nodeId: part->nodeIds) {
const SkeletonNode *node = findNode(nodeId);
for (const auto& nodeId : part->nodeIds) {
const SkeletonNode* node = findNode(nodeId);
if (nullptr == node)
continue;
offsetSum += node->getX();
@ -1663,16 +1644,16 @@ void Document::collectCutFaceList(std::vector<QString> &cutFaces) const
centerOffsetMap[partId] = offsetSum / part->nodeIds.size();
}
std::sort(cutFacePartIdList.begin(), cutFacePartIdList.end(),
[&](const dust3d::Uuid &firstPartId, const dust3d::Uuid &secondPartId) {
return centerOffsetMap[firstPartId] < centerOffsetMap[secondPartId];
});
[&](const dust3d::Uuid& firstPartId, const dust3d::Uuid& secondPartId) {
return centerOffsetMap[firstPartId] < centerOffsetMap[secondPartId];
});
size_t cutFaceTypeCount = (size_t)dust3d::CutFace::UserDefined;
for (size_t i = 0; i < (size_t)cutFaceTypeCount; ++i) {
dust3d::CutFace cutFace = (dust3d::CutFace)i;
cutFaces.push_back(QString(dust3d::CutFaceToString(cutFace).c_str()));
}
for (const auto &it: cutFacePartIdList)
for (const auto& it : cutFacePartIdList)
cutFaces.push_back(QString(it.toString().c_str()));
}

View File

@ -1,38 +1,36 @@
#ifndef DUST3D_APPLICATION_DOCUMENT_H_
#define DUST3D_APPLICATION_DOCUMENT_H_
#include <QObject>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <QImage>
#include <cmath>
#include <algorithm>
#include <QPolygon>
#include <dust3d/base/uuid.h>
#include <dust3d/base/snapshot.h>
#include <dust3d/base/texture_type.h>
#include <dust3d/base/combine_mode.h>
#include "material_layer.h"
#include "model_mesh.h"
#include "monochrome_mesh.h"
#include "theme.h"
#include "skeleton_document.h"
#include "material_layer.h"
#include "theme.h"
#include <QImage>
#include <QObject>
#include <QPolygon>
#include <algorithm>
#include <cmath>
#include <deque>
#include <dust3d/base/combine_mode.h>
#include <dust3d/base/snapshot.h>
#include <dust3d/base/texture_type.h>
#include <dust3d/base/uuid.h>
#include <map>
#include <set>
#include <vector>
class MaterialPreviewsGenerator;
class TextureGenerator;
class MeshGenerator;
class MeshResultPostProcessor;
class HistoryItem
{
class HistoryItem {
public:
dust3d::Snapshot snapshot;
};
class Material
{
class Material {
public:
Material()
{
@ -45,31 +43,30 @@ public:
QString name;
bool dirty = true;
std::vector<MaterialLayer> layers;
void updatePreviewMesh(ModelMesh *previewMesh)
void updatePreviewMesh(ModelMesh* previewMesh)
{
delete m_previewMesh;
m_previewMesh = previewMesh;
}
ModelMesh *takePreviewMesh() const
ModelMesh* takePreviewMesh() const
{
if (nullptr == m_previewMesh)
return nullptr;
return new ModelMesh(*m_previewMesh);
}
private:
Q_DISABLE_COPY(Material);
ModelMesh *m_previewMesh = nullptr;
ModelMesh* m_previewMesh = nullptr;
};
enum class DocumentToSnapshotFor
{
enum class DocumentToSnapshotFor {
Document = 0,
Nodes,
Materials
};
class Document : public SkeletonDocument
{
class Document : public SkeletonDocument {
Q_OBJECT
signals:
void nodeCutRotationChanged(dust3d::Uuid nodeId);
@ -121,26 +118,28 @@ signals:
void postProcessing();
void textureGenerating();
void textureChanged();
public: // need initialize
QImage *textureImage = nullptr;
QByteArray *textureImageByteArray = nullptr;
QImage *textureNormalImage = nullptr;
QByteArray *textureNormalImageByteArray = nullptr;
QImage *textureMetalnessImage = nullptr;
QByteArray *textureMetalnessImageByteArray = nullptr;
QImage *textureRoughnessImage = nullptr;
QByteArray *textureRoughnessImageByteArray = nullptr;
QImage *textureAmbientOcclusionImage = nullptr;
QByteArray *textureAmbientOcclusionImageByteArray = nullptr;
QImage* textureImage = nullptr;
QByteArray* textureImageByteArray = nullptr;
QImage* textureNormalImage = nullptr;
QByteArray* textureNormalImageByteArray = nullptr;
QImage* textureMetalnessImage = nullptr;
QByteArray* textureMetalnessImageByteArray = nullptr;
QImage* textureRoughnessImage = nullptr;
QByteArray* textureRoughnessImageByteArray = nullptr;
QImage* textureAmbientOcclusionImage = nullptr;
QByteArray* textureAmbientOcclusionImageByteArray = nullptr;
bool weldEnabled = true;
float brushMetalness = ModelMesh::m_defaultMetalness;
float brushRoughness = ModelMesh::m_defaultRoughness;
public:
Document();
~Document();
std::map<dust3d::Uuid, Material> materialMap;
std::vector<dust3d::Uuid> materialIdList;
bool undoable() const override;
bool redoable() const override;
bool hasPastableNodesInClipboard() const override;
@ -148,39 +147,38 @@ public:
bool isNodeEditable(dust3d::Uuid nodeId) const override;
bool isEdgeEditable(dust3d::Uuid edgeId) const override;
void copyNodes(std::set<dust3d::Uuid> nodeIdSet) const override;
void toSnapshot(dust3d::Snapshot *snapshot, const std::set<dust3d::Uuid> &limitNodeIds=std::set<dust3d::Uuid>(),
DocumentToSnapshotFor forWhat=DocumentToSnapshotFor::Document,
const std::set<dust3d::Uuid> &limitMaterialIds=std::set<dust3d::Uuid>()) const;
void fromSnapshot(const dust3d::Snapshot &snapshot);
enum class SnapshotSource
{
void toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uuid>& limitNodeIds = std::set<dust3d::Uuid>(),
DocumentToSnapshotFor forWhat = DocumentToSnapshotFor::Document,
const std::set<dust3d::Uuid>& limitMaterialIds = std::set<dust3d::Uuid>()) const;
void fromSnapshot(const dust3d::Snapshot& snapshot);
enum class SnapshotSource {
Unknown,
Paste,
Import
};
void addFromSnapshot(const dust3d::Snapshot &snapshot, enum SnapshotSource source=SnapshotSource::Paste);
const Material *findMaterial(dust3d::Uuid materialId) const;
ModelMesh *takeResultMesh();
MonochromeMesh *takeWireframeMesh();
ModelMesh *takePaintedMesh();
void addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSource source = SnapshotSource::Paste);
const Material* findMaterial(dust3d::Uuid materialId) const;
ModelMesh* takeResultMesh();
MonochromeMesh* takeWireframeMesh();
ModelMesh* takePaintedMesh();
bool isMeshGenerationSucceed();
ModelMesh *takeResultTextureMesh();
ModelMesh *takeResultRigWeightMesh();
void updateTurnaround(const QImage &image);
ModelMesh* takeResultTextureMesh();
ModelMesh* takeResultRigWeightMesh();
void updateTurnaround(const QImage& image);
void clearTurnaround();
void updateTextureImage(QImage *image);
void updateTextureNormalImage(QImage *image);
void updateTextureMetalnessImage(QImage *image);
void updateTextureRoughnessImage(QImage *image);
void updateTextureAmbientOcclusionImage(QImage *image);
void updateTextureImage(QImage* image);
void updateTextureNormalImage(QImage* image);
void updateTextureMetalnessImage(QImage* image);
void updateTextureRoughnessImage(QImage* image);
void updateTextureAmbientOcclusionImage(QImage* image);
bool hasPastableMaterialsInClipboard() const;
const dust3d::Object &currentPostProcessedObject() const;
const dust3d::Object& currentPostProcessedObject() const;
bool isExportReady() const;
bool isPostProcessResultObsolete() const;
bool isMeshGenerating() const;
bool isPostProcessing() const;
bool isTextureGenerating() const;
void collectCutFaceList(std::vector<QString> &cutFaces) const;
void collectCutFaceList(std::vector<QString>& cutFaces) const;
public slots:
void undo() override;
void redo() override;
@ -233,30 +231,32 @@ public slots:
void removeMaterial(dust3d::Uuid materialId);
void setMaterialLayers(dust3d::Uuid materialId, std::vector<MaterialLayer> layers);
void renameMaterial(dust3d::Uuid materialId, QString name);
private:
void resolveSnapshotBoundingBox(const dust3d::Snapshot &snapshot, QRectF *mainProfile, QRectF *sideProfile);
void resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile);
void settleOrigin();
void checkExportReadyState();
bool m_isResultMeshObsolete = false;
MeshGenerator *m_meshGenerator = nullptr;
ModelMesh *m_resultMesh = nullptr;
MeshGenerator* m_meshGenerator = nullptr;
ModelMesh* m_resultMesh = nullptr;
std::unique_ptr<MonochromeMesh> m_wireframeMesh;
bool m_isMeshGenerationSucceed = true;
int m_batchChangeRefCount = 0;
dust3d::Object *m_currentObject = nullptr;
dust3d::Object* m_currentObject = nullptr;
bool m_isTextureObsolete = false;
TextureGenerator *m_textureGenerator = nullptr;
TextureGenerator* m_textureGenerator = nullptr;
bool m_isPostProcessResultObsolete = false;
MeshResultPostProcessor *m_postProcessor = nullptr;
dust3d::Object *m_postProcessedObject = new dust3d::Object;
ModelMesh *m_resultTextureMesh = nullptr;
MeshResultPostProcessor* m_postProcessor = nullptr;
dust3d::Object* m_postProcessedObject = new dust3d::Object;
ModelMesh* m_resultTextureMesh = nullptr;
unsigned long long m_textureImageUpdateVersion = 0;
bool m_smoothNormal = false;
MaterialPreviewsGenerator *m_materialPreviewsGenerator = nullptr;
MaterialPreviewsGenerator* m_materialPreviewsGenerator = nullptr;
quint64 m_meshGenerationId = 0;
quint64 m_nextMeshGenerationId = 0;
void *m_generatedCacheContext = nullptr;
void* m_generatedCacheContext = nullptr;
private:
static unsigned long m_maxSnapshot;
std::deque<HistoryItem> m_undoItems;

View File

@ -1,17 +1,17 @@
#include <set>
#include "document_saver.h"
#include "image_forever.h"
#include <QGuiApplication>
#include <QtCore/qbuffer.h>
#include <dust3d/base/ds3_file.h>
#include <dust3d/base/snapshot_xml.h>
#include "document_saver.h"
#include "image_forever.h"
#include <set>
DocumentSaver::DocumentSaver(const QString *filename,
dust3d::Snapshot *snapshot,
QByteArray *turnaroundPngByteArray) :
m_filename(filename),
m_snapshot(snapshot),
m_turnaroundPngByteArray(turnaroundPngByteArray)
DocumentSaver::DocumentSaver(const QString* filename,
dust3d::Snapshot* snapshot,
QByteArray* turnaroundPngByteArray)
: m_filename(filename)
, m_snapshot(snapshot)
, m_turnaroundPngByteArray(turnaroundPngByteArray)
{
}
@ -29,12 +29,12 @@ void DocumentSaver::process()
emit finished();
}
void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot *snapshot,
std::set<dust3d::Uuid> &imageIds)
void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot* snapshot,
std::set<dust3d::Uuid>& imageIds)
{
for (const auto &material: snapshot->materials) {
for (auto &layer: material.second) {
for (auto &mapItem: layer.second) {
for (const auto& material : snapshot->materials) {
for (auto& layer : material.second) {
for (auto& mapItem : layer.second) {
auto findImageIdString = mapItem.find("linkData");
if (findImageIdString == mapItem.end())
continue;
@ -45,12 +45,12 @@ void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot *snapshot,
}
}
bool DocumentSaver::save(const QString *filename,
dust3d::Snapshot *snapshot,
const QByteArray *turnaroundPngByteArray)
bool DocumentSaver::save(const QString* filename,
dust3d::Snapshot* snapshot,
const QByteArray* turnaroundPngByteArray)
{
dust3d::Ds3FileWriter ds3Writer;
{
std::string modelXml;
saveSnapshotToXmlString(*snapshot, modelXml);
@ -58,20 +58,20 @@ bool DocumentSaver::save(const QString *filename,
ds3Writer.add("model.xml", "model", modelXml.c_str(), modelXml.size());
}
}
if (nullptr != turnaroundPngByteArray && turnaroundPngByteArray->size() > 0)
ds3Writer.add("canvas.png", "asset", turnaroundPngByteArray->data(), turnaroundPngByteArray->size());
std::set<dust3d::Uuid> imageIds;
collectUsedResourceIds(snapshot, imageIds);
for (const auto &imageId: imageIds) {
const QByteArray *pngByteArray = ImageForever::getPngByteArray(imageId);
for (const auto& imageId : imageIds) {
const QByteArray* pngByteArray = ImageForever::getPngByteArray(imageId);
if (nullptr == pngByteArray)
continue;
if (pngByteArray->size() > 0)
ds3Writer.add("images/" + imageId.toString() + ".png", "asset", pngByteArray->data(), pngByteArray->size());
}
return ds3Writer.save(filename->toUtf8().constData());
}

View File

@ -1,35 +1,35 @@
#ifndef DUST3D_APPLICATION_DOCUMENT_SAVER_H_
#define DUST3D_APPLICATION_DOCUMENT_SAVER_H_
#include <QString>
#include <QObject>
#include <QByteArray>
#include <QObject>
#include <QString>
#include <dust3d/base/snapshot.h>
#include <dust3d/base/uuid.h>
#include <map>
#include <set>
#include <dust3d/base/uuid.h>
#include <dust3d/base/snapshot.h>
class DocumentSaver : public QObject
{
class DocumentSaver : public QObject {
Q_OBJECT
public:
DocumentSaver(const QString *filename,
dust3d::Snapshot *snapshot,
QByteArray *turnaroundPngByteArray);
DocumentSaver(const QString* filename,
dust3d::Snapshot* snapshot,
QByteArray* turnaroundPngByteArray);
~DocumentSaver();
static bool save(const QString *filename,
dust3d::Snapshot *snapshot,
const QByteArray *turnaroundPngByteArray);
static void collectUsedResourceIds(const dust3d::Snapshot *snapshot,
std::set<dust3d::Uuid> &imageIds);
static bool save(const QString* filename,
dust3d::Snapshot* snapshot,
const QByteArray* turnaroundPngByteArray);
static void collectUsedResourceIds(const dust3d::Snapshot* snapshot,
std::set<dust3d::Uuid>& imageIds);
signals:
void finished();
public slots:
void process();
private:
const QString *m_filename = nullptr;
dust3d::Snapshot *m_snapshot = nullptr;
QByteArray *m_turnaroundPngByteArray = nullptr;
const QString* m_filename = nullptr;
dust3d::Snapshot* m_snapshot = nullptr;
QByteArray* m_turnaroundPngByteArray = nullptr;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,21 @@
#ifndef DUST3D_APPLICATION_DOCUMENT_WINDOW_H_
#define DUST3D_APPLICATION_DOCUMENT_WINDOW_H_
#include <memory>
#include <QMainWindow>
#include <QShowEvent>
#include <QPushButton>
#include <QString>
#include <QMenu>
#include <QAction>
#include <map>
#include <QStringList>
#include <QLabel>
#include <QShortcut>
#include "model_widget.h"
#include "component_preview_images_decorator.h"
#include "graphics_container_widget.h"
#include "mesh_preview_images_generator.h"
#include "component_preview_images_decorator.h"
#include "model_widget.h"
#include <QAction>
#include <QLabel>
#include <QMainWindow>
#include <QMenu>
#include <QPushButton>
#include <QShortcut>
#include <QShowEvent>
#include <QString>
#include <QStringList>
#include <map>
#include <memory>
class Document;
class SkeletonGraphicsWidget;
@ -23,38 +23,39 @@ class PartManageWidget;
class ToolbarButton;
class SpinnableToolbarIcon;
class DocumentWindow : public QMainWindow
{
class DocumentWindow : public QMainWindow {
Q_OBJECT
signals:
void initialized();
void uninialized();
void waitingExportFinished(const QString &filename, bool isSuccessful);
void waitingExportFinished(const QString& filename, bool isSuccessful);
void workingStatusChanged(bool isWorking);
public:
DocumentWindow();
~DocumentWindow();
Document *document();
ModelWidget *modelWidget();
Document* document();
ModelWidget* modelWidget();
bool isWorking();
static DocumentWindow *createDocumentWindow();
static const std::map<DocumentWindow *, dust3d::Uuid> &documentWindows();
static DocumentWindow* createDocumentWindow();
static const std::map<DocumentWindow*, dust3d::Uuid>& documentWindows();
static void showAcknowlegements();
static void showContributors();
static void showSupporters();
static void showAbout();
static size_t total();
protected:
void showEvent(QShowEvent *event);
void closeEvent(QCloseEvent *event);
void mousePressEvent(QMouseEvent *event);
void showEvent(QShowEvent* event);
void closeEvent(QCloseEvent* event);
void mousePressEvent(QMouseEvent* event);
public slots:
void changeTurnaround();
void save();
void saveTo(const QString &saveAsFilename);
void saveTo(const QString& saveAsFilename);
void open();
void openExample(const QString &modelName);
void openPathAs(const QString &path, const QString &asName);
void openExample(const QString& modelName);
void openPathAs(const QString& path, const QString& asName);
void exportObjResult();
void exportGlbResult();
void exportFbxResult();
@ -76,13 +77,13 @@ public slots:
void updateYlockButtonState();
void updateZlockButtonState();
void updateRadiusLockButtonState();
void registerDialog(QWidget *widget);
void unregisterDialog(QWidget *widget);
void setExportWaitingList(const QStringList &filenames);
void registerDialog(QWidget* widget);
void unregisterDialog(QWidget* widget);
void setExportWaitingList(const QStringList& filenames);
void checkExportWaitingList();
void exportObjToFilename(const QString &filename);
void exportFbxToFilename(const QString &filename);
void exportGlbToFilename(const QString &filename);
void exportObjToFilename(const QString& filename);
void exportFbxToFilename(const QString& filename);
void exportGlbToFilename(const QString& filename);
void toggleRotation();
void generateComponentPreviewImages();
void componentPreviewImagesReady();
@ -92,88 +93,88 @@ public slots:
void openRecentFile();
void updateRecentFileActions();
void toggleRenderColor();
private:
void setCurrentFilename(const QString &filename);
void setCurrentFilename(const QString& filename);
void updateTitle();
void initializeShortcuts();
void initializeToolShortcuts(SkeletonGraphicsWidget *graphicsWidget);
void initializeCanvasShortcuts(SkeletonGraphicsWidget *graphicsWidget);
QShortcut *createShortcut(QKeySequence key);
QString strippedName(const QString &fullFileName);
bool openFiles(const QStringList &pathList);
void initializeToolShortcuts(SkeletonGraphicsWidget* graphicsWidget);
void initializeCanvasShortcuts(SkeletonGraphicsWidget* graphicsWidget);
QShortcut* createShortcut(QKeySequence key);
QString strippedName(const QString& fullFileName);
bool openFiles(const QStringList& pathList);
Document *m_document = nullptr;
Document* m_document = nullptr;
bool m_firstShow = true;
bool m_documentSaved = true;
std::vector<QWidget *> m_dialogs;
std::vector<QWidget*> m_dialogs;
bool m_isLastMeshGenerationSucceed = true;
quint64 m_currentUpdatedMeshId = 0;
QStringList m_waitingForExportToFilenames;
QString m_currentFilename;
ModelWidget *m_modelRenderWidget = nullptr;
SkeletonGraphicsWidget *m_canvasGraphicsWidget = nullptr;
GraphicsContainerWidget *m_graphicsContainerWidget = nullptr;
QMenu *m_fileMenu = nullptr;
QAction *m_newWindowAction = nullptr;
QAction *m_newDocumentAction = nullptr;
QAction *m_openAction = nullptr;
QMenu *m_openExampleMenu = nullptr;
QAction *m_saveAction = nullptr;
QAction *m_saveAsAction = nullptr;
QAction *m_saveAllAction = nullptr;
QAction *m_changeTurnaroundAction = nullptr;
std::vector<QAction *> m_recentFileActions;
QAction *m_recentFileSeparatorAction = nullptr;
QAction *m_quitAction = nullptr;
QAction *m_exportAsObjAction = nullptr;
QAction *m_exportAsGlbAction = nullptr;
QAction *m_exportAsFbxAction = nullptr;
QMenu *m_viewMenu = nullptr;
QAction *m_toggleWireframeAction = nullptr;
QAction *m_toggleRotationAction = nullptr;
QAction *m_toggleColorAction = nullptr;
QString m_currentFilename;
ModelWidget* m_modelRenderWidget = nullptr;
SkeletonGraphicsWidget* m_canvasGraphicsWidget = nullptr;
GraphicsContainerWidget* m_graphicsContainerWidget = nullptr;
QMenu* m_fileMenu = nullptr;
QAction* m_newWindowAction = nullptr;
QAction* m_newDocumentAction = nullptr;
QAction* m_openAction = nullptr;
QMenu* m_openExampleMenu = nullptr;
QAction* m_saveAction = nullptr;
QAction* m_saveAsAction = nullptr;
QAction* m_saveAllAction = nullptr;
QAction* m_changeTurnaroundAction = nullptr;
std::vector<QAction*> m_recentFileActions;
QAction* m_recentFileSeparatorAction = nullptr;
QAction* m_quitAction = nullptr;
QAction* m_exportAsObjAction = nullptr;
QAction* m_exportAsGlbAction = nullptr;
QAction* m_exportAsFbxAction = nullptr;
QMenu* m_viewMenu = nullptr;
QAction* m_toggleWireframeAction = nullptr;
QAction* m_toggleRotationAction = nullptr;
QAction* m_toggleColorAction = nullptr;
bool m_modelRemoveColor = false;
QMenu *m_windowMenu = nullptr;
QAction *m_showPartsListAction = nullptr;
QAction *m_showDebugDialogAction = nullptr;
QAction *m_showMaterialsAction = nullptr;
QMenu *m_helpMenu = nullptr;
QAction *m_gotoHomepageAction = nullptr;
QAction *m_viewSourceAction = nullptr;
QAction *m_aboutAction = nullptr;
QAction *m_checkForUpdatesAction = nullptr;
QAction *m_reportIssuesAction = nullptr;
QAction *m_seeContributorsAction = nullptr;
QAction *m_seeSupportersAction = nullptr;
QAction *m_seeAcknowlegementsAction = nullptr;
QAction *m_seeReferenceGuideAction = nullptr;
ToolbarButton *m_xLockButton = nullptr;
ToolbarButton *m_yLockButton = nullptr;
ToolbarButton *m_zLockButton = nullptr;
ToolbarButton *m_radiusLockButton = nullptr;
QMenu* m_windowMenu = nullptr;
QAction* m_showPartsListAction = nullptr;
QAction* m_showDebugDialogAction = nullptr;
QAction* m_showMaterialsAction = nullptr;
QMenu* m_helpMenu = nullptr;
QAction* m_gotoHomepageAction = nullptr;
QAction* m_viewSourceAction = nullptr;
QAction* m_aboutAction = nullptr;
QAction* m_checkForUpdatesAction = nullptr;
QAction* m_reportIssuesAction = nullptr;
QAction* m_seeContributorsAction = nullptr;
QAction* m_seeSupportersAction = nullptr;
QAction* m_seeAcknowlegementsAction = nullptr;
QAction* m_seeReferenceGuideAction = nullptr;
ToolbarButton* m_xLockButton = nullptr;
ToolbarButton* m_yLockButton = nullptr;
ToolbarButton* m_zLockButton = nullptr;
ToolbarButton* m_radiusLockButton = nullptr;
QMetaObject::Connection m_partListDockerVisibleSwitchConnection;
MeshPreviewImagesGenerator *m_componentPreviewImagesGenerator = nullptr;
MeshPreviewImagesGenerator* m_componentPreviewImagesGenerator = nullptr;
bool m_isComponentPreviewImagesObsolete = false;
std::unique_ptr<ComponentPreviewImagesDecorator> m_componentPreviewImagesDecorator;
bool m_isComponentPreviewImageDecorationsObsolete = false;
PartManageWidget *m_partManageWidget = nullptr;
SpinnableToolbarIcon *m_inprogressIndicator = nullptr;
std::map<QKeySequence, QShortcut *> m_shortcutMap;
PartManageWidget* m_partManageWidget = nullptr;
SpinnableToolbarIcon* m_inprogressIndicator = nullptr;
std::map<QKeySequence, QShortcut*> m_shortcutMap;
};
#endif

View File

@ -1,13 +1,13 @@
#include "fbx_file.h"
#include "document.h"
#include "version.h"
#include <QByteArray>
#include <QDateTime>
#include <QFileInfo>
#include <QtCore/qbuffer.h>
#include <QtMath>
#include <fbxnode.h>
#include <fbxproperty.h>
#include <QDateTime>
#include <QtMath>
#include <QtCore/qbuffer.h>
#include <QByteArray>
#include <QFileInfo>
#include "fbx_file.h"
#include "version.h"
#include "document.h"
using namespace fbx;
@ -27,9 +27,9 @@ void FbxFileWriter::createFbxHeader()
headerExtension.addPropertyNode("EncryptionType", (int32_t)0);
{
auto currentDateTime = QDateTime::currentDateTime();
const auto &currentDate = currentDateTime.date();
const auto &currentTime = currentDateTime.time();
const auto& currentDate = currentDateTime.date();
const auto& currentTime = currentDateTime.time();
FBXNode creationTimeStamp("CreationTimeStamp");
creationTimeStamp.addPropertyNode("Version", (int32_t)1000);
creationTimeStamp.addPropertyNode("Year", (int32_t)currentDate.year());
@ -45,7 +45,7 @@ void FbxFileWriter::createFbxHeader()
headerExtension.addPropertyNode("Creator", APP_NAME " " APP_HUMAN_VER);
{
FBXNode sceneInfo("SceneInfo");
sceneInfo.addProperty(std::vector<uint8_t>({'G','l','o','b','a','l','I','n','f','o',0,1,'S','c','e','n','e','I','n','f','o'}), 'S');
sceneInfo.addProperty(std::vector<uint8_t>({ 'G', 'l', 'o', 'b', 'a', 'l', 'I', 'n', 'f', 'o', 0, 1, 'S', 'c', 'e', 'n', 'e', 'I', 'n', 'f', 'o' }), 'S');
sceneInfo.addProperty("UserData");
sceneInfo.addPropertyNode("Type", "UserData");
sceneInfo.addPropertyNode("Version", 100);
@ -185,7 +185,7 @@ void FbxFileWriter::createFbxHeader()
headerExtension.addChild(sceneInfo);
headerExtension.addChild(FBXNode());
}
m_fbxDocument.nodes.push_back(headerExtension);
}
@ -198,7 +198,7 @@ void FbxFileWriter::createCreationTime()
void FbxFileWriter::createFileId()
{
std::vector<uint8_t> fileIdBytes = {40, (uint8_t)-77, 42, (uint8_t)-21, (uint8_t)-74, 36, (uint8_t)-52, (uint8_t)-62, (uint8_t)-65, (uint8_t)-56, (uint8_t)-80, 42, (uint8_t)-87, 43, (uint8_t)-4, (uint8_t)-15};
std::vector<uint8_t> fileIdBytes = { 40, (uint8_t)-77, 42, (uint8_t)-21, (uint8_t)-74, 36, (uint8_t)-52, (uint8_t)-62, (uint8_t)-65, (uint8_t)-56, (uint8_t)-80, 42, (uint8_t)-87, 43, (uint8_t)-4, (uint8_t)-15 };
FBXNode fileId("FileId");
fileId.addProperty(fileIdBytes, 'R');
m_fbxDocument.nodes.push_back(fileId);
@ -415,13 +415,13 @@ void FbxFileWriter::createReferences()
}
void FbxFileWriter::createDefinitions(size_t deformerCount,
size_t textureCount,
size_t videoCount,
bool hasAnimtion,
size_t animationStackCount,
size_t animationLayerCount,
size_t animationCurveNodeCount,
size_t animationCurveCount)
size_t textureCount,
size_t videoCount,
bool hasAnimtion,
size_t animationStackCount,
size_t animationLayerCount,
size_t animationCurveNodeCount,
size_t animationCurveCount)
{
FBXNode definitions("Definitions");
definitions.addPropertyNode("Version", (int32_t)100);
@ -2198,15 +2198,15 @@ void FbxFileWriter::createDefinitions(size_t deformerCount,
m_fbxDocument.nodes.push_back(definitions);
}
FbxFileWriter::FbxFileWriter(dust3d::Object &object,
const QString &filename,
QImage *textureImage,
QImage *normalImage,
QImage *metalnessImage,
QImage *roughnessImage,
QImage *ambientOcclusionImage) :
m_filename(filename),
m_baseName(QFileInfo(m_filename).baseName())
FbxFileWriter::FbxFileWriter(dust3d::Object& object,
const QString& filename,
QImage* textureImage,
QImage* normalImage,
QImage* metalnessImage,
QImage* roughnessImage,
QImage* ambientOcclusionImage)
: m_filename(filename)
, m_baseName(QFileInfo(m_filename).baseName())
{
createFbxHeader();
createFileId();
@ -2215,24 +2215,24 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
createGlobalSettings();
createDocuments();
createReferences();
FBXNode connections("Connections");
size_t deformerCount = 0;
FBXNode geometry("Geometry");
int64_t geometryId = m_next64Id++;
geometry.addProperty(geometryId);
geometry.addProperty(std::vector<uint8_t>({'u','n','a','m','e','d','m','e','s','h',0,1,'G','e','o','m','e','t','r','y'}), 'S');
geometry.addProperty(std::vector<uint8_t>({ 'u', 'n', 'a', 'm', 'e', 'd', 'm', 'e', 's', 'h', 0, 1, 'G', 'e', 'o', 'm', 'e', 't', 'r', 'y' }), 'S');
geometry.addProperty("Mesh");
std::vector<double> positions;
for (const auto &vertex: object.vertices) {
for (const auto& vertex : object.vertices) {
positions.push_back((double)vertex.x());
positions.push_back((double)vertex.y());
positions.push_back((double)vertex.z());
}
std::vector<int32_t> indices;
for (const auto &triangle: object.triangles) {
for (const auto& triangle : object.triangles) {
indices.push_back(triangle[0]);
indices.push_back(triangle[1]);
indices.push_back(triangle[2] ^ -1);
@ -2248,7 +2248,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
std::vector<double> normals;
for (decltype(triangleVertexNormals->size()) i = 0; i < triangleVertexNormals->size(); ++i) {
for (size_t j = 0; j < 3; ++j) {
const auto &n = (*triangleVertexNormals)[i][j];
const auto& n = (*triangleVertexNormals)[i][j];
normals.push_back((double)n.x());
normals.push_back((double)n.y());
normals.push_back((double)n.z());
@ -2269,7 +2269,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
//std::vector<int32_t> uvIndices;
for (decltype(triangleVertexUvs->size()) i = 0; i < triangleVertexUvs->size(); ++i) {
for (size_t j = 0; j < 3; ++j) {
const auto &uv = (*triangleVertexUvs)[i][j];
const auto& uv = (*triangleVertexUvs)[i][j];
uvs.push_back((double)uv.x());
uvs.push_back((double)1.0 - uv.y());
//uvIndices.push_back(uvIndices.size());
@ -2285,7 +2285,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
layerElementMaterial.addPropertyNode("Name", "");
layerElementMaterial.addPropertyNode("MappingInformationType", "AllSame");
layerElementMaterial.addPropertyNode("ReferenceInformationType", "IndexToDirect");
std::vector<int32_t> materials = {(int32_t)0};
std::vector<int32_t> materials = { (int32_t)0 };
layerElementMaterial.addPropertyNode("Materials", materials);
layerElementMaterial.addChild(FBXNode());
FBXNode layer("Layer");
@ -2323,11 +2323,11 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
geometry.addChild(layerElementUv);
geometry.addChild(layer);
geometry.addChild(FBXNode());
int64_t modelId = m_next64Id++;
FBXNode model("Model");
model.addProperty(modelId);
model.addProperty(std::vector<uint8_t>({'u','n','a','m','e','d',0,1,'M','o','d','e','l'}), 'S');
model.addProperty(std::vector<uint8_t>({ 'u', 'n', 'a', 'm', 'e', 'd', 0, 1, 'M', 'o', 'd', 'e', 'l' }), 'S');
model.addProperty("Mesh");
model.addPropertyNode("Version", (int32_t)232);
{
@ -2390,7 +2390,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
model.addPropertyNode("Shading", (bool)true);
model.addPropertyNode("Culling", "CullingOff");
model.addChild(FBXNode());
FBXNode pose("Pose");
int64_t poseId = 0;
std::vector<FBXNode> deformers;
@ -2401,12 +2401,11 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
std::vector<int64_t> nodeAttributeIds;
int64_t skinId = 0;
int64_t armatureId = 0;
if (deformerCount > 0)
{
if (deformerCount > 0) {
poseId = m_next64Id++;
pose.addProperty(poseId);
pose.addProperty(std::vector<uint8_t>({'u','n','a','m','e','d',0,1,'P','o','s','e'}), 'S');
pose.addProperty(std::vector<uint8_t>({ 'u', 'n', 'a', 'm', 'e', 'd', 0, 1, 'P', 'o', 's', 'e' }), 'S');
pose.addProperty("BindPose");
pose.addPropertyNode("Type", "BindPose");
pose.addPropertyNode("Version", (int32_t)100);
@ -2427,17 +2426,17 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
}
pose.addChild(FBXNode());
}
size_t textureCount = 0;
size_t videoCount = 0;
std::vector<FBXNode> videos;
std::vector<FBXNode> textures;
FBXNode material("Material");
int64_t materialId = m_next64Id++;
material.addProperty(materialId);
material.addProperty(std::vector<uint8_t>({'M','a','t','e','r','i','a','l',0,1,'S','t','i','n','g','r','a','y','P','B','S'}), 'S');
material.addProperty(std::vector<uint8_t>({ 'M', 'a', 't', 'e', 'r', 'i', 'a', 'l', 0, 1, 'S', 't', 'i', 'n', 'g', 'r', 'a', 'y', 'P', 'B', 'S' }), 'S');
material.addProperty("");
material.addPropertyNode("Version", (int32_t)102);
material.addPropertyNode("ShadingModel", "unknown");
@ -2696,7 +2695,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
material.addChild(properties);
}
material.addChild(FBXNode());
/*
FBXNode material("Material");
int64_t materialId = m_next64Id++;
@ -2833,11 +2832,11 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
}
material.addChild(FBXNode());
*/
FBXNode implementation("Implementation");
int64_t implementationId = m_next64Id++;
implementation.addProperty(implementationId);
implementation.addProperty(std::vector<uint8_t>({'I','m','p','l','e','m','e','n','t','a','t','i','o','n',0,1,'S','t','i','n','g','r','a','y','P','B','S','_','I','m','p','l','e','m','e','n','t','a','t','i','o','n'}), 'S');
implementation.addProperty(std::vector<uint8_t>({ 'I', 'm', 'p', 'l', 'e', 'm', 'e', 'n', 't', 'a', 't', 'i', 'o', 'n', 0, 1, 'S', 't', 'i', 'n', 'g', 'r', 'a', 'y', 'P', 'B', 'S', '_', 'I', 'm', 'p', 'l', 'e', 'm', 'e', 'n', 't', 'a', 't', 'i', 'o', 'n' }), 'S');
implementation.addProperty("");
implementation.addPropertyNode("Version", (int32_t)100);
{
@ -2896,11 +2895,11 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
implementation.addChild(properties);
}
implementation.addChild(FBXNode());
FBXNode bindingTable("BindingTable");
int64_t bindingTableId = m_next64Id++;
bindingTable.addProperty(bindingTableId);
bindingTable.addProperty(std::vector<uint8_t>({'B','i','n','d','i','n','g','T','a','b','l','e',0,1,'S','t','i','n','g','r','a','y','P','B','S','_','B','i','n','d','i','n','g','T','a','b','l','e'}), 'S');
bindingTable.addProperty(std::vector<uint8_t>({ 'B', 'i', 'n', 'd', 'i', 'n', 'g', 'T', 'a', 'b', 'l', 'e', 0, 1, 'S', 't', 'i', 'n', 'g', 'r', 'a', 'y', 'P', 'B', 'S', '_', 'B', 'i', 'n', 'd', 'i', 'n', 'g', 'T', 'a', 'b', 'l', 'e' }), 'S');
bindingTable.addProperty("");
bindingTable.addPropertyNode("Version", (int32_t)100);
{
@ -3103,8 +3102,8 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
bindingTable.addChild(entry);
}
bindingTable.addChild(FBXNode());
auto addTexture = [&](const QImage *image, const std::vector<uint8_t> &clipName, const std::vector<uint8_t> &textureName, const QString &filename, const QString &propertyName){
auto addTexture = [&](const QImage* image, const std::vector<uint8_t>& clipName, const std::vector<uint8_t>& textureName, const QString& filename, const QString& propertyName) {
FBXNode video("Video");
int64_t videoId = m_next64Id++;
video.addProperty(videoId);
@ -3136,7 +3135,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
video.addChild(FBXNode());
videos.push_back(video);
videoCount++;
FBXNode texture("Texture");
int64_t textureId = m_next64Id++;
texture.addProperty(textureId);
@ -3195,7 +3194,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
texture.addChild(FBXNode());
textures.push_back(texture);
textureCount++;
{
FBXNode p("C");
p.addProperty("OO");
@ -3214,46 +3213,46 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
};
if (nullptr != textureImage) {
addTexture(textureImage,
std::vector<uint8_t>({'V','i','d','e','o',0,1,'B','a','s','e','C','o','l','o','r'}),
std::vector<uint8_t>({'T','e','x','t','u','r','e',0,1,'B','a','s','e','C','o','l','o','r'}),
std::vector<uint8_t>({ 'V', 'i', 'd', 'e', 'o', 0, 1, 'B', 'a', 's', 'e', 'C', 'o', 'l', 'o', 'r' }),
std::vector<uint8_t>({ 'T', 'e', 'x', 't', 'u', 'r', 'e', 0, 1, 'B', 'a', 's', 'e', 'C', 'o', 'l', 'o', 'r' }),
m_baseName + "_color.png",
"Maya|TEX_color_map");
}
if (nullptr != normalImage) {
addTexture(normalImage,
std::vector<uint8_t>({'V','i','d','e','o',0,1,'N','o','r','m','a','l'}),
std::vector<uint8_t>({'T','e','x','t','u','r','e',0,1,'N','o','r','m','a','l'}),
std::vector<uint8_t>({ 'V', 'i', 'd', 'e', 'o', 0, 1, 'N', 'o', 'r', 'm', 'a', 'l' }),
std::vector<uint8_t>({ 'T', 'e', 'x', 't', 'u', 'r', 'e', 0, 1, 'N', 'o', 'r', 'm', 'a', 'l' }),
m_baseName + "_normal.png",
"Maya|TEX_normal_map");
}
if (nullptr != metalnessImage) {
addTexture(metalnessImage,
std::vector<uint8_t>({'V','i','d','e','o',0,1,'M','e','t','a','l','l','i','c'}),
std::vector<uint8_t>({'T','e','x','t','u','r','e',0,1,'M','e','t','a','l','l','i','c'}),
std::vector<uint8_t>({ 'V', 'i', 'd', 'e', 'o', 0, 1, 'M', 'e', 't', 'a', 'l', 'l', 'i', 'c' }),
std::vector<uint8_t>({ 'T', 'e', 'x', 't', 'u', 'r', 'e', 0, 1, 'M', 'e', 't', 'a', 'l', 'l', 'i', 'c' }),
m_baseName + "_metallic.png",
"Maya|TEX_metallic_map");
}
if (nullptr != roughnessImage) {
addTexture(roughnessImage,
std::vector<uint8_t>({'V','i','d','e','o',0,1,'R','o','u','g','h','n','e','s','s'}),
std::vector<uint8_t>({'T','e','x','t','u','r','e',0,1,'R','o','u','g','h','n','e','s','s'}),
std::vector<uint8_t>({ 'V', 'i', 'd', 'e', 'o', 0, 1, 'R', 'o', 'u', 'g', 'h', 'n', 'e', 's', 's' }),
std::vector<uint8_t>({ 'T', 'e', 'x', 't', 'u', 'r', 'e', 0, 1, 'R', 'o', 'u', 'g', 'h', 'n', 'e', 's', 's' }),
m_baseName + "_roughness.png",
"Maya|TEX_roughness_map");
}
if (nullptr != ambientOcclusionImage) {
addTexture(ambientOcclusionImage,
std::vector<uint8_t>({'V','i','d','e','o',0,1,'A','o'}),
std::vector<uint8_t>({'T','e','x','t','u','r','e',0,1,'A','o'}),
std::vector<uint8_t>({ 'V', 'i', 'd', 'e', 'o', 0, 1, 'A', 'o' }),
std::vector<uint8_t>({ 'T', 'e', 'x', 't', 'u', 'r', 'e', 0, 1, 'A', 'o' }),
m_baseName + "_ao.png",
"Maya|TEX_ao_map");
}
bool hasAnimation = false;
size_t animationStackCount = 0;
size_t animationLayerCount = 0;
size_t animationCurveNodeCount = 0;
size_t animationCurveCount = 0;
std::vector<FBXNode> animationStacks;
std::vector<FBXNode> animationLayers;
std::vector<FBXNode> animationCurveNodes;
@ -3263,11 +3262,11 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
textureCount, videoCount,
hasAnimation,
animationStackCount, animationLayerCount, animationCurveNodeCount, animationCurveCount);
FBXNode objects("Objects");
objects.addChild(geometry);
objects.addChild(model);
for (const auto &limbNode: limbNodes) {
for (const auto& limbNode : limbNodes) {
objects.addChild(limbNode);
}
if (deformerCount > 0)
@ -3276,38 +3275,38 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
objects.addChild(implementation);
objects.addChild(bindingTable);
if (textureCount > 0) {
for (const auto &texture: textures) {
for (const auto& texture : textures) {
objects.addChild(texture);
}
}
if (videoCount > 0) {
for (const auto &video: videos) {
for (const auto& video : videos) {
objects.addChild(video);
}
}
for (const auto &deformer: deformers) {
for (const auto& deformer : deformers) {
objects.addChild(deformer);
}
for (const auto &nodeAttribute: nodeAttributes) {
for (const auto& nodeAttribute : nodeAttributes) {
objects.addChild(nodeAttribute);
}
if (hasAnimation) {
for (const auto &animationStack: animationStacks) {
for (const auto& animationStack : animationStacks) {
objects.addChild(animationStack);
}
for (const auto &animationLayer: animationLayers) {
for (const auto& animationLayer : animationLayers) {
objects.addChild(animationLayer);
}
for (const auto &animationCurveNode: animationCurveNodes) {
for (const auto& animationCurveNode : animationCurveNodes) {
objects.addChild(animationCurveNode);
}
for (const auto &animationCurve: animationCurves) {
for (const auto& animationCurve : animationCurves) {
objects.addChild(animationCurve);
}
}
objects.addChild(FBXNode());
m_fbxDocument.nodes.push_back(objects);
{
FBXNode p("C");
p.addProperty("OO");
@ -3315,8 +3314,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
p.addProperty((int64_t)0);
connections.addChild(p);
}
if (armatureId > 0)
{
if (armatureId > 0) {
FBXNode p("C");
p.addProperty("OO");
p.addProperty(armatureId);
@ -3330,8 +3328,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
p.addProperty(modelId);
connections.addChild(p);
}
if (skinId > 0)
{
if (skinId > 0) {
FBXNode p("C");
p.addProperty("OO");
p.addProperty(skinId);
@ -3375,7 +3372,7 @@ FbxFileWriter::FbxFileWriter(dust3d::Object &object,
}
connections.addChild(FBXNode());
m_fbxDocument.nodes.push_back(connections);
createTakes();
}
@ -3394,11 +3391,11 @@ bool FbxFileWriter::save()
return true;
}
std::vector<double> FbxFileWriter::matrixToVector(const QMatrix4x4 &matrix)
std::vector<double> FbxFileWriter::matrixToVector(const QMatrix4x4& matrix)
{
std::vector<double> vec;
for (size_t col = 0; col < 4; ++col) {
const auto &line = matrix.column(col);
const auto& line = matrix.column(col);
vec.push_back(line.x());
vec.push_back(line.y());
vec.push_back(line.z());

View File

@ -1,25 +1,24 @@
#ifndef DUST3D_APPLICATION_FBX_FILE_H_
#define DUST3D_APPLICATION_FBX_FILE_H_
#include <map>
#include <QString>
#include "fbxdocument.h"
#include <QImage>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QImage>
#include <QString>
#include <dust3d/base/object.h>
#include "fbxdocument.h"
#include <map>
class FbxFileWriter : public QObject
{
class FbxFileWriter : public QObject {
Q_OBJECT
public:
FbxFileWriter(dust3d::Object &object,
const QString &filename,
QImage *textureImage=nullptr,
QImage *normalImage=nullptr,
QImage *metalnessImage=nullptr,
QImage *roughnessImage=nullptr,
QImage *ambientOcclusionImage=nullptr);
FbxFileWriter(dust3d::Object& object,
const QString& filename,
QImage* textureImage = nullptr,
QImage* normalImage = nullptr,
QImage* metalnessImage = nullptr,
QImage* roughnessImage = nullptr,
QImage* ambientOcclusionImage = nullptr);
bool save();
private:
@ -31,17 +30,17 @@ private:
void createDocuments();
void createReferences();
void createDefinitions(size_t deformerCount,
size_t textureCount=0,
size_t videoCount=0,
bool hasAnimtion=false,
size_t animationStackCount=0,
size_t animationLayerCount=0,
size_t animationCurveNodeCount=0,
size_t animationCurveCount=0);
size_t textureCount = 0,
size_t videoCount = 0,
bool hasAnimtion = false,
size_t animationStackCount = 0,
size_t animationLayerCount = 0,
size_t animationCurveNodeCount = 0,
size_t animationCurveCount = 0);
void createTakes();
std::vector<double> matrixToVector(const QMatrix4x4 &matrix);
std::vector<double> matrixToVector(const QMatrix4x4& matrix);
int64_t secondsToKtime(double seconds);
int64_t m_next64Id = 612150000;
QString m_filename;
QString m_baseName;
@ -51,4 +50,3 @@ private:
};
#endif

View File

@ -1,11 +1,11 @@
#include <QtWidgets>
#include "float_number_widget.h"
#include "theme.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "theme.h"
#include "float_number_widget.h"
#include <QtWidgets>
FloatNumberWidget::FloatNumberWidget(QWidget *parent, bool singleLine) :
QWidget(parent)
FloatNumberWidget::FloatNumberWidget(QWidget* parent, bool singleLine)
: QWidget(parent)
{
m_slider = new QSlider(Qt::Horizontal, this);
m_slider->setRange(0, 100);
@ -19,8 +19,8 @@ FloatNumberWidget::FloatNumberWidget(QWidget *parent, bool singleLine) :
updateValueLabel(fvalue);
emit valueChanged(fvalue);
});
QBoxLayout *layout = nullptr;
QBoxLayout* layout = nullptr;
if (singleLine) {
layout = new QHBoxLayout(this);
layout->setMargin(2);
@ -48,7 +48,7 @@ void FloatNumberWidget::updateValueLabel(float value)
m_label->setText(m_itemName + ": " + valueString);
}
void FloatNumberWidget::setItemName(const QString &name)
void FloatNumberWidget::setItemName(const QString& name)
{
m_itemName = name;
updateValueLabel(value());

View File

@ -6,14 +6,13 @@
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QSlider)
class FloatNumberWidget : public QWidget
{
class FloatNumberWidget : public QWidget {
Q_OBJECT
public:
explicit FloatNumberWidget(QWidget *parent=nullptr, bool singleLine=true);
explicit FloatNumberWidget(QWidget* parent = nullptr, bool singleLine = true);
void setRange(float min, float max);
float value() const;
void setItemName(const QString &name);
void setItemName(const QString& name);
void setSliderFixedWidth(float width);
public slots:
@ -23,13 +22,13 @@ public slots:
signals:
void valueChanged(float value);
private:
void updateValueLabel(float value);
private:
QLabel *m_label = nullptr;
QSlider *m_slider = nullptr;
QLabel* m_label = nullptr;
QSlider* m_slider = nullptr;
QString m_itemName;
};

View File

@ -52,26 +52,29 @@
#include "flow_layout.h"
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
FlowLayout::FlowLayout(QWidget* parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent)
, m_hSpace(hSpacing)
, m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
: m_hSpace(hSpacing)
, m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
QLayoutItem* item;
while ((item = takeAt(0)))
delete item;
}
void FlowLayout::addItem(QLayoutItem *item)
void FlowLayout::addItem(QLayoutItem* item)
{
itemList.append(item);
}
@ -99,12 +102,12 @@ int FlowLayout::count() const
return itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
QLayoutItem* FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
QLayoutItem* FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
@ -128,7 +131,7 @@ int FlowLayout::heightForWidth(int width) const
return height;
}
void FlowLayout::setGeometry(const QRect &rect)
void FlowLayout::setGeometry(const QRect& rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
@ -142,15 +145,15 @@ QSize FlowLayout::sizeHint() const
QSize FlowLayout::minimumSize() const
{
QSize size;
QLayoutItem *item;
QLayoutItem* item;
foreach (item, itemList)
size = size.expandedTo(item->minimumSize());
size += QSize(2*margin(), 2*margin());
size += QSize(2 * margin(), 2 * margin());
return size;
}
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
int FlowLayout::doLayout(const QRect& rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
@ -159,9 +162,9 @@ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
int y = effectiveRect.y();
int lineHeight = 0;
QLayoutItem *item;
QLayoutItem* item;
foreach (item, itemList) {
QWidget *wid = item->widget();
QWidget* wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
@ -189,13 +192,13 @@ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
QObject* parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
QWidget* pw = static_cast<QWidget*>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
return static_cast<QLayout*>(parent)->spacing();
}
}

View File

@ -55,31 +55,30 @@
#include <QRect>
#include <QStyle>
class FlowLayout : public QLayout
{
class FlowLayout : public QLayout {
public:
explicit FlowLayout(QWidget *parent, int margin=-1, int hSpacing=-1, int vSpacing=-1);
explicit FlowLayout(int margin=-1, int hSpacing=-1, int vSpacing=-1);
explicit FlowLayout(QWidget* parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item) override;
void addItem(QLayoutItem* item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QLayoutItem* itemAt(int index) const override;
QSize minimumSize() const override;
void setGeometry(const QRect &rect) override;
void setGeometry(const QRect& rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
QLayoutItem* takeAt(int index) override;
private:
int doLayout(const QRect &rect, bool testOnly) const;
int doLayout(const QRect& rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
QList<QLayoutItem*> itemList;
int m_hSpace;
int m_vSpace;
};

View File

@ -1,29 +1,29 @@
#include <QFile>
#include <QQuaternion>
#include "glb_file.h"
#include "model_mesh.h"
#include "version.h"
#include <QByteArray>
#include <QDataStream>
#include <QFileInfo>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QQuaternion>
#include <QtCore/qbuffer.h>
#include "glb_file.h"
#include "version.h"
#include "model_mesh.h"
bool GlbFileWriter::m_enableComment = false;
GlbFileWriter::GlbFileWriter(dust3d::Object &object,
const QString &filename,
QImage *textureImage,
QImage *normalImage,
QImage *ormImage) :
m_filename(filename)
GlbFileWriter::GlbFileWriter(dust3d::Object& object,
const QString& filename,
QImage* textureImage,
QImage* normalImage,
QImage* ormImage)
: m_filename(filename)
{
const std::vector<std::vector<dust3d::Vector3>> *triangleVertexNormals = object.triangleVertexNormals();
const std::vector<std::vector<dust3d::Vector3>>* triangleVertexNormals = object.triangleVertexNormals();
if (m_outputNormal) {
m_outputNormal = nullptr != triangleVertexNormals;
}
const std::vector<std::vector<dust3d::Vector2>> *triangleVertexUvs = object.triangleVertexUvs();
const std::vector<std::vector<dust3d::Vector2>>* triangleVertexUvs = object.triangleVertexUvs();
if (m_outputUv) {
m_outputUv = nullptr != triangleVertexUvs;
}
@ -31,35 +31,35 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
QDataStream binStream(&m_binByteArray, QIODevice::WriteOnly);
binStream.setFloatingPointPrecision(QDataStream::SinglePrecision);
binStream.setByteOrder(QDataStream::LittleEndian);
auto alignBin = [this, &binStream] {
while (0 != this->m_binByteArray.size() % 4) {
binStream << (quint8)0;
}
};
QDataStream jsonStream(&m_jsonByteArray, QIODevice::WriteOnly);
jsonStream.setFloatingPointPrecision(QDataStream::SinglePrecision);
jsonStream.setByteOrder(QDataStream::LittleEndian);
auto alignJson = [this, &jsonStream] {
while (0 != this->m_jsonByteArray.size() % 4) {
jsonStream << (quint8)' ';
}
};
int bufferViewIndex = 0;
int bufferViewFromOffset;
m_json["asset"]["version"] = "2.0";
m_json["asset"]["generator"] = APP_NAME " " APP_HUMAN_VER;
m_json["scenes"][0]["nodes"] = {0};
m_json["scenes"][0]["nodes"] = { 0 };
m_json["nodes"][0]["mesh"] = 0;
std::vector<dust3d::Vector3> triangleVertexPositions;
std::vector<size_t> triangleVertexOldIndices;
for (const auto &triangleIndices: object.triangles) {
for (const auto& triangleIndices : object.triangles) {
for (size_t j = 0; j < 3; ++j) {
triangleVertexOldIndices.push_back(triangleIndices[j]);
triangleVertexPositions.push_back(object.vertices[triangleIndices[j]]);
@ -68,7 +68,7 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
int primitiveIndex = 0;
if (!triangleVertexPositions.empty()) {
m_json["meshes"][0]["primitives"][primitiveIndex]["indices"] = bufferViewIndex;
m_json["meshes"][0]["primitives"][primitiveIndex]["material"] = primitiveIndex;
int attributeIndex = 0;
@ -93,7 +93,7 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["roughnessFactor"] = 1.0;
textureIndex++;
}
primitiveIndex++;
bufferViewFromOffset = (int)m_binByteArray.size();
@ -114,7 +114,7 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexPositions.size();
m_json["accessors"][bufferViewIndex]["type"] = "SCALAR";
bufferViewIndex++;
bufferViewFromOffset = (int)m_binByteArray.size();
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
@ -124,7 +124,7 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
float maxY = -100;
float minZ = 100;
float maxZ = -100;
for (const auto &position: triangleVertexPositions) {
for (const auto& position : triangleVertexPositions) {
if (position.x() < minX)
minX = position.x();
if (position.x() > maxX)
@ -140,7 +140,7 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
binStream << (float)position.x() << (float)position.y() << (float)position.z();
}
Q_ASSERT((int)triangleVertexPositions.size() * 3 * sizeof(float) == m_binByteArray.size() - bufferViewFromOffset);
m_json["bufferViews"][bufferViewIndex]["byteLength"] = triangleVertexPositions.size() * 3 * sizeof(float);
m_json["bufferViews"][bufferViewIndex]["byteLength"] = triangleVertexPositions.size() * 3 * sizeof(float);
m_json["bufferViews"][bufferViewIndex]["target"] = 34962;
alignBin();
if (m_enableComment)
@ -148,26 +148,26 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexPositions.size();
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexPositions.size();
m_json["accessors"][bufferViewIndex]["type"] = "VEC3";
m_json["accessors"][bufferViewIndex]["max"] = {maxX, maxY, maxZ};
m_json["accessors"][bufferViewIndex]["min"] = {minX, minY, minZ};
m_json["accessors"][bufferViewIndex]["max"] = { maxX, maxY, maxZ };
m_json["accessors"][bufferViewIndex]["min"] = { minX, minY, minZ };
bufferViewIndex++;
if (m_outputNormal) {
bufferViewFromOffset = (int)m_binByteArray.size();
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
QStringList normalList;
for (const auto &normals: (*triangleVertexNormals)) {
for (const auto &it: normals) {
for (const auto& normals : (*triangleVertexNormals)) {
for (const auto& it : normals) {
binStream << (float)it.x() << (float)it.y() << (float)it.z();
if (m_enableComment && m_outputNormal)
normalList.append(QString("<%1,%2,%3>").arg(QString::number(it.x())).arg(QString::number(it.y())).arg(QString::number(it.z())));
}
}
Q_ASSERT((int)triangleVertexNormals->size() * 3 * 3 * sizeof(float) == m_binByteArray.size() - bufferViewFromOffset);
m_json["bufferViews"][bufferViewIndex]["byteLength"] = triangleVertexNormals->size() * 3 * 3 * sizeof(float);
m_json["bufferViews"][bufferViewIndex]["byteLength"] = triangleVertexNormals->size() * 3 * 3 * sizeof(float);
m_json["bufferViews"][bufferViewIndex]["target"] = 34962;
alignBin();
if (m_enableComment)
@ -175,17 +175,17 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexNormals->size() * 3;
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexNormals->size() * 3;
m_json["accessors"][bufferViewIndex]["type"] = "VEC3";
bufferViewIndex++;
}
if (m_outputUv) {
bufferViewFromOffset = (int)m_binByteArray.size();
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
for (const auto &uvs: (*triangleVertexUvs)) {
for (const auto &it: uvs)
for (const auto& uvs : (*triangleVertexUvs)) {
for (const auto& it : uvs)
binStream << (float)it.x() << (float)it.y();
}
m_json["bufferViews"][bufferViewIndex]["byteLength"] = m_binByteArray.size() - bufferViewFromOffset;
@ -195,7 +195,7 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexUvs->size() * 3;
m_json["accessors"][bufferViewIndex]["count"] = triangleVertexUvs->size() * 3;
m_json["accessors"][bufferViewIndex]["type"] = "VEC2";
bufferViewIndex++;
}
@ -205,15 +205,15 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["samplers"][0]["minFilter"] = 9987;
m_json["samplers"][0]["wrapS"] = 33648;
m_json["samplers"][0]["wrapT"] = 33648;
int imageIndex = 0;
int textureIndex = 0;
// Images should be put in the end of the buffer, because we are not using accessors
if (nullptr != textureImage) {
m_json["textures"][textureIndex]["sampler"] = 0;
m_json["textures"][textureIndex]["source"] = imageIndex;
bufferViewFromOffset = (int)m_binByteArray.size();
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
@ -226,14 +226,14 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["images"][imageIndex]["bufferView"] = bufferViewIndex;
m_json["images"][imageIndex]["mimeType"] = "image/png";
bufferViewIndex++;
imageIndex++;
textureIndex++;
}
if (nullptr != normalImage) {
m_json["textures"][textureIndex]["sampler"] = 0;
m_json["textures"][textureIndex]["source"] = imageIndex;
bufferViewFromOffset = (int)m_binByteArray.size();
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
@ -246,14 +246,14 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["images"][imageIndex]["bufferView"] = bufferViewIndex;
m_json["images"][imageIndex]["mimeType"] = "image/png";
bufferViewIndex++;
imageIndex++;
textureIndex++;
}
if (nullptr != ormImage) {
m_json["textures"][textureIndex]["sampler"] = 0;
m_json["textures"][textureIndex]["source"] = imageIndex;
bufferViewFromOffset = (int)m_binByteArray.size();
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
@ -266,13 +266,13 @@ GlbFileWriter::GlbFileWriter(dust3d::Object &object,
m_json["images"][imageIndex]["bufferView"] = bufferViewIndex;
m_json["images"][imageIndex]["mimeType"] = "image/png";
bufferViewIndex++;
imageIndex++;
textureIndex++;
}
m_json["buffers"][0]["byteLength"] = m_binByteArray.size();
auto jsonString = m_enableComment ? m_json.dump(4) : m_json.dump();
jsonStream.writeRawData(jsonString.data(), jsonString.size());
alignJson();
@ -287,50 +287,48 @@ bool GlbFileWriter::save()
QDataStream output(&file);
output.setFloatingPointPrecision(QDataStream::SinglePrecision);
output.setByteOrder(QDataStream::LittleEndian);
uint32_t headerSize = 12;
uint32_t chunk0DescriptionSize = 8;
uint32_t chunk1DescriptionSize = 8;
uint32_t fileSize = headerSize +
chunk0DescriptionSize + m_jsonByteArray.size() +
chunk1DescriptionSize + m_binByteArray.size();
uint32_t fileSize = headerSize + chunk0DescriptionSize + m_jsonByteArray.size() + chunk1DescriptionSize + m_binByteArray.size();
qDebug() << "Chunk 0 data size:" << m_jsonByteArray.size();
qDebug() << "Chunk 1 data size:" << m_binByteArray.size();
qDebug() << "File size:" << fileSize;
//////////// Header ////////////
// magic
output << (uint32_t)0x46546C67;
// version
output << (uint32_t)0x00000002;
// length
output << (uint32_t)fileSize;
//////////// Chunk 0 (Json) ////////////
// length
output << (uint32_t)m_jsonByteArray.size();
// type
output << (uint32_t)0x4E4F534A;
// data
output.writeRawData(m_jsonByteArray.data(), m_jsonByteArray.size());
//////////// Chunk 1 (Binary Buffer) ///
// length
output << (uint32_t)m_binByteArray.size();
// type
output << (uint32_t)0x004E4942;
// data
output.writeRawData(m_binByteArray.data(), m_binByteArray.size());
return true;
}

View File

@ -1,35 +1,37 @@
#ifndef DUST3D_APPLICATION_GLB_FILE_H_
#define DUST3D_APPLICATION_GLB_FILE_H_
#include <QObject>
#include <QString>
#include <QByteArray>
#include <QMatrix4x4>
#include <vector>
#include <QQuaternion>
#include <QImage>
#include <dust3d/base/object.h>
#include "json.hpp"
#include "document.h"
#include "json.hpp"
#include <QByteArray>
#include <QImage>
#include <QMatrix4x4>
#include <QObject>
#include <QQuaternion>
#include <QString>
#include <dust3d/base/object.h>
#include <vector>
class GlbFileWriter : public QObject
{
class GlbFileWriter : public QObject {
Q_OBJECT
public:
GlbFileWriter(dust3d::Object &object,
const QString &filename,
QImage *textureImage=nullptr,
QImage *normalImage=nullptr,
QImage *ormImage=nullptr);
GlbFileWriter(dust3d::Object& object,
const QString& filename,
QImage* textureImage = nullptr,
QImage* normalImage = nullptr,
QImage* ormImage = nullptr);
bool save();
private:
QString m_filename;
bool m_outputNormal = true;
bool m_outputUv = true;
QByteArray m_binByteArray;
QByteArray m_jsonByteArray;
private:
nlohmann::json m_json;
public:
static bool m_enableComment;
};

View File

@ -5,47 +5,47 @@ GraphicsContainerWidget::GraphicsContainerWidget()
setMouseTracking(true);
}
void GraphicsContainerWidget::resizeEvent(QResizeEvent *event)
void GraphicsContainerWidget::resizeEvent(QResizeEvent* event)
{
if (m_graphicsWidget && m_graphicsWidget->size() != event->size())
emit containerSizeChanged(event->size());
}
void GraphicsContainerWidget::mousePressEvent(QMouseEvent *event)
void GraphicsContainerWidget::mousePressEvent(QMouseEvent* event)
{
if (m_modelWidget)
m_modelWidget->inputMousePressEventFromOtherWidget(event);
}
void GraphicsContainerWidget::mouseMoveEvent(QMouseEvent *event)
void GraphicsContainerWidget::mouseMoveEvent(QMouseEvent* event)
{
if (m_modelWidget)
m_modelWidget->inputMouseMoveEventFromOtherWidget(event);
}
void GraphicsContainerWidget::mouseReleaseEvent(QMouseEvent *event)
void GraphicsContainerWidget::mouseReleaseEvent(QMouseEvent* event)
{
if (m_modelWidget)
m_modelWidget->inputMouseReleaseEventFromOtherWidget(event);
}
void GraphicsContainerWidget::wheelEvent(QWheelEvent *event)
void GraphicsContainerWidget::wheelEvent(QWheelEvent* event)
{
if (m_graphicsWidget) {
m_graphicsWidget->inputWheelEventFromOtherWidget(event);
return;
}
if (m_modelWidget)
m_modelWidget->inputWheelEventFromOtherWidget(event);
}
void GraphicsContainerWidget::setGraphicsWidget(SkeletonGraphicsWidget *graphicsWidget)
void GraphicsContainerWidget::setGraphicsWidget(SkeletonGraphicsWidget* graphicsWidget)
{
m_graphicsWidget = graphicsWidget;
}
void GraphicsContainerWidget::setModelWidget(ModelWidget *modelWidget)
void GraphicsContainerWidget::setModelWidget(ModelWidget* modelWidget)
{
m_modelWidget = modelWidget;
}

View File

@ -1,31 +1,33 @@
#ifndef DUST3D_APPLICATION_GRAPHICS_CONTAINER_WIDGET_H_
#define DUST3D_APPLICATION_GRAPHICS_CONTAINER_WIDGET_H_
#include <QWidget>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include "model_widget.h"
#include "skeleton_graphics_widget.h"
#include <QMouseEvent>
#include <QResizeEvent>
#include <QWheelEvent>
#include <QWidget>
class GraphicsContainerWidget : public QWidget
{
class GraphicsContainerWidget : public QWidget {
Q_OBJECT
signals:
void containerSizeChanged(QSize size);
public:
GraphicsContainerWidget();
void setGraphicsWidget(SkeletonGraphicsWidget *graphicsWidget);
void setModelWidget(ModelWidget *modelWidget);
void setGraphicsWidget(SkeletonGraphicsWidget* graphicsWidget);
void setModelWidget(ModelWidget* modelWidget);
protected:
void resizeEvent(QResizeEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
private:
ModelWidget *m_modelWidget = nullptr;
SkeletonGraphicsWidget *m_graphicsWidget = nullptr;
ModelWidget* m_modelWidget = nullptr;
SkeletonGraphicsWidget* m_graphicsWidget = nullptr;
};
#endif

View File

@ -1,7 +1,7 @@
#include "horizontal_line_widget.h"
HorizontalLineWidget::HorizontalLineWidget() :
QWidget()
HorizontalLineWidget::HorizontalLineWidget()
: QWidget()
{
setFixedHeight(1);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

View File

@ -3,8 +3,7 @@
#include <QWidget>
class HorizontalLineWidget : public QWidget
{
class HorizontalLineWidget : public QWidget {
Q_OBJECT
public:
HorizontalLineWidget();

View File

@ -1,19 +1,18 @@
#include <map>
#include "image_forever.h"
#include <QMutex>
#include <QMutexLocker>
#include <QtCore/qbuffer.h>
#include "image_forever.h"
#include <map>
struct ImageForeverItem
{
QImage *image;
struct ImageForeverItem {
QImage* image;
dust3d::Uuid id;
QByteArray *imageByteArray;
QByteArray* imageByteArray;
};
static std::map<dust3d::Uuid, ImageForeverItem> g_foreverMap;
static QMutex g_mapMutex;
const QImage *ImageForever::get(const dust3d::Uuid &id)
const QImage* ImageForever::get(const dust3d::Uuid& id)
{
QMutexLocker locker(&g_mapMutex);
auto findResult = g_foreverMap.find(id);
@ -22,7 +21,7 @@ const QImage *ImageForever::get(const dust3d::Uuid &id)
return findResult->second.image;
}
void ImageForever::copy(const dust3d::Uuid &id, QImage &image)
void ImageForever::copy(const dust3d::Uuid& id, QImage& image)
{
QMutexLocker locker(&g_mapMutex);
auto findResult = g_foreverMap.find(id);
@ -31,7 +30,7 @@ void ImageForever::copy(const dust3d::Uuid &id, QImage &image)
image = *findResult->second.image;
}
const QByteArray *ImageForever::getPngByteArray(const dust3d::Uuid &id)
const QByteArray* ImageForever::getPngByteArray(const dust3d::Uuid& id)
{
QMutexLocker locker(&g_mapMutex);
auto findResult = g_foreverMap.find(id);
@ -40,7 +39,7 @@ const QByteArray *ImageForever::getPngByteArray(const dust3d::Uuid &id)
return findResult->second.imageByteArray;
}
dust3d::Uuid ImageForever::add(const QImage *image, dust3d::Uuid toId)
dust3d::Uuid ImageForever::add(const QImage* image, dust3d::Uuid toId)
{
QMutexLocker locker(&g_mapMutex);
if (nullptr == image)
@ -48,16 +47,16 @@ dust3d::Uuid ImageForever::add(const QImage *image, dust3d::Uuid toId)
dust3d::Uuid newId = toId.isNull() ? dust3d::Uuid::createUuid() : toId;
if (g_foreverMap.find(newId) != g_foreverMap.end())
return newId;
QImage *newImage = new QImage(*image);
QByteArray *imageByteArray = new QByteArray();
QImage* newImage = new QImage(*image);
QByteArray* imageByteArray = new QByteArray();
QBuffer pngBuffer(imageByteArray);
pngBuffer.open(QIODevice::WriteOnly);
newImage->save(&pngBuffer, "PNG");
g_foreverMap[newId] = {newImage, newId, imageByteArray};
g_foreverMap[newId] = { newImage, newId, imageByteArray };
return newId;
}
void ImageForever::remove(const dust3d::Uuid &id)
void ImageForever::remove(const dust3d::Uuid& id)
{
QMutexLocker locker(&g_mapMutex);
auto findImage = g_foreverMap.find(id);

View File

@ -1,18 +1,17 @@
#ifndef DUST3D_APPLICATION_IMAGE_FOREVER_H_
#define DUST3D_APPLICATION_IMAGE_FOREVER_H_
#include <QImage>
#include <QByteArray>
#include <QImage>
#include <dust3d/base/uuid.h>
class ImageForever
{
class ImageForever {
public:
static const QImage *get(const dust3d::Uuid &id);
static void copy(const dust3d::Uuid &id, QImage &image);
static const QByteArray *getPngByteArray(const dust3d::Uuid &id);
static dust3d::Uuid add(const QImage *image, dust3d::Uuid toId=dust3d::Uuid());
static void remove(const dust3d::Uuid &id);
static const QImage* get(const dust3d::Uuid& id);
static void copy(const dust3d::Uuid& id, QImage& image);
static const QByteArray* getPngByteArray(const dust3d::Uuid& id);
static dust3d::Uuid add(const QImage* image, dust3d::Uuid toId = dust3d::Uuid());
static void remove(const dust3d::Uuid& id);
};
#endif

View File

@ -1,28 +1,28 @@
#include <QPainter>
#include "image_preview_widget.h"
#include <QPainter>
ImagePreviewWidget::ImagePreviewWidget(QWidget *parent) :
QWidget(parent)
ImagePreviewWidget::ImagePreviewWidget(QWidget* parent)
: QWidget(parent)
{
}
void ImagePreviewWidget::updateImage(const QImage &image)
void ImagePreviewWidget::updateImage(const QImage& image)
{
m_image = image;
update();
}
void ImagePreviewWidget::updateBackgroundColor(const QColor &color)
void ImagePreviewWidget::updateBackgroundColor(const QColor& color)
{
m_backgroundColor = color;
}
void ImagePreviewWidget::mousePressEvent(QMouseEvent *event)
void ImagePreviewWidget::mousePressEvent(QMouseEvent* event)
{
emit clicked();
}
void ImagePreviewWidget::paintEvent(QPaintEvent *event)
void ImagePreviewWidget::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
if (!m_image.isNull())
@ -30,4 +30,3 @@ void ImagePreviewWidget::paintEvent(QPaintEvent *event)
else
painter.fillRect(QRect(0, 0, width(), height()), QBrush(m_backgroundColor));
}

View File

@ -1,30 +1,30 @@
#ifndef DUST3D_APPLICATION_IMAGE_PREVIEW_WIDGET_H_
#define DUST3D_APPLICATION_IMAGE_PREVIEW_WIDGET_H_
#include <QWidget>
#include <QImage>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QWidget>
class ImagePreviewWidget : public QWidget
{
class ImagePreviewWidget : public QWidget {
Q_OBJECT
signals:
void clicked();
public:
ImagePreviewWidget(QWidget *parent=nullptr);
void updateImage(const QImage &image);
void updateBackgroundColor(const QColor &color);
ImagePreviewWidget(QWidget* parent = nullptr);
void updateImage(const QImage& image);
void updateBackgroundColor(const QColor& color);
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void paintEvent(QPaintEvent* event);
void mousePressEvent(QMouseEvent* event);
private:
QImage m_image;
QColor m_backgroundColor;
void resizeImage(QImage *image, const QSize &newSize);
void resizeImage(QImage* image, const QSize& newSize);
};
#endif

View File

@ -1,25 +1,25 @@
#include <QHBoxLayout>
#include "info_label.h"
#include "theme.h"
#include <QHBoxLayout>
InfoLabel::InfoLabel(const QString &text, QWidget *parent) :
QWidget(parent)
InfoLabel::InfoLabel(const QString& text, QWidget* parent)
: QWidget(parent)
{
m_icon = new QLabel(QChar(fa::infocircle));
Theme::initAwesomeLabel(m_icon);
m_label = new QLabel(text);
m_label->setWordWrap(true);
QHBoxLayout *mainLayout = new QHBoxLayout;
QHBoxLayout* mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_icon);
mainLayout->addWidget(m_label);
mainLayout->addStretch();
setLayout(mainLayout);
}
void InfoLabel::setText(const QString &text)
void InfoLabel::setText(const QString& text)
{
m_label->setText(text);
}

View File

@ -1,18 +1,18 @@
#ifndef DUST3D_APPLICATION_INFO_LABEL_H_
#define DUST3D_APPLICATION_INFO_LABEL_H_
#include <QLabel>
#include <QIcon>
#include <QLabel>
#include <QWidget>
class InfoLabel : public QWidget
{
class InfoLabel : public QWidget {
public:
InfoLabel(const QString &text=QString(), QWidget *parent=nullptr);
void setText(const QString &text);
InfoLabel(const QString& text = QString(), QWidget* parent = nullptr);
void setText(const QString& text);
private:
QLabel *m_label = nullptr;
QLabel *m_icon = nullptr;
QLabel* m_label = nullptr;
QLabel* m_icon = nullptr;
};
#endif

View File

@ -1,11 +1,11 @@
#include <QtWidgets>
#include "int_number_widget.h"
#include "theme.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "theme.h"
#include "int_number_widget.h"
#include <QtWidgets>
IntNumberWidget::IntNumberWidget(QWidget *parent, bool singleLine) :
QWidget(parent)
IntNumberWidget::IntNumberWidget(QWidget* parent, bool singleLine)
: QWidget(parent)
{
m_slider = new QSlider(Qt::Horizontal, this);
m_slider->setRange(0, 100);
@ -18,8 +18,8 @@ IntNumberWidget::IntNumberWidget(QWidget *parent, bool singleLine) :
updateValueLabel(value);
emit valueChanged(value);
});
QBoxLayout *layout = nullptr;
QBoxLayout* layout = nullptr;
if (singleLine) {
layout = new QHBoxLayout(this);
layout->setMargin(2);
@ -42,7 +42,7 @@ void IntNumberWidget::updateValueLabel(int value)
m_label->setText(m_itemName + ": " + valueString);
}
void IntNumberWidget::setItemName(const QString &name)
void IntNumberWidget::setItemName(const QString& name)
{
m_itemName = name;
updateValueLabel(value());

View File

@ -6,14 +6,13 @@
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QSlider)
class IntNumberWidget : public QWidget
{
class IntNumberWidget : public QWidget {
Q_OBJECT
public:
explicit IntNumberWidget(QWidget *parent = nullptr, bool singleLine=true);
explicit IntNumberWidget(QWidget* parent = nullptr, bool singleLine = true);
void setRange(int min, int max);
int value() const;
void setItemName(const QString &name);
void setItemName(const QString& name);
public slots:
void increaseValue();
@ -22,13 +21,13 @@ public slots:
signals:
void valueChanged(int value);
private:
void updateValueLabel(int value);
private:
QLabel *m_label = nullptr;
QSlider *m_slider = nullptr;
QLabel* m_label = nullptr;
QSlider* m_slider = nullptr;
QString m_itemName;
};

View File

@ -1,17 +1,17 @@
#include <QMetaType>
#include <QDir>
#include "log_browser.h"
#include "log_browser_dialog.h"
#include <QDir>
#include <QMetaType>
bool LogBrowser::m_enableOutputToFile = true;
LogBrowser::LogBrowser(QObject *parent) :
QObject(parent)
LogBrowser::LogBrowser(QObject* parent)
: QObject(parent)
{
qRegisterMetaType<QtMsgType>("QtMsgType");
m_browserDialog = new LogBrowserDialog;
connect(this, &LogBrowser::sendMessage, m_browserDialog, &LogBrowserDialog::outputMessage, Qt::QueuedConnection);
if (m_enableOutputToFile) {
QString filePath = "application.log";
m_outputTo = fopen(filePath.toUtf8().constData(), "w");
@ -42,7 +42,7 @@ bool LogBrowser::isDialogVisible()
return m_browserDialog->isVisible();
}
void LogBrowser::outputMessage(QtMsgType type, const QString &msg, const QString &source, int line)
void LogBrowser::outputMessage(QtMsgType type, const QString& msg, const QString& source, int line)
{
if (m_outputTo) {
fprintf(m_outputTo, "[%s:%d]: %s\n", source.toUtf8().constData(), line, msg.toUtf8().constData());

View File

@ -6,25 +6,24 @@
class LogBrowserDialog;
class LogBrowser : public QObject
{
class LogBrowser : public QObject {
Q_OBJECT
public:
explicit LogBrowser(QObject *parent=0);
explicit LogBrowser(QObject* parent = 0);
~LogBrowser();
public slots:
void outputMessage(QtMsgType type, const QString &msg, const QString &source, int line);
void outputMessage(QtMsgType type, const QString& msg, const QString& source, int line);
void showDialog();
void hideDialog();
bool isDialogVisible();
signals:
void sendMessage(QtMsgType type, const QString &msg, const QString &source, int line);
void sendMessage(QtMsgType type, const QString& msg, const QString& source, int line);
private:
LogBrowserDialog *m_browserDialog = nullptr;
FILE *m_outputTo = nullptr;
LogBrowserDialog* m_browserDialog = nullptr;
FILE* m_outputTo = nullptr;
static bool m_enableOutputToFile;
};

View File

@ -1,30 +1,30 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTextBrowser>
#include <QPushButton>
#include <QFileDialog>
#include <QDir>
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include <QCloseEvent>
#include <QKeyEvent>
#include "version.h"
#include "log_browser_dialog.h"
#include "document_window.h"
#include "version.h"
#include <QCloseEvent>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QMessageBox>
#include <QPushButton>
#include <QTextBrowser>
#include <QTextStream>
#include <QVBoxLayout>
LogBrowserDialog::LogBrowserDialog(QWidget *parent) :
QDialog(parent)
LogBrowserDialog::LogBrowserDialog(QWidget* parent)
: QDialog(parent)
{
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
QVBoxLayout *layout = new QVBoxLayout;
QVBoxLayout* layout = new QVBoxLayout;
setLayout(layout);
m_browser = new QTextBrowser(this);
layout->addWidget(m_browser);
QHBoxLayout *buttonLayout = new QHBoxLayout;
QHBoxLayout* buttonLayout = new QHBoxLayout;
buttonLayout->setContentsMargins(0, 0, 0, 0);
layout->addLayout(buttonLayout);
@ -41,20 +41,17 @@ LogBrowserDialog::LogBrowserDialog(QWidget *parent) :
connect(m_saveButton, SIGNAL(clicked()), this, SLOT(save()));
resize(600, 300);
setWindowTitle(applicationTitle(tr("Debug")));
hide();
}
LogBrowserDialog::~LogBrowserDialog()
{
}
void LogBrowserDialog::outputMessage(QtMsgType type, const QString &msg, const QString &source, int line)
void LogBrowserDialog::outputMessage(QtMsgType type, const QString& msg, const QString& source, int line)
{
switch (type) {
case QtDebugMsg:
@ -79,7 +76,6 @@ void LogBrowserDialog::outputMessage(QtMsgType type, const QString &msg, const Q
}
}
void LogBrowserDialog::save()
{
QString saveFileName = QFileDialog::getSaveFileName(this,
@ -95,8 +91,8 @@ void LogBrowserDialog::save()
QMessageBox::warning(this,
tr("Error"),
QString(tr("<nobr>File '%1'<br/>cannot be opened for writing.<br/><br/>"
"The log output could <b>not</b> be saved!</nobr>"))
.arg(saveFileName));
"The log output could <b>not</b> be saved!</nobr>"))
.arg(saveFileName));
return;
}
@ -105,7 +101,7 @@ void LogBrowserDialog::save()
file.close();
}
void LogBrowserDialog::closeEvent(QCloseEvent *e)
void LogBrowserDialog::closeEvent(QCloseEvent* e)
{
if (0 == DocumentWindow::total()) {
e->accept();
@ -115,7 +111,7 @@ void LogBrowserDialog::closeEvent(QCloseEvent *e)
hide();
}
void LogBrowserDialog::keyPressEvent(QKeyEvent *e)
void LogBrowserDialog::keyPressEvent(QKeyEvent* e)
{
e->ignore();
}

View File

@ -6,26 +6,25 @@
class QTextBrowser;
class QPushButton;
class LogBrowserDialog : public QDialog
{
class LogBrowserDialog : public QDialog {
Q_OBJECT
public:
LogBrowserDialog(QWidget *parent = 0);
LogBrowserDialog(QWidget* parent = 0);
~LogBrowserDialog();
public slots:
void outputMessage(QtMsgType type, const QString &msg, const QString &source, int line);
void outputMessage(QtMsgType type, const QString& msg, const QString& source, int line);
protected slots:
void save();
protected:
virtual void keyPressEvent(QKeyEvent *e);
virtual void closeEvent(QCloseEvent *e);
virtual void keyPressEvent(QKeyEvent* e);
virtual void closeEvent(QCloseEvent* e);
QTextBrowser *m_browser;
QPushButton *m_clearButton;
QPushButton *m_saveButton;
QTextBrowser* m_browser;
QPushButton* m_clearButton;
QPushButton* m_saveButton;
};
#endif

View File

@ -1,41 +1,40 @@
#include <QApplication>
#include <QSurfaceFormat>
#include <QDebug>
#include <iostream>
#include <cstdio>
#include <dust3d/base/string.h>
#include "document_window.h"
#include "document.h"
#include "document_window.h"
#include "theme.h"
#include "version.h"
#include <QApplication>
#include <QDebug>
#include <QSurfaceFormat>
#include <cstdio>
#include <dust3d/base/string.h>
#include <iostream>
int main(int argc, char *argv[])
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
format.setVersion(3, 3);
QSurfaceFormat::setDefaultFormat(format);
Theme::initialize();
QCoreApplication::setApplicationName(APP_NAME);
QCoreApplication::setOrganizationName(APP_COMPANY);
QCoreApplication::setOrganizationDomain(APP_HOMEPAGE_URL);
//freopen("dust3d.log", "w", stdout);
//setvbuf(stdout, 0, _IONBF, 0);
DocumentWindow *firstWindow = DocumentWindow::createDocumentWindow();
DocumentWindow* firstWindow = DocumentWindow::createDocumentWindow();
QStringList openFileList;
QStringList waitingExportList;
bool toggleColor = false;
for (int i = 1; i < argc; ++i) {
if ('-' == argv[i][0]) {
if (0 == strcmp(argv[i], "-output") ||
0 == strcmp(argv[i], "-o")) {
if (0 == strcmp(argv[i], "-output") || 0 == strcmp(argv[i], "-o")) {
++i;
if (i < argc)
waitingExportList.append(argv[i]);
@ -55,12 +54,12 @@ int main(int argc, char *argv[])
continue;
}
}
int finishedExportFileNum = 0;
int totalExportFileNum = 0;
int succeedExportNum = 0;
int exitCode = -1;
std::vector<DocumentWindow *> windowList;
std::vector<DocumentWindow*> windowList;
auto checkToSafelyExit = [&]() {
if (-1 == exitCode)
return;
@ -76,17 +75,16 @@ int main(int argc, char *argv[])
windowList.push_back(DocumentWindow::createDocumentWindow());
}
if (toggleColor) {
for (auto &it: windowList)
for (auto& it : windowList)
it->toggleRenderColor();
}
if (!waitingExportList.empty() &&
openFileList.size() == 1) {
if (!waitingExportList.empty() && openFileList.size() == 1) {
totalExportFileNum = openFileList.size() * waitingExportList.size();
for (int i = 0; i < openFileList.size(); ++i) {
QObject::connect(windowList[i], &DocumentWindow::workingStatusChanged, &app, checkToSafelyExit);
}
for (int i = 0; i < openFileList.size(); ++i) {
QObject::connect(windowList[i], &DocumentWindow::waitingExportFinished, &app, [&](const QString &filename, bool isSuccessful) {
QObject::connect(windowList[i], &DocumentWindow::waitingExportFinished, &app, [&](const QString& filename, bool isSuccessful) {
qDebug() << "Export to" << filename << (isSuccessful ? "isSuccessful" : "failed");
++finishedExportFileNum;
if (isSuccessful)
@ -112,6 +110,6 @@ int main(int argc, char *argv[])
windowList[i]->openPathAs(openFileList[i], openFileList[i]);
}
}
return app.exec();
}

View File

@ -1,21 +1,21 @@
#include "material.h"
#include "image_forever.h"
void initializeMaterialTexturesFromSnapshot(const dust3d::Snapshot &snapshot,
const dust3d::Uuid &materialId,
MaterialTextures &materialTextures,
float &tileScale)
void initializeMaterialTexturesFromSnapshot(const dust3d::Snapshot& snapshot,
const dust3d::Uuid& materialId,
MaterialTextures& materialTextures,
float& tileScale)
{
auto materialIdString = materialId.toString();
for (const auto &materialItem: snapshot.materials) {
for (const auto& materialItem : snapshot.materials) {
if (materialIdString != dust3d::String::valueOrEmpty(materialItem.first, "id"))
continue;
for (const auto &layer: materialItem.second) {
for (const auto& layer : materialItem.second) {
//FIXME: Only support one layer currently
auto findTileScale = layer.first.find("tileScale");
if (findTileScale != layer.first.end())
tileScale = dust3d::String::toFloat(findTileScale->second);
for (const auto &mapItem: layer.second) {
for (const auto& mapItem : layer.second) {
auto textureType = dust3d::TextureTypeFromString(dust3d::String::valueOrEmpty(mapItem, "for").c_str());
if (textureType != dust3d::TextureType::None) {
int index = (int)textureType - 1;

View File

@ -2,18 +2,17 @@
#define DUST3D_APPLICATION_MATERIAL_H_
#include <QImage>
#include <dust3d/base/uuid.h>
#include <dust3d/base/texture_type.h>
#include <dust3d/base/snapshot.h>
#include <dust3d/base/texture_type.h>
#include <dust3d/base/uuid.h>
struct MaterialTextures
{
const QImage *textureImages[(int)dust3d::TextureType::Count - 1] = {nullptr};
struct MaterialTextures {
const QImage* textureImages[(int)dust3d::TextureType::Count - 1] = { nullptr };
};
void initializeMaterialTexturesFromSnapshot(const dust3d::Snapshot &snapshot,
const dust3d::Uuid &materialId,
MaterialTextures &materialTextures,
float &tileScale);
void initializeMaterialTexturesFromSnapshot(const dust3d::Snapshot& snapshot,
const dust3d::Uuid& materialId,
MaterialTextures& materialTextures,
float& tileScale);
#endif

View File

@ -1,49 +1,49 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include "material_edit_widget.h"
#include "document.h"
#include "float_number_widget.h"
#include "horizontal_line_widget.h"
#include "image_forever.h"
#include "theme.h"
#include "version.h"
#include <QFileDialog>
#include <QFormLayout>
#include <QGridLayout>
#include <QMenu>
#include <QWidgetAction>
#include <QLineEdit>
#include <QMessageBox>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QMessageBox>
#include <QThread>
#include "theme.h"
#include "material_edit_widget.h"
#include "float_number_widget.h"
#include "version.h"
#include "image_forever.h"
#include "document.h"
#include "horizontal_line_widget.h"
#include <QVBoxLayout>
#include <QWidgetAction>
ImagePreviewWidget *MaterialEditWidget::createMapButton()
ImagePreviewWidget* MaterialEditWidget::createMapButton()
{
ImagePreviewWidget *mapButton = new ImagePreviewWidget;
ImagePreviewWidget* mapButton = new ImagePreviewWidget;
mapButton->setFixedSize(Theme::partPreviewImageSize * 2, Theme::partPreviewImageSize * 2);
updateMapButtonBackground(mapButton, nullptr);
return mapButton;
}
QImage *MaterialEditWidget::pickImage()
QImage* MaterialEditWidget::pickImage()
{
QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(),
tr("Image Files (*.png *.jpg *.bmp)")).trimmed();
tr("Image Files (*.png *.jpg *.bmp)"))
.trimmed();
if (fileName.isEmpty())
return nullptr;
QImage *image = new QImage();
QImage* image = new QImage();
if (!image->load(fileName))
return nullptr;
return image;
}
MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent) :
QDialog(parent),
m_document(document)
MaterialEditWidget::MaterialEditWidget(const Document* document, QWidget* parent)
: QDialog(parent)
, m_document(document)
{
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
m_layers.resize(1);
m_previewWidget = new ModelWidget(this);
@ -51,24 +51,24 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
m_previewWidget->resize(512, 512);
m_previewWidget->move(-128, -128);
m_previewWidget->setNotGraphics(true);
QFont nameFont;
nameFont.setWeight(QFont::Light);
nameFont.setBold(false);
QGridLayout *mapLayout = new QGridLayout;
QGridLayout* mapLayout = new QGridLayout;
int row = 0;
int col = 0;
for (int i = 1; i < (int)dust3d::TextureType::Count; i++) {
QVBoxLayout *textureManageLayout = new QVBoxLayout;
QVBoxLayout* textureManageLayout = new QVBoxLayout;
MaterialMap item;
item.forWhat = (dust3d::TextureType)i;
m_layers[0].maps.push_back(item);
ImagePreviewWidget *imageButton = createMapButton();
ImagePreviewWidget* imageButton = createMapButton();
connect(imageButton, &ImagePreviewWidget::clicked, [=]() {
QImage *image = pickImage();
QImage* image = pickImage();
if (nullptr == image)
return;
m_layers[0].maps[(int)i - 1].imageId = ImageForever::add(image);
@ -76,41 +76,41 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
delete image;
emit layersAdjusted();
});
QLabel *nameLabel = new QLabel(tr(dust3d::TextureTypeToDispName(item.forWhat).c_str()));
QLabel* nameLabel = new QLabel(tr(dust3d::TextureTypeToDispName(item.forWhat).c_str()));
nameLabel->setFont(nameFont);
QPushButton *eraser = new QPushButton(QChar(fa::eraser));
QPushButton* eraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(eraser);
connect(eraser, &QPushButton::clicked, [=]() {
m_layers[0].maps[(int)i - 1].imageId = dust3d::Uuid();
updateMapButtonBackground(imageButton, nullptr);
emit layersAdjusted();
});
QHBoxLayout *textureTitleLayout = new QHBoxLayout;
QHBoxLayout* textureTitleLayout = new QHBoxLayout;
textureTitleLayout->addWidget(eraser);
textureTitleLayout->addWidget(nameLabel);
textureTitleLayout->addStretch();
textureManageLayout->addWidget(imageButton);
textureManageLayout->addLayout(textureTitleLayout);
m_textureMapButtons[i - 1] = imageButton;
mapLayout->addLayout(textureManageLayout, row, col++);
if (col == 2) {
col = 0;
row++;
}
}
QVBoxLayout *rightLayout = new QVBoxLayout;
QVBoxLayout* rightLayout = new QVBoxLayout;
rightLayout->addStretch();
rightLayout->addLayout(mapLayout);
rightLayout->addStretch();
QHBoxLayout *paramtersLayout = new QHBoxLayout;
QHBoxLayout* paramtersLayout = new QHBoxLayout;
paramtersLayout->setContentsMargins(256, 0, 0, 0);
paramtersLayout->addStretch();
paramtersLayout->addLayout(rightLayout);
@ -120,41 +120,41 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
m_unsaved = true;
updateTitle();
});
QPushButton *saveButton = new QPushButton(tr("Save"));
QPushButton* saveButton = new QPushButton(tr("Save"));
connect(saveButton, &QPushButton::clicked, this, &MaterialEditWidget::save);
saveButton->setDefault(true);
FloatNumberWidget *tileScaleWidget = new FloatNumberWidget;
FloatNumberWidget* tileScaleWidget = new FloatNumberWidget;
tileScaleWidget->setItemName(tr("Tile Scale"));
tileScaleWidget->setRange(0.01, 1.0);
tileScaleWidget->setValue(m_layers[0].tileScale);
m_tileScaleSlider = tileScaleWidget;
connect(tileScaleWidget, &FloatNumberWidget::valueChanged, [=](float value) {
m_layers[0].tileScale = value;
emit layersAdjusted();
});
QPushButton *tileScaleEraser = new QPushButton(QChar(fa::eraser));
QPushButton* tileScaleEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(tileScaleEraser);
connect(tileScaleEraser, &QPushButton::clicked, [=]() {
tileScaleWidget->setValue(1.0);
});
QHBoxLayout *tileScaleLayout = new QHBoxLayout;
QHBoxLayout* tileScaleLayout = new QHBoxLayout;
tileScaleLayout->addWidget(tileScaleEraser);
tileScaleLayout->addWidget(tileScaleWidget);
tileScaleLayout->addStretch();
QHBoxLayout *baseInfoLayout = new QHBoxLayout;
QHBoxLayout* baseInfoLayout = new QHBoxLayout;
baseInfoLayout->addWidget(new QLabel(tr("Name")));
baseInfoLayout->addWidget(m_nameEdit);
baseInfoLayout->addStretch();
baseInfoLayout->addWidget(saveButton);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addLayout(paramtersLayout);
mainLayout->addStretch();
mainLayout->addWidget(new HorizontalLineWidget());
@ -176,7 +176,7 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
updateTitle();
}
void MaterialEditWidget::updateMapButtonBackground(ImagePreviewWidget *button, const QImage *image)
void MaterialEditWidget::updateMapButtonBackground(ImagePreviewWidget* button, const QImage* image)
{
if (nullptr == image)
button->updateImage(QImage());
@ -189,7 +189,7 @@ void MaterialEditWidget::reject()
close();
}
void MaterialEditWidget::closeEvent(QCloseEvent *event)
void MaterialEditWidget::closeEvent(QCloseEvent* event)
{
if (m_unsaved && !m_closed) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
@ -235,7 +235,7 @@ void MaterialEditWidget::updatePreview()
qDebug() << "Material preview generating..";
QThread *thread = new QThread;
QThread* thread = new QThread;
m_materialPreviewsGenerator = new MaterialPreviewsGenerator();
m_materialPreviewsGenerator->addMaterial(dust3d::Uuid(), m_layers);
m_materialPreviewsGenerator->moveToThread(thread);
@ -279,7 +279,7 @@ void MaterialEditWidget::updateTitle()
setWindowTitle(applicationTitle(tr("New") + (m_unsaved ? "*" : "")));
return;
}
const Material *material = m_document->findMaterial(m_materialId);
const Material* material = m_document->findMaterial(m_materialId);
if (nullptr == material) {
qDebug() << "Find material failed:" << m_materialId;
return;
@ -299,9 +299,9 @@ void MaterialEditWidget::setEditMaterialLayers(std::vector<MaterialLayer> layers
m_layers[0].maps[i - 1].imageId = dust3d::Uuid();
}
if (!layers.empty()) {
for (const auto &layer: layers) {
for (const auto& layer : layers) {
m_layers[0].tileScale = layer.tileScale;
for (const auto &mapItem: layer.maps) {
for (const auto& mapItem : layer.maps) {
int index = (int)mapItem.forWhat - 1;
if (index >= 0 && index < (int)dust3d::TextureType::Count - 1) {
m_layers[0].maps[index].imageId = mapItem.imageId;

View File

@ -1,26 +1,24 @@
#ifndef DUST3D_APPLICATION_MATERIAL_EDIT_WIDGET_H_
#define DUST3D_APPLICATION_MATERIAL_EDIT_WIDGET_H_
#include <QDialog>
#include <map>
#include <QCloseEvent>
#include <QLineEdit>
#include "model_widget.h"
#include "material_previews_generator.h"
#include "image_preview_widget.h"
#include "float_number_widget.h"
#include "image_preview_widget.h"
#include "material_layer.h"
#include "material_previews_generator.h"
#include "model_widget.h"
#include <QCloseEvent>
#include <QDialog>
#include <QLineEdit>
#include <map>
class Document;
enum class PopupWidgetType
{
enum class PopupWidgetType {
PitchYawRoll,
Intersection
};
class MaterialEditWidget : public QDialog
{
class MaterialEditWidget : public QDialog {
Q_OBJECT
signals:
void addMaterial(dust3d::Uuid materialId, QString name, std::vector<MaterialLayer> layers);
@ -28,8 +26,9 @@ signals:
void setMaterialLayers(dust3d::Uuid materialId, std::vector<MaterialLayer> layers);
void renameMaterial(dust3d::Uuid materialId, QString name);
void layersAdjusted();
public:
MaterialEditWidget(const Document *document, QWidget *parent=nullptr);
MaterialEditWidget(const Document* document, QWidget* parent = nullptr);
~MaterialEditWidget();
public slots:
void updatePreview();
@ -40,25 +39,27 @@ public slots:
void save();
void clearUnsaveState();
void previewReady();
protected:
QSize sizeHint() const override;
void closeEvent(QCloseEvent *event) override;
void closeEvent(QCloseEvent* event) override;
void reject() override;
private:
void updateMapButtonBackground(ImagePreviewWidget *button, const QImage *image);
ImagePreviewWidget *createMapButton();
QImage *pickImage();
const Document *m_document = nullptr;
MaterialPreviewsGenerator *m_materialPreviewsGenerator = nullptr;
ModelWidget *m_previewWidget = nullptr;
FloatNumberWidget *m_tileScaleSlider = nullptr;
void updateMapButtonBackground(ImagePreviewWidget* button, const QImage* image);
ImagePreviewWidget* createMapButton();
QImage* pickImage();
const Document* m_document = nullptr;
MaterialPreviewsGenerator* m_materialPreviewsGenerator = nullptr;
ModelWidget* m_previewWidget = nullptr;
FloatNumberWidget* m_tileScaleSlider = nullptr;
bool m_isPreviewDirty = false;
bool m_closed = false;
dust3d::Uuid m_materialId;
bool m_unsaved = false;
QLineEdit *m_nameEdit = nullptr;
QLineEdit* m_nameEdit = nullptr;
std::vector<MaterialLayer> m_layers;
ImagePreviewWidget *m_textureMapButtons[(int)dust3d::TextureType::Count - 1] = {nullptr};
ImagePreviewWidget* m_textureMapButtons[(int)dust3d::TextureType::Count - 1] = { nullptr };
};
#endif

View File

@ -1,19 +1,17 @@
#ifndef DUST3D_APPLICATION_MATERIAL_LAYER_H_
#define DUST3D_APPLICATION_MATERIAL_LAYER_H_
#include <vector>
#include <dust3d/base/texture_type.h>
#include <dust3d/base/uuid.h>
#include <vector>
class MaterialMap
{
class MaterialMap {
public:
dust3d::TextureType forWhat;
dust3d::Uuid imageId;
};
class MaterialLayer
{
class MaterialLayer {
public:
std::vector<MaterialMap> maps;
float tileScale = 1.0;

View File

@ -1,15 +1,15 @@
#include "material_list_widget.h"
#include "document.h"
#include <QApplication>
#include <QClipboard>
#include <QGuiApplication>
#include <QMenu>
#include <QXmlStreamWriter>
#include <QClipboard>
#include <QApplication>
#include <dust3d/base/snapshot_xml.h>
#include "material_list_widget.h"
#include "document.h"
MaterialListWidget::MaterialListWidget(const Document *document, QWidget *parent) :
QTreeWidget(parent),
m_document(document)
MaterialListWidget::MaterialListWidget(const Document* document, QWidget* parent)
: QTreeWidget(parent)
, m_document(document)
{
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setFocusPolicy(Qt::NoFocus);
@ -59,7 +59,7 @@ void MaterialListWidget::updateMaterialSelectState(dust3d::Uuid materialId, bool
qDebug() << "Find material item failed:" << materialId;
return;
}
MaterialWidget *materialWidget = (MaterialWidget *)itemWidget(findItemResult->second.first, findItemResult->second.second);
MaterialWidget* materialWidget = (MaterialWidget*)itemWidget(findItemResult->second.first, findItemResult->second.second);
materialWidget->updateCheckedState(selected);
}
@ -90,7 +90,7 @@ void MaterialListWidget::selectMaterial(dust3d::Uuid materialId, bool multiple)
}
}
if (!m_selectedMaterialIds.empty()) {
for (const auto &id: m_selectedMaterialIds) {
for (const auto& id : m_selectedMaterialIds) {
updateMaterialSelectState(id, false);
}
m_selectedMaterialIds.clear();
@ -107,20 +107,20 @@ void MaterialListWidget::selectMaterial(dust3d::Uuid materialId, bool multiple)
}
}
void MaterialListWidget::mousePressEvent(QMouseEvent *event)
void MaterialListWidget::mousePressEvent(QMouseEvent* event)
{
QModelIndex itemIndex = indexAt(event->pos());
QTreeView::mousePressEvent(event);
if (event->button() == Qt::LeftButton) {
bool multiple = QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier);
if (itemIndex.isValid()) {
QTreeWidgetItem *item = itemFromIndex(itemIndex);
QTreeWidgetItem* item = itemFromIndex(itemIndex);
auto materialId = dust3d::Uuid(item->data(itemIndex.column(), Qt::UserRole).toString().toUtf8().constData());
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
bool startAdd = false;
bool stopAdd = false;
std::vector<dust3d::Uuid> waitQueue;
for (const auto &childId: m_document->materialIdList) {
for (const auto& childId : m_document->materialIdList) {
if (m_shiftStartMaterialId == childId || materialId == childId) {
if (startAdd) {
stopAdd = true;
@ -135,7 +135,7 @@ void MaterialListWidget::mousePressEvent(QMouseEvent *event)
}
if (stopAdd && !waitQueue.empty()) {
if (!m_selectedMaterialIds.empty()) {
for (const auto &id: m_selectedMaterialIds) {
for (const auto& id : m_selectedMaterialIds) {
updateMaterialSelectState(id, false);
}
m_selectedMaterialIds.clear();
@ -143,7 +143,7 @@ void MaterialListWidget::mousePressEvent(QMouseEvent *event)
if (!m_currentSelectedMaterialId.isNull()) {
m_currentSelectedMaterialId = dust3d::Uuid();
}
for (const auto &waitId: waitQueue) {
for (const auto& waitId : waitQueue) {
selectMaterial(waitId, true);
}
}
@ -161,11 +161,10 @@ void MaterialListWidget::mousePressEvent(QMouseEvent *event)
bool MaterialListWidget::isMaterialSelected(dust3d::Uuid materialId)
{
return (m_currentSelectedMaterialId == materialId ||
m_selectedMaterialIds.find(materialId) != m_selectedMaterialIds.end());
return (m_currentSelectedMaterialId == materialId || m_selectedMaterialIds.find(materialId) != m_selectedMaterialIds.end());
}
void MaterialListWidget::showContextMenu(const QPoint &pos)
void MaterialListWidget::showContextMenu(const QPoint& pos)
{
if (!m_hasContextMenu)
return;
@ -177,7 +176,7 @@ void MaterialListWidget::showContextMenu(const QPoint &pos)
unorderedMaterialIds.insert(m_currentSelectedMaterialId);
std::vector<dust3d::Uuid> materialIds;
for (const auto &cand: m_document->materialIdList) {
for (const auto& cand : m_document->materialIdList) {
if (unorderedMaterialIds.find(cand) != unorderedMaterialIds.end())
materialIds.push_back(cand);
}
@ -205,7 +204,7 @@ void MaterialListWidget::showContextMenu(const QPoint &pos)
QAction deleteAction(tr("Delete"), this);
if (!materialIds.empty()) {
connect(&deleteAction, &QAction::triggered, [=]() {
for (const auto &materialId: materialIds)
for (const auto& materialId : materialIds)
emit removeMaterial(materialId);
});
contextMenu.addAction(&deleteAction);
@ -214,7 +213,7 @@ void MaterialListWidget::showContextMenu(const QPoint &pos)
contextMenu.exec(mapToGlobal(pos));
}
void MaterialListWidget::resizeEvent(QResizeEvent *event)
void MaterialListWidget::resizeEvent(QResizeEvent* event)
{
QTreeWidget::resizeEvent(event);
if (calculateColumnCount() != columnCount())
@ -247,11 +246,11 @@ void MaterialListWidget::reload()
setColumnCount(columns);
for (int i = 0; i < columns; i++)
setColumnWidth(i, columnWidth);
std::vector<dust3d::Uuid> orderedMaterialIdList = m_document->materialIdList;
std::sort(orderedMaterialIdList.begin(), orderedMaterialIdList.end(), [&](const dust3d::Uuid &firstMaterialId, const dust3d::Uuid &secondMaterialId) {
const auto *firstMaterial = m_document->findMaterial(firstMaterialId);
const auto *secondMaterial = m_document->findMaterial(secondMaterialId);
std::sort(orderedMaterialIdList.begin(), orderedMaterialIdList.end(), [&](const dust3d::Uuid& firstMaterialId, const dust3d::Uuid& secondMaterialId) {
const auto* firstMaterial = m_document->findMaterial(firstMaterialId);
const auto* secondMaterial = m_document->findMaterial(secondMaterialId);
if (nullptr == firstMaterial || nullptr == secondMaterial)
return false;
return QString::compare(firstMaterial->name, secondMaterial->name, Qt::CaseInsensitive) < 0;
@ -259,13 +258,13 @@ void MaterialListWidget::reload()
decltype(orderedMaterialIdList.size()) materialIndex = 0;
while (materialIndex < orderedMaterialIdList.size()) {
QTreeWidgetItem *item = new QTreeWidgetItem(this);
QTreeWidgetItem* item = new QTreeWidgetItem(this);
item->setFlags((item->flags() | Qt::ItemIsEnabled) & ~(Qt::ItemIsSelectable) & ~(Qt::ItemIsEditable));
for (int col = 0; col < columns && materialIndex < orderedMaterialIdList.size(); col++, materialIndex++) {
const auto &materialId = orderedMaterialIdList[materialIndex];
const auto& materialId = orderedMaterialIdList[materialIndex];
item->setSizeHint(col, QSize(columnWidth, MaterialWidget::preferredHeight() + 2));
item->setData(col, Qt::UserRole, QString(materialId.toString().c_str()));
MaterialWidget *widget = new MaterialWidget(m_document, materialId);
MaterialWidget* widget = new MaterialWidget(m_document, materialId);
connect(widget, &MaterialWidget::modifyMaterial, this, &MaterialListWidget::modifyMaterial);
setItemWidget(item, col, widget);
widget->reload();
@ -301,9 +300,9 @@ void MaterialListWidget::copy()
dust3d::Snapshot snapshot;
m_document->toSnapshot(&snapshot, emptySet, DocumentToSnapshotFor::Materials,
limitMaterialIds);
std::string snapshotXml;
dust3d::saveSnapshotToXmlString(snapshot, snapshotXml);
QClipboard *clipboard = QApplication::clipboard();
QClipboard* clipboard = QApplication::clipboard();
clipboard->setText(snapshotXml.c_str());
}

View File

@ -1,41 +1,43 @@
#ifndef DUST3D_APPLICATION_MATERIAL_LIST_WIDGET_H_
#define DUST3D_APPLICATION_MATERIAL_LIST_WIDGET_H_
#include "material_widget.h"
#include <QMouseEvent>
#include <QTreeWidget>
#include <map>
#include <QMouseEvent>
#include "material_widget.h"
class Document;
class MaterialListWidget : public QTreeWidget
{
class MaterialListWidget : public QTreeWidget {
Q_OBJECT
signals:
void removeMaterial(dust3d::Uuid materialId);
void modifyMaterial(dust3d::Uuid materialId);
void cornerButtonClicked(dust3d::Uuid materialId);
void currentSelectedMaterialChanged(dust3d::Uuid materialId);
public:
MaterialListWidget(const Document *document, QWidget *parent=nullptr);
MaterialListWidget(const Document* document, QWidget* parent = nullptr);
bool isMaterialSelected(dust3d::Uuid materialId);
void enableMultipleSelection(bool enabled);
public slots:
void reload();
void removeAllContent();
void materialRemoved(dust3d::Uuid materialId);
void showContextMenu(const QPoint &pos);
void selectMaterial(dust3d::Uuid materialId, bool multiple=false);
void showContextMenu(const QPoint& pos);
void selectMaterial(dust3d::Uuid materialId, bool multiple = false);
void copy();
void setHasContextMenu(bool hasContextMenu);
protected:
void resizeEvent(QResizeEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
private:
int calculateColumnCount();
void updateMaterialSelectState(dust3d::Uuid materialId, bool selected);
const Document *m_document = nullptr;
std::map<dust3d::Uuid, std::pair<QTreeWidgetItem *, int>> m_itemMap;
const Document* m_document = nullptr;
std::map<dust3d::Uuid, std::pair<QTreeWidgetItem*, int>> m_itemMap;
std::set<dust3d::Uuid> m_selectedMaterialIds;
dust3d::Uuid m_currentSelectedMaterialId;
dust3d::Uuid m_shiftStartMaterialId;

View File

@ -1,34 +1,34 @@
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include "material_manage_widget.h"
#include "theme.h"
#include "material_edit_widget.h"
#include "info_label.h"
#include "document.h"
#include "info_label.h"
#include "material_edit_widget.h"
#include "theme.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QVBoxLayout>
MaterialManageWidget::MaterialManageWidget(const Document *document, QWidget *parent) :
QWidget(parent),
m_document(document)
MaterialManageWidget::MaterialManageWidget(const Document* document, QWidget* parent)
: QWidget(parent)
, m_document(document)
{
QPushButton *addMaterialButton = new QPushButton(Theme::awesome()->icon(fa::plus), tr("Add Material..."));
QPushButton* addMaterialButton = new QPushButton(Theme::awesome()->icon(fa::plus), tr("Add Material..."));
connect(addMaterialButton, &QPushButton::clicked, this, &MaterialManageWidget::showAddMaterialDialog);
QHBoxLayout *toolsLayout = new QHBoxLayout;
QHBoxLayout* toolsLayout = new QHBoxLayout;
toolsLayout->addWidget(addMaterialButton);
m_materialListWidget = new MaterialListWidget(document);
connect(m_materialListWidget, &MaterialListWidget::modifyMaterial, this, &MaterialManageWidget::showMaterialDialog);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addLayout(toolsLayout);
mainLayout->addWidget(m_materialListWidget);
setLayout(mainLayout);
}
MaterialListWidget *MaterialManageWidget::materialListWidget()
MaterialListWidget* MaterialManageWidget::materialListWidget()
{
return m_materialListWidget;
}
@ -45,10 +45,10 @@ void MaterialManageWidget::showAddMaterialDialog()
void MaterialManageWidget::showMaterialDialog(dust3d::Uuid materialId)
{
MaterialEditWidget *materialEditWidget = new MaterialEditWidget(m_document);
MaterialEditWidget* materialEditWidget = new MaterialEditWidget(m_document);
materialEditWidget->setAttribute(Qt::WA_DeleteOnClose);
if (!materialId.isNull()) {
const Material *material = m_document->findMaterial(materialId);
const Material* material = m_document->findMaterial(materialId);
if (nullptr != material) {
materialEditWidget->setEditMaterialId(materialId);
materialEditWidget->setEditMaterialName(material->name);
@ -58,7 +58,7 @@ void MaterialManageWidget::showMaterialDialog(dust3d::Uuid materialId)
}
materialEditWidget->show();
connect(materialEditWidget, &QDialog::destroyed, [=]() {
emit unregisterDialog((QWidget *)materialEditWidget);
emit unregisterDialog((QWidget*)materialEditWidget);
});
emit registerDialog((QWidget *)materialEditWidget);
emit registerDialog((QWidget*)materialEditWidget);
}

View File

@ -1,28 +1,30 @@
#ifndef DUST3D_APPLICATION_MATERIAL_MANAGE_WIDGET_H_
#define DUST3D_APPLICATION_MATERIAL_MANAGE_WIDGET_H_
#include <QWidget>
#include "material_list_widget.h"
#include <QWidget>
class Document;
class MaterialManageWidget : public QWidget
{
class MaterialManageWidget : public QWidget {
Q_OBJECT
signals:
void registerDialog(QWidget *widget);
void unregisterDialog(QWidget *widget);
void registerDialog(QWidget* widget);
void unregisterDialog(QWidget* widget);
public:
MaterialManageWidget(const Document *document, QWidget *parent=nullptr);
MaterialListWidget *materialListWidget();
MaterialManageWidget(const Document* document, QWidget* parent = nullptr);
MaterialListWidget* materialListWidget();
protected:
virtual QSize sizeHint() const;
public slots:
void showAddMaterialDialog();
void showMaterialDialog(dust3d::Uuid materialId);
private:
const Document *m_document = nullptr;
MaterialListWidget *m_materialListWidget = nullptr;
const Document* m_document = nullptr;
MaterialListWidget* m_materialListWidget = nullptr;
};
#endif

View File

@ -1,14 +1,14 @@
#include <QGuiApplication>
#include <QElapsedTimer>
#include "material_previews_generator.h"
#include "image_forever.h"
#include "mesh_generator.h"
#include "mesh_result_post_processor.h"
#include "texture_generator.h"
#include <QDebug>
#include <QElapsedTimer>
#include <QFile>
#include <QGuiApplication>
#include <dust3d/base/ds3_file.h>
#include <dust3d/base/snapshot_xml.h>
#include "material_previews_generator.h"
#include "mesh_generator.h"
#include "texture_generator.h"
#include "image_forever.h"
#include "mesh_result_post_processor.h"
MaterialPreviewsGenerator::MaterialPreviewsGenerator()
{
@ -16,78 +16,78 @@ MaterialPreviewsGenerator::MaterialPreviewsGenerator()
MaterialPreviewsGenerator::~MaterialPreviewsGenerator()
{
for (auto &item: m_previews) {
for (auto& item : m_previews) {
delete item.second;
}
}
void MaterialPreviewsGenerator::addMaterial(dust3d::Uuid materialId, const std::vector<MaterialLayer> &layers)
void MaterialPreviewsGenerator::addMaterial(dust3d::Uuid materialId, const std::vector<MaterialLayer>& layers)
{
m_materials.push_back({materialId, layers});
m_materials.push_back({ materialId, layers });
}
const std::set<dust3d::Uuid> &MaterialPreviewsGenerator::generatedPreviewMaterialIds()
const std::set<dust3d::Uuid>& MaterialPreviewsGenerator::generatedPreviewMaterialIds()
{
return m_generatedMaterialIds;
}
ModelMesh *MaterialPreviewsGenerator::takePreview(dust3d::Uuid materialId)
ModelMesh* MaterialPreviewsGenerator::takePreview(dust3d::Uuid materialId)
{
ModelMesh *resultMesh = m_previews[materialId];
ModelMesh* resultMesh = m_previews[materialId];
m_previews[materialId] = nullptr;
return resultMesh;
}
void MaterialPreviewsGenerator::generate()
{
dust3d::Snapshot *snapshot = new dust3d::Snapshot;
dust3d::Snapshot* snapshot = new dust3d::Snapshot;
QFile file(":/resources/material-demo-model.ds3");
file.open(QFile::ReadOnly);
QByteArray fileData = file.readAll();
std::vector<dust3d::Uuid> partIds;
dust3d::Ds3FileReader ds3Reader((const std::uint8_t *)fileData.data(), fileData.size());
dust3d::Ds3FileReader ds3Reader((const std::uint8_t*)fileData.data(), fileData.size());
for (int i = 0; i < (int)ds3Reader.items().size(); ++i) {
dust3d::Ds3ReaderItem item = ds3Reader.items().at(i);
if (item.type == "model") {
std::vector<std::uint8_t> data;
ds3Reader.loadItem(item.name, &data);
std::string xmlString((char *)data.data(), data.size());
dust3d::loadSnapshotFromXmlString(snapshot, (char *)xmlString.c_str());
for (const auto &item: snapshot->parts) {
std::string xmlString((char*)data.data(), data.size());
dust3d::loadSnapshotFromXmlString(snapshot, (char*)xmlString.c_str());
for (const auto& item : snapshot->parts) {
partIds.push_back(dust3d::Uuid(item.first));
}
}
}
dust3d::MeshGenerator::GeneratedCacheContext *cacheContext = new dust3d::MeshGenerator::GeneratedCacheContext();
MeshGenerator *meshGenerator = new MeshGenerator(snapshot);
dust3d::MeshGenerator::GeneratedCacheContext* cacheContext = new dust3d::MeshGenerator::GeneratedCacheContext();
MeshGenerator* meshGenerator = new MeshGenerator(snapshot);
meshGenerator->setGeneratedCacheContext(cacheContext);
meshGenerator->generate();
for (const auto &mirror: cacheContext->partMirrorIdMap) {
for (const auto& mirror : cacheContext->partMirrorIdMap) {
partIds.push_back(dust3d::Uuid(mirror.first));
}
dust3d::Object *object = meshGenerator->takeObject();
dust3d::Object* object = meshGenerator->takeObject();
if (nullptr != object) {
MeshResultPostProcessor *poseProcessor = new MeshResultPostProcessor(*object);
MeshResultPostProcessor* poseProcessor = new MeshResultPostProcessor(*object);
poseProcessor->poseProcess();
delete object;
object = poseProcessor->takePostProcessedObject();
delete poseProcessor;
}
if (nullptr != object) {
for (const auto &material: m_materials) {
TextureGenerator *textureGenerator = new TextureGenerator(*object);
for (const auto &layer: material.second) {
for (const auto &mapItem: layer.maps) {
const QImage *image = ImageForever::get(mapItem.imageId);
for (const auto& material : m_materials) {
TextureGenerator* textureGenerator = new TextureGenerator(*object);
for (const auto& layer : material.second) {
for (const auto& mapItem : layer.maps) {
const QImage* image = ImageForever::get(mapItem.imageId);
if (nullptr == image)
continue;
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
if (dust3d::TextureType::BaseColor == mapItem.forWhat)
textureGenerator->addPartColorMap(partId, image, layer.tileScale);
else if (dust3d::TextureType::Normal == mapItem.forWhat)
@ -102,7 +102,7 @@ void MaterialPreviewsGenerator::generate()
}
}
textureGenerator->generate();
ModelMesh *texturedResultMesh = textureGenerator->takeResultMesh();
ModelMesh* texturedResultMesh = textureGenerator->takeResultMesh();
if (nullptr != texturedResultMesh) {
m_previews[material.first] = new ModelMesh(*texturedResultMesh);
m_generatedMaterialIds.insert(material.first);
@ -111,9 +111,9 @@ void MaterialPreviewsGenerator::generate()
delete textureGenerator;
}
}
delete object;
delete meshGenerator;
delete cacheContext;
}

View File

@ -1,29 +1,29 @@
#ifndef DUST3D_APPLICATION_MATERIAL_PREVIEWS_GENERATOR_H_
#define DUST3D_APPLICATION_MATERIAL_PREVIEWS_GENERATOR_H_
#include "material_layer.h"
#include "model_mesh.h"
#include <QObject>
#include <map>
#include <vector>
#include "model_mesh.h"
#include "material_layer.h"
class MaterialPreviewsGenerator : public QObject
{
class MaterialPreviewsGenerator : public QObject {
Q_OBJECT
public:
MaterialPreviewsGenerator();
~MaterialPreviewsGenerator();
void addMaterial(dust3d::Uuid materialId, const std::vector<MaterialLayer> &layers);
const std::set<dust3d::Uuid> &generatedPreviewMaterialIds();
ModelMesh *takePreview(dust3d::Uuid materialId);
void addMaterial(dust3d::Uuid materialId, const std::vector<MaterialLayer>& layers);
const std::set<dust3d::Uuid>& generatedPreviewMaterialIds();
ModelMesh* takePreview(dust3d::Uuid materialId);
void generate();
signals:
void finished();
public slots:
void process();
private:
std::vector<std::pair<dust3d::Uuid, std::vector<MaterialLayer>>> m_materials;
std::map<dust3d::Uuid, ModelMesh *> m_previews;
std::map<dust3d::Uuid, ModelMesh*> m_previews;
std::set<dust3d::Uuid> m_generatedMaterialIds;
};

View File

@ -1,10 +1,10 @@
#include <QVBoxLayout>
#include "material_widget.h"
#include "document.h"
#include <QVBoxLayout>
MaterialWidget::MaterialWidget(const Document *document, dust3d::Uuid materialId) :
m_materialId(materialId),
m_document(document)
MaterialWidget::MaterialWidget(const Document* document, dust3d::Uuid materialId)
: m_materialId(materialId)
, m_document(document)
{
setObjectName("MaterialFrame");
@ -23,7 +23,7 @@ MaterialWidget::MaterialWidget(const Document *document, dust3d::Uuid materialId
nameFont.setBold(false);
m_nameLabel->setFont(nameFont);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addStretch();
mainLayout->addWidget(m_nameLabel);
@ -36,7 +36,7 @@ MaterialWidget::MaterialWidget(const Document *document, dust3d::Uuid materialId
connect(document, &Document::materialPreviewChanged, this, &MaterialWidget::updatePreview);
}
void MaterialWidget::resizeEvent(QResizeEvent *event)
void MaterialWidget::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
m_previewWidget->move((width() - Theme::materialPreviewImageSize) / 2, 0);
@ -57,12 +57,12 @@ void MaterialWidget::updatePreview(dust3d::Uuid materialId)
{
if (materialId != m_materialId)
return;
const Material *material = m_document->findMaterial(m_materialId);
const Material* material = m_document->findMaterial(m_materialId);
if (!material) {
qDebug() << "Material not found:" << m_materialId;
return;
}
ModelMesh *previewMesh = material->takePreviewMesh();
ModelMesh* previewMesh = material->takePreviewMesh();
m_previewWidget->updateMesh(previewMesh);
}
@ -70,7 +70,7 @@ void MaterialWidget::updateName(dust3d::Uuid materialId)
{
if (materialId != m_materialId)
return;
const Material *material = m_document->findMaterial(m_materialId);
const Material* material = m_document->findMaterial(m_materialId);
if (!material) {
qDebug() << "Material not found:" << m_materialId;
return;
@ -86,12 +86,12 @@ void MaterialWidget::updateCheckedState(bool checked)
setStyleSheet("#MaterialFrame {border: 1px solid transparent;}");
}
ModelWidget *MaterialWidget::previewWidget()
ModelWidget* MaterialWidget::previewWidget()
{
return m_previewWidget;
}
void MaterialWidget::mouseDoubleClickEvent(QMouseEvent *event)
void MaterialWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
QFrame::mouseDoubleClickEvent(event);
emit modifyMaterial(m_materialId);

View File

@ -1,36 +1,38 @@
#ifndef DUST3D_APPLICATION_MATERIAL_WIDGET_H_
#define DUST3D_APPLICATION_MATERIAL_WIDGET_H_
#include <QFrame>
#include <QLabel>
#include <QIcon>
#include <QPushButton>
#include "model_widget.h"
#include <QFrame>
#include <QIcon>
#include <QLabel>
#include <QPushButton>
class Document;
class MaterialWidget : public QFrame
{
class MaterialWidget : public QFrame {
Q_OBJECT
signals:
void modifyMaterial(dust3d::Uuid materialId);
public:
MaterialWidget(const Document *document, dust3d::Uuid materialId);
MaterialWidget(const Document* document, dust3d::Uuid materialId);
static int preferredHeight();
ModelWidget *previewWidget();
ModelWidget* previewWidget();
protected:
void mouseDoubleClickEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
public slots:
void reload();
void updatePreview(dust3d::Uuid materialId);
void updateName(dust3d::Uuid materialId);
void updateCheckedState(bool checked);
private:
dust3d::Uuid m_materialId;
const Document *m_document = nullptr;
ModelWidget *m_previewWidget = nullptr;
QLabel *m_nameLabel = nullptr;
const Document* m_document = nullptr;
ModelWidget* m_previewWidget = nullptr;
QLabel* m_nameLabel = nullptr;
};
#endif

View File

@ -1,13 +1,13 @@
#include <dust3d/mesh/smooth_normal.h>
#include <dust3d/mesh/trim_vertices.h>
#include <QElapsedTimer>
#include <QDebug>
#include "mesh_generator.h"
#include "cut_face_preview.h"
#include <QDebug>
#include <QElapsedTimer>
#include <dust3d/mesh/smooth_normal.h>
#include <dust3d/mesh/trim_vertices.h>
MeshGenerator::MeshGenerator(dust3d::Snapshot *snapshot) :
dust3d::MeshGenerator(snapshot)
MeshGenerator::MeshGenerator(dust3d::Snapshot* snapshot)
: dust3d::MeshGenerator(snapshot)
{
}
@ -15,12 +15,12 @@ MeshGenerator::~MeshGenerator()
{
}
std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>> *MeshGenerator::takeComponentPreviewMeshes()
std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>* MeshGenerator::takeComponentPreviewMeshes()
{
return m_componentPreviewMeshes.release();
}
MonochromeMesh *MeshGenerator::takeWireframeMesh()
MonochromeMesh* MeshGenerator::takeWireframeMesh()
{
return m_wireframeMesh.release();
}
@ -29,29 +29,28 @@ void MeshGenerator::process()
{
QElapsedTimer countTimeConsumed;
countTimeConsumed.start();
generate();
if (nullptr != m_object)
m_resultMesh = std::make_unique<ModelMesh>(*m_object);
m_componentPreviewMeshes = std::make_unique<std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>>();
for (const auto &componentId: m_generatedPreviewComponentIds) {
for (const auto& componentId : m_generatedPreviewComponentIds) {
auto it = m_generatedComponentPreviews.find(componentId);
if (it == m_generatedComponentPreviews.end())
continue;
dust3d::trimVertices(&it->second.vertices, true);
for (auto &it: it->second.vertices) {
for (auto& it : it->second.vertices) {
it *= 2.0;
}
std::vector<dust3d::Vector3> previewTriangleNormals;
previewTriangleNormals.reserve(it->second.triangles.size());
for (const auto &face: it->second.triangles) {
for (const auto& face : it->second.triangles) {
previewTriangleNormals.emplace_back(dust3d::Vector3::normal(
it->second.vertices[face[0]],
it->second.vertices[face[1]],
it->second.vertices[face[2]]
));
it->second.vertices[face[2]]));
}
std::vector<std::vector<dust3d::Vector3>> previewTriangleVertexNormals;
dust3d::smoothNormal(it->second.vertices,
@ -70,14 +69,13 @@ void MeshGenerator::process()
if (nullptr != m_object)
m_wireframeMesh = std::make_unique<MonochromeMesh>(*m_object);
qDebug() << "The mesh generation took" << countTimeConsumed.elapsed() << "milliseconds";
emit finished();
}
ModelMesh *MeshGenerator::takeResultMesh()
ModelMesh* MeshGenerator::takeResultMesh()
{
return m_resultMesh.release();
}

View File

@ -1,26 +1,26 @@
#ifndef DUST3D_APPLICATION_MESH_GENERATOR_H_
#define DUST3D_APPLICATION_MESH_GENERATOR_H_
#include <memory>
#include <QObject>
#include <QImage>
#include <dust3d/mesh/mesh_generator.h>
#include "model_mesh.h"
#include "monochrome_mesh.h"
#include <QImage>
#include <QObject>
#include <dust3d/mesh/mesh_generator.h>
#include <memory>
class MeshGenerator : public QObject, public dust3d::MeshGenerator
{
class MeshGenerator : public QObject, public dust3d::MeshGenerator {
Q_OBJECT
public:
MeshGenerator(dust3d::Snapshot *snapshot);
MeshGenerator(dust3d::Snapshot* snapshot);
~MeshGenerator();
ModelMesh *takeResultMesh();
std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>> *takeComponentPreviewMeshes();
MonochromeMesh *takeWireframeMesh();
ModelMesh* takeResultMesh();
std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>* takeComponentPreviewMeshes();
MonochromeMesh* takeWireframeMesh();
public slots:
void process();
signals:
void finished();
private:
std::unique_ptr<ModelMesh> m_resultMesh;
std::unique_ptr<std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>> m_componentPreviewMeshes;

View File

@ -1,20 +1,20 @@
#include <QDebug>
#include "mesh_preview_images_generator.h"
#include "theme.h"
#include <QDebug>
void MeshPreviewImagesGenerator::addInput(const dust3d::Uuid &inputId, std::unique_ptr<ModelMesh> previewMesh, bool useFrontView)
void MeshPreviewImagesGenerator::addInput(const dust3d::Uuid& inputId, std::unique_ptr<ModelMesh> previewMesh, bool useFrontView)
{
m_previewInputMap.insert({inputId, PreviewInput {std::move(previewMesh), useFrontView}});
m_previewInputMap.insert({ inputId, PreviewInput { std::move(previewMesh), useFrontView } });
}
void MeshPreviewImagesGenerator::process()
{
generate();
emit finished();
}
std::map<dust3d::Uuid, QImage> *MeshPreviewImagesGenerator::takeImages()
std::map<dust3d::Uuid, QImage>* MeshPreviewImagesGenerator::takeImages()
{
return m_partImages.release();
}
@ -22,10 +22,10 @@ std::map<dust3d::Uuid, QImage> *MeshPreviewImagesGenerator::takeImages()
void MeshPreviewImagesGenerator::generate()
{
m_partImages = std::make_unique<std::map<dust3d::Uuid, QImage>>();
m_offscreenRender->setZRotation(0);
m_offscreenRender->setEyePosition(QVector3D(0, 0, -4.0));
for (auto &it: m_previewInputMap) {
for (auto& it : m_previewInputMap) {
if (it.second.useFrontView) {
m_offscreenRender->setXRotation(0);
m_offscreenRender->setYRotation(0);

View File

@ -1,43 +1,42 @@
#ifndef DUST3D_APPLICATION_MESH_PREVIEW_IMAGES_GENERATOR_H_
#define DUST3D_APPLICATION_MESH_PREVIEW_IMAGES_GENERATOR_H_
#include <QObject>
#include <QImage>
#include <memory>
#include <map>
#include <dust3d/base/uuid.h>
#include "model_offscreen_render.h"
#include <QImage>
#include <QObject>
#include <dust3d/base/uuid.h>
#include <map>
#include <memory>
class MeshPreviewImagesGenerator : public QObject
{
class MeshPreviewImagesGenerator : public QObject {
Q_OBJECT
public:
MeshPreviewImagesGenerator(ModelOffscreenRender *modelOffscreenRender) :
m_offscreenRender(modelOffscreenRender)
MeshPreviewImagesGenerator(ModelOffscreenRender* modelOffscreenRender)
: m_offscreenRender(modelOffscreenRender)
{
}
struct PreviewInput
{
struct PreviewInput {
std::unique_ptr<ModelMesh> mesh;
bool useFrontView = false;
};
~MeshPreviewImagesGenerator()
{
delete m_offscreenRender;
}
void addInput(const dust3d::Uuid &inputId, std::unique_ptr<ModelMesh> previewMesh, bool useFrontView=false);
void addInput(const dust3d::Uuid& inputId, std::unique_ptr<ModelMesh> previewMesh, bool useFrontView = false);
void generate();
std::map<dust3d::Uuid, QImage> *takeImages();
std::map<dust3d::Uuid, QImage>* takeImages();
signals:
void finished();
public slots:
void process();
private:
std::map<dust3d::Uuid, PreviewInput> m_previewInputMap;
ModelOffscreenRender *m_offscreenRender = nullptr;
ModelOffscreenRender* m_offscreenRender = nullptr;
std::unique_ptr<std::map<dust3d::Uuid, QImage>> m_partImages;
};

View File

@ -1,9 +1,9 @@
#include <QGuiApplication>
#include <dust3d/uv/unwrap_uv.h>
#include <dust3d/mesh/resolve_triangle_tangent.h>
#include "mesh_result_post_processor.h"
#include <QGuiApplication>
#include <dust3d/mesh/resolve_triangle_tangent.h>
#include <dust3d/uv/unwrap_uv.h>
MeshResultPostProcessor::MeshResultPostProcessor(const dust3d::Object &object)
MeshResultPostProcessor::MeshResultPostProcessor(const dust3d::Object& object)
{
m_object = new dust3d::Object;
*m_object = object;
@ -14,9 +14,9 @@ MeshResultPostProcessor::~MeshResultPostProcessor()
delete m_object;
}
dust3d::Object *MeshResultPostProcessor::takePostProcessedObject()
dust3d::Object* MeshResultPostProcessor::takePostProcessedObject()
{
dust3d::Object *object = m_object;
dust3d::Object* object = m_object;
m_object = nullptr;
return object;
}
@ -32,7 +32,7 @@ void MeshResultPostProcessor::poseProcess()
m_object->setTriangleVertexUvs(triangleVertexUvs);
m_object->setPartUvRects(partUvRects);
}
{
std::vector<dust3d::Vector3> triangleTangents;
dust3d::resolveTriangleTangent(*m_object, triangleTangents);

View File

@ -4,20 +4,20 @@
#include <QObject>
#include <dust3d/base/object.h>
class MeshResultPostProcessor : public QObject
{
class MeshResultPostProcessor : public QObject {
Q_OBJECT
public:
MeshResultPostProcessor(const dust3d::Object &object);
MeshResultPostProcessor(const dust3d::Object& object);
~MeshResultPostProcessor();
dust3d::Object *takePostProcessedObject();
dust3d::Object* takePostProcessedObject();
void poseProcess();
signals:
void finished();
public slots:
void process();
private:
dust3d::Object *m_object = nullptr;
dust3d::Object* m_object = nullptr;
};
#endif

View File

@ -1,20 +1,19 @@
#include <assert.h>
#include <QTextStream>
#include <QFile>
#include <cmath>
#include "model_mesh.h"
#include "version.h"
#include <QFile>
#include <QTextStream>
#include <assert.h>
#include <cmath>
float ModelMesh::m_defaultMetalness = 0.0;
float ModelMesh::m_defaultRoughness = 1.0;
ModelMesh::ModelMesh(const ModelMesh &mesh) :
m_triangleVertices(nullptr),
m_triangleVertexCount(0),
m_textureImage(nullptr)
ModelMesh::ModelMesh(const ModelMesh& mesh)
: m_triangleVertices(nullptr)
, m_triangleVertexCount(0)
, m_textureImage(nullptr)
{
if (nullptr != mesh.m_triangleVertices &&
mesh.m_triangleVertexCount > 0) {
if (nullptr != mesh.m_triangleVertices && mesh.m_triangleVertexCount > 0) {
this->m_triangleVertices = new ModelOpenGLVertex[mesh.m_triangleVertexCount];
this->m_triangleVertexCount = mesh.m_triangleVertexCount;
for (int i = 0; i < mesh.m_triangleVertexCount; i++)
@ -42,39 +41,39 @@ void ModelMesh::removeColor()
{
delete this->m_textureImage;
this->m_textureImage = nullptr;
delete this->m_normalMapImage;
this->m_normalMapImage = nullptr;
delete this->m_metalnessRoughnessAmbientOcclusionMapImage;
this->m_metalnessRoughnessAmbientOcclusionMapImage = nullptr;
this->m_hasMetalnessInImage = false;
this->m_hasRoughnessInImage = false;
this->m_hasAmbientOcclusionInImage = false;
for (int i = 0; i < this->m_triangleVertexCount; ++i) {
auto &vertex = this->m_triangleVertices[i];
auto& vertex = this->m_triangleVertices[i];
vertex.colorR = 1.0;
vertex.colorG = 1.0;
vertex.colorB = 1.0;
}
}
ModelMesh::ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum) :
m_triangleVertices(triangleVertices),
m_triangleVertexCount(vertexNum),
m_textureImage(nullptr)
ModelMesh::ModelMesh(ModelOpenGLVertex* triangleVertices, int vertexNum)
: m_triangleVertices(triangleVertices)
, m_triangleVertexCount(vertexNum)
, m_textureImage(nullptr)
{
}
ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices,
const std::vector<std::vector<size_t>> &triangles,
const std::vector<std::vector<dust3d::Vector3>> &triangleVertexNormals,
const dust3d::Color &color,
ModelMesh::ModelMesh(const std::vector<dust3d::Vector3>& vertices,
const std::vector<std::vector<size_t>>& triangles,
const std::vector<std::vector<dust3d::Vector3>>& triangleVertexNormals,
const dust3d::Color& color,
float metalness,
float roughness,
const std::vector<std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/>> *vertexProperties)
const std::vector<std::tuple<dust3d::Color, float /*metalness*/, float /*roughness*/>>* vertexProperties)
{
m_triangleVertexCount = (int)triangles.size() * 3;
m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount];
@ -82,9 +81,9 @@ ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices,
for (size_t i = 0; i < triangles.size(); ++i) {
for (auto j = 0; j < 3; j++) {
int vertexIndex = (int)triangles[i][j];
const dust3d::Vector3 *srcVert = &vertices[vertexIndex];
const dust3d::Vector3 *srcNormal = &(triangleVertexNormals)[i][j];
ModelOpenGLVertex *dest = &m_triangleVertices[destIndex];
const dust3d::Vector3* srcVert = &vertices[vertexIndex];
const dust3d::Vector3* srcNormal = &(triangleVertexNormals)[i][j];
ModelOpenGLVertex* dest = &m_triangleVertices[destIndex];
dest->posX = srcVert->x();
dest->posY = srcVert->y();
dest->posZ = srcVert->z();
@ -101,7 +100,7 @@ ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices,
dest->metalness = metalness;
dest->roughness = roughness;
} else {
const auto &property = (*vertexProperties)[vertexIndex];
const auto& property = (*vertexProperties)[vertexIndex];
dest->colorR = std::get<0>(property).r();
dest->colorG = std::get<0>(property).g();
dest->colorB = std::get<0>(property).b();
@ -117,21 +116,21 @@ ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices,
}
}
ModelMesh::ModelMesh(dust3d::Object &object) :
m_triangleVertices(nullptr),
m_triangleVertexCount(0),
m_textureImage(nullptr)
ModelMesh::ModelMesh(dust3d::Object& object)
: m_triangleVertices(nullptr)
, m_triangleVertexCount(0)
, m_textureImage(nullptr)
{
m_meshId = object.meshId;
m_vertices = object.vertices;
m_faces = object.triangleAndQuads;
std::map<std::pair<dust3d::Uuid, dust3d::Uuid>, const dust3d::ObjectNode *> nodeMap;
std::map<std::pair<dust3d::Uuid, dust3d::Uuid>, const dust3d::ObjectNode*> nodeMap;
for (size_t i = 0; i < object.nodes.size(); ++i) {
const auto &node = object.nodes[i];
nodeMap.insert({{node.partId, node.nodeId}, &node});
const auto& node = object.nodes[i];
nodeMap.insert({ { node.partId, node.nodeId }, &node });
}
m_triangleVertexCount = (int)object.triangles.size() * 3;
m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount];
int destIndex = 0;
@ -142,20 +141,20 @@ ModelMesh::ModelMesh(dust3d::Object &object) :
const dust3d::Vector2 defaultUv = dust3d::Vector2(0, 0);
const dust3d::Vector3 defaultTangent = dust3d::Vector3(0, 0, 0);
for (size_t i = 0; i < object.triangles.size(); ++i) {
const auto &triangleColor = &object.triangleColors[i];
const auto& triangleColor = &object.triangleColors[i];
for (auto j = 0; j < 3; j++) {
int vertexIndex = (int)object.triangles[i][j];
const dust3d::Vector3 *srcVert = &object.vertices[vertexIndex];
const dust3d::Vector3 *srcNormal = &defaultNormal;
const dust3d::Vector3* srcVert = &object.vertices[vertexIndex];
const dust3d::Vector3* srcNormal = &defaultNormal;
if (triangleVertexNormals)
srcNormal = &(*triangleVertexNormals)[i][j];
const dust3d::Vector2 *srcUv = &defaultUv;
const dust3d::Vector2* srcUv = &defaultUv;
if (triangleVertexUvs)
srcUv = &(*triangleVertexUvs)[i][j];
const dust3d::Vector3 *srcTangent = &defaultTangent;
const dust3d::Vector3* srcTangent = &defaultTangent;
if (triangleTangents)
srcTangent = &(*triangleTangents)[i];
ModelOpenGLVertex *dest = &m_triangleVertices[destIndex];
ModelOpenGLVertex* dest = &m_triangleVertices[destIndex];
dest->colorR = triangleColor->r();
dest->colorG = triangleColor->g();
dest->colorB = triangleColor->b();
@ -184,10 +183,10 @@ ModelMesh::ModelMesh(dust3d::Object &object) :
}
}
ModelMesh::ModelMesh() :
m_triangleVertices(nullptr),
m_triangleVertexCount(0),
m_textureImage(nullptr)
ModelMesh::ModelMesh()
: m_triangleVertices(nullptr)
, m_triangleVertexCount(0)
, m_textureImage(nullptr)
{
}
@ -200,22 +199,22 @@ ModelMesh::~ModelMesh()
delete m_metalnessRoughnessAmbientOcclusionMapImage;
}
const std::vector<dust3d::Vector3> &ModelMesh::vertices()
const std::vector<dust3d::Vector3>& ModelMesh::vertices()
{
return m_vertices;
}
const std::vector<std::vector<size_t>> &ModelMesh::faces()
const std::vector<std::vector<size_t>>& ModelMesh::faces()
{
return m_faces;
}
const std::vector<dust3d::Vector3> &ModelMesh::triangulatedVertices()
const std::vector<dust3d::Vector3>& ModelMesh::triangulatedVertices()
{
return m_triangulatedVertices;
}
ModelOpenGLVertex *ModelMesh::triangleVertices()
ModelOpenGLVertex* ModelMesh::triangleVertices()
{
return m_triangleVertices;
}
@ -225,53 +224,53 @@ int ModelMesh::triangleVertexCount()
return m_triangleVertexCount;
}
void ModelMesh::setTextureImage(QImage *textureImage)
void ModelMesh::setTextureImage(QImage* textureImage)
{
m_textureImage = textureImage;
}
const QImage *ModelMesh::textureImage()
const QImage* ModelMesh::textureImage()
{
return m_textureImage;
}
QImage *ModelMesh::takeTextureImage()
QImage* ModelMesh::takeTextureImage()
{
auto image = m_textureImage;
m_textureImage = nullptr;
return image;
}
void ModelMesh::setNormalMapImage(QImage *normalMapImage)
void ModelMesh::setNormalMapImage(QImage* normalMapImage)
{
m_normalMapImage = normalMapImage;
}
const QImage *ModelMesh::normalMapImage()
const QImage* ModelMesh::normalMapImage()
{
return m_normalMapImage;
}
QImage *ModelMesh::takeNormalMapImage()
QImage* ModelMesh::takeNormalMapImage()
{
auto image = m_normalMapImage;
m_normalMapImage = nullptr;
return image;
}
const QImage *ModelMesh::metalnessRoughnessAmbientOcclusionMapImage()
const QImage* ModelMesh::metalnessRoughnessAmbientOcclusionMapImage()
{
return m_metalnessRoughnessAmbientOcclusionMapImage;
}
QImage *ModelMesh::takeMetalnessRoughnessAmbientOcclusionMapImage()
QImage* ModelMesh::takeMetalnessRoughnessAmbientOcclusionMapImage()
{
auto image = m_metalnessRoughnessAmbientOcclusionMapImage;
m_metalnessRoughnessAmbientOcclusionMapImage = nullptr;
return image;
}
void ModelMesh::setMetalnessRoughnessAmbientOcclusionMapImage(QImage *image)
void ModelMesh::setMetalnessRoughnessAmbientOcclusionMapImage(QImage* image)
{
m_metalnessRoughnessAmbientOcclusionMapImage = image;
}
@ -306,24 +305,24 @@ void ModelMesh::setHasAmbientOcclusionInImage(bool hasInImage)
m_hasAmbientOcclusionInImage = hasInImage;
}
void ModelMesh::exportAsObj(QTextStream *textStream)
void ModelMesh::exportAsObj(QTextStream* textStream)
{
auto &stream = *textStream;
auto& stream = *textStream;
stream << "# " << APP_NAME << " " << APP_HUMAN_VER << endl;
stream << "# " << APP_HOMEPAGE_URL << endl;
for (std::vector<dust3d::Vector3>::const_iterator it = vertices().begin() ; it != vertices().end(); ++it) {
for (std::vector<dust3d::Vector3>::const_iterator it = vertices().begin(); it != vertices().end(); ++it) {
stream << "v " << QString::number((*it).x()) << " " << QString::number((*it).y()) << " " << QString::number((*it).z()) << endl;
}
for (std::vector<std::vector<size_t>>::const_iterator it = faces().begin() ; it != faces().end(); ++it) {
for (std::vector<std::vector<size_t>>::const_iterator it = faces().begin(); it != faces().end(); ++it) {
stream << "f";
for (std::vector<size_t>::const_iterator subIt = (*it).begin() ; subIt != (*it).end(); ++subIt) {
for (std::vector<size_t>::const_iterator subIt = (*it).begin(); subIt != (*it).end(); ++subIt) {
stream << " " << QString::number((1 + *subIt));
}
stream << endl;
}
}
void ModelMesh::exportAsObj(const QString &filename)
void ModelMesh::exportAsObj(const QString& filename)
{
QFile file(filename);
if (file.open(QIODevice::WriteOnly)) {
@ -332,12 +331,12 @@ void ModelMesh::exportAsObj(const QString &filename)
}
}
void ModelMesh::updateTriangleVertices(ModelOpenGLVertex *triangleVertices, int triangleVertexCount)
void ModelMesh::updateTriangleVertices(ModelOpenGLVertex* triangleVertices, int triangleVertexCount)
{
delete[] m_triangleVertices;
m_triangleVertices = 0;
m_triangleVertexCount = 0;
m_triangleVertices = triangleVertices;
m_triangleVertexCount = triangleVertexCount;
}

View File

@ -1,44 +1,43 @@
#ifndef DUST3D_APPLICATION_MODEL_MESH_H_
#define DUST3D_APPLICATION_MODEL_MESH_H_
#include <QObject>
#include <vector>
#include "model_opengl_vertex.h"
#include <QImage>
#include <QObject>
#include <QTextStream>
#include <dust3d/base/vector3.h>
#include <dust3d/base/color.h>
#include <dust3d/base/object.h>
#include "model_opengl_vertex.h"
#include <dust3d/base/vector3.h>
#include <vector>
class ModelMesh
{
class ModelMesh {
public:
ModelMesh(const std::vector<dust3d::Vector3> &vertices,
const std::vector<std::vector<size_t>> &triangles,
const std::vector<std::vector<dust3d::Vector3>> &triangleVertexNormals,
const dust3d::Color &color=dust3d::Color::createWhite(),
float metalness=0.0,
float roughness=1.0,
const std::vector<std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/>> *vertexProperties=nullptr);
ModelMesh(dust3d::Object &object);
ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum);
ModelMesh(const ModelMesh &mesh);
ModelMesh(const std::vector<dust3d::Vector3>& vertices,
const std::vector<std::vector<size_t>>& triangles,
const std::vector<std::vector<dust3d::Vector3>>& triangleVertexNormals,
const dust3d::Color& color = dust3d::Color::createWhite(),
float metalness = 0.0,
float roughness = 1.0,
const std::vector<std::tuple<dust3d::Color, float /*metalness*/, float /*roughness*/>>* vertexProperties = nullptr);
ModelMesh(dust3d::Object& object);
ModelMesh(ModelOpenGLVertex* triangleVertices, int vertexNum);
ModelMesh(const ModelMesh& mesh);
ModelMesh();
~ModelMesh();
ModelOpenGLVertex *triangleVertices();
ModelOpenGLVertex* triangleVertices();
int triangleVertexCount();
const std::vector<dust3d::Vector3> &vertices();
const std::vector<std::vector<size_t>> &faces();
const std::vector<dust3d::Vector3> &triangulatedVertices();
void setTextureImage(QImage *textureImage);
const QImage *textureImage();
QImage *takeTextureImage();
void setNormalMapImage(QImage *normalMapImage);
const QImage *normalMapImage();
QImage *takeNormalMapImage();
const QImage *metalnessRoughnessAmbientOcclusionMapImage();
QImage *takeMetalnessRoughnessAmbientOcclusionMapImage();
void setMetalnessRoughnessAmbientOcclusionMapImage(QImage *image);
const std::vector<dust3d::Vector3>& vertices();
const std::vector<std::vector<size_t>>& faces();
const std::vector<dust3d::Vector3>& triangulatedVertices();
void setTextureImage(QImage* textureImage);
const QImage* textureImage();
QImage* takeTextureImage();
void setNormalMapImage(QImage* normalMapImage);
const QImage* normalMapImage();
QImage* takeNormalMapImage();
const QImage* metalnessRoughnessAmbientOcclusionMapImage();
QImage* takeMetalnessRoughnessAmbientOcclusionMapImage();
void setMetalnessRoughnessAmbientOcclusionMapImage(QImage* image);
bool hasMetalnessInImage();
void setHasMetalnessInImage(bool hasInImage);
bool hasRoughnessInImage();
@ -47,21 +46,22 @@ public:
void setHasAmbientOcclusionInImage(bool hasInImage);
static float m_defaultMetalness;
static float m_defaultRoughness;
void exportAsObj(const QString &filename);
void exportAsObj(QTextStream *textStream);
void updateTriangleVertices(ModelOpenGLVertex *triangleVertices, int triangleVertexCount);
void exportAsObj(const QString& filename);
void exportAsObj(QTextStream* textStream);
void updateTriangleVertices(ModelOpenGLVertex* triangleVertices, int triangleVertexCount);
quint64 meshId() const;
void setMeshId(quint64 id);
void removeColor();
private:
ModelOpenGLVertex *m_triangleVertices = nullptr;
ModelOpenGLVertex* m_triangleVertices = nullptr;
int m_triangleVertexCount = 0;
std::vector<dust3d::Vector3> m_vertices;
std::vector<std::vector<size_t>> m_faces;
std::vector<dust3d::Vector3> m_triangulatedVertices;
QImage *m_textureImage = nullptr;
QImage *m_normalMapImage = nullptr;
QImage *m_metalnessRoughnessAmbientOcclusionMapImage = nullptr;
QImage* m_textureImage = nullptr;
QImage* m_normalMapImage = nullptr;
QImage* m_metalnessRoughnessAmbientOcclusionMapImage = nullptr;
bool m_hasMetalnessInImage = false;
bool m_hasRoughnessInImage = false;
bool m_hasAmbientOcclusionInImage = false;

View File

@ -2,10 +2,10 @@
#include "model_opengl_object.h"
#include "model_opengl_program.h"
ModelOffscreenRender::ModelOffscreenRender(const QSurfaceFormat &format, QScreen *targetScreen):
QOffscreenSurface(targetScreen),
m_context(nullptr),
m_mesh(nullptr)
ModelOffscreenRender::ModelOffscreenRender(const QSurfaceFormat& format, QScreen* targetScreen)
: QOffscreenSurface(targetScreen)
, m_context(nullptr)
, m_mesh(nullptr)
{
setFormat(format);
create();
@ -13,11 +13,11 @@ ModelOffscreenRender::ModelOffscreenRender(const QSurfaceFormat &format, QScreen
ModelOffscreenRender::~ModelOffscreenRender()
{
// FIXME: If delete m_renderFbo inside toImage,
// FIXME: If delete m_renderFbo inside toImage,
// sometimes, the application will freeze, maybe there are dead locks inside the destruction call
// move it here can make sure it will be deleted on the main GUI thread to avoid dead locks
delete m_renderFbo;
destroy();
delete m_mesh;
}
@ -37,28 +37,28 @@ void ModelOffscreenRender::setZRotation(int angle)
m_zRot = angle;
}
void ModelOffscreenRender::setEyePosition(const QVector3D &eyePosition)
void ModelOffscreenRender::setEyePosition(const QVector3D& eyePosition)
{
m_eyePosition = eyePosition;
}
void ModelOffscreenRender::setMoveToPosition(const QVector3D &moveToPosition)
void ModelOffscreenRender::setMoveToPosition(const QVector3D& moveToPosition)
{
m_moveToPosition = moveToPosition;
}
void ModelOffscreenRender::setRenderThread(QThread *thread)
void ModelOffscreenRender::setRenderThread(QThread* thread)
{
moveToThread(thread);
}
void ModelOffscreenRender::updateMesh(ModelMesh *mesh)
void ModelOffscreenRender::updateMesh(ModelMesh* mesh)
{
delete m_mesh;
m_mesh = mesh;
}
QImage ModelOffscreenRender::toImage(const QSize &size)
QImage ModelOffscreenRender::toImage(const QSize& size)
{
QImage image;
@ -105,7 +105,7 @@ QImage ModelOffscreenRender::toImage(const QSize &size)
m_renderFbo = new QOpenGLFramebufferObject(size, format);
m_renderFbo->bind();
QOpenGLFunctions *f = m_context->functions();
QOpenGLFunctions* f = m_context->functions();
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
f->glEnable(GL_BLEND);
f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

View File

@ -1,34 +1,34 @@
#ifndef DUST3D_APPLICATION_MODEL_OFFSCREEN_RENDER_H_
#define DUST3D_APPLICATION_MODEL_OFFSCREEN_RENDER_H_
#include "model_mesh.h"
#include <QOffscreenSurface>
#include <QOpenGLFramebufferObject>
#include <QSurfaceFormat>
#include <QVector3D>
#include "model_mesh.h"
class ModelOffscreenRender: public QOffscreenSurface
{
class ModelOffscreenRender : public QOffscreenSurface {
public:
ModelOffscreenRender(const QSurfaceFormat &format, QScreen *targetScreen=Q_NULLPTR);
ModelOffscreenRender(const QSurfaceFormat& format, QScreen* targetScreen = Q_NULLPTR);
~ModelOffscreenRender();
void setXRotation(int angle);
void setYRotation(int angle);
void setZRotation(int angle);
void setEyePosition(const QVector3D &eyePosition);
void setMoveToPosition(const QVector3D &moveToPosition);
void setRenderThread(QThread *thread);
void updateMesh(ModelMesh *mesh);
QImage toImage(const QSize &size);
void setEyePosition(const QVector3D& eyePosition);
void setMoveToPosition(const QVector3D& moveToPosition);
void setRenderThread(QThread* thread);
void updateMesh(ModelMesh* mesh);
QImage toImage(const QSize& size);
private:
int m_xRot = 0;
int m_yRot = 0;
int m_zRot = 0;
QVector3D m_eyePosition;
QVector3D m_moveToPosition;
QOpenGLContext *m_context = nullptr;
QOpenGLFramebufferObject *m_renderFbo = nullptr;
ModelMesh *m_mesh = nullptr;
QOpenGLContext* m_context = nullptr;
QOpenGLFramebufferObject* m_renderFbo = nullptr;
ModelMesh* m_mesh = nullptr;
};
#endif

View File

@ -1,7 +1,7 @@
#include <dust3d/base/debug.h>
#include <QOpenGLFunctions>
#include <QOpenGLContext>
#include "model_opengl_object.h"
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <dust3d/base/debug.h>
void ModelOpenGLObject::update(std::unique_ptr<ModelMesh> mesh)
{
@ -15,7 +15,7 @@ void ModelOpenGLObject::draw()
copyMeshToOpenGL();
if (0 == m_meshTriangleVertexCount)
return;
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
QOpenGLVertexArrayObject::Binder binder(&m_vertexArrayObject);
f->glDrawArrays(GL_TRIANGLES, 0, m_meshTriangleVertexCount);
}
@ -43,7 +43,7 @@ void ModelOpenGLObject::copyMeshToOpenGL()
m_buffer.bind();
m_buffer.allocate(mesh->triangleVertices(), mesh->triangleVertexCount() * sizeof(ModelOpenGLVertex));
m_meshTriangleVertexCount = mesh->triangleVertexCount();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glEnableVertexAttribArray(2);
@ -53,13 +53,13 @@ void ModelOpenGLObject::copyMeshToOpenGL()
f->glEnableVertexAttribArray(6);
f->glEnableVertexAttribArray(7);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(9 * sizeof(GLfloat)));
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(9 * sizeof(GLfloat)));
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ModelOpenGLVertex), reinterpret_cast<void*>(16 * sizeof(GLfloat)));
m_buffer.release();
}
}

View File

@ -1,17 +1,17 @@
#ifndef DUST3D_APPLICATION_MODEL_OPENGL_OBJECT_H_
#define DUST3D_APPLICATION_MODEL_OPENGL_OBJECT_H_
#include <memory>
#include <QMutex>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include "model_mesh.h"
#include <QMutex>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <memory>
class ModelOpenGLObject
{
class ModelOpenGLObject {
public:
void update(std::unique_ptr<ModelMesh> mesh);
void draw();
private:
void copyMeshToOpenGL();
QOpenGLVertexArrayObject m_vertexArrayObject;

View File

@ -1,11 +1,11 @@
#include <QOpenGLFunctions>
#include <QFile>
#include <QMutexLocker>
#include <dust3d/base/debug.h>
#include "model_opengl_program.h"
#include "dds_file.h"
#include <QFile>
#include <QMutexLocker>
#include <QOpenGLFunctions>
#include <dust3d/base/debug.h>
static const QString &loadShaderSource(const QString &name)
static const QString& loadShaderSource(const QString& name)
{
static std::map<QString, QString> s_shaderSources;
auto findShader = s_shaderSources.find(name);
@ -15,11 +15,11 @@ static const QString &loadShaderSource(const QString &name)
QFile file(name);
file.open(QFile::ReadOnly | QFile::Text);
QTextStream stream(&file);
auto insertResult = s_shaderSources.insert({name, stream.readAll()});
auto insertResult = s_shaderSources.insert({ name, stream.readAll() });
return insertResult.first->second;
}
void ModelOpenGLProgram::addShaderFromResource(QOpenGLShader::ShaderType type, const char *resourceName)
void ModelOpenGLProgram::addShaderFromResource(QOpenGLShader::ShaderType type, const char* resourceName)
{
if (!addShaderFromSourceCode(type, loadShaderSource(resourceName)))
dust3dDebug << "Failed to addShaderFromResource, resource:" << resourceName << ", " << log().toStdString();
@ -57,7 +57,7 @@ void ModelOpenGLProgram::updateMetalnessRoughnessAmbientOcclusionMapImage(std::u
m_imageIsDirty = true;
}
void ModelOpenGLProgram::activeAndBindTexture(int location, QOpenGLTexture *texture)
void ModelOpenGLProgram::activeAndBindTexture(int location, QOpenGLTexture* texture)
{
if (0 == texture->textureId()) {
dust3dDebug << "Expected texture with a bound id";
@ -105,7 +105,7 @@ void ModelOpenGLProgram::bindMaps()
DdsFileReader irradianceFile(":/resources/cedar_bridge_specular.dds");
m_environmentSpecularMap.reset(irradianceFile.createOpenGLTexture());
}
bindLocation++;
activeAndBindTexture(bindLocation, m_environmentIrradianceMap.get());
setUniformValue(getUniformLocationByName("environmentIrradianceMapId"), bindLocation);
@ -224,12 +224,12 @@ void ModelOpenGLProgram::releaseMaps()
}
}
int ModelOpenGLProgram::getUniformLocationByName(const std::string &name)
int ModelOpenGLProgram::getUniformLocationByName(const std::string& name)
{
auto findLocation = m_uniformLocationMap.find(name);
if (findLocation != m_uniformLocationMap.end())
return findLocation->second;
int location = uniformLocation(name.c_str());
m_uniformLocationMap.insert({name, location});
m_uniformLocationMap.insert({ name, location });
return location;
}

View File

@ -1,30 +1,29 @@
#ifndef DUST3D_APPLICATION_MODEL_OPENGL_PROGRAM_H_
#define DUST3D_APPLICATION_MODEL_OPENGL_PROGRAM_H_
#include <memory>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLTexture>
#include <QMutex>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <memory>
class ModelOpenGLProgram: public QOpenGLShaderProgram
{
class ModelOpenGLProgram : public QOpenGLShaderProgram {
public:
void load(bool isCoreProfile=false);
int getUniformLocationByName(const std::string &name);
void load(bool isCoreProfile = false);
int getUniformLocationByName(const std::string& name);
bool isCoreProfile() const;
void bindMaps();
void releaseMaps();
void updateTextureImage(std::unique_ptr<QImage> image);
void updateNormalMapImage(std::unique_ptr<QImage> image);
void updateMetalnessRoughnessAmbientOcclusionMapImage(std::unique_ptr<QImage> image,
bool hasMetalnessMap = false,
bool hasRoughnessMap = false,
bool hasMetalnessMap = false,
bool hasRoughnessMap = false,
bool hasAmbientOcclusionMap = false);
private:
void addShaderFromResource(QOpenGLShader::ShaderType type, const char *resourceName);
void activeAndBindTexture(int location, QOpenGLTexture *texture);
void addShaderFromResource(QOpenGLShader::ShaderType type, const char* resourceName);
void activeAndBindTexture(int location, QOpenGLTexture* texture);
bool m_isLoaded = false;
bool m_isCoreProfile = false;

View File

@ -1,11 +1,11 @@
#include <QMouseEvent>
#include <QCoreApplication>
#include <QGuiApplication>
#include <cmath>
#include <QVector4D>
#include <QSurfaceFormat>
#include "model_widget.h"
#include "dds_file.h"
#include <QCoreApplication>
#include <QGuiApplication>
#include <QMouseEvent>
#include <QSurfaceFormat>
#include <QVector4D>
#include <cmath>
float ModelWidget::m_minZoomRatio = 5.0;
float ModelWidget::m_maxZoomRatio = 80.0;
@ -18,36 +18,36 @@ QString ModelWidget::m_openGLVersion = "";
QString ModelWidget::m_openGLShadingLanguageVersion = "";
bool ModelWidget::m_openGLIsCoreProfile = false;
ModelWidget::ModelWidget(QWidget *parent) :
QOpenGLWidget(parent)
ModelWidget::ModelWidget(QWidget* parent)
: QOpenGLWidget(parent)
{
setAttribute(Qt::WA_AlwaysStackOnTop);
setAttribute(Qt::WA_TranslucentBackground);
QSurfaceFormat fmt = format();
fmt.setAlphaBufferSize(8);
fmt.setSamples(4);
setFormat(fmt);
setContextMenuPolicy(Qt::CustomContextMenu);
m_widthInPixels = width() * window()->devicePixelRatio();
m_heightInPixels = height() * window()->devicePixelRatio();
m_heightInPixels = height() * window()->devicePixelRatio();
zoom(200);
}
const QVector3D &ModelWidget::eyePosition()
const QVector3D& ModelWidget::eyePosition()
{
return m_eyePosition;
return m_eyePosition;
}
const QVector3D &ModelWidget::moveToPosition()
const QVector3D& ModelWidget::moveToPosition()
{
return m_moveToPosition;
}
void ModelWidget::setEyePosition(const QVector3D &eyePosition)
void ModelWidget::setEyePosition(const QVector3D& eyePosition)
{
m_eyePosition = eyePosition;
emit eyePositionChanged(m_eyePosition);
@ -130,7 +130,7 @@ void ModelWidget::disableCullFace()
m_enableCullFace = false;
}
void ModelWidget::setMoveToPosition(const QVector3D &moveToPosition)
void ModelWidget::setMoveToPosition(const QVector3D& moveToPosition)
{
m_moveToPosition = moveToPosition;
}
@ -144,13 +144,13 @@ void ModelWidget::updateProjectionMatrix()
void ModelWidget::resizeGL(int w, int h)
{
m_widthInPixels = w * window()->devicePixelRatio();
m_heightInPixels = h * window()->devicePixelRatio();
m_widthInPixels = w * window()->devicePixelRatio();
m_heightInPixels = h * window()->devicePixelRatio();
updateProjectionMatrix();
emit renderParametersChanged();
}
std::pair<QVector3D, QVector3D> ModelWidget::screenPositionToMouseRay(const QPoint &screenPosition)
std::pair<QVector3D, QVector3D> ModelWidget::screenPositionToMouseRay(const QPoint& screenPosition)
{
auto modelView = m_camera * m_world;
float x = qMax(qMin(screenPosition.x(), width() - 1), 0);
@ -190,12 +190,11 @@ void ModelWidget::toggleRotation()
}
}
bool ModelWidget::inputMousePressEventFromOtherWidget(QMouseEvent *event, bool notGraphics)
bool ModelWidget::inputMousePressEventFromOtherWidget(QMouseEvent* event, bool notGraphics)
{
bool shouldStartMove = false;
if (event->button() == Qt::LeftButton) {
if ((notGraphics || QGuiApplication::queryKeyboardModifiers().testFlag(Qt::AltModifier)) &&
!QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
if ((notGraphics || QGuiApplication::queryKeyboardModifiers().testFlag(Qt::AltModifier)) && !QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
shouldStartMove = m_moveEnabled;
}
if (!shouldStartMove && !m_mousePickTargetPositionInModelSpace.isNull())
@ -216,7 +215,7 @@ bool ModelWidget::inputMousePressEventFromOtherWidget(QMouseEvent *event, bool n
return false;
}
bool ModelWidget::inputMouseReleaseEventFromOtherWidget(QMouseEvent *event)
bool ModelWidget::inputMouseReleaseEventFromOtherWidget(QMouseEvent* event)
{
Q_UNUSED(event);
if (m_moveStarted) {
@ -235,10 +234,10 @@ void ModelWidget::canvasResized()
resize(parentWidget()->size());
}
bool ModelWidget::inputMouseMoveEventFromOtherWidget(QMouseEvent *event)
bool ModelWidget::inputMouseMoveEventFromOtherWidget(QMouseEvent* event)
{
QPoint pos = convertInputPosFromOtherWidget(event);
if (m_mousePickingEnabled) {
auto segment = screenPositionToMouseRay(pos);
emit mouseRayChanged(segment.first, segment.second);
@ -247,12 +246,11 @@ bool ModelWidget::inputMouseMoveEventFromOtherWidget(QMouseEvent *event)
if (!m_moveStarted) {
return false;
}
int dx = pos.x() - m_lastPos.x();
int dy = pos.y() - m_lastPos.y();
if ((event->buttons() & Qt::MidButton) ||
(m_moveStarted && (event->buttons() & Qt::LeftButton))) {
if ((event->buttons() & Qt::MidButton) || (m_moveStarted && (event->buttons() & Qt::LeftButton))) {
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
if (m_moveStarted) {
if (m_moveAndZoomByWindow) {
@ -283,27 +281,27 @@ bool ModelWidget::inputMouseMoveEventFromOtherWidget(QMouseEvent *event)
}
}
m_lastPos = pos;
return true;
}
QPoint ModelWidget::convertInputPosFromOtherWidget(QMouseEvent *event)
QPoint ModelWidget::convertInputPosFromOtherWidget(QMouseEvent* event)
{
return mapFromGlobal(event->globalPos());
}
bool ModelWidget::inputWheelEventFromOtherWidget(QWheelEvent *event)
bool ModelWidget::inputWheelEventFromOtherWidget(QWheelEvent* event)
{
if (m_moveStarted)
return true;
if (m_mousePickingEnabled) {
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
emit addMouseRadius((float)event->delta() / 200 / height());
return true;
}
}
if (!m_zoomEnabled)
return false;
@ -311,7 +309,7 @@ bool ModelWidget::inputWheelEventFromOtherWidget(QWheelEvent *event)
if (event->delta() < 0)
delta = -delta;
zoom(delta);
return true;
}
@ -359,7 +357,7 @@ void ModelWidget::setMousePickRadius(float radius)
update();
}
void ModelWidget::updateMesh(ModelMesh *mesh)
void ModelWidget::updateMesh(ModelMesh* mesh)
{
if (!m_modelOpenGLProgram)
m_modelOpenGLProgram = std::make_unique<ModelOpenGLProgram>();
@ -369,7 +367,7 @@ void ModelWidget::updateMesh(ModelMesh *mesh)
mesh && mesh->hasMetalnessInImage(),
mesh && mesh->hasRoughnessInImage(),
mesh && mesh->hasAmbientOcclusionInImage());
if (!m_modelOpenGLObject)
m_modelOpenGLObject = std::make_unique<ModelOpenGLObject>();
m_modelOpenGLObject->update(std::unique_ptr<ModelMesh>(mesh));
@ -378,7 +376,7 @@ void ModelWidget::updateMesh(ModelMesh *mesh)
update();
}
void ModelWidget::updateWireframeMesh(MonochromeMesh *mesh)
void ModelWidget::updateWireframeMesh(MonochromeMesh* mesh)
{
if (!m_wireframeOpenGLObject)
m_wireframeOpenGLObject = std::make_unique<MonochromeOpenGLObject>();
@ -389,12 +387,12 @@ void ModelWidget::updateWireframeMesh(MonochromeMesh *mesh)
int ModelWidget::widthInPixels()
{
return m_widthInPixels;
return m_widthInPixels;
}
int ModelWidget::heightInPixels()
{
return m_heightInPixels;
return m_heightInPixels;
}
void ModelWidget::enableMove(bool enabled)
@ -417,22 +415,22 @@ void ModelWidget::setMoveAndZoomByWindow(bool byWindow)
m_moveAndZoomByWindow = byWindow;
}
void ModelWidget::mousePressEvent(QMouseEvent *event)
void ModelWidget::mousePressEvent(QMouseEvent* event)
{
inputMousePressEventFromOtherWidget(event, m_notGraphics);
}
void ModelWidget::mouseMoveEvent(QMouseEvent *event)
void ModelWidget::mouseMoveEvent(QMouseEvent* event)
{
inputMouseMoveEventFromOtherWidget(event);
}
void ModelWidget::wheelEvent(QWheelEvent *event)
void ModelWidget::wheelEvent(QWheelEvent* event)
{
inputWheelEventFromOtherWidget(event);
}
void ModelWidget::mouseReleaseEvent(QMouseEvent *event)
void ModelWidget::mouseReleaseEvent(QMouseEvent* event)
{
inputMouseReleaseEventFromOtherWidget(event);
}
@ -442,7 +440,7 @@ void ModelWidget::setNotGraphics(bool notGraphics)
m_notGraphics = notGraphics;
}
void ModelWidget::normalizeAngle(int &angle)
void ModelWidget::normalizeAngle(int& angle)
{
while (angle < 0)
angle += 360 * 16;
@ -455,10 +453,10 @@ void ModelWidget::initializeGL()
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ModelWidget::cleanup);
if (m_openGLVersion.isEmpty()) {
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
const char *openGLVersion = (const char *)f->glGetString(GL_VERSION);
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
const char* openGLVersion = (const char*)f->glGetString(GL_VERSION);
m_openGLVersion = nullptr != openGLVersion ? openGLVersion : "<Unknown>";
const char *shadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
const char* shadingLanguageVersion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
m_openGLShadingLanguageVersion = nullptr != shadingLanguageVersion ? shadingLanguageVersion : "<Unknown>";
m_openGLIsCoreProfile = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile;
}
@ -466,7 +464,7 @@ void ModelWidget::initializeGL()
void ModelWidget::paintGL()
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
f->glEnable(GL_BLEND);
@ -485,13 +483,13 @@ void ModelWidget::paintGL()
f->glEnable(GL_POLYGON_OFFSET_FILL);
f->glPolygonOffset(1.0, 1.0);
f->glViewport(0, 0, m_widthInPixels, m_heightInPixels);
f->glViewport(0, 0, m_widthInPixels, m_heightInPixels);
m_world.setToIdentity();
m_world.rotate(m_xRot / 16.0f, 1, 0, 0);
m_world.rotate(m_yRot / 16.0f, 0, 1, 0);
m_world.rotate(m_zRot / 16.0f, 0, 0, 1);
m_camera.setToIdentity();
m_camera.translate(m_eyePosition.x(), m_eyePosition.y(), m_eyePosition.z());
@ -506,7 +504,7 @@ void ModelWidget::paintGL()
m_monochromeOpenGLProgram->load(format().profile() == QSurfaceFormat::CoreProfile);
}
}
drawModel();
if (m_isWireframeVisible) {
drawWireframe();

View File

@ -1,27 +1,26 @@
#ifndef DUST3D_APPLICATION_MODEL_WIDGET_H_
#define DUST3D_APPLICATION_MODEL_WIDGET_H_
#include <memory>
#include <QOpenGLWidget>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include "model_mesh.h"
#include "model_opengl_object.h"
#include "model_opengl_program.h"
#include "monochrome_mesh.h"
#include "monochrome_opengl_object.h"
#include "monochrome_opengl_program.h"
#include <QMatrix4x4>
#include <QMutex>
#include <QVector2D>
#include <QTimer>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLWidget>
#include <QString>
#include "model_mesh.h"
#include "model_opengl_program.h"
#include "model_opengl_object.h"
#include "monochrome_mesh.h"
#include "monochrome_opengl_program.h"
#include "monochrome_opengl_object.h"
#include <QTimer>
#include <QVector2D>
#include <memory>
class ModelWidget : public QOpenGLWidget
{
class ModelWidget : public QOpenGLWidget {
Q_OBJECT
signals:
void mouseRayChanged(const QVector3D &near, const QVector3D &far);
void mouseRayChanged(const QVector3D& near, const QVector3D& far);
void mousePressed();
void mouseReleased();
void addMouseRadius(float radius);
@ -29,13 +28,14 @@ signals:
void xRotationChanged(int angle);
void yRotationChanged(int angle);
void zRotationChanged(int angle);
void eyePositionChanged(const QVector3D &eyePosition);
void moveToPositionChanged(const QVector3D &moveToPosition);
void eyePositionChanged(const QVector3D& eyePosition);
void moveToPositionChanged(const QVector3D& moveToPosition);
public:
ModelWidget(QWidget *parent = 0);
ModelWidget(QWidget* parent = 0);
~ModelWidget();
void updateMesh(ModelMesh *mesh);
void updateWireframeMesh(MonochromeMesh *mesh);
void updateMesh(ModelMesh* mesh);
void updateWireframeMesh(MonochromeMesh* mesh);
void toggleWireframe();
bool isWireframeVisible();
void toggleRotation();
@ -44,40 +44,42 @@ public:
void enableMousePicking(bool enabled);
void setMoveAndZoomByWindow(bool byWindow);
void disableCullFace();
void setMoveToPosition(const QVector3D &moveToPosition);
bool inputMousePressEventFromOtherWidget(QMouseEvent *event, bool notGraphics=false);
bool inputMouseMoveEventFromOtherWidget(QMouseEvent *event);
bool inputWheelEventFromOtherWidget(QWheelEvent *event);
bool inputMouseReleaseEventFromOtherWidget(QMouseEvent *event);
QPoint convertInputPosFromOtherWidget(QMouseEvent *event);
void setMoveToPosition(const QVector3D& moveToPosition);
bool inputMousePressEventFromOtherWidget(QMouseEvent* event, bool notGraphics = false);
bool inputMouseMoveEventFromOtherWidget(QMouseEvent* event);
bool inputWheelEventFromOtherWidget(QWheelEvent* event);
bool inputMouseReleaseEventFromOtherWidget(QMouseEvent* event);
QPoint convertInputPosFromOtherWidget(QMouseEvent* event);
int widthInPixels();
int heightInPixels();
void setNotGraphics(bool notGraphics);
int xRot();
int yRot();
int zRot();
const QVector3D &eyePosition();
const QVector3D &moveToPosition();
const QString &openGLVersion();
const QVector3D& eyePosition();
const QVector3D& moveToPosition();
const QString& openGLVersion();
public slots:
void setXRotation(int angle);
void setYRotation(int angle);
void setZRotation(int angle);
void setEyePosition(const QVector3D &eyePosition);
void setEyePosition(const QVector3D& eyePosition);
void cleanup();
void zoom(float delta);
void setMousePickTargetPositionInModelSpace(QVector3D position);
void setMousePickRadius(float radius);
void reRender();
void canvasResized();
protected:
void initializeGL() override;
void paintGL() override;
void resizeGL(int width, int height) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
private:
int m_xRot = m_defaultXRotation;
int m_yRot = m_defaultYRotation;
@ -103,7 +105,7 @@ private:
QPoint m_moveStartPos;
QRect m_moveStartGeometry;
int m_modelInitialHeight = 0;
QTimer *m_rotationTimer = nullptr;
QTimer* m_rotationTimer = nullptr;
int m_widthInPixels = 0;
int m_heightInPixels = 0;
QVector3D m_moveToPosition;
@ -111,11 +113,12 @@ private:
bool m_enableCullFace = true;
bool m_notGraphics = false;
bool m_isWireframeVisible = false;
std::pair<QVector3D, QVector3D> screenPositionToMouseRay(const QPoint &screenPosition);
std::pair<QVector3D, QVector3D> screenPositionToMouseRay(const QPoint& screenPosition);
void updateProjectionMatrix();
void normalizeAngle(int &angle);
void normalizeAngle(int& angle);
void drawModel();
void drawWireframe();
public:
static int m_defaultXRotation;
static int m_defaultYRotation;

View File

@ -1,59 +1,57 @@
#include <set>
#include "monochrome_mesh.h"
#include <set>
MonochromeMesh::MonochromeMesh(const MonochromeMesh &mesh)
MonochromeMesh::MonochromeMesh(const MonochromeMesh& mesh)
{
m_lineVertices = mesh.m_lineVertices;
}
MonochromeMesh::MonochromeMesh(MonochromeMesh &&mesh)
MonochromeMesh::MonochromeMesh(MonochromeMesh&& mesh)
{
m_lineVertices = std::move(mesh.m_lineVertices);
}
MonochromeMesh::MonochromeMesh(const dust3d::Object &object)
MonochromeMesh::MonochromeMesh(const dust3d::Object& object)
{
std::set<std::pair<size_t, size_t>> halfEdges;
for (const auto &face: object.triangleAndQuads) {
for (const auto& face : object.triangleAndQuads) {
if (3 == face.size()) {
halfEdges.insert({face[0], face[1]});
halfEdges.insert({face[1], face[0]});
halfEdges.insert({face[1], face[2]});
halfEdges.insert({face[2], face[1]});
halfEdges.insert({face[2], face[0]});
halfEdges.insert({face[0], face[2]});
halfEdges.insert({ face[0], face[1] });
halfEdges.insert({ face[1], face[0] });
halfEdges.insert({ face[1], face[2] });
halfEdges.insert({ face[2], face[1] });
halfEdges.insert({ face[2], face[0] });
halfEdges.insert({ face[0], face[2] });
continue;
}
halfEdges.insert({face[0], face[1]});
halfEdges.insert({face[1], face[0]});
halfEdges.insert({face[1], face[2]});
halfEdges.insert({face[2], face[1]});
halfEdges.insert({face[2], face[3]});
halfEdges.insert({face[3], face[2]});
halfEdges.insert({face[3], face[0]});
halfEdges.insert({face[0], face[3]});
halfEdges.insert({ face[0], face[1] });
halfEdges.insert({ face[1], face[0] });
halfEdges.insert({ face[1], face[2] });
halfEdges.insert({ face[2], face[1] });
halfEdges.insert({ face[2], face[3] });
halfEdges.insert({ face[3], face[2] });
halfEdges.insert({ face[3], face[0] });
halfEdges.insert({ face[0], face[3] });
}
m_lineVertices.reserve(halfEdges.size() * 2);
for (const auto &halfEdge: halfEdges) {
for (const auto& halfEdge : halfEdges) {
// For two halfedges shared one edge, only output one line
if (halfEdge.first > halfEdge.second)
continue;
const auto &from = object.vertices[halfEdge.first];
const auto &to = object.vertices[halfEdge.second];
const auto& from = object.vertices[halfEdge.first];
const auto& to = object.vertices[halfEdge.second];
m_lineVertices.emplace_back(MonochromeOpenGLVertex {
(GLfloat)from.x(),
(GLfloat)from.y(),
(GLfloat)from.z()
});
(GLfloat)from.x(),
(GLfloat)from.y(),
(GLfloat)from.z() });
m_lineVertices.emplace_back(MonochromeOpenGLVertex {
(GLfloat)to.x(),
(GLfloat)to.y(),
(GLfloat)to.z()
});
(GLfloat)to.x(),
(GLfloat)to.y(),
(GLfloat)to.z() });
}
}
const MonochromeOpenGLVertex *MonochromeMesh::lineVertices()
const MonochromeOpenGLVertex* MonochromeMesh::lineVertices()
{
if (m_lineVertices.empty())
return nullptr;

View File

@ -1,21 +1,20 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_MESH_H_
#define DUST3D_APPLICATION_MONOCHROME_MESH_H_
#include <memory>
#include <dust3d/base/object.h>
#include "monochrome_opengl_vertex.h"
#include <dust3d/base/object.h>
#include <memory>
class MonochromeMesh
{
class MonochromeMesh {
public:
MonochromeMesh(const MonochromeMesh &mesh);
MonochromeMesh(MonochromeMesh &&mesh);
MonochromeMesh(const dust3d::Object &object);
const MonochromeOpenGLVertex *lineVertices();
MonochromeMesh(const MonochromeMesh& mesh);
MonochromeMesh(MonochromeMesh&& mesh);
MonochromeMesh(const dust3d::Object& object);
const MonochromeOpenGLVertex* lineVertices();
int lineVertexCount();
private:
std::vector<MonochromeOpenGLVertex> m_lineVertices;
};
#endif

View File

@ -1,7 +1,7 @@
#include <dust3d/base/debug.h>
#include <QOpenGLFunctions>
#include <QOpenGLContext>
#include "monochrome_opengl_object.h"
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <dust3d/base/debug.h>
void MonochromeOpenGLObject::update(std::unique_ptr<MonochromeMesh> mesh)
{
@ -15,7 +15,7 @@ void MonochromeOpenGLObject::draw()
copyMeshToOpenGL();
if (0 == m_meshLineVertexCount)
return;
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
QOpenGLVertexArrayObject::Binder binder(&m_vertexArrayObject);
f->glDrawArrays(GL_LINES, 0, m_meshLineVertexCount);
}
@ -43,13 +43,13 @@ void MonochromeOpenGLObject::copyMeshToOpenGL()
m_buffer.bind();
m_buffer.allocate(mesh->lineVertices(), mesh->lineVertexCount() * sizeof(MonochromeOpenGLVertex));
m_meshLineVertexCount = mesh->lineVertexCount();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glEnableVertexAttribArray(2);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), reinterpret_cast<void*>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(MonochromeOpenGLVertex), reinterpret_cast<void*>(6 * sizeof(GLfloat)));
m_buffer.release();
}
}

View File

@ -1,17 +1,17 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_OPENGL_OBJECT_H_
#define DUST3D_APPLICATION_MONOCHROME_OPENGL_OBJECT_H_
#include <memory>
#include <QMutex>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include "monochrome_mesh.h"
#include <QMutex>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <memory>
class MonochromeOpenGLObject
{
class MonochromeOpenGLObject {
public:
void update(std::unique_ptr<MonochromeMesh> mesh);
void draw();
private:
void copyMeshToOpenGL();
QOpenGLVertexArrayObject m_vertexArrayObject;

View File

@ -1,9 +1,9 @@
#include <QOpenGLFunctions>
#include <QFile>
#include <dust3d/base/debug.h>
#include "monochrome_opengl_program.h"
#include <QFile>
#include <QOpenGLFunctions>
#include <dust3d/base/debug.h>
static const QString &loadShaderSource(const QString &name)
static const QString& loadShaderSource(const QString& name)
{
static std::map<QString, QString> s_shaderSources;
auto findShader = s_shaderSources.find(name);
@ -13,11 +13,11 @@ static const QString &loadShaderSource(const QString &name)
QFile file(name);
file.open(QFile::ReadOnly | QFile::Text);
QTextStream stream(&file);
auto insertResult = s_shaderSources.insert({name, stream.readAll()});
auto insertResult = s_shaderSources.insert({ name, stream.readAll() });
return insertResult.first->second;
}
void MonochromeOpenGLProgram::addShaderFromResource(QOpenGLShader::ShaderType type, const char *resourceName)
void MonochromeOpenGLProgram::addShaderFromResource(QOpenGLShader::ShaderType type, const char* resourceName)
{
if (!addShaderFromSourceCode(type, loadShaderSource(resourceName)))
dust3dDebug << "Failed to addShaderFromResource, resource:" << resourceName << ", " << log().toStdString();
@ -49,12 +49,12 @@ void MonochromeOpenGLProgram::load(bool isCoreProfile)
m_isLoaded = true;
}
int MonochromeOpenGLProgram::getUniformLocationByName(const std::string &name)
int MonochromeOpenGLProgram::getUniformLocationByName(const std::string& name)
{
auto findLocation = m_uniformLocationMap.find(name);
if (findLocation != m_uniformLocationMap.end())
return findLocation->second;
int location = uniformLocation(name.c_str());
m_uniformLocationMap.insert({name, location});
m_uniformLocationMap.insert({ name, location });
return location;
}

View File

@ -1,19 +1,18 @@
#ifndef DUST3D_APPLICATION_MONOCHROME_OPENGL_PROGRAM_H_
#define DUST3D_APPLICATION_MONOCHROME_OPENGL_PROGRAM_H_
#include <memory>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <memory>
class MonochromeOpenGLProgram: public QOpenGLShaderProgram
{
class MonochromeOpenGLProgram : public QOpenGLShaderProgram {
public:
void load(bool isCoreProfile=false);
int getUniformLocationByName(const std::string &name);
void load(bool isCoreProfile = false);
int getUniformLocationByName(const std::string& name);
bool isCoreProfile() const;
private:
void addShaderFromResource(QOpenGLShader::ShaderType type, const char *resourceName);
void addShaderFromResource(QOpenGLShader::ShaderType type, const char* resourceName);
bool m_isLoaded = false;
bool m_isCoreProfile = false;

View File

@ -1,27 +1,27 @@
#include <QVBoxLayout>
#include <QWidgetAction>
#include <QMenu>
#include "part_manage_widget.h"
#include "component_list_model.h"
#include "component_preview_grid_widget.h"
#include "component_property_widget.h"
#include "component_list_model.h"
#include "theme.h"
#include "document.h"
#include "theme.h"
#include <QMenu>
#include <QVBoxLayout>
#include <QWidgetAction>
PartManageWidget::PartManageWidget(Document *document, QWidget *parent):
QWidget(parent),
m_document(document)
PartManageWidget::PartManageWidget(Document* document, QWidget* parent)
: QWidget(parent)
, m_document(document)
{
setContextMenuPolicy(Qt::CustomContextMenu);
QHBoxLayout *toolsLayout = new QHBoxLayout;
QHBoxLayout* toolsLayout = new QHBoxLayout;
toolsLayout->setSpacing(0);
toolsLayout->setMargin(0);
setStyleSheet("QPushButton:disabled {border: 0; color: " + Theme::gray.name() + "}");
auto createButton = [](QChar icon, const QString &title) {
QPushButton *button = new QPushButton(icon);
auto createButton = [](QChar icon, const QString& title) {
QPushButton* button = new QPushButton(icon);
Theme::initIconButton(button);
button->setToolTip(title);
return button;
@ -58,50 +58,50 @@ PartManageWidget::PartManageWidget(Document *document, QWidget *parent):
//connect(m_componentPreviewGridWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &PartManageWidget::showSelectedComponentProperties);
connect(m_levelUpButton, &QPushButton::clicked, [this]() {
const auto &parent = m_document->findComponentParent(this->m_componentPreviewGridWidget->componentListModel()->listingComponentId());
const auto& parent = m_document->findComponentParent(this->m_componentPreviewGridWidget->componentListModel()->listingComponentId());
if (nullptr == parent)
return;
this->m_componentPreviewGridWidget->componentListModel()->setListingComponentId(parent->id);
});
connect(m_hideButton, &QPushButton::clicked, [this]() {
for (const auto &partId: this->m_componentPreviewGridWidget->getSelectedPartIds())
for (const auto& partId : this->m_componentPreviewGridWidget->getSelectedPartIds())
this->m_document->setPartVisibleState(partId, false);
this->m_document->saveSnapshot();
});
connect(m_showButton, &QPushButton::clicked, [this]() {
for (const auto &partId: this->m_componentPreviewGridWidget->getSelectedPartIds())
for (const auto& partId : this->m_componentPreviewGridWidget->getSelectedPartIds())
this->m_document->setPartVisibleState(partId, true);
this->m_document->saveSnapshot();
});
connect(m_unlockButton, &QPushButton::clicked, [this]() {
for (const auto &partId: this->m_componentPreviewGridWidget->getSelectedPartIds())
for (const auto& partId : this->m_componentPreviewGridWidget->getSelectedPartIds())
this->m_document->setPartLockState(partId, false);
this->m_document->saveSnapshot();
});
connect(m_lockButton, &QPushButton::clicked, [this]() {
for (const auto &partId: this->m_componentPreviewGridWidget->getSelectedPartIds())
for (const auto& partId : this->m_componentPreviewGridWidget->getSelectedPartIds())
this->m_document->setPartLockState(partId, true);
this->m_document->saveSnapshot();
});
connect(m_unlinkButton, &QPushButton::clicked, [this]() {
for (const auto &partId: this->m_componentPreviewGridWidget->getSelectedPartIds())
for (const auto& partId : this->m_componentPreviewGridWidget->getSelectedPartIds())
this->m_document->setPartDisableState(partId, true);
this->m_document->saveSnapshot();
});
connect(m_linkButton, &QPushButton::clicked, [this]() {
for (const auto &partId: this->m_componentPreviewGridWidget->getSelectedPartIds())
for (const auto& partId : this->m_componentPreviewGridWidget->getSelectedPartIds())
this->m_document->setPartDisableState(partId, false);
this->m_document->saveSnapshot();
});
connect(m_selectButton, &QPushButton::clicked, [this]() {
for (const auto &componentId: this->m_componentPreviewGridWidget->getSelectedComponentIds()) {
for (const auto& componentId : this->m_componentPreviewGridWidget->getSelectedComponentIds()) {
std::vector<dust3d::Uuid> partIds;
this->m_document->collectComponentDescendantParts(componentId, partIds);
for (const auto &partId: partIds)
for (const auto& partId : partIds)
emit this->selectPartOnCanvas(partId);
}
});
@ -119,7 +119,7 @@ PartManageWidget::PartManageWidget(Document *document, QWidget *parent):
connect(this, &PartManageWidget::customContextMenuRequested, this, &PartManageWidget::showContextMenu);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addLayout(toolsLayout);
mainLayout->addWidget(m_componentPreviewGridWidget);
@ -135,10 +135,10 @@ void PartManageWidget::showSelectedComponentProperties()
if (componentIds.empty())
return;
auto *propertyWidget = new ComponentPropertyWidget(m_document, componentIds);
auto* propertyWidget = new ComponentPropertyWidget(m_document, componentIds);
auto menu = std::make_unique<QMenu>(this->parentWidget());
QWidgetAction *widgetAction = new QWidgetAction(menu.get());
QWidgetAction* widgetAction = new QWidgetAction(menu.get());
widgetAction->setDefaultWidget(propertyWidget);
menu->addAction(widgetAction);
@ -146,14 +146,13 @@ void PartManageWidget::showSelectedComponentProperties()
if (x <= 0)
x = QCursor::pos().x();
menu->exec(QPoint(
x - propertyWidget->width(),
QCursor::pos().y()
));
x - propertyWidget->width(),
QCursor::pos().y()));
}
void PartManageWidget::selectComponentByPartId(const dust3d::Uuid &partId)
void PartManageWidget::selectComponentByPartId(const dust3d::Uuid& partId)
{
const auto &part = m_document->findPart(partId);
const auto& part = m_document->findPart(partId);
if (nullptr == part)
return;
auto componentId = part->componentId;
@ -163,7 +162,7 @@ void PartManageWidget::selectComponentByPartId(const dust3d::Uuid &partId)
m_componentPreviewGridWidget->scrollTo(index);
return;
}
const auto &component = m_document->findComponent(componentId);
const auto& component = m_document->findComponent(componentId);
if (nullptr == component)
return;
m_componentPreviewGridWidget->componentListModel()->setListingComponentId(component->parentId);
@ -178,7 +177,7 @@ void PartManageWidget::selectComponentByPartId(const dust3d::Uuid &partId)
void PartManageWidget::updateLevelUpButton()
{
const auto &parent = m_document->findComponentParent(m_componentPreviewGridWidget->componentListModel()->listingComponentId());
const auto& parent = m_document->findComponentParent(m_componentPreviewGridWidget->componentListModel()->listingComponentId());
m_levelUpButton->setEnabled(nullptr != parent);
}
@ -193,13 +192,13 @@ void PartManageWidget::updateToolButtons()
bool enableUnlinkButton = false;
bool enableLinkButton = false;
bool enablePropertyButton = false;
for (const auto &component: selectedComponents) {
for (const auto& component : selectedComponents) {
enablePropertyButton = true;
enableSelectButton = true;
if (component->linkToPartId.isNull()) {
continue;
}
const auto &part = m_document->findPart(component->linkToPartId);
const auto& part = m_document->findPart(component->linkToPartId);
if (part->visible) {
enableHideButton = true;
} else {
@ -229,14 +228,14 @@ void PartManageWidget::updateToolButtons()
bool PartManageWidget::hasSelectedGroupedComponent()
{
auto selectedComponents = m_componentPreviewGridWidget->getSelectedComponents();
for (auto &component: selectedComponents) {
for (auto& component : selectedComponents) {
if (!component->childrenIds.empty())
return true;
}
return false;
}
void PartManageWidget::showContextMenu(const QPoint &pos)
void PartManageWidget::showContextMenu(const QPoint& pos)
{
auto selectedComponentIds = m_componentPreviewGridWidget->getSelectedComponentIds();
if (selectedComponentIds.empty())
@ -255,7 +254,7 @@ void PartManageWidget::showContextMenu(const QPoint &pos)
QAction ungroupAction(tr("Ungroup"), this);
if (hasSelectedGroupedComponent()) {
connect(&ungroupAction, &QAction::triggered, this, [=]() {
for (const auto &it: selectedComponentIds)
for (const auto& it : selectedComponentIds)
emit this->ungroupComponent(it);
emit this->groupOperationAdded();
});

View File

@ -1,41 +1,42 @@
#ifndef DUST3D_APPLICATION_PART_MANAGE_WIDGET_H_
#define DUST3D_APPLICATION_PART_MANAGE_WIDGET_H_
#include <dust3d/base/uuid.h>
#include <QWidget>
#include <dust3d/base/uuid.h>
class Document;
class ComponentPreviewGridWidget;
class ComponentPropertyWidget;
class QPushButton;
class PartManageWidget: public QWidget
{
class PartManageWidget : public QWidget {
Q_OBJECT
signals:
void unselectAllOnCanvas();
void selectPartOnCanvas(const dust3d::Uuid &partId);
void groupComponents(const std::vector<dust3d::Uuid> &componentIds);
void ungroupComponent(const dust3d::Uuid &componentId);
void selectPartOnCanvas(const dust3d::Uuid& partId);
void groupComponents(const std::vector<dust3d::Uuid>& componentIds);
void ungroupComponent(const dust3d::Uuid& componentId);
void groupOperationAdded();
public slots:
void selectComponentByPartId(const dust3d::Uuid &partId);
void selectComponentByPartId(const dust3d::Uuid& partId);
void showSelectedComponentProperties();
void showContextMenu(const QPoint &pos);
void showContextMenu(const QPoint& pos);
public:
PartManageWidget(Document *document, QWidget *parent=nullptr);
PartManageWidget(Document* document, QWidget* parent = nullptr);
private:
Document *m_document = nullptr;
ComponentPreviewGridWidget *m_componentPreviewGridWidget = nullptr;
QPushButton *m_levelUpButton = nullptr;
QPushButton *m_selectButton = nullptr;
QPushButton *m_lockButton = nullptr;
QPushButton *m_unlockButton = nullptr;
QPushButton *m_showButton = nullptr;
QPushButton *m_hideButton = nullptr;
QPushButton *m_unlinkButton = nullptr;
QPushButton *m_linkButton = nullptr;
QPushButton *m_propertyButton = nullptr;
Document* m_document = nullptr;
ComponentPreviewGridWidget* m_componentPreviewGridWidget = nullptr;
QPushButton* m_levelUpButton = nullptr;
QPushButton* m_selectButton = nullptr;
QPushButton* m_lockButton = nullptr;
QPushButton* m_unlockButton = nullptr;
QPushButton* m_showButton = nullptr;
QPushButton* m_hideButton = nullptr;
QPushButton* m_unlinkButton = nullptr;
QPushButton* m_linkButton = nullptr;
QPushButton* m_propertyButton = nullptr;
void updateToolButtons();
void updateLevelUpButton();
bool hasSelectedGroupedComponent();

View File

@ -1,10 +1,10 @@
#include "preferences.h"
#define MAX_RECENT_FILES 7
#define MAX_RECENT_FILES 7
Preferences &Preferences::instance()
Preferences& Preferences::instance()
{
static Preferences *s_preferences = nullptr;
static Preferences* s_preferences = nullptr;
if (nullptr == s_preferences) {
s_preferences = new Preferences;
}
@ -40,15 +40,15 @@ int Preferences::maxRecentFiles() const
return MAX_RECENT_FILES;
}
void Preferences::setCurrentFile(const QString &fileName)
void Preferences::setCurrentFile(const QString& fileName)
{
QStringList files = m_settings.value("recentFileList").toStringList();
files.removeAll(fileName);
files.prepend(fileName);
while (files.size() > MAX_RECENT_FILES)
files.removeLast();
m_settings.setValue("recentFileList", files);
}
@ -57,6 +57,6 @@ void Preferences::reset()
auto files = m_settings.value("recentFileList").toStringList();
m_settings.clear();
m_settings.setValue("recentFileList", files);
loadDefault();
}

View File

@ -5,19 +5,19 @@
#include <QSize>
#include <QStringList>
class Preferences : public QObject
{
class Preferences : public QObject {
Q_OBJECT
public:
static Preferences &instance();
static Preferences& instance();
Preferences();
QSize documentWindowSize() const;
void setDocumentWindowSize(const QSize&);
QStringList recentFileList() const;
int maxRecentFiles() const;
public slots:
void setCurrentFile(const QString &fileName);
void setCurrentFile(const QString& fileName);
void reset();
private:
QSettings m_settings;
void loadDefault();

View File

@ -1,8 +1,8 @@
#include "preview_grid_view.h"
#include "theme.h"
PreviewGridView::PreviewGridView(QWidget *parent):
QListView(parent)
PreviewGridView::PreviewGridView(QWidget* parent)
: QListView(parent)
{
QPalette viewPalette = palette();
viewPalette.setColor(QPalette::Window, Qt::transparent);
@ -13,9 +13,7 @@ PreviewGridView::PreviewGridView(QWidget *parent):
auto margin = Theme::previewIconMargin;
auto borderRadius = Theme::previewIconBorderRadius;
setStyleSheet(
"QListView::item {border:" + QString::number(borderSize) + "px solid transparent; margin:" + QString::number(margin) + "px; background-color: " + Theme::gray.name() +"; border-radius: " + QString::number(borderRadius) + ";}" +
"QListView::item:selected {border-color: " + Theme::red.name() + ";}"
);
"QListView::item {border:" + QString::number(borderSize) + "px solid transparent; margin:" + QString::number(margin) + "px; background-color: " + Theme::gray.name() + "; border-radius: " + QString::number(borderRadius) + ";}" + "QListView::item:selected {border-color: " + Theme::red.name() + ";}");
setViewMode(QListView::IconMode);
setGridSize(QSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize));

View File

@ -3,11 +3,10 @@
#include <QListView>
class PreviewGridView: public QListView
{
class PreviewGridView : public QListView {
Q_OBJECT
public:
PreviewGridView(QWidget *parent=nullptr);
PreviewGridView(QWidget* parent = nullptr);
};
#endif

View File

@ -1,7 +1,7 @@
#include <QDebug>
#include "skeleton_document.h"
#include <QDebug>
const SkeletonNode *SkeletonDocument::findNode(dust3d::Uuid nodeId) const
const SkeletonNode* SkeletonDocument::findNode(dust3d::Uuid nodeId) const
{
auto it = nodeMap.find(nodeId);
if (it == nodeMap.end())
@ -9,7 +9,7 @@ const SkeletonNode *SkeletonDocument::findNode(dust3d::Uuid nodeId) const
return &it->second;
}
const SkeletonEdge *SkeletonDocument::findEdge(dust3d::Uuid edgeId) const
const SkeletonEdge* SkeletonDocument::findEdge(dust3d::Uuid edgeId) const
{
auto it = edgeMap.find(edgeId);
if (it == edgeMap.end())
@ -17,7 +17,7 @@ const SkeletonEdge *SkeletonDocument::findEdge(dust3d::Uuid edgeId) const
return &it->second;
}
const SkeletonPart *SkeletonDocument::findPart(dust3d::Uuid partId) const
const SkeletonPart* SkeletonDocument::findPart(dust3d::Uuid partId) const
{
auto it = partMap.find(partId);
if (it == partMap.end())
@ -25,9 +25,9 @@ const SkeletonPart *SkeletonDocument::findPart(dust3d::Uuid partId) const
return &it->second;
}
const SkeletonEdge *SkeletonDocument::findEdgeByNodes(dust3d::Uuid firstNodeId, dust3d::Uuid secondNodeId) const
const SkeletonEdge* SkeletonDocument::findEdgeByNodes(dust3d::Uuid firstNodeId, dust3d::Uuid secondNodeId) const
{
const SkeletonNode *firstNode = nullptr;
const SkeletonNode* firstNode = nullptr;
firstNode = findNode(firstNodeId);
if (nullptr == firstNode) {
return nullptr;
@ -43,18 +43,18 @@ const SkeletonEdge *SkeletonDocument::findEdgeByNodes(dust3d::Uuid firstNodeId,
return nullptr;
}
void SkeletonDocument::findAllNeighbors(dust3d::Uuid nodeId, std::set<dust3d::Uuid> &neighbors) const
void SkeletonDocument::findAllNeighbors(dust3d::Uuid nodeId, std::set<dust3d::Uuid>& neighbors) const
{
const auto &node = findNode(nodeId);
const auto& node = findNode(nodeId);
if (nullptr == node) {
return;
}
for (const auto &edgeId: node->edgeIds) {
const auto &edge = findEdge(edgeId);
for (const auto& edgeId : node->edgeIds) {
const auto& edge = findEdge(edgeId);
if (nullptr == edge) {
continue;
}
const auto &neighborNodeId = edge->neighborOf(nodeId);
const auto& neighborNodeId = edge->neighborOf(nodeId);
if (neighborNodeId.isNull()) {
continue;
}
@ -68,7 +68,7 @@ void SkeletonDocument::findAllNeighbors(dust3d::Uuid nodeId, std::set<dust3d::Uu
bool SkeletonDocument::isNodeConnectable(dust3d::Uuid nodeId) const
{
const auto &node = findNode(nodeId);
const auto& node = findNode(nodeId);
if (nullptr == node)
return false;
if (node->edgeIds.size() < 2)
@ -78,7 +78,7 @@ bool SkeletonDocument::isNodeConnectable(dust3d::Uuid nodeId) const
void SkeletonDocument::reduceNode(dust3d::Uuid nodeId)
{
const SkeletonNode *node = findNode(nodeId);
const SkeletonNode* node = findNode(nodeId);
if (nullptr == node) {
return;
}
@ -87,11 +87,11 @@ void SkeletonDocument::reduceNode(dust3d::Uuid nodeId)
}
dust3d::Uuid firstEdgeId = node->edgeIds[0];
dust3d::Uuid secondEdgeId = node->edgeIds[1];
const SkeletonEdge *firstEdge = findEdge(firstEdgeId);
const SkeletonEdge* firstEdge = findEdge(firstEdgeId);
if (nullptr == firstEdge) {
return;
}
const SkeletonEdge *secondEdge = findEdge(secondEdgeId);
const SkeletonEdge* secondEdge = findEdge(secondEdgeId);
if (nullptr == secondEdge) {
return;
}
@ -103,7 +103,7 @@ void SkeletonDocument::reduceNode(dust3d::Uuid nodeId)
void SkeletonDocument::breakEdge(dust3d::Uuid edgeId)
{
const SkeletonEdge *edge = findEdge(edgeId);
const SkeletonEdge* edge = findEdge(edgeId);
if (nullptr == edge) {
return;
}
@ -112,11 +112,11 @@ void SkeletonDocument::breakEdge(dust3d::Uuid edgeId)
}
dust3d::Uuid firstNodeId = edge->nodeIds[0];
dust3d::Uuid secondNodeId = edge->nodeIds[1];
const SkeletonNode *firstNode = findNode(firstNodeId);
const SkeletonNode* firstNode = findNode(firstNodeId);
if (nullptr == firstNode) {
return;
}
const SkeletonNode *secondNode = findNode(secondNodeId);
const SkeletonNode* secondNode = findNode(secondNodeId);
if (nullptr == secondNode) {
return;
}
@ -134,7 +134,7 @@ void SkeletonDocument::breakEdge(dust3d::Uuid edgeId)
void SkeletonDocument::reverseEdge(dust3d::Uuid edgeId)
{
SkeletonEdge *edge = (SkeletonEdge *)findEdge(edgeId);
SkeletonEdge* edge = (SkeletonEdge*)findEdge(edgeId);
if (nullptr == edge) {
return;
}
@ -151,13 +151,13 @@ void SkeletonDocument::reverseEdge(dust3d::Uuid edgeId)
void SkeletonDocument::removeEdge(dust3d::Uuid edgeId)
{
const SkeletonEdge *edge = findEdge(edgeId);
const SkeletonEdge* edge = findEdge(edgeId);
if (nullptr == edge) {
return;
}
if (isPartReadonly(edge->partId))
return;
const SkeletonPart *oldPart = findPart(edge->partId);
const SkeletonPart* oldPart = findPart(edge->partId);
if (nullptr == oldPart) {
return;
}
@ -169,7 +169,7 @@ void SkeletonDocument::removeEdge(dust3d::Uuid edgeId)
std::vector<dust3d::Uuid> newPartIds;
for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) {
const auto newUuid = dust3d::Uuid::createUuid();
SkeletonPart &part = partMap[newUuid];
SkeletonPart& part = partMap[newUuid];
part.id = newUuid;
part.copyAttributes(*oldPart);
part.name = nextPartName;
@ -189,7 +189,7 @@ void SkeletonDocument::removeEdge(dust3d::Uuid edgeId)
}
}
addPartToComponent(part.id, findComponentParentId(part.componentId));
newPartNodeNumMap.push_back({part.id, part.nodeIds.size()});
newPartNodeNumMap.push_back({ part.id, part.nodeIds.size() });
newPartIds.push_back(part.id);
emit partAdded(part.id);
}
@ -204,27 +204,26 @@ void SkeletonDocument::removeEdge(dust3d::Uuid edgeId)
edgeMap.erase(edgeId);
emit edgeRemoved(edgeId);
removePart(oldPartId);
if (!newPartNodeNumMap.empty()) {
std::sort(newPartNodeNumMap.begin(), newPartNodeNumMap.end(), [&](
const std::pair<dust3d::Uuid, size_t> &first, const std::pair<dust3d::Uuid, size_t> &second) {
std::sort(newPartNodeNumMap.begin(), newPartNodeNumMap.end(), [&](const std::pair<dust3d::Uuid, size_t>& first, const std::pair<dust3d::Uuid, size_t>& second) {
return first.second > second.second;
});
updateLinkedPart(oldPartId, newPartNodeNumMap[0].first);
}
emit skeletonChanged();
}
void SkeletonDocument::removeNode(dust3d::Uuid nodeId)
{
const SkeletonNode *node = findNode(nodeId);
const SkeletonNode* node = findNode(nodeId);
if (nullptr == node) {
return;
}
if (isPartReadonly(node->partId))
return;
const SkeletonPart *oldPart = findPart(node->partId);
const SkeletonPart* oldPart = findPart(node->partId);
if (nullptr == oldPart) {
return;
}
@ -236,7 +235,7 @@ void SkeletonDocument::removeNode(dust3d::Uuid nodeId)
std::vector<dust3d::Uuid> newPartIds;
for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) {
const auto newUuid = dust3d::Uuid::createUuid();
SkeletonPart &part = partMap[newUuid];
SkeletonPart& part = partMap[newUuid];
part.id = newUuid;
part.copyAttributes(*oldPart);
part.name = nextPartName;
@ -256,7 +255,7 @@ void SkeletonDocument::removeNode(dust3d::Uuid nodeId)
}
}
addPartToComponent(part.id, findComponentParentId(part.componentId));
newPartNodeNumMap.push_back({part.id, part.nodeIds.size()});
newPartNodeNumMap.push_back({ part.id, part.nodeIds.size() });
newPartIds.push_back(part.id);
emit partAdded(part.id);
}
@ -277,15 +276,14 @@ void SkeletonDocument::removeNode(dust3d::Uuid nodeId)
nodeMap.erase(nodeId);
emit nodeRemoved(nodeId);
removePart(oldPartId);
if (!newPartNodeNumMap.empty()) {
std::sort(newPartNodeNumMap.begin(), newPartNodeNumMap.end(), [&](
const std::pair<dust3d::Uuid, size_t> &first, const std::pair<dust3d::Uuid, size_t> &second) {
std::sort(newPartNodeNumMap.begin(), newPartNodeNumMap.end(), [&](const std::pair<dust3d::Uuid, size_t>& first, const std::pair<dust3d::Uuid, size_t>& second) {
return first.second > second.second;
});
updateLinkedPart(oldPartId, newPartNodeNumMap[0].first);
}
emit skeletonChanged();
}
@ -302,11 +300,11 @@ void SkeletonDocument::addNodeWithId(dust3d::Uuid nodeId, float x, float y, floa
dust3d::Uuid SkeletonDocument::createNode(dust3d::Uuid nodeId, float x, float y, float z, float radius, dust3d::Uuid fromNodeId)
{
dust3d::Uuid partId;
const SkeletonNode *fromNode = nullptr;
const SkeletonNode* fromNode = nullptr;
bool newPartAdded = false;
if (fromNodeId.isNull()) {
const auto newUuid = dust3d::Uuid::createUuid();
SkeletonPart &part = partMap[newUuid];
SkeletonPart& part = partMap[newUuid];
part.id = newUuid;
partId = part.id;
emit partAdded(partId);
@ -331,35 +329,35 @@ dust3d::Uuid SkeletonDocument::createNode(dust3d::Uuid nodeId, float x, float y,
node.setZ(z);
nodeMap[node.id] = node;
partMap[partId].nodeIds.push_back(node.id);
emit nodeAdded(node.id);
if (nullptr != fromNode) {
SkeletonEdge edge;
edge.partId = partId;
edge.nodeIds.push_back(fromNode->id);
edge.nodeIds.push_back(node.id);
edgeMap[edge.id] = edge;
nodeMap[node.id].edgeIds.push_back(edge.id);
nodeMap[fromNode->id].edgeIds.push_back(edge.id);
emit edgeAdded(edge.id);
}
if (newPartAdded)
addPartToComponent(partId, m_currentCanvasComponentId);
emit skeletonChanged();
return node.id;
}
void SkeletonDocument::joinNodeAndNeiborsToGroup(std::vector<dust3d::Uuid> *group, dust3d::Uuid nodeId, std::set<dust3d::Uuid> *visitMap, dust3d::Uuid noUseEdgeId)
void SkeletonDocument::joinNodeAndNeiborsToGroup(std::vector<dust3d::Uuid>* group, dust3d::Uuid nodeId, std::set<dust3d::Uuid>* visitMap, dust3d::Uuid noUseEdgeId)
{
if (nodeId.isNull() || visitMap->find(nodeId) != visitMap->end())
return;
const SkeletonNode *node = findNode(nodeId);
const SkeletonNode* node = findNode(nodeId);
if (nullptr == node) {
return;
}
@ -368,7 +366,7 @@ void SkeletonDocument::joinNodeAndNeiborsToGroup(std::vector<dust3d::Uuid> *grou
for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) {
if (noUseEdgeId == *edgeIt)
continue;
const SkeletonEdge *edge = findEdge(*edgeIt);
const SkeletonEdge* edge = findEdge(*edgeIt);
if (nullptr == edge) {
continue;
}
@ -378,14 +376,14 @@ void SkeletonDocument::joinNodeAndNeiborsToGroup(std::vector<dust3d::Uuid> *grou
}
}
void SkeletonDocument::splitPartByNode(std::vector<std::vector<dust3d::Uuid>> *groups, dust3d::Uuid nodeId)
void SkeletonDocument::splitPartByNode(std::vector<std::vector<dust3d::Uuid>>* groups, dust3d::Uuid nodeId)
{
const SkeletonNode *node = findNode(nodeId);
const SkeletonNode* node = findNode(nodeId);
std::set<dust3d::Uuid> visitMap;
visitMap.insert(nodeId);
for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) {
std::vector<dust3d::Uuid> group;
const SkeletonEdge *edge = findEdge(*edgeIt);
const SkeletonEdge* edge = findEdge(*edgeIt);
if (nullptr == edge) {
continue;
}
@ -395,9 +393,9 @@ void SkeletonDocument::splitPartByNode(std::vector<std::vector<dust3d::Uuid>> *g
}
}
void SkeletonDocument::splitPartByEdge(std::vector<std::vector<dust3d::Uuid>> *groups, dust3d::Uuid edgeId)
void SkeletonDocument::splitPartByEdge(std::vector<std::vector<dust3d::Uuid>>* groups, dust3d::Uuid edgeId)
{
const SkeletonEdge *edge = findEdge(edgeId);
const SkeletonEdge* edge = findEdge(edgeId);
if (nullptr == edge) {
return;
}
@ -410,17 +408,17 @@ void SkeletonDocument::splitPartByEdge(std::vector<std::vector<dust3d::Uuid>> *g
}
}
const SkeletonComponent *SkeletonDocument::findComponentParent(dust3d::Uuid componentId) const
const SkeletonComponent* SkeletonDocument::findComponentParent(dust3d::Uuid componentId) const
{
auto component = componentMap.find(componentId);
if (component == componentMap.end()) {
return nullptr;
}
if (component->second.parentId.isNull())
return &rootComponent;
return (SkeletonComponent *)findComponent(component->second.parentId);
return (SkeletonComponent*)findComponent(component->second.parentId);
}
dust3d::Uuid SkeletonDocument::findComponentParentId(dust3d::Uuid componentId) const
@ -429,18 +427,18 @@ dust3d::Uuid SkeletonDocument::findComponentParentId(dust3d::Uuid componentId) c
if (component == componentMap.end()) {
return dust3d::Uuid();
}
return component->second.parentId;
}
void SkeletonDocument::moveComponentUp(dust3d::Uuid componentId)
{
SkeletonComponent *parent = (SkeletonComponent *)findComponentParent(componentId);
SkeletonComponent* parent = (SkeletonComponent*)findComponentParent(componentId);
if (nullptr == parent)
return;
dust3d::Uuid parentId = findComponentParentId(componentId);
parent->moveChildUp(componentId);
parent->dirty = true;
emit componentChildrenChanged(parentId);
@ -449,12 +447,12 @@ void SkeletonDocument::moveComponentUp(dust3d::Uuid componentId)
void SkeletonDocument::moveComponentDown(dust3d::Uuid componentId)
{
SkeletonComponent *parent = (SkeletonComponent *)findComponentParent(componentId);
SkeletonComponent* parent = (SkeletonComponent*)findComponentParent(componentId);
if (nullptr == parent)
return;
dust3d::Uuid parentId = findComponentParentId(componentId);
parent->moveChildDown(componentId);
parent->dirty = true;
emit componentChildrenChanged(parentId);
@ -463,12 +461,12 @@ void SkeletonDocument::moveComponentDown(dust3d::Uuid componentId)
void SkeletonDocument::moveComponentToTop(dust3d::Uuid componentId)
{
SkeletonComponent *parent = (SkeletonComponent *)findComponentParent(componentId);
SkeletonComponent* parent = (SkeletonComponent*)findComponentParent(componentId);
if (nullptr == parent)
return;
dust3d::Uuid parentId = findComponentParentId(componentId);
parent->moveChildToTop(componentId);
parent->dirty = true;
emit componentChildrenChanged(parentId);
@ -477,12 +475,12 @@ void SkeletonDocument::moveComponentToTop(dust3d::Uuid componentId)
void SkeletonDocument::moveComponentToBottom(dust3d::Uuid componentId)
{
SkeletonComponent *parent = (SkeletonComponent *)findComponentParent(componentId);
SkeletonComponent* parent = (SkeletonComponent*)findComponentParent(componentId);
if (nullptr == parent)
return;
dust3d::Uuid parentId = findComponentParentId(componentId);
parent->moveChildToBottom(componentId);
parent->dirty = true;
emit componentChildrenChanged(parentId);
@ -495,10 +493,10 @@ void SkeletonDocument::renameComponent(dust3d::Uuid componentId, QString name)
if (component == componentMap.end()) {
return;
}
if (component->second.name == name)
return;
if (!name.trimmed().isEmpty())
component->second.name = name;
emit componentNameChanged(componentId);
@ -511,20 +509,20 @@ void SkeletonDocument::setComponentExpandState(dust3d::Uuid componentId, bool ex
if (component == componentMap.end()) {
return;
}
if (component->second.expanded == expanded)
return;
component->second.expanded = expanded;
emit componentExpandStateChanged(componentId);
emit optionsChanged();
}
void SkeletonDocument::ungroupComponent(const dust3d::Uuid &componentId)
void SkeletonDocument::ungroupComponent(const dust3d::Uuid& componentId)
{
if (componentId.isNull())
return;
SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId);
SkeletonComponent* component = (SkeletonComponent*)findComponent(componentId);
if (nullptr == component) {
dust3dDebug << "Component not found:" << componentId.toString();
return;
@ -532,15 +530,15 @@ void SkeletonDocument::ungroupComponent(const dust3d::Uuid &componentId)
if (component->childrenIds.empty())
return;
auto childrenIds = component->childrenIds;
SkeletonComponent *newParent = (SkeletonComponent *)findComponentParent(componentId);
SkeletonComponent* newParent = (SkeletonComponent*)findComponentParent(componentId);
if (nullptr == newParent) {
dust3dDebug << "Expected parent component to be found, component:" << componentId.toString();
return;
}
auto newParentId = newParent->id;
newParent->replaceChildWithOthers(componentId, childrenIds);
for (const auto &childId: childrenIds) {
SkeletonComponent *child = (SkeletonComponent *)findComponent(childId);
for (const auto& childId : childrenIds) {
SkeletonComponent* child = (SkeletonComponent*)findComponent(childId);
if (nullptr == child)
continue;
child->parentId = newParentId;
@ -551,7 +549,7 @@ void SkeletonDocument::ungroupComponent(const dust3d::Uuid &componentId)
emit skeletonChanged();
}
void SkeletonDocument::groupComponents(const std::vector<dust3d::Uuid> &componentIds)
void SkeletonDocument::groupComponents(const std::vector<dust3d::Uuid>& componentIds)
{
if (componentIds.empty())
return;
@ -563,7 +561,7 @@ void SkeletonDocument::groupComponents(const std::vector<dust3d::Uuid> &componen
auto it = componentIds.begin();
SkeletonComponent *oldParent = (SkeletonComponent *)findComponentParent(*it);
SkeletonComponent* oldParent = (SkeletonComponent*)findComponentParent(*it);
if (nullptr == oldParent) {
dust3dDebug << "Expected parent component to be found, component:" << it->toString();
return;
@ -574,7 +572,7 @@ void SkeletonDocument::groupComponents(const std::vector<dust3d::Uuid> &componen
oldParent->removeChild(*it);
}
for (const auto &componentId: componentIds) {
for (const auto& componentId : componentIds) {
auto component = componentMap.find(componentId);
if (component == componentMap.end()) {
continue;
@ -594,21 +592,21 @@ void SkeletonDocument::groupComponents(const std::vector<dust3d::Uuid> &componen
void SkeletonDocument::createNewChildComponent(dust3d::Uuid parentComponentId)
{
SkeletonComponent *parentComponent = (SkeletonComponent *)findComponent(parentComponentId);
SkeletonComponent* parentComponent = (SkeletonComponent*)findComponent(parentComponentId);
if (!parentComponent->linkToPartId.isNull()) {
parentComponentId = parentComponent->parentId;
parentComponent = (SkeletonComponent *)findComponent(parentComponentId);
parentComponent = (SkeletonComponent*)findComponent(parentComponentId);
}
SkeletonComponent newComponent(dust3d::Uuid::createUuid());
newComponent.name = tr("Group") + " " + QString::number(componentMap.size() - partMap.size() + 1);
parentComponent->addChild(newComponent.id);
newComponent.parentId = parentComponentId;
auto newComponentId = newComponent.id;
componentMap.emplace(newComponentId, std::move(newComponent));
emit componentChildrenChanged(parentComponentId);
emit componentAdded(newComponentId);
emit optionsChanged();
@ -620,12 +618,12 @@ void SkeletonDocument::removePart(dust3d::Uuid partId)
if (part == partMap.end()) {
return;
}
if (!part->second.componentId.isNull()) {
removeComponent(part->second.componentId);
return;
}
removePartDontCareComponent(partId);
}
@ -635,10 +633,10 @@ void SkeletonDocument::removePartDontCareComponent(dust3d::Uuid partId)
if (part == partMap.end()) {
return;
}
std::vector<dust3d::Uuid> removedNodeIds;
std::vector<dust3d::Uuid> removedEdgeIds;
for (auto nodeIt = nodeMap.begin(); nodeIt != nodeMap.end();) {
if (nodeIt->second.partId != partId) {
nodeIt++;
@ -647,7 +645,7 @@ void SkeletonDocument::removePartDontCareComponent(dust3d::Uuid partId)
removedNodeIds.push_back(nodeIt->second.id);
nodeIt = nodeMap.erase(nodeIt);
}
for (auto edgeIt = edgeMap.begin(); edgeIt != edgeMap.end();) {
if (edgeIt->second.partId != partId) {
edgeIt++;
@ -656,13 +654,13 @@ void SkeletonDocument::removePartDontCareComponent(dust3d::Uuid partId)
removedEdgeIds.push_back(edgeIt->second.id);
edgeIt = edgeMap.erase(edgeIt);
}
partMap.erase(part);
for (const auto &nodeId: removedNodeIds) {
for (const auto& nodeId : removedNodeIds) {
emit nodeRemoved(nodeId);
}
for (const auto &edgeId: removedEdgeIds) {
for (const auto& edgeId : removedEdgeIds) {
emit edgeRemoved(edgeId);
}
emit partRemoved(partId);
@ -671,7 +669,7 @@ void SkeletonDocument::removePartDontCareComponent(dust3d::Uuid partId)
void SkeletonDocument::addPartToComponent(dust3d::Uuid partId, dust3d::Uuid componentId)
{
SkeletonComponent child(dust3d::Uuid::createUuid());
if (!componentId.isNull()) {
auto parentComponent = componentMap.find(componentId);
if (parentComponent == componentMap.end()) {
@ -683,13 +681,13 @@ void SkeletonDocument::addPartToComponent(dust3d::Uuid partId, dust3d::Uuid comp
} else {
rootComponent.addChild(child.id);
}
partMap[partId].componentId = child.id;
child.linkToPartId = partId;
child.parentId = componentId;
auto childId = child.id;
componentMap.emplace(childId, std::move(child));
emit componentChildrenChanged(componentId);
emit componentAdded(childId);
}
@ -706,16 +704,16 @@ void SkeletonDocument::removeComponentRecursively(dust3d::Uuid componentId)
if (component == componentMap.end()) {
return;
}
if (!component->second.linkToPartId.isNull()) {
removePartDontCareComponent(component->second.linkToPartId);
}
auto childrenIds = component->second.childrenIds;
for (const auto &childId: childrenIds) {
for (const auto& childId : childrenIds) {
removeComponentRecursively(childId);
}
dust3d::Uuid parentId = component->second.parentId;
if (!parentId.isNull()) {
auto parentComponent = componentMap.find(parentId);
@ -726,7 +724,7 @@ void SkeletonDocument::removeComponentRecursively(dust3d::Uuid componentId)
} else {
rootComponent.removeChild(componentId);
}
componentMap.erase(component);
emit componentRemoved(componentId);
emit componentChildrenChanged(parentId);
@ -735,7 +733,7 @@ void SkeletonDocument::removeComponentRecursively(dust3d::Uuid componentId)
void SkeletonDocument::setCurrentCanvasComponentId(dust3d::Uuid componentId)
{
m_currentCanvasComponentId = componentId;
const SkeletonComponent *component = findComponent(m_currentCanvasComponentId);
const SkeletonComponent* component = findComponent(m_currentCanvasComponentId);
if (nullptr == component) {
m_currentCanvasComponentId = dust3d::Uuid();
} else {
@ -749,7 +747,7 @@ void SkeletonDocument::setCurrentCanvasComponentId(dust3d::Uuid componentId)
void SkeletonDocument::addComponent(dust3d::Uuid parentId)
{
SkeletonComponent component(dust3d::Uuid::createUuid());
if (!parentId.isNull()) {
auto parentComponent = componentMap.find(parentId);
if (parentComponent == componentMap.end()) {
@ -759,18 +757,18 @@ void SkeletonDocument::addComponent(dust3d::Uuid parentId)
} else {
rootComponent.addChild(component.id);
}
component.parentId = parentId;
auto componentId = component.id;
componentMap.emplace(componentId, std::move(component));
emit componentChildrenChanged(parentId);
emit componentAdded(componentId);
}
bool SkeletonDocument::isDescendantComponent(dust3d::Uuid componentId, dust3d::Uuid suspiciousId)
{
const SkeletonComponent *loopComponent = findComponentParent(suspiciousId);
const SkeletonComponent* loopComponent = findComponentParent(suspiciousId);
while (nullptr != loopComponent) {
if (loopComponent->id == componentId)
return true;
@ -788,13 +786,13 @@ void SkeletonDocument::moveComponent(dust3d::Uuid componentId, dust3d::Uuid toPa
if (component == componentMap.end()) {
return;
}
if (component->second.parentId == toParentId)
return;
if (isDescendantComponent(componentId, toParentId))
return;
if (component->second.parentId.isNull()) {
rootComponent.removeChild(componentId);
emit componentChildrenChanged(rootComponent.id);
@ -806,9 +804,9 @@ void SkeletonDocument::moveComponent(dust3d::Uuid componentId, dust3d::Uuid toPa
emit componentChildrenChanged(oldParent->second.id);
}
}
component->second.parentId = toParentId;
if (toParentId.isNull()) {
rootComponent.addChild(componentId);
emit componentChildrenChanged(rootComponent.id);
@ -820,7 +818,7 @@ void SkeletonDocument::moveComponent(dust3d::Uuid componentId, dust3d::Uuid toPa
emit componentChildrenChanged(newParent->second.id);
}
}
emit skeletonChanged();
}
@ -864,25 +862,25 @@ void SkeletonDocument::setPartDisableState(dust3d::Uuid partId, bool disabled)
emit skeletonChanged();
}
void SkeletonDocument::collectComponentDescendantParts(dust3d::Uuid componentId, std::vector<dust3d::Uuid> &partIds) const
void SkeletonDocument::collectComponentDescendantParts(dust3d::Uuid componentId, std::vector<dust3d::Uuid>& partIds) const
{
const SkeletonComponent *component = findComponent(componentId);
const SkeletonComponent* component = findComponent(componentId);
if (nullptr == component)
return;
if (!component->linkToPartId.isNull()) {
partIds.push_back(component->linkToPartId);
return;
}
for (const auto &childId: component->childrenIds) {
for (const auto& childId : component->childrenIds) {
collectComponentDescendantParts(childId, partIds);
}
}
void SkeletonDocument::collectComponentDescendantComponents(dust3d::Uuid componentId, std::vector<dust3d::Uuid> &componentIds) const
void SkeletonDocument::collectComponentDescendantComponents(dust3d::Uuid componentId, std::vector<dust3d::Uuid>& componentIds) const
{
const SkeletonComponent *component = findComponent(componentId);
const SkeletonComponent* component = findComponent(componentId);
if (nullptr == component)
return;
@ -890,7 +888,7 @@ void SkeletonDocument::collectComponentDescendantComponents(dust3d::Uuid compone
return;
}
for (const auto &childId: component->childrenIds) {
for (const auto& childId : component->childrenIds) {
componentIds.push_back(childId);
collectComponentDescendantComponents(childId, componentIds);
}
@ -901,10 +899,10 @@ void SkeletonDocument::hideOtherComponents(dust3d::Uuid componentId)
std::vector<dust3d::Uuid> partIds;
collectComponentDescendantParts(componentId, partIds);
std::set<dust3d::Uuid> partIdSet;
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
partIdSet.insert(partId);
}
for (const auto &part: partMap) {
for (const auto& part : partMap) {
if (partIdSet.find(part.first) != partIdSet.end())
continue;
setPartVisibleState(part.first, false);
@ -916,10 +914,10 @@ void SkeletonDocument::lockOtherComponents(dust3d::Uuid componentId)
std::vector<dust3d::Uuid> partIds;
collectComponentDescendantParts(componentId, partIds);
std::set<dust3d::Uuid> partIdSet;
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
partIdSet.insert(partId);
}
for (const auto &part: partMap) {
for (const auto& part : partMap) {
if (partIdSet.find(part.first) != partIdSet.end())
continue;
setPartLockState(part.first, true);
@ -928,14 +926,14 @@ void SkeletonDocument::lockOtherComponents(dust3d::Uuid componentId)
void SkeletonDocument::hideAllComponents()
{
for (const auto &part: partMap) {
for (const auto& part : partMap) {
setPartVisibleState(part.first, false);
}
}
void SkeletonDocument::showAllComponents()
{
for (const auto &part: partMap) {
for (const auto& part : partMap) {
setPartVisibleState(part.first, true);
}
}
@ -943,7 +941,7 @@ void SkeletonDocument::showAllComponents()
void SkeletonDocument::showOrHideAllComponents()
{
bool foundVisiblePart = false;
for (const auto &part: partMap) {
for (const auto& part : partMap) {
if (part.second.visible) {
foundVisiblePart = true;
}
@ -956,7 +954,7 @@ void SkeletonDocument::showOrHideAllComponents()
void SkeletonDocument::collapseAllComponents()
{
for (const auto &component: componentMap) {
for (const auto& component : componentMap) {
if (!component.second.linkToPartId.isNull())
continue;
setComponentExpandState(component.first, false);
@ -965,7 +963,7 @@ void SkeletonDocument::collapseAllComponents()
void SkeletonDocument::expandAllComponents()
{
for (const auto &component: componentMap) {
for (const auto& component : componentMap) {
if (!component.second.linkToPartId.isNull())
continue;
setComponentExpandState(component.first, true);
@ -974,14 +972,14 @@ void SkeletonDocument::expandAllComponents()
void SkeletonDocument::lockAllComponents()
{
for (const auto &part: partMap) {
for (const auto& part : partMap) {
setPartLockState(part.first, true);
}
}
void SkeletonDocument::unlockAllComponents()
{
for (const auto &part: partMap) {
for (const auto& part : partMap) {
setPartLockState(part.first, false);
}
}
@ -990,7 +988,7 @@ void SkeletonDocument::hideDescendantComponents(dust3d::Uuid componentId)
{
std::vector<dust3d::Uuid> partIds;
collectComponentDescendantParts(componentId, partIds);
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
setPartVisibleState(partId, false);
}
}
@ -999,7 +997,7 @@ void SkeletonDocument::showDescendantComponents(dust3d::Uuid componentId)
{
std::vector<dust3d::Uuid> partIds;
collectComponentDescendantParts(componentId, partIds);
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
setPartVisibleState(partId, true);
}
}
@ -1008,7 +1006,7 @@ void SkeletonDocument::lockDescendantComponents(dust3d::Uuid componentId)
{
std::vector<dust3d::Uuid> partIds;
collectComponentDescendantParts(componentId, partIds);
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
setPartLockState(partId, true);
}
}
@ -1017,7 +1015,7 @@ void SkeletonDocument::unlockDescendantComponents(dust3d::Uuid componentId)
{
std::vector<dust3d::Uuid> partIds;
collectComponentDescendantParts(componentId, partIds);
for (const auto &partId: partIds) {
for (const auto& partId : partIds) {
setPartLockState(partId, false);
}
}
@ -1042,7 +1040,7 @@ void SkeletonDocument::scaleNodeByAddRadius(dust3d::Uuid nodeId, float amount)
bool SkeletonDocument::isPartReadonly(dust3d::Uuid partId) const
{
const SkeletonPart *part = findPart(partId);
const SkeletonPart* part = findPart(partId);
if (nullptr == part) {
return true;
}
@ -1151,7 +1149,7 @@ void SkeletonDocument::switchNodeXZ(dust3d::Uuid nodeId)
emit skeletonChanged();
}
const SkeletonComponent *SkeletonDocument::findComponent(dust3d::Uuid componentId) const
const SkeletonComponent* SkeletonDocument::findComponent(dust3d::Uuid componentId) const
{
if (componentId.isNull())
return &rootComponent;
@ -1166,36 +1164,36 @@ void SkeletonDocument::addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId)
if (findEdgeByNodes(fromNodeId, toNodeId)) {
return;
}
const SkeletonNode *fromNode = nullptr;
const SkeletonNode *toNode = nullptr;
const SkeletonNode* fromNode = nullptr;
const SkeletonNode* toNode = nullptr;
bool toPartRemoved = false;
fromNode = findNode(fromNodeId);
if (nullptr == fromNode) {
return;
}
if (isPartReadonly(fromNode->partId))
return;
toNode = findNode(toNodeId);
if (nullptr == toNode) {
return;
}
if (isPartReadonly(toNode->partId))
return;
dust3d::Uuid toPartId = toNode->partId;
auto fromPart = partMap.find(fromNode->partId);
if (fromPart == partMap.end()) {
return;
}
fromPart->second.dirty = true;
if (fromNode->partId != toNode->partId) {
toPartRemoved = true;
std::vector<dust3d::Uuid> toGroup;
@ -1217,7 +1215,7 @@ void SkeletonDocument::addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId)
}
}
}
SkeletonEdge edge;
edge.partId = fromNode->partId;
edge.nodeIds.push_back(fromNode->id);
@ -1226,34 +1224,34 @@ void SkeletonDocument::addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId)
nodeMap[toNodeId].edgeIds.push_back(edge.id);
nodeMap[fromNode->id].edgeIds.push_back(edge.id);
emit edgeAdded(edge.id);
if (toPartRemoved) {
updateLinkedPart(toPartId, fromNode->partId);
removePart(toPartId);
}
emit skeletonChanged();
}
void SkeletonDocument::updateLinkedPart(dust3d::Uuid oldPartId, dust3d::Uuid newPartId)
{
for (auto &partIt: partMap) {
for (auto& partIt : partMap) {
if (partIt.second.cutFaceLinkedId == oldPartId) {
partIt.second.dirty = true;
partIt.second.setCutFaceLinkedId(newPartId);
}
}
std::set<dust3d::Uuid> dirtyPartIds;
for (auto &nodeIt: nodeMap) {
for (auto& nodeIt : nodeMap) {
if (nodeIt.second.cutFaceLinkedId == oldPartId) {
dirtyPartIds.insert(nodeIt.second.partId);
nodeIt.second.setCutFaceLinkedId(newPartId);
}
}
for (const auto &partId: dirtyPartIds) {
SkeletonPart *part = (SkeletonPart *)findPart(partId);
for (const auto& partId : dirtyPartIds) {
SkeletonPart* part = (SkeletonPart*)findPart(partId);
if (nullptr == part)
continue;
part->dirty = true;
@ -1272,17 +1270,17 @@ void SkeletonDocument::disableAllPositionRelatedLocks()
void SkeletonDocument::resetDirtyFlags()
{
for (auto &part: partMap) {
for (auto& part : partMap) {
part.second.dirty = false;
}
for (auto &component: componentMap) {
for (auto& component : componentMap) {
component.second.dirty = false;
}
}
void SkeletonDocument::markAllDirty()
{
for (auto &part: partMap) {
for (auto& part : partMap) {
part.second.dirty = true;
}
}
@ -1319,27 +1317,27 @@ void SkeletonDocument::setRadiusLockState(bool locked)
emit radiusLockStateChanged();
}
void SkeletonDocument::setComponentPreviewImage(const dust3d::Uuid &componentId, std::unique_ptr<QImage> image)
void SkeletonDocument::setComponentPreviewImage(const dust3d::Uuid& componentId, std::unique_ptr<QImage> image)
{
SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId);
SkeletonComponent* component = (SkeletonComponent*)findComponent(componentId);
if (nullptr == component)
return;
component->isPreviewImageDecorationObsolete = true;
component->previewImage = std::move(image);
}
void SkeletonDocument::setComponentPreviewPixmap(const dust3d::Uuid &componentId, const QPixmap &pixmap)
void SkeletonDocument::setComponentPreviewPixmap(const dust3d::Uuid& componentId, const QPixmap& pixmap)
{
SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId);
SkeletonComponent* component = (SkeletonComponent*)findComponent(componentId);
if (nullptr == component)
return;
component->previewPixmap = pixmap;
emit componentPreviewPixmapChanged(componentId);
}
void SkeletonDocument::setComponentPreviewMesh(const dust3d::Uuid &componentId, std::unique_ptr<ModelMesh> mesh)
void SkeletonDocument::setComponentPreviewMesh(const dust3d::Uuid& componentId, std::unique_ptr<ModelMesh> mesh)
{
SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId);
SkeletonComponent* component = (SkeletonComponent*)findComponent(componentId);
if (nullptr == component)
return;
component->updatePreviewMesh(std::move(mesh));

View File

@ -1,35 +1,34 @@
#ifndef DUST3D_APPLICATION_SKELETON_DOCUMENT_H_
#define DUST3D_APPLICATION_SKELETON_DOCUMENT_H_
#include <QObject>
#include <QString>
#include <cmath>
#include <QImage>
#include <QByteArray>
#include <QDebug>
#include <QVector3D>
#include <QPixmap>
#include <dust3d/base/uuid.h>
#include <dust3d/base/cut_face.h>
#include <dust3d/base/part_target.h>
#include <dust3d/base/part_base.h>
#include <dust3d/base/combine_mode.h>
#include "theme.h"
#include "model_mesh.h"
#include "debug.h"
#include "mesh_generator.h"
#include "model_mesh.h"
#include "theme.h"
#include <QByteArray>
#include <QDebug>
#include <QImage>
#include <QObject>
#include <QPixmap>
#include <QString>
#include <QVector3D>
#include <cmath>
#include <dust3d/base/combine_mode.h>
#include <dust3d/base/cut_face.h>
#include <dust3d/base/part_base.h>
#include <dust3d/base/part_target.h>
#include <dust3d/base/uuid.h>
class SkeletonNode
{
class SkeletonNode {
public:
SkeletonNode(const dust3d::Uuid &withId=dust3d::Uuid()) :
radius(0),
cutRotation(0.0),
cutFace(dust3d::CutFace::Quad),
hasCutFaceSettings(false),
m_x(0),
m_y(0),
m_z(0)
SkeletonNode(const dust3d::Uuid& withId = dust3d::Uuid())
: radius(0)
, cutRotation(0.0)
, cutFace(dust3d::CutFace::Quad)
, hasCutFaceSettings(false)
, m_x(0)
, m_y(0)
, m_z(0)
{
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
}
@ -56,7 +55,7 @@ public:
cutFaceLinkedId = dust3d::Uuid();
hasCutFaceSettings = true;
}
void setCutFaceLinkedId(const dust3d::Uuid &linkedId)
void setCutFaceLinkedId(const dust3d::Uuid& linkedId)
{
if (linkedId.isNull()) {
clearCutFaceSettings();
@ -73,21 +72,21 @@ public:
cutRotation = 0;
hasCutFaceSettings = false;
}
float getX(bool rotated=false) const
float getX(bool rotated = false) const
{
if (rotated)
return m_y;
return m_x;
}
float getY(bool rotated=false) const
float getY(bool rotated = false) const
{
if (rotated)
return m_x;
return m_y;
}
float getZ(bool rotated=false) const
float getZ(bool rotated = false) const
{
(void) rotated;
(void)rotated;
return m_z;
}
void setX(float x)
@ -123,16 +122,16 @@ public:
dust3d::Uuid cutFaceLinkedId;
bool hasCutFaceSettings;
std::vector<dust3d::Uuid> edgeIds;
private:
float m_x;
float m_y;
float m_z;
};
class SkeletonEdge
{
class SkeletonEdge {
public:
SkeletonEdge(const dust3d::Uuid &withId=dust3d::Uuid())
SkeletonEdge(const dust3d::Uuid& withId = dust3d::Uuid())
{
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
}
@ -148,8 +147,7 @@ public:
}
};
class SkeletonPart
{
class SkeletonPart {
public:
dust3d::Uuid id;
QString name;
@ -180,30 +178,30 @@ public:
float hollowThickness;
bool countershaded;
bool smooth;
SkeletonPart(const dust3d::Uuid &withId=dust3d::Uuid()) :
visible(true),
locked(false),
subdived(false),
disabled(false),
xMirrored(false),
base(dust3d::PartBase::Average),
deformThickness(1.0),
deformWidth(1.0),
deformUnified(false),
rounded(false),
chamfered(false),
color(Qt::white),
hasColor(false),
dirty(true),
cutRotation(0.0),
cutFace(dust3d::CutFace::Quad),
target(dust3d::PartTarget::Model),
colorSolubility(0.0),
metalness(0.0),
roughness(1.0),
hollowThickness(0.0),
countershaded(false),
smooth(false)
SkeletonPart(const dust3d::Uuid& withId = dust3d::Uuid())
: visible(true)
, locked(false)
, subdived(false)
, disabled(false)
, xMirrored(false)
, base(dust3d::PartBase::Average)
, deformThickness(1.0)
, deformWidth(1.0)
, deformUnified(false)
, rounded(false)
, chamfered(false)
, color(Qt::white)
, hasColor(false)
, dirty(true)
, cutRotation(0.0)
, cutFace(dust3d::CutFace::Quad)
, target(dust3d::PartTarget::Model)
, colorSolubility(0.0)
, metalness(0.0)
, roughness(1.0)
, hollowThickness(0.0)
, countershaded(false)
, smooth(false)
{
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
}
@ -296,7 +294,7 @@ public:
cutFace = face;
cutFaceLinkedId = dust3d::Uuid();
}
void setCutFaceLinkedId(const dust3d::Uuid &linkedId)
void setCutFaceLinkedId(const dust3d::Uuid& linkedId)
{
if (linkedId.isNull()) {
setCutFace(dust3d::CutFace::Quad);
@ -353,7 +351,7 @@ public:
{
return visible && !disabled;
}
void copyAttributes(const SkeletonPart &other)
void copyAttributes(const SkeletonPart& other)
{
visible = other.visible;
locked = other.locked;
@ -382,12 +380,12 @@ public:
smooth = other.smooth;
hollowThickness = other.hollowThickness;
}
private:
Q_DISABLE_COPY(SkeletonPart);
};
enum class SkeletonDocumentEditMode
{
enum class SkeletonDocumentEditMode {
Add = 0,
Select,
Paint,
@ -396,20 +394,18 @@ enum class SkeletonDocumentEditMode
ZoomOut
};
enum class SkeletonProfile
{
enum class SkeletonProfile {
Unknown = 0,
Main,
Side
};
class SkeletonComponent
{
class SkeletonComponent {
public:
SkeletonComponent()
{
}
SkeletonComponent(const dust3d::Uuid &withId, const QString &linkData=QString(), const QString &linkDataType=QString())
SkeletonComponent(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString())
{
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
if (!linkData.isEmpty()) {
@ -445,13 +441,13 @@ public:
m_childrenIdSet.insert(childId);
childrenIds.push_back(childId);
}
void replaceChildWithOthers(const dust3d::Uuid &childId, const std::vector<dust3d::Uuid> &others)
void replaceChildWithOthers(const dust3d::Uuid& childId, const std::vector<dust3d::Uuid>& others)
{
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
return;
m_childrenIdSet.erase(childId);
std::vector<dust3d::Uuid> candidates;
for (const auto &it: others) {
for (const auto& it : others) {
if (m_childrenIdSet.find(it) == m_childrenIdSet.end()) {
m_childrenIdSet.insert(it);
candidates.emplace_back(it);
@ -500,7 +496,7 @@ public:
if (it == childrenIds.end()) {
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == 0)
return;
@ -512,7 +508,7 @@ public:
if (it == childrenIds.end()) {
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == (int)childrenIds.size() - 1)
return;
@ -524,7 +520,7 @@ public:
if (it == childrenIds.end()) {
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == 0)
return;
@ -537,7 +533,7 @@ public:
if (it == childrenIds.end()) {
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == (int)childrenIds.size() - 1)
return;
@ -549,19 +545,19 @@ public:
m_previewMesh = std::move(mesh);
isPreviewMeshObsolete = true;
}
ModelMesh *takePreviewMesh() const
ModelMesh* takePreviewMesh() const
{
if (nullptr == m_previewMesh)
return nullptr;
return new ModelMesh(*m_previewMesh);
}
private:
std::unique_ptr<ModelMesh> m_previewMesh;
std::set<dust3d::Uuid> m_childrenIdSet;
};
class SkeletonDocument : public QObject
{
class SkeletonDocument : public QObject {
Q_OBJECT
signals:
void partAdded(dust3d::Uuid partId);
@ -576,8 +572,8 @@ signals:
void componentRemoved(dust3d::Uuid componentId);
void componentAdded(dust3d::Uuid componentId);
void componentExpandStateChanged(dust3d::Uuid componentId);
void componentPreviewMeshChanged(const dust3d::Uuid &componentId);
void componentPreviewPixmapChanged(const dust3d::Uuid &componentId);
void componentPreviewMeshChanged(const dust3d::Uuid& componentId);
void componentPreviewPixmapChanged(const dust3d::Uuid& componentId);
void nodeRemoved(dust3d::Uuid nodeId);
void edgeRemoved(dust3d::Uuid edgeId);
void nodeRadiusChanged(dust3d::Uuid nodeId);
@ -590,6 +586,7 @@ signals:
void ylockStateChanged();
void zlockStateChanged();
void radiusLockStateChanged();
public:
SkeletonDocumentEditMode editMode = SkeletonDocumentEditMode::Select;
bool xlocked = false;
@ -604,22 +601,22 @@ public:
std::map<dust3d::Uuid, SkeletonComponent> componentMap;
SkeletonComponent rootComponent;
const SkeletonNode *findNode(dust3d::Uuid nodeId) const;
const SkeletonEdge *findEdge(dust3d::Uuid edgeId) const;
const SkeletonPart *findPart(dust3d::Uuid partId) const;
const SkeletonEdge *findEdgeByNodes(dust3d::Uuid firstNodeId, dust3d::Uuid secondNodeId) const;
void findAllNeighbors(dust3d::Uuid nodeId, std::set<dust3d::Uuid> &neighbors) const;
const SkeletonNode* findNode(dust3d::Uuid nodeId) const;
const SkeletonEdge* findEdge(dust3d::Uuid edgeId) const;
const SkeletonPart* findPart(dust3d::Uuid partId) const;
const SkeletonEdge* findEdgeByNodes(dust3d::Uuid firstNodeId, dust3d::Uuid secondNodeId) const;
void findAllNeighbors(dust3d::Uuid nodeId, std::set<dust3d::Uuid>& neighbors) const;
bool isNodeConnectable(dust3d::Uuid nodeId) const;
const SkeletonComponent *findComponent(dust3d::Uuid componentId) const;
const SkeletonComponent *findComponentParent(dust3d::Uuid componentId) const;
const SkeletonComponent* findComponent(dust3d::Uuid componentId) const;
const SkeletonComponent* findComponentParent(dust3d::Uuid componentId) const;
dust3d::Uuid findComponentParentId(dust3d::Uuid componentId) const;
void collectComponentDescendantParts(dust3d::Uuid componentId, std::vector<dust3d::Uuid> &partIds) const;
void collectComponentDescendantComponents(dust3d::Uuid componentId, std::vector<dust3d::Uuid> &componentIds) const;
void setComponentPreviewMesh(const dust3d::Uuid &componentId, std::unique_ptr<ModelMesh> mesh);
void setComponentPreviewImage(const dust3d::Uuid &componentId, std::unique_ptr<QImage> image);
void collectComponentDescendantParts(dust3d::Uuid componentId, std::vector<dust3d::Uuid>& partIds) const;
void collectComponentDescendantComponents(dust3d::Uuid componentId, std::vector<dust3d::Uuid>& componentIds) const;
void setComponentPreviewMesh(const dust3d::Uuid& componentId, std::unique_ptr<ModelMesh> mesh);
void setComponentPreviewImage(const dust3d::Uuid& componentId, std::unique_ptr<QImage> image);
void resetDirtyFlags();
void markAllDirty();
virtual bool undoable() const = 0;
virtual bool redoable() const = 0;
virtual bool hasPastableNodesInClipboard() const = 0;
@ -628,31 +625,31 @@ public:
virtual bool isEdgeEditable(dust3d::Uuid edgeId) const = 0;
virtual bool isNodeDeactivated(dust3d::Uuid nodeId) const
{
(void) nodeId;
(void)nodeId;
return false;
};
virtual bool isEdgeDeactivated(dust3d::Uuid edgeId) const
{
(void) edgeId;
(void)edgeId;
return false;
};
virtual void copyNodes(std::set<dust3d::Uuid> nodeIdSet) const = 0;
float getOriginX(bool rotated=false) const
float getOriginX(bool rotated = false) const
{
if (rotated)
return m_originY;
return m_originX;
}
float getOriginY(bool rotated=false) const
float getOriginY(bool rotated = false) const
{
if (rotated)
return m_originX;
return m_originY;
}
float getOriginZ(bool rotated=false) const
float getOriginZ(bool rotated = false) const
{
(void) rotated;
(void)rotated;
return m_originZ;
}
void setOriginX(float originX)
@ -679,7 +676,7 @@ public:
{
m_originZ += originZ;
}
public slots:
virtual void undo() = 0;
virtual void redo() = 0;
@ -706,8 +703,8 @@ public slots:
void addComponent(dust3d::Uuid parentId);
void moveComponent(dust3d::Uuid componentId, dust3d::Uuid toParentId);
void setCurrentCanvasComponentId(dust3d::Uuid componentId);
void groupComponents(const std::vector<dust3d::Uuid> &componentIds);
void ungroupComponent(const dust3d::Uuid &componentId);
void groupComponents(const std::vector<dust3d::Uuid>& componentIds);
void ungroupComponent(const dust3d::Uuid& componentId);
void createNewChildComponent(dust3d::Uuid parentComponentId);
void setComponentExpandState(dust3d::Uuid componentId, bool expanded);
void hideOtherComponents(dust3d::Uuid componentId);
@ -723,7 +720,7 @@ public slots:
void showDescendantComponents(dust3d::Uuid componentId);
void lockDescendantComponents(dust3d::Uuid componentId);
void unlockDescendantComponents(dust3d::Uuid componentId);
void setComponentPreviewPixmap(const dust3d::Uuid &componentId, const QPixmap &pixmap);
void setComponentPreviewPixmap(const dust3d::Uuid& componentId, const QPixmap& pixmap);
void setPartLockState(dust3d::Uuid partId, bool locked);
void setPartVisibleState(dust3d::Uuid partId, bool visible);
void setPartDisableState(dust3d::Uuid partId, bool disabled);
@ -737,18 +734,18 @@ public slots:
void setYlockState(bool locked);
void setZlockState(bool locked);
void setRadiusLockState(bool locked);
private:
float m_originX = 0;
float m_originY = 0;
float m_originZ = 0;
dust3d::Uuid m_currentCanvasComponentId;
bool m_allPositionRelatedLocksEnabled = true;
void splitPartByNode(std::vector<std::vector<dust3d::Uuid>> *groups, dust3d::Uuid nodeId);
void joinNodeAndNeiborsToGroup(std::vector<dust3d::Uuid> *group, dust3d::Uuid nodeId, std::set<dust3d::Uuid> *visitMap, dust3d::Uuid noUseEdgeId=dust3d::Uuid());
void splitPartByEdge(std::vector<std::vector<dust3d::Uuid>> *groups, dust3d::Uuid edgeId);
void splitPartByNode(std::vector<std::vector<dust3d::Uuid>>* groups, dust3d::Uuid nodeId);
void joinNodeAndNeiborsToGroup(std::vector<dust3d::Uuid>* group, dust3d::Uuid nodeId, std::set<dust3d::Uuid>* visitMap, dust3d::Uuid noUseEdgeId = dust3d::Uuid());
void splitPartByEdge(std::vector<std::vector<dust3d::Uuid>>* groups, dust3d::Uuid edgeId);
void removePartDontCareComponent(dust3d::Uuid partId);
void addPartToComponent(dust3d::Uuid partId, dust3d::Uuid componentId);
bool isDescendantComponent(dust3d::Uuid componentId, dust3d::Uuid suspiciousId);

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,31 @@
#ifndef DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
#define DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
#include <map>
#include <QMouseEvent>
#include <QKeyEvent>
#include "model_widget.h"
#include "skeleton_document.h"
#include "skeleton_ik_mover.h"
#include "theme.h"
#include "turnaround_loader.h"
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QGraphicsPolygonItem>
#include <QGraphicsView>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QThread>
#include <cmath>
#include <set>
#include <QTimer>
#include "skeleton_document.h"
#include "turnaround_loader.h"
#include "theme.h"
#include "skeleton_ik_mover.h"
#include "model_widget.h"
#include <cmath>
#include <map>
#include <set>
class SkeletonGraphicsOriginItem : public QGraphicsPolygonItem
{
class SkeletonGraphicsOriginItem : public QGraphicsPolygonItem {
public:
SkeletonGraphicsOriginItem(SkeletonProfile profile=SkeletonProfile::Unknown) :
m_profile(profile),
m_hovered(false),
m_checked(false),
m_rotated(false)
SkeletonGraphicsOriginItem(SkeletonProfile profile = SkeletonProfile::Unknown)
: m_profile(profile)
, m_hovered(false)
, m_checked(false)
, m_rotated(false)
{
setData(0, "origin");
}
@ -37,9 +36,8 @@ public:
void updateAppearance()
{
QColor color = Theme::white;
switch (m_profile)
{
switch (m_profile) {
case SkeletonProfile::Unknown:
break;
case SkeletonProfile::Main:
@ -49,13 +47,13 @@ public:
color = Theme::green;
break;
}
QColor penColor = color;
penColor.setAlphaF(m_checked ? Theme::checkedAlpha : Theme::normalAlpha);
QPen pen(penColor);
pen.setWidth(0);
setPen(pen);
QColor brushColor = color;
brushColor.setAlphaF((m_checked || m_hovered) ? Theme::checkedAlpha : Theme::normalAlpha);
QBrush brush(brushColor);
@ -99,6 +97,7 @@ public:
{
return m_hovered;
}
private:
SkeletonProfile m_profile;
bool m_hovered;
@ -107,8 +106,7 @@ private:
bool m_rotated;
};
class SkeletonGraphicsSelectionItem : public QGraphicsRectItem
{
class SkeletonGraphicsSelectionItem : public QGraphicsRectItem {
public:
SkeletonGraphicsSelectionItem()
{
@ -124,16 +122,15 @@ public:
}
};
class SkeletonGraphicsNodeItem : public QGraphicsEllipseItem
{
class SkeletonGraphicsNodeItem : public QGraphicsEllipseItem {
public:
SkeletonGraphicsNodeItem(SkeletonProfile profile=SkeletonProfile::Unknown) :
m_profile(profile),
m_hovered(false),
m_checked(false),
m_markColor(Qt::transparent),
m_deactivated(false),
m_rotated(false)
SkeletonGraphicsNodeItem(SkeletonProfile profile = SkeletonProfile::Unknown)
: m_profile(profile)
, m_hovered(false)
, m_checked(false)
, m_markColor(Qt::transparent)
, m_deactivated(false)
, m_rotated(false)
{
setData(0, "node");
setRadius(32);
@ -145,10 +142,9 @@ public:
void updateAppearance()
{
QColor color = Qt::gray;
if (!m_deactivated) {
switch (m_profile)
{
switch (m_profile) {
case SkeletonProfile::Unknown:
break;
case SkeletonProfile::Main:
@ -159,13 +155,13 @@ public:
break;
}
}
QColor penColor = color;
penColor.setAlphaF((m_checked || m_hovered) ? Theme::checkedAlpha : Theme::normalAlpha);
QPen pen(penColor);
pen.setWidth(0);
setPen(pen);
QColor brushColor;
Qt::BrushStyle style;
if (m_markColor == Qt::transparent) {
@ -253,6 +249,7 @@ public:
{
return m_hovered;
}
private:
dust3d::Uuid m_uuid;
SkeletonProfile m_profile;
@ -263,17 +260,16 @@ private:
bool m_rotated;
};
class SkeletonGraphicsEdgeItem : public QGraphicsPolygonItem
{
class SkeletonGraphicsEdgeItem : public QGraphicsPolygonItem {
public:
SkeletonGraphicsEdgeItem() :
m_firstItem(nullptr),
m_secondItem(nullptr),
m_hovered(false),
m_checked(false),
m_profile(SkeletonProfile::Unknown),
m_deactivated(false),
m_rotated(false)
SkeletonGraphicsEdgeItem()
: m_firstItem(nullptr)
, m_secondItem(nullptr)
, m_hovered(false)
, m_checked(false)
, m_profile(SkeletonProfile::Unknown)
, m_deactivated(false)
, m_rotated(false)
{
setData(0, "edge");
}
@ -281,17 +277,17 @@ public:
{
m_rotated = rotated;
}
void setEndpoints(SkeletonGraphicsNodeItem *first, SkeletonGraphicsNodeItem *second)
void setEndpoints(SkeletonGraphicsNodeItem* first, SkeletonGraphicsNodeItem* second)
{
m_firstItem = first;
m_secondItem = second;
updateAppearance();
}
SkeletonGraphicsNodeItem *firstItem()
SkeletonGraphicsNodeItem* firstItem()
{
return m_firstItem;
}
SkeletonGraphicsNodeItem *secondItem()
SkeletonGraphicsNodeItem* secondItem()
{
return m_secondItem;
}
@ -299,11 +295,11 @@ public:
{
if (nullptr == m_firstItem || nullptr == m_secondItem)
return;
m_profile = m_firstItem->profile();
QLineF line(m_firstItem->origin(), m_secondItem->origin());
QPolygonF polygon;
float radAngle = line.angle() * M_PI / 180;
float dx = 2 * sin(radAngle);
@ -313,12 +309,11 @@ public:
//polygon << line.p1() + offset1 << line.p1() + offset2 << line.p2() + offset2 << line.p2() + offset1;
polygon << line.p1() + offset1 << line.p1() + offset2 << line.p2();
setPolygon(polygon);
QColor color = Qt::gray;
if (!m_deactivated) {
switch (m_firstItem->profile())
{
switch (m_firstItem->profile()) {
case SkeletonProfile::Unknown:
break;
case SkeletonProfile::Main:
@ -329,7 +324,7 @@ public:
break;
}
}
QColor penColor = color;
penColor.setAlphaF((m_checked || m_hovered) ? Theme::checkedAlpha : Theme::normalAlpha);
QPen pen(penColor);
@ -380,10 +375,11 @@ public:
{
return m_hovered;
}
private:
dust3d::Uuid m_uuid;
SkeletonGraphicsNodeItem *m_firstItem;
SkeletonGraphicsNodeItem *m_secondItem;
SkeletonGraphicsNodeItem* m_firstItem;
SkeletonGraphicsNodeItem* m_secondItem;
QPolygonF m_selectionPolygon;
bool m_hovered;
bool m_checked;
@ -392,8 +388,7 @@ private:
bool m_rotated;
};
class SkeletonGraphicsWidget : public QGraphicsView
{
class SkeletonGraphicsWidget : public QGraphicsView {
Q_OBJECT
public:
~SkeletonGraphicsWidget();
@ -445,43 +440,45 @@ signals:
void shortcutToggleFlatShading();
void shortcutToggleRotation();
void loadedTurnaroundImageChanged();
public:
SkeletonGraphicsWidget(const SkeletonDocument *document);
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsNodeItem *, SkeletonGraphicsNodeItem *>> nodeItemMap;
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsEdgeItem *, SkeletonGraphicsEdgeItem *>> edgeItemMap;
bool mouseMove(QMouseEvent *event);
bool wheel(QWheelEvent *event);
bool mouseRelease(QMouseEvent *event);
bool mousePress(QMouseEvent *event);
bool mouseDoubleClick(QMouseEvent *event);
bool keyPress(QKeyEvent *event);
bool keyRelease(QKeyEvent *event);
bool checkSkeletonItem(QGraphicsItem *item, bool checked);
dust3d::Uuid querySkeletonItemPartId(QGraphicsItem *item);
static SkeletonProfile readSkeletonItemProfile(QGraphicsItem *item);
void getOtherProfileNodeItems(const std::set<SkeletonGraphicsNodeItem *> &nodeItemSet,
std::set<SkeletonGraphicsNodeItem *> *otherProfileNodeItemSet);
void readMergedSkeletonNodeSetFromRangeSelection(std::set<SkeletonGraphicsNodeItem *> *nodeItemSet);
void readSkeletonNodeAndEdgeIdSetFromRangeSelection(std::set<dust3d::Uuid> *nodeIdSet, std::set<dust3d::Uuid> *edgeIdSet=nullptr);
bool readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(SkeletonGraphicsNodeItem **nodeItem, SkeletonGraphicsEdgeItem **edgeItem);
SkeletonGraphicsWidget(const SkeletonDocument* document);
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsNodeItem*, SkeletonGraphicsNodeItem*>> nodeItemMap;
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsEdgeItem*, SkeletonGraphicsEdgeItem*>> edgeItemMap;
bool mouseMove(QMouseEvent* event);
bool wheel(QWheelEvent* event);
bool mouseRelease(QMouseEvent* event);
bool mousePress(QMouseEvent* event);
bool mouseDoubleClick(QMouseEvent* event);
bool keyPress(QKeyEvent* event);
bool keyRelease(QKeyEvent* event);
bool checkSkeletonItem(QGraphicsItem* item, bool checked);
dust3d::Uuid querySkeletonItemPartId(QGraphicsItem* item);
static SkeletonProfile readSkeletonItemProfile(QGraphicsItem* item);
void getOtherProfileNodeItems(const std::set<SkeletonGraphicsNodeItem*>& nodeItemSet,
std::set<SkeletonGraphicsNodeItem*>* otherProfileNodeItemSet);
void readMergedSkeletonNodeSetFromRangeSelection(std::set<SkeletonGraphicsNodeItem*>* nodeItemSet);
void readSkeletonNodeAndEdgeIdSetFromRangeSelection(std::set<dust3d::Uuid>* nodeIdSet, std::set<dust3d::Uuid>* edgeIdSet = nullptr);
bool readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(SkeletonGraphicsNodeItem** nodeItem, SkeletonGraphicsEdgeItem** edgeItem);
bool hasSelection();
bool hasItems();
bool hasMultipleSelection();
bool hasEdgeSelection();
bool hasNodeSelection();
bool hasTwoDisconnectedNodesSelection();
void setModelWidget(ModelWidget *modelWidget);
bool inputWheelEventFromOtherWidget(QWheelEvent *event);
void setModelWidget(ModelWidget* modelWidget);
bool inputWheelEventFromOtherWidget(QWheelEvent* event);
bool rotated();
const QImage *loadedTurnaroundImage() const;
const QImage* loadedTurnaroundImage() const;
protected:
void mouseMoveEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
public slots:
void nodeAdded(dust3d::Uuid nodeId);
void edgeAdded(dust3d::Uuid edgeId);
@ -495,7 +492,7 @@ public slots:
void editModeChanged();
void updateCursor();
void partVisibleStateChanged(dust3d::Uuid partId);
void showContextMenu(const QPoint &pos);
void showContextMenu(const QPoint& pos);
void deleteSelected();
void selectAll();
void unselectAll();
@ -577,8 +574,9 @@ public slots:
void shortcutEscape();
private slots:
void turnaroundImageReady();
private:
QPointF mouseEventScenePos(QMouseEvent *event);
QPointF mouseEventScenePos(QMouseEvent* event);
QPointF scenePosToUnified(QPointF pos);
QPointF scenePosFromUnified(QPointF pos);
float sceneRadiusToUnified(float radius);
@ -587,56 +585,57 @@ private:
void updateItems();
void checkRangeSelection();
void clearRangeSelection();
void removeItem(QGraphicsItem *item);
QVector2D centerOfNodeItemSet(const std::set<SkeletonGraphicsNodeItem *> &set);
void removeItem(QGraphicsItem* item);
QVector2D centerOfNodeItemSet(const std::set<SkeletonGraphicsNodeItem*>& set);
bool isSingleNodeSelected();
void addItemToRangeSelection(QGraphicsItem *item);
void removeItemFromRangeSelection(QGraphicsItem *item);
void addItemToRangeSelection(QGraphicsItem* item);
void removeItemFromRangeSelection(QGraphicsItem* item);
void hoverPart(dust3d::Uuid partId);
void switchProfileOnRangeSelection();
void setItemHoveredOnAllProfiles(QGraphicsItem *item, bool hovered);
void setItemHoveredOnAllProfiles(QGraphicsItem* item, bool hovered);
void alignSelectedToGlobal(bool alignToVerticalCenter, bool alignToHorizontalCenter);
void alignSelectedToLocal(bool alignToVerticalCenter, bool alignToHorizontalCenter);
void rotateItems(const std::set<SkeletonGraphicsNodeItem *> &nodeItems, int degree, QVector2D center);
void rotateItems(const std::set<SkeletonGraphicsNodeItem*>& nodeItems, int degree, QVector2D center);
void rotateAllSideProfile(int degree);
bool isFloatEqual(float a, float b);
private:
const SkeletonDocument *m_document = nullptr;
QGraphicsPixmapItem *m_backgroundItem = nullptr;
const SkeletonDocument* m_document = nullptr;
QGraphicsPixmapItem* m_backgroundItem = nullptr;
bool m_turnaroundChanged = false;
TurnaroundLoader *m_turnaroundLoader = nullptr;
TurnaroundLoader* m_turnaroundLoader = nullptr;
bool m_dragStarted = false;
bool m_moveStarted = false;
SkeletonGraphicsNodeItem *m_cursorNodeItem = nullptr;
SkeletonGraphicsEdgeItem *m_cursorEdgeItem = nullptr;
SkeletonGraphicsNodeItem *m_addFromNodeItem = nullptr;
SkeletonGraphicsNodeItem *m_hoveredNodeItem = nullptr;
SkeletonGraphicsEdgeItem *m_hoveredEdgeItem = nullptr;
SkeletonGraphicsNodeItem* m_cursorNodeItem = nullptr;
SkeletonGraphicsEdgeItem* m_cursorEdgeItem = nullptr;
SkeletonGraphicsNodeItem* m_addFromNodeItem = nullptr;
SkeletonGraphicsNodeItem* m_hoveredNodeItem = nullptr;
SkeletonGraphicsEdgeItem* m_hoveredEdgeItem = nullptr;
float m_lastAddedX = false;
float m_lastAddedY = false;
float m_lastAddedZ = false;
SkeletonGraphicsSelectionItem *m_selectionItem = nullptr;
SkeletonGraphicsSelectionItem* m_selectionItem = nullptr;
bool m_rangeSelectionStarted = false;
bool m_mouseEventFromSelf = false;
bool m_moveHappened = false;
int m_lastRot = 0;
SkeletonGraphicsOriginItem *m_mainOriginItem = nullptr;
SkeletonGraphicsOriginItem *m_sideOriginItem = nullptr;
SkeletonGraphicsOriginItem *m_hoveredOriginItem = nullptr;
SkeletonGraphicsOriginItem *m_checkedOriginItem = nullptr;
SkeletonGraphicsOriginItem* m_mainOriginItem = nullptr;
SkeletonGraphicsOriginItem* m_sideOriginItem = nullptr;
SkeletonGraphicsOriginItem* m_hoveredOriginItem = nullptr;
SkeletonGraphicsOriginItem* m_checkedOriginItem = nullptr;
unsigned long long m_ikMoveUpdateVersion = 0;
SkeletonIkMover *m_ikMover = nullptr;
QTimer *m_deferredRemoveTimer = nullptr;
SkeletonIkMover* m_ikMover = nullptr;
QTimer* m_deferredRemoveTimer = nullptr;
bool m_eventForwardingToModelWidget = false;
ModelWidget *m_modelWidget = nullptr;
ModelWidget* m_modelWidget = nullptr;
bool m_inTempDragMode = false;
SkeletonDocumentEditMode m_modeBeforeEnterTempDragMode = SkeletonDocumentEditMode::Select;
float m_turnaroundOpacity = 0.25f;
bool m_rotated = false;
QImage *m_backgroundImage = nullptr;
QImage* m_backgroundImage = nullptr;
QVector3D m_ikMoveTarget;
dust3d::Uuid m_ikMoveEndEffectorId;
std::set<QGraphicsItem *> m_rangeSelectionSet;
std::set<QGraphicsItem*> m_rangeSelectionSet;
QPoint m_lastGlobalPos;
QPointF m_lastScenePos;
QPointF m_rangeSelectionStartPos;
@ -645,27 +644,28 @@ private:
std::set<dust3d::Uuid> m_deferredRemoveEdgeIds;
};
class SkeletonGraphicsContainerWidget : public QWidget
{
class SkeletonGraphicsContainerWidget : public QWidget {
Q_OBJECT
signals:
void containerSizeChanged(QSize size);
public:
SkeletonGraphicsContainerWidget() :
m_graphicsWidget(nullptr)
SkeletonGraphicsContainerWidget()
: m_graphicsWidget(nullptr)
{
}
void resizeEvent(QResizeEvent *event) override
void resizeEvent(QResizeEvent* event) override
{
if (m_graphicsWidget && m_graphicsWidget->size() != event->size())
emit containerSizeChanged(event->size());
}
void setGraphicsWidget(SkeletonGraphicsWidget *graphicsWidget)
void setGraphicsWidget(SkeletonGraphicsWidget* graphicsWidget)
{
m_graphicsWidget = graphicsWidget;
}
private:
SkeletonGraphicsWidget *m_graphicsWidget;
SkeletonGraphicsWidget* m_graphicsWidget;
};
#endif

View File

@ -1,6 +1,6 @@
#include <QGuiApplication>
#include "skeleton_ik_mover.h"
#include "ccd_ik_resolver.h"
#include <QGuiApplication>
SkeletonIkMover::SkeletonIkMover()
{
@ -10,7 +10,7 @@ SkeletonIkMover::~SkeletonIkMover()
{
}
void SkeletonIkMover::setTarget(const QVector3D &target)
void SkeletonIkMover::setTarget(const QVector3D& target)
{
m_target = target;
}
@ -33,7 +33,7 @@ void SkeletonIkMover::addNode(dust3d::Uuid id, QVector3D position)
m_ikNodes.push_back(ikNode);
}
const std::vector<SkeletonIkNode> &SkeletonIkMover::ikNodes()
const std::vector<SkeletonIkNode>& SkeletonIkMover::ikNodes()
{
return m_ikNodes;
}
@ -41,7 +41,7 @@ const std::vector<SkeletonIkNode> &SkeletonIkMover::ikNodes()
void SkeletonIkMover::process()
{
resolve();
emit finished();
}

View File

@ -2,34 +2,34 @@
#define DUST3D_APPLICATION_SKELETON_IK_MOVER_H_
#include <QObject>
#include <vector>
#include <QVector3D>
#include <dust3d/base/uuid.h>
#include <vector>
struct SkeletonIkNode
{
struct SkeletonIkNode {
dust3d::Uuid id;
QVector3D position;
QVector3D newPosition;
};
class SkeletonIkMover : public QObject
{
class SkeletonIkMover : public QObject {
Q_OBJECT
public:
SkeletonIkMover();
~SkeletonIkMover();
void setTarget(const QVector3D &target);
void setTarget(const QVector3D& target);
void setUpdateVersion(unsigned long long version);
unsigned long long getUpdateVersion();
void addNode(dust3d::Uuid id, QVector3D position);
const std::vector<SkeletonIkNode> &ikNodes();
const std::vector<SkeletonIkNode>& ikNodes();
signals:
void finished();
public slots:
void process();
private:
void resolve();
private:
unsigned long long m_updateVersion = 0;
std::vector<SkeletonIkNode> m_ikNodes;

View File

@ -1,8 +1,8 @@
#include "spinnable_toolbar_icon.h"
#include "theme.h"
SpinnableToolbarIcon::SpinnableToolbarIcon(QWidget *parent) :
QWidget(parent)
SpinnableToolbarIcon::SpinnableToolbarIcon(QWidget* parent)
: QWidget(parent)
{
setFixedSize(Theme::toolIconSize, Theme::toolIconSize);

View File

@ -1,18 +1,18 @@
#ifndef DUST3D_APPLICATION_SPINNABLE_TOOLBAR_ICON_H_
#define DUST3D_APPLICATION_SPINNABLE_TOOLBAR_ICON_H_
#include <QWidget>
#include "waitingspinnerwidget.h"
#include "toolbar_button.h"
#include "waitingspinnerwidget.h"
#include <QWidget>
class SpinnableToolbarIcon : public QWidget
{
class SpinnableToolbarIcon : public QWidget {
public:
SpinnableToolbarIcon(QWidget *parent=nullptr);
void showSpinner(bool showSpinner=true);
SpinnableToolbarIcon(QWidget* parent = nullptr);
void showSpinner(bool showSpinner = true);
bool isSpinning();
private:
WaitingSpinnerWidget *m_spinner = nullptr;
WaitingSpinnerWidget* m_spinner = nullptr;
};
#endif

View File

@ -1,19 +1,19 @@
#include <QPainter>
#include <QGuiApplication>
#include <QRegion>
#include <QPolygon>
#include <QElapsedTimer>
#include <QRadialGradient>
#include <dust3d/base/texture_type.h>
#include "texture_generator.h"
#include "theme.h"
#include "material.h"
#include "debug.h"
#include "material.h"
#include "theme.h"
#include <QElapsedTimer>
#include <QGuiApplication>
#include <QPainter>
#include <QPolygon>
#include <QRadialGradient>
#include <QRegion>
#include <dust3d/base/texture_type.h>
QColor TextureGenerator::m_defaultTextureColor = Qt::transparent;
TextureGenerator::TextureGenerator(const dust3d::Object &object, dust3d::Snapshot *snapshot) :
m_snapshot(snapshot)
TextureGenerator::TextureGenerator(const dust3d::Object& object, dust3d::Snapshot* snapshot)
: m_snapshot(snapshot)
{
m_object = new dust3d::Object();
*m_object = object;
@ -31,84 +31,84 @@ TextureGenerator::~TextureGenerator()
delete m_snapshot;
}
QImage *TextureGenerator::takeResultTextureColorImage()
QImage* TextureGenerator::takeResultTextureColorImage()
{
QImage *resultTextureColorImage = m_resultTextureColorImage;
QImage* resultTextureColorImage = m_resultTextureColorImage;
m_resultTextureColorImage = nullptr;
return resultTextureColorImage;
}
QImage *TextureGenerator::takeResultTextureNormalImage()
QImage* TextureGenerator::takeResultTextureNormalImage()
{
QImage *resultTextureNormalImage = m_resultTextureNormalImage;
QImage* resultTextureNormalImage = m_resultTextureNormalImage;
m_resultTextureNormalImage = nullptr;
return resultTextureNormalImage;
}
QImage *TextureGenerator::takeResultTextureRoughnessImage()
QImage* TextureGenerator::takeResultTextureRoughnessImage()
{
QImage *resultTextureRoughnessImage = m_resultTextureRoughnessImage;
QImage* resultTextureRoughnessImage = m_resultTextureRoughnessImage;
m_resultTextureRoughnessImage = nullptr;
return resultTextureRoughnessImage;
}
QImage *TextureGenerator::takeResultTextureMetalnessImage()
QImage* TextureGenerator::takeResultTextureMetalnessImage()
{
QImage *resultTextureMetalnessImage = m_resultTextureMetalnessImage;
QImage* resultTextureMetalnessImage = m_resultTextureMetalnessImage;
m_resultTextureMetalnessImage = nullptr;
return resultTextureMetalnessImage;
}
QImage *TextureGenerator::takeResultTextureAmbientOcclusionImage()
QImage* TextureGenerator::takeResultTextureAmbientOcclusionImage()
{
QImage *resultTextureAmbientOcclusionImage = m_resultTextureAmbientOcclusionImage;
QImage* resultTextureAmbientOcclusionImage = m_resultTextureAmbientOcclusionImage;
m_resultTextureAmbientOcclusionImage = nullptr;
return resultTextureAmbientOcclusionImage;
}
dust3d::Object *TextureGenerator::takeObject()
dust3d::Object* TextureGenerator::takeObject()
{
dust3d::Object *object = m_object;
dust3d::Object* object = m_object;
m_object = nullptr;
return object;
}
ModelMesh *TextureGenerator::takeResultMesh()
ModelMesh* TextureGenerator::takeResultMesh()
{
ModelMesh *resultMesh = m_resultMesh;
ModelMesh* resultMesh = m_resultMesh;
m_resultMesh = nullptr;
return resultMesh;
}
void TextureGenerator::addPartColorMap(dust3d::Uuid partId, const QImage *image, float tileScale)
void TextureGenerator::addPartColorMap(dust3d::Uuid partId, const QImage* image, float tileScale)
{
if (nullptr == image)
return;
m_partColorTextureMap[partId] = std::make_pair(*image, tileScale);
}
void TextureGenerator::addPartNormalMap(dust3d::Uuid partId, const QImage *image, float tileScale)
void TextureGenerator::addPartNormalMap(dust3d::Uuid partId, const QImage* image, float tileScale)
{
if (nullptr == image)
return;
m_partNormalTextureMap[partId] = std::make_pair(*image, tileScale);
}
void TextureGenerator::addPartMetalnessMap(dust3d::Uuid partId, const QImage *image, float tileScale)
void TextureGenerator::addPartMetalnessMap(dust3d::Uuid partId, const QImage* image, float tileScale)
{
if (nullptr == image)
return;
m_partMetalnessTextureMap[partId] = std::make_pair(*image, tileScale);
}
void TextureGenerator::addPartRoughnessMap(dust3d::Uuid partId, const QImage *image, float tileScale)
void TextureGenerator::addPartRoughnessMap(dust3d::Uuid partId, const QImage* image, float tileScale)
{
if (nullptr == image)
return;
m_partRoughnessTextureMap[partId] = std::make_pair(*image, tileScale);
}
void TextureGenerator::addPartAmbientOcclusionMap(dust3d::Uuid partId, const QImage *image, float tileScale)
void TextureGenerator::addPartAmbientOcclusionMap(dust3d::Uuid partId, const QImage* image, float tileScale)
{
if (nullptr == image)
return;
@ -119,28 +119,28 @@ void TextureGenerator::prepare()
{
if (nullptr == m_snapshot)
return;
std::map<dust3d::Uuid, dust3d::Uuid> updatedMaterialIdMap;
std::map<dust3d::Uuid, bool> updatedCountershadedMap;
for (const auto &partIt: m_snapshot->parts) {
for (const auto& partIt : m_snapshot->parts) {
dust3d::Uuid materialId;
auto materialIdIt = partIt.second.find("materialId");
if (materialIdIt != partIt.second.end())
materialId = dust3d::Uuid(materialIdIt->second);
dust3d::Uuid partId = dust3d::Uuid(partIt.first);
updatedMaterialIdMap.insert({partId, materialId});
updatedCountershadedMap.insert({partId,
dust3d::String::isTrue(dust3d::String::valueOrEmpty(partIt.second, "countershaded"))});
updatedMaterialIdMap.insert({ partId, materialId });
updatedCountershadedMap.insert({ partId,
dust3d::String::isTrue(dust3d::String::valueOrEmpty(partIt.second, "countershaded")) });
}
for (const auto &bmeshNode: m_object->nodes) {
for (const auto& bmeshNode : m_object->nodes) {
bool countershaded = bmeshNode.countershaded;
auto findUpdatedCountershadedMap = updatedCountershadedMap.find(bmeshNode.mirrorFromPartId.isNull() ? bmeshNode.partId : bmeshNode.mirrorFromPartId);
if (findUpdatedCountershadedMap != updatedCountershadedMap.end())
countershaded = findUpdatedCountershadedMap->second;
if (countershaded)
m_countershadedPartIds.insert(bmeshNode.partId);
for (size_t i = 0; i < (int)dust3d::TextureType::Count - 1; ++i) {
dust3d::TextureType forWhat = (dust3d::TextureType)(i + 1);
MaterialTextures materialTextures;
@ -150,7 +150,7 @@ void TextureGenerator::prepare()
materialId = findUpdatedMaterialIdResult->second;
float tileScale = 1.0;
initializeMaterialTexturesFromSnapshot(*m_snapshot, materialId, materialTextures, tileScale);
const QImage *image = materialTextures.textureImages[i];
const QImage* image = materialTextures.textureImages[i];
if (nullptr != image) {
if (dust3d::TextureType::BaseColor == forWhat)
addPartColorMap(bmeshNode.partId, image, tileScale);
@ -175,100 +175,100 @@ bool TextureGenerator::hasTransparencySettings()
void TextureGenerator::generate()
{
m_resultMesh = new ModelMesh(*m_object);
if (nullptr == m_object->triangleVertexUvs())
return;
if (nullptr == m_object->triangleSourceNodes())
return;
if (nullptr == m_object->partUvRects())
return;
QElapsedTimer countTimeConsumed;
countTimeConsumed.start();
prepare();
bool hasNormalMap = false;
bool hasMetalnessMap = false;
bool hasRoughnessMap = false;
bool hasAmbientOcclusionMap = false;
const auto &triangleVertexUvs = *m_object->triangleVertexUvs();
const auto &triangleSourceNodes = *m_object->triangleSourceNodes();
const auto &partUvRects = *m_object->partUvRects();
const auto &triangleNormals = m_object->triangleNormals;
const auto& triangleVertexUvs = *m_object->triangleVertexUvs();
const auto& triangleSourceNodes = *m_object->triangleSourceNodes();
const auto& partUvRects = *m_object->partUvRects();
const auto& triangleNormals = m_object->triangleNormals;
std::map<dust3d::Uuid, QColor> partColorMap;
std::map<std::pair<dust3d::Uuid, dust3d::Uuid>, const dust3d::ObjectNode *> nodeMap;
std::map<std::pair<dust3d::Uuid, dust3d::Uuid>, const dust3d::ObjectNode*> nodeMap;
std::map<dust3d::Uuid, float> partColorSolubilityMap;
std::map<dust3d::Uuid, float> partMetalnessMap;
std::map<dust3d::Uuid, float> partRoughnessMap;
for (const auto &item: m_object->nodes) {
for (const auto& item : m_object->nodes) {
if (!m_hasTransparencySettings) {
if (!qFuzzyCompare(1.0, item.color.alpha()))
m_hasTransparencySettings = true;
}
nodeMap.insert({{item.partId, item.nodeId}, &item});
partColorMap.insert({item.partId, QColor(item.color.toString().c_str())});
partColorSolubilityMap.insert({item.partId, item.colorSolubility});
partMetalnessMap.insert({item.partId, item.metalness});
partRoughnessMap.insert({item.partId, item.roughness});
nodeMap.insert({ { item.partId, item.nodeId }, &item });
partColorMap.insert({ item.partId, QColor(item.color.toString().c_str()) });
partColorSolubilityMap.insert({ item.partId, item.colorSolubility });
partMetalnessMap.insert({ item.partId, item.metalness });
partRoughnessMap.insert({ item.partId, item.roughness });
}
m_resultTextureColorImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32);
m_resultTextureColorImage->fill(m_hasTransparencySettings ? m_defaultTextureColor : Qt::white);
m_resultTextureNormalImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32);
m_resultTextureNormalImage->fill(QColor(128, 128, 255));
m_resultTextureMetalnessImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32);
m_resultTextureMetalnessImage->fill(Qt::black);
m_resultTextureRoughnessImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32);
m_resultTextureRoughnessImage->fill(Qt::white);
m_resultTextureAmbientOcclusionImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32);
m_resultTextureAmbientOcclusionImage->fill(Qt::white);
QColor borderColor = Qt::darkGray;
QPen pen(borderColor);
QPainter texturePainter;
texturePainter.begin(m_resultTextureColorImage);
texturePainter.setRenderHint(QPainter::Antialiasing);
texturePainter.setRenderHint(QPainter::HighQualityAntialiasing);
QPainter textureNormalPainter;
textureNormalPainter.begin(m_resultTextureNormalImage);
textureNormalPainter.setRenderHint(QPainter::Antialiasing);
textureNormalPainter.setRenderHint(QPainter::HighQualityAntialiasing);
QPainter textureMetalnessPainter;
textureMetalnessPainter.begin(m_resultTextureMetalnessImage);
textureMetalnessPainter.setRenderHint(QPainter::Antialiasing);
textureMetalnessPainter.setRenderHint(QPainter::HighQualityAntialiasing);
QPainter textureRoughnessPainter;
textureRoughnessPainter.begin(m_resultTextureRoughnessImage);
textureRoughnessPainter.setRenderHint(QPainter::Antialiasing);
textureRoughnessPainter.setRenderHint(QPainter::HighQualityAntialiasing);
QPainter textureAmbientOcclusionPainter;
textureAmbientOcclusionPainter.begin(m_resultTextureAmbientOcclusionImage);
textureAmbientOcclusionPainter.setRenderHint(QPainter::Antialiasing);
textureAmbientOcclusionPainter.setRenderHint(QPainter::HighQualityAntialiasing);
texturePainter.setPen(Qt::NoPen);
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
for (const auto& it : partUvRects) {
const auto& partId = it.first;
const auto& rects = it.second;
auto findSourceColorResult = partColorMap.find(partId);
if (findSourceColorResult != partColorMap.end()) {
const auto &color = findSourceColorResult->second;
const auto& color = findSourceColorResult->second;
QBrush brush(color);
float fillExpandSize = 2;
for (const auto &rect: rects) {
for (const auto& rect : rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize - fillExpandSize,
rect.top() * TextureGenerator::m_textureSize - fillExpandSize,
@ -279,20 +279,20 @@ void TextureGenerator::generate()
}
}
}
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
for (const auto& it : partUvRects) {
const auto& partId = it.first;
const auto& rects = it.second;
auto findMetalnessResult = partMetalnessMap.find(partId);
if (findMetalnessResult != partMetalnessMap.end()) {
if (qFuzzyCompare(findMetalnessResult->second, (float)0.0))
continue;
const auto &color = QColor(findMetalnessResult->second * 255,
const auto& color = QColor(findMetalnessResult->second * 255,
findMetalnessResult->second * 255,
findMetalnessResult->second * 255);
QBrush brush(color);
float fillExpandSize = 2;
for (const auto &rect: rects) {
for (const auto& rect : rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize - fillExpandSize,
rect.top() * TextureGenerator::m_textureSize - fillExpandSize,
@ -304,20 +304,20 @@ void TextureGenerator::generate()
}
}
}
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
for (const auto& it : partUvRects) {
const auto& partId = it.first;
const auto& rects = it.second;
auto findRoughnessResult = partRoughnessMap.find(partId);
if (findRoughnessResult != partRoughnessMap.end()) {
if (qFuzzyCompare(findRoughnessResult->second, (float)1.0))
continue;
const auto &color = QColor(findRoughnessResult->second * 255,
const auto& color = QColor(findRoughnessResult->second * 255,
findRoughnessResult->second * 255,
findRoughnessResult->second * 255);
QBrush brush(color);
float fillExpandSize = 2;
for (const auto &rect: rects) {
for (const auto& rect : rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize - fillExpandSize,
rect.top() * TextureGenerator::m_textureSize - fillExpandSize,
@ -329,25 +329,25 @@ void TextureGenerator::generate()
}
}
}
auto drawTexture = [&](const std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> &map, QPainter &painter, bool useAlpha) {
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
auto drawTexture = [&](const std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>>& map, QPainter& painter, bool useAlpha) {
for (const auto& it : partUvRects) {
const auto& partId = it.first;
const auto& rects = it.second;
float alpha = 1.0;
if (useAlpha) {
auto findSourceColorResult = partColorMap.find(partId);
if (findSourceColorResult != partColorMap.end()) {
const auto &color = findSourceColorResult->second;
const auto& color = findSourceColorResult->second;
alpha = color.alphaF();
}
}
auto findTextureResult = map.find(partId);
if (findTextureResult != map.end()) {
const auto &pixmap = findTextureResult->second.first;
const auto &rotatedPixmap = findTextureResult->second.second;
const auto& pixmap = findTextureResult->second.first;
const auto& rotatedPixmap = findTextureResult->second.second;
painter.setOpacity(alpha);
for (const auto &rect: rects) {
for (const auto& rect : rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize,
rect.top() * TextureGenerator::m_textureSize,
@ -364,12 +364,12 @@ void TextureGenerator::generate()
}
}
};
auto convertTextureImageToPixmap = [&](const std::map<dust3d::Uuid, std::pair<QImage, float>> &sourceMap,
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> &targetMap) {
for (const auto &it: sourceMap) {
auto convertTextureImageToPixmap = [&](const std::map<dust3d::Uuid, std::pair<QImage, float>>& sourceMap,
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>>& targetMap) {
for (const auto& it : sourceMap) {
float tileScale = it.second.second;
const auto &image = it.second.first;
const auto& image = it.second.first;
auto newSize = image.size() * tileScale;
QImage scaledImage = image.scaled(newSize);
QPoint center = scaledImage.rect().center();
@ -381,53 +381,52 @@ void TextureGenerator::generate()
QPixmap::fromImage(rotatedImage));
}
};
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> partColorTexturePixmaps;
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> partNormalTexturePixmaps;
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> partMetalnessTexturePixmaps;
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> partRoughnessTexturePixmaps;
std::map<dust3d::Uuid, std::pair<QPixmap, QPixmap>> partAmbientOcclusionTexturePixmaps;
convertTextureImageToPixmap(m_partColorTextureMap, partColorTexturePixmaps);
convertTextureImageToPixmap(m_partNormalTextureMap, partNormalTexturePixmaps);
convertTextureImageToPixmap(m_partMetalnessTextureMap, partMetalnessTexturePixmaps);
convertTextureImageToPixmap(m_partRoughnessTextureMap, partRoughnessTexturePixmaps);
convertTextureImageToPixmap(m_partAmbientOcclusionTextureMap, partAmbientOcclusionTexturePixmaps);
drawTexture(partColorTexturePixmaps, texturePainter, true);
drawTexture(partNormalTexturePixmaps, textureNormalPainter, false);
drawTexture(partMetalnessTexturePixmaps, textureMetalnessPainter, false);
drawTexture(partRoughnessTexturePixmaps, textureRoughnessPainter, false);
drawTexture(partAmbientOcclusionTexturePixmaps, textureAmbientOcclusionPainter, false);
auto drawBySolubility = [&](const dust3d::Uuid &partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex,
const dust3d::Uuid &neighborPartId) {
const std::vector<dust3d::Vector2> &uv = triangleVertexUvs[triangleIndex];
const auto &allRects = partUvRects.find(partId);
auto drawBySolubility = [&](const dust3d::Uuid& partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex,
const dust3d::Uuid& neighborPartId) {
const std::vector<dust3d::Vector2>& uv = triangleVertexUvs[triangleIndex];
const auto& allRects = partUvRects.find(partId);
if (allRects == partUvRects.end()) {
qDebug() << "Found part uv rects failed";
return;
}
const auto &firstPoint = uv[firstVertexIndex];
const auto &secondPoint = uv[secondVertexIndex];
const auto& firstPoint = uv[firstVertexIndex];
const auto& secondPoint = uv[secondVertexIndex];
auto edgeLength = (firstPoint - secondPoint).length();
auto middlePoint = (firstPoint + secondPoint) / 2.0;
float alpha = 1.0;
const auto &findColor = partColorMap.find(partId);
const auto& findColor = partColorMap.find(partId);
if (findColor == partColorMap.end())
return;
alpha = findColor->second.alphaF();
const auto &findNeighborColorSolubility = partColorSolubilityMap.find(neighborPartId);
const auto& findNeighborColorSolubility = partColorSolubilityMap.find(neighborPartId);
if (findNeighborColorSolubility == partColorSolubilityMap.end())
return;
if (qFuzzyIsNull(findNeighborColorSolubility->second))
return;
const auto &findNeighborColor = partColorMap.find(neighborPartId);
const auto& findNeighborColor = partColorMap.find(neighborPartId);
if (findNeighborColor == partColorMap.end())
return;
for (const auto &it: allRects->second) {
if (it.contains(firstPoint.x(), firstPoint.y()) ||
it.contains(secondPoint.x(), secondPoint.y())) {
for (const auto& it : allRects->second) {
if (it.contains(firstPoint.x(), firstPoint.y()) || it.contains(secondPoint.x(), secondPoint.y())) {
float finalRadius = (it.width() + it.height()) * 0.5 * findNeighborColorSolubility->second;
if (finalRadius < edgeLength)
finalRadius = edgeLength;
@ -445,14 +444,14 @@ void TextureGenerator::generate()
texturePainter.setOpacity(alpha);
auto findTextureResult = partColorTexturePixmaps.find(neighborPartId);
if (findTextureResult != partColorTexturePixmaps.end()) {
const auto &pixmap = findTextureResult->second.first;
const auto &rotatedPixmap = findTextureResult->second.second;
const auto& pixmap = findTextureResult->second.first;
const auto& rotatedPixmap = findTextureResult->second.second;
QImage tmpImage(translatedRect.width(), translatedRect.height(), QImage::Format_ARGB32);
QPixmap tmpPixmap = QPixmap::fromImage(tmpImage);
QPainter tmpPainter;
QRectF tmpImageFrame = QRectF(0, 0, translatedRect.width(), translatedRect.height());
// Fill tiled texture
tmpPainter.begin(&tmpPixmap);
tmpPainter.setOpacity(alpha);
@ -463,23 +462,23 @@ void TextureGenerator::generate()
}
tmpPainter.setOpacity(1.0);
tmpPainter.end();
// Apply gradient
QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize - translatedRect.left(),
middlePoint.y() * TextureGenerator::m_textureSize - translatedRect.top()),
middlePoint.y() * TextureGenerator::m_textureSize - translatedRect.top()),
finalRadius * TextureGenerator::m_textureSize);
gradient.setColorAt(0.0, findNeighborColor->second);
gradient.setColorAt(1.0, Qt::transparent);
tmpPainter.begin(&tmpPixmap);
tmpPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
tmpPainter.fillRect(tmpImageFrame, gradient);
tmpPainter.end();
texturePainter.drawPixmap(translatedRect, tmpPixmap, tmpImageFrame);
} else {
QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize,
middlePoint.y() * TextureGenerator::m_textureSize),
middlePoint.y() * TextureGenerator::m_textureSize),
finalRadius * TextureGenerator::m_textureSize);
gradient.setColorAt(0.0, findNeighborColor->second);
gradient.setColorAt(1.0, Qt::transparent);
@ -490,10 +489,10 @@ void TextureGenerator::generate()
}
}
};
std::map<std::pair<size_t, size_t>, std::tuple<size_t, size_t, size_t>> halfEdgeToTriangleMap;
for (size_t i = 0; i < m_object->triangles.size(); ++i) {
const auto &triangleIndices = m_object->triangles[i];
const auto& triangleIndices = m_object->triangles[i];
if (triangleIndices.size() != 3) {
qDebug() << "Found invalid triangle indices";
continue;
@ -504,38 +503,38 @@ void TextureGenerator::generate()
std::make_tuple(i, j, k)));
}
}
for (const auto &it: halfEdgeToTriangleMap) {
for (const auto& it : halfEdgeToTriangleMap) {
auto oppositeHalfEdge = std::make_pair(it.first.second, it.first.first);
const auto &opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge);
const auto& opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge);
if (opposite == halfEdgeToTriangleMap.end())
continue;
const std::pair<dust3d::Uuid, dust3d::Uuid> &source = triangleSourceNodes[std::get<0>(it.second)];
const std::pair<dust3d::Uuid, dust3d::Uuid> &oppositeSource = triangleSourceNodes[std::get<0>(opposite->second)];
const std::pair<dust3d::Uuid, dust3d::Uuid>& source = triangleSourceNodes[std::get<0>(it.second)];
const std::pair<dust3d::Uuid, dust3d::Uuid>& oppositeSource = triangleSourceNodes[std::get<0>(opposite->second)];
if (source.first == oppositeSource.first)
continue;
drawBySolubility(source.first, std::get<0>(it.second), std::get<1>(it.second), std::get<2>(it.second), oppositeSource.first);
drawBySolubility(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first);
}
// Draw belly white
texturePainter.setCompositionMode(QPainter::CompositionMode_SoftLight);
for (size_t triangleIndex = 0; triangleIndex < m_object->triangles.size(); ++triangleIndex) {
const auto &normal = triangleNormals[triangleIndex];
const std::pair<dust3d::Uuid, dust3d::Uuid> &source = triangleSourceNodes[triangleIndex];
const auto &partId = source.first;
const auto& normal = triangleNormals[triangleIndex];
const std::pair<dust3d::Uuid, dust3d::Uuid>& source = triangleSourceNodes[triangleIndex];
const auto& partId = source.first;
if (m_countershadedPartIds.find(partId) == m_countershadedPartIds.end())
continue;
const auto &allRects = partUvRects.find(partId);
const auto& allRects = partUvRects.find(partId);
if (allRects == partUvRects.end()) {
qDebug() << "Found part uv rects failed";
continue;
}
const auto &findObjectNode = nodeMap.find(source);
const auto& findObjectNode = nodeMap.find(source);
if (findObjectNode == nodeMap.end())
continue;
const dust3d::ObjectNode *objectNode = findObjectNode->second;
const dust3d::ObjectNode* objectNode = findObjectNode->second;
if (qAbs(dust3d::Vector3::dotProduct(objectNode->direction, dust3d::Vector3(0, 1, 0))) >= 0.707) {
if (dust3d::Vector3::dotProduct(normal, dust3d::Vector3(0, 0, 1)) <= 0.0)
continue;
@ -543,24 +542,22 @@ void TextureGenerator::generate()
if (dust3d::Vector3::dotProduct(normal, dust3d::Vector3(0, -1, 0)) <= 0.0)
continue;
}
const auto &triangleIndices = m_object->triangles[triangleIndex];
const auto& triangleIndices = m_object->triangles[triangleIndex];
if (triangleIndices.size() != 3) {
qDebug() << "Found invalid triangle indices";
continue;
}
const std::vector<dust3d::Vector2> &uv = triangleVertexUvs[triangleIndex];
const std::vector<dust3d::Vector2>& uv = triangleVertexUvs[triangleIndex];
dust3d::Vector2 middlePoint = (uv[0] + uv[1] + uv[2]) / 3.0;
float finalRadius = ((uv[0] - uv[1]).length() +
(uv[1] - uv[2]).length() +
(uv[2] - uv[0]).length()) / 3.0;
float finalRadius = ((uv[0] - uv[1]).length() + (uv[1] - uv[2]).length() + (uv[2] - uv[0]).length()) / 3.0;
QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize,
middlePoint.y() * TextureGenerator::m_textureSize),
middlePoint.y() * TextureGenerator::m_textureSize),
finalRadius * TextureGenerator::m_textureSize);
gradient.setColorAt(0.0, Qt::white);
gradient.setColorAt(1.0, Qt::transparent);
for (const auto &it: allRects->second) {
for (const auto& it : allRects->second) {
if (it.contains(middlePoint.x(), middlePoint.y())) {
dust3d::Rectangle fillTarget((middlePoint.x() - finalRadius),
(middlePoint.y() - finalRadius),
@ -576,31 +573,31 @@ void TextureGenerator::generate()
texturePainter.fillRect(translatedRect, gradient);
}
}
// Fill the neighbor halfedges
for (int i = 0; i < 3; ++i) {
int j = (i + 1) % 3;
auto oppositeHalfEdge = std::make_pair(triangleIndices[j], triangleIndices[i]);
const auto &opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge);
const auto& opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge);
if (opposite == halfEdgeToTriangleMap.end())
continue;
auto oppositeTriangleIndex = std::get<0>(opposite->second);
const std::pair<dust3d::Uuid, dust3d::Uuid> &oppositeSource = triangleSourceNodes[oppositeTriangleIndex];
const std::pair<dust3d::Uuid, dust3d::Uuid>& oppositeSource = triangleSourceNodes[oppositeTriangleIndex];
if (partId == oppositeSource.first)
continue;
const auto &oppositeAllRects = partUvRects.find(oppositeSource.first);
const auto& oppositeAllRects = partUvRects.find(oppositeSource.first);
if (oppositeAllRects == partUvRects.end()) {
qDebug() << "Found part uv rects failed";
continue;
}
const std::vector<dust3d::Vector2> &oppositeUv = triangleVertexUvs[oppositeTriangleIndex];
const std::vector<dust3d::Vector2>& oppositeUv = triangleVertexUvs[oppositeTriangleIndex];
dust3d::Vector2 oppositeMiddlePoint = (oppositeUv[std::get<1>(opposite->second)] + oppositeUv[std::get<2>(opposite->second)]) * 0.5;
QRadialGradient oppositeGradient(QPointF(oppositeMiddlePoint.x() * TextureGenerator::m_textureSize,
oppositeMiddlePoint.y() * TextureGenerator::m_textureSize),
oppositeMiddlePoint.y() * TextureGenerator::m_textureSize),
finalRadius * TextureGenerator::m_textureSize);
oppositeGradient.setColorAt(0.0, Qt::white);
oppositeGradient.setColorAt(1.0, Qt::transparent);
for (const auto &it: oppositeAllRects->second) {
for (const auto& it : oppositeAllRects->second) {
if (it.contains(oppositeMiddlePoint.x(), oppositeMiddlePoint.y())) {
dust3d::Rectangle fillTarget((oppositeMiddlePoint.x() - finalRadius),
(oppositeMiddlePoint.y() - finalRadius),
@ -618,7 +615,7 @@ void TextureGenerator::generate()
}
}
}
hasNormalMap = !m_partNormalTextureMap.empty();
if (!m_partMetalnessTextureMap.empty())
hasMetalnessMap = true;
@ -631,12 +628,12 @@ void TextureGenerator::generate()
textureMetalnessPainter.end();
textureRoughnessPainter.end();
textureAmbientOcclusionPainter.end();
if (!hasNormalMap) {
delete m_resultTextureNormalImage;
m_resultTextureNormalImage = nullptr;
}
if (!hasMetalnessMap && !hasRoughnessMap && !hasAmbientOcclusionMap) {
delete m_resultTextureMetalnessImage;
m_resultTextureMetalnessImage = nullptr;
@ -647,7 +644,7 @@ void TextureGenerator::generate()
delete m_resultTextureAmbientOcclusionImage;
m_resultTextureAmbientOcclusionImage = nullptr;
}
m_resultMesh->setTextureImage(new QImage(*m_resultTextureColorImage));
if (nullptr != m_resultTextureNormalImage)
m_resultMesh->setNormalMapImage(new QImage(*m_resultTextureNormalImage));
@ -660,18 +657,16 @@ void TextureGenerator::generate()
m_resultMesh->setHasRoughnessInImage(hasRoughnessMap);
m_resultMesh->setHasAmbientOcclusionInImage(hasAmbientOcclusionMap);
}
qDebug() << "The texture[" << TextureGenerator::m_textureSize << "x" << TextureGenerator::m_textureSize << "] generation took" << countTimeConsumed.elapsed() << "milliseconds";
}
QImage *TextureGenerator::combineMetalnessRoughnessAmbientOcclusionImages(QImage *metalnessImage,
QImage *roughnessImage,
QImage *ambientOcclusionImage)
QImage* TextureGenerator::combineMetalnessRoughnessAmbientOcclusionImages(QImage* metalnessImage,
QImage* roughnessImage,
QImage* ambientOcclusionImage)
{
QImage *textureMetalnessRoughnessAmbientOcclusionImage = nullptr;
if (nullptr != metalnessImage ||
nullptr != roughnessImage ||
nullptr != ambientOcclusionImage) {
QImage* textureMetalnessRoughnessAmbientOcclusionImage = nullptr;
if (nullptr != metalnessImage || nullptr != roughnessImage || nullptr != ambientOcclusionImage) {
int textureSize = 0;
if (nullptr != metalnessImage)
textureSize = metalnessImage->height();

View File

@ -1,61 +1,63 @@
#ifndef DUST3D_APPLICATION_TEXTURE_GENERATOR_H_
#define DUST3D_APPLICATION_TEXTURE_GENERATOR_H_
#include <QObject>
#include <vector>
#include <QImage>
#include "model_mesh.h"
#include <QColor>
#include <QImage>
#include <QObject>
#include <QPixmap>
#include <dust3d/base/object.h>
#include <dust3d/base/snapshot.h>
#include "model_mesh.h"
#include <vector>
class TextureGenerator : public QObject
{
class TextureGenerator : public QObject {
Q_OBJECT
public:
TextureGenerator(const dust3d::Object &object, dust3d::Snapshot *snapshot=nullptr);
TextureGenerator(const dust3d::Object& object, dust3d::Snapshot* snapshot = nullptr);
~TextureGenerator();
QImage *takeResultTextureColorImage();
QImage *takeResultTextureNormalImage();
QImage *takeResultTextureRoughnessImage();
QImage *takeResultTextureMetalnessImage();
QImage *takeResultTextureAmbientOcclusionImage();
dust3d::Object *takeObject();
ModelMesh *takeResultMesh();
QImage* takeResultTextureColorImage();
QImage* takeResultTextureNormalImage();
QImage* takeResultTextureRoughnessImage();
QImage* takeResultTextureMetalnessImage();
QImage* takeResultTextureAmbientOcclusionImage();
dust3d::Object* takeObject();
ModelMesh* takeResultMesh();
bool hasTransparencySettings();
void addPartColorMap(dust3d::Uuid partId, const QImage *image, float tileScale);
void addPartNormalMap(dust3d::Uuid partId, const QImage *image, float tileScale);
void addPartMetalnessMap(dust3d::Uuid partId, const QImage *image, float tileScale);
void addPartRoughnessMap(dust3d::Uuid partId, const QImage *image, float tileScale);
void addPartAmbientOcclusionMap(dust3d::Uuid partId, const QImage *image, float tileScale);
void addPartColorMap(dust3d::Uuid partId, const QImage* image, float tileScale);
void addPartNormalMap(dust3d::Uuid partId, const QImage* image, float tileScale);
void addPartMetalnessMap(dust3d::Uuid partId, const QImage* image, float tileScale);
void addPartRoughnessMap(dust3d::Uuid partId, const QImage* image, float tileScale);
void addPartAmbientOcclusionMap(dust3d::Uuid partId, const QImage* image, float tileScale);
void generate();
static QImage *combineMetalnessRoughnessAmbientOcclusionImages(QImage *metalnessImage,
QImage *roughnessImage,
QImage *ambientOcclusionImage);
static QImage* combineMetalnessRoughnessAmbientOcclusionImages(QImage* metalnessImage,
QImage* roughnessImage,
QImage* ambientOcclusionImage);
signals:
void finished();
public slots:
void process();
public:
static QColor m_defaultTextureColor;
private:
void prepare();
private:
dust3d::Object *m_object = nullptr;
QImage *m_resultTextureColorImage = nullptr;
QImage *m_resultTextureNormalImage = nullptr;
QImage *m_resultTextureRoughnessImage = nullptr;
QImage *m_resultTextureMetalnessImage = nullptr;
QImage *m_resultTextureAmbientOcclusionImage = nullptr;
ModelMesh *m_resultMesh = nullptr;
dust3d::Object* m_object = nullptr;
QImage* m_resultTextureColorImage = nullptr;
QImage* m_resultTextureNormalImage = nullptr;
QImage* m_resultTextureRoughnessImage = nullptr;
QImage* m_resultTextureMetalnessImage = nullptr;
QImage* m_resultTextureAmbientOcclusionImage = nullptr;
ModelMesh* m_resultMesh = nullptr;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partColorTextureMap;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partNormalTextureMap;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partMetalnessTextureMap;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partRoughnessTextureMap;
std::map<dust3d::Uuid, std::pair<QImage, float>> m_partAmbientOcclusionTextureMap;
std::set<dust3d::Uuid> m_countershadedPartIds;
dust3d::Snapshot *m_snapshot = nullptr;
dust3d::Snapshot* m_snapshot = nullptr;
bool m_hasTransparencySettings = false;
int m_textureSize = 1024;
};

Some files were not shown because too many files have changed in this diff Show More