From 5b42c4d319d6c0710d22f70fcb9ac1330c9147b7 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 13:14:26 +0800 Subject: [PATCH 1/9] refactor(math): Vector3 --- UnityPy/math/Vector3.py | 60 ++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/UnityPy/math/Vector3.py b/UnityPy/math/Vector3.py index 5e19f994..e0abc3f3 100644 --- a/UnityPy/math/Vector3.py +++ b/UnityPy/math/Vector3.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from math import sqrt +from typing import Sequence kEpsilon = 0.00001 @@ -7,16 +8,28 @@ @dataclass class Vector3: + '''https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector3.cs''' + X: float = 0.0 Y: float = 0.0 Z: float = 0.0 def __init__(self, *args): - if len(args) == 3 or len(args) == 1 and isinstance(args[0], (tuple, list)): - self.X, self.Y, self.Z = args - elif len(args) == 1: - # dirty patch for Vector4 - self.__dict__ = args[0].__dict__ + if len(args) == 1: + args = args[0] + + if isinstance(args, Sequence): + if len(args) == 3: # args=(x, y, z) + self.X, self.Y, self.Z = args + return + if len(args) == 0: # args=() + self.X = self.Y = self.Z = 0.0 + return + else: # dirty patch for Vector4 + self.X, self.Y, self.Z = args.X, args.Y, args.Z + return + + raise TypeError("Invalid arguments for Vector3") def __getitem__(self, index): return (self.X, self.Y, self.Z)[index] @@ -32,13 +45,11 @@ def __setitem__(self, index, value): raise IndexError("Index out of range") def __hash__(self): - return self.X.__hash__() ^ (self.Y.__hash__() << 2) ^ (self.Z.__hash__() >> 2) - - def __eq__(self, other): - if isinstance(other, Vector3): - return self.X == other.X and self.Y == other.Y and self.Z == other.Z - else: - return False + return ( + self.X.__hash__() ^ + (self.Y.__hash__() << 2) ^ + (self.Z.__hash__() >> 2) + ) def normalize(self): length = self.length() @@ -48,21 +59,19 @@ def normalize(self): self.Y *= invNorm self.Z *= invNorm else: - X = 0 - Y = 0 - Z = 0 + self.X = self.Y = self.Z = 0.0 - def Normalize(self): - self.normalize() + Normalize = normalize def length(self): - return sqrt(self.LengthSquared()) + return sqrt(self.lengthSquared()) + + Length = length - def Length(self): - return self.length() + def lengthSquared(self): + return self.X ** 2 + self.Y ** 2 + self.Z ** 2 - def LengthSquared(self): - return self.X ** 2 + self.Y ** 2 + self.Y ** 2 + LengthSquared = lengthSquared @staticmethod def Zero(): @@ -81,11 +90,14 @@ def __sub__(a, b): def __mul__(a, d): return Vector3(a.X * d, a.Y * d, a.Z * d) - def __div__(a, d): + def __truediv__(a, d): return Vector3(a.X / d, a.Y / d, a.Z / d) def __eq__(lhs, rhs): - return (lhs - rhs).LengthSquared() < kEpsilon + if isinstance(rhs, Vector3): + diff = lhs - rhs + return diff.lengthSquared() < kEpsilon * kEpsilon + return False def __ne__(lhs, rhs): return not (lhs == rhs) From e0d92c0831ad5e7fbd9cc57ad2b8317d383fa5e8 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 14:00:08 +0800 Subject: [PATCH 2/9] refactor(math): Vector4 --- UnityPy/math/Vector4.py | 261 +++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 152 deletions(-) diff --git a/UnityPy/math/Vector4.py b/UnityPy/math/Vector4.py index 5b90096e..7930da82 100644 --- a/UnityPy/math/Vector4.py +++ b/UnityPy/math/Vector4.py @@ -1,155 +1,112 @@ +from dataclasses import dataclass +from math import sqrt +from typing import Sequence + + +kEpsilon = 0.00001 + + +@dataclass class Vector4: - X: float - Y: float - Z: float - W: float + '''https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector4.cs''' + + X: float = 0.0 + Y: float = 0.0 + Z: float = 0.0 + W: float = 0.0 def __init__(self, *args): - if len(args) == 4: # float x, float y, float z, float w - self.X = args[0] - self.Y = args[1] - self.Z = args[2] - self.W = args[3] - elif len(args) == 2: # Vector3 value, float w - self.X = args[0].X - self.Y = args[0].Y - self.Z = args[0].Z - self.W = args[1] - - """ - public float this[int index] - { - get - { - switch (index) - { - case 0: return X; - case 1: return Y; - case 2: return Z; - case 3: return W; - default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!"); - } - } - - set - { - switch (index) - { - case 0: X = value; break; - case 1: Y = value; break; - case 2: Z = value; break; - case 3: W = value; break; - default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!"); - } - } - } - - - public override int GetHashCode() - { - return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1); - } - - public override bool Equals(object other) - { - if (!(other is Vector4)) - return false; - return Equals((Vector4)other); - } - - public bool Equals(Vector4 other) - { - return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W); - } - - public void Normalize() - { - var length = Length(); - if (length > kEpsilon) - { - var invNorm = 1.0f / length; - X *= invNorm; - Y *= invNorm; - Z *= invNorm; - W *= invNorm; - } - else - { - X = 0; - Y = 0; - Z = 0; - W = 0; - } - } - - public float Length() - { - return (float)Math.Sqrt(LengthSquared()); - } - - public float LengthSquared() - { - return X * X + Y * Y + Z * Z + W * W; - } - - public static Vector4 Zero => new Vector4(); - - public static Vector4 operator +(Vector4 a, Vector4 b) - { - return new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W); - } - - public static Vector4 operator -(Vector4 a, Vector4 b) - { - return new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W); - } - - public static Vector4 operator -(Vector4 a) - { - return new Vector4(-a.X, -a.Y, -a.Z, -a.W); - } - - public static Vector4 operator *(Vector4 a, float d) - { - return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d); - } - - public static Vector4 operator *(float d, Vector4 a) - { - return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d); - } - - public static Vector4 operator /(Vector4 a, float d) - { - return new Vector4(a.X / d, a.Y / d, a.Z / d, a.W / d); - } - - public static bool operator ==(Vector4 lhs, Vector4 rhs) - { - return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon; - } - - public static bool operator !=(Vector4 lhs, Vector4 rhs) - { - return !(lhs == rhs); - } - - public static implicit operator Vector2(Vector4 v) - { - return new Vector2(v.X, v.Y); - } - - public static implicit operator Vector3(Vector4 v) - { - return new Vector3(v.X, v.Y, v.Z); - } - - public static implicit operator Color(Vector4 v) - { - return new Color(v.X, v.Y, v.Z, v.W); - } - - private const float kEpsilon = 0.00001F; - } -} -""" + if len(args) == 1: + args = args[0] + + if isinstance(args, Sequence): + if len(args) == 4: # args=(x, y, z, w) + self.X, self.Y, self.Z, self.W = args + return + if len(args) == 2: # args=(Vector3, w) + self.X, self.Y, self.Z = args[0] + self.W = args[1] + if len(args) == 0: # args=() + self.X = self.Y = self.Z = self.W = 0.0 + return + + raise TypeError("Invalid arguments for Vector4") + + def __getitem__(self, index): + return (self.X, self.Y, self.Z, self.W)[index] + + def __setitem__(self, index, value): + if index == 0: + self.X = value + elif index == 1: + self.Y = value + elif index == 2: + self.Z = value + elif index == 3: + self.W = value + else: + raise IndexError("Index out of range") + + def __hash__(self): + return ( + self.X.__hash__() ^ + (self.Y.__hash__() << 2) ^ + (self.Z.__hash__() >> 2) ^ + (self.W.__hash__() >> 1) + ) + + def normalize(self): + length = self.length() + if length > kEpsilon: + invNorm = 1.0 / length + self.X *= invNorm + self.Y *= invNorm + self.Z *= invNorm + self.W *= invNorm + else: + self.X = self.Y = self.Z = self.W = 0.0 + + Normalize = normalize + + def length(self): + return sqrt(self.lengthSquared()) + + Length = length + + def lengthSquared(self): + return self.X ** 2 + self.Y ** 2 + self.Z ** 2 + self.W ** 2 + + LengthSquared = lengthSquared + + @staticmethod + def Zero(): + return Vector4(0, 0, 0, 0) + + @staticmethod + def One(): + return Vector4(1, 1, 1, 1) + + def __add__(a, b): + return Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W) + + def __sub__(a, b): + return Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W) + + def __mul__(a, d): + return Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d) + + def __truediv__(a, d): + return Vector4(a.X / d, a.Y / d, a.Z / d, a.W / d) + + def __eq__(lhs, rhs): + if isinstance(rhs, Vector4): + diff = lhs - rhs + return diff.lengthSquared() < kEpsilon * kEpsilon + return False + + def __ne__(lhs, rhs): + return not (lhs == rhs) + + def Vector3(self): + from .Vector3 import Vector3 + return Vector3(self.X, self.Y, self.Z) From e94afcc68a82a5b1a4698954e2ac9cfe2520f913 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 14:00:31 +0800 Subject: [PATCH 3/9] refactor(math): Vector2 --- UnityPy/math/Vector2.py | 241 ++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 159 deletions(-) diff --git a/UnityPy/math/Vector2.py b/UnityPy/math/Vector2.py index e20601a6..c876bca3 100644 --- a/UnityPy/math/Vector2.py +++ b/UnityPy/math/Vector2.py @@ -1,160 +1,83 @@ +from dataclasses import dataclass +from math import sqrt + + +kEpsilon = 0.00001 + + +@dataclass class Vector2: - X: float - Y: float - - def __init__(self, x: float, y: float): - self.X = x - self.Y = y - - -""" -using System; -using System.Runtime.InteropServices; - -namespace AssetStudio -{ - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Vector2 : IEquatable - { - public float X; - public float Y; - - public Vector2(float x, float y) - { - X = x; - Y = y; - } - - public float this[int index] - { - get - { - switch (index) - { - case 0: return X; - case 1: return Y; - default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!"); - } - } - - set - { - switch (index) - { - case 0: X = value; break; - case 1: Y = value; break; - default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!"); - } - } - } - - public override int GetHashCode() - { - return X.GetHashCode() ^ (Y.GetHashCode() << 2); - } - - public override bool Equals(object other) - { - if (!(other is Vector2)) - return false; - return Equals((Vector2)other); - } - - public bool Equals(Vector2 other) - { - return X.Equals(other.X) && Y.Equals(other.Y); - } - - public void Normalize() - { - var length = Length(); - if (length > kEpsilon) - { - var invNorm = 1.0f / length; - X *= invNorm; - Y *= invNorm; - } - else - { - X = 0; - Y = 0; - } - } - - public float Length() - { - return (float)Math.Sqrt(LengthSquared()); - } - - public float LengthSquared() - { - return X * X + Y * Y; - } - - public static Vector2 Zero => new Vector2(); - - public static Vector2 operator +(Vector2 a, Vector2 b) - { - return new Vector2(a.X + b.X, a.Y + b.Y); - } - - public static Vector2 operator -(Vector2 a, Vector2 b) - { - return new Vector2(a.X - b.X, a.Y - b.Y); - } - - public static Vector2 operator *(Vector2 a, Vector2 b) - { - return new Vector2(a.X * b.X, a.Y * b.Y); - } - - public static Vector2 operator /(Vector2 a, Vector2 b) - { - return new Vector2(a.X / b.X, a.Y / b.Y); - } - - public static Vector2 operator -(Vector2 a) - { - return new Vector2(-a.X, -a.Y); - } - - public static Vector2 operator *(Vector2 a, float d) - { - return new Vector2(a.X * d, a.Y * d); - } - - public static Vector2 operator *(float d, Vector2 a) - { - return new Vector2(a.X * d, a.Y * d); - } - - public static Vector2 operator /(Vector2 a, float d) - { - return new Vector2(a.X / d, a.Y / d); - } - - public static bool operator ==(Vector2 lhs, Vector2 rhs) - { - return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon; - } - - public static bool operator !=(Vector2 lhs, Vector2 rhs) - { - return !(lhs == rhs); - } - - public static implicit operator Vector3(Vector2 v) - { - return new Vector3(v.X, v.Y, 0); - } - - public static implicit operator Vector4(Vector2 v) - { - return new Vector4(v.X, v.Y, 0.0F, 0.0F); - } - - private const float kEpsilon = 0.00001F; - } -} - -""" + '''https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector2.cs''' + + X: float = 0.0 + Y: float = 0.0 + + def __init__(self, x: float = 0.0, y: float = 0.0): + if not all(isinstance(v, (int, float)) for v in (x, y)): + raise TypeError("All components must be numeric.") + self.X = float(x) + self.Y = float(y) + + def __getitem__(self, index): + return (self.X, self.Y)[index] + + def __setitem__(self, index, value): + if index == 0: + self.X = value + elif index == 1: + self.Y = value + else: + raise IndexError("Index out of range") + + def __hash__(self): + return self.X.__hash__() ^ (self.Y.__hash__() << 2) + + def normalize(self): + length = self.length() + if length > kEpsilon: + invNorm = 1.0 / length + self.X *= invNorm + self.Y *= invNorm + else: + self.X = self.Y = 0.0 + + Normalize = normalize + + def length(self): + return sqrt(self.lengthSquared()) + + Length = length + + def lengthSquared(self): + return self.X ** 2 + self.Y ** 2 + + LengthSquared = lengthSquared + + @staticmethod + def Zero(): + return Vector2(0, 0) + + @staticmethod + def One(): + return Vector2(1, 1) + + def __add__(a, b): + return Vector2(a.X + b.X, a.Y + b.Y) + + def __sub__(a, b): + return Vector2(a.X - b.X, a.Y - b.Y) + + def __mul__(a, d): + return Vector2(a.X * d, a.Y * d) + + def __truediv__(a, d): + return Vector2(a.X / d, a.Y / d) + + def __eq__(lhs, rhs): + if isinstance(rhs, Vector2): + diff = lhs - rhs + return diff.lengthSquared() < kEpsilon * kEpsilon + return False + + def __ne__(lhs, rhs): + return not (lhs == rhs) From 73b7e987c9981823d4778e9bb17d5f3773c496ef Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 14:21:36 +0800 Subject: [PATCH 4/9] refactor(math): Quaternion --- UnityPy/math/Quaternion.py | 66 +++++++++++++------------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/UnityPy/math/Quaternion.py b/UnityPy/math/Quaternion.py index e315785f..064427f2 100644 --- a/UnityPy/math/Quaternion.py +++ b/UnityPy/math/Quaternion.py @@ -3,48 +3,26 @@ class Quaternion: Y: float Z: float W: float - - def __init__(self, x: float = 0.0, y: float = 0.0, z: float = 0.0, w: float = 0.0): - self._data = [0.0] * 4 - self.X = x - self.Y = y - self.Z = z - self.W = w - - @property - def X(self) -> float: - return self._data[0] - - @X.setter - def X(self, value: float): - self._data[0] = value - - @property - def Y(self) -> float: - return self._data[1] - - @Y.setter - def Y(self, value: float): - self._data[1] = value - - @property - def Z(self) -> float: - return self._data[2] - - @Z.setter - def Z(self, value: float): - self._data[2] = value - - @property - def W(self) -> float: - return self._data[3] - - @W.setter - def W(self, value: float): - self._data[3] = value - - def __getitem__(self, value): - return self._data[value] - + + def __init__(self, x: float = 0.0, y: float = 0.0, z: float = 0.0, w: float = 1.0): + if not all(isinstance(v, (int, float)) for v in (x, y, z, w)): + raise TypeError("All components must be numeric.") + self.X = float(x) + self.Y = float(y) + self.Z = float(z) + self.W = float(w) + + def __getitem__(self, index): + return (self.X, self.Y, self.Z, self.W)[index] + def __setitem__(self, index, value): - self._data[index] = value + if index == 0: + self.X = value + elif index == 1: + self.Y = value + elif index == 2: + self.Z = value + elif index == 3: + self.W = value + else: + raise IndexError("Index out of range") From 058c6f1e95e7a9e54c994a08b3f0cb0737fd58c2 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 15:06:47 +0800 Subject: [PATCH 5/9] refactor(math): Matrix4x4 --- UnityPy/math/Matrix4x4.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/UnityPy/math/Matrix4x4.py b/UnityPy/math/Matrix4x4.py index a38c5967..05e04903 100644 --- a/UnityPy/math/Matrix4x4.py +++ b/UnityPy/math/Matrix4x4.py @@ -1,31 +1,41 @@ +from typing import MutableSequence, Sequence, Union from .Vector3 import Vector3 class Matrix4x4: - M: list + M: MutableSequence[float] - def __init__(self, values): - if len(values) != 16: - raise ValueError( - "There must be sixteen and only sixteen input values for Matrix." - ) - self.M = values + def __init__(self, values: Sequence[Union[int, float]]): + if not isinstance(values, Sequence) or len(values) != 16: + raise ValueError("Values must be a sequence with 16 elements.") + if not all(isinstance(v, (int, float)) for v in values): + raise TypeError("All values must be numeric.") + self.M = [float(v) for v in values] def __getitem__(self, index): if isinstance(index, tuple): - index = index[0] + index[1] * 4 + row, col = index + if not (0 <= row < 4 and 0 <= col < 4): + raise IndexError("Row and column indices must in range [0, 3].") + index = row + col * 4 + if not (0 <= index < 16): + raise IndexError("Index out of range for Matrix4x4.") return self.M[index] def __setitem__(self, index, value): if isinstance(index, tuple): - # row, column - index = index[0] + index[1] * 4 + row, col = index + if not (0 <= row < 4 and 0 <= col < 4): + raise IndexError("Row and column indices must in range [0, 3].") + index = row + col * 4 + if not (0 <= index < 16): + raise IndexError("Index out of range for Matrix4x4.") self.M[index] = value def __eq__(self, other): if not isinstance(other, Matrix4x4): return False - print() + return all(abs(a - b) < 1e-6 for a, b in zip(self.M, other.M)) def __mul__(lhs, rhs): res = Matrix4x4([0] * 16) @@ -134,7 +144,10 @@ def __mul__(lhs, rhs): @staticmethod def Scale(vector: Vector3): return Matrix4x4( - [vector.X, 0, 0, 0, 0, vector.Y, 0, 0, 0, 0, vector.Z, 0, 0, 0, 0, 1] + [vector.X, 0, 0, 0, + 0, vector.Y, 0, 0, + 0, 0, vector.Z, 0, + 0, 0, 0, 1] ) @property From c9b89f0591d7ad3557e9361e62ccff80ff57719c Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 20:45:29 +0800 Subject: [PATCH 6/9] refactor(math): Color --- UnityPy/math/Color.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/UnityPy/math/Color.py b/UnityPy/math/Color.py index fced5e1c..42016bc8 100644 --- a/UnityPy/math/Color.py +++ b/UnityPy/math/Color.py @@ -8,17 +8,13 @@ class Color: A: float def __init__(self, r: float = 0.0, g: float = 0.0, b: float = 0.0, a: float = 0.0): + if not all(isinstance(v, (int, float)) for v in (r, g, b, a)): + raise TypeError("All components must be numeric.") self.R = r self.G = g self.B = b self.A = a - def __eq__(self, other): - if isinstance(other, Color): - return self.__dict__ == other.__dict__ - else: - return False - def __add__(self, other): return Color( self.R + other.R, self.G + other.G, self.B + other.B, self.A + other.A @@ -37,7 +33,7 @@ def __mul__(self, other): else: return Color(self.R * other, self.G * other, self.B * other, self.A * other) - def __div__(self, other): + def __truediv__(self, other): if isinstance(other, Color): return Color( self.R / other.R, self.G / other.G, self.B / other.B, self.A / other.A @@ -46,10 +42,13 @@ def __div__(self, other): return Color(self.R / other, self.G / other, self.B / other, self.A / other) def __eq__(self, other): - return self.__dict__ == other.__dict__ + if isinstance(other, Color): + return self.__dict__ == other.__dict__ + else: + return False def __ne__(self, other): - return self.__dict__ != other.__dict__ + return not (self == other) def Vector4(self): return Vector4(self.R, self.G, self.B, self.A) From c8a307e75c78edabc46edaff2ec9e8ed6bf0f241 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 20:47:18 +0800 Subject: [PATCH 7/9] chore(math): apply dataclass decorator --- UnityPy/math/Color.py | 2 ++ UnityPy/math/Matrix4x4.py | 2 ++ UnityPy/math/Quaternion.py | 4 ++++ UnityPy/math/Rectangle.py | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/UnityPy/math/Color.py b/UnityPy/math/Color.py index 42016bc8..9390aff8 100644 --- a/UnityPy/math/Color.py +++ b/UnityPy/math/Color.py @@ -1,6 +1,8 @@ +from dataclasses import dataclass from .Vector4 import Vector4 +@dataclass class Color: R: float G: float diff --git a/UnityPy/math/Matrix4x4.py b/UnityPy/math/Matrix4x4.py index 05e04903..e09f2ac0 100644 --- a/UnityPy/math/Matrix4x4.py +++ b/UnityPy/math/Matrix4x4.py @@ -1,7 +1,9 @@ +from dataclasses import dataclass from typing import MutableSequence, Sequence, Union from .Vector3 import Vector3 +@dataclass class Matrix4x4: M: MutableSequence[float] diff --git a/UnityPy/math/Quaternion.py b/UnityPy/math/Quaternion.py index 064427f2..6c27afec 100644 --- a/UnityPy/math/Quaternion.py +++ b/UnityPy/math/Quaternion.py @@ -1,3 +1,7 @@ +from dataclasses import dataclass + + +@dataclass class Quaternion: X: float Y: float diff --git a/UnityPy/math/Rectangle.py b/UnityPy/math/Rectangle.py index d32ca639..a198ec43 100644 --- a/UnityPy/math/Rectangle.py +++ b/UnityPy/math/Rectangle.py @@ -1,3 +1,7 @@ +from dataclasses import dataclass + + +@dataclass class Rectangle: height: int width: int From b9471389408a5bd94902ce9081b11a30b081a5b5 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 31 Jan 2025 20:47:39 +0800 Subject: [PATCH 8/9] chore(math): remove Half --- UnityPy/math/Half.py | 102 ------------------------------------------- 1 file changed, 102 deletions(-) delete mode 100644 UnityPy/math/Half.py diff --git a/UnityPy/math/Half.py b/UnityPy/math/Half.py deleted file mode 100644 index 6d56e1b9..00000000 --- a/UnityPy/math/Half.py +++ /dev/null @@ -1,102 +0,0 @@ -import struct -import math - -MaxValue = 65504.0 -MinValue = -65504.0 - - -def ToHalf(*args) -> float: - """ - Converts the input into a half-float. - Inputs: - unsigned integer - or - buffer (bytes, buffer) - offset - """ - # int input -> pack as UInt16 - if len(args) == 1: - data = struct.pack("H", args[0]) - val = struct.unpack("e", data)[0] - # buffer input - elif len(args) == 2: - val = struct.unpack_from("e", args[0], args[1])[0] - else: - raise ValueError("Invalid amount of arguments") - - if math.isnan(val): - # print('Nan') - return 0 - elif math.isinf(val): - return MaxValue - - return val - - -# #CONSTANTS -# Epsilon = ToHalf(0x0001) -# MaxValue = ToHalf(0x7bff) -# MinValue = ToHalf(0xfbff) -# NaN = ToHalf(0xfe00) -# NegativeInfinity = ToHalf(0xfc00) -# PositiveInfinity = ToHalf(0x7c00) - -# class Float16Compressor: -# def __init__(self): -# self.temp = 0 - -# def compress(self, float32): -# F16_EXPONENT_BITS = 0x1F -# F16_EXPONENT_SHIFT = 10 -# F16_EXPONENT_BIAS = 15 -# F16_MANTISSA_BITS = 0x3ff -# F16_MANTISSA_SHIFT = (23 - F16_EXPONENT_SHIFT) -# F16_MAX_EXPONENT = (F16_EXPONENT_BITS << F16_EXPONENT_SHIFT) - -# a = struct.pack('>f', float32) -# b = binascii.hexlify(a) - -# f32 = int(b, 16) -# f16 = 0 -# sign = (f32 >> 16) & 0x8000 -# exponent = ((f32 >> 23) & 0xff) - 127 -# mantissa = f32 & 0x007fffff - -# if exponent == 128: -# f16 = sign | F16_MAX_EXPONENT -# if mantissa: -# f16 |= (mantissa & F16_MANTISSA_BITS) -# elif exponent > 15: -# f16 = sign | F16_MAX_EXPONENT -# elif exponent > -15: -# exponent += F16_EXPONENT_BIAS -# mantissa >>= F16_MANTISSA_SHIFT -# f16 = sign | exponent << F16_EXPONENT_SHIFT | mantissa -# else: -# f16 = sign -# return f16 - -# def decompress(self, float16): -# s = int((float16 >> 15) & 0x00000001) # sign -# e = int((float16 >> 10) & 0x0000001f) # exponent -# f = int(float16 & 0x000003ff) # fraction - -# if e == 0: -# if f == 0: -# return int(s << 31) -# else: -# while not (f & 0x00000400): -# f = f << 1 -# e -= 1 -# e += 1 -# f &= ~0x00000400 -# # print(s,e,f) -# elif e == 31: -# if f == 0: -# return int((s << 31) | 0x7f800000) -# else: -# return int((s << 31) | 0x7f800000 | (f << 13)) - -# e = e + (127 - 15) -# f = f << 13 -# return int((s << 31) | (e << 23) | f) From dbe2b800006fc060148cb20be1d8e68e28c49bc2 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Tue, 4 Feb 2025 13:14:52 +0800 Subject: [PATCH 9/9] fix(math): optimize __init__ in Vectors --- UnityPy/math/Vector3.py | 15 ++++++++------- UnityPy/math/Vector4.py | 12 ++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/UnityPy/math/Vector3.py b/UnityPy/math/Vector3.py index e0abc3f3..a821ec1d 100644 --- a/UnityPy/math/Vector3.py +++ b/UnityPy/math/Vector3.py @@ -15,21 +15,22 @@ class Vector3: Z: float = 0.0 def __init__(self, *args): + from .Vector4 import Vector4 if len(args) == 1: args = args[0] if isinstance(args, Sequence): if len(args) == 3: # args=(x, y, z) self.X, self.Y, self.Z = args - return - if len(args) == 0: # args=() + elif len(args) == 0: # args=() self.X = self.Y = self.Z = 0.0 - return - else: # dirty patch for Vector4 + else: + raise TypeError("Invalid argument length for Vector3") + elif isinstance(args, Vector4): + # dirty patch for Vector4 self.X, self.Y, self.Z = args.X, args.Y, args.Z - return - - raise TypeError("Invalid arguments for Vector3") + else: + raise TypeError("If only 1 argument passed, it must be a sequence or Vector4") def __getitem__(self, index): return (self.X, self.Y, self.Z)[index] diff --git a/UnityPy/math/Vector4.py b/UnityPy/math/Vector4.py index 7930da82..d6e87c8b 100644 --- a/UnityPy/math/Vector4.py +++ b/UnityPy/math/Vector4.py @@ -22,15 +22,15 @@ def __init__(self, *args): if isinstance(args, Sequence): if len(args) == 4: # args=(x, y, z, w) self.X, self.Y, self.Z, self.W = args - return - if len(args) == 2: # args=(Vector3, w) + elif len(args) == 2: # args=(Vector3, w) self.X, self.Y, self.Z = args[0] self.W = args[1] - if len(args) == 0: # args=() + elif len(args) == 0: # args=() self.X = self.Y = self.Z = self.W = 0.0 - return - - raise TypeError("Invalid arguments for Vector4") + else: + raise TypeError("Invalid argument length for Vector4") + else: + raise TypeError("If only 1 argument passed, it must be a sequence") def __getitem__(self, index): return (self.X, self.Y, self.Z, self.W)[index]