XMB PS3 TO PC
ENG VERSION
I recreated the iconic PS3 animation system using linear interpolation (Lerp) to handle transitions between icons. This ensures that the movement feels smooth and responsive, just like the original XMB.
float dist = (float)i - m_CatAnim;
float absDist = fabsf(dist);
if (absDist < 0.5f) {
scale = lerp(SCALE_SELECTED, SCALE_ADJACENT, absDist * 2.0f);
alpha = lerp(ALPHA_SELECTED, ALPHA_ADJACENT, absDist * 2.0f);
} else {
scale = lerp(SCALE_ADJACENT, SCALE_FAR, absDist - 0.5f);
alpha = lerp(ALPHA_ADJACENT, ALPHA_FAR, absDist - 0.5f);
}
The video pipeline is managed through Windows Media Foundation, which is mapped directly onto DirectX 11 textures. By mapping GPU memory to update video frames in real-time, the system can render MP4 files as high-performance animated backgrounds.
D3D11_MAPPED_SUBRESOURCE mapped = {};
if (SUCCEEDED(m_Ctx->Map(m_Texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped))) {
UINT srcPitch = m_VideoWidth * 4;
for (UINT row = 0; row < m_VideoHeight; row++) {
// Copia riga per riga invertendo l'asse Y se necessario
memcpy(
(BYTE*)mapped.pData + row * mapped.RowPitch,
data + (m_VideoHeight - 1 - row) * srcPitch,
srcPitch
);
}
m_Ctx->Unmap(m_Texture, 0);
}
I implemented a data-driven architecture using tinyxml2 for dynamic content management. This allows the system to inject new nodes into the XML layout at runtime, permanently saving the executable paths and icon locations added by the user.
tinyxml2::XMLElement* newItem = doc.NewElement("Item");
newItem->SetAttribute("name", WStringToString(game.Name).c_str());
newItem->SetAttribute("icon", WStringToString(game.ThumbnailPath).c_str());
newItem->SetAttribute("exe", WStringToString(game.ExecPath).c_str());
// Inserisce il nuovo gioco nel layout mantenendo l'ordine delle categorie
if (ps3Item) {
gameCat->InsertAfterChild(ps3Item, newItem);
} else {
gameCat->InsertEndChild(newItem);
}
doc.SaveFile("xml/menu_layout.xml", false);
The rendering core manages the entire frame lifecycle and shader communication. By constantly updating Constant Buffers, the system synchronizes global data such as time and alpha blending to handle all visual effects.
void Renderer::Render(float time) {
float clearColor[4] = { 0.02f, 0.02f, 0.1f, 1.0f };
m_DeviceContext->ClearRenderTargetView(m_RenderTargetView, clearColor);
ConstantBufferData cb;
cb.Time = time;
m_DeviceContext->UpdateSubresource(m_ConstantBuffer, 0, NULL, &cb, 0, 0);
m_DeviceContext->PSSetShader(m_PSVideo, NULL, 0);
m_DeviceContext->Draw(4, 0);
}
~Foxy
ITA VERSION:
Ho provato a ricreare un sistema uguale a quello usato sulla PS3 per le animazioni tra una icona e l’altra usando interpolazione lineare (Lerp).
float dist = (float)i - m_CatAnim;
float absDist = fabsf(dist);
if (absDist < 0.5f) {
scale = lerp(SCALE_SELECTED, SCALE_ADJACENT, absDist * 2.0f);
alpha = lerp(ALPHA_SELECTED, ALPHA_ADJACENT, absDist * 2.0f);
} else {
scale = lerp(SCALE_ADJACENT, SCALE_FAR, absDist - 0.5f);
alpha = lerp(ALPHA_ADJACENT, ALPHA_FAR, absDist - 0.5f);
}
Qui per la gestione della pipeline video ho usato Windows Media Foundation che mappata direttamente su texture DirectX 11. Il mapping della memoria GPU per aggiornare i frame video in tempo reale, permettendo di utilizzare video MP4 come sfondo animato.
D3D11_MAPPED_SUBRESOURCE mapped = {};
if (SUCCEEDED(m_Ctx->Map(m_Texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped))) {
UINT srcPitch = m_VideoWidth * 4;
for (UINT row = 0; row < m_VideoHeight; row++) {
// Copia riga per riga invertendo l'asse Y se necessario
memcpy(
(BYTE*)mapped.pData + row * mapped.RowPitch,
data + (m_VideoHeight - 1 - row) * srcPitch,
srcPitch
);
}
m_Ctx->Unmap(m_Texture, 0);
}
Ho usato architettura data-driven basata su tinyxml2 per la gestione dinamica dei contenuti. Il suo sistema permette di iniettare nuovi nodi nel layout XML a runtime, salvando permanentemente i percorsi degli eseguibili e delle icone aggiunti dall’utente.
tinyxml2::XMLElement* newItem = doc.NewElement("Item");
newItem->SetAttribute("name", WStringToString(game.Name).c_str());
newItem->SetAttribute("icon", WStringToString(game.ThumbnailPath).c_str());
newItem->SetAttribute("exe", WStringToString(game.ExecPath).c_str());
// Inserisce il nuovo gioco nel layout mantenendo l'ordine delle categorie
if (ps3Item) {
gameCat->InsertAfterChild(ps3Item, newItem);
} else {
gameCat->InsertEndChild(newItem);
}
doc.SaveFile("xml/menu_layout.xml", false);
Il core del sistema di rendering, che gestisce il ciclo di vita del frame e la comunicazione con gli shader. Attraverso l’aggiornamento dei Constant Buffer, il sistema sincronizza dati come il tempo e l’alpha blending per gestire gli effetti visivi globali.
void Renderer::Render(float time) {
float clearColor[4] = { 0.02f, 0.02f, 0.1f, 1.0f };
m_DeviceContext->ClearRenderTargetView(m_RenderTargetView, clearColor);
ConstantBufferData cb;
cb.Time = time;
m_DeviceContext->UpdateSubresource(m_ConstantBuffer, 0, NULL, &cb, 0, 0);
m_DeviceContext->PSSetShader(m_PSVideo, NULL, 0);
m_DeviceContext->Draw(4, 0);
}
~Foxy