KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
UChatInputBox 클래스 참조

#include <ChatInputBox.h>

+ UChatInputBox에 대한 상속 다이어그램 :
+ UChatInputBox에 대한 협력 다이어그램:

Public 멤버 함수

bool HasKeyboardFocus ()
 
virtual void NativeOnInitialized () override
 
virtual FReply NativeOnPreviewKeyDown (const FGeometry &InGeometry, const FKeyEvent &InKeyEvent) override
 
virtual void NativeTick (const FGeometry &MyGeometry, float InDeltaTime) override
 
void SetInputFocus (bool bFocus)
 
void SetOwningChatWidget (class UChatWidget *InChatWidget)
 

Public 속성

TObjectPtr< class UButton > Button_Send
 
TObjectPtr< class UMultiLineEditableTextBox > MultiLineEditableTextBox_Input
 

Private 멤버 함수

FText FlushMessage ()
 
TArray< struct FWordDataGetRandomKoreanWords (int32 Count)
 GameDataManager에서 랜덤 한국어 단어 데이터 가져오기 (FWordData 형태)
 
void HandleSendClicked ()
 
bool IsAIAsk (const FString &InMessage, FString &OutQuestion) const
 
bool IsDailyAsk (const FString &InMessage, FString &OutQuestion) const
 
void OnDailyAnswerReceived (FResponseChatDailys &ResponseData, bool bWasSuccessful)
 

Private 속성

bool bWasFocused = false
 
TObjectPtr< class UChatWidgetOwningChatWidget = nullptr
 

상세한 설명

ChatInputBox.h 파일의 15 번째 라인에서 정의되었습니다.

멤버 함수 문서화

◆ FlushMessage()

FText UChatInputBox::FlushMessage ( )
private

ChatInputBox.cpp 파일의 93 번째 라인에서 정의되었습니다.

94{
95 // message에 저장 & 텍스트 칸 비우기
96 FText message = MultiLineEditableTextBox_Input->GetText();
97
98 MultiLineEditableTextBox_Input->SetText(FText::GetEmpty());
99
100 return message;
101}
TObjectPtr< class UMultiLineEditableTextBox > MultiLineEditableTextBox_Input

다음을 참조함 : MultiLineEditableTextBox_Input.

다음에 의해서 참조됨 : HandleSendClicked().

+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetRandomKoreanWords()

TArray< FWordData > UChatInputBox::GetRandomKoreanWords ( int32  Count)
private

GameDataManager에서 랜덤 한국어 단어 데이터 가져오기 (FWordData 형태)

ChatInputBox.cpp 파일의 237 번째 라인에서 정의되었습니다.

238{
239 TArray<FWordData> RandomWordDataArray;
240
241 UGameDataManager* DataManager = UGameDataManager::Get(GetWorld());
242 if (!DataManager)
243 {
244 PRINTLOG(TEXT("[Daily] Error: GameDataManager not found"));
245 return RandomWordDataArray;
246 }
247
248 // ReadData에서 모든 키 가져오기
249 TArray<int32> AllKeys = DataManager->GetAllReadDataKeys();
250
251 if (AllKeys.Num() == 0)
252 {
253 PRINTLOG(TEXT("[Daily] Error: No ReadData available"));
254 return RandomWordDataArray;
255 }
256
257 // 요청한 개수만큼 랜덤 단어 선택
258 int32 WordsToGenerate = FMath::Min(Count, AllKeys.Num());
259
260 for (int32 i = 0; i < WordsToGenerate; ++i)
261 {
262 // 랜덤 인덱스 선택
263 int32 RandomIndex = FMath::RandRange(0, AllKeys.Num() - 1);
264 int32 RandomKey = AllKeys[RandomIndex];
265 AllKeys.RemoveAt(RandomIndex); // 중복 방지
266
267 // 데이터 로드
268 FReadData ReadData;
269 if (DataManager->GetReadData(RandomKey, ReadData))
270 {
271 // FWordData 생성 (ReadData에는 Pronunciation이 없으므로 Eng로 임시 설정)
272 FWordData WordData;
273 WordData.Kor = ReadData.Word;
274 WordData.Eng = ReadData.Eng;
275 WordData.Pronunciation = ReadData.Eng; // TODO: 나중에 실제 발음 데이터로 교체
276
277 RandomWordDataArray.Add(WordData);
278 }
279 }
280
281 PRINTLOG(TEXT("[Daily] Generated %d random word data from ReadData"), RandomWordDataArray.Num());
282 return RandomWordDataArray;
283}
#define PRINTLOG(fmt,...)
Definition GameLogging.h:30
데이터 테이블(.csv)에서 게임 데이터를 로드하고 캐시하여 런타임에 빠르게 접근할 수 있도록 제공하는 데이터 관리 서브시스템입니다.
bool GetReadData(int32 Index, FReadData &Out) const
TArray< int32 > GetAllReadDataKeys() const
읽기 학습 데이터를 정의하는 구조체
Definition FReadData.h:19
FString Eng
학습 단어
Definition FReadData.h:39
FString Word
학습 단어
Definition FReadData.h:32
단어 데이터 구조체입니다.
FString Kor
FString Pronunciation
FString Eng

