144 lines
4.5 KiB
C#
144 lines
4.5 KiB
C#
using T3.Core.Rendering;
|
|
using T3.Core.Utils;
|
|
|
|
namespace Lib.render.camera;
|
|
|
|
[Guid("e3ff58e2-847a-4c97-947c-cfbcf8f9c79d")]
|
|
internal sealed class BlendCameras : Instance<BlendCameras>, IStatusProvider, ICamera, ICameraPropertiesProvider
|
|
{
|
|
[Output(Guid = "d0a6f926-c4ed-4cc9-917d-942f8c34fd65")]
|
|
public readonly Slot<Command> Output = new();
|
|
|
|
[Output(Guid = "2DD98046-F80C-4CFB-8A90-AE46515EE07F")]
|
|
public readonly Slot<object> CameraReference = new();
|
|
|
|
public BlendCameras()
|
|
{
|
|
Output.UpdateAction += Update;
|
|
CameraReference.UpdateAction += Update;
|
|
|
|
CameraReference.Value = this;
|
|
|
|
}
|
|
|
|
private void Update(EvaluationContext context)
|
|
{
|
|
try
|
|
{
|
|
var cameraInputs = CameraReferences.GetCollectedTypedInputs();
|
|
var cameraCount = cameraInputs.Count;
|
|
|
|
var floatIndex = Index.GetValue(context).Clamp(0, cameraCount - 1.0001f);
|
|
var index = (int)floatIndex;
|
|
|
|
ICamera camA;
|
|
ICamera camB;
|
|
|
|
CameraReferences.DirtyFlag.Clear();
|
|
if (cameraCount == 0)
|
|
{
|
|
_lastErrorMessage = "No cameras connected?";
|
|
return;
|
|
}
|
|
|
|
if (cameraCount == 1)
|
|
{
|
|
if (cameraInputs[0].GetValue(context) is ICamera cam)
|
|
{
|
|
camA = cam;
|
|
camB = cam;
|
|
}
|
|
else
|
|
{
|
|
_lastErrorMessage = "That's not a camera";
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cameraInputs[index].GetValue(context) is ICamera camA_
|
|
&& cameraInputs[index + 1].GetValue(context) is ICamera camB_)
|
|
{
|
|
_lastErrorMessage = null;
|
|
camA = camA_;
|
|
camB = camB_;
|
|
}
|
|
else
|
|
{
|
|
_lastErrorMessage = "Can't access cameras.";
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
var blend = floatIndex - index;
|
|
_blendedCamDef = CameraDefinition.Blend(camA.CameraDefinition, camB.CameraDefinition, blend);
|
|
|
|
_blendedCamDef.BuildProjectionMatrices(out var camToClipSpace, out var worldToCamera);
|
|
//CameraDefinition.BuildBlendedMatrices(camA.CameraDefinition, camB.CameraDefinition, blend, out var camToClipSpace, out var worldToCamera);
|
|
|
|
WorldToCamera = worldToCamera;
|
|
CameraToClipSpace = camToClipSpace;
|
|
|
|
if (context.BypassCameras)
|
|
{
|
|
Command.GetValue(context);
|
|
return;
|
|
}
|
|
|
|
// Set properties and evaluate sub-tree
|
|
var prevWorldToCamera = context.WorldToCamera;
|
|
var prevCameraToClipSpace = context.CameraToClipSpace;
|
|
|
|
context.WorldToCamera = worldToCamera;
|
|
context.CameraToClipSpace = camToClipSpace;
|
|
|
|
Command.GetValue(context);
|
|
|
|
context.CameraToClipSpace = prevCameraToClipSpace;
|
|
context.WorldToCamera = prevWorldToCamera;
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_lastErrorMessage = "Didn't work " + e.Message;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public IStatusProvider.StatusLevel GetStatusLevel()
|
|
{
|
|
return string.IsNullOrEmpty(_lastErrorMessage) ? IStatusProvider.StatusLevel.Success : IStatusProvider.StatusLevel.Warning;
|
|
}
|
|
|
|
public string GetStatusMessage()
|
|
{
|
|
return _lastErrorMessage;
|
|
}
|
|
|
|
#region Implement ICamera
|
|
|
|
public Vector3 CameraPosition { get => _blendedCamDef.Position; set {} }
|
|
public Vector3 CameraTarget { get=> _blendedCamDef.Target; set { } }
|
|
public float CameraRoll { get => _blendedCamDef.Roll; set { } }
|
|
public CameraDefinition CameraDefinition => _blendedCamDef;
|
|
public Matrix4x4 WorldToCamera { get; set; }
|
|
public Matrix4x4 CameraToClipSpace { get; set; }
|
|
public Matrix4x4 LastObjectToWorld { get; set; } = Matrix4x4.Identity;
|
|
#endregion
|
|
|
|
private string _lastErrorMessage;
|
|
private CameraDefinition _blendedCamDef;
|
|
|
|
|
|
[Input(Guid = "C7EE5D97-86C1-442F-91D0-B60E6CFE24C7")]
|
|
public readonly InputSlot<Command> Command = new();
|
|
|
|
[Input(Guid = "FF2ED90B-38BD-4BA8-AF07-23BE87EABCC3")]
|
|
public readonly MultiInputSlot<Object> CameraReferences = new();
|
|
|
|
[Input(Guid = "3B71FDBF-CB2D-45F1-84DD-7AC66763E6AE")]
|
|
public readonly InputSlot<float> Index = new();
|
|
}
|