Fix UI hover, add icon
This commit is contained in:
parent
725aebf3b1
commit
efdffb34b9
@ -108,7 +108,7 @@ void init() {
|
|||||||
Input::addMouseListener(MouseCallback(defaultMouseCallback, nullptr));
|
Input::addMouseListener(MouseCallback(defaultMouseCallback, nullptr));
|
||||||
|
|
||||||
options = new ButtonElement(px(0), px(100), px(100), px(50));
|
options = new ButtonElement(px(0), px(100), px(100), px(50));
|
||||||
UI::addElement(options);
|
//UI::addElement(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ int init() {
|
|||||||
|
|
||||||
kekData.screenWidth = 800.0f;
|
kekData.screenWidth = 800.0f;
|
||||||
kekData.screenHeight = 600.0f;
|
kekData.screenHeight = 600.0f;
|
||||||
kekData.window = glfwCreateWindow(kekData.screenWidth, kekData.screenHeight, "KekEngine", NULL, NULL);
|
kekData.window = glfwCreateWindow(kekData.screenWidth, kekData.screenHeight, "KekEngine", nullptr, nullptr);
|
||||||
if(!kekData.window) {
|
if(!kekData.window) {
|
||||||
const char *errorMsg;
|
const char *errorMsg;
|
||||||
int code = glfwGetError(&errorMsg);
|
int code = glfwGetError(&errorMsg);
|
||||||
@ -122,7 +122,7 @@ int init() {
|
|||||||
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
|
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
glDebugMessageCallback(glDebugOutput, NULL);
|
glDebugMessageCallback(glDebugOutput, nullptr);
|
||||||
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
|
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +140,19 @@ int init() {
|
|||||||
return KEK_ERROR;
|
return KEK_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryBuffer *buf = Resource::loadResource("image/icon.png");
|
||||||
|
if(buf) {
|
||||||
|
int width, height, nrChannels;
|
||||||
|
unsigned char *data = stbi_load_from_memory((stbi_uc *) buf->buffer, buf->length, &width, &height, &nrChannels, 0);
|
||||||
|
GLFWimage image;
|
||||||
|
image.width = width;
|
||||||
|
image.height = height;
|
||||||
|
image.pixels = data;
|
||||||
|
glfwSetWindowIcon(kekData.window, 1, &image);
|
||||||
|
delete buf;
|
||||||
|
}
|
||||||
|
|
||||||
kekData.activeCamera = new Camera();
|
kekData.activeCamera = new Camera();
|
||||||
std::cout << "Poop cam is " << kekData.activeCamera << std::endl;
|
|
||||||
kekData.shader = new Shader("shader/mesh/vertex.glsl", "shader/mesh/fragment.glsl");
|
kekData.shader = new Shader("shader/mesh/vertex.glsl", "shader/mesh/fragment.glsl");
|
||||||
kekData.shader->initLighting();
|
kekData.shader->initLighting();
|
||||||
|
|
||||||
@ -166,7 +177,7 @@ int init() {
|
|||||||
Defaults::init();
|
Defaults::init();
|
||||||
|
|
||||||
fpsText = new TextElement(px(0), px(0));
|
fpsText = new TextElement(px(0), px(0));
|
||||||
UI::addElement(fpsText);
|
//UI::addElement(fpsText);
|
||||||
|
|
||||||
return KEK_SUCCESS;
|
return KEK_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -280,7 +291,8 @@ int start() {
|
|||||||
prevTime = time;
|
prevTime = time;
|
||||||
|
|
||||||
for(UIElement *uiEl : kekData.uiElements) {
|
for(UIElement *uiEl : kekData.uiElements) {
|
||||||
uiEl->drawAll(UIPoint(0, 0), uiProjection);
|
UIPoint pos = uiEl->getPosition();
|
||||||
|
uiEl->drawAll(pos, uiProjection);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
@ -97,7 +97,7 @@ void TextObject::allocateBuffer(TextBlock *block, int numChars) {
|
|||||||
glBindVertexArray(block->vao);
|
glBindVertexArray(block->vao);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, block->vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, block->vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, targetSize * sizeof(RenderChar), NULL, GL_DYNAMIC_DRAW); // 6 verts/char, 4 floats/vertex
|
glBufferData(GL_ARRAY_BUFFER, targetSize * sizeof(RenderChar), nullptr, GL_DYNAMIC_DRAW); // 6 verts/char, 4 floats/vertex
|
||||||
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
|
@ -81,7 +81,6 @@ GLFWKeyState getKeyState(KeyBinding binding) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setCursorMode(GLFWCursorMode mode) {
|
void setCursorMode(GLFWCursorMode mode) {
|
||||||
//std::cout << "POOP is " << mode << std::endl;
|
|
||||||
glfwSetInputMode(kekData.window, GLFW_CURSOR, (int) mode);
|
glfwSetInputMode(kekData.window, GLFW_CURSOR, (int) mode);
|
||||||
kekData.uiCursorMode = mode;
|
kekData.uiCursorMode = mode;
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,13 @@ static GLuint compileShader(GLenum type, std::string path) {
|
|||||||
GLint success;
|
GLint success;
|
||||||
|
|
||||||
GLuint shaderID = glCreateShader(type);
|
GLuint shaderID = glCreateShader(type);
|
||||||
glShaderSource(shaderID, 1, &src, NULL);
|
glShaderSource(shaderID, 1, &src, nullptr);
|
||||||
glCompileShader(shaderID);
|
glCompileShader(shaderID);
|
||||||
|
|
||||||
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
|
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
|
||||||
if(!success) {
|
if(!success) {
|
||||||
char log[512];
|
char log[512];
|
||||||
glGetShaderInfoLog(shaderID, 512, NULL, log);
|
glGetShaderInfoLog(shaderID, 512, nullptr, log);
|
||||||
std::cout << "Failed to compile shader \"" << path << "\":\n" << log << std::endl;
|
std::cout << "Failed to compile shader \"" << path << "\":\n" << log << std::endl;
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ static GLuint compileProgram(unsigned int n, GLenum *types, std::string *paths)
|
|||||||
|
|
||||||
if(!success) {
|
if(!success) {
|
||||||
char log[512];
|
char log[512];
|
||||||
glGetProgramInfoLog(id, 512, NULL, log);
|
glGetProgramInfoLog(id, 512, nullptr, log);
|
||||||
std::cout << "Failed to link program:\n" << log << std::endl;
|
std::cout << "Failed to link program:\n" << log << std::endl;
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ std::vector<UIElement *> UIElement::getChildren() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UIElement::addChild(UIElement *child) {
|
void UIElement::addChild(UIElement *child) {
|
||||||
|
child->parent = this;
|
||||||
children.push_back(child);
|
children.push_back(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ bool UIElement::hoverAll(UIPoint pos, UIPoint screenPos) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIElement *hoveredChild = NULL;
|
UIElement *hoveredChild = nullptr;
|
||||||
for(UIElement *child : children) {
|
for(UIElement *child : children) {
|
||||||
UIPoint childPos = child->getPosition();
|
UIPoint childPos = child->getPosition();
|
||||||
int relX = pos.x - childPos.x;
|
int relX = pos.x - childPos.x;
|
||||||
@ -135,7 +136,7 @@ bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button)
|
|||||||
UIBounds bounds = getBounds();
|
UIBounds bounds = getBounds();
|
||||||
if(!bounds.contains(pos)) return false; // Only used by topmost parent UIElement
|
if(!bounds.contains(pos)) return false; // Only used by topmost parent UIElement
|
||||||
|
|
||||||
UIElement *clickedChild = NULL;
|
UIElement *clickedChild = nullptr;
|
||||||
for(UIElement *child : children) {
|
for(UIElement *child : children) {
|
||||||
if(!child->clickable) continue;
|
if(!child->clickable) continue;
|
||||||
UIPoint childPos = child->getPosition();
|
UIPoint childPos = child->getPosition();
|
||||||
@ -146,7 +147,7 @@ bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button)
|
|||||||
clickedChild = child;
|
clickedChild = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(clickedChild != NULL) {
|
if(clickedChild != nullptr) {
|
||||||
UIPoint childPos = clickedChild->getPosition();
|
UIPoint childPos = clickedChild->getPosition();
|
||||||
clickedChild->clickAll(UIPoint(pos.x - childPos.x, pos.y - childPos.y), screenPos, button);
|
clickedChild->clickAll(UIPoint(pos.x - childPos.x, pos.y - childPos.y), screenPos, button);
|
||||||
}else {
|
}else {
|
||||||
|
@ -180,10 +180,6 @@ UIBounds RectangleElement::getBounds() {
|
|||||||
return offsetUIBounds(uiToScreen(w), uiToScreen(h), origin);
|
return offsetUIBounds(uiToScreen(w), uiToScreen(h), origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RectangleElement::setColor(Color color) {
|
|
||||||
this->color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RectangleElement::draw(UIPoint screenPos, glm::mat4 projection) {
|
void RectangleElement::draw(UIPoint screenPos, glm::mat4 projection) {
|
||||||
kekData.uiRectangleShader->use();
|
kekData.uiRectangleShader->use();
|
||||||
|
|
||||||
@ -199,7 +195,9 @@ void RectangleElement::draw(UIPoint screenPos, glm::mat4 projection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ButtonElement::ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h): RectangleElement(x, y, w, h) {
|
ButtonElement::ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h): RectangleElement(x, y, w, h) {
|
||||||
this->text = new TextElement(px(0), px(0));
|
this->text = new TextElement(pw(0.5), ph(0.5));
|
||||||
|
text->origin = Origin::CENTER;
|
||||||
|
addChild(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonElement::~ButtonElement() {
|
ButtonElement::~ButtonElement() {
|
||||||
@ -210,28 +208,16 @@ UIElementType ButtonElement::getType() {
|
|||||||
return UIElementType::BUTTON;
|
return UIElementType::BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextElement *ButtonElement::getText() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonElement::setColor(Color color) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonElement::setOnClickCallback(Callable onClick) {
|
|
||||||
this->onClick = onClick;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonElement::hover(UIPoint pos, UIPoint screenPos) {
|
void ButtonElement::hover(UIPoint pos, UIPoint screenPos) {
|
||||||
RectangleElement::setColor(Colors::YELLOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonElement::hoverEnter() {
|
void ButtonElement::hoverEnter(UIPoint pos, UIPoint screenPos) {
|
||||||
RectangleElement::setColor(Colors::RED);
|
color = hoverColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonElement::hoverExit() {
|
void ButtonElement::hoverExit() {
|
||||||
|
color = defaultColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonElement::click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {
|
void ButtonElement::click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {
|
||||||
|
@ -20,19 +20,20 @@ struct Color {
|
|||||||
class Colors {
|
class Colors {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr Color RED = Color(1.0, 0.0, 0.0);
|
static constexpr Color RED = Color(1.0, 0.0, 0.0);
|
||||||
static constexpr Color ORANGE = Color(1.0, 0.5, 0.0);
|
static constexpr Color ORANGE = Color(1.0, 0.5, 0.0);
|
||||||
static constexpr Color YELLOW = Color(1.0, 1.0, 0.0);
|
static constexpr Color YELLOW = Color(1.0, 1.0, 0.0);
|
||||||
static constexpr Color GREEN = Color(0.0, 1.0, 0.0);
|
static constexpr Color GREEN = Color(0.0, 1.0, 0.0);
|
||||||
static constexpr Color CYAN = Color(0.0, 1.0, 1.0);
|
static constexpr Color CYAN = Color(0.0, 1.0, 1.0);
|
||||||
static constexpr Color BLUE = Color(0.0, 0.0, 1.0);
|
static constexpr Color BLUE = Color(0.0, 0.0, 1.0);
|
||||||
static constexpr Color PURPLE = Color(0.5, 0.0, 0.5);
|
static constexpr Color PURPLE = Color(0.5, 0.0, 0.5);
|
||||||
static constexpr Color MAGENTA = Color(1.0, 0.0, 1.0);
|
static constexpr Color MAGENTA = Color(1.0, 0.0, 1.0);
|
||||||
static constexpr Color GRAY = Color(0.5, 0.5, 0.5);
|
static constexpr Color GRAY = Color(0.5, 0.5, 0.5);
|
||||||
static constexpr Color WHITE = Color(1.0, 1.0, 1.0);
|
static constexpr Color WHITE = Color(1.0, 1.0, 1.0);
|
||||||
static constexpr Color BLACK = Color(0.0, 0.0, 0.0);
|
static constexpr Color BLACK = Color(0.0, 0.0, 0.0);
|
||||||
|
static constexpr Color TRANSPARENT = Color(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
Colors() = delete;
|
Colors() = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct UIBounds {
|
|||||||
UIBounds(int x, int y, int w, int h): x(x), y(y), w(w), h(h) {}
|
UIBounds(int x, int y, int w, int h): x(x), y(y), w(w), h(h) {}
|
||||||
|
|
||||||
inline bool contains(UIPoint pos) {
|
inline bool contains(UIPoint pos) {
|
||||||
return pos.x < x || pos.y < y || pos.x >= x + w || pos.y >= y + h;
|
return pos.x > x && pos.y > y && pos.x < x + w && pos.y < y + h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ protected:
|
|||||||
int uiToScreen(UIValue val);
|
int uiToScreen(UIValue val);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Returns the bounds of the element relative to its origin (as returned by getX() and getY())
|
// Returns the bounds of the element relative to its origin
|
||||||
virtual UIBounds getBounds() = 0;
|
virtual UIBounds getBounds() = 0;
|
||||||
|
|
||||||
void drawAll(UIPoint screenPos, glm::mat4 projection);
|
void drawAll(UIPoint screenPos, glm::mat4 projection);
|
||||||
|
@ -47,12 +47,13 @@ class RectangleElement: public UIElement {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
UIValue w, h;
|
UIValue w, h;
|
||||||
Color color;
|
|
||||||
|
|
||||||
unsigned int vao;
|
unsigned int vao;
|
||||||
unsigned int vbo;
|
unsigned int vbo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Color color;
|
||||||
|
|
||||||
RectangleElement(UIValue x, UIValue y, UIValue w, UIValue h);
|
RectangleElement(UIValue x, UIValue y, UIValue w, UIValue h);
|
||||||
|
|
||||||
virtual ~RectangleElement();
|
virtual ~RectangleElement();
|
||||||
@ -61,35 +62,27 @@ public:
|
|||||||
|
|
||||||
virtual UIBounds getBounds();
|
virtual UIBounds getBounds();
|
||||||
|
|
||||||
virtual void setColor(Color color);
|
|
||||||
|
|
||||||
virtual void draw(UIPoint screenPos, glm::mat4 projection);
|
virtual void draw(UIPoint screenPos, glm::mat4 projection);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ButtonElement: public RectangleElement {
|
class ButtonElement: public RectangleElement {
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
TextElement *text;
|
TextElement *text;
|
||||||
Color color;
|
Color defaultColor;
|
||||||
|
Color hoverColor;
|
||||||
Callable onClick;
|
Callable onClick;
|
||||||
|
|
||||||
public:
|
|
||||||
ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h);
|
ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h);
|
||||||
|
|
||||||
virtual ~ButtonElement();
|
virtual ~ButtonElement();
|
||||||
|
|
||||||
virtual UIElementType getType();
|
virtual UIElementType getType();
|
||||||
|
|
||||||
TextElement *getText();
|
|
||||||
|
|
||||||
virtual void setColor(Color color);
|
|
||||||
|
|
||||||
void setOnClickCallback(Callable onClick);
|
|
||||||
|
|
||||||
virtual void hover(UIPoint pos, UIPoint screenPos);
|
virtual void hover(UIPoint pos, UIPoint screenPos);
|
||||||
|
|
||||||
virtual void hoverEnter();
|
virtual void hoverEnter(UIPoint pos, UIPoint screenPos);
|
||||||
|
|
||||||
virtual void hoverExit();
|
virtual void hoverExit();
|
||||||
|
|
||||||
|
BIN
src/kekengine/res/image/icon.png
Normal file
BIN
src/kekengine/res/image/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
@ -6,4 +6,4 @@ uniform vec4 rectColor;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
color = rectColor;
|
color = rectColor;
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,4 @@ uniform vec4 bounds;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = projection * vec4(position * bounds.zw + bounds.xy, 0.0, 1.0);
|
gl_Position = projection * vec4(position * bounds.zw + bounds.xy, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
@ -6,27 +6,16 @@
|
|||||||
|
|
||||||
using namespace kek;
|
using namespace kek;
|
||||||
|
|
||||||
static KeyBinding keyWow;
|
|
||||||
|
|
||||||
void periodicCallback(GLFWwindow *window, void *data){
|
void periodicCallback(GLFWwindow *window, void *data){
|
||||||
if(Input::getKeyState(keyWow) == GLFW_PRESS) {
|
|
||||||
//std::cout << "WOW" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data){
|
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data){
|
||||||
if(key == Input::getKeyBinding(keyWow).key && action == GLFW_PRESS) {
|
|
||||||
std::cout << "WOW" << std::endl;
|
|
||||||
if(glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) {
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
|
||||||
}else {
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods, void *data){
|
void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods, void *data){
|
||||||
std::cout << "HELLO" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
@ -61,13 +50,15 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
Engine::setActiveScene(scene);
|
Engine::setActiveScene(scene);
|
||||||
|
|
||||||
keyWow = Input::createKeyBinding("wow", GLFW_KEY_O);
|
|
||||||
Input::addPeriodicCallback(PeriodicCallback(periodicCallback, nullptr));
|
Input::addPeriodicCallback(PeriodicCallback(periodicCallback, nullptr));
|
||||||
Input::addKeyListener(KeyCallback(keyCallback, nullptr));
|
Input::addKeyListener(KeyCallback(keyCallback, nullptr));
|
||||||
Input::addMouseButtonListener(MouseButtonCallback(mouseButtonCallback, nullptr));
|
Input::addMouseButtonListener(MouseButtonCallback(mouseButtonCallback, nullptr));
|
||||||
|
|
||||||
ButtonElement *btn = new ButtonElement(px(0), px(100), px(200), px(50));
|
ButtonElement *btn = new ButtonElement(px(0), px(100), px(200), px(50));
|
||||||
btn->getText()->setText("Hello There!");
|
btn->text->color = Colors::BLACK;
|
||||||
|
btn->defaultColor = btn->color = Colors::WHITE;
|
||||||
|
btn->hoverColor = Colors::GRAY;
|
||||||
|
btn->text->setText("Hello There!");
|
||||||
UI::addElement(btn);
|
UI::addElement(btn);
|
||||||
|
|
||||||
Engine::start();
|
Engine::start();
|
||||||
|
Loading…
Reference in New Issue
Block a user