forked from new-frontiers-14/frontier-station-14
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AAC tablet for speech-impaired characters (new-frontiers-14#1491)
* basic AAC tablet prototype using station map as a base * set up aac component/system * quick phrase prototype will probably touch this up later * basic example phrases just so i have data to work with * get AACWindow to iterate over quick phrases * add the rest of the job phrases * fix this one job name * actually fix prison guard name * buttons for aac window * fix phrase inheritance * add tabs to aac contaner * fix column spacing and add button padding * aac tablet button colors * AAC tablet sends messages now * add aac tablet voice sound yay * add a 1 second cooldown between phrases * subjects for most departments * location phrases * more phrases * cleanup + sort buttons alphabetically * fix these phrases * even more departmental subject phrases * common phrases * cleanup imports * show name of player that pressed button * aac tablet can be used by multipel people after all it does not rely on state changes and also multiple people can press buttons on a tablet at once * capitalize aac its an acronym * you know what it is its more phrases!!!! * SAFETY PHRASES * last second phrases * redundant phrase * and one more hazard phrase for the road * change voice of aac tablet from borg to alto just sounds nicer * localize ALL Phrases i love utility scripting to automate tedious tasks * add AAC tablet to loadout * add AAC tablet to medfab * tweak: use multiple parents instead of whatever this is * add: justice department phrases * add: time quantity phrases * add: ores and kitchen appliance phrases * fix: resolve duplicate phrases * add: aac tablet sprites * add: justice button style * fix: misplaced this line oops * add: justice dept locations * remove: redundant phrase * re-run tests * fix: move aac tablet loadout format * fix: use Identity instead of Name for aac tablet sender * fix: return on send phrase if id is invalid * fix: remove redundant line * fix: use LocId instead of String for phrase text type * add: new phrases bc upstream updates * fix: newlines * tweak: add end comments to these style comments * fix: this phrase was broken lol --------- Co-authored-by: deltanedas <[email protected]>
- Loading branch information
Showing
49 changed files
with
3,934 additions
and
0 deletions.
There are no files selected for viewing
38 changes: 38 additions & 0 deletions
38
Content.Client/DeltaV/AACTablet/UI/AACBoundUserInterface.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using Content.Shared.DeltaV.AACTablet; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client.DeltaV.AACTablet.UI; | ||
|
||
public sealed class AACBoundUserInterface : BoundUserInterface | ||
{ | ||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; | ||
|
||
[ViewVariables] | ||
private AACWindow? _window; | ||
|
||
public AACBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) | ||
{ | ||
} | ||
|
||
protected override void Open() | ||
{ | ||
base.Open(); | ||
_window?.Close(); | ||
_window = new AACWindow(this, _prototypeManager); | ||
_window.OpenCentered(); | ||
|
||
_window.PhraseButtonPressed += OnPhraseButtonPressed; | ||
_window.OnClose += Close; | ||
} | ||
|
||
private void OnPhraseButtonPressed(string phraseId) | ||
{ | ||
SendMessage(new AACTabletSendPhraseMessage(phraseId)); | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
base.Dispose(disposing); | ||
_window?.Dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<controls:FancyWindow xmlns="https://spacestation14.io" | ||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" | ||
Title="AAC Tablet" | ||
Resizable="False" | ||
SetSize="540 300" | ||
MinSize="540 300"> | ||
<ScrollContainer HScrollEnabled="False" Name="WindowBody"> | ||
</ScrollContainer> | ||
</controls:FancyWindow> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
using System.Linq; | ||
using System.Numerics; | ||
using Content.Client.UserInterface.Controls; | ||
using Content.Shared.DeltaV.QuickPhrase; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.UserInterface; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client.DeltaV.AACTablet.UI; | ||
|
||
[GenerateTypedNameReferences] | ||
public sealed partial class AACWindow : FancyWindow | ||
{ | ||
private IPrototypeManager _prototypeManager; | ||
public event Action<string>? PhraseButtonPressed; | ||
|
||
public AACWindow(AACBoundUserInterface ui, IPrototypeManager prototypeManager) | ||
{ | ||
RobustXamlLoader.Load(this); | ||
_prototypeManager = prototypeManager; | ||
PopulateGui(ui); | ||
} | ||
|
||
private void PopulateGui(AACBoundUserInterface ui) | ||
{ | ||
var loc = IoCManager.Resolve<ILocalizationManager>(); | ||
var phrases = _prototypeManager.EnumeratePrototypes<QuickPhrasePrototype>().ToList(); | ||
|
||
// take ALL phrases and turn them into tabs and groups, so the buttons are sorted and tabbed | ||
var sortedTabs = phrases | ||
.GroupBy(p => p.Tab) | ||
.OrderBy(g => g.Key) | ||
.ToDictionary( | ||
g => g.Key, | ||
g => g.GroupBy(p => p.Group) | ||
.OrderBy(gg => gg.Key) | ||
.ToDictionary( | ||
gg => gg.Key, | ||
gg => gg.OrderBy(p => loc.GetString(p.Text)).ToList() | ||
) | ||
); | ||
|
||
var tabContainer = CreateTabContainer(sortedTabs); | ||
WindowBody.AddChild(tabContainer); | ||
} | ||
|
||
private TabContainer CreateTabContainer(Dictionary<string, Dictionary<string, List<QuickPhrasePrototype>>> sortedTabs) | ||
{ | ||
var tabContainer = new TabContainer(); | ||
var loc = IoCManager.Resolve<ILocalizationManager>(); | ||
|
||
foreach (var tab in sortedTabs) | ||
{ | ||
var tabName = loc.GetString(tab.Key); | ||
var boxContainer = CreateBoxContainerForTab(tab.Value); | ||
tabContainer.AddChild(boxContainer); | ||
tabContainer.SetTabTitle(tabContainer.ChildCount - 1, tabName); | ||
} | ||
|
||
return tabContainer; | ||
} | ||
|
||
private BoxContainer CreateBoxContainerForTab(Dictionary<string, List<QuickPhrasePrototype>> groups) | ||
{ | ||
var boxContainer = new BoxContainer() | ||
{ | ||
HorizontalExpand = true, | ||
Orientation = BoxContainer.LayoutOrientation.Vertical | ||
}; | ||
|
||
foreach (var group in groups) | ||
{ | ||
var buttonContainer = CreateButtonContainerForGroup(group.Value); | ||
boxContainer.AddChild(buttonContainer); | ||
} | ||
|
||
return boxContainer; | ||
} | ||
|
||
private GridContainer CreateButtonContainerForGroup(List<QuickPhrasePrototype> phrases) | ||
{ | ||
var loc = IoCManager.Resolve<ILocalizationManager>(); | ||
var buttonContainer = CreateButtonContainer(); | ||
foreach (var phrase in phrases) | ||
{ | ||
var text = loc.GetString(phrase.Text); | ||
var button = CreatePhraseButton(text, phrase.StyleClass); | ||
button.OnPressed += _ => OnPhraseButtonPressed(phrase.ID); | ||
buttonContainer.AddChild(button); | ||
} | ||
return buttonContainer; | ||
} | ||
|
||
private static GridContainer CreateButtonContainer() | ||
{ | ||
var buttonContainer = new GridContainer | ||
{ | ||
Margin = new Thickness(10), | ||
Columns = 4 | ||
}; | ||
|
||
return buttonContainer; | ||
} | ||
|
||
private static Button CreatePhraseButton(string text, string styleClass) | ||
{ | ||
var buttonWidth = GetButtonWidth(); | ||
var phraseButton = new Button | ||
{ | ||
Access = AccessLevel.Public, | ||
MaxSize = new Vector2(buttonWidth, buttonWidth), | ||
ClipText = false, | ||
HorizontalExpand = true, | ||
StyleClasses = { styleClass } | ||
}; | ||
|
||
var buttonLabel = new RichTextLabel | ||
{ | ||
Margin = new Thickness(0, 5), | ||
StyleClasses = { "WhiteText" } | ||
}; | ||
|
||
buttonLabel.SetMessage(text); | ||
phraseButton.AddChild(buttonLabel); | ||
return phraseButton; | ||
} | ||
|
||
private static int GetButtonWidth() | ||
{ | ||
var spaceWidth = 10; | ||
var parentWidth = 540; | ||
var columnCount = 4; | ||
|
||
var paddingSize = spaceWidth * 2; | ||
var gutterScale = (columnCount - 1) / columnCount; | ||
var columnWidth = (parentWidth - paddingSize) / columnCount; | ||
var buttonWidth = columnWidth - spaceWidth * gutterScale; | ||
return buttonWidth; | ||
} | ||
|
||
private void OnPhraseButtonPressed(string phraseId) | ||
{ | ||
PhraseButtonPressed?.Invoke(phraseId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace Content.Server.DeltaV.AACTablet; | ||
|
||
[RegisterComponent] | ||
public sealed partial class AACTabletComponent : Component | ||
{ | ||
// Minimum time between each phrase, to prevent spam | ||
[DataField] | ||
public TimeSpan Cooldown = TimeSpan.FromSeconds(1); | ||
|
||
// Time that the next phrase can be sent. | ||
[DataField] | ||
public TimeSpan NextPhrase; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using Content.Server.Chat.Systems; | ||
using Content.Shared.DeltaV.AACTablet; | ||
using Content.Shared.DeltaV.QuickPhrase; | ||
using Content.Shared.IdentityManagement; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Timing; | ||
|
||
namespace Content.Server.DeltaV.AACTablet; | ||
|
||
public sealed class AACTabletSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly ChatSystem _chat = default!; | ||
[Dependency] private readonly ILocalizationManager _loc = default!; | ||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; | ||
[Dependency] protected readonly IGameTiming Timing = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
SubscribeLocalEvent<AACTabletComponent, AACTabletSendPhraseMessage>(OnSendPhrase); | ||
} | ||
|
||
private void OnSendPhrase(EntityUid uid, AACTabletComponent component, AACTabletSendPhraseMessage message) | ||
{ | ||
if (component.NextPhrase > Timing.CurTime) | ||
return; | ||
|
||
// the AAC tablet uses the name of the person who pressed the tablet button | ||
// for quality of life | ||
var senderName = Identity.Entity(message.Actor, EntityManager); | ||
var speakerName = Loc.GetString("speech-name-relay", | ||
("speaker", Name(uid)), | ||
("originalName", senderName)); | ||
|
||
if (!_prototypeManager.TryIndex<QuickPhrasePrototype>(message.PhraseID, out var phrase)) | ||
return; | ||
|
||
_chat.TrySendInGameICMessage(uid, | ||
_loc.GetString(phrase.Text), | ||
InGameICChatType.Speak, | ||
hideChat: false, | ||
nameOverride: speakerName); | ||
|
||
var curTime = Timing.CurTime; | ||
component.NextPhrase = curTime + component.Cooldown; | ||
} | ||
} |
Oops, something went wrong.