Created
November 30, 2014 15:48
-
-
Save pixeltris/40fde2a6b4d8b68caeee to your computer and use it in GitHub Desktop.
Canvas / HUD clipping for Unreal Engine using scissor rects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ClipCanvas.h" | |
#include "HUDEx.h" | |
class FCanvasScissorRectItem : public FCanvasItem | |
{ | |
public: | |
bool bEnable; | |
int32 MinX; | |
int32 MaxX; | |
int32 MinY; | |
int32 MaxY; | |
FCanvasScissorRectItem(bool enable, int32 minX, int32 minY, int32 maxX, int32 maxY) : | |
FCanvasItem(FVector2D::ZeroVector), | |
bEnable(enable), | |
MinX(minX), | |
MaxX(maxX), | |
MinY(minY), | |
MaxY(maxY) | |
{ | |
} | |
FCanvasScissorRectItem() : | |
FCanvasScissorRectItem(false, 0, 0, 0, 0) | |
{ | |
} | |
public: | |
void Draw(FCanvas* InCanvas); | |
}; | |
class FCanvasScissorRectRenderItem : public FCanvasBaseRenderItem | |
{ | |
public: | |
FCanvasScissorRectItem ScissorInfo; | |
FCanvasScissorRectRenderItem(FCanvasScissorRectItem& scissorInfo) | |
{ | |
ScissorInfo = scissorInfo; | |
} | |
virtual bool Render_RenderThread(FRHICommandListImmediate& RHICmdList, const FCanvas* Canvas) override | |
{ | |
RHICmdList.SetScissorRect(ScissorInfo.bEnable, ScissorInfo.MinX, ScissorInfo.MinY, ScissorInfo.MaxX, ScissorInfo.MaxY); | |
return false; | |
} | |
virtual bool Render_GameThread(const FCanvas* Canvas) override | |
{ | |
struct FCanvasScissorRectParameters | |
{ | |
bool bEnable; | |
int32 MinX; | |
int32 MaxX; | |
int32 MinY; | |
int32 MaxY; | |
}; | |
FCanvasScissorRectParameters ScissorParameters = | |
{ | |
ScissorInfo.bEnable, | |
ScissorInfo.MinX, | |
ScissorInfo.MaxX, | |
ScissorInfo.MinY, | |
ScissorInfo.MaxY | |
}; | |
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( | |
CanvasScissorRectCommand, | |
FCanvasScissorRectParameters, Parameters, ScissorParameters, | |
{ | |
RHICmdList.SetScissorRect(Parameters.bEnable, Parameters.MinX, Parameters.MinY, Parameters.MaxX, Parameters.MaxY); | |
}); | |
return false; | |
} | |
}; | |
void FCanvasScissorRectItem::Draw(FCanvas* InCanvas) | |
{ | |
Canvas_GetSortElement(*InCanvas, InCanvas->TopDepthSortKey()).RenderBatchArray.Add(new FCanvasScissorRectRenderItem(*this)); | |
} | |
FCanvas::FCanvasSortElement& Canvas_GetSortElement(FCanvas& canvas, int32 DepthSortKey) | |
{ | |
// Optimization to resuse last index so that the more expensive Find() does not | |
// need to be called as much. | |
if (canvas.SortedElements.IsValidIndex(canvas.LastElementIndex)) | |
{ | |
FCanvas::FCanvasSortElement & LastElement = canvas.SortedElements[canvas.LastElementIndex]; | |
if (LastElement.DepthSortKey == DepthSortKey) | |
{ | |
return LastElement; | |
} | |
} | |
// find the FCanvasSortElement array entry based on the sortkey | |
int32 ElementIdx = INDEX_NONE; | |
int32* ElementIdxFromMap = canvas.SortedElementLookupMap.Find(DepthSortKey); | |
if (ElementIdxFromMap) | |
{ | |
ElementIdx = *ElementIdxFromMap; | |
checkSlow(canvas.SortedElements.IsValidIndex(ElementIdx)); | |
} | |
// if it doesn't exist then add a new entry (no duplicates allowed) | |
else | |
{ | |
new(canvas.SortedElements)FCanvas::FCanvasSortElement(DepthSortKey); | |
ElementIdx = canvas.SortedElements.Num() - 1; | |
// keep track of newly added array index for later lookup | |
canvas.SortedElementLookupMap.Add(DepthSortKey, ElementIdx); | |
} | |
canvas.LastElementIndex = ElementIdx; | |
return canvas.SortedElements[ElementIdx]; | |
} | |
void ClipCanvas(UCanvas* canvas, bool enable, int32 minX, int32 minY, int32 maxX, int32 maxY) | |
{ | |
if (canvas) | |
{ | |
ClipCanvas(canvas->Canvas, enable, minX, minY, maxX, maxY); | |
} | |
} | |
void ClipCanvas(FCanvas* canvas, bool enable, int32 minX, int32 minY, int32 maxX, int32 maxY) | |
{ | |
if (canvas) | |
{ | |
FCanvasScissorRectItem item(enable, minX, minY, maxX, maxY); | |
canvas->DrawItem(item); | |
} | |
} | |
void ClipCanvas(UCanvas* canvas, int32 minX, int32 minY, int32 maxX, int32 maxY) | |
{ | |
ClipCanvas(canvas, true, minX, minY, maxX, maxY); | |
} | |
void ClipCanvas(FCanvas* canvas, int32 minX, int32 minY, int32 maxX, int32 maxY) | |
{ | |
ClipCanvas(canvas, true, minX, minY, maxX, maxY); | |
} | |
void ClearCanvasClip(UCanvas* canvas) | |
{ | |
ClipCanvas(canvas, false, 0, 0, 0, 0); | |
} | |
void ClearCanvasClip(FCanvas* canvas) | |
{ | |
ClipCanvas(canvas, false, 0, 0, 0, 0); | |
} | |
// Blueprint related code below, remove if not required | |
AHUDEx::AHUDEx(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP) | |
{ | |
} | |
void AHUDEx::ClipHUD(int32 minX, int32 minY, int32 maxX, int32 maxY) | |
{ | |
ClipCanvas(Canvas, true, minX, minY, maxX, maxY); | |
} | |
void AHUDEx::ClearHUDClip() | |
{ | |
ClearCanvasClip(Canvas); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
// Could call GetSortElement directly but it seems to cause a linker errors | |
FCanvas::FCanvasSortElement& Canvas_GetSortElement(FCanvas& canvas, int32 DepthSortKey); | |
void ClipCanvas(UCanvas* canvas, bool enable, int32 minX, int32 minY, int32 maxX, int32 maxY); | |
void ClipCanvas(FCanvas* canvas, bool enable, int32 minX, int32 minY, int32 maxX, int32 maxY); | |
void ClipCanvas(UCanvas* canvas, int32 minX, int32 minY, int32 maxX, int32 maxY); | |
void ClipCanvas(FCanvas* canvas, int32 minX, int32 minY, int32 maxX, int32 maxY); | |
void ClearCanvasClip(UCanvas* canvas); | |
void ClearCanvasClip(FCanvas* canvas); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "HUDEx.generated.h" | |
UCLASS() | |
class AHUDEx : public AHUD | |
{ | |
GENERATED_UCLASS_BODY() | |
UFUNCTION(BlueprintCallable, Category = HUD, meta = (FriendlyName = "Clip")) | |
void ClipHUD(int32 minX, int32 minY, int32 maxX, int32 maxY); | |
UFUNCTION(BlueprintCallable, Category = HUD, meta = (FriendlyName = "Clear Clip")) | |
void ClearHUDClip(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
With Unreal 4.24 ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER will look like this: