1+ // Fill out your copyright notice in the Description page of Project Settings.
2+
3+
4+ #include " ReplicatedCanvasWidgetBase.h"
5+
6+ #include " EngineUtils.h"
7+ #include " Blueprint/WidgetBlueprintLibrary.h"
8+ #include " Blueprint/WidgetTree.h"
9+ #include " CanvasHelpers/CanvasPlayerStateHelper.h"
10+ #include " CanvasHelpers/ReplicatedCanvasManager.h"
11+ #include " CanvasHelpers/WorldCanvasSubsystem.h"
12+ #include " Components/Border.h"
13+ #include " Components/Overlay.h"
14+ #include " Components/OverlaySlot.h"
15+ #include " GameFramework/PlayerState.h"
16+ #include " Kismet/GameplayStatics.h"
17+
18+
19+ void UReplicatedCanvasWidgetBase::DrawLines (FPaintContext& context) const {
20+ for (const FCanvasLineData& line : LineData) {
21+ if (ShouldDrawLine (line)) {
22+ FLinearColor color (line.Tint );
23+ color *= Tint;
24+ const float lineLife = line.GetLineLife (GetWorld ());
25+ if (FadeDuration > 0 && EraseTime > 0 && lineLife > (EraseTime - FadeDuration)) {
26+ const float fadeOpacity = (EraseTime - lineLife) / FadeDuration;
27+ color.A *= FMath::Clamp (fadeOpacity, 0 .f , 1 .f );
28+ }
29+ UWidgetBlueprintLibrary::DrawSpline (context, line.StartingPoint , line.StartingDirection , line.StoppingPoint , line.StoppingDirection , color, line.Size );
30+ }
31+ }
32+ }
33+
34+ void UReplicatedCanvasWidgetBase::CleanupLines (){
35+ if (EraseTime <= 0 ) {
36+ return ;
37+ }
38+ while (LineData.Num () > 0 && LineData[0 ].GetLineLife (GetWorld ()) > EraseTime) {
39+ LineData.RemoveAt (0 );
40+ }
41+ }
42+
43+ // UReplicatedCanvasWidgetBase::UReplicatedCanvasWidgetBase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) {
44+ //
45+ // }
46+
47+ void UReplicatedCanvasWidgetBase::TrySetupReplicator () {
48+ if (Replicator) { return ; }
49+
50+ if (const auto subsys = GetWorld ()->GetSubsystem <UWorldCanvasSubsystem>()) {
51+
52+ Replicator = subsys->Replicator ;
53+ if (Replicator) {
54+ Replicator->OnLineAdded .AddDynamic (this , &UReplicatedCanvasWidgetBase::OnLineAddedToBoard);
55+ }
56+ }
57+ }
58+
59+ void UReplicatedCanvasWidgetBase::NativeConstruct () {
60+ Super::NativeConstruct ();
61+
62+ if (!WidgetTree) { return ; }
63+
64+ UOverlay* root = WidgetTree->ConstructWidget <UOverlay>(UOverlay::StaticClass (), TEXT (" OverlayRoot" ));
65+ WidgetTree->RootWidget = root;
66+
67+ DrawingPad = WidgetTree->ConstructWidget <UBorder>(UBorder::StaticClass (), TEXT (" DrawingPad" ));
68+ DrawingPad->SetVisibility (ESlateVisibility::Visible);
69+ DrawingPad->SetBrushColor (FLinearColor (0 , 0 , 0 , 0 ));
70+
71+ if (UOverlaySlot* slot = root->AddChildToOverlay (DrawingPad)) {
72+ slot->SetHorizontalAlignment (HAlign_Fill);
73+ slot->SetHorizontalAlignment (HAlign_Fill);
74+ }
75+
76+ SetVisibility (ESlateVisibility::Visible);
77+ SetIsEnabled (true );
78+ SetIsFocusable (true );
79+
80+ }
81+
82+ void UReplicatedCanvasWidgetBase::NativeTick (const FGeometry& MyGeometry, float InDeltaTime) {
83+ Super::NativeTick (MyGeometry, InDeltaTime);
84+ TrySetupReplicator ();
85+ CleanupLines ();
86+ }
87+
88+ int32 UReplicatedCanvasWidgetBase::NativePaint (const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
89+ const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const {
90+
91+ FPaintContext context (AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
92+ DrawLines (context);
93+ if (ShouldDraw ()) {
94+
95+ }
96+ return Super::NativePaint (Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
97+ }
98+
99+ #pragma region Mouse Overrides
100+ FReply UReplicatedCanvasWidgetBase::NativeOnMouseButtonDown (const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) {
101+ if (InMouseEvent.GetEffectingButton () == FKey (" LeftMouseButton" )) {
102+ bWantsToDraw = true ;
103+
104+ }
105+
106+ return Super::NativeOnMouseButtonDown (InGeometry, InMouseEvent);
107+ }
108+
109+ FReply UReplicatedCanvasWidgetBase::NativeOnMouseMove (const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) {
110+ if (ShouldDraw ()) {
111+
112+ FVector2D currentPosition = InGeometry.AbsoluteToLocal ( InMouseEvent.GetScreenSpacePosition ());
113+ FVector2D currentDirection = FVector2D::ZeroVector;
114+ if (InMouseEvent.IsPointerEvent ()) {
115+ currentDirection = InMouseEvent.GetCursorDelta ();
116+ }
117+ if (InMouseEvent.IsTouchEvent ()) {
118+ currentDirection = InMouseEvent.GetGestureDelta ();
119+ }
120+ if (bStartedDrawing) {
121+ const FCanvasLineData line (GetDrawerName (), UGameplayStatics::GetTimeSeconds (GetWorld ()), LastPosition, LastDirection, currentPosition, currentDirection, PenData.Size , PenData.Tint );
122+ LineData.Add (line);
123+ AddLineToState (line);
124+ }
125+ else {
126+ bStartedDrawing = true ;
127+ }
128+ LastPosition = currentPosition;
129+ LastDirection = currentDirection;
130+ }
131+ return Super::NativeOnMouseMove (InGeometry, InMouseEvent);
132+ }
133+
134+ FReply UReplicatedCanvasWidgetBase::NativeOnMouseButtonUp (const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) {
135+ bWantsToDraw = false ;
136+ bStartedDrawing = false ;
137+ return Super::NativeOnMouseButtonUp (InGeometry, InMouseEvent);
138+ }
139+
140+ void UReplicatedCanvasWidgetBase::NativeOnMouseLeave (const FPointerEvent& InMouseEvent) {
141+ Super::NativeOnMouseLeave (InMouseEvent);
142+ bWantsToDraw = false ;
143+ bStartedDrawing = false ;
144+ }
145+ #pragma endregion Mouse Overrides
146+
147+ void UReplicatedCanvasWidgetBase::OnLineAddedToBoard (FName board, const FCanvasLineData& line) {
148+ UKismetSystemLibrary::PrintString (this , " Func Hit" );
149+
150+ if (board != BoardName) {
151+ return ;
152+ }
153+ if (true ){// line.DrawingPlayer != GetDrawerName()) {
154+ LineData.Add (line);
155+ UKismetSystemLibrary::PrintString (this , " Line Added" );
156+ }
157+ }
158+
159+ void UReplicatedCanvasWidgetBase::RefreshFromReplicator () {
160+ LineData.Empty ();
161+ if (Replicator) {
162+ LineData = Replicator->GetCanvasLines (BoardName);
163+ }
164+ }
165+
166+ void UReplicatedCanvasWidgetBase::CleanBoard () {
167+ LineData.Empty ();
168+ if (Replicator) {
169+ Replicator->CleanBoard (BoardName);
170+ }
171+ }
172+
173+ void UReplicatedCanvasWidgetBase::AddLineToState (const FCanvasLineData& line) {
174+ if (!StateHelper) {
175+ if (APlayerState* state = GetOwningPlayerState ()) {
176+ StateHelper = Cast<UCanvasPlayerStateHelper>(state->GetComponentByClass (UCanvasPlayerStateHelper::StaticClass ()));
177+ }
178+ }
179+
180+ if (StateHelper) {
181+
182+ StateHelper->AddLine (BoardName, line);
183+ }
184+ }
185+
186+ FName UReplicatedCanvasWidgetBase::GetDrawerName_Implementation () {
187+ if (DrawerName == FName ()) {
188+ DrawerName = FName (GetOwningPlayerState (true )->GetPlayerName ());
189+ }
190+ return DrawerName;
191+ }
192+
193+ bool UReplicatedCanvasWidgetBase::ShouldDraw_Implementation () const {
194+
195+ if (!bWantsToDraw || !(PenData.Size > 0 ) || !(PenData.Tint .A > 0 )) {
196+ return false ;
197+ }
198+
199+ return true ;
200+ }
0 commit comments