우리가 개발할때 아무렇지도 않게 쓰는 TextBox...
타이니렌더에서 직접 다 만들어야한다...
imgui쓸걸....
FreeType
https://learnopengl.com/In-Practice/Text-Rendering
텍스트는 FreeType이라는 라이브러리를 활용해서 렌더링했다.
이 라이브러리도 활용하는데 문제가 있었던게..
LearnOpenGL 사이트에도 나와있는데
여러군데에서 include하면 conflict이 날 수도 있다고 한다
(실제로 conflict나서인지 라이브러리 인식이 안됬다.)
???????
아니 여러곳에서 라이브러리를 써야하는데?
어떻게해요..
FreeTypeImporter.h
#pragma once
#include <ft2build.h>
#include FT_FREETYPE_H
이런식으로 FreeTypeImporter.h라는 헤더파일을 만들어
여기에만 인클루드 한 다음에
FreeTypeImporter.h 이 헤더파일을 불러왔다.
왜 이렇게 해야하는지는 사실 잘 모르겠다.
(아는게없음)
어쨌든 라이브러리는 이렇게 불러왔고..
텍스트 관련 코드는 LearnOpenGL에서 가져왔다.
TextBox
우선 키보드 입력을 받기위해
인터페이스를 작성했다.
class IKeyDown{
public:
virtual ~IKeyDown() {};
virtual void GeyKeyDown(std::string str) =0;
};
void InputEventSystem::HandleKeyEvent(int key, int action)
{
if (key == GLFW_KEY_0 && action == GLFW_PRESS)
{
for (IKeyDown *child : mKeyDown)
{
child->GeyKeyDown("0");
}
return;
}
if (key == GLFW_KEY_1 && action == GLFW_PRESS)
{
for (IKeyDown *child : mKeyDown)
{
child->GeyKeyDown("1");
}
return;
}
....
}
이런식으로 등록된 인터페이스에 string으로 바로 값을 보낸다.
enum을 따로 선언해서 보낼까도 생각했는데
굳이? 라는 생각이 들어서 바로 string을 보냈다.
TextBox.h
class TextBox : public Widget,public IPressedDown,public IKeyDown{
public:
TextBox(glm::vec3 textBoxPos,float sizeX, float sizeY,std::string text, float textSize,glm::vec3 textColor, bool stringFlag);
void OnPointerDown(float xpos, float ypos,float xdelta,float ydelta) override;
void GeyKeyDown(std::string str) override;
void SetText(std::string str);
void SetEventCallback(std::function<void(std::string)> func);
std::string GetText() const {return mStr;}
void Draw() override;
private:
bool bString; //입력이 string인지 number인지
bool bTextActive=true;
unsigned int mVAO, mVBO, mEBO;
float mVertexArray[20];
unsigned int mIndices[6]={
0,1,2,
2,1,3
};
unsigned int mTextVAO, mTextVBO;
Shader* UIShader= new Shader("Shader/UIVertexShader.glsl", "Shader/FragShader.glsl");
Shader* mTextShader = new Shader("Shader/fontVertex.glsl", "Shader/fontFrag.glsl");
float mTextSize=1.0f;
std::string mStr;
glm::vec3 mTextColor;
FT_Library mFreeType;
std::string mFont = "resource/font/LINESeedSans_A_Th.ttf";
FT_Face mFace;
std::map<GLchar, Character> mCharacters;
std::function<void(std::string str)> mEventCallback=NULL;
void renderText(Shader* shader, std::string text, float scale, glm::vec3 color);
};
void TextBox::OnPointerDown(float xpos, float ypos, float xdelta, float ydelta)
{
glm::vec3 pointNDC = ScreenToNDC(glm::vec2(xpos, ypos));
glm::vec2 sizeHalf = glm::vec2(mSizeX / 2, mSizeY / 2);
if (pointNDC.x >= (mPos.x - sizeHalf.x) && pointNDC.x <= (mPos.x + sizeHalf.x) && pointNDC.y >= (mPos.y - sizeHalf.y) && pointNDC.y <= (mPos.y + sizeHalf.y))
{
bTextActive = true;
}
else
{
bTextActive = false;
}
}
먼저 마우스 좌클릭 입력이 들어오면..
입력이 텍스트박스 범위 내인지를 판별하고
범위 내라면 텍스트 박스를 활성화시킨다.
void TextBox::GeyKeyDown(std::string str)
{
if (!bTextActive)
return;
if(str=="BACKSPACE"){
mStr.pop_back();
return;
}
if (!bString && str[0] < 48 && str[0] > 58)
{
return;
}
mStr.append(str);
}
키보드 입력이 들어오면
텍스트박스가 활성화 상태인지 판별하고
mStr에 추가한다.
그리고 범위를 튀어나가지 않도록 마스킹도 추가했다!
인스펙터
그리고 인스펙터도 만들었다.
인스펙터는 현재 레이어의 상태를 보여주고 수정할 수 있도록 하는 역할이다.
우선 위치, 회전, 크기 정보를 보여주고 수정할 수 있는 transform을 구현했다.
????????
position, rotation 바꿔도 아무 변화가 없는데요?
당연함
지금 텍스트박스 내부적으로만 텍스트를 가지고 있어서
외부에서는 어떤 이벤트가 일어났고 어떤 텍스트를 가지고 있는지 알 수가 없다.
그래서 텍스트가 변하는 이벤트가 발생할 때마다 해야하는 일을
함수포인터에 등록해서 실행되도록 했다.
std::function<void(std::string str)> mEventCallback=NULL;
void TextBox::GeyKeyDown(std::string str)
{
if (!bTextActive)
return;
if(str=="BACKSPACE"){
mStr.pop_back();
if(mEventCallback)
mEventCallback(mStr);
return;
}
if (!bString && str[0] < 48 && str[0] > 58)
{
return;
}
mStr.append(str);
if(mEventCallback)
mEventCallback(mStr);
}
mStr에 string이 추가될때마다
등록된 콜백함수를 호출해서 원하는 동작을 할 수 있도록 구현했다.
'컴퓨터 그래픽스 > OpenGL' 카테고리의 다른 글
#11 Tinylender 개발일지 : color 기능 추가 (1) | 2024.09.05 |
---|---|
#10 Tinylender 개발일지 : 곡선으로 메시만들기 (1) | 2024.09.05 |
#8 Tinylender 개발일지 : 레이어 개발(1) (0) | 2024.07.25 |
#7 tinylender 개발일지 : extrude 기능 개발 (5) | 2024.05.31 |
#6 tinylender 개발일지 : 펜툴 제작 (0) | 2024.05.31 |