#pragma once #include #include #include // NativeUI — Direct D3D11 2D rendering for SWF-free UIScene subclasses. // // Renders rectangles, text, and widgets via raw D3D11 draw calls, // completely independent of the Tesselator/RenderManager pipeline. // // Usage: // // void MyScene::render(S32 w, S32 h, C4JRender::eViewportType vp) // { // if (!m_hasTickedOnce) return; // NativeUI::BeginFrame(); // // NativeUI::DrawRect(0, 0, 1280, 720, 0xCC000000u); // NativeUI::DrawShadowText(640, 300, L"Hello", // 0xFFFFFFFFu, 22.0f, ALIGN_CENTER_X); // // NativeUI::EndFrame(); // } // // Coordinate space: 1280 x 720 virtual canvas (resolution-independent). // Color format: 0xAARRGGBB (alpha 0xFF = opaque). // Font size: Height in virtual pixels. Bitmap font is 8 units tall; // system scales to match. Common sizes: 8, 12, 14, 16, 22. namespace NativeUI { // ---- Alignment flags ------------------------------------------ enum : uint32_t { ALIGN_LEFT = 0x00u, ALIGN_RIGHT = 0x01u, ALIGN_CENTER_X = 0x02u, ALIGN_CENTER_Y = 0x04u, ALIGN_BOTTOM = 0x08u, }; // ---- Lifecycle ------------------------------------------------ void BeginFrame(); void EndFrame(); void Shutdown(); // ---- Input helpers (Windows64) ----------------------------------- // Convert window mouse coords to 1280x720 virtual canvas. // Returns false if the window handle is invalid or has zero size. bool GetMouseVirtual(float& outX, float& outY); // ---- Primitives ----------------------------------------------- // Filled axis-aligned rectangle. void DrawRect(float x, float y, float w, float h, uint32_t color); // Fullscreen rectangle that covers the entire backbuffer (ignores 16:9 viewport). // Use for dim overlays, backgrounds, etc. that must reach into pillarbox/letterbox bands. void DrawRectFullscreen(uint32_t color); // Filled rectangle with rounded corners (radius in virtual pixels). void DrawRoundedRect(float x, float y, float w, float h, float radius, uint32_t color); // Rounded border (outline only, no fill). void DrawRoundedBorder(float x, float y, float w, float h, float radius, float thickness, uint32_t color); // Outlined rectangle (border only, no fill). void DrawBorder(float x, float y, float w, float h, float thickness, uint32_t color); // Horizontal line. void DrawLine(float x, float y, float length, float thickness, uint32_t color); // Vertical line. void DrawLineV(float x, float y, float length, float thickness, uint32_t color); // Filled rectangle with gradient (top to bottom). void DrawGradientRect(float x, float y, float w, float h, uint32_t topColor, uint32_t bottomColor); // Rounded rect with gradient (top to bottom). void DrawGradientRoundedRect(float x, float y, float w, float h, float radius, uint32_t topColor, uint32_t bottomColor); // Drop shadow behind a rectangle (semi-transparent, offset). void DrawDropShadow(float x, float y, float w, float h, float offset = 4.0f, float spread = 6.0f, uint32_t color = 0x60000000u); // Panel with rounded corners, drop shadow, and optional border. void DrawPanel(float x, float y, float w, float h, float radius = 8.0f, uint32_t bgColor = 0xF0181818u, uint32_t borderColor = 0xFF333333u, float borderThick = 1.0f, bool shadow = true); // Horizontal divider line with optional fade at edges. void DrawDivider(float x, float y, float w, uint32_t color = 0xFF333333u, float thickness = 1.0f); // ---- Text ----------------------------------------------------- void DrawText(float x, float y, const wchar_t* text, uint32_t color, float size = 14.0f, uint32_t align = ALIGN_LEFT); void DrawShadowText(float x, float y, const wchar_t* text, uint32_t color, float size = 14.0f, uint32_t align = ALIGN_LEFT); float DrawTextWrapped(float x, float y, const wchar_t* text, float maxWidth, uint32_t color, float size = 14.0f, uint32_t align = ALIGN_LEFT); void MeasureText(const wchar_t* text, float size, float* outWidth, float* outHeight); float LineHeight(float size); // ---- Clipping ------------------------------------------------- void PushClipRect(float x, float y, float w, float h); void PopClipRect(); // ---- Widgets -------------------------------------------------- void DrawButton(float x, float y, float w, float h, const wchar_t* label, bool focused, bool hovered = false, float labelSize = 16.0f); // Text input box from gui/gui.png (y=46, 20px tall in atlas). void DrawTextBox(float x, float y, float w, float h, uint32_t tint = 0xFFFFFFFFu); // Clickable link text with underline. Opens URL on activation. void DrawLink(float x, float y, const wchar_t* text, const char* url, bool focused, bool hovered = false, float size = 14.0f, uint32_t align = ALIGN_LEFT, float* outX = nullptr, float* outY = nullptr, float* outW = nullptr, float* outH = nullptr); void DrawProgressBar(float x, float y, float w, float h, float progress, uint32_t fillColor = 0xFF1A71D1u, uint32_t trackColor = 0xFF333333u); void DrawSpinner(float cx, float cy, float radius, int tick, uint32_t color = 0xFFFFFFFFu); void DrawCheckbox(float x, float y, float size, bool checked, bool focused, bool hovered = false); void DrawSlider(float x, float y, float w, float h, float value, bool focused, bool hovered = false, uint32_t fillColor = 0xFF1A71D1u, uint32_t trackColor = 0xFF333333u); void DrawTooltip(float x, float y, const wchar_t* text, float size = 12.0f); // Open a URL in the system default browser (Windows only, no-op elsewhere). void OpenURL(const char* url); // ---- Texture drawing ------------------------------------------ // Load a texture from the game's resource pack (e.g. L"/gui/container.png"). // Returns an internal texture ID for use with Draw calls. // Textures are cached — calling this multiple times with the same path is cheap. int LoadTexture(const wchar_t* path); // Load a pre-registered texture by TEXTURE_NAME enum value. // See Textures.h for the full list (TN_GUI_GUI, TN_TERRAIN, etc.). int LoadTextureByName(int textureName); // Load a PNG file and create a D3D11 texture directly (bypasses RenderManager). // Decodes via WIC, creates DXGI_FORMAT_R8G8B8A8_UNORM texture. // Use this for externally sourced PNGs (e.g. Mojang skins) where the // RenderManager's pixel format assumptions may not match. // Returns texture ID (for use with DrawTexture/DrawTextureUV), or -1 on failure. // Caches by path. Must be called from the main/render thread. int LoadTextureFromFileDirect(const char* filePath, int* outWidth = nullptr, int* outHeight = nullptr); // Load a texture from an arbitrary filesystem path relative to the EXE dir. // e.g. "Common/Media/Graphics/PanelsAndTabs/Panel_MM.png" // Returns texture ID, or -1 on failure. Caches by path. // Also returns texture dimensions via optional out params. int LoadTextureFromFile(const char* filePath, int* outWidth = nullptr, int* outHeight = nullptr); // 9-slice panel: draws a scalable panel from 9 texture pieces. // basePath = folder + prefix, e.g. "Common/Media/Graphics/PanelsAndTabs/Panel" // Auto-detects naming convention: // Convention A: _TL, _TM, _TR, _ML, _MM, _MR, _BL, _BM, _BR // Convention B: _Top_L, _Top_M, _Top_R, _Mid_L, _Mid_M, _Mid_R, _Bot_L, _Bot_M, _Bot_R struct NineSlice { int tl, tm, tr; // texture IDs: top-left, top-mid, top-right int ml, mm, mr; // mid-left, mid-mid, mid-right int bl, bm, br; // bot-left, bot-mid, bot-right int cornerW, cornerH; // corner piece dimensions bool valid; }; // Load a 9-slice panel set from disk. Caches internally. // Supports both naming conventions (auto-detected). NineSlice LoadNineSlice(const char* basePath); // Draw a 9-slice panel scaled to any size. void DrawNineSlice(float x, float y, float w, float h, const NineSlice& ns, uint32_t tint = 0xFFFFFFFFu); // 3-slice horizontal strip (tabs, bars). // basePath e.g. "Common/Media/Graphics/PanelsAndTabs/Tab" // Expects: {basePath}_Left.png, _Middle.png, _Right.png struct ThreeSlice { int left, mid, right; // texture IDs int capW, capH; // left/right cap dimensions bool valid; }; // Load a 3-slice strip from disk. Caches internally. ThreeSlice LoadThreeSlice(const char* basePath); // Draw a 3-slice strip scaled horizontally. void DrawThreeSlice(float x, float y, float w, float h, const ThreeSlice& ts, uint32_t tint = 0xFFFFFFFFu); // Draw a texture filling the given rect. tint multiplies the texture color. // Pass 0xFFFFFFFF for no tint. textureId comes from LoadTexture/LoadTextureByName. void DrawTexture(float x, float y, float w, float h, int textureId, uint32_t tint = 0xFFFFFFFFu); // Draw a sub-region of a texture (UV rect in [0,1] space). void DrawTextureUV(float x, float y, float w, float h, int textureId, float u0, float v0, float u1, float v1, uint32_t tint = 0xFFFFFFFFu); // Draw a texture clipped to rounded corners (uses scissor). void DrawTextureRounded(float x, float y, float w, float h, int textureId, float radius, uint32_t tint = 0xFFFFFFFFu); // Draw a texture scaled to fit (maintaining aspect ratio, centered). // texW/texH = source texture dimensions in pixels. void DrawTextureFit(float x, float y, float w, float h, int textureId, int texW, int texH, uint32_t tint = 0xFFFFFFFFu); // ---- Focus list ----------------------------------------------- class FocusList { public: struct Entry { int id; float x, y, w, h; }; void Clear() { m_entries.clear(); m_hoveredId = -1; } void Add(int id, float x, float y, float w, float h); int GetFocused() const; int GetHovered() const { return m_hoveredId; } bool IsFocused(int id) const { return GetFocused() == id; } bool IsHovered(int id) const { return m_lastDevice == eDevice_Mouse && m_hoveredId == id; } bool IsActive(int id) const { return IsFocused(id) || IsHovered(id); } // For rendering: show highlight based on last-used input device. // Gamepad last → show focus ring on focused element, ignore mouse hover. // Mouse last → show hover highlight, suppress gamepad focus ring. bool ShowFocus(int id) const { if (m_lastDevice == eDevice_Mouse) return m_hoveredId >= 0 && m_hoveredId == id; // Gamepad or no device: show gamepad focus, ignore hover return IsFocused(id); } void MoveNext(); void MovePrev(); void SetFocus(int id); bool HitTest(float mx, float my, int& outId) const; bool UpdateHover(float mx, float my); void ClearHover() { m_hoveredId = -1; } int Count() const { return (int)m_entries.size(); } // Mouse hover — call once per tick from tick(). // Updates hover state, plays hover sound. No click handling. void TickMouse(); // True while the mouse was used for the last interaction. bool IsMouseConsumed() const { return m_mouseConsumed; } // Gamepad/keyboard — standard menu key handling. // Handles UP/DOWN/LEFT/RIGHT (navigation with sound), // OK (returns focused id with press sound), // CANCEL (returns backId with back sound). // // backId = the control id to return when CANCEL is pressed. // // Returns: >=0 = activated element id (OK or CANCEL) // -1 = navigation happened (focus moved, no activation) // -2 = key not handled (scene should set handled=false) static constexpr int RESULT_NAVIGATED = -1; static constexpr int RESULT_UNHANDLED = -2; // panelX/Y/W/H = scene panel bounds. Used to hit-test mouse clicks // when UIController sends ACTION_MENU_OK from a left-click. int HandleMenuKey(int key, int backId = 0, float panelX = 0, float panelY = 0, float panelW = 0, float panelH = 0); // Input device tracking — same concept as Iggy's lastUsedDevice. // When the gamepad navigates, mouse hover is suppressed. // When the mouse moves, gamepad focus ring is suppressed. enum ELastDevice { eDevice_None, eDevice_Gamepad, eDevice_Mouse }; ELastDevice GetLastDevice() const { return m_lastDevice; } private: std::vector m_entries; int m_focusIdx = 0; int m_hoveredId = -1; int m_lastHoveredId = -1; // hover id from previous tick bool m_mouseConsumed = false; // true = click in progress, don't re-fire ELastDevice m_lastDevice = eDevice_None; float m_lastMouseX = -1.0f; float m_lastMouseY = -1.0f; }; } // namespace NativeUI