master
huxingyi 2020-12-19 15:07:44 +09:30
parent aae9d3fca5
commit 1bd1d58069
8 changed files with 1494 additions and 3238 deletions

View File

@ -394,9 +394,6 @@ HEADERS += src/proceduralanimation.h
SOURCES += src/boundingboxmesh.cpp
HEADERS += src/boundingboxmesh.h
SOURCES += src/regionfiller.cpp
HEADERS += src/regionfiller.h
SOURCES += src/meshwrapper.cpp
HEADERS += src/meshwrapper.h

File diff suppressed because it is too large Load Diff

View File

@ -40,153 +40,6 @@ public:
Snapshot snapshot;
};
class Component
{
public:
Component()
{
}
Component(const QUuid &withId, const QString &linkData=QString(), const QString &linkDataType=QString())
{
id = withId.isNull() ? QUuid::createUuid() : withId;
if (!linkData.isEmpty()) {
if ("partId" == linkDataType) {
linkToPartId = QUuid(linkData);
}
}
}
QUuid id;
QString name;
QUuid linkToPartId;
QUuid parentId;
bool expanded = true;
CombineMode combineMode = Preferences::instance().componentCombineMode();
bool dirty = true;
float smoothAll = 0.0;
float smoothSeam = 0.0;
std::vector<QUuid> childrenIds;
QString linkData() const
{
return linkToPartId.isNull() ? QString() : linkToPartId.toString();
}
QString linkDataType() const
{
return linkToPartId.isNull() ? QString() : QString("partId");
}
void addChild(QUuid childId)
{
if (m_childrenIdSet.find(childId) != m_childrenIdSet.end())
return;
m_childrenIdSet.insert(childId);
childrenIds.push_back(childId);
}
void removeChild(QUuid 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(QUuid childId, QUuid 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(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == 0)
return;
std::swap(childrenIds[index - 1], childrenIds[index]);
}
void moveChildDown(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == (int)childrenIds.size() - 1)
return;
std::swap(childrenIds[index], childrenIds[index + 1]);
}
void moveChildToTop(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
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(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
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 setSmoothAll(float toSmoothAll)
{
if (toSmoothAll < 0)
toSmoothAll = 0;
else if (toSmoothAll > 1)
toSmoothAll = 1;
smoothAll = toSmoothAll;
}
void setSmoothSeam(float toSmoothSeam)
{
if (toSmoothSeam < 0)
toSmoothSeam = 0;
else if (toSmoothSeam > 1)
toSmoothSeam = 1;
smoothSeam = toSmoothSeam;
}
bool smoothAllAdjusted() const
{
return fabs(smoothAll - 0.0) >= 0.01;
}
bool smoothSeamAdjusted() const
{
return fabs(smoothSeam - 0.0) >= 0.01;
}
bool smoothAdjusted() const
{
return smoothAllAdjusted() || smoothSeamAdjusted();
}
private:
std::set<QUuid> m_childrenIdSet;
};
class Motion
{
public:
@ -261,25 +114,9 @@ class Document : public SkeletonDocument
{
Q_OBJECT
signals:
void partAdded(QUuid partId);
void nodeAdded(QUuid nodeId);
void edgeAdded(QUuid edgeId);
void partRemoved(QUuid partId);
void componentNameChanged(QUuid componentId);
void componentChildrenChanged(QUuid componentId);
void componentRemoved(QUuid componentId);
void componentAdded(QUuid componentId);
void componentExpandStateChanged(QUuid componentId);
void componentLayerChanged(QUuid componentId);
void nodeRemoved(QUuid nodeId);
void edgeRemoved(QUuid edgeId);
void nodeRadiusChanged(QUuid nodeId);
void nodeBoneMarkChanged(QUuid nodeId);
void nodeColorStateChanged(QUuid nodeId);
void nodeCutRotationChanged(QUuid nodeId);
void nodeCutFaceChanged(QUuid nodeId);
void nodeOriginChanged(QUuid nodeId);
void edgeReversed(QUuid edgeId);
void partPreviewChanged(QUuid partId);
void resultMeshChanged();
void resultPartPreviewsChanged();
@ -287,7 +124,6 @@ signals:
void turnaroundChanged();
void editModeChanged();
void paintModeChanged();
void skeletonChanged();
//void resultSkeletonChanged();
void resultTextureChanged();
void resultColorTextureChanged();
@ -295,10 +131,7 @@ signals:
void postProcessedResultChanged();
void resultRigChanged();
void rigChanged();
void partLockStateChanged(QUuid partId);
void partVisibleStateChanged(QUuid partId);
void partSubdivStateChanged(QUuid partId);
void partDisableStateChanged(QUuid partId);
void partXmirrorStateChanged(QUuid partId);
//void partZmirrorStateChanged(QUuid partId);
void partBaseChanged(QUuid partId);
@ -320,11 +153,9 @@ signals:
void partHollowThicknessChanged(QUuid partId);
void partCountershadeStateChanged(QUuid partId);
void partSmoothStateChanged(QUuid partId);
void partGridStateChanged(QUuid partId);
void componentCombineModeChanged(QUuid componentId);
void cleanup();
void cleanupScript();
void originChanged();
void xlockStateChanged();
void ylockStateChanged();
void zlockStateChanged();
@ -338,7 +169,6 @@ signals:
void uncheckAll();
void checkNode(QUuid nodeId);
void checkEdge(QUuid edgeId);
void optionsChanged();
void rigTypeChanged();
void motionsChanged();
void motionAdded(QUuid motionId);
@ -368,30 +198,28 @@ signals:
void mousePickRadiusChanged();
void objectLockStateChanged();
public: // need initialize
QImage *textureImage;
QByteArray *textureImageByteArray;
QImage *textureNormalImage;
QByteArray *textureNormalImageByteArray;
QImage *textureMetalnessImage;
QByteArray *textureMetalnessImageByteArray;
QImage *textureRoughnessImage;
QByteArray *textureRoughnessImageByteArray;
QImage *textureAmbientOcclusionImage;
QByteArray *textureAmbientOcclusionImageByteArray;
RigType rigType;
bool weldEnabled;
QColor brushColor;
bool objectLocked;
QImage *textureImage = nullptr;
QByteArray *textureImageByteArray = nullptr;
QImage *textureNormalImage = nullptr;
QByteArray *textureNormalImageByteArray = nullptr;
QImage *textureMetalnessImage = nullptr;
QByteArray *textureMetalnessImageByteArray = nullptr;
QImage *textureRoughnessImage = nullptr;
QByteArray *textureRoughnessImageByteArray = nullptr;
QImage *textureAmbientOcclusionImage = nullptr;
QByteArray *textureAmbientOcclusionImageByteArray = nullptr;
RigType rigType = RigType::None;
bool weldEnabled = true;
QColor brushColor = Qt::white;
bool objectLocked = false;
float brushMetalness = Model::m_defaultMetalness;
float brushRoughness = Model::m_defaultRoughness;
public:
Document();
~Document();
std::map<QUuid, Component> componentMap;
std::map<QUuid, Material> materialMap;
std::vector<QUuid> materialIdList;
std::map<QUuid, Motion> motionMap;
Component rootComponent;
QImage preview;
bool undoable() const override;
bool redoable() const override;
@ -412,9 +240,6 @@ public:
Import
};
void addFromSnapshot(const Snapshot &snapshot, enum SnapshotSource source=SnapshotSource::Paste);
const Component *findComponent(QUuid componentId) const;
const Component *findComponentParent(QUuid componentId) const;
QUuid findComponentParentId(QUuid componentId) const;
const Material *findMaterial(QUuid materialId) const;
const Motion *findMotion(QUuid motionId) const;
Model *takeResultMesh();
@ -436,8 +261,6 @@ public:
const Object &currentPostProcessedObject() const;
bool isExportReady() const;
bool isPostProcessResultObsolete() const;
void collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const;
void collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds) const;
const std::vector<std::pair<QtMsgType, QString>> &resultRigMessages() const;
const Object &currentRiggedObject() const;
bool currentRigSucceed() const;
@ -455,29 +278,15 @@ public slots:
void undo() override;
void redo() override;
void paste() override;
void removeNode(QUuid nodeId);
void removeEdge(QUuid edgeId);
void removePart(QUuid partId);
void addNodeWithId(QUuid nodeId, float x, float y, float z, float radius, QUuid fromNodeId);
void addNode(float x, float y, float z, float radius, QUuid fromNodeId);
void scaleNodeByAddRadius(QUuid nodeId, float amount);
void moveNodeBy(QUuid nodeId, float x, float y, float z);
void setNodeOrigin(QUuid nodeId, float x, float y, float z);
void setNodeRadius(QUuid nodeId, float radius);
void setNodeBoneMark(QUuid nodeId, BoneMark mark);
void setNodeCutRotation(QUuid nodeId, float cutRotation);
void setNodeCutFace(QUuid nodeId, CutFace cutFace);
void setNodeCutFaceLinkedId(QUuid nodeId, QUuid linkedId);
void clearNodeCutFaceSettings(QUuid nodeId);
void switchNodeXZ(QUuid nodeId);
void moveOriginBy(float x, float y, float z);
void addEdge(QUuid fromNodeId, QUuid toNodeId);
void setEditMode(SkeletonDocumentEditMode mode);
void setMeshLockState(bool locked);
void setPaintMode(PaintMode mode);
void setMousePickRadius(float radius);
void createSinglePartFromEdges(const std::vector<QVector3D> &nodes,
const std::vector<std::pair<size_t, size_t>> &edges);
void uiReady();
void generateMesh();
void regenerateMesh();
@ -495,10 +304,7 @@ public slots:
void pickMouseTarget(const QVector3D &nearPosition, const QVector3D &farPosition);
void paint();
void paintReady();
void setPartLockState(QUuid partId, bool locked);
void setPartVisibleState(QUuid partId, bool visible);
void setPartSubdivState(QUuid partId, bool subdived);
void setPartDisableState(QUuid partId, bool disabled);
void setPartXmirrorState(QUuid partId, bool mirrored);
//void setPartZmirrorState(QUuid partId, bool mirrored);
void setPartBase(QUuid partId, PartBase base);
@ -522,31 +328,6 @@ public slots:
void setPartCountershaded(QUuid partId, bool countershaded);
void setPartSmoothState(QUuid partId, bool smooth);
void setComponentCombineMode(QUuid componentId, CombineMode combineMode);
void moveComponentUp(QUuid componentId);
void moveComponentDown(QUuid componentId);
void moveComponentToTop(QUuid componentId);
void moveComponentToBottom(QUuid componentId);
void renameComponent(QUuid componentId, QString name);
void removeComponent(QUuid componentId);
void addComponent(QUuid parentId);
void moveComponent(QUuid componentId, QUuid toParentId);
void setCurrentCanvasComponentId(QUuid componentId);
void createNewComponentAndMoveThisIn(QUuid componentId);
void createNewChildComponent(QUuid parentComponentId);
void setComponentExpandState(QUuid componentId, bool expanded);
void hideOtherComponents(QUuid componentId);
void lockOtherComponents(QUuid componentId);
void hideAllComponents();
void showAllComponents();
void showOrHideAllComponents();
void collapseAllComponents();
void expandAllComponents();
void lockAllComponents();
void unlockAllComponents();
void hideDescendantComponents(QUuid componentId);
void showDescendantComponents(QUuid componentId);
void lockDescendantComponents(QUuid componentId);
void unlockDescendantComponents(QUuid componentId);
void saveSnapshot();
void batchChangeBegin();
void batchChangeEnd();
@ -555,15 +336,10 @@ public slots:
void clearHistories();
void silentReset();
void silentResetScript();
void breakEdge(QUuid edgeId);
void reduceNode(QUuid nodeId);
void reverseEdge(QUuid edgeId);
void setXlockState(bool locked);
void setYlockState(bool locked);
void setZlockState(bool locked);
void setRadiusLockState(bool locked);
void enableAllPositionRelatedLocks();
void disableAllPositionRelatedLocks();
void toggleSmoothNormal();
void enableWeld(bool enabled);
void setRigType(RigType toRigType);
@ -590,62 +366,48 @@ public slots:
void setMousePickMaskNodeIds(const std::set<QUuid> &nodeIds);
void updateObject(Object *object);
private:
void splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId);
void joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId, std::set<QUuid> *visitMap, QUuid noUseEdgeId=QUuid());
void splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId);
bool isPartReadonly(QUuid partId) const;
QUuid createNode(QUuid nodeId, float x, float y, float z, float radius, QUuid fromNodeId);
void settleOrigin();
void checkExportReadyState();
void removePartDontCareComponent(QUuid partId);
void addPartToComponent(QUuid partId, QUuid componentId);
bool isDescendantComponent(QUuid componentId, QUuid suspiciousId);
void removeComponentRecursively(QUuid componentId);
void resetDirtyFlags();
void markAllDirty();
void removeRigResults();
void updateLinkedPart(QUuid oldPartId, QUuid newPartId);
bool updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables);
private: // need initialize
bool m_isResultMeshObsolete;
MeshGenerator *m_meshGenerator;
Model *m_resultMesh;
Model *m_paintedMesh;
std::map<QUuid, std::map<QString, QVector2D>> *m_resultMeshNodesCutFaces;
bool m_isMeshGenerationSucceed;
int m_batchChangeRefCount;
Object *m_currentObject;
bool m_isTextureObsolete;
TextureGenerator *m_textureGenerator;
bool m_isPostProcessResultObsolete;
MeshResultPostProcessor *m_postProcessor;
Object *m_postProcessedObject;
Model *m_resultTextureMesh;
unsigned long long m_textureImageUpdateVersion;
QUuid m_currentCanvasComponentId;
bool m_allPositionRelatedLocksEnabled;
bool m_smoothNormal;
RigGenerator *m_rigGenerator;
Model *m_resultRigWeightMesh;
std::vector<RigBone> *m_resultRigBones;
std::map<int, RigVertexWeights> *m_resultRigWeights;
bool m_isRigObsolete;
Object *m_riggedObject;
bool m_currentRigSucceed;
MaterialPreviewsGenerator *m_materialPreviewsGenerator;
MotionsGenerator *m_motionsGenerator;
quint64 m_meshGenerationId;
quint64 m_nextMeshGenerationId;
private:
bool m_isResultMeshObsolete = false;
MeshGenerator *m_meshGenerator = nullptr;
Model *m_resultMesh = nullptr;
Model *m_paintedMesh = nullptr;
std::map<QUuid, std::map<QString, QVector2D>> *m_resultMeshNodesCutFaces = nullptr;
bool m_isMeshGenerationSucceed = true;
int m_batchChangeRefCount = 0;
Object *m_currentObject = nullptr;
bool m_isTextureObsolete = false;
TextureGenerator *m_textureGenerator = nullptr;
bool m_isPostProcessResultObsolete = false;
MeshResultPostProcessor *m_postProcessor = nullptr;
Object *m_postProcessedObject = new Object;
Model *m_resultTextureMesh = nullptr;
unsigned long long m_textureImageUpdateVersion = 0;
bool m_smoothNormal = !Preferences::instance().flatShading();
RigGenerator *m_rigGenerator = nullptr;
Model *m_resultRigWeightMesh = nullptr;
std::vector<RigBone> *m_resultRigBones = nullptr;
std::map<int, RigVertexWeights> *m_resultRigWeights = nullptr;
bool m_isRigObsolete = false;
Object *m_riggedObject = new Object;
bool m_currentRigSucceed = false;
MaterialPreviewsGenerator *m_materialPreviewsGenerator = nullptr;
MotionsGenerator *m_motionsGenerator = nullptr;
quint64 m_meshGenerationId = 0;
quint64 m_nextMeshGenerationId = 0;
std::map<QString, std::map<QString, QString>> m_cachedVariables;
std::map<QString, std::map<QString, QString>> m_mergedVariables;
ScriptRunner *m_scriptRunner;
bool m_isScriptResultObsolete;
TexturePainter *m_texturePainter;
bool m_isMouseTargetResultObsolete;
PaintMode m_paintMode;
float m_mousePickRadius;
GeneratedCacheContext *m_generatedCacheContext;
TexturePainterContext *m_texturePainterContext;
ScriptRunner *m_scriptRunner = nullptr;
bool m_isScriptResultObsolete = false;
TexturePainter *m_texturePainter = nullptr;
bool m_isMouseTargetResultObsolete = false;
PaintMode m_paintMode = PaintMode::None;
float m_mousePickRadius = 0.02f;
GeneratedCacheContext *m_generatedCacheContext = nullptr;
TexturePainterContext *m_texturePainterContext = nullptr;
private:
static unsigned long m_maxSnapshot;
std::deque<HistoryItem> m_undoItems;

View File

@ -133,9 +133,9 @@ void PartTreeWidget::updateComponentAppearance(QUuid componentId)
void PartTreeWidget::updateComponentSelectState(QUuid componentId, bool selected)
{
const Component *component = m_document->findComponent(componentId);
const SkeletonComponent *component = m_document->findComponent(componentId);
if (nullptr == component) {
qDebug() << "Component not found:" << componentId;
qDebug() << "SkeletonComponent not found:" << componentId;
return;
}
if (!component->linkToPartId.isNull()) {
@ -196,7 +196,7 @@ void PartTreeWidget::handleSingleClick(const QPoint &pos)
auto componentId = QUuid(item->data(0, Qt::UserRole).toString());
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
if (!m_shiftStartComponentId.isNull()) {
const Component *parent = m_document->findComponentParent(m_shiftStartComponentId);
const SkeletonComponent *parent = m_document->findComponentParent(m_shiftStartComponentId);
if (parent) {
if (!parent->childrenIds.empty()) {
bool startAdd = false;
@ -288,7 +288,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
//delete m_delayedMousePressTimer;
//m_delayedMousePressTimer = nullptr;
const Component *component = nullptr;
const SkeletonComponent *component = nullptr;
const SkeletonPart *part = nullptr;
PartWidget *partWidget = nullptr;
@ -305,7 +305,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
QUuid componentId = *componentIds.begin();
component = m_document->findComponent(componentId);
if (nullptr == component) {
qDebug() << "Component not found:" << componentId;
qDebug() << "SkeletonComponent not found:" << componentId;
return;
}
if (component && !component->linkToPartId.isNull()) {
@ -394,7 +394,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
if (nullptr == partBaseSelectBox) {
std::set<PartBase> partBases;
for (const auto &componentId: componentIds) {
const Component *oneComponent = m_document->findComponent(componentId);
const SkeletonComponent *oneComponent = m_document->findComponent(componentId);
if (nullptr == oneComponent || oneComponent->linkToPartId.isNull())
continue;
const SkeletonPart *onePart = m_document->findPart(oneComponent->linkToPartId);
@ -419,7 +419,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
if (index < startIndex)
return;
for (const auto &componentId: componentIds) {
const Component *oneComponent = m_document->findComponent(componentId);
const SkeletonComponent *oneComponent = m_document->findComponent(componentId);
if (nullptr == oneComponent || oneComponent->linkToPartId.isNull())
continue;
emit setPartBase(oneComponent->linkToPartId, (PartBase)(index - startIndex));
@ -432,7 +432,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
if (nullptr == combineModeSelectBox) {
std::set<CombineMode> combineModes;
for (const auto &componentId: componentIds) {
const Component *oneComponent = m_document->findComponent(componentId);
const SkeletonComponent *oneComponent = m_document->findComponent(componentId);
if (nullptr == oneComponent)
continue;
combineModes.insert(oneComponent->combineMode);
@ -732,7 +732,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
});
addChildGroupsFunc = [this, &groupsActions, &addChildGroupsFunc, &moveToMenu, &componentIds](QUuid currentId, int tabs) -> void {
const Component *current = m_document->findComponent(currentId);
const SkeletonComponent *current = m_document->findComponent(currentId);
if (nullptr == current)
return;
if (!current->id.isNull() && current->linkDataType().isEmpty()) {
@ -799,7 +799,7 @@ void PartTreeWidget::componentNameChanged(QUuid componentId)
return;
}
const Component *component = m_document->findComponent(componentId);
const SkeletonComponent *component = m_document->findComponent(componentId);
if (nullptr == component) {
qDebug() << "Find component failed:" << componentId;
return;
@ -816,7 +816,7 @@ void PartTreeWidget::componentExpandStateChanged(QUuid componentId)
return;
}
const Component *component = m_document->findComponent(componentId);
const SkeletonComponent *component = m_document->findComponent(componentId);
if (nullptr == component) {
qDebug() << "Find component failed:" << componentId;
return;
@ -837,12 +837,12 @@ void PartTreeWidget::componentTargetChanged(QUuid componentId)
void PartTreeWidget::addComponentChildrenToItem(QUuid componentId, QTreeWidgetItem *parentItem)
{
const Component *parentComponent = m_document->findComponent(componentId);
const SkeletonComponent *parentComponent = m_document->findComponent(componentId);
if (nullptr == parentComponent)
return;
for (const auto &childId: parentComponent->childrenIds) {
const Component *component = m_document->findComponent(childId);
const SkeletonComponent *component = m_document->findComponent(childId);
if (nullptr == component)
continue;
if (!component->linkToPartId.isNull()) {
@ -885,7 +885,7 @@ void PartTreeWidget::deleteItemChildren(QTreeWidgetItem *item)
while (!children.isEmpty()) {
auto first = children.takeFirst();
auto componentId = QUuid(first->data(0, Qt::UserRole).toString());
const Component *component = m_document->findComponent(componentId);
const SkeletonComponent *component = m_document->findComponent(componentId);
if (nullptr != component) {
m_componentItemMap.erase(componentId);
if (!component->linkToPartId.isNull()) {
@ -983,7 +983,7 @@ void PartTreeWidget::groupChanged(QTreeWidgetItem *item, int column)
auto componentId = QUuid(item->data(0, Qt::UserRole).toString());
const Component *component = m_document->findComponent(componentId);
const SkeletonComponent *component = m_document->findComponent(componentId);
if (nullptr == component) {
qDebug() << "Find component failed:" << componentId;
return;

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
#ifndef DUST3D_REGION_FILLER_H
#define DUST3D_REGION_FILLER_H
#include <QVector3D>
#include <vector>
#include <set>
class RegionFiller
{
public:
struct Node
{
QVector3D position;
float radius = 0.0;
size_t source = 0;
};
RegionFiller(const std::vector<Node> *vertices,
const std::vector<std::vector<size_t>> *polylines);
~RegionFiller();
bool fill();
void fillWithoutPartition();
const std::vector<Node> &getOldAndNewVertices();
const std::vector<std::vector<size_t>> &getNewFaces();
private:
const std::vector<Node> *m_sourceVertices = nullptr;
std::vector<std::vector<size_t>> *m_sourcePolylines = nullptr;
int m_sideNum = 0;
int m_sumOfSegments = 0;
std::vector<int> m_sideSegmentNums;
std::vector<Node> m_oldAndNewVertices;
std::vector<std::vector<size_t>> m_newFaces;
std::vector<std::vector<std::vector<size_t>>> m_newRegions;
std::set<size_t> m_centerSources;
float averageRadius(size_t *maxNodeIndex=nullptr);
void createPointsBetween(size_t fromIndex,
size_t toIndex,
size_t segments,
std::vector<size_t> *newPointIndices);
std::vector<size_t> createPointsBetween(size_t fromIndex,
size_t toIndex,
size_t segments);
void collectEdgePoints(size_t polyline, int startPos, int stopPos,
std::vector<size_t> *pointIndices);
std::vector<size_t> collectEdgePoints(size_t polyline, int startPos, int stopPos);
std::vector<size_t> reversed(const std::vector<size_t> &pointIndices);
std::vector<size_t> createPointsToMapBetween(size_t fromIndex,
size_t toIndex,
size_t segments,
std::map<std::pair<size_t, size_t>, std::vector<size_t>> *map);
bool resolveOddSidedEvenSumOfSegments(int siUpperBound);
bool resolveOddSidedOddSumOfSegments(int siUpperBound);
bool resolveEvenSidedEvenSumOfSegmentsAndBothL2L2AreEven();
bool resolveEvenSidedEvenSumOfSegmentsAndBothL2L2AreOdd();
bool resolveEvenSideEvenSumOfSegmentsAndL1IsEvenL2IsOdd();
bool resolveEvenSideEvenSumOfSegmentsAndL1IsOddL2IsEven();
bool resolveQuadrilateralRegion();
bool resolveQuadrilateralRegionWithIntegerSolution(int m, int n, int p, int q, bool pqSwapped);
bool resolveQuadrilateralRegionMismatchSimilarCase(int m, int n, int p, int q, bool pqSwapped);
bool resolveQuadrilateralRegionWithNonIntegerSolution(int m, int n, int p, int q, bool pqSwapped);
bool resolveQuadrilateralRegionDirectCase();
void convertRegionsToFaces();
void prepare();
bool createCoonsPatch(const std::vector<std::vector<size_t>> &region);
bool convertRegionsToPatches();
bool createCoonsPatchFrom(const std::vector<size_t> &c0,
const std::vector<size_t> &c1,
const std::vector<size_t> &d0,
const std::vector<size_t> &d1,
bool fillLastTriangle=false);
bool createCoonsPatchThreeSidedRegion(const std::vector<std::vector<size_t>> &region);
void convertPolylinesToFaces();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
#include <cmath>
#include <QImage>
#include <QByteArray>
#include <QDebug>
#include "bonemark.h"
#include "theme.h"
#include "model.h"
@ -183,7 +184,6 @@ public:
QUuid deformMapImageId;
float hollowThickness;
bool countershaded;
bool gridded;
QUuid fillMeshLinkedId;
bool isPreviewMeshObsolete;
QPixmap previewPixmap;
@ -213,7 +213,6 @@ public:
deformMapScale(1.0),
hollowThickness(0.0),
countershaded(false),
gridded(false),
isPreviewMeshObsolete(false),
smooth(true)
{
@ -441,9 +440,147 @@ enum class SkeletonProfile
Side
};
class SkeletonComponent
{
public:
SkeletonComponent()
{
}
SkeletonComponent(const QUuid &withId, const QString &linkData=QString(), const QString &linkDataType=QString())
{
id = withId.isNull() ? QUuid::createUuid() : withId;
if (!linkData.isEmpty()) {
if ("partId" == linkDataType) {
linkToPartId = QUuid(linkData);
}
}
}
QUuid id;
QString name;
QUuid linkToPartId;
QUuid parentId;
bool expanded = true;
CombineMode combineMode = Preferences::instance().componentCombineMode();
bool dirty = true;
std::vector<QUuid> childrenIds;
QString linkData() const
{
return linkToPartId.isNull() ? QString() : linkToPartId.toString();
}
QString linkDataType() const
{
return linkToPartId.isNull() ? QString() : QString("partId");
}
void addChild(QUuid childId)
{
if (m_childrenIdSet.find(childId) != m_childrenIdSet.end())
return;
m_childrenIdSet.insert(childId);
childrenIds.push_back(childId);
}
void removeChild(QUuid 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(QUuid childId, QUuid 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(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == 0)
return;
std::swap(childrenIds[index - 1], childrenIds[index]);
}
void moveChildDown(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
return;
}
auto index = std::distance(childrenIds.begin(), it);
if (index == (int)childrenIds.size() - 1)
return;
std::swap(childrenIds[index], childrenIds[index + 1]);
}
void moveChildToTop(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
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(QUuid childId)
{
auto it = std::find(childrenIds.begin(), childrenIds.end(), childId);
if (it == childrenIds.end()) {
qDebug() << "Child not found in list:" << childId;
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]);
}
private:
std::set<QUuid> m_childrenIdSet;
};
class SkeletonDocument : public QObject
{
Q_OBJECT
signals:
void partAdded(QUuid partId);
void nodeAdded(QUuid nodeId);
void edgeAdded(QUuid edgeId);
void partRemoved(QUuid partId);
void partLockStateChanged(QUuid partId);
void partVisibleStateChanged(QUuid partId);
void partDisableStateChanged(QUuid partId);
void componentNameChanged(QUuid componentId);
void componentChildrenChanged(QUuid componentId);
void componentRemoved(QUuid componentId);
void componentAdded(QUuid componentId);
void componentExpandStateChanged(QUuid componentId);
void nodeRemoved(QUuid nodeId);
void edgeRemoved(QUuid edgeId);
void nodeRadiusChanged(QUuid nodeId);
void nodeOriginChanged(QUuid nodeId);
void edgeReversed(QUuid edgeId);
void originChanged();
void skeletonChanged();
void optionsChanged();
public:
SkeletonDocumentEditMode editMode = SkeletonDocumentEditMode::Select;
bool xlocked = false;
@ -455,6 +592,8 @@ public:
std::map<QUuid, SkeletonPart> partMap;
std::map<QUuid, SkeletonNode> nodeMap;
std::map<QUuid, SkeletonEdge> edgeMap;
std::map<QUuid, SkeletonComponent> componentMap;
SkeletonComponent rootComponent;
const SkeletonNode *findNode(QUuid nodeId) const;
const SkeletonEdge *findEdge(QUuid edgeId) const;
@ -462,6 +601,13 @@ public:
const SkeletonEdge *findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const;
void findAllNeighbors(QUuid nodeId, std::set<QUuid> &neighbors) const;
bool isNodeConnectable(QUuid nodeId) const;
const SkeletonComponent *findComponent(QUuid componentId) const;
const SkeletonComponent *findComponentParent(QUuid componentId) const;
QUuid findComponentParentId(QUuid componentId) const;
void collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const;
void collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds) const;
void resetDirtyFlags();
void markAllDirty();
virtual bool undoable() const = 0;
virtual bool redoable() const = 0;
@ -528,10 +674,70 @@ public slots:
virtual void redo() = 0;
virtual void paste() = 0;
void removeNode(QUuid nodeId);
void removeEdge(QUuid edgeId);
void removePart(QUuid partId);
void addNodeWithId(QUuid nodeId, float x, float y, float z, float radius, QUuid fromNodeId);
void addNode(float x, float y, float z, float radius, QUuid fromNodeId);
void scaleNodeByAddRadius(QUuid nodeId, float amount);
void moveNodeBy(QUuid nodeId, float x, float y, float z);
void setNodeOrigin(QUuid nodeId, float x, float y, float z);
void setNodeRadius(QUuid nodeId, float radius);
void switchNodeXZ(QUuid nodeId);
void moveOriginBy(float x, float y, float z);
void addEdge(QUuid fromNodeId, QUuid toNodeId);
void moveComponentUp(QUuid componentId);
void moveComponentDown(QUuid componentId);
void moveComponentToTop(QUuid componentId);
void moveComponentToBottom(QUuid componentId);
void renameComponent(QUuid componentId, QString name);
void removeComponent(QUuid componentId);
void addComponent(QUuid parentId);
void moveComponent(QUuid componentId, QUuid toParentId);
void setCurrentCanvasComponentId(QUuid componentId);
void createNewComponentAndMoveThisIn(QUuid componentId);
void createNewChildComponent(QUuid parentComponentId);
void setComponentExpandState(QUuid componentId, bool expanded);
void hideOtherComponents(QUuid componentId);
void lockOtherComponents(QUuid componentId);
void hideAllComponents();
void showAllComponents();
void showOrHideAllComponents();
void collapseAllComponents();
void expandAllComponents();
void lockAllComponents();
void unlockAllComponents();
void hideDescendantComponents(QUuid componentId);
void showDescendantComponents(QUuid componentId);
void lockDescendantComponents(QUuid componentId);
void unlockDescendantComponents(QUuid componentId);
void setPartLockState(QUuid partId, bool locked);
void setPartVisibleState(QUuid partId, bool visible);
void setPartDisableState(QUuid partId, bool disabled);
void enableAllPositionRelatedLocks();
void disableAllPositionRelatedLocks();
bool isPartReadonly(QUuid partId) const;
void breakEdge(QUuid edgeId);
void reduceNode(QUuid nodeId);
void reverseEdge(QUuid edgeId);
private:
float m_originX = 0;
float m_originY = 0;
float m_originZ = 0;
QUuid m_currentCanvasComponentId;
bool m_allPositionRelatedLocksEnabled = true;
void splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId);
void joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId, std::set<QUuid> *visitMap, QUuid noUseEdgeId=QUuid());
void splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId);
void removePartDontCareComponent(QUuid partId);
void addPartToComponent(QUuid partId, QUuid componentId);
bool isDescendantComponent(QUuid componentId, QUuid suspiciousId);
void removeComponentRecursively(QUuid componentId);
void updateLinkedPart(QUuid oldPartId, QUuid newPartId);
QUuid createNode(QUuid nodeId, float x, float y, float z, float radius, QUuid fromNodeId);
};
#endif