Add new pose setting: yTranslationScale
Normally, when pose been generated, foot is always been pulling to the ground by a y-translation. This setting could be used to scale the y-translation. It's usefull for birds fly kind of motion.master
parent
3e29528ee0
commit
516df9a1b7
|
@ -20,62 +20,31 @@ void AnimalPoser::resolveTransform()
|
||||||
resolveChainRotation(chain.second);
|
resolveChainRotation(chain.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
//int firstSpineBoneIndex = findBoneIndex(Rigger::firstSpineBoneName);
|
|
||||||
//if (-1 == firstSpineBoneIndex) {
|
|
||||||
// qDebug() << "Find first spine bone failed:" << Rigger::firstSpineBoneName;
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//const auto &firstSpineBone = bones()[firstSpineBoneIndex];
|
|
||||||
|
|
||||||
float mostBottomYBeforeTransform = std::numeric_limits<float>::max();
|
float mostBottomYBeforeTransform = std::numeric_limits<float>::max();
|
||||||
for (const auto &bone: bones()) {
|
for (const auto &bone: bones()) {
|
||||||
if (bone.tailPosition.y() < mostBottomYBeforeTransform)
|
if (bone.tailPosition.y() < mostBottomYBeforeTransform)
|
||||||
mostBottomYBeforeTransform = bone.tailPosition.y();
|
mostBottomYBeforeTransform = bone.tailPosition.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
//float legHeightBeforeTransform = std::abs(mostBottomYBeforeTransform - firstSpineBone.headPosition.y());
|
|
||||||
auto transformedJointNodeTree = m_jointNodeTree;
|
auto transformedJointNodeTree = m_jointNodeTree;
|
||||||
transformedJointNodeTree.recalculateTransformMatrices();
|
transformedJointNodeTree.recalculateTransformMatrices();
|
||||||
float mostBottomYAfterTransform = std::numeric_limits<float>::max();
|
float mostBottomYAfterTransform = std::numeric_limits<float>::max();
|
||||||
//QVector3D firstSpineBonePositionAfterTransform = firstSpineBone.headPosition;
|
|
||||||
for (int i = 0; i < (int)transformedJointNodeTree.nodes().size(); ++i) {
|
for (int i = 0; i < (int)transformedJointNodeTree.nodes().size(); ++i) {
|
||||||
const auto &bone = bones()[i];
|
const auto &bone = bones()[i];
|
||||||
const auto &jointNode = transformedJointNodeTree.nodes()[i];
|
const auto &jointNode = transformedJointNodeTree.nodes()[i];
|
||||||
QVector3D newPosition = jointNode.transformMatrix * bone.tailPosition;
|
QVector3D newPosition = jointNode.transformMatrix * bone.tailPosition;
|
||||||
//if (0 == i) {
|
|
||||||
// Root bone's tail position is the first spine bone's head position
|
|
||||||
// firstSpineBonePositionAfterTransform = newPosition;
|
|
||||||
//}
|
|
||||||
if (newPosition.y() < mostBottomYAfterTransform)
|
if (newPosition.y() < mostBottomYAfterTransform)
|
||||||
mostBottomYAfterTransform = newPosition.y();
|
mostBottomYAfterTransform = newPosition.y();
|
||||||
}
|
}
|
||||||
//float legHeightAfterTransform = std::abs(mostBottomYAfterTransform - firstSpineBonePositionAfterTransform.y());
|
|
||||||
//float translateY = legHeightAfterTransform - legHeightBeforeTransform;
|
|
||||||
float translateY = mostBottomYBeforeTransform - mostBottomYAfterTransform;
|
float translateY = mostBottomYBeforeTransform - mostBottomYAfterTransform;
|
||||||
|
|
||||||
//qDebug() << "Leg height changed, translateY:" << translateY << "legHeightBeforeTransform:" << legHeightBeforeTransform << "legHeightAfterTransform:" << legHeightAfterTransform << "firstSpineBonePositionAfterTransform:" << firstSpineBonePositionAfterTransform << "firstSpineBone.headPosition:" << firstSpineBone.headPosition;
|
|
||||||
|
|
||||||
/*
|
|
||||||
const auto &findRootParameters = parameters().find(Rigger::rootBoneName);
|
|
||||||
if (findRootParameters != parameters().end()) {
|
|
||||||
auto findHeightAboveGroundLevel = findRootParameters->second.find("heightAboveGroundLevel");
|
|
||||||
if (findHeightAboveGroundLevel != findRootParameters->second.end()) {
|
|
||||||
float heightAboveGroundLevel = findHeightAboveGroundLevel->second.toFloat();
|
|
||||||
float myHeightAboveGroundLevel = heightAboveGroundLevel * legHeightAfterTransform;
|
|
||||||
translateY += myHeightAboveGroundLevel;
|
|
||||||
//qDebug() << "heightAboveGroundLevel:" << heightAboveGroundLevel << "myHeightAboveGroundLevel:" << myHeightAboveGroundLevel << "legHeightBeforeTransform:" << legHeightBeforeTransform << "applied translateY:" << translateY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!qFuzzyIsNull(translateY)) {
|
if (!qFuzzyIsNull(translateY)) {
|
||||||
int rootBoneIndex = findBoneIndex(Rigger::rootBoneName);
|
int rootBoneIndex = findBoneIndex(Rigger::rootBoneName);
|
||||||
if (-1 == rootBoneIndex) {
|
if (-1 == rootBoneIndex) {
|
||||||
qDebug() << "Find root bone failed:" << Rigger::rootBoneName;
|
qDebug() << "Find root bone failed:" << Rigger::rootBoneName;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_jointNodeTree.addTranslation(rootBoneIndex, QVector3D(0, translateY, 0));
|
m_jointNodeTree.addTranslation(rootBoneIndex, QVector3D(0, translateY * m_yTranslationScale, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +155,7 @@ void AnimalPoser::resolveChainRotation(const std::vector<QString> &limbBoneNames
|
||||||
|
|
||||||
QVector3D targetMiddleBoneStartPosition;
|
QVector3D targetMiddleBoneStartPosition;
|
||||||
{
|
{
|
||||||
//qDebug() << beginBoneName << "Angle:" << angleBetweenDistanceAndMiddleBones;
|
qDebug() << beginBoneName << "Angle:" << angleBetweenDistanceAndMiddleBones << "Distance:" << targetDistanceBetweenBeginAndEndBones;
|
||||||
auto rotation = QQuaternion::fromAxisAndAngle(matchRotatePlaneNormal, angleBetweenDistanceAndMiddleBones);
|
auto rotation = QQuaternion::fromAxisAndAngle(matchRotatePlaneNormal, angleBetweenDistanceAndMiddleBones);
|
||||||
targetMiddleBoneStartPosition = targetEndBoneStartPosition + rotation.rotatedVector(-matchDirectionBetweenBeginAndEndPones).normalized() * targetMiddleBoneLength;
|
targetMiddleBoneStartPosition = targetEndBoneStartPosition + rotation.rotatedVector(-matchDirectionBetweenBeginAndEndPones).normalized() * targetMiddleBoneLength;
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,7 +356,7 @@ QUuid Document::createNode(QUuid nodeId, float x, float y, float z, float radius
|
||||||
return node.id;
|
return node.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::addPose(QUuid poseId, QString name, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames, QUuid turnaroundImageId)
|
void Document::addPose(QUuid poseId, QString name, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames, QUuid turnaroundImageId, float yTranslationScale)
|
||||||
{
|
{
|
||||||
QUuid newPoseId = poseId;
|
QUuid newPoseId = poseId;
|
||||||
auto &pose = poseMap[newPoseId];
|
auto &pose = poseMap[newPoseId];
|
||||||
|
@ -365,6 +365,7 @@ void Document::addPose(QUuid poseId, QString name, std::vector<std::pair<std::ma
|
||||||
pose.name = name;
|
pose.name = name;
|
||||||
pose.frames = frames;
|
pose.frames = frames;
|
||||||
pose.turnaroundImageId = turnaroundImageId;
|
pose.turnaroundImageId = turnaroundImageId;
|
||||||
|
pose.yTranslationScale = yTranslationScale;
|
||||||
pose.dirty = true;
|
pose.dirty = true;
|
||||||
|
|
||||||
poseIdList.push_back(newPoseId);
|
poseIdList.push_back(newPoseId);
|
||||||
|
@ -481,6 +482,19 @@ void Document::setPoseTurnaroundImageId(QUuid poseId, QUuid imageId)
|
||||||
emit optionsChanged();
|
emit optionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::setPoseYtranslationScale(QUuid poseId, float scale)
|
||||||
|
{
|
||||||
|
auto findPoseResult = poseMap.find(poseId);
|
||||||
|
if (findPoseResult == poseMap.end()) {
|
||||||
|
qDebug() << "Find pose failed:" << poseId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
findPoseResult->second.yTranslationScale = scale;
|
||||||
|
findPoseResult->second.dirty = true;
|
||||||
|
emit poseYtranslationScaleChanged(poseId);
|
||||||
|
emit optionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void Document::renamePose(QUuid poseId, QString name)
|
void Document::renamePose(QUuid poseId, QString name)
|
||||||
{
|
{
|
||||||
auto findPoseResult = poseMap.find(poseId);
|
auto findPoseResult = poseMap.find(poseId);
|
||||||
|
@ -1061,6 +1075,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
|
||||||
pose["name"] = poseIt.second.name;
|
pose["name"] = poseIt.second.name;
|
||||||
if (!poseIt.second.turnaroundImageId.isNull())
|
if (!poseIt.second.turnaroundImageId.isNull())
|
||||||
pose["canvasImageId"] = poseIt.second.turnaroundImageId.toString();
|
pose["canvasImageId"] = poseIt.second.turnaroundImageId.toString();
|
||||||
|
if (poseIt.second.yTranslationScaleAdjusted())
|
||||||
|
pose["yTranslationScale"] = QString::number(poseIt.second.yTranslationScale);
|
||||||
snapshot->poses.push_back(std::make_pair(pose, poseIt.second.frames));
|
snapshot->poses.push_back(std::make_pair(pose, poseIt.second.frames));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1341,6 +1357,9 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
|
||||||
auto findCanvasImageId = poseAttributes.find("canvasImageId");
|
auto findCanvasImageId = poseAttributes.find("canvasImageId");
|
||||||
if (findCanvasImageId != poseAttributes.end())
|
if (findCanvasImageId != poseAttributes.end())
|
||||||
newPose.turnaroundImageId = QUuid(findCanvasImageId->second);
|
newPose.turnaroundImageId = QUuid(findCanvasImageId->second);
|
||||||
|
auto findYtranslationScale = poseAttributes.find("yTranslationScale");
|
||||||
|
if (findYtranslationScale != poseAttributes.end())
|
||||||
|
newPose.yTranslationScale = findYtranslationScale->second.toFloat();
|
||||||
newPose.frames = poseIt.second;
|
newPose.frames = poseIt.second;
|
||||||
oldNewIdMap[QUuid(valueOfKeyInMapOrEmpty(poseAttributes, "id"))] = newPoseId;
|
oldNewIdMap[QUuid(valueOfKeyInMapOrEmpty(poseAttributes, "id"))] = newPoseId;
|
||||||
poseIdList.push_back(newPoseId);
|
poseIdList.push_back(newPoseId);
|
||||||
|
@ -2875,7 +2894,7 @@ void Document::generateMotions()
|
||||||
m_motionsGenerator = new MotionsGenerator(rigType, rigBones, rigWeights, currentRiggedOutcome());
|
m_motionsGenerator = new MotionsGenerator(rigType, rigBones, rigWeights, currentRiggedOutcome());
|
||||||
bool hasDirtyMotion = false;
|
bool hasDirtyMotion = false;
|
||||||
for (const auto &pose: poseMap) {
|
for (const auto &pose: poseMap) {
|
||||||
m_motionsGenerator->addPoseToLibrary(pose.first, pose.second.frames);
|
m_motionsGenerator->addPoseToLibrary(pose.first, pose.second.frames, pose.second.yTranslationScale);
|
||||||
}
|
}
|
||||||
for (auto &motion: motionMap) {
|
for (auto &motion: motionMap) {
|
||||||
if (motion.second.dirty) {
|
if (motion.second.dirty) {
|
||||||
|
|
|
@ -198,6 +198,7 @@ public:
|
||||||
QString name;
|
QString name;
|
||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
QUuid turnaroundImageId;
|
QUuid turnaroundImageId;
|
||||||
|
float yTranslationScale = 1.0;
|
||||||
std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames; // pair<attributes, parameters>
|
std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames; // pair<attributes, parameters>
|
||||||
void updatePreviewMesh(MeshLoader *previewMesh)
|
void updatePreviewMesh(MeshLoader *previewMesh)
|
||||||
{
|
{
|
||||||
|
@ -210,6 +211,10 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return new MeshLoader(*m_previewMesh);
|
return new MeshLoader(*m_previewMesh);
|
||||||
}
|
}
|
||||||
|
bool yTranslationScaleAdjusted() const
|
||||||
|
{
|
||||||
|
return fabs(yTranslationScale - 1.0) >= 0.01;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(Pose);
|
Q_DISABLE_COPY(Pose);
|
||||||
MeshLoader *m_previewMesh = nullptr;
|
MeshLoader *m_previewMesh = nullptr;
|
||||||
|
@ -434,6 +439,7 @@ signals:
|
||||||
void poseNameChanged(QUuid poseId);
|
void poseNameChanged(QUuid poseId);
|
||||||
void poseFramesChanged(QUuid poseId);
|
void poseFramesChanged(QUuid poseId);
|
||||||
void poseTurnaroundImageIdChanged(QUuid poseId);
|
void poseTurnaroundImageIdChanged(QUuid poseId);
|
||||||
|
void poseYtranslationScaleChanged(QUuid poseId);
|
||||||
void posePreviewChanged(QUuid poseId);
|
void posePreviewChanged(QUuid poseId);
|
||||||
void motionAdded(QUuid motionId);
|
void motionAdded(QUuid motionId);
|
||||||
void motionRemoved(QUuid motionId);
|
void motionRemoved(QUuid motionId);
|
||||||
|
@ -612,10 +618,12 @@ public slots:
|
||||||
void enableWeld(bool enabled);
|
void enableWeld(bool enabled);
|
||||||
void setRigType(RigType toRigType);
|
void setRigType(RigType toRigType);
|
||||||
void addPose(QUuid poseId, QString name, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames,
|
void addPose(QUuid poseId, QString name, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames,
|
||||||
QUuid turnaroundImageId);
|
QUuid turnaroundImageId,
|
||||||
|
float yTranslationScale);
|
||||||
void removePose(QUuid poseId);
|
void removePose(QUuid poseId);
|
||||||
void setPoseFrames(QUuid poseId, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames);
|
void setPoseFrames(QUuid poseId, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames);
|
||||||
void setPoseTurnaroundImageId(QUuid poseId, QUuid imageId);
|
void setPoseTurnaroundImageId(QUuid poseId, QUuid imageId);
|
||||||
|
void setPoseYtranslationScale(QUuid poseId, float scale);
|
||||||
void renamePose(QUuid poseId, QString name);
|
void renamePose(QUuid poseId, QString name);
|
||||||
void addMotion(QUuid motionId, QString name, std::vector<MotionClip> clips);
|
void addMotion(QUuid motionId, QString name, std::vector<MotionClip> clips);
|
||||||
void removeMotion(QUuid motionId);
|
void removeMotion(QUuid motionId);
|
||||||
|
|
|
@ -251,7 +251,7 @@ void MotionEditWidget::generatePreviews()
|
||||||
m_previewsGenerator = new MotionsGenerator(m_document->rigType, rigBones, rigWeights,
|
m_previewsGenerator = new MotionsGenerator(m_document->rigType, rigBones, rigWeights,
|
||||||
m_document->currentRiggedOutcome());
|
m_document->currentRiggedOutcome());
|
||||||
for (const auto &pose: m_document->poseMap)
|
for (const auto &pose: m_document->poseMap)
|
||||||
m_previewsGenerator->addPoseToLibrary(pose.first, pose.second.frames);
|
m_previewsGenerator->addPoseToLibrary(pose.first, pose.second.frames, pose.second.yTranslationScale);
|
||||||
for (const auto &motion: m_document->motionMap)
|
for (const auto &motion: m_document->motionMap)
|
||||||
m_previewsGenerator->addMotionToLibrary(motion.first, motion.second.clips);
|
m_previewsGenerator->addMotionToLibrary(motion.first, motion.second.clips);
|
||||||
m_previewsGenerator->addMotionToLibrary(QUuid(), m_timelineWidget->clips());
|
m_previewsGenerator->addMotionToLibrary(QUuid(), m_timelineWidget->clips());
|
||||||
|
|
|
@ -27,9 +27,10 @@ MotionsGenerator::~MotionsGenerator()
|
||||||
delete m_poser;
|
delete m_poser;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionsGenerator::addPoseToLibrary(const QUuid &poseId, const std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> &frames)
|
void MotionsGenerator::addPoseToLibrary(const QUuid &poseId, const std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> &frames, float yTranslationScale)
|
||||||
{
|
{
|
||||||
m_poses[poseId] = frames;
|
m_poses[poseId] = frames;
|
||||||
|
m_posesYtranslationScales[poseId] = yTranslationScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionsGenerator::addMotionToLibrary(const QUuid &motionId, const std::vector<MotionClip> &clips)
|
void MotionsGenerator::addMotionToLibrary(const QUuid &motionId, const std::vector<MotionClip> &clips)
|
||||||
|
@ -231,6 +232,7 @@ const JointNodeTree &MotionsGenerator::poseJointNodeTree(const QUuid &poseId, in
|
||||||
return findResult->second;
|
return findResult->second;
|
||||||
|
|
||||||
const auto &frames = m_poses[poseId];
|
const auto &frames = m_poses[poseId];
|
||||||
|
const auto &posesYtranslationScale = m_posesYtranslationScales[poseId];
|
||||||
|
|
||||||
m_poser->reset();
|
m_poser->reset();
|
||||||
if (frame < (int)frames.size()) {
|
if (frame < (int)frames.size()) {
|
||||||
|
@ -240,6 +242,7 @@ const JointNodeTree &MotionsGenerator::poseJointNodeTree(const QUuid &poseId, in
|
||||||
std::map<QString, std::map<QString, QString>> translatedParameters;
|
std::map<QString, std::map<QString, QString>> translatedParameters;
|
||||||
postDocument.toParameters(translatedParameters);
|
postDocument.toParameters(translatedParameters);
|
||||||
m_poser->parameters() = translatedParameters;
|
m_poser->parameters() = translatedParameters;
|
||||||
|
m_poser->setYtranslationScale(posesYtranslationScale);
|
||||||
}
|
}
|
||||||
m_poser->commit();
|
m_poser->commit();
|
||||||
auto insertResult = m_poseJointNodeTreeMap.insert({{poseId, frame}, m_poser->resultJointNodeTree()});
|
auto insertResult = m_poseJointNodeTreeMap.insert({{poseId, frame}, m_poser->resultJointNodeTree()});
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
const std::map<int, RiggerVertexWeights> *rigWeights,
|
const std::map<int, RiggerVertexWeights> *rigWeights,
|
||||||
const Outcome &outcome);
|
const Outcome &outcome);
|
||||||
~MotionsGenerator();
|
~MotionsGenerator();
|
||||||
void addPoseToLibrary(const QUuid &poseId, const std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> &frames);
|
void addPoseToLibrary(const QUuid &poseId, const std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> &frames, float yTranslationScale);
|
||||||
void addMotionToLibrary(const QUuid &motionId, const std::vector<MotionClip> &clips);
|
void addMotionToLibrary(const QUuid &motionId, const std::vector<MotionClip> &clips);
|
||||||
void addRequirement(const QUuid &motionId);
|
void addRequirement(const QUuid &motionId);
|
||||||
std::vector<std::pair<float, MeshLoader *>> takeResultPreviewMeshs(const QUuid &motionId);
|
std::vector<std::pair<float, MeshLoader *>> takeResultPreviewMeshs(const QUuid &motionId);
|
||||||
|
@ -50,6 +50,7 @@ private:
|
||||||
std::map<int, RiggerVertexWeights> m_rigWeights;
|
std::map<int, RiggerVertexWeights> m_rigWeights;
|
||||||
Outcome m_outcome;
|
Outcome m_outcome;
|
||||||
std::map<QUuid, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>>> m_poses;
|
std::map<QUuid, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>>> m_poses;
|
||||||
|
std::map<QUuid, float> m_posesYtranslationScales;
|
||||||
std::map<QUuid, std::vector<MotionClip>> m_motions;
|
std::map<QUuid, std::vector<MotionClip>> m_motions;
|
||||||
std::set<QUuid> m_requiredMotionIds;
|
std::set<QUuid> m_requiredMotionIds;
|
||||||
std::set<QUuid> m_generatedMotionIds;
|
std::set<QUuid> m_generatedMotionIds;
|
||||||
|
|
|
@ -194,6 +194,11 @@ PoseEditWidget::PoseEditWidget(const Document *document, QWidget *parent) :
|
||||||
connect(saveButton, &QPushButton::clicked, this, &PoseEditWidget::save);
|
connect(saveButton, &QPushButton::clicked, this, &PoseEditWidget::save);
|
||||||
saveButton->setDefault(true);
|
saveButton->setDefault(true);
|
||||||
|
|
||||||
|
QPushButton *setPoseSettingButton = new QPushButton(Theme::awesome()->icon(fa::gear), tr(""));
|
||||||
|
connect(setPoseSettingButton, &QPushButton::clicked, this, [=]() {
|
||||||
|
showPoseSettingPopup(mapFromGlobal(QCursor::pos()));
|
||||||
|
});
|
||||||
|
|
||||||
QPushButton *changeReferenceSheet = new QPushButton(tr("Change Reference Sheet..."));
|
QPushButton *changeReferenceSheet = new QPushButton(tr("Change Reference Sheet..."));
|
||||||
connect(changeReferenceSheet, &QPushButton::clicked, this, &PoseEditWidget::changeTurnaround);
|
connect(changeReferenceSheet, &QPushButton::clicked, this, &PoseEditWidget::changeTurnaround);
|
||||||
connect(m_poseDocument, &PoseDocument::turnaroundChanged,
|
connect(m_poseDocument, &PoseDocument::turnaroundChanged,
|
||||||
|
@ -261,6 +266,7 @@ PoseEditWidget::PoseEditWidget(const Document *document, QWidget *parent) :
|
||||||
baseInfoLayout->addWidget(new QLabel(tr("Duration")));
|
baseInfoLayout->addWidget(new QLabel(tr("Duration")));
|
||||||
baseInfoLayout->addWidget(m_durationEdit);
|
baseInfoLayout->addWidget(m_durationEdit);
|
||||||
baseInfoLayout->addStretch();
|
baseInfoLayout->addStretch();
|
||||||
|
baseInfoLayout->addWidget(setPoseSettingButton);
|
||||||
baseInfoLayout->addWidget(changeReferenceSheet);
|
baseInfoLayout->addWidget(changeReferenceSheet);
|
||||||
baseInfoLayout->addWidget(saveButton);
|
baseInfoLayout->addWidget(saveButton);
|
||||||
|
|
||||||
|
@ -280,6 +286,7 @@ PoseEditWidget::PoseEditWidget(const Document *document, QWidget *parent) :
|
||||||
connect(this, &PoseEditWidget::renamePose, m_document, &Document::renamePose);
|
connect(this, &PoseEditWidget::renamePose, m_document, &Document::renamePose);
|
||||||
connect(this, &PoseEditWidget::setPoseFrames, m_document, &Document::setPoseFrames);
|
connect(this, &PoseEditWidget::setPoseFrames, m_document, &Document::setPoseFrames);
|
||||||
connect(this, &PoseEditWidget::setPoseTurnaroundImageId, m_document, &Document::setPoseTurnaroundImageId);
|
connect(this, &PoseEditWidget::setPoseTurnaroundImageId, m_document, &Document::setPoseTurnaroundImageId);
|
||||||
|
connect(this, &PoseEditWidget::setPoseYtranslationScale, m_document, &Document::setPoseYtranslationScale);
|
||||||
|
|
||||||
updatePoseDocument();
|
updatePoseDocument();
|
||||||
updateTitle();
|
updateTitle();
|
||||||
|
@ -308,6 +315,43 @@ void PoseEditWidget::updateSideButtonState(QPushButton *button, bool visible)
|
||||||
button->setStyleSheet("QPushButton {color: #252525}");
|
button->setStyleSheet("QPushButton {color: #252525}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PoseEditWidget::showPoseSettingPopup(const QPoint &pos)
|
||||||
|
{
|
||||||
|
QMenu popupMenu;
|
||||||
|
|
||||||
|
QWidget *popup = new QWidget;
|
||||||
|
|
||||||
|
FloatNumberWidget *yTranslationScaleWidget = new FloatNumberWidget;
|
||||||
|
yTranslationScaleWidget->setItemName(tr("Height Adjustment Scale"));
|
||||||
|
yTranslationScaleWidget->setRange(0, 1);
|
||||||
|
yTranslationScaleWidget->setValue(m_yTranslationScale);
|
||||||
|
|
||||||
|
connect(yTranslationScaleWidget, &FloatNumberWidget::valueChanged, [&](float value) {
|
||||||
|
m_yTranslationScale = value;
|
||||||
|
setUnsaveState();
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *yTranslationScaleEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeToolButton(yTranslationScaleEraser);
|
||||||
|
|
||||||
|
connect(yTranslationScaleEraser, &QPushButton::clicked, [=]() {
|
||||||
|
yTranslationScaleWidget->setValue(1.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
QHBoxLayout *yTranslationScaleLayout = new QHBoxLayout;
|
||||||
|
yTranslationScaleLayout->addWidget(yTranslationScaleEraser);
|
||||||
|
yTranslationScaleLayout->addWidget(yTranslationScaleWidget);
|
||||||
|
|
||||||
|
popup->setLayout(yTranslationScaleLayout);
|
||||||
|
|
||||||
|
QWidgetAction *action = new QWidgetAction(this);
|
||||||
|
action->setDefaultWidget(popup);
|
||||||
|
|
||||||
|
popupMenu.addAction(action);
|
||||||
|
|
||||||
|
popupMenu.exec(mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
void PoseEditWidget::showFramesSettingPopup(const QPoint &pos)
|
void PoseEditWidget::showFramesSettingPopup(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QMenu popupMenu;
|
QMenu popupMenu;
|
||||||
|
@ -315,13 +359,13 @@ void PoseEditWidget::showFramesSettingPopup(const QPoint &pos)
|
||||||
QWidget *popup = new QWidget;
|
QWidget *popup = new QWidget;
|
||||||
|
|
||||||
QSpinBox *framesEdit = new QSpinBox();
|
QSpinBox *framesEdit = new QSpinBox();
|
||||||
framesEdit->setMaximum(60);
|
framesEdit->setMaximum(m_frames.size());
|
||||||
framesEdit->setMinimum(1);
|
framesEdit->setMinimum(1);
|
||||||
framesEdit->setSingleStep(1);
|
framesEdit->setSingleStep(1);
|
||||||
framesEdit->setValue(m_frames.size());
|
framesEdit->setValue(m_frames.size());
|
||||||
|
|
||||||
connect(framesEdit, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [=](int value) {
|
connect(framesEdit, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [=](int value) {
|
||||||
setFrameCount(value);
|
setCurrentFrame(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
QFormLayout *formLayout = new QFormLayout;
|
QFormLayout *formLayout = new QFormLayout;
|
||||||
|
@ -361,21 +405,6 @@ void PoseEditWidget::syncFrameFromCurrent()
|
||||||
updateFramesDurations();
|
updateFramesDurations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoseEditWidget::setFrameCount(int count)
|
|
||||||
{
|
|
||||||
if (count == (int)m_frames.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
setUnsaveState();
|
|
||||||
count = std::max(count, 1);
|
|
||||||
m_frames.resize(count);
|
|
||||||
updateFramesDurations();
|
|
||||||
updateFramesSettingButton();
|
|
||||||
if (m_currentFrame >= count) {
|
|
||||||
setCurrentFrame(count - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PoseEditWidget::updateFramesDurations()
|
void PoseEditWidget::updateFramesDurations()
|
||||||
{
|
{
|
||||||
if (m_frames.empty())
|
if (m_frames.empty())
|
||||||
|
@ -604,6 +633,11 @@ void PoseEditWidget::setEditPoseTurnaroundImageId(QUuid imageId)
|
||||||
m_poseDocument->updateTurnaround(*image);
|
m_poseDocument->updateTurnaround(*image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PoseEditWidget::setEditPoseYtranslationScale(float yTranslationScale)
|
||||||
|
{
|
||||||
|
m_yTranslationScale = yTranslationScale;
|
||||||
|
}
|
||||||
|
|
||||||
void PoseEditWidget::clearUnsaveState()
|
void PoseEditWidget::clearUnsaveState()
|
||||||
{
|
{
|
||||||
m_unsaved = false;
|
m_unsaved = false;
|
||||||
|
@ -620,11 +654,12 @@ void PoseEditWidget::save()
|
||||||
{
|
{
|
||||||
if (m_poseId.isNull()) {
|
if (m_poseId.isNull()) {
|
||||||
m_poseId = QUuid::createUuid();
|
m_poseId = QUuid::createUuid();
|
||||||
emit addPose(m_poseId, m_nameEdit->text(), m_frames, m_imageId);
|
emit addPose(m_poseId, m_nameEdit->text(), m_frames, m_imageId, m_yTranslationScale);
|
||||||
} else if (m_unsaved) {
|
} else if (m_unsaved) {
|
||||||
emit renamePose(m_poseId, m_nameEdit->text());
|
emit renamePose(m_poseId, m_nameEdit->text());
|
||||||
emit setPoseFrames(m_poseId, m_frames);
|
emit setPoseFrames(m_poseId, m_frames);
|
||||||
emit setPoseTurnaroundImageId(m_poseId, m_imageId);
|
emit setPoseTurnaroundImageId(m_poseId, m_imageId);
|
||||||
|
emit setPoseYtranslationScale(m_poseId, m_yTranslationScale);
|
||||||
}
|
}
|
||||||
clearUnsaveState();
|
clearUnsaveState();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,11 @@ class PoseEditWidget : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
signals:
|
signals:
|
||||||
void addPose(QUuid poseId, QString name, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames, QUuid turnaroundImageId);
|
void addPose(QUuid poseId, QString name, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames, QUuid turnaroundImageId, float yTranslationScale);
|
||||||
void removePose(QUuid poseId);
|
void removePose(QUuid poseId);
|
||||||
void setPoseFrames(QUuid poseId, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames);
|
void setPoseFrames(QUuid poseId, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames);
|
||||||
void setPoseTurnaroundImageId(QUuid poseId, QUuid imageId);
|
void setPoseTurnaroundImageId(QUuid poseId, QUuid imageId);
|
||||||
|
void setPoseYtranslationScale(QUuid poseId, float scale);
|
||||||
void renamePose(QUuid poseId, QString name);
|
void renamePose(QUuid poseId, QString name);
|
||||||
void parametersAdjusted();
|
void parametersAdjusted();
|
||||||
public:
|
public:
|
||||||
|
@ -38,10 +39,10 @@ public slots:
|
||||||
void setEditPoseName(QString name);
|
void setEditPoseName(QString name);
|
||||||
void setEditPoseFrames(std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames);
|
void setEditPoseFrames(std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>> frames);
|
||||||
void setEditPoseTurnaroundImageId(QUuid imageId);
|
void setEditPoseTurnaroundImageId(QUuid imageId);
|
||||||
|
void setEditPoseYtranslationScale(float yTranslationScale);
|
||||||
void setCurrentFrame(int frame);
|
void setCurrentFrame(int frame);
|
||||||
void insertFrameAfterCurrentFrame();
|
void insertFrameAfterCurrentFrame();
|
||||||
void removeCurrentFrame();
|
void removeCurrentFrame();
|
||||||
void setFrameCount(int count);
|
|
||||||
void setDuration(float duration);
|
void setDuration(float duration);
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
void save();
|
void save();
|
||||||
|
@ -51,6 +52,7 @@ public slots:
|
||||||
private slots:
|
private slots:
|
||||||
void updateFramesSettingButton();
|
void updateFramesSettingButton();
|
||||||
void showFramesSettingPopup(const QPoint &pos);
|
void showFramesSettingPopup(const QPoint &pos);
|
||||||
|
void showPoseSettingPopup(const QPoint &pos);
|
||||||
void updateFramesDurations();
|
void updateFramesDurations();
|
||||||
protected:
|
protected:
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
@ -71,6 +73,7 @@ private:
|
||||||
QUuid m_poseId;
|
QUuid m_poseId;
|
||||||
bool m_unsaved = false;
|
bool m_unsaved = false;
|
||||||
QUuid m_imageId;
|
QUuid m_imageId;
|
||||||
|
float m_yTranslationScale = 1.0;
|
||||||
QLineEdit *m_nameEdit = nullptr;
|
QLineEdit *m_nameEdit = nullptr;
|
||||||
QDoubleSpinBox *m_durationEdit = nullptr;
|
QDoubleSpinBox *m_durationEdit = nullptr;
|
||||||
PoseDocument *m_poseDocument = nullptr;
|
PoseDocument *m_poseDocument = nullptr;
|
||||||
|
|
|
@ -78,6 +78,7 @@ void PoseManageWidget::showPoseDialog(QUuid poseId)
|
||||||
poseEditWidget->setEditPoseName(pose->name);
|
poseEditWidget->setEditPoseName(pose->name);
|
||||||
poseEditWidget->setEditPoseFrames(pose->frames);
|
poseEditWidget->setEditPoseFrames(pose->frames);
|
||||||
poseEditWidget->setEditPoseTurnaroundImageId(pose->turnaroundImageId);
|
poseEditWidget->setEditPoseTurnaroundImageId(pose->turnaroundImageId);
|
||||||
|
poseEditWidget->setEditPoseYtranslationScale(pose->yTranslationScale);
|
||||||
poseEditWidget->clearUnsaveState();
|
poseEditWidget->clearUnsaveState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@ Poser::~Poser()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Poser::setYtranslationScale(float scale)
|
||||||
|
{
|
||||||
|
m_yTranslationScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
int Poser::findBoneIndex(const QString &name)
|
int Poser::findBoneIndex(const QString &name)
|
||||||
{
|
{
|
||||||
auto findResult = m_boneNameToIndexMap.find(name);
|
auto findResult = m_boneNameToIndexMap.find(name);
|
||||||
|
|
|
@ -17,6 +17,7 @@ public:
|
||||||
const std::vector<JointNode> &resultNodes() const;
|
const std::vector<JointNode> &resultNodes() const;
|
||||||
const JointNodeTree &resultJointNodeTree() const;
|
const JointNodeTree &resultJointNodeTree() const;
|
||||||
std::map<QString, std::map<QString, QString>> ¶meters();
|
std::map<QString, std::map<QString, QString>> ¶meters();
|
||||||
|
void setYtranslationScale(float scale);
|
||||||
virtual void commit();
|
virtual void commit();
|
||||||
void reset();
|
void reset();
|
||||||
static void fetchChains(const std::vector<QString> &boneNames, std::map<QString, std::vector<QString>> &chains);
|
static void fetchChains(const std::vector<QString> &boneNames, std::map<QString, std::vector<QString>> &chains);
|
||||||
|
@ -25,6 +26,7 @@ protected:
|
||||||
std::map<QString, int> m_boneNameToIndexMap;
|
std::map<QString, int> m_boneNameToIndexMap;
|
||||||
JointNodeTree m_jointNodeTree;
|
JointNodeTree m_jointNodeTree;
|
||||||
std::map<QString, std::map<QString, QString>> m_parameters;
|
std::map<QString, std::map<QString, QString>> m_parameters;
|
||||||
|
float m_yTranslationScale = 1.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue