Divide document elements to separate file
parent
6335742b17
commit
0f77ed243d
|
@ -121,6 +121,11 @@ HEADERS += sources/debug.h
|
|||
SOURCES += sources/debug.cc
|
||||
HEADERS += sources/document.h
|
||||
SOURCES += sources/document.cc
|
||||
SOURCES += sources/document_bone.cc
|
||||
SOURCES += sources/document_component.cc
|
||||
SOURCES += sources/document_edge.cc
|
||||
SOURCES += sources/document_node.cc
|
||||
SOURCES += sources/document_part.cc
|
||||
HEADERS += sources/document_saver.h
|
||||
SOURCES += sources/document_saver.cc
|
||||
HEADERS += sources/document_window.h
|
||||
|
|
|
@ -20,20 +20,6 @@
|
|||
|
||||
unsigned long Document::m_maxSnapshot = 1000;
|
||||
|
||||
Document::Bone::Bone(const dust3d::Uuid& withId)
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
||||
|
||||
void Document::Node::setRadius(float toRadius)
|
||||
{
|
||||
if (toRadius < MeshGenerator::m_minimalRadius)
|
||||
toRadius = MeshGenerator::m_minimalRadius;
|
||||
else if (toRadius > 1)
|
||||
toRadius = 1;
|
||||
radius = toRadius;
|
||||
}
|
||||
|
||||
Document::Document()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -57,84 +57,21 @@ public:
|
|||
|
||||
class Node {
|
||||
public:
|
||||
Node(const dust3d::Uuid& withId = dust3d::Uuid())
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
||||
Node(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||
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;
|
||||
}
|
||||
void setCutRotation(float toRotation);
|
||||
void setCutFace(dust3d::CutFace face);
|
||||
void setCutFaceLinkedId(const dust3d::Uuid& linkedId);
|
||||
void clearCutFaceSettings();
|
||||
float getX(bool rotated = false) const;
|
||||
float getY(bool rotated = false) const;
|
||||
float getZ(bool rotated = false) const;
|
||||
void setX(float x);
|
||||
void setY(float y);
|
||||
void setZ(float z);
|
||||
void addX(float x);
|
||||
void addY(float y);
|
||||
void addZ(float z);
|
||||
dust3d::Uuid id;
|
||||
dust3d::Uuid partId;
|
||||
QString name;
|
||||
|
@ -155,20 +92,12 @@ public:
|
|||
|
||||
class Edge {
|
||||
public:
|
||||
Edge(const dust3d::Uuid& withId = dust3d::Uuid())
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
||||
Edge(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||
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];
|
||||
}
|
||||
dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const;
|
||||
};
|
||||
|
||||
class Part {
|
||||
|
@ -201,201 +130,39 @@ public:
|
|||
bool countershaded;
|
||||
bool smooth;
|
||||
dust3d::Uuid colorImageId;
|
||||
Part(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 isEditVisible() const
|
||||
{
|
||||
return visible && !disabled;
|
||||
}
|
||||
void copyAttributes(const Part& 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;
|
||||
target = other.target;
|
||||
colorSolubility = other.colorSolubility;
|
||||
countershaded = other.countershaded;
|
||||
metalness = other.metalness;
|
||||
roughness = other.roughness;
|
||||
deformUnified = other.deformUnified;
|
||||
smooth = other.smooth;
|
||||
hollowThickness = other.hollowThickness;
|
||||
}
|
||||
Part(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||
bool hasPolyFunction() const;
|
||||
bool hasSmoothFunction() const;
|
||||
bool hasSubdivFunction() const;
|
||||
bool hasRoundEndFunction() const;
|
||||
bool hasMirrorFunction() const;
|
||||
bool hasChamferFunction() const;
|
||||
bool hasRotationFunction() const;
|
||||
bool hasHollowFunction() const;
|
||||
bool hasCutFaceFunction() const;
|
||||
bool hasLayerFunction() const;
|
||||
bool hasTargetFunction() const;
|
||||
bool hasBaseFunction() const;
|
||||
bool hasCombineModeFunction() const;
|
||||
bool hasDeformFunction() const;
|
||||
bool hasColorFunction() const;
|
||||
void setDeformThickness(float toThickness);
|
||||
void setDeformWidth(float toWidth);
|
||||
void setCutRotation(float toRotation);
|
||||
void setCutFace(dust3d::CutFace face);
|
||||
void setCutFaceLinkedId(const dust3d::Uuid& linkedId);
|
||||
bool deformThicknessAdjusted() const;
|
||||
bool deformWidthAdjusted() const;
|
||||
bool deformAdjusted() const;
|
||||
bool colorSolubilityAdjusted() const;
|
||||
bool metalnessAdjusted() const;
|
||||
bool roughnessAdjusted() const;
|
||||
bool cutRotationAdjusted() const;
|
||||
bool hollowThicknessAdjusted() const;
|
||||
bool cutFaceAdjusted() const;
|
||||
bool cutAdjusted() const;
|
||||
bool isEditVisible() const;
|
||||
void copyAttributes(const Part& other);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Part);
|
||||
|
@ -403,18 +170,20 @@ public:
|
|||
|
||||
class Component {
|
||||
public:
|
||||
Component()
|
||||
{
|
||||
}
|
||||
Component(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Component();
|
||||
Component(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString());
|
||||
QString linkData() const;
|
||||
QString linkDataType() const;
|
||||
void addChild(dust3d::Uuid childId);
|
||||
void replaceChildWithOthers(const dust3d::Uuid& childId, const std::vector<dust3d::Uuid>& others);
|
||||
void removeChild(dust3d::Uuid childId);
|
||||
void replaceChild(dust3d::Uuid childId, dust3d::Uuid newId);
|
||||
void moveChildUp(dust3d::Uuid childId);
|
||||
void moveChildDown(dust3d::Uuid childId);
|
||||
void moveChildToTop(dust3d::Uuid childId);
|
||||
void moveChildToBottom(dust3d::Uuid childId);
|
||||
void updatePreviewMesh(std::unique_ptr<ModelMesh> mesh);
|
||||
ModelMesh* takePreviewMesh() const;
|
||||
dust3d::Uuid id;
|
||||
QString name;
|
||||
dust3d::Uuid linkToPartId;
|
||||
|
@ -427,131 +196,6 @@ public:
|
|||
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;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#include "document.h"
|
||||
|
||||
Document::Bone::Bone(const dust3d::Uuid& withId)
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
#include "document.h"
|
||||
|
||||
Document::Component::Component()
|
||||
{
|
||||
}
|
||||
|
||||
Document::Component::Component(const dust3d::Uuid& withId, const QString& linkData, const QString& linkDataType)
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
if (!linkData.isEmpty()) {
|
||||
if ("partId" == linkDataType) {
|
||||
linkToPartId = dust3d::Uuid(linkData.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString Document::Component::linkData() const
|
||||
{
|
||||
return linkToPartId.isNull() ? QString() : QString(linkToPartId.toString().c_str());
|
||||
}
|
||||
|
||||
QString Document::Component::linkDataType() const
|
||||
{
|
||||
return linkToPartId.isNull() ? QString() : QString("partId");
|
||||
}
|
||||
|
||||
void Document::Component::addChild(dust3d::Uuid childId)
|
||||
{
|
||||
if (m_childrenIdSet.find(childId) != m_childrenIdSet.end())
|
||||
return;
|
||||
m_childrenIdSet.insert(childId);
|
||||
childrenIds.push_back(childId);
|
||||
}
|
||||
|
||||
void Document::Component::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 Document::Component::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 Document::Component::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 Document::Component::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 Document::Component::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 Document::Component::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 Document::Component::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 Document::Component::updatePreviewMesh(std::unique_ptr<ModelMesh> mesh)
|
||||
{
|
||||
m_previewMesh = std::move(mesh);
|
||||
isPreviewMeshObsolete = true;
|
||||
}
|
||||
|
||||
ModelMesh* Document::Component::takePreviewMesh() const
|
||||
{
|
||||
if (nullptr == m_previewMesh)
|
||||
return nullptr;
|
||||
return new ModelMesh(*m_previewMesh);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include "document.h"
|
||||
|
||||
Document::Edge::Edge(const dust3d::Uuid& withId)
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
||||
|
||||
dust3d::Uuid Document::Edge::neighborOf(dust3d::Uuid nodeId) const
|
||||
{
|
||||
if (nodeIds.size() != 2)
|
||||
return dust3d::Uuid();
|
||||
return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0];
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
#include "document.h"
|
||||
#include "mesh_generator.h"
|
||||
|
||||
Document::Node::Node(const dust3d::Uuid& withId)
|
||||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
||||
|
||||
void Document::Node::setRadius(float toRadius)
|
||||
{
|
||||
if (toRadius < MeshGenerator::m_minimalRadius)
|
||||
toRadius = MeshGenerator::m_minimalRadius;
|
||||
else if (toRadius > 1)
|
||||
toRadius = 1;
|
||||
radius = toRadius;
|
||||
}
|
||||
|
||||
void Document::Node::setCutRotation(float toRotation)
|
||||
{
|
||||
if (toRotation < -1)
|
||||
toRotation = -1;
|
||||
else if (toRotation > 1)
|
||||
toRotation = 1;
|
||||
cutRotation = toRotation;
|
||||
hasCutFaceSettings = true;
|
||||
}
|
||||
|
||||
void Document::Node::setCutFace(dust3d::CutFace face)
|
||||
{
|
||||
cutFace = face;
|
||||
cutFaceLinkedId = dust3d::Uuid();
|
||||
hasCutFaceSettings = true;
|
||||
}
|
||||
|
||||
void Document::Node::setCutFaceLinkedId(const dust3d::Uuid& linkedId)
|
||||
{
|
||||
if (linkedId.isNull()) {
|
||||
clearCutFaceSettings();
|
||||
return;
|
||||
}
|
||||
cutFace = dust3d::CutFace::UserDefined;
|
||||
cutFaceLinkedId = linkedId;
|
||||
hasCutFaceSettings = true;
|
||||
}
|
||||
|
||||
void Document::Node::clearCutFaceSettings()
|
||||
{
|
||||
cutFace = dust3d::CutFace::Quad;
|
||||
cutFaceLinkedId = dust3d::Uuid();
|
||||
cutRotation = 0;
|
||||
hasCutFaceSettings = false;
|
||||
}
|
||||
|
||||
float Document::Node::getX(bool rotated) const
|
||||
{
|
||||
if (rotated)
|
||||
return m_y;
|
||||
return m_x;
|
||||
}
|
||||
|
||||
float Document::Node::getY(bool rotated) const
|
||||
{
|
||||
if (rotated)
|
||||
return m_x;
|
||||
return m_y;
|
||||
}
|
||||
|
||||
float Document::Node::getZ(bool rotated) const
|
||||
{
|
||||
(void)rotated;
|
||||
return m_z;
|
||||
}
|
||||
|
||||
void Document::Node::setX(float x)
|
||||
{
|
||||
m_x = x;
|
||||
}
|
||||
|
||||
void Document::Node::setY(float y)
|
||||
{
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
void Document::Node::setZ(float z)
|
||||
{
|
||||
m_z = z;
|
||||
}
|
||||
|
||||
void Document::Node::addX(float x)
|
||||
{
|
||||
m_x += x;
|
||||
}
|
||||
|
||||
void Document::Node::addY(float y)
|
||||
{
|
||||
m_y += y;
|
||||
}
|
||||
|
||||
void Document::Node::addZ(float z)
|
||||
{
|
||||
m_z += z;
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
#include "document.h"
|
||||
|
||||
Document::Part::Part(const dust3d::Uuid& withId)
|
||||
: 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 Document::Part::hasPolyFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasSmoothFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasSubdivFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasRoundEndFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasMirrorFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasChamferFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasRotationFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasHollowFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasCutFaceFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasLayerFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasTargetFunction() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Document::Part::hasBaseFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasCombineModeFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasDeformFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
bool Document::Part::hasColorFunction() const
|
||||
{
|
||||
return dust3d::PartTarget::Model == target;
|
||||
}
|
||||
|
||||
void Document::Part::setDeformThickness(float toThickness)
|
||||
{
|
||||
if (toThickness < 0)
|
||||
toThickness = 0;
|
||||
else if (toThickness > 2)
|
||||
toThickness = 2;
|
||||
deformThickness = toThickness;
|
||||
}
|
||||
|
||||
void Document::Part::setDeformWidth(float toWidth)
|
||||
{
|
||||
if (toWidth < 0)
|
||||
toWidth = 0;
|
||||
else if (toWidth > 2)
|
||||
toWidth = 2;
|
||||
deformWidth = toWidth;
|
||||
}
|
||||
|
||||
void Document::Part::setCutRotation(float toRotation)
|
||||
{
|
||||
if (toRotation < -1)
|
||||
toRotation = -1;
|
||||
else if (toRotation > 1)
|
||||
toRotation = 1;
|
||||
cutRotation = toRotation;
|
||||
}
|
||||
|
||||
void Document::Part::setCutFace(dust3d::CutFace face)
|
||||
{
|
||||
cutFace = face;
|
||||
cutFaceLinkedId = dust3d::Uuid();
|
||||
}
|
||||
|
||||
void Document::Part::setCutFaceLinkedId(const dust3d::Uuid& linkedId)
|
||||
{
|
||||
if (linkedId.isNull()) {
|
||||
setCutFace(dust3d::CutFace::Quad);
|
||||
return;
|
||||
}
|
||||
cutFace = dust3d::CutFace::UserDefined;
|
||||
cutFaceLinkedId = linkedId;
|
||||
}
|
||||
|
||||
bool Document::Part::deformThicknessAdjusted() const
|
||||
{
|
||||
return fabs(deformThickness - 1.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::deformWidthAdjusted() const
|
||||
{
|
||||
return fabs(deformWidth - 1.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::deformAdjusted() const
|
||||
{
|
||||
return deformThicknessAdjusted() || deformWidthAdjusted() || deformUnified;
|
||||
}
|
||||
|
||||
bool Document::Part::colorSolubilityAdjusted() const
|
||||
{
|
||||
return fabs(colorSolubility - 0.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::metalnessAdjusted() const
|
||||
{
|
||||
return fabs(metalness - 0.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::roughnessAdjusted() const
|
||||
{
|
||||
return fabs(roughness - 1.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::cutRotationAdjusted() const
|
||||
{
|
||||
return fabs(cutRotation - 0.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::hollowThicknessAdjusted() const
|
||||
{
|
||||
return fabs(hollowThickness - 0.0) >= 0.01;
|
||||
}
|
||||
|
||||
bool Document::Part::cutFaceAdjusted() const
|
||||
{
|
||||
return cutFace != dust3d::CutFace::Quad;
|
||||
}
|
||||
|
||||
bool Document::Part::cutAdjusted() const
|
||||
{
|
||||
return cutRotationAdjusted() || cutFaceAdjusted() || hollowThicknessAdjusted();
|
||||
}
|
||||
|
||||
bool Document::Part::isEditVisible() const
|
||||
{
|
||||
return visible && !disabled;
|
||||
}
|
||||
|
||||
void Document::Part::copyAttributes(const Part& 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;
|
||||
target = other.target;
|
||||
colorSolubility = other.colorSolubility;
|
||||
countershaded = other.countershaded;
|
||||
metalness = other.metalness;
|
||||
roughness = other.roughness;
|
||||
deformUnified = other.deformUnified;
|
||||
smooth = other.smooth;
|
||||
hollowThickness = other.hollowThickness;
|
||||
}
|
|
@ -48,22 +48,93 @@ void SkeletonGenerator::addBone(const Uuid& boneId, const Bone& bone)
|
|||
m_boneMap.emplace(std::make_pair(boneId, bone));
|
||||
}
|
||||
|
||||
void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& node)
|
||||
void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding)
|
||||
{
|
||||
m_nodeBindingMap.emplace(std::make_pair(nodeId, node));
|
||||
m_nodeBindingMap.emplace(std::make_pair(nodeId, nodeBinding));
|
||||
}
|
||||
|
||||
void SkeletonGenerator::buildEdges()
|
||||
{
|
||||
for (const auto& face : m_faces) {
|
||||
for (size_t i = 0; i < face.size(); ++i) {
|
||||
size_t j = (i + 1) % face.size();
|
||||
m_edges[face[i]].insert(face[j]);
|
||||
m_edges[face[j]].insert(face[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Uuid SkeletonGenerator::resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set<size_t>& visited)
|
||||
{
|
||||
visited.insert(vertexIndex);
|
||||
auto findNeighbors = m_edges.find(vertexIndex);
|
||||
if (findNeighbors == m_edges.end())
|
||||
return Uuid();
|
||||
for (const auto& it : findNeighbors->second) {
|
||||
if (!m_vertexSourceNodes[it].isNull())
|
||||
return m_vertexSourceNodes[it];
|
||||
}
|
||||
for (const auto& it : findNeighbors->second) {
|
||||
if (visited.end() != visited.find(it))
|
||||
continue;
|
||||
Uuid foundId = resolveVertexSourceByBreadthFirstSearch(it, visited);
|
||||
if (!foundId.isNull())
|
||||
return foundId;
|
||||
}
|
||||
return Uuid();
|
||||
}
|
||||
|
||||
void SkeletonGenerator::resolveVertexSources()
|
||||
{
|
||||
m_vertexSourceNodes.resize(m_vertices.size());
|
||||
for (size_t i = 0; i < m_vertices.size(); ++i) {
|
||||
auto findNode = m_positionToNodeMap.find(m_vertices[i]);
|
||||
if (findNode == m_positionToNodeMap.end())
|
||||
continue;
|
||||
m_vertexSourceNodes[i] = findNode->second;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) {
|
||||
if (!m_vertexSourceNodes[i].isNull())
|
||||
continue;
|
||||
std::unordered_set<size_t> visited;
|
||||
m_vertexSourceNodes[i] = resolveVertexSourceByBreadthFirstSearch(i, visited);
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonGenerator::buildBoneJoints()
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void SkeletonGenerator::assignBoneJointToVertices()
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void SkeletonGenerator::groupBoneVertices()
|
||||
{
|
||||
/*
|
||||
for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) {
|
||||
const Uuid& sourceNodeId = m_vertexSourceNodes[i];
|
||||
if (sourceNodeId.isNull())
|
||||
continue;
|
||||
auto findBinding = m_nodeBindingMap.find(sourceNodeId);
|
||||
if (findBinding == m_nodeBindingMap.end())
|
||||
continue;
|
||||
// TODO:
|
||||
}
|
||||
*/
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void SkeletonGenerator::bind()
|
||||
{
|
||||
// TODO: Build vertex edge map
|
||||
|
||||
// TODO: Bind unbound nodes
|
||||
|
||||
// TODO: Build bone skeleton
|
||||
|
||||
// TODO: Assign bone to vertex
|
||||
|
||||
// TODO: finalize
|
||||
buildEdges();
|
||||
resolveVertexSources();
|
||||
groupBoneVertices();
|
||||
buildBoneJoints();
|
||||
assignBoneJointToVertices();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <dust3d/base/uuid.h>
|
||||
#include <dust3d/base/vector3.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace dust3d {
|
||||
|
@ -40,7 +42,6 @@ public:
|
|||
|
||||
struct Bone {
|
||||
std::string name;
|
||||
std::string parent;
|
||||
};
|
||||
|
||||
SkeletonGenerator();
|
||||
|
@ -48,7 +49,7 @@ public:
|
|||
void setFaces(const std::vector<std::vector<size_t>>& faces);
|
||||
void setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap);
|
||||
void addBone(const Uuid& boneId, const Bone& bone);
|
||||
void addNodeBinding(const Uuid& nodeId, const NodeBinding& node);
|
||||
void addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding);
|
||||
void bind();
|
||||
|
||||
private:
|
||||
|
@ -57,6 +58,15 @@ private:
|
|||
std::map<PositionKey, Uuid> m_positionToNodeMap;
|
||||
std::map<Uuid, NodeBinding> m_nodeBindingMap;
|
||||
std::map<Uuid, Bone> m_boneMap;
|
||||
std::map<size_t, std::set<size_t>> m_edges;
|
||||
std::vector<Uuid> m_vertexSourceNodes;
|
||||
|
||||
void buildEdges();
|
||||
void resolveVertexSources();
|
||||
Uuid resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set<size_t>& visited);
|
||||
void groupBoneVertices();
|
||||
void buildBoneJoints();
|
||||
void assignBoneJointToVertices();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue