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:
Knud Dollereder
2020-04-06 11:22:30 +02:00
parent 93e788fd19
commit 7e76a76402
16 changed files with 520 additions and 306 deletions

View File

@@ -73,6 +73,8 @@ struct CurveItemStyleOption
QColor color = QColor(0, 200, 0); QColor color = QColor(0, 200, 0);
QColor selectionColor = QColor(200, 200, 200); QColor selectionColor = QColor(200, 200, 200);
QColor easingCurveColor = QColor(200, 0, 200); QColor easingCurveColor = QColor(200, 0, 200);
QColor lockedColor = QColor(50, 50, 50);
QColor hoverColor = QColor(200, 0, 200);
}; };
struct PlayheadStyleOption struct PlayheadStyleOption

View File

@@ -118,10 +118,10 @@ void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidg
pen.setColor(m_style.easingCurveColor); pen.setColor(m_style.easingCurveColor);
} else { } else {
if (locked()) if (locked())
pen.setColor(Qt::black); pen.setColor(m_style.lockedColor);
else if (isUnderMouse()) else if (isUnderMouse())
pen.setColor(Qt::red); pen.setColor(m_style.hoverColor);
else if (hasSelection()) else if (hasSelectedKeyframe())
pen.setColor(m_style.selectionColor); pen.setColor(m_style.selectionColor);
else else
pen.setColor(m_style.color); pen.setColor(m_style.color);
@@ -146,7 +146,25 @@ bool CurveItem::isDirty() const
return m_itemDirty; 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) { for (auto *frame : m_keyframes) {
if (frame->selected()) if (frame->selected())
@@ -203,7 +221,7 @@ std::vector<AnimationCurve> CurveItem::curves() const
std::vector<Keyframe> tmp; 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]; KeyframeItem *item = m_keyframes[i];
Keyframe current = item->keyframe(); Keyframe current = item->keyframe();
@@ -233,6 +251,33 @@ std::vector<AnimationCurve> CurveItem::curves() const
return out; 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() void CurveItem::restore()
{ {
if (m_keyframes.empty()) if (m_keyframes.empty())
@@ -248,7 +293,7 @@ void CurveItem::restore()
if (prevItem->hasLeftHandle()) if (prevItem->hasLeftHandle())
prevItem->setLeftHandle(QPointF()); 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]; KeyframeItem *currItem = m_keyframes[i];
bool left = prevItem->hasRightHandle(); bool left = prevItem->hasRightHandle();
@@ -328,7 +373,7 @@ void CurveItem::setInterpolation(Keyframe::Interpolation interpolation)
return; return;
KeyframeItem *prevItem = m_keyframes[0]; 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]; KeyframeItem *currItem = m_keyframes[i];
if (currItem->selected()) { if (currItem->selected()) {
Keyframe prev = prevItem->keyframe(); Keyframe prev = prevItem->keyframe();

View File

@@ -73,7 +73,11 @@ public:
bool isDirty() const; bool isDirty() const;
bool hasSelection() const; bool hasActiveKeyframe() const;
bool hasActiveHandle() const;
bool hasSelectedKeyframe() const;
unsigned int id() const; unsigned int id() const;
@@ -87,6 +91,12 @@ public:
std::vector<AnimationCurve> curves() const; std::vector<AnimationCurve> curves() const;
QVector<KeyframeItem *> keyframes() const;
QVector<KeyframeItem *> selectedKeyframes() const;
QVector<HandleItem *> handles() const;
void restore(); void restore();
void setDirty(bool dirty); void setDirty(bool dirty);
@@ -126,7 +136,7 @@ private:
QTransform m_transform; QTransform m_transform;
std::vector<KeyframeItem *> m_keyframes; QVector<KeyframeItem *> m_keyframes;
bool m_itemDirty; bool m_itemDirty;
}; };

View File

@@ -31,20 +31,60 @@
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <cmath>
namespace DesignTools { namespace DesignTools {
GraphicsScene::GraphicsScene(QObject *parent) GraphicsScene::GraphicsScene(QObject *parent)
: QGraphicsScene(parent) : QGraphicsScene(parent)
, m_curves()
, m_dirty(true) , m_dirty(true)
, m_limits() , m_limits()
, m_doNotMoveItems(false) , m_doNotMoveItems(false)
{} {}
GraphicsScene::~GraphicsScene()
{
m_curves.clear();
}
bool GraphicsScene::empty() const bool GraphicsScene::empty() const
{ {
return items().empty(); 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 double GraphicsScene::minimumTime() const
{ {
return limits().left(); return limits().left();
@@ -65,6 +105,103 @@ double GraphicsScene::maximumValue() const
return limits().top(); 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) void GraphicsScene::doNotMoveItems(bool val)
{ {
m_doNotMoveItems = val; m_doNotMoveItems = val;
@@ -76,16 +213,15 @@ void GraphicsScene::addCurveItem(CurveItem *item)
item->setDirty(false); item->setDirty(false);
item->connect(this); item->connect(this);
addItem(item); addItem(item);
m_curves.push_back(item);
} }
void GraphicsScene::setComponentTransform(const QTransform &transform) void GraphicsScene::setComponentTransform(const QTransform &transform)
{ {
QRectF bounds; QRectF bounds;
const auto itemList = items();
for (auto *item : itemList) { for (auto *curve : m_curves)
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) bounds = bounds.united(curve->setComponentTransform(transform));
bounds = bounds.united(curveItem->setComponentTransform(transform));
}
if (bounds.isNull()) { if (bounds.isNull()) {
if (GraphicsView *gview = graphicsView()) if (GraphicsView *gview = graphicsView())
@@ -98,29 +234,20 @@ void GraphicsScene::setComponentTransform(const QTransform &transform)
void GraphicsScene::keyframeMoved(KeyframeItem *movedItem, const QPointF &direction) void GraphicsScene::keyframeMoved(KeyframeItem *movedItem, const QPointF &direction)
{ {
const auto itemList = items(); for (auto *curve : m_curves) {
for (auto *item : itemList) { for (auto *keyframe : curve->keyframes()) {
if (item == movedItem) if (keyframe != movedItem && keyframe->selected())
continue; keyframe->moveKeyframe(direction);
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
if (frameItem->selected())
frameItem->moveKeyframe(direction);
} }
} }
} }
void GraphicsScene::handleUnderMouse(HandleItem *handle) void GraphicsScene::handleUnderMouse(HandleItem *handle)
{ {
const auto itemList = items(); for (auto *curve : m_curves) {
for (auto *item : itemList) { for (auto *keyframe : curve->keyframes()) {
if (item == handle) if (keyframe->selected())
continue; keyframe->setActivated(handle->isUnderMouse(), handle->slot());
if (auto *keyItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
if (keyItem->selected()) {
keyItem->setActivated(handle->isUnderMouse(), handle->slot());
}
} }
} }
} }
@@ -142,16 +269,13 @@ void GraphicsScene::handleMoved(KeyframeItem *frame,
} }
}; };
const auto itemList = items(); for (auto *curve : m_curves) {
for (auto *item : itemList) { for (auto *keyframe : curve->keyframes()) {
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) { if (keyframe == frame)
if (item == frame) { moveUnified(keyframe);
moveUnified(frameItem); else if (keyframe->selected()) {
continue; keyframe->moveHandle(handle, angle, deltaLength);
} moveUnified(keyframe);
if (frameItem->selected()) {
frameItem->moveHandle(handle, angle, deltaLength);
moveUnified(frameItem);
} }
} }
} }
@@ -159,27 +283,24 @@ void GraphicsScene::handleMoved(KeyframeItem *frame,
void GraphicsScene::setPinned(uint id, bool pinned) void GraphicsScene::setPinned(uint id, bool pinned)
{ {
const auto itemList = items(); if (CurveItem *curve = findCurve(id))
for (auto *item : itemList) { curve->setPinned(pinned);
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
if (curveItem->id() == id)
curveItem->setPinned(pinned);
}
}
} }
std::vector<CurveItem *> GraphicsScene::takePinnedItems() std::vector<CurveItem *> GraphicsScene::takePinnedItems()
{ {
std::vector<CurveItem *> out; std::vector<CurveItem *> out;
const auto itemList = items(); for (auto *curve : m_curves) {
for (auto *item : itemList) { if (curve->pinned())
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) { out.push_back(curve);
if (curveItem->pinned()) {
removeItem(curveItem);
out.push_back(curveItem);
}
}
} }
for (auto *curve : out) {
curve->disconnect(this);
m_curves.removeOne(curve);
removeItem(curve);
}
return out; return out;
} }
@@ -187,12 +308,24 @@ void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{ {
QGraphicsScene::mouseMoveEvent(mouseEvent); QGraphicsScene::mouseMoveEvent(mouseEvent);
const auto itemList = items(); QPointF mouse = mouseEvent->scenePos();
for (auto *item : itemList) { bool hasHandle = false;
if (auto *handleItem = qgraphicsitem_cast<HandleItem *>(item))
handleItem->setIsUnderMouse(handleItem->contains(mouseEvent->scenePos())); for (auto *curve : m_curves) {
else if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) for (auto *handle : curve->handles()) {
curveItem->setIsUnderMouse(curveItem->contains(mouseEvent->scenePos())); 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); QGraphicsScene::mouseReleaseEvent(mouseEvent);
const auto itemList = items(); for (auto *curve : m_curves) {
for (auto *item : itemList) { // CurveItems might become invalid after a keyframe-drag operation.
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) { curve->restore();
// CurveItems might become invalid after a keyframe-drag operation. if (curve->isDirty()) {
curveItem->restore(); m_dirty = true;
curve->setDirty(false);
if (curveItem->isDirty()) { emit curveChanged(curve->id(), curve->curve());
m_dirty = true;
curveItem->setDirty(false);
emit curveChanged(curveItem->id(), curveItem->curve());
}
} }
} }
@@ -218,40 +347,11 @@ void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
graphicsView()->setZoomY(0.0); 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 GraphicsView *GraphicsScene::graphicsView() const
{ {
const QList<QGraphicsView *> viewList = views(); const QList<QGraphicsView *> viewList = views();
for (auto &&view : viewList) { if (viewList.size() == 1) {
if (GraphicsView *gview = qobject_cast<GraphicsView *>(view)) if (GraphicsView *gview = qobject_cast<GraphicsView *>(viewList.at(0)))
return gview; return gview;
} }
return nullptr; return nullptr;
@@ -263,22 +363,19 @@ QRectF GraphicsScene::limits() const
QPointF min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max()); QPointF min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
QPointF max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest()); QPointF max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
const auto itemList = items(); for (auto *curveItem : m_curves) {
for (auto *item : itemList) { auto curve = curveItem->resolvedCurve();
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) { if (min.x() > curve.minimumTime())
auto curve = curveItem->resolvedCurve(); min.rx() = curve.minimumTime();
if (min.x() > curve.minimumTime())
min.rx() = curve.minimumTime();
if (min.y() > curve.minimumValue()) if (min.y() > curve.minimumValue())
min.ry() = curve.minimumValue(); min.ry() = curve.minimumValue();
if (max.x() < curve.maximumTime()) if (max.x() < curve.maximumTime())
max.rx() = curve.maximumTime(); max.rx() = curve.maximumTime();
if (max.y() < curve.maximumValue()) if (max.y() < curve.maximumValue())
max.ry() = curve.maximumValue(); max.ry() = curve.maximumValue();
}
} }
m_limits = QRectF(QPointF(min.x(), max.y()), QPointF(max.x(), min.y())); m_limits = QRectF(QPointF(min.x(), max.y()), QPointF(max.x(), min.y()));

View File

@@ -45,6 +45,8 @@ signals:
public: public:
GraphicsScene(QObject *parent = nullptr); GraphicsScene(QObject *parent = nullptr);
~GraphicsScene() override;
bool empty() const; bool empty() const;
bool hasActiveKeyframe() const; bool hasActiveKeyframe() const;
@@ -53,6 +55,8 @@ public:
bool hasActiveItem() const; bool hasActiveItem() const;
bool hasSelectedKeyframe() const;
double minimumTime() const; double minimumTime() const;
double maximumTime() const; double maximumTime() const;
@@ -61,6 +65,28 @@ public:
double maximumValue() const; 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 doNotMoveItems(bool tmp);
void addCurveItem(CurveItem *item); void addCurveItem(CurveItem *item);
@@ -85,10 +111,16 @@ protected:
private: private:
using QGraphicsScene::addItem; using QGraphicsScene::addItem;
using QGraphicsScene::clear;
using QGraphicsScene::removeItem;
GraphicsView *graphicsView() const; GraphicsView *graphicsView() const;
QRectF limits() const; QRectF limits() const;
QVector<CurveItem *> m_curves;
mutable bool m_dirty; mutable bool m_dirty;
mutable QRectF m_limits; mutable QRectF m_limits;

View File

@@ -43,7 +43,7 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
, m_zoomX(0.0) , m_zoomX(0.0)
, m_zoomY(0.0) , m_zoomY(0.0)
, m_transform() , m_transform()
, m_scene() , m_scene(new GraphicsScene())
, m_model(model) , m_model(model)
, m_playhead(this) , m_playhead(this)
, m_selector() , m_selector()
@@ -52,7 +52,7 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
{ {
model->setGraphicsView(this); model->setGraphicsView(this);
setScene(&m_scene); setScene(m_scene);
setAlignment(Qt::AlignLeft | Qt::AlignVCenter); setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
setResizeAnchor(QGraphicsView::NoAnchor); setResizeAnchor(QGraphicsView::NoAnchor);
setRenderHint(QPainter::Antialiasing, true); setRenderHint(QPainter::Antialiasing, true);
@@ -68,15 +68,23 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
m_model->setCurve(id, curve); 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); connect(m_model, &CurveEditorModel::curveChanged, pinSlot);
applyZoom(m_zoomX, m_zoomY); applyZoom(m_zoomX, m_zoomY);
update(); update();
} }
GraphicsView::~GraphicsView()
{
if (m_scene) {
delete m_scene;
m_scene = nullptr;
}
}
CurveEditorModel *GraphicsView::model() const CurveEditorModel *GraphicsView::model() const
{ {
return m_model; return m_model;
@@ -87,48 +95,26 @@ CurveEditorStyle GraphicsView::editorStyle() const
return m_style; 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 double GraphicsView::minimumTime() const
{ {
bool check = m_model->minimumTime() < m_scene.minimumTime(); bool check = m_model->minimumTime() < m_scene->minimumTime();
return check ? m_model->minimumTime() : m_scene.minimumTime(); return check ? m_model->minimumTime() : m_scene->minimumTime();
} }
double GraphicsView::maximumTime() const double GraphicsView::maximumTime() const
{ {
bool check = m_model->maximumTime() > m_scene.maximumTime(); bool check = m_model->maximumTime() > m_scene->maximumTime();
return check ? m_model->maximumTime() : m_scene.maximumTime(); return check ? m_model->maximumTime() : m_scene->maximumTime();
} }
double GraphicsView::minimumValue() const 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 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 double GraphicsView::zoomX() const
@@ -179,11 +165,9 @@ void GraphicsView::setStyle(const CurveEditorStyle &style)
{ {
m_style = style; m_style = style;
const auto itemList = items(); const auto curves = m_scene->curves();
for (auto *item : itemList) { for (auto *curve : curves)
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) curve->setStyle(style);
curveItem->setStyle(style);
}
applyZoom(m_zoomX, m_zoomY); applyZoom(m_zoomX, m_zoomY);
viewport()->update(); viewport()->update();
@@ -191,12 +175,8 @@ void GraphicsView::setStyle(const CurveEditorStyle &style)
void GraphicsView::setLocked(PropertyTreeItem *item) void GraphicsView::setLocked(PropertyTreeItem *item)
{ {
const auto itemList = items(); if (CurveItem *curve = m_scene->findCurve(item->id()))
for (auto *gitem : itemList) { curve->setLocked(item->locked());
if (auto *citem = qgraphicsitem_cast<CurveItem *>(gitem))
if (item->id() == citem->id())
citem->setLocked(item->locked());
}
} }
void GraphicsView::setZoomX(double zoom, const QPoint &pivot) 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) void GraphicsView::reset(const std::vector<CurveItem *> &items)
{ {
m_scene.clear(); m_scene->reset();
for (auto *item : items) for (auto *item : items)
m_scene.addCurveItem(item); m_scene->addCurveItem(item);
applyZoom(m_zoomX, m_zoomY); applyZoom(m_zoomX, m_zoomY);
viewport()->update(); viewport()->update();
@@ -241,49 +221,31 @@ void GraphicsView::reset(const std::vector<CurveItem *> &items)
void GraphicsView::updateSelection(const std::vector<CurveItem *> &items) void GraphicsView::updateSelection(const std::vector<CurveItem *> &items)
{ {
const std::vector<CurveItem *> pinnedItems = m_scene.takePinnedItems(); std::vector<CurveItem *> preservedItems = m_scene->takePinnedItems();
auto notPinned = [pinnedItems](CurveItem *item) { for (auto *curve : items) {
for (auto *pinned : pinnedItems) { auto finder = [curve](CurveItem *item) { return curve->id() == item->id(); };
if (pinned->id() == item->id()) auto iter = std::find_if(preservedItems.begin(), preservedItems.end(), finder);
return false; if (iter == preservedItems.end())
} preservedItems.push_back(curve);
return true;
};
m_scene.clear();
for (auto *item : items) {
if (notPinned(item))
m_scene.addCurveItem(item);
} }
reset(preservedItems);
for (auto *item : pinnedItems)
m_scene.addCurveItem(item);
applyZoom(m_zoomX, m_zoomY);
viewport()->update();
} }
void GraphicsView::setInterpolation(Keyframe::Interpolation interpol) void GraphicsView::setInterpolation(Keyframe::Interpolation interpol)
{ {
const auto itemList = items(); const auto selectedCurves = m_scene->selectedCurves();
for (auto *item : itemList) { for (auto *curve : selectedCurves)
if (auto *citem = qgraphicsitem_cast<CurveItem *>(item)) curve->setInterpolation(interpol);
if (citem->hasSelection())
citem->setInterpolation(interpol);
}
viewport()->update(); viewport()->update();
} }
void GraphicsView::toggleUnified() void GraphicsView::toggleUnified()
{ {
const auto itemList = items(); const auto selectedCurves = m_scene->selectedCurves();
for (auto *item : itemList) { for (auto *curve : selectedCurves)
if (auto *citem = qgraphicsitem_cast<CurveItem *>(item)) { curve->toggleUnified();
if (citem->hasSelection())
citem->toggleUnified();
}
}
viewport()->update(); viewport()->update();
} }
@@ -299,7 +261,7 @@ void GraphicsView::keyPressEvent(QKeyEvent *event)
if (shortcut == m_style.shortcuts.frameAll) if (shortcut == m_style.shortcuts.frameAll)
applyZoom(0.0, 0.0); applyZoom(0.0, 0.0);
else if (shortcut == m_style.shortcuts.deleteKeyframe) else if (shortcut == m_style.shortcuts.deleteKeyframe)
deleteSelectedKeyframes(); m_scene->deleteSelectedKeyframes();
} }
void GraphicsView::mousePressEvent(QMouseEvent *event) void GraphicsView::mousePressEvent(QMouseEvent *event)
@@ -309,7 +271,7 @@ void GraphicsView::mousePressEvent(QMouseEvent *event)
Shortcut shortcut(event); Shortcut shortcut(event);
if (shortcut == m_style.shortcuts.insertKeyframe) { if (shortcut == m_style.shortcuts.insertKeyframe) {
insertKeyframe(globalToRaster(event->globalPos()).x()); m_scene->insertKeyframe(globalToRaster(event->globalPos()).x());
return; return;
} }
@@ -325,7 +287,7 @@ void GraphicsView::mousePressEvent(QMouseEvent *event)
QGraphicsView::mousePressEvent(event); QGraphicsView::mousePressEvent(event);
m_selector.mousePress(event, this); m_selector.mousePress(event, this, m_scene);
} }
void GraphicsView::mouseMoveEvent(QMouseEvent *event) void GraphicsView::mouseMoveEvent(QMouseEvent *event)
@@ -335,7 +297,7 @@ void GraphicsView::mouseMoveEvent(QMouseEvent *event)
QGraphicsView::mouseMoveEvent(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) void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
@@ -343,7 +305,7 @@ void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
QGraphicsView::mouseReleaseEvent(event); QGraphicsView::mouseReleaseEvent(event);
m_playhead.mouseRelease(this); m_playhead.mouseRelease(this);
m_selector.mouseRelease(event, this); m_selector.mouseRelease(event, m_scene);
this->viewport()->update(); this->viewport()->update();
} }
@@ -371,16 +333,16 @@ void GraphicsView::contextMenuEvent(QContextMenuEvent *event)
menu.addSeparator(); menu.addSeparator();
auto insertKeyframes = [this, event]() { 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")); QAction *insertKeyframeAction = menu.addAction(tr("Insert Keyframe"));
connect(insertKeyframeAction, &QAction::triggered, insertKeyframes); 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")); QAction *deleteKeyframeAction = menu.addAction(tr("Delete Selected Keyframes"));
connect(deleteKeyframeAction, &QAction::triggered, deleteKeyframes); connect(deleteKeyframeAction, &QAction::triggered, deleteKeyframes);
if (!hasSelectedKeyframe()) if (!m_scene->hasSelectedKeyframe())
deleteKeyframeAction->setEnabled(false); deleteKeyframeAction->setEnabled(false);
menu.exec(event->globalPos()); 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) void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
{ {
m_scene.doNotMoveItems(true); m_scene->doNotMoveItems(true);
QPointF pivotRaster(globalToRaster(pivot)); 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); double scaleY = lerp(clamp(m_zoomY, 0.0, 1.0), -yZoomedOut, -yZoomedIn);
m_transform = QTransform::fromScale(scaleX, scaleY); 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.valueAxisWidth - m_style.canvasMargin,
-m_style.timeAxisHeight - m_style.canvasMargin, -m_style.timeAxisHeight - m_style.canvasMargin,
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())); scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
} }
m_scene.doNotMoveItems(false); 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();
}
} }
void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect) 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) void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect)
{ {
if (m_scene.empty()) if (m_scene->empty())
return; return;
auto drawHorizontalLine = [rect, painter](double position) { auto drawHorizontalLine = [rect, painter](double position) {
@@ -560,8 +500,8 @@ void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect)
painter->save(); painter->save();
painter->setPen(Qt::blue); painter->setPen(Qt::blue);
drawHorizontalLine(mapValueToY(m_scene.minimumValue())); drawHorizontalLine(mapValueToY(m_scene->minimumValue()));
drawHorizontalLine(mapValueToY(m_scene.maximumValue())); drawHorizontalLine(mapValueToY(m_scene->maximumValue()));
painter->restore(); painter->restore();
} }

View File

@@ -52,16 +52,12 @@ signals:
public: public:
GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr); GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr);
~GraphicsView() override;
CurveEditorModel *model() const; CurveEditorModel *model() const;
CurveEditorStyle editorStyle() const; CurveEditorStyle editorStyle() const;
bool hasActiveItem() const;
bool hasActiveHandle() const;
bool hasSelectedKeyframe() const;
int mapTimeToX(double time) const; int mapTimeToX(double time) const;
int mapValueToY(double value) const; int mapValueToY(double value) const;
@@ -136,10 +132,6 @@ protected:
private: private:
void applyZoom(double x, double y, const QPoint &pivot = QPoint()); 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); void drawGrid(QPainter *painter, const QRectF &rect);
#if 0 #if 0
@@ -167,7 +159,7 @@ private:
QTransform m_transform; QTransform m_transform;
GraphicsScene m_scene; GraphicsScene *m_scene;
CurveEditorModel *m_model; CurveEditorModel *m_model;

