Add project files.
This commit is contained in:
88
Examples/Nodify.StateMachine/Runner/Blackboard/Blackboard.cs
Normal file
88
Examples/Nodify.StateMachine/Runner/Blackboard/Blackboard.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
public class Blackboard
|
||||
{
|
||||
private readonly Dictionary<BlackboardKey, object?> _objects = new Dictionary<BlackboardKey, object?>();
|
||||
|
||||
public virtual IReadOnlyCollection<BlackboardKey> Keys
|
||||
=> _objects.Keys;
|
||||
|
||||
public virtual T? GetValue<T>(BlackboardKey key)
|
||||
where T : struct
|
||||
{
|
||||
if (_objects.TryGetValue(key, out var value) && value is T result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public virtual T? GetObject<T>(BlackboardKey key)
|
||||
where T : class
|
||||
{
|
||||
if (_objects.TryGetValue(key, out var value))
|
||||
{
|
||||
return value as T;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public virtual object? GetObject(BlackboardKey key)
|
||||
{
|
||||
if (_objects.TryGetValue(key, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public virtual void Set(BlackboardKey key, object? value)
|
||||
=> _objects[key] = value;
|
||||
|
||||
public virtual bool HasKey(BlackboardKey key)
|
||||
=> _objects.ContainsKey(key);
|
||||
|
||||
public virtual void Remove(BlackboardKey key)
|
||||
=> _objects.Remove(key);
|
||||
|
||||
public virtual void Clear()
|
||||
=> _objects.Clear();
|
||||
|
||||
public void CopyTo(Blackboard newBlackboard)
|
||||
{
|
||||
foreach (var kvp in _objects)
|
||||
{
|
||||
newBlackboard.Set(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public object? this[BlackboardKey key]
|
||||
{
|
||||
get => GetObject(key);
|
||||
set => Set(key, value);
|
||||
}
|
||||
|
||||
public T? GetValue<T>(BlackboardProperty value) where T : struct
|
||||
=> value.IsValue ? value.GetValue<T>() : GetValue<T>(value.Key);
|
||||
|
||||
public T? GetObject<T>(BlackboardProperty value) where T : class
|
||||
=> value.IsValue ? value.GetObject<T>() : GetObject<T>(value.Key);
|
||||
|
||||
public object? GetObject(BlackboardProperty value)
|
||||
=> value.IsValue ? value.Value : GetObject(value.Key);
|
||||
}
|
||||
|
||||
public static class BlackboardExtensions
|
||||
{
|
||||
public static bool IsValid(this BlackboardKey key)
|
||||
=> key != BlackboardKey.Invalid;
|
||||
|
||||
public static bool IsValid(this BlackboardProperty action)
|
||||
=> action != BlackboardProperty.Invalid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
public enum BooleanOperator
|
||||
{
|
||||
And,
|
||||
Or
|
||||
}
|
||||
|
||||
public class BlackboardConditionSet : IBlackboardCondition
|
||||
{
|
||||
public BlackboardConditionSet(IEnumerable<IBlackboardCondition> conditions, BooleanOperator op)
|
||||
{
|
||||
Conditions = new List<IBlackboardCondition>(conditions);
|
||||
Operator = op;
|
||||
}
|
||||
|
||||
public IReadOnlyList<IBlackboardCondition> Conditions { get; }
|
||||
public BooleanOperator Operator { get; set; }
|
||||
|
||||
public async Task<bool> Evaluate(Blackboard blackboard)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (Operator == BooleanOperator.And)
|
||||
{
|
||||
for (int i = 0; i < Conditions.Count; i++)
|
||||
{
|
||||
result &= await Conditions[i].Evaluate(blackboard);
|
||||
}
|
||||
}
|
||||
else if (Operator == BooleanOperator.Or)
|
||||
{
|
||||
for (int i = 0; i < Conditions.Count; i++)
|
||||
{
|
||||
result |= await Conditions[i].Evaluate(blackboard);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class BlackboardItemAttribute : Attribute
|
||||
{
|
||||
public BlackboardItemAttribute(string displayName)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public string DisplayName { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
public enum BlackboardKeyType
|
||||
{
|
||||
Boolean,
|
||||
Integer,
|
||||
Double,
|
||||
String,
|
||||
Object
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Name}: {Type}")]
|
||||
public readonly struct BlackboardKey : IEquatable<BlackboardKey>
|
||||
{
|
||||
public static BlackboardKey Invalid { get; } = new BlackboardKey();
|
||||
|
||||
public BlackboardKey(string name, BlackboardKeyType type)
|
||||
{
|
||||
Name = name ?? throw new ArgumentException(nameof(name));
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public BlackboardKey(string name) : this(name, BlackboardKeyType.Object)
|
||||
{
|
||||
}
|
||||
|
||||
public readonly string Name;
|
||||
public readonly BlackboardKeyType Type;
|
||||
|
||||
public static implicit operator BlackboardKey(string name)
|
||||
=> new BlackboardKey(name);
|
||||
|
||||
public static implicit operator string(BlackboardKey key)
|
||||
=> key.Name;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
=> obj is BlackboardKey bk && bk.Equals(this);
|
||||
|
||||
public override int GetHashCode()
|
||||
=> Name?.GetHashCode() ?? -1;
|
||||
|
||||
public bool Equals(BlackboardKey other)
|
||||
=> other.Name == Name;
|
||||
|
||||
public static bool operator ==(BlackboardKey left, BlackboardKey right)
|
||||
=> left.Equals(right);
|
||||
|
||||
public static bool operator !=(BlackboardKey left, BlackboardKey right)
|
||||
=> !(left == right);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
[DebuggerDisplay("{IsKey ? Key : Value}")]
|
||||
public struct BlackboardProperty : IEquatable<BlackboardProperty>
|
||||
{
|
||||
public static BlackboardProperty Invalid { get; } = new BlackboardProperty();
|
||||
|
||||
public BlackboardProperty(BlackboardKey key)
|
||||
{
|
||||
Key = key;
|
||||
Value = default;
|
||||
}
|
||||
|
||||
public BlackboardProperty(object? value)
|
||||
{
|
||||
Key = BlackboardKey.Invalid;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public BlackboardKey Key { get; }
|
||||
public object? Value { get; }
|
||||
|
||||
public bool IsKey => Key.IsValid();
|
||||
public bool IsValue => !IsKey;
|
||||
|
||||
public static implicit operator BlackboardKey(BlackboardProperty action)
|
||||
=> action.Key;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
=> obj is BlackboardProperty action && action.Equals(this);
|
||||
|
||||
public override int GetHashCode()
|
||||
=> IsKey ? Key.GetHashCode() : Value?.GetHashCode() ?? -1;
|
||||
|
||||
public bool Equals(BlackboardProperty other)
|
||||
=> IsKey == other.IsKey && IsValue == other.IsValue && Key == other.Key && Value == other.Value;
|
||||
|
||||
public static bool operator ==(BlackboardProperty left, BlackboardProperty right)
|
||||
=> left.Equals(right);
|
||||
|
||||
public static bool operator !=(BlackboardProperty left, BlackboardProperty right)
|
||||
=> !(left == right);
|
||||
|
||||
public T? GetValue<T>() where T : struct
|
||||
=> Value is T result ? result : default;
|
||||
|
||||
public T? GetObject<T>() where T : class
|
||||
=> Value as T;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
public enum BlackboardKeyUsage
|
||||
{
|
||||
Input,
|
||||
Output
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Properties decorated with this attribute must always be of type <see cref="BlackboardProperty"/>.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class BlackboardPropertyAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Properties decorated with this attribute must always be of type <see cref="BlackboardProperty"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The display name of the key.</param>
|
||||
/// <param name="type">The data type of the value that the key refers to.</param>
|
||||
public BlackboardPropertyAttribute(string? name, BlackboardKeyType type = BlackboardKeyType.Object)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Properties decorated with this attribute must always be of type <see cref="BlackboardProperty"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The data type of the value that the key refers to.</param>
|
||||
public BlackboardPropertyAttribute(BlackboardKeyType type = BlackboardKeyType.Object) : this(null, type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public string? Name { get; }
|
||||
public BlackboardKeyType Type { get; }
|
||||
public BlackboardKeyUsage Usage { get; set; }
|
||||
public bool CanChangeType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
public interface IBlackboardAction
|
||||
{
|
||||
Task Execute(Blackboard blackboard);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nodify.StateMachine
|
||||
{
|
||||
public interface IBlackboardCondition
|
||||
{
|
||||
Task<bool> Evaluate(Blackboard blackboard);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user