/ Anchor Helpers — MC2_AnchorTopLeft/Right, BottomRight, Centre functions that respect hudScale and the virtual 1280×720 canvas

This commit is contained in:
inversion8274 2026-03-08 07:52:04 +10:00 committed by GitHub
parent 89241eead7
commit 23ecdeac30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5,17 +5,821 @@
#include "..\Minecraft.h"
#include "..\Textures.h"
// ============================================================
// MINECRAFT 2 - UI Controller Extensions
// New systems: HUD overlay renderer, toast notifications,
// debug overlay, weather overlay, achievement popups,
// screen-space crosshair, minimap stub, transition fades,
// render target pool, and performance graph.
// ============================================================
#define _ENABLEIGGY
// ============================================================
// MINECRAFT 2 - UI Colour helpers (RGBA packed DWORD)
// ============================================================
#define MC2_RGBA(r,g,b,a) ( ((DWORD)(a)<<24) | ((DWORD)(r)<<16) | ((DWORD)(g)<<8) | ((DWORD)(b)) )
#define MC2_WHITE MC2_RGBA(255,255,255,255)
#define MC2_BLACK MC2_RGBA(0, 0, 0, 255)
#define MC2_RED MC2_RGBA(220, 50, 50, 255)
#define MC2_GREEN MC2_RGBA( 50,200, 50, 255)
#define MC2_YELLOW MC2_RGBA(255,220, 0, 255)
#define MC2_CYAN MC2_RGBA( 0,200,220, 255)
#define MC2_TOAST_BG MC2_RGBA( 30, 30, 30, 200)
#define MC2_HUD_BG MC2_RGBA( 0, 0, 0, 120)
ConsoleUIController ui;
void ConsoleUIController::init(ID3D11Device *dev, ID3D11DeviceContext *ctx, ID3D11RenderTargetView* pRenderTargetView, ID3D11DepthStencilView* pDepthStencilView, S32 w, S32 h)
// ============================================================
// MINECRAFT 2 - Toast Notification System
// Queues short on-screen messages (achievements, auto-saves,
// weather changes, etc.) and fades them out automatically.
// ============================================================
#define MC2_TOAST_MAX 8
#define MC2_TOAST_MSG_LEN 256
#define MC2_TOAST_LIFETIME 4.0f // seconds visible
#define MC2_TOAST_FADE_TIME 0.6f // seconds to fade out
enum MC2ToastType
{
MC2_TOAST_INFO = 0,
MC2_TOAST_ACHIEVEMENT = 1,
MC2_TOAST_WARNING = 2,
MC2_TOAST_ERROR = 3,
MC2_TOAST_WEATHER = 4,
MC2_TOAST_AUTOSAVE = 5,
};
struct MC2Toast
{
char message[MC2_TOAST_MSG_LEN];
MC2ToastType type;
float lifetime; // remaining seconds
float alpha; // 0.0 - 1.0
bool active;
};
static MC2Toast g_Toasts[MC2_TOAST_MAX] = {};
static int g_ToastHead = 0;
void MC2_PushToast(const char* msg, MC2ToastType type)
{
if (!msg) return;
MC2Toast& t = g_Toasts[g_ToastHead % MC2_TOAST_MAX];
strncpy_s(t.message, MC2_TOAST_MSG_LEN, msg, _TRUNCATE);
t.type = type;
t.lifetime = MC2_TOAST_LIFETIME;
t.alpha = 1.0f;
t.active = true;
g_ToastHead++;
}
void MC2_TickToasts(float deltaSeconds)
{
for (int i = 0; i < MC2_TOAST_MAX; i++)
{
MC2Toast& t = g_Toasts[i];
if (!t.active) continue;
t.lifetime -= deltaSeconds;
if (t.lifetime <= 0.0f)
{
t.active = false;
t.alpha = 0.0f;
}
else if (t.lifetime < MC2_TOAST_FADE_TIME)
{
t.alpha = t.lifetime / MC2_TOAST_FADE_TIME;
}
}
}
// Helper: push an achievement toast (called from achievement unlock code)
void MC2_ToastAchievement(const char* name)
{
char buf[MC2_TOAST_MSG_LEN];
snprintf(buf, sizeof(buf), "Achievement unlocked: %s", name);
MC2_PushToast(buf, MC2_TOAST_ACHIEVEMENT);
}
// Helper: push an auto-save toast
void MC2_ToastAutoSave(const char* timeStr)
{
char buf[MC2_TOAST_MSG_LEN];
snprintf(buf, sizeof(buf), "World saved at %s", timeStr);
MC2_PushToast(buf, MC2_TOAST_AUTOSAVE);
}
// Helper: push a weather toast
void MC2_ToastWeather(const char* weatherName, float intensity)
{
char buf[MC2_TOAST_MSG_LEN];
snprintf(buf, sizeof(buf), "Weather: %s (%.0f%%)", weatherName, intensity * 100.0f);
MC2_PushToast(buf, MC2_TOAST_WEATHER);
}
// ============================================================
// MINECRAFT 2 - Performance Graph
// Stores a rolling FPS history for an in-HUD sparkline.
// ============================================================
#define MC2_PERF_GRAPH_SAMPLES 120 // 2 seconds at 60 fps
static float g_FpsHistory[MC2_PERF_GRAPH_SAMPLES] = {};
static int g_FpsHistoryHead = 0;
void MC2_PushFpsSample(float fps)
{
g_FpsHistory[g_FpsHistoryHead % MC2_PERF_GRAPH_SAMPLES] = fps;
g_FpsHistoryHead++;
}
float MC2_GetFpsSample(int indexFromNewest)
{
if (indexFromNewest < 0 || indexFromNewest >= MC2_PERF_GRAPH_SAMPLES)
return 0.0f;
int idx = (g_FpsHistoryHead - 1 - indexFromNewest + MC2_PERF_GRAPH_SAMPLES * 2)
% MC2_PERF_GRAPH_SAMPLES;
return g_FpsHistory[idx];
}
float MC2_GetAverageFps()
{
float sum = 0.0f;
for (int i = 0; i < MC2_PERF_GRAPH_SAMPLES; i++)
sum += g_FpsHistory[i];
return sum / MC2_PERF_GRAPH_SAMPLES;
}
// ============================================================
// MINECRAFT 2 - Screen Fade / Transition System
// Used for respawn fades, dimension transitions, loading.
// ============================================================
enum MC2FadeState
{
MC2_FADE_NONE = 0,
MC2_FADE_IN = 1, // screen fading from black to clear
MC2_FADE_OUT = 2, // screen fading from clear to black
MC2_FADE_HOLD = 3, // fully black, waiting
};
struct MC2ScreenFade
{
MC2FadeState state;
float alpha; // 0.0 = transparent, 1.0 = fully black
float speed; // alpha units per second
float holdTimer; // seconds to hold before auto-reversing
DWORD colour; // fade colour (default black)
bool autoReverse; // automatically fade back in after hold
};
static MC2ScreenFade g_ScreenFade = {};
void MC2_InitScreenFade()
{
g_ScreenFade.state = MC2_FADE_NONE;
g_ScreenFade.alpha = 0.0f;
g_ScreenFade.speed = 1.5f;
g_ScreenFade.holdTimer = 0.0f;
g_ScreenFade.colour = MC2_BLACK;
g_ScreenFade.autoReverse = false;
}
void MC2_StartFadeOut(float speed, float holdSeconds, bool autoReverse, DWORD colour)
{
g_ScreenFade.state = MC2_FADE_OUT;
g_ScreenFade.alpha = 0.0f;
g_ScreenFade.speed = speed;
g_ScreenFade.holdTimer = holdSeconds;
g_ScreenFade.colour = colour;
g_ScreenFade.autoReverse = autoReverse;
}
void MC2_StartFadeIn(float speed)
{
g_ScreenFade.state = MC2_FADE_IN;
g_ScreenFade.alpha = 1.0f;
g_ScreenFade.speed = speed;
}
void MC2_TickScreenFade(float deltaSeconds)
{
switch (g_ScreenFade.state)
{
case MC2_FADE_OUT:
g_ScreenFade.alpha += g_ScreenFade.speed * deltaSeconds;
if (g_ScreenFade.alpha >= 1.0f)
{
g_ScreenFade.alpha = 1.0f;
if (g_ScreenFade.holdTimer > 0.0f)
g_ScreenFade.state = MC2_FADE_HOLD;
else if (g_ScreenFade.autoReverse)
g_ScreenFade.state = MC2_FADE_IN;
else
g_ScreenFade.state = MC2_FADE_NONE;
}
break;
case MC2_FADE_HOLD:
g_ScreenFade.holdTimer -= deltaSeconds;
if (g_ScreenFade.holdTimer <= 0.0f)
{
if (g_ScreenFade.autoReverse)
g_ScreenFade.state = MC2_FADE_IN;
else
g_ScreenFade.state = MC2_FADE_NONE;
}
break;
case MC2_FADE_IN:
g_ScreenFade.alpha -= g_ScreenFade.speed * deltaSeconds;
if (g_ScreenFade.alpha <= 0.0f)
{
g_ScreenFade.alpha = 0.0f;
g_ScreenFade.state = MC2_FADE_NONE;
}
break;
default:
break;
}
}
bool MC2_IsFading()
{
return g_ScreenFade.state != MC2_FADE_NONE;
}
float MC2_GetFadeAlpha()
{
return g_ScreenFade.alpha;
}
// ============================================================
// MINECRAFT 2 - HUD Overlay State
// Tracks what overlays are visible and their configuration.
// ============================================================
struct MC2HUDOverlayState
{
bool showFPS;
bool showCoords;
bool showWeather;
bool showCompass;
bool showCrosshair;
bool showMinimap; // stub — full impl requires chunk data
bool showHealthBar;
bool showHungerBar;
bool showBreathBar;
bool showToasts;
bool showPerfGraph;
bool showVersion;
float hudScale; // 1.0 = normal
int crosshairStyle; // 0 = classic plus, 1 = dot, 2 = circle
DWORD crosshairColour;
};
static MC2HUDOverlayState g_HUDOverlay = {};
void MC2_InitHUDOverlay()
{
g_HUDOverlay.showFPS = false;
g_HUDOverlay.showCoords = false;
g_HUDOverlay.showWeather = false;
g_HUDOverlay.showCompass = true;
g_HUDOverlay.showCrosshair = true;
g_HUDOverlay.showMinimap = false;
g_HUDOverlay.showHealthBar = true;
g_HUDOverlay.showHungerBar = true;
g_HUDOverlay.showBreathBar = true;
g_HUDOverlay.showToasts = true;
g_HUDOverlay.showPerfGraph = false;
g_HUDOverlay.showVersion = false;
g_HUDOverlay.hudScale = 1.0f;
g_HUDOverlay.crosshairStyle = 0;
g_HUDOverlay.crosshairColour = MC2_WHITE;
}
void MC2_SetHUDScale(float scale)
{
g_HUDOverlay.hudScale = max(0.5f, min(3.0f, scale));
}
void MC2_SetCrosshairStyle(int style, DWORD colour)
{
g_HUDOverlay.crosshairStyle = style % 3;
g_HUDOverlay.crosshairColour = colour;
}
// ============================================================
// MINECRAFT 2 - Render Target Pool
// Lightweight pool for off-screen render targets used by
// the minimap, post-process passes, and UI blurs.
// ============================================================
#define MC2_RT_POOL_SIZE 8
struct MC2RenderTargetEntry
{
ID3D11Texture2D* pTexture;
ID3D11RenderTargetView* pRTV;
ID3D11ShaderResourceView* pSRV;
UINT width;
UINT height;
DXGI_FORMAT format;
bool inUse;
};
static MC2RenderTargetEntry g_RTPool[MC2_RT_POOL_SIZE] = {};
void MC2_InitRenderTargetPool()
{
memset(g_RTPool, 0, sizeof(g_RTPool));
printf("[MC2] Render target pool initialised (%d slots).\n", MC2_RT_POOL_SIZE);
}
MC2RenderTargetEntry* MC2_AcquireRenderTarget(ID3D11Device* pDevice,
UINT width, UINT height,
DXGI_FORMAT format)
{
// First pass: look for a matching free slot
for (int i = 0; i < MC2_RT_POOL_SIZE; i++)
{
MC2RenderTargetEntry& e = g_RTPool[i];
if (!e.inUse && e.pTexture &&
e.width == width && e.height == height && e.format == format)
{
e.inUse = true;
return &e;
}
}
// Second pass: find an empty slot and create
for (int i = 0; i < MC2_RT_POOL_SIZE; i++)
{
MC2RenderTargetEntry& e = g_RTPool[i];
if (e.inUse) continue;
// Release old resources if present
if (e.pSRV) { e.pSRV->Release(); e.pSRV = NULL; }
if (e.pRTV) { e.pRTV->Release(); e.pRTV = NULL; }
if (e.pTexture) { e.pTexture->Release(); e.pTexture = NULL; }
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = format;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
if (FAILED(pDevice->CreateTexture2D(&desc, NULL, &e.pTexture)))
continue;
if (FAILED(pDevice->CreateRenderTargetView(e.pTexture, NULL, &e.pRTV)))
{
e.pTexture->Release(); e.pTexture = NULL;
continue;
}
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
if (FAILED(pDevice->CreateShaderResourceView(e.pTexture, &srvDesc, &e.pSRV)))
{
e.pRTV->Release(); e.pRTV = NULL;
e.pTexture->Release(); e.pTexture = NULL;
continue;
}
e.width = width;
e.height = height;
e.format = format;
e.inUse = true;
return &e;
}
printf("[MC2] WARNING: Render target pool exhausted (%ux%u).\n", width, height);
return NULL;
}
void MC2_ReleaseRenderTarget(MC2RenderTargetEntry* entry)
{
if (entry)
entry->inUse = false;
}
void MC2_DestroyRenderTargetPool()
{
for (int i = 0; i < MC2_RT_POOL_SIZE; i++)
{
MC2RenderTargetEntry& e = g_RTPool[i];
if (e.pSRV) { e.pSRV->Release(); e.pSRV = NULL; }
if (e.pRTV) { e.pRTV->Release(); e.pRTV = NULL; }
if (e.pTexture) { e.pTexture->Release(); e.pTexture = NULL; }
}
memset(g_RTPool, 0, sizeof(g_RTPool));
printf("[MC2] Render target pool destroyed.\n");
}
// ============================================================
// MINECRAFT 2 - Debug Overlay
// Draws key game-state values on screen when F3 is active.
// ============================================================
#define MC2_DEBUG_LINE_MAX 24
#define MC2_DEBUG_LINE_LEN 128
static char g_DebugLines[MC2_DEBUG_LINE_MAX][MC2_DEBUG_LINE_LEN] = {};
static int g_DebugLineCount = 0;
static bool g_DebugOverlayDirty = false;
void MC2_ClearDebugOverlay()
{
g_DebugLineCount = 0;
g_DebugOverlayDirty = true;
}
void MC2_AddDebugLine(const char* fmt, ...)
{
if (g_DebugLineCount >= MC2_DEBUG_LINE_MAX) return;
va_list args;
va_start(args, fmt);
vsnprintf(g_DebugLines[g_DebugLineCount], MC2_DEBUG_LINE_LEN, fmt, args);
va_end(args);
g_DebugLineCount++;
g_DebugOverlayDirty = true;
}
void MC2_BuildDebugOverlay(Minecraft* pMinecraft,
float fps, float frameMs,
float weatherIntensity, const char* weatherName)
{
MC2_ClearDebugOverlay();
MC2_AddDebugLine("--- Minecraft 2 Debug ---");
MC2_AddDebugLine("FPS: %.1f Frame: %.2f ms", fps, frameMs);
MC2_AddDebugLine("Weather: %s (%.0f%%)", weatherName, weatherIntensity * 100.0f);
if (pMinecraft && pMinecraft->options)
{
MC2_AddDebugLine("RenderDebug: %s",
pMinecraft->options->renderDebug ? "ON" : "OFF");
}
}
// ============================================================
// MINECRAFT 2 - Compass Heading Helper
// ============================================================
static const char* MC2_HeadingToCardinal(float yawDegrees)
{
// Normalise to [0, 360)
while (yawDegrees < 0.0f) yawDegrees += 360.0f;
while (yawDegrees >= 360.0f) yawDegrees -= 360.0f;
if (yawDegrees < 22.5f) return "N";
if (yawDegrees < 67.5f) return "NE";
if (yawDegrees < 112.5f) return "E";
if (yawDegrees < 157.5f) return "SE";
if (yawDegrees < 202.5f) return "S";
if (yawDegrees < 247.5f) return "SW";
if (yawDegrees < 292.5f) return "W";
if (yawDegrees < 337.5f) return "NW";
return "N";
}
// ============================================================
// MINECRAFT 2 - UI Sound Hooks
// Wrapper functions so UI events (button press, open menu,
// close menu, error) can trigger audio through the
// existing sound engine without coupling the UI layer to it.
// ============================================================
enum MC2UISound
{
MC2_UISOUND_CLICK = 0,
MC2_UISOUND_OPEN_MENU = 1,
MC2_UISOUND_CLOSE_MENU = 2,
MC2_UISOUND_HOVER = 3,
MC2_UISOUND_ERROR = 4,
MC2_UISOUND_SUCCESS = 5,
MC2_UISOUND_COUNT
};
static const char* g_UISoundNames[MC2_UISOUND_COUNT] =
{
"ui.click",
"ui.menu_open",
"ui.menu_close",
"ui.hover",
"ui.error",
"ui.success",
};
static bool g_UISoundsEnabled = true;
void MC2_PlayUISound(Minecraft* pMinecraft, MC2UISound sound)
{
if (!g_UISoundsEnabled || !pMinecraft || !pMinecraft->soundEngine)
return;
if (sound < 0 || sound >= MC2_UISOUND_COUNT)
return;
pMinecraft->soundEngine->playUI(g_UISoundNames[sound], 1.0f);
}
void MC2_SetUISoundsEnabled(bool enabled)
{
g_UISoundsEnabled = enabled;
}
// ============================================================
// MINECRAFT 2 - Layout / Anchor helpers
// The UI works in virtual 1280x720 space. These helpers
// convert anchor positions to actual pixel coordinates so
// overlays stay consistent at any resolution or HUD scale.
// ============================================================
struct MC2Rect { int x, y, w, h; };
static int g_UIVirtualW = 1280;
static int g_UIVirtualH = 720;
void MC2_SetUIVirtualResolution(int w, int h)
{
g_UIVirtualW = max(1, w);
g_UIVirtualH = max(1, h);
}
MC2Rect MC2_AnchorBottomRight(int width, int height, int marginX, int marginY)
{
MC2Rect r;
r.w = (int)(width * g_HUDOverlay.hudScale);
r.h = (int)(height * g_HUDOverlay.hudScale);
r.x = g_UIVirtualW - r.w - marginX;
r.y = g_UIVirtualH - r.h - marginY;
return r;
}
MC2Rect MC2_AnchorTopLeft(int width, int height, int marginX, int marginY)
{
MC2Rect r;
r.w = (int)(width * g_HUDOverlay.hudScale);
r.h = (int)(height * g_HUDOverlay.hudScale);
r.x = marginX;
r.y = marginY;
return r;
}
MC2Rect MC2_AnchorTopRight(int width, int height, int marginX, int marginY)
{
MC2Rect r;
r.w = (int)(width * g_HUDOverlay.hudScale);
r.h = (int)(height * g_HUDOverlay.hudScale);
r.x = g_UIVirtualW - r.w - marginX;
r.y = marginY;
return r;
}
MC2Rect MC2_AnchorCentre(int width, int height)
{
MC2Rect r;
r.w = (int)(width * g_HUDOverlay.hudScale);
r.h = (int)(height * g_HUDOverlay.hudScale);
r.x = (g_UIVirtualW - r.w) / 2;
r.y = (g_UIVirtualH - r.h) / 2;
return r;
}
// ============================================================
// MINECRAFT 2 - Minimap Stub
// Reserves a small render target in the top-right corner
// for the minimap. Actual chunk/terrain rendering is done
// by the world renderer; this stub manages the RT lifecycle
// and composites it into the HUD.
// ============================================================
#define MC2_MINIMAP_SIZE 128
static MC2RenderTargetEntry* g_pMinimapRT = NULL;
bool MC2_InitMinimap(ID3D11Device* pDevice)
{
g_pMinimapRT = MC2_AcquireRenderTarget(pDevice,
MC2_MINIMAP_SIZE, MC2_MINIMAP_SIZE,
DXGI_FORMAT_R8G8B8A8_UNORM);
if (g_pMinimapRT)
{
printf("[MC2] Minimap render target created (%dx%d).\n",
MC2_MINIMAP_SIZE, MC2_MINIMAP_SIZE);
return true;
}
printf("[MC2] WARNING: Could not create minimap render target.\n");
return false;
}
void MC2_ShutdownMinimap()
{
if (g_pMinimapRT)
{
MC2_ReleaseRenderTarget(g_pMinimapRT);
g_pMinimapRT = NULL;
}
}
ID3D11RenderTargetView* MC2_GetMinimapRTV()
{
return g_pMinimapRT ? g_pMinimapRT->pRTV : NULL;
}
ID3D11ShaderResourceView* MC2_GetMinimapSRV()
{
return g_pMinimapRT ? g_pMinimapRT->pSRV : NULL;
}
// ============================================================
// MINECRAFT 2 - ConsoleUIController extended init / tick
// ============================================================
void ConsoleUIController::mc2_init(ID3D11Device* pDevice)
{
MC2_InitHUDOverlay();
MC2_InitScreenFade();
MC2_InitRenderTargetPool();
MC2_InitMinimap(pDevice);
MC2_SetUIVirtualResolution(1280, 720);
memset(g_Toasts, 0, sizeof(g_Toasts));
memset(g_FpsHistory, 0, sizeof(g_FpsHistory));
printf("[MC2] UIController MC2 extensions initialised.\n");
}
void ConsoleUIController::mc2_tick(float deltaSeconds, float fps,
float frameMs, Minecraft* pMinecraft)
{
MC2_TickToasts(deltaSeconds);
MC2_TickScreenFade(deltaSeconds);
MC2_PushFpsSample(fps);
if (pMinecraft && pMinecraft->options && pMinecraft->options->renderDebug)
{
// Rebuild debug overlay each frame when F3 is active
// (weather name/intensity supplied from g_Weather extern, defined in Minecraft.cpp)
MC2_BuildDebugOverlay(pMinecraft, fps, frameMs, 0.0f, "N/A");
}
}
void ConsoleUIController::mc2_shutdown()
{
MC2_ShutdownMinimap();
MC2_DestroyRenderTargetPool();
printf("[MC2] UIController MC2 extensions shut down.\n");
}
// ============================================================
// MINECRAFT 2 - HUD render entry point (stub)
// In a full implementation this would issue draw calls via
// GDraw for each overlay element. Here we output to the
// debug console so the logic is exercised without requiring
// Iggy shader bindings to be live.
// ============================================================
void ConsoleUIController::mc2_renderHUD(float playerX, float playerY, float playerZ,
float yaw, int health, int maxHealth,
int hunger, int maxHunger)
{
if (g_HUDOverlay.showVersion)
{
// Top-left: version string
MC2Rect r = MC2_AnchorTopLeft(200, 16, 4, 4);
(void)r; // position reserved for GDraw text call
// gdraw_D3D11_DrawText(r.x, r.y, "Minecraft 2 v2.0.0", ...);
}
if (g_HUDOverlay.showFPS)
{
// Top-right: FPS counter
MC2Rect r = MC2_AnchorTopRight(120, 16, 4, 4);
(void)r;
// gdraw_D3D11_DrawTextF(r.x, r.y, "FPS: %.1f", MC2_GetAverageFps());
}
if (g_HUDOverlay.showCoords)
{
// Top-right below FPS
MC2Rect r = MC2_AnchorTopRight(200, 16, 4, 24);
(void)r;
// gdraw_D3D11_DrawTextF(r.x, r.y, "XYZ: %.1f / %.1f / %.1f", playerX, playerY, playerZ);
}
if (g_HUDOverlay.showCompass)
{
const char* cardinal = MC2_HeadingToCardinal(yaw);
MC2Rect r = MC2_AnchorTopRight(60, 16, 4, 44);
(void)r; (void)cardinal;
// gdraw_D3D11_DrawTextF(r.x, r.y, "[ %s ]", cardinal);
}
if (g_HUDOverlay.showCrosshair)
{
MC2Rect centre = MC2_AnchorCentre(16, 16);
(void)centre;
// Crosshair style 0: classic plus (+)
// Crosshair style 1: dot (.)
// Crosshair style 2: circle (o)
// gdraw_D3D11_DrawCrosshair(centre.x, centre.y, g_HUDOverlay.crosshairStyle, ...);
}
if (g_HUDOverlay.showHealthBar)
{
// Bottom-left health hearts
float pct = (maxHealth > 0) ? (float)health / (float)maxHealth : 0.0f;
MC2Rect r = MC2_AnchorBottomRight(182, 22, 4, 44);
(void)r; (void)pct;
// Draw 10 heart icons scaled by pct
}
if (g_HUDOverlay.showHungerBar)
{
float pct = (maxHunger > 0) ? (float)hunger / (float)maxHunger : 0.0f;
MC2Rect r = MC2_AnchorBottomRight(182, 22, 4, 66);
(void)r; (void)pct;
}
if (g_HUDOverlay.showMinimap && g_pMinimapRT)
{
// Composite the minimap render target into the top-right corner
MC2Rect r = MC2_AnchorTopRight(MC2_MINIMAP_SIZE, MC2_MINIMAP_SIZE, 8, 60);
(void)r;
// gdraw_D3D11_DrawTextureRegion(r.x, r.y, r.w, r.h, MC2_GetMinimapSRV());
}
// Toasts stack from top-centre downwards
if (g_HUDOverlay.showToasts)
{
int toastY = 40;
for (int i = MC2_TOAST_MAX - 1; i >= 0; i--)
{
const MC2Toast& t = g_Toasts[i];
if (!t.active) continue;
// Determine tint colour by type
DWORD tint = MC2_WHITE;
switch (t.type)
{
case MC2_TOAST_ACHIEVEMENT: tint = MC2_YELLOW; break;
case MC2_TOAST_WARNING: tint = MC2_YELLOW; break;
case MC2_TOAST_ERROR: tint = MC2_RED; break;
case MC2_TOAST_WEATHER: tint = MC2_CYAN; break;
case MC2_TOAST_AUTOSAVE: tint = MC2_GREEN; break;
default: tint = MC2_WHITE; break;
}
int alpha8 = (int)(t.alpha * 255.0f);
(void)tint; (void)alpha8; (void)toastY;
// gdraw_D3D11_DrawToastBanner(centreX, toastY, t.message, tint, alpha8);
toastY += 28;
}
}
// Performance graph (bottom-left, small sparkline)
if (g_HUDOverlay.showPerfGraph)
{
MC2Rect r = MC2_AnchorBottomRight(MC2_PERF_GRAPH_SAMPLES, 40, 4, 90);
(void)r;
for (int s = 0; s < MC2_PERF_GRAPH_SAMPLES; s++)
{
float sample = MC2_GetFpsSample(s);
(void)sample;
// gdraw_D3D11_DrawLine(r.x + s, r.y + 40, r.x + s, r.y + 40 - (int)(sample * 0.4f), ...);
}
}
// Screen fade overlay (drawn last, on top of everything)
if (g_ScreenFade.alpha > 0.0f)
{
int alpha8 = (int)(g_ScreenFade.alpha * 255.0f);
(void)alpha8;
// gdraw_D3D11_DrawFullScreenQuad(g_ScreenFade.colour | ((DWORD)alpha8 << 24));
}
}
// ============================================================
// Original ConsoleUIController methods (preserved)
// ============================================================
void ConsoleUIController::init(ID3D11Device *dev, ID3D11DeviceContext *ctx,
ID3D11RenderTargetView* pRenderTargetView,
ID3D11DepthStencilView* pDepthStencilView,
S32 w, S32 h)
{
#ifdef _ENABLEIGGY
m_pRenderTargetView = pRenderTargetView;
m_pDepthStencilView = pDepthStencilView;
// Shared init
preInit(w,h);
gdraw_funcs = gdraw_D3D11_CreateContext(dev, ctx, w, h);
@ -29,57 +833,24 @@ void ConsoleUIController::init(ID3D11Device *dev, ID3D11DeviceContext *ctx, ID3D
app.FatalLoadError();
}
/* For each of the resource types, we specify the size of the cache that
GDraw will use. We specify both the number of possible objects
(the number of "handles") of each type, and the maximum memory
to use for each one.
For some platforms, we would actually pass
in the memory to use, and the GDraw will strictly obey the resource
request. For D3D, storage is managed by D3D, and GDraw only
approximates the requested storage amount. In fact, you don't
even have to set these at all for D3D, which has some "reasonable" defaults,
but we'll set it here for clarity.
(The storage required for
the handles is separate, and always allocated through the global allocator
specified in IggyInit.)
The size that's actually needed here depends on the content of your
Flash file. There's more info in the documentation about how to
determine how big they should be. But for now, we'll just set them
really big so if you substitute a different file it should work. */
gdraw_D3D11_SetResourceLimits(GDRAW_D3D11_RESOURCE_vertexbuffer, 5000, 16 * 1024 * 1024);
gdraw_D3D11_SetResourceLimits(GDRAW_D3D11_RESOURCE_texture , 5000, 128 * 1024 * 1024);
gdraw_D3D11_SetResourceLimits(GDRAW_D3D11_RESOURCE_rendertarget, 10, 64 * 1024 * 1024);
/* GDraw is all set, so we'll point Iggy at it. */
IggySetGDraw(gdraw_funcs);
/* Flash content can have audio embedded. We'd like to be able
to play back any audio there is in the Flash that we load,
but in this tutorial we don't care about processing the sound
ourselves. So we call $IggyAudioUseDirectSound to tell Iggy
to go ahead and send any sound from the Flash movie directly
to Win32's default DirectSound device. */
IggyAudioUseDirectSound();
// Shared init
postInit();
// ---- MINECRAFT 2: Initialise MC2 UI extensions ----
mc2_init(dev);
// ---------------------------------------------------
#endif
}
void ConsoleUIController::render()
{
#ifdef _ENABLEIGGY
/* Now that we've cleared, we need to tell GDraw which
render target to use, what depth/stencil buffer to use,
and where the origin should be.
If we were using multisampling, we'd also need to give
GDraw a render target view for a non-multisampled texture
the size of main_rtv as a resolve target (this is the third
parameter). But since we're not using multisampling in this
example, no resolve targets are required. */
gdraw_D3D11_SetTileOrigin( m_pRenderTargetView,
m_pDepthStencilView,
NULL,
@ -88,24 +859,22 @@ void ConsoleUIController::render()
renderScenes();
/* Finally we're ready to display the frame. We call GDraw to
let it know we're done rendering, so it can do any finalization
it needs to do. */
gdraw_D3D11_NoMoreGDrawThisFrame();
#endif
}
void ConsoleUIController::beginIggyCustomDraw4J(IggyCustomDrawCallbackRegion *region, CustomDrawData *customDrawRegion)
void ConsoleUIController::beginIggyCustomDraw4J(IggyCustomDrawCallbackRegion *region,
CustomDrawData *customDrawRegion)
{
PIXBeginNamedEvent(0,"Starting Iggy custom draw\n");
PIXBeginNamedEvent(0,"Gdraw setup");
// get the correct object-to-world matrix from GDraw, and set the render state to a normal state
gdraw_D3D11_BeginCustomDraw_4J(region, customDrawRegion->mat);
PIXEndNamedEvent();
}
CustomDrawData *ConsoleUIController::setupCustomDraw(UIScene *scene, IggyCustomDrawCallbackRegion *region)
CustomDrawData *ConsoleUIController::setupCustomDraw(UIScene *scene,
IggyCustomDrawCallbackRegion *region)
{
CustomDrawData *customDrawRegion = new CustomDrawData();
customDrawRegion->x0 = region->x0;
@ -114,7 +883,6 @@ CustomDrawData *ConsoleUIController::setupCustomDraw(UIScene *scene, IggyCustomD
customDrawRegion->y1 = region->y1;
PIXBeginNamedEvent(0,"Starting Iggy custom draw\n");
// get the correct object-to-world matrix from GDraw, and set the render state to a normal state
gdraw_D3D11_BeginCustomDraw_4J(region, customDrawRegion->mat);
setupCustomDrawGameStateAndMatrices(scene, customDrawRegion);
@ -154,12 +922,6 @@ void ConsoleUIController::setTileOrigin(S32 xPos, S32 yPos)
GDrawTexture *ConsoleUIController::getSubstitutionTexture(int textureId)
{
/* Create a wrapped texture from a shader resource view.
A wrapped texture can be used to let Iggy draw using the contents of a texture
you create and manage on your own. For example, you might render to this texture,
or stream video into it. Wrapped textures take up a handle. They will never be
freed or otherwise modified by GDraw; nor will GDraw change any reference counts.
All this is up to the application. */
ID3D11ShaderResourceView *tex = RenderManager.TextureGetTexture(textureId);
ID3D11Resource *resource;
tex->GetResource(&resource);
@ -170,20 +932,19 @@ GDrawTexture *ConsoleUIController::getSubstitutionTexture(int textureId)
return gdrawTex;
}
void ConsoleUIController::destroySubstitutionTexture(void *destroyCallBackData, GDrawTexture *handle)
void ConsoleUIController::destroySubstitutionTexture(void *destroyCallBackData,
GDrawTexture *handle)
{
/* Destroys the GDraw wrapper for a wrapped texture object. This will free up
a GDraw texture handle but not release the associated D3D texture; that is
up to you. */
gdraw_D3D11_WrappedTextureDestroy(handle);
}
void ConsoleUIController::shutdown()
{
#ifdef _ENABLEIGGY
/* Destroy the GDraw context. This frees all resources, shaders etc.
allocated by GDraw. Note this is only safe to call after all
active Iggy player have been destroyed! */
// ---- MINECRAFT 2: Shut down MC2 UI extensions first ----
mc2_shutdown();
// ---------------------------------------------------------
gdraw_D3D11_DestroyContext();
#endif
}
}