// // Created by jovian on 18/07/17. // #include #include "Renderer.h" #define RAD_TO_DEG 57.2957795130f Renderer::Renderer() : m_screenWidth(0), m_screenHeight(0), m_window(nullptr), m_renderer(nullptr), m_font(nullptr) {} Renderer::~Renderer() { // Destroy textures while (!m_pictureTab.empty()) { if (m_pictureTab.back() != nullptr) SDL_DestroyTexture(m_pictureTab.back()); m_pictureTab.pop_back(); } // Destroy string textures for (auto it(m_stringTab.begin()); it != m_stringTab.end(); it++) { if (it->second != nullptr) SDL_DestroyTexture(it->second); it->second = nullptr; } m_stringTab.clear(); // Destroy SDL renderer if (m_renderer != nullptr) { SDL_DestroyRenderer(m_renderer); m_renderer = nullptr; } // Destroy the beautiful window if (m_window != nullptr) { SDL_DestroyWindow(m_window); m_window = nullptr; } // Quit modules TTF_Quit(); SDL_Quit(); } bool Renderer::initialize() { // Announce std::cout << "Renderer::initialize() > "; // Already initialized if (m_window != nullptr) { std::cout << "Window already created." << std::endl << std::endl; return false; } // Default screen size m_screenWidth = WIN_W; m_screenHeight = WIN_H; // Init video if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "SDL video failed : " << SDL_GetError() << std::endl << std::endl; return false; } // Init font if (TTF_Init() == -1) { std::cout << "TTF failed : " << TTF_GetError() << std::endl << std::endl; return false; } m_font = TTF_OpenFont("droid.ttf", 28); if (m_font == NULL) { std::cout << "Open droid.ttf failed : " << TTF_GetError() << std::endl << std::endl; return false; } // Opening window m_window = SDL_CreateWindow("MetaBalls visualizer - Jovian Hersemeule", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_screenWidth, m_screenHeight, SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN_DESKTOP*/); if (m_window == nullptr) { std::cout << "Window creation failed : " << SDL_GetError() << std::endl << std::endl; SDL_Quit(); return false; } // Hardware physical screen size SDL_GetWindowSize(m_window, &m_screenWidth, &m_screenHeight); // Create renderer m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (m_renderer == nullptr) { SDL_DestroyWindow(m_window); std::cout << "SDL Renderer creation failed : " << SDL_GetError() << std::endl << std::endl; SDL_Quit(); return false; } // End std::cout << "Done, no error detected." << std::endl; // Okay return true; } void Renderer::clearWindow() { // Clean up buffer SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(m_renderer); } /*void Renderer::renderScene(std::vector &scope, const b2Vec2 ¢er, float zoom) { // Texture existence if (m_pictureTab.empty()) return; // Rect SDL_Rect dst; SDL_Texture *tex; b2Vec2 rel; float localZoom; // For each for (auto it(scope.begin()); it != scope.end(); it++) { // Skip if no invalid texture if ((*it)->getImgId() > m_pictureTab.size() || m_pictureTab[(*it)->getImgId()] == nullptr) tex = m_pictureTab[0]; else tex = m_pictureTab[(*it)->getImgId()]; // Adjusting local zoom localZoom = zoom * (*it)->getScale(); // Rect set up rel = (*it)->getPos() - center; dst.x = (int) (rel.x * zoom) + m_screenWidth / 2; dst.y = (int) (rel.y * zoom) + m_screenHeight / 2; SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); // Zoom correction dst.w = (int) (localZoom * dst.w / DEFAULT_ZOOM); dst.h = (int) (localZoom * dst.h / DEFAULT_ZOOM); // Center texture dst.x -= dst.w / 2; dst.y -= dst.h / 2; // SDL rendering SDL_RenderCopyEx(m_renderer, tex, NULL, &dst, (*it)->getAngle() * RAD_TO_DEG, NULL, SDL_FLIP_NONE); } }*/ /*void Renderer::renderPlanetHUD(PlanetDef def) { // Variable SDL_Rect dst; // Line under color const Uint8 uncl(0xaf); // Render rect dst.x = 10; dst.y = 10; int w = m_screenWidth / 2 - 2*dst.x + 24; int h = m_screenHeight * 2 / 3 - 2*dst.y; dst.w = w; dst.h = h; SDL_SetRenderDrawColor(m_renderer, 0x66, 0x66, 0x66, 0xff); SDL_RenderFillRect(m_renderer, &dst); SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0xff, 0xff); SDL_RenderDrawRect(m_renderer, &dst); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + 37, dst.x + dst.w - 1, dst.y + 37); // Render planet name dst.x = 11; dst.y = 11; renderName(dst, def.name); // Column dst.x = 20; // Jumps #define H_NEXT_BAR 32 #define H_OFFSET_BAR 10 // People dst.y = 60; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "People"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(PEOPLE)); }*/ void Renderer::renderName(SDL_Rect &dst, std::string name) { // Seek an existing name texture auto it(m_stringTab.find(name)); if (it == m_stringTab.end()) { // Not loaded yet, let's fix this ! if (!loadStringTexture(name)) return; SDL_QueryTexture(m_stringTab[name], NULL, NULL, &dst.w, &dst.h); SDL_RenderCopy(m_renderer, m_stringTab[name], NULL, &dst); } else { // Faster plot SDL_QueryTexture(it->second, NULL, NULL, &dst.w, &dst.h); SDL_RenderCopy(m_renderer, it->second, NULL, &dst); } } void Renderer::renderBoolMatrix(bool mat[WIN_H][WIN_W]) { SDL_SetRenderDrawColor(m_renderer, 255, 255, 0, 255); std::vector points; for (int i(0); i < WIN_H; i++) for (int j(0); j < WIN_W; j++) { if (mat[i][j]) //SDL_RenderDrawPoint(m_renderer, j, i); points.push_back({j, i}); } SDL_RenderDrawPoints(m_renderer, points.data(), (int)points.size()); } /*void Renderer::renderBar(int y, const int &value) { // Set position SDL_Rect dst; dst.x = 208; dst.y = y; dst.h = 16; // Set color and scale if (value == 0) { SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0xff); dst.w = dst.h; } else if (value < 400) { SDL_SetRenderDrawColor(m_renderer, 0x00, 0xff, 0x00, 0xff); dst.w = value; } else if (value < 4000) { SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0x00, 0xff); dst.w = value / 10; } else if (value < 400000) { SDL_SetRenderDrawColor(m_renderer, 0xff, 0xaa, 0x00, 0xff); dst.w = value / 1000; } else if (value < 40000000) { SDL_SetRenderDrawColor(m_renderer, 0xff, 0x55, 0x00, 0xff); dst.w = value / 100000; } else { SDL_SetRenderDrawColor(m_renderer, 0xff, 0x00, 0x00, 0xff); dst.w = value / 10000000; } // Draw SDL_RenderFillRect(m_renderer, &dst); SDL_SetRenderDrawColor(m_renderer, 0xaf, 0xaf, 0xaf, 0xff); if (value == 0) { SDL_RenderDrawLine(m_renderer, dst.x, dst.y, dst.x + dst.w - 1, dst.y + dst.h - 1); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + dst.h - 1, dst.x + dst.w - 1, dst.y); } else { dst.w = 400; } SDL_RenderDrawRect(m_renderer, &dst); }*/ void Renderer::presentWindow() { // Activate display SDL_RenderPresent(m_renderer); } bool Renderer::loadStringTexture(std::string name) { // Render text surface //SDL_Surface* textSurface = TTF_RenderText_Solid(m_font, name.c_str(), {0, 255, 0, 255}); SDL_Surface *textSurface = TTF_RenderText_Shaded(m_font, name.c_str(), {0x00, 0xff, 0x00, 0xff}, {0x66, 0x66, 0x66, 0xff}); if (textSurface == NULL) { std::cout << "Renderer::loadStringTexture() [1] > " << TTF_GetError() << std::endl << std::endl; return false; } // Create texture from surface pixels SDL_Texture *texture(SDL_CreateTextureFromSurface(m_renderer, textSurface)); SDL_FreeSurface(textSurface); if (texture == NULL) { std::cout << "Renderer::loadStringTexture() [2] > " << SDL_GetError() << std::endl << std::endl; return false; } m_stringTab[name] = texture; // All right return true; } SDL_Window *Renderer::getWindow() const { return m_window; }