280 lines
9.1 KiB
C++
280 lines
9.1 KiB
C++
#include "Plot_p.h"
|
||
#include "PerformanceShower_p.h"
|
||
#include "Global.h"
|
||
|
||
namespace YSG {
|
||
class PrePareMutiDataMutexGuard {
|
||
public:
|
||
QVector<PrePareMutiDataMutex*> mLockList;
|
||
PrePareMutiDataMutexGuard(RenderAble* renderAble, Plot* plot) {
|
||
for(PrePareMutiDataMutex* curLock : plot->mMutiSpinLock) {
|
||
if(curLock->mSet.contains(renderAble)) {
|
||
mLockList.append(curLock);
|
||
}
|
||
}
|
||
for(PrePareMutiDataMutex* curLock : mLockList) curLock->lock(renderAble);
|
||
}
|
||
~PrePareMutiDataMutexGuard() {
|
||
for(PrePareMutiDataMutex* curLock : mLockList) curLock->unlock();
|
||
}
|
||
};
|
||
|
||
|
||
void startAllRenderThread() {
|
||
Global::instance()->startAllTimeThread();
|
||
}
|
||
|
||
void Plot::bindRenderThread(const QString& threadName) {
|
||
auto g = Global::instance();
|
||
if (!g->mTimerThreadMap.contains(threadName)) {
|
||
auto newThread = new TimerThread;
|
||
g->mTimerThreadMap[threadName] = newThread;
|
||
newThread->setObjectName(threadName);
|
||
}
|
||
g->mTimerThreadMap[threadName]->mPlots.append(this);
|
||
}
|
||
|
||
Plot::Plot(){
|
||
d = new PlotPrivate(this);
|
||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||
setFocusPolicy(Qt::NoFocus);
|
||
}
|
||
bool Plot::usePerformanceShower() {
|
||
return d->mShower;
|
||
}
|
||
void Plot::set_usePerformanceShower(bool use) {
|
||
SpinLockGuard g(&d->mRenderLock);
|
||
|
||
if(!use) {
|
||
PerformanceShower* t = d->mShower;
|
||
d->mShower = nullptr;
|
||
delete t;
|
||
} else {
|
||
if(d->mShower) return;
|
||
d->mShower = new PerformanceShower(this);
|
||
d->mShower->show();
|
||
}
|
||
}
|
||
|
||
Plot::~Plot() {
|
||
delete d->mRenderBuffer;
|
||
}
|
||
|
||
bool Plot::isRendering() {
|
||
if(!d->mTimer) return false;
|
||
return d->mTimer->isActive();
|
||
}
|
||
|
||
void Plot::startRender(int refreshTimesPreSecond) {
|
||
d->mRefreshTimesPreSecond = refreshTimesPreSecond;
|
||
startRender();
|
||
}
|
||
|
||
void Plot::startRender() const {
|
||
if(d->mTimer) QMetaObject::invokeMethod(d->mTimer, "start", Qt::AutoConnection, Q_ARG(int, qRound(1000.0 / (double) d->mRefreshTimesPreSecond)));
|
||
}
|
||
|
||
void Plot::pauseRender() const {
|
||
if(d->mTimer) QMetaObject::invokeMethod(d->mTimer, "stop", Qt::AutoConnection);
|
||
}
|
||
|
||
void Plot::paintEvent(QPaintEvent* event) {
|
||
SpinLockGuard guard(&d->mBufferLock);
|
||
QPainter painter(this);
|
||
painter.drawPixmap(QPoint(0, 0), d->mPaintBuffer);
|
||
//painter.drawImage(QPoint(0, 0), d->mPaintBuffer);
|
||
painter.end();
|
||
if(d->mShower) d->mShower->counterIncrease("plot paint");
|
||
d->mPlotState.storeRelease(PlotPrivate::NeedToRender);
|
||
}
|
||
void Plot::render() {
|
||
if (mFirstResize) return;
|
||
if (d->mPlotState.loadAcquire() != PlotPrivate::NeedToRender) return;
|
||
if(!d->mRenderBuffer) return;
|
||
SpinLockGuard renderGuard(&d->mRenderLock);
|
||
if(d->mRenderBuffer->isNull()) return;
|
||
|
||
if(d->mShower) {
|
||
d->mShower->counterIncrease("渲染帧率");
|
||
d->mShower->mInfos["interval"] = QString("渲染:%1, global:%2").arg(d->mTimer->interval()).arg(Global::instance()->mInterval);
|
||
}
|
||
Cacl renderData("整体渲染耗时: %1 avg: %2", d->mShower);
|
||
QPainter painter(d->mRenderBuffer);
|
||
painter.fillRect(rect(), d->mBackground);
|
||
{
|
||
Cacl prepareData("准备数据耗时: %1 avg: %2", d->mShower);
|
||
SpinLockGuard prepareDataLock(&d->mPrepareDataLock);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble *cur : layer->mRenderAbles) {
|
||
//qDebug() << "info: "<< layer->mLayerName << " " << cur->mObjectName;
|
||
for(auto rely : cur->mBeRelyList) {
|
||
if(!rely->mPrepared){
|
||
PrePareMutiDataMutexGuard _guard(rely, this);
|
||
// qDebug() << cur->mObjectName << "rely: " << mObjectName;
|
||
rely->prepareData();
|
||
rely->mPrepared = true;
|
||
}
|
||
}
|
||
if(!cur->mPrepared){
|
||
PrePareMutiDataMutexGuard _guard(cur, this);
|
||
cur->prepareData();
|
||
//qDebug() << cur->mObjectName << " prepareData";
|
||
cur->mPrepared = true;
|
||
}
|
||
}
|
||
}
|
||
if(mFirstPrepareData) mFirstPrepareData = false;
|
||
}
|
||
|
||
|
||
{
|
||
Cacl prepareData("draw耗时: %1 avg: %2", d->mShower);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* cur : layer->mRenderAbles) {
|
||
if(!cur->mVisable) continue;
|
||
cur->draw(&painter);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
{
|
||
SpinLockGuard bufferGuard(&d->mBufferLock);
|
||
// d->mPaintBuffer = *d->mRenderBuffer;
|
||
d->mPaintBuffer = QPixmap::fromImage(*d->mRenderBuffer);
|
||
d->mPlotState.storeRelease(PlotPrivate::NeedToPaint);
|
||
}
|
||
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->mPrepared = false;
|
||
}
|
||
}
|
||
if(d->mShower) {
|
||
d->mShower->refresh();
|
||
}
|
||
}
|
||
|
||
QColor Plot::backgroundColor() {
|
||
return d->mBackground;
|
||
}
|
||
|
||
void Plot::setBackgroundColor(const QColor& color) const {
|
||
d->mBackground = color;
|
||
}
|
||
|
||
bool Plot::event(QEvent* event) {
|
||
bool ret = QWidget::event(event);
|
||
switch (event->type()){
|
||
case QEvent::Resize: {
|
||
auto e = reinterpret_cast<QResizeEvent*>(event);
|
||
{
|
||
//qDebug() << resizeEvent->size();
|
||
SpinLockGuard guard(&d->mRenderLock);
|
||
delete d->mRenderBuffer;
|
||
//d->mRenderBuffer = new QPixmap(e->size());
|
||
d->mRenderBuffer = new QImage(e->size().width(), e->size().height(), QImage::Format_ARGB32);
|
||
|
||
if(mFirstResize) {
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->firstResizeEvent(e);
|
||
}
|
||
}
|
||
}
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->resizeEvent(e);
|
||
}
|
||
}
|
||
if(mFirstResize) mFirstResize = false;
|
||
}
|
||
break;
|
||
}
|
||
case QEvent::Show: {
|
||
startRender();
|
||
break;
|
||
}
|
||
case QEvent::Hide: {
|
||
pauseRender();
|
||
break;
|
||
}
|
||
case QEvent::Enter: {
|
||
break;
|
||
}
|
||
case QEvent::Leave: {
|
||
|
||
break;
|
||
}
|
||
case QEvent::Wheel: {
|
||
auto e = reinterpret_cast<QWheelEvent*>(event);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->wheelEvent(e);
|
||
}
|
||
}
|
||
}
|
||
case QEvent::MouseMove: {
|
||
auto e = reinterpret_cast<QMouseEvent*>(event);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
if(able->selectTest(e->pos())) {
|
||
able->mouseMoveEvent(e);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case QEvent::MouseButtonPress: {
|
||
auto e = reinterpret_cast<QMouseEvent*>(event);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
if(able->selectTest(e->pos())) {
|
||
able->mousePressEvent(e);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case QEvent::MouseButtonRelease: {
|
||
auto e = reinterpret_cast<QMouseEvent*>(event);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
if(able->selectTest(e->pos())) {
|
||
able->mouseReleaseEvent(e);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case QEvent::KeyPress: {
|
||
auto e = reinterpret_cast<QKeyEvent*>(event);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->keyPressEvent(e);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case QEvent::KeyRelease: {
|
||
auto e = reinterpret_cast<QKeyEvent*>(event);
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->keyReleaseEvent(e);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
default: break;
|
||
}
|
||
for(Layer* layer : mLayerList) {
|
||
for(RenderAble* able : layer->mRenderAbles) {
|
||
able->plotEvent(event);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
}
|