From e1bf674c16e3c8472b29574159c789cd3f0c64e0 Mon Sep 17 00:00:00 2001 From: Bryan Galdrikian Date: Fri, 24 Feb 2017 09:32:20 -0800 Subject: Updating to blast_source-windows@1.0.347-21749006 and blast_tools_and_samples-windows@1.0.347-21749006 with a new directory structure. NvBlast folder is gone, files have been moved to top level directory. README is changed to reflect this. --- .../source/Internal/Window/CurveWidget.cpp | 1229 ++++++++++++++++++++ 1 file changed, 1229 insertions(+) create mode 100644 tools/CurveEditor/source/Internal/Window/CurveWidget.cpp (limited to 'tools/CurveEditor/source/Internal/Window/CurveWidget.cpp') diff --git a/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp b/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp new file mode 100644 index 0000000..fc778e5 --- /dev/null +++ b/tools/CurveEditor/source/Internal/Window/CurveWidget.cpp @@ -0,0 +1,1229 @@ +#include "CurveWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "CurveEditorMainWindow.h" + +namespace nvidia { +namespace CurveEditor { + +const int MARGIN_X = 2; +const int MARGIN_Y = 2; +const int SNAP_DISTANCE = 5; +const float CROSS_THRESHOLD = 5.0f; +const int GRID_INTIAL_SEGMENT_COUNT = 4; +const int CTRL_PNT_ICON_SIZE = 6; +const int CLICK_ON_CURVE_THRESHOLD = 4; +const int CURVE_WIDTH = 2; +const QColor GRID_COLOR = QColor(32, 32, 32, 64); + +////////////////////////////////////////////////////////////////////////////// +QPointF NDCToScreenCoord(QWidget* pWidget, QPointF p) +{ + int w = pWidget->width(); + int h = pWidget->height(); + + float x = MARGIN_X + p.x() * (w - MARGIN_X * 2.0f); + float y = h - MARGIN_Y * 2.0 + p.y() * (MARGIN_Y * 3.0f - h); + + return QPointF(x, y); +} + +////////////////////////////////////////////////////////////////////////////// +QPointF ScreenToNDC(QWidget* pWidget, QPointF p) +{ + int w = pWidget->width(); + int h = pWidget->height(); + + float sizey = 1.0f - 2.0f * MARGIN_Y; + + float x = (p.x() - MARGIN_X) / (2 - MARGIN_X * 2.0f); + float y = (MARGIN_Y * 2.0f + p.y() - h) / (MARGIN_Y * 3.0f - h); + + return QPointF(x, y); +} + +////////////////////////////////////////////////////////////////////////////// +bool IsInSelectedCtrlPnts(const std::vector& pickedPoints, int pointIndex) +{ + for (std::vector::const_iterator itr = pickedPoints.begin(); itr != pickedPoints.end(); ++itr) + { + if (*itr == pointIndex) + return true; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// +bool IsSamePoint(const QPointF& pntA, const QPointF& pntB, int threshold) +{ + float dx = pntB.x() - pntA.x(); + float dy = pntB.y() - pntA.y(); + + float r = sqrt(dx * dx + dy * dy); + if (r <= threshold) + return true; + else + return false; +} + +////////////////////////////////////////////////////////////////////////////// +int FindSelectedCtrlPnt(const std::vector& points, const QPointF& pickPos) +{ + for (size_t i = 0; i < points.size(); i++) + { + if (IsSamePoint(points[i], pickPos, CTRL_PNT_ICON_SIZE/2)) + return (int)i; + } + return -1; +} + +////////////////////////////////////////////////////////////////////////////// +CurveEntity::CurveEntity(CurveWidget* holder, CurveAttribute* attribute, const QColor& color) + : _holder(holder) + , _attribute(attribute) + , _curve(&(attribute->curve)) + , _color(color) + , _pickedPoint(-1) + , _pickedPoints() + , _lastMousePosScreen() + , _ctrlPntToRemove(-1) +{ + +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::setLocation(float location) +{ + if (_pickedPoints.size() != 1) + return ; + + ControlPoint pnt = _curve->getControlPoint(_pickedPoints[0]); + pnt.value.setX(location); + _curve->setControlPoint(_pickedPoints[0], pnt); + emit _holder->CurveAttributeChanged(_attribute); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::setValue(float value) +{ + if (_pickedPoints.size() != 1) + return ; + + ControlPoint pnt = _curve->getControlPoint(_pickedPoints[0]); + pnt.value.setY(value); + _curve->setControlPoint(_pickedPoints[0], pnt); + emit _holder->CurveAttributeChanged(_attribute); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::addControlPointsBeforeSelected() +{ + bool update = false; + for (std::vector::iterator itr = _pickedPoints.begin(); itr != _pickedPoints.end(); ++itr) + { + if (*itr == 0) + continue; + + _curve->insertControlPointAt(*itr); + ++(*itr); + update = true; + + if (*itr <= _pickedPoint) + { + ++_pickedPoint; + } + + for (std::vector::iterator itrRight = itr + 1; itrRight != _pickedPoints.end(); ++itrRight) + { + ++(*itrRight); + } + } + + if (update) + { + _curve->_needSample = true; + emit _holder->CurveAttributeChanged(_attribute); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::addControlPointsAfterSelected() +{ + bool update = false; + for (std::vector::iterator itr = _pickedPoints.begin(); itr != _pickedPoints.end(); ++itr) + { + _curve->insertControlPointAt(*itr + 1); + update = true; + + if ((*itr + 1) < _pickedPoint) + { + ++_pickedPoint; + } + + for (std::vector::iterator itrRight = itr + 1; itrRight != _pickedPoints.end(); ++itrRight) + { + ++(*itrRight); + } + } + + if (update) + { + _curve->_needSample = true; + emit _holder->CurveAttributeChanged(_attribute); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::removeSelectedControlPoints() +{ + if (_pickedPoints.size() > 0) + { + _curve->removeControlPoints(_pickedPoints); + _pickedPoints.clear(); + _pickedPoint = -1; + _curve->_needSample = true; + emit _holder->CurveAttributeChanged(_attribute); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::setTangentType(InterpolateMode mode) +{ + size_t pointsCount = _curve->getControlPointCount(); + for (int i = 0; i < pointsCount; i++) + { + if (IsInSelectedCtrlPnts(_pickedPoints, i)) + { + ControlPoint ctrlPnt = _curve->getControlPoint(i); + ctrlPnt.mode = mode; + _curve->setControlPoint(i, ctrlPnt); + emit _holder->CurveAttributeChanged(_attribute); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::setSmoothTangent() +{ + size_t pointsCount = _curve->getControlPointCount(); + for (int i = 0; i < pointsCount; i++) + { + if (IsInSelectedCtrlPnts(_pickedPoints, i) && i != pointsCount - 1) + { + ControlPoint ctrlctrlPntFront = _curve->getControlPoint(i); + ctrlctrlPntFront.mode = eBezierSpline; + ctrlctrlPntFront.splineData.outLen = 1.0; + ctrlctrlPntFront.splineData.outTan = 0; + _curve->setControlPoint(i, ctrlctrlPntFront); + + ControlPoint ctrlPntBehiand = _curve->getControlPoint(i + 1); + ctrlPntBehiand.mode = eBezierSpline; + ctrlPntBehiand.splineData.inLen = 1.0; + ctrlPntBehiand.splineData.inTan = 0.0; + _curve->setControlPoint(i + 1, ctrlPntBehiand); + + emit _holder->CurveAttributeChanged(_attribute); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::setEaseInTangent() +{ + size_t pointsCount = _curve->getControlPointCount(); + for (int i = 0; i < pointsCount; i++) + { + if (IsInSelectedCtrlPnts(_pickedPoints, i) && i != pointsCount - 1) + { + ControlPoint ctrlctrlPntFront = _curve->getControlPoint(i); + ctrlctrlPntFront.mode = eBezierSpline; + ctrlctrlPntFront.splineData.outLen = 0.0; + ctrlctrlPntFront.splineData.outTan = 0; + _curve->setControlPoint(i, ctrlctrlPntFront); + + ControlPoint ctrlPntBehiand = _curve->getControlPoint(i + 1); + ctrlPntBehiand.mode = eBezierSpline; + ctrlPntBehiand.splineData.inLen = 1.0; + ctrlPntBehiand.splineData.inTan = 0; + _curve->setControlPoint(i + 1, ctrlPntBehiand); + + emit _holder->CurveAttributeChanged(_attribute); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::setEaseOutTangent() +{ + size_t pointsCount = _curve->getControlPointCount(); + for (int i = 0; i < pointsCount; i++) + { + if (IsInSelectedCtrlPnts(_pickedPoints, i) && i != pointsCount - 1) + { + ControlPoint ctrlctrlPntFront = _curve->getControlPoint(i); + ctrlctrlPntFront.mode = eBezierSpline; + ctrlctrlPntFront.splineData.outLen = 1.0; + ctrlctrlPntFront.splineData.outTan = 0; + _curve->setControlPoint(i, ctrlctrlPntFront); + + ControlPoint ctrlPntBehiand = _curve->getControlPoint(i + 1); + ctrlPntBehiand.mode = eBezierSpline; + ctrlPntBehiand.splineData.inLen = 0.0; + ctrlPntBehiand.splineData.inTan = 0; + _curve->setControlPoint(i + 1, ctrlPntBehiand); + + emit _holder->CurveAttributeChanged(_attribute); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +int CurveEntity::getControlPointCount() +{ + return _curve->getControlPointCount(); +} + +////////////////////////////////////////////////////////////////////////////// +QRectF CurveEntity::getBoundingBox() +{ + return QRectF(_curve->getMinValue(), _curve->getMaxValue()); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::mousePressEvent( QMouseEvent* e, bool& pickedPoint) +{ + if (!(e->modifiers() & Qt::ControlModifier)) + { + _pickedPoints.clear(); + } + + std::vector points; + _makePoints(points); + QPoint mousePos = e->pos(); + _lastMousePosScreen = mousePos; + + _pickedPoint = FindSelectedCtrlPnt(points, mousePos); + if (-1 != _pickedPoint) + { + if (_holder->_canRemoveCtrlPntByClick && _attribute->canAddRemoveControlPoint()) + { + _curve->removeControlPoint(_pickedPoint); + _pickedPoint = -1; + return; + } + pickedPoint = true; + } + else + { + if (_holder->_canAddCtrlPntByClick) + { + _addCtrlPntByClick(mousePos); + } + return ; + } + + std::vector::iterator itr = _pickedPoints.begin(); + for (; itr != _pickedPoints.end(); ++itr) + { + if (*itr == _pickedPoint) + break; + else if (*itr > _pickedPoint) + { + itr = _pickedPoints.insert(itr, _pickedPoint); + break; + } + } + + if (itr == _pickedPoints.end()) + { + _pickedPoints.insert(itr, _pickedPoint); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::mouseReleaseEvent( QMouseEvent* e ) +{ +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::mouseMoveEvent( QMouseEvent* e ) +{ + Qt::MouseButton buttons = e->button(); + + { + //if (_pickedPoint >= 0) + QPointF mousePosScreen = e->pos(); + QPointF deltaPosScreen = mousePosScreen - _lastMousePosScreen; + QPointF destinationPosScreen = mousePosScreen; + _lastMousePosScreen = mousePosScreen; + std::vector::iterator itr = _pickedPoints.begin(); + for (; itr != _pickedPoints.end(); ++itr) + { + int pickedPoint = *itr; + ControlPoint pickedCtrlPnt = _curve->getControlPoint(pickedPoint); + QPointF ctrlPntLastScreenPos = _holder->_valueToScreen(pickedCtrlPnt.value); + + destinationPosScreen = ctrlPntLastScreenPos + deltaPosScreen; + destinationPosScreen = _holder->_getSnapSreenPos(destinationPosScreen); + + if (!_attribute->canMoveControlPointHorizontally()) + destinationPosScreen.setX(ctrlPntLastScreenPos.x()); + else + { + // make sure this picked control point not move accross other control point + if (pickedPoint == 0) + { + QPointF nextCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint + 1).value); + if (destinationPosScreen.x() > (nextCtrlPntScreenPos.x() - CROSS_THRESHOLD)) + destinationPosScreen.setX(nextCtrlPntScreenPos.x() - CROSS_THRESHOLD); + } + else if (pickedPoint == (_curve->getControlPointCount() - 1) ) + { + QPointF fomerCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint - 1).value); + if (destinationPosScreen.x() < (fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD)) + destinationPosScreen.setX(fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD); + } + else + { + QPointF fomerCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint - 1).value); + QPointF nextCtrlPntScreenPos = _holder->_valueToScreen(_curve->getControlPoint(pickedPoint + 1).value); + if (destinationPosScreen.x() < (fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD)) + destinationPosScreen.setX(fomerCtrlPntScreenPos.x() + CROSS_THRESHOLD); + if (destinationPosScreen.x() > (nextCtrlPntScreenPos.x() - CROSS_THRESHOLD)) + destinationPosScreen.setX(nextCtrlPntScreenPos.x() - CROSS_THRESHOLD); + } + } + + QPointF p = _holder->_screenToValue(destinationPosScreen); + + QPointF min = _curve->getMinValue(); + QPointF max = _curve->getMaxValue(); + + //make control point move in value range + { + if (p.x() < min.x()) + p.setX(min.x()); + else if (p.x() > max.x()) + p.setX(max.x()); + + if (p.y() < min.y()) + p.setY(min.y()); + else if (p.y() > max.y()) + p.setY(max.y()); + } + + pickedCtrlPnt.value = p; + _curve->setControlPoint(pickedPoint, pickedCtrlPnt); + emit _holder->PickedControlPointValueChanged(p); + + emit _holder->CurveAttributeChanged(_attribute); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::draw(QPainter &painter) +{ + std::vector points; + _makePoints(points); + + _drawCurve(painter); + + _drawPoints(points, painter, _pickedPoints); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::_drawCurve(QPainter &painter) +{ + painter.save(); + + { + QPen pen( Qt::black ); + pen.setColor(_color); + pen.setWidth(CURVE_WIDTH); + pen.setStyle(Qt::SolidLine); + + painter.setPen(pen); + painter.setRenderHint(QPainter::Antialiasing, false); + } + + QPainterPath path; + + std::vector samplePoints = _curve->getSamplePoints(); + path.moveTo(_holder->_valueToScreen(samplePoints[0])); + + for (size_t i = 0; i < samplePoints.size(); ++i) + { + path.lineTo(_holder->_valueToScreen(samplePoints[i])); + } + painter.drawPath(path); + + painter.restore(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::_makePoints(std::vector& points) +{ + size_t ctrlPntsCount = _curve->getControlPointCount(); + for (int i = 0; i < ctrlPntsCount; i++) + points.push_back( _holder->_valueToScreen(_curve->getControlPoint(i).value) ); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::_drawPoints(const std::vector& points, QPainter &painter, const std::vector& pickedPoints) +{ + { + QPen pen( Qt::black ); + pen.setColor(QColor(255,255,255)); + pen.setWidth(6); + pen.setStyle(Qt::SolidLine); + + painter.setPen(pen); + painter.setRenderHint(QPainter::Antialiasing, false); + } + + for (int i = 0; i < points.size(); i++) + { + QPen pen( Qt::black ); + pen.setWidth(CTRL_PNT_ICON_SIZE); + pen.setStyle(Qt::SolidLine); + + if (IsInSelectedCtrlPnts(pickedPoints,i)) + pen.setColor(QColor(255,0,0)); + else + pen.setColor(QColor(255,255,255)); + + painter.setPen(pen); + painter.drawPoint( points[i] ); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveEntity::_addCtrlPntByClick(const QPointF& mouseScreenPos) +{ + if (!_attribute->canAddRemoveControlPoint()) + return ; + + QPointF pos= _holder->_screenToValue(mouseScreenPos); + + QPointF pntOnCurve = _curve->getPointByX(pos.x()); + QPointF pntOnCurveScreen = _holder->_valueToScreen(pntOnCurve); + + if ( IsSamePoint(mouseScreenPos, pntOnCurveScreen, CLICK_ON_CURVE_THRESHOLD) ) + { + _pickedPoint = _curve->appendControlPoint(pntOnCurve.x()); + _holder->update(); + } + +} + +////////////////////////////////////////////////////////////////////////////// +bool CurveEntity::_canRemoveCtrlPntByRightClick(const QPointF& mouseScreenPos) +{ + std::vector points; + _makePoints(points); + + _ctrlPntToRemove = FindSelectedCtrlPnt(points, mouseScreenPos); + + if ( !_attribute->canAddRemoveControlPoint() + || (-1 == _ctrlPntToRemove) + || 2 == _curve->_controlPoints.size() && -1 != _ctrlPntToRemove) + { + return false; + } + else + return true; +} + +void CurveEntity::_removeCtrlPntByRightClick() +{ + if (-1 != _ctrlPntToRemove && _attribute->canAddRemoveControlPoint()) + { + _curve->removeControlPoint(_ctrlPntToRemove); + } + _ctrlPntToRemove = -1; + _pickedPoint = -1; + _pickedPoints.clear(); +} + +////////////////////////////////////////////////////////////////////////////// +CurveWidget::CurveWidget(QWidget* parent) + : QFrame(parent) + , _parent(parent) + , _moveCrossOtherCtrlPnt(false) + , _moveCtrlPnt(false) + , _pan(false) + , _snapHorizontal(false) + , _snapVertical(false) + , _canAddCtrlPntByClick(false) + , _canRemoveCtrlPntByClick(false) + , _curveFitWindowScale(1.0, 1.0) + , _curveFitWindowOffset(0.0, 0.0) + , _curveScaleLevel(1.0, 1.0) + , _contextMenu(nullptr) + , _removeCtrlPntAction(nullptr) +{ + setFocusPolicy(Qt::ClickFocus ); + //QString focusStyle = QString("QFrame:focus { border:1px solid #FF0000; }"); + //setStyleSheet(focusStyle); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onShowContextMenu(const QPoint&))); + + _contextMenu = new QMenu(this);; + _removeCtrlPntAction = new QAction(this); + _removeCtrlPntAction->setText(tr("Remove Control Point")); + _contextMenu->addAction(_removeCtrlPntAction); + + connect(_removeCtrlPntAction, SIGNAL(triggered()), this, SLOT(onRemoveControlPoint()) ); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::onShowContextMenu(const QPoint& pos) +{ + bool enableRemoveCtrlPntAction = false; + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + if (curveEntity._canRemoveCtrlPntByRightClick(pos)) + enableRemoveCtrlPntAction = true; + } + + _removeCtrlPntAction->setEnabled(enableRemoveCtrlPntAction); + _contextMenu->exec(QCursor::pos()); +} + +void CurveWidget::onRemoveControlPoint() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity._removeCtrlPntByRightClick(); + } + + std::vector pickedCurves; + emit PickedControlPointChanged(pickedCurves); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::paintEvent(QPaintEvent * e) +{ + QFrame::paintEvent(e); + + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing, true); + + _drawGrid(painter); + + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.draw(painter); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::resizeEvent(QResizeEvent* e) +{ + _updateCurveFitWindowPara(); + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::mousePressEvent( QMouseEvent* e ) +{ + if (e->buttons() == Qt::MiddleButton) + { + setCursor(Qt::OpenHandCursor); + _mousePressScreenPos = QPointF(e->pos().x(), e->pos().y()); + _pan = true; + } + else + { + std::vector pickedCurves; + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.mousePressEvent(e, _moveCtrlPnt); + if (curveEntity.getPickedControlPointIndexes().size() > 0) + pickedCurves.push_back(&curveEntity); + } + + emit PickedControlPointChanged(pickedCurves); + + update(); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::mouseReleaseEvent( QMouseEvent* e ) +{ + if (_moveCtrlPnt) + { + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.mouseReleaseEvent(e); + } + } + else if (_pan) + { + setCursor(Qt::ArrowCursor); + _curOrinScreenPos = _lastOrinScreenPos + (QPointF(e->pos().x() - _mousePressScreenPos.x(), _mousePressScreenPos.y() - e->pos().y())); + _lastOrinScreenPos = _curOrinScreenPos; + _updateCurveFitWindowPara(); + + } + + _moveCtrlPnt = false; + _pan = false; + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::mouseMoveEvent( QMouseEvent* e ) +{ + if (_moveCtrlPnt) + { + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.mouseMoveEvent(e); + } + } + else if (e->buttons() & Qt::MiddleButton) + { + _curOrinScreenPos = _lastOrinScreenPos + (QPointF(e->pos().x() - _mousePressScreenPos.x(), _mousePressScreenPos.y() - e->pos().y())); + _updateCurveFitWindowPara(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::wheelEvent(QWheelEvent *e) +{ + int numDegrees = e->delta() / 8; + + float zoom = 1.0 + numDegrees / 360.0f; + _curveScaleLevel.setX(_curveScaleLevel.x() * zoom); + _curveScaleLevel.setY(_curveScaleLevel.y() * zoom); + + _updateCurveFitWindowPara(); + update(); + e->accept(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::keyPressEvent(QKeyEvent *e) +{ + bool move = false; + switch(e->key()) + { + case Qt::Key_Left: + _curOrinScreenPos = _lastOrinScreenPos + QPointF(-1.0f, 0.0f); + _lastOrinScreenPos = _curOrinScreenPos; + move = true; + break; + case Qt::Key_Up: + _curOrinScreenPos = _lastOrinScreenPos + QPointF(0.0f, 1.0f); + _lastOrinScreenPos = _curOrinScreenPos; + move = true; + break; + case Qt::Key_Right: + _curOrinScreenPos = _lastOrinScreenPos + QPointF(1.0f, 0.0f); + _lastOrinScreenPos = _curOrinScreenPos; + move = true; + break; + case Qt::Key_Down: + _curOrinScreenPos = _lastOrinScreenPos + QPointF(0.0f, -1.0f); + _lastOrinScreenPos = _curOrinScreenPos; + move = true; + break; + } + + if (move) + { + _updateCurveFitWindowPara(); + update(); + } +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setLocation(float location) +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.setLocation(location); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setValue(float value) +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.setValue(value); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setCurveAttributes(std::vector attributes) +{ + _curves.clear(); + + for (std::vector::iterator itr = attributes.begin(); itr != attributes.end(); ++itr) + { + CurveAttributeBase* attribute = *itr; + if (attribute->getType() == eSingleAttr) + { + CurveAttribute* attributeSpecific = static_cast(attribute); + + CurveEntity curveEntity(this, attributeSpecific, attributeSpecific->color); + _curves.push_back(curveEntity); + } + else if (attribute->getType() == eGroupAttr) + { + CurveAttributeGroup* attributeGroup = static_cast(attribute); + size_t countAttributesInGroup = attributeGroup->attributes.size(); + for (size_t i = 0; i < countAttributesInGroup; ++i) + { + CurveAttribute* attributeInGroup = attributeGroup->attributes[i]; + + CurveEntity curveEntity(this, attributeInGroup, attributeInGroup->color); + _curves.push_back(curveEntity); + } + } + } + + _updateCurveFitWindowPara(); + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::reset() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity._attribute->curve.reset(); + emit CurveAttributeChanged(curveEntity._attribute); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::addControlPointsBeforeSelected() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.addControlPointsBeforeSelected(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::addControlPointsAfterSelected() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.addControlPointsAfterSelected(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::removeSelectedControlPoints() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.removeSelectedControlPoints(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setTangentType(InterpolateMode mode) +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.setTangentType(mode); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setSmoothTangent() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.setSmoothTangent(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setEaseInTangent() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.setEaseInTangent(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::setEaseOutTangent() +{ + size_t curveCount = _curves.size(); + for (size_t i = 0; i < curveCount; ++i) + { + CurveEntity& curveEntity = _curves[i]; + curveEntity.setEaseOutTangent(); + } + + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::increaseCurveScaleHorizontally() +{ + _curveScaleLevel.setX(_curveScaleLevel.x() * 2); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::decreaseCurveScaleHorizontally() +{ + _curveScaleLevel.setX(_curveScaleLevel.x() / 2); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::increaseCurveScaleVertically() +{ + _curveScaleLevel.setY(_curveScaleLevel.y() * 2); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::decreaseCurveScaleVertically() +{ + _curveScaleLevel.setY(_curveScaleLevel.y() / 2); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::frameCurveScaleHorizontally() +{ + _curveScaleLevel.setX(1.0f); + _curOrinScreenPos.setX(0); + _lastOrinScreenPos.setX(0); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::frameCurveScaleVertically() +{ + _curveScaleLevel.setY(1.0f); + _curOrinScreenPos.setY(0); + _lastOrinScreenPos.setY(0); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::frameCurveScale() +{ + _curveScaleLevel.setX(1.0f); + _curveScaleLevel.setY(1.0f); + _curOrinScreenPos = QPointF(0,0); + _lastOrinScreenPos = QPointF(0,0); + _updateCurveFitWindowPara(); + update(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::_updateCurveFitWindowPara() +{ + QRect winSize = rect(); + + float minX = 0; + float minY = 0; + float maxX = 0; + float maxY = 0; + + for (size_t i = 0; i < _curves.size(); ++i) + { + CurveEntity& curveEntity = _curves[i]; + + QRectF boundingBox = curveEntity.getBoundingBox(); + + if (minX > boundingBox.x()) + minX = boundingBox.x(); + + if (minY > boundingBox.y()) + minY = boundingBox.y(); + + if (maxX < boundingBox.right()) + maxX = boundingBox.right(); + + if (maxY < boundingBox.bottom()) + maxY = boundingBox.bottom(); + } + + float curveWidth = maxX - minX; + float curveHeight = maxY - minY; + + if (0 == curveWidth && 0 == curveHeight) + { + curveWidth = 1.0; + curveHeight = 1.0; + } + else if (0 == curveWidth) + { + curveWidth = curveHeight; + } + else if (0 == curveHeight) + { + curveHeight = curveWidth; + } + + float widthScale = (winSize.width() - MARGIN_X * 2.0f) / curveWidth; + float heightScale = (MARGIN_Y * 2.0f - winSize.height()) / curveHeight; + _curveFitWindowScale = QPointF(widthScale, heightScale); + + float widthOffset = MARGIN_X + _curOrinScreenPos.x() - minX * widthScale * _curveScaleLevel.x(); + float heightOffset = (winSize.height() - MARGIN_Y - _curOrinScreenPos.y())- minY * heightScale * _curveScaleLevel.y(); + _curveFitWindowOffset = QPointF(widthOffset, heightOffset); +} + +////////////////////////////////////////////////////////////////////////////// +QPointF CurveWidget::_valueToScreen(const QPointF& pnt) +{ + QPointF curveScale = QPointF(_curveFitWindowScale.x() * _curveScaleLevel.x(), _curveFitWindowScale.y() * _curveScaleLevel.y()); + + float x = pnt.x() * curveScale.x() + _curveFitWindowOffset.x(); + float y = pnt.y() * curveScale.y() + _curveFitWindowOffset.y(); + return QPointF(x, y); +} + +////////////////////////////////////////////////////////////////////////////// +QPointF CurveWidget::_screenToValue(const QPointF& pnt) +{ + QPointF curveScale = QPointF(_curveFitWindowScale.x() * _curveScaleLevel.x(), _curveFitWindowScale.y() * _curveScaleLevel.y()); + + float x = (pnt.x() - _curveFitWindowOffset.x()) / curveScale.x(); + float y = (pnt.y() - _curveFitWindowOffset.y()) / curveScale.y(); + + return QPointF(x, y); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::_drawAxis(QPainter &painter) +{ + painter.save(); + { + QPen pen( Qt::black ); + pen.setColor(GRID_COLOR); + pen.setWidth(2); + pen.setStyle(Qt::SolidLine); + + painter.setPen(pen); + painter.setRenderHint(QPainter::Antialiasing, false); + } + + { + int w = width() - MARGIN_X * 2; + int h = height() - MARGIN_Y * 2; + + QPainterPath path; + + QPointF x = _dragedCoordinateToScreen(QPointF(w, 0)); + QPointF y = _dragedCoordinateToScreen(QPointF(0, h)); + + path.moveTo(_dragedCoordinateToScreen(QPointF(0, 0))); + path.lineTo(x); + path.moveTo(_dragedCoordinateToScreen(QPointF(0, 0))); + path.lineTo(y); + + painter.drawPath(path); + } + + painter.restore(); +} + +////////////////////////////////////////////////////////////////////////////// +void CurveWidget::_drawGrid(QPainter &painter) +{ + painter.save(); + { + QPen pen( Qt::black ); + pen.setColor(GRID_COLOR); + pen.setWidth(1); + pen.setStyle(Qt::SolidLine); + + painter.setPen(pen); + painter.setRenderHint(QPainter::Antialiasing, false); + } + + { + QPainterPath path; + + int w = width() - MARGIN_X * 2; + int h = height() - MARGIN_Y * 2; + + QPointF newOri = _dragedCoordinateToScreen(_curOrinScreenPos); + + float width = w; + float height = h; + int gridXSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.x(); + int gridYSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.y(); + + if (_curveScaleLevel.x() > 1) + { + width = w * _curveScaleLevel.x(); + gridXSegmentCount *= _curveScaleLevel.x(); + } + + if (_curveScaleLevel.y() > 1) + { + height = h * _curveScaleLevel.y(); + gridYSegmentCount *= _curveScaleLevel.y(); + } + + // draw horizontal lines + for (int i = 0 - gridXSegmentCount; i <= gridXSegmentCount * 2; ++i) + { + QPointF bottom = _dragedCoordinateToScreen(QPointF(width * i / (float)gridXSegmentCount, -height)); + QPointF up = _dragedCoordinateToScreen(QPointF(width * i / (float)gridXSegmentCount, height * 2)); + path.moveTo(bottom); + path.lineTo(up); + + painter.drawPath(path); + } + + // draw vertical lines + for (int i = 0 - gridYSegmentCount; i <= gridYSegmentCount * 2; ++i) + { + QPointF left = _dragedCoordinateToScreen(QPointF(-width, i * height / (float)gridYSegmentCount)); + QPointF right = _dragedCoordinateToScreen(QPointF(2 * width, i * height / (float)gridYSegmentCount)); + path.moveTo(left); + path.lineTo(right); + + painter.drawPath(path); + } + + } + painter.restore(); +} + +////////////////////////////////////////////////////////////////////////////// +QPointF CurveWidget::_getSnapSreenPos(const QPointF& mouseScreenPos) +{ + int w = width() - MARGIN_X * 2; + int h = height() - MARGIN_Y * 2; + + QPointF pos = _screenToDragedCoordinate(mouseScreenPos); + + // snap horizontally + if (_snapHorizontal) + { + int gridXSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.x(); + if (gridXSegmentCount < 2) + gridXSegmentCount = 2; + for (int i = 0; i <= gridXSegmentCount; ++i) + { + if (abs(i * w / gridXSegmentCount - pos.x()) <= SNAP_DISTANCE ) + { + pos.setX(i * w / gridXSegmentCount); + break; + } + } + } + + // snap vertically + if (_snapVertical) + { + int gridYSegmentCount = GRID_INTIAL_SEGMENT_COUNT / _curveScaleLevel.y(); + if (gridYSegmentCount < 2) + gridYSegmentCount = 2; + for (int i = 0; i <= gridYSegmentCount; ++i) + { + if (abs(i * h / gridYSegmentCount - pos.y()) <= SNAP_DISTANCE) + { + pos.setY(i * h / gridYSegmentCount); + } + } + } + + return _dragedCoordinateToScreen(pos); +} + +////////////////////////////////////////////////////////////////////////////// +QPointF CurveWidget::_dragedCoordinateToScreen(const QPointF& pnt) +{ + float x = pnt.x() + MARGIN_X + _curOrinScreenPos.x(); + float y = height() - MARGIN_Y - pnt.y() - _curOrinScreenPos.y(); + return QPointF(x, y); +} + +////////////////////////////////////////////////////////////////////////////// +QPointF CurveWidget::_screenToDragedCoordinate(const QPointF& pnt) +{ + float x = pnt.x() - MARGIN_X - _curOrinScreenPos.x(); + float y = height() - MARGIN_Y - pnt.y() - _curOrinScreenPos.y(); + return QPointF(x, y); +} + +} // namespace CurveEditor +} // namespace nvidia \ No newline at end of file -- cgit v1.2.3