Files
2026-07-13 13:13:17 +08:00

155 lines
5.4 KiB
C#

using T3.Core.Animation;
using T3.Core.Operator;
using T3.Core.Operator.Slots;
namespace T3.Editor.UiModel.Commands.Graph;
public sealed class ChangeInputValueCommand : ICommand
{
public string Name => "Change Input Value";
public bool IsUndoable => true;
public ChangeInputValueCommand(Symbol composition, Guid symbolChildId, Symbol.Child.Input input, InputValue newValue)
{
_inputParentSymbolId = composition.Id;
_childId = symbolChildId;
_inputId = input.InputDefinition.Id;
_wasAnimated = composition.Animator.IsAnimated(_childId, _inputId);
_wasDefault = input.IsDefault;
_animationTime = Playback.Current.TimeInBars;
OriginalValue = input.Value.Clone();
_newValue = newValue == null ? input.Value.Clone() : newValue.Clone();
if (_wasAnimated)
{
_originalKeyframes = composition.Animator.GetTimeKeys(_childId, _inputId, _animationTime).ToList();
}
}
public void Undo()
{
if(!SymbolUiRegistry.TryGetSymbolUi(_inputParentSymbolId, out var inputParentSymbolUi))
throw new Exception("Symbol not found: " + _inputParentSymbolId);
var inputParentSymbol = inputParentSymbolUi.Symbol;
if (_wasAnimated)
{
var hasNewKeyframes = false;
foreach (var v in _originalKeyframes)
{
if (v == null)
{
hasNewKeyframes = true;
break;
}
}
var animator = inputParentSymbol.Animator;
if (hasNewKeyframes)
{
// todo: these are identical?
}
animator.SetTimeKeys(_childId, _inputId,_animationTime, _originalKeyframes); // TODO: Remove keyframes
var symbolChild = inputParentSymbol.Children[_childId];
InvalidateInstances(inputParentSymbol, symbolChild);
}
else
{
if (_wasDefault)
{
if (!inputParentSymbol.Children.TryGetValue(_childId, out var symbolChild))
return;
var input = symbolChild.Inputs[_inputId];
input.ResetToDefault();
InvalidateInstances(inputParentSymbol, symbolChild);
}
else
{
AssignValue(OriginalValue);
}
}
inputParentSymbolUi.FlagAsModified();
}
public void Do()
{
AssignValue(_newValue);
}
public void AssignNewValue(InputValue valueToSet)
{
_newValue.Assign(valueToSet);
AssignValue(valueToSet);
}
private void AssignValue(InputValue valueToSet)
{
if(!SymbolUiRegistry.TryGetSymbolUi(_inputParentSymbolId, out var inputParentSymbolUi))
throw new Exception("Symbol not found: " + _inputParentSymbolId);
var inputParentSymbol = inputParentSymbolUi.Symbol;
if (!inputParentSymbol.Children.TryGetValue(_childId, out var symbolChild))
{
// This can happen if blended instances are deleted
Log.Debug($"Can't assign value to missing symbolChild {_childId}");
return;
}
var input = symbolChild.Inputs[_inputId];
if (!SymbolUiRegistry.TryGetSymbolUi(symbolChild.Symbol.Id, out var symbolUi))
{
Log.Warning($"Can't find symbol child's SymbolUI {symbolChild.Symbol.Id} - was it removed? [{symbolChild.Symbol.Name}]");
return;
}
if (_wasAnimated)
{
var inputUi = symbolUi.InputUis[_inputId];
var animator = inputParentSymbol.Animator;
var symbolChildId = symbolChild.Id;
foreach (var parentInstance in inputParentSymbol.InstancesOfSelf)
{
var instance = parentInstance.Children[symbolChildId];
var inputSlot = instance.Inputs.Single(slot => slot.Id == _inputId);
inputUi.ApplyValueToAnimation(inputSlot, valueToSet, animator, _animationTime);
inputSlot.DirtyFlag.ForceInvalidate();
}
}
else
{
input.IsDefault = false;
input.Value.Assign(valueToSet);
InvalidateInstances(inputParentSymbol, symbolChild);
}
inputParentSymbolUi.FlagAsModified();
}
private void InvalidateInstances(Symbol inputParentSymbol, Symbol.Child symbolChild)
{
var symbolChildId = symbolChild.Id;
foreach (var parentInstance in inputParentSymbol.InstancesOfSelf)
{
var instance = parentInstance.Children[symbolChildId];
var inputSlot = instance.Inputs.Single(slot => slot.Id == _inputId);
inputSlot.DirtyFlag.ForceInvalidate();
}
}
private InputValue OriginalValue { get; set; }
private readonly InputValue _newValue;
private readonly Guid _inputParentSymbolId;
private readonly Guid _childId;
private readonly Guid _inputId;
private readonly bool _wasDefault;
private readonly bool _wasAnimated;
private readonly double _animationTime;
private readonly List<VDefinition> _originalKeyframes;
}