다음을 참조함 : FReadData::Eng, FWordData::Eng, UGameDataManager::GetAllReadDataKeys(), UGameDataManager::GetReadData(), FWordData::Kor, PRINTLOG, FWordData::Pronunciation, FReadData::Word.

다음에 의해서 참조됨 : OnDailyAnswerReceived().

+ 이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HandleSendClicked()

void UChatInputBox::HandleSendClicked ( )
private

ChatInputBox.cpp 파일의 182 번째 라인에서 정의되었습니다.

183{
184 // 텍스트가 비어있지 않다면 처리
185 FText Message = FlushMessage();
186 if (Message.IsEmpty())
187 {
188 // 빈 메시지면 포커스만 해제
189 SetInputFocus(false);
190 return;
191 }
192
193 auto* PC = Cast<APlayerControl>(GetWorld()->GetFirstPlayerController());
194 if (!PC)
195 return;
196
197 const FString MessageStr = Message.ToString();
198 FString CleanQuestion;
199
200 if (IsAIAsk(MessageStr, CleanQuestion))
201 {
202 // 사용자가 입력한 전체 메시지 표시 (로그성)
203 PC->ServerRPC_SendChat(Message);
204
205 // AI에게 정제된 질문 전송
206 PC->ServerRPC_SendAIQuestion(CleanQuestion);
207
208 PRINTLOG(TEXT("[AI Chat] User question: %s"), *CleanQuestion);
209 }
210 else if (IsDailyAsk(MessageStr, CleanQuestion))
211 {
212 // Daily 단어 생성 요청
213 if (UKLingoNetworkSystem* NetworkSystem = UKLingoNetworkSystem::Get(GetWorld()))
214 {
215 NetworkSystem->RequestDailyQuestion(DefineData::DailySystemPrompt, CleanQuestion,
216 FResponseChatDailysDelegate::CreateUObject(this, &UChatInputBox::OnDailyAnswerReceived));
217
218 PRINTLOG(TEXT("[Daily] Word generation request: %s"), *CleanQuestion);
219 }
220 }
221 else
222 {
223 // 2. 일반 채팅 메시지 전송
224 PC->ServerRPC_SendChat(Message);
225 }
226
227 // 메시지 전송 후 포커스 해제 및 게임 모드로 복원
228 SetInputFocus(false);
229
230}
void OnDailyAnswerReceived(FResponseChatDailys &ResponseData, bool bWasSuccessful)
void SetInputFocus(bool bFocus)
FText FlushMessage()
bool IsAIAsk(const FString &InMessage, FString &OutQuestion) const
bool IsDailyAsk(const FString &InMessage, FString &OutQuestion) const
KLingo 서버와의 HTTP 요청을 중재하는 게임 인스턴스 서브시스템입니다.
static const FString DailySystemPrompt
Definition Onepiece.h:70

다음을 참조함 : DefineData::DailySystemPrompt, FlushMessage(), IsAIAsk(), IsDailyAsk(), OnDailyAnswerReceived(), PRINTLOG, SetInputFocus().

다음에 의해서 참조됨 : NativeOnInitialized(), NativeOnPreviewKeyDown().

+ 이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HasKeyboardFocus()

bool UChatInputBox::HasKeyboardFocus ( )

ChatInputBox.cpp 파일의 232 번째 라인에서 정의되었습니다.

233{
235}

다음을 참조함 : MultiLineEditableTextBox_Input.

◆ IsAIAsk()

bool UChatInputBox::IsAIAsk ( const FString &  InMessage,
FString &  OutQuestion 
) const
private

ChatInputBox.cpp 파일의 150 번째 라인에서 정의되었습니다.

151{
152 FString LeftPart, RightPart;
153
154 // 콜론(:)을 기준으로 분리
155 if (InMessage.Split(TEXT(":"), &LeftPart, &RightPart))
156 {
157 // 왼쪽 파트의 공백을 제거하고 "AI"와 일치하는지 확인 (대소문자 무시)
158 if (LeftPart.TrimStartAndEnd().Equals(DefineData::AI, ESearchCase::IgnoreCase))
159 {
160 OutQuestion = RightPart.TrimStart();
161 return !OutQuestion.IsEmpty(); // 내용이 비어있지 않아야 true
162 }
163 }
164 return false;
165}
static const FString AI
Definition Onepiece.h:59

다음을 참조함 : DefineData::AI.

다음에 의해서 참조됨 : HandleSendClicked().

+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IsDailyAsk()

bool UChatInputBox::IsDailyAsk ( const FString &  InMessage,
FString &  OutQuestion 
) const
private

ChatInputBox.cpp 파일의 167 번째 라인에서 정의되었습니다.

168{
169 FString LeftPart, RightPart;
170
171 if (InMessage.Split(TEXT(":"), &LeftPart, &RightPart))
172 {
173 if (LeftPart.TrimStartAndEnd().Equals(DefineData::Daily, ESearchCase::IgnoreCase))
174 {
175 OutQuestion = RightPart.TrimStart();
176 return !OutQuestion.IsEmpty(); // 내용이 비어있지 않아야 true
177 }
178 }
179 return false;
180}
static const FString Daily
Definition Onepiece.h:61

다음을 참조함 : DefineData::Daily.

다음에 의해서 참조됨 : HandleSendClicked().

+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ NativeOnInitialized()

void UChatInputBox::NativeOnInitialized ( )
overridevirtual

ChatInputBox.cpp 파일의 25 번째 라인에서 정의되었습니다.

26{
27 Super::NativeOnInitialized();
28
29 Button_Send->OnClicked.AddDynamic(this, &UChatInputBox::HandleSendClicked);
30}
void HandleSendClicked()
TObjectPtr< class UButton > Button_Send

다음을 참조함 : Button_Send, HandleSendClicked().

+ 이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ NativeOnPreviewKeyDown()

FReply UChatInputBox::NativeOnPreviewKeyDown ( const FGeometry &  InGeometry,
const FKeyEvent &  InKeyEvent 
)
overridevirtual

ChatInputBox.cpp 파일의 74 번째 라인에서 정의되었습니다.

75{
76 // Enter 키 감지 & Shift+Enter는 줄바꿈 허용
77 if (InKeyEvent.GetKey() == EKeys::Enter && !InKeyEvent.IsShiftDown())
78 {
80 return FReply::Handled();
81 }
82
83 // ESC 키로 포커스 해제
84 if (InKeyEvent.GetKey() == EKeys::Escape)
85 {
86 SetInputFocus(false);
87 return FReply::Handled();
88 }
89
90 return Super::NativeOnPreviewKeyDown(InGeometry, InKeyEvent);
91}

다음을 참조함 : HandleSendClicked(), SetInputFocus().

+ 이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ NativeTick()

void UChatInputBox::NativeTick ( const FGeometry &  MyGeometry,
float  InDeltaTime 
)
overridevirtual

ChatInputBox.cpp 파일의 32 번째 라인에서 정의되었습니다.

33{
34 Super::NativeTick(MyGeometry, InDeltaTime);
35
36 // 현재 포커스 상태 확인
37 bool bIsFocused = MultiLineEditableTextBox_Input && MultiLineEditableTextBox_Input->HasKeyboardFocus();
38
39 // 포커스 상태 변화 감지
40 if (bWasFocused != bIsFocused)
41 {
42 PRINTLOG(TEXT("[ChatInputBox] Focus changed: %d -> %d"), bWasFocused, bIsFocused);
43
44 // 포커스를 잃었을 때만 처리 (화면 클릭 등)
45 if (bWasFocused && !bIsFocused)
46 {
47 PRINTLOG(TEXT("[ChatInputBox] Focus lost - switching to GameOnly mode"));
48
49 // GameOnly 모드로 전환
50 if (APlayerControl* PC = Cast<APlayerControl>(GetOwningPlayer()))
51 {
52 FInputModeGameOnly InputMode;
53 PC->SetInputMode(InputMode);
54 PC->SetShowMouseCursor(false);
55 FSlateApplication::Get().SetAllUserFocusToGameViewport();
56 }
57
58 // ChatWidget에 포커스 해제 알림
60 {
61 PRINTLOG(TEXT("[ChatInputBox] Notifying ChatWidget of focus loss"));
62 OwningChatWidget->OnInputFocusChanged(false);
63 }
64 else
65 {
66 PRINTLOG(TEXT("[ChatInputBox] ERROR: OwningChatWidget is null!"));
67 }
68 }
69 }
70
71 bWasFocused = bIsFocused;
72}
TObjectPtr< class UChatWidget > OwningChatWidget

다음을 참조함 : bWasFocused, MultiLineEditableTextBox_Input, OwningChatWidget, PRINTLOG.

◆ OnDailyAnswerReceived()

void UChatInputBox::OnDailyAnswerReceived ( FResponseChatDailys ResponseData,
bool  bWasSuccessful 
)
private

ChatInputBox.cpp 파일의 285 번째 라인에서 정의되었습니다.

286{
287 const int32 MIN_REQUIRED_WORDS = 3;
288
289 if (!bWasSuccessful)
290 {
291 // 네트워크 실패 시 랜덤 단어 데이터로 대체
292 TArray<FWordData> FallbackWordData = GetRandomKoreanWords(MIN_REQUIRED_WORDS);
293
294 if (FallbackWordData.Num() > 0)
295 {
296 if (UPopup_DailyStudy* DailyStudyPopup = UPopupManager::Get(GetWorld())->ShowPopupAs<UPopup_DailyStudy>(EPopupType::DailyStudy))
297 {
298 DailyStudyPopup->InitPopup(FallbackWordData);
299 }
300 }
301
302 return;
303 }
304
305 // AI 응답을 | 구분자로 파싱 (형식: "개|DOG|Gae|고양이|CAT|Go-yang-i")
306 TArray<FString> RawTokens;
307 ResponseData.answer.ParseIntoArray(RawTokens, TEXT("|"), true);
308
309 // 3개씩 묶어서 FWordData로 변환 (Kor|Eng|Pronunciation)
310 TArray<FWordData> ValidWordDataArray;
311 for (int32 i = 0; i + 2 < RawTokens.Num(); i += 3)
312 {
313 FString Kor = RawTokens[i].TrimStartAndEnd();
314 FString Eng = RawTokens[i + 1].TrimStartAndEnd();
315 FString Pronunciation = RawTokens[i + 2].TrimStartAndEnd();
316
317 // 빈 문자열 체크
318 if (Kor.IsEmpty() || Eng.IsEmpty() || Pronunciation.IsEmpty())
319 {
320 PRINTLOG(TEXT("[Daily] Skipped: Empty field (Kor: '%s', Eng: '%s', Phon: '%s')"), *Kor, *Eng, *Pronunciation);
321 continue;
322 }
323
324 // 한국어 검증 (Kor 필드만)
326 {
327 PRINTLOG(TEXT("[Daily] Skipped: Invalid Korean word '%s'"), *Kor);
328 continue;
329 }
330
331 // FWordData 생성
332 FWordData WordData;
333 WordData.Kor = Kor;
334 WordData.Eng = Eng;
335 WordData.Pronunciation = Pronunciation;
336
337 ValidWordDataArray.Add(WordData);
338 PRINTLOG(TEXT("[Daily] Parsed Word: Kor='%s', Eng='%s', Phon='%s'"), *Kor, *Eng, *Pronunciation);
339 }
340
341 // 유효한 단어가 부족하면 GameDataManager에서 보충
342 if (ValidWordDataArray.Num() < MIN_REQUIRED_WORDS)
343 {
344 int32 WordsNeeded = MIN_REQUIRED_WORDS - ValidWordDataArray.Num();
345
346 TArray<FWordData> AdditionalWordData = GetRandomKoreanWords(WordsNeeded);
347 ValidWordDataArray.Append(AdditionalWordData);
348
349 PRINTLOG(TEXT("[Daily] Added %d fallback words from ReadData"), AdditionalWordData.Num());
350 }
351
352 // 최종 검증 및 팝업 표시
353 if (ValidWordDataArray.Num() > 0)
354 {
355 if (UPopup_DailyStudy* DailyStudyPopup = UPopupManager::Get(GetWorld())->ShowPopupAs<UPopup_DailyStudy>(EPopupType::DailyStudy))
356 {
357 DailyStudyPopup->InitPopup(ValidWordDataArray);
358 PRINTLOG(TEXT("[Daily] Initialized DailyStudy popup with %d words"), ValidWordDataArray.Num());
359 }
360 }
361}
TArray< struct FWordData > GetRandomKoreanWords(int32 Count)
GameDataManager에서 랜덤 한국어 단어 데이터 가져오기 (FWordData 형태)
static bool IsValidKoreanWord(const FString &Word)
한국어 단어 검증 (한글만 포함되어 있는지 확인)
Daily Study 팝업

다음을 참조함 : FResponseChatDailys::answer, FWordData::Eng, GetRandomKoreanWords(), UCommonFunctionLibrary::IsValidKoreanWord(), FWordData::Kor, PRINTLOG, FWordData::Pronunciation.

다음에 의해서 참조됨 : HandleSendClicked().

+ 이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetInputFocus()

void UChatInputBox::SetInputFocus ( bool  bFocus)

ChatInputBox.cpp 파일의 103 번째 라인에서 정의되었습니다.

104{
105 if ( bFocus )
106 {
107 // 먼저 포커스 설정
108 MultiLineEditableTextBox_Input->SetKeyboardFocus();
109
110 // UI 입력 모드로 전환
111 if (APlayerControl* PC = Cast<APlayerControl>(GetOwningPlayer()))
112 {
113 FInputModeUIOnly InputMode;
114 InputMode.SetWidgetToFocus(MultiLineEditableTextBox_Input->TakeWidget());
115 PC->SetInputMode(InputMode);
116 PC->SetShowMouseCursor(true);
117 }
118
119 // ChatWidget에 포커스 획득 알림
121 {
122 OwningChatWidget->OnInputFocusChanged(true);
123 }
124
125 bWasFocused = true;
126 }
127 else
128 {
129 // GameOnly 모드로 전환 및 포커스 해제
130 if (APlayerControl* PC = Cast<APlayerControl>(GetOwningPlayer()))
131 {
132 FInputModeGameOnly InputMode;
133 PC->SetInputMode(InputMode);
134 PC->SetShowMouseCursor(false);
135
136 // 뷰포트로 포커스 이동 (자동으로 입력창 포커스 해제됨)
137 FSlateApplication::Get().SetAllUserFocusToGameViewport();
138 }
139
140 // ChatWidget에 포커스 해제 알림
142 {
143 OwningChatWidget->OnInputFocusChanged(false);
144 }
145
146 bWasFocused = false;
147 }
148}

다음을 참조함 : bWasFocused, MultiLineEditableTextBox_Input, OwningChatWidget.

다음에 의해서 참조됨 : HandleSendClicked(), NativeOnPreviewKeyDown().

+ 이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ SetOwningChatWidget()

void UChatInputBox::SetOwningChatWidget ( class UChatWidget InChatWidget)
inline

ChatInputBox.h 파일의 24 번째 라인에서 정의되었습니다.

24{ OwningChatWidget = InChatWidget; }

멤버 데이터 문서화

◆ Button_Send

TObjectPtr<class UButton> UChatInputBox::Button_Send

ChatInputBox.h 파일의 49 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : NativeOnInitialized().

◆ bWasFocused

bool UChatInputBox::bWasFocused = false
private

ChatInputBox.h 파일의 53 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : NativeTick(), SetInputFocus().

◆ MultiLineEditableTextBox_Input

TObjectPtr<class UMultiLineEditableTextBox> UChatInputBox::MultiLineEditableTextBox_Input

ChatInputBox.h 파일의 46 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : FlushMessage(), HasKeyboardFocus(), NativeTick(), SetInputFocus().

◆ OwningChatWidget

TObjectPtr<class UChatWidget> UChatInputBox::OwningChatWidget = nullptr
private

ChatInputBox.h 파일의 57 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : NativeTick(), SetInputFocus().


이 클래스에 대한 문서화 페이지는 다음의 파일들로부터 생성되었습니다.: