using System.IO; using ImGuiNET; using T3.Core.Operator.Slots; using T3.Editor.Gui.InputUi.SimpleInputUis; using T3.Editor.Gui.Styling; using T3.Editor.UiModel; namespace T3.Editor.Gui.Windows.Utilities; public static class FileAssetsHelper { private static FileResource _activeFileResource; private static bool _wasFilenameChanged; public static void Draw() { if (ImGui.Button("Rescan Assets")) { ScanResources(); } CustomComponents.DrawInputFieldWithPlaceholder("Filter", ref _filter); ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(2, 2)); foreach (var (path, r) in _resources.OrderBy(r => r.Key)) { if (!string.IsNullOrEmpty(_filter) && !path.Contains(_filter)) continue; ImGui.PushID(path); ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted($"{r.InputUsages.Count + r.DefaultValueUsages.Count}"); if (ImGui.IsItemHovered()) { ImGui.BeginTooltip(); ListUsages(r.DefaultValueUsages, "Default Values..."); ListUsages(r.InputUsages, "Inputs..."); ImGui.EndTooltip(); } CustomComponents.TooltipForLastItem(" "); ImGui.SameLine(50); ImGui.PushStyleColor(ImGuiCol.Text, r.State == FileResource.States.Missing ? UiColors.StatusWarning : UiColors.Text.Rgba); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.4f * ImGui.GetStyle().Alpha); ImGui.TextUnformatted(r.Directory + "\\"); ImGui.PopStyleVar(); ImGui.SameLine(); if (_activeFileResource == r) { ImGui.SetKeyboardFocusHere(); if (CustomComponents.DrawInputFieldWithPlaceholder("Filename", ref r.FileName, 400 * T3Ui.UiScaleFactor, false)) { _wasFilenameChanged = true; } if (ImGui.IsItemDeactivated()) { // Apply changes... if( _wasFilenameChanged) { var newPath = Path.Combine(r.Directory, r.FileName); foreach (var usage in r.InputUsages) { usage.InputValue.Value = newPath; usage.SymbolUi.FlagAsModified(); } foreach (var usage in r.DefaultValueUsages) { usage.InputValue.Value = newPath; usage.SymbolUi.FlagAsModified(); } try { Log.Debug($"Renaming {path} -> {r.FileName}"); File.Move(path, newPath); } catch (Exception e) { Log.Warning("Failed: " + e.Message); } T3Ui.Save(false); ScanResources(); _wasFilenameChanged = false; _activeFileResource = null; break; } _activeFileResource = null; } } else { ImGui.TextUnformatted(r.FileName); if (ImGui.IsItemClicked()) { _activeFileResource = r; } } ImGui.PopStyleColor(); ImGui.PopID(); } ImGui.PopStyleVar(); } private static void ListUsages(List rDefaultValueUsages, string label) { if (rDefaultValueUsages.Count <= 0) return; CustomComponents.HelpText(label); foreach (var inputUsage in rDefaultValueUsages) { ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); ImGui.TextUnformatted($"{inputUsage.SymbolUi.Symbol.Name} / "); ImGui.PopStyleColor(); ImGui.SameLine(); ImGui.TextUnformatted($"{inputUsage.StringInputUi.Parent.Symbol.Name}"); ImGui.SameLine(); ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); ImGui.TextUnformatted($".{inputUsage.StringInputUi.InputDefinition.Name}"); ImGui.PopStyleColor(); } } private static string _filter = ""; private static void ScanResources() { _resources.Clear(); foreach (var symbolUi in EditorSymbolPackage.AllSymbolUis) { var symbol = symbolUi.Symbol; // Default values foreach (var inputDef in symbol.InputDefinitions) { if (!symbolUi.InputUis.TryGetValue(inputDef.Id, out var inputUi)) continue; if (inputUi is not StringInputUi stringInputUi) continue; if (stringInputUi.Usage != StringInputUi.UsageType.FilePath) continue; if (inputDef.DefaultValue is not InputValue stringValue) continue; var path = stringValue.Value; AddResourceUsage(path, out var resource); resource.DefaultValueUsages.Add(new InputUsage { InputValue = stringValue, StringInputUi = stringInputUi, SymbolUi = symbolUi, }); } // Collect children foreach (var symbolChild in symbol.Children.Values) { var childUiSymbolUi = symbolChild.Symbol.GetSymbolUi(); foreach (var (inputId, input) in symbolChild.Inputs) { if (input.Value is not InputValue stringValue) continue; if (!childUiSymbolUi.InputUis.TryGetValue(inputId, out var inputUi)) continue; if (inputUi is not StringInputUi stringInputUi) continue; if (stringInputUi.Usage != StringInputUi.UsageType.FilePath) continue; var path = stringValue.Value; AddResourceUsage(path, out var resource); resource.InputUsages.Add(new InputUsage { InputValue = stringValue, StringInputUi = stringInputUi, SymbolUi = symbolUi, }); } } } } private static void AddResourceUsage(string path, out FileResource resource) { if (_resources.TryGetValue(path, out resource)) return; resource = new FileResource { Directory = Path.GetDirectoryName(path), FileName = Path.GetFileName(path), InputUsages = new(), DefaultValueUsages = new(), State = FileResource.States.Unused }; resource.State = !File.Exists(path) ? FileResource.States.Missing : FileResource.States.Used; _resources.Add(path, resource); } private static readonly Dictionary _resources = new(); private sealed class FileResource { public string Directory; public string FileName; public List InputUsages; public List DefaultValueUsages; public States State; public enum States { Unused, Missing, Used, } } private struct InputUsage { public InputValue InputValue; public StringInputUi StringInputUi; public SymbolUi SymbolUi; } }