using ImGuiNET; using T3.Core.Animation; using T3.Core.Audio; using T3.Core.Resource; using T3.Editor.App; using T3.Editor.Gui.Dialog; using T3.Editor.Compilation; using T3.Editor.Gui.Input; using T3.Editor.Gui.Interaction; using T3.Editor.Gui.Interaction.Keyboard; using T3.Editor.Gui.Interaction.Midi; using T3.Editor.Gui.Interaction.Timing; using T3.Editor.Gui.Interaction.Variations; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; using T3.Editor.Gui.UiHelpers.Thumbnails; using T3.Editor.Gui.Windows; using T3.Editor.Gui.Windows.Layouts; using T3.Editor.Gui.Windows.RenderExport; using T3.Editor.Skills.Training; using T3.Editor.Skills.Ui; using T3.Editor.UiModel; using T3.Editor.UiModel.ProjectHandling; using T3.Editor.UiModel.Selection; using T3.SystemUi; namespace T3.Editor.Gui; public static partial class T3Ui { internal static void ProcessFrame() { Profiling.KeepFrameData(); //ImGui.PushStyleColor(ImGuiCol.Text, UiColors.Text.Rgba); DragAndDropHandling.Update(); MagGraph.Ui.DropHandling.DrawDragIndicator(); CustomComponents.BeginFrame(); FormInputs.BeginFrame(); InitializeAfterAppWindowReady(); MouseWheelPanning.ProcessFrame(120); // Prepare the current frame RenderStatsCollector.StartNewFrame(); UpdateModifiedProjects(); if (!Playback.Current.IsRenderingToFile && ProjectView.Focused != null) { PlaybackUtils.UpdatePlaybackAndSyncing(); AudioEngine.CompleteFrame(Playback.Current, Playback.LastFrameDuration); } ScreenshotWriter.Update(); RenderProcess.Update(); SkillTraining.Update(); SkillMapEditor.Draw(); ResourcePackageManager.RaiseFileWatchingEvents(); VariationHandling.Update(); MouseWheelFieldWasHoveredLastFrame = MouseWheelFieldHovered; MouseWheelFieldHovered = false; // A workaround for potential mouse capture DragFieldWasHoveredLastFrame = DragFieldHovered; DragFieldHovered = false; FitViewToSelectionHandling.ProcessNewFrame(); SrvManager.RemoveForDisposedTextures(); KeyActionHandling.InitializeFrame(); CompatibleMidiDeviceHandling.UpdateConnectedDevices(); var nodeSelection = ProjectView.Focused?.NodeSelection; if (nodeSelection != null) { // Set selected id so operator can check if they are selected or not var selectedInstance = nodeSelection.GetSelectedInstanceWithoutComposition(); MouseInput.SelectedChildId = selectedInstance?.SymbolChildId ?? Guid.Empty; NodeSelection.InvalidateSelectedOpsForTransformGizmo(nodeSelection); } // Draw everything! ImGui.DockSpaceOverViewport(); ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 1); WindowManager.Draw(); ImGui.PopStyleVar(); // Complete frame SingleValueEdit.StartNextFrame(); SkillTraining.PostUpdate(); FrameStats.CompleteFrame(); TriggerGlobalActionsFromKeyBindings(); PlaybackTimeScrubHandling.ProcessFrame(); //if (UserSettings.Config.ShowMainMenu || UserSettings.Config.EnableMainMenuHoverPeek && ImGui.GetMousePos().Y < 3) if (UserSettings.Config.ShowMainMenu || ImGui.GetMousePos().Y < 3) { AppMenuBar.DrawAppMenuBar(); } ThumbnailManager.Update(); _searchDialog.Draw(); NewProjectDialog.Draw(); RestoreBackupDialog.Draw(); CreateFromTemplateDialog.Draw(); _userNameDialog.Draw(); AboutDialog.Draw(); ExitDialog.Draw(); OperatorHelp.EditDescriptionDialog.Draw(); SkillMapPopup.Draw(); // Classify the launch first so the welcome window claims the foreground before the // user-name prompt. They must not overlap — the user-name dialog waits until the // welcome window is closed (see the IsVisible guard below). CheckForVersionWelcome(); if (IsWindowLayoutComplete() && _versionWelcomeChecked && !WindowManager.WelcomeWindow.IsVisible) { if (!UserSettings.IsUserNameDefined()) { UserSettings.Config.UserName = Environment.UserName; _userNameDialog.ShowNextFrame(); } } KeyboardAndMouseOverlay.Draw(); Playback.OpNotReady = false; AutoBackup.AutoBackup.CheckForSave(); Profiling.EndFrameData(); } private static void InitializeAfterAppWindowReady() { if (_initialed || ImGui.GetWindowSize() == Vector2.Zero) return; CompatibleMidiDeviceHandling.InitializeConnectedDevices(); _initialed = true; } private static bool _initialed; /// /// Once per launch, after the layout is up and no other popup is open, opens the welcome window if /// the user keeps it on startup, or if this is a version they haven't run in this folder before. /// Otherwise just records the run so the next new version is detected. Waits for any startup popup /// (e.g. user name) to close first. /// private static void CheckForVersionWelcome() { if (_versionWelcomeChecked || !IsWindowLayoutComplete() || IsAnyPopupOpen) return; _versionWelcomeChecked = true; var isNewVersion = VersionMarker.Classify() == VersionMarker.LaunchKind.NewToUser; // Snapshot existing projects before the first save can upgrade them to the new file format. // Runs before the marker is written (on welcome-window close) so a crash mid-pass retries. if (isNewVersion) AutoBackup.PreUpgradeSnapshot.CreateForExistingProjects(); if (UserSettings.Config.ShowWelcomeOnStartup || isNewVersion) WindowManager.WelcomeWindow.Open(); else VersionMarker.MarkCurrentVersionSeen(); } private static bool _versionWelcomeChecked; private static void UpdateModifiedProjects() { foreach (var project in EditableSymbolProject.AllProjects) { project.Update(out var needsUpdating); if (needsUpdating) { _modifiedProjects.Add(project); } } if (_modifiedProjects.Count > 0) { var projects = _modifiedProjects.Cast().ToArray(); ProjectSetup.UpdateSymbolPackages(projects); } _modifiedProjects.Clear(); } }