/************************************************************************** This file is part of JahshakaVR, VR Authoring Toolkit http://www.jahshaka.com Copyright (c) 2016 GPLv3 Jahshaka LLC <[email protected]> This is free software: you may copy, redistribute and/or modify it under the terms of the GPLv3 License For more information see the LICENSE file *************************************************************************/ #include <QWidget> #include <QDebug> #include <QPainter> #include <QMouseEvent> #include "../irisgl/src/scenegraph/scenenode.h" #include "timelinewidget.h" #include <QtMath> #include <cmath> #include "animationwidgetdata.h" //https://kernelcoder.wordpress.com/2010/08/25/how-to-insert-ruler-scale-type-widget-into-a-qabstractscrollarea-type-widget/ TimelineWidget::TimelineWidget(QWidget* parent): QWidget(parent) { QSizePolicy sizePolicy; sizePolicy.setHorizontalPolicy(QSizePolicy::Fixed); sizePolicy.setVerticalPolicy(QSizePolicy::Preferred); this->setSizePolicy(sizePolicy); this->setGeometry(0, 0, 100, 21); bgColor = QColor::fromRgb(30,30,30); itemColor = QColor::fromRgb(255,255,255); linePen = QPen(itemColor); cursorPen = QPen(QColor::fromRgb(255, 255, 255)); cursorPen.setWidth(1); setMouseTracking(true); dragging = false; drawHighlight = false; leftButtonDown = false; middleButtonDown = false; rightButtonDown = false; animWidgetData = nullptr; } void TimelineWidget::showHighlight(float start,float end) { highlightStart = start; highlightEnd = end; drawHighlight = true; this->repaint(); } void TimelineWidget::hideHighlight() { drawHighlight = false; this->repaint(); } void TimelineWidget::paintEvent(QPaintEvent *painter) { Q_UNUSED(painter); if (!animWidgetData) return; int widgetWidth = this->geometry().width(); int widgetHeight = this->geometry().height(); QPainter paint(this); paint.setRenderHint(QPainter::Antialiasing); paint.setRenderHint(QPainter::HighQualityAntialiasing); //black bg //paint.fillRect(0,0,widgetWidth,widgetHeight,bgColor); // draws the dark part of the bottom of the frame paint.setPen(QColor::fromRgb(100,100,100)); paint.fillRect(0,0,widgetWidth,widgetHeight,QColor::fromRgb(80, 80, 80)); paint.setPen(linePen); QPen smallPen = QPen(QColor::fromRgb(55,55,55)); QPen bigPen = QPen(QColor::fromRgb(200,200,200)); //find increment automatically float increment = 10.0f;//start on the smallest level auto range = animWidgetData->rangeEnd - animWidgetData->rangeStart; while(increment*10<range) increment*=10; float startTime = animWidgetData->rangeStart - fmod(animWidgetData->rangeStart, increment) - increment; float endTime = animWidgetData->rangeEnd - fmod(animWidgetData->rangeEnd, increment) + increment; //big increments paint.setPen(bigPen); for(float x=startTime;x<endTime;x+=increment) { int screenPos = timeToPos(x); paint.drawLine(screenPos, widgetHeight - widgetHeight/3.0f, screenPos, widgetHeight); int timeInSeconds = (int)x; int secs = timeInSeconds%60; int mins = timeInSeconds/60; int hours = timeInSeconds/3600; paint.drawText(screenPos+3,widgetHeight-5,QString("%1:%2:%3") .arg(hours,2,10,QLatin1Char('0')) .arg(mins,2,10,QLatin1Char('0')) .arg(secs,2,10,QLatin1Char('0'))); } //highlights the animation range of the selected node if(drawHighlight) { int start = timeToPos(highlightStart); int end = timeToPos(highlightEnd-highlightStart); paint.fillRect(start,0,end,widgetWidth,QColor(200,200,255,100)); } //cursor auto cursorX = timeToPos(animWidgetData->cursorPosInSeconds); paint.setPen(cursorPen); paint.drawLine(cursorX, 0, cursorX, widgetHeight); // draw cursor's "handle" int handleWidth = 10; int halfHandleWidth = handleWidth/2; int handleHeight = 15; QPainterPath path; path.moveTo(cursorX - halfHandleWidth, 0); path.lineTo(cursorX + halfHandleWidth, 0); path.lineTo(cursorX + halfHandleWidth, handleHeight); path.lineTo(cursorX, handleHeight+5); path.lineTo(cursorX - halfHandleWidth, handleHeight); //path.lineTo(); paint.fillPath(path, QBrush(QColor(255, 255, 255))); } int TimelineWidget::timeToPos(float timeInSeconds) { return animWidgetData->timeToPos(timeInSeconds, this->width()); } float TimelineWidget::posToTime(int xpos) { return animWidgetData->posToTime(xpos, this->width()); } void TimelineWidget::setAnimWidgetData(AnimationWidgetData *value) { animWidgetData = value; } void TimelineWidget::mousePressEvent(QMouseEvent* evt) { Q_UNUSED(evt); mousePos = evt->pos(); clickPos = mousePos; if(evt->button() == Qt::LeftButton) leftButtonDown = true; if(evt->button() == Qt::MiddleButton) middleButtonDown = true; if(evt->button() == Qt::RightButton) rightButtonDown = true; if(evt->button() == Qt::LeftButton) { dragging = true; animWidgetData->cursorPosInSeconds = posToTime(evt->x()); } } void TimelineWidget::mouseReleaseEvent(QMouseEvent* evt) { Q_UNUSED(evt); dragging = false; mousePos = evt->pos(); if(evt->button() == Qt::LeftButton) leftButtonDown = false; if(evt->button() == Qt::MiddleButton) middleButtonDown = false; if(evt->button() == Qt::RightButton) rightButtonDown = false; } void TimelineWidget::mouseMoveEvent(QMouseEvent* evt) { if(leftButtonDown) { animWidgetData->cursorPosInSeconds = posToTime(evt->x()); cursorMoved(animWidgetData->cursorPosInSeconds); animWidgetData->refreshWidgets(); } if(middleButtonDown) { //qDebug()<<"middle mouse dragging"<<endl; auto timeDiff = posToTime(evt->x()) - posToTime(mousePos.x()); animWidgetData->rangeStart-=timeDiff; animWidgetData->rangeEnd-=timeDiff; animWidgetData->refreshWidgets(); } mousePos = evt->pos(); } void TimelineWidget::wheelEvent(QWheelEvent* evt) { auto delta = evt->delta(); float sign = delta<0?-1:1; //0.2f here is the zoom speed float scale = 1.0f-sign*0.2f; float timeSpacePivot = posToTime(evt->x()); animWidgetData->rangeStart = timeSpacePivot+(animWidgetData->rangeStart-timeSpacePivot) * scale; animWidgetData->rangeEnd = timeSpacePivot+(animWidgetData->rangeEnd-timeSpacePivot) * scale; animWidgetData->refreshWidgets(); } void TimelineWidget::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); }