mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 17:45:23 +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)
|
void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
||||||
|
{
|
||||||
|
CurrentLine = InLine;
|
||||||
|
RemainingLinePart = CurrentLine.ToString();
|
||||||
|
PlayNextLinePart(Speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTypewriterTextWidget::PlayNextLinePart(float Speed)
|
||||||
{
|
{
|
||||||
check(GetWorld());
|
check(GetWorld());
|
||||||
|
|
||||||
FTimerManager& TimerManager = GetWorld()->GetTimerManager();
|
FTimerManager& TimerManager = GetWorld()->GetTimerManager();
|
||||||
TimerManager.ClearTimer(LetterTimer);
|
TimerManager.ClearTimer(LetterTimer);
|
||||||
|
|
||||||
CurrentLine = InLine;
|
|
||||||
CurrentRunName = "";
|
CurrentRunName = "";
|
||||||
CurrentLetterIndex = 0;
|
CurrentLetterIndex = 0;
|
||||||
CachedLetterIndex = 0;
|
CachedLetterIndex = 0;
|
||||||
@ -87,7 +93,7 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
|||||||
Segments.Empty();
|
Segments.Empty();
|
||||||
CachedSegmentText.Empty();
|
CachedSegmentText.Empty();
|
||||||
|
|
||||||
if (CurrentLine.IsEmpty())
|
if (RemainingLinePart.IsEmpty())
|
||||||
{
|
{
|
||||||
if (IsValid(LineText))
|
if (IsValid(LineText))
|
||||||
{
|
{
|
||||||
@ -107,6 +113,7 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
|||||||
LineText->SetText(FText::GetEmpty());
|
LineText->SetText(FText::GetEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bHasMoreLineParts = false;
|
||||||
bHasFinishedPlaying = false;
|
bHasFinishedPlaying = false;
|
||||||
|
|
||||||
if (bFirstPlayLine)
|
if (bFirstPlayLine)
|
||||||
@ -127,7 +134,20 @@ void UTypewriterTextWidget::PlayLine(const FText& InLine, float Speed)
|
|||||||
|
|
||||||
void UTypewriterTextWidget::StartPlayLine()
|
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;
|
FTimerDelegate Delegate;
|
||||||
Delegate.BindUObject(this, &ThisClass::PlayNextLetter);
|
Delegate.BindUObject(this, &ThisClass::PlayNextLetter);
|
||||||
@ -214,7 +234,56 @@ bool UTypewriterTextWidget::IsSentenceTerminator(TCHAR Letter)
|
|||||||
return Letter == '.' || Letter == '!' || 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:
|
// Rich Text views give you:
|
||||||
// - A blank block at the start for some reason
|
// - 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
|
// - 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
|
// If we've got here, that means the text isn't empty so 1 line at least
|
||||||
NumberOfLines = 1;
|
NumberOfLines = 1;
|
||||||
|
MaxLetterIndex = 0;
|
||||||
|
CombinedTextHeight = 0;
|
||||||
|
Segments.Empty();
|
||||||
if (IsValid(LineText) && LineText->GetTextLayout().IsValid())
|
if (IsValid(LineText) && LineText->GetTextLayout().IsValid())
|
||||||
{
|
{
|
||||||
TSharedPtr<FSlateTextLayout> Layout = LineText->GetTextLayout();
|
TSharedPtr<FSlateTextLayout> Layout = LineText->GetTextLayout();
|
||||||
@ -233,7 +305,7 @@ void UTypewriterTextWidget::CalculateWrappedString()
|
|||||||
|
|
||||||
Layout->ClearLines();
|
Layout->ClearLines();
|
||||||
Layout->SetWrappingWidth(TextBoxSize.X);
|
Layout->SetWrappingWidth(TextBoxSize.X);
|
||||||
Marshaller->SetText(CurrentLine.ToString(), *Layout.Get());
|
Marshaller->SetText(CurrentLineString, *Layout.Get());
|
||||||
Layout->UpdateLayout();
|
Layout->UpdateLayout();
|
||||||
|
|
||||||
bool bHasWrittenText = false;
|
bool bHasWrittenText = false;
|
||||||
@ -299,7 +371,7 @@ void UTypewriterTextWidget::CalculateWrappedString()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Segments.Add(FTypewriterTextSegment{CurrentLine.ToString()});
|
Segments.Add(FTypewriterTextSegment{CurrentLineString});
|
||||||
MaxLetterIndex = Segments[0].Text.Len();
|
MaxLetterIndex = Segments[0].Text.Len();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,10 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Typewriter")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Typewriter")
|
||||||
float PauseTimeAtSentenceTerminators = 0.5f;
|
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
|
/// Set Text immediately
|
||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
void SetText(const FText& InText);
|
void SetText(const FText& InText);
|
||||||
@ -92,16 +96,33 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
FText GetText() const;
|
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")
|
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||||
void PlayLine(const FText& InLine, float Speed = 1.0f);
|
void PlayLine(const FText& InLine, float Speed = 1.0f);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||||
void GetCurrentLine(FText& OutLine) const { OutLine = CurrentLine; }
|
void GetCurrentLine(FText& OutLine) const { OutLine = CurrentLine; }
|
||||||
|
|
||||||
|
/// Return whether the entire line has finished playing
|
||||||
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||||
bool HasFinishedPlayingLine() const { return bHasFinishedPlaying; }
|
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")
|
UFUNCTION(BlueprintCallable, Category = "Typewriter")
|
||||||
void SkipToLineEnd();
|
void SkipToLineEnd();
|
||||||
|
|
||||||
@ -127,15 +148,18 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void PlayNextLetter();
|
void PlayNextLetter();
|
||||||
static bool IsSentenceTerminator(TCHAR Letter);
|
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);
|
FString CalculateSegments(FString* OutCurrentRunName);
|
||||||
void StartPlayLine();
|
void StartPlayLine();
|
||||||
|
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
FText CurrentLine;
|
FText CurrentLine;
|
||||||
|
|
||||||
|
FString RemainingLinePart;
|
||||||
|
|
||||||
struct FTypewriterTextSegment
|
struct FTypewriterTextSegment
|
||||||
{
|
{
|
||||||
@ -158,6 +182,7 @@ private:
|
|||||||
float CombinedTextHeight = 0;
|
float CombinedTextHeight = 0;
|
||||||
|
|
||||||
uint32 bHasFinishedPlaying : 1;
|
uint32 bHasFinishedPlaying : 1;
|
||||||
|
uint32 bHasMoreLineParts : 1;
|
||||||
|
|
||||||
FTimerHandle LetterTimer;
|
FTimerHandle LetterTimer;
|
||||||
float CurrentPlaySpeed = 1;
|
float CurrentPlaySpeed = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user