327 lines
13 KiB
C#
327 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
using Microsoft.Xna.Framework;
|
|
using Monocle;
|
|
|
|
using YamlDotNet.Serialization;
|
|
|
|
namespace Celeste.Mod.AvaliSkin {
|
|
[SettingName("AVALI_SKIN_TITLE")]
|
|
public class AvaliSkinSettings : EverestModuleSettings {
|
|
private void updateOptions() {
|
|
bool loadedCelestenet = Everest.Loader.DependencyLoaded(AvaliSkinModule.CelesteNetMeta);
|
|
|
|
// send the new settings to other celestenet players if we're connected
|
|
if (loadedCelestenet) { updateSkinCelestenet(); }
|
|
|
|
// menu is not loaded; don't bother
|
|
if (ColorModeOptItem == null) { return; }
|
|
|
|
// disable all the normal options if the main toggle is disabled
|
|
ColorModeOptItem.Disabled = !Enabled;
|
|
ColorSubmenuItem.Disabled = !Enabled;
|
|
|
|
// change up the colormode note based on the selection
|
|
string colorModeNote = "";
|
|
switch (ColorModeOpt) {
|
|
case ColorMode.ExternalDash: colorModeNote = "modoptions_avaliskin_colormodeopt_ExternalDash_note"; break;
|
|
case ColorMode.ManualPreset: colorModeNote = "modoptions_avaliskin_colormodeopt_ManualPreset_note"; break;
|
|
case ColorMode.ManualRGB: colorModeNote = "modoptions_avaliskin_colormodeopt_ManualRGB_note"; break;
|
|
}
|
|
ColorModeOptNote.Title = colorModeNote.DialogOrKey();
|
|
|
|
// no point in showing the submenu at all for externaldash; there's
|
|
// nothing to configure!
|
|
ColorSubmenuItem.Visible = ColorModeOpt != ColorMode.ExternalDash;
|
|
|
|
// disable and change item visibility based on main toggle or colormode
|
|
foreach (var item in DashRGBItems) {
|
|
item.Disabled = !Enabled;
|
|
item.Visible = ColorModeOpt == ColorMode.ManualRGB;
|
|
}
|
|
|
|
foreach (var item in DashPresetItems) {
|
|
item.Disabled = !Enabled;
|
|
item.Visible = ColorModeOpt == ColorMode.ManualPreset;
|
|
}
|
|
|
|
|
|
// Disable if Celestenet is not installed/enabled.
|
|
EnableCelesteNetItem.Disabled = !loadedCelestenet;
|
|
|
|
// Independently disable the celestenet options
|
|
// The user might want the skin disabled, but not for others!
|
|
// Also disable these options if Celestenet is not installed/enabled.
|
|
CelesteNetSyncItem.Disabled = !EnableCelesteNet || !loadedCelestenet;
|
|
CelesteNetEveryoneHasSkinItem.Disabled = !EnableCelesteNet || !loadedCelestenet;
|
|
}
|
|
|
|
// CelesteNet must be loaded when calling this function.
|
|
private void updateSkinCelestenet() {
|
|
// this needs to be in a seperate function because the entire component
|
|
// relies on an assembly reference
|
|
if (CelesteNetAvaliComponent.Instance != null) {
|
|
CelesteNetAvaliComponent.Instance.SendAvaliSkin();
|
|
}
|
|
}
|
|
|
|
// note: YamlDotNet ignores all private member variables
|
|
private bool enabled = true;
|
|
public bool Enabled {
|
|
get => enabled;
|
|
set {
|
|
enabled = value;
|
|
|
|
if (Engine.Scene is Level level) {
|
|
// we're in a map: reset sprite the same way the Other Self toggle does.
|
|
// the hook on PlayerSprite will decide if we should use the Avali skin or not.
|
|
Player player = level.Tracker.GetEntity<Player>();
|
|
if (player != null) {
|
|
PlayerSpriteMode mode = (SaveData.Instance.Assists.PlayAsBadeline ? PlayerSpriteMode.MadelineAsBadeline : player.DefaultSpriteMode);
|
|
if (player.Active) {
|
|
player.ResetSpriteNextFrame(mode);
|
|
} else {
|
|
player.ResetSprite(mode);
|
|
}
|
|
}
|
|
}
|
|
|
|
updateOptions();
|
|
}
|
|
}
|
|
|
|
|
|
public enum ColorMode {
|
|
ExternalDash,
|
|
ManualPreset,
|
|
ManualRGB
|
|
}
|
|
|
|
public ColorMode ColorModeOpt { get; set; } = ColorMode.ExternalDash;
|
|
private TextMenu.Item ColorModeOptItem;
|
|
private TextMenu.SubHeader ColorModeOptNote;
|
|
public void CreateColorModeOptEntry(TextMenu menu, bool inGame) {
|
|
ColorModeOptItem = new TextMenuExt.EnumerableSlider<ColorMode>(
|
|
"modoptions_avaliskin_colormodeopt".DialogOrKey(),
|
|
// Enum.GetValues returns an Array, which is not enumerable.
|
|
// However, normal object vectors are. So...
|
|
((ColorMode[]) Enum.GetValues(typeof(ColorMode))).Select(
|
|
variant => new KeyValuePair<ColorMode, string>(
|
|
variant,
|
|
$"modoptions_avaliskin_colormodeopt_{variant.ToString()}".DialogOrKey()
|
|
)
|
|
),
|
|
ColorModeOpt
|
|
).Change(opt => {
|
|
ColorModeOpt = opt;
|
|
updateOptions();
|
|
});
|
|
menu.Add(ColorModeOptItem);
|
|
ColorModeOptItem.AddDescription(menu, "modoptions_avaliskin_colormodeopt_note".DialogOrKey());
|
|
|
|
List<TextMenu.Item> items = menu.GetItems();
|
|
ColorModeOptNote = (TextMenu.SubHeader) items[items.IndexOf(ColorModeOptItem) + 1];
|
|
}
|
|
|
|
#region AvaliColorSettings
|
|
|
|
// ColorSubmenu is a dummy setting that is only used to position the
|
|
// Submenu. This setting is never used, hence why it is Void!
|
|
[YamlIgnore]
|
|
public Void ColorSubmenu { get; set; }
|
|
private TextMenuExt.OptionSubMenu ColorSubmenuItem;
|
|
public void CreateColorSubmenuEntry(TextMenu menu, bool inGame) {
|
|
DashRGBItems.Clear();
|
|
DashPresetItems.Clear();
|
|
|
|
ColorSubmenuItem = new TextMenuExt.OptionSubMenu(
|
|
"AVALI_SKIN_COLORS".DialogOrKey()
|
|
);
|
|
|
|
// This generates n submenus, one for each dash
|
|
for (int i = 0; i < DashRGBColor.Count; i++) {
|
|
TextMenuExt.IntSlider DashRItem, DashGItem, DashBItem;
|
|
TextMenu.Option<ColorChoice> DashColorItem;
|
|
|
|
int j = i; // C# lambda are wierd: capturing i directly mutates the captured variable
|
|
|
|
ColorSubmenuItem.Add(
|
|
$"AVALI_SKIN_DASH{i}".DialogOrKey(),
|
|
new List<TextMenu.Item> {
|
|
(DashRItem = new TextMenuExt.IntSlider(
|
|
"AVALI_SKIN_RED".DialogOrKey(),
|
|
0, 255, DashRGBColor[j].R
|
|
).Change(
|
|
// C# is stupidly pendatic and doesn't support property assignment in List elements
|
|
// so we have to do this ugly shit to avoid breaking up this expression into two
|
|
c => DashRGBColor[j] = new Color((byte) c, DashRGBColor[j].B, DashRGBColor[j].G)
|
|
)),
|
|
(DashGItem = new TextMenuExt.IntSlider(
|
|
"AVALI_SKIN_BLUE".DialogOrKey(),
|
|
0, 255, DashRGBColor[j].G
|
|
).Change(
|
|
c => DashRGBColor[j] = new Color(DashRGBColor[j].R, (byte) c, DashRGBColor[j].G)
|
|
)),
|
|
(DashBItem = new TextMenuExt.IntSlider(
|
|
"AVALI_SKIN_GREEN".DialogOrKey(),
|
|
0, 255, DashRGBColor[j].B
|
|
).Change(
|
|
c => DashRGBColor[j] = new Color(DashRGBColor[j].R, DashRGBColor[j].B, (byte) c)
|
|
)),
|
|
(DashColorItem = new TextMenuExt.EnumSlider<ColorChoice>(
|
|
"AVALI_SKIN_COLOR".DialogOrKey(),
|
|
DashPreset[j]
|
|
).Change(c => DashPreset[j] = c)),
|
|
}
|
|
);
|
|
|
|
DashRGBItems.Add(DashRItem);
|
|
DashRGBItems.Add(DashGItem);
|
|
DashRGBItems.Add(DashBItem);
|
|
DashPresetItems.Add(DashColorItem);
|
|
}
|
|
|
|
menu.Add(ColorSubmenuItem);
|
|
}
|
|
|
|
|
|
// The following two settings DashRGB & DashPreset are not shown, but
|
|
// stored. They are set in the above submenu.
|
|
[SettingIgnore]
|
|
[YamlIgnore]
|
|
public List<Color> DashRGBColor { get; set; } = new List<Color> {
|
|
ColorUtil.SettingToColor(ColorChoice.BlueLight),
|
|
ColorUtil.SettingToColor(ColorChoice.Turquoise),
|
|
ColorUtil.SettingToColor(ColorChoice.Pink),
|
|
ColorUtil.SettingToColor(ColorChoice.BlueDark),
|
|
ColorUtil.SettingToColor(ColorChoice.Yellow),
|
|
ColorUtil.SettingToColor(ColorChoice.Red),
|
|
};
|
|
// this will get (de)serialized from/into a yaml list
|
|
[SettingIgnore]
|
|
public IEnumerable<string> DashRGB {
|
|
get => DashRGBColor.Select(c => ColorUtil.ColorToHex(c));
|
|
set {
|
|
DashRGBColor = value.Select(c => ColorUtil.HexToColor(c)).ToList();
|
|
}
|
|
}
|
|
// Stores submenu items that are enabled/disabled when colormode is RGB
|
|
private List<TextMenuExt.IntSlider> DashRGBItems = new List<TextMenuExt.IntSlider>();
|
|
|
|
|
|
[SettingIgnore]
|
|
public List<ColorChoice> DashPreset { get; set; } = new List<ColorChoice> {
|
|
ColorChoice.BlueLight,
|
|
ColorChoice.Turquoise,
|
|
ColorChoice.Pink,
|
|
ColorChoice.BlueDark,
|
|
ColorChoice.Yellow,
|
|
ColorChoice.Red,
|
|
};
|
|
// Stores submenu items that are enabled/disabled when colormode is preset
|
|
private List<TextMenu.Option<ColorChoice>> DashPresetItems = new List<TextMenu.Option<ColorChoice>>();
|
|
|
|
|
|
|
|
public bool EnableCelesteNet { get; set; } = true;
|
|
[YamlIgnore]
|
|
private TextMenu.Item EnableCelesteNetItem;
|
|
public void CreateEnableCelesteNetEntry(TextMenu menu, bool inGame) {
|
|
menu.Add(new TextMenu.SubHeader(
|
|
"modoptions_avaliskin_celestenet_header".DialogOrKey(), false
|
|
));
|
|
|
|
EnableCelesteNetItem = new TextMenu.OnOff(
|
|
"modoptions_avaliskin_celestenet".DialogOrKey(),
|
|
EnableCelesteNet
|
|
).Change(enabled => {
|
|
EnableCelesteNet = enabled;
|
|
updateOptions();
|
|
});
|
|
menu.Add(EnableCelesteNetItem);
|
|
|
|
if (!Everest.Loader.DependencyLoaded(AvaliSkinModule.CelesteNetMeta)) {
|
|
menu.Add(new TextMenu.SubHeader(
|
|
"modoptions_avaliskin_celestenet_nocelestenet".DialogOrKey(), false
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
public enum SendReceive {
|
|
SendReceive,
|
|
Send,
|
|
Receive,
|
|
None
|
|
}
|
|
|
|
public SendReceive CelesteNetSync { get; set; } = SendReceive.SendReceive;
|
|
[YamlIgnore]
|
|
private TextMenu.Item CelesteNetSyncItem;
|
|
public void CreateCelesteNetSyncEntry(TextMenu menu, bool inGame) {
|
|
CelesteNetSyncItem = new TextMenuExt.EnumerableSlider<SendReceive>(
|
|
"modoptions_avaliskin_celestenetsync".DialogOrKey(),
|
|
((SendReceive[]) Enum.GetValues(typeof(SendReceive))).Select(
|
|
variant => new KeyValuePair<SendReceive, string>(
|
|
variant,
|
|
$"modoptions_avaliskin_celestenetsync_{variant.ToString()}".DialogOrKey()
|
|
)
|
|
),
|
|
CelesteNetSync
|
|
).Change(opt => CelesteNetSync = opt);
|
|
menu.Add(CelesteNetSyncItem);
|
|
CelesteNetSyncItem.AddDescription(
|
|
menu,
|
|
"modoptions_avaliskin_celestenetsync_note".DialogOrKey()
|
|
);
|
|
}
|
|
|
|
public bool CelesteNetEveryoneHasSkin { get; set; } = false;
|
|
[YamlIgnore]
|
|
private TextMenu.Item CelesteNetEveryoneHasSkinItem;
|
|
public void CreateCelesteNetEveryoneHasSkinEntry(TextMenu menu, bool inGame) {
|
|
CelesteNetEveryoneHasSkinItem = new TextMenu.OnOff(
|
|
"modoptions_avaliskin_celesteneteveryonehasskin".DialogOrKey(),
|
|
CelesteNetEveryoneHasSkin
|
|
).Change(enabled => CelesteNetEveryoneHasSkin = enabled);
|
|
menu.Add(CelesteNetEveryoneHasSkinItem);
|
|
CelesteNetEveryoneHasSkinItem.AddDescription(
|
|
menu,
|
|
"modoptions_avaliskin_celesteneteveryonehasskin_note".DialogOrKey()
|
|
);
|
|
|
|
// call update options once the entire menu is loaded: this item is
|
|
// added last
|
|
updateOptions();
|
|
}
|
|
|
|
#endregion
|
|
|
|
public enum ColorChoice
|
|
{
|
|
Beige,
|
|
Black,
|
|
BlueDark,
|
|
BlueLight,
|
|
Brown,
|
|
Cyan,
|
|
GreenDark,
|
|
GreenLight,
|
|
GreyDark,
|
|
GreyLight,
|
|
Magenta,
|
|
Orange,
|
|
Pink,
|
|
Purple,
|
|
Red,
|
|
Turquoise,
|
|
White,
|
|
Yellow,
|
|
}
|
|
}
|
|
|
|
|
|
}
|