View File

@@ -64,6 +64,22 @@ int HandleItem::type() const
return Type; 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 HandleItem::Slot HandleItem::slot() const
{ {
return m_slot; return m_slot;
@@ -77,7 +93,7 @@ QRectF HandleItem::boundingRect() const
bool HandleItem::contains(const QPointF &point) const bool HandleItem::contains(const QPointF &point) const
{ {
if (KeyframeItem *parent = qgraphicsitem_cast<KeyframeItem *>(parentItem())) { if (KeyframeItem *parent = keyframe()) {
HandleGeometry geom(pos(), m_style); HandleGeometry geom(pos(), m_style);
geom.handle.moveCenter(parent->pos() + pos()); geom.handle.moveCenter(parent->pos() + pos());
return geom.handle.contains(point); return geom.handle.contains(point);
@@ -130,7 +146,7 @@ void HandleItem::setStyle(const CurveEditorStyle &style)
QVariant HandleItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) QVariant HandleItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{ {
if (change == ItemPositionChange) { if (change == ItemPositionChange) {
if (qgraphicsitem_cast<KeyframeItem *>(parentItem())) { if (keyframe()) {
QPointF pos = value.toPointF(); QPointF pos = value.toPointF();
if (m_slot == HandleItem::Slot::Left) { if (m_slot == HandleItem::Slot::Left) {
if (pos.x() > 0.0) if (pos.x() > 0.0)

View File

@@ -30,6 +30,8 @@
namespace DesignTools { namespace DesignTools {
class KeyframeItem;
class HandleItem : public SelectableItem class HandleItem : public SelectableItem
{ {
Q_OBJECT Q_OBJECT
@@ -53,6 +55,10 @@ public:
void underMouseCallback() override; void underMouseCallback() override;
bool keyframeSelected() const;
KeyframeItem *keyframe() const;
Slot slot() const; Slot slot() const;
void setStyle(const CurveEditorStyle &style); void setStyle(const CurveEditorStyle &style);

View File

@@ -116,6 +116,27 @@ bool KeyframeItem::hasRightHandle() const
return m_frame.hasRightHandle(); 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 QTransform KeyframeItem::transform() const
{ {
return m_transform; return m_transform;

View File

@@ -72,6 +72,12 @@ public:
bool hasRightHandle() const; bool hasRightHandle() const;
bool hasActiveHandle() const;
HandleItem *leftHandle() const;
HandleItem *rightHandle() const;
QTransform transform() const; QTransform transform() const;
void setHandleVisibility(bool visible); void setHandleVisibility(bool visible);

View File

@@ -83,7 +83,6 @@ SelectableItem::SelectableItem(QGraphicsItem *parent)
: CurveEditorItem(parent) : CurveEditorItem(parent)
, m_active(false) , m_active(false)
, m_selected(false) , m_selected(false)
, m_locked(false)
, m_preSelected(SelectionMode::Undefined) , m_preSelected(SelectionMode::Undefined)
{ {
setFlag(QGraphicsItem::ItemIsSelectable, false); setFlag(QGraphicsItem::ItemIsSelectable, false);
@@ -139,7 +138,7 @@ void SelectableItem::setSelected(bool selected)
void SelectableItem::setPreselected(SelectionMode mode) void SelectableItem::setPreselected(SelectionMode mode)
{ {
if (m_locked) if (locked())
return; return;
m_preSelected = mode; m_preSelected = mode;
@@ -158,7 +157,7 @@ void SelectableItem::selectionCallback() {}
void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (m_locked) if (locked())
return; return;
m_active = true; m_active = true;
@@ -168,7 +167,7 @@ void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
if (m_locked) if (locked())
return; return;
if (type() == KeyframeItem::Type && !selected()) if (type() == KeyframeItem::Type && !selected())
@@ -179,7 +178,7 @@ void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
if (m_locked) if (locked())
return; return;
m_active = false; m_active = false;

View File

@@ -99,8 +99,6 @@ private:
bool m_selected; bool m_selected;
bool m_locked;
SelectionMode m_preSelected; SelectionMode m_preSelected;
}; };

View File

@@ -23,6 +23,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include "selector.h" #include "selector.h"
#include "graphicsscene.h"
#include "graphicsview.h" #include "graphicsview.h"
#include "keyframeitem.h" #include "keyframeitem.h"
#include "playhead.h" #include "playhead.h"
@@ -55,29 +56,40 @@ void Selector::paint(QPainter *painter)
painter->restore(); painter->restore();
} }
void Selector::mousePress(QMouseEvent *event, GraphicsView *view) void Selector::mousePress(QMouseEvent *event, GraphicsView *view, GraphicsScene *scene)
{ {
m_shortcut = Shortcut(event); m_shortcut = Shortcut(event);
if (view->hasActiveHandle()) QPointF click = view->globalToScene(event->globalPos());
return;
m_mouseInit = event->globalPos(); if (SelectableItem *sitem = scene->intersect(click)) {
m_mouseCurr = event->globalPos(); 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)) // Init selection tools.
if (select(SelectionTool::Undefined, click, view)) m_mouseInit = event->globalPos();
applyPreSelection(view); m_mouseCurr = event->globalPos();
m_lasso = QPainterPath(click); m_lasso = QPainterPath(click);
m_lasso.closeSubpath(); 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()) if (m_mouseInit.isNull())
return; 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 if (m_shortcut == m_shortcuts.newSelection || m_shortcut == m_shortcuts.addToSelection
|| m_shortcut == m_shortcuts.removeFromSelection || m_shortcut == m_shortcuts.removeFromSelection
|| m_shortcut == m_shortcuts.toggleSelection) { || m_shortcut == m_shortcuts.toggleSelection) {
if (view->hasActiveItem()) if (scene->hasActiveItem())
return; return;
select(m_tool, view->globalToScene(event->globalPos()), view); select(m_tool, view->globalToScene(event->globalPos()), scene);
event->accept(); event->accept();
view->viewport()->update(); 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) Q_UNUSED(event)
applyPreSelection(view); applyPreSelection(scene);
m_shortcut = Shortcut(); m_shortcut = Shortcut();
m_mouseInit = QPoint(); m_mouseInit = QPoint();
@@ -124,50 +136,73 @@ void Selector::mouseRelease(QMouseEvent *event, GraphicsView *view)
m_rect = QRectF(); m_rect = QRectF();
} }
bool Selector::isOverSelectedKeyframe(const QPointF &pos, GraphicsView *view) bool Selector::isOverMovableItem(const QPointF &pos, GraphicsScene *scene)
{ {
const auto itemList = view->items(); auto intersect = [pos](QGraphicsObject *item) {
for (auto *item : itemList) { return item->mapRectToScene(item->boundingRect()).contains(pos);
if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) { };
QRectF itemRect = frame->mapRectToScene(frame->boundingRect());
if (itemRect.contains(pos)) const auto frames = scene->keyframes();
return frame->selected(); 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; 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) { switch (tool) {
case SelectionTool::Lasso: case SelectionTool::Lasso:
return lassoSelection(mode, pos, view); return lassoSelection(mode, pos, scene);
case SelectionTool::Rectangle: case SelectionTool::Rectangle:
return rectangleSelection(mode, pos, view); return rectangleSelection(mode, pos, scene);
default: default:
return pressSelection(mode, pos, view); return pressSelection(mode, pos, scene);
} }
}; };
if (m_shortcut == m_shortcuts.newSelection) { if (m_shortcut == m_shortcuts.newSelection) {
clearSelection(view); clearSelection(scene);
return selectWidthTool(SelectionMode::New, pos, view); return selectWidthTool(SelectionMode::New, pos, scene);
} else if (m_shortcut == m_shortcuts.addToSelection) { } 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) { } 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) { } else if (m_shortcut == m_shortcuts.toggleSelection) {
return selectWidthTool(SelectionMode::Toggle, pos, view); return selectWidthTool(SelectionMode::Toggle, pos, scene);
} }
return false; 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; bool out = false;
const auto itemList = view->items(); const auto itemList = scene->items();
for (auto *item : itemList) { for (auto *item : itemList) {
if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) { if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) {
QRectF itemRect = frame->mapRectToScene(frame->boundingRect()); QRectF itemRect = frame->mapRectToScene(frame->boundingRect());
@@ -176,15 +211,25 @@ bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsVi
out = true; 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; 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; bool out = false;
m_rect.setBottomRight(pos); m_rect.setBottomRight(pos);
const auto itemList = view->items(); const auto itemList = scene->items();
for (auto *item : itemList) { for (auto *item : itemList) {
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) { if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
if (m_rect.contains(keyframeItem->pos())) { if (m_rect.contains(keyframeItem->pos())) {
@@ -198,11 +243,11 @@ bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, Graphi
return out; 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; bool out = false;
m_lasso.lineTo(pos); m_lasso.lineTo(pos);
const auto itemList = view->items(); const auto itemList = scene->items();
for (auto *item : itemList) { for (auto *item : itemList) {
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) { if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
if (m_lasso.contains(keyframeItem->pos())) { if (m_lasso.contains(keyframeItem->pos())) {
@@ -216,20 +261,22 @@ bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsVi
return out; 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) { for (auto *item : itemList) {
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) { if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
frameItem->setPreselected(SelectionMode::Clear); frameItem->setPreselected(SelectionMode::Clear);
frameItem->applyPreselection(); 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) { for (auto *item : itemList) {
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item))
keyframeItem->applyPreselection(); keyframeItem->applyPreselection();

View File

@@ -31,6 +31,7 @@
namespace DesignTools { namespace DesignTools {
class GraphicsView; class GraphicsView;
class GraphicsScene;
class Playhead; class Playhead;
enum class SelectionTool { Undefined, Lasso, Rectangle }; enum class SelectionTool { Undefined, Lasso, Rectangle };
@@ -42,26 +43,28 @@ public:
void paint(QPainter *painter); 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: 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; Shortcuts m_shortcuts;

View File

@@ -50,7 +50,7 @@ QRectF bbox(const QRectF &rect, const QTransform &transform);
QPalette singleColorPalette(const QColor &color); QPalette singleColorPalette(const QColor &color);
template<typename T> template<typename T>
inline void freeClear(std::vector<T *> &vec) inline void freeClear(T &vec)
{ {
for (auto *&el : vec) for (auto *&el : vec)
delete el; delete el;