commonlibsse_ng\re\m\Misc/message_box.rs
1use core::ffi::{CStr, c_char};
2use core::ptr;
3
4use crate::re::GameSettingCollection::GameSettingCollection;
5use crate::re::IMessageBoxCallback::{IMessageBoxCallback, Message};
6use crate::re::Setting::SettingValue;
7
8#[commonlibsse_ng_derive_internal::relocate_fn(se_id = 51420, ae_id = 52269)]
9pub fn CreateMessage(
10 message: *const c_char,
11 callback: *mut IMessageBoxCallback,
12 arg3: u32,
13 arg4: u32,
14 arg5: u32,
15 button_text: *const c_char,
16 secondary_button_text: *const c_char,
17) {
18}
19
20/// The configuration for displaying the message box.
21pub struct MessageBoxConfig<'a> {
22 /// The message to be displayed in the message box.
23 pub message: &'a CStr,
24 /// Text for the primary button (defaults to `"OK"`)
25 ///
26 /// If a task is registered, press this button in the game to execute it.
27 pub button_text: &'a CStr,
28 /// Text for the secondary button (no secondary button if None)
29 pub secondary_button_text: Option<&'a CStr>,
30 /// Optional task (closure) to execute when a button is pressed
31 ///
32 /// FIXME: Currently not running as it crashes mysteriously.
33 pub task: Option<fn(Message)>,
34}
35
36impl Default for MessageBoxConfig<'_> {
37 fn default() -> Self {
38 Self {
39 message: c"",
40 button_text: c"OK",
41 secondary_button_text: None,
42 task: Default::default(),
43 }
44 }
45}
46
47/// Displays a message box with the given configuration.
48///
49/// This function creates a message box with the provided `message` and optional button texts.
50/// If a `task` is provided, it will be executed when the button is pressed.
51///
52/// # Example
53/// ```no_run
54/// use std::ffi::CString;
55/// use commonlibsse_ng::re::Misc::{DebugMessageBoxWithConfig, MessageBoxConfig};
56///
57/// let message = CString::new(format!("This is a {}", "message")).unwrap();
58///
59/// let config = MessageBoxConfig {
60/// message: &message,
61/// button_text: c"Yes",
62/// secondary_button_text: Some(c"No"),
63/// task: None,
64/// };
65///
66/// DebugMessageBoxWithConfig(config);
67/// ```
68///
69/// # Message Box Layout
70/// ```txt
71/// +--------------------------+
72/// | This is a message |
73/// | |
74/// | [Yes] [No] | <-- Primary and Secondary Buttons
75/// +--------------------------+
76/// ```
77#[inline]
78pub fn DebugMessageBoxWithConfig(config: MessageBoxConfig) {
79 // If secondary button text is not provided, use null pointer
80 let secondary_button_text =
81 config.secondary_button_text.map_or(ptr::null(), |cstr| cstr.as_ptr());
82
83 // FIXME: Currently not running as it crashes mysteriously.
84 // If a task is provided, create a callback for it
85 // use crate::re::OldMessageBoxCallback::OldMessageBoxCallback;
86 // let callback_ptr = config
87 // .task
88 // .map_or(ptr::null_mut(), |task| Box::into_raw(Box::new(OldMessageBoxCallback::new(task))));
89
90 CreateMessage(
91 config.message.as_ptr(),
92 // callback_ptr.cast(),
93 ptr::null_mut(),
94 0,
95 4,
96 10,
97 config.button_text.as_ptr(),
98 secondary_button_text,
99 );
100 // drop(unsafe { Box::from_raw(callback_ptr) });
101}
102
103/// Display a simple dialog box with the given message.
104///
105/// # Message Box Layout
106/// ```txt
107/// +--------------------------+
108/// | This is a message |
109/// | |
110/// | [OK] | <-- Primary Buttons
111/// +--------------------------+
112/// ```
113///
114/// # Example
115/// ```no_run
116/// commonlibsse_ng::re::Misc::DebugMessageBox(c"This is a message");
117/// ```
118#[inline]
119pub fn DebugMessageBox(message: &CStr) {
120 DebugMessageBoxWithConfig(MessageBoxConfig { message, ..Default::default() });
121}
122
123/// C++ `DebugMessageBox`
124///
125/// with i18n `OK` button
126pub fn DebugMessageOkBox(message: &CStr) {
127 unsafe {
128 let ok_button = GameSettingCollection::get_singleton()
129 .and_then(|gsc| gsc.__base.settings.__base.__base.__base.get(&c"sOk".as_ptr()))
130 .and_then(|setting| {
131 if let SettingValue::String(string) = setting.as_ref()?.get_value() {
132 return Some(string);
133 }
134 None
135 })
136 .unwrap_or(c"OK");
137 DebugMessageBoxWithConfig(MessageBoxConfig {
138 message,
139 button_text: ok_button,
140 ..Default::default()
141 });
142 }
143}