#include "building/research.hpp" #include "defaults/ui.hpp" #include "defaults/icons.hpp" #include "building/building.hpp" namespace Research { const int MENU_BG_COLOR_R = 0; const int MENU_BG_COLOR_G = 0; const int MENU_BG_COLOR_B = 0; const int MENU_BG_COLOR_A = 182; const int MENU_PADDING = 16; const float MENU_INNER_W = 800; const float MENU_INNER_H = 600; const float MENU_W = MENU_PADDING * 2 + MENU_INNER_W; const float MENU_H = MENU_PADDING * 2 + MENU_INNER_H; const int MENU_ITEM_SPACING = 6; const float MENU_TILE_SIZE = 48.0f; const float MENU_INFO_W = 300.0f; const float MENU_BORDER_OUTER = 4.0f; const float MENU_BORDER_SEPARATOR = 4.0f; const float MENU_TILE_BORDER = 2.0f; const int MENU_COLS = 6; const int MENU_ROWS = 8; SDL_FRect MENU_RESEARCH_BUTTON = {0,0,0,0}; SDL_FRect MENU_INFO_PANEL = {0,0,0,0}; SDL_Color MENU_HOVER_BORDER_C = Default::menu_hovering_color; const float RESEARCH_DURATION_MAX = 2.2f; bool is_researching = false; Researching research_item; std::vector research_buildings; std::vector research_items; void draw_ReserachMenu(SDL_Renderer* renderer, SDL_Rect win_size, BuildingType type, std::vector& researched_buildings, std::vector& researched_items, bool hovering_research_button) { BuildingData_s building_s = BuildingData::building_data[static_cast(type)]; const float menu_x = static_cast(win_size.w/2) - MENU_W/2; const float menu_y = static_cast(win_size.h/2) - MENU_H/2; const float inner_x = menu_x + MENU_BORDER_OUTER; const float inner_y = menu_y + MENU_BORDER_OUTER; const float inner_w = MENU_W - MENU_BORDER_OUTER * 2; const float inner_h = MENU_H - MENU_BORDER_OUTER * 2; const float info_x = inner_x + inner_w - MENU_INFO_W; const float sep_x = info_x - MENU_BORDER_SEPARATOR; const float grid_x = inner_x; const float grid_y = inner_y; const float grid_w = sep_x - inner_x; const float grid_h = inner_h; // MENU BACKGROUND SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, MENU_BG_COLOR_R, MENU_BG_COLOR_G, MENU_BG_COLOR_B, MENU_BG_COLOR_A ); SDL_FRect bg = { menu_x, menu_y, MENU_W, MENU_H }; SDL_RenderFillRect(renderer, &bg); // LEFT RIGHT SEPARATOR SDL_FRect separator_bar = { sep_x, inner_y, MENU_BORDER_SEPARATOR, inner_h }; SDL_SetRenderDrawColor(renderer, 80, 80, 80, 255); SDL_RenderFillRect(renderer, &separator_bar); // HEADER BAR const float header_h = 40.0f; SDL_FRect header_rect = { grid_x, grid_y, grid_w, header_h }; SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255); SDL_RenderFillRect(renderer, &header_rect); const std::string header_text = building_s.title + std::string(" | Level ") + std::to_string(BuildingData::get_WorkbenchLevel(building_s.type)); int text_w = 0; int text_h = 0; TTF_GetStringSize(Ui::font_menu, header_text.c_str(), header_text.size(), &text_w, &text_h); float text_x = header_rect.x + (header_rect.w - text_w) * 0.5f; float text_y = header_rect.y + (header_h - text_h) * 0.5f; SDL_FRect text_dest = { text_x, text_y, static_cast(text_w), static_cast(text_h) }; SDL_Color text_color = { 230, 230, 230, 255 }; SDL_Surface* surface_text = TTF_RenderText_Blended(Ui::font_menu, header_text.c_str(), header_text.size(), text_color); if (!surface_text) { SDL_DestroySurface(surface_text); return; } SDL_Texture* texture_text = SDL_CreateTextureFromSurface(renderer, surface_text); if (!texture_text) { SDL_DestroySurface(surface_text); return; } SDL_RenderTexture(renderer, texture_text, nullptr, &text_dest); SDL_DestroyTexture(texture_text); // GRID const float tile_total = MENU_TILE_SIZE + MENU_TILE_BORDER * 2; const float grid_required_w = MENU_COLS * tile_total + (MENU_COLS - 1) * MENU_ITEM_SPACING; const float grid_required_h = MENU_ROWS * tile_total + (MENU_ROWS - 1) * MENU_ITEM_SPACING; const float grid_content_y = grid_y + header_h; const float grid_start_x = grid_x + (grid_w - grid_required_w) * 0.5f; const float grid_start_y = grid_content_y + (grid_h - header_h - grid_required_h) * 0.5f; size_t b_count = research_buildings.size(); size_t i_count = research_items.size(); size_t slot_index = 0; //std::cout << "BC " << b_count << " IC " << i_count << std::endl; int active_b_el = -1; int active_i_el = -1; auto draw_checkmark = [&](SDL_Renderer* renderer, const SDL_FRect& rect) { auto it = Icon::icon_pos.find(IconType::CHECKMARK); SDL_FRect src{ it->second.x * 16.f, it->second.y * 16.f, 16.f, 16.f }; SDL_RenderTexture(renderer, Icon::icons_texture, &src, &rect); }; for (int r = 0; r < MENU_ROWS; ++r) { for (int c = 0; c < MENU_COLS; ++c) { if (Building::draw_menu_curser_grid_active == r*MENU_COLS+c) { if (slot_index < b_count) active_b_el = slot_index; else active_i_el = slot_index - b_count; } float x = grid_start_x + c * (tile_total + MENU_ITEM_SPACING); float y = grid_start_y + r * (tile_total + MENU_ITEM_SPACING); SDL_FRect border_rect{ x, y, tile_total, tile_total }; SDL_FRect tile_rect{ x + MENU_TILE_BORDER, y + MENU_TILE_BORDER, MENU_TILE_SIZE, MENU_TILE_SIZE }; if (Building::draw_menu_curser_grid_active == static_cast(slot_index)) SDL_SetRenderDrawColor(renderer, 20, 215, 0, 255); else if (Building::draw_menu_curser_grid == static_cast(slot_index)) SDL_SetRenderDrawColor(renderer, MENU_HOVER_BORDER_C.r, MENU_HOVER_BORDER_C.g, MENU_HOVER_BORDER_C.b, MENU_HOVER_BORDER_C.a); else SDL_SetRenderDrawColor(renderer, 20, 20, 20, 255); SDL_RenderFillRect(renderer, &border_rect); SDL_SetRenderDrawColor(renderer, 60, 60, 60, 255); SDL_RenderFillRect(renderer, &tile_rect); if (slot_index < b_count) { BuildingType bt = research_buildings[slot_index]; auto it = Icon::building_pos.find(bt); if (it != Icon::building_pos.end()) { SDL_FRect src{ it->second.x * 16.f, it->second.y * 16.f, 16.f, 16.f }; SDL_RenderTexture(renderer, Icon::icons_texture, &src, &tile_rect); } if (researched_buildings[static_cast(bt)]) { draw_checkmark(renderer, tile_rect); } } else if (slot_index < b_count + i_count) { ItemType itype = research_items[slot_index - b_count]; auto it2 = Icon::item_pos.find(itype); if (it2 != Icon::item_pos.end()) { SDL_FRect src{ it2->second.x * 16.f, it2->second.y * 16.f, 16.f, 16.f }; SDL_RenderTexture(renderer, Icon::icons_texture, &src, &tile_rect); } if (researched_items[static_cast(itype)]) { draw_checkmark(renderer, tile_rect); } } slot_index++; } } // INFO PANEL std::string info_title; if (active_b_el > -1 && active_b_el < static_cast(research_buildings.size())) { info_title = BuildingData::building_data[static_cast(research_buildings[static_cast(active_b_el)])].title; } else if (active_i_el > -1 && active_i_el < static_cast(research_items.size())) { info_title = Item::stats[static_cast(research_items[static_cast(active_i_el)])].title; } SDL_FRect info_panel = { info_x, inner_y, MENU_INFO_W, inner_h }; MENU_INFO_PANEL = info_panel; SDL_SetRenderDrawColor(renderer, 40, 40, 40, 255); SDL_RenderFillRect(renderer, &info_panel); // INFO TEXT int tw = 0; int th = 0; TTF_GetStringSize(Ui::font_menu, info_title.c_str(), info_title.size(), &tw, &th); const float t_x = info_panel.x + (info_panel.w - tw) * 0.5f; const float t_y = info_panel.y + MENU_BORDER_OUTER; SDL_Color t_color = { 230, 230, 230, 255 }; SDL_Surface* s = TTF_RenderText_Blended(Ui::font_menu, info_title.c_str(), info_title.size(), t_color); if (!s) return; SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, s); if (!tex) { SDL_DestroySurface(s); return; } SDL_FRect dst = { t_x, t_y, static_cast(tw), static_cast(th) }; SDL_RenderTexture(renderer, tex, nullptr, &dst); SDL_DestroyTexture(tex); // RESEARCH BUTTON float btn_h = 36.0f; float btn_w = MENU_INFO_W - MENU_BORDER_OUTER * 2; float btn_x = info_x + MENU_BORDER_OUTER; float btn_y = inner_y + inner_h - btn_h - MENU_BORDER_OUTER; SDL_FRect btn_rect = { btn_x, btn_y, btn_w, btn_h }; SDL_FRect btn_rect_bg = { btn_x-2, btn_y-2, btn_w+4, btn_h+4 }; MENU_RESEARCH_BUTTON = btn_rect; if (hovering_research_button) SDL_SetRenderDrawColor(renderer, MENU_HOVER_BORDER_C.r, MENU_HOVER_BORDER_C.g, MENU_HOVER_BORDER_C.b, MENU_HOVER_BORDER_C.a); else SDL_SetRenderDrawColor(renderer, 0,0,0, 255); SDL_RenderFillRect(renderer, &btn_rect_bg); SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255); SDL_RenderFillRect(renderer, &btn_rect); // Draw progress if (Research::research_item.is_researching) { float progress = Research::research_item.duration / RESEARCH_DURATION_MAX; SDL_FRect progress_rect = { btn_x, btn_y, btn_w * progress, btn_h }; SDL_SetRenderDrawColor(renderer, 100, 200, 100, 255); SDL_RenderFillRect(renderer, &progress_rect); } // Button label const std::string btn_text = "Research"; int r_w = 0; int r_h = 0; TTF_GetStringSize(Ui::font_menu, btn_text.c_str(), btn_text.size(), &r_w, &r_h); float r_x = btn_x + (btn_w - r_w) * 0.5f; float r_y = btn_y + (btn_h - r_h) * 0.5f; SDL_FRect r_dest = { r_x, r_y, static_cast(r_w), static_cast(r_h) }; SDL_Color r_color = { 230, 230, 230, 255 }; SDL_Surface* r_surface = TTF_RenderText_Blended(Ui::font_menu, btn_text.c_str(), btn_text.size(), r_color); if (!r_surface) { SDL_DestroySurface(r_surface); return; } SDL_Texture* r_texture = SDL_CreateTextureFromSurface(renderer, r_surface); if (!r_texture) { SDL_DestroySurface(r_surface); return; } SDL_RenderTexture(renderer, r_texture, nullptr, &r_dest); SDL_DestroyTexture(r_texture); } bool is_CursorOverMenuInfoPanel(const SDL_FPoint mouse_pos) { return ( mouse_pos.x >= MENU_INFO_PANEL.x && mouse_pos.x <= MENU_INFO_PANEL.x + MENU_INFO_PANEL.w && mouse_pos.y >= MENU_INFO_PANEL.y && mouse_pos.y <= MENU_INFO_PANEL.y + MENU_INFO_PANEL.h ); } bool cursor_OverResearchButton(const SDL_FPoint mouse_pos) { return ( mouse_pos.x >= MENU_RESEARCH_BUTTON.x && mouse_pos.x <= MENU_RESEARCH_BUTTON.x + MENU_RESEARCH_BUTTON.w && mouse_pos.y >= MENU_RESEARCH_BUTTON.y && mouse_pos.y <= MENU_RESEARCH_BUTTON.y + MENU_RESEARCH_BUTTON.h ); } int cursor_ResearchGridTileIndex(SDL_FPoint mouse, SDL_Rect win_size) { const float MENU_W = MENU_PADDING * 2 + MENU_INNER_W; const float MENU_H = MENU_PADDING * 2 + MENU_INNER_H; const float menu_x = static_cast(win_size.w / 2) - MENU_W / 2; const float menu_y = static_cast(win_size.h / 2) - MENU_H / 2; const float inner_x = menu_x + MENU_BORDER_OUTER; const float inner_y = menu_y + MENU_BORDER_OUTER; const float inner_w = MENU_W - MENU_BORDER_OUTER * 2; const float inner_h = MENU_H - MENU_BORDER_OUTER * 2; const float info_x = inner_x + inner_w - MENU_INFO_W; const float sep_x = info_x - MENU_BORDER_SEPARATOR; const float grid_x = inner_x; const float grid_y = inner_y; const float grid_w = sep_x - inner_x; const float grid_h = inner_h; const float header_h = 40.0f; const float tile_total = MENU_TILE_SIZE + MENU_TILE_BORDER * 2; const float grid_required_w = MENU_COLS * tile_total + (MENU_COLS - 1) * MENU_ITEM_SPACING; const float grid_required_h = MENU_ROWS * tile_total + (MENU_ROWS - 1) * MENU_ITEM_SPACING; const float grid_content_y = grid_y + header_h; const float grid_start_x = grid_x + (grid_w - grid_required_w) * 0.5f; const float grid_start_y = grid_content_y + (grid_h - header_h - grid_required_h) * 0.5f; if (mouse.x < grid_start_x || mouse.y < grid_start_y || mouse.x > grid_start_x + grid_required_w || mouse.y > grid_start_y + grid_required_h) { return -1; } float rel_x = mouse.x - grid_start_x; float rel_y = mouse.y - grid_start_y; const float step = tile_total + MENU_ITEM_SPACING; int c = static_cast(rel_x / step); int r = static_cast(rel_y / step); if (c < 0 || c >= MENU_COLS || r < 0 || r >= MENU_ROWS) { return -1; } float cx = rel_x - c * step; float cy = rel_y - r * step; if (cx < MENU_TILE_BORDER || cx > MENU_TILE_BORDER + MENU_TILE_SIZE || cy < MENU_TILE_BORDER || cy > MENU_TILE_BORDER + MENU_TILE_SIZE) { return -1; } return r * MENU_COLS + c; } bool research_Start() { if (!is_researching) return false; Researching item; size_t active_index = static_cast(Building::draw_menu_curser_grid_active); size_t b_count = research_buildings.size(); size_t index = active_index; if (active_index >= b_count) { // RESEACHING ITEM index = active_index - b_count; item.i_type = Research::research_items[index]; item.i_stats = Item::stats[static_cast(item.i_type)]; } else { item.b_type = Research::research_buildings[index]; item.b_stats = BuildingData::building_data[static_cast(item.b_type)]; } item.is_researching = true; research_item = item; return true; } void research_Stop() { Researching item; research_item = item; is_researching = false; } bool research_Continue(std::vector& researched_buildings, std::vector& researched_items) { research_item.duration += Default::delta_time; if (research_item.duration < RESEARCH_DURATION_MAX) return false; std::cout << "Researched something!\n"; if (research_item.i_type != ItemType::NONE) { researched_items[static_cast(research_item.i_type)] = true; } else if (research_item.b_type != BuildingType::NONE) { researched_buildings[static_cast(research_item.b_type)] = true; } research_Stop(); return true; } }