Made Load Game Menu accessible, organised code
parent
d8c088b9ec
commit
a513a14ca0
|
@ -5,7 +5,7 @@ namespace stardew_access.Game
|
|||
{
|
||||
internal class CurrentPlayer
|
||||
{
|
||||
private static Farmer player = null;
|
||||
private static Farmer? player = null;
|
||||
|
||||
CurrentPlayer()
|
||||
{
|
||||
|
@ -40,5 +40,23 @@ namespace stardew_access.Game
|
|||
|
||||
return staminaPercentage;
|
||||
}
|
||||
|
||||
public static int getPositionX()
|
||||
{
|
||||
if (player == null)
|
||||
initPlayer();
|
||||
|
||||
int x = (int)player.getTileLocation().X;
|
||||
return x;
|
||||
}
|
||||
|
||||
public static int getPositionY()
|
||||
{
|
||||
if (player == null)
|
||||
initPlayer();
|
||||
|
||||
int y = (int)player.getTileLocation().Y;
|
||||
return y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,20 @@
|
|||
using AccessibleOutput;
|
||||
using stardew_access.Game;
|
||||
using stardew_access.Game;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
using HarmonyLib;
|
||||
using StardewValley.Menus;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Text;
|
||||
using StardewValley.BellsAndWhistles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using stardew_access.Patches;
|
||||
|
||||
namespace stardew_access
|
||||
{
|
||||
/// <summary>The mod entry point.</summary>
|
||||
|
||||
public class MainClass : Mod
|
||||
{
|
||||
public static IAccessibleOutput screenReader;
|
||||
Harmony harmony;
|
||||
public static IMonitor monitor;
|
||||
private static string prevText = "";
|
||||
private static DialogueBox? dialogueBox = null;
|
||||
private int index = 0;
|
||||
private Harmony? harmony;
|
||||
public static IMonitor? monitor;
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
|
@ -32,7 +26,7 @@ namespace stardew_access
|
|||
monitor = Monitor;
|
||||
|
||||
// Initialize the screen reader
|
||||
initializeScreenReader();
|
||||
ScreenReader.initializeScreenReader();
|
||||
|
||||
// Init harmony
|
||||
harmony = new Harmony(ModManifest.UniqueID);
|
||||
|
@ -40,225 +34,29 @@ namespace stardew_access
|
|||
// Add patches
|
||||
harmony.Patch(
|
||||
original: AccessTools.Method(typeof(DialogueBox), nameof(DialogueBox.draw), new Type[] {typeof(SpriteBatch)}),
|
||||
postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.DialoguePatch))
|
||||
postfix: new HarmonyMethod(typeof(DialoguePatch), nameof(DialoguePatch.CharachterDialoguePatch))
|
||||
);
|
||||
|
||||
harmony.Patch(
|
||||
original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawHoverText), new Type[] { typeof(SpriteBatch), typeof(string), typeof(SpriteFont), typeof(int), typeof(int), typeof(int) , typeof(string) , typeof(int) , typeof(string[]) , typeof(Item) , typeof(int) , typeof(int), typeof(int), typeof(int), typeof(int), typeof(float), typeof(CraftingRecipe) , typeof(IList < Item >) }),
|
||||
postfix: new HarmonyMethod(typeof(MainClass), nameof(MainClass.HoverTextPatch))
|
||||
postfix: new HarmonyMethod(typeof(DialoguePatch), nameof(DialoguePatch.HoverTextPatch))
|
||||
);
|
||||
|
||||
harmony.Patch(
|
||||
original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.draw) , new Type[] {typeof(SpriteBatch)}),
|
||||
postfix: new HarmonyMethod(typeof(MainClass), nameof(TitleMenuPatch))
|
||||
postfix: new HarmonyMethod(typeof(MenuPatch), nameof(MenuPatch.TitleMenuPatch))
|
||||
);
|
||||
|
||||
harmony.Patch(
|
||||
original: AccessTools.Method(typeof(LoadGameMenu.SaveFileSlot), nameof(LoadGameMenu.SaveFileSlot.Draw), new Type[] { typeof(SpriteBatch), typeof(int) }),
|
||||
postfix: new HarmonyMethod(typeof(MenuPatch), nameof(MenuPatch.LoadGameMenuPatch))
|
||||
);
|
||||
|
||||
helper.Events.Input.ButtonPressed += this.OnButtonPressed;
|
||||
//helper.Events.GameLoop.OneSecondUpdateTicked += this.OnOneSecondUpdateTicked;
|
||||
}
|
||||
|
||||
private static void TitleMenuPatch(TitleMenu __instance, SpriteBatch b)
|
||||
{
|
||||
try
|
||||
{
|
||||
__instance.allClickableComponents.ForEach(component =>
|
||||
{
|
||||
if(component.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
string name = component.name;
|
||||
string label = component.label;
|
||||
string toSpeak = $"{name} {label}";
|
||||
|
||||
if(prevText != toSpeak)
|
||||
{
|
||||
prevText = toSpeak;
|
||||
screenReader.Speak(toSpeak, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static void DialoguePatch(DialogueBox __instance, SpriteBatch b)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dialogue dialogue = __instance.characterDialogue;
|
||||
string speakerName = dialogue.speaker.Name;
|
||||
List<string> dialogues = dialogue.dialogues;
|
||||
int dialogueIndex = dialogue.currentDialogueIndex;
|
||||
monitor.Log("" + dialogue.isCurrentStringContinuedOnNextScreen, LogLevel.Debug);
|
||||
|
||||
if (prevText != $"{speakerName} said, {dialogues[dialogueIndex]}")
|
||||
{
|
||||
prevText = $"{speakerName} said, {dialogues[dialogueIndex]}";
|
||||
screenReader.Speak($"{speakerName} said, {dialogues[dialogueIndex]}", false);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnOneSecondUpdateTicked(object sender, OneSecondUpdateTickedEventArgs e)
|
||||
{
|
||||
if (Game1.activeClickableMenu != null)
|
||||
{
|
||||
string name = Game1.activeClickableMenu.getCurrentlySnappedComponent().name;
|
||||
string label = Game1.activeClickableMenu.getCurrentlySnappedComponent().label;
|
||||
string toSpeeak = $"{name} {label}";
|
||||
|
||||
if (prevText != toSpeeak)
|
||||
{
|
||||
prevText = toSpeeak;
|
||||
screenReader.Speak(toSpeeak, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void HoverTextPatch(SpriteBatch b, string text, SpriteFont font, int xOffset = 0, int yOffset = 0, int moneyAmountToDisplayAtBottom = -1, string boldTitleText = null, int healAmountToDisplay = -1, string[] buffIconsToDisplay = null, Item hoveredItem = null, int currencySymbol = 0, int extraItemToShowIndex = -1, int extraItemToShowAmount = -1, int overrideX = -1, int overrideY = -1, float alpha = 1f, CraftingRecipe craftingIngredients = null, IList<Item> additional_craft_materials = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder toSpeak = new StringBuilder();
|
||||
|
||||
#region Add title if any
|
||||
if (boldTitleText != null)
|
||||
toSpeak.Append($"{boldTitleText}.\n");
|
||||
#endregion
|
||||
|
||||
#region Add the base text
|
||||
toSpeak.Append(text);
|
||||
#endregion
|
||||
|
||||
#region Add crafting ingredients
|
||||
if (craftingIngredients != null)
|
||||
{
|
||||
|
||||
toSpeak.Append($"\n{craftingIngredients.description}");
|
||||
toSpeak.Append("\nIngredients\n");
|
||||
|
||||
craftingIngredients.recipeList.ToList().ForEach(recipe =>
|
||||
{
|
||||
int count = recipe.Value;
|
||||
int item = recipe.Key;
|
||||
string name = craftingIngredients.getNameFromIndex(item);
|
||||
|
||||
toSpeak.Append($" ,{count} {name}");
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add health & stamina
|
||||
if (hoveredItem is StardewValley.Object && (hoveredItem as StardewValley.Object).Edibility != -300)
|
||||
{
|
||||
int stamina_recovery = (hoveredItem as StardewValley.Object).staminaRecoveredOnConsumption();
|
||||
toSpeak.Append($"{stamina_recovery} Energy\n");
|
||||
if (stamina_recovery >= 0)
|
||||
{
|
||||
int health_recovery = (hoveredItem as StardewValley.Object).healthRecoveredOnConsumption();
|
||||
toSpeak.Append($"{health_recovery} Health");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add buff items (effects like +1 walking speed)
|
||||
if (buffIconsToDisplay != null)
|
||||
{
|
||||
for (int i = 0; i < buffIconsToDisplay.Length; i++)
|
||||
{
|
||||
string buffName = ((Convert.ToInt32(buffIconsToDisplay[i]) > 0) ? "+" : "") + buffIconsToDisplay[i] + " ";
|
||||
if (i <= 11)
|
||||
{
|
||||
buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + i, buffName);
|
||||
}
|
||||
try
|
||||
{
|
||||
int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' ')));
|
||||
monitor.Log("" + count);
|
||||
if (count != 0)
|
||||
toSpeak.Append($"{buffName}\n");
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add money
|
||||
if (moneyAmountToDisplayAtBottom != -1)
|
||||
toSpeak.Append($"\nValue: {moneyAmountToDisplayAtBottom} coins\n");
|
||||
#endregion
|
||||
|
||||
#region Narrate toSpeak
|
||||
if (prevText != toSpeak.ToString())
|
||||
{
|
||||
prevText = toSpeak.ToString();
|
||||
screenReader.Speak(toSpeak.ToString(), true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeScreenReader()
|
||||
{
|
||||
NvdaOutput nvdaOutput = null;
|
||||
JawsOutput jawsOutput = null;
|
||||
SapiOutput sapiOutput = null;
|
||||
|
||||
// Initialize NVDA
|
||||
try{
|
||||
nvdaOutput = new NvdaOutput();
|
||||
}catch(Exception ex){
|
||||
Monitor.Log($"Error initializing NVDA:\n{ex.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
// Initialize JAWS
|
||||
try
|
||||
{
|
||||
jawsOutput = new JawsOutput();
|
||||
}catch (Exception ex){
|
||||
Monitor.Log($"Error initializing JAWS:\n{ex.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
// Initialize SAPI
|
||||
try
|
||||
{
|
||||
sapiOutput = new SapiOutput();
|
||||
}catch (Exception ex){
|
||||
Monitor.Log($"Error initializing SAPI:\n{ex.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
if (nvdaOutput != null && nvdaOutput.IsAvailable())
|
||||
screenReader = nvdaOutput;
|
||||
|
||||
if(jawsOutput != null && jawsOutput.IsAvailable())
|
||||
screenReader = jawsOutput;
|
||||
|
||||
if (sapiOutput != null && sapiOutput.IsAvailable())
|
||||
screenReader = sapiOutput;
|
||||
}
|
||||
|
||||
private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
|
||||
{
|
||||
if (Equals(e.Button, SButton.K))
|
||||
{
|
||||
if (Game1.activeClickableMenu != null)
|
||||
{
|
||||
string name = Game1.activeClickableMenu.getCurrentlySnappedComponent().label;
|
||||
screenReader.Speak(name, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ignore if player hasn't loaded a save yet
|
||||
if (!Context.IsWorldReady)
|
||||
return;
|
||||
|
@ -266,7 +64,15 @@ namespace stardew_access
|
|||
// Narrate Health And Energy
|
||||
if (Equals(e.Button, SButton.I))
|
||||
{
|
||||
screenReader.Speak($"Health is {CurrentPlayer.getHealth()} and Stamina is {CurrentPlayer.getStamina()}");
|
||||
string toSpeak = $"Health is {CurrentPlayer.getHealth()} and Stamina is {CurrentPlayer.getStamina()}";
|
||||
ScreenReader.say(toSpeak, true);
|
||||
}
|
||||
|
||||
// Narrate Position
|
||||
if (Equals(e.Button, SButton.K))
|
||||
{
|
||||
string toSpeak = $"X: {CurrentPlayer.getPositionX()} , Y: {CurrentPlayer.getPositionX()}";
|
||||
ScreenReader.say(toSpeak, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
using Microsoft.Xna.Framework.Graphics;
|
||||
using StardewModdingAPI;
|
||||
using StardewValley;
|
||||
using StardewValley.Menus;
|
||||
using System.Text;
|
||||
|
||||
namespace stardew_access.Patches
|
||||
{
|
||||
internal class DialoguePatch
|
||||
{
|
||||
public static void CharachterDialoguePatch(DialogueBox __instance, SpriteBatch b)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dialogue dialogue = __instance.characterDialogue;
|
||||
string speakerName = dialogue.speaker.Name;
|
||||
List<string> dialogues = dialogue.dialogues;
|
||||
int dialogueIndex = dialogue.currentDialogueIndex;
|
||||
MainClass.monitor.Log("" + dialogue.isCurrentStringContinuedOnNextScreen, LogLevel.Debug);
|
||||
string toSpeak = $"{speakerName} said, {dialogues[dialogueIndex]}";
|
||||
|
||||
ScreenReader.sayWithChecker(toSpeak, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void HoverTextPatch(string? text, int moneyAmountToDisplayAtBottom = -1, string? boldTitleText = null, string[]? buffIconsToDisplay = null, Item? hoveredItem = null, CraftingRecipe? craftingIngredients = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder toSpeak = new StringBuilder();
|
||||
|
||||
#region Add title if any
|
||||
if (boldTitleText != null)
|
||||
toSpeak.Append($"{boldTitleText}.\n");
|
||||
#endregion
|
||||
|
||||
#region Add the base text
|
||||
toSpeak.Append(text);
|
||||
#endregion
|
||||
|
||||
#region Add crafting ingredients
|
||||
if (craftingIngredients != null)
|
||||
{
|
||||
|
||||
toSpeak.Append($"\n{craftingIngredients.description}");
|
||||
toSpeak.Append("\nIngredients\n");
|
||||
|
||||
craftingIngredients.recipeList.ToList().ForEach(recipe =>
|
||||
{
|
||||
int count = recipe.Value;
|
||||
int item = recipe.Key;
|
||||
string name = craftingIngredients.getNameFromIndex(item);
|
||||
|
||||
toSpeak.Append($" ,{count} {name}");
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add health & stamina
|
||||
if (hoveredItem is StardewValley.Object && (hoveredItem as StardewValley.Object).Edibility != -300)
|
||||
{
|
||||
int stamina_recovery = (hoveredItem as StardewValley.Object).staminaRecoveredOnConsumption();
|
||||
toSpeak.Append($"{stamina_recovery} Energy\n");
|
||||
if (stamina_recovery >= 0)
|
||||
{
|
||||
int health_recovery = (hoveredItem as StardewValley.Object).healthRecoveredOnConsumption();
|
||||
toSpeak.Append($"{health_recovery} Health");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add buff items (effects like +1 walking speed)
|
||||
if (buffIconsToDisplay != null)
|
||||
{
|
||||
for (int i = 0; i < buffIconsToDisplay.Length; i++)
|
||||
{
|
||||
string buffName = ((Convert.ToInt32(buffIconsToDisplay[i]) > 0) ? "+" : "") + buffIconsToDisplay[i] + " ";
|
||||
if (i <= 11)
|
||||
{
|
||||
buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + i, buffName);
|
||||
}
|
||||
try
|
||||
{
|
||||
int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' ')));
|
||||
MainClass.monitor.Log("" + count);
|
||||
if (count != 0)
|
||||
toSpeak.Append($"{buffName}\n");
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add money
|
||||
if (moneyAmountToDisplayAtBottom != -1)
|
||||
toSpeak.Append($"\nValue: {moneyAmountToDisplayAtBottom} coins\n");
|
||||
#endregion
|
||||
|
||||
#region Narrate toSpeak
|
||||
ScreenReader.sayWithChecker(toSpeak.ToString(), true);
|
||||
#endregion
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"Unable to narrate dialog:\n{e.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using StardewModdingAPI;
|
||||
using StardewValley;
|
||||
using StardewValley.Menus;
|
||||
|
||||
namespace stardew_access.Patches
|
||||
{
|
||||
internal class MenuPatch
|
||||
{
|
||||
|
||||
public static void TitleMenuPatch(TitleMenu __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
string toSpeak = "";
|
||||
|
||||
__instance.buttons.ForEach(component =>
|
||||
{
|
||||
if (component.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
string name = component.name;
|
||||
string label = component.label;
|
||||
toSpeak = $"{name} {label} Button";
|
||||
}
|
||||
});
|
||||
|
||||
if(__instance.muteMusicButton.containsPoint(Game1.getMousePosition(true).X,Game1.getMousePosition(true).Y))
|
||||
{
|
||||
toSpeak = "Mute Music Button";
|
||||
}
|
||||
|
||||
if (__instance.aboutButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
toSpeak = "About Button";
|
||||
}
|
||||
|
||||
if (__instance.languageButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
toSpeak = "Language Button";
|
||||
}
|
||||
|
||||
if (__instance.windowedButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
toSpeak = "Fullscreen toggle Button";
|
||||
}
|
||||
|
||||
if (TitleMenu.subMenu != null && __instance.backButton.containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
string text = "Back Button";
|
||||
ScreenReader.sayWithChecker(text, true);
|
||||
}
|
||||
|
||||
if (TitleMenu.subMenu == null && toSpeak != "")
|
||||
ScreenReader.sayWithChecker(toSpeak, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadGameMenuPatch(LoadGameMenu.SaveFileSlot __instance, LoadGameMenu ___menu, int i)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (___menu.slotButtons[i].containsPoint(Game1.getMousePosition(true).X, Game1.getMousePosition(true).Y))
|
||||
{
|
||||
if (__instance.Farmer == null)
|
||||
return;
|
||||
|
||||
String farmerName = __instance.Farmer.Name;
|
||||
String farmName = __instance.Farmer.farmName;
|
||||
String money = __instance.Farmer.Money.ToString();
|
||||
String hoursPlayed = Utility.getHoursMinutesStringFromMilliseconds(__instance.Farmer.millisecondsPlayed);
|
||||
string dateStringForSaveGame = ((!__instance.Farmer.dayOfMonthForSaveGame.HasValue ||
|
||||
!__instance.Farmer.seasonForSaveGame.HasValue ||
|
||||
!__instance.Farmer.yearForSaveGame.HasValue) ? __instance.Farmer.dateStringForSaveGame : Utility.getDateStringFor(__instance.Farmer.dayOfMonthForSaveGame.Value, __instance.Farmer.seasonForSaveGame.Value, __instance.Farmer.yearForSaveGame.Value));
|
||||
|
||||
string toSpeak = $"{farmName} Farm, \t\n Farmer:{farmerName}, \t\nMoney:{money}, \t\nHours Played:{hoursPlayed}, \t\nDate:{dateStringForSaveGame}";
|
||||
|
||||
ScreenReader.sayWithChecker(toSpeak, true);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MainClass.monitor.Log($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
using AccessibleOutput;
|
||||
using StardewModdingAPI;
|
||||
|
||||
namespace stardew_access
|
||||
{
|
||||
internal class ScreenReader
|
||||
{
|
||||
public static IAccessibleOutput? screenReader = null;
|
||||
private static string prevText = "";
|
||||
|
||||
public static void initializeScreenReader()
|
||||
{
|
||||
NvdaOutput? nvdaOutput = null;
|
||||
JawsOutput? jawsOutput = null;
|
||||
SapiOutput? sapiOutput = null;
|
||||
|
||||
// Initialize NVDA
|
||||
try
|
||||
{
|
||||
nvdaOutput = new NvdaOutput();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MainClass.monitor.Log($"Error initializing NVDA:\n{ex.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
// Initialize JAWS
|
||||
try
|
||||
{
|
||||
jawsOutput = new JawsOutput();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MainClass.monitor.Log($"Error initializing JAWS:\n{ex.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
// Initialize SAPI
|
||||
try
|
||||
{
|
||||
sapiOutput = new SapiOutput();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MainClass.monitor.Log($"Error initializing SAPI:\n{ex.StackTrace}", LogLevel.Error);
|
||||
}
|
||||
|
||||
if (nvdaOutput != null && nvdaOutput.IsAvailable())
|
||||
screenReader = nvdaOutput;
|
||||
|
||||
if (jawsOutput != null && jawsOutput.IsAvailable())
|
||||
screenReader = jawsOutput;
|
||||
|
||||
if (sapiOutput != null && sapiOutput.IsAvailable())
|
||||
screenReader = sapiOutput;
|
||||
}
|
||||
|
||||
public static void say(string text, bool interrupt)
|
||||
{
|
||||
if (screenReader == null)
|
||||
return;
|
||||
|
||||
screenReader.Speak(text, interrupt);
|
||||
}
|
||||
|
||||
public static void sayWithChecker(string text, bool interrupt)
|
||||
{
|
||||
if (screenReader == null)
|
||||
return;
|
||||
|
||||
if (prevText != text)
|
||||
{
|
||||
prevText = text;
|
||||
screenReader.Speak(text, interrupt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue