commonlibsse_ng\re\i/
IMenu.rs

1use crate::re::GPtr::GPtr;
2use crate::re::UIMessage::UIMessage;
3use crate::re::UserEvents::INPUT_CONTEXT_ID;
4use crate::re::offsets_rtti::RTTI_IMenu;
5use crate::re::offsets_vtable::VTABLE_IMenu;
6use crate::re::{CallbackProcessor, FxDelegate, GFxMovieView};
7use crate::rel::id::VariantID;
8use core::ffi::c_void;
9
10#[repr(C)]
11#[derive(Debug)]
12pub struct IMenu {
13    // NOTE: extract FxDelegateHandler size 0x10
14    pub vtable: *const IMenuVtbl,                // 0x00
15    pub refCount: core::sync::atomic::AtomicU32, // 0x04
16    pad0C: u16,                                  // 0x08
17
18    pub uiMovie: GPtr<GFxMovieView>,    // 0x10
19    pub depthPriority: i8,              // 0x18
20    pad19: u8,                          // 0x19
21    pad20: u16,                         // 0x1A
22    pub menuFlags: UI_MENU_FLAGS,       // 0x1C
23    pub inputContext: INPUT_CONTEXT_ID, // 0x20
24    pad24: u32,                         // 0x24
25    pub fxDelegate: GPtr<FxDelegate>,   // 0x28
26}
27const _: () = assert!(core::mem::size_of::<IMenu>() == 0x30);
28
29impl IMenu {
30    /// Address & Offset of the runtime type information (RTTI) identifier.
31    pub const RTTI: VariantID = RTTI_IMenu;
32
33    /// Address & Offset of the virtual function table.
34    pub const VTABLE: [VariantID; 1] = VTABLE_IMenu;
35
36    /// Returns `true` if the menu advances while the pause menu is active.
37    #[inline]
38    pub const fn advances_under_pause_menu(&self) -> bool {
39        self.menuFlags.contains(UI_MENU_FLAGS::AdvancesUnderPauseMenu)
40    }
41
42    /// Returns `true` if the menu allows saving the game.
43    #[inline]
44    pub const fn allow_saving(&self) -> bool {
45        self.menuFlags.contains(UI_MENU_FLAGS::AllowSaving)
46    }
47
48    /// Returns `true` if the menu is always open.
49    #[inline]
50    pub const fn always_open(&self) -> bool {
51        self.menuFlags.contains(UI_MENU_FLAGS::AlwaysOpen)
52    }
53
54    /// Returns `true` if this is an application-level menu.
55    #[inline]
56    pub const fn application_menu(&self) -> bool {
57        self.menuFlags.contains(UI_MENU_FLAGS::ApplicationMenu)
58    }
59
60    /// Returns `true` if the cursor is assigned to the renderer.
61    #[inline]
62    pub const fn assign_cursor_to_renderer(&self) -> bool {
63        self.menuFlags.contains(UI_MENU_FLAGS::AssignCursorToRenderer)
64    }
65
66    /// Returns `true` if the menu uses custom rendering.
67    #[inline]
68    pub const fn custom_rendering(&self) -> bool {
69        self.menuFlags.contains(UI_MENU_FLAGS::CustomRendering)
70    }
71
72    /// Returns `true` if the companion app is allowed to access this menu.
73    #[inline]
74    pub const fn companion_app_allowed(&self) -> bool {
75        self.menuFlags.contains(UI_MENU_FLAGS::CompanionAppAllowed)
76    }
77
78    /// Returns `true` if the pause menu should be disabled.
79    #[inline]
80    pub const fn disable_pause_menu(&self) -> bool {
81        self.menuFlags.contains(UI_MENU_FLAGS::DisablePauseMenu)
82    }
83
84    /// Returns `true` if the cursor should remain visible when this menu is topmost.
85    #[inline]
86    pub const fn dont_hide_cursor_when_topmost(&self) -> bool {
87        self.menuFlags.contains(UI_MENU_FLAGS::DontHideCursorWhenTopmost)
88    }
89
90    /// Returns `true` if the background is frozen while the menu is active.
91    #[inline]
92    pub const fn freeze_frame_background(&self) -> bool {
93        self.menuFlags.contains(UI_MENU_FLAGS::FreezeFrameBackground)
94    }
95
96    /// Returns `true` if the menu causes a freeze frame pause.
97    #[inline]
98    pub const fn freeze_frame_pause(&self) -> bool {
99        self.menuFlags.contains(UI_MENU_FLAGS::FreezeFramePause)
100    }
101
102    /// Returns `true` if the menu includes a button bar.
103    #[inline]
104    pub const fn has_button_bar(&self) -> bool {
105        self.menuFlags.contains(UI_MENU_FLAGS::HasButtonBar)
106    }
107
108    /// Returns `true` if this is an inventory item menu.
109    #[inline]
110    pub const fn inventory_item_menu(&self) -> bool {
111        self.menuFlags.contains(UI_MENU_FLAGS::InventoryItemMenu)
112    }
113
114    /// Returns `true` if this menu is the top button bar.
115    #[inline]
116    pub const fn is_top_button_bar(&self) -> bool {
117        self.menuFlags.contains(UI_MENU_FLAGS::IsTopButtonBar)
118    }
119
120    /// Returns `true` if large-scaleform render cache mode is enabled.
121    #[inline]
122    pub const fn large_scaleform_render_cache_mode(&self) -> bool {
123        self.menuFlags.contains(UI_MENU_FLAGS::LargeScaleformRenderCacheMode)
124    }
125
126    /// Returns `true` if the menu is modal and blocks interaction with other menus.
127    #[inline]
128    pub const fn modal(&self) -> bool {
129        self.menuFlags.contains(UI_MENU_FLAGS::Modal)
130    }
131
132    /// Returns `true` if the menu is currently on the menu stack.
133    #[inline]
134    pub const fn on_stack(&self) -> bool {
135        self.menuFlags.contains(UI_MENU_FLAGS::OnStack)
136    }
137
138    /// Returns `true` if the menu causes the game to pause.
139    #[inline]
140    pub const fn pauses_game(&self) -> bool {
141        self.menuFlags.contains(UI_MENU_FLAGS::PausesGame)
142    }
143
144    /// Returns `true` if the menu renders offscreen targets.
145    #[inline]
146    pub const fn renders_offscreen_targets(&self) -> bool {
147        self.menuFlags.contains(UI_MENU_FLAGS::RendersOffscreenTargets)
148    }
149
150    /// Returns `true` if the menu renders underneath the pause menu.
151    #[inline]
152    pub const fn renders_under_pause_menu(&self) -> bool {
153        self.menuFlags.contains(UI_MENU_FLAGS::RendersUnderPauseMenu)
154    }
155
156    /// Returns `true` if the menu requires updates while active.
157    #[inline]
158    pub const fn requires_update(&self) -> bool {
159        self.menuFlags.contains(UI_MENU_FLAGS::RequiresUpdate)
160    }
161
162    /// Returns `true` if rendering is skipped during freeze frame screenshots.
163    #[inline]
164    pub const fn skip_render_during_freeze_frame_screenshot(&self) -> bool {
165        self.menuFlags.contains(UI_MENU_FLAGS::SkipRenderDuringFreezeFrameScreenshot)
166    }
167
168    /// Returns `true` if this is the topmost rendered menu.
169    #[inline]
170    pub const fn topmost_rendered_menu(&self) -> bool {
171        self.menuFlags.contains(UI_MENU_FLAGS::TopmostRenderedMenu)
172    }
173
174    /// Returns `true` if the menu uses the cursor during update.
175    #[inline]
176    pub const fn update_uses_cursor(&self) -> bool {
177        self.menuFlags.contains(UI_MENU_FLAGS::UpdateUsesCursor)
178    }
179
180    /// Returns `true` if the menu uses a blurred background.
181    #[inline]
182    pub const fn uses_blurred_background(&self) -> bool {
183        self.menuFlags.contains(UI_MENU_FLAGS::UsesBlurredBackground)
184    }
185
186    /// Returns `true` if the menu uses a cursor for interaction.
187    #[inline]
188    pub const fn uses_cursor(&self) -> bool {
189        self.menuFlags.contains(UI_MENU_FLAGS::UsesCursor)
190    }
191
192    /// Returns `true` if the menu uses a custom menu context.
193    #[inline]
194    pub const fn uses_menu_context(&self) -> bool {
195        self.menuFlags.contains(UI_MENU_FLAGS::UsesMenuContext)
196    }
197
198    /// Returns `true` if movement input is translated into direction within the menu.
199    #[inline]
200    pub const fn uses_movement_to_direction(&self) -> bool {
201        self.menuFlags.contains(UI_MENU_FLAGS::UsesMovementToDirection)
202    }
203}
204
205pub struct IMenuVtbl {
206    /// Destructor for `IMenu` (represented as a virtual method in C++).
207    pub CxxDrop: unsafe extern "C" fn(this: *mut IMenu),
208    pub Accept: fn(this: *mut IMenu, processor: *mut CallbackProcessor), // 01 - override { return; }
209
210    pub PostCreate: fn(this: *mut IMenu),     // 0x02
211    pub Unk_03: fn(this: *mut IMenu, c_void), // 0x03
212    pub ProcessMessage: fn(this: *mut IMenu, message: &UIMessage) -> UI_MESSAGE_RESULTS, // 0x04
213    pub AdvanceMovie: fn(this: *mut IMenu, interval: f32, currentTime: u32), // 0x05
214    pub PostDisplay: fn(this: *mut IMenu),    // 0x06
215
216    /// Only available if kRendersOffscreenTargets is set
217    pub PreDisplay: fn(this: *mut IMenu), // 0x07
218    pub RefreshPlatform: fn(this: *mut IMenu), // 0x08
219
220    /// - VR Only method: `{ unk30 = a_unk; }`
221    pub Unk_09: fn(this: *mut IMenu, unk: UI_MENU_Unk09), // 0x09
222    /// Does something with _root.ResetOnShow swf function
223    /// - VR Only method.
224    pub Unk_0A: fn(this: *mut IMenu), // 0x0A
225}
226
227impl crate::re::GPtr::RefCounted for IMenu {
228    fn add_ref(&mut self) {
229        self.refCount.fetch_add(1, core::sync::atomic::Ordering::Acquire);
230    }
231    fn release(&mut self) {
232        self.refCount.fetch_sub(1, core::sync::atomic::Ordering::Release);
233    }
234}
235
236#[commonlibsse_ng_derive_internal::to_bitflags]
237#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
238#[repr(u32)]
239pub enum UI_MENU_FLAGS {
240    None = 0,
241    PausesGame = 1 << 0,
242    AlwaysOpen = 1 << 1,
243    UsesCursor = 1 << 2,
244    UsesMenuContext = 1 << 3,
245    Modal = 1 << 4, // prevents lower movies with this flag from advancing
246    FreezeFrameBackground = 1 << 5,
247    OnStack = 1 << 6,
248    DisablePauseMenu = 1 << 7,
249    RequiresUpdate = 1 << 8,
250    TopmostRenderedMenu = 1 << 9,
251    UpdateUsesCursor = 1 << 10,
252    AllowSaving = 1 << 11,
253    RendersOffscreenTargets = 1 << 12,
254    InventoryItemMenu = 1 << 13,
255    DontHideCursorWhenTopmost = 1 << 14,
256    CustomRendering = 1 << 15,
257    AssignCursorToRenderer = 1 << 16,
258    ApplicationMenu = 1 << 17,
259    HasButtonBar = 1 << 18,
260    IsTopButtonBar = 1 << 19,
261    AdvancesUnderPauseMenu = 1 << 20,
262    RendersUnderPauseMenu = 1 << 21,
263    UsesBlurredBackground = 1 << 22,
264    CompanionAppAllowed = 1 << 23,
265    FreezeFramePause = 1 << 24,
266    SkipRenderDuringFreezeFrameScreenshot = 1 << 25,
267    LargeScaleformRenderCacheMode = 1 << 26,
268    UsesMovementToDirection = 1 << 27,
269}
270
271#[commonlibsse_ng_derive_internal::ffi_enum]
272#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
273#[repr(u32)]
274pub enum UI_MESSAGE_RESULTS {
275    Handled = 0,
276    Ignore = 1,
277    PassOn = 2,
278}
279
280/// NOTE: Entire enum needs more REing
281#[commonlibsse_ng_derive_internal::ffi_enum]
282#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
283#[repr(u32)]
284#[non_exhaustive]
285pub enum UI_MENU_Unk09 {
286    None = u32::MAX,
287}