Working on list of players
This commit is contained in:
1 parent
a8ded217df
commit
785b96ce82
10 files changed
+544
-13
No files matched your search
+262
-2
@@ -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
|
||||
Reference in new issue
Block a user