using T3.Core.Operator; using T3.Core.Operator.Slots; using T3.Core.Utils; using T3.Editor.UiModel; using T3.Editor.UiModel.Commands; using T3.Editor.UiModel.Commands.Graph; using T3.Editor.UiModel.ProjectHandling; using Vector2 = System.Numerics.Vector2; using Vector4 = System.Numerics.Vector4; namespace T3.Editor.Gui.Windows.Exploration; internal sealed class ExplorationVariation { public GridCell GridCell; public bool ThumbnailNeedsUpdate; public string Title; public bool IsLiked; private ExplorationVariation(Dictionary valuesForParameters) { ValuesForParameters = valuesForParameters; ThumbnailNeedsUpdate = true; } public ExplorationVariation Clone(Structure structure) { var newVariation = new ExplorationVariation(new Dictionary(ValuesForParameters)); newVariation.UpdateUndoCommand(structure); return newVariation; } public void KeepCurrentAndApplyNewValues(Structure structure) { _changeCommand = CreateChangeCommand(structure); _changeCommand.Do(); } public void ApplyPermanently() { if (_changeCommand == null) return; UndoRedoStack.AddAndExecute(_changeCommand); } public void RestoreValues() { _changeCommand?.Undo(); } // private void InvalidateParameters() // { // foreach (var param in ValuesForParameters.Keys) // { // param.InputSlot.DirtyFlag.ForceInvalidate(); // } // } public void UpdateUndoCommand(Structure structure) { _changeCommand = CreateChangeCommand(structure); } public static ExplorationVariation Mix(IEnumerable variationParameters, IReadOnlyCollection> neighboursAndWeights, float scatter, GridCell cell = new()) { // Collect neighbours var valuesForParameters = new Dictionary(); if (neighboursAndWeights.Count == 0) { foreach (var param in variationParameters) { valuesForParameters.Add(param, param.InputSlot.Input.Value); } return new ExplorationVariation(valuesForParameters) { GridCell = cell, }; } foreach (var param in variationParameters) { if (param.Type == typeof(float)) { var value = 0f; var sumWeight = 0f; foreach (var (neighbourVariation, weight) in neighboursAndWeights) { if (!neighbourVariation.ValuesForParameters.TryGetValue(param, out var matchingParam)) matchingParam = param.InputSlot.Input.Value; if (matchingParam is InputValue floatInput) { value += floatInput.Value * weight; sumWeight += weight; } } value *= 1f / sumWeight; value += _random.NextFloat(-scatter, scatter) * param.ParameterScale * param.ScatterStrength; valuesForParameters.Add(param, new InputValue(value)); } if (param.Type == typeof(Vector2)) { var value = Vector2.Zero; var sumWeight = 0f; foreach (var (neighbourVariation, weight) in neighboursAndWeights) { if (!neighbourVariation.ValuesForParameters.TryGetValue(param, out var matchingParam)) matchingParam = param.InputSlot.Input.Value; if (matchingParam is InputValue typedInput) { value += typedInput.Value * weight; sumWeight += weight; } } value *= 1f / sumWeight; value += new Vector2( _random.NextFloat(-scatter, scatter), _random.NextFloat(-scatter, scatter) ) * param.ParameterScale * param.ScatterStrength; valuesForParameters.Add(param, new InputValue(value)); } if (param.Type == typeof(Vector3)) { var value = Vector3.Zero; var sumWeight = 0f; foreach (var (neighbourVariation, weight) in neighboursAndWeights) { if (!neighbourVariation.ValuesForParameters.TryGetValue(param, out var matchingParam)) matchingParam = param.InputSlot.Input.Value; if (matchingParam is InputValue typedInput) { value += typedInput.Value * weight; sumWeight += weight; } } value *= 1f / sumWeight; value += new Vector3( _random.NextFloat(-scatter, scatter), _random.NextFloat(-scatter, scatter), _random.NextFloat(-scatter, scatter) ) * param.ParameterScale * param.ScatterStrength; valuesForParameters.Add(param, new InputValue(value)); } if (param.Type == typeof(Vector4)) { var value = Vector4.Zero; var sumWeight = 0f; foreach (var (neighbourVariation, weight) in neighboursAndWeights) { if (!neighbourVariation.ValuesForParameters.TryGetValue(param, out var matchingParam)) matchingParam = param.InputSlot.Input.Value; if (matchingParam is InputValue typedInput) { value += typedInput.Value * weight; sumWeight += weight; } } value *= 1f / sumWeight; value += new Vector4( _random.NextFloat(-scatter, scatter), _random.NextFloat(-scatter, scatter), _random.NextFloat(-scatter, scatter), _random.NextFloat(-scatter, scatter) ) * param.ParameterScale * param.ScatterStrength; valuesForParameters.Add(param, new InputValue(value)); } } return new ExplorationVariation(valuesForParameters) { GridCell = cell, }; } private MacroCommand CreateChangeCommand(Structure structure) { var commands = new List(); foreach (var (param, value) in ValuesForParameters) { try { var instance = structure.GetInstanceFromIdPath(param.InstanceIdPath); var newCommand = new ChangeInputValueCommand(instance.Parent.Symbol, param.TargetChild.Id, param.Input, value); commands.Add(newCommand); } catch (Exception) { Log.Warning("Skipping no longer valid variation parameter"); } } return new MacroCommand("Set Preset Values", commands); } public sealed class VariationParameter { public IReadOnlyList InstanceIdPath = Array.Empty(); public SymbolUi.Child TargetChild; public IInputSlot InputSlot { get; set; } public Symbol.Child.Input Input; public Type Type; public float ScatterStrength = 1; public float ParameterScale = 1; public float ParameterMin = float.NegativeInfinity; public float ParameterMax = float.PositiveInfinity; public bool ParameterClampMin = false; public bool ParameterClampMax = false; //public bool IsHidden; } public readonly Dictionary ValuesForParameters; private static readonly Random _random = new(); private ICommand _changeCommand; }