Files
Tower-Defense/src/render/WorldRenderer.cpp

244 lines
6.8 KiB
C++

#include "render/WorldRenderer.h"
#include "render/loader/WorldLoader.h"
#include "render/Renderer.h"
#include "render/gui/imgui/imgui.h"
#include "gui/imgui/imgui_internal.h"
#include "window/Display.h"
#include "game/client/ClientGame.h"
#include "game/client/Client.h"
#include "misc/Format.h"
namespace td {
namespace render {
ImVec4 WorldRenderer::GetImGuiTeamColor(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 WorldRenderer::LoadModels() {
utils::LOGD("World Created !");
m_WorldVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadWorldModel(m_World)));
m_MobVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadMobModel()));
m_SelectTileVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadTileSelectModel()));
utils::LOGD(utils::format("Vertex Count : %u", m_WorldVao->GetVertexCount()));
}
WorldRenderer::WorldRenderer(game::World* world, client::ClientGame* client) : m_Client(client), m_Renderer(m_Client->GetRenderer()), m_World(world), m_Zoom(0.1) {
m_Renderer->SetZoom(m_Zoom);
m_Renderer->SetCamMovement({});
m_TowerPlacePopup = std::make_unique<gui::TowerPlacePopup>(m_Client->GetClient());
m_TowerUpgradePopup = std::make_unique<gui::TowerUpgradePopup>(m_Client->GetClient());
m_MobTooltip = std::make_unique<gui::MobTooltip>(m_Client->GetClient());
m_CastleTooltip = std::make_unique<gui::CastleTooltip>(m_Client->GetClient());
m_Client->GetWorldClient().GetWorldNotifier().BindListener(this);
}
void WorldRenderer::UpdateCursorPos() {
m_CursorPos = GetCursorWorldPos();
}
void WorldRenderer::Update() {
if (m_WorldVao == nullptr)
return;
ImGuiIO& io = ImGui::GetIO();
if (io.MouseDown[0] && !ImGui::IsAnyItemActive() && !ImGui::IsAnyItemHovered()) {
ImVec2 mouseDelta = ImGui::GetIO().MouseDelta;
m_Renderer->SetCamMovement({ mouseDelta.x, mouseDelta.y });
}
if (io.MouseDown[1] && !ImGui::IsAnyItemActive() && !ImGui::IsAnyItemHovered()) {
ImVec2 mouseDelta = ImGui::GetIO().MouseDelta;
m_Renderer->SetCamAngularMovement({ mouseDelta.x, mouseDelta.y });
}
if (io.MouseWheel != 0) {
ChangeZoom(io.MouseWheel);
}
UpdateCursorPos();
if (ImGui::IsMouseClicked(0)) {
if (!m_TowerUpgradePopup->IsPopupOpened()) {
m_HoldCursorPos = { io.MousePos.x, io.MousePos.y };
}
}
if (ImGui::IsMouseDoubleClicked(1)) RemoveTower();
}
void WorldRenderer::RemoveTower() {
Vec2f cursorPos = GetCursorWorldPos();
game::TowerPtr clickedTower = m_World->GetTower(cursorPos);
if (clickedTower != nullptr) {
m_Client->GetClient()->RemoveTower(clickedTower->GetID());
}
}
void WorldRenderer::RenderWorld() const {
m_Renderer->RenderVAO(*m_WorldVao);
}
void WorldRenderer::RenderMobs() const {
for (game::MobPtr mob : m_World->GetMobList()) {
Renderer::Model model;
model.vao = m_MobVao.get();
model.positon = { mob->GetCenterX(), 0, mob->GetCenterY() };
model.color = mob->HasTakenDamage() ? Vec3f{ 1, 0.5, 0.5 } : Vec3f{ 1, 1, 1 };
m_Renderer->RenderModel(model);
}
}
void WorldRenderer::RenderTowers() const {
if (!m_TowersCache.IsEmpty())
m_Renderer->RenderVAO(m_TowersCache.GetVertexArray());
}
void WorldRenderer::RenderTileSelect() const {
if (ImGui::IsAnyItemHovered()) return;
if (m_MobTooltip->IsShown() || m_CastleTooltip->IsShown()) return;
Renderer::Model tileSelectModel;
tileSelectModel.vao = m_SelectTileVao.get();
tileSelectModel.positon = { std::floor(m_CursorPos.x), 0, std::floor(m_CursorPos.y) };
m_Renderer->RenderModel(tileSelectModel);
}
void WorldRenderer::RenderPopups() {
m_TowerPlacePopup->Render();
m_TowerUpgradePopup->Render();
}
void WorldRenderer::Render() {
if (m_WorldVao == nullptr)
return;
RenderWorld();
RenderMobs();
RenderTowers();
RenderTileSelect();
RenderTooltips();
RenderPopups();
DetectClick();
}
WorldRenderer::~WorldRenderer() {
}
void WorldRenderer::RenderTooltips() const {
RenderMobTooltip();
RenderCastleTooltip();
}
void WorldRenderer::MoveCam(float relativeX, float relativeY) {
if (m_WorldVao == nullptr)
return;
}
void WorldRenderer::ChangeZoom(float zoomStep) {
if (m_WorldVao == nullptr)
return;
m_Renderer->SetZoom(zoomStep);
}
void WorldRenderer::Click() {
const game::TowerPtr tower = m_Client->GetWorld().GetTower(GetClickWorldPos());
m_TowerPlacePopup->SetClickPos(GetClickWorldPos());
m_TowerUpgradePopup->SetClickPos(GetClickWorldPos());
if (tower != nullptr) { // there is a tower here
ImGui::OpenPopup("TowerUpgrade");
} else if (m_Client->GetWorld().CanPlaceLittleTower(GetClickWorldPos(), m_Client->GetPlayer()->GetID())) {
ImGui::OpenPopup("TowerPlace");
}
}
void WorldRenderer::SetCamPos(float camX, float camY) {
m_CamPos = { camX, camY };
m_Renderer->SetCamLook({ camX, camY });
}
void WorldRenderer::DetectClick() {
ImGuiIO& io = ImGui::GetIO();
if (ImGui::IsMouseReleased(0) && !ImGui::IsAnyItemHovered() && !ImGui::IsAnyItemFocused()) {
Vec2f cursorPos = { io.MousePos.x, io.MousePos.y };
if (cursorPos == m_HoldCursorPos) {
m_LastClicked = m_HoldCursorPos;
Click();
}
}
}
void WorldRenderer::RenderMobTooltip() const {
if (ImGui::IsAnyItemHovered()) return;
DetectMobHovering();
m_MobTooltip->Render();
}
void WorldRenderer::RenderCastleTooltip() const {
if (ImGui::IsAnyItemHovered()) return;
DetectCastleHovering();
m_CastleTooltip->Render();
}
void WorldRenderer::DetectMobHovering() const {
Vec2f cursorWorldPos = GetCursorWorldPos();
for (game::MobPtr mob : m_World->GetMobList()) {
if (mob->CollidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
m_MobTooltip->SetMob(mob.get());
return;
}
}
m_MobTooltip->SetMob(nullptr);
}
void WorldRenderer::DetectCastleHovering() const {
Vec2f cursorWorldPos = GetCursorWorldPos();
for (const game::Team& team : m_World->GetTeams()) {
if (team.GetCastle().CollidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
m_CastleTooltip->SetCastle(&team.GetCastle());
return;
}
}
m_CastleTooltip->SetCastle(nullptr);
}
void WorldRenderer::OnTowerAdd(game::TowerPtr tower) {
WorldLoader::RenderData RenderData = WorldLoader::LoadTowerModel(tower);
m_TowersCache.AddData(tower->GetID(), RenderData.positions, RenderData.colors);
m_TowersCache.UpdateVertexArray();
}
void WorldRenderer::OnTowerRemove(game::TowerPtr tower) {
m_TowersCache.RemoveData(tower->GetID());
m_TowersCache.UpdateVertexArray();
}
Vec2f WorldRenderer::GetCursorWorldPos() const {
ImGuiIO& io = ImGui::GetIO();
return m_Renderer->GetCursorWorldPos({ io.MousePos.x, io.MousePos.y }, Display::GetWindowWidth(), Display::GetWindowHeight());
}
Vec2f WorldRenderer::GetClickWorldPos() const {
return m_Renderer->GetCursorWorldPos(m_LastClicked, Display::GetWindowWidth(), Display::GetWindowHeight());
}
} // namespace render
} // namespace td