2021-11-18 14:58:01 +00:00
|
|
|
#ifndef DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
|
|
|
|
#define DUST3D_APPLICATION_SKELETON_GRAPHICS_VIEW_H_
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
#include "model_widget.h"
|
|
|
|
#include "skeleton_document.h"
|
|
|
|
#include "skeleton_ik_mover.h"
|
|
|
|
#include "theme.h"
|
|
|
|
#include "turnaround_loader.h"
|
2018-04-07 08:44:39 +00:00
|
|
|
#include <QGraphicsEllipseItem>
|
|
|
|
#include <QGraphicsLineItem>
|
|
|
|
#include <QGraphicsPixmapItem>
|
2018-04-15 12:11:51 +00:00
|
|
|
#include <QGraphicsPolygonItem>
|
2022-10-18 09:35:04 +00:00
|
|
|
#include <QGraphicsView>
|
|
|
|
#include <QKeyEvent>
|
|
|
|
#include <QMouseEvent>
|
2018-04-07 08:44:39 +00:00
|
|
|
#include <QThread>
|
2022-10-18 09:35:04 +00:00
|
|
|
#include <QTimer>
|
2018-04-07 08:44:39 +00:00
|
|
|
#include <cmath>
|
2022-10-18 09:35:04 +00:00
|
|
|
#include <map>
|
2018-04-08 15:08:23 +00:00
|
|
|
#include <set>
|
2018-04-07 08:44:39 +00:00
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
class SkeletonGraphicsOriginItem : public QGraphicsPolygonItem {
|
2018-04-15 12:11:51 +00:00
|
|
|
public:
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsOriginItem(SkeletonProfile profile = SkeletonProfile::Unknown)
|
|
|
|
: m_profile(profile)
|
|
|
|
, m_hovered(false)
|
|
|
|
, m_checked(false)
|
|
|
|
, m_rotated(false)
|
2018-04-15 12:11:51 +00:00
|
|
|
{
|
|
|
|
setData(0, "origin");
|
|
|
|
}
|
2019-10-19 13:14:36 +00:00
|
|
|
void setRotated(bool rotated)
|
|
|
|
{
|
|
|
|
m_rotated = rotated;
|
|
|
|
}
|
2018-04-15 12:11:51 +00:00
|
|
|
void updateAppearance()
|
|
|
|
{
|
|
|
|
QColor color = Theme::white;
|
2022-10-18 09:35:04 +00:00
|
|
|
|
|
|
|
switch (m_profile) {
|
2018-04-15 12:11:51 +00:00
|
|
|
case SkeletonProfile::Unknown:
|
|
|
|
break;
|
|
|
|
case SkeletonProfile::Main:
|
2019-10-19 13:14:36 +00:00
|
|
|
color = m_rotated ? Theme::blue : Theme::red;
|
2018-04-15 12:11:51 +00:00
|
|
|
break;
|
|
|
|
case SkeletonProfile::Side:
|
|
|
|
color = Theme::green;
|
|
|
|
break;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-15 12:11:51 +00:00
|
|
|
QColor penColor = color;
|
|
|
|
penColor.setAlphaF(m_checked ? Theme::checkedAlpha : Theme::normalAlpha);
|
|
|
|
QPen pen(penColor);
|
|
|
|
pen.setWidth(0);
|
|
|
|
setPen(pen);
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-15 12:11:51 +00:00
|
|
|
QColor brushColor = color;
|
|
|
|
brushColor.setAlphaF((m_checked || m_hovered) ? Theme::checkedAlpha : Theme::normalAlpha);
|
|
|
|
QBrush brush(brushColor);
|
|
|
|
setBrush(brush);
|
|
|
|
}
|
|
|
|
void setOrigin(QPointF point)
|
|
|
|
{
|
|
|
|
m_origin = point;
|
|
|
|
QPolygonF triangle;
|
|
|
|
const int triangleRadius = 10;
|
|
|
|
triangle.append(QPointF(point.x() - triangleRadius, point.y()));
|
|
|
|
triangle.append(QPointF(point.x() + triangleRadius, point.y()));
|
|
|
|
triangle.append(QPointF(point.x(), point.y() - triangleRadius));
|
|
|
|
triangle.append(QPointF(point.x() - triangleRadius, point.y()));
|
|
|
|
setPolygon(triangle);
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
QPointF origin()
|
|
|
|
{
|
|
|
|
return m_origin;
|
|
|
|
}
|
|
|
|
SkeletonProfile profile()
|
|
|
|
{
|
|
|
|
return m_profile;
|
|
|
|
}
|
|
|
|
void setHovered(bool hovered)
|
|
|
|
{
|
|
|
|
m_hovered = hovered;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
void setChecked(bool checked)
|
|
|
|
{
|
|
|
|
m_checked = checked;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
bool checked()
|
|
|
|
{
|
|
|
|
return m_checked;
|
|
|
|
}
|
|
|
|
bool hovered()
|
|
|
|
{
|
|
|
|
return m_hovered;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-15 12:11:51 +00:00
|
|
|
private:
|
|
|
|
SkeletonProfile m_profile;
|
|
|
|
bool m_hovered;
|
|
|
|
bool m_checked;
|
|
|
|
QPointF m_origin;
|
2019-10-19 13:14:36 +00:00
|
|
|
bool m_rotated;
|
2018-04-15 12:11:51 +00:00
|
|
|
};
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
class SkeletonGraphicsSelectionItem : public QGraphicsRectItem {
|
2018-04-08 15:08:23 +00:00
|
|
|
public:
|
|
|
|
SkeletonGraphicsSelectionItem()
|
|
|
|
{
|
|
|
|
QColor penColor = Theme::white;
|
|
|
|
QPen pen(penColor);
|
|
|
|
pen.setWidth(0);
|
|
|
|
pen.setStyle(Qt::DashLine);
|
|
|
|
setPen(pen);
|
|
|
|
}
|
|
|
|
void updateRange(QPointF beginPos, QPointF endPos)
|
|
|
|
{
|
|
|
|
setRect(QRectF(beginPos, endPos).normalized());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
class SkeletonGraphicsNodeItem : public QGraphicsEllipseItem {
|
2018-04-07 08:44:39 +00:00
|
|
|
public:
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsNodeItem(SkeletonProfile profile = SkeletonProfile::Unknown)
|
|
|
|
: m_profile(profile)
|
|
|
|
, m_hovered(false)
|
|
|
|
, m_checked(false)
|
|
|
|
, m_markColor(Qt::transparent)
|
|
|
|
, m_deactivated(false)
|
|
|
|
, m_rotated(false)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
setData(0, "node");
|
|
|
|
setRadius(32);
|
|
|
|
}
|
2019-10-19 13:14:36 +00:00
|
|
|
void setRotated(bool rotated)
|
|
|
|
{
|
|
|
|
m_rotated = rotated;
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
void updateAppearance()
|
|
|
|
{
|
2019-03-03 00:05:13 +00:00
|
|
|
QColor color = Qt::gray;
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2019-03-03 00:05:13 +00:00
|
|
|
if (!m_deactivated) {
|
2022-10-18 09:35:04 +00:00
|
|
|
switch (m_profile) {
|
2019-03-03 00:05:13 +00:00
|
|
|
case SkeletonProfile::Unknown:
|
|
|
|
break;
|
|
|
|
case SkeletonProfile::Main:
|
2019-10-19 13:14:36 +00:00
|
|
|
color = m_rotated ? Theme::blue : Theme::red;
|
2019-03-03 00:05:13 +00:00
|
|
|
break;
|
|
|
|
case SkeletonProfile::Side:
|
|
|
|
color = Theme::green;
|
|
|
|
break;
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
QColor penColor = color;
|
2018-11-01 15:24:06 +00:00
|
|
|
penColor.setAlphaF((m_checked || m_hovered) ? Theme::checkedAlpha : Theme::normalAlpha);
|
2018-04-07 08:44:39 +00:00
|
|
|
QPen pen(penColor);
|
|
|
|
pen.setWidth(0);
|
|
|
|
setPen(pen);
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-11-01 15:24:06 +00:00
|
|
|
QColor brushColor;
|
|
|
|
Qt::BrushStyle style;
|
2018-05-30 01:51:38 +00:00
|
|
|
if (m_markColor == Qt::transparent) {
|
2018-11-01 15:24:06 +00:00
|
|
|
brushColor = color;
|
2018-05-30 01:51:38 +00:00
|
|
|
brushColor.setAlphaF((m_checked || m_hovered) ? Theme::fillAlpha : 0);
|
2018-11-01 15:24:06 +00:00
|
|
|
style = Qt::SolidPattern;
|
2018-05-30 01:51:38 +00:00
|
|
|
} else {
|
2018-11-01 15:24:06 +00:00
|
|
|
brushColor = m_markColor;
|
2018-05-30 01:51:38 +00:00
|
|
|
brushColor.setAlphaF((m_checked || m_hovered) ? Theme::fillAlpha * 4 : Theme::fillAlpha * 1.5);
|
2018-11-01 15:24:06 +00:00
|
|
|
style = Qt::Dense4Pattern;
|
2018-05-30 01:51:38 +00:00
|
|
|
}
|
2018-11-01 15:24:06 +00:00
|
|
|
if (m_checked)
|
|
|
|
brushColor.setAlphaF(brushColor.alphaF() * 1.2);
|
|
|
|
QBrush brush(brushColor);
|
|
|
|
brush.setStyle(style);
|
|
|
|
setBrush(brush);
|
2018-04-07 08:44:39 +00:00
|
|
|
}
|
|
|
|
void setOrigin(QPointF point)
|
|
|
|
{
|
|
|
|
QPointF moveBy = point - origin();
|
|
|
|
QRectF newRect = rect();
|
|
|
|
newRect.adjust(moveBy.x(), moveBy.y(), moveBy.x(), moveBy.y());
|
|
|
|
setRect(newRect);
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
QPointF origin()
|
|
|
|
{
|
|
|
|
return QPointF(rect().x() + rect().width() / 2,
|
|
|
|
rect().y() + rect().height() / 2);
|
|
|
|
}
|
|
|
|
float radius()
|
|
|
|
{
|
|
|
|
return rect().width() / 2;
|
|
|
|
}
|
|
|
|
void setRadius(float radius)
|
|
|
|
{
|
2018-04-26 02:23:22 +00:00
|
|
|
if (radius < 1)
|
|
|
|
radius = 1;
|
2018-04-07 08:44:39 +00:00
|
|
|
QPointF oldOrigin = origin();
|
|
|
|
setRect(oldOrigin.x() - radius, oldOrigin.y() - radius,
|
|
|
|
radius * 2, radius * 2);
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2018-05-30 01:51:38 +00:00
|
|
|
void setMarkColor(QColor color)
|
|
|
|
{
|
|
|
|
m_markColor = color;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
SkeletonProfile profile()
|
|
|
|
{
|
|
|
|
return m_profile;
|
|
|
|
}
|
2021-11-18 14:58:01 +00:00
|
|
|
dust3d::Uuid id()
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
return m_uuid;
|
|
|
|
}
|
2021-11-18 14:58:01 +00:00
|
|
|
void setId(dust3d::Uuid id)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
m_uuid = id;
|
|
|
|
}
|
|
|
|
void setHovered(bool hovered)
|
|
|
|
{
|
|
|
|
m_hovered = hovered;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
void setChecked(bool checked)
|
|
|
|
{
|
|
|
|
m_checked = checked;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2019-03-03 00:05:13 +00:00
|
|
|
void setDeactivated(bool deactivated)
|
|
|
|
{
|
|
|
|
m_deactivated = deactivated;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
bool deactivated()
|
|
|
|
{
|
|
|
|
return m_deactivated;
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
bool checked()
|
|
|
|
{
|
|
|
|
return m_checked;
|
|
|
|
}
|
2018-04-08 15:08:23 +00:00
|
|
|
bool hovered()
|
|
|
|
{
|
|
|
|
return m_hovered;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
private:
|
2021-11-18 14:58:01 +00:00
|
|
|
dust3d::Uuid m_uuid;
|
2018-04-07 08:44:39 +00:00
|
|
|
SkeletonProfile m_profile;
|
|
|
|
bool m_hovered;
|
|
|
|
bool m_checked;
|
2018-05-30 01:51:38 +00:00
|
|
|
QColor m_markColor;
|
2019-03-03 00:05:13 +00:00
|
|
|
bool m_deactivated;
|
2019-10-19 13:14:36 +00:00
|
|
|
bool m_rotated;
|
2018-04-07 08:44:39 +00:00
|
|
|
};
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
class SkeletonGraphicsEdgeItem : public QGraphicsPolygonItem {
|
2018-04-07 08:44:39 +00:00
|
|
|
public:
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsEdgeItem()
|
|
|
|
: m_firstItem(nullptr)
|
|
|
|
, m_secondItem(nullptr)
|
|
|
|
, m_hovered(false)
|
|
|
|
, m_checked(false)
|
|
|
|
, m_profile(SkeletonProfile::Unknown)
|
|
|
|
, m_deactivated(false)
|
|
|
|
, m_rotated(false)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
setData(0, "edge");
|
|
|
|
}
|
2019-10-19 13:14:36 +00:00
|
|
|
void setRotated(bool rotated)
|
|
|
|
{
|
|
|
|
m_rotated = rotated;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
void setEndpoints(SkeletonGraphicsNodeItem* first, SkeletonGraphicsNodeItem* second)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
m_firstItem = first;
|
|
|
|
m_secondItem = second;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsNodeItem* firstItem()
|
2018-04-08 15:08:23 +00:00
|
|
|
{
|
|
|
|
return m_firstItem;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsNodeItem* secondItem()
|
2018-04-08 15:08:23 +00:00
|
|
|
{
|
|
|
|
return m_secondItem;
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
void updateAppearance()
|
|
|
|
{
|
|
|
|
if (nullptr == m_firstItem || nullptr == m_secondItem)
|
|
|
|
return;
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-08 15:08:23 +00:00
|
|
|
m_profile = m_firstItem->profile();
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
QLineF line(m_firstItem->origin(), m_secondItem->origin());
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
QPolygonF polygon;
|
|
|
|
float radAngle = line.angle() * M_PI / 180;
|
2018-04-08 08:05:12 +00:00
|
|
|
float dx = 2 * sin(radAngle);
|
|
|
|
float dy = 2 * cos(radAngle);
|
2018-04-07 08:44:39 +00:00
|
|
|
QPointF offset1 = QPointF(dx, dy);
|
|
|
|
QPointF offset2 = QPointF(-dx, -dy);
|
2020-03-24 11:12:29 +00:00
|
|
|
//polygon << line.p1() + offset1 << line.p1() + offset2 << line.p2() + offset2 << line.p2() + offset1;
|
|
|
|
polygon << line.p1() + offset1 << line.p1() + offset2 << line.p2();
|
2018-04-07 08:44:39 +00:00
|
|
|
setPolygon(polygon);
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2019-03-03 00:05:13 +00:00
|
|
|
QColor color = Qt::gray;
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2019-03-03 00:05:13 +00:00
|
|
|
if (!m_deactivated) {
|
2022-10-18 09:35:04 +00:00
|
|
|
switch (m_firstItem->profile()) {
|
2019-03-03 00:05:13 +00:00
|
|
|
case SkeletonProfile::Unknown:
|
|
|
|
break;
|
|
|
|
case SkeletonProfile::Main:
|
2019-10-19 13:14:36 +00:00
|
|
|
color = m_rotated ? Theme::blue : Theme::red;
|
2019-03-03 00:05:13 +00:00
|
|
|
break;
|
|
|
|
case SkeletonProfile::Side:
|
|
|
|
color = Theme::green;
|
|
|
|
break;
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
QColor penColor = color;
|
|
|
|
penColor.setAlphaF((m_checked || m_hovered) ? Theme::checkedAlpha : Theme::normalAlpha);
|
|
|
|
QPen pen(penColor);
|
|
|
|
pen.setWidth(0);
|
|
|
|
setPen(pen);
|
|
|
|
}
|
2021-11-18 14:58:01 +00:00
|
|
|
dust3d::Uuid id()
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
return m_uuid;
|
|
|
|
}
|
2021-11-18 14:58:01 +00:00
|
|
|
void setId(dust3d::Uuid id)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
m_uuid = id;
|
|
|
|
}
|
2018-04-08 15:08:23 +00:00
|
|
|
SkeletonProfile profile()
|
|
|
|
{
|
|
|
|
return m_profile;
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
void setHovered(bool hovered)
|
|
|
|
{
|
|
|
|
m_hovered = hovered;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
|
|
|
void setChecked(bool checked)
|
|
|
|
{
|
|
|
|
m_checked = checked;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2019-03-03 00:05:13 +00:00
|
|
|
void setDeactivated(bool deactivated)
|
|
|
|
{
|
|
|
|
m_deactivated = deactivated;
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2020-04-07 23:15:20 +00:00
|
|
|
void reverse()
|
|
|
|
{
|
|
|
|
std::swap(m_firstItem, m_secondItem);
|
|
|
|
updateAppearance();
|
|
|
|
}
|
2019-03-03 00:05:13 +00:00
|
|
|
bool deactivated()
|
|
|
|
{
|
|
|
|
return m_deactivated;
|
|
|
|
}
|
2018-04-08 15:08:23 +00:00
|
|
|
bool checked()
|
|
|
|
{
|
|
|
|
return m_checked;
|
|
|
|
}
|
|
|
|
bool hovered()
|
|
|
|
{
|
|
|
|
return m_hovered;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
private:
|
2021-11-18 14:58:01 +00:00
|
|
|
dust3d::Uuid m_uuid;
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsNodeItem* m_firstItem;
|
|
|
|
SkeletonGraphicsNodeItem* m_secondItem;
|
2018-04-07 08:44:39 +00:00
|
|
|
QPolygonF m_selectionPolygon;
|
|
|
|
bool m_hovered;
|
|
|
|
bool m_checked;
|
2018-04-08 15:08:23 +00:00
|
|
|
SkeletonProfile m_profile;
|
2019-03-03 00:05:13 +00:00
|
|
|
bool m_deactivated;
|
2019-10-19 13:14:36 +00:00
|
|
|
bool m_rotated;
|
2018-04-07 08:44:39 +00:00
|
|
|
};
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
class SkeletonGraphicsWidget : public QGraphicsView {
|
2018-04-07 08:44:39 +00:00
|
|
|
Q_OBJECT
|
2019-10-25 14:11:17 +00:00
|
|
|
public:
|
|
|
|
~SkeletonGraphicsWidget();
|
2018-04-07 08:44:39 +00:00
|
|
|
signals:
|
2021-11-18 14:58:01 +00:00
|
|
|
void addNode(float x, float y, float z, float radius, dust3d::Uuid fromNodeId);
|
|
|
|
void scaleNodeByAddRadius(dust3d::Uuid nodeId, float amount);
|
|
|
|
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
|
|
|
void removeNode(dust3d::Uuid nodeId);
|
|
|
|
void removePart(dust3d::Uuid partId);
|
2018-11-03 08:09:42 +00:00
|
|
|
void setEditMode(SkeletonDocumentEditMode mode);
|
2021-11-18 14:58:01 +00:00
|
|
|
void removeEdge(dust3d::Uuid edgeId);
|
|
|
|
void addEdge(dust3d::Uuid fromNodeId, dust3d::Uuid toNodeId);
|
2018-04-07 08:44:39 +00:00
|
|
|
void cursorChanged();
|
2018-04-08 23:34:46 +00:00
|
|
|
void groupOperationAdded();
|
|
|
|
void undo();
|
|
|
|
void redo();
|
2018-04-09 08:46:06 +00:00
|
|
|
void paste();
|
2018-04-09 11:13:34 +00:00
|
|
|
void changeTurnaround();
|
2018-04-09 14:24:30 +00:00
|
|
|
void batchChangeBegin();
|
|
|
|
void batchChangeEnd();
|
2018-04-10 07:59:20 +00:00
|
|
|
void open();
|
|
|
|
void exportResult();
|
2021-11-18 14:58:01 +00:00
|
|
|
void breakEdge(dust3d::Uuid edgeId);
|
|
|
|
void reduceNode(dust3d::Uuid nodeId);
|
|
|
|
void reverseEdge(dust3d::Uuid edgeId);
|
2018-04-15 12:11:51 +00:00
|
|
|
void moveOriginBy(float x, float y, float z);
|
2021-11-18 14:58:01 +00:00
|
|
|
void partChecked(dust3d::Uuid partId);
|
|
|
|
void partUnchecked(dust3d::Uuid partId);
|
|
|
|
void setPartLockState(dust3d::Uuid partId, bool locked);
|
|
|
|
void setPartVisibleState(dust3d::Uuid partId, bool visible);
|
|
|
|
void setPartSubdivState(dust3d::Uuid partId, bool subdived);
|
|
|
|
void setPartDisableState(dust3d::Uuid partId, bool disabled);
|
|
|
|
void setPartXmirrorState(dust3d::Uuid partId, bool mirrored);
|
|
|
|
void setPartRoundState(dust3d::Uuid partId, bool rounded);
|
|
|
|
void setPartWrapState(dust3d::Uuid partId, bool wrapped);
|
|
|
|
void setPartChamferState(dust3d::Uuid partId, bool chamfered);
|
|
|
|
void setPartColorState(dust3d::Uuid partId, bool hasColor, QColor color);
|
2018-04-18 03:14:48 +00:00
|
|
|
void setXlockState(bool locked);
|
|
|
|
void setYlockState(bool locked);
|
|
|
|
void setZlockState(bool locked);
|
2021-11-18 14:58:01 +00:00
|
|
|
void setNodeOrigin(dust3d::Uuid nodeId, float x, float y, float z);
|
2018-05-24 07:08:57 +00:00
|
|
|
void zoomRenderedModelBy(float delta);
|
2021-11-18 14:58:01 +00:00
|
|
|
void switchNodeXZ(dust3d::Uuid nodeId);
|
2018-09-03 07:05:05 +00:00
|
|
|
void enableAllPositionRelatedLocks();
|
|
|
|
void disableAllPositionRelatedLocks();
|
2019-02-23 00:41:56 +00:00
|
|
|
void shortcutToggleWireframe();
|
2021-11-18 14:58:01 +00:00
|
|
|
void partComponentChecked(dust3d::Uuid partId);
|
2019-10-19 00:31:27 +00:00
|
|
|
void showOrHideAllComponents();
|
2019-10-19 02:07:23 +00:00
|
|
|
void shortcutToggleFlatShading();
|
2019-10-19 13:14:36 +00:00
|
|
|
void shortcutToggleRotation();
|
2020-12-13 13:21:45 +00:00
|
|
|
void loadedTurnaroundImageChanged();
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
public:
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsWidget(const SkeletonDocument* document);
|
|
|
|
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsNodeItem*, SkeletonGraphicsNodeItem*>> nodeItemMap;
|
|
|
|
std::map<dust3d::Uuid, std::pair<SkeletonGraphicsEdgeItem*, SkeletonGraphicsEdgeItem*>> edgeItemMap;
|
|
|
|
bool mouseMove(QMouseEvent* event);
|
|
|
|
bool wheel(QWheelEvent* event);
|
|
|
|
bool mouseRelease(QMouseEvent* event);
|
|
|
|
bool mousePress(QMouseEvent* event);
|
|
|
|
bool mouseDoubleClick(QMouseEvent* event);
|
|
|
|
bool keyPress(QKeyEvent* event);
|
|
|
|
bool keyRelease(QKeyEvent* event);
|
|
|
|
bool checkSkeletonItem(QGraphicsItem* item, bool checked);
|
|
|
|
dust3d::Uuid querySkeletonItemPartId(QGraphicsItem* item);
|
|
|
|
static SkeletonProfile readSkeletonItemProfile(QGraphicsItem* item);
|
|
|
|
void getOtherProfileNodeItems(const std::set<SkeletonGraphicsNodeItem*>& nodeItemSet,
|
|
|
|
std::set<SkeletonGraphicsNodeItem*>* otherProfileNodeItemSet);
|
|
|
|
void readMergedSkeletonNodeSetFromRangeSelection(std::set<SkeletonGraphicsNodeItem*>* nodeItemSet);
|
|
|
|
void readSkeletonNodeAndEdgeIdSetFromRangeSelection(std::set<dust3d::Uuid>* nodeIdSet, std::set<dust3d::Uuid>* edgeIdSet = nullptr);
|
|
|
|
bool readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(SkeletonGraphicsNodeItem** nodeItem, SkeletonGraphicsEdgeItem** edgeItem);
|
2018-04-10 07:59:20 +00:00
|
|
|
bool hasSelection();
|
|
|
|
bool hasItems();
|
|
|
|
bool hasMultipleSelection();
|
2018-04-12 12:27:21 +00:00
|
|
|
bool hasEdgeSelection();
|
2018-05-30 01:51:38 +00:00
|
|
|
bool hasNodeSelection();
|
2018-04-12 12:46:13 +00:00
|
|
|
bool hasTwoDisconnectedNodesSelection();
|
2022-10-18 09:35:04 +00:00
|
|
|
void setModelWidget(ModelWidget* modelWidget);
|
|
|
|
bool inputWheelEventFromOtherWidget(QWheelEvent* event);
|
2020-11-09 10:46:06 +00:00
|
|
|
bool rotated();
|
2022-10-18 09:35:04 +00:00
|
|
|
const QImage* loadedTurnaroundImage() const;
|
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
protected:
|
2022-10-18 09:35:04 +00:00
|
|
|
void mouseMoveEvent(QMouseEvent* event) override;
|
|
|
|
void wheelEvent(QWheelEvent* event) override;
|
|
|
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
|
|
|
void mousePressEvent(QMouseEvent* event) override;
|
|
|
|
void mouseDoubleClickEvent(QMouseEvent* event) override;
|
|
|
|
void keyPressEvent(QKeyEvent* event) override;
|
|
|
|
void keyReleaseEvent(QKeyEvent* event) override;
|
2018-04-07 08:44:39 +00:00
|
|
|
public slots:
|
2021-11-18 14:58:01 +00:00
|
|
|
void nodeAdded(dust3d::Uuid nodeId);
|
|
|
|
void edgeAdded(dust3d::Uuid edgeId);
|
|
|
|
void nodeRemoved(dust3d::Uuid nodeId);
|
|
|
|
void edgeRemoved(dust3d::Uuid edgeId);
|
|
|
|
void nodeRadiusChanged(dust3d::Uuid nodeId);
|
|
|
|
void nodeOriginChanged(dust3d::Uuid nodeId);
|
|
|
|
void edgeReversed(dust3d::Uuid edgeId);
|
2018-04-07 08:44:39 +00:00
|
|
|
void turnaroundChanged();
|
|
|
|
void canvasResized();
|
|
|
|
void editModeChanged();
|
|
|
|
void updateCursor();
|
2021-11-18 14:58:01 +00:00
|
|
|
void partVisibleStateChanged(dust3d::Uuid partId);
|
2022-10-18 09:35:04 +00:00
|
|
|
void showContextMenu(const QPoint& pos);
|
2018-04-09 03:39:04 +00:00
|
|
|
void deleteSelected();
|
|
|
|
void selectAll();
|
|
|
|
void unselectAll();
|
2018-04-09 05:22:25 +00:00
|
|
|
void selectPartAll();
|
2018-12-11 11:55:55 +00:00
|
|
|
void selectConnectedAll();
|
2021-11-18 14:58:01 +00:00
|
|
|
void addPartToSelection(dust3d::Uuid partId);
|
2018-04-09 08:46:06 +00:00
|
|
|
void cut();
|
|
|
|
void copy();
|
2018-04-09 14:24:30 +00:00
|
|
|
void flipHorizontally();
|
|
|
|
void flipVertically();
|
2018-06-15 09:58:46 +00:00
|
|
|
void rotateClockwise90Degree();
|
|
|
|
void rotateCounterclockwise90Degree();
|
2018-09-03 07:05:05 +00:00
|
|
|
void rotateAllMainProfileClockwise90DegreeAlongOrigin();
|
|
|
|
void rotateAllMainProfileCounterclockwise90DegreeAlongOrigin();
|
2018-04-10 07:59:20 +00:00
|
|
|
void removeAllContent();
|
2019-10-25 14:11:17 +00:00
|
|
|
void fadeSelected();
|
|
|
|
void colorizeSelected();
|
2018-04-12 12:27:21 +00:00
|
|
|
void breakSelected();
|
2020-10-20 22:04:12 +00:00
|
|
|
void reduceSelected();
|
2020-04-07 23:15:20 +00:00
|
|
|
void reverseSelectedEdges();
|
2018-04-12 12:46:13 +00:00
|
|
|
void connectSelected();
|
2018-04-13 01:27:28 +00:00
|
|
|
void rotateSelected(int degree);
|
|
|
|
void zoomSelected(float delta);
|
|
|
|
void scaleSelected(float delta);
|
|
|
|
void moveSelected(float byX, float byY);
|
2018-04-15 12:11:51 +00:00
|
|
|
void moveCheckedOrigin(float byX, float byY);
|
|
|
|
void originChanged();
|
2018-06-02 09:34:48 +00:00
|
|
|
void alignSelectedToGlobalCenter();
|
|
|
|
void alignSelectedToGlobalVerticalCenter();
|
|
|
|
void alignSelectedToGlobalHorizontalCenter();
|
|
|
|
void alignSelectedToLocalCenter();
|
|
|
|
void alignSelectedToLocalVerticalCenter();
|
|
|
|
void alignSelectedToLocalHorizontalCenter();
|
2021-11-18 14:58:01 +00:00
|
|
|
void selectPartAllById(dust3d::Uuid partId);
|
|
|
|
void addSelectNode(dust3d::Uuid nodeId);
|
|
|
|
void addSelectEdge(dust3d::Uuid edgeId);
|
2018-04-26 02:23:22 +00:00
|
|
|
void enableBackgroundBlur();
|
|
|
|
void disableBackgroundBlur();
|
2018-12-16 05:29:22 +00:00
|
|
|
void setBackgroundBlur(float turnaroundOpacity);
|
2021-11-18 14:58:01 +00:00
|
|
|
void ikMove(dust3d::Uuid endEffectorId, QVector3D target);
|
2018-05-24 01:44:40 +00:00
|
|
|
void ikMoveReady();
|
2018-06-15 11:54:13 +00:00
|
|
|
void timeToRemoveDeferredNodesAndEdges();
|
2018-06-21 08:24:18 +00:00
|
|
|
void switchSelectedXZ();
|
2019-10-19 13:14:36 +00:00
|
|
|
void setRotated(bool rotated);
|
2018-10-24 13:44:21 +00:00
|
|
|
void shortcutDelete();
|
|
|
|
void shortcutAddMode();
|
|
|
|
void shortcutUndo();
|
|
|
|
void shortcutRedo();
|
|
|
|
void shortcutXlock();
|
|
|
|
void shortcutYlock();
|
|
|
|
void shortcutZlock();
|
|
|
|
void shortcutCut();
|
|
|
|
void shortcutCopy();
|
|
|
|
void shortcutPaste();
|
|
|
|
void shortcutSelectMode();
|
2019-08-17 10:13:11 +00:00
|
|
|
void shortcutPaintMode();
|
2018-10-24 13:44:21 +00:00
|
|
|
void shortcutZoomRenderedModelByMinus10();
|
|
|
|
void shortcutZoomSelectedByMinus1();
|
|
|
|
void shortcutZoomRenderedModelBy10();
|
|
|
|
void shortcutZoomSelectedBy1();
|
|
|
|
void shortcutRotateSelectedByMinus1();
|
|
|
|
void shortcutRotateSelectedBy1();
|
|
|
|
void shortcutMoveSelectedToLeft();
|
|
|
|
void shortcutMoveSelectedToRight();
|
|
|
|
void shortcutMoveSelectedToUp();
|
|
|
|
void shortcutMoveSelectedToDown();
|
|
|
|
void shortcutScaleSelectedByMinus1();
|
|
|
|
void shortcutScaleSelectedBy1();
|
|
|
|
void shortcutSwitchProfileOnSelected();
|
|
|
|
void shortcutShowOrHideSelectedPart();
|
|
|
|
void shortcutEnableOrDisableSelectedPart();
|
|
|
|
void shortcutLockOrUnlockSelectedPart();
|
|
|
|
void shortcutXmirrorOnOrOffSelectedPart();
|
|
|
|
void shortcutSubdivedOrNotSelectedPart();
|
|
|
|
void shortcutRoundEndOrNotSelectedPart();
|
2019-10-18 22:51:23 +00:00
|
|
|
void shortcutCheckPartComponent();
|
2019-10-19 00:46:00 +00:00
|
|
|
void shortcutChamferedOrNotSelectedPart();
|
2019-10-25 14:11:17 +00:00
|
|
|
void shortcutSelectAll();
|
|
|
|
void shortcutEscape();
|
2018-04-07 08:44:39 +00:00
|
|
|
private slots:
|
|
|
|
void turnaroundImageReady();
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
private:
|
2022-10-18 09:35:04 +00:00
|
|
|
QPointF mouseEventScenePos(QMouseEvent* event);
|
2018-04-07 08:44:39 +00:00
|
|
|
QPointF scenePosToUnified(QPointF pos);
|
|
|
|
QPointF scenePosFromUnified(QPointF pos);
|
|
|
|
float sceneRadiusToUnified(float radius);
|
|
|
|
float sceneRadiusFromUnified(float radius);
|
|
|
|
void updateTurnaround();
|
|
|
|
void updateItems();
|
2018-04-08 15:08:23 +00:00
|
|
|
void checkRangeSelection();
|
|
|
|
void clearRangeSelection();
|
2022-10-18 09:35:04 +00:00
|
|
|
void removeItem(QGraphicsItem* item);
|
|
|
|
QVector2D centerOfNodeItemSet(const std::set<SkeletonGraphicsNodeItem*>& set);
|
2018-04-09 14:37:20 +00:00
|
|
|
bool isSingleNodeSelected();
|
2022-10-18 09:35:04 +00:00
|
|
|
void addItemToRangeSelection(QGraphicsItem* item);
|
|
|
|
void removeItemFromRangeSelection(QGraphicsItem* item);
|
2021-11-18 14:58:01 +00:00
|
|
|
void hoverPart(dust3d::Uuid partId);
|
2018-04-18 02:16:54 +00:00
|
|
|
void switchProfileOnRangeSelection();
|
2022-10-18 09:35:04 +00:00
|
|
|
void setItemHoveredOnAllProfiles(QGraphicsItem* item, bool hovered);
|
2018-06-02 09:34:48 +00:00
|
|
|
void alignSelectedToGlobal(bool alignToVerticalCenter, bool alignToHorizontalCenter);
|
|
|
|
void alignSelectedToLocal(bool alignToVerticalCenter, bool alignToHorizontalCenter);
|
2022-10-18 09:35:04 +00:00
|
|
|
void rotateItems(const std::set<SkeletonGraphicsNodeItem*>& nodeItems, int degree, QVector2D center);
|
2018-09-03 07:05:05 +00:00
|
|
|
void rotateAllSideProfile(int degree);
|
2021-11-18 14:58:01 +00:00
|
|
|
bool isFloatEqual(float a, float b);
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-06-15 11:54:13 +00:00
|
|
|
private:
|
2022-10-18 09:35:04 +00:00
|
|
|
const SkeletonDocument* m_document = nullptr;
|
|
|
|
QGraphicsPixmapItem* m_backgroundItem = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
bool m_turnaroundChanged = false;
|
2022-10-18 09:35:04 +00:00
|
|
|
TurnaroundLoader* m_turnaroundLoader = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
bool m_dragStarted = false;
|
|
|
|
bool m_moveStarted = false;
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsNodeItem* m_cursorNodeItem = nullptr;
|
|
|
|
SkeletonGraphicsEdgeItem* m_cursorEdgeItem = nullptr;
|
|
|
|
SkeletonGraphicsNodeItem* m_addFromNodeItem = nullptr;
|
|
|
|
SkeletonGraphicsNodeItem* m_hoveredNodeItem = nullptr;
|
|
|
|
SkeletonGraphicsEdgeItem* m_hoveredEdgeItem = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
float m_lastAddedX = false;
|
|
|
|
float m_lastAddedY = false;
|
|
|
|
float m_lastAddedZ = false;
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsSelectionItem* m_selectionItem = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
bool m_rangeSelectionStarted = false;
|
|
|
|
bool m_mouseEventFromSelf = false;
|
|
|
|
bool m_moveHappened = false;
|
|
|
|
int m_lastRot = 0;
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsOriginItem* m_mainOriginItem = nullptr;
|
|
|
|
SkeletonGraphicsOriginItem* m_sideOriginItem = nullptr;
|
|
|
|
SkeletonGraphicsOriginItem* m_hoveredOriginItem = nullptr;
|
|
|
|
SkeletonGraphicsOriginItem* m_checkedOriginItem = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
unsigned long long m_ikMoveUpdateVersion = 0;
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonIkMover* m_ikMover = nullptr;
|
|
|
|
QTimer* m_deferredRemoveTimer = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
bool m_eventForwardingToModelWidget = false;
|
2022-10-18 09:35:04 +00:00
|
|
|
ModelWidget* m_modelWidget = nullptr;
|
2020-12-19 08:12:50 +00:00
|
|
|
bool m_inTempDragMode = false;
|
|
|
|
SkeletonDocumentEditMode m_modeBeforeEnterTempDragMode = SkeletonDocumentEditMode::Select;
|
|
|
|
float m_turnaroundOpacity = 0.25f;
|
|
|
|
bool m_rotated = false;
|
2022-10-18 09:35:04 +00:00
|
|
|
QImage* m_backgroundImage = nullptr;
|
2018-05-24 01:44:40 +00:00
|
|
|
QVector3D m_ikMoveTarget;
|
2021-11-18 14:58:01 +00:00
|
|
|
dust3d::Uuid m_ikMoveEndEffectorId;
|
2022-10-18 09:35:04 +00:00
|
|
|
std::set<QGraphicsItem*> m_rangeSelectionSet;
|
2018-04-15 12:11:51 +00:00
|
|
|
QPoint m_lastGlobalPos;
|
|
|
|
QPointF m_lastScenePos;
|
|
|
|
QPointF m_rangeSelectionStartPos;
|
2021-11-18 14:58:01 +00:00
|
|
|
dust3d::Uuid m_lastCheckedPart;
|
|
|
|
std::set<dust3d::Uuid> m_deferredRemoveNodeIds;
|
|
|
|
std::set<dust3d::Uuid> m_deferredRemoveEdgeIds;
|
2018-04-07 08:44:39 +00:00
|
|
|
};
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
class SkeletonGraphicsContainerWidget : public QWidget {
|
2018-04-07 08:44:39 +00:00
|
|
|
Q_OBJECT
|
|
|
|
signals:
|
|
|
|
void containerSizeChanged(QSize size);
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
public:
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsContainerWidget()
|
|
|
|
: m_graphicsWidget(nullptr)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
void resizeEvent(QResizeEvent* event) override
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
if (m_graphicsWidget && m_graphicsWidget->size() != event->size())
|
|
|
|
emit containerSizeChanged(event->size());
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
void setGraphicsWidget(SkeletonGraphicsWidget* graphicsWidget)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
|
|
|
m_graphicsWidget = graphicsWidget;
|
|
|
|
}
|
2022-10-18 09:35:04 +00:00
|
|
|
|
2018-04-07 08:44:39 +00:00
|
|
|
private:
|
2022-10-18 09:35:04 +00:00
|
|
|
SkeletonGraphicsWidget* m_graphicsWidget;
|
2018-04-07 08:44:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|