Add popup UI method to Client
This commit is contained in:
parent
926d968eed
commit
ea8a9184bc
3 changed files with 163 additions and 0 deletions
|
@ -1,8 +1,12 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
|
||||
using RobocraftX.Services;
|
||||
using UnityEngine;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using RobocraftX.Common;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
|
@ -14,6 +18,12 @@ namespace GamecraftModdingAPI.App
|
|||
// extensible engine
|
||||
protected static AppEngine appEngine = new AppEngine();
|
||||
|
||||
protected static Func<object> ErrorHandlerInstanceGetter;
|
||||
|
||||
protected static Action<object, Error> EnqueueError;
|
||||
|
||||
protected static Action<object> HandleErrorClosed;
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires whenever the main menu is loaded.
|
||||
/// </summary>
|
||||
|
@ -74,9 +84,76 @@ namespace GamecraftModdingAPI.App
|
|||
get => appEngine.IsInMenu;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open a popup which prompts the user to click a button.
|
||||
/// This reuses Gamecraft's error dialog popup
|
||||
/// </summary>
|
||||
/// <param name="popup">The popup to display. Use an instance of SingleChoicePrompt or DualChoicePrompt.</param>
|
||||
public void PromptUser(Error popup)
|
||||
{
|
||||
// if the stuff wasn't mostly set to internal, this would be written as:
|
||||
// RobocraftX.Services.ErrorHandler.Instance.EqueueError(error);
|
||||
object errorHandlerInstance = ErrorHandlerInstanceGetter();
|
||||
EnqueueError(errorHandlerInstance, popup);
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*public void CloseCurrentPrompt()
|
||||
{
|
||||
// RobocraftX.Services.ErrorHandler.Instance.HandlePopupClosed();
|
||||
// FIXME: this is a call that is also called when closing, not the actual closing action itself (so it doesn't work)
|
||||
object errorHandlerInstance = ErrorHandlerInstanceGetter();
|
||||
HandleErrorClosed(errorHandlerInstance);
|
||||
}*/
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
// this would have been so much simpler if this didn't involve a bunch of internal fields & classes
|
||||
Type errorHandler = AccessTools.TypeByName("RobocraftX.Services.ErrorHandler");
|
||||
Type errorHandle = AccessTools.TypeByName("RobocraftX.Services.ErrorHandle");
|
||||
ErrorHandlerInstanceGetter = (Func<object>) AccessTools.Method("GamecraftModdingAPI.App.Client:GenInstanceGetter")
|
||||
.MakeGenericMethod(errorHandler)
|
||||
.Invoke(null, new object[0]);
|
||||
EnqueueError = (Action<object, Error>) AccessTools.Method("GamecraftModdingAPI.App.Client:GenEnqueueError")
|
||||
.MakeGenericMethod(errorHandler, errorHandle)
|
||||
.Invoke(null, new object[0]);
|
||||
/*HandleErrorClosed = (Action<object>) AccessTools.Method("GamecraftModdingAPI.App.Client:GenHandlePopupClosed")
|
||||
.MakeGenericMethod(errorHandler)
|
||||
.Invoke(null, new object[0]);*/
|
||||
// register engines
|
||||
MenuEngineManager.AddMenuEngine(appEngine);
|
||||
}
|
||||
|
||||
// Creating delegates once is faster than reflection every time
|
||||
// Admittedly, this way is more difficult to code and less readable
|
||||
private static Func<object> GenInstanceGetter<T>()
|
||||
{
|
||||
Type errorHandler = AccessTools.TypeByName("RobocraftX.Services.ErrorHandler");
|
||||
MethodInfo instance = AccessTools.PropertyGetter(errorHandler, "Instance");
|
||||
Func<T> getterSimple = (Func<T>) Delegate.CreateDelegate(typeof(Func<T>), null, instance);
|
||||
Func<object> getterCasted = () => (object) getterSimple();
|
||||
return getterCasted;
|
||||
}
|
||||
|
||||
private static Action<object, Error> GenEnqueueError<T, TRes>()
|
||||
{
|
||||
Type errorHandler = AccessTools.TypeByName("RobocraftX.Services.ErrorHandler");
|
||||
MethodInfo enqueueError = AccessTools.Method(errorHandler, "EnqueueError");
|
||||
Func<T, Error, TRes> enqueueSimple =
|
||||
(Func<T, Error, TRes>) Delegate.CreateDelegate(typeof(Func<T, Error, TRes>), enqueueError);
|
||||
Action<object, Error> enqueueCasted =
|
||||
(object instance, Error error) => { enqueueSimple((T) instance, error); };
|
||||
return enqueueCasted;
|
||||
}
|
||||
|
||||
private static Action<object> GenHandlePopupClosed<T>()
|
||||
{
|
||||
Type errorHandler = AccessTools.TypeByName("RobocraftX.Services.ErrorHandler");
|
||||
MethodInfo handlePopupClosed = AccessTools.Method(errorHandler, "HandlePopupClosed");
|
||||
Action<T> handleSimple =
|
||||
(Action<T>) Delegate.CreateDelegate(typeof(Action<T>), handlePopupClosed);
|
||||
Action<object> handleCasted = (object instance) => handleSimple((T) instance);
|
||||
return handleCasted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
59
GamecraftModdingAPI/App/ClientAlertTest.cs
Normal file
59
GamecraftModdingAPI/App/ClientAlertTest.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using HarmonyLib;
|
||||
|
||||
using RobocraftX.Services;
|
||||
|
||||
using GamecraftModdingAPI.Tests;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
#if TEST
|
||||
/// <summary>
|
||||
/// Client popups tests.
|
||||
/// Only available in TEST builds.
|
||||
/// </summary>
|
||||
[APITestClass]
|
||||
public static class ClientAlertTest
|
||||
{
|
||||
private static DualChoicePrompt popup2 = null;
|
||||
|
||||
private static SingleChoicePrompt popup1 = null;
|
||||
|
||||
[APITestStartUp]
|
||||
public static void StartUp2()
|
||||
{
|
||||
popup2 = new DualChoicePrompt("This is a test double-button popup",
|
||||
"The cake is a lie",
|
||||
"lmao",
|
||||
() => { },
|
||||
"kek",
|
||||
() => { });
|
||||
}
|
||||
|
||||
[APITestStartUp]
|
||||
public static void StartUp1()
|
||||
{
|
||||
popup1 = new SingleChoicePrompt("The cake is a lie",
|
||||
"This is a test single-button popup",
|
||||
"qwertyuiop",
|
||||
() => { });
|
||||
}
|
||||
|
||||
[APITestCase(TestType.Menu)]
|
||||
public static void TestPopUp2()
|
||||
{
|
||||
Client c = new Client();
|
||||
c.PromptUser(popup2);
|
||||
//c.CloseCurrentPrompt();
|
||||
}
|
||||
|
||||
[APITestCase(TestType.Menu)]
|
||||
public static void TestPopUp1()
|
||||
{
|
||||
Client c = new Client();
|
||||
c.PromptUser(popup1);
|
||||
//c.CloseCurrentPrompt();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
27
GamecraftModdingAPI/App/UserPrompts.cs
Normal file
27
GamecraftModdingAPI/App/UserPrompts.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using HarmonyLib;
|
||||
|
||||
using RobocraftX.Services;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
public class DualChoicePrompt : MultiChoiceError
|
||||
{
|
||||
public DualChoicePrompt(string errorMessage, string title, string firstButtonText, Action firstButtonAction, string secondButtonText, Action secondButtonAction) : base(errorMessage, firstButtonText, firstButtonAction, secondButtonText, secondButtonAction)
|
||||
{
|
||||
// internal readonly field smh
|
||||
new Traverse(this).Field<string>("Title").Value = title;
|
||||
}
|
||||
}
|
||||
|
||||
public class SingleChoicePrompt : SingleChoiceError
|
||||
{
|
||||
public SingleChoicePrompt(string errorMessage, string buttonText, Action buttonClickAction) : base(errorMessage, buttonText, buttonClickAction)
|
||||
{
|
||||
}
|
||||
|
||||
public SingleChoicePrompt(string titleText, string errorMessage, string buttonText, Action buttonClickAction) : base(titleText, errorMessage, buttonText, buttonClickAction)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue