158 lines
5.8 KiB
C#
158 lines
5.8 KiB
C#
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Reactive.Linq;
|
|
using DynamicData;
|
|
using Intromat.Graphics;
|
|
using Intromat.Model.Compiler;
|
|
using Intromat.Nodes.Code;
|
|
using Intromat.PersistentModel;
|
|
using Intromat.ViewModels;
|
|
using Intromat.ViewModels.Editors;
|
|
using Intromat.ViewModels.Previews;
|
|
using NodeNetwork.Toolkit.ValueNode;
|
|
using NodeNetwork.ViewModels;
|
|
using ReactiveUI;
|
|
using SharpDX.Direct3D11;
|
|
using SharpDX.DXGI;
|
|
using Splat;
|
|
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
|
|
using Device = SharpDX.Direct3D11.Device;
|
|
|
|
namespace Intromat.Nodes.Textures
|
|
{
|
|
[CategoryOrder("Texture", 0)]
|
|
public abstract class DxTextureNodeBase : DxNodeBase
|
|
{
|
|
protected TextureValue? _output;
|
|
protected Texture2DDescription _texDesc;
|
|
protected bool _resourcesCreated;
|
|
|
|
protected DxTextureNodeBase()
|
|
{
|
|
var textureGroup = new EndpointGroup("Texture");
|
|
var parentObservable = this.WhenAnyObservable(vm => vm.ParentChanged).Select(parent => (CodeGenNetworkViewModel?)parent);
|
|
Inputs.Add(Width = new CodeGenInputViewModel<ITypedExpression<int>>(EPortType.None)
|
|
{
|
|
Name = "Width",
|
|
Group = textureGroup,
|
|
Editor = WidthEditor = new()
|
|
{
|
|
ParentValueProvider = parentObservable.Select(parent => parent?.DefaultWidth ?? -1),
|
|
MinValue = -16,
|
|
MaxValue = 16,
|
|
CustomValue = 0,
|
|
RelativeSource = ERelativeSource.Parent
|
|
}
|
|
});
|
|
Inputs.Add(Height = new CodeGenInputViewModel<ITypedExpression<int>>(EPortType.None)
|
|
{
|
|
Name = "Height",
|
|
Group = textureGroup,
|
|
Editor = HeightEditor = new()
|
|
{
|
|
ParentValueProvider = parentObservable.Select(parent => parent?.DefaultHeight ?? -1),
|
|
MinValue = -16,
|
|
MaxValue = 16,
|
|
CustomValue = 0,
|
|
RelativeSource = ERelativeSource.Parent
|
|
}
|
|
});
|
|
Outputs.Add(Output = new CodeGenOutputViewModel<TextureValue?>(EPortType.Texture)
|
|
{
|
|
Name = "Output",
|
|
Group = textureGroup
|
|
});
|
|
|
|
var dxHost = Locator.Current.GetService<DxHost>()!;
|
|
Output.Value = this
|
|
.WhenAnyObservable(vm => vm.ParentChanged, vm => vm.AnyInputChanged, (parent, _) => parent)
|
|
.Where(parent => parent != null)
|
|
.Throttle(TimeSpan.FromMilliseconds(1))
|
|
.ObserveOn(dxHost.RenderDispatcher)
|
|
.Do(_ => { UpdateFrame(dxHost.Device, dxHost.Device.ImmediateContext); })
|
|
.Select(_ => new TextureValue(_output!));
|
|
|
|
var dxTexturePreviewViewModel = new DxTexturePreviewViewModel(this, Output.Value);
|
|
Preview = dxTexturePreviewViewModel;
|
|
|
|
_texDesc = new Texture2DDescription
|
|
{
|
|
ArraySize = 1,
|
|
Format = Format.R16G16B16A16_Float,
|
|
BindFlags = BindFlags.ShaderResource | BindFlags.UnorderedAccess,
|
|
Usage = ResourceUsage.Default,
|
|
SampleDescription = new(1, 0)
|
|
};
|
|
}
|
|
|
|
[MemberNotNull(nameof(_output))]
|
|
protected bool EnsureBuffers(Device device)
|
|
{
|
|
return EnsureTexture(device, ref _output);
|
|
}
|
|
|
|
protected bool EnsureTexture(Device device, [NotNull] ref TextureValue? textureValue)
|
|
{
|
|
var width = ((IntLiteralValue)Width.Value).EvaluateDimension();
|
|
var height = ((IntLiteralValue)Height.Value).EvaluateDimension();
|
|
if (_texDesc.Width != width || _texDesc.Height != height || textureValue == null)
|
|
{
|
|
textureValue?.ShaderResourceView?.Resource?.Dispose();
|
|
textureValue?.ShaderResourceView?.Dispose();
|
|
textureValue?.UnorderedAccessView?.Dispose();
|
|
|
|
_texDesc.Width = width;
|
|
_texDesc.Height = height;
|
|
var texture = new Texture2D(device, _texDesc);
|
|
|
|
textureValue ??= new TextureValue();
|
|
textureValue.Width = width;
|
|
textureValue.Height = height;
|
|
textureValue.ShaderResourceView = new ShaderResourceView(device, texture);
|
|
textureValue.UnorderedAccessView = new UnorderedAccessView(device, texture);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected virtual void UpdateFrame(Device device, DeviceContext deviceContext)
|
|
{
|
|
if (!_resourcesCreated)
|
|
{
|
|
_resourcesCreated = true;
|
|
CreateDeviceResources(device);
|
|
}
|
|
EnsureBuffers(device);
|
|
}
|
|
|
|
protected virtual void CreateDeviceResources(Device device)
|
|
{
|
|
}
|
|
|
|
public override void SaveModel(NodeModelBase model)
|
|
{
|
|
base.SaveModel(model);
|
|
var textureModel = (DxTextureModelBase)model;
|
|
textureModel.Width = WidthEditor.CreateModel();
|
|
textureModel.Height = HeightEditor.CreateModel();
|
|
}
|
|
|
|
public override void LoadModel(NodeModelBase model)
|
|
{
|
|
base.LoadModel(model);
|
|
var textureModel = (DxTextureModelBase)model;
|
|
WidthEditor.LoadModel(textureModel.Width);
|
|
HeightEditor.LoadModel(textureModel.Height);
|
|
}
|
|
|
|
public DimensionEditorViewModel WidthEditor { get; }
|
|
public ValueNodeInputViewModel<ITypedExpression<int>> Width { get; }
|
|
|
|
public DimensionEditorViewModel HeightEditor { get; }
|
|
public ValueNodeInputViewModel<ITypedExpression<int>> Height { get; }
|
|
|
|
public ValueNodeOutputViewModel<TextureValue?> Output { get; }
|
|
}
|
|
}
|