Remove skeleton document
parent
86a6e5f163
commit
4fb109a583
|
@ -189,8 +189,6 @@ HEADERS += sources/preferences.h
|
||||||
SOURCES += sources/preferences.cc
|
SOURCES += sources/preferences.cc
|
||||||
HEADERS += sources/preview_grid_view.h
|
HEADERS += sources/preview_grid_view.h
|
||||||
SOURCES += sources/preview_grid_view.cc
|
SOURCES += sources/preview_grid_view.cc
|
||||||
HEADERS += sources/skeleton_document.h
|
|
||||||
SOURCES += sources/skeleton_document.cc
|
|
||||||
HEADERS += sources/skeleton_graphics_widget.h
|
HEADERS += sources/skeleton_graphics_widget.h
|
||||||
SOURCES += sources/skeleton_graphics_widget.cc
|
SOURCES += sources/skeleton_graphics_widget.cc
|
||||||
HEADERS += sources/skeleton_ik_mover.h
|
HEADERS += sources/skeleton_ik_mover.h
|
||||||
|
@ -203,8 +201,8 @@ HEADERS += sources/theme.h
|
||||||
SOURCES += sources/theme.cc
|
SOURCES += sources/theme.cc
|
||||||
HEADERS += sources/toolbar_button.h
|
HEADERS += sources/toolbar_button.h
|
||||||
SOURCES += sources/toolbar_button.cc
|
SOURCES += sources/toolbar_button.cc
|
||||||
HEADERS += sources/tube_uv_preview_image_generator.h
|
HEADERS += sources/uv_preview_image_generator.h
|
||||||
SOURCES += sources/tube_uv_preview_image_generator.cc
|
SOURCES += sources/uv_preview_image_generator.cc
|
||||||
HEADERS += sources/turnaround_loader.h
|
HEADERS += sources/turnaround_loader.h
|
||||||
SOURCES += sources/turnaround_loader.cc
|
SOURCES += sources/turnaround_loader.cc
|
||||||
HEADERS += sources/updates_check_widget.h
|
HEADERS += sources/updates_check_widget.h
|
||||||
|
@ -243,8 +241,6 @@ SOURCES += ../dust3d/base/ds3_file.cc
|
||||||
HEADERS += ../dust3d/base/math.h
|
HEADERS += ../dust3d/base/math.h
|
||||||
HEADERS += ../dust3d/base/matrix4x4.h
|
HEADERS += ../dust3d/base/matrix4x4.h
|
||||||
HEADERS += ../dust3d/base/object.h
|
HEADERS += ../dust3d/base/object.h
|
||||||
HEADERS += ../dust3d/base/part_base.h
|
|
||||||
SOURCES += ../dust3d/base/part_base.cc
|
|
||||||
HEADERS += ../dust3d/base/part_target.h
|
HEADERS += ../dust3d/base/part_target.h
|
||||||
SOURCES += ../dust3d/base/part_target.cc
|
SOURCES += ../dust3d/base/part_target.cc
|
||||||
HEADERS += ../dust3d/base/position_key.h
|
HEADERS += ../dust3d/base/position_key.h
|
||||||
|
|
|
@ -188,12 +188,29 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
|
||||||
cutFaceGroupBox->setLayout(cutFaceLayout);
|
cutFaceGroupBox->setLayout(cutFaceLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QGroupBox* skinGroupBox = nullptr;
|
||||||
|
if (nullptr != m_part) {
|
||||||
|
QCheckBox* useImageBox = new QCheckBox();
|
||||||
|
Theme::initCheckbox(useImageBox);
|
||||||
|
useImageBox->setText(tr("Use image"));
|
||||||
|
useImageBox->setChecked(m_part->rounded);
|
||||||
|
|
||||||
|
QHBoxLayout* skinLayout = new QHBoxLayout;
|
||||||
|
skinLayout->addStretch();
|
||||||
|
skinLayout->addWidget(useImageBox);
|
||||||
|
|
||||||
|
skinGroupBox = new QGroupBox(tr("Skin"));
|
||||||
|
skinGroupBox->setLayout(skinLayout);
|
||||||
|
}
|
||||||
|
|
||||||
QVBoxLayout* mainLayout = new QVBoxLayout;
|
QVBoxLayout* mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addLayout(colorLayout);
|
mainLayout->addLayout(colorLayout);
|
||||||
if (nullptr != deformGroupBox)
|
if (nullptr != deformGroupBox)
|
||||||
mainLayout->addWidget(deformGroupBox);
|
mainLayout->addWidget(deformGroupBox);
|
||||||
if (nullptr != cutFaceGroupBox)
|
if (nullptr != cutFaceGroupBox)
|
||||||
mainLayout->addWidget(cutFaceGroupBox);
|
mainLayout->addWidget(cutFaceGroupBox);
|
||||||
|
if (nullptr != skinGroupBox)
|
||||||
|
mainLayout->addWidget(skinGroupBox);
|
||||||
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||||
|
|
||||||
connect(this, &ComponentPropertyWidget::setPartColorState, m_document, &Document::setPartColorState);
|
connect(this, &ComponentPropertyWidget::setPartColorState, m_document, &Document::setPartColorState);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,10 @@
|
||||||
#ifndef DUST3D_APPLICATION_DOCUMENT_H_
|
#ifndef DUST3D_APPLICATION_DOCUMENT_H_
|
||||||
#define DUST3D_APPLICATION_DOCUMENT_H_
|
#define DUST3D_APPLICATION_DOCUMENT_H_
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
#include "material_layer.h"
|
#include "material_layer.h"
|
||||||
#include "model_mesh.h"
|
#include "model_mesh.h"
|
||||||
#include "monochrome_mesh.h"
|
#include "monochrome_mesh.h"
|
||||||
#include "skeleton_document.h"
|
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
@ -13,6 +13,8 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <dust3d/base/combine_mode.h>
|
#include <dust3d/base/combine_mode.h>
|
||||||
|
#include <dust3d/base/cut_face.h>
|
||||||
|
#include <dust3d/base/part_target.h>
|
||||||
#include <dust3d/base/snapshot.h>
|
#include <dust3d/base/snapshot.h>
|
||||||
#include <dust3d/base/texture_type.h>
|
#include <dust3d/base/texture_type.h>
|
||||||
#include <dust3d/base/uuid.h>
|
#include <dust3d/base/uuid.h>
|
||||||
|
@ -20,6 +22,535 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||||
|
}
|
||||||
|
void setRadius(float toRadius);
|
||||||
|
void setCutRotation(float toRotation)
|
||||||
|
{
|
||||||
|
if (toRotation < -1)
|
||||||
|
toRotation = -1;
|
||||||
|
else if (toRotation > 1)
|
||||||
|
toRotation = 1;
|
||||||
|
cutRotation = toRotation;
|
||||||
|
hasCutFaceSettings = true;
|
||||||
|
}
|
||||||
|
void setCutFace(dust3d::CutFace face)
|
||||||
|
{
|
||||||
|
cutFace = face;
|
||||||
|
cutFaceLinkedId = dust3d::Uuid();
|
||||||
|
hasCutFaceSettings = true;
|
||||||
|
}
|
||||||
|
void setCutFaceLinkedId(const dust3d::Uuid& linkedId)
|
||||||
|
{
|
||||||
|
if (linkedId.isNull()) {
|
||||||
|
clearCutFaceSettings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cutFace = dust3d::CutFace::UserDefined;
|
||||||
|
cutFaceLinkedId = linkedId;
|
||||||
|
hasCutFaceSettings = true;
|
||||||
|
}
|
||||||
|
void clearCutFaceSettings()
|
||||||
|
{
|
||||||
|
cutFace = dust3d::CutFace::Quad;
|
||||||
|
cutFaceLinkedId = dust3d::Uuid();
|
||||||
|
cutRotation = 0;
|
||||||
|
hasCutFaceSettings = false;
|
||||||
|
}
|
||||||
|
float getX(bool rotated = false) const
|
||||||
|
{
|
||||||
|
if (rotated)
|
||||||
|
return m_y;
|
||||||
|
return m_x;
|
||||||
|
}
|
||||||
|
float getY(bool rotated = false) const
|
||||||
|
{
|
||||||
|
if (rotated)
|
||||||
|
return m_x;
|
||||||
|
return m_y;
|
||||||
|
}
|
||||||
|
float getZ(bool rotated = false) const
|
||||||
|
{
|
||||||
|
(void)rotated;
|
||||||
|
return m_z;
|
||||||
|
}
|
||||||
|
void setX(float x)
|
||||||
|
{
|
||||||
|
m_x = x;
|
||||||
|
}
|
||||||
|
void setY(float y)
|
||||||
|
{
|
||||||
|
m_y = y;
|
||||||
|
}
|
||||||
|
void setZ(float z)
|
||||||
|
{
|
||||||
|
m_z = z;
|
||||||
|
}
|
||||||
|
void addX(float x)
|
||||||
|
{
|
||||||
|
m_x += x;
|
||||||
|
}
|
||||||
|
void addY(float y)
|
||||||
|
{
|
||||||
|
m_y += y;
|
||||||
|
}
|
||||||
|
void addZ(float z)
|
||||||
|
{
|
||||||
|
m_z += z;
|
||||||
|
}
|
||||||
|
dust3d::Uuid id;
|
||||||
|
dust3d::Uuid partId;
|
||||||
|
QString name;
|
||||||
|
float radius;
|
||||||
|
float cutRotation;
|
||||||
|
dust3d::CutFace cutFace;
|
||||||
|
dust3d::Uuid cutFaceLinkedId;
|
||||||
|
bool hasCutFaceSettings;
|
||||||
|
std::vector<dust3d::Uuid> edgeIds;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_x;
|
||||||
|
float m_y;
|
||||||
|
float m_z;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkeletonEdge {
|
||||||
|
public:
|
||||||
|
SkeletonEdge(const dust3d::Uuid& withId = dust3d::Uuid())
|
||||||
|
{
|
||||||
|
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||||
|
}
|
||||||
|
dust3d::Uuid id;
|
||||||
|
dust3d::Uuid partId;
|
||||||
|
QString name;
|
||||||
|
std::vector<dust3d::Uuid> nodeIds;
|
||||||
|
dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const
|
||||||
|
{
|
||||||
|
if (nodeIds.size() != 2)
|
||||||
|
return dust3d::Uuid();
|
||||||
|
return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkeletonPart {
|
||||||
|
public:
|
||||||
|
dust3d::Uuid id;
|
||||||
|
QString name;
|
||||||
|
bool visible;
|
||||||
|
bool locked;
|
||||||
|
bool subdived;
|
||||||
|
bool disabled;
|
||||||
|
bool xMirrored;
|
||||||
|
float deformThickness;
|
||||||
|
float deformWidth;
|
||||||
|
bool deformUnified;
|
||||||
|
bool rounded;
|
||||||
|
bool chamfered;
|
||||||
|
QColor color;
|
||||||
|
bool hasColor;
|
||||||
|
dust3d::Uuid componentId;
|
||||||
|
std::vector<dust3d::Uuid> nodeIds;
|
||||||
|
bool dirty;
|
||||||
|
float cutRotation;
|
||||||
|
dust3d::CutFace cutFace;
|
||||||
|
dust3d::Uuid cutFaceLinkedId;
|
||||||
|
dust3d::Uuid materialId;
|
||||||
|
dust3d::PartTarget target;
|
||||||
|
float colorSolubility;
|
||||||
|
float metalness;
|
||||||
|
float roughness;
|
||||||
|
float hollowThickness;
|
||||||
|
bool countershaded;
|
||||||
|
bool smooth;
|
||||||
|
dust3d::Uuid colorImageId;
|
||||||
|
SkeletonPart(const dust3d::Uuid& withId = dust3d::Uuid())
|
||||||
|
: visible(true)
|
||||||
|
, locked(false)
|
||||||
|
, subdived(false)
|
||||||
|
, disabled(false)
|
||||||
|
, xMirrored(false)
|
||||||
|
, 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;
|
||||||
|
}
|
||||||
|
bool hasPolyFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasSmoothFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasSubdivFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasRoundEndFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasMirrorFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasChamferFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasRotationFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasHollowFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasCutFaceFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasLayerFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasTargetFunction() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool hasBaseFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasCombineModeFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasDeformFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
bool hasColorFunction() const
|
||||||
|
{
|
||||||
|
return dust3d::PartTarget::Model == target;
|
||||||
|
}
|
||||||
|
void setDeformThickness(float toThickness)
|
||||||
|
{
|
||||||
|
if (toThickness < 0)
|
||||||
|
toThickness = 0;
|
||||||
|
else if (toThickness > 2)
|
||||||
|
toThickness = 2;
|
||||||
|
deformThickness = toThickness;
|
||||||
|
}
|
||||||
|
void setDeformWidth(float toWidth)
|
||||||
|
{
|
||||||
|
if (toWidth < 0)
|
||||||
|
toWidth = 0;
|
||||||
|
else if (toWidth > 2)
|
||||||
|
toWidth = 2;
|
||||||
|
deformWidth = toWidth;
|
||||||
|
}
|
||||||
|
void setCutRotation(float toRotation)
|
||||||
|
{
|
||||||
|
if (toRotation < -1)
|
||||||
|
toRotation = -1;
|
||||||
|
else if (toRotation > 1)
|
||||||
|
toRotation = 1;
|
||||||
|
cutRotation = toRotation;
|
||||||
|
}
|
||||||
|
void setCutFace(dust3d::CutFace face)
|
||||||
|
{
|
||||||
|
cutFace = face;
|
||||||
|
cutFaceLinkedId = dust3d::Uuid();
|
||||||
|
}
|
||||||
|
void setCutFaceLinkedId(const dust3d::Uuid& linkedId)
|
||||||
|
{
|
||||||
|
if (linkedId.isNull()) {
|
||||||
|
setCutFace(dust3d::CutFace::Quad);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cutFace = dust3d::CutFace::UserDefined;
|
||||||
|
cutFaceLinkedId = linkedId;
|
||||||
|
}
|
||||||
|
bool deformThicknessAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(deformThickness - 1.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool deformWidthAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(deformWidth - 1.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool deformAdjusted() const
|
||||||
|
{
|
||||||
|
return deformThicknessAdjusted() || deformWidthAdjusted() || deformUnified;
|
||||||
|
}
|
||||||
|
bool colorSolubilityAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(colorSolubility - 0.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool metalnessAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(metalness - 0.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool roughnessAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(roughness - 1.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool cutRotationAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(cutRotation - 0.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool hollowThicknessAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(hollowThickness - 0.0) >= 0.01;
|
||||||
|
}
|
||||||
|
bool cutFaceAdjusted() const
|
||||||
|
{
|
||||||
|
return cutFace != dust3d::CutFace::Quad;
|
||||||
|
}
|
||||||
|
bool cutAdjusted() const
|
||||||
|
{
|
||||||
|
return cutRotationAdjusted() || cutFaceAdjusted() || hollowThicknessAdjusted();
|
||||||
|
}
|
||||||
|
bool materialAdjusted() const
|
||||||
|
{
|
||||||
|
return !materialId.isNull();
|
||||||
|
}
|
||||||
|
bool isEditVisible() const
|
||||||
|
{
|
||||||
|
return visible && !disabled;
|
||||||
|
}
|
||||||
|
void copyAttributes(const SkeletonPart& other)
|
||||||
|
{
|
||||||
|
visible = other.visible;
|
||||||
|
locked = other.locked;
|
||||||
|
subdived = other.subdived;
|
||||||
|
disabled = other.disabled;
|
||||||
|
xMirrored = other.xMirrored;
|
||||||
|
deformThickness = other.deformThickness;
|
||||||
|
deformWidth = other.deformWidth;
|
||||||
|
rounded = other.rounded;
|
||||||
|
chamfered = other.chamfered;
|
||||||
|
color = other.color;
|
||||||
|
hasColor = other.hasColor;
|
||||||
|
cutRotation = other.cutRotation;
|
||||||
|
cutFace = other.cutFace;
|
||||||
|
cutFaceLinkedId = other.cutFaceLinkedId;
|
||||||
|
componentId = other.componentId;
|
||||||
|
dirty = other.dirty;
|
||||||
|
materialId = other.materialId;
|
||||||
|
target = other.target;
|
||||||
|
colorSolubility = other.colorSolubility;
|
||||||
|
countershaded = other.countershaded;
|
||||||
|
metalness = other.metalness;
|
||||||
|
roughness = other.roughness;
|
||||||
|
deformUnified = other.deformUnified;
|
||||||
|
smooth = other.smooth;
|
||||||
|
hollowThickness = other.hollowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(SkeletonPart);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DocumentEditMode {
|
||||||
|
Add = 0,
|
||||||
|
Select,
|
||||||
|
Paint,
|
||||||
|
Drag,
|
||||||
|
ZoomIn,
|
||||||
|
ZoomOut
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SkeletonProfile {
|
||||||
|
Unknown = 0,
|
||||||
|
Main,
|
||||||
|
Side
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkeletonComponent {
|
||||||
|
public:
|
||||||
|
SkeletonComponent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
SkeletonComponent(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString())
|
||||||
|
{
|
||||||
|
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||||
|
if (!linkData.isEmpty()) {
|
||||||
|
if ("partId" == linkDataType) {
|
||||||
|
linkToPartId = dust3d::Uuid(linkData.toUtf8().constData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dust3d::Uuid id;
|
||||||
|
QString name;
|
||||||
|
dust3d::Uuid linkToPartId;
|
||||||
|
dust3d::Uuid parentId;
|
||||||
|
bool expanded = true;
|
||||||
|
dust3d::CombineMode combineMode = dust3d::CombineMode::Normal;
|
||||||
|
bool dirty = true;
|
||||||
|
std::vector<dust3d::Uuid> childrenIds;
|
||||||
|
bool isPreviewMeshObsolete = false;
|
||||||
|
std::unique_ptr<QImage> previewImage;
|
||||||
|
bool isPreviewImageDecorationObsolete = false;
|
||||||
|
QPixmap previewPixmap;
|
||||||
|
QString linkData() const
|
||||||
|
{
|
||||||
|
return linkToPartId.isNull() ? QString() : QString(linkToPartId.toString().c_str());
|
||||||
|
}
|
||||||
|
QString linkDataType() const
|
||||||
|
{
|
||||||
|
return linkToPartId.isNull() ? QString() : QString("partId");
|
||||||
|
}
|
||||||
|
void addChild(dust3d::Uuid childId)
|
||||||
|
{
|
||||||
|
if (m_childrenIdSet.find(childId) != m_childrenIdSet.end())
|
||||||
|
return;
|
||||||
|
m_childrenIdSet.insert(childId);
|
||||||
|
childrenIds.push_back(childId);
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
if (m_childrenIdSet.find(it) == m_childrenIdSet.end()) {
|
||||||
|
m_childrenIdSet.insert(it);
|
||||||
|
candidates.emplace_back(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < childrenIds.size(); ++i) {
|
||||||
|
if (childId == childrenIds[i]) {
|
||||||
|
size_t newAddSize = candidates.size() - 1;
|
||||||
|
if (newAddSize > 0) {
|
||||||
|
size_t oldSize = childrenIds.size();
|
||||||
|
childrenIds.resize(childrenIds.size() + newAddSize);
|
||||||
|
for (int j = (int)oldSize - 1; j > (int)i; --j) {
|
||||||
|
childrenIds[j + newAddSize] = childrenIds[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t k = 0; k < candidates.size(); ++k)
|
||||||
|
childrenIds[i + k] = candidates[k];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void removeChild(dust3d::Uuid childId)
|
||||||
|
{
|
||||||
|
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
|
||||||
|
return;
|
||||||
|
m_childrenIdSet.erase(childId);
|
||||||
|
auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
||||||
|
if (findResult != childrenIds.end())
|
||||||
|
childrenIds.erase(findResult);
|
||||||
|
}
|
||||||
|
void replaceChild(dust3d::Uuid childId, dust3d::Uuid newId)
|
||||||
|
{
|
||||||
|
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
|
||||||
|
return;
|
||||||
|
if (m_childrenIdSet.find(newId) != m_childrenIdSet.end())
|
||||||
|
return;
|
||||||
|
m_childrenIdSet.erase(childId);
|
||||||
|
m_childrenIdSet.insert(newId);
|
||||||
|
auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
||||||
|
if (findResult != childrenIds.end())
|
||||||
|
*findResult = newId;
|
||||||
|
}
|
||||||
|
void moveChildUp(dust3d::Uuid childId)
|
||||||
|
{
|
||||||
|
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
||||||
|
if (it == childrenIds.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto index = std::distance(childrenIds.begin(), it);
|
||||||
|
if (index == 0)
|
||||||
|
return;
|
||||||
|
std::swap(childrenIds[index - 1], childrenIds[index]);
|
||||||
|
}
|
||||||
|
void moveChildDown(dust3d::Uuid childId)
|
||||||
|
{
|
||||||
|
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
||||||
|
if (it == childrenIds.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto index = std::distance(childrenIds.begin(), it);
|
||||||
|
if (index == (int)childrenIds.size() - 1)
|
||||||
|
return;
|
||||||
|
std::swap(childrenIds[index], childrenIds[index + 1]);
|
||||||
|
}
|
||||||
|
void moveChildToTop(dust3d::Uuid childId)
|
||||||
|
{
|
||||||
|
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
||||||
|
if (it == childrenIds.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto index = std::distance(childrenIds.begin(), it);
|
||||||
|
if (index == 0)
|
||||||
|
return;
|
||||||
|
for (int i = index; i >= 1; i--)
|
||||||
|
std::swap(childrenIds[i - 1], childrenIds[i]);
|
||||||
|
}
|
||||||
|
void moveChildToBottom(dust3d::Uuid childId)
|
||||||
|
{
|
||||||
|
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
||||||
|
if (it == childrenIds.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto index = std::distance(childrenIds.begin(), it);
|
||||||
|
if (index == (int)childrenIds.size() - 1)
|
||||||
|
return;
|
||||||
|
for (int i = index; i <= (int)childrenIds.size() - 2; i++)
|
||||||
|
std::swap(childrenIds[i], childrenIds[i + 1]);
|
||||||
|
}
|
||||||
|
void updatePreviewMesh(std::unique_ptr<ModelMesh> mesh)
|
||||||
|
{
|
||||||
|
m_previewMesh = std::move(mesh);
|
||||||
|
isPreviewMeshObsolete = true;
|
||||||
|
}
|
||||||
|
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 MaterialPreviewsGenerator;
|
class MaterialPreviewsGenerator;
|
||||||
class TextureGenerator;
|
class TextureGenerator;
|
||||||
class MeshGenerator;
|
class MeshGenerator;
|
||||||
|
@ -66,7 +597,7 @@ enum class DocumentToSnapshotFor {
|
||||||
Materials
|
Materials
|
||||||
};
|
};
|
||||||
|
|
||||||
class Document : public SkeletonDocument {
|
class Document : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
signals:
|
signals:
|
||||||
void nodeCutRotationChanged(dust3d::Uuid nodeId);
|
void nodeCutRotationChanged(dust3d::Uuid nodeId);
|
||||||
|
@ -80,7 +611,6 @@ signals:
|
||||||
void postProcessedResultChanged();
|
void postProcessedResultChanged();
|
||||||
void partSubdivStateChanged(dust3d::Uuid partId);
|
void partSubdivStateChanged(dust3d::Uuid partId);
|
||||||
void partXmirrorStateChanged(dust3d::Uuid partId);
|
void partXmirrorStateChanged(dust3d::Uuid partId);
|
||||||
void partBaseChanged(dust3d::Uuid partId);
|
|
||||||
void partDeformThicknessChanged(dust3d::Uuid partId);
|
void partDeformThicknessChanged(dust3d::Uuid partId);
|
||||||
void partDeformWidthChanged(dust3d::Uuid partId);
|
void partDeformWidthChanged(dust3d::Uuid partId);
|
||||||
void partDeformUnifyStateChanged(dust3d::Uuid partId);
|
void partDeformUnifyStateChanged(dust3d::Uuid partId);
|
||||||
|
@ -118,6 +648,33 @@ signals:
|
||||||
void postProcessing();
|
void postProcessing();
|
||||||
void textureGenerating();
|
void textureGenerating();
|
||||||
void textureChanged();
|
void textureChanged();
|
||||||
|
void partAdded(dust3d::Uuid partId);
|
||||||
|
void nodeAdded(dust3d::Uuid nodeId);
|
||||||
|
void edgeAdded(dust3d::Uuid edgeId);
|
||||||
|
void partRemoved(dust3d::Uuid partId);
|
||||||
|
void partLockStateChanged(dust3d::Uuid partId);
|
||||||
|
void partVisibleStateChanged(dust3d::Uuid partId);
|
||||||
|
void partDisableStateChanged(dust3d::Uuid partId);
|
||||||
|
void partColorImageChanged(const dust3d::Uuid& partId);
|
||||||
|
void componentNameChanged(dust3d::Uuid componentId);
|
||||||
|
void componentChildrenChanged(dust3d::Uuid componentId);
|
||||||
|
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 nodeRemoved(dust3d::Uuid nodeId);
|
||||||
|
void edgeRemoved(dust3d::Uuid edgeId);
|
||||||
|
void nodeRadiusChanged(dust3d::Uuid nodeId);
|
||||||
|
void nodeOriginChanged(dust3d::Uuid nodeId);
|
||||||
|
void edgeReversed(dust3d::Uuid edgeId);
|
||||||
|
void originChanged();
|
||||||
|
void skeletonChanged();
|
||||||
|
void optionsChanged();
|
||||||
|
void xlockStateChanged();
|
||||||
|
void ylockStateChanged();
|
||||||
|
void zlockStateChanged();
|
||||||
|
void radiusLockStateChanged();
|
||||||
|
|
||||||
public: // need initialize
|
public: // need initialize
|
||||||
QImage* textureImage = nullptr;
|
QImage* textureImage = nullptr;
|
||||||
|
@ -133,6 +690,18 @@ public: // need initialize
|
||||||
bool weldEnabled = true;
|
bool weldEnabled = true;
|
||||||
float brushMetalness = ModelMesh::m_defaultMetalness;
|
float brushMetalness = ModelMesh::m_defaultMetalness;
|
||||||
float brushRoughness = ModelMesh::m_defaultRoughness;
|
float brushRoughness = ModelMesh::m_defaultRoughness;
|
||||||
|
DocumentEditMode editMode = DocumentEditMode::Select;
|
||||||
|
bool xlocked = false;
|
||||||
|
bool ylocked = false;
|
||||||
|
bool zlocked = false;
|
||||||
|
bool radiusLocked = false;
|
||||||
|
QImage turnaround;
|
||||||
|
QByteArray turnaroundPngByteArray;
|
||||||
|
std::map<dust3d::Uuid, SkeletonPart> partMap;
|
||||||
|
std::map<dust3d::Uuid, SkeletonNode> nodeMap;
|
||||||
|
std::map<dust3d::Uuid, SkeletonEdge> edgeMap;
|
||||||
|
std::map<dust3d::Uuid, SkeletonComponent> componentMap;
|
||||||
|
SkeletonComponent rootComponent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Document();
|
Document();
|
||||||
|
@ -140,13 +709,13 @@ public:
|
||||||
std::map<dust3d::Uuid, Material> materialMap;
|
std::map<dust3d::Uuid, Material> materialMap;
|
||||||
std::vector<dust3d::Uuid> materialIdList;
|
std::vector<dust3d::Uuid> materialIdList;
|
||||||
|
|
||||||
bool undoable() const override;
|
bool undoable() const;
|
||||||
bool redoable() const override;
|
bool redoable() const;
|
||||||
bool hasPastableNodesInClipboard() const override;
|
bool hasPastableNodesInClipboard() const;
|
||||||
bool originSettled() const override;
|
bool originSettled() const;
|
||||||
bool isNodeEditable(dust3d::Uuid nodeId) const override;
|
bool isNodeEditable(dust3d::Uuid nodeId) const;
|
||||||
bool isEdgeEditable(dust3d::Uuid edgeId) const override;
|
bool isEdgeEditable(dust3d::Uuid edgeId) const;
|
||||||
void copyNodes(std::set<dust3d::Uuid> nodeIdSet) const override;
|
void copyNodes(std::set<dust3d::Uuid> nodeIdSet) const;
|
||||||
void toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uuid>& limitNodeIds = std::set<dust3d::Uuid>(),
|
void toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uuid>& limitNodeIds = std::set<dust3d::Uuid>(),
|
||||||
DocumentToSnapshotFor forWhat = DocumentToSnapshotFor::Document,
|
DocumentToSnapshotFor forWhat = DocumentToSnapshotFor::Document,
|
||||||
const std::set<dust3d::Uuid>& limitMaterialIds = std::set<dust3d::Uuid>()) const;
|
const std::set<dust3d::Uuid>& limitMaterialIds = std::set<dust3d::Uuid>()) const;
|
||||||
|
@ -179,15 +748,72 @@ public:
|
||||||
bool isPostProcessing() const;
|
bool isPostProcessing() const;
|
||||||
bool isTextureGenerating() const;
|
bool isTextureGenerating() const;
|
||||||
void collectCutFaceList(std::vector<QString>& cutFaces) const;
|
void collectCutFaceList(std::vector<QString>& cutFaces) const;
|
||||||
|
float getOriginX(bool rotated = false) const
|
||||||
|
{
|
||||||
|
if (rotated)
|
||||||
|
return m_originY;
|
||||||
|
return m_originX;
|
||||||
|
}
|
||||||
|
float getOriginY(bool rotated = false) const
|
||||||
|
{
|
||||||
|
if (rotated)
|
||||||
|
return m_originX;
|
||||||
|
return m_originY;
|
||||||
|
}
|
||||||
|
float getOriginZ(bool rotated = false) const
|
||||||
|
{
|
||||||
|
(void)rotated;
|
||||||
|
return m_originZ;
|
||||||
|
}
|
||||||
|
void setOriginX(float originX)
|
||||||
|
{
|
||||||
|
m_originX = originX;
|
||||||
|
}
|
||||||
|
void setOriginY(float originY)
|
||||||
|
{
|
||||||
|
m_originY = originY;
|
||||||
|
}
|
||||||
|
void setOriginZ(float originZ)
|
||||||
|
{
|
||||||
|
m_originZ = originZ;
|
||||||
|
}
|
||||||
|
void addOriginX(float originX)
|
||||||
|
{
|
||||||
|
m_originX += originX;
|
||||||
|
}
|
||||||
|
void addOriginY(float originY)
|
||||||
|
{
|
||||||
|
m_originY += originY;
|
||||||
|
}
|
||||||
|
void addOriginZ(float originZ)
|
||||||
|
{
|
||||||
|
m_originZ += originZ;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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 resetDirtyFlags();
|
||||||
|
void markAllDirty();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void undo() override;
|
void undo();
|
||||||
void redo() override;
|
void redo();
|
||||||
void paste() override;
|
void paste();
|
||||||
void setNodeCutRotation(dust3d::Uuid nodeId, float cutRotation);
|
void setNodeCutRotation(dust3d::Uuid nodeId, float cutRotation);
|
||||||
void setNodeCutFace(dust3d::Uuid nodeId, dust3d::CutFace cutFace);
|
void setNodeCutFace(dust3d::Uuid nodeId, dust3d::CutFace cutFace);
|
||||||
void setNodeCutFaceLinkedId(dust3d::Uuid nodeId, dust3d::Uuid linkedId);
|
void setNodeCutFaceLinkedId(dust3d::Uuid nodeId, dust3d::Uuid linkedId);
|
||||||
void clearNodeCutFaceSettings(dust3d::Uuid nodeId);
|
void clearNodeCutFaceSettings(dust3d::Uuid nodeId);
|
||||||
void setEditMode(SkeletonDocumentEditMode mode);
|
void setEditMode(DocumentEditMode mode);
|
||||||
void uiReady();
|
void uiReady();
|
||||||
void generateMesh();
|
void generateMesh();
|
||||||
void regenerateMesh();
|
void regenerateMesh();
|
||||||
|
@ -200,7 +826,6 @@ public slots:
|
||||||
void materialPreviewsReady();
|
void materialPreviewsReady();
|
||||||
void setPartSubdivState(dust3d::Uuid partId, bool subdived);
|
void setPartSubdivState(dust3d::Uuid partId, bool subdived);
|
||||||
void setPartXmirrorState(dust3d::Uuid partId, bool mirrored);
|
void setPartXmirrorState(dust3d::Uuid partId, bool mirrored);
|
||||||
void setPartBase(dust3d::Uuid partId, dust3d::PartBase base);
|
|
||||||
void setPartDeformThickness(dust3d::Uuid partId, float thickness);
|
void setPartDeformThickness(dust3d::Uuid partId, float thickness);
|
||||||
void setPartDeformWidth(dust3d::Uuid partId, float width);
|
void setPartDeformWidth(dust3d::Uuid partId, float width);
|
||||||
void setPartDeformUnified(dust3d::Uuid partId, bool unified);
|
void setPartDeformUnified(dust3d::Uuid partId, bool unified);
|
||||||
|
@ -231,11 +856,73 @@ public slots:
|
||||||
void removeMaterial(dust3d::Uuid materialId);
|
void removeMaterial(dust3d::Uuid materialId);
|
||||||
void setMaterialLayers(dust3d::Uuid materialId, std::vector<MaterialLayer> layers);
|
void setMaterialLayers(dust3d::Uuid materialId, std::vector<MaterialLayer> layers);
|
||||||
void renameMaterial(dust3d::Uuid materialId, QString name);
|
void renameMaterial(dust3d::Uuid materialId, QString name);
|
||||||
|
void removeNode(dust3d::Uuid nodeId);
|
||||||
|
void removeEdge(dust3d::Uuid edgeId);
|
||||||
|
void removePart(dust3d::Uuid partId);
|
||||||
|
void addNodeWithId(dust3d::Uuid nodeId, float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
||||||
|
void addNode(float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
||||||
|
void scaleNodeByAddRadius(dust3d::Uuid nodeId, float amount);
|
||||||
|
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
||||||
|
void setNodeOrigin(dust3d::Uuid nodeId, float x, float y, float z);
|
||||||
|
void setNodeRadius(dust3d::Uuid nodeId, float radius);
|
||||||
|
void switchNodeXZ(dust3d::Uuid nodeId);
|
||||||
|
void moveOriginBy(float x, float y, float z);
|
||||||
|
void addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId);
|
||||||
|
void moveComponentUp(dust3d::Uuid componentId);
|
||||||
|
void moveComponentDown(dust3d::Uuid componentId);
|
||||||
|
void moveComponentToTop(dust3d::Uuid componentId);
|
||||||
|
void moveComponentToBottom(dust3d::Uuid componentId);
|
||||||
|
void renameComponent(dust3d::Uuid componentId, QString name);
|
||||||
|
void removeComponent(dust3d::Uuid componentId);
|
||||||
|
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 createNewChildComponent(dust3d::Uuid parentComponentId);
|
||||||
|
void setComponentExpandState(dust3d::Uuid componentId, bool expanded);
|
||||||
|
void hideOtherComponents(dust3d::Uuid componentId);
|
||||||
|
void lockOtherComponents(dust3d::Uuid componentId);
|
||||||
|
void hideAllComponents();
|
||||||
|
void showAllComponents();
|
||||||
|
void showOrHideAllComponents();
|
||||||
|
void collapseAllComponents();
|
||||||
|
void expandAllComponents();
|
||||||
|
void lockAllComponents();
|
||||||
|
void unlockAllComponents();
|
||||||
|
void hideDescendantComponents(dust3d::Uuid componentId);
|
||||||
|
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 setPartLockState(dust3d::Uuid partId, bool locked);
|
||||||
|
void setPartVisibleState(dust3d::Uuid partId, bool visible);
|
||||||
|
void setPartDisableState(dust3d::Uuid partId, bool disabled);
|
||||||
|
void setPartColorImage(const dust3d::Uuid& partId, const dust3d::Uuid& imageId);
|
||||||
|
void enableAllPositionRelatedLocks();
|
||||||
|
void disableAllPositionRelatedLocks();
|
||||||
|
bool isPartReadonly(dust3d::Uuid partId) const;
|
||||||
|
void breakEdge(dust3d::Uuid edgeId);
|
||||||
|
void reduceNode(dust3d::Uuid nodeId);
|
||||||
|
void reverseEdge(dust3d::Uuid edgeId);
|
||||||
|
void setXlockState(bool locked);
|
||||||
|
void setYlockState(bool locked);
|
||||||
|
void setZlockState(bool locked);
|
||||||
|
void setRadiusLockState(bool locked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile);
|
void resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile);
|
||||||
void settleOrigin();
|
void settleOrigin();
|
||||||
void checkExportReadyState();
|
void checkExportReadyState();
|
||||||
|
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);
|
||||||
|
void removeComponentRecursively(dust3d::Uuid componentId);
|
||||||
|
void updateLinkedPart(dust3d::Uuid oldPartId, dust3d::Uuid newPartId);
|
||||||
|
dust3d::Uuid createNode(dust3d::Uuid nodeId, float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
||||||
|
|
||||||
bool m_isResultMeshObsolete = false;
|
bool m_isResultMeshObsolete = false;
|
||||||
MeshGenerator* m_meshGenerator = nullptr;
|
MeshGenerator* m_meshGenerator = nullptr;
|
||||||
|
@ -256,6 +943,11 @@ private:
|
||||||
quint64 m_meshGenerationId = 0;
|
quint64 m_meshGenerationId = 0;
|
||||||
quint64 m_nextMeshGenerationId = 0;
|
quint64 m_nextMeshGenerationId = 0;
|
||||||
void* m_generatedCacheContext = nullptr;
|
void* m_generatedCacheContext = nullptr;
|
||||||
|
float m_originX = 0;
|
||||||
|
float m_originY = 0;
|
||||||
|
float m_originZ = 0;
|
||||||
|
dust3d::Uuid m_currentCanvasComponentId;
|
||||||
|
bool m_allPositionRelatedLocksEnabled = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static unsigned long m_maxSnapshot;
|
static unsigned long m_maxSnapshot;
|
||||||
|
|
|
@ -511,11 +511,11 @@ DocumentWindow::DocumentWindow()
|
||||||
canvasGraphicsWidget, &SkeletonGraphicsWidget::turnaroundChanged);
|
canvasGraphicsWidget, &SkeletonGraphicsWidget::turnaroundChanged);
|
||||||
|
|
||||||
connect(addButton, &QPushButton::clicked, [=]() {
|
connect(addButton, &QPushButton::clicked, [=]() {
|
||||||
m_document->setEditMode(SkeletonDocumentEditMode::Add);
|
m_document->setEditMode(DocumentEditMode::Add);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(selectButton, &QPushButton::clicked, [=]() {
|
connect(selectButton, &QPushButton::clicked, [=]() {
|
||||||
m_document->setEditMode(SkeletonDocumentEditMode::Select);
|
m_document->setEditMode(DocumentEditMode::Select);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_xLockButton, &QPushButton::clicked, [=]() {
|
connect(m_xLockButton, &QPushButton::clicked, [=]() {
|
||||||
|
|
|
@ -10,9 +10,9 @@ typedef struct
|
||||||
GLfloat posX;
|
GLfloat posX;
|
||||||
GLfloat posY;
|
GLfloat posY;
|
||||||
GLfloat posZ;
|
GLfloat posZ;
|
||||||
GLfloat colorR = 0.0;
|
GLfloat colorR = 24.0 / 255.0;
|
||||||
GLfloat colorG = 0.0;
|
GLfloat colorG = 29.0 / 255.0;
|
||||||
GLfloat colorB = 0.0;
|
GLfloat colorB = 49.0 / 255.0;
|
||||||
GLfloat alpha = 1.0;
|
GLfloat alpha = 1.0;
|
||||||
} MonochromeOpenGLVertex;
|
} MonochromeOpenGLVertex;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,757 +0,0 @@
|
||||||
#ifndef DUST3D_APPLICATION_SKELETON_DOCUMENT_H_
|
|
||||||
#define DUST3D_APPLICATION_SKELETON_DOCUMENT_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 {
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
|
||||||
}
|
|
||||||
void setRadius(float toRadius)
|
|
||||||
{
|
|
||||||
if (toRadius < MeshGenerator::m_minimalRadius)
|
|
||||||
toRadius = MeshGenerator::m_minimalRadius;
|
|
||||||
else if (toRadius > 1)
|
|
||||||
toRadius = 1;
|
|
||||||
radius = toRadius;
|
|
||||||
}
|
|
||||||
void setCutRotation(float toRotation)
|
|
||||||
{
|
|
||||||
if (toRotation < -1)
|
|
||||||
toRotation = -1;
|
|
||||||
else if (toRotation > 1)
|
|
||||||
toRotation = 1;
|
|
||||||
cutRotation = toRotation;
|
|
||||||
hasCutFaceSettings = true;
|
|
||||||
}
|
|
||||||
void setCutFace(dust3d::CutFace face)
|
|
||||||
{
|
|
||||||
cutFace = face;
|
|
||||||
cutFaceLinkedId = dust3d::Uuid();
|
|
||||||
hasCutFaceSettings = true;
|
|
||||||
}
|
|
||||||
void setCutFaceLinkedId(const dust3d::Uuid& linkedId)
|
|
||||||
{
|
|
||||||
if (linkedId.isNull()) {
|
|
||||||
clearCutFaceSettings();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cutFace = dust3d::CutFace::UserDefined;
|
|
||||||
cutFaceLinkedId = linkedId;
|
|
||||||
hasCutFaceSettings = true;
|
|
||||||
}
|
|
||||||
void clearCutFaceSettings()
|
|
||||||
{
|
|
||||||
cutFace = dust3d::CutFace::Quad;
|
|
||||||
cutFaceLinkedId = dust3d::Uuid();
|
|
||||||
cutRotation = 0;
|
|
||||||
hasCutFaceSettings = false;
|
|
||||||
}
|
|
||||||
float getX(bool rotated = false) const
|
|
||||||
{
|
|
||||||
if (rotated)
|
|
||||||
return m_y;
|
|
||||||
return m_x;
|
|
||||||
}
|
|
||||||
float getY(bool rotated = false) const
|
|
||||||
{
|
|
||||||
if (rotated)
|
|
||||||
return m_x;
|
|
||||||
return m_y;
|
|
||||||
}
|
|
||||||
float getZ(bool rotated = false) const
|
|
||||||
{
|
|
||||||
(void)rotated;
|
|
||||||
return m_z;
|
|
||||||
}
|
|
||||||
void setX(float x)
|
|
||||||
{
|
|
||||||
m_x = x;
|
|
||||||
}
|
|
||||||
void setY(float y)
|
|
||||||
{
|
|
||||||
m_y = y;
|
|
||||||
}
|
|
||||||
void setZ(float z)
|
|
||||||
{
|
|
||||||
m_z = z;
|
|
||||||
}
|
|
||||||
void addX(float x)
|
|
||||||
{
|
|
||||||
m_x += x;
|
|
||||||
}
|
|
||||||
void addY(float y)
|
|
||||||
{
|
|
||||||
m_y += y;
|
|
||||||
}
|
|
||||||
void addZ(float z)
|
|
||||||
{
|
|
||||||
m_z += z;
|
|
||||||
}
|
|
||||||
dust3d::Uuid id;
|
|
||||||
dust3d::Uuid partId;
|
|
||||||
QString name;
|
|
||||||
float radius;
|
|
||||||
float cutRotation;
|
|
||||||
dust3d::CutFace cutFace;
|
|
||||||
dust3d::Uuid cutFaceLinkedId;
|
|
||||||
bool hasCutFaceSettings;
|
|
||||||
std::vector<dust3d::Uuid> edgeIds;
|
|
||||||
|
|
||||||
private:
|
|
||||||
float m_x;
|
|
||||||
float m_y;
|
|
||||||
float m_z;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SkeletonEdge {
|
|
||||||
public:
|
|
||||||
SkeletonEdge(const dust3d::Uuid& withId = dust3d::Uuid())
|
|
||||||
{
|
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
|
||||||
}
|
|
||||||
dust3d::Uuid id;
|
|
||||||
dust3d::Uuid partId;
|
|
||||||
QString name;
|
|
||||||
std::vector<dust3d::Uuid> nodeIds;
|
|
||||||
dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const
|
|
||||||
{
|
|
||||||
if (nodeIds.size() != 2)
|
|
||||||
return dust3d::Uuid();
|
|
||||||
return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SkeletonPart {
|
|
||||||
public:
|
|
||||||
dust3d::Uuid id;
|
|
||||||
QString name;
|
|
||||||
bool visible;
|
|
||||||
bool locked;
|
|
||||||
bool subdived;
|
|
||||||
bool disabled;
|
|
||||||
bool xMirrored;
|
|
||||||
dust3d::PartBase base;
|
|
||||||
float deformThickness;
|
|
||||||
float deformWidth;
|
|
||||||
bool deformUnified;
|
|
||||||
bool rounded;
|
|
||||||
bool chamfered;
|
|
||||||
QColor color;
|
|
||||||
bool hasColor;
|
|
||||||
dust3d::Uuid componentId;
|
|
||||||
std::vector<dust3d::Uuid> nodeIds;
|
|
||||||
bool dirty;
|
|
||||||
float cutRotation;
|
|
||||||
dust3d::CutFace cutFace;
|
|
||||||
dust3d::Uuid cutFaceLinkedId;
|
|
||||||
dust3d::Uuid materialId;
|
|
||||||
dust3d::PartTarget target;
|
|
||||||
float colorSolubility;
|
|
||||||
float metalness;
|
|
||||||
float roughness;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
|
||||||
}
|
|
||||||
bool hasPolyFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasSmoothFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasSubdivFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasRoundEndFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasMirrorFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasChamferFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasRotationFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasHollowFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasCutFaceFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasLayerFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasTargetFunction() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool hasBaseFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasCombineModeFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasDeformFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
bool hasColorFunction() const
|
|
||||||
{
|
|
||||||
return dust3d::PartTarget::Model == target;
|
|
||||||
}
|
|
||||||
void setDeformThickness(float toThickness)
|
|
||||||
{
|
|
||||||
if (toThickness < 0)
|
|
||||||
toThickness = 0;
|
|
||||||
else if (toThickness > 2)
|
|
||||||
toThickness = 2;
|
|
||||||
deformThickness = toThickness;
|
|
||||||
}
|
|
||||||
void setDeformWidth(float toWidth)
|
|
||||||
{
|
|
||||||
if (toWidth < 0)
|
|
||||||
toWidth = 0;
|
|
||||||
else if (toWidth > 2)
|
|
||||||
toWidth = 2;
|
|
||||||
deformWidth = toWidth;
|
|
||||||
}
|
|
||||||
void setCutRotation(float toRotation)
|
|
||||||
{
|
|
||||||
if (toRotation < -1)
|
|
||||||
toRotation = -1;
|
|
||||||
else if (toRotation > 1)
|
|
||||||
toRotation = 1;
|
|
||||||
cutRotation = toRotation;
|
|
||||||
}
|
|
||||||
void setCutFace(dust3d::CutFace face)
|
|
||||||
{
|
|
||||||
cutFace = face;
|
|
||||||
cutFaceLinkedId = dust3d::Uuid();
|
|
||||||
}
|
|
||||||
void setCutFaceLinkedId(const dust3d::Uuid& linkedId)
|
|
||||||
{
|
|
||||||
if (linkedId.isNull()) {
|
|
||||||
setCutFace(dust3d::CutFace::Quad);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cutFace = dust3d::CutFace::UserDefined;
|
|
||||||
cutFaceLinkedId = linkedId;
|
|
||||||
}
|
|
||||||
bool deformThicknessAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(deformThickness - 1.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool deformWidthAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(deformWidth - 1.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool deformAdjusted() const
|
|
||||||
{
|
|
||||||
return deformThicknessAdjusted() || deformWidthAdjusted() || deformUnified;
|
|
||||||
}
|
|
||||||
bool colorSolubilityAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(colorSolubility - 0.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool metalnessAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(metalness - 0.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool roughnessAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(roughness - 1.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool cutRotationAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(cutRotation - 0.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool hollowThicknessAdjusted() const
|
|
||||||
{
|
|
||||||
return fabs(hollowThickness - 0.0) >= 0.01;
|
|
||||||
}
|
|
||||||
bool cutFaceAdjusted() const
|
|
||||||
{
|
|
||||||
return cutFace != dust3d::CutFace::Quad;
|
|
||||||
}
|
|
||||||
bool cutAdjusted() const
|
|
||||||
{
|
|
||||||
return cutRotationAdjusted() || cutFaceAdjusted() || hollowThicknessAdjusted();
|
|
||||||
}
|
|
||||||
bool materialAdjusted() const
|
|
||||||
{
|
|
||||||
return !materialId.isNull();
|
|
||||||
}
|
|
||||||
bool isEditVisible() const
|
|
||||||
{
|
|
||||||
return visible && !disabled;
|
|
||||||
}
|
|
||||||
void copyAttributes(const SkeletonPart& other)
|
|
||||||
{
|
|
||||||
visible = other.visible;
|
|
||||||
locked = other.locked;
|
|
||||||
subdived = other.subdived;
|
|
||||||
disabled = other.disabled;
|
|
||||||
xMirrored = other.xMirrored;
|
|
||||||
base = other.base;
|
|
||||||
deformThickness = other.deformThickness;
|
|
||||||
deformWidth = other.deformWidth;
|
|
||||||
rounded = other.rounded;
|
|
||||||
chamfered = other.chamfered;
|
|
||||||
color = other.color;
|
|
||||||
hasColor = other.hasColor;
|
|
||||||
cutRotation = other.cutRotation;
|
|
||||||
cutFace = other.cutFace;
|
|
||||||
cutFaceLinkedId = other.cutFaceLinkedId;
|
|
||||||
componentId = other.componentId;
|
|
||||||
dirty = other.dirty;
|
|
||||||
materialId = other.materialId;
|
|
||||||
target = other.target;
|
|
||||||
colorSolubility = other.colorSolubility;
|
|
||||||
countershaded = other.countershaded;
|
|
||||||
metalness = other.metalness;
|
|
||||||
roughness = other.roughness;
|
|
||||||
deformUnified = other.deformUnified;
|
|
||||||
smooth = other.smooth;
|
|
||||||
hollowThickness = other.hollowThickness;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DISABLE_COPY(SkeletonPart);
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SkeletonDocumentEditMode {
|
|
||||||
Add = 0,
|
|
||||||
Select,
|
|
||||||
Paint,
|
|
||||||
Drag,
|
|
||||||
ZoomIn,
|
|
||||||
ZoomOut
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SkeletonProfile {
|
|
||||||
Unknown = 0,
|
|
||||||
Main,
|
|
||||||
Side
|
|
||||||
};
|
|
||||||
|
|
||||||
class SkeletonComponent {
|
|
||||||
public:
|
|
||||||
SkeletonComponent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
SkeletonComponent(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString())
|
|
||||||
{
|
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
|
||||||
if (!linkData.isEmpty()) {
|
|
||||||
if ("partId" == linkDataType) {
|
|
||||||
linkToPartId = dust3d::Uuid(linkData.toUtf8().constData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dust3d::Uuid id;
|
|
||||||
QString name;
|
|
||||||
dust3d::Uuid linkToPartId;
|
|
||||||
dust3d::Uuid parentId;
|
|
||||||
bool expanded = true;
|
|
||||||
dust3d::CombineMode combineMode = dust3d::CombineMode::Normal;
|
|
||||||
bool dirty = true;
|
|
||||||
std::vector<dust3d::Uuid> childrenIds;
|
|
||||||
bool isPreviewMeshObsolete = false;
|
|
||||||
std::unique_ptr<QImage> previewImage;
|
|
||||||
bool isPreviewImageDecorationObsolete = false;
|
|
||||||
QPixmap previewPixmap;
|
|
||||||
QString linkData() const
|
|
||||||
{
|
|
||||||
return linkToPartId.isNull() ? QString() : QString(linkToPartId.toString().c_str());
|
|
||||||
}
|
|
||||||
QString linkDataType() const
|
|
||||||
{
|
|
||||||
return linkToPartId.isNull() ? QString() : QString("partId");
|
|
||||||
}
|
|
||||||
void addChild(dust3d::Uuid childId)
|
|
||||||
{
|
|
||||||
if (m_childrenIdSet.find(childId) != m_childrenIdSet.end())
|
|
||||||
return;
|
|
||||||
m_childrenIdSet.insert(childId);
|
|
||||||
childrenIds.push_back(childId);
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
if (m_childrenIdSet.find(it) == m_childrenIdSet.end()) {
|
|
||||||
m_childrenIdSet.insert(it);
|
|
||||||
candidates.emplace_back(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < childrenIds.size(); ++i) {
|
|
||||||
if (childId == childrenIds[i]) {
|
|
||||||
size_t newAddSize = candidates.size() - 1;
|
|
||||||
if (newAddSize > 0) {
|
|
||||||
size_t oldSize = childrenIds.size();
|
|
||||||
childrenIds.resize(childrenIds.size() + newAddSize);
|
|
||||||
for (int j = (int)oldSize - 1; j > (int)i; --j) {
|
|
||||||
childrenIds[j + newAddSize] = childrenIds[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t k = 0; k < candidates.size(); ++k)
|
|
||||||
childrenIds[i + k] = candidates[k];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void removeChild(dust3d::Uuid childId)
|
|
||||||
{
|
|
||||||
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
|
|
||||||
return;
|
|
||||||
m_childrenIdSet.erase(childId);
|
|
||||||
auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
|
||||||
if (findResult != childrenIds.end())
|
|
||||||
childrenIds.erase(findResult);
|
|
||||||
}
|
|
||||||
void replaceChild(dust3d::Uuid childId, dust3d::Uuid newId)
|
|
||||||
{
|
|
||||||
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
|
|
||||||
return;
|
|
||||||
if (m_childrenIdSet.find(newId) != m_childrenIdSet.end())
|
|
||||||
return;
|
|
||||||
m_childrenIdSet.erase(childId);
|
|
||||||
m_childrenIdSet.insert(newId);
|
|
||||||
auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
|
||||||
if (findResult != childrenIds.end())
|
|
||||||
*findResult = newId;
|
|
||||||
}
|
|
||||||
void moveChildUp(dust3d::Uuid childId)
|
|
||||||
{
|
|
||||||
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
|
||||||
if (it == childrenIds.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto index = std::distance(childrenIds.begin(), it);
|
|
||||||
if (index == 0)
|
|
||||||
return;
|
|
||||||
std::swap(childrenIds[index - 1], childrenIds[index]);
|
|
||||||
}
|
|
||||||
void moveChildDown(dust3d::Uuid childId)
|
|
||||||
{
|
|
||||||
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
|
||||||
if (it == childrenIds.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto index = std::distance(childrenIds.begin(), it);
|
|
||||||
if (index == (int)childrenIds.size() - 1)
|
|
||||||
return;
|
|
||||||
std::swap(childrenIds[index], childrenIds[index + 1]);
|
|
||||||
}
|
|
||||||
void moveChildToTop(dust3d::Uuid childId)
|
|
||||||
{
|
|
||||||
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
|
||||||
if (it == childrenIds.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto index = std::distance(childrenIds.begin(), it);
|
|
||||||
if (index == 0)
|
|
||||||
return;
|
|
||||||
for (int i = index; i >= 1; i--)
|
|
||||||
std::swap(childrenIds[i - 1], childrenIds[i]);
|
|
||||||
}
|
|
||||||
void moveChildToBottom(dust3d::Uuid childId)
|
|
||||||
{
|
|
||||||
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
|
|
||||||
if (it == childrenIds.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto index = std::distance(childrenIds.begin(), it);
|
|
||||||
if (index == (int)childrenIds.size() - 1)
|
|
||||||
return;
|
|
||||||
for (int i = index; i <= (int)childrenIds.size() - 2; i++)
|
|
||||||
std::swap(childrenIds[i], childrenIds[i + 1]);
|
|
||||||
}
|
|
||||||
void updatePreviewMesh(std::unique_ptr<ModelMesh> mesh)
|
|
||||||
{
|
|
||||||
m_previewMesh = std::move(mesh);
|
|
||||||
isPreviewMeshObsolete = true;
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
Q_OBJECT
|
|
||||||
signals:
|
|
||||||
void partAdded(dust3d::Uuid partId);
|
|
||||||
void nodeAdded(dust3d::Uuid nodeId);
|
|
||||||
void edgeAdded(dust3d::Uuid edgeId);
|
|
||||||
void partRemoved(dust3d::Uuid partId);
|
|
||||||
void partLockStateChanged(dust3d::Uuid partId);
|
|
||||||
void partVisibleStateChanged(dust3d::Uuid partId);
|
|
||||||
void partDisableStateChanged(dust3d::Uuid partId);
|
|
||||||
void componentNameChanged(dust3d::Uuid componentId);
|
|
||||||
void componentChildrenChanged(dust3d::Uuid componentId);
|
|
||||||
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 nodeRemoved(dust3d::Uuid nodeId);
|
|
||||||
void edgeRemoved(dust3d::Uuid edgeId);
|
|
||||||
void nodeRadiusChanged(dust3d::Uuid nodeId);
|
|
||||||
void nodeOriginChanged(dust3d::Uuid nodeId);
|
|
||||||
void edgeReversed(dust3d::Uuid edgeId);
|
|
||||||
void originChanged();
|
|
||||||
void skeletonChanged();
|
|
||||||
void optionsChanged();
|
|
||||||
void xlockStateChanged();
|
|
||||||
void ylockStateChanged();
|
|
||||||
void zlockStateChanged();
|
|
||||||
void radiusLockStateChanged();
|
|
||||||
|
|
||||||
public:
|
|
||||||
SkeletonDocumentEditMode editMode = SkeletonDocumentEditMode::Select;
|
|
||||||
bool xlocked = false;
|
|
||||||
bool ylocked = false;
|
|
||||||
bool zlocked = false;
|
|
||||||
bool radiusLocked = false;
|
|
||||||
QImage turnaround;
|
|
||||||
QByteArray turnaroundPngByteArray;
|
|
||||||
std::map<dust3d::Uuid, SkeletonPart> partMap;
|
|
||||||
std::map<dust3d::Uuid, SkeletonNode> nodeMap;
|
|
||||||
std::map<dust3d::Uuid, SkeletonEdge> edgeMap;
|
|
||||||
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;
|
|
||||||
bool isNodeConnectable(dust3d::Uuid nodeId) 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 resetDirtyFlags();
|
|
||||||
void markAllDirty();
|
|
||||||
|
|
||||||
virtual bool undoable() const = 0;
|
|
||||||
virtual bool redoable() const = 0;
|
|
||||||
virtual bool hasPastableNodesInClipboard() const = 0;
|
|
||||||
virtual bool originSettled() const = 0;
|
|
||||||
virtual bool isNodeEditable(dust3d::Uuid nodeId) const = 0;
|
|
||||||
virtual bool isEdgeEditable(dust3d::Uuid edgeId) const = 0;
|
|
||||||
virtual bool isNodeDeactivated(dust3d::Uuid nodeId) const
|
|
||||||
{
|
|
||||||
(void)nodeId;
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
virtual bool isEdgeDeactivated(dust3d::Uuid edgeId) const
|
|
||||||
{
|
|
||||||
(void)edgeId;
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
virtual void copyNodes(std::set<dust3d::Uuid> nodeIdSet) const = 0;
|
|
||||||
|
|
||||||
float getOriginX(bool rotated = false) const
|
|
||||||
{
|
|
||||||
if (rotated)
|
|
||||||
return m_originY;
|
|
||||||
return m_originX;
|
|
||||||
}
|
|
||||||
float getOriginY(bool rotated = false) const
|
|
||||||
{
|
|
||||||
if (rotated)
|
|
||||||
return m_originX;
|
|
||||||
return m_originY;
|
|
||||||
}
|
|
||||||
float getOriginZ(bool rotated = false) const
|
|
||||||
{
|
|
||||||
(void)rotated;
|
|
||||||
return m_originZ;
|
|
||||||
}
|
|
||||||
void setOriginX(float originX)
|
|
||||||
{
|
|
||||||
m_originX = originX;
|
|
||||||
}
|
|
||||||
void setOriginY(float originY)
|
|
||||||
{
|
|
||||||
m_originY = originY;
|
|
||||||
}
|
|
||||||
void setOriginZ(float originZ)
|
|
||||||
{
|
|
||||||
m_originZ = originZ;
|
|
||||||
}
|
|
||||||
void addOriginX(float originX)
|
|
||||||
{
|
|
||||||
m_originX += originX;
|
|
||||||
}
|
|
||||||
void addOriginY(float originY)
|
|
||||||
{
|
|
||||||
m_originY += originY;
|
|
||||||
}
|
|
||||||
void addOriginZ(float originZ)
|
|
||||||
{
|
|
||||||
m_originZ += originZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
virtual void undo() = 0;
|
|
||||||
virtual void redo() = 0;
|
|
||||||
virtual void paste() = 0;
|
|
||||||
|
|
||||||
void removeNode(dust3d::Uuid nodeId);
|
|
||||||
void removeEdge(dust3d::Uuid edgeId);
|
|
||||||
void removePart(dust3d::Uuid partId);
|
|
||||||
void addNodeWithId(dust3d::Uuid nodeId, float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
|
||||||
void addNode(float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
|
||||||
void scaleNodeByAddRadius(dust3d::Uuid nodeId, float amount);
|
|
||||||
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
|
||||||
void setNodeOrigin(dust3d::Uuid nodeId, float x, float y, float z);
|
|
||||||
void setNodeRadius(dust3d::Uuid nodeId, float radius);
|
|
||||||
void switchNodeXZ(dust3d::Uuid nodeId);
|
|
||||||
void moveOriginBy(float x, float y, float z);
|
|
||||||
void addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId);
|
|
||||||
void moveComponentUp(dust3d::Uuid componentId);
|
|
||||||
void moveComponentDown(dust3d::Uuid componentId);
|
|
||||||
void moveComponentToTop(dust3d::Uuid componentId);
|
|
||||||
void moveComponentToBottom(dust3d::Uuid componentId);
|
|
||||||
void renameComponent(dust3d::Uuid componentId, QString name);
|
|
||||||
void removeComponent(dust3d::Uuid componentId);
|
|
||||||
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 createNewChildComponent(dust3d::Uuid parentComponentId);
|
|
||||||
void setComponentExpandState(dust3d::Uuid componentId, bool expanded);
|
|
||||||
void hideOtherComponents(dust3d::Uuid componentId);
|
|
||||||
void lockOtherComponents(dust3d::Uuid componentId);
|
|
||||||
void hideAllComponents();
|
|
||||||
void showAllComponents();
|
|
||||||
void showOrHideAllComponents();
|
|
||||||
void collapseAllComponents();
|
|
||||||
void expandAllComponents();
|
|
||||||
void lockAllComponents();
|
|
||||||
void unlockAllComponents();
|
|
||||||
void hideDescendantComponents(dust3d::Uuid componentId);
|
|
||||||
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 setPartLockState(dust3d::Uuid partId, bool locked);
|
|
||||||
void setPartVisibleState(dust3d::Uuid partId, bool visible);
|
|
||||||
void setPartDisableState(dust3d::Uuid partId, bool disabled);
|
|
||||||
void enableAllPositionRelatedLocks();
|
|
||||||
void disableAllPositionRelatedLocks();
|
|
||||||
bool isPartReadonly(dust3d::Uuid partId) const;
|
|
||||||
void breakEdge(dust3d::Uuid edgeId);
|
|
||||||
void reduceNode(dust3d::Uuid nodeId);
|
|
||||||
void reverseEdge(dust3d::Uuid edgeId);
|
|
||||||
void setXlockState(bool locked);
|
|
||||||
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 removePartDontCareComponent(dust3d::Uuid partId);
|
|
||||||
void addPartToComponent(dust3d::Uuid partId, dust3d::Uuid componentId);
|
|
||||||
bool isDescendantComponent(dust3d::Uuid componentId, dust3d::Uuid suspiciousId);
|
|
||||||
void removeComponentRecursively(dust3d::Uuid componentId);
|
|
||||||
void updateLinkedPart(dust3d::Uuid oldPartId, dust3d::Uuid newPartId);
|
|
||||||
dust3d::Uuid createNode(dust3d::Uuid nodeId, float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument* document)
|
SkeletonGraphicsWidget::SkeletonGraphicsWidget(const Document* document)
|
||||||
: m_document(document)
|
: m_document(document)
|
||||||
{
|
{
|
||||||
setRenderHint(QPainter::Antialiasing, false);
|
setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
@ -101,20 +101,20 @@ void SkeletonGraphicsWidget::shortcutEscape()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Add == m_document->editMode || SkeletonDocumentEditMode::Paint == m_document->editMode) {
|
if (DocumentEditMode::Add == m_document->editMode || DocumentEditMode::Paint == m_document->editMode) {
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Select);
|
emit setEditMode(DocumentEditMode::Select);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonGraphicsWidget::showContextMenu(const QPoint& pos)
|
void SkeletonGraphicsWidget::showContextMenu(const QPoint& pos)
|
||||||
{
|
{
|
||||||
if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Select);
|
emit setEditMode(DocumentEditMode::Select);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select != m_document->editMode) {
|
if (DocumentEditMode::Select != m_document->editMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,19 +122,19 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint& pos)
|
||||||
|
|
||||||
QAction addAction(tr("Add..."), this);
|
QAction addAction(tr("Add..."), this);
|
||||||
connect(&addAction, &QAction::triggered, [=]() {
|
connect(&addAction, &QAction::triggered, [=]() {
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Add);
|
emit setEditMode(DocumentEditMode::Add);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&addAction);
|
contextMenu.addAction(&addAction);
|
||||||
|
|
||||||
QAction undoAction(tr("Undo"), this);
|
QAction undoAction(tr("Undo"), this);
|
||||||
if (m_document->undoable()) {
|
if (m_document->undoable()) {
|
||||||
connect(&undoAction, &QAction::triggered, m_document, &SkeletonDocument::undo);
|
connect(&undoAction, &QAction::triggered, m_document, &Document::undo);
|
||||||
contextMenu.addAction(&undoAction);
|
contextMenu.addAction(&undoAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction redoAction(tr("Redo"), this);
|
QAction redoAction(tr("Redo"), this);
|
||||||
if (m_document->redoable()) {
|
if (m_document->redoable()) {
|
||||||
connect(&redoAction, &QAction::triggered, m_document, &SkeletonDocument::redo);
|
connect(&redoAction, &QAction::triggered, m_document, &Document::redo);
|
||||||
contextMenu.addAction(&redoAction);
|
contextMenu.addAction(&redoAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint& pos)
|
||||||
|
|
||||||
QAction pasteAction(tr("Paste"), this);
|
QAction pasteAction(tr("Paste"), this);
|
||||||
if (m_document->hasPastableNodesInClipboard()) {
|
if (m_document->hasPastableNodesInClipboard()) {
|
||||||
connect(&pasteAction, &QAction::triggered, m_document, &SkeletonDocument::paste);
|
connect(&pasteAction, &QAction::triggered, m_document, &Document::paste);
|
||||||
contextMenu.addAction(&pasteAction);
|
contextMenu.addAction(&pasteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,7 +657,7 @@ const QImage* SkeletonGraphicsWidget::loadedTurnaroundImage() const
|
||||||
|
|
||||||
void SkeletonGraphicsWidget::updateCursor()
|
void SkeletonGraphicsWidget::updateCursor()
|
||||||
{
|
{
|
||||||
if (SkeletonDocumentEditMode::Add != m_document->editMode) {
|
if (DocumentEditMode::Add != m_document->editMode) {
|
||||||
m_cursorEdgeItem->hide();
|
m_cursorEdgeItem->hide();
|
||||||
m_cursorNodeItem->hide();
|
m_cursorNodeItem->hide();
|
||||||
}
|
}
|
||||||
|
@ -670,7 +670,7 @@ void SkeletonGraphicsWidget::updateCursor()
|
||||||
void SkeletonGraphicsWidget::editModeChanged()
|
void SkeletonGraphicsWidget::editModeChanged()
|
||||||
{
|
{
|
||||||
updateCursor();
|
updateCursor();
|
||||||
if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
SkeletonGraphicsNodeItem* choosenNodeItem = nullptr;
|
SkeletonGraphicsNodeItem* choosenNodeItem = nullptr;
|
||||||
if (!m_rangeSelectionSet.empty()) {
|
if (!m_rangeSelectionSet.empty()) {
|
||||||
std::set<SkeletonGraphicsNodeItem*> nodeItems;
|
std::set<SkeletonGraphicsNodeItem*> nodeItems;
|
||||||
|
@ -771,7 +771,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent* event)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (m_rangeSelectionStarted) {
|
if (m_rangeSelectionStarted) {
|
||||||
QPointF mouseScenePos = mouseEventScenePos(event);
|
QPointF mouseScenePos = mouseEventScenePos(event);
|
||||||
m_selectionItem->updateRange(m_rangeSelectionStartPos, mouseScenePos);
|
m_selectionItem->updateRange(m_rangeSelectionStartPos, mouseScenePos);
|
||||||
|
@ -782,7 +782,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent* event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode || SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode || DocumentEditMode::Add == m_document->editMode) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// > For overlapping nodes, you can make it a bit better by selecting the node center nearest the mouse, rather than simply checking against the wider circle.
|
// > For overlapping nodes, you can make it a bit better by selecting the node center nearest the mouse, rather than simply checking against the wider circle.
|
||||||
|
@ -872,7 +872,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent* event)
|
||||||
hoverPart(hoveredPartId);
|
hoverPart(hoveredPartId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
QPointF mouseScenePos = mouseEventScenePos(event);
|
QPointF mouseScenePos = mouseEventScenePos(event);
|
||||||
m_cursorNodeItem->setOrigin(mouseScenePos);
|
m_cursorNodeItem->setOrigin(mouseScenePos);
|
||||||
if (m_addFromNodeItem) {
|
if (m_addFromNodeItem) {
|
||||||
|
@ -889,7 +889,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent* event)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (m_moveStarted) {
|
if (m_moveStarted) {
|
||||||
if (m_checkedOriginItem) {
|
if (m_checkedOriginItem) {
|
||||||
QPointF mouseScenePos = mouseEventScenePos(event);
|
QPointF mouseScenePos = mouseEventScenePos(event);
|
||||||
|
@ -1200,12 +1200,12 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent* event)
|
||||||
delta = 1;
|
delta = 1;
|
||||||
else
|
else
|
||||||
delta = -1;
|
delta = -1;
|
||||||
if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
if (m_cursorNodeItem->isVisible()) {
|
if (m_cursorNodeItem->isVisible()) {
|
||||||
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + delta);
|
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + delta);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
} else if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (!m_rangeSelectionSet.empty()) {
|
if (!m_rangeSelectionSet.empty()) {
|
||||||
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
|
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
|
||||||
scaleSelected(delta);
|
scaleSelected(delta);
|
||||||
|
@ -1347,13 +1347,13 @@ QPointF SkeletonGraphicsWidget::mouseEventScenePos(QMouseEvent* event)
|
||||||
bool SkeletonGraphicsWidget::mousePress(QMouseEvent* event)
|
bool SkeletonGraphicsWidget::mousePress(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode) {
|
if (DocumentEditMode::ZoomIn == m_document->editMode) {
|
||||||
ViewportAnchor lastAnchor = transformationAnchor();
|
ViewportAnchor lastAnchor = transformationAnchor();
|
||||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||||
scale(1.25, 1.25);
|
scale(1.25, 1.25);
|
||||||
setTransformationAnchor(lastAnchor);
|
setTransformationAnchor(lastAnchor);
|
||||||
return true;
|
return true;
|
||||||
} else if (SkeletonDocumentEditMode::ZoomOut == m_document->editMode) {
|
} else if (DocumentEditMode::ZoomOut == m_document->editMode) {
|
||||||
ViewportAnchor lastAnchor = transformationAnchor();
|
ViewportAnchor lastAnchor = transformationAnchor();
|
||||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||||
scale(0.8, 0.8);
|
scale(0.8, 0.8);
|
||||||
|
@ -1363,20 +1363,20 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent* event)
|
||||||
// setTransform(QTransform());
|
// setTransform(QTransform());
|
||||||
//}
|
//}
|
||||||
return true;
|
return true;
|
||||||
} else if (SkeletonDocumentEditMode::Drag == m_document->editMode) {
|
} else if (DocumentEditMode::Drag == m_document->editMode) {
|
||||||
if (!m_dragStarted) {
|
if (!m_dragStarted) {
|
||||||
m_lastGlobalPos = event->globalPos();
|
m_lastGlobalPos = event->globalPos();
|
||||||
m_dragStarted = true;
|
m_dragStarted = true;
|
||||||
updateCursor();
|
updateCursor();
|
||||||
}
|
}
|
||||||
} else if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
} else if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
if (m_cursorNodeItem->isVisible()) {
|
if (m_cursorNodeItem->isVisible()) {
|
||||||
if (m_addFromNodeItem) {
|
if (m_addFromNodeItem) {
|
||||||
if (m_hoveredNodeItem && m_addFromNodeItem && m_hoveredNodeItem != m_addFromNodeItem && m_hoveredNodeItem->profile() == m_addFromNodeItem->profile() && !m_document->findEdgeByNodes(m_addFromNodeItem->id(), m_hoveredNodeItem->id()) && m_document->isNodeEditable(m_hoveredNodeItem->id())) {
|
if (m_hoveredNodeItem && m_addFromNodeItem && m_hoveredNodeItem != m_addFromNodeItem && m_hoveredNodeItem->profile() == m_addFromNodeItem->profile() && !m_document->findEdgeByNodes(m_addFromNodeItem->id(), m_hoveredNodeItem->id()) && m_document->isNodeEditable(m_hoveredNodeItem->id())) {
|
||||||
if (m_document->isNodeConnectable(m_hoveredNodeItem->id())) {
|
if (m_document->isNodeConnectable(m_hoveredNodeItem->id())) {
|
||||||
emit addEdge(m_addFromNodeItem->id(), m_hoveredNodeItem->id());
|
emit addEdge(m_addFromNodeItem->id(), m_hoveredNodeItem->id());
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Select);
|
emit setEditMode(DocumentEditMode::Select);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1410,7 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent* event)
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
} else if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
if (m_hoveredOriginItem != m_checkedOriginItem) {
|
if (m_hoveredOriginItem != m_checkedOriginItem) {
|
||||||
if (m_checkedOriginItem) {
|
if (m_checkedOriginItem) {
|
||||||
|
@ -1467,7 +1467,7 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent* event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (!m_rangeSelectionStarted) {
|
if (!m_rangeSelectionStarted) {
|
||||||
m_rangeSelectionStartPos = mouseEventScenePos(event);
|
m_rangeSelectionStartPos = mouseEventScenePos(event);
|
||||||
m_rangeSelectionStarted = true;
|
m_rangeSelectionStarted = true;
|
||||||
|
@ -1644,10 +1644,10 @@ void SkeletonGraphicsWidget::shortcutDelete()
|
||||||
|
|
||||||
void SkeletonGraphicsWidget::shortcutAddMode()
|
void SkeletonGraphicsWidget::shortcutAddMode()
|
||||||
{
|
{
|
||||||
if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Select);
|
emit setEditMode(DocumentEditMode::Select);
|
||||||
} else {
|
} else {
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Add);
|
emit setEditMode(DocumentEditMode::Add);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1708,12 +1708,12 @@ void SkeletonGraphicsWidget::shortcutPaste()
|
||||||
|
|
||||||
void SkeletonGraphicsWidget::shortcutSelectMode()
|
void SkeletonGraphicsWidget::shortcutSelectMode()
|
||||||
{
|
{
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Select);
|
emit setEditMode(DocumentEditMode::Select);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonGraphicsWidget::shortcutPaintMode()
|
void SkeletonGraphicsWidget::shortcutPaintMode()
|
||||||
{
|
{
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Paint);
|
emit setEditMode(DocumentEditMode::Paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonGraphicsWidget::shortcutZoomRenderedModelByMinus10()
|
void SkeletonGraphicsWidget::shortcutZoomRenderedModelByMinus10()
|
||||||
|
@ -1729,10 +1729,10 @@ void SkeletonGraphicsWidget::shortcutZoomSelectedByMinus1()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
|
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) {
|
||||||
zoomSelected(-1);
|
zoomSelected(-1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
} else if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
} else if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
if (m_cursorNodeItem->isVisible()) {
|
if (m_cursorNodeItem->isVisible()) {
|
||||||
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + -1);
|
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + -1);
|
||||||
}
|
}
|
||||||
|
@ -1752,10 +1752,10 @@ void SkeletonGraphicsWidget::shortcutZoomSelectedBy1()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
|
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) {
|
||||||
zoomSelected(1);
|
zoomSelected(1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
} else if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
} else if (DocumentEditMode::Add == m_document->editMode) {
|
||||||
if (m_cursorNodeItem->isVisible()) {
|
if (m_cursorNodeItem->isVisible()) {
|
||||||
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + 1);
|
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + 1);
|
||||||
}
|
}
|
||||||
|
@ -1767,7 +1767,7 @@ void SkeletonGraphicsWidget::shortcutRotateSelectedByMinus1()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
||||||
rotateSelected(-1);
|
rotateSelected(-1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
}
|
}
|
||||||
|
@ -1778,7 +1778,7 @@ void SkeletonGraphicsWidget::shortcutRotateSelectedBy1()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
||||||
rotateSelected(1);
|
rotateSelected(1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
}
|
}
|
||||||
|
@ -1789,7 +1789,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToLeft()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (m_checkedOriginItem) {
|
if (m_checkedOriginItem) {
|
||||||
moveCheckedOrigin(-1, 0);
|
moveCheckedOrigin(-1, 0);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
|
@ -1805,7 +1805,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToRight()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (m_checkedOriginItem) {
|
if (m_checkedOriginItem) {
|
||||||
moveCheckedOrigin(1, 0);
|
moveCheckedOrigin(1, 0);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
|
@ -1821,7 +1821,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToUp()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (m_checkedOriginItem) {
|
if (m_checkedOriginItem) {
|
||||||
moveCheckedOrigin(0, -1);
|
moveCheckedOrigin(0, -1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
|
@ -1837,7 +1837,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToDown()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (m_checkedOriginItem) {
|
if (m_checkedOriginItem) {
|
||||||
moveCheckedOrigin(0, 1);
|
moveCheckedOrigin(0, 1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
|
@ -1853,7 +1853,7 @@ void SkeletonGraphicsWidget::shortcutScaleSelectedByMinus1()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
||||||
scaleSelected(-1);
|
scaleSelected(-1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
}
|
}
|
||||||
|
@ -1864,7 +1864,7 @@ void SkeletonGraphicsWidget::shortcutScaleSelectedBy1()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
||||||
scaleSelected(1);
|
scaleSelected(1);
|
||||||
emit groupOperationAdded();
|
emit groupOperationAdded();
|
||||||
}
|
}
|
||||||
|
@ -1875,7 +1875,7 @@ void SkeletonGraphicsWidget::shortcutSwitchProfileOnSelected()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && hasSelection()) {
|
||||||
switchProfileOnRangeSelection();
|
switchProfileOnRangeSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1885,7 +1885,7 @@ void SkeletonGraphicsWidget::shortcutShowOrHideSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
if (DocumentEditMode::Select == m_document->editMode) {
|
||||||
if (!m_lastCheckedPart.isNull()) {
|
if (!m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partVisible = part && part->visible;
|
bool partVisible = part && part->visible;
|
||||||
|
@ -1902,7 +1902,7 @@ void SkeletonGraphicsWidget::shortcutEnableOrDisableSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partDisabled = part && part->disabled;
|
bool partDisabled = part && part->disabled;
|
||||||
emit setPartDisableState(m_lastCheckedPart, !partDisabled);
|
emit setPartDisableState(m_lastCheckedPart, !partDisabled);
|
||||||
|
@ -1915,7 +1915,7 @@ void SkeletonGraphicsWidget::shortcutLockOrUnlockSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partLocked = part && part->locked;
|
bool partLocked = part && part->locked;
|
||||||
emit setPartLockState(m_lastCheckedPart, !partLocked);
|
emit setPartLockState(m_lastCheckedPart, !partLocked);
|
||||||
|
@ -1928,7 +1928,7 @@ void SkeletonGraphicsWidget::shortcutXmirrorOnOrOffSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partXmirrored = part && part->xMirrored;
|
bool partXmirrored = part && part->xMirrored;
|
||||||
emit setPartXmirrorState(m_lastCheckedPart, !partXmirrored);
|
emit setPartXmirrorState(m_lastCheckedPart, !partXmirrored);
|
||||||
|
@ -1941,7 +1941,7 @@ void SkeletonGraphicsWidget::shortcutSubdivedOrNotSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partSubdived = part && part->subdived;
|
bool partSubdived = part && part->subdived;
|
||||||
emit setPartSubdivState(m_lastCheckedPart, !partSubdived);
|
emit setPartSubdivState(m_lastCheckedPart, !partSubdived);
|
||||||
|
@ -1954,7 +1954,7 @@ void SkeletonGraphicsWidget::shortcutChamferedOrNotSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partChamfered = part && part->chamfered;
|
bool partChamfered = part && part->chamfered;
|
||||||
emit setPartChamferState(m_lastCheckedPart, !partChamfered);
|
emit setPartChamferState(m_lastCheckedPart, !partChamfered);
|
||||||
|
@ -1975,7 +1975,7 @@ void SkeletonGraphicsWidget::shortcutRoundEndOrNotSelectedPart()
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((SkeletonDocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
if ((DocumentEditMode::Select == m_document->editMode) && !m_lastCheckedPart.isNull()) {
|
||||||
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
const SkeletonPart* part = m_document->findPart(m_lastCheckedPart);
|
||||||
bool partRounded = part && part->rounded;
|
bool partRounded = part && part->rounded;
|
||||||
emit setPartRoundState(m_lastCheckedPart, !partRounded);
|
emit setPartRoundState(m_lastCheckedPart, !partRounded);
|
||||||
|
@ -1986,10 +1986,10 @@ void SkeletonGraphicsWidget::shortcutRoundEndOrNotSelectedPart()
|
||||||
bool SkeletonGraphicsWidget::keyPress(QKeyEvent* event)
|
bool SkeletonGraphicsWidget::keyPress(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
if (event->key() == Qt::Key_Space) {
|
if (event->key() == Qt::Key_Space) {
|
||||||
if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode || SkeletonDocumentEditMode::ZoomOut == m_document->editMode || SkeletonDocumentEditMode::Select == m_document->editMode || SkeletonDocumentEditMode::Add == m_document->editMode) {
|
if (DocumentEditMode::ZoomIn == m_document->editMode || DocumentEditMode::ZoomOut == m_document->editMode || DocumentEditMode::Select == m_document->editMode || DocumentEditMode::Add == m_document->editMode) {
|
||||||
m_inTempDragMode = true;
|
m_inTempDragMode = true;
|
||||||
m_modeBeforeEnterTempDragMode = m_document->editMode;
|
m_modeBeforeEnterTempDragMode = m_document->editMode;
|
||||||
emit setEditMode(SkeletonDocumentEditMode::Drag);
|
emit setEditMode(DocumentEditMode::Drag);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2044,10 +2044,6 @@ void SkeletonGraphicsWidget::nodeAdded(dust3d::Uuid nodeId)
|
||||||
sideProfileItem->setRadius(sceneRadiusFromUnified(node->radius));
|
sideProfileItem->setRadius(sceneRadiusFromUnified(node->radius));
|
||||||
mainProfileItem->setId(nodeId);
|
mainProfileItem->setId(nodeId);
|
||||||
sideProfileItem->setId(nodeId);
|
sideProfileItem->setId(nodeId);
|
||||||
if (m_document->isNodeDeactivated(nodeId)) {
|
|
||||||
mainProfileItem->setDeactivated(true);
|
|
||||||
sideProfileItem->setDeactivated(true);
|
|
||||||
}
|
|
||||||
scene()->addItem(mainProfileItem);
|
scene()->addItem(mainProfileItem);
|
||||||
scene()->addItem(sideProfileItem);
|
scene()->addItem(sideProfileItem);
|
||||||
nodeItemMap[nodeId] = std::make_pair(mainProfileItem, sideProfileItem);
|
nodeItemMap[nodeId] = std::make_pair(mainProfileItem, sideProfileItem);
|
||||||
|
@ -2115,10 +2111,6 @@ void SkeletonGraphicsWidget::edgeAdded(dust3d::Uuid edgeId)
|
||||||
sideProfileEdgeItem->setId(edgeId);
|
sideProfileEdgeItem->setId(edgeId);
|
||||||
mainProfileEdgeItem->setEndpoints(fromIt->second.first, toIt->second.first);
|
mainProfileEdgeItem->setEndpoints(fromIt->second.first, toIt->second.first);
|
||||||
sideProfileEdgeItem->setEndpoints(fromIt->second.second, toIt->second.second);
|
sideProfileEdgeItem->setEndpoints(fromIt->second.second, toIt->second.second);
|
||||||
if (m_document->isNodeDeactivated(edgeId)) {
|
|
||||||
mainProfileEdgeItem->setDeactivated(true);
|
|
||||||
sideProfileEdgeItem->setDeactivated(true);
|
|
||||||
}
|
|
||||||
scene()->addItem(mainProfileEdgeItem);
|
scene()->addItem(mainProfileEdgeItem);
|
||||||
scene()->addItem(sideProfileEdgeItem);
|
scene()->addItem(sideProfileEdgeItem);
|
||||||
edgeItemMap[edgeId] = std::make_pair(mainProfileEdgeItem, sideProfileEdgeItem);
|
edgeItemMap[edgeId] = std::make_pair(mainProfileEdgeItem, sideProfileEdgeItem);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
|
#ifndef DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
|
||||||
#define DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
|
#define DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
|
||||||
|
|
||||||
|
#include "document.h"
|
||||||
#include "model_widget.h"
|
#include "model_widget.h"
|
||||||
#include "skeleton_document.h"
|
|
||||||
#include "skeleton_ik_mover.h"
|
#include "skeleton_ik_mover.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "turnaround_loader.h"
|
#include "turnaround_loader.h"
|
||||||
|
@ -398,7 +398,7 @@ signals:
|
||||||
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
||||||
void removeNode(dust3d::Uuid nodeId);
|
void removeNode(dust3d::Uuid nodeId);
|
||||||
void removePart(dust3d::Uuid partId);
|
void removePart(dust3d::Uuid partId);
|
||||||
void setEditMode(SkeletonDocumentEditMode mode);
|
void setEditMode(DocumentEditMode mode);
|
||||||
void removeEdge(dust3d::Uuid edgeId);
|
void removeEdge(dust3d::Uuid edgeId);
|
||||||
void addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId);
|
void addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId);
|
||||||
void cursorChanged();
|
void cursorChanged();
|
||||||
|
@ -442,7 +442,7 @@ signals:
|
||||||
void loadedTurnaroundImageChanged();
|
void loadedTurnaroundImageChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SkeletonGraphicsWidget(const SkeletonDocument* document);
|
SkeletonGraphicsWidget(const Document* document);
|
||||||
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsNodeItem*, SkeletonGraphicsNodeItem*>> nodeItemMap;
|
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsNodeItem*, SkeletonGraphicsNodeItem*>> nodeItemMap;
|
||||||
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsEdgeItem*, SkeletonGraphicsEdgeItem*>> edgeItemMap;
|
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsEdgeItem*, SkeletonGraphicsEdgeItem*>> edgeItemMap;
|
||||||
bool mouseMove(QMouseEvent* event);
|
bool mouseMove(QMouseEvent* event);
|
||||||
|
@ -600,7 +600,7 @@ private:
|
||||||
bool isFloatEqual(float a, float b);
|
bool isFloatEqual(float a, float b);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const SkeletonDocument* m_document = nullptr;
|
const Document* m_document = nullptr;
|
||||||
QGraphicsPixmapItem* m_backgroundItem = nullptr;
|
QGraphicsPixmapItem* m_backgroundItem = nullptr;
|
||||||
bool m_turnaroundChanged = false;
|
bool m_turnaroundChanged = false;
|
||||||
TurnaroundLoader* m_turnaroundLoader = nullptr;
|
TurnaroundLoader* m_turnaroundLoader = nullptr;
|
||||||
|
@ -629,7 +629,7 @@ private:
|
||||||
bool m_eventForwardingToModelWidget = false;
|
bool m_eventForwardingToModelWidget = false;
|
||||||
ModelWidget* m_modelWidget = nullptr;
|
ModelWidget* m_modelWidget = nullptr;
|
||||||
bool m_inTempDragMode = false;
|
bool m_inTempDragMode = false;
|
||||||
SkeletonDocumentEditMode m_modeBeforeEnterTempDragMode = SkeletonDocumentEditMode::Select;
|
DocumentEditMode m_modeBeforeEnterTempDragMode = DocumentEditMode::Select;
|
||||||
float m_turnaroundOpacity = 0.25f;
|
float m_turnaroundOpacity = 0.25f;
|
||||||
bool m_rotated = false;
|
bool m_rotated = false;
|
||||||
QImage* m_backgroundImage = nullptr;
|
QImage* m_backgroundImage = nullptr;
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
#include "tube_uv_preview_image_generator.h"
|
|
||||||
|
|
||||||
const size_t TubeUvPreviewImageGenerator::m_uvImageSize = 1024;
|
|
||||||
|
|
||||||
TubeUvPreviewImageGenerator::TubeUvPreviewImageGenerator(std::vector<std::vector<dust3d::Vector2>>&& faceUvs)
|
|
||||||
: m_faceUvs(faceUvs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void TubeUvPreviewImageGenerator::generate()
|
|
||||||
{
|
|
||||||
m_previewImage = std::make_unique<QImage>(m_uvImageSize, m_uvImageSize, QImage::Format_ARGB32);
|
|
||||||
// TODO:
|
|
||||||
}
|
|
||||||
|
|
||||||
void TubeUvPreviewImageGenerator::process()
|
|
||||||
{
|
|
||||||
generate();
|
|
||||||
emit finished();
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "uv_preview_image_generator.h"
|
||||||
|
|
||||||
|
const size_t UvPreviewImageGenerator::m_uvImageSize = 1024;
|
||||||
|
|
||||||
|
UvPreviewImageGenerator::UvPreviewImageGenerator(std::vector<std::vector<dust3d::Vector2>>&& faceUvs)
|
||||||
|
: m_faceUvs(faceUvs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void UvPreviewImageGenerator::generate()
|
||||||
|
{
|
||||||
|
m_previewImage = std::make_unique<QImage>(m_uvImageSize, m_uvImageSize, QImage::Format_ARGB32);
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
void UvPreviewImageGenerator::process()
|
||||||
|
{
|
||||||
|
generate();
|
||||||
|
emit finished();
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef DUST3D_APPLICATION_TUBE_UV_PREVIEW_IMAGE_GENERATOR_H_
|
#ifndef DUST3D_APPLICATION_TUBE_PREVIEW_IMAGE_GENERATOR_H_
|
||||||
#define DUST3D_APPLICATION_TUBE_UV_PREVIEW_IMAGE_GENERATOR_H_
|
#define DUST3D_APPLICATION_TUBE_PREVIEW_IMAGE_GENERATOR_H_
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
@ -7,10 +7,10 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TubeUvPreviewImageGenerator : public QObject {
|
class UvPreviewImageGenerator : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TubeUvPreviewImageGenerator(std::vector<std::vector<dust3d::Vector2>>&& faceUvs);
|
UvPreviewImageGenerator(std::vector<std::vector<dust3d::Vector2>>&& faceUvs);
|
||||||
void generate();
|
void generate();
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016-2021 Jeremy HU <jeremy-at-dust3d dot org>. All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dust3d/base/part_base.h>
|
|
||||||
|
|
||||||
namespace dust3d {
|
|
||||||
|
|
||||||
IMPL_PartBaseFromString
|
|
||||||
IMPL_PartBaseToString
|
|
||||||
IMPL_PartBaseToDispName
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016-2021 Jeremy HU <jeremy-at-dust3d dot org>. All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DUST3D_BASE_PART_BASE_H_
|
|
||||||
#define DUST3D_BASE_PART_BASE_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace dust3d {
|
|
||||||
|
|
||||||
enum class PartBase {
|
|
||||||
XYZ = 0,
|
|
||||||
Average,
|
|
||||||
YZ,
|
|
||||||
XY,
|
|
||||||
ZX,
|
|
||||||
Count
|
|
||||||
};
|
|
||||||
PartBase PartBaseFromString(const char* baseString);
|
|
||||||
#define IMPL_PartBaseFromString \
|
|
||||||
PartBase PartBaseFromString(const char* baseString) \
|
|
||||||
{ \
|
|
||||||
std::string base = baseString; \
|
|
||||||
if (base == "XYZ") \
|
|
||||||
return PartBase::XYZ; \
|
|
||||||
if (base == "Average") \
|
|
||||||
return PartBase::Average; \
|
|
||||||
if (base == "YZ") \
|
|
||||||
return PartBase::YZ; \
|
|
||||||
if (base == "XY") \
|
|
||||||
return PartBase::XY; \
|
|
||||||
if (base == "ZX") \
|
|
||||||
return PartBase::ZX; \
|
|
||||||
return PartBase::XYZ; \
|
|
||||||
}
|
|
||||||
const char* PartBaseToString(PartBase base);
|
|
||||||
#define IMPL_PartBaseToString \
|
|
||||||
const char* PartBaseToString(PartBase base) \
|
|
||||||
{ \
|
|
||||||
switch (base) { \
|
|
||||||
case PartBase::XYZ: \
|
|
||||||
return "XYZ"; \
|
|
||||||
case PartBase::Average: \
|
|
||||||
return "Average"; \
|
|
||||||
case PartBase::YZ: \
|
|
||||||
return "YZ"; \
|
|
||||||
case PartBase::XY: \
|
|
||||||
return "XY"; \
|
|
||||||
case PartBase::ZX: \
|
|
||||||
return "ZX"; \
|
|
||||||
default: \
|
|
||||||
return "XYZ"; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
std::string PartBaseToDispName(PartBase base);
|
|
||||||
#define IMPL_PartBaseToDispName \
|
|
||||||
std::string PartBaseToDispName(PartBase base) \
|
|
||||||
{ \
|
|
||||||
switch (base) { \
|
|
||||||
case PartBase::XYZ: \
|
|
||||||
return std::string("Dynamic"); \
|
|
||||||
case PartBase::Average: \
|
|
||||||
return std::string("Average"); \
|
|
||||||
case PartBase::YZ: \
|
|
||||||
return std::string("Side Plane"); \
|
|
||||||
case PartBase::XY: \
|
|
||||||
return std::string("Front Plane"); \
|
|
||||||
case PartBase::ZX: \
|
|
||||||
return std::string("Top Plane"); \
|
|
||||||
default: \
|
|
||||||
return std::string("Dynamic"); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -21,7 +21,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dust3d/base/cut_face.h>
|
#include <dust3d/base/cut_face.h>
|
||||||
#include <dust3d/base/part_base.h>
|
|
||||||
#include <dust3d/base/part_target.h>
|
#include <dust3d/base/part_target.h>
|
||||||
#include <dust3d/base/snapshot_xml.h>
|
#include <dust3d/base/snapshot_xml.h>
|
||||||
#include <dust3d/base/string.h>
|
#include <dust3d/base/string.h>
|
||||||
|
@ -591,7 +590,6 @@ std::unique_ptr<MeshCombiner::Mesh> MeshGenerator::combinePartMesh(const std::st
|
||||||
float cutRotation = 0.0;
|
float cutRotation = 0.0;
|
||||||
float hollowThickness = 0.0;
|
float hollowThickness = 0.0;
|
||||||
auto target = PartTargetFromString(String::valueOrEmpty(part, "target").c_str());
|
auto target = PartTargetFromString(String::valueOrEmpty(part, "target").c_str());
|
||||||
auto base = PartBaseFromString(String::valueOrEmpty(part, "base").c_str());
|
|
||||||
|
|
||||||
std::string searchPartIdString = __mirrorFromPartId.empty() ? partIdString : __mirrorFromPartId;
|
std::string searchPartIdString = __mirrorFromPartId.empty() ? partIdString : __mirrorFromPartId;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue