diff --git a/src/LiveSplit.AutoSplittingRuntime/ASR.cs b/src/LiveSplit.AutoSplittingRuntime/ASR.cs index 1ae81b2..611f0a3 100644 --- a/src/LiveSplit.AutoSplittingRuntime/ASR.cs +++ b/src/LiveSplit.AutoSplittingRuntime/ASR.cs @@ -134,6 +134,16 @@ public void SettingsMapSetString(string key, string value) ASRNative.Runtime_settings_map_set_string(ptr, key, value); } + public bool InvokeSettingsButton(string key) + { + if (ptr == IntPtr.Zero) + { + return false; + } + + return ASRNative.Runtime_invoke_settings_button(ptr, key) != 0; + } + public SettingsMap GetSettingsMap() { if (ptr == IntPtr.Zero) @@ -607,6 +617,7 @@ public string GetType(ulong index) 2 => "title", 3 => "choice", 4 => "file-select", + 5 => "button", _ => "", }; } @@ -749,6 +760,8 @@ LogDelegate log [DllImport("asr_capi", CallingConvention = CallingConvention.Cdecl)] public static extern void Runtime_settings_map_set_string(IntPtr self, ASRString key, ASRString value); [DllImport("asr_capi", CallingConvention = CallingConvention.Cdecl)] + public static extern byte Runtime_invoke_settings_button(IntPtr self, ASRString key); + [DllImport("asr_capi", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr Runtime_get_settings_map(IntPtr self); [DllImport("asr_capi", CallingConvention = CallingConvention.Cdecl)] public static extern void Runtime_set_settings_map(IntPtr self, IntPtr settings_map); diff --git a/src/LiveSplit.AutoSplittingRuntime/ComponentSettings.cs b/src/LiveSplit.AutoSplittingRuntime/ComponentSettings.cs index 75cc216..2e74741 100644 --- a/src/LiveSplit.AutoSplittingRuntime/ComponentSettings.cs +++ b/src/LiveSplit.AutoSplittingRuntime/ComponentSettings.cs @@ -331,6 +331,37 @@ public void BuildTree() rowIndex++; break; } + case "button": + { + if (rowIndex < settingsTable.RowStyles.Count + && settingsTable.GetControlFromPosition(0, rowIndex) is Button exButton + && exButton.Tag is string exTag + && exTag == widgets.GetKey(i) + && exButton.Text == desc + && exButton.Margin.Left == margin) + { + toolTip.SetToolTip(exButton, tooltip); + } + else + { + ClearSettingsTableTail(rowIndex); + var button = new Button + { + Tag = widgets.GetKey(i), + Text = desc, + Margin = new Padding(margin, 0, 0, 0), + AutoSize = true, + AutoSizeMode = AutoSizeMode.GrowAndShrink, + }; + button.Click += SettingsButton_Click; + toolTip.SetToolTip(button, tooltip); + settingsTable.Controls.Add(button, 0, settingsTable.RowStyles.Count); + settingsTable.RowStyles.Add(new RowStyle(SizeType.Absolute, button.Height)); + } + + rowIndex++; + break; + } default: { break; @@ -434,6 +465,22 @@ private void FileSelect_Click(object sender, EventArgs e) } } + private void SettingsButton_Click(object sender, EventArgs e) + { + var button = (Button)sender; + if (button.Tag is not string key || runtime == null) + { + return; + } + + runtime.InvokeSettingsButton(key); + // Callback may have mutated the settings map or widgets + SettingsMap prev = previousMap; + previousMap = runtime.GetSettingsMap(); + prev?.Dispose(); + BuildTree(); + } + private class Choice { public string key; diff --git a/src/LiveSplit.AutoSplittingRuntime/x64/asr_capi.dll b/src/LiveSplit.AutoSplittingRuntime/x64/asr_capi.dll index e63052c..59c713e 100644 Binary files a/src/LiveSplit.AutoSplittingRuntime/x64/asr_capi.dll and b/src/LiveSplit.AutoSplittingRuntime/x64/asr_capi.dll differ diff --git a/src/LiveSplit.AutoSplittingRuntime/x86/asr_capi.dll b/src/LiveSplit.AutoSplittingRuntime/x86/asr_capi.dll index 548b449..aadf416 100644 Binary files a/src/LiveSplit.AutoSplittingRuntime/x86/asr_capi.dll and b/src/LiveSplit.AutoSplittingRuntime/x86/asr_capi.dll differ diff --git a/src/asr-capi/src/runtime.rs b/src/asr-capi/src/runtime.rs index 560d105..136b50a 100644 --- a/src/asr-capi/src/runtime.rs +++ b/src/asr-capi/src/runtime.rs @@ -193,6 +193,31 @@ pub unsafe extern "C" fn Runtime_settings_map_set_string( panic!("Index out of bounds") } +/// # Safety +/// `key` must be a valid NUL-terminated UTF-8 C string (same convention as other Runtime_* key APIs). +#[no_mangle] +pub unsafe extern "C" fn Runtime_invoke_settings_button( + _this: &Runtime, + key: *const u8, +) -> bool { + #[cfg(target_pointer_width = "64")] + { + let key = str(key); + match _this.runtime.invoke_settings_button(key) { + Ok(_) => true, + Err(err) => { + log( + _this.log, + format_args!("{:?}", err.context("Failed executing the auto splitter.")), + ); + false + } + } + } + #[cfg(not(target_pointer_width = "64"))] + false +} + #[no_mangle] pub extern "C" fn Runtime_get_settings_map(_this: &Runtime) -> Box { #[cfg(target_pointer_width = "64")] diff --git a/src/asr-capi/src/widgets.rs b/src/asr-capi/src/widgets.rs index 403d400..d316803 100644 --- a/src/asr-capi/src/widgets.rs +++ b/src/asr-capi/src/widgets.rs @@ -67,6 +67,7 @@ pub extern "C" fn Widgets_get_type(_this: &Widgets, _index: usize) -> usize { WidgetKind::Title { .. } => 2, WidgetKind::Choice { .. } => 3, WidgetKind::FileSelect { .. } => 4, + WidgetKind::Button => 5, } } #[cfg(not(target_pointer_width = "64"))]