Files
Renderive/YSGraphic_Core/RenderAble.h
T
2026-07-23 09:35:29 +08:00

257 lines
9.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <array>
#include <atomic>
#include <cstdint>
#include <qlinkedlist.h>
#include <QImage>
#include <QRegion>
#include <qscreen.h>
#include "GlobalTypes.h"
namespace YSG {
#define INIT_GET(className) className##Private* privateData = d(); \
className##RenderState* renderState = reinterpret_cast<className##RenderState*>(d()->getState(src));
struct TempData {
virtual ~TempData() = default;
};
struct RenderState {
virtual ~RenderState() = default;
std::uint64_t version = 0;
RenderData* dPtr{};
SRC src();
};
struct RenderData {
SpinLock mBufferLock;
RenderAble* qPtr{};
bool mRenderStart = false;
RenderState* getState(SRC src) const {
switch (src) {
case SRC::Render: {
return mRenderState;
}
case SRC::Cache: {
return mRenderStateCache;
}
case SRC::Auto: {
return mRenderStart ? mRenderState : mRenderStateCache;
}
}
qDebug() << "RenderState* RenderData::getState(SRC src) error 不存在的枚举值" << static_cast<int>(src);
return nullptr;
}
RenderState *mRenderState{}, *mRenderStateCache{};
TempData *mTempData{}, *mTempDataCache{};
protected:
virtual void loadCache() = 0;
virtual RenderState* renderState() = 0;
virtual RenderState* renderStateCache() = 0;
virtual TempData* tempData() = 0;
virtual TempData* tempDataCache() = 0;
virtual ~RenderData() {
delete mTempData;
delete mTempDataCache;
delete mRenderState;
delete mRenderStateCache;
}
virtual void draw(QPainter* painter) {}
virtual void prepareData() {
SpinLockGuard g(&mBufferLock);
//qDebug() << "qPtr->mObjectName " << qPtr->mObjectName;
loadCache();
}
virtual bool selectTest(const QPointF& pos) {
return false;
}
virtual void plotEvent(QEvent* event) {}
virtual void mousePressEvent(QMouseEvent* event) {}
virtual void mouseMoveEvent(QMouseEvent* event) {}
virtual void mouseReleaseEvent(QMouseEvent* event) {}
virtual void setHoverState(const QPoint& pos, bool active) {}
virtual void keyPressEvent(QKeyEvent* event) {}
virtual void keyReleaseEvent(QKeyEvent* event) {}
virtual void firstResizeEvent(QResizeEvent* event) {}
virtual void resizeEvent(QResizeEvent* event) {}
virtual void wheelEvent(QWheelEvent* event) {}
friend struct RenderAble;
};
struct BaseRenderData : RenderData {
RenderState* renderState() override {
return nullptr;
}
RenderState* renderStateCache() override {
return nullptr;
}
TempData* tempData() override {
return nullptr;
}
TempData* tempDataCache() override {
return nullptr;
}
void loadCache() override {}
};
class Plot;
struct LIB_DECL RenderEditGuard {
explicit RenderEditGuard(RenderData* data);
~RenderEditGuard();
RenderData* mData{};
};
struct RenderAble {
enum class JobState {
Idle,
Queued,
Running
};
struct ColorBuffer {
std::uint64_t version = 0;
QImage image;
QRegion dirtyRegion;
};
struct RenderPipeline {
SpinLock colorLock;
std::array<ColorBuffer, 3> colorBuffers;
ColorBuffer* frontColor{};
ColorBuffer* readyColor{};
ColorBuffer* renderColor{};
std::atomic<std::uint64_t> editStateVersion{1};
std::uint64_t renderStateVersion = 0;
JobState jobState = JobState::Idle;
bool paintRequestPending = false;
QRegion dirtyRegion;
RenderPipeline();
void markEditState();
bool hasNewState() const;
ColorBuffer* currentRenderColor() const;
QRegion publishRenderColor();
ColorBuffer* consumeReadyColor();
};
virtual RenderData* createRenderData() {
return new BaseRenderData;
}
virtual RenderState* createRenderState() {
return new RenderState;
}
virtual TempData* createTempData() {
return new TempData;
}
virtual void init(Plot* plot, QString layerName = "");
virtual void draw(QPainter* painter) {
dPtr->draw(painter);
}
virtual void prepareData() {
dPtr->prepareData();
}
virtual bool selectTest(const QPointF& pos) {
return dPtr->selectTest(pos);
}
virtual void plotEvent(QEvent* event) {
dPtr->plotEvent(event);
}
virtual void mousePressEvent(QMouseEvent* event) {
dPtr->mousePressEvent(event);
}
virtual void mouseMoveEvent(QMouseEvent* event) {
dPtr->mouseMoveEvent(event);
}
virtual void mouseReleaseEvent(QMouseEvent* event) {
dPtr->mouseReleaseEvent(event);
}
virtual void setHoverState(const QPoint& pos, bool active) {
dPtr->setHoverState(pos, active);
}
virtual void keyPressEvent(QKeyEvent* event) {
dPtr->keyPressEvent(event);
}
virtual void keyReleaseEvent(QKeyEvent* event) {
dPtr->keyReleaseEvent(event);
}
virtual void firstResizeEvent(QResizeEvent* event) {
dPtr->firstResizeEvent(event);
}
virtual void resizeEvent(QResizeEvent* event) {
dPtr->resizeEvent(event);
}
virtual void wheelEvent(QWheelEvent* event) {
dPtr->wheelEvent(event);
};
static bool version_newer(std::uint64_t a, std::uint64_t b) {
return static_cast<std::int64_t>(a - b) > 0;
}
void markStateDirty();
QString mObjectName;
RenderData* dPtr{};
Plot* mPlot{};
[[nodiscard]] bool ok() const;
bool mPrepared = false;
// 这里面可以预先准备数据用来同步
virtual ~RenderAble();
virtual bool select(QPointF pos) {
return false;
}
bool mVisable = true;
RenderAble* mParent{};
QVector<RenderAble*> mBeRelyList;
bool dectCycleRely();
private:
bool hasCycleRely(RenderAble* node, QSet<RenderAble*>& visited, QSet<RenderAble*>& recursionStack, QVector<RenderAble*>& currentPath);
};
#define Q_Ptr2(ClassName) \
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
RenderData* createRenderData() override; \
RenderState* createRenderState() override; \
TempData* createTempData() override; \
protected: \
ClassName(); \
friend struct ClassName##Private; \
friend struct ClassName##RenderState; \
friend struct ClassName##TempData; \
public:
#define Q_Ptr(ClassName) \
ClassName(); \
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
RenderData* createRenderData() override; \
RenderState* createRenderState() override; \
TempData* createTempData() override;
#define Q_Ptr_cpp(ClassName) \
ClassName::ClassName() { \
dPtr = new ClassName##Private; \
mObjectName = #ClassName; \
} \
RenderData* ClassName::createRenderData() {return new ClassName##Private;} \
RenderState* ClassName::createRenderState() {return new ClassName##RenderState;} \
TempData* ClassName::createTempData() {return new ClassName##TempData;}
#define D_Ptr_3(ClassName) \
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(mRenderState);} \
ClassName##RenderState* renderStateCache() override {return reinterpret_cast<ClassName##RenderState*>(mRenderStateCache);} \
ClassName##TempData* tempData() override {return reinterpret_cast<ClassName##TempData*>(mTempData);} \
ClassName##TempData* tempDataCache() override {return reinterpret_cast<ClassName##TempData*>(mTempDataCache);} \
friend class ClassName; \
void loadCache() override { \
*renderState() = *renderStateCache(); \
std::swap(mTempData, mTempDataCache); \
if(!mRenderStart) mRenderStart = true; \
}
#define D_Ptr(ClassName) \
ClassName* q() {return reinterpret_cast<ClassName*>(qPtr);} \
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(mRenderState);} \
ClassName##RenderState* renderStateCache() override {return reinterpret_cast<ClassName##RenderState*>(mRenderStateCache);} \
ClassName##TempData* tempData() override {return reinterpret_cast<ClassName##TempData*>(mTempData);} \
ClassName##TempData* tempDataCache() override {return reinterpret_cast<ClassName##TempData*>(mTempDataCache);} \
friend class ClassName; \
void loadCache() override { \
*renderState() = *renderStateCache(); \
std::swap(mTempData, mTempDataCache); \
if(!mRenderStart) mRenderStart = true; \
}
#define D_Ptr2(ClassName) \
ClassName* q() {return reinterpret_cast<ClassName*>(qPtr);} \
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(mRenderState);} \
ClassName##RenderState* renderStateCache() override {return reinterpret_cast<ClassName##RenderState*>(mRenderStateCache);} \
ClassName##TempData* tempData() override {return reinterpret_cast<ClassName##TempData*>(mTempData);} \
ClassName##TempData* tempDataCache() override {return reinterpret_cast<ClassName##TempData*>(mTempDataCache);} \
friend class ClassName;
#define INIT_SET(className) className##Private* pd = d(); \
className##RenderState* sc = pd->renderStateCache();\
className##TempData* td = pd->tempDataCache(); \
SpinLockGuard _guard(&pd->mBufferLock); \
RenderEditGuard _editGuard(pd);
}