// UE/SystemLibrary.ts import { BlueprintFunctionLibrary } from '#root/UE/BlueprintFunctionLibrary.ts'; import type { Color } from '#root/UE/Color.ts'; import type { Float } from '#root/UE/Float.ts'; import type { Integer } from '#root/UE/Integer.ts'; import { LinearColor } from '#root/UE/LinearColor.ts'; import { Vector } from '#root/UE/Vector.ts'; /** * System Library: Core Mathematical Functions * Wrapper for JavaScript Math functions with UE5 compatibility * Provides deterministic mathematical operations for movement calculations */ class MathLibraryClass extends BlueprintFunctionLibrary { constructor( outer: null | BlueprintFunctionLibrary = null, name: string = 'MathLibrary' ) { super(outer, name); } // ════════════════════════════════════════════════════════════════════════════════════════ // FUNCTIONS // ════════════════════════════════════════════════════════════════════════════════════════ /** * Convert degrees to radians * @param Degrees - Angle in degrees * @returns Angle in radians * @example * // Convert 90 degrees to radians * DegreesToRadians(90) // returns π/2 */ public DegreesToRadians(Degrees: Float): Float { return (Degrees * Math.PI) / 180; } /** * Convert radians to degrees * @param Radians - Angle in radians * @returns Angle in degrees * @example * // Convert π/2 radians to degrees * RadiansToDegrees(Math.PI / 2) // returns 90 */ public RadiansToDegrees(Radians: Float): Float { return (Radians * 180) / Math.PI; } /** * Calculate sine of angle in radians * @param Value - Angle in radians * @returns Sine value (-1 to 1) */ public Sin(Value: Float): Float { return Math.sin(Value); } /** * Calculate cosine of angle in radians * @param Value - Angle in radians * @returns Cosine value (-1 to 1) */ public Cos(Value: Float): Float { return Math.cos(Value); } /** * Calculate arccosine (inverse cosine) of value * @param Value - Input value (-1 to 1) * @returns Angle in radians (0 to π) */ public Acos(Value: Float): Float { return Math.acos(Value); } /** * Calculate arctangent2 of Y and X * @param Y - Y coordinate * @param X - X coordinate * @returns Angle in radians (-π to π) */ public Atan2(Y: Float, X: Float): Float { return Math.atan2(Y, X); } /** * Calculate dot product of two vectors * @param Vector1 - First vector * @param Vector2 - Second vector * @returns Dot product scalar value * @example * // Dot product of perpendicular vectors * Dot(new Vector(1,0,0), new Vector(0,1,0)) // returns 0 */ public Dot(Vector1: Vector, Vector2: Vector): Float { return ( Vector1.X * Vector2.X + Vector1.Y * Vector2.Y + Vector1.Z * Vector2.Z ); } /** * Color to LinearColor conversion * @param color - Color with 0-255 RGBA components * @returns LinearColor with 0-1 RGBA components * @example * // Convert Color(255,0,0,255) to LinearColor * ColorToLinearColor(new Color(255,0,0,255)) // returns LinearColor(1,0,0,1) */ public ColorToLinearColor(color: Color): LinearColor { return new LinearColor( color.R / 255, color.G / 255, color.B / 255, color.A / 255 ); } /** * Clamp a float value between a minimum and maximum * @param Value - Value to clamp * @param Min - Minimum limit * @param Max - Maximum limit * @returns Clamped value * @example * // Clamp 10 between 0 and 5 * Clamp(10, 0, 5) // returns 5 */ public ClampFloat(Value: Float, Min: Float, Max: Float): Float { return Math.min(Math.max(Value, Min), Max); } /** * Calculate vector length (magnitude) * @param Vector - Input vector * @returns Length (magnitude) of vector * @example * // Length of vector (3,4,0) * VectorLength(new Vector(3,4,0)) // returns 5 */ public VectorLength(Vector: Vector): Float { return Math.sqrt( Vector.X * Vector.X + Vector.Y * Vector.Y + Vector.Z * Vector.Z ); } /** * Interpolate a float value towards a target * @param Current - Current value * @param Target - Target value * @param DeltaTime - Time since last update * @param InterpSpeed - Speed of interpolation * @returns New interpolated value * @example * // Interpolate 0 towards 10 over 1 second at speed 5 * FInterpTo(0, 10, 1, 5) // returns 5 */ public FInterpTo( Current: Float, Target: Float, DeltaTime: Float, InterpSpeed: Float ): Float { if (InterpSpeed <= 0) { return Target; } const Dist = Target - Current; if (Dist * Dist < 0.00001) { return Target; } const DeltaMove = Dist * Math.min(DeltaTime * InterpSpeed, 1); return Current + DeltaMove; } /** * Absolute value of a float * @param Value - Input value * @returns Absolute value * @example * // Absolute value of -5 * abs(-5) // returns 5 */ public abs(Value: Float): Float { return Math.abs(Value); } /** * Interpolate a vector towards a target vector * @param Current - Current vector * @param Target - Target vector * @param DeltaTime - Time since last update * @param InterpSpeed - Speed of interpolation * @returns New interpolated vector * @example * // Interpolate (0,0,0) towards (10,10,10) over 1 second at speed 5 * VInterpTo(new Vector(0,0,0), new Vector(10,10,10), 1, 5) // returns Vector(5,5,5) */ public VInterpTo( Current: Vector = new Vector(0, 0, 0), Target: Vector = new Vector(0, 0, 0), DeltaTime: Float = 0, InterpSpeed: Float = 0 ): Vector { return new Vector( this.FInterpTo(Current.X, Target.X, DeltaTime, InterpSpeed), this.FInterpTo(Current.Y, Target.Y, DeltaTime, InterpSpeed), this.FInterpTo(Current.Z, Target.Z, DeltaTime, InterpSpeed) ); } /** * Normalize a vector to unit length * @param A - Input vector * @param Tolerance - Minimum length to avoid division by zero * @returns Normalized vector (length 1) or zero vector if input is zero * @example * // Normalize vector (3,4,0) * Normalize(new Vector(3,4,0)) // returns Vector(0.6,0.8,0) */ public Normal( A: Vector = new Vector(0, 0, 0), Tolerance: Float = 0.0001 ): Vector { const length = this.VectorLength(A); if (length > Tolerance) { return new Vector(A.X / length, A.Y / length, A.Z / length); } return new Vector(0, 0, 0); } /** * Get the minimum of two float values * @param A - First value * @param B - Second value * @returns Minimum value * @example * // Minimum of 3 and 5 * Min(3, 5) // returns 3 */ public Min(A: Float, B: Float): Float { return Math.min(A, B); } /** * Get right vector from roll, pitch, yaw angles * @param Roll - Rotation around forward axis in radians * @param Pitch - Rotation around right axis in radians * @param Yaw - Rotation around up axis in radians * @returns Right direction vector * @example * // Right vector for no rotation * GetRightVector(0, 0, 0) // returns Vector(1,0,0) */ public GetRightVector( Roll: Float = 0, Pitch: Float = 0, Yaw: Float = 0 ): Vector { const CP = this.Cos(Pitch); const SP = this.Sin(Pitch); const CY = this.Cos(Yaw); const SY = this.Sin(Yaw); console.log(Roll); return new Vector(CP * CY, CP * SY, SP); } /** * Get forward vector from roll, pitch, yaw angles * @param Roll - Rotation around forward axis in radians * @param Pitch - Rotation around right axis in radians * @param Yaw - Rotation around up axis in radians * @returns Forward direction vector * @example * // Forward vector for no rotation * GetForwardVector(0, 0, 0) // returns Vector(1,0,0) */ public GetForwardVector( Roll: Float = 0, Pitch: Float = 0, Yaw: Float = 0 ): Vector { const CP = this.Cos(Pitch); const SP = this.Sin(Pitch); const CY = this.Cos(Yaw); const SY = this.Sin(Yaw); console.log(Roll); return new Vector(CP * CY, CP * SY, SP); } /** * Floor a float value to the nearest lower integer * @param Value - Input float value * @returns Floored integer value * @example * // Floor 3.7 to 3 * Floor(3.7) // returns 3 */ public Ceil(Value: Float): Integer { return Math.ceil(Value); } } /** * Global instance of math library * Used throughout the movement system for mathematical calculations */ export const MathLibrary = new MathLibraryClass();