244 lines
6.8 KiB
C++
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
|