Add hover sync and CO hover component

Add a hover system to restore :hover-like behavior for custom UI elements in the CommonwealthOnline view. Changes include:

- plugin/src/F4TPrismaUI.cpp: add SyncBrowserHover() which reads the native cursor position, converts it to client coordinates, and invokes a JS update on the server browser view; register a periodic task to call SyncBrowserHover every other tick.
- ui/views/CommonwealthOnline/browser/components/hover.js: new component that tracks pointer position, determines hovered targets using a selector list, and applies/removes a .hovered class; exposes bind(), updateFromPoint(), and clear().
- ui/views/CommonwealthOnline/browser/app.js & index.html: include and bind the new hover component during UI initialization.
- ui/views/CommonwealthOnline/browser/styles.css: add .hovered variants and transitions for nav items, buttons, rows, and filter controls to match hover visuals.
- steam_interfaces.txt: add a list of Steam interface version strings (new file).

Purpose: ensure custom buttons/rows that don't receive native :hover updates from the renderer get visible hover feedback by syncing the native cursor into the web UI and toggling a .hovered class.
This commit is contained in:
2026-06-16 15:55:32 +12:00
parent 7ab3f080f7
commit 31406a1275
6 changed files with 206 additions and 5 deletions
+33
View File
@@ -76,6 +76,31 @@ namespace F4T::PrismaUI
g_cursorRestoreFramesLeft = 4;
}
void SyncBrowserHover()
{
if (!g_visible || !g_domReady || !g_api || !g_api->IsValid(g_serverBrowserView)) {
return;
}
const auto* renderWindow = RE::BSGraphics::GetCurrentRendererWindow();
if (!renderWindow || !renderWindow->hwnd) {
return;
}
POINT cursor{};
if (!::GetCursorPos(&cursor)) {
return;
}
::ScreenToClient(reinterpret_cast<HWND>(renderWindow->hwnd), &cursor);
const auto script = std::format(
"if(window.CO_Hover&&window.CO_Hover.updateFromPoint){{window.CO_Hover.updateFromPoint({},{});}}",
cursor.x,
cursor.y);
g_api->Invoke(g_serverBrowserView, script.c_str());
}
void HideServerBrowserInternal()
{
const bool wasVisible = g_visible;
@@ -283,6 +308,14 @@ namespace F4T::PrismaUI
taskInterface->AddTaskPermanent(WatchMainMenuState);
g_menuWatchTaskStarted = true;
}
taskInterface->AddTaskPermanent([]() {
static std::uint32_t hoverSyncCounter = 0;
if (++hoverSyncCounter % 2 != 0) {
return;
}
SyncBrowserHover();
});
}
}