diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index dbae3fed..4cee2393 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -156,6 +156,7 @@ + diff --git a/FModel/Framework/Command.cs b/FModel/Framework/Command.cs index ed4b1d61..329eb404 100644 --- a/FModel/Framework/Command.cs +++ b/FModel/Framework/Command.cs @@ -15,4 +15,19 @@ public abstract class Command : ICommand } public event EventHandler CanExecuteChanged; -} \ No newline at end of file +} + +public class DelegateCommand : Command +{ + private readonly Action _action; + private readonly Func? _condition; + + public DelegateCommand(Action action, Func? executeCondition = default) + { + _action = action ?? throw new ArgumentNullException(nameof(action)); + _condition = executeCondition; + } + + public override void Execute(object parameter) => _action(); + public override bool CanExecute(object parameter) => _condition?.Invoke() ?? true; +} diff --git a/FModel/Framework/NodifyObservableCollection.cs b/FModel/Framework/NodifyObservableCollection.cs new file mode 100644 index 00000000..ce5eef9a --- /dev/null +++ b/FModel/Framework/NodifyObservableCollection.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; + +namespace FModel.Framework; + +public interface INodifyObservableCollection +{ + /// + /// Called when a new item is added + /// + /// The callback to execute when an item is added + /// Returns self + INodifyObservableCollection WhenAdded(Action added); + + /// + /// Called when an existing item is removed + /// Note: It is not called when items are cleared if is used + /// + /// The callback to execute when an item is removed + /// Returns self + INodifyObservableCollection WhenRemoved(Action removed); + + /// + /// Called when the collection is cleared + /// NOTE: It does not call on each item + /// + /// The callback to execute when the collection is cleared + /// Returns self + INodifyObservableCollection WhenCleared(Action> cleared); +} + +public class NodifyObservableCollection : Collection, INodifyObservableCollection, INotifyPropertyChanged, INotifyCollectionChanged +{ + protected static readonly PropertyChangedEventArgs IndexerPropertyChanged = new("Item[]"); + protected static readonly PropertyChangedEventArgs CountPropertyChanged = new("Count"); + protected static readonly NotifyCollectionChangedEventArgs ResetCollectionChanged = new(NotifyCollectionChangedAction.Reset); + + private readonly List> _added = []; + private readonly List> _removed = []; + private readonly List>> _cleared = []; + + public event NotifyCollectionChangedEventHandler? CollectionChanged; + public event PropertyChangedEventHandler? PropertyChanged; + + public NodifyObservableCollection() + { + } + + public NodifyObservableCollection(IEnumerable collection) + : base(new List(collection)) + { + } + + #region Collection Events + + public INodifyObservableCollection WhenAdded(Action added) + { + if (added != null) + { + _added.Add(added); + } + return this; + } + + public INodifyObservableCollection WhenRemoved(Action removed) + { + if (removed != null) + { + _removed.Add(removed); + } + return this; + } + + public INodifyObservableCollection WhenCleared(Action> cleared) + { + if (cleared != null) + { + _cleared.Add(cleared); + } + return this; + } + + protected virtual void NotifyOnItemAdded(T item) + { + for (int i = 0; i < _added.Count; i++) + { + _added[i](item); + } + } + + protected virtual void NotifyOnItemRemoved(T item) + { + for (int i = 0; i < _removed.Count; i++) + { + _removed[i](item); + } + } + + protected virtual void NotifyOnItemsCleared(IList items) + { + for (int i = 0; i < _cleared.Count; i++) + { + _cleared[i](items); + } + } + + #endregion + + #region Collection Handlers + + protected override void ClearItems() + { + var items = _cleared.Count > 0 || _removed.Count > 0 ? new List(this) : new List(); + base.ClearItems(); + + if (_cleared.Count > 0) + { + NotifyOnItemsCleared(items); + } + else if (_removed.Count > 0) + { + for (int i = 0; i < items.Count; i++) + { + NotifyOnItemRemoved(items[i]); + } + } + + OnPropertyChanged(CountPropertyChanged); + OnPropertyChanged(IndexerPropertyChanged); + OnCollectionChanged(ResetCollectionChanged); + } + + protected override void InsertItem(int index, T item) + { + base.InsertItem(index, item); + + OnPropertyChanged(CountPropertyChanged); + OnPropertyChanged(IndexerPropertyChanged); + OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index); + NotifyOnItemAdded(item); + } + + protected override void RemoveItem(int index) + { + var item = base[index]; + base.RemoveItem(index); + + OnPropertyChanged(CountPropertyChanged); + OnPropertyChanged(IndexerPropertyChanged); + OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index); + NotifyOnItemRemoved(item); + } + + protected override void SetItem(int index, T item) + { + T prev = base[index]; + base.SetItem(index, item); + OnPropertyChanged(IndexerPropertyChanged); + OnCollectionChanged(NotifyCollectionChangedAction.Replace, prev, item, index); + NotifyOnItemRemoved(prev); + NotifyOnItemAdded(item); + } + + public void Move(int oldIndex, int newIndex) + { + T prev = base[oldIndex]; + base.RemoveItem(oldIndex); + base.InsertItem(newIndex, prev); + OnPropertyChanged(IndexerPropertyChanged); + OnCollectionChanged(NotifyCollectionChangedAction.Move, prev, newIndex, oldIndex); + } + + protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + => CollectionChanged?.Invoke(this, e); + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + => PropertyChanged?.Invoke(this, args); + + private void OnCollectionChanged(NotifyCollectionChangedAction action, object? item, int index) + => OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index)); + + private void OnCollectionChanged(NotifyCollectionChangedAction action, object? item, int index, int oldIndex) + => OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex)); + + private void OnCollectionChanged(NotifyCollectionChangedAction action, object? oldItem, object? newItem, int index) + => OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index)); + + #endregion +} diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 1fe3623a..c1cb5093 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -83,9 +83,9 @@ public partial class MainWindow ).ConfigureAwait(false); #if DEBUG - // await _threadWorkerView.Begin(cancellationToken => - // _applicationView.CUE4Parse.Extract(cancellationToken, - // "FortniteGame/Content/Athena/Apollo/Maps/UI/Apollo_Terrain_Minimap.uasset")); + await _threadWorkerView.Begin(cancellationToken => + _applicationView.CUE4Parse.Extract(cancellationToken, + "FortniteGame/Plugins/GameFeatures/BRCosmetics/Content/Athena/Items/Cosmetics/Characters/Character_Amour.uasset")); // await _threadWorkerView.Begin(cancellationToken => // _applicationView.CUE4Parse.Extract(cancellationToken, // "FortniteGame/Content/Environments/Helios/Props/GlacierHotel/GlacierHotel_Globe_A/Meshes/SM_GlacierHotel_Globe_A.uasset")); diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index ef4928c9..b13caaf1 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -8,9 +8,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; - using AdonisUI.Controls; - using CUE4Parse.Compression; using CUE4Parse.Encryption.Aes; using CUE4Parse.FileProvider; @@ -53,7 +51,6 @@ using CUE4Parse.UE4.Wwise; using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; -using CUE4Parse.UE4.Assets; using EpicManifestParser; using FModel.Creator; @@ -61,6 +58,7 @@ using FModel.Extensions; using FModel.Framework; using FModel.Services; using FModel.Settings; +using FModel.ViewModels.Nodify; using FModel.Views; using FModel.Views.Resources.Controls; using FModel.Views.Snooper; @@ -612,15 +610,18 @@ public class CUE4ParseViewModel : ViewModel case "uasset": case "umap": { - var exports = Provider.LoadAllObjects(fullPath); - TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(exports, Formatting.Indented), saveProperties, updateUi); - if (HasFlag(bulk, EBulkType.Properties)) break; // do not search for viewable exports if we are dealing with jsons + var package = Provider.LoadPackage(fullPath); + TabControl.SelectedTab.NodifyEditor = new NodifyEditorViewModel(package); - foreach (var e in exports) - { - if (CheckExport(cancellationToken, e, bulk)) - break; - } + // var exports = Provider.LoadAllObjects(fullPath); + // TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(exports, Formatting.Indented), saveProperties, updateUi); + // if (HasFlag(bulk, EBulkType.Properties)) break; // do not search for viewable exports if we are dealing with jsons + // + // foreach (var e in exports) + // { + // if (CheckExport(cancellationToken, e, bulk)) + // break; + // } break; } diff --git a/FModel/ViewModels/Nodify/ConnectionViewModel.cs b/FModel/ViewModels/Nodify/ConnectionViewModel.cs new file mode 100644 index 00000000..3086e612 --- /dev/null +++ b/FModel/ViewModels/Nodify/ConnectionViewModel.cs @@ -0,0 +1,32 @@ +using FModel.Framework; + +namespace FModel.ViewModels.Nodify; + +public class ConnectionViewModel : ViewModel +{ + private ConnectorViewModel _input; + public ConnectorViewModel Input + { + get => _input; + set => SetProperty(ref _input, value); + } + + private ConnectorViewModel _output; + public ConnectorViewModel Output + { + get => _output; + set => SetProperty(ref _output, value); + } + + private bool _isSelected; + public bool IsSelected + { + get => _isSelected; + set => SetProperty(ref _isSelected, value); + } + + public ConnectionViewModel() + { + + } +} diff --git a/FModel/ViewModels/Nodify/ConnectorViewModel.cs b/FModel/ViewModels/Nodify/ConnectorViewModel.cs new file mode 100644 index 00000000..9a0d1611 --- /dev/null +++ b/FModel/ViewModels/Nodify/ConnectorViewModel.cs @@ -0,0 +1,69 @@ +using System.Windows; +using CUE4Parse.UE4.Assets.Objects.Properties; +using FModel.Framework; + +namespace FModel.ViewModels.Nodify; + +public enum ConnectorFlow +{ + Input, + Output +} + +public enum ConnectorShape +{ + Circle, + Triangle, + Square, +} + +public class ConnectorViewModel : ViewModel +{ + private string? _title; + public string? Title + { + get => _title; + set => SetProperty(ref _title, value); + } + + private bool _isConnected; + public bool IsConnected + { + get => _isConnected; + set => SetProperty(ref _isConnected, value); + } + + private Point _anchor; + public Point Anchor + { + get => _anchor; + set => SetProperty(ref _anchor, value); + } + + private ConnectorShape _shape; + public ConnectorShape Shape + { + get => _shape; + set => SetProperty(ref _shape, value); + } + + public NodeViewModel Node { get; set; } + public ConnectorFlow Flow { get; set; } + + public NodifyObservableCollection Connections { get; } = new(); + + public ConnectorViewModel() + { + Connections.WhenAdded(c => c.Input = this); + } + + public ConnectorViewModel(string title) : this() + { + Title = title; + } + + public ConnectorViewModel(FPropertyTagType? tag) : this(tag?.ToString()) + { + + } +} diff --git a/FModel/ViewModels/Nodify/FlowNodeViewModel.cs b/FModel/ViewModels/Nodify/FlowNodeViewModel.cs new file mode 100644 index 00000000..31e86287 --- /dev/null +++ b/FModel/ViewModels/Nodify/FlowNodeViewModel.cs @@ -0,0 +1,60 @@ +using System.Windows.Controls; +using CUE4Parse.UE4.Assets.Objects; +using CUE4Parse.UE4.Assets.Objects.Properties; +using CUE4Parse.UE4.Objects.Core.i18N; +using CUE4Parse.UE4.Objects.UObject; +using FModel.Framework; + +namespace FModel.ViewModels.Nodify; + +public class FlowNodeViewModel : NodeViewModel +{ + private string? _title; + public string? Title + { + get => _title; + set => SetProperty(ref _title, value); + } + + public NodifyObservableCollection Input { get; } = new(); + public NodifyObservableCollection Output { get; } = new(); + + public FlowNodeViewModel() + { + Input.WhenAdded(c => + { + c.Flow = ConnectorFlow.Input; + c.Node = this; + }); + Output.WhenAdded(c => + { + c.Flow = ConnectorFlow.Output; + c.Node = this; + }); + + Orientation = Orientation.Horizontal; + } + + protected void ConnectOutput(ConnectorViewModel output, FPropertyTagType? tag) + { + switch (tag) + { + case FPropertyTagType { Value: not null } s: + switch (s.Value.StructType) + { + case FStructFallback fallback: + break; + } + break; + case FPropertyTagType { Value.Properties.Count: > 0 } a: + break; + case FPropertyTagType { Value: not null } p: + break; + case FPropertyTagType s: + break; + case { } t: + output.Title = t.GenericValue?.ToString(); + break; + } + } +} diff --git a/FModel/ViewModels/Nodify/IndexedNodeViewModel.cs b/FModel/ViewModels/Nodify/IndexedNodeViewModel.cs new file mode 100644 index 00000000..c7ef104a --- /dev/null +++ b/FModel/ViewModels/Nodify/IndexedNodeViewModel.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using CUE4Parse.UE4.Assets.Objects.Properties; +using FModel.Framework; + +namespace FModel.ViewModels.Nodify; + +public class IndexedNodeViewModel : BaseIndexedNodeViewModel +{ + public IndexedNodeViewModel(List properties) : base(properties.Count) { } + + protected override void OnArrayIndexChanged() + { + + } +} + +public abstract class BaseIndexedNodeViewModel : FlowNodeViewModel +{ + private int _arrayIndex = -1; + public int ArrayIndex + { + get => _arrayIndex; + set + { + if (!SetProperty(ref _arrayIndex, value)) return; + + RaisePropertyChanged(nameof(DisplayIndex)); + NextCommand.RaiseCanExecuteChanged(); + PreviousCommand.RaiseCanExecuteChanged(); + + Input.Clear(); + Output.Clear(); + OnArrayIndexChanged(); + } + } + public int ArrayMax { get; } + + public DelegateCommand NextCommand { get; } + public DelegateCommand PreviousCommand { get; } + + public BaseIndexedNodeViewModel(int arrayMax) + { + NextCommand = new DelegateCommand(() => ArrayIndex++, () => ArrayIndex < ArrayMax - 1); + PreviousCommand = new DelegateCommand(() => ArrayIndex--, () => ArrayIndex > 0); + + ArrayMax = arrayMax; + ArrayIndex = 0; + } + + protected abstract void OnArrayIndexChanged(); + + public int DisplayIndex => ArrayIndex + 1; +} diff --git a/FModel/ViewModels/Nodify/NodeViewModel.cs b/FModel/ViewModels/Nodify/NodeViewModel.cs new file mode 100644 index 00000000..a4704e5b --- /dev/null +++ b/FModel/ViewModels/Nodify/NodeViewModel.cs @@ -0,0 +1,24 @@ +using System.Windows; +using System.Windows.Controls; +using FModel.Framework; + +namespace FModel.ViewModels.Nodify; + +public abstract class NodeViewModel : ViewModel +{ + public NodifyEditorViewModel Graph { get; set; } + + private Point _location; + public Point Location + { + get => _location; + set => SetProperty(ref _location, value); + } + + public Orientation Orientation { get; protected set; } + + protected NodeViewModel() + { + + } +} diff --git a/FModel/ViewModels/Nodify/NodifyEditorViewModel.cs b/FModel/ViewModels/Nodify/NodifyEditorViewModel.cs new file mode 100644 index 00000000..78aec7ed --- /dev/null +++ b/FModel/ViewModels/Nodify/NodifyEditorViewModel.cs @@ -0,0 +1,201 @@ +using System.Collections.ObjectModel; +using System.Windows; +using CUE4Parse.UE4.Assets; +using FModel.Framework; + +namespace FModel.ViewModels.Nodify; + +public class NodifyEditorViewModel : ViewModel +{ + public NodifyEditorViewModel() + { + Nodes + .WhenAdded(n => n.Graph = this) + .WhenCleared(_ => Connections.Clear()); + } + + public NodifyEditorViewModel(IPackage package) : this() + { + var root = new PackagedNodeViewModel(package); + Nodes.Add(root); + } + + // private void AddToCollection(NodeViewModel parent, NodeViewModel node) + // { + // parent.Children.Add(Nodes.Count); + // Nodes.Add(node); + // } + // + // private void AddPropertyToNode(NodeViewModel parent, IPropertyHolder holder) => AddPropertyToNode(parent, holder.Properties); + // private void AddPropertyToNode(NodeViewModel parent, List properties) + // { + // var node = new NodeViewModel { Title = "Properties", Depth = parent.Depth + 1 }; + // properties.ForEach(p => AddPropertyToNode(parent, node, p.Name.ToString(), p.Tag, p.TagData)); + // AddToCollection(parent, node); + // } + // + // private void AddPropertyToNode(NodeViewModel parent, List properties, FPropertyTagData type) + // { + // var node = new ArrayNodeViewModel { Title = "Properties", Depth = parent.Depth + 1, ArraySize = properties.Count }; + // AddPropertyToNode(parent, node, "In", properties[0], type); + // AddToCollection(parent, node); + // } + // + // private void AddPropertyToNode(NodeViewModel parent, NodeViewModel node, string name, FPropertyTagType tag, FPropertyTagData type) + // { + // switch (tag) + // { + // case FPropertyTagType { Value: not null } s: + // switch (s.Value.StructType) + // { + // case FStructFallback fallback: + // if (node.Input.Count == 0) + // { + // // node.Output.RemoveAt(node.Output.Count - 1); + // fallback.Properties.ForEach(p => AddPropertyToNode(parent, node, p.Name.ToString(), p.Tag, p.TagData)); + // } + // else + // { + // AddPropertyToNode(node, fallback); + // } + // break; + // default: + // var fields = s.Value.StructType.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public); + // AddPropertyToNode(node, fields.Select(field => new FPropertyTag(field, s.Value.StructType)).ToList()); + // break; + // } + // break; + // case FPropertyTagType { Value.Properties.Count: > 0 } a: + // AddPropertyToNode(node, a.Value.Properties, a.Value.InnerTagData); + // break; + // // case FPropertyTagType { Value: not null } i: + // // // special node that if clicked will open the asset + // // break; + // // case FPropertyTagType s: + // // // special node that if clicked will open the asset + // // break; + // case { } t: + // AddPropertyToNode(node, name, t.GenericValue); + // break; + // default: + // AddPropertyToNode(node, name, tag); + // break; + // } + // + // if (parent.Output.Count > 0 && node.Input.Count > 0) + // { + // Connections.Add(new ConnectionViewModel(parent.Output[^1], node.Input[^1])); + // } + // } + // + // private void AddPropertyToNode(NodeViewModel node, string name, object? property) + // { + // node.AddProperty(name, property?.ToString() ?? "null"); + // } + // + // private const int MarginX = 64; + // private const int MarginY = 16; + // + // public void OrganizeNodes() => OrganizeNodes(Nodes[^1]); + // private void OrganizeNodes(NodeViewModel root) + // { + // FirstPass(root); + // AssignFinalPositions(root); + // } + // + // private double currentLeafY = 0; + // + // private void FirstPass(NodeViewModel node, double x = 0) + // { + // node.X = x; + // + // if (node.Children.Count == 0) + // { + // node.Y = currentLeafY; + // currentLeafY += node.ActualSize.Height + MarginY; + // } + // else + // { + // foreach (var child in node.Children) + // { + // FirstPass(Nodes[child], node.X + node.ActualSize.Width + MarginX); + // } + // + // var leftmost = Nodes[node.Children[0]]; + // var rightmost = Nodes[node.Children[^1]]; + // node.Y = (leftmost.Y + rightmost.Y) / 2; + // } + // } + // + // private void AssignFinalPositions(NodeViewModel node) + // { + // node.Location = new Point((int)node.X, (int)node.Y); + // foreach (var child in node.Children) + // { + // AssignFinalPositions(Nodes[child]); + // } + // } + + private NodifyObservableCollection _nodes = new(); + public NodifyObservableCollection Nodes + { + get => _nodes; + set => SetProperty(ref _nodes, value); + } + + private ObservableCollection _selectedNodes = new(); + public ObservableCollection SelectedNodes + { + get => _selectedNodes; + set => SetProperty(ref _selectedNodes, value); + } + + private NodifyObservableCollection _connections = new(); + public NodifyObservableCollection Connections + { + get => _connections; + set => SetProperty(ref _connections, value); + } + + private ObservableCollection _selectedConnections = new(); + public ObservableCollection SelectedConnections + { + get => _selectedConnections; + set => SetProperty(ref _selectedConnections, value); + } + + private ConnectionViewModel? _selectedConnection; + public ConnectionViewModel? SelectedConnection + { + get => _selectedConnection; + set => SetProperty(ref _selectedConnection, value); + } + + private NodeViewModel? _selectedNode; + public NodeViewModel? SelectedNode + { + get => _selectedNode; + set => SetProperty(ref _selectedNode, value); + } + + private Size _viewportSize; + public Size ViewportSize + { + get => _viewportSize; + set => SetProperty(ref _viewportSize, value); + } + + private Point _viewportLocation; + public Point ViewportLocation + { + get => _viewportLocation; + set => SetProperty(ref _viewportLocation, value); + } + + private double _viewportZoom; + public double ViewportZoom + { + get => _viewportZoom; + set => SetProperty(ref _viewportZoom, value); + } +} diff --git a/FModel/ViewModels/Nodify/PackagedNodeViewModel.cs b/FModel/ViewModels/Nodify/PackagedNodeViewModel.cs new file mode 100644 index 00000000..f5243f22 --- /dev/null +++ b/FModel/ViewModels/Nodify/PackagedNodeViewModel.cs @@ -0,0 +1,19 @@ +using CUE4Parse.UE4.Assets; + +namespace FModel.ViewModels.Nodify; + +public class PackagedNodeViewModel(IPackage package) : BaseIndexedNodeViewModel(package.ExportsLazy.Length) +{ + protected override void OnArrayIndexChanged() + { + var export = package.ExportsLazy[ArrayIndex].Value; + Title = export.Name; + + foreach (var property in export.Properties) + { + Input.Add(new ConnectorViewModel(property.Name.Text)); + Output.Add(new ConnectorViewModel(property.TagData?.ToString())); + ConnectOutput(Output[^1], property.Tag); + } + } +} diff --git a/FModel/ViewModels/TabControlViewModel.cs b/FModel/ViewModels/TabControlViewModel.cs index a09c1596..2f427de8 100644 --- a/FModel/ViewModels/TabControlViewModel.cs +++ b/FModel/ViewModels/TabControlViewModel.cs @@ -16,6 +16,7 @@ using System.Windows; using System.Windows.Media.Imaging; using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse_Conversion.Textures; +using FModel.ViewModels.Nodify; namespace FModel.ViewModels; @@ -108,6 +109,13 @@ public class TabItem : ViewModel public string FullPath => this.Directory + "/" + this.Header.SubstringBeforeLast(" ("); + private NodifyEditorViewModel _nodifyEditor; + public NodifyEditorViewModel NodifyEditor + { + get => _nodifyEditor; + set => SetProperty(ref _nodifyEditor, value); + } + private bool _hasSearchOpen; public bool HasSearchOpen { diff --git a/FModel/Views/Resources/Controls/NodeTemplateSelector.cs b/FModel/Views/Resources/Controls/NodeTemplateSelector.cs new file mode 100644 index 00000000..3eadf974 --- /dev/null +++ b/FModel/Views/Resources/Controls/NodeTemplateSelector.cs @@ -0,0 +1,24 @@ +using System.Windows; +using System.Windows.Controls; +using FModel.ViewModels.Nodify; + +namespace FModel.Views.Resources.Controls; + +public class NodeTemplateSelector : DataTemplateSelector +{ + public DataTemplate DefaultTemplate { get; set; } + public DataTemplate FlowNodeTemplate { get; set; } + public DataTemplate IndexedTemplate { get; set; } + public DataTemplate PackagedTemplate { get; set; } + + public override DataTemplate SelectTemplate(object item, DependencyObject container) + { + return item switch + { + PackagedNodeViewModel => PackagedTemplate, + BaseIndexedNodeViewModel => IndexedTemplate, + FlowNodeViewModel => FlowNodeTemplate, + _ => DefaultTemplate + }; + } +} diff --git a/FModel/Views/Resources/Controls/NodifyEditor.xaml b/FModel/Views/Resources/Controls/NodifyEditor.xaml new file mode 100644 index 00000000..39b545ed --- /dev/null +++ b/FModel/Views/Resources/Controls/NodifyEditor.xaml @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FModel/Views/Resources/Controls/NodifyEditor.xaml.cs b/FModel/Views/Resources/Controls/NodifyEditor.xaml.cs new file mode 100644 index 00000000..0eaf85ff --- /dev/null +++ b/FModel/Views/Resources/Controls/NodifyEditor.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace FModel.Views.Resources.Controls; + +public partial class NodifyEditor : UserControl +{ + public NodifyEditor() + { + InitializeComponent(); + } +} + diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index 03e061d9..b0ed74df 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -675,7 +675,7 @@ - +