[UE4] RichTextBlock에서 타자기 연출
어드벤처 게임에서 텍스트를 한 글자씩 표시하게 하는 것입니다.
문자 하나만 표시하면 TextBlock으로 충분하지만 문자 색상을 변경하거나 장식을 추가하기 위해 RichTextBlock을 사용하고 싶습니다. 하지만 구문 분석이라든지 어떻게 하는 거야? 라고 이야기가 됩니다.
RichTextBlock 시리즈
[UE4] RichTextBlock에서 루비 흔들기
[UE4] RichTextBlock에서 자체 태그 정의
RichTextBlock 정보 (가볍게)
UMG 리치 텍스트 블록 - 언리얼 엔진 4 문서
고배는 고양이이다. 이름은 아직 없다.
자주 사용하는 기능으로서는 텍스트중의 부분적인 색변이군요. 색상뿐만 아니라 글꼴 스타일 및 기타 장식도 설정할 수 있습니다. 폰트 설정의 부분 변경을 할 수 없거나, 중첩 구조(문자라든지)로 할 수 없거나 하는 것은 어떻게든 하고 싶은 곳입니다만, 조사해 보면 그것은 더 유연하게 확장 할 수 있도록 설계되었습니다 (구현을 읽는 재미). 그 근처는 또 다음번에도.
한 문자씩 표시
자주 있는 구현이라면, FString::Len() 로 문자수를 취득해 텍스트 치환하는 등이 있다고 생각합니다.
고배는
하지만, 예를 들면 5 문자째까지의 잘라내면 이렇게 되어 버립니다군요.
구문 부분도 잡히기 때문에, 성형 후의 문자수를 취득할 필요가 있습니다.
구문 분석 클래스 확장
구문 분석의 구현은 FDefaultRichTextMarkupParser 로 되어 있어 URichTextBlock::CreateMarkupParser 로부터 확장을 할 수 있게 되어 있습니다. 우선은 URichTextBlock 상속의 UMyRichTextBlock 를 작성합니다.
MyRichTextBlock.cppTSharedPtr<IRichTextMarkupParser> UMyRichTextBlock::CreateMarkupParser()
{
// 後で MarkupParserInstance にアクセスするために SharedPtr をメンバ変数に保存する
RichTextMarkupParser = MakeShareable( new FMyDefaultRichTextMarkupParser() );
return RichTextMarkupParser;
}
void UMyRichTextBlock::SetCharacterCount( int32 NewCount )
{
if ( RichTextMarkupParser.IsValid() )
{
// 後述の MyDefaultRichTextMarkupParser へ表示位置を渡す
RichTextMarkupParser->SetDisplayCharacterCount( NewCount );
if ( MyRichTextBlock.IsValid() )
{
// 解析処理を再実行
MyRichTextBlock->Refresh();
}
}
}
여기에서는 FDefaultRichTextMarkupParser를 복제한 FMyDefaultRichTextMarkupParser를 만들고 확장합니다.
MyRichTextMarkupProcessing.cppvoid FMyDefaultRichTextMarkupParser::Process(
TArray<FTextLineParseResults>& Results, const FString& Input, FString& Output )
{
// エンジン側実装の構文解析処理
TArray<FTextRange> LineRanges;
FTextRange::CalculateLineRangesFromString( Input, LineRanges );
ParseLineRanges( Input, LineRanges, Results );
HandleEscapeSequences( Input, Results, Output );
// 整形後の文字列をさらに整形する処理を追加
bHiddenCharacters = HiddenCharacters( Results, DisplayString, Output );
}
void FMyDefaultRichTextMarkupParser::SetDisplayCharacterCount( int32 NewCount )
{
// 表示位置を指定する
DisplayCharacterCount = NewCount;
}
bool FMyDefaultRichTextMarkupParser::HiddenCharacters(
const TArray<FTextLineParseResults>& LineParseResultsArray,
FString& OutDisplayString, FString& InOutConcatenatedLines ) const
{
bool bFoundToReplace = false;
OutDisplayString.Empty();
if ( !InOutConcatenatedLines.IsEmpty() && DisplayCharacterCount != INDEX_NONE )
{
int32 CharIndex = 0;
for ( const FTextLineParseResults& LineParseResult : LineParseResultsArray )
{
for ( const FTextRunParseResults& RunParseResult : LineParseResult.Runs )
{
FTextRange TargetRange =
RunParseResult.ContentRange.IsEmpty() ?
RunParseResult.OriginalRange : RunParseResult.ContentRange;
// 整形後の文字列を保存する
OutDisplayString += InOutConcatenatedLines.Mid(
TargetRange.BeginIndex, TargetRange.EndIndex - TargetRange.BeginIndex );
bool bFoundInRunParseResult = false;
for ( int32 i = 0; i < TargetRange.Len(); ++i )
{
int32 TargetIndex = TargetRange.BeginIndex + i;
if ( ensure( InOutConcatenatedLines.IsValidIndex( TargetIndex ) ) )
{
if ( CharIndex++ < DisplayCharacterCount )
{
// 表示文字であれば何もしない
continue;
}
// 表示位置まで到達していない文字列は空白に置換する
InOutConcatenatedLines[TargetIndex] = *TEXT( "\u0020" );
bFoundInRunParseResult = true;
}
}
bFoundToReplace |= bFoundInRunParseResult;
}
}
}
return bFoundToReplace;
}
타자기로 숨기는 부분을 공백으로 바꿉니다.
텍스트 내의 공백은 레이아웃 측에서 좋은 느낌으로 처리해 줍니다. 좋은 느낌으로.
블루프린트로 적당히 처리를 작성
Tick에서 DeltaTime을 더하여 표시 간격 시간으로 나눕니다.
Reference
이 문제에 관하여([UE4] RichTextBlock에서 타자기 연출), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/koorinonaka/items/5eb82738479667fa3d9c
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
자주 사용하는 기능으로서는 텍스트중의 부분적인 색변이군요. 색상뿐만 아니라 글꼴 스타일 및 기타 장식도 설정할 수 있습니다. 폰트 설정의 부분 변경을 할 수 없거나, 중첩 구조(문자라든지)로 할 수 없거나 하는 것은 어떻게든 하고 싶은 곳입니다만, 조사해 보면 그것은 더 유연하게 확장 할 수 있도록 설계되었습니다 (구현을 읽는 재미). 그 근처는 또 다음번에도.
한 문자씩 표시
자주 있는 구현이라면, FString::Len() 로 문자수를 취득해 텍스트 치환하는 등이 있다고 생각합니다.
고배는
하지만, 예를 들면 5 문자째까지의 잘라내면 이렇게 되어 버립니다군요.
구문 부분도 잡히기 때문에, 성형 후의 문자수를 취득할 필요가 있습니다.
구문 분석 클래스 확장
구문 분석의 구현은 FDefaultRichTextMarkupParser 로 되어 있어 URichTextBlock::CreateMarkupParser 로부터 확장을 할 수 있게 되어 있습니다. 우선은 URichTextBlock 상속의 UMyRichTextBlock 를 작성합니다.
MyRichTextBlock.cppTSharedPtr<IRichTextMarkupParser> UMyRichTextBlock::CreateMarkupParser()
{
// 後で MarkupParserInstance にアクセスするために SharedPtr をメンバ変数に保存する
RichTextMarkupParser = MakeShareable( new FMyDefaultRichTextMarkupParser() );
return RichTextMarkupParser;
}
void UMyRichTextBlock::SetCharacterCount( int32 NewCount )
{
if ( RichTextMarkupParser.IsValid() )
{
// 後述の MyDefaultRichTextMarkupParser へ表示位置を渡す
RichTextMarkupParser->SetDisplayCharacterCount( NewCount );
if ( MyRichTextBlock.IsValid() )
{
// 解析処理を再実行
MyRichTextBlock->Refresh();
}
}
}
여기에서는 FDefaultRichTextMarkupParser를 복제한 FMyDefaultRichTextMarkupParser를 만들고 확장합니다.
MyRichTextMarkupProcessing.cppvoid FMyDefaultRichTextMarkupParser::Process(
TArray<FTextLineParseResults>& Results, const FString& Input, FString& Output )
{
// エンジン側実装の構文解析処理
TArray<FTextRange> LineRanges;
FTextRange::CalculateLineRangesFromString( Input, LineRanges );
ParseLineRanges( Input, LineRanges, Results );
HandleEscapeSequences( Input, Results, Output );
// 整形後の文字列をさらに整形する処理を追加
bHiddenCharacters = HiddenCharacters( Results, DisplayString, Output );
}
void FMyDefaultRichTextMarkupParser::SetDisplayCharacterCount( int32 NewCount )
{
// 表示位置を指定する
DisplayCharacterCount = NewCount;
}
bool FMyDefaultRichTextMarkupParser::HiddenCharacters(
const TArray<FTextLineParseResults>& LineParseResultsArray,
FString& OutDisplayString, FString& InOutConcatenatedLines ) const
{
bool bFoundToReplace = false;
OutDisplayString.Empty();
if ( !InOutConcatenatedLines.IsEmpty() && DisplayCharacterCount != INDEX_NONE )
{
int32 CharIndex = 0;
for ( const FTextLineParseResults& LineParseResult : LineParseResultsArray )
{
for ( const FTextRunParseResults& RunParseResult : LineParseResult.Runs )
{
FTextRange TargetRange =
RunParseResult.ContentRange.IsEmpty() ?
RunParseResult.OriginalRange : RunParseResult.ContentRange;
// 整形後の文字列を保存する
OutDisplayString += InOutConcatenatedLines.Mid(
TargetRange.BeginIndex, TargetRange.EndIndex - TargetRange.BeginIndex );
bool bFoundInRunParseResult = false;
for ( int32 i = 0; i < TargetRange.Len(); ++i )
{
int32 TargetIndex = TargetRange.BeginIndex + i;
if ( ensure( InOutConcatenatedLines.IsValidIndex( TargetIndex ) ) )
{
if ( CharIndex++ < DisplayCharacterCount )
{
// 表示文字であれば何もしない
continue;
}
// 表示位置まで到達していない文字列は空白に置換する
InOutConcatenatedLines[TargetIndex] = *TEXT( "\u0020" );
bFoundInRunParseResult = true;
}
}
bFoundToReplace |= bFoundInRunParseResult;
}
}
}
return bFoundToReplace;
}
타자기로 숨기는 부분을 공백으로 바꿉니다.
텍스트 내의 공백은 레이아웃 측에서 좋은 느낌으로 처리해 줍니다. 좋은 느낌으로.
블루프린트로 적당히 처리를 작성
Tick에서 DeltaTime을 더하여 표시 간격 시간으로 나눕니다.
TSharedPtr<IRichTextMarkupParser> UMyRichTextBlock::CreateMarkupParser()
{
// 後で MarkupParserInstance にアクセスするために SharedPtr をメンバ変数に保存する
RichTextMarkupParser = MakeShareable( new FMyDefaultRichTextMarkupParser() );
return RichTextMarkupParser;
}
void UMyRichTextBlock::SetCharacterCount( int32 NewCount )
{
if ( RichTextMarkupParser.IsValid() )
{
// 後述の MyDefaultRichTextMarkupParser へ表示位置を渡す
RichTextMarkupParser->SetDisplayCharacterCount( NewCount );
if ( MyRichTextBlock.IsValid() )
{
// 解析処理を再実行
MyRichTextBlock->Refresh();
}
}
}
void FMyDefaultRichTextMarkupParser::Process(
TArray<FTextLineParseResults>& Results, const FString& Input, FString& Output )
{
// エンジン側実装の構文解析処理
TArray<FTextRange> LineRanges;
FTextRange::CalculateLineRangesFromString( Input, LineRanges );
ParseLineRanges( Input, LineRanges, Results );
HandleEscapeSequences( Input, Results, Output );
// 整形後の文字列をさらに整形する処理を追加
bHiddenCharacters = HiddenCharacters( Results, DisplayString, Output );
}
void FMyDefaultRichTextMarkupParser::SetDisplayCharacterCount( int32 NewCount )
{
// 表示位置を指定する
DisplayCharacterCount = NewCount;
}
bool FMyDefaultRichTextMarkupParser::HiddenCharacters(
const TArray<FTextLineParseResults>& LineParseResultsArray,
FString& OutDisplayString, FString& InOutConcatenatedLines ) const
{
bool bFoundToReplace = false;
OutDisplayString.Empty();
if ( !InOutConcatenatedLines.IsEmpty() && DisplayCharacterCount != INDEX_NONE )
{
int32 CharIndex = 0;
for ( const FTextLineParseResults& LineParseResult : LineParseResultsArray )
{
for ( const FTextRunParseResults& RunParseResult : LineParseResult.Runs )
{
FTextRange TargetRange =
RunParseResult.ContentRange.IsEmpty() ?
RunParseResult.OriginalRange : RunParseResult.ContentRange;
// 整形後の文字列を保存する
OutDisplayString += InOutConcatenatedLines.Mid(
TargetRange.BeginIndex, TargetRange.EndIndex - TargetRange.BeginIndex );
bool bFoundInRunParseResult = false;
for ( int32 i = 0; i < TargetRange.Len(); ++i )
{
int32 TargetIndex = TargetRange.BeginIndex + i;
if ( ensure( InOutConcatenatedLines.IsValidIndex( TargetIndex ) ) )
{
if ( CharIndex++ < DisplayCharacterCount )
{
// 表示文字であれば何もしない
continue;
}
// 表示位置まで到達していない文字列は空白に置換する
InOutConcatenatedLines[TargetIndex] = *TEXT( "\u0020" );
bFoundInRunParseResult = true;
}
}
bFoundToReplace |= bFoundInRunParseResult;
}
}
}
return bFoundToReplace;
}
Reference
이 문제에 관하여([UE4] RichTextBlock에서 타자기 연출), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/koorinonaka/items/5eb82738479667fa3d9c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)