I'm cooked, will finish this later.

This commit is contained in:
MapleWheels
2026-02-26 19:16:50 -05:00
parent 94556fd6e7
commit 6e556a02d4
9 changed files with 409 additions and 42 deletions

View File

@@ -4,8 +4,8 @@ namespace Barotrauma.LuaCs.Data;
public interface ISettingControl : ISettingBase
{
event Action<ISettingControl> OnDown;
KeyOrMouse Value { get; }
bool TrySetValue(KeyOrMouse value);
bool IsDown();
bool IsHit();
}

View File

@@ -0,0 +1,146 @@
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.LuaCs.Data;
using Microsoft.Xna.Framework.Input;
using OneOf;
namespace Barotrauma.LuaCs.Configuration;
public class SettingControl : ISettingControl
{
public string InternalName { get; }
public ContentPackage OwnerPackage { get; }
public bool Equals(ISettingBase other)
{
throw new NotImplementedException();
}
public void Dispose()
{
throw new NotImplementedException();
}
public IConfigDisplayInfo GetDisplayInfo()
{
throw new NotImplementedException();
}
public Type GetValueType() => typeof(KeyOrMouse);
public string GetStringValue() => Value.ToString();
public string GetDefaultStringValue() => new KeyOrMouse(Keys.NumLock).ToString();
public bool TrySetValue(OneOf<string, XElement> value)
{
var newVal = value.Match<KeyOrMouse>(
(string v) => GetKeyOrMouse(v),
(XElement e) => e.GetAttributeKeyOrMouse("Value", null));
if (newVal is null)
{
return false;
}
Value = newVal;
OnValueChanged?.Invoke(this);
return true;
KeyOrMouse GetKeyOrMouse(string strValue)
{
strValue ??= string.Empty;
if (Enum.TryParse(strValue, true, out Microsoft.Xna.Framework.Input.Keys key))
{
return key;
}
else if (Enum.TryParse(strValue, out MouseButton mouseButton))
{
return mouseButton;
}
else if (int.TryParse(strValue, NumberStyles.Any, CultureInfo.InvariantCulture, out int mouseButtonInt) &&
Enum.GetValues<MouseButton>().Contains((MouseButton)mouseButtonInt))
{
return (MouseButton)mouseButtonInt;
}
else if (string.Equals(strValue, "LeftMouse", StringComparison.OrdinalIgnoreCase))
{
return !PlayerInput.MouseButtonsSwapped() ? MouseButton.PrimaryMouse : MouseButton.SecondaryMouse;
}
else if (string.Equals(strValue, "RightMouse", StringComparison.OrdinalIgnoreCase))
{
return !PlayerInput.MouseButtonsSwapped() ? MouseButton.SecondaryMouse : MouseButton.PrimaryMouse;
}
return null;
}
}
public event Action<ISettingBase> OnValueChanged;
public OneOf<string, XElement> GetSerializableValue()
{
return Value.ToString();
}
public KeyOrMouse Value { get; private set; } = new KeyOrMouse(Keys.NumLock);
public bool TrySetValue(KeyOrMouse value)
{
Value = value;
OnValueChanged?.Invoke(this);
return true;
}
public bool IsDown()
{
if (this.Value is null)
return false;
switch (this.Value.MouseButton)
{
case MouseButton.None:
return Barotrauma.PlayerInput.KeyDown(this.Value.Key);
case MouseButton.PrimaryMouse:
return Barotrauma.PlayerInput.PrimaryMouseButtonHeld();
case MouseButton.SecondaryMouse:
return Barotrauma.PlayerInput.SecondaryMouseButtonHeld();
case MouseButton.MiddleMouse:
return Barotrauma.PlayerInput.MidButtonHeld();
case MouseButton.MouseButton4:
return Barotrauma.PlayerInput.Mouse4ButtonHeld();
case MouseButton.MouseButton5:
return Barotrauma.PlayerInput.Mouse5ButtonHeld();
case MouseButton.MouseWheelUp:
return Barotrauma.PlayerInput.MouseWheelUpClicked();
case MouseButton.MouseWheelDown:
return Barotrauma.PlayerInput.MouseWheelDownClicked();
}
return false;
}
public bool IsHit()
{
if (this.Value is null)
return false;
switch (this.Value.MouseButton)
{
case MouseButton.None:
return Barotrauma.PlayerInput.KeyHit(this.Value.Key);
case MouseButton.PrimaryMouse:
return Barotrauma.PlayerInput.PrimaryMouseButtonClicked();
case MouseButton.SecondaryMouse:
return Barotrauma.PlayerInput.SecondaryMouseButtonClicked();
case MouseButton.MiddleMouse:
return Barotrauma.PlayerInput.MidButtonClicked();
case MouseButton.MouseButton4:
return Barotrauma.PlayerInput.Mouse4ButtonClicked();
case MouseButton.MouseButton5:
return Barotrauma.PlayerInput.Mouse5ButtonClicked();
case MouseButton.MouseWheelUp:
return Barotrauma.PlayerInput.MouseWheelUpClicked();
case MouseButton.MouseWheelDown:
return Barotrauma.PlayerInput.MouseWheelDownClicked();
}
return false;
}
}

