Skip to content

Commit

Permalink
feat: Support changing color in-game
Browse files Browse the repository at this point in the history
  • Loading branch information
WEGFan committed Jan 9, 2022
1 parent a499cfb commit 9d8de8c
Show file tree
Hide file tree
Showing 5 changed files with 661 additions and 12 deletions.
51 changes: 39 additions & 12 deletions Code/TrailineSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Celeste.Mod.Trailine.Modules;
using Celeste.Mod.Trailine.UI;
using Celeste.Mod.Trailine.Utils;
using Celeste.Mod.UI;
using Microsoft.Xna.Framework;
using Monocle;
using MonoMod.Utils;
Expand Down Expand Up @@ -41,7 +40,6 @@ public float TrailDuration {
set => TrailDurationSliderValue = Calc.Clamp((int)Math.Round(value * 20), 1, 60 * 20);
}


[YamlIgnore]
public int TrailOpacitySliderValue { get; set; } = (int)(0.8 * 20);

Expand Down Expand Up @@ -200,19 +198,49 @@ public void CreatePatternEntries(TextMenu textMenu, bool inGame) {
CurrentPattern.DurationSliderValue = value;
}));
for (int i = 0; i < CurrentPattern.ColorStops.Count; i++) {
int index = i;

ColorStop colorStop = CurrentPattern.ColorStops[i];
TextMenuExt.SubMenu subMenu = new TextMenuExt.SubMenu($"Color {i + 1}: {ColorUtils.ColorToHex(colorStop.Color)}", false);

subMenu.Add(new TextMenu.Button($"Color: {ColorUtils.ColorToHex(colorStop.Color)}") {
Disabled = inGame
subMenu.Add(new TextInputButton("Color", ColorUtils.ColorToHex(colorStop.Color).Trim('#'), 6, 6) {
Disabled = false,
LetterChars = string.Join("\n",
"0 1 2 3",
"4 5 6 7",
"8 9 A B",
"C D E F"
)
}
.Pressed(() => {
Audio.Play("event:/ui/main/savefile_rename_start");
textMenu.SceneAs<Overworld>().Goto<OuiModOptionString>()
.Init<OuiModOptions>(ColorUtils.ColorToHex(colorStop.Color).TrimStart('#'),
value => {
colorStop.Color = Calc.HexToColor(value);
}, 6, 6);
.Apply(it => {
it.Pressed(() => {
// temporary fix for pressing a button in a submenu item which goes to another menu
// in this case, textMenu.Focused is false but subMenu.Focused is true
// so the button can be pressed multiple times and cause issues
subMenu.Focused = false;
});
it.Change(value => {
colorStop.Color = Calc.HexToColor(value);
});
it.OnMenuExit += confirm => {
subMenu.Focused = true;
if (!confirm) {
return;
}

subMenu.Exit();
RecreatePatternEntries(textMenu, inGame);
textMenu.MoveSelection(0);
if (textMenu.Current is TextMenuExt.SubMenu selectedSubMenu) {
string originalConfirmSfx = selectedSubMenu.ConfirmSfx;
selectedSubMenu.ConfirmSfx = SFX.NONE;
selectedSubMenu.ConfirmPressed();
selectedSubMenu.ConfirmSfx = originalConfirmSfx;
new DynData<TextMenuExt.SubMenu>(selectedSubMenu).Set("ease", 1f);
selectedSubMenu.Selection = -1;
selectedSubMenu.MoveSelection(1);
}
};
}));

if (i != 0) {
Expand All @@ -222,7 +250,6 @@ public void CreatePatternEntries(TextMenu textMenu, bool inGame) {
}));
}

int index = i;
subMenu.Add(new TextMenu.Button("Move Up") {
Disabled = i == 0
}
Expand Down
62 changes: 62 additions & 0 deletions Code/UI/OuiTextInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Collections;
using Celeste.Mod.UI;
using Microsoft.Xna.Framework;
using Monocle;

namespace Celeste.Mod.Trailine.UI {
public class OuiTextInput : Oui, OuiModOptions.ISubmenu {

private const float OnScreenX = 0f;
private const float OffScreenX = 1920f;

private TextInputMenu menu;
private float alpha;

public TextInputMenu Init(TextInputMenu menu) {
this.menu = menu;
return menu;
}

public override IEnumerator Enter(Oui from) {
Overworld.ShowInputUI = false;
Scene.Add(menu);

Visible = true;
menu.Visible = true;
menu.Focused = false;

for (float p = 0f; p < 1f; p += Engine.DeltaTime * 4f) {
menu.X = OffScreenX + -1920f * Ease.CubeOut(p);
alpha = Ease.CubeOut(p);
yield return null;
}
alpha = 1f;

menu.Focused = true;
}

public override IEnumerator Leave(Oui next) {
Audio.Play(SFX.ui_main_whoosh_large_out);
menu.Focused = false;
Overworld.ShowInputUI = true;

for (float p = 0f; p < 1f; p += Engine.DeltaTime * 4f) {
menu.X = OnScreenX + 1920f * Ease.CubeIn(p);
alpha = 1f - Ease.CubeIn(p);
yield return null;
}

menu.Visible = Visible = false;
menu.RemoveSelf();
menu = null;
}

public override void Render() {
if (alpha > 0f) {
Draw.Rect(-10f, -10f, 1940f, 1100f, Color.Black * alpha * 0.4f);
}
base.Render();
}

}
}
99 changes: 99 additions & 0 deletions Code/UI/TextInputButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using Celeste.Mod.Trailine.Utils;
using Microsoft.Xna.Framework;

namespace Celeste.Mod.Trailine.UI {
public class TextInputButton : TextMenu.Item {

public bool AlwaysCenter;
public string Label;
public int MinValueLength;
public int MaxValueLength;
public string Value;
public string LetterChars;

public Action<string> OnValueChange;
public Action<bool> OnMenuExit;

public string ButtonLabel => $"{Label}: {Value}";

public TextInputButton(string label, string value, int minValueLength = 1, int maxValueLength = 12) {
Label = label;
Value = value;
MinValueLength = Math.Max(minValueLength, 1);
MaxValueLength = Math.Max(maxValueLength, 1);
Selectable = true;
LetterChars = string.Join("\n",
"ABCDEFGHI abcdefghi",
"JKLMNOPQR jklmnopqr",
"STUVWXYZ stuvwxyz",
"1234567890+=:~!@$%",
"^&*_-#\"'()<>/\\.,|`"
);
}

public TextInputButton Change(Action<string> action) {
OnValueChange = action;
return this;
}

public TextInputButton MenuExit(Action<bool> action) {
OnMenuExit = action;
return this;
}

public override void ConfirmPressed() {
Audio.Play(SFX.ui_main_button_select);

TextInputMenu textInputMenu = new TextInputMenu(Value, OnValueChange, MinValueLength, MaxValueLength) {
LetterChars = LetterChars
};
switch (Container.Scene) {
case Overworld overworld: {
textInputMenu.OnExit += confirm => {
overworld.Goto(overworld.Last.GetType());
};
overworld.Goto<OuiTextInput>().Init(textInputMenu);
break;
}
case Level level: {
Container.RemoveSelf();

// notify the pause menu that we aren't in the main menu anymore (hides the strawberry tracker)
bool comesFromPauseMainMenu = level.PauseMainMenuOpen;
level.PauseMainMenuOpen = false;

textInputMenu.OnExit += confirm => {
textInputMenu.RemoveSelf();
level.Add(Container);
level.PauseMainMenuOpen = comesFromPauseMainMenu;
};

// add the menu to the scene
level.Add(textInputMenu);
break;
}
}
textInputMenu.OnExit += OnMenuExit;
}

public override float LeftWidth() {
return ActiveFont.Measure(ButtonLabel).X;
}

public override float Height() {
return ActiveFont.LineHeight;
}

public override void Render(Vector2 position, bool highlighted) {
float alpha = Container.Alpha;
Color color = Disabled ? Color.DarkSlateGray : (highlighted ? Container.HighlightColor : Color.White) * alpha;
Color strokeColor = Color.Black * (alpha * alpha * alpha);
bool center = Container.InnerContent == TextMenu.InnerContentMode.TwoColumn && !AlwaysCenter;
Vector2 position2 = position + (center ? Vector2.Zero : new Vector2(Container.Width * 0.5f, 0f));
Vector2 justify = center && !AlwaysCenter ? new Vector2(0f, 0.5f) : new Vector2(0.5f, 0.5f);
ActiveFont.DrawOutline(ButtonLabel, position2, justify, Vector2.One, color, 2f, strokeColor);
}

}
}
Loading

0 comments on commit 9d8de8c

Please sign in to comment.