|
@@ -0,0 +1,314 @@
|
|
|
+//
|
|
|
+// Created by jovian on 18/07/17.
|
|
|
+//
|
|
|
+
|
|
|
+#include <iostream>
|
|
|
+#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<Visual *> &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<SDL_Point> 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;
|
|
|
+}
|