Add translation parameter for pose editor
parent
0d45d65b98
commit
e7249db089
|
@ -38,6 +38,19 @@ void GenericPoser::commit()
|
||||||
m_jointNodeTree.updateRotation(boneIndex, rotation);
|
m_jointNodeTree.updateRotation(boneIndex, rotation);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
auto findXResult = item.second.find("x");
|
||||||
|
auto findYResult = item.second.find("y");
|
||||||
|
auto findZResult = item.second.find("z");
|
||||||
|
if (findXResult != item.second.end() ||
|
||||||
|
findYResult != item.second.end() ||
|
||||||
|
findZResult != item.second.end()) {
|
||||||
|
float x = valueOfKeyInMapOrEmpty(item.second, "x").toFloat();
|
||||||
|
float y = valueOfKeyInMapOrEmpty(item.second, "y").toFloat();
|
||||||
|
float z = valueOfKeyInMapOrEmpty(item.second, "z").toFloat();
|
||||||
|
QVector3D translation = {x, y, z};
|
||||||
|
m_jointNodeTree.addTranslation(boneIndex, translation);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Poser::commit();
|
Poser::commit();
|
||||||
|
|
|
@ -304,6 +304,9 @@ bool GenericRigger::rig()
|
||||||
bodyBone.index = m_resultBones.size() - 1;
|
bodyBone.index = m_resultBones.size() - 1;
|
||||||
bodyBone.name = "Body";
|
bodyBone.name = "Body";
|
||||||
bodyBone.headPosition = QVector3D(0, 0, 0);
|
bodyBone.headPosition = QVector3D(0, 0, 0);
|
||||||
|
bodyBone.hasButton = true;
|
||||||
|
bodyBone.button = {spineNodes.size(), 0};
|
||||||
|
bodyBone.buttonParameterType = RiggerButtonParameterType::Translation;
|
||||||
boneIndexMap[bodyBone.name] = bodyBone.index;
|
boneIndexMap[bodyBone.name] = bodyBone.index;
|
||||||
|
|
||||||
auto remainingSpineVerticies = bodyVerticies;
|
auto remainingSpineVerticies = bodyVerticies;
|
||||||
|
|
|
@ -11,6 +11,16 @@ void JointNodeTree::updateRotation(int index, QQuaternion rotation)
|
||||||
m_boneNodes[index].rotation = rotation;
|
m_boneNodes[index].rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JointNodeTree::updateTranslation(int index, QVector3D translation)
|
||||||
|
{
|
||||||
|
m_boneNodes[index].translation = translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JointNodeTree::addTranslation(int index, QVector3D translation)
|
||||||
|
{
|
||||||
|
m_boneNodes[index].translation += translation;
|
||||||
|
}
|
||||||
|
|
||||||
void JointNodeTree::reset()
|
void JointNodeTree::reset()
|
||||||
{
|
{
|
||||||
for (auto &node: m_boneNodes) {
|
for (auto &node: m_boneNodes) {
|
||||||
|
@ -80,6 +90,7 @@ JointNodeTree JointNodeTree::slerp(const JointNodeTree &first, const JointNodeTr
|
||||||
for (decltype(first.nodes().size()) i = 0; i < first.nodes().size() && i < second.nodes().size(); i++) {
|
for (decltype(first.nodes().size()) i = 0; i < first.nodes().size() && i < second.nodes().size(); i++) {
|
||||||
slerpResult.updateRotation(i,
|
slerpResult.updateRotation(i,
|
||||||
quaternionOvershootSlerp(first.nodes()[i].rotation, second.nodes()[i].rotation, t));
|
quaternionOvershootSlerp(first.nodes()[i].rotation, second.nodes()[i].rotation, t));
|
||||||
|
slerpResult.updateTranslation(i, (first.nodes()[i].translation * (1.0 - t) + second.nodes()[i].translation * t));
|
||||||
}
|
}
|
||||||
slerpResult.recalculateTransformMatrices();
|
slerpResult.recalculateTransformMatrices();
|
||||||
return slerpResult;
|
return slerpResult;
|
||||||
|
|
|
@ -23,6 +23,8 @@ public:
|
||||||
const std::vector<JointNode> &nodes() const;
|
const std::vector<JointNode> &nodes() const;
|
||||||
JointNodeTree(const std::vector<RiggerBone> *resultRigBones);
|
JointNodeTree(const std::vector<RiggerBone> *resultRigBones);
|
||||||
void updateRotation(int index, QQuaternion rotation);
|
void updateRotation(int index, QQuaternion rotation);
|
||||||
|
void updateTranslation(int index, QVector3D translation);
|
||||||
|
void addTranslation(int index, QVector3D translation);
|
||||||
void reset();
|
void reset();
|
||||||
void recalculateTransformMatrices();
|
void recalculateTransformMatrices();
|
||||||
static JointNodeTree slerp(const JointNodeTree &first, const JointNodeTree &second, float t);
|
static JointNodeTree slerp(const JointNodeTree &first, const JointNodeTree &second, float t);
|
||||||
|
|
|
@ -294,6 +294,60 @@ void PoseEditWidget::showPopupAngleDialog(QString boneName, PopupWidgetType popu
|
||||||
intersectionLayout->addWidget(intersectionEraser);
|
intersectionLayout->addWidget(intersectionEraser);
|
||||||
intersectionLayout->addWidget(intersectionWidget);
|
intersectionLayout->addWidget(intersectionWidget);
|
||||||
layout->addLayout(intersectionLayout);
|
layout->addLayout(intersectionLayout);
|
||||||
|
} else if (PopupWidgetType::Translation == popupWidgetType) {
|
||||||
|
FloatNumberWidget *xWidget = new FloatNumberWidget;
|
||||||
|
xWidget->setItemName(tr("X"));
|
||||||
|
xWidget->setRange(-1, 1);
|
||||||
|
xWidget->setValue(valueOfKeyInMapOrEmpty(m_parameters[boneName], "x").toFloat());
|
||||||
|
connect(xWidget, &FloatNumberWidget::valueChanged, this, [=](float value) {
|
||||||
|
m_parameters[boneName]["x"] = QString::number(value);
|
||||||
|
emit parametersAdjusted();
|
||||||
|
});
|
||||||
|
QPushButton *xEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeMiniButton(xEraser);
|
||||||
|
connect(xEraser, &QPushButton::clicked, this, [=]() {
|
||||||
|
xWidget->setValue(0.0);
|
||||||
|
});
|
||||||
|
QHBoxLayout *xLayout = new QHBoxLayout;
|
||||||
|
xLayout->addWidget(xEraser);
|
||||||
|
xLayout->addWidget(xWidget);
|
||||||
|
layout->addLayout(xLayout);
|
||||||
|
|
||||||
|
FloatNumberWidget *yWidget = new FloatNumberWidget;
|
||||||
|
yWidget->setItemName(tr("Y"));
|
||||||
|
yWidget->setRange(-1, 1);
|
||||||
|
yWidget->setValue(valueOfKeyInMapOrEmpty(m_parameters[boneName], "y").toFloat());
|
||||||
|
connect(yWidget, &FloatNumberWidget::valueChanged, this, [=](float value) {
|
||||||
|
m_parameters[boneName]["y"] = QString::number(value);
|
||||||
|
emit parametersAdjusted();
|
||||||
|
});
|
||||||
|
QPushButton *yEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeMiniButton(yEraser);
|
||||||
|
connect(yEraser, &QPushButton::clicked, this, [=]() {
|
||||||
|
yWidget->setValue(0.0);
|
||||||
|
});
|
||||||
|
QHBoxLayout *yLayout = new QHBoxLayout;
|
||||||
|
yLayout->addWidget(yEraser);
|
||||||
|
yLayout->addWidget(yWidget);
|
||||||
|
layout->addLayout(yLayout);
|
||||||
|
|
||||||
|
FloatNumberWidget *zWidget = new FloatNumberWidget;
|
||||||
|
zWidget->setItemName(tr("Z"));
|
||||||
|
zWidget->setRange(-1, 1);
|
||||||
|
zWidget->setValue(valueOfKeyInMapOrEmpty(m_parameters[boneName], "z").toFloat());
|
||||||
|
connect(zWidget, &FloatNumberWidget::valueChanged, this, [=](float value) {
|
||||||
|
m_parameters[boneName]["z"] = QString::number(value);
|
||||||
|
emit parametersAdjusted();
|
||||||
|
});
|
||||||
|
QPushButton *zEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeMiniButton(zEraser);
|
||||||
|
connect(zEraser, &QPushButton::clicked, this, [=]() {
|
||||||
|
zWidget->setValue(0.0);
|
||||||
|
});
|
||||||
|
QHBoxLayout *zLayout = new QHBoxLayout;
|
||||||
|
zLayout->addWidget(zEraser);
|
||||||
|
zLayout->addWidget(zWidget);
|
||||||
|
layout->addLayout(zLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
popup->setLayout(layout);
|
popup->setLayout(layout);
|
||||||
|
|
|
@ -15,7 +15,8 @@ enum class RiggerButtonParameterType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
PitchYawRoll,
|
PitchYawRoll,
|
||||||
Intersection
|
Intersection,
|
||||||
|
Translation
|
||||||
};
|
};
|
||||||
|
|
||||||
class RiggerMark
|
class RiggerMark
|
||||||
|
|
|
@ -65,6 +65,19 @@ void TetrapodPoser::commit()
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
auto findXResult = item.second.find("x");
|
||||||
|
auto findYResult = item.second.find("y");
|
||||||
|
auto findZResult = item.second.find("z");
|
||||||
|
if (findXResult != item.second.end() ||
|
||||||
|
findYResult != item.second.end() ||
|
||||||
|
findZResult != item.second.end()) {
|
||||||
|
float x = valueOfKeyInMapOrEmpty(item.second, "x").toFloat();
|
||||||
|
float y = valueOfKeyInMapOrEmpty(item.second, "y").toFloat();
|
||||||
|
float z = valueOfKeyInMapOrEmpty(item.second, "z").toFloat();
|
||||||
|
QVector3D translation = {x, y, z};
|
||||||
|
m_jointNodeTree.addTranslation(boneIndex, translation);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Poser::commit();
|
Poser::commit();
|
||||||
|
|
|
@ -374,6 +374,9 @@ bool TetrapodRigger::rig()
|
||||||
bodyBone.name = "Body";
|
bodyBone.name = "Body";
|
||||||
bodyBone.headPosition = QVector3D(0, 0, 0);
|
bodyBone.headPosition = QVector3D(0, 0, 0);
|
||||||
bodyBone.tailPosition = bonesOrigin;
|
bodyBone.tailPosition = bonesOrigin;
|
||||||
|
bodyBone.hasButton = true;
|
||||||
|
bodyBone.button = {7, 1};
|
||||||
|
bodyBone.buttonParameterType = RiggerButtonParameterType::Translation;
|
||||||
boneIndexMap[bodyBone.name] = bodyBone.index;
|
boneIndexMap[bodyBone.name] = bodyBone.index;
|
||||||
|
|
||||||
m_resultBones.push_back(RiggerBone());
|
m_resultBones.push_back(RiggerBone());
|
||||||
|
|
Loading…
Reference in New Issue