TextBox validation + minor refactor, fixes

This commit is contained in:
MihailRis 2024-01-11 02:37:29 +03:00
parent 61ad839ebf
commit e1d30732df
7 changed files with 85 additions and 53 deletions

View File

@ -28,7 +28,7 @@ void BlocksPreview::begin(const Viewport* viewport) {
shader->uniformMatrix("u_projview",
glm::ortho(0.0f, float(viewport->getWidth()),
0.0f, float(viewport->getHeight()),
-1000.0f, 1000.0f) *
-100.0f, 100.0f) *
glm::lookAt(glm::vec3(2, 2, 2), glm::vec3(0.0f), glm::vec3(0, 1, 0)));
atlas->getTexture()->bind();
}
@ -42,15 +42,17 @@ void BlocksPreview::draw(const Block* def, int x, int y, int size, glm::vec4 tin
x += 2;
if (def->model == BlockModel::aabb) {
y += (1.0f - def->hitbox.size()).y * size * 0.5f;
x += (1.0f - def->hitbox.size()).x * size * 0.5f;
y += (1.0f - def->hitbox.size()).y * size * 0.25f;
}
glm::vec3 offset (x/float(width) * 2, y/float(height) * 2, 0.0f);
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
blockid_t id = def->rt.id;
const UVRegion texfaces[6]{ cache->getRegion(id, 0), cache->getRegion(id, 1),
cache->getRegion(id, 2), cache->getRegion(id, 3),
cache->getRegion(id, 4), cache->getRegion(id, 5)};
const UVRegion texfaces[6]{cache->getRegion(id, 0), cache->getRegion(id, 1),
cache->getRegion(id, 2), cache->getRegion(id, 3),
cache->getRegion(id, 4), cache->getRegion(id, 5)};
switch (def->model) {
case BlockModel::none:

View File

@ -144,7 +144,19 @@ TextBox::TextBox(wstring placeholder, vec4 padding)
void TextBox::drawBackground(Batch2D* batch, Assets* assets) {
vec2 coord = calcCoord();
batch->texture(nullptr);
batch->color = (isfocused() ? focusedColor : (hover_ ? hoverColor : color_));
if (valid) {
if (isfocused()) {
batch->color = focusedColor;
} else if (hover_) {
batch->color = hoverColor;
} else {
batch->color = color_;
}
} else {
batch->color = invalidColor;
}
batch->rect(coord.x, coord.y, size_.x, size_.y);
if (!focused_ && supplier) {
input = supplier();
@ -162,6 +174,24 @@ void TextBox::drawBackground(Batch2D* batch, Assets* assets) {
void TextBox::typed(unsigned int codepoint) {
input += wstring({(wchar_t)codepoint});
validate();
}
bool TextBox::validate() {
if (validator) {
valid = validator(input);
} else {
valid = true;
}
return valid;
}
void TextBox::setValid(bool valid) {
this->valid = valid;
}
bool TextBox::isValid() const {
return valid;
}
void TextBox::keyPressed(int key) {
@ -169,10 +199,11 @@ void TextBox::keyPressed(int key) {
case KEY_BACKSPACE:
if (!input.empty()){
input = input.substr(0, input.length()-1);
validate();
}
break;
case KEY_ENTER:
if (consumer) {
if (validate() && consumer) {
consumer(label->text());
}
defocus();
@ -183,6 +214,7 @@ void TextBox::keyPressed(int key) {
const char* text = Window::getClipboardText();
if (text) {
input += util::str2wstr_utf8(text);
validate();
}
}
}
@ -199,6 +231,10 @@ void TextBox::textConsumer(wstringconsumer consumer) {
this->consumer = consumer;
}
void TextBox::textValidator(wstringchecker validator) {
this->validator = validator;
}
wstring TextBox::text() const {
if (input.empty())
return placeholder;
@ -297,6 +333,7 @@ void TrackBar::mouseMove(GUI*, int x, int y) {
// ================================ CheckBox ==================================
CheckBox::CheckBox(bool checked) : UINode(vec2(), vec2(32.0f)), checked_(checked) {
color(vec4(0.0f, 0.0f, 0.0f, 0.5f));
margin(vec4(0.0f, 0.0f, 5.0f, 0.0f));
}
void CheckBox::draw(Batch2D* batch, Assets* assets) {

View File

@ -23,6 +23,8 @@ namespace gui {
typedef std::function<bool()> boolsupplier;
typedef std::function<void(bool)> boolconsumer;
typedef std::function<bool(const std::wstring&)> wstringchecker;
class Label : public UINode {
protected:
std::wstring text_;
@ -71,11 +73,14 @@ namespace gui {
protected:
glm::vec4 hoverColor {0.05f, 0.1f, 0.2f, 0.75f};
glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f};
glm::vec4 invalidColor {0.1f, 0.05f, 0.03f, 1.0f};
Label* label;
std::wstring input;
std::wstring placeholder;
wstringsupplier supplier = nullptr;
wstringconsumer consumer = nullptr;
wstringchecker validator = nullptr;
bool valid = true;
public:
TextBox(std::wstring placeholder,
glm::vec4 padding=glm::vec4(2.0f));
@ -87,8 +92,12 @@ namespace gui {
virtual void keyPressed(int key) override;
virtual void textSupplier(wstringsupplier supplier);
virtual void textConsumer(wstringconsumer consumer);
virtual void textValidator(wstringchecker validator);
virtual bool isfocuskeeper() const override {return true;}
virtual std::wstring text() const;
virtual bool validate();
virtual void setValid(bool valid);
virtual bool isValid() const;
};
class InputBindBox : public Panel {

View File

@ -135,22 +135,14 @@ void HudRenderer::createDebugPanel(Engine* engine) {
}));
{
TrackBar* bar = new TrackBar(0.0f, 1.0f, 1.0f, 0.005f, 8);
bar->supplier([=]() {
return level->world->daytime;
});
bar->consumer([=](double val) {
level->world->daytime = val;
});
bar->supplier([=]() {return level->world->daytime;});
bar->consumer([=](double val) {level->world->daytime = val;});
panel->add(bar);
}
{
TrackBar* bar = new TrackBar(0.0f, 1.0f, 0.0f, 0.005f, 8);
bar->supplier([=]() {
return WorldRenderer::fog;
});
bar->consumer([=](double val) {
WorldRenderer::fog = val;
});
bar->supplier([=]() {return WorldRenderer::fog;});
bar->consumer([=](double val) {WorldRenderer::fog = val;});
panel->add(bar);
}
{
@ -159,7 +151,6 @@ void HudRenderer::createDebugPanel(Engine* engine) {
checkpanel->orientation(Orientation::horizontal);
CheckBox* checkbox = new CheckBox();
checkbox->margin(vec4(0.0f, 0.0f, 5.0f, 0.0f));
checkbox->supplier([=]() {
return engine->getSettings().debug.showChunkBorders;
});
@ -249,19 +240,25 @@ void HudRenderer::draw(const GfxContext& ctx){
const uint width = viewport.getWidth();
const uint height = viewport.getHeight();
debugPanel->visible(level->player->debug);
Player* player = level->player;
debugPanel->visible(player->debug);
uicamera->setFov(height);
Shader* uishader = assets->getShader("ui");
uishader->use();
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
auto batch = ctx.getBatch2D();
batch->begin();
// Chosen block preview
batch->color = vec4(1.0f);
Shader* uishader = assets->getShader("ui");
uishader->use();
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
// Draw selected item preview
hotbarView->setPosition(width-60, height-60);
hotbarView->setItems({player->getChosenItem()});
hotbarView->actAndDraw(&ctx);
// Crosshair
batch->begin();
if (Events::_cursor_locked && !level->player->debug) {
batch->lineWidth(2);
batch->line(width/2, height/2-6, width/2, height/2+6, 0.2f, 0.2f, 0.2f, 1.0f);
@ -270,20 +267,16 @@ void HudRenderer::draw(const GfxContext& ctx){
batch->line(width/2+5, height/2-5, width/2-5, height/2+5, 0.9f, 0.9f, 0.9f, 1.0f);
}
Player* player = level->player;
hotbarView->setPosition(width-56, height-56);
hotbarView->setItems({player->getChosenItem()});
hotbarView->actAndDraw(&ctx);
uishader->use();
batch->begin();
if (pause) {
// draw fullscreen dark overlay
batch->texture(nullptr);
batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f);
batch->rect(0, 0, width, height);
}
if (inventoryOpen) {
// draw content access panel (all available items)
contentAccess->setPosition(viewport.getWidth()-contentAccess->getWidth(), 0);
contentAccess->actAndDraw(&ctx);
}

View File

@ -277,6 +277,12 @@ void create_new_world_panel(Engine* engine, PagesControl* menu) {
panel->add(label);
TextBox* input = new TextBox(L"New World", vec4(6.0f));
input->textValidator([=](const std::wstring& text) {
EnginePaths* paths = engine->getPaths();
std::string textutf8 = util::wstr2str_utf8(text);
return util::is_valid_filename(text) &&
!paths->isWorldNameUsed(textutf8);
});
panel->add(input);
worldNameInput = input;
}
@ -287,29 +293,15 @@ void create_new_world_panel(Engine* engine, PagesControl* menu) {
panel->add(seedInput);
}
vec4 basecolor = worldNameInput->color();
panel->add(create_button( L"Create World", vec4(10), vec4(1, 20, 1, 1),
[=](GUI*) {
if (!worldNameInput->validate())
return;
std::wstring name = worldNameInput->text();
std::string nameutf8 = util::wstr2str_utf8(name);
EnginePaths* paths = engine->getPaths();
// Basic validation
if (!util::is_valid_filename(name) ||
paths->isWorldNameUsed(nameutf8)) {
// blink red two times
panel->listenInterval(0.1f, [worldNameInput, basecolor]() {
static bool flag = true;
if (flag) {
worldNameInput->color(vec4(0.3f, 0.0f, 0.0f, 0.5f));
} else {
worldNameInput->color(basecolor);
}
flag = !flag;
}, 4);
return;
}
std::wstring seedstr = seedInput->text();
uint64_t seed = str2seed(seedstr);
std::cout << "world seed: " << seed << std::endl;
@ -447,7 +439,6 @@ void create_settings_panel(Engine* engine, PagesControl* menu) {
checkpanel->orientation(Orientation::horizontal);
CheckBox* checkbox = new CheckBox();
checkbox->margin(vec4(0.0f, 0.0f, 5.0f, 0.0f));
checkbox->supplier([=]() {
return engine->getSettings().display.swapInterval != 0;
});
@ -466,7 +457,6 @@ void create_settings_panel(Engine* engine, PagesControl* menu) {
checkpanel->orientation(Orientation::horizontal);
CheckBox* checkbox = new CheckBox();
checkbox->margin(vec4(0.0f, 0.0f, 5.0f, 0.0f));
checkbox->supplier([=]() {
return engine->getSettings().graphics.backlight != 0;
});

View File

@ -36,6 +36,7 @@ Batch2D::~Batch2D(){
void Batch2D::begin(){
_texture = nullptr;
blank->bind();
color = vec4(1.0f);
}
void Batch2D::vertex(float x, float y,

View File

@ -169,7 +169,7 @@ void Batch3D::xSprite(float w, float h, const UVRegion& uv, const vec4 tint, boo
}
void Batch3D::blockCube(const vec3 size, const UVRegion(&texfaces)[6], const vec4 tint, bool shading) {
vec3 coord = (1.0f - size) * -0.45f;
vec3 coord = (1.0f - size) * -0.5f;
face(coord+vec3(0.0f, 0.0f, 0.0f), size.x, size.y, vec3(1, 0, 0), vec3(0, 1, 0), texfaces[5], (shading ? do_tint(0.8)*tint : tint));
face(coord+vec3(size.x, 0.0f, -size.z), size.x, size.y, vec3(-1, 0, 0), vec3(0, 1, 0), texfaces[4], (shading ? do_tint(0.8f)*tint : tint));
face(coord+vec3(0.0f, size.y, 0.0f), size.x, size.z, vec3(1, 0, 0), vec3(0, 0, -1), texfaces[3], (shading ? do_tint(1.0f)*tint : tint));