namespace AcDream.App.UI; /// /// Retail cursor metadata used outside ordinary LayoutDesc widget-state lookup. /// Global cursors resolve through enum table 6; synthetic retained-window control /// regions use the exact direct cursor media authored on retail Dragbar/Resizebar /// elements. /// internal static class RetailCursorCatalog { public const uint CursorEnumTable = 6; // Complete reachable ClientUISystem::UpdateCursorState (0x00564630) // catalog. Enum values 0x07..0x09 exist in the DAT but are not selected by // this method, so no semantics are invented for them here. public static bool TryGetGlobalCursor(RetailGlobalCursorKind kind, out RetailCursorSpec spec) { spec = kind switch { RetailGlobalCursorKind.Default => new RetailCursorSpec(0x01u, 0, 0), RetailGlobalCursorKind.DefaultFound => new RetailCursorSpec(0x02u, 0, 0), RetailGlobalCursorKind.MeleeOrMissile => new RetailCursorSpec(0x03u, 0, 0), RetailGlobalCursorKind.MeleeOrMissileFound => new RetailCursorSpec(0x04u, 0, 0), RetailGlobalCursorKind.Magic => new RetailCursorSpec(0x05u, 0, 0), RetailGlobalCursorKind.MagicFound => new RetailCursorSpec(0x06u, 0, 0), RetailGlobalCursorKind.Examine => new RetailCursorSpec(0x0Au, 0, 0), RetailGlobalCursorKind.ExamineFound => new RetailCursorSpec(0x0Bu, 0, 0), RetailGlobalCursorKind.Use => new RetailCursorSpec(0x0Cu, 14, 14), RetailGlobalCursorKind.UseFound => new RetailCursorSpec(0x0Du, 14, 14), RetailGlobalCursorKind.Busy => new RetailCursorSpec(0x0Eu, 0, 0), RetailGlobalCursorKind.BusyFound => new RetailCursorSpec(0x0Fu, 0, 0), RetailGlobalCursorKind.TargetPending => new RetailCursorSpec(0x27u, 14, 14), RetailGlobalCursorKind.TargetValid => new RetailCursorSpec(0x28u, 14, 14), RetailGlobalCursorKind.TargetInvalid => new RetailCursorSpec(0x29u, 14, 14), _ => default, }; return spec.IsValid; } /// /// Direct MD_Data_Cursor surfaces authored on retail Type-2 Dragbar and /// Type-9 Resizebar controls. The retained wrapper border has no LayoutDesc /// element of its own, so it uses the same media through this shared seam. /// public static bool TryGetWindowControlCursor( CursorFeedbackKind kind, out UiCursorMedia cursor) { // MediaMachine::Update_Cursor @ 0x00465A80 installs these element-local // cursor DIDs; UIElementManager::CheckCursor @ 0x0045ABF0 preserves the // captured Dragbar/Resizebar cursor for the complete operation. cursor = kind switch { CursorFeedbackKind.WindowMove => new UiCursorMedia(0x06006119u, 16, 16), CursorFeedbackKind.ResizeHorizontal => new UiCursorMedia(0x06006128u, 16, 16), CursorFeedbackKind.ResizeVertical => new UiCursorMedia(0x06005E66u, 16, 16), CursorFeedbackKind.ResizeDiagonalNwse => new UiCursorMedia(0x06006126u, 16, 16), CursorFeedbackKind.ResizeDiagonalNesw => new UiCursorMedia(0x06006127u, 16, 16), _ => default, }; return cursor.IsValid; } } internal readonly record struct RetailCursorSpec(uint EnumId, int HotspotX, int HotspotY) { public bool IsValid => EnumId != 0; }