Updated UI
This commit is contained in:
parent
46d7a2a25d
commit
1265d87bc5
@ -63,6 +63,10 @@ add_executable(space-game001
|
|||||||
../src/network/WebSocketClientEmscripten.cpp
|
../src/network/WebSocketClientEmscripten.cpp
|
||||||
../src/render/TextRenderer.h
|
../src/render/TextRenderer.h
|
||||||
../src/render/TextRenderer.cpp
|
../src/render/TextRenderer.cpp
|
||||||
|
../src/MenuManager.h
|
||||||
|
../src/MenuManager.cpp
|
||||||
|
../src/Space.h
|
||||||
|
../src/Space.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Установка проекта по умолчанию для Visual Studio
|
# Установка проекта по умолчанию для Visual Studio
|
||||||
@ -84,7 +88,7 @@ target_compile_definitions(space-game001 PRIVATE
|
|||||||
WIN32_LEAN_AND_MEAN
|
WIN32_LEAN_AND_MEAN
|
||||||
PNG_ENABLED
|
PNG_ENABLED
|
||||||
SDL_MAIN_HANDLED
|
SDL_MAIN_HANDLED
|
||||||
NETWORK
|
#NETWORK
|
||||||
# SIMPLIFIED
|
# SIMPLIFIED
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
297
src/Game.cpp
297
src/Game.cpp
@ -34,7 +34,9 @@ namespace ZL
|
|||||||
const char* CONST_ZIP_FILE = "";
|
const char* CONST_ZIP_FILE = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool g_exitBgAnimating = false;
|
bool g_exitBgAnimating = false;
|
||||||
|
|
||||||
|
bool firePressed = false;
|
||||||
|
|
||||||
float x = 0;
|
float x = 0;
|
||||||
|
|
||||||
@ -246,6 +248,7 @@ namespace ZL
|
|||||||
, newTickCount(0)
|
, newTickCount(0)
|
||||||
, lastTickCount(0)
|
, lastTickCount(0)
|
||||||
, planetObject(renderer, taskManager, mainThreadHandler)
|
, planetObject(renderer, taskManager, mainThreadHandler)
|
||||||
|
, menuManager(renderer)
|
||||||
{
|
{
|
||||||
projectiles.reserve(maxProjectiles);
|
projectiles.reserve(maxProjectiles);
|
||||||
for (int i = 0; i < maxProjectiles; ++i) {
|
for (int i = 0; i < maxProjectiles; ++i) {
|
||||||
@ -307,156 +310,29 @@ namespace ZL
|
|||||||
explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||||
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||||
|
|
||||||
uiManager.loadFromFile("resources/config/main_menu.json", renderer, CONST_ZIP_FILE);
|
menuManager.onRestartPressed = [this]() {
|
||||||
std::function<void()> loadGameplayUI;
|
this->shipAlive = true;
|
||||||
loadGameplayUI = [this]() {
|
this->gameOver = false;
|
||||||
uiManager.loadFromFile("resources/config/ui.json", renderer, CONST_ZIP_FILE);
|
this->showExplosion = false;
|
||||||
|
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||||
|
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
||||||
|
Environment::shipState.velocity = 0.0f;
|
||||||
|
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
||||||
|
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
||||||
|
Environment::zoom = DEFAULT_ZOOM;
|
||||||
|
Environment::tapDownHold = false;
|
||||||
|
|
||||||
auto velocityTv = uiManager.findTextView("velocityText");
|
std::cerr << "Game restarted\n";
|
||||||
if (velocityTv) {
|
|
||||||
velocityTv->rect.x = 10.0f;
|
|
||||||
velocityTv->rect.y = static_cast<float>(Environment::height) - velocityTv->rect.h - 10.0f;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Failed to find velocityText in UI" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
uiManager.startAnimationOnNode("backgroundNode", "bgScroll");
|
|
||||||
static bool isExitButtonAnimating = false;
|
|
||||||
uiManager.setAnimationCallback("settingsButton", "buttonsExit", [this]() {
|
|
||||||
std::cerr << "Settings button animation finished -> переход в настройки" << std::endl;
|
|
||||||
if (uiManager.pushMenuFromFile("resources/config/settings.json", this->renderer, CONST_ZIP_FILE)) {
|
|
||||||
uiManager.setButtonCallback("Opt1", [this](const std::string& n) {
|
|
||||||
std::cerr << "Opt1 pressed: " << n << std::endl;
|
|
||||||
});
|
|
||||||
uiManager.setButtonCallback("Opt2", [this](const std::string& n) {
|
|
||||||
std::cerr << "Opt2 pressed: " << n << std::endl;
|
|
||||||
});
|
|
||||||
uiManager.setButtonCallback("backButton", [this](const std::string& n) {
|
|
||||||
uiManager.stopAllAnimations();
|
|
||||||
uiManager.popMenu();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Failed to open settings menu after animations" << std::endl;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setAnimationCallback("exitButton", "bgScroll", []() {
|
|
||||||
std::cerr << "Exit button bgScroll animation finished" << std::endl;
|
|
||||||
g_exitBgAnimating = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
|
|
||||||
std::cerr << "Play button pressed: " << name << std::endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("settingsButton", [this](const std::string& name) {
|
|
||||||
std::cerr << "Settings button pressed: " << name << std::endl;
|
|
||||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
|
||||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
|
||||||
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("exitButton", [this](const std::string& name) {
|
|
||||||
std::cerr << "Exit button pressed: " << name << std::endl;
|
|
||||||
|
|
||||||
if (!g_exitBgAnimating) {
|
|
||||||
std::cerr << "start repeat anim bgScroll on exitButton" << std::endl;
|
|
||||||
g_exitBgAnimating = true;
|
|
||||||
uiManager.startAnimationOnNode("exitButton", "bgScroll");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "stop repeat anim bgScroll on exitButton" << std::endl;
|
|
||||||
g_exitBgAnimating = false;
|
|
||||||
uiManager.stopAnimationOnNode("exitButton", "bgScroll");
|
|
||||||
|
|
||||||
auto exitButton = uiManager.findButton("exitButton");
|
|
||||||
if (exitButton) {
|
|
||||||
exitButton->animOffsetX = 0.0f;
|
|
||||||
exitButton->animOffsetY = 0.0f;
|
|
||||||
exitButton->animScaleX = 1.0f;
|
|
||||||
exitButton->animScaleY = 1.0f;
|
|
||||||
exitButton->buildMesh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("shootButton", [this](const std::string& name) {
|
|
||||||
firePressed = true;
|
|
||||||
});
|
|
||||||
uiManager.setButtonCallback("shootButton2", [this](const std::string& name) {
|
|
||||||
firePressed = true;
|
|
||||||
});
|
|
||||||
uiManager.setSliderCallback("velocitySlider", [this](const std::string& name, float value) {
|
|
||||||
int newVel = roundf(value * 10);
|
|
||||||
if (newVel > 2)
|
|
||||||
{
|
|
||||||
newVel = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newVel != Environment::shipState.selectedVelocity) {
|
|
||||||
newShipVelocity = newVel;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uiManager.setButtonCallback("singleButton", [loadGameplayUI](const std::string& name) {
|
menuManager.onVelocityChanged = [this](float newVelocity) {
|
||||||
std::cerr << "Single button pressed: " << name << " -> load gameplay UI\n";
|
newShipVelocity = newVelocity;
|
||||||
loadGameplayUI();
|
//Environment::shipState.velocity = newVelocity;
|
||||||
});
|
//std::cerr << "Ship velocity changed: " << newVelocity << "\n";
|
||||||
/*uiManager.setButtonCallback("multiplayerButton", [loadGameplayUI](const std::string& name) {
|
};
|
||||||
std::cerr << "Multiplayer button pressed: " << name << " -> load gameplay UI\n";
|
menuManager.setupMenu();
|
||||||
loadGameplayUI();
|
|
||||||
});*/
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("multiplayerButton", [this](const std::string& name) {
|
|
||||||
std::cerr << "Multiplayer button pressed → opening multiplayer menu\n";
|
|
||||||
|
|
||||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
|
||||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
|
||||||
uiManager.startAnimationOnNode("multiplayerButton", "buttonsExit");
|
|
||||||
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
|
||||||
|
|
||||||
if (uiManager.pushMenuFromFile("resources/config/multiplayer_menu.json", this->renderer, CONST_ZIP_FILE)) {
|
|
||||||
|
|
||||||
// Callback для кнопки подключения
|
|
||||||
uiManager.setButtonCallback("connectButton", [this](const std::string& buttonName) {
|
|
||||||
std::string serverAddress = uiManager.getTextFieldValue("serverInputField");
|
|
||||||
|
|
||||||
if (serverAddress.empty()) {
|
|
||||||
uiManager.setText("statusText", "Please enter server address");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uiManager.setText("statusText", "Connecting to " + serverAddress + "...");
|
|
||||||
std::cerr << "Connecting to server: " << serverAddress << std::endl;
|
|
||||||
|
|
||||||
// Здесь добавить вашу логику подключения к серверу
|
|
||||||
// connectToServer(serverAddress);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Callback для кнопки назад
|
|
||||||
uiManager.setButtonCallback("backButton", [this](const std::string& buttonName) {
|
|
||||||
uiManager.popMenu();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Callback для отслеживания ввода текста
|
|
||||||
uiManager.setTextFieldCallback("serverInputField",
|
|
||||||
[this](const std::string& fieldName, const std::string& newText) {
|
|
||||||
std::cout << "Server input field changed to: " << newText << std::endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
std::cerr << "Multiplayer menu loaded successfully\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Failed to load multiplayer menu\n";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
uiManager.setButtonCallback("exitButton", [](const std::string& name) {
|
|
||||||
std::cerr << "Exit from main menu pressed: " << name << " -> exiting\n";
|
|
||||||
Environment::exitGameLoop = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
cubemapTexture = std::make_shared<Texture>(
|
cubemapTexture = std::make_shared<Texture>(
|
||||||
std::array<TextureDataStruct, 6>{
|
std::array<TextureDataStruct, 6>{
|
||||||
@ -756,7 +632,7 @@ namespace ZL
|
|||||||
renderer.DisableVertexAttribArray(vPositionName);
|
renderer.DisableVertexAttribArray(vPositionName);
|
||||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
uiManager.draw(renderer);
|
menuManager.uiManager.draw(renderer);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
renderer.shaderManager.PopShader();
|
renderer.shaderManager.PopShader();
|
||||||
CheckGlError();
|
CheckGlError();
|
||||||
@ -1445,41 +1321,7 @@ namespace ZL
|
|||||||
|
|
||||||
std::cerr << "GAME OVER: collision with planet (moved back and exploded)\n";
|
std::cerr << "GAME OVER: collision with planet (moved back and exploded)\n";
|
||||||
|
|
||||||
if (!uiGameOverShown) {
|
menuManager.showGameOver();
|
||||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json", this->renderer, CONST_ZIP_FILE)) {
|
|
||||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
|
||||||
|
|
||||||
std::string respawnMsg = "RESPAWN:" + std::to_string(networkClient->GetClientId());
|
|
||||||
networkClient->Send(respawnMsg);
|
|
||||||
|
|
||||||
this->shipAlive = true;
|
|
||||||
this->gameOver = false;
|
|
||||||
this->uiGameOverShown = false;
|
|
||||||
this->showExplosion = false;
|
|
||||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
|
||||||
this->deadRemotePlayers.clear();
|
|
||||||
|
|
||||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
|
||||||
Environment::shipState.velocity = 0.0f;
|
|
||||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
|
||||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
|
||||||
Environment::zoom = DEFAULT_ZOOM;
|
|
||||||
Environment::tapDownHold = false;
|
|
||||||
|
|
||||||
uiManager.popMenu();
|
|
||||||
std::cerr << "Game restarted\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
|
||||||
Environment::exitGameLoop = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
uiGameOverShown = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Failed to load game_over.json\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bool stoneCollided = false;
|
bool stoneCollided = false;
|
||||||
@ -1554,34 +1396,7 @@ namespace ZL
|
|||||||
planetObject.planetStones.statuses[collidedTriIdx] = ChunkStatus::Empty;
|
planetObject.planetStones.statuses[collidedTriIdx] = ChunkStatus::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uiGameOverShown) {
|
menuManager.showGameOver();
|
||||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json", this->renderer, CONST_ZIP_FILE)) {
|
|
||||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
|
||||||
this->shipAlive = true;
|
|
||||||
this->gameOver = false;
|
|
||||||
this->uiGameOverShown = false;
|
|
||||||
this->showExplosion = false;
|
|
||||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
|
||||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
|
||||||
Environment::shipState.velocity = 0.0f;
|
|
||||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
|
||||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
|
||||||
Environment::zoom = DEFAULT_ZOOM;
|
|
||||||
Environment::tapDownHold = false;
|
|
||||||
uiManager.popMenu();
|
|
||||||
std::cerr << "Game restarted\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
|
||||||
Environment::exitGameLoop = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
uiGameOverShown = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Failed to load game_over.json\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1643,14 +1458,14 @@ namespace ZL
|
|||||||
|
|
||||||
// update velocity text
|
// update velocity text
|
||||||
if (shipAlive && !gameOver) {
|
if (shipAlive && !gameOver) {
|
||||||
auto velocityTv = uiManager.findTextView("velocityText");
|
auto velocityTv = menuManager.uiManager.findTextView("velocityText");
|
||||||
if (velocityTv) {
|
if (velocityTv) {
|
||||||
std::string velocityStr = "Velocity: " + std::to_string(static_cast<int>(Environment::shipState.velocity));
|
std::string velocityStr = "Velocity: " + std::to_string(static_cast<int>(Environment::shipState.velocity));
|
||||||
uiManager.setText("velocityText", velocityStr);
|
menuManager.uiManager.setText("velocityText", velocityStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uiManager.update(static_cast<float>(delta));
|
menuManager.uiManager.update(static_cast<float>(delta));
|
||||||
lastTickCount = newTickCount;
|
lastTickCount = newTickCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1763,14 +1578,14 @@ namespace ZL
|
|||||||
// Обработка ввода текста
|
// Обработка ввода текста
|
||||||
if (event.type == SDL_KEYDOWN) {
|
if (event.type == SDL_KEYDOWN) {
|
||||||
if (event.key.keysym.sym == SDLK_BACKSPACE) {
|
if (event.key.keysym.sym == SDLK_BACKSPACE) {
|
||||||
uiManager.onKeyBackspace();
|
menuManager.uiManager.onKeyBackspace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == SDL_TEXTINPUT) {
|
if (event.type == SDL_TEXTINPUT) {
|
||||||
// Пропускаем ctrl+c и другие команды
|
// Пропускаем ctrl+c и другие команды
|
||||||
if ((event.text.text[0] & 0x80) == 0) { // ASCII символы
|
if ((event.text.text[0] & 0x80) == 0) { // ASCII символы
|
||||||
uiManager.onKeyPress((unsigned char)event.text.text[0]);
|
menuManager.uiManager.onKeyPress((unsigned char)event.text.text[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1903,41 +1718,7 @@ namespace ZL
|
|||||||
shipAlive = false;
|
shipAlive = false;
|
||||||
gameOver = true;
|
gameOver = true;
|
||||||
Environment::shipState.velocity = 0.0f;
|
Environment::shipState.velocity = 0.0f;
|
||||||
|
menuManager.showGameOver();
|
||||||
if (!uiGameOverShown) {
|
|
||||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json",
|
|
||||||
this->renderer, CONST_ZIP_FILE)) {
|
|
||||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
|
||||||
std::cout << "Client: Restart button clicked, sending RESPAWN" << std::endl;
|
|
||||||
|
|
||||||
std::string respawnMsg = "RESPAWN:" + std::to_string(networkClient->GetClientId());
|
|
||||||
networkClient->Send(respawnMsg);
|
|
||||||
|
|
||||||
this->shipAlive = true;
|
|
||||||
this->gameOver = false;
|
|
||||||
this->uiGameOverShown = false;
|
|
||||||
this->showExplosion = false;
|
|
||||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
|
||||||
this->deadRemotePlayers.clear();
|
|
||||||
|
|
||||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
|
||||||
Environment::shipState.velocity = 0.0f;
|
|
||||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
|
||||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
|
||||||
Environment::zoom = DEFAULT_ZOOM;
|
|
||||||
Environment::tapDownHold = false;
|
|
||||||
|
|
||||||
uiManager.popMenu();
|
|
||||||
std::cerr << "Game restarted\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
|
||||||
Environment::exitGameLoop = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
uiGameOverShown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
deadRemotePlayers.insert(d.targetId);
|
deadRemotePlayers.insert(d.targetId);
|
||||||
@ -1998,22 +1779,22 @@ namespace ZL
|
|||||||
int uiX = mx;
|
int uiX = mx;
|
||||||
int uiY = Environment::height - my;
|
int uiY = Environment::height - my;
|
||||||
|
|
||||||
uiManager.onMouseDown(uiX, uiY);
|
menuManager.uiManager.onMouseDown(uiX, uiY);
|
||||||
|
|
||||||
bool uiHandled = false;
|
bool uiHandled = false;
|
||||||
|
|
||||||
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
for (const auto& button : menuManager.uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
||||||
(void)button;
|
(void)button;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pressedSlider = [&]() -> std::shared_ptr<UiSlider> {
|
auto pressedSlider = [&]() -> std::shared_ptr<UiSlider> {
|
||||||
for (const auto& slider : uiManager.findSlider("") ? std::vector<std::shared_ptr<UiSlider>>{} : std::vector<std::shared_ptr<UiSlider>>{}) {
|
for (const auto& slider : menuManager.uiManager.findSlider("") ? std::vector<std::shared_ptr<UiSlider>>{} : std::vector<std::shared_ptr<UiSlider>>{}) {
|
||||||
(void)slider;
|
(void)slider;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (!uiManager.isUiInteraction()) {
|
if (!menuManager.uiManager.isUiInteraction()) {
|
||||||
Environment::tapDownHold = true;
|
Environment::tapDownHold = true;
|
||||||
|
|
||||||
Environment::tapDownStartPos(0) = mx;
|
Environment::tapDownStartPos(0) = mx;
|
||||||
@ -2029,9 +1810,9 @@ namespace ZL
|
|||||||
int uiX = mx;
|
int uiX = mx;
|
||||||
int uiY = Environment::height - my;
|
int uiY = Environment::height - my;
|
||||||
|
|
||||||
uiManager.onMouseUp(uiX, uiY);
|
menuManager.uiManager.onMouseUp(uiX, uiY);
|
||||||
|
|
||||||
if (!uiManager.isUiInteraction()) {
|
if (!menuManager.uiManager.isUiInteraction()) {
|
||||||
Environment::tapDownHold = false;
|
Environment::tapDownHold = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2041,9 +1822,9 @@ namespace ZL
|
|||||||
int uiX = mx;
|
int uiX = mx;
|
||||||
int uiY = Environment::height - my;
|
int uiY = Environment::height - my;
|
||||||
|
|
||||||
uiManager.onMouseMove(uiX, uiY);
|
menuManager.uiManager.onMouseMove(uiX, uiY);
|
||||||
|
|
||||||
if (Environment::tapDownHold && !uiManager.isUiInteraction()) {
|
if (Environment::tapDownHold && !menuManager.uiManager.isUiInteraction()) {
|
||||||
Environment::tapDownCurrentPos(0) = mx;
|
Environment::tapDownCurrentPos(0) = mx;
|
||||||
Environment::tapDownCurrentPos(1) = my;
|
Environment::tapDownCurrentPos(1) = my;
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/Game.h
19
src/Game.h
@ -14,19 +14,13 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <render/TextRenderer.h>
|
#include <render/TextRenderer.h>
|
||||||
|
#include "MenuManager.h"
|
||||||
|
#include "Space.h"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
|
|
||||||
struct BoxCoords
|
|
||||||
{
|
|
||||||
Vector3f pos;
|
|
||||||
Matrix3f m;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
@ -43,6 +37,8 @@ namespace ZL {
|
|||||||
MainThreadHandler mainThreadHandler;
|
MainThreadHandler mainThreadHandler;
|
||||||
|
|
||||||
std::unique_ptr<INetworkClient> networkClient;
|
std::unique_ptr<INetworkClient> networkClient;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t getSyncTimeMs();
|
int64_t getSyncTimeMs();
|
||||||
void processTickCount();
|
void processTickCount();
|
||||||
@ -100,7 +96,8 @@ namespace ZL {
|
|||||||
SparkEmitter projectileEmitter;
|
SparkEmitter projectileEmitter;
|
||||||
SparkEmitter explosionEmitter;
|
SparkEmitter explosionEmitter;
|
||||||
PlanetObject planetObject;
|
PlanetObject planetObject;
|
||||||
UiManager uiManager;
|
|
||||||
|
MenuManager menuManager;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Projectile>> projectiles;
|
std::vector<std::unique_ptr<Projectile>> projectiles;
|
||||||
std::shared_ptr<Texture> projectileTexture;
|
std::shared_ptr<Texture> projectileTexture;
|
||||||
@ -115,12 +112,10 @@ namespace ZL {
|
|||||||
std::vector<bool> boxAlive;
|
std::vector<bool> boxAlive;
|
||||||
float shipCollisionRadius = 15.0f;
|
float shipCollisionRadius = 15.0f;
|
||||||
float boxCollisionRadius = 2.0f;
|
float boxCollisionRadius = 2.0f;
|
||||||
bool uiGameOverShown = false;
|
//bool uiGameOverShown = false;
|
||||||
bool showExplosion = false;
|
bool showExplosion = false;
|
||||||
uint64_t lastExplosionTime = 0;
|
uint64_t lastExplosionTime = 0;
|
||||||
const uint64_t explosionDurationMs = 500;
|
const uint64_t explosionDurationMs = 500;
|
||||||
bool firePressed = false;
|
|
||||||
|
|
||||||
|
|
||||||
bool serverBoxesApplied = false;
|
bool serverBoxesApplied = false;
|
||||||
|
|
||||||
|
|||||||
196
src/MenuManager.cpp
Normal file
196
src/MenuManager.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#include "MenuManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZL {
|
||||||
|
|
||||||
|
MenuManager::MenuManager(Renderer& iRenderer) :
|
||||||
|
renderer(iRenderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::setupMenu()
|
||||||
|
{
|
||||||
|
|
||||||
|
uiManager.loadFromFile("resources/config/main_menu.json", renderer, CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
uiSavedRoot = loadUiFromFile("resources/config/ui.json", renderer, CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
settingsSavedRoot = loadUiFromFile("resources/config/settings.json", renderer, CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
multiplayerSavedRoot = loadUiFromFile("resources/config/multiplayer_menu.json", renderer, CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
gameOverSavedRoot = loadUiFromFile("resources/config/game_over.json", renderer, CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
std::function<void()> loadGameplayUI;
|
||||||
|
loadGameplayUI = [this]() {
|
||||||
|
uiManager.replaceRoot(uiSavedRoot);
|
||||||
|
|
||||||
|
auto velocityTv = uiManager.findTextView("velocityText");
|
||||||
|
if (velocityTv) {
|
||||||
|
velocityTv->rect.x = 10.0f;
|
||||||
|
velocityTv->rect.y = static_cast<float>(Environment::height) - velocityTv->rect.h - 10.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Failed to find velocityText in UI" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiManager.startAnimationOnNode("backgroundNode", "bgScroll");
|
||||||
|
static bool isExitButtonAnimating = false;
|
||||||
|
uiManager.setAnimationCallback("settingsButton", "buttonsExit", [this]() {
|
||||||
|
std::cerr << "Settings button animation finished -> переход в настройки" << std::endl;
|
||||||
|
if (uiManager.pushMenuFromSavedRoot(settingsSavedRoot)) {
|
||||||
|
uiManager.setButtonCallback("Opt1", [this](const std::string& n) {
|
||||||
|
std::cerr << "Opt1 pressed: " << n << std::endl;
|
||||||
|
});
|
||||||
|
uiManager.setButtonCallback("Opt2", [this](const std::string& n) {
|
||||||
|
std::cerr << "Opt2 pressed: " << n << std::endl;
|
||||||
|
});
|
||||||
|
uiManager.setButtonCallback("backButton", [this](const std::string& n) {
|
||||||
|
uiManager.stopAllAnimations();
|
||||||
|
uiManager.popMenu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Failed to open settings menu after animations" << std::endl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setAnimationCallback("exitButton", "bgScroll", []() {
|
||||||
|
std::cerr << "Exit button bgScroll animation finished" << std::endl;
|
||||||
|
g_exitBgAnimating = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
|
||||||
|
std::cerr << "Play button pressed: " << name << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("settingsButton", [this](const std::string& name) {
|
||||||
|
std::cerr << "Settings button pressed: " << name << std::endl;
|
||||||
|
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||||
|
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||||
|
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("exitButton", [this](const std::string& name) {
|
||||||
|
std::cerr << "Exit button pressed: " << name << std::endl;
|
||||||
|
|
||||||
|
if (!g_exitBgAnimating) {
|
||||||
|
std::cerr << "start repeat anim bgScroll on exitButton" << std::endl;
|
||||||
|
g_exitBgAnimating = true;
|
||||||
|
uiManager.startAnimationOnNode("exitButton", "bgScroll");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "stop repeat anim bgScroll on exitButton" << std::endl;
|
||||||
|
g_exitBgAnimating = false;
|
||||||
|
uiManager.stopAnimationOnNode("exitButton", "bgScroll");
|
||||||
|
|
||||||
|
auto exitButton = uiManager.findButton("exitButton");
|
||||||
|
if (exitButton) {
|
||||||
|
exitButton->animOffsetX = 0.0f;
|
||||||
|
exitButton->animOffsetY = 0.0f;
|
||||||
|
exitButton->animScaleX = 1.0f;
|
||||||
|
exitButton->animScaleY = 1.0f;
|
||||||
|
exitButton->buildMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("shootButton", [this](const std::string& name) {
|
||||||
|
firePressed = true;
|
||||||
|
});
|
||||||
|
uiManager.setButtonCallback("shootButton2", [this](const std::string& name) {
|
||||||
|
firePressed = true;
|
||||||
|
});
|
||||||
|
uiManager.setSliderCallback("velocitySlider", [this](const std::string& name, float value) {
|
||||||
|
int newVel = roundf(value * 10);
|
||||||
|
/*if (newVel > 2)
|
||||||
|
{
|
||||||
|
newVel = 2;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (newVel != Environment::shipState.selectedVelocity) {
|
||||||
|
onVelocityChanged(newVel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("singleButton", [loadGameplayUI](const std::string& name) {
|
||||||
|
std::cerr << "Single button pressed: " << name << " -> load gameplay UI\n";
|
||||||
|
loadGameplayUI();
|
||||||
|
});
|
||||||
|
/*uiManager.setButtonCallback("multiplayerButton", [loadGameplayUI](const std::string& name) {
|
||||||
|
std::cerr << "Multiplayer button pressed: " << name << " -> load gameplay UI\n";
|
||||||
|
loadGameplayUI();
|
||||||
|
});*/
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("multiplayerButton", [this](const std::string& name) {
|
||||||
|
std::cerr << "Multiplayer button pressed → opening multiplayer menu\n";
|
||||||
|
|
||||||
|
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||||
|
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||||
|
uiManager.startAnimationOnNode("multiplayerButton", "buttonsExit");
|
||||||
|
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
||||||
|
|
||||||
|
if (uiManager.pushMenuFromSavedRoot(multiplayerSavedRoot)) {
|
||||||
|
|
||||||
|
// Callback для кнопки подключения
|
||||||
|
uiManager.setButtonCallback("connectButton", [this](const std::string& buttonName) {
|
||||||
|
std::string serverAddress = uiManager.getTextFieldValue("serverInputField");
|
||||||
|
|
||||||
|
if (serverAddress.empty()) {
|
||||||
|
uiManager.setText("statusText", "Please enter server address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiManager.setText("statusText", "Connecting to " + serverAddress + "...");
|
||||||
|
std::cerr << "Connecting to server: " << serverAddress << std::endl;
|
||||||
|
|
||||||
|
// Здесь добавить вашу логику подключения к серверу
|
||||||
|
// connectToServer(serverAddress);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Callback для кнопки назад
|
||||||
|
uiManager.setButtonCallback("backButton", [this](const std::string& buttonName) {
|
||||||
|
uiManager.popMenu();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Callback для отслеживания ввода текста
|
||||||
|
uiManager.setTextFieldCallback("serverInputField",
|
||||||
|
[this](const std::string& fieldName, const std::string& newText) {
|
||||||
|
std::cout << "Server input field changed to: " << newText << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
std::cerr << "Multiplayer menu loaded successfully\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Failed to load multiplayer menu\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
uiManager.setButtonCallback("exitButton", [](const std::string& name) {
|
||||||
|
std::cerr << "Exit from main menu pressed: " << name << " -> exiting\n";
|
||||||
|
Environment::exitGameLoop = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::showGameOver()
|
||||||
|
{
|
||||||
|
if (!uiGameOverShown) {
|
||||||
|
if (uiManager.pushMenuFromSavedRoot(gameOverSavedRoot)) {
|
||||||
|
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
||||||
|
uiGameOverShown = false;
|
||||||
|
uiManager.popMenu();
|
||||||
|
onRestartPressed();
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
||||||
|
Environment::exitGameLoop = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
uiGameOverShown = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Failed to load game_over.json\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/MenuManager.h
Normal file
38
src/MenuManager.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "render/Renderer.h"
|
||||||
|
#include "Environment.h"
|
||||||
|
#include "render/TextureManager.h"
|
||||||
|
#include "UiManager.h"
|
||||||
|
|
||||||
|
namespace ZL {
|
||||||
|
|
||||||
|
extern const char* CONST_ZIP_FILE;
|
||||||
|
extern bool g_exitBgAnimating;
|
||||||
|
extern bool firePressed;
|
||||||
|
|
||||||
|
class MenuManager
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Renderer& renderer;
|
||||||
|
bool uiGameOverShown = false;
|
||||||
|
|
||||||
|
std::shared_ptr<UiNode> uiSavedRoot;
|
||||||
|
std::shared_ptr<UiNode> gameOverSavedRoot;
|
||||||
|
std::shared_ptr<UiNode> settingsSavedRoot;
|
||||||
|
std::shared_ptr<UiNode> multiplayerSavedRoot;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UiManager uiManager;
|
||||||
|
|
||||||
|
MenuManager(Renderer& iRenderer);
|
||||||
|
|
||||||
|
void setupMenu();
|
||||||
|
|
||||||
|
void showGameOver();
|
||||||
|
|
||||||
|
std::function<void()> onRestartPressed;
|
||||||
|
std::function<void(float)> onVelocityChanged;
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
0
src/Space.cpp
Normal file
0
src/Space.cpp
Normal file
152
src/Space.h
Normal file
152
src/Space.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "render/Renderer.h"
|
||||||
|
#include "Environment.h"
|
||||||
|
#include "render/TextureManager.h"
|
||||||
|
#include "SparkEmitter.h"
|
||||||
|
#include "planet/PlanetObject.h"
|
||||||
|
#include "UiManager.h"
|
||||||
|
#include "Projectile.h"
|
||||||
|
#include "utils/TaskManager.h"
|
||||||
|
#include "network/NetworkInterface.h"
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <render/TextRenderer.h>
|
||||||
|
#include "MenuManager.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace ZL {
|
||||||
|
|
||||||
|
|
||||||
|
struct BoxCoords
|
||||||
|
{
|
||||||
|
Vector3f pos;
|
||||||
|
Matrix3f m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
class Space {
|
||||||
|
public:
|
||||||
|
Space(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler);
|
||||||
|
~Space();
|
||||||
|
|
||||||
|
void setup();
|
||||||
|
void update();
|
||||||
|
void render();
|
||||||
|
|
||||||
|
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||||
|
|
||||||
|
Renderer& renderer;
|
||||||
|
TaskManager& taskManager;
|
||||||
|
MainThreadHandler& mainThreadHandler;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t getSyncTimeMs();
|
||||||
|
void processTickCount();
|
||||||
|
void drawScene();
|
||||||
|
void drawCubemap(float skyPercent);
|
||||||
|
void drawShip();
|
||||||
|
void drawBoxes();
|
||||||
|
void drawBoxesLabels();
|
||||||
|
void drawUI();
|
||||||
|
void drawRemoteShips();
|
||||||
|
void drawRemoteShipsLabels();
|
||||||
|
void fireProjectiles();
|
||||||
|
|
||||||
|
bool worldToScreen(const Vector3f& world, float& outX, float& outY, float& outDepth) const;
|
||||||
|
|
||||||
|
void handleDown(int mx, int my);
|
||||||
|
void handleUp(int mx, int my);
|
||||||
|
void handleMotion(int mx, int my);
|
||||||
|
|
||||||
|
SDL_Window* window;
|
||||||
|
SDL_GLContext glContext;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int64_t newTickCount;
|
||||||
|
int64_t lastTickCount;
|
||||||
|
|
||||||
|
std::vector<BoxCoords> boxCoordsArr;
|
||||||
|
std::vector<VertexRenderStruct> boxRenderArr;
|
||||||
|
|
||||||
|
std::vector<std::string> boxLabels;
|
||||||
|
std::unique_ptr<TextRenderer> textRenderer;
|
||||||
|
|
||||||
|
//std::unordered_map<int, ClientStateInterval> latestRemotePlayers;
|
||||||
|
std::unordered_map<int, ClientState> remotePlayerStates;
|
||||||
|
|
||||||
|
float newShipVelocity = 0;
|
||||||
|
|
||||||
|
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||||
|
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||||
|
|
||||||
|
std::shared_ptr<Texture> sparkTexture;
|
||||||
|
std::shared_ptr<Texture> spaceshipTexture;
|
||||||
|
std::shared_ptr<Texture> cubemapTexture;
|
||||||
|
VertexDataStruct spaceshipBase;
|
||||||
|
VertexRenderStruct spaceship;
|
||||||
|
|
||||||
|
|
||||||
|
VertexRenderStruct cubemap;
|
||||||
|
|
||||||
|
std::shared_ptr<Texture> boxTexture;
|
||||||
|
VertexDataStruct boxBase;
|
||||||
|
|
||||||
|
SparkEmitter sparkEmitter;
|
||||||
|
SparkEmitter projectileEmitter;
|
||||||
|
SparkEmitter explosionEmitter;
|
||||||
|
PlanetObject planetObject;
|
||||||
|
|
||||||
|
MenuManager menuManager;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Projectile>> projectiles;
|
||||||
|
std::shared_ptr<Texture> projectileTexture;
|
||||||
|
float projectileCooldownMs = 500.0f;
|
||||||
|
int64_t lastProjectileFireTime = 0;
|
||||||
|
int maxProjectiles = 32;
|
||||||
|
std::vector<Vector3f> shipLocalEmissionPoints;
|
||||||
|
|
||||||
|
|
||||||
|
bool shipAlive = true;
|
||||||
|
bool gameOver = false;
|
||||||
|
std::vector<bool> boxAlive;
|
||||||
|
float shipCollisionRadius = 15.0f;
|
||||||
|
float boxCollisionRadius = 2.0f;
|
||||||
|
//bool uiGameOverShown = false;
|
||||||
|
bool showExplosion = false;
|
||||||
|
uint64_t lastExplosionTime = 0;
|
||||||
|
const uint64_t explosionDurationMs = 500;
|
||||||
|
|
||||||
|
bool serverBoxesApplied = false;
|
||||||
|
|
||||||
|
static constexpr float MAX_DIST_SQ = 10000.f * 10000.f;
|
||||||
|
static constexpr float FADE_START = 6000.f;
|
||||||
|
static constexpr float FADE_RANGE = 4000.f;
|
||||||
|
static constexpr float BASE_SCALE = 140.f;
|
||||||
|
static constexpr float PERSPECTIVE_K = 0.05f; // Tune
|
||||||
|
static constexpr float MIN_SCALE = 0.4f;
|
||||||
|
static constexpr float MAX_SCALE = 0.8f;
|
||||||
|
static constexpr float CLOSE_DIST = 600.0f;
|
||||||
|
|
||||||
|
std::unordered_set<int> deadRemotePlayers;
|
||||||
|
|
||||||
|
// --- Target HUD (brackets + offscreen arrow) ---
|
||||||
|
int trackedTargetId = -1;
|
||||||
|
bool targetWasVisible = false;
|
||||||
|
float targetAcquireAnim = 0.0f; // 0..1 схлопывание (0 = далеко, 1 = на месте)
|
||||||
|
|
||||||
|
// временный меш для HUD (будем перезаливать VBO маленькими порциями)
|
||||||
|
VertexRenderStruct hudTempMesh;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool projectToNDC(const Vector3f& world, float& ndcX, float& ndcY, float& ndcZ, float& clipW) const;
|
||||||
|
void drawTargetHud(); // рисует рамку или стрелку
|
||||||
|
int pickTargetId() const; // выбирает цель (пока: ближайший живой удаленный игрок)
|
||||||
|
};*/
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ZL
|
||||||
@ -182,60 +182,7 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiManager::loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
std::shared_ptr<UiNode> parseNode(const json& j, Renderer& renderer, const std::string& zipFile) {
|
||||||
std::string content;
|
|
||||||
try {
|
|
||||||
if (zipFile.empty()) {
|
|
||||||
content = readTextFile(path);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto buf = readFileFromZIP(path, zipFile);
|
|
||||||
if (buf.empty()) {
|
|
||||||
std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
|
|
||||||
throw std::runtime_error("Failed to load UI file: " + path);
|
|
||||||
}
|
|
||||||
content.assign(buf.begin(), buf.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception& e) {
|
|
||||||
std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
|
|
||||||
throw std::runtime_error("Failed to load UI file: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
json j;
|
|
||||||
try {
|
|
||||||
j = json::parse(content);
|
|
||||||
}
|
|
||||||
catch (const std::exception& e) {
|
|
||||||
std::cerr << "UiManager: json parse error: " << e.what() << std::endl;
|
|
||||||
throw std::runtime_error("Failed to load UI file: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!j.contains("root") || !j["root"].is_object()) {
|
|
||||||
std::cerr << "UiManager: root node missing or invalid" << std::endl;
|
|
||||||
throw std::runtime_error("Failed to load UI file: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
root = parseNode(j["root"], renderer, zipFile);
|
|
||||||
layoutNode(root);
|
|
||||||
buttons.clear();
|
|
||||||
sliders.clear();
|
|
||||||
textViews.clear();
|
|
||||||
textFields.clear();
|
|
||||||
collectButtonsAndSliders(root);
|
|
||||||
|
|
||||||
nodeActiveAnims.clear();
|
|
||||||
|
|
||||||
for (auto& b : buttons) {
|
|
||||||
b->buildMesh();
|
|
||||||
}
|
|
||||||
for (auto& s : sliders) {
|
|
||||||
s->buildTrackMesh();
|
|
||||||
s->buildKnobMesh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<UiNode> UiManager::parseNode(const json& j, Renderer& renderer, const std::string& zipFile) {
|
|
||||||
auto node = std::make_shared<UiNode>();
|
auto node = std::make_shared<UiNode>();
|
||||||
if (j.contains("type") && j["type"].is_string()) node->type = j["type"].get<std::string>();
|
if (j.contains("type") && j["type"].is_string()) node->type = j["type"].get<std::string>();
|
||||||
if (j.contains("name") && j["name"].is_string()) node->name = j["name"].get<std::string>();
|
if (j.contains("name") && j["name"].is_string()) node->name = j["name"].get<std::string>();
|
||||||
@ -416,6 +363,76 @@ namespace ZL {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<UiNode> loadUiFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile)
|
||||||
|
{
|
||||||
|
std::shared_ptr<UiNode> root;
|
||||||
|
|
||||||
|
std::string content;
|
||||||
|
try {
|
||||||
|
if (zipFile.empty()) {
|
||||||
|
content = readTextFile(path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto buf = readFileFromZIP(path, zipFile);
|
||||||
|
if (buf.empty()) {
|
||||||
|
std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
|
||||||
|
throw std::runtime_error("Failed to load UI file: " + path);
|
||||||
|
}
|
||||||
|
content.assign(buf.begin(), buf.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
|
||||||
|
throw std::runtime_error("Failed to load UI file: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
json j;
|
||||||
|
try {
|
||||||
|
j = json::parse(content);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "UiManager: json parse error: " << e.what() << std::endl;
|
||||||
|
throw std::runtime_error("Failed to load UI file: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!j.contains("root") || !j["root"].is_object()) {
|
||||||
|
std::cerr << "UiManager: root node missing or invalid" << std::endl;
|
||||||
|
throw std::runtime_error("Failed to load UI file: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
root = parseNode(j["root"], renderer, zipFile);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiManager::replaceRoot(std::shared_ptr<UiNode> newRoot) {
|
||||||
|
root = newRoot;
|
||||||
|
layoutNode(root);
|
||||||
|
buttons.clear();
|
||||||
|
sliders.clear();
|
||||||
|
textViews.clear();
|
||||||
|
textFields.clear();
|
||||||
|
collectButtonsAndSliders(root);
|
||||||
|
|
||||||
|
nodeActiveAnims.clear();
|
||||||
|
|
||||||
|
for (auto& b : buttons) {
|
||||||
|
b->buildMesh();
|
||||||
|
}
|
||||||
|
for (auto& s : sliders) {
|
||||||
|
s->buildTrackMesh();
|
||||||
|
s->buildKnobMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiManager::loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
||||||
|
|
||||||
|
std::shared_ptr<UiNode> newRoot = loadUiFromFile(path, renderer, zipFile);
|
||||||
|
replaceRoot(newRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void UiManager::layoutNode(const std::shared_ptr<UiNode>& node) {
|
void UiManager::layoutNode(const std::shared_ptr<UiNode>& node) {
|
||||||
for (auto& child : node->children) {
|
for (auto& child : node->children) {
|
||||||
child->rect.x += node->rect.x;
|
child->rect.x += node->rect.x;
|
||||||
@ -553,7 +570,8 @@ namespace ZL {
|
|||||||
return tf->text;
|
return tf->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UiManager::pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
bool UiManager::pushMenuFromSavedRoot(std::shared_ptr<UiNode> newRoot)
|
||||||
|
{
|
||||||
MenuState prev;
|
MenuState prev;
|
||||||
prev.root = root;
|
prev.root = root;
|
||||||
prev.buttons = buttons;
|
prev.buttons = buttons;
|
||||||
@ -579,17 +597,22 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFromFile(path, renderer, zipFile);
|
replaceRoot(newRoot);
|
||||||
menuStack.push_back(std::move(prev));
|
menuStack.push_back(std::move(prev));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
catch (const std::exception& e) {
|
||||||
std::cerr << "UiManager: pushMenuFromFile failed to load " << path << " : " << e.what() << std::endl;
|
std::cerr << "UiManager: pushMenuFromFile failed to load from root : " << e.what() << std::endl;
|
||||||
animCallbacks = prev.animCallbacks;
|
animCallbacks = prev.animCallbacks;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UiManager::pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
||||||
|
auto newRoot = loadUiFromFile(path, renderer, zipFile);
|
||||||
|
return pushMenuFromSavedRoot(newRoot);
|
||||||
|
}
|
||||||
|
|
||||||
bool UiManager::popMenu() {
|
bool UiManager::popMenu() {
|
||||||
if (menuStack.empty()) {
|
if (menuStack.empty()) {
|
||||||
std::cerr << "UiManager: popMenu called but menu stack is empty" << std::endl;
|
std::cerr << "UiManager: popMenu called but menu stack is empty" << std::endl;
|
||||||
|
|||||||
@ -136,10 +136,15 @@ namespace ZL {
|
|||||||
std::map<std::string, AnimSequence> animations;
|
std::map<std::string, AnimSequence> animations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<UiNode> parseNode(const json& j, Renderer& renderer, const std::string& zipFile);
|
||||||
|
std::shared_ptr<UiNode> loadUiFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||||
|
|
||||||
|
|
||||||
class UiManager {
|
class UiManager {
|
||||||
public:
|
public:
|
||||||
UiManager() = default;
|
UiManager() = default;
|
||||||
|
|
||||||
|
void replaceRoot(std::shared_ptr<UiNode> newRoot);
|
||||||
void loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
void loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||||
|
|
||||||
void draw(Renderer& renderer);
|
void draw(Renderer& renderer);
|
||||||
@ -186,6 +191,7 @@ namespace ZL {
|
|||||||
std::string getTextFieldValue(const std::string& name);
|
std::string getTextFieldValue(const std::string& name);
|
||||||
|
|
||||||
bool pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
bool pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||||
|
bool pushMenuFromSavedRoot(std::shared_ptr<UiNode> newRoot);
|
||||||
bool popMenu();
|
bool popMenu();
|
||||||
void clearMenuStack();
|
void clearMenuStack();
|
||||||
|
|
||||||
@ -196,7 +202,6 @@ namespace ZL {
|
|||||||
bool setAnimationCallback(const std::string& nodeName, const std::string& animName, std::function<void()> cb);
|
bool setAnimationCallback(const std::string& nodeName, const std::string& animName, std::function<void()> cb);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<UiNode> parseNode(const json& j, Renderer& renderer, const std::string& zipFile);
|
|
||||||
void layoutNode(const std::shared_ptr<UiNode>& node);
|
void layoutNode(const std::shared_ptr<UiNode>& node);
|
||||||
void collectButtonsAndSliders(const std::shared_ptr<UiNode>& node);
|
void collectButtonsAndSliders(const std::shared_ptr<UiNode>& node);
|
||||||
|
|
||||||
|
|||||||
@ -239,7 +239,7 @@ namespace ZL {
|
|||||||
for (size_t bi = 0; bi < serverBoxes.size(); ++bi) {
|
for (size_t bi = 0; bi < serverBoxes.size(); ++bi) {
|
||||||
if (serverBoxes[bi].destroyed) continue;
|
if (serverBoxes[bi].destroyed) continue;
|
||||||
|
|
||||||
Eigen::Vector3f boxWorld = serverBoxes[bi].position + Eigen::Vector3f(0.0f, 6.0f, 45000.0f);
|
Eigen::Vector3f boxWorld = serverBoxes[bi].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
|
||||||
|
|
||||||
for (size_t pi = 0; pi < projectiles.size(); ++pi) {
|
for (size_t pi = 0; pi < projectiles.size(); ++pi) {
|
||||||
const auto& pr = projectiles[pi];
|
const auto& pr = projectiles[pi];
|
||||||
@ -387,8 +387,8 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Eigen::Vector3f> localOffsets = {
|
const std::vector<Eigen::Vector3f> localOffsets = {
|
||||||
Eigen::Vector3f(-1.5f, 0.9f, 5.0f),
|
Eigen::Vector3f(-1.5f, 0.9f - 6.f, 5.0f),
|
||||||
Eigen::Vector3f(1.5f, 0.9f, 5.0f)
|
Eigen::Vector3f(1.5f, 0.9f - 6.f, 5.0f)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user