Init
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an async Task into an action.
|
||||
/// </summary>
|
||||
public class Async : ICommandAction
|
||||
{
|
||||
private readonly Task _task;
|
||||
|
||||
public bool IsFinished => _task.IsCompleted ||
|
||||
_task.IsCanceled ||
|
||||
_task.IsFaulted;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="task">The async Task to convert.</param>
|
||||
public Async(Task task)
|
||||
{
|
||||
_task = task;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
if (_task.IsFaulted)
|
||||
{
|
||||
throw _task.Exception.InnerException;
|
||||
}
|
||||
if (_task.IsCanceled)
|
||||
{
|
||||
throw new TaskCanceledException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an async Task into an action.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of the Task to convert.</typeparam>
|
||||
public class Async<T> : ICommandAction
|
||||
{
|
||||
private readonly Task<T> _task;
|
||||
private readonly Action<T> _onResult;
|
||||
|
||||
public bool IsFinished => _task.IsCompleted ||
|
||||
_task.IsCanceled ||
|
||||
_task.IsFaulted;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="task">The async Task to convert.</param>
|
||||
/// <param name="onResult">The action to invoke when the Task completes.</param>
|
||||
public Async(Task<T> task, Action<T> onResult)
|
||||
{
|
||||
_task = task;
|
||||
_onResult = onResult;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
if (_task.IsFaulted)
|
||||
{
|
||||
throw _task.Exception.InnerException;
|
||||
}
|
||||
if (_task.IsCanceled)
|
||||
{
|
||||
throw new TaskCanceledException();
|
||||
}
|
||||
|
||||
_onResult(_task.Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aed3880bc1532c7418a020825bd88a2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using QFSW.QC.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Give the user a selection of choices which can be made by using the arrow keys and enter key.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the choices.</typeparam>
|
||||
public class Choice<T> : Composite
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration for the Choice action.
|
||||
/// </summary>
|
||||
public struct Config
|
||||
{
|
||||
public string ItemFormat;
|
||||
public string Delimiter;
|
||||
public Color SelectedColor;
|
||||
|
||||
public static readonly Config Default = new Config
|
||||
{
|
||||
ItemFormat = "{0} [{1}]",
|
||||
Delimiter = " ",
|
||||
SelectedColor = Color.green
|
||||
};
|
||||
}
|
||||
|
||||
/// <param name="choices">The choices to select between.</param>
|
||||
/// <param name="onSelect">Action to invoke when a selection is made.</param>
|
||||
public Choice(IEnumerable<T> choices, Action<T> onSelect)
|
||||
: this(choices, onSelect, Config.Default)
|
||||
{ }
|
||||
|
||||
/// <param name="choices">The choices to select between.</param>
|
||||
/// <param name="onSelect">Action to invoke when a selection is made.</param>
|
||||
/// <param name="config">The configuration to be used.</param>
|
||||
public Choice(IEnumerable<T> choices, Action<T> onSelect, Config config)
|
||||
: base(Generate(choices, onSelect, config))
|
||||
{ }
|
||||
|
||||
private static IEnumerator<ICommandAction> Generate(IEnumerable<T> choices, Action<T> onSelect, Config config)
|
||||
{
|
||||
QuantumConsole console = null;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
IReadOnlyList<T> choiceList = choices as IReadOnlyList<T> ?? choices.ToList();
|
||||
KeyCode key = KeyCode.None;
|
||||
int choice = 0;
|
||||
|
||||
yield return new GetContext(ctx => console = ctx.Console);
|
||||
|
||||
ICommandAction DrawRow()
|
||||
{
|
||||
builder.Clear();
|
||||
for (int i = 0; i < choiceList.Count; i++)
|
||||
{
|
||||
string item = console.Serialize(choiceList[i]);
|
||||
builder.Append(i == choice
|
||||
? string.Format(config.ItemFormat, item, 'x').ColorText(config.SelectedColor)
|
||||
: string.Format(config.ItemFormat, item, ' '));
|
||||
|
||||
if (i != choiceList.Count - 1)
|
||||
{
|
||||
builder.Append(config.Delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
return new Value(builder.ToString());
|
||||
}
|
||||
|
||||
yield return DrawRow();
|
||||
while (key != KeyCode.Return)
|
||||
{
|
||||
yield return new GetKey(k => key = k);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KeyCode.LeftArrow: choice--; break;
|
||||
case KeyCode.RightArrow: choice++; break;
|
||||
case KeyCode.DownArrow: choice++; break;
|
||||
case KeyCode.UpArrow: choice--; break;
|
||||
}
|
||||
|
||||
choice = (choice + choiceList.Count) % choiceList.Count;
|
||||
yield return new RemoveLog();
|
||||
yield return DrawRow();
|
||||
}
|
||||
|
||||
onSelect(choiceList[choice]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 629e5579947e6da4688f17d834a20b56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Combines a sequence of actions into a single action.
|
||||
/// </summary>
|
||||
public class Composite : ICommandAction
|
||||
{
|
||||
private ActionContext _context;
|
||||
private readonly IEnumerator<ICommandAction> _actions;
|
||||
|
||||
public bool IsFinished => _actions.Execute(_context) == ActionState.Complete;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="actions">The sequence of actions to create the composite from.</param>
|
||||
public Composite(IEnumerator<ICommandAction> actions)
|
||||
{
|
||||
_actions = actions;
|
||||
}
|
||||
|
||||
/// <param name="actions">The sequence of actions to create the composite from.</param>
|
||||
public Composite(IEnumerable<ICommandAction> actions) : this(actions.GetEnumerator())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Start(ActionContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext context) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ecb8c263614be7489f996de15278bf5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dba2d4b65cfdad428d18b1bd91c54e7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// The context that an action is being invoked on.
|
||||
/// </summary>
|
||||
public struct ActionContext
|
||||
{
|
||||
public QuantumConsole Console;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16c86e1b478f19a4fa02d70bd8aafcde
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC
|
||||
{
|
||||
public static class ActionExecuter
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes an action command until it becomes idle.
|
||||
/// </summary>
|
||||
/// <param name="action">The action command to execute.</param>
|
||||
/// <param name="context">The context that the command is being executed on.</param>
|
||||
/// <returns>The current state of the action command.</returns>
|
||||
public static ActionState Execute(this IEnumerator<ICommandAction> action, ActionContext context)
|
||||
{
|
||||
ActionState state = ActionState.Running;
|
||||
bool idle = false;
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
if (action.MoveNext())
|
||||
{
|
||||
action.Current?.Start(context);
|
||||
idle = action.Current?.StartsIdle ?? false;
|
||||
}
|
||||
else
|
||||
{
|
||||
idle = true;
|
||||
state = ActionState.Complete;
|
||||
action.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
while (!idle)
|
||||
{
|
||||
if (action.Current == null)
|
||||
{
|
||||
MoveNext();
|
||||
}
|
||||
else if (action.Current.IsFinished)
|
||||
{
|
||||
action.Current.Finalize(context);
|
||||
MoveNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
idle = true;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc98ecd40616cc142a69f2c94957435f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// The execution state of an action.
|
||||
/// </summary>
|
||||
public enum ActionState
|
||||
{
|
||||
Unknown = 0,
|
||||
Running = 1,
|
||||
Complete = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c68b189efbe61cc41af4263794f5b1b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace QFSW.QC
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an action that can be yielded in commands.
|
||||
/// </summary>
|
||||
public interface ICommandAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts the action.
|
||||
/// </summary>
|
||||
/// <param name="context">The context that the action is being executed on.</param>
|
||||
void Start(ActionContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes the action. Should not be called unless <c>IsFinished</c> is true.
|
||||
/// </summary>
|
||||
/// <param name="context">The context that the action is being executed on.</param>
|
||||
void Finalize(ActionContext context);
|
||||
|
||||
/// <summary>
|
||||
/// If the action has finished. Should not be called before <c>Start</c>.
|
||||
/// </summary>
|
||||
bool IsFinished { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If the action should start off idle, causing the execution to suspend until executed again.
|
||||
/// It is recommended to make this <c>false</c> if the action should be instant.
|
||||
/// </summary>
|
||||
bool StartsIdle { get; }
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ad6ee627978b454d9938922d0e5415c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom action implemented via delegates.
|
||||
/// For more complex actions it is usually recommended to create a new action implementing <c>ICommandAction</c>.
|
||||
/// </summary>
|
||||
public class Custom : ICommandAction
|
||||
{
|
||||
private readonly Func<bool> _isFinished;
|
||||
private readonly Func<bool> _startsIdle;
|
||||
private readonly Action<ActionContext> _start;
|
||||
private readonly Action<ActionContext> _finalize;
|
||||
|
||||
public Custom(
|
||||
Func<bool> isFinished,
|
||||
Func<bool> startsIdle,
|
||||
Action<ActionContext> start,
|
||||
Action<ActionContext> finalize
|
||||
)
|
||||
{
|
||||
_isFinished = isFinished;
|
||||
_startsIdle = startsIdle;
|
||||
_start = start;
|
||||
_finalize = finalize;
|
||||
}
|
||||
|
||||
public bool IsFinished => _isFinished();
|
||||
public bool StartsIdle => _startsIdle();
|
||||
|
||||
public void Start(ActionContext context) { _start(context); }
|
||||
public void Finalize(ActionContext context) { _finalize(context); }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9bd021bf2e291447a56d4cede936d56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <c>ActionContext</c> that the command is currently being invoked on.
|
||||
/// </summary>
|
||||
public class GetContext : ICommandAction
|
||||
{
|
||||
private readonly Action<ActionContext> _onContext;
|
||||
|
||||
public bool IsFinished => true;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="onContext">Action to invoke when the context is retrieved.</param>
|
||||
public GetContext(Action<ActionContext> onContext)
|
||||
{
|
||||
_onContext = onContext;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
_onContext(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2b0f8e4c27c89e4caac865a57f52f99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for any key to be pressed and returns the key via the given delegate.
|
||||
/// </summary>
|
||||
public class GetKey : ICommandAction
|
||||
{
|
||||
private KeyCode _key;
|
||||
private readonly Action<KeyCode> _onKey;
|
||||
private static readonly KeyCode[] KeyCodes = Enum.GetValues(typeof(KeyCode))
|
||||
.Cast<KeyCode>()
|
||||
.Where(k => (int)k < (int)KeyCode.Mouse0)
|
||||
.ToArray();
|
||||
|
||||
public bool IsFinished
|
||||
{
|
||||
get
|
||||
{
|
||||
_key = GetCurrentKeyDown();
|
||||
return _key != KeyCode.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="onKey">The action to perform when a key is pressed.</param>
|
||||
public GetKey(Action<KeyCode> onKey)
|
||||
{
|
||||
_onKey = onKey;
|
||||
}
|
||||
|
||||
private KeyCode GetCurrentKeyDown()
|
||||
{
|
||||
return KeyCodes.FirstOrDefault(InputHelper.GetKeyDown);
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
_onKey(_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a0a962a9335e7e408af971ed79d4e8e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the next line of text entered into the console as a user
|
||||
/// response instead of invoking it as a command.
|
||||
/// </summary>
|
||||
public class ReadLine : ICommandAction
|
||||
{
|
||||
private readonly Action<string> _getInput;
|
||||
private readonly ResponseConfig _config;
|
||||
private QuantumConsole _console;
|
||||
private string _response;
|
||||
|
||||
public bool IsFinished => _response != null;
|
||||
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="getInput">A delegate which returns the input entered by the user.</param>
|
||||
/// <param name="config">The config to provide the response flow with.</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public ReadLine(Action<string> getInput, ResponseConfig config)
|
||||
{
|
||||
// validate
|
||||
if (getInput == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(getInput));
|
||||
}
|
||||
|
||||
// set fields
|
||||
_getInput = getInput;
|
||||
_config = config;
|
||||
_console = null;
|
||||
_response = null;
|
||||
}
|
||||
|
||||
/// <param name="getInput">A delegate which returns the input entered by the user.</param>
|
||||
/// <param name="config">The config to provide the response flow with.</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public ReadLine(Action<string> getInput) : this(getInput, ResponseConfig.Default)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
_getInput(_response); // push value to the caller
|
||||
}
|
||||
|
||||
public void Start(ActionContext context)
|
||||
{
|
||||
_response = null; // reset flag
|
||||
_console = context.Console;
|
||||
_console.BeginResponse(OnResponseSubmittedHandler, _config);
|
||||
}
|
||||
|
||||
private void OnResponseSubmittedHandler(string response)
|
||||
{
|
||||
_response = response; // changes IsFinished flag
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cda4247941153d44bdace0c87133c6d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the next line of text entered into the console as a user response
|
||||
/// and parses it to a value of the specified type.
|
||||
/// </summary>
|
||||
public class ReadValue<T> : Composite
|
||||
{
|
||||
private static readonly QuantumParser Parser = new QuantumParser();
|
||||
|
||||
/// <param name="getValue">A delegate which returns the parsed value entered by the user.</param>
|
||||
/// <param name="config">The config to provide the response flow with.</param>
|
||||
public ReadValue(Action<T> getValue, ResponseConfig config)
|
||||
: base(Generate(getValue, config))
|
||||
{ }
|
||||
|
||||
/// <param name="getValue">A delegate which returns the parsed value entered by the user.</param>
|
||||
public ReadValue(Action<T> getValue)
|
||||
: this(getValue, ResponseConfig.Default)
|
||||
{ }
|
||||
|
||||
private static IEnumerator<ICommandAction> Generate(Action<T> getValue, ResponseConfig config)
|
||||
{
|
||||
string line = default;
|
||||
yield return new ReadLine(t => line = t, config);
|
||||
|
||||
T value = Parser.Parse<T>(line);
|
||||
getValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13f674045cd08b947b6cc784b98e45f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes the most recent log from the console.
|
||||
/// </summary>
|
||||
public class RemoveLog : ICommandAction
|
||||
{
|
||||
public bool IsFinished => true;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
context.Console.RemoveLogTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4e97d9251aaa994aa83824d9bccfd59
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gradually types a message to the console.
|
||||
/// </summary>
|
||||
public class Typewriter : Composite
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration for the Typewriter action.
|
||||
/// </summary>
|
||||
public struct Config
|
||||
{
|
||||
public enum ChunkType
|
||||
{
|
||||
Character,
|
||||
Word,
|
||||
Line
|
||||
}
|
||||
|
||||
public float PrintInterval;
|
||||
public ChunkType Chunks;
|
||||
|
||||
public static readonly Config Default = new Config
|
||||
{
|
||||
PrintInterval = 0f,
|
||||
Chunks = ChunkType.Character
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly Regex WhiteRegex = new Regex(@"(?<=[\s+])", RegexOptions.Compiled);
|
||||
private static readonly Regex LineRegex = new Regex(@"(?<=[\n+])", RegexOptions.Compiled);
|
||||
|
||||
/// <param name="message">The message to display to the console.</param>
|
||||
public Typewriter(string message)
|
||||
: this(message, Config.Default)
|
||||
{ }
|
||||
|
||||
/// <param name="message">The message to display to the console.</param>
|
||||
/// <param name="config">The configuration to be used.</param>
|
||||
public Typewriter(string message, Config config)
|
||||
: base(Generate(message, config))
|
||||
{ }
|
||||
|
||||
private static IEnumerator<ICommandAction> Generate(string message, Config config)
|
||||
{
|
||||
string[] chunks;
|
||||
switch (config.Chunks)
|
||||
{
|
||||
case Config.ChunkType.Character: chunks = message.Select(c => c.ToString()).ToArray(); break;
|
||||
case Config.ChunkType.Word: chunks = WhiteRegex.Split(message); break;
|
||||
case Config.ChunkType.Line: chunks = LineRegex.Split(message); break;
|
||||
default: throw new ArgumentException($"Chunk type {config.Chunks} is not supported.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < chunks.Length; i++)
|
||||
{
|
||||
yield return new WaitRealtime(config.PrintInterval);
|
||||
yield return new Value(chunks[i], i == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea886313beb68ed45b9b597a71c3514a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializes and logs a value to the console.
|
||||
/// </summary>
|
||||
public class Value : ICommandAction
|
||||
{
|
||||
private readonly object _value;
|
||||
private readonly bool _newline;
|
||||
|
||||
public bool IsFinished => true;
|
||||
public bool StartsIdle => false;
|
||||
|
||||
/// <param name="value">The value to log to the console.</param>
|
||||
/// <param name="newline">If the value should be logged on a new line.</param>
|
||||
public Value(object value, bool newline = true)
|
||||
{
|
||||
_value = value;
|
||||
_newline = newline;
|
||||
}
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
|
||||
public void Finalize(ActionContext context)
|
||||
{
|
||||
QuantumConsole console = context.Console;
|
||||
string serialized = _value as string ?? console.Serialize(_value);
|
||||
console.LogToConsole(serialized, _newline);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa35d5d3d1cdc54429fbcd0a8754323f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for the given amount of seconds using scaled time.
|
||||
/// </summary>
|
||||
public class Wait : ICommandAction
|
||||
{
|
||||
private float _startTime;
|
||||
private readonly float _duration;
|
||||
|
||||
public bool IsFinished => Time.time >= _startTime + _duration;
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="seconds">The duration to wait in seconds.</param>
|
||||
public Wait(float seconds)
|
||||
{
|
||||
_duration = seconds;
|
||||
}
|
||||
|
||||
public void Start(ActionContext ctx)
|
||||
{
|
||||
_startTime = Time.time;
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext ctx) { }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da3e71593087b0145b4c7416865c73ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits until the next frame.
|
||||
/// </summary>
|
||||
public class WaitFrame : WaitRealtime
|
||||
{
|
||||
public WaitFrame() : base(0)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec7bf5a05072b33469812750790bff62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits until the given key is pressed.
|
||||
/// </summary>
|
||||
public class WaitKey : WaitUntil
|
||||
{
|
||||
/// <param name="key">The key to wait for.</param>
|
||||
public WaitKey(KeyCode key) : base(() => InputHelper.GetKeyDown(key))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67f025b392a312e45bb0ed80959d5cd1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for the given amount of seconds using real time.
|
||||
/// </summary>
|
||||
public class WaitRealtime : ICommandAction
|
||||
{
|
||||
private float _startTime;
|
||||
private readonly float _duration;
|
||||
|
||||
public bool IsFinished => Time.realtimeSinceStartup >= _startTime + _duration;
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="seconds">The duration to wait for in seconds.</param>
|
||||
public WaitRealtime(float seconds)
|
||||
{
|
||||
_duration = seconds;
|
||||
}
|
||||
|
||||
public void Start(ActionContext ctx)
|
||||
{
|
||||
_startTime = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
public void Finalize(ActionContext ctx) { }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32cadea9087bc5d4682ac8455fde1fd4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits until the given condition is met.
|
||||
/// </summary>
|
||||
public class WaitUntil : WaitWhile
|
||||
{
|
||||
/// <param name="condition">The condition to wait on.</param>
|
||||
public WaitUntil(Func<bool> condition) : base(() => !condition())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10b1ff66cd0d51d4a9363f7ad3477830
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace QFSW.QC.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits while the given condition is met.
|
||||
/// </summary>
|
||||
public class WaitWhile : ICommandAction
|
||||
{
|
||||
private readonly Func<bool> _condition;
|
||||
|
||||
public bool IsFinished => !_condition();
|
||||
public bool StartsIdle => true;
|
||||
|
||||
/// <param name="condition">The condition to wait on.</param>
|
||||
public WaitWhile(Func<bool> condition)
|
||||
{
|
||||
_condition = condition;
|
||||
}
|
||||
|
||||
|
||||
public void Start(ActionContext context) { }
|
||||
public void Finalize(ActionContext context) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8050f33217e30684a9a0ea5dfefdfd45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user