125 lines
2.8 KiB
C++
125 lines
2.8 KiB
C++
#pragma once
|
|
#include "CoreMinimal.h"
|
|
#include "RenderingCommon.h"
|
|
#include "SlateUpdatableTexture.h"
|
|
#include "Thread/ThreadMessage.h"
|
|
#include "Misc/CallRateLimiter.h"
|
|
|
|
struct FImageData
|
|
{
|
|
TArray<uint8> Data;
|
|
FIntPoint TextureSize = FIntPoint::ZeroValue;
|
|
|
|
bool Resize(FIntPoint NewSize)
|
|
{
|
|
if (NewSize == TextureSize)
|
|
return false;
|
|
if (NewSize.X <= 0 || NewSize.Y <= 0)
|
|
return false;
|
|
TextureSize = NewSize;
|
|
Data.SetNumZeroed(TextureSize.X * TextureSize.Y * 4);
|
|
return true;
|
|
}
|
|
|
|
void ClearColor(const FColor& Color)
|
|
{
|
|
for (int32 x = 0; x < TextureSize.X; ++x)
|
|
{
|
|
for (int32 y = 0; y < TextureSize.Y; ++y)
|
|
{
|
|
DrawPixel(x, y, Color);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawPixel(const FIntPoint& Pos, const FColor& Color)
|
|
{
|
|
DrawPixel(Pos.X, Pos.Y, Color);
|
|
}
|
|
|
|
void DrawPixel(int32 X, int32 Y, const FColor& Color)
|
|
{
|
|
#if UE_BUILD_DEBUG
|
|
const bool Error = X < 0 || X >= TextureSize.X || Y < 0 || Y >= TextureSize.Y;
|
|
ensureMsgf(!Error, TEXT("X: %d, Y: %d, TextureSize: %d, %d"), X, Y, TextureSize.X, TextureSize.Y);
|
|
if (Error)
|
|
return;
|
|
#endif
|
|
const int32 Pixel = X + Y * TextureSize.X;
|
|
uint8* Ptr = Data.GetData() + Pixel * 4;
|
|
*Ptr++ = Color.R;
|
|
*Ptr++ = Color.G;
|
|
*Ptr++ = Color.B;
|
|
*Ptr = Color.A;
|
|
}
|
|
|
|
void DrawLine(const FIntPoint& P1, const FIntPoint& P2, const FColor& Color)
|
|
{
|
|
int32 x1 = P1.X;
|
|
int32 y1 = P1.Y;
|
|
const int32& x2 = P2.X;
|
|
const int32& y2 = P2.Y;
|
|
|
|
const int dx = abs(x2 - x1);
|
|
const int dy = abs(y2 - y1);
|
|
const int sx = (x1 < x2) ? 1 : -1;
|
|
const int sy = (y1 < y2) ? 1 : -1;
|
|
int err = dx - dy;
|
|
|
|
while (true)
|
|
{
|
|
DrawPixel(x1, y1, Color);
|
|
|
|
if (x1 == x2 && y1 == y2)
|
|
break;
|
|
|
|
int e2 = 2 * err;
|
|
if (e2 > -dy)
|
|
{
|
|
err -= dy;
|
|
x1 += sx;
|
|
}
|
|
if (e2 < dx)
|
|
{
|
|
err += dx;
|
|
y1 += sy;
|
|
}
|
|
}
|
|
}
|
|
|
|
FColor& operator[](int32 PixelIndex)
|
|
{
|
|
return *(FColor*)(Data.GetData() + PixelIndex * 4);
|
|
}
|
|
};
|
|
|
|
DECLARE_DELEGATE_OneParam(FUpdatableImageDataEvent, FImageData&)
|
|
|
|
class FUpdatableTexture : public ISlateViewport, public TSharedFromThis<FUpdatableTexture>
|
|
{
|
|
FRIEND_THREAD_MESSAGE(UpdatableTexture)
|
|
public:
|
|
FUpdatableTexture(FIntPoint InTextureSize);
|
|
|
|
void Resize(FIntPoint NewSize);
|
|
void RequestUpdate(bool Async = true);
|
|
|
|
virtual FIntPoint GetSize() const override { return Data.TextureSize; }
|
|
virtual FSlateShaderResource* GetViewportRenderTargetTexture() const override { return Texture->GetSlateResource(); }
|
|
virtual bool RequiresVsync() const override { return false; }
|
|
ISlateViewport* GetViewportInterface() { return this; }
|
|
|
|
FUpdatableImageDataEvent RedrawImage;
|
|
FSimpleDelegate OnOverRedraw;
|
|
private:
|
|
FCallOnce UpdateCaller;
|
|
|
|
void Update(); // 只能在主线程调用
|
|
void AsyncUpdate();
|
|
|
|
FSlateUpdatableTexture* Texture;
|
|
FImageData Data;
|
|
bool ReSized = false;
|
|
FIntPoint NextSize;
|
|
};
|