mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 09:35:25 +00:00
Merge branch 'line-splitting'
This commit is contained in:
commit
d102c5de67
@ -69,13 +69,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,7 +93,7 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
||||
Segments.Empty();
|
||||
CachedSegmentText.Empty();
|
||||
|
||||
if (CurrentLine.IsEmpty())
|
||||
if (RemainingLinePart.IsEmpty())
|
||||
{
|
||||
if (IsValid(LineText))
|
||||
{
|
||||
@ -107,6 +113,7 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
||||
LineText->SetText(FText::GetEmpty());
|
||||
}
|
||||
|
||||
bHasMoreLineParts = false;
|
||||
bHasFinishedPlaying = false;
|
||||
|
||||
if (bFirstPlayLine)
|
||||
@ -127,7 +134,20 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
||||
|
||||
void UTypewriterTextWidget::StartPlayLine()
|
||||
{
|
||||
CalculateWrappedString();
|
||||
CalculateWrappedString(RemainingLinePart);
|
||||
|
||||
if (MaxNumberOfLines > 0 && NumberOfLines > MaxNumberOfLines)
|
||||
{
|
||||
int MaxLength = CalculateMaxLength();
|
||||
int TerminatorIndex = FindLastTerminator(RemainingLinePart, MaxLength);
|
||||
int Length = TerminatorIndex + 1;
|
||||
const FString& FirstLinePart = RemainingLinePart.Left(Length);
|
||||
|
||||
CalculateWrappedString(FirstLinePart);
|
||||
|
||||
RemainingLinePart.RightChopInline(Length);
|
||||
bHasMoreLineParts = true;
|
||||
}
|
||||
|
||||
FTimerDelegate Delegate;
|
||||
Delegate.BindUObject(this, &ThisClass::PlayNextLetter);
|
||||
@ -214,7 +234,56 @@ bool UTypewriterTextWidget::IsSentenceTerminator(TCHAR Letter)
|
||||
return Letter == '.' || Letter == '!' || Letter == '?';
|
||||
}
|
||||
|
||||
void UTypewriterTextWidget::CalculateWrappedString()
|
||||
bool UTypewriterTextWidget::IsClauseTerminator(TCHAR Letter)
|
||||
{
|
||||
return Letter == ',' || Letter == ';';
|
||||
}
|
||||
|
||||
int UTypewriterTextWidget::FindLastTerminator(const FString& CurrentLineString, int Count)
|
||||
{
|
||||
int TerminatorIndex = CurrentLineString.FindLastCharByPredicate(IsSentenceTerminator, Count);
|
||||
if (TerminatorIndex != INDEX_NONE)
|
||||
{
|
||||
return TerminatorIndex;
|
||||
}
|
||||
|
||||
TerminatorIndex = CurrentLineString.FindLastCharByPredicate(IsClauseTerminator, Count);
|
||||
if (TerminatorIndex != INDEX_NONE)
|
||||
{
|
||||
return TerminatorIndex;
|
||||
}
|
||||
|
||||
TerminatorIndex = CurrentLineString.FindLastCharByPredicate(FText::IsWhitespace, Count);
|
||||
if (TerminatorIndex != INDEX_NONE)
|
||||
{
|
||||
return TerminatorIndex;
|
||||
}
|
||||
|
||||
return (Count - 1);
|
||||
}
|
||||
|
||||
int UTypewriterTextWidget::CalculateMaxLength()
|
||||
{
|
||||
int MaxLength = 0;
|
||||
int CurrentNumberOfLines = 1;
|
||||
for (int i = 0; i < Segments.Num(); i++)
|
||||
{
|
||||
const FTypewriterTextSegment& Segment = Segments[i];
|
||||
MaxLength += Segment.Text.Len();
|
||||
if (Segment.Text.Equals(FString(TEXT("\n"))))
|
||||
{
|
||||
CurrentNumberOfLines++;
|
||||
if (MaxNumberOfLines > 0 && CurrentNumberOfLines > MaxNumberOfLines)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MaxLength;
|
||||
}
|
||||
|
||||
void UTypewriterTextWidget::CalculateWrappedString(const FString& CurrentLineString)
|
||||
{
|
||||
// Rich Text views give you:
|
||||
// - A blank block at the start for some reason
|
||||
@ -223,6 +292,9 @@ void UTypewriterTextWidget::CalculateWrappedString()
|
||||
// - The newlines we add are the only newlines in the output so that's the number of lines
|
||||
// If we've got here, that means the text isn't empty so 1 line at least
|
||||
NumberOfLines = 1;
|
||||
MaxLetterIndex = 0;
|
||||
CombinedTextHeight = 0;
|
||||
Segments.Empty();
|
||||
if (IsValid(LineText) && LineText->GetTextLayout().IsValid())
|
||||
{
|
||||
TSharedPtr<FSlateTextLayout> Layout = LineText->GetTextLayout();
|
||||
@ -233,7 +305,7 @@ void UTypewriterTextWidget::CalculateWrappedString()
|
||||
|
||||
Layout->ClearLines();
|
||||
Layout->SetWrappingWidth(TextBoxSize.X);
|
||||
Marshaller->SetText(CurrentLine.ToString(), *Layout.Get());
|
||||
Marshaller->SetText(CurrentLineString, *Layout.Get());
|
||||
Layout->UpdateLayout();
|
||||
|
||||
bool bHasWrittenText = false;
|
||||
@ -299,7 +371,7 @@ void UTypewriterTextWidget::CalculateWrappedString()
|
||||
}
|
||||
else
|
||||
{
|
||||
Segments.Add(FTypewriterTextSegment{CurrentLine.ToString()});
|
||||
Segments.Add(FTypewriterTextSegment{CurrentLineString});
|
||||
MaxLetterIndex = Segments[0].Text.Len();
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,10 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Typewriter")
|
||||
float PauseTimeAtSentenceTerminators = 0.5f;
|
||||
|
||||
/// If set > 0, splits a single PlayLine into multiple segments of this number of lines maximum
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Typewriter")
|
||||
int MaxNumberOfLines = 0;
|
||||
|
||||
/// Set Text immediately
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetText(const FText& InText);
|
||||
@ -92,16 +96,33 @@ public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
FText GetText() const;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Play a line of text.
|
||||
* Note: if, when line splits are calculated, this line exceeds MaxNumberOfLines, then only this number of lines
|
||||
* will be played by this call. In that case, HasMoreLineParts() will return true, and you will need to call
|
||||
* PlayNextLinePart() to play the remainder of the line.
|
||||
* @param InLine The input line
|
||||
* @param Speed
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||
void PlayLine(const FText& InLine, float Speed = 1.0f);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||
void GetCurrentLine(FText& OutLine) const { OutLine = CurrentLine; }
|
||||
|
||||
/// Return whether the entire line has finished playing
|
||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||
bool HasFinishedPlayingLine() const { return bHasFinishedPlaying; }
|
||||
|
||||
/// Returns whether the number of lines exceeded MaxNumberOfLines and there are still parts to play.
|
||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||
bool HasMoreLineParts() const { return bHasMoreLineParts; }
|
||||
|
||||
/// If HasMoreLineParts() is true, play the next part of the line originally requested by PlayLine
|
||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||
void PlayNextLinePart(float Speed = 1.0f);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||
void SkipToLineEnd();
|
||||
|
||||
@ -127,15 +148,18 @@ protected:
|
||||
private:
|
||||
void PlayNextLetter();
|
||||
static bool IsSentenceTerminator(TCHAR Letter);
|
||||
static bool IsClauseTerminator(TCHAR Letter);
|
||||
static int FindLastTerminator(const FString& CurrentLineString, int Count);
|
||||
|
||||
void CalculateWrappedString();
|
||||
int CalculateMaxLength();
|
||||
void CalculateWrappedString(const FString& CurrentLineString);
|
||||
FString CalculateSegments(FString* OutCurrentRunName);
|
||||
void StartPlayLine();
|
||||
|
||||
UPROPERTY()
|
||||
FText CurrentLine;
|
||||
|
||||
|
||||
FString RemainingLinePart;
|
||||
|
||||
struct FTypewriterTextSegment
|
||||
{
|
||||
@ -158,6 +182,7 @@ private:
|
||||
float CombinedTextHeight = 0;
|
||||
|
||||
uint32 bHasFinishedPlaying : 1;
|
||||
uint32 bHasMoreLineParts : 1;
|
||||
|
||||
FTimerHandle LetterTimer;
|
||||
float CurrentPlaySpeed = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user