diff --git a/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentDataFeedItem.cs b/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentDataFeedItem.cs index 8367cf3..1b0db48 100644 --- a/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentDataFeedItem.cs +++ b/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentDataFeedItem.cs @@ -1,5 +1,6 @@ using Elements.Core; using FrooxEngine; +using System; namespace Obsidian; diff --git a/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentsDataFeed.cs b/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentsDataFeed.cs index 8948db9..d0b1576 100644 --- a/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentsDataFeed.cs +++ b/ProjectObsidian/Components/Radiant UI/Data Feeds/Feeds/ComponentsDataFeed.cs @@ -59,7 +59,7 @@ private void OnSlotComponentRemoved(Component c) { var result = updateHandler.Value.RemoveComponent(c); result.data.ClearSubmitted(); - updateHandler.Key.handler(ToItem(result.data), DataFeedItemChange.Removed); + updateHandler.Key.handler(GenerateComponent(result.data), DataFeedItemChange.Removed); } } @@ -99,12 +99,12 @@ private void ProcessUpdate(SearchPhraseFeedUpdateHandler handler, ComponentData if (data.Submitted) { data.ClearSubmitted(); - handler.handler(ToItem(data), DataFeedItemChange.Removed); + handler.handler(GenerateComponent(data), DataFeedItemChange.Removed); } return; } data.MarkSubmitted(); - DataFeedItem item = ToItem(data); + DataFeedItem item = GenerateComponent(data); handler.handler(item, DataFeedItemChange.Added); } @@ -120,10 +120,18 @@ private void Unsubscribe(Slot s) s.ComponentRemoved -= OnSlotComponentRemoved; } - protected override void OnAwake() + protected override void OnStart() { - base.OnAwake(); + base.OnStart(); _lastSlot = TargetSlot.Target; + if (_lastSlot != null) + { + Subscribe(_lastSlot); + if (IncludeChildrenSlots) + { + _lastSlot.ForeachChild(childSlot => Subscribe(childSlot)); + } + } } protected override void OnChanges() @@ -226,6 +234,14 @@ private DataFeedCategory GenerateCategory(string key, IReadOnlyList path return dataFeedCategory; } + private TypeFeedItem GenerateType(Type type, string key, IReadOnlyList path) + { + TypeFeedItem typeFeedItem = new TypeFeedItem(type); + // random icon + typeFeedItem.InitBase(key, path, null, type.GetNiceName(), OfficialAssets.Graphics.Icons.Gizmo.TransformLocal); + return typeFeedItem; + } + public async IAsyncEnumerable Enumerate(IReadOnlyList path, IReadOnlyList groupKeys, string searchPhrase, object viewData) { if (TargetSlot.Target != null && (path != null && path.Count > 0)) @@ -324,7 +340,14 @@ public async IAsyncEnumerable Enumerate(IReadOnlyList path if (componentData.MatchesSearchParameters(optionalTerms, requiredTerms, excludedTerms)) { componentData.MarkSubmitted(); - yield return ToItem(componentData); + if (TargetSlot.Target != null) + { + yield return GenerateComponent(componentData); + } + else + { + yield return GenerateType(componentData.ComponentType, componentData.ComponentType.GetHashCode().ToString(), path); + } } } Pool.Return(ref optionalTerms); @@ -332,7 +355,7 @@ public async IAsyncEnumerable Enumerate(IReadOnlyList path Pool.Return(ref excludedTerms); } - private DataFeedItem ToItem(ComponentData data) + private ComponentDataFeedItem GenerateComponent(ComponentData data) { return new ComponentDataFeedItem(data); } diff --git a/ProjectObsidian/Components/Radiant UI/Data Feeds/Interfaces/TypeFeedItem.cs b/ProjectObsidian/Components/Radiant UI/Data Feeds/Interfaces/TypeFeedItem.cs new file mode 100644 index 0000000..85056a6 --- /dev/null +++ b/ProjectObsidian/Components/Radiant UI/Data Feeds/Interfaces/TypeFeedItem.cs @@ -0,0 +1,38 @@ +using Elements.Core; +using FrooxEngine; +using System; + +namespace Obsidian; + +public class TypeFeedItem : DataFeedItem +{ + public Type Type; + + public bool IsGenericType; + + public Type GenericTypeDefinition; + + public SlimList GenericTypes; + + public int GenericTypesCount; + + public TypeFeedItem(Type type) + { + InitBase(type.GetHashCode().ToString(), null, null, type.GetNiceName()); + Type = type; + IsGenericType = type.IsGenericType; + GenericTypeDefinition = IsGenericType ? type.GetGenericTypeDefinition() : null; + int count = 0; + if (type.IsGenericTypeDefinition) + { + foreach (Type genericType in WorkerInitializer.GetCommonGenericTypes(type)) + { + TypeFeedItem typeFeedItem = new TypeFeedItem(genericType); + typeFeedItem.InitBase(genericType.GetHashCode().ToString(), null, null, genericType.GetNiceName()); + GenericTypes.Add(typeFeedItem); + count++; + } + } + GenericTypesCount = count; + } +} \ No newline at end of file diff --git a/ProjectObsidian/Components/Radiant UI/Data Feeds/Interfaces/TypeItemInterface.cs b/ProjectObsidian/Components/Radiant UI/Data Feeds/Interfaces/TypeItemInterface.cs new file mode 100644 index 0000000..ead6479 --- /dev/null +++ b/ProjectObsidian/Components/Radiant UI/Data Feeds/Interfaces/TypeItemInterface.cs @@ -0,0 +1,31 @@ +using System; +using FrooxEngine; + +namespace Obsidian; + +[Category(new string[] { "Obsidian/Radiant UI/Data Feeds/Interfaces" })] +public class TypeItemInterface : FeedItemInterface +{ + public readonly SyncRef> Type; + + public readonly SyncRef> IsGenericType; + + public readonly SyncRef> GenericTypeDefinition; + + public readonly SyncRef> GenericTypesCount; + + public readonly FeedSubTemplate GenericTypes; + + public override void Set(IDataFeedView view, DataFeedItem item) + { + base.Set(view, item); + if (item is TypeFeedItem typeFeedItem) + { + Type.TrySetTarget(typeFeedItem.Type); + IsGenericType.TrySetTarget(typeFeedItem.IsGenericType); + GenericTypeDefinition.TrySetTarget(typeFeedItem.GenericTypeDefinition); + GenericTypesCount.TrySetTarget(typeFeedItem.GenericTypesCount); + GenericTypes.Set(typeFeedItem.GenericTypes, view); + } + } +} \ No newline at end of file diff --git a/ProjectObsidian/Components/Utility/IsValidGenericTypeDriver.cs b/ProjectObsidian/Components/Utility/IsValidGenericTypeDriver.cs new file mode 100644 index 0000000..1f63e89 --- /dev/null +++ b/ProjectObsidian/Components/Utility/IsValidGenericTypeDriver.cs @@ -0,0 +1,28 @@ +using Elements.Core; +using FrooxEngine; +using System; +using System.Linq; + +namespace Obsidian; + +[Category(new string[] { "Obsidian/Utility" })] +public class IsValidGenericTypeDriver : Component +{ + public readonly SyncType Type; + + public readonly FieldDrive Target; + + protected override void OnChanges() + { + base.OnChanges(); + if (!Target.IsLinkValid) return; + if (Type.Value == null || !Type.Value.IsGenericType) + { + Target.Target.Value = false; + } + else + { + Target.Target.Value = Type.Value.IsValidGenericType(validForInstantiation: true); + } + } +} \ No newline at end of file diff --git a/ProjectObsidian/Components/Utility/StringToTypeDriver.cs b/ProjectObsidian/Components/Utility/StringToTypeDriver.cs new file mode 100644 index 0000000..ce2c61a --- /dev/null +++ b/ProjectObsidian/Components/Utility/StringToTypeDriver.cs @@ -0,0 +1,36 @@ +using Elements.Core; +using FrooxEngine; +using System; + +namespace Obsidian; + +[Category(new string[] { "Obsidian/Utility" })] +public class StringToTypeDriver : Component +{ + public readonly Sync Text; + + public readonly FieldDrive Target; + + protected override void OnChanges() + { + base.OnChanges(); + if (!Target.IsLinkValid) return; + if (string.IsNullOrWhiteSpace(Text.Value)) + { + Target.Target.Value = null; + } + else + { + try + { + var parsedType = WorkerManager.ParseNiceType(Text.Value); + Target.Target.Value = parsedType; + } + catch (Exception ex) + { + UniLog.Warning("Exception when parsing type from string:\n" + ex.ToString()); + Target.Target.Value = null; + } + } + } +} \ No newline at end of file