diff --git a/Engine/Graphics/3DRenderer.cpp b/Engine/Graphics/3DRenderer.cpp index 80b77a2..dfaf3d7 100644 --- a/Engine/Graphics/3DRenderer.cpp +++ b/Engine/Graphics/3DRenderer.cpp @@ -21,10 +21,12 @@ // * https://www.coranac.com/tonc/text/mode7.htm Graphic3DRenderer::Graphic3DRenderer() { + mRTSize = {1280.f, 324.f}; + if (mMainCamera == nullptr) { mMainCamera = std::make_unique(); mMainCamera->SetPosition(0.0f, 1.5f, -8.0f); - mMainCamera->SetFrustrum(90.0f, 1280.f/324.f, 1.0f, 100.f); + mMainCamera->SetFrustrum(90.0f, mRTSize.x/mRTSize.y, 1.0f, 100.f); mMainCamera->UpdateCamView(); } @@ -46,6 +48,11 @@ Graphic3DRenderer::Graphic3DRenderer() { Graphic3DRenderer::~Graphic3DRenderer() {} +void Graphic3DRenderer::SetRTSize(unsigned int w, unsigned int h) { + mRTSize.x = w; mRTSize.y = h; + mMainCamera->SetFrustrum(90.0f, mRTSize.x/mRTSize.y, 1.0f, 100.f); +} + void Graphic3DRenderer::UpdateCamera(CAMERA_MOVE type, const float value) { switch (type) { case CAMERA_MOVE_WALK: @@ -129,9 +136,9 @@ void Graphic3DRenderer::Draw(sf::RenderTexture& context) { M3D_VECTOR V2 = M3D_V4LoadF3(&(projVertices + processedVerticesCnt)[indicePtr[i+1]]); M3D_VECTOR V3 = M3D_V4LoadF3(&(projVertices + processedVerticesCnt)[indicePtr[i+2]]); - V1 = M3D_V3TransformNDCToViewport(V1, 0.f, 0.f, 1280.f, 324.f, 1.f, 100.f); - V2 = M3D_V3TransformNDCToViewport(V2, 0.f, 0.f, 1280.f, 324.f, 1.f, 100.f); - V3 = M3D_V3TransformNDCToViewport(V3, 0.f, 0.f, 1280.f, 324.f, 1.f, 100.f); + V1 = M3D_V3TransformNDCToViewport(V1, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f); + V2 = M3D_V3TransformNDCToViewport(V2, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f); + V3 = M3D_V3TransformNDCToViewport(V3, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f); v_tri[0].position = sf::Vector2f(M3D_V4GetX(V1), M3D_V4GetY(V1)); v_tri[0].color = oMesh.vertices[indicePtr[i]].color; diff --git a/Engine/Graphics/3DRenderer.hpp b/Engine/Graphics/3DRenderer.hpp index 2d81341..01575ef 100644 --- a/Engine/Graphics/3DRenderer.hpp +++ b/Engine/Graphics/3DRenderer.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "Camera.hpp" #include "../Utils/MeshHelper.hpp" @@ -25,11 +26,15 @@ public: Graphic3DRenderer(Graphic3DRenderer const&) = delete; Graphic3DRenderer& operator= (Graphic3DRenderer const&) = delete; + const sf::Vector2f& GetRTSize() const noexcept { return mRTSize; } + void SetRTSize(unsigned int w, unsigned int h); + void UpdateCamera(CAMERA_MOVE type, const float value); void Draw(sf::RenderTexture& context); private: std::unique_ptr mMainCamera; // Default player view + sf::Vector2f mRTSize; std::vector> mRenderList; // List of elements to be rendered next frame diff --git a/Engine/Graphics/UI.cpp b/Engine/Graphics/UI.cpp index ae09b8a..55c26b4 100644 --- a/Engine/Graphics/UI.cpp +++ b/Engine/Graphics/UI.cpp @@ -2,37 +2,49 @@ #include -#include #include #include #include #include +#include -#include #include -void UI::DrawUIOnRenderWindow(std::shared_ptr context) { - sf::Sprite spriteRender; - spriteRender.setTexture(this->mUIRender.getTexture()); - spriteRender.setPosition(0.0f, 0.0f); - spriteRender.setScale(1.0f, 1.0f); - context->draw(spriteRender); +void UI::SetRTSize(unsigned int w, unsigned int h, bool recreateCanvas) { + mRTSize.x = w; mRTSize.y = h; + + // Don't resize/recreate canvas, this cut the fixed sprite + //TODO: use scaling feature on the assets to put on the canvas, then resize the canvas + if (recreateCanvas) + CreateDefaultRenderWindow(); } - -CockpitUI::CockpitUI() : UI() { +void UI::CreateDefaultRenderWindow() { sf::ContextSettings sViewSettings; sViewSettings.depthBits = 0; sViewSettings.stencilBits = 0; sViewSettings.antialiasingLevel = 8; sViewSettings.sRgbCapable = true; - if (!mUIRender.create(1280, 720, sViewSettings)) + if (!mUIRender.create(mRTSize.x, mRTSize.y, sViewSettings)) throw std::runtime_error("Texture renderer creation failure"); mUIRender.setSmooth(true); mUIRender.setRepeated(false); +} + +void UI::DrawUIOnRenderWindow(std::shared_ptr context, float& viewX, float& viewY) { + sf::Sprite spriteRender; + spriteRender.setTexture(this->mUIRender.getTexture()); + spriteRender.setPosition(0.0f, 0.0f); + spriteRender.setScale(mRTSize.x / viewX, mRTSize.y / viewY); + context->draw(spriteRender); +} + + +CockpitUI::CockpitUI(unsigned int w, unsigned int h) : UI(w, h) { + CreateDefaultRenderWindow(); mStaticCockpitTexture.setSrgb(true); if (!mStaticCockpitTexture.loadFromFile("cockpit_ui_empty_rescaled.png", sf::IntRect(0, 0, 1280, 780))) @@ -65,24 +77,15 @@ void CockpitUI::Draw(std::shared_ptr context) { mUIRender.display(); // OnScreen rendering - DrawUIOnRenderWindow(context); + auto tvSize = sf::Vector2f(1280.f, 720.f); + DrawUIOnRenderWindow(context, tvSize); } -WorldUI::WorldUI(std::shared_ptr engineInstance) : UI(), mWorld3D(engineInstance) { - sf::ContextSettings sViewSettings; - sViewSettings.depthBits = 0; - sViewSettings.stencilBits = 0; - sViewSettings.antialiasingLevel = 8; - sViewSettings.sRgbCapable = true; +WorldUI::WorldUI(unsigned int w, unsigned int h, std::shared_ptr engineInstance) : UI(w, h), mWorld3D(engineInstance) { + CreateDefaultRenderWindow(); - if (!mUIRender.create(1280, 324, sViewSettings)) // Only the upper of the screen is renderer as the UI hide whats left. - throw std::runtime_error("Texture renderer creation failure"); - - mUIRender.setSmooth(true); - mUIRender.setRepeated(false); mUIRender.clear(sf::Color::Black); - mUIRender.display(); } @@ -104,5 +107,5 @@ void WorldUI::Draw(std::shared_ptr context) { mUIRender.display(); // OnScreen rendering - DrawUIOnRenderWindow(context); + UI::Draw(context); } \ No newline at end of file diff --git a/Engine/Graphics/UI.hpp b/Engine/Graphics/UI.hpp index 469f64d..03372ba 100644 --- a/Engine/Graphics/UI.hpp +++ b/Engine/Graphics/UI.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -10,13 +11,23 @@ class UI { public: virtual ~UI() = 0; + const sf::Vector2f& GetRTSize() const noexcept { return mRTSize; } + void SetRTSize(unsigned int w, unsigned int h, bool recreateCanvas = false); + virtual void Update() = 0; virtual inline void Draw(std::shared_ptr c) { DrawUIOnRenderWindow(c); } protected: + UI(unsigned int w, unsigned int h) : mRTSize(sf::Vector2f(w, h)) {} + UI(sf::Vector2f size) : mRTSize(size) {} + + sf::Vector2f mRTSize; sf::RenderTexture mUIRender; // The screen to draw onto - void DrawUIOnRenderWindow(std::shared_ptr context); + void CreateDefaultRenderWindow(); + void DrawUIOnRenderWindow(std::shared_ptr context, float& viewX, float& viewY); + inline void DrawUIOnRenderWindow(std::shared_ptr context) { DrawUIOnRenderWindow(context, mRTSize); } + inline void DrawUIOnRenderWindow(std::shared_ptr context, sf::Vector2f& view) { DrawUIOnRenderWindow(context, view.x, view.y); } }; @@ -24,7 +35,7 @@ inline UI::~UI() {} class CockpitUI final : public UI { public: - CockpitUI(); + CockpitUI(unsigned int w, unsigned int h); ~CockpitUI() {} CockpitUI(CockpitUI&&) = default; @@ -42,7 +53,7 @@ private: class WorldUI final : public UI { public: - WorldUI(std::shared_ptr engineInstance); + WorldUI(unsigned int w, unsigned int h, std::shared_ptr engineInstance); ~WorldUI() {} WorldUI(WorldUI&&) = default; diff --git a/Game.cpp b/Game.cpp index 3712928..9d0727f 100644 --- a/Game.cpp +++ b/Game.cpp @@ -11,15 +11,16 @@ using std::make_shared; using std::make_unique; -#define TARGET_FPS (60) - Game* Game::smInstance = nullptr; Game::Game(std::shared_ptr mainWnd, bool dbgFlag) : mbDbgModeEnabled(dbgFlag), mMainWindow(mainWnd) { + unsigned int wndWidth, wndHeight; + GetDefaultWindowSize(wndWidth, wndHeight); + mWorld3D = make_shared(); - mCockpitUI = make_unique(); - mWorldUI = make_unique(mWorld3D); + mCockpitUI = make_unique(wndWidth, (wndWidth * H_RATIO)); + mWorldUI = make_unique(wndWidth, std::floor((wndWidth * H_RATIO) * 0.45f), mWorld3D); if (mbDbgModeEnabled) { mDbgUI = make_unique(); @@ -92,6 +93,12 @@ void Game::EventMouseMoved(int _x, int _y) { mPrevMousePos.y = _y; } +void Game::EventWindowSizeChanged(unsigned int w, unsigned int h) { + mCockpitUI->SetRTSize(static_cast(w), (w * H_RATIO)); + mWorldUI->SetRTSize(static_cast(w), std::floor((w * H_RATIO) * 0.45f), true); + mWorld3D->SetRTSize(static_cast(w), std::floor((w * H_RATIO) * 0.45f)); +} + void Game::Update() { // Refresh keyboard inputs KeyboardInputsCheck(); diff --git a/Game.hpp b/Game.hpp index af17f9a..d84515b 100644 --- a/Game.hpp +++ b/Game.hpp @@ -7,6 +7,12 @@ #include "Engine/Graphics/3DRenderer.hpp" #include "Engine/Utils/Timers.hpp" +#define WNDSIZE_DEFAULT_W (1280) +#define WNDSIZE_DEFAULT_H (720) +#define W_RATIO (16.f / 9.f) +#define H_RATIO (9.f / 16.f) +#define TARGET_FPS (60) + typedef enum eGameStatus { GAME_INIT, @@ -30,8 +36,13 @@ public: Game(Game const&) = delete; Game& operator= (Game const&) = delete; + static void GetDefaultWindowSize(unsigned int& w, unsigned int& h) noexcept { + w = WNDSIZE_DEFAULT_W; h = WNDSIZE_DEFAULT_H; + } + GAME_STATUS Tick(); void EventMouseMoved(int _x, int _y); + void EventWindowSizeChanged(unsigned int w, unsigned int h); private: Game(std::shared_ptr mainWnd, bool dbgFlag) noexcept(false); diff --git a/ProtoTank.cpp b/ProtoTank.cpp index 1867211..08945f8 100644 --- a/ProtoTank.cpp +++ b/ProtoTank.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "icon.h" #include "Engine/Misc/Logger.hpp" @@ -9,15 +10,28 @@ #include "Game.hpp" -static std::shared_ptr InitWindow(unsigned int width, unsigned int height, bool fullscreen); +struct MainWindowParams { + sf::Vector2u wndSize = {0, 0}; // Ignored on fullscreen mode + sf::ContextSettings wndContextSettings; + bool wndFullscreen = false; +}; + +static void CreateWindow(std::shared_ptr wnd, MainWindowParams& params); +//static void ForceWindowRatio(sf::RenderWindow* wnd); int main(int argc, char** argv) { Logger& log = Logger::getInstance(); log.PrintInfo(LOGGER_MSG_FT("Create main window")); - std::shared_ptr mainWindow = nullptr; + MainWindowParams wndParams; + Game::GetDefaultWindowSize(wndParams.wndSize.x, wndParams.wndSize.y); + wndParams.wndContextSettings.depthBits = 0; + wndParams.wndContextSettings.stencilBits = 0; + wndParams.wndContextSettings.antialiasingLevel = 8; + wndParams.wndContextSettings.sRgbCapable = true; + auto mainWindow = std::make_shared(); try { - mainWindow = InitWindow(1280, 720, false); + CreateWindow(mainWindow, wndParams); } catch (const std::exception& ex) { log.PrintCritical(std::string(ex.what())); return EXIT_FAILURE; @@ -30,6 +44,7 @@ int main(int argc, char** argv) { Game& arcadeGame = Game::getInstance(mainWindow, false); #endif GAME_STATUS status = GAME_INIT; + sf::FloatRect visibleArea(0, 0, WNDSIZE_DEFAULT_W, WNDSIZE_DEFAULT_H); for ( ;; ) { sf::Event event; @@ -40,9 +55,11 @@ int main(int argc, char** argv) { break; case sf::Event::Resized: - //TODO: Recreate window related resource - //event.size.width - //event.size.height + visibleArea.width = event.size.width; + visibleArea.height = event.size.height; + mainWindow->setView(sf::View(visibleArea)); // Adapt the view resolution + arcadeGame.EventWindowSizeChanged(event.size.width, event.size.height); + //ForceWindowRatio(mainWindow.get()); break; //case sf::Event::LostFocus: @@ -73,6 +90,16 @@ int main(int argc, char** argv) { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) { mainWindow->close(); status = GAME_QUIT; + } else if ((sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt) || sf::Keyboard::isKeyPressed(sf::Keyboard::RAlt)) && sf::Keyboard::isKeyPressed(sf::Keyboard::Enter)) { + wndParams.wndFullscreen = !wndParams.wndFullscreen; + try { + CreateWindow(mainWindow, wndParams); + } catch (const std::exception& ex) { + log.PrintCritical(std::string(ex.what())); + return EXIT_FAILURE; + } + + arcadeGame.EventWindowSizeChanged(mainWindow->getSize().x, mainWindow->getSize().y); } status = arcadeGame.Tick(); @@ -85,32 +112,45 @@ int main(int argc, char** argv) { return EXIT_SUCCESS; } -static std::shared_ptr InitWindow(unsigned int width, unsigned int height, bool fullscreen) { - // Create default game window - sf::ContextSettings sWindowSettings; - sWindowSettings.depthBits = 0; - sWindowSettings.stencilBits = 0; - sWindowSettings.antialiasingLevel = 8; - sWindowSettings.sRgbCapable = true; - +static void CreateWindow(std::shared_ptr wnd, MainWindowParams& params) { sf::Uint32 wndStyle = sf::Style::Close | sf::Style::Titlebar; - if(fullscreen) - wndStyle = wndStyle | sf::Style::Fullscreen; - - auto wnd = std::make_shared( - sf::VideoMode(width, height), "ProtoTank", - wndStyle, - sWindowSettings - ); + sf::VideoMode vMode; if (wnd == nullptr) - throw std::runtime_error("Failed to create the window"); + throw std::invalid_argument("Failed to create the window"); + + if (params.wndFullscreen) { + vMode = sf::VideoMode::getFullscreenModes().front(); + wndStyle = sf::Style::Fullscreen; + } else { + vMode = sf::VideoMode(params.wndSize.x, params.wndSize.y); + wndStyle = sf::Style::Close | sf::Style::Titlebar | sf::Style::Resize; + } + /*if(mode == BORDERLESS) { + //vMode = sf::VideoMode::getFullscreenModes().front(); + //vMode = sf::VideoMode(params.wndSize.x, params.wndSize.y); + vMode = sf::VideoMode::getDesktopMode(); + wndStyle = sf::Style::None; + }*/ + + wnd->create(vMode, "ProtoTank", wndStyle, params.wndContextSettings); wnd->setVerticalSyncEnabled(false); // Never use simultaneously with framerate limiter wnd->setFramerateLimit(60); // Never use simultaneously with VSync wnd->setKeyRepeatEnabled(false); wnd->setMouseCursorVisible(true); wnd->setIcon(64, 64, _aicon_bin); +} - return wnd; -} \ No newline at end of file +/* +inline static void ForceWindowRatio(sf::RenderWindow* wnd) { + auto wndSize = wnd->getSize(); + + if (wndSize.y * W_RATIO <= wndSize.x) + wndSize.x = wndSize.y * W_RATIO; + else if (wndSize.x * H_RATIO <= wndSize.y) + wndSize.y = wndSize.x * H_RATIO; + + wnd->setSize(wndSize); +} +*/ \ No newline at end of file