port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
using Intromat.Nodes.Code;
using Intromat.Views.Editors;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class BooleanExpressionEditorViewModel : ExpressionEditorBaseViewModel<bool, BooleanLiteralValue, BooleanLiteralModel>
{
static BooleanExpressionEditorViewModel()
{
Locator.CurrentMutable.Register(() => new BooleanExpressionEditorView(), typeof(IViewFor<BooleanExpressionEditorViewModel>));
}
}
}

View File

@@ -0,0 +1,15 @@
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class BooleanValueEditorViewModel : ValueEditorViewModel<bool>
{
static BooleanValueEditorViewModel()
{
Locator.CurrentMutable.Register(() => new BooleanValueEditorView(), typeof(IViewFor<BooleanValueEditorViewModel>));
}
}
}

View File

@@ -0,0 +1,14 @@
using Intromat.Views.Editors;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class DimensionEditorViewModel : IntegerExpressionEditorViewModel
{
static DimensionEditorViewModel()
{
Locator.CurrentMutable.Register(() => new DimensionEditorView(), typeof(IViewFor<DimensionEditorViewModel>));
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using Intromat.Interfaces;
using Intromat.Nodes.Code;
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class EnumEditorViewModel : ValueEditorViewModel<int>, IExpressionEditor
{
static EnumEditorViewModel()
{
Locator.CurrentMutable.Register(() => new EnumEditorView(), typeof(IViewFor<EnumEditorViewModel>));
}
public EnumEditorViewModel(Type enumType)
{
EnumType = enumType;
}
public Type EnumType { get; }
public ERelativeSource RelativeSource
{
get => ERelativeSource.Custom;
set => throw new NotSupportedException();
}
public bool HasParentSource => false;
public bool HasInputSource => false;
public CodeGenPortViewModel CodeGenPort => (CodeGenPortViewModel)Parent.Port;
}
}

View File

@@ -0,0 +1,89 @@
using System;
using Intromat.Interfaces;
using Intromat.Model.Compiler;
using Intromat.Nodes.Code;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
namespace Intromat.ViewModels.Editors
{
public abstract class ExpressionEditorBaseViewModel<T, TValue, TModel> : ValueEditorViewModel<ITypedExpression<T>?>, IExpressionEditor where TValue : LiteralValueBase<T>, new() where TModel : LiteralModelBase<T>, new()
{
private T _customValue = default!;
private ERelativeSource _relativeSource;
private IObservable<T>? _parentValueProvider;
private IObservable<T>? _inputValueProvider;
private readonly ObservableAsPropertyHelper<T> _parentValue;
private readonly ObservableAsPropertyHelper<T> _inputValue;
protected ExpressionEditorBaseViewModel()
{
this.WhenAnyObservable(vm => vm.ParentValueProvider)
.ToProperty(this, vm => vm.ParentValue, out _parentValue);
this.WhenAnyObservable(vm => vm.InputValueProvider)
.ToProperty(this, vm => vm.InputValue, out _inputValue);
this.WhenAnyValue(vm => vm.ParentValue, vm => vm.InputValue, vm => vm.CustomValue, vm => vm.RelativeSource)
.Subscribe(v => Value = CreateLiteralValue(v.Item1, v.Item2, v.Item3, v.Item4));
}
protected LiteralValueBase<T> CreateLiteralValue(T parentValue, T inputValue, T customValue, ERelativeSource relativeSource)
{
return new TValue
{
InputValue = inputValue,
ParentValue = parentValue,
Value = customValue,
RelativeSource = relativeSource
};
}
public TModel CreateModel()
{
return new()
{
RelativeSource = RelativeSource,
Value = CustomValue
};
}
public void LoadModel(TModel model)
{
RelativeSource = model.RelativeSource;
CustomValue = model.Value;
}
public T CustomValue
{
get => _customValue;
set => this.RaiseAndSetIfChanged(ref _customValue, value);
}
public ERelativeSource RelativeSource
{
get => _relativeSource;
set => this.RaiseAndSetIfChanged(ref _relativeSource, value);
}
public IObservable<T>? ParentValueProvider
{
get => _parentValueProvider;
set => this.RaiseAndSetIfChanged(ref _parentValueProvider, value);
}
public T ParentValue => _parentValue.Value;
public bool HasParentSource => ParentValueProvider != null;
public IObservable<T>? InputValueProvider
{
get => _inputValueProvider;
set => this.RaiseAndSetIfChanged(ref _inputValueProvider, value);
}
public T InputValue => _inputValue.Value;
public bool HasInputSource => InputValueProvider != null;
public CodeGenPortViewModel CodeGenPort => (CodeGenPortViewModel)Parent.Port;
}
}

View File

@@ -0,0 +1,50 @@
using System;
using Intromat.Nodes.Code;
using Intromat.Views.Editors;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class FloatExpressionEditorViewModel : ExpressionEditorBaseViewModel<float, FloatLiteralValue, FloatLiteralModel>
{
private float _maxValue;
private float _minValue;
static FloatExpressionEditorViewModel()
{
Locator.CurrentMutable.Register(() => new FloatExpressionEditorView(), typeof(IViewFor<FloatExpressionEditorViewModel>));
}
public FloatExpressionEditorViewModel()
{
this.WhenAnyValue(vm => vm.Value)
.Subscribe(t =>
{
var newValue = t!.Evaluate();
if (newValue > MaxValue)
{
var delta = newValue - MinValue;
MaxValue = newValue + delta;
}
else if (newValue < MinValue)
{
var delta = MaxValue - newValue;
MinValue = newValue - delta;
}
});
}
public float MinValue
{
get => _minValue;
set => this.RaiseAndSetIfChanged(ref _minValue, value);
}
public float MaxValue
{
get => _maxValue;
set => this.RaiseAndSetIfChanged(ref _maxValue, value);
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class FloatValueEditorViewModel : ValueEditorViewModel<float>
{
private float _minValue;
private float _maxValue;
static FloatValueEditorViewModel()
{
Locator.CurrentMutable.Register(() => new FloatValueEditorView(), typeof(IViewFor<FloatValueEditorViewModel>));
}
public FloatValueEditorViewModel(float min = 0, float max = 1)
{
MinValue = min;
MaxValue = max;
Value = 0;
this.WhenAnyValue(vm => vm.Value)
.Subscribe(newValue =>
{
if (newValue > MaxValue)
{
var delta = newValue - MinValue;
MaxValue = newValue + delta;
}
else if (newValue < MinValue)
{
var delta = MaxValue - newValue;
MinValue = newValue - delta;
}
});
}
public float MinValue
{
get => _minValue;
set => this.RaiseAndSetIfChanged(ref _minValue, value);
}
public float MaxValue
{
get => _maxValue;
set => this.RaiseAndSetIfChanged(ref _maxValue, value);
}
}
}

View File

@@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using NodeNetwork.ViewModels;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Nodes
{
/// <summary>
/// A non-generic interface that provides access to the data in GroupEndpointEditorViewModel.
/// Mapping a view onto a generic viewmodel is problematic because the generic type often isn't known in the view,
/// and generic views are often not allowed.
/// </summary>
public interface IGroupEndpointEditorViewModel
{
public Endpoint Endpoint { get; }
public ReactiveCommand<Unit, Unit> MoveUp { get; }
public ReactiveCommand<Unit, Unit> MoveDown { get; }
public ReactiveCommand<Unit, Unit> Delete { get; }
}
public class GroupEndpointEditorViewModel<T> : ValueEditorViewModel<T>, IGroupEndpointEditorViewModel
{
static GroupEndpointEditorViewModel()
{
Locator.CurrentMutable.Register(() => new GroupEndpointEditorView(), typeof(IViewFor<GroupEndpointEditorViewModel<T>>));
}
public GroupEndpointEditorViewModel(CodeNodeGroupIOBinding nodeGroupBinding)
{
MoveUp = ReactiveCommand.Create(() =>
{
var isInput = Parent is NodeInputViewModel;
IEnumerable<Endpoint> endpoints = isInput ? Parent.Parent.Inputs.Items : Parent.Parent.Outputs.Items;
// Swap SortIndex of this endpoint with the SortIndex of the previous endpoint in the list, if any.
var prevElement = endpoints
.Where(e => e.SortIndex < Parent.SortIndex)
.MaxBy(e => e.SortIndex);
if (prevElement != null)
{
var idx = prevElement.SortIndex;
prevElement.SortIndex = Parent.SortIndex;
Parent.SortIndex = idx;
}
});
MoveDown = ReactiveCommand.Create(() =>
{
var isInput = Parent is NodeInputViewModel;
IEnumerable<Endpoint> endpoints = isInput ? Parent.Parent.Inputs.Items : Parent.Parent.Outputs.Items;
var nextElement = endpoints
.Where(e => e.SortIndex > Parent.SortIndex)
.MinBy(e => e.SortIndex);
if (nextElement != null)
{
var idx = nextElement.SortIndex;
nextElement.SortIndex = Parent.SortIndex;
Parent.SortIndex = idx;
}
});
Delete = ReactiveCommand.Create(() => { nodeGroupBinding.DeleteEndpoint(Parent); });
}
public Endpoint Endpoint => Parent;
public ReactiveCommand<Unit, Unit> MoveUp { get; }
public ReactiveCommand<Unit, Unit> MoveDown { get; }
public ReactiveCommand<Unit, Unit> Delete { get; }
}
}

View File

@@ -0,0 +1,49 @@
using System;
using Intromat.Nodes.Code;
using Intromat.Views.Editors;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class IntegerExpressionEditorViewModel : ExpressionEditorBaseViewModel<int, IntLiteralValue, IntLiteralModel>
{
private int _maxValue;
private int _minValue;
static IntegerExpressionEditorViewModel()
{
Locator.CurrentMutable.Register(() => new IntegerExpressionEditorView(), typeof(IViewFor<IntegerExpressionEditorViewModel>));
}
public IntegerExpressionEditorViewModel()
{
this.WhenAnyValue(vm => vm.CustomValue)
.Subscribe(newValue =>
{
if (newValue > MaxValue)
{
var delta = newValue - MinValue;
MaxValue = newValue + delta;
}
else if (newValue < MinValue)
{
var delta = MaxValue - newValue;
MinValue = newValue - delta;
}
});
}
public int MinValue
{
get => _minValue;
set => this.RaiseAndSetIfChanged(ref _minValue, value);
}
public int MaxValue
{
get => _maxValue;
set => this.RaiseAndSetIfChanged(ref _maxValue, value);
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class IntegerValueEditorViewModel : ValueEditorViewModel<int>
{
private int _minValue;
private int _maxValue;
static IntegerValueEditorViewModel()
{
Locator.CurrentMutable.Register(() => new IntegerValueEditorView(), typeof(IViewFor<IntegerValueEditorViewModel>));
}
public IntegerValueEditorViewModel(int min = 0, int max = 100)
{
MinValue = min;
MaxValue = max;
Value = 0;
this.WhenAnyValue(vm => vm.Value)
.Subscribe(newValue =>
{
if (newValue > MaxValue)
{
var delta = newValue - MinValue;
MaxValue = newValue + delta;
}
else if (newValue < MinValue)
{
var delta = MaxValue - newValue;
MinValue = newValue - delta;
}
});
}
public int MinValue
{
get => _minValue;
set => this.RaiseAndSetIfChanged(ref _minValue, value);
}
public int MaxValue
{
get => _maxValue;
set => this.RaiseAndSetIfChanged(ref _maxValue, value);
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Reactive;
using System.Reactive.Linq;
using Intromat.Model.Compiler;
using Intromat.Nodes.Textures;
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using SharpDX.Direct3D11;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class SamplerEditorViewModel : ExpressionEditorBaseViewModel<SamplerDesc, SamplerLiteralValue, SamplerLiteralModel>
{
private Filter _filter = SamplerStateDescription.Default().Filter;
private TextureAddressMode _address = SamplerStateDescription.Default().AddressU;
static SamplerEditorViewModel()
{
Locator.CurrentMutable.Register(() => new SamplerEditorView(), typeof(IViewFor<SamplerEditorViewModel>));
}
public SamplerEditorViewModel()
{
this.WhenAnyValue(vm => vm.CustomValue)
.Where(s => s != null)
.Subscribe(s =>
{
Filter = s.Filter;
Address = s.Address;
});
this.WhenAnyValue(vm => vm.Filter, vm => vm.Address)
.Subscribe((p) =>
{
CustomValue = new SamplerDesc()
{
Filter = p.Item1,
Address = p.Item2
};
});
}
public Filter Filter
{
get => _filter;
set => this.RaiseAndSetIfChanged(ref _filter, value);
}
public TextureAddressMode Address
{
get => _address;
set => this.RaiseAndSetIfChanged(ref _address, value);
}
}
}

View File

@@ -0,0 +1,15 @@
using Intromat.Nodes.Code;
using Intromat.Views.Editors;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class StringExpressionEditorViewModel : ExpressionEditorBaseViewModel<string?, StringLiteralValue, StringLiteralModel>
{
static StringExpressionEditorViewModel()
{
Locator.CurrentMutable.Register(() => new StringExpressionEditorView(), typeof(IViewFor<StringExpressionEditorViewModel>));
}
}
}

View File

@@ -0,0 +1,20 @@
using Intromat.Views.Editors;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.ViewModels.Editors
{
public class StringValueEditorViewModel : ValueEditorViewModel<string?>
{
static StringValueEditorViewModel()
{
Locator.CurrentMutable.Register(() => new StringValueEditorView(), typeof(IViewFor<StringValueEditorViewModel>));
}
public StringValueEditorViewModel()
{
Value = "";
}
}
}