Add project files.

This commit is contained in:
Ankitkumar Satapara
2026-04-17 22:31:58 +05:30
commit 21aaef6776
473 changed files with 50152 additions and 0 deletions

View 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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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; }
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Nodify.StateMachine
{
public interface IBlackboardAction
{
Task Execute(Blackboard blackboard);
}
}

View File

@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Nodify.StateMachine
{
public interface IBlackboardCondition
{
Task<bool> Evaluate(Blackboard blackboard);
}
}