// Toasts/Components/AC_ToastSystem.ts import type { S_ToastMessage } from '#root/Toasts/Structs/S_ToastMessage.ts'; import type { WBP_Toast } from '#root/Toasts/UI/WBP_Toast.ts'; import { WBP_ToastContainer } from '#root/Toasts/UI/WBP_ToastContainer.ts'; import { ActorComponent } from '#root/UE/ActorComponent.ts'; import { CreateWidget } from '#root/UE/CteateWidget.ts'; import type { Float } from '#root/UE/Float.ts'; import type { Integer } from '#root/UE/Integer.ts'; import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; import type { Text } from '#root/UE/Text.ts'; import { UEArray } from '#root/UE/UEArray.ts'; import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts'; /** * Toast Notification System Component * Manages temporary status messages with automatic positioning and lifecycle * Provides visual feedback for debug operations and system events */ export class AC_ToastSystem extends ActorComponent { // ════════════════════════════════════════════════════════════════════════════════════════ // FUNCTIONS // ════════════════════════════════════════════════════════════════════════════════════════ /** * Check if toast system should process updates this frame * @returns True if system is initialized and enabled * @pure * @category Toast Management */ private ShouldProcessToasts(): boolean { /** * Validate system state and settings */ return this.IsInitialized && this.IsEnabled; } /** * Remove expired toasts from the system * @category Toast Lifecycle */ private RemoveExpiredToasts(): void { let i = 0; /** * Check if there are more toasts to process */ const HasMoreToastsToCheck = (activeToastsLength: Integer): boolean => i < activeToastsLength; while (HasMoreToastsToCheck(this.ActiveToasts.length)) { /** * Check if toast has exceeded its display duration */ const IsToastExpired = ( currentTime: Float, createdTime: Float, duration: Float ): boolean => currentTime - createdTime > duration; const el = this.ActiveToasts.Get(i); if ( IsToastExpired( SystemLibrary.GetGameTimeInSeconds(), el.CreatedTime, el.Duration ) ) { const widget = this.ToastWidgets.Get(i); if (SystemLibrary.IsValid(widget)) { if (SystemLibrary.IsValid(this.ToastContainer)) { this.ToastContainer.RemoveToast(widget); } } this.ActiveToasts.RemoveIndex(i); this.ToastWidgets.RemoveIndex(i); } else { i++; } } } /** * Enforce maximum visible toasts limit * Removes oldest toasts when limit is exceeded * @category Toast Lifecycle */ private EnforceToastLimit(): void { /** * Check if current toast count exceeds maximum allowed */ const ExceedsToastLimit = ( activeToastsLength: Integer, maxVisibleToasts: Integer ): boolean => activeToastsLength >= maxVisibleToasts; while (ExceedsToastLimit(this.ActiveToasts.length, this.MaxVisibleToasts)) { const widget = this.ToastWidgets.Get(0); if (SystemLibrary.IsValid(widget)) { if (SystemLibrary.IsValid(this.ToastContainer)) { this.ToastContainer.RemoveToast(widget); } } this.ActiveToasts.RemoveIndex(0); this.ToastWidgets.RemoveIndex(0); } } /** * Create and display a new toast message * @param Message - Text to display in the toast * @param Type - Type of toast (affects color and styling) * @param Duration - How long to display toast (optional, uses default) * @returns Toast ID for tracking * @example * // Create success toast * ShowToast("Test passed!", E_MessageType.Success, 2.0) * // Create error toast with default duration * ShowToast("Test failed!", E_MessageType.Error) * @category Toast Creation */ public ShowToast( Message: Text = '', Type: E_MessageType = E_MessageType.Info, Duration: Float = 5 ): Integer { if (this.ShouldProcessToasts()) { const currentTime = SystemLibrary.GetGameTimeInSeconds(); const newToast: S_ToastMessage = { ID: this.NextToastID++, Message, Type, Duration, CreatedTime: currentTime, }; this.EnforceToastLimit(); if (SystemLibrary.IsValid(this.ToastContainer)) { const toastWidget = this.ToastContainer.AddToast(Message, Type); if (SystemLibrary.IsValid(toastWidget)) { this.ActiveToasts.Add(newToast); this.ToastWidgets.Add(toastWidget); this.LogToConsole(Type, Message); return newToast.ID; } else { return -1; } } } this.LogToConsole(Type, Message); return -1; } /** * Main update loop for toast system * Removes expired toasts automatically * @category System Main Loop */ public UpdateToastSystem(): void { if (this.ShouldProcessToasts()) { this.RemoveExpiredToasts(); } } /** * Get system state and configuration for testing purposes * Provides read-only access to private configuration and active widgets * @returns Object containing toast widgets array and system configuration * @category Testing */ public GetTestData(): { ToastWidgets: UEArray; MaxVisibleToasts: Integer; IsEnabled: boolean; } { return { ToastWidgets: this.ToastWidgets, MaxVisibleToasts: this.MaxVisibleToasts, IsEnabled: this.IsEnabled, }; } /** * Initialize toast system with container widget * @example * // Initialize toast system in main character * this.ToastSystemComponent.InitializeToastSystem(); * @category System Setup */ public InitializeToastSystem(): void { this.ToastContainer = CreateWidget(WBP_ToastContainer); this.ToastContainer.InitializeContainer(); this.IsInitialized = true; this.NextToastID = 1; } /** * Log toast message to console if enabled * @param Type - Message type for formatting * @param Message - Message text to log * @category System Utilities */ public LogToConsole(Type: E_MessageType, Message: Text): void { if (this.AlsoLogToConsole) { SystemLibrary.PrintString(`[${Type}] ${Message}`, false); } } // ════════════════════════════════════════════════════════════════════════════════════════ // VARIABLES // ════════════════════════════════════════════════════════════════════════════════════════ /** * Maximum number of simultaneously visible toast notifications * When limit is exceeded, oldest toasts are automatically removed * @default 5 * @range 1-10 recommended * @category System Config * @instanceEditable true */ private readonly MaxVisibleToasts: Integer = 5; /** * Duplicate all toast messages to console output for debugging * Format: [MessageType] Message text * @default true * @recommendation Set false in production builds for performance * @category System Config * @instanceEditable true */ private readonly AlsoLogToConsole: boolean = true; /** * Master switch for the entire toast system * When disabled: ShowToast() returns -1, widgets are not created * LogToConsole still works if AlsoLogToConsole is true * @default true * @category System Config * @instanceEditable true */ private readonly IsEnabled: boolean = true; /** * System initialization state flag * Set to true after successful InitializeToastSystem call * @category System State */ private IsInitialized: boolean = false; /** * Next unique ID for new toasts * Incremented for each new toast * @category System State */ private NextToastID: Integer = 1; /** * Toast container widget that handles positioning and layout * @category Container Management */ private ToastContainer: WBP_ToastContainer | null = null; /** * Array of currently active toast messages * Contains all visible toasts with metadata * @category Toast Management */ private ActiveToasts: UEArray = new UEArray([]); /** * Array of toast widget instances * Corresponds to ActiveToasts array for UI display * @category Widget Management */ private ToastWidgets: UEArray = new UEArray([]); }