View File

@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
#nullable enable
namespace Barotrauma.LuaCs;
/// <summary>
/// A collection of helper GUI functions. Mostly ripped from "Barotrauma/ClientSource/Settings/SettingsMenu.cs"
/// </summary>
public static class GUIUtil
{
public static (GUILayoutGroup Left, GUILayoutGroup Right) CreateSidebars(GUIFrame parent, bool split = false)
{
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(Vector2.One, parent.RectTransform), isHorizontal: true);
GUILayoutGroup left = new GUILayoutGroup(new RectTransform((0.4875f, 1.0f), layout.RectTransform), isHorizontal: false);
var centerFrame = new GUIFrame(new RectTransform((0.025f, 1.0f), layout.RectTransform), style: null);
if (split)
{
new GUICustomComponent(new RectTransform(Vector2.One, centerFrame.RectTransform),
onDraw: (sb, c) =>
{
sb.DrawLine((c.Rect.Center.X, c.Rect.Top),
(c.Rect.Center.X, c.Rect.Bottom),
GUIStyle.TextColorDim,
2f);
});
}
GUILayoutGroup right = new GUILayoutGroup(new RectTransform((0.4875f, 1.0f), layout.RectTransform), isHorizontal: false);
return (left, right);
}
public static GUILayoutGroup CreateCenterLayout(GUIFrame parent)
=> new GUILayoutGroup(new RectTransform((0.5f, 1.0f), parent.RectTransform, Anchor.TopCenter, Pivot.TopCenter)) { ChildAnchor = Anchor.TopCenter };
public static RectTransform NewItemRectT(GUILayoutGroup parent, Vector2 adjustRatio)
=> new RectTransform((1.0f * adjustRatio.X, 0.06f * adjustRatio.Y), parent.RectTransform, Anchor.CenterLeft);
public static void Spacer(GUILayoutGroup parent, Vector2 adjustRatio)
=> new GUIFrame(new RectTransform((1.0f * adjustRatio.X, 0.03f * adjustRatio.Y), parent.RectTransform, Anchor.CenterLeft), style: null);
public static void ClearChildElements(GUIComponent component, bool clearSelfFromParent = false)
{
component.GetAllChildren().ForEachMod(c =>
{
c.Visible = false;
component.RemoveChild(c);
});
if (clearSelfFromParent && component.Parent is not null)
component.Parent.RemoveChild(component);
}
public static GUITextBlock Label(GUILayoutGroup parent, LocalizedString str, GUIFont font, Vector2 adjustRatio)
=> new GUITextBlock(NewItemRectT(parent, adjustRatio), str, font: font);
public static GUIDropDown DropdownEnum<T>(GUILayoutGroup parent, Func<T, LocalizedString> textFunc, Func<T, LocalizedString>? tooltipFunc, T currentValue,
Action<T> setter, Vector2 adjustRatio) where T : Enum
=> Dropdown(parent, textFunc, tooltipFunc, (T[])Enum.GetValues(typeof(T)), currentValue, setter, adjustRatio);
public static GUIDropDown Dropdown<T>(GUILayoutGroup parent, Func<T, LocalizedString> textFunc, Func<T,
LocalizedString>? tooltipFunc, IReadOnlyList<T> values, T currentValue, Action<T> setter, Vector2 adjustRatio)
{
var dropdown = new GUIDropDown(NewItemRectT(parent, adjustRatio));
values.ForEach(v => dropdown.AddItem(text: textFunc(v), userData: v, toolTip: tooltipFunc?.Invoke(v) ?? null));
int childIndex = values.IndexOf(currentValue);
dropdown.Select(childIndex);
dropdown.ListBox.ForceLayoutRecalculation();
dropdown.ListBox.ScrollToElement(dropdown.ListBox.Content.GetChild(childIndex));
dropdown.OnSelected = (dd, obj) =>
{
setter((T)obj);
return true;
};
return dropdown;
}
public static (GUIScrollBar, GUITextBlock) Slider(GUILayoutGroup parent, Vector2 range, int steps, Func<float,
string> labelFunc, float currentValue, Action<float> setter, LocalizedString? tooltip, Vector2 adjustRatio)
{
var layout = new GUILayoutGroup(NewItemRectT(parent, adjustRatio), isHorizontal: true);
var slider = new GUIScrollBar(new RectTransform((0.72f, 1.0f), layout.RectTransform), style: "GUISlider")
{
Range = range,
BarScrollValue = currentValue,
Step = 1.0f / (float)(steps - 1),
BarSize = 1.0f / steps
};
if (tooltip != null)
{
slider.ToolTip = tooltip;
}
var label = new GUITextBlock(new RectTransform((0.28f, 1.0f), layout.RectTransform),
labelFunc(currentValue), wrap: false, textAlignment: Alignment.Center);
slider.OnMoved = (sb, val) =>
{
label.Text = labelFunc(sb.BarScrollValue);
setter(sb.BarScrollValue);
return true;
};
return (slider, label);
}
public static GUITickBox Tickbox(GUILayoutGroup parent, LocalizedString label, LocalizedString tooltip,
bool currentValue, Action<bool> setter, Vector2 adjustRatio)
{
var tickbox = new GUITickBox(NewItemRectT(parent, adjustRatio), label)
{
Selected = currentValue,
ToolTip = tooltip,
OnSelected = (tb) =>
{
setter(tb.Selected);
return true;
}
};
return tickbox;
}
public static string Percentage(float v) => ToolBox.GetFormattedPercentage(v);
public static int Round(float v) => (int)MathF.Round(v);
}

View File

@@ -0,0 +1,17 @@
namespace Barotrauma.LuaCs;
internal sealed class ModsControlsSettingsMenu : ModsSettingsMenu
{
public ModsControlsSettingsMenu(GUIFrame contentFrame,
IPackageManagementService packageManagementService,
IConfigService configService,
SettingsMenu settingsMenuInstance) : base(contentFrame, packageManagementService, configService, settingsMenuInstance)
{
}
protected override void DisposeInternal()
{
// TODO: Finish this later.
}
}

View File

@@ -0,0 +1,17 @@
namespace Barotrauma.LuaCs;
internal sealed class ModsGameplaySettingsMenu : ModsSettingsMenu
{
public ModsGameplaySettingsMenu(GUIFrame contentFrame,
IPackageManagementService packageManagementService,
IConfigService configService,
SettingsMenu settingsMenuInstance) : base(contentFrame, packageManagementService, configService, settingsMenuInstance)
{
}
protected override void DisposeInternal()
{
// TODO: Finish this later.
}
}

View File

@@ -0,0 +1,35 @@
using System;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
namespace Barotrauma.LuaCs;
internal abstract class ModsSettingsMenu : IDisposable
{
public GUIFrame ContentFrame { get; private set; }
protected IPackageManagementService PackageManagementService { get; private set; }
protected IConfigService ConfigService { get; private set; }
protected SettingsMenu SettingsMenuInstance { get; private set; }
protected ModsSettingsMenu(GUIFrame contentFrame,
IPackageManagementService packageManagementService,
IConfigService configService, SettingsMenu settingsMenuInstance)
{
ContentFrame = contentFrame;
PackageManagementService = packageManagementService;
ConfigService = configService;
SettingsMenuInstance = settingsMenuInstance;
}
protected abstract void DisposeInternal();
public void Dispose()
{
DisposeInternal();
ContentFrame?.Parent.RemoveChild(ContentFrame);
SettingsMenuInstance = null;
ContentFrame = null;
PackageManagementService = null;
ConfigService = null;
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Barotrauma.Extensions;
using HarmonyLib;
using Microsoft.Xna.Framework;
@@ -7,65 +8,81 @@ namespace Barotrauma.LuaCs;
public class SettingsMenuSystem : ISettingsMenuSystem
{
private GUIFrame _menuFrame;
private GUIButton _menuOpenButton;
private readonly Harmony _harmony;
private static SettingsMenuSystem _systemInstance;
public SettingsMenuSystem()
private ModsControlsSettingsMenu _controlsMenuInstance;
private ModsGameplaySettingsMenu _gameplayMenuInstance;
private readonly Harmony _harmony;
private readonly IPackageManagementService _packageManagementService;
private readonly IConfigService _configService;
private static SettingsMenuSystem SystemInstance;
public SettingsMenuSystem(IPackageManagementService packageManagementService, IConfigService configService)
{
_systemInstance = this;
_packageManagementService = packageManagementService;
_configService = configService;
SystemInstance = this;
_harmony = Harmony.CreateAndPatchAll(typeof(SettingsMenuSystem));
}
[HarmonyPatch(typeof(SettingsMenu), "CreateModsTab"), HarmonyPostfix]
private static void SettingsMenu_CreateModsTab_Post(SettingsMenu __instance)
{
_systemInstance.CreateSettingsMenu(__instance);
SystemInstance.CreateSettingsMenu(__instance);
}
private void CreateSettingsMenu(SettingsMenu __instance)
{
var tabIndex = (SettingsMenu.Tab)Enum.GetValues<SettingsMenu.Tab>().Length;
var contentFrame = CreateNewContentFrame(tabIndex);
contentFrame.RectTransform.RelativeSize = Vector2.One;
DisposeMenuFrames();
var tabCount = Enum.GetValues<SettingsMenu.Tab>().Length;
var tabGameplayIndex = (SettingsMenu.Tab)tabCount;
var tabControlsIndex = (SettingsMenu.Tab)tabCount+1;
GUIFrame CreateNewContentFrame(SettingsMenu.Tab tab)
var gameplayContentFrame = CreateNewContentTab(tabGameplayIndex, __instance,
"SettingsMenuTab.Mods", "LuaCsForBarotrauma.SettingsMenu.ModGameplayButton");
var controlsContentFrame = CreateNewContentTab(tabControlsIndex, __instance,
"SettingsMenuTab.Mods", "LuaCsForBarotrauma.SettingsMenu.ModControlsButton");
_gameplayMenuInstance = new ModsGameplaySettingsMenu(gameplayContentFrame, _packageManagementService, _configService, __instance);
_controlsMenuInstance = new ModsControlsSettingsMenu(controlsContentFrame, _packageManagementService, _configService, __instance);
}
private GUIFrame CreateNewContentTab(SettingsMenu.Tab tab, SettingsMenu settingsMenuInstance, string settingsMenuTabName, string settingMenuHoverTextIdent)
{
if (settingsMenuInstance.tabContents.TryGetValue(tab, out (GUIButton Button, GUIFrame Content) tabContent))
{
if (__instance.tabContents.TryGetValue(tab, out (GUIButton Button, GUIFrame Content) tabContent))
{
return tabContent.Content;
}
var contentFr = new GUIFrame(new RectTransform(Vector2.One * 0.95f, __instance.contentFrame.RectTransform, Anchor.Center, Pivot.Center), style: null);
var button = new GUIButton(new RectTransform(Vector2.One, __instance.tabber.RectTransform, Anchor.TopLeft, Pivot.TopLeft, scaleBasis: ScaleBasis.Smallest), "", style: $"SettingsMenuTab.Mods")
{
ToolTip = TextManager.Get($"LuaCsForBarotrauma.SettingsMenu.ModSettingsButton"),
OnClicked = (b, _) =>
{
__instance.SelectTab(tab);
return false;
}
};
button.RectTransform.MaxSize = RectTransform.MaxPoint;
button.Children.ForEach(c => c.RectTransform.MaxSize = RectTransform.MaxPoint);
__instance.tabContents.Add(tab, (button, contentFr));
return contentFr;
return tabContent.Content;
}
var contentFr = new GUIFrame(new RectTransform(Vector2.One * 0.95f, settingsMenuInstance.contentFrame.RectTransform, Anchor.Center, Pivot.Center), style: null);
var button = new GUIButton(new RectTransform(Vector2.One, settingsMenuInstance.tabber.RectTransform,
Anchor.TopLeft, Pivot.TopLeft, scaleBasis: ScaleBasis.Smallest), "", style: $"SettingsMenuTab.Mods")
{
ToolTip = TextManager.Get($"LuaCsForBarotrauma.SettingsMenu.ModSettingsButton"),
OnClicked = (b, _) =>
{
settingsMenuInstance.SelectTab(tab);
return false;
}
};
button.RectTransform.MaxSize = RectTransform.MaxPoint;
button.Children.ForEach(c => c.RectTransform.MaxSize = RectTransform.MaxPoint);
settingsMenuInstance.tabContents.Add(tab, (button, contentFr));
return contentFr;
}
private void DisposeMenuFrame()
private void DisposeMenuFrames()
{
if (_menuFrame is not null)
{
_menuFrame.Parent.RemoveChild(_menuFrame);
_menuFrame = null;
}
_controlsMenuInstance?.Dispose();
_gameplayMenuInstance?.Dispose();
_controlsMenuInstance = null;
_gameplayMenuInstance = null;
}
#region DISPOSAL
@@ -76,7 +93,7 @@ public class SettingsMenuSystem : ISettingsMenuSystem
{
return;
}
DisposeMenuFrame();
DisposeMenuFrames();
GC.SuppressFinalize(this);
}
private int _isDisposed = 0;

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<infotexts language="English" nowhitespace="false" translatedname="English">
<LuaCsForBarotrauma.SettingsMenu.ModControlsButton>Mod Controls Settings</LuaCsForBarotrauma.SettingsMenu.ModControlsButton>
<LuaCsForBarotrauma.SettingsMenu.ModGameplayButton>Mod Gameplay Settings</LuaCsForBarotrauma.SettingsMenu.ModGameplayButton>
<LuaCsForBarotrauma.Setting.DisableErrorGUIOverlay>Suppress GUI Popup on Error</LuaCsForBarotrauma.Setting.DisableErrorGUIOverlay>
<LuaCsForBarotrauma.Setting.IsCsEnabled>Are C# Mods Allowed</LuaCsForBarotrauma.Setting.IsCsEnabled>
<LuaCsForBarotrauma.Setting.HideUserNamesInLogs>Hide Local OS Account Name In Logs</LuaCsForBarotrauma.Setting.HideUserNamesInLogs>
<LuaCsForBarotrauma.Setting.LocalDataSavePath>Where to Save Local Data</LuaCsForBarotrauma.Setting.LocalDataSavePath>
</infotexts>

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<infotexts language="Portuguese" nowhitespace="false" translatedname="Portuguese">
</infotexts>