forked from qt-creator/qt-creator
Refactor GraphicsScene and Graphicsview
Make sure to deselect keyframes when clicking on an unselected handle Task-number: QDS-1033 Change-Id: I2b98188237f8a0618e6ff3e64280091583112196 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -73,6 +73,8 @@ struct CurveItemStyleOption
|
||||
QColor color = QColor(0, 200, 0);
|
||||
QColor selectionColor = QColor(200, 200, 200);
|
||||
QColor easingCurveColor = QColor(200, 0, 200);
|
||||
QColor lockedColor = QColor(50, 50, 50);
|
||||
QColor hoverColor = QColor(200, 0, 200);
|
||||
};
|
||||
|
||||
struct PlayheadStyleOption
|
||||
|
@@ -118,10 +118,10 @@ void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidg
|
||||
pen.setColor(m_style.easingCurveColor);
|
||||
} else {
|
||||
if (locked())
|
||||
pen.setColor(Qt::black);
|
||||
pen.setColor(m_style.lockedColor);
|
||||
else if (isUnderMouse())
|
||||
pen.setColor(Qt::red);
|
||||
else if (hasSelection())
|
||||
pen.setColor(m_style.hoverColor);
|
||||
else if (hasSelectedKeyframe())
|
||||
pen.setColor(m_style.selectionColor);
|
||||
else
|
||||
pen.setColor(m_style.color);
|
||||
@@ -146,7 +146,25 @@ bool CurveItem::isDirty() const
|
||||
return m_itemDirty;
|
||||
}
|
||||
|
||||
bool CurveItem::hasSelection() const
|
||||
bool CurveItem::hasActiveKeyframe() const
|
||||
{
|
||||
for (auto *frame : m_keyframes) {
|
||||
if (frame->activated())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CurveItem::hasActiveHandle() const
|
||||
{
|
||||
for (auto *frame : m_keyframes) {
|
||||
if (frame->hasActiveHandle())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CurveItem::hasSelectedKeyframe() const
|
||||
{
|
||||
for (auto *frame : m_keyframes) {
|
||||
if (frame->selected())
|
||||
@@ -203,7 +221,7 @@ std::vector<AnimationCurve> CurveItem::curves() const
|
||||
|
||||
std::vector<Keyframe> tmp;
|
||||
|
||||
for (size_t i = 0; i < m_keyframes.size(); ++i) {
|
||||
for (int i = 0; i < m_keyframes.size(); ++i) {
|
||||
KeyframeItem *item = m_keyframes[i];
|
||||
|
||||
Keyframe current = item->keyframe();
|
||||
@@ -233,6 +251,33 @@ std::vector<AnimationCurve> CurveItem::curves() const
|
||||
return out;
|
||||
}
|
||||
|
||||
QVector<KeyframeItem *> CurveItem::keyframes() const
|
||||
{
|
||||
return m_keyframes;
|
||||
}
|
||||
|
||||
QVector<KeyframeItem *> CurveItem::selectedKeyframes() const
|
||||
{
|
||||
QVector<KeyframeItem *> out;
|
||||
for (auto *frame : m_keyframes) {
|
||||
if (frame->selected())
|
||||
out.push_back(frame);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QVector<HandleItem *> CurveItem::handles() const
|
||||
{
|
||||
QVector<HandleItem *> out;
|
||||
for (auto *frame : m_keyframes) {
|
||||
if (auto *left = frame->leftHandle())
|
||||
out.push_back(left);
|
||||
if (auto *right = frame->rightHandle())
|
||||
out.push_back(right);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void CurveItem::restore()
|
||||
{
|
||||
if (m_keyframes.empty())
|
||||
@@ -248,7 +293,7 @@ void CurveItem::restore()
|
||||
if (prevItem->hasLeftHandle())
|
||||
prevItem->setLeftHandle(QPointF());
|
||||
|
||||
for (size_t i = 1; i < m_keyframes.size(); ++i) {
|
||||
for (int i = 1; i < m_keyframes.size(); ++i) {
|
||||
KeyframeItem *currItem = m_keyframes[i];
|
||||
|
||||
bool left = prevItem->hasRightHandle();
|
||||
@@ -328,7 +373,7 @@ void CurveItem::setInterpolation(Keyframe::Interpolation interpolation)
|
||||
return;
|
||||
|
||||
KeyframeItem *prevItem = m_keyframes[0];
|
||||
for (size_t i = 1; i < m_keyframes.size(); ++i) {
|
||||
for (int i = 1; i < m_keyframes.size(); ++i) {
|
||||
KeyframeItem *currItem = m_keyframes[i];
|
||||
if (currItem->selected()) {
|
||||
Keyframe prev = prevItem->keyframe();
|
||||
|
@@ -73,7 +73,11 @@ public:
|
||||
|
||||
bool isDirty() const;
|
||||
|
||||
bool hasSelection() const;
|
||||
bool hasActiveKeyframe() const;
|
||||
|
||||
bool hasActiveHandle() const;
|
||||
|
||||
bool hasSelectedKeyframe() const;
|
||||
|
||||
unsigned int id() const;
|
||||
|
||||
@@ -87,6 +91,12 @@ public:
|
||||
|
||||
std::vector<AnimationCurve> curves() const;
|
||||
|
||||
QVector<KeyframeItem *> keyframes() const;
|
||||
|
||||
QVector<KeyframeItem *> selectedKeyframes() const;
|
||||
|
||||
QVector<HandleItem *> handles() const;
|
||||
|
||||
void restore();
|
||||
|
||||
void setDirty(bool dirty);
|
||||
@@ -126,7 +136,7 @@ private:
|
||||
|
||||
QTransform m_transform;
|
||||
|
||||
std::vector<KeyframeItem *> m_keyframes;
|
||||
QVector<KeyframeItem *> m_keyframes;
|
||||
|
||||
bool m_itemDirty;
|
||||
};
|
||||
|
@@ -31,20 +31,60 @@
|
||||
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace DesignTools {
|
||||
|
||||
GraphicsScene::GraphicsScene(QObject *parent)
|
||||
: QGraphicsScene(parent)
|
||||
, m_curves()
|
||||
, m_dirty(true)
|
||||
, m_limits()
|
||||
, m_doNotMoveItems(false)
|
||||
{}
|
||||
|
||||
GraphicsScene::~GraphicsScene()
|
||||
{
|
||||
m_curves.clear();
|
||||
}
|
||||
|
||||
bool GraphicsScene::empty() const
|
||||
{
|
||||
return items().empty();
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasActiveKeyframe() const
|
||||
{
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->hasActiveKeyframe())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasActiveHandle() const
|
||||
{
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->hasActiveHandle())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasActiveItem() const
|
||||
{
|
||||
return hasActiveKeyframe() || hasActiveHandle();
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasSelectedKeyframe() const
|
||||
{
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->hasSelectedKeyframe())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double GraphicsScene::minimumTime() const
|
||||
{
|
||||
return limits().left();
|
||||
@@ -65,6 +105,103 @@ double GraphicsScene::maximumValue() const
|
||||
return limits().top();
|
||||
}
|
||||
|
||||
QRectF GraphicsScene::rect() const
|
||||
{
|
||||
return sceneRect();
|
||||
}
|
||||
|
||||
QVector<CurveItem *> GraphicsScene::curves() const
|
||||
{
|
||||
return m_curves;
|
||||
}
|
||||
|
||||
QVector<CurveItem *> GraphicsScene::selectedCurves() const
|
||||
{
|
||||
QVector<CurveItem *> out;
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->hasSelectedKeyframe())
|
||||
out.push_back(curve);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QVector<KeyframeItem *> GraphicsScene::keyframes() const
|
||||
{
|
||||
QVector<KeyframeItem *> out;
|
||||
for (auto *curve : m_curves)
|
||||
out.append(curve->keyframes());
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QVector<KeyframeItem *> GraphicsScene::selectedKeyframes() const
|
||||
{
|
||||
QVector<KeyframeItem *> out;
|
||||
for (auto *curve : m_curves)
|
||||
out.append(curve->selectedKeyframes());
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
CurveItem *GraphicsScene::findCurve(unsigned int id) const
|
||||
{
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->id() == id)
|
||||
return curve;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SelectableItem *GraphicsScene::intersect(const QPointF &pos) const
|
||||
{
|
||||
auto hitTest = [pos](QGraphicsObject *item) {
|
||||
return item->mapRectToScene(item->boundingRect()).contains(pos);
|
||||
};
|
||||
|
||||
const auto frames = keyframes();
|
||||
for (auto *frame : frames) {
|
||||
if (hitTest(frame))
|
||||
return frame;
|
||||
|
||||
if (auto *leftHandle = frame->leftHandle()) {
|
||||
if (hitTest(leftHandle))
|
||||
return leftHandle;
|
||||
}
|
||||
|
||||
if (auto *rightHandle = frame->rightHandle()) {
|
||||
if (hitTest(rightHandle))
|
||||
return rightHandle;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GraphicsScene::reset()
|
||||
{
|
||||
m_curves.clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
void GraphicsScene::deleteSelectedKeyframes()
|
||||
{
|
||||
for (auto *curve : m_curves)
|
||||
curve->deleteSelectedKeyframes();
|
||||
}
|
||||
|
||||
void GraphicsScene::insertKeyframe(double time, bool all)
|
||||
{
|
||||
if (!all) {
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->isUnderMouse())
|
||||
curve->insertKeyframeByTime(std::round(time));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto *curve : m_curves)
|
||||
curve->insertKeyframeByTime(std::round(time));
|
||||
}
|
||||
|
||||
void GraphicsScene::doNotMoveItems(bool val)
|
||||
{
|
||||
m_doNotMoveItems = val;
|
||||
@@ -76,16 +213,15 @@ void GraphicsScene::addCurveItem(CurveItem *item)
|
||||
item->setDirty(false);
|
||||
item->connect(this);
|
||||
addItem(item);
|
||||
m_curves.push_back(item);
|
||||
}
|
||||
|
||||
void GraphicsScene::setComponentTransform(const QTransform &transform)
|
||||
{
|
||||
QRectF bounds;
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||
bounds = bounds.united(curveItem->setComponentTransform(transform));
|
||||
}
|
||||
|
||||
for (auto *curve : m_curves)
|
||||
bounds = bounds.united(curve->setComponentTransform(transform));
|
||||
|
||||
if (bounds.isNull()) {
|
||||
if (GraphicsView *gview = graphicsView())
|
||||
@@ -98,29 +234,20 @@ void GraphicsScene::setComponentTransform(const QTransform &transform)
|
||||
|
||||
void GraphicsScene::keyframeMoved(KeyframeItem *movedItem, const QPointF &direction)
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (item == movedItem)
|
||||
continue;
|
||||
|
||||
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
if (frameItem->selected())
|
||||
frameItem->moveKeyframe(direction);
|
||||
for (auto *curve : m_curves) {
|
||||
for (auto *keyframe : curve->keyframes()) {
|
||||
if (keyframe != movedItem && keyframe->selected())
|
||||
keyframe->moveKeyframe(direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::handleUnderMouse(HandleItem *handle)
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (item == handle)
|
||||
continue;
|
||||
|
||||
if (auto *keyItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
if (keyItem->selected()) {
|
||||
keyItem->setActivated(handle->isUnderMouse(), handle->slot());
|
||||
}
|
||||
for (auto *curve : m_curves) {
|
||||
for (auto *keyframe : curve->keyframes()) {
|
||||
if (keyframe->selected())
|
||||
keyframe->setActivated(handle->isUnderMouse(), handle->slot());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,16 +269,13 @@ void GraphicsScene::handleMoved(KeyframeItem *frame,
|
||||
}
|
||||
};
|
||||
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
if (item == frame) {
|
||||
moveUnified(frameItem);
|
||||
continue;
|
||||
}
|
||||
if (frameItem->selected()) {
|
||||
frameItem->moveHandle(handle, angle, deltaLength);
|
||||
moveUnified(frameItem);
|
||||
for (auto *curve : m_curves) {
|
||||
for (auto *keyframe : curve->keyframes()) {
|
||||
if (keyframe == frame)
|
||||
moveUnified(keyframe);
|
||||
else if (keyframe->selected()) {
|
||||
keyframe->moveHandle(handle, angle, deltaLength);
|
||||
moveUnified(keyframe);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,27 +283,24 @@ void GraphicsScene::handleMoved(KeyframeItem *frame,
|
||||
|
||||
void GraphicsScene::setPinned(uint id, bool pinned)
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
if (curveItem->id() == id)
|
||||
curveItem->setPinned(pinned);
|
||||
}
|
||||
}
|
||||
if (CurveItem *curve = findCurve(id))
|
||||
curve->setPinned(pinned);
|
||||
}
|
||||
|
||||
std::vector<CurveItem *> GraphicsScene::takePinnedItems()
|
||||
{
|
||||
std::vector<CurveItem *> out;
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
if (curveItem->pinned()) {
|
||||
removeItem(curveItem);
|
||||
out.push_back(curveItem);
|
||||
}
|
||||
}
|
||||
for (auto *curve : m_curves) {
|
||||
if (curve->pinned())
|
||||
out.push_back(curve);
|
||||
}
|
||||
|
||||
for (auto *curve : out) {
|
||||
curve->disconnect(this);
|
||||
m_curves.removeOne(curve);
|
||||
removeItem(curve);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -187,12 +308,24 @@ void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||
{
|
||||
QGraphicsScene::mouseMoveEvent(mouseEvent);
|
||||
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *handleItem = qgraphicsitem_cast<HandleItem *>(item))
|
||||
handleItem->setIsUnderMouse(handleItem->contains(mouseEvent->scenePos()));
|
||||
else if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||
curveItem->setIsUnderMouse(curveItem->contains(mouseEvent->scenePos()));
|
||||
QPointF mouse = mouseEvent->scenePos();
|
||||
bool hasHandle = false;
|
||||
|
||||
for (auto *curve : m_curves) {
|
||||
for (auto *handle : curve->handles()) {
|
||||
bool intersects = handle->contains(mouse);
|
||||
handle->setIsUnderMouse(intersects);
|
||||
if (intersects)
|
||||
hasHandle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasHandle) {
|
||||
for (auto *curve : m_curves)
|
||||
curve->setIsUnderMouse(false);
|
||||
} else {
|
||||
for (auto *curve : m_curves)
|
||||
curve->setIsUnderMouse(curve->contains(mouseEvent->scenePos()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,17 +333,13 @@ void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||
{
|
||||
QGraphicsScene::mouseReleaseEvent(mouseEvent);
|
||||
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
// CurveItems might become invalid after a keyframe-drag operation.
|
||||
curveItem->restore();
|
||||
|
||||
if (curveItem->isDirty()) {
|
||||
m_dirty = true;
|
||||
curveItem->setDirty(false);
|
||||
emit curveChanged(curveItem->id(), curveItem->curve());
|
||||
}
|
||||
for (auto *curve : m_curves) {
|
||||
// CurveItems might become invalid after a keyframe-drag operation.
|
||||
curve->restore();
|
||||
if (curve->isDirty()) {
|
||||
m_dirty = true;
|
||||
curve->setDirty(false);
|
||||
emit curveChanged(curve->id(), curve->curve());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,40 +347,11 @@ void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||
graphicsView()->setZoomY(0.0);
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasActiveKeyframe() const
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *kitem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
if (kitem->activated())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasActiveHandle() const
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *hitem = qgraphicsitem_cast<HandleItem *>(item)) {
|
||||
if (hitem->activated())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GraphicsScene::hasActiveItem() const
|
||||
{
|
||||
return hasActiveKeyframe() || hasActiveHandle();
|
||||
}
|
||||
|
||||
GraphicsView *GraphicsScene::graphicsView() const
|
||||
{
|
||||
const QList<QGraphicsView *> viewList = views();
|
||||
for (auto &&view : viewList) {
|
||||
if (GraphicsView *gview = qobject_cast<GraphicsView *>(view))
|
||||
if (viewList.size() == 1) {
|
||||
if (GraphicsView *gview = qobject_cast<GraphicsView *>(viewList.at(0)))
|
||||
return gview;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -263,22 +363,19 @@ QRectF GraphicsScene::limits() const
|
||||
QPointF min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
|
||||
QPointF max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
|
||||
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
auto curve = curveItem->resolvedCurve();
|
||||
if (min.x() > curve.minimumTime())
|
||||
min.rx() = curve.minimumTime();
|
||||
for (auto *curveItem : m_curves) {
|
||||
auto curve = curveItem->resolvedCurve();
|
||||
if (min.x() > curve.minimumTime())
|
||||
min.rx() = curve.minimumTime();
|
||||
|
||||
if (min.y() > curve.minimumValue())
|
||||
min.ry() = curve.minimumValue();
|
||||
if (min.y() > curve.minimumValue())
|
||||
min.ry() = curve.minimumValue();
|
||||
|
||||
if (max.x() < curve.maximumTime())
|
||||
max.rx() = curve.maximumTime();
|
||||
if (max.x() < curve.maximumTime())
|
||||
max.rx() = curve.maximumTime();
|
||||
|
||||
if (max.y() < curve.maximumValue())
|
||||
max.ry() = curve.maximumValue();
|
||||
}
|
||||
if (max.y() < curve.maximumValue())
|
||||
max.ry() = curve.maximumValue();
|
||||
}
|
||||
|
||||
m_limits = QRectF(QPointF(min.x(), max.y()), QPointF(max.x(), min.y()));
|
||||
|
@@ -45,6 +45,8 @@ signals:
|
||||
public:
|
||||
GraphicsScene(QObject *parent = nullptr);
|
||||
|
||||
~GraphicsScene() override;
|
||||
|
||||
bool empty() const;
|
||||
|
||||
bool hasActiveKeyframe() const;
|
||||
@@ -53,6 +55,8 @@ public:
|
||||
|
||||
bool hasActiveItem() const;
|
||||
|
||||
bool hasSelectedKeyframe() const;
|
||||
|
||||
double minimumTime() const;
|
||||
|
||||
double maximumTime() const;
|
||||
@@ -61,6 +65,28 @@ public:
|
||||
|
||||
double maximumValue() const;
|
||||
|
||||
QRectF rect() const;
|
||||
|
||||
QVector<CurveItem *> curves() const;
|
||||
|
||||
QVector<CurveItem *> selectedCurves() const;
|
||||
|
||||
QVector<KeyframeItem *> keyframes() const;
|
||||
|
||||
QVector<KeyframeItem *> selectedKeyframes() const;
|
||||
|
||||
QVector<HandleItem *> handles() const;
|
||||
|
||||
CurveItem *findCurve(unsigned int id) const;
|
||||
|
||||
SelectableItem *intersect(const QPointF &pos) const;
|
||||
|
||||
void reset();
|
||||
|
||||
void deleteSelectedKeyframes();
|
||||
|
||||
void insertKeyframe(double time, bool all = false);
|
||||
|
||||
void doNotMoveItems(bool tmp);
|
||||
|
||||
void addCurveItem(CurveItem *item);
|
||||
@@ -85,10 +111,16 @@ protected:
|
||||
private:
|
||||
using QGraphicsScene::addItem;
|
||||
|
||||
using QGraphicsScene::clear;
|
||||
|
||||
using QGraphicsScene::removeItem;
|
||||
|
||||
GraphicsView *graphicsView() const;
|
||||
|
||||
QRectF limits() const;
|
||||
|
||||
QVector<CurveItem *> m_curves;
|
||||
|
||||
mutable bool m_dirty;
|
||||
|
||||
mutable QRectF m_limits;
|
||||
|
@@ -43,7 +43,7 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
, m_zoomX(0.0)
|
||||
, m_zoomY(0.0)
|
||||
, m_transform()
|
||||
, m_scene()
|
||||
, m_scene(new GraphicsScene())
|
||||
, m_model(model)
|
||||
, m_playhead(this)
|
||||
, m_selector()
|
||||
@@ -52,7 +52,7 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
{
|
||||
model->setGraphicsView(this);
|
||||
|
||||
setScene(&m_scene);
|
||||
setScene(m_scene);
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
setResizeAnchor(QGraphicsView::NoAnchor);
|
||||
setRenderHint(QPainter::Antialiasing, true);
|
||||
@@ -68,15 +68,23 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
m_model->setCurve(id, curve);
|
||||
};
|
||||
|
||||
connect(&m_scene, &GraphicsScene::curveChanged, itemSlot);
|
||||
connect(m_scene, &GraphicsScene::curveChanged, itemSlot);
|
||||
|
||||
auto pinSlot = [this](PropertyTreeItem *pti) { m_scene.setPinned(pti->id(), pti->pinned()); };
|
||||
auto pinSlot = [this](PropertyTreeItem *pti) { m_scene->setPinned(pti->id(), pti->pinned()); };
|
||||
connect(m_model, &CurveEditorModel::curveChanged, pinSlot);
|
||||
|
||||
applyZoom(m_zoomX, m_zoomY);
|
||||
update();
|
||||
}
|
||||
|
||||
GraphicsView::~GraphicsView()
|
||||
{
|
||||
if (m_scene) {
|
||||
delete m_scene;
|
||||
m_scene = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CurveEditorModel *GraphicsView::model() const
|
||||
{
|
||||
return m_model;
|
||||
@@ -87,48 +95,26 @@ CurveEditorStyle GraphicsView::editorStyle() const
|
||||
return m_style;
|
||||
}
|
||||
|
||||
bool GraphicsView::hasActiveItem() const
|
||||
{
|
||||
return m_scene.hasActiveItem();
|
||||
}
|
||||
|
||||
bool GraphicsView::hasActiveHandle() const
|
||||
{
|
||||
return m_scene.hasActiveHandle();
|
||||
}
|
||||
|
||||
bool GraphicsView::hasSelectedKeyframe() const
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
if (curveItem->hasSelection())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double GraphicsView::minimumTime() const
|
||||
{
|
||||
bool check = m_model->minimumTime() < m_scene.minimumTime();
|
||||
return check ? m_model->minimumTime() : m_scene.minimumTime();
|
||||
bool check = m_model->minimumTime() < m_scene->minimumTime();
|
||||
return check ? m_model->minimumTime() : m_scene->minimumTime();
|
||||
}
|
||||
|
||||
double GraphicsView::maximumTime() const
|
||||
{
|
||||
bool check = m_model->maximumTime() > m_scene.maximumTime();
|
||||
return check ? m_model->maximumTime() : m_scene.maximumTime();
|
||||
bool check = m_model->maximumTime() > m_scene->maximumTime();
|
||||
return check ? m_model->maximumTime() : m_scene->maximumTime();
|
||||
}
|
||||
|
||||
double GraphicsView::minimumValue() const
|
||||
{
|
||||
return m_scene.empty() ? -1.0 : m_scene.minimumValue();
|
||||
return m_scene->empty() ? -1.0 : m_scene->minimumValue();
|
||||
}
|
||||
|
||||
double GraphicsView::maximumValue() const
|
||||
{
|
||||
return m_scene.empty() ? 1.0 : m_scene.maximumValue();
|
||||
return m_scene->empty() ? 1.0 : m_scene->maximumValue();
|
||||
}
|
||||
|
||||
double GraphicsView::zoomX() const
|
||||
@@ -179,11 +165,9 @@ void GraphicsView::setStyle(const CurveEditorStyle &style)
|
||||
{
|
||||
m_style = style;
|
||||
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||
curveItem->setStyle(style);
|
||||
}
|
||||
const auto curves = m_scene->curves();
|
||||
for (auto *curve : curves)
|
||||
curve->setStyle(style);
|
||||
|
||||
applyZoom(m_zoomX, m_zoomY);
|
||||
viewport()->update();
|
||||
@@ -191,12 +175,8 @@ void GraphicsView::setStyle(const CurveEditorStyle &style)
|
||||
|
||||
void GraphicsView::setLocked(PropertyTreeItem *item)
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *gitem : itemList) {
|
||||
if (auto *citem = qgraphicsitem_cast<CurveItem *>(gitem))
|
||||
if (item->id() == citem->id())
|
||||
citem->setLocked(item->locked());
|
||||
}
|
||||
if (CurveItem *curve = m_scene->findCurve(item->id()))
|
||||
curve->setLocked(item->locked());
|
||||
}
|
||||
|
||||
void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
|
||||
@@ -231,9 +211,9 @@ void GraphicsView::scrollContent(double x, double y)
|
||||
|
||||
void GraphicsView::reset(const std::vector<CurveItem *> &items)
|
||||
{
|
||||
m_scene.clear();
|
||||
m_scene->reset();
|
||||
for (auto *item : items)
|
||||
m_scene.addCurveItem(item);
|
||||
m_scene->addCurveItem(item);
|
||||
|
||||
applyZoom(m_zoomX, m_zoomY);
|
||||
viewport()->update();
|
||||
@@ -241,49 +221,31 @@ void GraphicsView::reset(const std::vector<CurveItem *> &items)
|
||||
|
||||
void GraphicsView::updateSelection(const std::vector<CurveItem *> &items)
|
||||
{
|
||||
const std::vector<CurveItem *> pinnedItems = m_scene.takePinnedItems();
|
||||
auto notPinned = [pinnedItems](CurveItem *item) {
|
||||
for (auto *pinned : pinnedItems) {
|
||||
if (pinned->id() == item->id())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
m_scene.clear();
|
||||
for (auto *item : items) {
|
||||
if (notPinned(item))
|
||||
m_scene.addCurveItem(item);
|
||||
std::vector<CurveItem *> preservedItems = m_scene->takePinnedItems();
|
||||
for (auto *curve : items) {
|
||||
auto finder = [curve](CurveItem *item) { return curve->id() == item->id(); };
|
||||
auto iter = std::find_if(preservedItems.begin(), preservedItems.end(), finder);
|
||||
if (iter == preservedItems.end())
|
||||
preservedItems.push_back(curve);
|
||||
}
|
||||
|
||||
for (auto *item : pinnedItems)
|
||||
m_scene.addCurveItem(item);
|
||||
|
||||
applyZoom(m_zoomX, m_zoomY);
|
||||
viewport()->update();
|
||||
reset(preservedItems);
|
||||
}
|
||||
|
||||
void GraphicsView::setInterpolation(Keyframe::Interpolation interpol)
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *citem = qgraphicsitem_cast<CurveItem *>(item))
|
||||
if (citem->hasSelection())
|
||||
citem->setInterpolation(interpol);
|
||||
}
|
||||
const auto selectedCurves = m_scene->selectedCurves();
|
||||
for (auto *curve : selectedCurves)
|
||||
curve->setInterpolation(interpol);
|
||||
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void GraphicsView::toggleUnified()
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *citem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
if (citem->hasSelection())
|
||||
citem->toggleUnified();
|
||||
}
|
||||
}
|
||||
const auto selectedCurves = m_scene->selectedCurves();
|
||||
for (auto *curve : selectedCurves)
|
||||
curve->toggleUnified();
|
||||
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
@@ -299,7 +261,7 @@ void GraphicsView::keyPressEvent(QKeyEvent *event)
|
||||
if (shortcut == m_style.shortcuts.frameAll)
|
||||
applyZoom(0.0, 0.0);
|
||||
else if (shortcut == m_style.shortcuts.deleteKeyframe)
|
||||
deleteSelectedKeyframes();
|
||||
m_scene->deleteSelectedKeyframes();
|
||||
}
|
||||
|
||||
void GraphicsView::mousePressEvent(QMouseEvent *event)
|
||||
@@ -309,7 +271,7 @@ void GraphicsView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
Shortcut shortcut(event);
|
||||
if (shortcut == m_style.shortcuts.insertKeyframe) {
|
||||
insertKeyframe(globalToRaster(event->globalPos()).x());
|
||||
m_scene->insertKeyframe(globalToRaster(event->globalPos()).x());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,7 +287,7 @@ void GraphicsView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
|
||||
m_selector.mousePress(event, this);
|
||||
m_selector.mousePress(event, this, m_scene);
|
||||
}
|
||||
|
||||
void GraphicsView::mouseMoveEvent(QMouseEvent *event)
|
||||
@@ -335,7 +297,7 @@ void GraphicsView::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
QGraphicsView::mouseMoveEvent(event);
|
||||
|
||||
m_selector.mouseMove(event, this, m_playhead);
|
||||
m_selector.mouseMove(event, this, m_scene, m_playhead);
|
||||
}
|
||||
|
||||
void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
||||
@@ -343,7 +305,7 @@ void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
||||
QGraphicsView::mouseReleaseEvent(event);
|
||||
|
||||
m_playhead.mouseRelease(this);
|
||||
m_selector.mouseRelease(event, this);
|
||||
m_selector.mouseRelease(event, m_scene);
|
||||
this->viewport()->update();
|
||||
}
|
||||
|
||||
@@ -371,16 +333,16 @@ void GraphicsView::contextMenuEvent(QContextMenuEvent *event)
|
||||
|
||||
menu.addSeparator();
|
||||
auto insertKeyframes = [this, event]() {
|
||||
insertKeyframe(globalToRaster(event->globalPos()).x(), true);
|
||||
m_scene->insertKeyframe(globalToRaster(event->globalPos()).x(), true);
|
||||
};
|
||||
QAction *insertKeyframeAction = menu.addAction(tr("Insert Keyframe"));
|
||||
connect(insertKeyframeAction, &QAction::triggered, insertKeyframes);
|
||||
|
||||
auto deleteKeyframes = [this, event] { deleteSelectedKeyframes(); };
|
||||
auto deleteKeyframes = [this, event] { m_scene->deleteSelectedKeyframes(); };
|
||||
QAction *deleteKeyframeAction = menu.addAction(tr("Delete Selected Keyframes"));
|
||||
connect(deleteKeyframeAction, &QAction::triggered, deleteKeyframes);
|
||||
|
||||
if (!hasSelectedKeyframe())
|
||||
if (!m_scene->hasSelectedKeyframe())
|
||||
deleteKeyframeAction->setEnabled(false);
|
||||
|
||||
menu.exec(event->globalPos());
|
||||
@@ -445,7 +407,7 @@ QPointF GraphicsView::globalToRaster(const QPoint &point) const
|
||||
|
||||
void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
|
||||
{
|
||||
m_scene.doNotMoveItems(true);
|
||||
m_scene->doNotMoveItems(true);
|
||||
|
||||
QPointF pivotRaster(globalToRaster(pivot));
|
||||
|
||||
@@ -469,9 +431,9 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
|
||||
double scaleY = lerp(clamp(m_zoomY, 0.0, 1.0), -yZoomedOut, -yZoomedIn);
|
||||
|
||||
m_transform = QTransform::fromScale(scaleX, scaleY);
|
||||
m_scene.setComponentTransform(m_transform);
|
||||
m_scene->setComponentTransform(m_transform);
|
||||
|
||||
QRectF sr = m_scene.sceneRect().adjusted(
|
||||
QRectF sr = m_scene->rect().adjusted(
|
||||
-m_style.valueAxisWidth - m_style.canvasMargin,
|
||||
-m_style.timeAxisHeight - m_style.canvasMargin,
|
||||
m_style.canvasMargin,
|
||||
@@ -486,29 +448,7 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
|
||||
scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
|
||||
}
|
||||
|
||||
m_scene.doNotMoveItems(false);
|
||||
}
|
||||
|
||||
void GraphicsView::insertKeyframe(double time, bool allVisibleCurves)
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||
if (allVisibleCurves)
|
||||
curveItem->insertKeyframeByTime(std::round(time));
|
||||
else if (curveItem->isUnderMouse())
|
||||
curveItem->insertKeyframeByTime(std::round(time));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsView::deleteSelectedKeyframes()
|
||||
{
|
||||
const auto itemList = items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||
curveItem->deleteSelectedKeyframes();
|
||||
}
|
||||
m_scene->doNotMoveItems(false);
|
||||
}
|
||||
|
||||
void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
|
||||
@@ -551,7 +491,7 @@ void GraphicsView::drawExtremaX(QPainter *painter, const QRectF &rect)
|
||||
|
||||
void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
if (m_scene.empty())
|
||||
if (m_scene->empty())
|
||||
return;
|
||||
|
||||
auto drawHorizontalLine = [rect, painter](double position) {
|
||||
@@ -560,8 +500,8 @@ void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect)
|
||||
|
||||
painter->save();
|
||||
painter->setPen(Qt::blue);
|
||||
drawHorizontalLine(mapValueToY(m_scene.minimumValue()));
|
||||
drawHorizontalLine(mapValueToY(m_scene.maximumValue()));
|
||||
drawHorizontalLine(mapValueToY(m_scene->minimumValue()));
|
||||
drawHorizontalLine(mapValueToY(m_scene->maximumValue()));
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
@@ -52,16 +52,12 @@ signals:
|
||||
public:
|
||||
GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||
|
||||
~GraphicsView() override;
|
||||
|
||||
CurveEditorModel *model() const;
|
||||
|
||||
CurveEditorStyle editorStyle() const;
|
||||
|
||||
bool hasActiveItem() const;
|
||||
|
||||
bool hasActiveHandle() const;
|
||||
|
||||
bool hasSelectedKeyframe() const;
|
||||
|
||||
int mapTimeToX(double time) const;
|
||||
|
||||
int mapValueToY(double value) const;
|
||||
@@ -136,10 +132,6 @@ protected:
|
||||
private:
|
||||
void applyZoom(double x, double y, const QPoint &pivot = QPoint());
|
||||
|
||||
void insertKeyframe(double time, bool allVisibleCurves = false);
|
||||
|
||||
void deleteSelectedKeyframes();
|
||||
|
||||
void drawGrid(QPainter *painter, const QRectF &rect);
|
||||
|
||||
#if 0
|
||||
@@ -167,7 +159,7 @@ private:
|
||||
|
||||
QTransform m_transform;
|
||||
|
||||
GraphicsScene m_scene;
|
||||
GraphicsScene *m_scene;
|
||||
|
||||
CurveEditorModel *m_model;
|
||||
|
||||
|
@@ -64,6 +64,22 @@ int HandleItem::type() const
|
||||
return Type;
|
||||
}
|
||||
|
||||
bool HandleItem::keyframeSelected() const
|
||||
{
|
||||
if (auto *frame = keyframe())
|
||||
return frame->selected();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyframeItem *HandleItem::keyframe() const
|
||||
{
|
||||
if (KeyframeItem *parent = qgraphicsitem_cast<KeyframeItem *>(parentItem()))
|
||||
return parent;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HandleItem::Slot HandleItem::slot() const
|
||||
{
|
||||
return m_slot;
|
||||
@@ -77,7 +93,7 @@ QRectF HandleItem::boundingRect() const
|
||||
|
||||
bool HandleItem::contains(const QPointF &point) const
|
||||
{
|
||||
if (KeyframeItem *parent = qgraphicsitem_cast<KeyframeItem *>(parentItem())) {
|
||||
if (KeyframeItem *parent = keyframe()) {
|
||||
HandleGeometry geom(pos(), m_style);
|
||||
geom.handle.moveCenter(parent->pos() + pos());
|
||||
return geom.handle.contains(point);
|
||||
@@ -130,7 +146,7 @@ void HandleItem::setStyle(const CurveEditorStyle &style)
|
||||
QVariant HandleItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
if (change == ItemPositionChange) {
|
||||
if (qgraphicsitem_cast<KeyframeItem *>(parentItem())) {
|
||||
if (keyframe()) {
|
||||
QPointF pos = value.toPointF();
|
||||
if (m_slot == HandleItem::Slot::Left) {
|
||||
if (pos.x() > 0.0)
|
||||
|
@@ -30,6 +30,8 @@
|
||||
|
||||
namespace DesignTools {
|
||||
|
||||
class KeyframeItem;
|
||||
|
||||
class HandleItem : public SelectableItem
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -53,6 +55,10 @@ public:
|
||||
|
||||
void underMouseCallback() override;
|
||||
|
||||
bool keyframeSelected() const;
|
||||
|
||||
KeyframeItem *keyframe() const;
|
||||
|
||||
Slot slot() const;
|
||||
|
||||
void setStyle(const CurveEditorStyle &style);
|
||||
|
@@ -116,6 +116,27 @@ bool KeyframeItem::hasRightHandle() const
|
||||
return m_frame.hasRightHandle();
|
||||
}
|
||||
|
||||
bool KeyframeItem::hasActiveHandle() const
|
||||
{
|
||||
if (m_left && m_left->activated())
|
||||
return true;
|
||||
|
||||
if (m_right && m_right->activated())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
HandleItem *KeyframeItem::leftHandle() const
|
||||
{
|
||||
return m_left;
|
||||
}
|
||||
|
||||
HandleItem *KeyframeItem::rightHandle() const
|
||||
{
|
||||
return m_right;
|
||||
}
|
||||
|
||||
QTransform KeyframeItem::transform() const
|
||||
{
|
||||
return m_transform;
|
||||
|
@@ -72,6 +72,12 @@ public:
|
||||
|
||||
bool hasRightHandle() const;
|
||||
|
||||
bool hasActiveHandle() const;
|
||||
|
||||
HandleItem *leftHandle() const;
|
||||
|
||||
HandleItem *rightHandle() const;
|
||||
|
||||
QTransform transform() const;
|
||||
|
||||
void setHandleVisibility(bool visible);
|
||||
|
@@ -83,7 +83,6 @@ SelectableItem::SelectableItem(QGraphicsItem *parent)
|
||||
: CurveEditorItem(parent)
|
||||
, m_active(false)
|
||||
, m_selected(false)
|
||||
, m_locked(false)
|
||||
, m_preSelected(SelectionMode::Undefined)
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
@@ -139,7 +138,7 @@ void SelectableItem::setSelected(bool selected)
|
||||
|
||||
void SelectableItem::setPreselected(SelectionMode mode)
|
||||
{
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
m_preSelected = mode;
|
||||
@@ -158,7 +157,7 @@ void SelectableItem::selectionCallback() {}
|
||||
|
||||
void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
m_active = true;
|
||||
@@ -168,7 +167,7 @@ void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (type() == KeyframeItem::Type && !selected())
|
||||
@@ -179,7 +178,7 @@ void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
m_active = false;
|
||||
|
@@ -99,8 +99,6 @@ private:
|
||||
|
||||
bool m_selected;
|
||||
|
||||
bool m_locked;
|
||||
|
||||
SelectionMode m_preSelected;
|
||||
};
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "selector.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "graphicsview.h"
|
||||
#include "keyframeitem.h"
|
||||
#include "playhead.h"
|
||||
@@ -55,29 +56,40 @@ void Selector::paint(QPainter *painter)
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void Selector::mousePress(QMouseEvent *event, GraphicsView *view)
|
||||
void Selector::mousePress(QMouseEvent *event, GraphicsView *view, GraphicsScene *scene)
|
||||
{
|
||||
m_shortcut = Shortcut(event);
|
||||
|
||||
if (view->hasActiveHandle())
|
||||
return;
|
||||
QPointF click = view->globalToScene(event->globalPos());
|
||||
|
||||
m_mouseInit = event->globalPos();
|
||||
m_mouseCurr = event->globalPos();
|
||||
if (SelectableItem *sitem = scene->intersect(click)) {
|
||||
KeyframeItem *kitem = qobject_cast<KeyframeItem *>(sitem);
|
||||
if (HandleItem *hitem = qobject_cast<HandleItem *>(sitem))
|
||||
kitem = hitem->keyframe();
|
||||
|
||||
QPointF click = view->globalToScene(m_mouseInit);
|
||||
if (!kitem->selected()) {
|
||||
if (select(SelectionTool::Undefined, click, scene))
|
||||
applyPreSelection(scene);
|
||||
}
|
||||
} else {
|
||||
if (select(SelectionTool::Undefined, click, scene))
|
||||
applyPreSelection(scene);
|
||||
|
||||
if (!isOverSelectedKeyframe(click, view))
|
||||
if (select(SelectionTool::Undefined, click, view))
|
||||
applyPreSelection(view);
|
||||
// Init selection tools.
|
||||
m_mouseInit = event->globalPos();
|
||||
m_mouseCurr = event->globalPos();
|
||||
|
||||
m_lasso = QPainterPath(click);
|
||||
m_lasso.closeSubpath();
|
||||
m_lasso = QPainterPath(click);
|
||||
m_lasso.closeSubpath();
|
||||
|
||||
m_rect = QRectF(click, click);
|
||||
m_rect = QRectF(click, click);
|
||||
}
|
||||
}
|
||||
|
||||
void Selector::mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playhead)
|
||||
void Selector::mouseMove(QMouseEvent *event,
|
||||
GraphicsView *view,
|
||||
GraphicsScene *scene,
|
||||
Playhead &playhead)
|
||||
{
|
||||
if (m_mouseInit.isNull())
|
||||
return;
|
||||
@@ -89,10 +101,10 @@ void Selector::mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playh
|
||||
if (m_shortcut == m_shortcuts.newSelection || m_shortcut == m_shortcuts.addToSelection
|
||||
|| m_shortcut == m_shortcuts.removeFromSelection
|
||||
|| m_shortcut == m_shortcuts.toggleSelection) {
|
||||
if (view->hasActiveItem())
|
||||
if (scene->hasActiveItem())
|
||||
return;
|
||||
|
||||
select(m_tool, view->globalToScene(event->globalPos()), view);
|
||||
select(m_tool, view->globalToScene(event->globalPos()), scene);
|
||||
|
||||
event->accept();
|
||||
view->viewport()->update();
|
||||
@@ -111,11 +123,11 @@ void Selector::mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playh
|
||||
}
|
||||
}
|
||||
|
||||
void Selector::mouseRelease(QMouseEvent *event, GraphicsView *view)
|
||||
void Selector::mouseRelease(QMouseEvent *event, GraphicsScene *scene)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
applyPreSelection(view);
|
||||
applyPreSelection(scene);
|
||||
|
||||
m_shortcut = Shortcut();
|
||||
m_mouseInit = QPoint();
|
||||
@@ -124,50 +136,73 @@ void Selector::mouseRelease(QMouseEvent *event, GraphicsView *view)
|
||||
m_rect = QRectF();
|
||||
}
|
||||
|
||||
bool Selector::isOverSelectedKeyframe(const QPointF &pos, GraphicsView *view)
|
||||
bool Selector::isOverMovableItem(const QPointF &pos, GraphicsScene *scene)
|
||||
{
|
||||
const auto itemList = view->items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
QRectF itemRect = frame->mapRectToScene(frame->boundingRect());
|
||||
if (itemRect.contains(pos))
|
||||
return frame->selected();
|
||||
auto intersect = [pos](QGraphicsObject *item) {
|
||||
return item->mapRectToScene(item->boundingRect()).contains(pos);
|
||||
};
|
||||
|
||||
const auto frames = scene->keyframes();
|
||||
for (auto *frame : frames) {
|
||||
if (intersect(frame))
|
||||
return true;
|
||||
|
||||
if (auto *leftHandle = frame->leftHandle()) {
|
||||
if (intersect(leftHandle))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto *rightHandle = frame->rightHandle()) {
|
||||
if (intersect(rightHandle))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Selector::select(const SelectionTool &tool, const QPointF &pos, GraphicsView *view)
|
||||
bool Selector::isOverSelectedKeyframe(const QPointF &pos, GraphicsScene *scene)
|
||||
{
|
||||
auto selectWidthTool = [this, tool](SelectionMode mode, const QPointF &pos, GraphicsView *view) {
|
||||
const auto frames = scene->selectedKeyframes();
|
||||
for (auto *frame : frames) {
|
||||
QRectF frameRect = frame->mapRectToScene(frame->boundingRect());
|
||||
if (frameRect.contains(pos))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Selector::select(const SelectionTool &tool, const QPointF &pos, GraphicsScene *scene)
|
||||
{
|
||||
auto selectWidthTool = [this,
|
||||
tool](SelectionMode mode, const QPointF &pos, GraphicsScene *scene) {
|
||||
switch (tool) {
|
||||
case SelectionTool::Lasso:
|
||||
return lassoSelection(mode, pos, view);
|
||||
return lassoSelection(mode, pos, scene);
|
||||
case SelectionTool::Rectangle:
|
||||
return rectangleSelection(mode, pos, view);
|
||||
return rectangleSelection(mode, pos, scene);
|
||||
default:
|
||||
return pressSelection(mode, pos, view);
|
||||
return pressSelection(mode, pos, scene);
|
||||
}
|
||||
};
|
||||
|
||||
if (m_shortcut == m_shortcuts.newSelection) {
|
||||
clearSelection(view);
|
||||
return selectWidthTool(SelectionMode::New, pos, view);
|
||||
clearSelection(scene);
|
||||
return selectWidthTool(SelectionMode::New, pos, scene);
|
||||
} else if (m_shortcut == m_shortcuts.addToSelection) {
|
||||
return selectWidthTool(SelectionMode::Add, pos, view);
|
||||
return selectWidthTool(SelectionMode::Add, pos, scene);
|
||||
} else if (m_shortcut == m_shortcuts.removeFromSelection) {
|
||||
return selectWidthTool(SelectionMode::Remove, pos, view);
|
||||
return selectWidthTool(SelectionMode::Remove, pos, scene);
|
||||
} else if (m_shortcut == m_shortcuts.toggleSelection) {
|
||||
return selectWidthTool(SelectionMode::Toggle, pos, view);
|
||||
return selectWidthTool(SelectionMode::Toggle, pos, scene);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
|
||||
bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
|
||||
{
|
||||
bool out = false;
|
||||
const auto itemList = view->items();
|
||||
const auto itemList = scene->items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
QRectF itemRect = frame->mapRectToScene(frame->boundingRect());
|
||||
@@ -176,15 +211,25 @@ bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsVi
|
||||
out = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *handle = qgraphicsitem_cast<HandleItem *>(item)) {
|
||||
QRectF itemRect = handle->mapRectToScene(handle->boundingRect());
|
||||
if (itemRect.contains(pos)) {
|
||||
if (auto *frame = handle->keyframe()) {
|
||||
frame->setPreselected(mode);
|
||||
out = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
|
||||
bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
|
||||
{
|
||||
bool out = false;
|
||||
m_rect.setBottomRight(pos);
|
||||
const auto itemList = view->items();
|
||||
const auto itemList = scene->items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
if (m_rect.contains(keyframeItem->pos())) {
|
||||
@@ -198,11 +243,11 @@ bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, Graphi
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
|
||||
bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
|
||||
{
|
||||
bool out = false;
|
||||
m_lasso.lineTo(pos);
|
||||
const auto itemList = view->items();
|
||||
const auto itemList = scene->items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
if (m_lasso.contains(keyframeItem->pos())) {
|
||||
@@ -216,20 +261,22 @@ bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsVi
|
||||
return out;
|
||||
}
|
||||
|
||||
void Selector::clearSelection(GraphicsView *view)
|
||||
void Selector::clearSelection(GraphicsScene *scene)
|
||||
{
|
||||
const auto itemList = view->items();
|
||||
const auto itemList = scene->items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||
frameItem->setPreselected(SelectionMode::Clear);
|
||||
frameItem->applyPreselection();
|
||||
frameItem->setActivated(false, HandleItem::Slot::Left);
|
||||
frameItem->setActivated(false, HandleItem::Slot::Right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Selector::applyPreSelection(GraphicsView *view)
|
||||
void Selector::applyPreSelection(GraphicsScene *scene)
|
||||
{
|
||||
const auto itemList = view->items();
|
||||
const auto itemList = scene->items();
|
||||
for (auto *item : itemList) {
|
||||
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item))
|
||||
keyframeItem->applyPreselection();
|
||||
|
@@ -31,6 +31,7 @@
|
||||
namespace DesignTools {
|
||||
|
||||
class GraphicsView;
|
||||
class GraphicsScene;
|
||||
class Playhead;
|
||||
|
||||
enum class SelectionTool { Undefined, Lasso, Rectangle };
|
||||
@@ -42,26 +43,28 @@ public:
|
||||
|
||||
void paint(QPainter *painter);
|
||||
|
||||
void mousePress(QMouseEvent *event, GraphicsView *view);
|
||||
void mousePress(QMouseEvent *event, GraphicsView *view, GraphicsScene *scene);
|
||||
|
||||
void mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playhead);
|
||||
void mouseMove(QMouseEvent *event, GraphicsView *view, GraphicsScene *scene, Playhead &playhead);
|
||||
|
||||
void mouseRelease(QMouseEvent *event, GraphicsView *view);
|
||||
void mouseRelease(QMouseEvent *event, GraphicsScene *scene);
|
||||
|
||||
private:
|
||||
bool isOverSelectedKeyframe(const QPointF &pos, GraphicsView *view);
|
||||
bool isOverSelectedKeyframe(const QPointF &pos, GraphicsScene *scene);
|
||||
|
||||
bool select(const SelectionTool &tool, const QPointF &pos, GraphicsView *view);
|
||||
bool isOverMovableItem(const QPointF &pos, GraphicsScene *scene);
|
||||
|
||||
bool pressSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
|
||||
bool select(const SelectionTool &tool, const QPointF &pos, GraphicsScene *scene);
|
||||
|
||||
bool rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
|
||||
bool pressSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
|
||||
|
||||
bool lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
|
||||
bool rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
|
||||
|
||||
void clearSelection(GraphicsView *view);
|
||||
bool lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
|
||||
|
||||
void applyPreSelection(GraphicsView *view);
|
||||
void clearSelection(GraphicsScene *scene);
|
||||
|
||||
void applyPreSelection(GraphicsScene *scene);
|
||||
|
||||
Shortcuts m_shortcuts;
|
||||
|
||||
|
@@ -50,7 +50,7 @@ QRectF bbox(const QRectF &rect, const QTransform &transform);
|
||||
QPalette singleColorPalette(const QColor &color);
|
||||
|
||||
template<typename T>
|
||||
inline void freeClear(std::vector<T *> &vec)
|
||||
inline void freeClear(T &vec)
|
||||
{
|
||||
for (auto *&el : vec)
|
||||
delete el;
|
||||
|
Reference in New Issue
Block a user