midas+son의 크리에이티브(creative) 이야기

https://wiki.unrealengine.com/Iterators:_Object_%26_Actor_Iterators,_Optional_Class_Scope_For_Faster_Search

참고 사이트


UWorld* myWorld = nullptr;

UDataSingleton* dataSingleton = Cast<UDataSingleton>(GEngine->GameSingleton);

if (dataSingleton)

{

AGameMode* gameMode = dataSingleton->gameMode;

if (gameMode)

{

myWorld = gameMode->GetWorld();

}

}


if (myWorld == nullptr) return;


for (TActorIterator<AItemActor> ActorItr(myWorld); ActorItr; ++ActorItr)

{

AItemActor *Mesh = *ActorItr;

if (Mesh && Mesh->inventoryIndex != -1)

{

this->ApplyItemInInventory(Mesh, Mesh->inventoryIndex);

}

}

UWorld를 받아와서 TActorIterator<액터클래스명>을 받아와 반복문을 돌리는 형태이다.

현재 레벨의 World에서 Spwan된 모든 Actor를 검사하여 <AItemActor>로 캐스팅 되는 것을 찾아

이터레이터 형식으로 변환된다고 생각된다.(내부 코드를 보지 않아 정확하진 않다.)

//4.12.5에서 사용한 코드

//FString path;//인자값

//std::string filename(TCHAR_TO_UTF8(*path));

//인코딩 문제 발생 : https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/StringHandling/CharacterEncoding/


const wchar_t* ptr = *path;

int csize = 1024; //글자 바이트 제한

char* tempFileName = new char[csize];

char def = '?';


//함수 참고 Url : https://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx

WideCharToMultiByte(CP_ACP, 0, ptr, -1, tempFileName, csize, &def, NULL);


std::string fileName(tempFileName);

delete[] tempFileName;

4.12.5 버전에서는 #include <Windows.h>를 하여 

WideCharToMultiByte를 사용하였었다.

하지만 4.15.1로 오면서 #include <Windows.h> 를 사용하면

Winnt.h 에서 TEXT 매크로 재정의 Warning이 발생하는 등

여러 문제가 발생하여 #include <Windows.h>를 사용하지 않게 바꾸기로 했다.


wchar_t를 char*나 string으로 바꾸는 방법을 구글링으로 열심히 찾았으나

다 의미없는 소스와 블로그 글들 뿐이었다.

한글에 대한 처리가 고려되지 않는 글들도 많았다.

공식 MSDN이나 언리얼에서도 명확한 해결법을 주지 않았다.


UTF-16과 UTF-8에 대한 컨버팅 구조는 찾았으나

CP949로 가는 구조는 못찾았다.


2일째 고민하던 중 찾은 방법은 codecvt을 사용한 방법이었다.

저 헤더는 처음 봤다.(자세한 설명은 맨 위의 참고사이트 링크에 들어가보자.)

컨버트용 헤더로 생각된다.


//include해야 하는 헤더들

#include <string> 

#include <vector> 

#include <codecvt> 

#include <locale>

//4.15.1에서 새로 작성한 코드

std::wstring str = *FilePath;

typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_t;

//std::locale loc = std::locale("ko_KR.UTF-8"); // windows 에서는 사용이 안됨

std::locale loc = std::locale("Korean"); // windows 용

codecvt_t const& codecvt = std::use_facet<codecvt_t>(loc);

std::mbstate_t state = std::mbstate_t();

std::vector<char> buf((str.size() + 1) * codecvt.max_length());

wchar_t const* in_next = str.c_str();

char* out_next = &buf[0];

std::codecvt_base::result r = codecvt.out(state,

str.c_str(), str.c_str() + str.size(), in_next,

&buf[0], &buf[0] + buf.size(), out_next);

if (r == std::codecvt_base::error)

throw std::runtime_error("can't convert wstring to string");    //실제 에러가 난다. 언리얼 로그로 바꾸어도 된다.

std::string fileName(&buf[0]);

위와 같이 바꾸니 Warning없이 정상적으로 동작한다.

복잡해보이니 아래와 같이 함수로 바꾸어 사용했다.(참고사이트에 있는 것 복붙 + 약간 수정)

std::string CommonFunc::WCStoMBCS(std::wstring const& str, std::locale const& loc /*= std::locale("")*/)

{

//loc에 std::locale("")로 들어오면 자동으로 OS의 locale을 찾는것 같다.(확인 필요), std::locale()로 하면 에러 난다.

typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_t;

codecvt_t const& codecvt = std::use_facet<codecvt_t>(loc);

std::mbstate_t state = std::mbstate_t();

std::vector<char> buf((str.size() + 1) * codecvt.max_length());

wchar_t const* in_next = str.c_str();

char* out_next = &buf[0];

std::codecvt_base::result r = codecvt.out(state,

str.c_str(), str.c_str() + str.size(), in_next,

&buf[0], &buf[0] + buf.size(), out_next);

if (r == std::codecvt_base::error)

throw std::runtime_error("can't convert wstring to string");    //실제 에러가 난다. UELOG로 바꾸어도 된다.

return std::string(&buf[0]);

}

마이그레이션 하던 것 중 제일 골치 아팠던 게 해결 되었다.

굿굿!!

[회덮밥]

신촌에서의 점심
자주가던 스시 집
8000원 짜리 회덮밥

간만에 가서 그런가
날이 따듯해 져서 그런가

회 양이 많이 줄었다.
아쉽다.
홍대에서 신촌까지 
이 가게의 회 양이 많았기 때문에 
점심시간에 지하철 타고도 왔었는데
이제 딴 집을 찾아 봐야겠다.


'개인사 > ' 카테고리의 다른 글

20170407_코케뽕  (0) 2017.04.07
20170406_편도,컵라면  (0) 2017.04.06
20170403_편도  (0) 2017.04.03
20170401_덮밥  (0) 2017.04.01
20170330_갈비탕  (0) 2017.03.30