Working on list of players

This commit is contained in:
Vladislav Khorev committed 2026-03-09 23:04:48 +03:00
1 parent a8ded217df
commit 785b96ce82
10 files changed
+544 -13

No files matched your search

+262 -2
View File
@@ -72,6 +72,65 @@ namespace ZL {
renderer.PopMatrix();
}
void UiTextButton::buildMesh() {
mesh.data.PositionData.clear();
mesh.data.TexCoordData.clear();
float x0 = rect.x;
float y0 = rect.y;
float x1 = rect.x + rect.w;
float y1 = rect.y + rect.h;
mesh.data.PositionData.push_back({ x0, y0, 0 });
mesh.data.TexCoordData.push_back({ 0, 0 });
mesh.data.PositionData.push_back({ x0, y1, 0 });
mesh.data.TexCoordData.push_back({ 0, 1 });
mesh.data.PositionData.push_back({ x1, y1, 0 });
mesh.data.TexCoordData.push_back({ 1, 1 });
mesh.data.PositionData.push_back({ x0, y0, 0 });
mesh.data.TexCoordData.push_back({ 0, 0 });
mesh.data.PositionData.push_back({ x1, y1, 0 });
mesh.data.TexCoordData.push_back({ 1, 1 });
mesh.data.PositionData.push_back({ x1, y0, 0 });
mesh.data.TexCoordData.push_back({ 1, 0 });
mesh.RefreshVBO();
}
void UiTextButton::draw(Renderer& renderer) const {
renderer.PushMatrix();
renderer.TranslateMatrix({ animOffsetX, animOffsetY, 0.0f });
renderer.ScaleMatrix({ animScaleX, animScaleY, 1.0f });
// Draw background texture (optional)
const std::shared_ptr<Texture>* tex = nullptr;
switch (state) {
case ButtonState::Normal: if (texNormal) tex = &texNormal; break;
case ButtonState::Hover: tex = texHover ? &texHover : (texNormal ? &texNormal : nullptr); break;
case ButtonState::Pressed: tex = texPressed ? &texPressed : (texNormal ? &texNormal : nullptr); break;
case ButtonState::Disabled: tex = texDisabled ? &texDisabled : (texNormal ? &texNormal : nullptr); break;
}
if (tex && *tex) {
renderer.RenderUniform1i(textureUniformName, 0);
glBindTexture(GL_TEXTURE_2D, (*tex)->getTexID());
renderer.DrawVertexRenderStruct(mesh);
}
renderer.PopMatrix();
// Draw text on top (uses absolute coords, add anim offset manually)
if (textRenderer && !text.empty()) {
float cx = rect.x + rect.w / 2.0f + animOffsetX;
float cy = rect.y + rect.h / 2.0f + animOffsetY;
textRenderer->drawText(text, cx, cy, 1.0f, textCentered, color);
}
}
void UiSlider::buildTrackMesh() {
trackMesh.data.PositionData.clear();
trackMesh.data.TexCoordData.clear();
@@ -393,6 +452,49 @@ namespace ZL {
node->textField = tf;
}
if (typeStr == "TextButton") {
auto tb = std::make_shared<UiTextButton>();
tb->name = node->name;
tb->rect = initialRect;
tb->border = j.value("border", 0.0f);
// Textures are optional
if (j.contains("textures") && j["textures"].is_object()) {
auto t = j["textures"];
auto loadTex = [&](const std::string& key) -> std::shared_ptr<Texture> {
if (!t.contains(key) || !t[key].is_string()) return nullptr;
std::string path = t[key].get<std::string>();
try {
auto data = CreateTextureDataFromPng(path.c_str(), zipFile.c_str());
return std::make_shared<Texture>(data);
}
catch (const std::exception& e) {
std::cerr << "UiManager: TextButton '" << tb->name << "' failed to load texture " << path << ": " << e.what() << std::endl;
return nullptr;
}
};
tb->texNormal = loadTex("normal");
tb->texHover = loadTex("hover");
tb->texPressed = loadTex("pressed");
tb->texDisabled = loadTex("disabled");
}
if (j.contains("text")) tb->text = j["text"].get<std::string>();
if (j.contains("fontPath")) tb->fontPath = j["fontPath"].get<std::string>();
if (j.contains("fontSize")) tb->fontSize = j["fontSize"].get<int>();
if (j.contains("textCentered")) tb->textCentered = j["textCentered"].get<bool>();
if (j.contains("color") && j["color"].is_array() && j["color"].size() == 4) {
for (int i = 0; i < 4; ++i) tb->color[i] = j["color"][i].get<float>();
}
tb->textRenderer = std::make_unique<TextRenderer>();
if (!tb->textRenderer->init(renderer, tb->fontPath, tb->fontSize, zipFile)) {
std::cerr << "UiManager: Failed to init TextRenderer for TextButton: " << tb->name << std::endl;
}
node->textButton = tb;
}
if (j.contains("animations") && j["animations"].is_object()) {
for (auto it = j["animations"].begin(); it != j["animations"].end(); ++it) {
std::string animName = it.key();
@@ -536,6 +638,7 @@ namespace ZL {
root->localY // finalLocalY
);
buttons.clear();
textButtons.clear();
sliders.clear();
textViews.clear();
textFields.clear();
@@ -547,6 +650,9 @@ namespace ZL {
for (auto& b : buttons) {
b->buildMesh();
}
for (auto& tb : textButtons) {
tb->buildMesh();
}
for (auto& s : sliders) {
s->buildTrackMesh();
s->buildKnobMesh();
@@ -694,11 +800,14 @@ namespace ZL {
// 1. Обновляем кнопку
if (node->button) {
node->button->rect = node->screenRect;
// Если у кнопки есть анимационные смещения, они учитываются внутри buildMesh
// или при рендеринге через Uniform-переменные матрицы модели.
node->button->buildMesh();
}
if (node->textButton) {
node->textButton->rect = node->screenRect;
node->textButton->buildMesh();
}
// 2. Обновляем слайдер
if (node->slider) {
node->slider->rect = node->screenRect;
@@ -744,6 +853,9 @@ namespace ZL {
if (node->button) {
buttons.push_back(node->button);
}
if (node->textButton) {
textButtons.push_back(node->textButton);
}
if (node->slider) {
sliders.push_back(node->slider);
}
@@ -862,10 +974,13 @@ namespace ZL {
MenuState prev;
prev.root = root;
prev.buttons = buttons;
prev.textButtons = textButtons;
prev.sliders = sliders;
prev.textViews = textViews;
prev.textFields = textFields;
prev.staticImages = staticImages;
prev.pressedButtons = pressedButtons;
prev.pressedTextButtons = pressedTextButtons;
prev.pressedSliders = pressedSliders;
prev.focusedTextField = focusedTextField;
prev.path = "";
@@ -884,6 +999,14 @@ namespace ZL {
b->animScaleY = 1.0f;
}
}
for (auto& tb : textButtons) {
if (tb) {
tb->animOffsetX = 0.0f;
tb->animOffsetY = 0.0f;
tb->animScaleX = 1.0f;
tb->animScaleY = 1.0f;
}
}
replaceRoot(newRoot);
menuStack.push_back(std::move(prev));
@@ -913,10 +1036,13 @@ namespace ZL {
root = s.root;
buttons = s.buttons;
textButtons = s.textButtons;
sliders = s.sliders;
textViews = s.textViews;
textFields = s.textFields;
staticImages = s.staticImages;
pressedButtons = s.pressedButtons;
pressedTextButtons = s.pressedTextButtons;
pressedSliders = s.pressedSliders;
focusedTextField = s.focusedTextField;
@@ -931,6 +1057,15 @@ namespace ZL {
b->buildMesh();
}
}
for (auto& tb : textButtons) {
if (tb) {
tb->animOffsetX = 0.0f;
tb->animOffsetY = 0.0f;
tb->animScaleX = 1.0f;
tb->animScaleY = 1.0f;
tb->buildMesh();
}
}
for (auto& sl : sliders) {
if (sl) {
@@ -956,6 +1091,9 @@ namespace ZL {
for (const auto& b : buttons) {
b->draw(renderer);
}
for (const auto& tb : textButtons) {
tb->draw(renderer);
}
for (const auto& s : sliders) {
s->draw(renderer);
}
@@ -1007,6 +1145,12 @@ namespace ZL {
node->button->animScaleX = act.origScaleX;
node->button->animScaleY = act.origScaleY;
}
if (node->textButton) {
node->textButton->animOffsetX = act.origOffsetX;
node->textButton->animOffsetY = act.origOffsetY;
node->textButton->animScaleX = act.origScaleX;
node->textButton->animScaleY = act.origScaleY;
}
act.stepIndex = 0;
act.elapsedMs = 0.0f;
act.stepStarted = false;
@@ -1028,12 +1172,20 @@ namespace ZL {
node->button->animOffsetX = step.toX;
node->button->animOffsetY = step.toY;
}
if (node->textButton) {
node->textButton->animOffsetX = step.toX;
node->textButton->animOffsetY = step.toY;
}
}
else if (step.type == "scale") {
if (node->button) {
node->button->animScaleX = step.toX;
node->button->animScaleY = step.toY;
}
if (node->textButton) {
node->textButton->animScaleX = step.toX;
node->textButton->animScaleY = step.toY;
}
}
act.stepIndex++;
act.elapsedMs = 0.0f;
@@ -1048,6 +1200,12 @@ namespace ZL {
act.origScaleX = node->button->animScaleX;
act.origScaleY = node->button->animScaleY;
}
else if (node->textButton) {
act.origOffsetX = node->textButton->animOffsetX;
act.origOffsetY = node->textButton->animOffsetY;
act.origScaleX = node->textButton->animScaleX;
act.origScaleY = node->textButton->animScaleY;
}
else {
act.origOffsetX = act.origOffsetY = 0.0f;
act.origScaleX = act.origScaleY = 1.0f;
@@ -1064,6 +1222,12 @@ namespace ZL {
act.startScaleX = node->button->animScaleX;
act.startScaleY = node->button->animScaleY;
}
else if (node->textButton) {
act.startOffsetX = node->textButton->animOffsetX;
act.startOffsetY = node->textButton->animOffsetY;
act.startScaleX = node->textButton->animScaleX;
act.startScaleY = node->textButton->animScaleY;
}
else {
act.startOffsetX = act.startOffsetY = 0.0f;
act.startScaleX = act.startScaleY = 1.0f;
@@ -1089,6 +1253,10 @@ namespace ZL {
node->button->animOffsetX = nx;
node->button->animOffsetY = ny;
}
if (node->textButton) {
node->textButton->animOffsetX = nx;
node->textButton->animOffsetY = ny;
}
}
else if (step.type == "scale") {
float sx = act.startScaleX + (act.endScaleX - act.startScaleX) * te;
@@ -1097,6 +1265,10 @@ namespace ZL {
node->button->animScaleX = sx;
node->button->animScaleY = sy;
}
if (node->textButton) {
node->textButton->animScaleX = sx;
node->textButton->animScaleY = sy;
}
}
else if (step.type == "wait") {
//wait
@@ -1146,6 +1318,17 @@ namespace ZL {
}
}
}
for (auto& tb : textButtons) {
if (tb->state != ButtonState::Disabled)
{
if (tb->rect.containsConsideringBorder((float)x, (float)y, tb->border)) {
if (tb->state != ButtonState::Pressed) tb->state = ButtonState::Hover;
}
else {
if (tb->state != ButtonState::Pressed) tb->state = ButtonState::Normal;
}
}
}
}
auto it = pressedSliders.find(fingerId);
@@ -1180,6 +1363,18 @@ namespace ZL {
}
}
for (auto& tb : textButtons) {
if (tb->state != ButtonState::Disabled)
{
if (tb->rect.containsConsideringBorder((float)x, (float)y, tb->border)) {
tb->state = ButtonState::Pressed;
pressedTextButtons[fingerId] = tb;
if (tb->onPress) tb->onPress(tb->name);
break;
}
}
}
for (auto& s : sliders) {
if (s->rect.contains((float)x, (float)y)) {
pressedSliders[fingerId] = s;
@@ -1212,6 +1407,7 @@ namespace ZL {
void UiManager::onTouchUp(int64_t fingerId, int x, int y) {
std::vector<std::shared_ptr<UiButton>> clicked;
std::vector<std::shared_ptr<UiTextButton>> clickedText;
auto btnIt = pressedButtons.find(fingerId);
if (btnIt != pressedButtons.end()) {
@@ -1229,6 +1425,21 @@ namespace ZL {
pressedButtons.erase(btnIt);
}
auto tbIt = pressedTextButtons.find(fingerId);
if (tbIt != pressedTextButtons.end()) {
auto tb = tbIt->second;
if (tb) {
bool contains = tb->rect.contains((float)x, (float)y);
if (tb->state == ButtonState::Pressed) {
if (contains) {
clickedText.push_back(tb);
}
tb->state = (contains && fingerId == MOUSE_FINGER_ID) ? ButtonState::Hover : ButtonState::Normal;
}
}
pressedTextButtons.erase(tbIt);
}
pressedSliders.erase(fingerId);
for (auto& b : clicked) {
@@ -1236,6 +1447,11 @@ namespace ZL {
b->onClick(b->name);
}
}
for (auto& tb : clickedText) {
if (tb->onClick) {
tb->onClick(tb->name);
}
}
}
void UiManager::onKeyPress(unsigned char key) {
@@ -1287,6 +1503,12 @@ namespace ZL {
aa.origScaleX = node->button->animScaleX;
aa.origScaleY = node->button->animScaleY;
}
else if (node->textButton) {
aa.origOffsetX = node->textButton->animOffsetX;
aa.origOffsetY = node->textButton->animOffsetY;
aa.origScaleX = node->textButton->animScaleX;
aa.origScaleY = node->textButton->animScaleY;
}
auto cbIt = animCallbacks.find({ nodeName, animName });
if (cbIt != animCallbacks.end()) aa.onComplete = cbIt->second;
nodeActiveAnims[node].push_back(std::move(aa));
@@ -1337,6 +1559,12 @@ namespace ZL {
aa.origScaleX = n->button->animScaleX;
aa.origScaleY = n->button->animScaleY;
}
else if (n->textButton) {
aa.origOffsetX = n->textButton->animOffsetX;
aa.origOffsetY = n->textButton->animOffsetY;
aa.origScaleX = n->textButton->animScaleX;
aa.origScaleY = n->textButton->animScaleY;
}
auto cbIt = animCallbacks.find({ n->name, animName });
if (cbIt != animCallbacks.end()) aa.onComplete = cbIt->second;
nodeActiveAnims[n].push_back(std::move(aa));
@@ -1374,4 +1602,36 @@ namespace ZL {
return true;
}
std::shared_ptr<UiTextButton> UiManager::findTextButton(const std::string& name) {
for (auto& tb : textButtons) if (tb->name == name) return tb;
return nullptr;
}
bool UiManager::setTextButtonCallback(const std::string& name, std::function<void(const std::string&)> cb) {
auto tb = findTextButton(name);
if (!tb) {
std::cerr << "UiManager: setTextButtonCallback failed, textButton not found: " << name << std::endl;
return false;
}
tb->onClick = std::move(cb);
return true;
}
bool UiManager::setTextButtonPressCallback(const std::string& name, std::function<void(const std::string&)> cb) {
auto tb = findTextButton(name);
if (!tb) {
std::cerr << "UiManager: setTextButtonPressCallback failed, textButton not found: " << name << std::endl;
return false;
}
tb->onPress = std::move(cb);
return true;
}
bool UiManager::setTextButtonText(const std::string& name, const std::string& newText) {
auto tb = findTextButton(name);
if (!tb) return false;
tb->text = newText;
return true;
}
} // namespace ZL