#include #include #include #include #include #include #include #include #include namespace td { Display::Display(int a_Width, int a_Height, const std::string& a_Title) : m_LastWidth(0), m_LastHeight(0), m_AspectRatio(1), m_ShouldClose(false) { if (!SDL_Init(SDL_INIT_VIDEO)) { utils::LOGE(utils::Format("Could not initialize SDL! SDL error: %s", SDL_GetError())); } m_Window = SDL_CreateWindow(a_Title.c_str(), a_Width, a_Height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); m_LastWidth = a_Width; m_LastHeight = a_Height; m_AspectRatio = (float)m_LastWidth / m_LastHeight; // Prepare and create context #ifdef __ANDROID__ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); m_GLContext = SDL_GL_CreateContext(m_Window); if (!m_GLContext) { utils::LOGE(utils::Format("Could not create context! SDL error: %s", SDL_GetError())); } int major, minor, mask; int r, g, b, a, depth; int mBuffers, mSamples; SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &mask); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r); SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g); SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b); SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a); SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth); SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &mBuffers); SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &mSamples); const char* mask_desc; if (mask & SDL_GL_CONTEXT_PROFILE_CORE) { mask_desc = "core"; } else if (mask & SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) { mask_desc = "compatibility"; } else if (mask & SDL_GL_CONTEXT_PROFILE_ES) { mask_desc = "es"; } else { mask_desc = "?"; } utils::LOG(utils::Format( "GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth)); utils::LOG(utils::Format("MultiSamples : Buffers : %i, Samples : %i", mBuffers, mSamples)); SDL_GL_MakeCurrent(m_Window, m_GLContext); GLenum error = glewInit(); if (error) { utils::LOGE(utils::Format("Error initializing glew : %s", glewGetErrorString(error))); } // WindowResizeEvent(WindowWidth, WindowHeight); // vsync SDL_GL_SetSwapInterval(1); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls // Setup Dear ImGui style ImGui::StyleColorsDark(); // ImGui::StyleColorsLight(); // Setup scaling float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); // ImGuiStyle& style = ImGui::GetStyle(); // style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing // this // // requires resetting Style + calling this again) // style.FontSizeBase = 13 * main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We // leave // // both here for documentation purpose) ImFontConfig cfg; cfg.SizePixels = 13 * main_scale * 2; io.Fonts->AddFontDefault(&cfg); // Setup Platform/Renderer backends ImGui_ImplSDL3_InitForOpenGL(m_Window, m_GLContext); ImGui_ImplOpenGL3_Init("#version 330"); LoadTheme(); } void Display::Close() { m_ShouldClose = true; } void Display::PollEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_EVENT_QUIT: case SDL_EVENT_WINDOW_CLOSE_REQUESTED: { m_ShouldClose = true; break; } case SDL_EVENT_WINDOW_RESIZED: { m_LastWidth = event.window.data1; m_LastHeight = event.window.data2; m_AspectRatio = (float)m_LastWidth / m_LastHeight; OnAspectRatioChange(m_AspectRatio); break; } case SDL_EVENT_KEY_DOWN: { if (!event.key.repeat) OnKeyDown(event.key.key); break; } default: break; } ImGui_ImplSDL3_ProcessEvent(&event); } // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL3_NewFrame(); ImGui::NewFrame(); } void Display::Update(float a_Delta) { StateMachine::Update(a_Delta); #ifndef NDEBUG ImGui::ShowDemoWindow(); #endif ImGui::Render(); ImGuiIO& io = ImGui::GetIO(); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); // glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(m_Window); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } Display::~Display() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL3_Shutdown(); ImGui::DestroyContext(); SDL_GL_DestroyContext(m_GLContext); SDL_DestroyWindow(m_Window); SDL_Quit(); } } // namespace td