removed Structural instance and SJKScript was changed to be using an nuget package.
This commit is contained in:
@@ -1,133 +0,0 @@
|
|||||||
namespace ChickenGameTest;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
// public partial class StructuralInstance<TAttribute> where TAttribute : class
|
|
||||||
// {
|
|
||||||
public sealed class StructuralBuilder<TAttribute> where TAttribute : class
|
|
||||||
{
|
|
||||||
|
|
||||||
private readonly Dictionary<int, TAttribute> _components = [];
|
|
||||||
|
|
||||||
public StructuralBuilder() { }
|
|
||||||
|
|
||||||
public StructuralBuilder(IStructuralInstance<TAttribute> existing)
|
|
||||||
{
|
|
||||||
foreach (var (id, value) in existing.GetAttributes())
|
|
||||||
{
|
|
||||||
_components[id] = value;
|
|
||||||
}
|
|
||||||
// for (int i = 0; i < existing.ComponentCount; i++)
|
|
||||||
// {
|
|
||||||
// var typeId = existing._attributesTypeIds[i];
|
|
||||||
// var component = existing.GetComponentAt(i);
|
|
||||||
|
|
||||||
// _components[typeId] = component;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public StructuralBuilder<TAttribute> Add<T>(T component) where T : TAttribute
|
|
||||||
{
|
|
||||||
int id = ComponentTypeRegistry.GetId<T>();
|
|
||||||
_components[id] = component;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public StructuralBuilder<TAttribute> Upsert<T>(Func<T, T> ifExists, Func<T> none) where T : TAttribute
|
|
||||||
{
|
|
||||||
int id = ComponentTypeRegistry.GetId<T>();
|
|
||||||
_components[id] = _components.TryGetValue(id, out var old) ? ifExists((T)old) : none();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public StructuralBuilder<TAttribute> CombineWith(IStructuralInstance<TAttribute> other, Action<CombineBinder>? configure = null)
|
|
||||||
{
|
|
||||||
var binder = new CombineBinder();
|
|
||||||
configure?.Invoke(binder);
|
|
||||||
foreach (var (id, value) in other.GetAttributes())
|
|
||||||
{
|
|
||||||
if (binder._ignores.Contains(id))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_components.TryGetValue(id, out var existing)
|
|
||||||
&& binder._rules.TryGetValue(id, out var rule))
|
|
||||||
{
|
|
||||||
_components[id] = rule.Invoke(existing, value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_components[id] = value;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StructuralBuilder<TAttribute> Remove<T>() where T : TAttribute
|
|
||||||
{
|
|
||||||
int id = ComponentTypeRegistry.GetId<T>();
|
|
||||||
_components.Remove(id);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Has<T>() where T : TAttribute
|
|
||||||
{
|
|
||||||
int id = ComponentTypeRegistry.GetId<T>();
|
|
||||||
return _components.ContainsKey(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StructuralInstance<TAttribute> Build()
|
|
||||||
{
|
|
||||||
int count = _components.Count;
|
|
||||||
|
|
||||||
var typeIds = new int[count];
|
|
||||||
var components = new TAttribute[count];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
foreach (var kv in _components)
|
|
||||||
{
|
|
||||||
typeIds[i] = kv.Key;
|
|
||||||
components[i] = kv.Value;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array.Sort(typeIds, components);
|
|
||||||
return new StructuralInstance<TAttribute>(typeIds, components);
|
|
||||||
}
|
|
||||||
public MutableStructuralInstance<TAttribute> BuildMutable()
|
|
||||||
{
|
|
||||||
// int count = _components.Count;
|
|
||||||
|
|
||||||
var sortedList = new SortedList<int, TAttribute>(_components);
|
|
||||||
// var typeIds = new int[count];
|
|
||||||
// var components = new TAttribute[count];
|
|
||||||
|
|
||||||
// int i = 0;
|
|
||||||
// foreach (var kv in _components)
|
|
||||||
// {
|
|
||||||
// typeIds[i] = kv.Key;
|
|
||||||
// components[i] = kv.Value;
|
|
||||||
// i++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Array.Sort(typeIds, components);
|
|
||||||
return new MutableStructuralInstance<TAttribute>(sortedList);
|
|
||||||
}
|
|
||||||
public class CombineBinder
|
|
||||||
{
|
|
||||||
internal readonly Dictionary<int, Func<TAttribute, TAttribute, TAttribute>> _rules = [];
|
|
||||||
internal readonly HashSet<int> _ignores = [];
|
|
||||||
public CombineBinder Bind<T>(Func<T, T, T> func) where T : TAttribute
|
|
||||||
{
|
|
||||||
_rules[ComponentType<T>.Id] = (a, b) => func((T)a, (T)b);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public CombineBinder Ignore<T>() where T : TAttribute
|
|
||||||
{
|
|
||||||
_ignores.Add(ComponentType<T>.Id);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://bk721rnhegl0x
|
|
||||||
@@ -1,255 +0,0 @@
|
|||||||
namespace ChickenGameTest;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Chickensoft.Sync.Primitives;
|
|
||||||
using SJK.Functional;
|
|
||||||
|
|
||||||
public interface IStructuralInstance<TAttribute> : IEquatable<IStructuralInstance<TAttribute>>
|
|
||||||
{
|
|
||||||
int ComponentCount { get; }
|
|
||||||
bool Has<T>() where T : TAttribute;
|
|
||||||
Option<T> Get<T>() where T : TAttribute;
|
|
||||||
// TAttribute GetComponentAt(int index);
|
|
||||||
IEnumerable<(int Id, TAttribute Value)> GetAttributes();
|
|
||||||
bool IEquatable<IStructuralInstance<TAttribute>>.Equals(IStructuralInstance<TAttribute>? other) => Enumerable.SequenceEqual(GetAttributes(), other.GetAttributes(), EqualityComparer<(int, TAttribute)>.Default);
|
|
||||||
|
|
||||||
int ComputeHashCode()
|
|
||||||
{
|
|
||||||
HashCode hash = new HashCode();
|
|
||||||
foreach (var item in GetAttributes())
|
|
||||||
{
|
|
||||||
hash.Add(item);
|
|
||||||
}
|
|
||||||
return hash.ToHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed partial class StructuralInstance<TAttribute> : IStructuralInstance<TAttribute>, IEquatable<StructuralInstance<TAttribute>> where TAttribute : class
|
|
||||||
{
|
|
||||||
private readonly int _hashCode;
|
|
||||||
internal readonly int[] _attributesTypeIds;
|
|
||||||
internal readonly TAttribute[] _attributes;
|
|
||||||
|
|
||||||
public int ComponentCount => _attributes.Length;
|
|
||||||
|
|
||||||
public TAttribute GetComponentAt(int index) => _attributes[index];
|
|
||||||
internal StructuralInstance(int[] componentTypeIds, TAttribute[] attributes)
|
|
||||||
{
|
|
||||||
_attributesTypeIds = componentTypeIds;
|
|
||||||
_attributes = attributes;
|
|
||||||
_hashCode = (this as IStructuralInstance<TAttribute>).ComputeHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Has<T>() where T : TAttribute
|
|
||||||
{
|
|
||||||
// int typeId = ComponentTypeRegistry.GetId<T>();
|
|
||||||
var typeId = ComponentType<T>.Id;
|
|
||||||
return Array.BinarySearch(_attributesTypeIds, typeId) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Option<T> Get<T>() where T : TAttribute
|
|
||||||
{
|
|
||||||
// int typeId = ComponentTypeRegistry.GetId<T>();
|
|
||||||
var typeId = ComponentType<T>.Id;
|
|
||||||
int index = Array.BinarySearch(_attributesTypeIds, typeId);
|
|
||||||
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
return Option<T>.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Option<T>.Some((T)_attributes[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(StructuralInstance<TAttribute>? other)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(this, other))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (other is null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _hashCode == other._hashCode && Enumerable.SequenceEqual(_attributes, other._attributes, EqualityComparer<TAttribute>.Default);// && AttributesAreEqual(other);
|
|
||||||
}
|
|
||||||
public override bool Equals(object? obj) => obj is StructuralInstance<TAttribute> value? Equals(value) : obj is IStructuralInstance<TAttribute> v && v.Equals(this);
|
|
||||||
|
|
||||||
public override int GetHashCode() => _hashCode;
|
|
||||||
public IEnumerable<(int Id, TAttribute Value)> GetAttributes()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ComponentCount; i++)
|
|
||||||
{
|
|
||||||
yield return (_attributesTypeIds[i], _attributes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override string ToString() => base.ToString();
|
|
||||||
}
|
|
||||||
public sealed class MutableStructuralInstance<TAttribute> : IStructuralInstance<TAttribute>, IEquatable<MutableStructuralInstance<TAttribute>> where TAttribute : class
|
|
||||||
{
|
|
||||||
private readonly SortedList<int, TAttribute> _attributes = [];
|
|
||||||
public int ComponentCount => _attributes.Count;
|
|
||||||
public MutableStructuralInstance(SortedList<int, TAttribute> attributes)
|
|
||||||
{
|
|
||||||
_attributes = attributes;
|
|
||||||
}
|
|
||||||
public Option<T> Get<T>() where T : TAttribute => _attributes.TryGetValue(ComponentType<T>.Id, out var attribute) ? Option<T>.Some((T)attribute) : Option<T>.None;
|
|
||||||
public IEnumerable<(int Id, TAttribute Value)> GetAttributes() => _attributes.Select(x => (x.Key, x.Value));
|
|
||||||
public TAttribute GetComponentAt(int index) => _attributes[index];
|
|
||||||
public bool Has<T>() where T : TAttribute => _attributes.ContainsKey(ComponentType<T>.Id);
|
|
||||||
public void Set<T>(T value) where T : TAttribute => _attributes[ComponentType<T>.Id] = value;
|
|
||||||
public override int GetHashCode() => (this as IStructuralInstance<TAttribute>).ComputeHashCode();
|
|
||||||
public bool Equals(MutableStructuralInstance<TAttribute>? other) => other is not null && Enumerable.SequenceEqual(_attributes, other._attributes, EqualityComparer<KeyValuePair<int, TAttribute>>.Default);
|
|
||||||
public override bool Equals(object? obj) => obj is MutableStructuralInstance<TAttribute> other ? Equals(other) : obj is IStructuralInstance<TAttribute> v && v.Equals(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ComponentTypeRegistry
|
|
||||||
{
|
|
||||||
private static readonly Dictionary<Type, int> _typeToId = [];
|
|
||||||
private static readonly List<Type> _idToType = [];
|
|
||||||
|
|
||||||
public static int GetId(Type type)
|
|
||||||
{
|
|
||||||
if (_typeToId.TryGetValue(type, out var id))
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = _idToType.Count;
|
|
||||||
_typeToId[type] = id;
|
|
||||||
_idToType.Add(type);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
public static int GetId<T>() => GetId(typeof(T));
|
|
||||||
}
|
|
||||||
public static class ComponentType<T>
|
|
||||||
{
|
|
||||||
public static readonly int Id = ComponentTypeRegistry.GetId<T>();
|
|
||||||
public static readonly bool CacheTransitions = Resolve();
|
|
||||||
|
|
||||||
private static bool Resolve()
|
|
||||||
{
|
|
||||||
var attr = typeof(T).GetCustomAttributes(typeof(ComponentOptionsAttribute), false);
|
|
||||||
return attr.OfType<ComponentOptionsAttribute>().FirstOrNone().Map(static f => f.CacheTransitions).Or(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
|
||||||
public sealed class ComponentOptionsAttribute : Attribute
|
|
||||||
{
|
|
||||||
public bool CacheTransitions { get; init; } = true;
|
|
||||||
}
|
|
||||||
public interface IStructureRegistry<TAttribute> where TAttribute : class
|
|
||||||
{
|
|
||||||
StructuralInstance<TAttribute> Canonicalize(StructuralInstance<TAttribute> value);
|
|
||||||
StructuralInstance<TAttribute> AddOrReplaceAttribute<T>(StructuralInstance<TAttribute> instance, T attribute) where T : TAttribute;
|
|
||||||
StructuralInstance<TAttribute> RemoveAttribute<T>(StructuralInstance<TAttribute> instance) where T : TAttribute;
|
|
||||||
}
|
|
||||||
public class StructuralInstanceManger<TAttribute> : IStructureRegistry<TAttribute> where TAttribute : class
|
|
||||||
{
|
|
||||||
private readonly HashSet<StructuralInstance<TAttribute>> _instances = [];
|
|
||||||
public StructuralInstance<TAttribute> Add<T>(StructuralInstance<TAttribute> instance, T component) where T : TAttribute
|
|
||||||
{
|
|
||||||
var builder = new StructuralBuilder<TAttribute>(instance).Add(component);
|
|
||||||
return Canonicalize(builder.Build());
|
|
||||||
|
|
||||||
}
|
|
||||||
public StructuralInstance<TAttribute> Canonicalize(StructuralInstance<TAttribute> value)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (_instances.TryGetValue(value, out var id))
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
_instances.Add(value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
public StructuralInstance<TAttribute> AddOrReplaceAttribute<T>(StructuralInstance<TAttribute> instance, T attribute) where T : TAttribute
|
|
||||||
{
|
|
||||||
if (!graph.TryGetValue(instance, out var results))
|
|
||||||
{
|
|
||||||
graph[instance] = results = [];
|
|
||||||
}
|
|
||||||
for (int i = 0; i < results.Count; i++)
|
|
||||||
{
|
|
||||||
if (results[i] is AddTransitionEntry<T> addTransitionEntry && EqualityComparer<T>.Default.Equals(addTransitionEntry.Value, attribute))
|
|
||||||
{
|
|
||||||
return addTransitionEntry.Result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var result =new AddTransitionEntry<T>(ComponentType<T>.Id, attribute, Canonicalize(new StructuralBuilder<TAttribute>(instance).Add(attribute).Build()));
|
|
||||||
if (ComponentType<T>.CacheTransitions)
|
|
||||||
{
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
return result.Result;
|
|
||||||
}
|
|
||||||
public StructuralInstance<TAttribute> RemoveAttribute<T>(StructuralInstance<TAttribute> instance) where T : TAttribute
|
|
||||||
{
|
|
||||||
if (!graph.TryGetValue(instance, out var results))
|
|
||||||
{
|
|
||||||
graph[instance] = results = [];
|
|
||||||
}
|
|
||||||
var id = ComponentType<T>.Id;
|
|
||||||
for (int i = 0; i < results.Count; i++)
|
|
||||||
{
|
|
||||||
if (results[i] is RemoveTransitionEntry removeTransitionEntry && removeTransitionEntry.Id == id)
|
|
||||||
{
|
|
||||||
return removeTransitionEntry.Result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var result =new RemoveTransitionEntry(id, Canonicalize(new StructuralBuilder<TAttribute>(instance).Remove<T>().Build()));
|
|
||||||
if (ComponentType<T>.CacheTransitions)
|
|
||||||
{
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
return result.Result;
|
|
||||||
}
|
|
||||||
private Dictionary<StructuralInstance<TAttribute>, List<TransitionEntry>> graph = [];
|
|
||||||
|
|
||||||
private record TransitionEntry(int Id);
|
|
||||||
|
|
||||||
private record AddTransitionEntry<T>(int Id, T Value, StructuralInstance<TAttribute> Result) : TransitionEntry(Id) where T : TAttribute;
|
|
||||||
|
|
||||||
private record RemoveTransitionEntry(int Id, StructuralInstance<TAttribute> Result) : TransitionEntry(Id);
|
|
||||||
// private record ModifyTransitionEntry<T>(int Id, TAttribute Value, StructuralInstance<TAttribute> Result) : TransitionEntry(Id) where T : TAttribute;
|
|
||||||
|
|
||||||
}
|
|
||||||
public class AutoStructureInstance<TAttribute> where TAttribute : class
|
|
||||||
{
|
|
||||||
private StructuralInstance<TAttribute> _structuralInstance;
|
|
||||||
private IStructureRegistry<TAttribute> _registry;
|
|
||||||
private Dictionary<int,List<Delegate>> _bindings = [];
|
|
||||||
|
|
||||||
public void Set<T>(T? value) where T : TAttribute
|
|
||||||
{
|
|
||||||
var old = _structuralInstance.Get<T>();
|
|
||||||
if (old.HasValue && old.Value.Equals(value))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value is null)
|
|
||||||
{
|
|
||||||
_structuralInstance = _registry.RemoveAttribute<T>(_structuralInstance);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_structuralInstance = _registry.AddOrReplaceAttribute(_structuralInstance, value);
|
|
||||||
}
|
|
||||||
_bindings[ComponentType<T>.Id].ForEach(item => item.DynamicInvoke(old,value));
|
|
||||||
|
|
||||||
}
|
|
||||||
public void Bind<T>(Action<T?, T?> callback) where T : TAttribute
|
|
||||||
{
|
|
||||||
int id = ComponentType<T>.Id;
|
|
||||||
|
|
||||||
if (!_bindings.TryGetValue(id, out var list))
|
|
||||||
{
|
|
||||||
_bindings[id] = list = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://cexmjk01dgtbe
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
namespace ChickenGameTest;
|
|
||||||
|
|
||||||
using System.Diagnostics;
|
|
||||||
using Godot;
|
|
||||||
using SJK.Functional;
|
|
||||||
|
|
||||||
public class TestStructural
|
|
||||||
{
|
|
||||||
public static void Test()
|
|
||||||
{
|
|
||||||
var a = new StructuralBuilder<object>()
|
|
||||||
.Add(new Vector3(0,0,0))
|
|
||||||
.Add(new Vector2(0,5))
|
|
||||||
.Add(new Vector4(0,0,0,0))
|
|
||||||
.Add(new Aabb())
|
|
||||||
.Add(new int())
|
|
||||||
.Add(new float())
|
|
||||||
.Add(new Node())
|
|
||||||
.Add(new Node())
|
|
||||||
.Add(new Node2D())
|
|
||||||
.Add("")
|
|
||||||
.Add(new test(){a = 5, b = "gg"})
|
|
||||||
.Build();
|
|
||||||
var registy = new StructuralInstanceManger<object>();
|
|
||||||
var b = registy.Add(a,new Vector2(1,2));
|
|
||||||
var c = registy.Add(a,new Vector2(1,2));
|
|
||||||
var d = registy.Canonicalize(new StructuralBuilder<object>(a).Add(new Vector2(1,2)).Build());
|
|
||||||
var g = new StructuralBuilder<object>(a).Add(Option<int>.Some(5)).Build();
|
|
||||||
var h = new StructuralBuilder<object>(a).Add(Option<int>.Some(5)).BuildMutable();
|
|
||||||
GD.Print(g.Equals(h));
|
|
||||||
GD.Print(ReferenceEquals(b,c));
|
|
||||||
GD.Print(ReferenceEquals(b,d));
|
|
||||||
GD.Print(ComponentType<Vector3>.Id);
|
|
||||||
GD.Print(ComponentType<Vector2>.Id);
|
|
||||||
|
|
||||||
var help = new StructuralBuilder<object>(a)
|
|
||||||
.CombineWith(b, static configure => configure
|
|
||||||
.Bind<Vector2>(static (a, b) => a + b)
|
|
||||||
.Ignore<Vector4>())
|
|
||||||
.Add(Vector2I.Zero)
|
|
||||||
.Build();
|
|
||||||
GD.Print(help.Get<Vector2>().Map(i=>$"{i}").OrDefault("none"));
|
|
||||||
var timer = new Stopwatch();
|
|
||||||
timer.Start();
|
|
||||||
for (int i = 0; i < 100000; i++)
|
|
||||||
{
|
|
||||||
var e = registy.AddOrReplaceAttribute(a,new test());
|
|
||||||
}
|
|
||||||
timer.Stop();
|
|
||||||
GD.Print(timer.Elapsed);
|
|
||||||
timer.Reset();
|
|
||||||
timer.Start();
|
|
||||||
for (int i = 0; i < 100000; i++)
|
|
||||||
{
|
|
||||||
var e = registy.Canonicalize(new StructuralBuilder<object>(a).Add(new test()).Build());
|
|
||||||
}
|
|
||||||
timer.Stop();
|
|
||||||
GD.Print(timer.Elapsed);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[ComponentOptions(CacheTransitions = true)]
|
|
||||||
record test
|
|
||||||
{
|
|
||||||
public int a;
|
|
||||||
public string b;
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://br6rfqtryq0cx
|
|
||||||
@@ -83,7 +83,7 @@ public interface IBeltPort
|
|||||||
yield return (Profile.LocalOffset.Right * i) + Profile.LocalOffset.Origin;
|
yield return (Profile.LocalOffset.Right * i) + Profile.LocalOffset.Origin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LaneSpan LaneSpan => new LaneSpan(0,(ushort)Profile.Width);
|
LaneSpan LaneSpan => new(0, (ushort)Profile.Width);
|
||||||
}
|
}
|
||||||
public sealed class ConveyorPort : IBeltPort
|
public sealed class ConveyorPort : IBeltPort
|
||||||
{
|
{
|
||||||
@@ -150,20 +150,10 @@ public sealed class ConveyorPort : IBeltPort
|
|||||||
public interface IBeltSlotProfile
|
public interface IBeltSlotProfile
|
||||||
{
|
{
|
||||||
Vector3I Position { get; }
|
Vector3I Position { get; }
|
||||||
// Direction Direction { get; }
|
|
||||||
int Width { get; }
|
int Width { get; }
|
||||||
PortAccess Access { get; }
|
PortAccess Access { get; }
|
||||||
// bool CanAcceptItem(IBeltItem beltItem, LaneSpan laneSpan, float beltT = 0);
|
|
||||||
// /// <summary>
|
|
||||||
// ///Tries to insert an belt item offset by laneSpan,
|
|
||||||
// /// </summary>
|
|
||||||
// /// <param name="beltItem"></param>
|
|
||||||
// /// <param name="laneSpan"></param>
|
|
||||||
// /// <param name="beltT"></param>
|
|
||||||
// /// <returns></returns>
|
|
||||||
// bool TryInsertItem(IBeltItem beltItem, LaneSpan laneSpan, float beltT = 0);
|
|
||||||
}
|
}
|
||||||
public record LaneId(int Index);
|
// public record LaneId(int Index);
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum PortAccess : byte
|
public enum PortAccess : byte
|
||||||
{
|
{
|
||||||
@@ -181,7 +171,7 @@ public enum TransferMode : byte//Need Better Name
|
|||||||
Pull = 2,
|
Pull = 2,
|
||||||
PushPull = Push | Pull
|
PushPull = Push | Pull
|
||||||
}
|
}
|
||||||
public static class SlotExtesion
|
public static class SlotExtension
|
||||||
{
|
{
|
||||||
public static LaneSpan MapLaneSpanToFacingPort(this IBeltPort self, IBeltPort other) => MapSlotToFacingSlot(self.Profile.LocalOffset, self.Profile.Width, other.Profile.LocalOffset, other.Profile.Width);
|
public static LaneSpan MapLaneSpanToFacingPort(this IBeltPort self, IBeltPort other) => MapSlotToFacingSlot(self.Profile.LocalOffset, self.Profile.Width, other.Profile.LocalOffset, other.Profile.Width);
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
|
|
||||||
public static partial class SJKMath
|
|
||||||
{
|
|
||||||
// public static Vector3I Lerp(Vector3I from, Vector3I to, float weight) => new Vector3I(
|
|
||||||
// Mathf.Lerp(from.X, to.X, weight),
|
|
||||||
// Mathf.Lerp(from.Y, to.Y, weight),
|
|
||||||
// Mathf.Lerp(from.Z, to.Z, weight)
|
|
||||||
// );
|
|
||||||
public static Vector3 Lerp(Vector3 from, Vector3 to, float weight) => new Vector3(
|
|
||||||
Mathf.Lerp(from.X, to.X, weight),
|
|
||||||
Mathf.Lerp(from.Y, to.Y, weight),
|
|
||||||
Mathf.Lerp(from.Z, to.Z, weight)
|
|
||||||
);
|
|
||||||
// public static Vector2I Lerp(Vector2I from, Vector2I to, float weight) => new Vector2I(
|
|
||||||
// Mathf.Lerp(from.X, to.X, weight),
|
|
||||||
// Mathf.Lerp(from.Y, to.Y, weight)
|
|
||||||
// );
|
|
||||||
public static Vector2 Lerp(Vector2 from, Vector2 to, float weight) => new Vector2(
|
|
||||||
Mathf.Lerp(from.X, to.X, weight),
|
|
||||||
Mathf.Lerp(from.Y, to.Y, weight)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://133eop5e4mii
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace SJK.GodotHelpers;
|
|
||||||
public static class MyNodeExtensions{
|
|
||||||
public static void FreeDeferred(this Node node)=>node.CallDeferred(Node.MethodName.Free);
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if given Property exists on <c>Base</c>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Base">Current <c>GodotObject</c></param>
|
|
||||||
/// <param name="PropertyName">Property Name</param>
|
|
||||||
/// <returns><c>bool</c> true if given property exists on Base</returns>
|
|
||||||
public static bool HasProperty(this GodotObject Base, string PropertyName){
|
|
||||||
/*
|
|
||||||
Returns the object's property list as an Godot.Collections.Array of dictionaries.
|
|
||||||
Each Godot.Collections.Dictionary contains the following entries:
|
|
||||||
- name is the property's name, as a string;
|
|
||||||
- class_name is an empty StringName, unless the property is Variant.Type.Object and it inherits from a class;
|
|
||||||
- type is the property's type, as an int (see Variant.Type);
|
|
||||||
- hint is how the property is meant to be edited (see PropertyHint);
|
|
||||||
- hint_string depends on the hint (see PropertyHint);
|
|
||||||
- usage is a combination of PropertyUsageFlags.
|
|
||||||
*/
|
|
||||||
foreach (var Property in Base.GetPropertyListEx())
|
|
||||||
{
|
|
||||||
if(Property.Name == PropertyName){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public static (Node node, Resource resource, NodePath remaining) GetNodeAndResourceEx(this Node self, NodePath path)
|
|
||||||
{
|
|
||||||
var result = self.GetNodeAndResource(path);
|
|
||||||
return ((Node)result[0], (Resource)result[1], (NodePath)result[2]);
|
|
||||||
}
|
|
||||||
public static void QueueFreeChildren(this Node node) => node.GetChildren().ToList().ForEach(item=>item.QueueFree());
|
|
||||||
public static void QueueFreeChildren(this Node node, Func<Node,bool> predicate) => node.GetChildren().Where(predicate).ToList().ForEach(item=>item.QueueFree());
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://bklfdjfp02pav
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
using SJK.Functional;
|
|
||||||
|
|
||||||
namespace SJK.GodotHelpers.Raycasts;
|
|
||||||
public record CollisionResultBase(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape
|
|
||||||
);
|
|
||||||
|
|
||||||
public record RaycastResult3D(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape,
|
|
||||||
Vector3 Position,
|
|
||||||
Vector3 Normal
|
|
||||||
) : CollisionResultBase(Collider, ColliderId, Rid, Shape);
|
|
||||||
|
|
||||||
public record RaycastResult2D(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape,
|
|
||||||
Vector2 Position,
|
|
||||||
Vector2 Normal
|
|
||||||
) : CollisionResultBase(Collider, ColliderId, Rid, Shape);
|
|
||||||
|
|
||||||
public record ShapeCastResult3D(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape,
|
|
||||||
Vector3 Point,
|
|
||||||
Vector3 Normal,
|
|
||||||
int CollisionCount
|
|
||||||
) : CollisionResultBase(Collider, ColliderId, Rid, Shape);
|
|
||||||
|
|
||||||
public record ShapeCastResult2D(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape,
|
|
||||||
Vector2 Point,
|
|
||||||
Vector2 Normal,
|
|
||||||
int CollisionCount
|
|
||||||
) : CollisionResultBase(Collider, ColliderId, Rid, Shape);
|
|
||||||
|
|
||||||
public record PointQueryResult3D(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape
|
|
||||||
) : CollisionResultBase(Collider, ColliderId, Rid, Shape);
|
|
||||||
|
|
||||||
public record PointQueryResult2D(
|
|
||||||
GodotObject Collider,
|
|
||||||
int ColliderId,
|
|
||||||
Rid Rid,
|
|
||||||
int Shape
|
|
||||||
) : CollisionResultBase(Collider, ColliderId, Rid, Shape);
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
public static class RaycastExtensions
|
|
||||||
{
|
|
||||||
// --- 3D ---
|
|
||||||
|
|
||||||
public static RaycastResult3D? RaycastEx(this PhysicsDirectSpaceState3D space, Vector3 from, Vector3 to, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
|
|
||||||
{
|
|
||||||
var query = new PhysicsRayQueryParameters3D
|
|
||||||
{
|
|
||||||
From = from,
|
|
||||||
To = to,
|
|
||||||
CollisionMask = collisionMask,
|
|
||||||
HitFromInside = hitFromInside,
|
|
||||||
};
|
|
||||||
if (exclude != null)
|
|
||||||
query.Exclude = new Array<Rid>(exclude);
|
|
||||||
|
|
||||||
var result = space.IntersectRay(query);
|
|
||||||
if (result.Count == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return new RaycastResult3D(
|
|
||||||
Collider: result["collider"].AsGodotObject(),
|
|
||||||
ColliderId: result["collider_id"].AsInt32(),
|
|
||||||
Rid: (Rid)result["rid"],
|
|
||||||
Shape: result["shape"].AsInt32(),
|
|
||||||
Position: result["position"].AsVector3(),
|
|
||||||
Normal: result["normal"].AsVector3()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool RaycastHitEx(this PhysicsDirectSpaceState3D space, Vector3 from, Vector3 to,[NotNullWhen(true)] out RaycastResult3D hit, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
|
|
||||||
{
|
|
||||||
hit = space.RaycastEx(from, to, collisionMask, exclude, hitFromInside)!;
|
|
||||||
return hit is not null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 2D ---
|
|
||||||
|
|
||||||
public static RaycastResult2D? RaycastEx(this PhysicsDirectSpaceState2D space, Vector2 from, Vector2 to, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
|
|
||||||
{
|
|
||||||
var query = new PhysicsRayQueryParameters2D
|
|
||||||
{
|
|
||||||
From = from,
|
|
||||||
To = to,
|
|
||||||
CollisionMask = collisionMask,
|
|
||||||
HitFromInside = hitFromInside,
|
|
||||||
};
|
|
||||||
if (exclude != null)
|
|
||||||
query.Exclude = new Array<Rid>(exclude);
|
|
||||||
|
|
||||||
var result = space.IntersectRay(query);
|
|
||||||
if (result.Count == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return new RaycastResult2D(
|
|
||||||
Collider: result["collider"].AsGodotObject(),
|
|
||||||
ColliderId: result["collider_id"].AsInt32(),
|
|
||||||
Rid: (Rid)result["rid"],
|
|
||||||
Shape: result["shape"].AsInt32(),
|
|
||||||
Position: result["position"].AsVector2(),
|
|
||||||
Normal: result["normal"].AsVector2()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
public static IOption<RaycastResult2D> RaycastOptionEx(this PhysicsDirectSpaceState2D space, Vector2 from, Vector2 to, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
|
|
||||||
=> RaycastEx(space, from, to, collisionMask, exclude, hitFromInside).ToOption();
|
|
||||||
|
|
||||||
|
|
||||||
public static bool RaycastHitEx(this PhysicsDirectSpaceState2D space, Vector2 from, Vector2 to, out RaycastResult2D hit, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
|
|
||||||
{
|
|
||||||
hit = space.RaycastEx(from, to, collisionMask, exclude, hitFromInside)!;
|
|
||||||
return hit is not null;
|
|
||||||
}
|
|
||||||
// 3D Shape Cast
|
|
||||||
public static List<CollisionResultBase> IntersectShapeEx(this PhysicsDirectSpaceState3D space, PhysicsShapeQueryParameters3D query, int maxResults = 32)
|
|
||||||
{
|
|
||||||
var results = space.IntersectShape(query, maxResults);
|
|
||||||
var list = new List<CollisionResultBase>(results.Count);
|
|
||||||
|
|
||||||
foreach (var dict in results)
|
|
||||||
{
|
|
||||||
list.Add(new CollisionResultBase(
|
|
||||||
Collider: dict["collider"].AsGodotObject(),
|
|
||||||
ColliderId: dict["collider_id"].AsInt32(),
|
|
||||||
Rid: (Rid)dict["rid"],
|
|
||||||
Shape: dict["shape"].AsInt32()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2D Shape Cast
|
|
||||||
public static List<CollisionResultBase> IntersectShapeEx(this PhysicsDirectSpaceState2D space, PhysicsShapeQueryParameters2D query, int maxResults = 32)
|
|
||||||
{
|
|
||||||
var results = space.IntersectShape(query, maxResults);
|
|
||||||
var list = new List<CollisionResultBase>(results.Count);
|
|
||||||
|
|
||||||
foreach (var dict in results)
|
|
||||||
{
|
|
||||||
list.Add(new CollisionResultBase(
|
|
||||||
Collider: dict["collider"].AsGodotObject(),
|
|
||||||
ColliderId: dict["collider_id"].AsInt32(),
|
|
||||||
Rid: (Rid)dict["rid"],
|
|
||||||
Shape: dict["shape"].AsInt32()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://b8b5eyg6l31o1
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Array = Godot.Collections.Array;
|
|
||||||
namespace SJK.GodotHelpers;
|
|
||||||
/// <summary>
|
|
||||||
/// Strong‑typed view of Godot's get_method_list / get_property_list output.
|
|
||||||
/// </summary>
|
|
||||||
public static class Reflector
|
|
||||||
{
|
|
||||||
/* ──────────── Typed records ──────────── */
|
|
||||||
|
|
||||||
public readonly record struct ArgInfo(
|
|
||||||
string Name,
|
|
||||||
Variant.Type Type,
|
|
||||||
PropertyHint Hint,
|
|
||||||
string HintString,
|
|
||||||
Variant DefaultValue);
|
|
||||||
|
|
||||||
public readonly record struct MethodInfoEx(
|
|
||||||
string Name,
|
|
||||||
IReadOnlyList<ArgInfo> Args,
|
|
||||||
IReadOnlyList<Variant> DefaultArgs,
|
|
||||||
MethodFlags Flags,
|
|
||||||
int Id,
|
|
||||||
ArgInfo? ReturnValue);
|
|
||||||
|
|
||||||
public readonly record struct PropertyInfoEx(
|
|
||||||
string Name,
|
|
||||||
string ClassName,
|
|
||||||
Variant.Type Type,
|
|
||||||
PropertyHint Hint,
|
|
||||||
string HintString,
|
|
||||||
PropertyUsageFlags Usage);
|
|
||||||
|
|
||||||
/* ──────────── Public helpers ──────────── */
|
|
||||||
|
|
||||||
public static List<MethodInfoEx> GetMethodsListEx(this GodotObject godotObject)=>GetMethods(godotObject);
|
|
||||||
public static List<MethodInfoEx> GetMethods(GodotObject obj)
|
|
||||||
{
|
|
||||||
var raw = obj.GetMethodList();
|
|
||||||
var list = new List<MethodInfoEx>(raw.Count);
|
|
||||||
|
|
||||||
foreach (Dictionary dict in raw)
|
|
||||||
{
|
|
||||||
// — Parse args —
|
|
||||||
var argsRaw = (Array)dict["args"];
|
|
||||||
var args = new List<ArgInfo>(argsRaw.Count);
|
|
||||||
foreach (Dictionary a in argsRaw)
|
|
||||||
args.Add(ParseArg(a));
|
|
||||||
|
|
||||||
// — Parse return (may be empty) —
|
|
||||||
ArgInfo? ret = null;
|
|
||||||
if (dict.TryGetValue("return", out var retRaw) && retRaw.AsGodotDictionary() is Dictionary rd && rd.Count > 0)
|
|
||||||
ret = ParseArg(rd);
|
|
||||||
|
|
||||||
list.Add(new MethodInfoEx(
|
|
||||||
Name: (string)dict["name"],
|
|
||||||
Args: args,
|
|
||||||
DefaultArgs: (Array)dict["default_args"],
|
|
||||||
Flags: (MethodFlags)(int)dict["flags"],
|
|
||||||
Id: (int)dict["id"],
|
|
||||||
ReturnValue: ret
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
public static bool TryGetMethodInfo(this GodotObject godotObject, string property, out MethodInfoEx info){
|
|
||||||
foreach (var item in GetMethods(godotObject))
|
|
||||||
{
|
|
||||||
if (item.Name == property){
|
|
||||||
info = item;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public static List<PropertyInfoEx> GetPropertyListEx(this GodotObject godotObject)=>GetProperties(godotObject);
|
|
||||||
public static List<PropertyInfoEx> GetProperties(GodotObject obj)
|
|
||||||
{
|
|
||||||
var raw = obj.GetPropertyList();
|
|
||||||
var list = new List<PropertyInfoEx>(raw.Count);
|
|
||||||
|
|
||||||
foreach (Dictionary dict in raw)
|
|
||||||
{
|
|
||||||
list.Add(new PropertyInfoEx(
|
|
||||||
Name: (string)dict["name"],
|
|
||||||
ClassName: (string)dict["class_name"],
|
|
||||||
Type: (Variant.Type)(int)dict["type"],
|
|
||||||
Hint: (PropertyHint)(int)dict["hint"],
|
|
||||||
HintString: (string)dict["hint_string"],
|
|
||||||
Usage: (PropertyUsageFlags)(int)dict["usage"]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
public static PropertyInfoEx GetProperty(this IEnumerable<PropertyInfoEx> properties, string name)=>properties.FirstOrDefault(item=>item.Name == name);
|
|
||||||
public static bool TryGetPropertyInfo(this GodotObject godotObject, string property, out PropertyInfoEx info){
|
|
||||||
foreach (var item in GetProperties(godotObject))
|
|
||||||
{
|
|
||||||
if (item.Name == property){
|
|
||||||
info = item;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* ──────────── Internals ──────────── */
|
|
||||||
|
|
||||||
private static ArgInfo ParseArg(Dictionary d) => new(
|
|
||||||
Name: (string)d["name"],
|
|
||||||
Type: (Variant.Type)(int)d["type"],
|
|
||||||
Hint: (PropertyHint)(int)d["hint"],
|
|
||||||
HintString: (string)d["hint_string"],
|
|
||||||
DefaultValue: d.TryGetValue("default_value", out var dv) ? dv : default);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://bis0ef0hnuxin
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
namespace SJK.GodotHelpers;
|
|
||||||
public static class VariantUtils
|
|
||||||
{
|
|
||||||
public static Variant SafeToVariant(object value)
|
|
||||||
{
|
|
||||||
return value switch
|
|
||||||
{
|
|
||||||
null => new Variant(),
|
|
||||||
bool b => Variant.From(b),
|
|
||||||
int i => Variant.From(i),
|
|
||||||
long l => Variant.From((int)l), // Godot Variant only supports 32-bit int
|
|
||||||
float f => Variant.From(f),
|
|
||||||
double d => Variant.From((float)d),
|
|
||||||
string s => Variant.From(s),
|
|
||||||
Vector2 v2 => Variant.From(v2),
|
|
||||||
Vector2I v2i => Variant.From(v2i),
|
|
||||||
Vector3 v3 => Variant.From(v3),
|
|
||||||
Vector3I v3i => Variant.From(v3i),
|
|
||||||
Vector4 v4 => Variant.From(v4),
|
|
||||||
Vector4I v4i => Variant.From(v4i),
|
|
||||||
Rect2 rect2 => Variant.From(rect2),
|
|
||||||
Rect2I rect2i => Variant.From(rect2i),
|
|
||||||
Quaternion q => Variant.From(q),
|
|
||||||
Basis basis => Variant.From(basis),
|
|
||||||
Transform2D t2d => Variant.From(t2d),
|
|
||||||
Transform3D t3d => Variant.From(t3d),
|
|
||||||
Color color => Variant.From(color),
|
|
||||||
Plane plane => Variant.From(plane),
|
|
||||||
Aabb aabb => Variant.From(aabb),
|
|
||||||
GodotObject go => Variant.From(go),
|
|
||||||
byte[] bytes => Variant.From(bytes),
|
|
||||||
StringName sn => Variant.From(sn),
|
|
||||||
NodePath np => Variant.From(np),
|
|
||||||
Callable call => Variant.From(call),
|
|
||||||
Signal sig => Variant.From(sig),
|
|
||||||
Dictionary dict => Variant.From(dict),
|
|
||||||
Godot.Collections.Array array => Variant.From(array),
|
|
||||||
_ => throw new InvalidCastException($"Unsupported type '{value?.GetType().FullName}' for Variant conversion.")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public static Type GetSystemType(this Variant.Type type) => type switch
|
|
||||||
{
|
|
||||||
Variant.Type.Nil => typeof(object),
|
|
||||||
Variant.Type.Bool => typeof(bool),
|
|
||||||
Variant.Type.Int => typeof(int),
|
|
||||||
Variant.Type.Float => typeof(float),
|
|
||||||
Variant.Type.String => typeof(string),
|
|
||||||
Variant.Type.Vector2 => typeof(Vector2),
|
|
||||||
Variant.Type.Vector2I => typeof(Vector2I),
|
|
||||||
Variant.Type.Rect2 => typeof(Rect2),
|
|
||||||
Variant.Type.Rect2I => typeof(Rect2I),
|
|
||||||
Variant.Type.Vector3 => typeof(Vector3),
|
|
||||||
Variant.Type.Vector3I => typeof(Vector3I),
|
|
||||||
Variant.Type.Vector4 => typeof(Vector4),
|
|
||||||
Variant.Type.Vector4I => typeof(Vector4I),
|
|
||||||
Variant.Type.Transform2D => typeof(Transform2D),
|
|
||||||
Variant.Type.Transform3D => typeof(Transform3D),
|
|
||||||
Variant.Type.Basis => typeof(Basis),
|
|
||||||
Variant.Type.Quaternion => typeof(Quaternion),
|
|
||||||
Variant.Type.Aabb => typeof(Aabb),
|
|
||||||
Variant.Type.Color => typeof(Color),
|
|
||||||
Variant.Type.Plane => typeof(Plane),
|
|
||||||
Variant.Type.StringName => typeof(StringName),
|
|
||||||
Variant.Type.NodePath => typeof(NodePath),
|
|
||||||
Variant.Type.Rid => typeof(Rid),
|
|
||||||
Variant.Type.Object => typeof(GodotObject),
|
|
||||||
Variant.Type.Callable => typeof(Callable),
|
|
||||||
Variant.Type.Signal => typeof(Signal),
|
|
||||||
Variant.Type.Dictionary => typeof(Godot.Collections.Dictionary),
|
|
||||||
Variant.Type.Array => typeof(Godot.Collections.Array),
|
|
||||||
_ => typeof(object)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://b18a1dp6f8tsv
|
|
||||||
@@ -12,7 +12,8 @@ using SJK.Functional;
|
|||||||
|
|
||||||
[Tool]
|
[Tool]
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta(typeof(IAutoNode))]
|
||||||
public partial class BeltPort : Node3D, IBeltPort {
|
public partial class BeltPort : Node3D, IBeltPort
|
||||||
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
public override void _Notification(int what) => this.Notify(what);
|
||||||
[Dependency] public IVoxelGridRegistry Grid => this.DependOn<IVoxelGridRegistry>();
|
[Dependency] public IVoxelGridRegistry Grid => this.DependOn<IVoxelGridRegistry>();
|
||||||
[Export] public Direction Face { get; set; } = default!;
|
[Export] public Direction Face { get; set; } = default!;
|
||||||
@@ -122,9 +123,11 @@ public class CurveItemTransfer : IItemTransferAnimator
|
|||||||
);
|
);
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public Tween StartTransfer(ConveyorSlice item, Action onFinished = null){
|
public Tween StartTransfer(ConveyorSlice item, Action onFinished = null)
|
||||||
|
{
|
||||||
var tween = AnimateAlongCurve(item, Curve3D, 1, ItemRenderer);
|
var tween = AnimateAlongCurve(item, Curve3D, 1, ItemRenderer);
|
||||||
if (onFinished is not null){
|
if (onFinished is not null)
|
||||||
|
{
|
||||||
tween.TweenCallback(Callable.From(onFinished));
|
tween.TweenCallback(Callable.From(onFinished));
|
||||||
}
|
}
|
||||||
return tween;
|
return tween;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public partial class ConveyorItemRender : Node
|
|||||||
[Export] protected Path3D Path3D { get; set; } = default!;
|
[Export] protected Path3D Path3D { get; set; } = default!;
|
||||||
[Export] protected TestItemConveyor ItemConveyor { get; set; } = default!;
|
[Export] protected TestItemConveyor ItemConveyor { get; set; } = default!;
|
||||||
[Chickensoft.AutoInject.Dependency] protected IItemRenderer Items => this.DependOn<IItemRenderer>();
|
[Chickensoft.AutoInject.Dependency] protected IItemRenderer Items => this.DependOn<IItemRenderer>();
|
||||||
private Chickensoft.Sync.Primitives.AutoList<ConveyorSlice>.Binding binding = default!;
|
private Chickensoft.Sync.Primitives.AutoList<ConveyorSlice>.Binding _binding = default!;
|
||||||
public override async void _Ready()
|
public override async void _Ready()
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
@@ -24,7 +24,7 @@ public partial class ConveyorItemRender : Node
|
|||||||
{
|
{
|
||||||
await ToSignal(ItemConveyor, Node.SignalName.Ready);
|
await ToSignal(ItemConveyor, Node.SignalName.Ready);
|
||||||
}
|
}
|
||||||
binding = ItemConveyor.Items.Items.Bind();
|
_binding = ItemConveyor.Items.Items.Bind();
|
||||||
// binding.OnRemove(callback =>
|
// binding.OnRemove(callback =>
|
||||||
// {
|
// {
|
||||||
// Items.Remove(callback.Item);
|
// Items.Remove(callback.Item);
|
||||||
@@ -36,37 +36,14 @@ public partial class ConveyorItemRender : Node
|
|||||||
// // node.QueueFree();
|
// // node.QueueFree();
|
||||||
// // }
|
// // }
|
||||||
// });
|
// });
|
||||||
binding.OnAdd((i, v) =>
|
_binding.OnAdd((i, v) => Items.UpdateTransform(i.Item, Path3D.GlobalTransform * Path3D.Curve.SampleBakedWithRotation(i.BeltT)));
|
||||||
{
|
_binding.OnUpdate((a, b) => Items.UpdateTransform(a.Item, Path3D.GlobalTransform * Path3D.Curve.SampleBakedWithRotation(b.BeltT).Translated(-Path3D.Curve.SampleBakedWithRotation(b.BeltT).Basis.X * b.LaneSpan.Start)));
|
||||||
|
|
||||||
// itemsRenders[i.Item] = new MeshInstance3D(){Mesh = new BoxMesh()};
|
|
||||||
// AddSibling(itemsRenders[i.Item]);
|
|
||||||
// itemsRenders[i.Item].Transform = Path3D.Curve.SampleBakedWithRotation(i.BeltT);
|
|
||||||
// GD.Print($"Item : {i},{v} added");
|
|
||||||
Items.UpdateTransform(i.Item,Path3D.GlobalTransform *Path3D.Curve.SampleBakedWithRotation(i.BeltT));
|
|
||||||
});
|
|
||||||
binding.OnUpdate((a,b) =>
|
|
||||||
{
|
|
||||||
Items.UpdateTransform(a.Item, Path3D.GlobalTransform *Path3D.Curve.SampleBakedWithRotation(b.BeltT).Translated(-Path3D.Curve.SampleBakedWithRotation(b.BeltT).Basis.X*(b.LaneSpan.Start)));
|
|
||||||
return;
|
|
||||||
if (itemsRenders.TryGetValue(a.Item, out var node))
|
|
||||||
{
|
|
||||||
if (tweens.TryGetValue(a.Item, out var t))
|
|
||||||
{
|
|
||||||
t.Kill();
|
|
||||||
}
|
|
||||||
tweens[a.Item] = t = CreateTween();
|
|
||||||
t.TweenProperty(node, "transform",Path3D.Curve.SampleBakedWithRotation(b.BeltT), .25f);
|
|
||||||
// node.Transform = Path3D.Curve.SampleBakedWithRotation(b.BeltT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
private Dictionary<IBeltItem, Node3D> itemsRenders = [];//This would be an item server for reuse via depency
|
|
||||||
private Dictionary<IBeltItem, Tween> tweens = [];//This would be an item server for reuse via depency
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
binding.Dispose();
|
_binding.Dispose();
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,13 +61,15 @@ public partial class TestItemRendered : Node3D, IItemRenderer
|
|||||||
private ConditionalWeakTable<IBeltItem, Tween> _tweens = [];
|
private ConditionalWeakTable<IBeltItem, Tween> _tweens = [];
|
||||||
public void Remove(IBeltItem beltItem)
|
public void Remove(IBeltItem beltItem)
|
||||||
{
|
{
|
||||||
if (_items.TryGetValue(beltItem, out var node)){
|
if (_items.TryGetValue(beltItem, out var node))
|
||||||
|
{
|
||||||
node.QueueFree();
|
node.QueueFree();
|
||||||
}
|
}
|
||||||
_items.Remove(beltItem);
|
_items.Remove(beltItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateTransform(IBeltItem beltItem, Transform3D newTransform, float time ){
|
public void UpdateTransform(IBeltItem beltItem, Transform3D newTransform, float time)
|
||||||
|
{
|
||||||
if (!_items.TryGetValue(beltItem, out var node))
|
if (!_items.TryGetValue(beltItem, out var node))
|
||||||
{
|
{
|
||||||
_items.Add(beltItem, node = beltItem.CreateItemVisual());
|
_items.Add(beltItem, node = beltItem.CreateItemVisual());
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ public class Sorted1DList<T>
|
|||||||
public void Replace(T slice) => _replace(slice);
|
public void Replace(T slice) => _replace(slice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Meta(typeof(IAutoNode))][Tool]
|
[Meta(typeof(IAutoNode))]
|
||||||
|
[Tool]
|
||||||
public partial class TestItemConveyor : Node, IMovementConveyor
|
public partial class TestItemConveyor : Node, IMovementConveyor
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
public override void _Notification(int what) => this.Notify(what);
|
||||||
@@ -566,9 +567,6 @@ private static Vector3[] _Square = [new(-.5f, .5f, -.5f), new(.5f, .5f, -.5f), n
|
|||||||
// var upperObstacleAllowed = upperObstacle.DistanceToCenter - (upperObstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
|
// var upperObstacleAllowed = upperObstacle.DistanceToCenter - (upperObstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
|
||||||
// return ItemConveyor.ITEMSIZE < lowerDistanceAllowed && ItemConveyor.ITEMSIZE < upperObstacleAllowed;
|
// return ItemConveyor.ITEMSIZE < lowerDistanceAllowed && ItemConveyor.ITEMSIZE < upperObstacleAllowed;
|
||||||
}
|
}
|
||||||
// return true;
|
|
||||||
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
// if (beltT is ItemConveyor.BeltTEnd end && end.End == ItemConveyor.ConveyorEnd.End){
|
// if (beltT is ItemConveyor.BeltTEnd end && end.End == ItemConveyor.ConveyorEnd.End){
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridQuery<LayeredEqu
|
|||||||
IItemRenderer IProvide<IItemRenderer>.Value() => _itemRenderer;
|
IItemRenderer IProvide<IItemRenderer>.Value() => _itemRenderer;
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
TestStructural.Test();
|
|
||||||
GD.Print();
|
GD.Print();
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_voxelGrid = new EquipmentVoxelGrid();
|
_voxelGrid = new EquipmentVoxelGrid();
|
||||||
@@ -107,7 +106,8 @@ public class LayeredEquipment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public sealed class SlotDescriptor {
|
public sealed class SlotDescriptor
|
||||||
|
{
|
||||||
public SlotDirection Direction { get; }
|
public SlotDirection Direction { get; }
|
||||||
|
|
||||||
public SlotDescriptor(
|
public SlotDescriptor(
|
||||||
@@ -117,10 +117,12 @@ public sealed class SlotDescriptor {
|
|||||||
Direction = direction;
|
Direction = direction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public abstract class SlotLogic<TPayload> {
|
public abstract class SlotLogic<TPayload>
|
||||||
|
{
|
||||||
public SlotDescriptor Descriptor { get; }
|
public SlotDescriptor Descriptor { get; }
|
||||||
|
|
||||||
protected SlotLogic(SlotDescriptor descriptor) {
|
protected SlotLogic(SlotDescriptor descriptor)
|
||||||
|
{
|
||||||
Descriptor = descriptor;
|
Descriptor = descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +135,8 @@ public abstract class SlotLogic<TPayload> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
public sealed class ItemSlotLogic
|
public sealed class ItemSlotLogic
|
||||||
: SlotLogic<IBeltItem> {
|
: SlotLogic<IBeltItem>
|
||||||
|
{
|
||||||
|
|
||||||
public ItemSlotLogic(SlotDescriptor descriptor)
|
public ItemSlotLogic(SlotDescriptor descriptor)
|
||||||
: base(descriptor) { }
|
: base(descriptor) { }
|
||||||
@@ -141,18 +144,21 @@ public sealed class ItemSlotLogic
|
|||||||
public override bool CanTransfer(IBeltItem item) => false;
|
public override bool CanTransfer(IBeltItem item) => false;
|
||||||
// item.Count > 0;
|
// item.Count > 0;
|
||||||
|
|
||||||
public override bool TryTransfer(IBeltItem item) {
|
public override bool TryTransfer(IBeltItem item)
|
||||||
|
{
|
||||||
// routing rules
|
// routing rules
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Meta]
|
[Meta]
|
||||||
public partial class ItemSlotNode
|
public partial class ItemSlotNode
|
||||||
: SlotComponentNode {
|
: SlotComponentNode
|
||||||
|
{
|
||||||
|
|
||||||
private ItemSlotLogic _logic;
|
private ItemSlotLogic _logic;
|
||||||
|
|
||||||
public override void _Ready() {
|
public override void _Ready()
|
||||||
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_logic = new ItemSlotLogic(
|
_logic = new ItemSlotLogic(
|
||||||
new SlotDescriptor(Direction)
|
new SlotDescriptor(Direction)
|
||||||
@@ -163,7 +169,8 @@ public partial class ItemSlotNode
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick(IBeltItem stack) {
|
public void Tick(IBeltItem stack)
|
||||||
|
{
|
||||||
if (_logic.CanTransfer(stack))
|
if (_logic.CanTransfer(stack))
|
||||||
_logic.TryTransfer(stack);
|
_logic.TryTransfer(stack);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user