193 lines
5.7 KiB
TypeScript
193 lines
5.7 KiB
TypeScript
// Content/Toasts/Components/AC_ToastSystem.ts
|
|
|
|
// TODO: Написать тесты
|
|
|
|
import {AddToArray, CreateWidget, GetGameTimeInSeconds, IsValid, Print, RemoveIndexFromArray} from "../../functions.js";
|
|
import {WBP_ToastContainer} from "../UI/WBP_ToastContainer.js";
|
|
import type {Float, Integer, Text} from "../../types.js";
|
|
import {E_MessageType} from "../../UI/Enums/E_MessageType.js";
|
|
import type {S_ToastMessage} from "../Structs/S_ToastMessage.js";
|
|
import type {S_ToastSettings} from "../Structs/S_ToastSettings.js";
|
|
import type {WBP_Toast} from "../UI/WBP_Toast.js";
|
|
|
|
export class AC_ToastSystem {
|
|
// Category: "System Configuration"
|
|
// Instance Editable: true
|
|
/**
|
|
* Toast system configuration settings
|
|
* Simplified - no positioning settings needed
|
|
* Instance editable for designer customization
|
|
*/
|
|
public ToastSettings: S_ToastSettings = {
|
|
MaxVisibleToasts: 5,
|
|
DefaultDuration: 3.0,
|
|
AlsoLogToConsole: true,
|
|
IsEnabled: true
|
|
};
|
|
|
|
// Category: "System State"
|
|
/**
|
|
* System initialization state flag
|
|
* Set to true after successful InitializeToastSystem call
|
|
*/
|
|
private IsInitialized: boolean = false;
|
|
|
|
// Category: "System State"
|
|
/**
|
|
* Next unique ID for new toasts
|
|
* Incremented for each new toast
|
|
*/
|
|
private NextToastID: Integer = 1;
|
|
|
|
// Category: "Container Management"
|
|
/**
|
|
* Toast container widget that handles all positioning
|
|
* Replaces manual position management
|
|
*/
|
|
private ToastContainer: WBP_ToastContainer | null = null;
|
|
|
|
// Category: "Toast Management"
|
|
/**
|
|
* Array of currently active toast messages
|
|
* Contains all visible toasts
|
|
*/
|
|
private ActiveToasts: S_ToastMessage[] = [];
|
|
|
|
// Category: "Widget Management"
|
|
/**
|
|
* Array of toast widget instances
|
|
* Corresponds to ActiveToasts array
|
|
*/
|
|
private ToastWidgets: WBP_Toast[] = [];
|
|
|
|
// Category: "Toast Management"
|
|
// Pure: true
|
|
/**
|
|
* Check if toast system should process updates this frame
|
|
* @returns True if system is initialized and enabled
|
|
* @pure Function has no side effects
|
|
*/
|
|
private ShouldProcessToasts(): boolean {
|
|
return this.IsInitialized && this.ToastSettings.IsEnabled && IsValid(this.ToastContainer);
|
|
}
|
|
|
|
// Category: "Toast Lifecycle"
|
|
/**
|
|
* Remove expired toasts from the system
|
|
* @private Internal cleanup method
|
|
*/
|
|
private RemoveExpiredToasts(): void {
|
|
let i = 0;
|
|
|
|
while (i < this.ActiveToasts.length) {
|
|
if ((GetGameTimeInSeconds() - this.ActiveToasts[i].CreatedTime) > this.ActiveToasts[i].Duration) {
|
|
if (IsValid(this.ToastWidgets[i]) && IsValid(this.ToastContainer)) {
|
|
this.ToastContainer.RemoveToast(this.ToastWidgets[i]);
|
|
}
|
|
|
|
RemoveIndexFromArray(this.ActiveToasts, i);
|
|
RemoveIndexFromArray(this.ToastWidgets, i);
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Category: "Toast Lifecycle"
|
|
/**
|
|
* Enforce maximum visible toasts limit
|
|
* Uses container's capacity management
|
|
* @private Internal management method
|
|
*/
|
|
private EnforceToastLimit(): void {
|
|
while(this.ActiveToasts.length >= this.ToastSettings.MaxVisibleToasts) {
|
|
if (IsValid(this.ToastWidgets[0])) {
|
|
this.ToastContainer.RemoveToast(this.ToastWidgets[0]);
|
|
}
|
|
|
|
RemoveIndexFromArray(this.ActiveToasts, 0);
|
|
RemoveIndexFromArray(this.ToastWidgets, 0);
|
|
}
|
|
}
|
|
|
|
// Category: "Toast Creation"
|
|
/**
|
|
* Create and display a new toast message
|
|
* Uses container for automatic positioning
|
|
* @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
|
|
* @public Main interface for creating toasts
|
|
* @example
|
|
* // Create success toast
|
|
* ShowToast("Test passed!", E_ToastType.Success, 2.0)
|
|
* // Create error toast with default duration
|
|
* ShowToast("Test failed!", E_ToastType.Error)
|
|
*/
|
|
public ShowToast(Message: Text, Type: E_MessageType, Duration?: Float): Integer {
|
|
if (this.ShouldProcessToasts()) {
|
|
const toastDuration = Duration === 0 ? this.ToastSettings.DefaultDuration : Duration;
|
|
const currentTime = GetGameTimeInSeconds();
|
|
const newToast: S_ToastMessage = {
|
|
ID: this.NextToastID++,
|
|
Message: Message,
|
|
Type: Type,
|
|
Duration: toastDuration,
|
|
CreatedTime: currentTime,
|
|
}
|
|
|
|
this.EnforceToastLimit();
|
|
|
|
const toastWidget = this.ToastContainer.AddToast(Message, Type);
|
|
|
|
if (IsValid(toastWidget)) {
|
|
AddToArray(this.ActiveToasts, newToast);
|
|
AddToArray(this.ToastWidgets, toastWidget);
|
|
|
|
if (this.ToastSettings.AlsoLogToConsole) {
|
|
Print(`[${Type}] ${Message}`, false, true);
|
|
}
|
|
|
|
return newToast.ID;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (this.ToastSettings.AlsoLogToConsole) {
|
|
Print(`[${Type}] ${Message}`, false, true);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Category: "System Main Loop"
|
|
/**
|
|
* Simplified update loop for toast system
|
|
* Container handles positioning automatically
|
|
* @public Called by BP_MainCharacter or game framework
|
|
*/
|
|
public UpdateToastSystem(): void {
|
|
if (this.ShouldProcessToasts()) {
|
|
this.RemoveExpiredToasts();
|
|
}
|
|
}
|
|
|
|
// Category: "System Setup"
|
|
/**
|
|
* Initialize toast system with container
|
|
* @public Called by BP_MainCharacter during initialization
|
|
* @example
|
|
* // Initialize toast system in main character
|
|
* this.ToastSystemComponent.InitializeToastSystem();
|
|
*/
|
|
public InitializeToastSystem(): void {
|
|
this.ToastContainer = CreateWidget(new WBP_ToastContainer);
|
|
this.ToastContainer.InitializeContainer();
|
|
this.IsInitialized = true;
|
|
this.NextToastID = 1;
|
|
this.ShowToast(("Toast System Initialized" as Text), E_MessageType.Info);
|
|
}
|
|
}
|