diff --git a/Engine_Master_UPC/ModuleRender.cpp b/Engine_Master_UPC/ModuleRender.cpp index 56698b59..8b771b33 100644 --- a/Engine_Master_UPC/ModuleRender.cpp +++ b/Engine_Master_UPC/ModuleRender.cpp @@ -366,6 +366,8 @@ void ModuleRender::renderScene(ID3D12GraphicsCommandList4* commandList, const Re const float w = static_cast(outputSurface.getWidth()); const float h = static_cast(outputSurface.getHeight()); + app->getModuleUI()->buildCommandsForViewport(w, h); + D3D12_VIEWPORT viewport = { 0.0f, 0.0f, w, h, 0.0f, 1.0f }; D3D12_RECT scissorRect = { 0, 0, static_cast(w), static_cast(h) }; diff --git a/Engine_Master_UPC/ModuleUI.cpp b/Engine_Master_UPC/ModuleUI.cpp index 6b07094d..2f3297a6 100644 --- a/Engine_Master_UPC/ModuleUI.cpp +++ b/Engine_Master_UPC/ModuleUI.cpp @@ -29,23 +29,26 @@ void ModuleUI::preRender() { m_textCommands.clear(); m_imageCommands.clear(); +} -#ifdef GAME_RELEASE - auto viewport = app->getModuleD3D12()->getSwapChain()->getViewport(); - const ImVec2 screenSize(viewport.Width, viewport.Height); -#else - const ImVec2 screenSize = app->getModuleEditor()->getWindowSceneEditor()->getSize(); -#endif +void ModuleUI::buildCommandsForViewport(float width, float height) +{ + m_textCommands.clear(); + m_imageCommands.clear(); - if (screenSize.x <= 0.0f || screenSize.y <= 0.0f) + if (width <= 0.0f || height <= 0.0f) + { return; + } - m_rootScreenRect = { 0.0f, 0.0f, screenSize.x, screenSize.y }; + m_rootScreenRect = { 0.0f, 0.0f, width, height }; for (GameObject* go : app->getModuleScene()->getScene()->getAllGameObjects()) { if (!go || !go->GetActive()) + { continue; + } Canvas* canvas = go->GetComponentAs(ComponentType::CANVAS); if (!canvas || !canvas->isActive()) @@ -60,22 +63,22 @@ void ModuleUI::preRender() if (isScreenSpace) { - uiScale = UILayoutUtils::CalculateScreenSpaceScale(screenSize.x, screenSize.y); + uiScale = UILayoutUtils::CalculateScreenSpaceScale(width, height); } else { rootRect = { -0.5f, -0.5f, 1.0f, 1.0f }; } - if (Transform2D* canvasTransform = go->GetComponentAs(ComponentType::TRANSFORM2D)) - { - if (canvasTransform->isActive()) - { - rootRect = canvasTransform->getRect(rootRect, { 1.0f, 1.0f }); - } - } + if (Transform2D* canvasTransform = go->GetComponentAs(ComponentType::TRANSFORM2D)) + { + if (canvasTransform->isActive()) + { + rootRect = canvasTransform->getRect(rootRect, { 1.0f, 1.0f }); + } + } - buildUIDrawCommands(go, rootRect, canvas->renderMode, go->GetTransform()->getGlobalMatrix(), canvas->zTest, uiScale); + buildUIDrawCommands(go, rootRect, canvas->renderMode, go->GetTransform()->getGlobalMatrix(), canvas->zTest, uiScale); } } @@ -226,9 +229,43 @@ void ModuleUI::buildUIImage(GameObject* gameObject, const Rect2D& myRect, Canvas command.sheetOffset = Vector2(0.5f, 0.5f) * command.uvScale + uiImg->getSheetOffset(); const bool hasSheet = uiImg->getSheetColumns() > 1 || uiImg->getSheetRows() > 1; - if (uiImg->getStretchDrawMode() == UIImage::StretchDrawMode::Tile && !hasSheet) + const UIImage::StretchDrawMode drawMode = uiImg->getStretchDrawMode(); + + if (drawMode == UIImage::StretchDrawMode::Cover && !hasSheet) { + TextureAsset* textureAsset = uiImg->getTextureAsset(); + + if (textureAsset) + { + const float textureWidth = static_cast(textureAsset->getWidth()); + const float textureHeight = static_cast(textureAsset->getHeight()); + + if (textureWidth > 0.0f && textureHeight > 0.0f && myRect.w > 0.0f && myRect.h > 0.0f) + { + const float textureAspect = textureWidth / textureHeight; + const float rectAspect = myRect.w / myRect.h; + if (rectAspect > textureAspect) + { + // if the rectAspect is wider than the texture, fill width and crop top/bottom. + const float visibleV = textureAspect / rectAspect; + + command.uvScale = { 1.0f, visibleV }; + command.sheetOffset = { 0.5f, 0.5f }; + } + else + { + // int he other hand, if the rect is taller/narrower than the texture, fill height and crop left/right. + const float visibleU = rectAspect / textureAspect; + + command.uvScale = { visibleU, 1.0f }; + command.sheetOffset = { 0.5f, 0.5f }; + } + } + } + } + else if (drawMode == UIImage::StretchDrawMode::Tile && !hasSheet) + { if (t2d->getStretchMode() == StretchMode::HORIZONTAL) { command.uvScale.y *= t2d->getScale().y; @@ -236,16 +273,17 @@ void ModuleUI::buildUIImage(GameObject* gameObject, const Rect2D& myRect, Canvas else if (t2d->getStretchMode() == StretchMode::VERTICAL) { command.uvScale.x *= t2d->getScale().x; - } + } else if (t2d->getStretchMode() == StretchMode::BOTH) - { - command.uvScale *= Vector2(myRect.w / t2d->getBaseSize().x, myRect.h / t2d->getBaseSize().y); - } + { + command.uvScale *= Vector2(myRect.w / t2d->getBaseSize().x, myRect.h / t2d->getBaseSize().y); + } else { command.uvScale *= t2d->getScale(); - } - command.sheetOffset = Vector2(0.5f, 0.5f); + } + + command.sheetOffset = Vector2(0.5f, 0.5f); } command.renderMode = renderMode; diff --git a/Engine_Master_UPC/ModuleUI.h b/Engine_Master_UPC/ModuleUI.h index dad4db6b..5c301c4d 100644 --- a/Engine_Master_UPC/ModuleUI.h +++ b/Engine_Master_UPC/ModuleUI.h @@ -17,6 +17,8 @@ class ModuleUI : public Module void preRender() override; bool cleanUp() override; + void buildCommandsForViewport(float width, float height); + const std::vector& getTextCommands() const { return m_textCommands; } const std::vector& getImageCommands() const { return m_imageCommands; } diff --git a/Engine_Master_UPC/RenderSurface.cpp b/Engine_Master_UPC/RenderSurface.cpp index bb184cb1..fd2c0858 100644 --- a/Engine_Master_UPC/RenderSurface.cpp +++ b/Engine_Master_UPC/RenderSurface.cpp @@ -16,14 +16,6 @@ RenderSurface::RenderSurface() : m_textures(AttachmentPoint::NUM_ATTACHMENT_POIN void RenderSurface::attachTexture(AttachmentPoint attachmentPoint, std::shared_ptr texture) { m_textures[attachmentPoint] = texture; - - if (texture && texture->getD3D12Resource()) - { - auto desc = texture->getD3D12ResourceDesc(); - - m_size.x = static_cast(desc.Width); - m_size.y = static_cast(desc.Height); - } } std::shared_ptr RenderSurface::getTexture(AttachmentPoint attachmentPoint) const @@ -88,6 +80,11 @@ void RenderSurface::resize(uint32_t width, uint32_t height) resize(Vector2(static_cast(width), static_cast(height))); } +void RenderSurface::setSize(uint32_t width, uint32_t height) +{ + m_size = Vector2(static_cast(width), static_cast(height)); +} + Vector2 RenderSurface::getSize() const { return m_size; diff --git a/Engine_Master_UPC/RenderSurface.h b/Engine_Master_UPC/RenderSurface.h index a214c5fc..d5dd7ad5 100644 --- a/Engine_Master_UPC/RenderSurface.h +++ b/Engine_Master_UPC/RenderSurface.h @@ -39,6 +39,7 @@ class RenderSurface void resize(Vector2 size); void resize(uint32_t width, uint32_t height); + void setSize(uint32_t width, uint32_t height); Vector2 getSize() const; uint32_t getWidth() const; diff --git a/Engine_Master_UPC/SwapChain.cpp b/Engine_Master_UPC/SwapChain.cpp index 19cfe7ca..618def10 100644 --- a/Engine_Master_UPC/SwapChain.cpp +++ b/Engine_Master_UPC/SwapChain.cpp @@ -60,6 +60,8 @@ SwapChain::SwapChain(HWND hWnd, ComPtr device, CommandQueue* queu auto* depthTexture = app->getModuleResources()->createDepthBuffer(float(m_windowWidth), float(m_windowHeight)); m_renderSurface.attachTexture( RenderSurface::DEPTH_STENCIL, std::shared_ptr(depthTexture)); + + m_renderSurface.setSize(m_windowWidth, m_windowHeight); } SwapChain::~SwapChain() @@ -114,7 +116,11 @@ void SwapChain::resize() DXCall(m_swapChain->ResizeBuffers(FRAMES_IN_FLIGHT, width, height, swapChainDesc.BufferDesc.Format, swapChainDesc.Flags)); createRenderTargetViews(app->getModuleD3D12()->getDevice()); - m_renderSurface.resize(m_windowWidth, m_windowHeight); + + auto* depthTexture = app->getModuleResources()->createDepthBuffer(float(m_windowWidth), float(m_windowHeight)); + m_renderSurface.attachTexture(RenderSurface::DEPTH_STENCIL, std::shared_ptr(depthTexture)); + + m_renderSurface.setSize(m_windowWidth, m_windowHeight); } } diff --git a/Engine_Master_UPC/UIImage.cpp b/Engine_Master_UPC/UIImage.cpp index e6ab1939..e5694cc6 100644 --- a/Engine_Master_UPC/UIImage.cpp +++ b/Engine_Master_UPC/UIImage.cpp @@ -107,7 +107,7 @@ void UIImage::drawUi() ImGui::Separator(); ImGui::TextUnformatted("Stretch"); { - const char* modes[] = { "Stretch", "Tile" }; + const char* modes[] = { "Stretch", "Tile", "Cover" }; int mode = static_cast(m_stretchDrawMode); if (ImGui::Combo("When Stretched", &mode, modes, IM_ARRAYSIZE(modes))) { diff --git a/Engine_Master_UPC/UIImage.h b/Engine_Master_UPC/UIImage.h index abead62f..d4bf7926 100644 --- a/Engine_Master_UPC/UIImage.h +++ b/Engine_Master_UPC/UIImage.h @@ -13,18 +13,27 @@ class UIImage : public Component enum class StretchDrawMode { Stretch = 0, - Tile = 1 + Tile = 1, + Cover = 2 }; static const char* StretchDrawModeToString(uint32_t v) { - return v == 0 ? "Stretch" : "Tile"; + switch (static_cast(v)) + { + case StretchDrawMode::Stretch: return "Stretch"; + case StretchDrawMode::Tile: return "Tile"; + case StretchDrawMode::Cover: return "Cover"; + } } static uint32_t StringToStretchDrawMode(const char* s) { - return std::strcmp(s, "Tile") == 0 ? 1 : 0; + if (std::strcmp(s, "Tile") == 0) return 1; + if (std::strcmp(s, "Cover") == 0) return 2; + return 0; } + UIImage(UID id, GameObject* owner); std::unique_ptr clone(GameObject* newOwner) const override;