Skip to content

Commit 5c6fb34

Browse files
committed
Added Brush support. Modified structs. Fixed client time.
- Brushes are now supported and can be included with a SlateBrush. - The variables in PenData and LineData structs have been changed. - Added internal function to the widget to draw rotated boxes. - Lines are assigned time when replicated so they decay correctly. - Fixed culling settings in the Canvas Manager. Now you can set 1 culling method instead of an all or nothing.
1 parent ca30fdf commit 5c6fb34

5 files changed

Lines changed: 97 additions & 25 deletions

File tree

-149 Bytes
Binary file not shown.

Source/ReplicatedDrawingWidgetPlugin/Private/Canvas/ReplicatedCanvasWidgetBase.cpp

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@
1616
#include "Curves/CurveFloat.h"
1717
#include "GameFramework/PlayerState.h"
1818
#include "Kismet/GameplayStatics.h"
19+
#include "Slate/SlateBrushAsset.h"
1920

2021

2122
void UReplicatedCanvasWidgetBase::DrawLines(FPaintContext& context) const{
23+
FVector2D currentPos = FVector2D::ZeroVector;
24+
FVector2D lineDirection = FVector2D::ZeroVector;
2225
for (const FCanvasLineData& line : LineData) {
2326
if(ShouldDrawLine(line)) {
2427
FLinearColor color(line.PenData.Tint);
2528
const float lineLife = line.GetLineLifetime(GetWorld());
26-
float size = line.PenData.Size;
29+
float sizeScalar = 1.f;
2730
if (FadeDuration > 0 && EraseTime > 0 && lineLife > (EraseTime - FadeDuration)) {
2831
const float fadeAmount = ( (EraseTime - lineLife) / FadeDuration);
2932

@@ -43,18 +46,40 @@ void UReplicatedCanvasWidgetBase::DrawLines(FPaintContext& context) const{
4346
/* Size Fade */ {
4447
const auto sizeFadeType = line.PenData.SizeFadeType;
4548
if (sizeFadeType == EPenDataFadeType::PENFADETYPE_Linear) {
46-
size *= fadeAmount;
49+
sizeScalar *= fadeAmount;
4750
}
4851
if (sizeFadeType == EPenDataFadeType::PENFADETYPE_Curve) {
4952
if (line.PenData.SizeFadeCurve) {
50-
size *= FMath::Abs(line.PenData.SizeFadeCurve->GetFloatValue(1-fadeAmount));
53+
sizeScalar *= FMath::Abs(line.PenData.SizeFadeCurve->GetFloatValue(1-fadeAmount));
5154
}
5255
}
5356

5457
}
5558
}
56-
UWidgetBlueprintLibrary::DrawSpline(context, line.StartingPoint, line.StartingDirection, line.StoppingPoint, line.StoppingDirection, color, size);
57-
59+
if (line.PenData.Brush) {
60+
const FVector2D brushSize = line.PenData.BrushSize * sizeScalar;
61+
currentPos = line.StartingPoint;
62+
lineDirection = (line.StoppingPoint - currentPos).GetSafeNormal();
63+
float rotationAngle = 0.f;
64+
if (line.PenData.bBrushFollowsLine) {
65+
rotationAngle = FMath::RadiansToDegrees(FMath::Atan2(lineDirection.X, -lineDirection.Y));
66+
while (rotationAngle < 0.f) { rotationAngle += 360.f; }
67+
while (rotationAngle > 360.f) { rotationAngle -= 360.f; }
68+
}
69+
while (currentPos != line.StoppingPoint) {
70+
MakeRotatedBrush(context, line.PenData, brushSize, currentPos, rotationAngle);
71+
if ((currentPos - line.StoppingPoint).Size() <= line.PenData.StepSize) {
72+
currentPos = line.StoppingPoint;
73+
}
74+
else {
75+
currentPos += lineDirection * line.PenData.StepSize;
76+
}
77+
}
78+
MakeRotatedBrush(context, line.PenData, brushSize, currentPos, rotationAngle);
79+
}
80+
else {
81+
UWidgetBlueprintLibrary::DrawLine(context, line.StartingPoint, line.StoppingPoint, color, false, sizeScalar * line.PenData.LineSize);
82+
}
5883
}
5984
}
6085
}
@@ -81,6 +106,21 @@ void UReplicatedCanvasWidgetBase::TrySetupCanvasManager() {
81106
}
82107
}
83108

109+
void UReplicatedCanvasWidgetBase::MakeRotatedBrush(FPaintContext& context, const FCanvasPenData& penData, FVector2D brushSize, FVector2D pos, float rotation) const {
110+
context.MaxLayer++;
111+
FSlateDrawElement::MakeRotatedBox(
112+
context.OutDrawElements,
113+
context.MaxLayer,
114+
context.AllottedGeometry.ToPaintGeometry(brushSize, FSlateLayoutTransform(pos - (brushSize/2))),
115+
&penData.Brush->Brush,
116+
ESlateDrawEffect(penData.DrawEffect),
117+
rotation,
118+
TOptional<FVector2f>(),
119+
FSlateDrawElement::RelativeToElement,
120+
penData.Tint
121+
);
122+
}
123+
84124
void UReplicatedCanvasWidgetBase::NativeConstruct() {
85125
Super::NativeConstruct();
86126

@@ -132,6 +172,7 @@ FReply UReplicatedCanvasWidgetBase::NativeOnMouseButtonDown(const FGeometry& InG
132172
}
133173

134174
FReply UReplicatedCanvasWidgetBase::NativeOnMouseMove(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) {
175+
UKismetSystemLibrary::PrintString(this, "We hit");
135176
if (ShouldDraw()) {
136177

137178
FVector2D currentPosition = InGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition());
@@ -143,7 +184,7 @@ FReply UReplicatedCanvasWidgetBase::NativeOnMouseMove(const FGeometry& InGeometr
143184
currentDirection = InMouseEvent.GetGestureDelta();
144185
}
145186
if (bStartedDrawing) {
146-
const FCanvasLineData line(GetDrawerName(), BoardID, UGameplayStatics::GetTimeSeconds(GetWorld()), LastPosition, LastDirection, currentPosition, currentDirection, PenData);
187+
const FCanvasLineData line(GetDrawerName(), BoardID, UGameplayStatics::GetTimeSeconds(GetWorld()), LastPosition, currentPosition, PenData);
147188
LineData.Add(line);
148189
AddLineToState(line);
149190
}
@@ -174,7 +215,7 @@ void UReplicatedCanvasWidgetBase::OnLineAddedToBoard(FName board, const FCanvasL
174215
return;
175216
}
176217
if (line.DrawingPlayer != GetDrawerName() && BoardID != line.BoardID) {
177-
LineData.Add(line);
218+
LineData.Add(FCanvasLineData(line, UGameplayStatics::GetTimeSeconds(GetWorld())));
178219
}
179220
}
180221

@@ -216,7 +257,7 @@ FName UReplicatedCanvasWidgetBase::GetDrawerName_Implementation() {
216257

217258
bool UReplicatedCanvasWidgetBase::ShouldDraw_Implementation() const {
218259

219-
if (!bWantsToDraw || !(PenData.Size > 0) || !(PenData.Tint.A > 0)) {
260+
if (!bWantsToDraw || PenData.HasNoSize() || !(PenData.Tint.A > 0)) {
220261
return false;
221262
}
222263

Source/ReplicatedDrawingWidgetPlugin/Private/Canvas/ReplicatedCanvasWidgetBase.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ UCLASS()
1818
class REPLICATEDDRAWINGWIDGETPLUGIN_API UReplicatedCanvasWidgetBase : public UUserWidget {
1919
GENERATED_BODY()
2020

21+
2122
// Basically a tick function that draws lines.
2223
void DrawLines(FPaintContext& context) const;
2324
// Tick function that deletes unused lines outside the EraseTime.
2425
void CleanupLines();
2526
/* Tick function that attempts to set up maanger. If it's already set this does nothing. ONLY ONE CANVAS MANAGER SHOULD BE USED PER MAP. */
2627
void TrySetupCanvasManager();
27-
28+
29+
30+
//
31+
void MakeRotatedBrush(FPaintContext& context, const FCanvasPenData& penData, FVector2D brushSize, FVector2D pos, float rotation) const;
2832
bool bWantsToDraw = false;
2933
bool bStartedDrawing = false;
3034
TArray<FCanvasLineData> LineData;

Source/ReplicatedDrawingWidgetPlugin/Private/CanvasHelpers/ReplicatedCanvasManager.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,13 @@ void AReplicatedCanvasManager::CleanLines() {
6060
}
6161

6262
for (FReplicatedCanvasData& board : Boards) {
63-
while (board.Lines.Num() > 0 && (board.Lines.Num() > MaxNumberOfLines || board.Lines[0].GetLineLifetime(GetWorld()) > MaxLineDuration)) {
64-
board.Lines.RemoveAt(0);
63+
64+
while (board.Lines.Num() > 0) {
65+
const bool timeCull = MaxLineDuration > 0 ? board.Lines[0].GetLineLifetime(GetWorld()) > MaxLineDuration : false;
66+
const bool numCull = MaxNumberOfLines > 0 ? board.Lines.Num() > MaxNumberOfLines : false;
67+
if (timeCull || numCull) {
68+
board.Lines.RemoveAt(0);
69+
}
6570
}
6671

6772
}

Source/ReplicatedDrawingWidgetPlugin/Public/CanvasHelpers/ReplicatedCanvasData.h

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,35 @@ enum EPenDataFadeType : uint8 {
1818
PENFADETYPE_Curve = 2 UMETA(DisplayName = "Curve"),
1919
};
2020

21+
UENUM(BlueprintType)
22+
enum class EPenDrawEffect : uint8 {
23+
/** No effect applied */
24+
PENEFFECT_None = 0 UMETA(DisplayName = "None"),
25+
/** Advanced: Draw the element with no blending */
26+
PENEFFECT_NoBlending = 1 << 0 UMETA(DisplayName = "No Blending"),
27+
/** Advanced: Blend using pre-multiplied alpha. Ignored if NoBlending is set. */
28+
PENEFFECT_PreMultipliedAlpha = 1 << 1 UMETA(DisplayName = "Pre-Multiplied Alpha"),
29+
/** Advanced: No gamma correction should be done */
30+
PENEFFECT_NoGamma = 1 << 2 UMETA(DisplayName = "No Gamma"),
31+
/** Advanced: Change the alpha value to 1 - Alpha. */
32+
PENEFFECT_InvertAlpha = 1 << 3 UMETA(DisplayName = "Invert Alpha"),
33+
};
2134
USTRUCT(BlueprintType)
2235
struct FCanvasPenData {
2336
GENERATED_BODY()
2437

2538
FCanvasPenData() {}
2639

2740
/* Brush used to draw the line. THIS IS NOT IMPLEMENTED*/
28-
UPROPERTY( /* EditAnywhere, */ BlueprintReadWrite, Category = "Pen")
41+
UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Pen")
2942
TObjectPtr<USlateBrushAsset> Brush = nullptr;
3043

44+
UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Pen")
45+
bool bBrushFollowsLine = false;
46+
47+
UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Pen")
48+
EPenDrawEffect DrawEffect = EPenDrawEffect::PENEFFECT_None;
49+
3150
/* Distance between each stamp of the brush. */
3251
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pen", meta=(EditCondition = "Brush != nullptr", EditConditionHides))
3352
float StepSize = 1.f;
@@ -37,9 +56,13 @@ struct FCanvasPenData {
3756
FLinearColor Tint = FColor::White;
3857

3958
/* Size of the line. */
40-
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pen", meta=(EditCondition = "Brush == nullptr", EditConditionHides))
41-
float Size = 1.f;
59+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pen", meta=(EditCondition = "Brush != nullptr", EditConditionHides))
60+
FVector2D BrushSize = FVector2D::One();
4261

62+
/* Size of the line. */
63+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pen", meta=(EditCondition = "Brush == nullptr", EditConditionHides))
64+
float LineSize = 1.f;
65+
4366
/* Determines how the opacity fades if the board supports fading. */
4467
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pen|Fading")
4568
TEnumAsByte<EPenDataFadeType> OpacityFadeType = EPenDataFadeType::PENFADETYPE_Linear;
@@ -55,16 +78,20 @@ struct FCanvasPenData {
5578
/* A curve that makes the line size decrease if the board fades lines. The value used will be an absolute value of -1 to 1. */
5679
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pen|Fading", meta=(EditCondition = "SizeFadeType == EPenDataFadeType::PENFADETYPE_Curve", EditConditionHides))
5780
TObjectPtr<UCurveFloat> SizeFadeCurve = nullptr;
58-
81+
82+
bool HasNoSize() const { return Brush != nullptr ? BrushSize.GetMin() <= 0 : LineSize <= 0.f; }
5983
};
6084

6185
USTRUCT(BlueprintType)
6286
struct FCanvasLineData {
6387
GENERATED_BODY()
6488

6589
FCanvasLineData() {}
66-
FCanvasLineData(FName boardName, int boardID, float time, FVector2D startP, FVector2D startD, FVector2D stopP, FVector2D stopD, FCanvasPenData penData = FCanvasPenData()) :
67-
DrawingPlayer(boardName), BoardID(boardID), DrawnTime(time), StartingPoint(startP), StartingDirection(startD), StoppingPoint(stopP), StoppingDirection(stopD), PenData(penData)
90+
FCanvasLineData(const FCanvasLineData& line, float newTime) :
91+
DrawingPlayer(line.DrawingPlayer), BoardID(line.BoardID), DrawnTime(newTime), StartingPoint(line.StartingPoint), StoppingPoint(line.StoppingPoint), PenData(line.PenData)
92+
{};
93+
FCanvasLineData(FName drawerName, int boardID, float time, FVector2D startingPoint, FVector2D stoppingPoint, FCanvasPenData penData = FCanvasPenData()) :
94+
DrawingPlayer(drawerName), BoardID(boardID), DrawnTime(time), StartingPoint(startingPoint), StoppingPoint(stoppingPoint), PenData(penData)
6895
{};
6996

7097
/* Player that drew the line. */
@@ -79,19 +106,14 @@ struct FCanvasLineData {
79106
/* The starting point of the line. */
80107
UPROPERTY(BlueprintReadOnly, Category = "Line")
81108
FVector2D StartingPoint = FVector2D::ZeroVector;
82-
/* The starting direction the cursor was going when the line was started. */
83-
UPROPERTY(BlueprintReadOnly, Category = "Line")
84-
FVector2D StartingDirection = FVector2D::ZeroVector;
85-
/* Stopping Point of the line. */
109+
/* The stopping point of the line. */
86110
UPROPERTY(BlueprintReadOnly, Category = "Line")
87111
FVector2D StoppingPoint = FVector2D::ZeroVector;
88-
/* The stopping direction the cursor was going when the line was started. */
89-
UPROPERTY(BlueprintReadOnly, Category = "Line")
90-
FVector2D StoppingDirection = FVector2D::ZeroVector;
91112
/* Pen data that is used for drawing the line. */
92113
UPROPERTY(BlueprintReadOnly, Category = "Line")
93114
FCanvasPenData PenData = FCanvasPenData();
94-
115+
95116
/* Returns how long since the line has been drawn. */
96117
float GetLineLifetime(UObject* worldContext) const;
118+
97119
};

0 commit comments

Comments
 (0)