diff --git a/Source/StevesUEHelpers/Private/StevesUI/TypewriterTextWidget.cpp b/Source/StevesUEHelpers/Private/StevesUI/TypewriterTextWidget.cpp index 681a377..ff0777b 100644 --- a/Source/StevesUEHelpers/Private/StevesUI/TypewriterTextWidget.cpp +++ b/Source/StevesUEHelpers/Private/StevesUI/TypewriterTextWidget.cpp @@ -42,6 +42,7 @@ TSharedRef URichTextBlockForTypewriter::RebuildWidget() UTypewriterTextWidget::UTypewriterTextWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { + bHasMoreLineParts = false; bHasFinishedPlaying = true; } @@ -54,6 +55,7 @@ void UTypewriterTextWidget::SetText(const FText& InText) LineText->SetText(InText); + bHasMoreLineParts = false; bHasFinishedPlaying = true; } } @@ -69,13 +71,19 @@ FText UTypewriterTextWidget::GetText() const } void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed) +{ + CurrentLine = InLine; + RemainingLinePart = CurrentLine.ToString(); + PlayNextLinePart(Speed); +} + +void UTypewriterTextWidget::PlayNextLinePart(float Speed) { check(GetWorld()); FTimerManager& TimerManager = GetWorld()->GetTimerManager(); TimerManager.ClearTimer(LetterTimer); - CurrentLine = InLine; CurrentRunName = ""; CurrentLetterIndex = 0; CachedLetterIndex = 0; @@ -87,13 +95,14 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed) Segments.Empty(); CachedSegmentText.Empty(); - if (CurrentLine.IsEmpty()) + if (RemainingLinePart.IsEmpty()) { if (IsValid(LineText)) { LineText->SetText(FText::GetEmpty()); } + bHasMoreLineParts = false; bHasFinishedPlaying = true; OnTypewriterLineFinished.Broadcast(this); OnLineFinishedPlaying(); @@ -107,11 +116,12 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed) LineText->SetText(FText::GetEmpty()); } + bHasMoreLineParts = false; bHasFinishedPlaying = false; LineText->SetText(FText()); - const FString& currentLineString = CurrentLine.ToString(); + const FString& currentLineString = RemainingLinePart; CalculateWrappedString(currentLineString); int maxLines = 3; @@ -139,7 +149,8 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed) int lastTerminator = currentLineString.FindLastCharByPredicate(IsSentenceTerminator, numLetters); if (lastTerminator != INDEX_NONE) { - const FString& shortenedString = currentLineString.Left(lastTerminator + 1); + int count = lastTerminator + 1; + const FString& shortenedString = currentLineString.Left(count); CurrentRunName = ""; CurrentLetterIndex = 0; @@ -154,10 +165,8 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed) CalculateWrappedString(shortenedString); - // TODO Jonas: Play remaining line after the shortened string. - // If this is done purely in the typewriter then advancing the dialog would - // skip over all but the last part of the text. Alternatively advancing has - // to get rerouted to trigger a dialogue action only for the last part. + RemainingLinePart.RightInline(count); + bHasMoreLineParts = true; } } @@ -181,9 +190,16 @@ void UTypewriterTextWidget::SkipToLineEnd() LineText->SetText(FText::FromString(CalculateSegments(nullptr))); } - bHasFinishedPlaying = true; - OnTypewriterLineFinished.Broadcast(this); - OnLineFinishedPlaying(); + if (bHasMoreLineParts) + { + OnTypewriterLinePartFinished.Broadcast(this); + } + else + { + bHasFinishedPlaying = true; + OnTypewriterLineFinished.Broadcast(this); + OnLineFinishedPlaying(); + } } void UTypewriterTextWidget::PlayNextLetter() diff --git a/Source/StevesUEHelpers/Public/StevesUI/TypewriterTextWidget.h b/Source/StevesUEHelpers/Public/StevesUI/TypewriterTextWidget.h index b9ff31f..e453961 100644 --- a/Source/StevesUEHelpers/Public/StevesUI/TypewriterTextWidget.h +++ b/Source/StevesUEHelpers/Public/StevesUI/TypewriterTextWidget.h @@ -56,6 +56,10 @@ class STEVESUEHELPERS_API UTypewriterTextWidget : public UUserWidget public: UTypewriterTextWidget(const FObjectInitializer& ObjectInitializer); + /// Event called when a line part has finished playing, whether on its own or when skipped to end + UPROPERTY(BlueprintAssignable) + FOnTypewriterLineFinished OnTypewriterLinePartFinished; + /// Event called when a line has finished playing, whether on its own or when skipped to end UPROPERTY(BlueprintAssignable) FOnTypewriterLineFinished OnTypewriterLineFinished; @@ -102,6 +106,9 @@ public: UFUNCTION(BlueprintCallable, Category = "Typewriter") bool HasFinishedPlayingLine() const { return bHasFinishedPlaying; } + UFUNCTION(BlueprintCallable, Category = "Typewriter") + void PlayNextLinePart(float Speed = 1.0f); + UFUNCTION(BlueprintCallable, Category = "Typewriter") void SkipToLineEnd(); @@ -132,7 +139,7 @@ private: UPROPERTY() FText CurrentLine; - + FString RemainingLinePart; struct FTypewriterTextSegment { @@ -155,6 +162,7 @@ private: float CombinedTextHeight = 0; uint32 bHasFinishedPlaying : 1; + uint32 bHasMoreLineParts : 1; FTimerHandle LetterTimer; float CurrentPlaySpeed = 1;