ArticyXImporter
ArticyXImporter for Unreal Engine
Loading...
Searching...
No Matches
ArticyTextExtension.h
1//
2// Copyright (c) 2023 articy Software GmbH & Co. KG. All rights reserved.
3//
4
5#pragma once
6
7#include "CoreMinimal.h"
8#include "Dom/JsonValue.h"
9#include "ArticyTextExtension.generated.h"
10
11using FArticyUserMethodCallback = TFunction<FString(const TArray<FString>&)>;
12
13struct FArticyGvName;
14class UArticyVariable;
15
16UENUM()
17enum class EArticyObjectType : uint8
18{
19 UArticyBool = 0,
20 UArticyInt = 1,
21 UArticyString = 2,
22 Other
23};
24
25UCLASS(BlueprintType)
26class ARTICYRUNTIME_API UArticyTextExtension : public UObject
27{
28 GENERATED_BODY()
29
30public:
31 static UArticyTextExtension* Get();
32
33 template<typename... Types>
34 FText Resolve
35 (
36 UObject* Outer,
37 const FText* Format,
38 Types... Args
39 ) const;
40
41 template<typename ... Types>
42 FText ResolveAdvance
43 (
44 const FText& Format,
45 TMap<FString, TFunction<FString(Types...)>> CallbackMap,
46 Types... Args
47 ) const;
48
49 void AddUserMethod(const FString& MethodName, FArticyUserMethodCallback Callback);
50
51protected:
52 FString GetSource(UObject* Outer, const FString &SourceName) const;
53 FString FormatNumber(const FString &SourceValue, const FString &NumberFormat) const;
54 void GetGlobalVariable(UObject* Outer, const FString& SourceName, const FArticyGvName GvName, FString& OutString, bool& OutSuccess) const;
55 void GetObjectProperty(UObject* Outer, const FString& SourceName, const FString& NameOrId, const FString& PropertyName, const bool bRequestType, FString& OutString, bool& OutSuccess) const;
56 static void GetTypeProperty(const FString& TypeName, const FString& PropertyName, FString& OutString, bool& OutSuccess);
57 FString ExecuteMethod(UObject* Outer, const FText& Method, const TArray<FString>& Args) const;
58 EArticyObjectType GetObjectType(UArticyVariable** Object) const;
59 FString ResolveBoolean(UObject* Outer, const FString &SourceName, const bool Value) const;
60 FString LocalizeString(UObject* Outer, const FString &Input) const;
61 static void SplitInstance(const FString& InString, FString& OutName, FString& OutInstanceNumber);
62
63 TMap<FString, FArticyUserMethodCallback> UserMethodMap;
64};
65
66template<typename ... Types>
67FText UArticyTextExtension::Resolve(UObject* Outer, const FText* Format, Types... Args) const
68{
69 // Do not try to process null values
70 if (Format == nullptr)
71 {
72 return FText::GetEmpty();
73 }
74
75 TArray<FString> ArgumentValues = {FString::Printf(TEXT("%s"), Args)...};
76
77 FString FormattedString = Format->ToString();
78
79 // Regular placeholder replacement
80 for (int32 ArgIndex = 0; ArgIndex < ArgumentValues.Num(); ++ArgIndex)
81 {
82 const FString Placeholder = FString::Printf(TEXT("{%d}"), ArgIndex);
83 FormattedString = FormattedString.Replace(*Placeholder, *ArgumentValues[ArgIndex]);
84 }
85
86 // Token replacement
87 while (true)
88 {
89 const int32 TokenStartIndex = FormattedString.Find(TEXT("["), ESearchCase::CaseSensitive);
90 if (TokenStartIndex == INDEX_NONE)
91 break;
92
93 const int32 TokenEndIndex = FormattedString.Find(TEXT("]"), ESearchCase::CaseSensitive, ESearchDir::FromStart, TokenStartIndex);
94 if (TokenEndIndex == INDEX_NONE)
95 break;
96
97 FString Token = FormattedString.Mid(TokenStartIndex + 1, TokenEndIndex - TokenStartIndex - 1);
98 FString FullToken = FormattedString.Mid(TokenStartIndex, TokenEndIndex - TokenStartIndex + 1);
99 FString SourceName, Formatting;
100
101 Token.Split(TEXT(":"), &SourceName, &Formatting);
102 if (SourceName.IsEmpty())
103 {
104 SourceName = Token;
105 }
106
107 if (!SourceName.IsEmpty())
108 {
109 // Get value from source
110 FString SourceValue = GetSource(Outer, SourceName);
111
112 if (!Formatting.IsEmpty())
113 {
114 // Custom format the SourceValue based on the rules of C#'s custom numeric format strings
115 FString FormattedValue = FormatNumber(SourceValue, Formatting);
116 FormattedString = FormattedString.Replace(*FullToken, *FormattedValue);
117 }
118 else
119 {
120 FormattedString = FormattedString.Replace(*FullToken, *SourceValue);
121 }
122 }
123 else
124 {
125 // Remove invalid token if source name is empty
126 FormattedString = FormattedString.Replace(*FullToken, TEXT(""));
127 }
128 }
129
130 return FText::FromString(FormattedString);
131}
132
133template<typename ... Types>
134FText UArticyTextExtension::ResolveAdvance(const FText& Format, TMap<FString, TFunction<FString(Types...)>> CallbackMap, Types... Args) const
135{
136 TArray<FString> ArgumentValues = {FString::Printf(TEXT("%s"), Args)...};
137
138 FString FormattedString = Format.ToString();
139
140 // Regular placeholder replacement
141 for (int32 ArgIndex = 0; ArgIndex < ArgumentValues.Num(); ++ArgIndex)
142 {
143 const FString Placeholder = FString::Printf(TEXT("{%d}"), ArgIndex);
144 FormattedString = FormattedString.Replace(*Placeholder, *ArgumentValues[ArgIndex]);
145 }
146
147 // Token replacement
148 while (true)
149 {
150 const int32 TokenStartIndex = FormattedString.Find(TEXT("["), ESearchCase::CaseSensitive);
151 if (TokenStartIndex == INDEX_NONE)
152 break;
153
154 const int32 TokenEndIndex = FormattedString.Find(TEXT("]"), ESearchCase::CaseSensitive, ESearchDir::FromStart, TokenStartIndex);
155 if (TokenEndIndex == INDEX_NONE)
156 break;
157
158 FString Token = FormattedString.Mid(TokenStartIndex + 1, TokenEndIndex - TokenStartIndex - 1);
159 FString FullToken = FormattedString.Mid(TokenStartIndex, TokenEndIndex - TokenStartIndex + 1);
160 FString SourceName, Formatting;
161
162 Token.Split(TEXT(":"), &SourceName, &Formatting);
163 if (SourceName.IsEmpty())
164 {
165 SourceName = Token;
166 }
167
168 if (!SourceName.IsEmpty())
169 {
170 TFunction<FString(Types...)> Callback;
171 if (CallbackMap.Contains(SourceName))
172 {
173 Callback = CallbackMap[SourceName];
174 FString ReplacementValue = Callback(Args...);
175 FormattedString = FormattedString.Replace(*FullToken, *ReplacementValue);
176 }
177 else
178 {
179 FormattedString = FormattedString.Replace(*FullToken, TEXT(""));
180 }
181 }
182 else
183 {
184 FormattedString = FormattedString.Replace(*FullToken, TEXT(""));
185 }
186 }
187
188 return FText::FromString(FormattedString);
189}
Definition ArticyGlobalVariables.h:320
Definition ArticyGlobalVariables.h:168
Definition ArticyGlobalVariables.h:359
Definition ArticyTextExtension.h:27
Definition ArticyGlobalVariables.h:89
Definition ArticyGlobalVariables.h:64