Files
Tower-Defense/src/render/gui/TowerGui.cpp

351 lines
10 KiB
C++

/*
* TowerGui.cpp
*
* Created on: 5 nov. 2020
* Author: simon
*/
#include "render/gui/TowerGui.h"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_opengl3.h"
#include "imgui/imgui_impl_sdl.h"
#include <SDL2/SDL.h>
#include <thread>
#include "game/client/Client.h"
#include "game/server/Server.h"
#include "misc/Time.h"
#include "imgui/imgui_filebrowser.h"
#include "render/Renderer.h"
#include "network/Network.h"
#include <iostream>
#include <cmath>
namespace TowerGui {
static SDL_Window* window;
static SDL_GLContext gl_context;
static std::unique_ptr<td::client::Client> client;
static std::thread* serverThread;
static td::render::Renderer* renderer;
bool serverShouldStop = false;
void init(SDL_Window* sdl_window, SDL_GLContext sdlContext, td::render::Renderer* render) {
window = sdl_window;
gl_context = sdlContext;
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui::StyleColorsDark();
ImGui_ImplSDL2_InitForOpenGL(sdl_window, gl_context);
ImGui_ImplOpenGL3_Init();
ImFontConfig c;
c.SizePixels = 25;
ImGui::GetIO().Fonts->AddFontDefault(&c);
renderer = render;
client = std::make_unique<td::client::Client>(render);
}
void beginFrame() {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
}
void endFrame() {
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
void renderFPSCounter() {
ImGui::Begin("FPS Counter");
ImGui::Text("FPS : %i", (int)ImGui::GetIO().Framerate);
static bool vsync = true;
if (ImGui::Checkbox("V-Sync", &vsync)) {
SDL_GL_SetSwapInterval(vsync);
}
static bool isometric = true;
if (ImGui::Checkbox("Vue Isometrique ?", &isometric)) {
renderer->setIsometricView(isometric);
}
ImGui::End();
}
bool startServer(int port, const std::string& worldFilePath) {
if (worldFilePath.empty())
return false;
std::shared_ptr<td::server::Server> server = std::make_shared<td::server::Server>(worldFilePath);
if (!server->start(port)) {
return false;
}
serverThread = new std::thread([server]() {
while (!serverShouldStop) {
static std::uint64_t lastTime = td::utils::getTime();
std::uint64_t time = td::utils::getTime();
std::uint64_t delta = time - lastTime;
if (delta >= SERVER_TICK) {
server->tick(delta);
lastTime = td::utils::getTime();
std::uint64_t sleepTime = SERVER_TICK - (delta - SERVER_TICK);
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
}
}
server->stop();
});
return true;
}
void renderMainMenu() {
ImGui::Begin("Main Menu");
if (ImGui::Button("Rejoindre une partie##join")) {
ImGui::OpenPopup("Rejoindre une partie##join_popup");
}
if (ImGui::Button("Créer une partie")) {
ImGui::OpenPopup("Créer une partie##create_popup");
}
if (ImGui::Button("Options")) {
}
static bool triedToConnect = false;
if (ImGui::BeginPopup("Rejoindre une partie##join_popup")) {
static char buffer[512] = "localhost";
static int port = 25565;
ImGui::InputText("Server Adress", buffer, sizeof(buffer));
ImGui::InputInt("Port", &port, -1);
if (ImGui::Button("Rejoindre")) {
client->connect(td::network::Dns::Resolve(buffer), port);
triedToConnect = true;
}
if (triedToConnect) {
ImGui::Text("Impossible de se connecter");
}
ImGui::EndPopup();
} else {
triedToConnect = false;
}
static bool triedToCreate = false;
if (ImGui::BeginPopup("Créer une partie##create_popup")) {
static imgui_addons::ImGuiFileBrowser file_dialog;
static int port = 25565;
static std::string worldFilePath;
ImGui::InputInt("Server Port", &port, -1);
ImGui::Text("%s", std::string("Fichier de monde sélectionné : " + (worldFilePath.empty() ? std::string("Aucun") : worldFilePath)).c_str());
ImGui::SameLine();
if (ImGui::Button("Ouvrir un fichier")) {
ImGui::OpenPopup("WorldFileDialog");
}
if (file_dialog.showFileDialog("WorldFileDialog", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(600, 300), ".tdmap")) {
worldFilePath = file_dialog.selected_path;
}
if (ImGui::Button("Créer")) {
if (!startServer(port, worldFilePath)) {
triedToCreate = true;
} else {
client->connect(td::network::Dns::Resolve("localhost"), port);
}
}
if (triedToCreate)
ImGui::Text("Failed to launch server");
ImGui::EndPopup();
} else {
triedToCreate = false;
}
ImGui::End();
}
ImVec4 getImGuiTeamColor(td::game::TeamColor color) {
switch (color) {
case td::game::TeamColor::None:
break;
case td::game::TeamColor::Red:
return ImVec4(1, 0, 0, 1);
case td::game::TeamColor::Blue:
return ImVec4(0, 0, 1, 1);
}
return ImVec4(1, 1, 1, 1);
}
void showPlayers() {
if (ImGui::TreeNode(std::string("Players (" + std::to_string(client->getGame().getPlayers().size()) + ")##player_list").c_str())) {
for (auto pair : client->getGame().getPlayers()) {
const td::game::Player& player = pair.second;
ImGui::PushStyleColor(ImGuiCol_Text, getImGuiTeamColor(player.getTeamColor()));
ImGui::Text("%s", player.getName().c_str());
ImGui::PopStyleColor();
}
ImGui::TreePop();
}
}
void showTeamSelection() {
if (client->getGame().getPlayer() == nullptr)
return;
td::game::TeamColor playerTeam = client->getGame().getPlayer()->getTeamColor();
if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Red ? "Leave" : "Join") + std::string(" Red Team")).c_str())) {
if (playerTeam == td::game::TeamColor::Red)
client->selectTeam(td::game::TeamColor::None);
else
client->selectTeam(td::game::TeamColor::Red);
}
ImGui::SameLine();
if (ImGui::Button(std::string((playerTeam == td::game::TeamColor::Blue ? "Leave" : "Join") + std::string(" Blue Team")).c_str())) {
if (playerTeam == td::game::TeamColor::Blue)
client->selectTeam(td::game::TeamColor::None);
else
client->selectTeam(td::game::TeamColor::Blue);
}
}
void showLobbyProgress() {
const int timePassed = LOBBY_WAITING_TIME - client->getGame().getLobbyTime();
const float progress = (float)timePassed / (float)(LOBBY_WAITING_TIME);
if (progress > 0 && progress < 1) {
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f), std::string(std::to_string(client->getGame().getLobbyTime() / 1000) + "s").c_str());
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::Text("Time Remaining");
} else {
ImGui::Text("Waiting for players ...\n");
}
}
void showTPS() {
ImGui::Text("Server TPS : %.1f", client->getConnexion().getServerTPS());
ImGui::Text("Server Ping : %i", client->getConnexion().getServerPing());
}
void showStats() {
ImGui::Text("Gold : %i", client->getGame().getPlayer()->getGold());
}
void capValues(int* values, int& value) {
value = std::max(0, value);
value = std::min(12, value);
int total = 0;
for (int j = 0; j < 16; j++) {
total += values[j];
}
if (total == 13)
value--;
}
void renderSummonMenu() {
static bool menu_open = true;
if (menu_open) {
ImGui::Begin("Summon", &menu_open);
static int width = 100;
static int values[16]{ 0 };
ImTextureID my_tex_id = ImGui::GetIO().Fonts->TexID;
for (int i = 0; i < 8; i++) {
ImGui::SameLine();
ImGui::PushID(i);
ImGui::Image(my_tex_id, ImVec2(100, 100));
ImGui::PopID();
}
ImGui::Separator();
ImGui::PushItemWidth(width);
for (int i = 0; i < 8; i++) {
ImGui::SameLine();
ImGui::PushID(i);
if (ImGui::InputInt("", values + i, 1, 10)) {
capValues(values, values[i]);
}
ImGui::PopID();
}
ImGui::PopItemWidth();
ImGui::Separator();
for (int i = 0; i < 8; i++) {
ImGui::SameLine();
ImGui::PushID(i);
ImGui::Image(my_tex_id, ImVec2(100, 100));
ImGui::PopID();
}
ImGui::Separator();
ImGui::PushItemWidth(width);
for (int i = 8; i < 16; i++) {
ImGui::SameLine();
ImGui::PushID(i);
if (ImGui::InputInt("", values + i, 1, 10)) {
capValues(values, values[i]);
}
ImGui::PopID();
}
ImGui::PopItemWidth();
if (ImGui::Button("Send")) {
std::cout << "Sending Troops ...\n";
}
ImGui::End();
}
}
void renderGame() {
if (client->getGame().getGameState() == td::game::GameState::Lobby) {
ImGui::Begin("Lobby");
showTPS();
showPlayers();
showLobbyProgress();
showTeamSelection();
ImGui::End();
}
if (client->getGame().getGameState() == td::game::GameState::Game) {
ImGui::Begin("Game");
showTPS();
showStats();
showPlayers();
renderSummonMenu();
ImGui::End();
}
}
void tick() {
static std::uint64_t lastTime = td::utils::getTime();
std::uint64_t time = td::utils::getTime();
std::uint64_t delta = time - lastTime;
client->tick(delta);
lastTime = td::utils::getTime();
}
void render() {
tick();
beginFrame();
client->render();
if (client->isConnected())
renderGame();
else
renderMainMenu();
static bool demo_open = false;
if (demo_open)
ImGui::ShowDemoWindow(&demo_open);
renderFPSCounter();
endFrame();
}
void destroy() {
client->closeConnection();
client.reset();
serverShouldStop = true;
if (serverThread != nullptr) {
serverThread->join();
delete serverThread;
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
}
}