feat: 集成Rust WASM渲染引擎与TypeScript ECS框架 (#228)
* feat: 集成Rust WASM渲染引擎与TypeScript ECS框架 * feat: 增强编辑器UI功能与跨平台支持 * fix: 修复CI测试和类型检查问题 * fix: 修复CI问题并提高测试覆盖率 * fix: 修复CI问题并提高测试覆盖率
This commit is contained in:
184
packages/engine/src/math/color.rs
Normal file
184
packages/engine/src/math/color.rs
Normal file
@@ -0,0 +1,184 @@
|
||||
//! Color utilities.
|
||||
//! 颜色工具。
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
/// RGBA color representation.
|
||||
/// RGBA颜色表示。
|
||||
///
|
||||
/// Colors are stored as normalized floats (0.0-1.0) and can be converted
|
||||
/// to packed u32 format for efficient GPU transfer.
|
||||
/// 颜色以归一化浮点数(0.0-1.0)存储,可转换为打包的u32格式以高效传输到GPU。
|
||||
///
|
||||
/// # Examples | 示例
|
||||
/// ```rust
|
||||
/// let red = Color::RED;
|
||||
/// let custom = Color::new(0.5, 0.7, 0.3, 1.0);
|
||||
/// let packed = custom.to_packed(); // For GPU
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct Color {
|
||||
/// Red component (0.0-1.0).
|
||||
/// 红色分量。
|
||||
pub r: f32,
|
||||
/// Green component (0.0-1.0).
|
||||
/// 绿色分量。
|
||||
pub g: f32,
|
||||
/// Blue component (0.0-1.0).
|
||||
/// 蓝色分量。
|
||||
pub b: f32,
|
||||
/// Alpha component (0.0-1.0).
|
||||
/// 透明度分量。
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
/// White (1, 1, 1, 1).
|
||||
/// 白色。
|
||||
pub const WHITE: Self = Self { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
|
||||
|
||||
/// Black (0, 0, 0, 1).
|
||||
/// 黑色。
|
||||
pub const BLACK: Self = Self { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
|
||||
|
||||
/// Red (1, 0, 0, 1).
|
||||
/// 红色。
|
||||
pub const RED: Self = Self { r: 1.0, g: 0.0, b: 0.0, a: 1.0 };
|
||||
|
||||
/// Green (0, 1, 0, 1).
|
||||
/// 绿色。
|
||||
pub const GREEN: Self = Self { r: 0.0, g: 1.0, b: 0.0, a: 1.0 };
|
||||
|
||||
/// Blue (0, 0, 1, 1).
|
||||
/// 蓝色。
|
||||
pub const BLUE: Self = Self { r: 0.0, g: 0.0, b: 1.0, a: 1.0 };
|
||||
|
||||
/// Transparent (0, 0, 0, 0).
|
||||
/// 透明。
|
||||
pub const TRANSPARENT: Self = Self { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
|
||||
|
||||
/// Create a new color.
|
||||
/// 创建新颜色。
|
||||
#[inline]
|
||||
pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
|
||||
/// Create a color from RGB values (alpha = 1.0).
|
||||
/// 从RGB值创建颜色(alpha = 1.0)。
|
||||
#[inline]
|
||||
pub const fn rgb(r: f32, g: f32, b: f32) -> Self {
|
||||
Self { r, g, b, a: 1.0 }
|
||||
}
|
||||
|
||||
/// Create from u8 values (0-255).
|
||||
/// 从u8值创建(0-255)。
|
||||
#[inline]
|
||||
pub fn from_rgba8(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self {
|
||||
r: r as f32 / 255.0,
|
||||
g: g as f32 / 255.0,
|
||||
b: b as f32 / 255.0,
|
||||
a: a as f32 / 255.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from hex value (0xRRGGBB or 0xRRGGBBAA).
|
||||
/// 从十六进制值创建。
|
||||
#[inline]
|
||||
pub fn from_hex(hex: u32) -> Self {
|
||||
if hex > 0xFFFFFF {
|
||||
// 0xRRGGBBAA format
|
||||
Self::from_rgba8(
|
||||
((hex >> 24) & 0xFF) as u8,
|
||||
((hex >> 16) & 0xFF) as u8,
|
||||
((hex >> 8) & 0xFF) as u8,
|
||||
(hex & 0xFF) as u8,
|
||||
)
|
||||
} else {
|
||||
// 0xRRGGBB format
|
||||
Self::from_rgba8(
|
||||
((hex >> 16) & 0xFF) as u8,
|
||||
((hex >> 8) & 0xFF) as u8,
|
||||
(hex & 0xFF) as u8,
|
||||
255,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to packed u32 (ABGR format for WebGL).
|
||||
/// 转换为打包的u32(WebGL的ABGR格式)。
|
||||
#[inline]
|
||||
pub fn to_packed(&self) -> u32 {
|
||||
let r = (self.r.clamp(0.0, 1.0) * 255.0) as u32;
|
||||
let g = (self.g.clamp(0.0, 1.0) * 255.0) as u32;
|
||||
let b = (self.b.clamp(0.0, 1.0) * 255.0) as u32;
|
||||
let a = (self.a.clamp(0.0, 1.0) * 255.0) as u32;
|
||||
|
||||
(a << 24) | (b << 16) | (g << 8) | r
|
||||
}
|
||||
|
||||
/// Create from packed u32 (ABGR format).
|
||||
/// 从打包的u32创建(ABGR格式)。
|
||||
#[inline]
|
||||
pub fn from_packed(packed: u32) -> Self {
|
||||
Self::from_rgba8(
|
||||
(packed & 0xFF) as u8,
|
||||
((packed >> 8) & 0xFF) as u8,
|
||||
((packed >> 16) & 0xFF) as u8,
|
||||
((packed >> 24) & 0xFF) as u8,
|
||||
)
|
||||
}
|
||||
|
||||
/// Linear interpolation between two colors.
|
||||
/// 两个颜色之间的线性插值。
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: &Self, t: f32) -> Self {
|
||||
Self {
|
||||
r: self.r + (other.r - self.r) * t,
|
||||
g: self.g + (other.g - self.g) * t,
|
||||
b: self.b + (other.b - self.b) * t,
|
||||
a: self.a + (other.a - self.a) * t,
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiply color by alpha (premultiplied alpha).
|
||||
/// 颜色乘以alpha(预乘alpha)。
|
||||
#[inline]
|
||||
pub fn premultiply(&self) -> Self {
|
||||
Self {
|
||||
r: self.r * self.a,
|
||||
g: self.g * self.a,
|
||||
b: self.b * self.a,
|
||||
a: self.a,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the alpha value.
|
||||
/// 设置alpha值。
|
||||
#[inline]
|
||||
pub fn with_alpha(self, a: f32) -> Self {
|
||||
Self { a, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Color {
|
||||
fn default() -> Self {
|
||||
Self::WHITE
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 4]> for Color {
|
||||
#[inline]
|
||||
fn from([r, g, b, a]: [f32; 4]) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for [f32; 4] {
|
||||
#[inline]
|
||||
fn from(c: Color) -> Self {
|
||||
[c.r, c.g, c.b, c.a]
|
||||
}
|
||||
}
|
||||
19
packages/engine/src/math/mod.rs
Normal file
19
packages/engine/src/math/mod.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
//! Mathematical primitives for 2D game development.
|
||||
//! 用于2D游戏开发的数学基元。
|
||||
//!
|
||||
//! This module provides wrappers around `glam` types with additional
|
||||
//! game-specific functionality.
|
||||
//! 此模块提供对`glam`类型的封装,并添加游戏特定的功能。
|
||||
|
||||
mod vec2;
|
||||
mod transform;
|
||||
mod rect;
|
||||
mod color;
|
||||
|
||||
pub use vec2::Vec2;
|
||||
pub use transform::Transform2D;
|
||||
pub use rect::Rect;
|
||||
pub use color::Color;
|
||||
|
||||
// Re-export glam types for internal use | 重新导出glam类型供内部使用
|
||||
pub use glam::{Mat3, Mat4, Vec3, Vec4};
|
||||
148
packages/engine/src/math/rect.rs
Normal file
148
packages/engine/src/math/rect.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
//! Rectangle implementation.
|
||||
//! 矩形实现。
|
||||
|
||||
use super::Vec2;
|
||||
|
||||
/// Axis-aligned rectangle.
|
||||
/// 轴对齐矩形。
|
||||
///
|
||||
/// # Examples | 示例
|
||||
/// ```rust
|
||||
/// let rect = Rect::new(10.0, 20.0, 100.0, 50.0);
|
||||
/// let point = Vec2::new(50.0, 40.0);
|
||||
/// assert!(rect.contains_point(point));
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
pub struct Rect {
|
||||
/// X position (left edge).
|
||||
/// X位置(左边缘)。
|
||||
pub x: f32,
|
||||
/// Y position (top edge).
|
||||
/// Y位置(上边缘)。
|
||||
pub y: f32,
|
||||
/// Width.
|
||||
/// 宽度。
|
||||
pub width: f32,
|
||||
/// Height.
|
||||
/// 高度。
|
||||
pub height: f32,
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
/// Create a new rectangle.
|
||||
/// 创建新矩形。
|
||||
#[inline]
|
||||
pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
|
||||
Self { x, y, width, height }
|
||||
}
|
||||
|
||||
/// Create a rectangle from two corner points.
|
||||
/// 从两个角点创建矩形。
|
||||
#[inline]
|
||||
pub fn from_corners(min: Vec2, max: Vec2) -> Self {
|
||||
Self {
|
||||
x: min.x,
|
||||
y: min.y,
|
||||
width: max.x - min.x,
|
||||
height: max.y - min.y,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a rectangle centered at a point.
|
||||
/// 创建以某点为中心的矩形。
|
||||
#[inline]
|
||||
pub fn from_center(center: Vec2, width: f32, height: f32) -> Self {
|
||||
Self {
|
||||
x: center.x - width * 0.5,
|
||||
y: center.y - height * 0.5,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the minimum (top-left) corner.
|
||||
/// 获取最小(左上)角点。
|
||||
#[inline]
|
||||
pub fn min(&self) -> Vec2 {
|
||||
Vec2::new(self.x, self.y)
|
||||
}
|
||||
|
||||
/// Get the maximum (bottom-right) corner.
|
||||
/// 获取最大(右下)角点。
|
||||
#[inline]
|
||||
pub fn max(&self) -> Vec2 {
|
||||
Vec2::new(self.x + self.width, self.y + self.height)
|
||||
}
|
||||
|
||||
/// Get the center point.
|
||||
/// 获取中心点。
|
||||
#[inline]
|
||||
pub fn center(&self) -> Vec2 {
|
||||
Vec2::new(self.x + self.width * 0.5, self.y + self.height * 0.5)
|
||||
}
|
||||
|
||||
/// Get the size as a vector.
|
||||
/// 获取尺寸向量。
|
||||
#[inline]
|
||||
pub fn size(&self) -> Vec2 {
|
||||
Vec2::new(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Check if the rectangle contains a point.
|
||||
/// 检查矩形是否包含某点。
|
||||
#[inline]
|
||||
pub fn contains_point(&self, point: Vec2) -> bool {
|
||||
point.x >= self.x
|
||||
&& point.x <= self.x + self.width
|
||||
&& point.y >= self.y
|
||||
&& point.y <= self.y + self.height
|
||||
}
|
||||
|
||||
/// Check if this rectangle intersects with another.
|
||||
/// 检查此矩形是否与另一个相交。
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Rect) -> bool {
|
||||
self.x < other.x + other.width
|
||||
&& self.x + self.width > other.x
|
||||
&& self.y < other.y + other.height
|
||||
&& self.y + self.height > other.y
|
||||
}
|
||||
|
||||
/// Get the intersection of two rectangles.
|
||||
/// 获取两个矩形的交集。
|
||||
pub fn intersection(&self, other: &Rect) -> Option<Rect> {
|
||||
let x = self.x.max(other.x);
|
||||
let y = self.y.max(other.y);
|
||||
let right = (self.x + self.width).min(other.x + other.width);
|
||||
let bottom = (self.y + self.height).min(other.y + other.height);
|
||||
|
||||
if right > x && bottom > y {
|
||||
Some(Rect::new(x, y, right - x, bottom - y))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the union of two rectangles (bounding box).
|
||||
/// 获取两个矩形的并集(包围盒)。
|
||||
pub fn union(&self, other: &Rect) -> Rect {
|
||||
let x = self.x.min(other.x);
|
||||
let y = self.y.min(other.y);
|
||||
let right = (self.x + self.width).max(other.x + other.width);
|
||||
let bottom = (self.y + self.height).max(other.y + other.height);
|
||||
|
||||
Rect::new(x, y, right - x, bottom - y)
|
||||
}
|
||||
|
||||
/// Expand the rectangle by a margin.
|
||||
/// 按边距扩展矩形。
|
||||
#[inline]
|
||||
pub fn expand(&self, margin: f32) -> Rect {
|
||||
Rect::new(
|
||||
self.x - margin,
|
||||
self.y - margin,
|
||||
self.width + margin * 2.0,
|
||||
self.height + margin * 2.0,
|
||||
)
|
||||
}
|
||||
}
|
||||
164
packages/engine/src/math/transform.rs
Normal file
164
packages/engine/src/math/transform.rs
Normal file
@@ -0,0 +1,164 @@
|
||||
//! 2D transform implementation.
|
||||
//! 2D变换实现。
|
||||
|
||||
use super::Vec2;
|
||||
use glam::Mat3;
|
||||
|
||||
/// 2D transformation combining position, rotation, and scale.
|
||||
/// 组合位置、旋转和缩放的2D变换。
|
||||
///
|
||||
/// # Examples | 示例
|
||||
/// ```rust
|
||||
/// let mut transform = Transform2D::new();
|
||||
/// transform.position = Vec2::new(100.0, 200.0);
|
||||
/// transform.rotation = std::f32::consts::PI / 4.0; // 45 degrees
|
||||
/// transform.scale = Vec2::new(2.0, 2.0);
|
||||
///
|
||||
/// let matrix = transform.to_matrix();
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Transform2D {
|
||||
/// Position in world space.
|
||||
/// 世界空间中的位置。
|
||||
pub position: Vec2,
|
||||
|
||||
/// Rotation in radians.
|
||||
/// 旋转角度(弧度)。
|
||||
pub rotation: f32,
|
||||
|
||||
/// Scale factor.
|
||||
/// 缩放因子。
|
||||
pub scale: Vec2,
|
||||
|
||||
/// Origin point for rotation and scaling (0-1 range, relative to size).
|
||||
/// 旋转和缩放的原点(0-1范围,相对于尺寸)。
|
||||
pub origin: Vec2,
|
||||
}
|
||||
|
||||
impl Default for Transform2D {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
position: Vec2::ZERO,
|
||||
rotation: 0.0,
|
||||
scale: Vec2::new(1.0, 1.0),
|
||||
origin: Vec2::new(0.5, 0.5), // Center by default | 默认居中
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transform2D {
|
||||
/// Create a new transform with default values.
|
||||
/// 使用默认值创建新变换。
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Create a transform with specified position.
|
||||
/// 使用指定位置创建变换。
|
||||
#[inline]
|
||||
pub fn from_position(x: f32, y: f32) -> Self {
|
||||
Self {
|
||||
position: Vec2::new(x, y),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a transform with position, rotation, and scale.
|
||||
/// 使用位置、旋转和缩放创建变换。
|
||||
#[inline]
|
||||
pub fn from_pos_rot_scale(position: Vec2, rotation: f32, scale: Vec2) -> Self {
|
||||
Self {
|
||||
position,
|
||||
rotation,
|
||||
scale,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to a 3x3 transformation matrix.
|
||||
/// 转换为3x3变换矩阵。
|
||||
///
|
||||
/// The matrix is constructed as: T * R * S (translate, rotate, scale).
|
||||
/// 矩阵构造顺序为:T * R * S(平移、旋转、缩放)。
|
||||
pub fn to_matrix(&self) -> Mat3 {
|
||||
let cos = self.rotation.cos();
|
||||
let sin = self.rotation.sin();
|
||||
|
||||
// Construct TRS matrix directly for performance
|
||||
// 直接构造TRS矩阵以提高性能
|
||||
Mat3::from_cols(
|
||||
glam::Vec3::new(cos * self.scale.x, sin * self.scale.x, 0.0),
|
||||
glam::Vec3::new(-sin * self.scale.y, cos * self.scale.y, 0.0),
|
||||
glam::Vec3::new(self.position.x, self.position.y, 1.0),
|
||||
)
|
||||
}
|
||||
|
||||
/// Convert to a 3x3 matrix with origin offset applied.
|
||||
/// 转换为应用原点偏移的3x3矩阵。
|
||||
///
|
||||
/// # Arguments | 参数
|
||||
/// * `width` - Sprite width | 精灵宽度
|
||||
/// * `height` - Sprite height | 精灵高度
|
||||
pub fn to_matrix_with_origin(&self, width: f32, height: f32) -> Mat3 {
|
||||
let ox = -self.origin.x * width * self.scale.x;
|
||||
let oy = -self.origin.y * height * self.scale.y;
|
||||
|
||||
let cos = self.rotation.cos();
|
||||
let sin = self.rotation.sin();
|
||||
|
||||
// Apply origin offset after rotation
|
||||
// 在旋转后应用原点偏移
|
||||
let tx = self.position.x + ox * cos - oy * sin;
|
||||
let ty = self.position.y + ox * sin + oy * cos;
|
||||
|
||||
Mat3::from_cols(
|
||||
glam::Vec3::new(cos * self.scale.x, sin * self.scale.x, 0.0),
|
||||
glam::Vec3::new(-sin * self.scale.y, cos * self.scale.y, 0.0),
|
||||
glam::Vec3::new(tx, ty, 1.0),
|
||||
)
|
||||
}
|
||||
|
||||
/// Transform a local point to world space.
|
||||
/// 将局部点变换到世界空间。
|
||||
#[inline]
|
||||
pub fn transform_point(&self, point: Vec2) -> Vec2 {
|
||||
let rotated = point.rotate(self.rotation);
|
||||
Vec2::new(
|
||||
rotated.x * self.scale.x + self.position.x,
|
||||
rotated.y * self.scale.y + self.position.y,
|
||||
)
|
||||
}
|
||||
|
||||
/// Inverse transform a world point to local space.
|
||||
/// 将世界点反变换到局部空间。
|
||||
#[inline]
|
||||
pub fn inverse_transform_point(&self, point: Vec2) -> Vec2 {
|
||||
let local = Vec2::new(
|
||||
(point.x - self.position.x) / self.scale.x,
|
||||
(point.y - self.position.y) / self.scale.y,
|
||||
);
|
||||
local.rotate(-self.rotation)
|
||||
}
|
||||
|
||||
/// Translate the transform by a delta.
|
||||
/// 按增量平移变换。
|
||||
#[inline]
|
||||
pub fn translate(&mut self, delta: Vec2) {
|
||||
self.position = self.position + delta;
|
||||
}
|
||||
|
||||
/// Rotate the transform by an angle (in radians).
|
||||
/// 按角度旋转变换(弧度)。
|
||||
#[inline]
|
||||
pub fn rotate(&mut self, angle: f32) {
|
||||
self.rotation += angle;
|
||||
}
|
||||
|
||||
/// Scale the transform by a factor.
|
||||
/// 按因子缩放变换。
|
||||
#[inline]
|
||||
pub fn scale_by(&mut self, factor: Vec2) {
|
||||
self.scale = Vec2::new(self.scale.x * factor.x, self.scale.y * factor.y);
|
||||
}
|
||||
}
|
||||
214
packages/engine/src/math/vec2.rs
Normal file
214
packages/engine/src/math/vec2.rs
Normal file
@@ -0,0 +1,214 @@
|
||||
//! 2D vector implementation.
|
||||
//! 2D向量实现。
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
/// 2D vector for positions, velocities, and directions.
|
||||
/// 用于位置、速度和方向的2D向量。
|
||||
///
|
||||
/// # Examples | 示例
|
||||
/// ```rust
|
||||
/// let pos = Vec2::new(100.0, 200.0);
|
||||
/// let velocity = Vec2::new(1.0, 0.0);
|
||||
/// let new_pos = pos + velocity * 16.0;
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct Vec2 {
|
||||
/// X component.
|
||||
/// X分量。
|
||||
pub x: f32,
|
||||
/// Y component.
|
||||
/// Y分量。
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Vec2 {
|
||||
/// Zero vector (0, 0).
|
||||
/// 零向量。
|
||||
pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
|
||||
|
||||
/// Unit vector pointing right (1, 0).
|
||||
/// 指向右的单位向量。
|
||||
pub const RIGHT: Self = Self { x: 1.0, y: 0.0 };
|
||||
|
||||
/// Unit vector pointing up (0, 1).
|
||||
/// 指向上的单位向量。
|
||||
pub const UP: Self = Self { x: 0.0, y: 1.0 };
|
||||
|
||||
/// Create a new 2D vector.
|
||||
/// 创建新的2D向量。
|
||||
#[inline]
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
/// Create a vector with both components set to the same value.
|
||||
/// 创建两个分量相同的向量。
|
||||
#[inline]
|
||||
pub const fn splat(v: f32) -> Self {
|
||||
Self { x: v, y: v }
|
||||
}
|
||||
|
||||
/// Calculate the length (magnitude) of the vector.
|
||||
/// 计算向量的长度(模)。
|
||||
#[inline]
|
||||
pub fn length(&self) -> f32 {
|
||||
(self.x * self.x + self.y * self.y).sqrt()
|
||||
}
|
||||
|
||||
/// Calculate the squared length (avoids sqrt).
|
||||
/// 计算长度的平方(避免开方运算)。
|
||||
#[inline]
|
||||
pub fn length_squared(&self) -> f32 {
|
||||
self.x * self.x + self.y * self.y
|
||||
}
|
||||
|
||||
/// Normalize the vector (make it unit length).
|
||||
/// 归一化向量(使其成为单位长度)。
|
||||
#[inline]
|
||||
pub fn normalize(&self) -> Self {
|
||||
let len = self.length();
|
||||
if len > 0.0 {
|
||||
Self {
|
||||
x: self.x / len,
|
||||
y: self.y / len,
|
||||
}
|
||||
} else {
|
||||
Self::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate dot product with another vector.
|
||||
/// 计算与另一个向量的点积。
|
||||
#[inline]
|
||||
pub fn dot(&self, other: &Self) -> f32 {
|
||||
self.x * other.x + self.y * other.y
|
||||
}
|
||||
|
||||
/// Calculate cross product (returns scalar for 2D).
|
||||
/// 计算叉积(2D返回标量)。
|
||||
#[inline]
|
||||
pub fn cross(&self, other: &Self) -> f32 {
|
||||
self.x * other.y - self.y * other.x
|
||||
}
|
||||
|
||||
/// Calculate distance to another point.
|
||||
/// 计算到另一点的距离。
|
||||
#[inline]
|
||||
pub fn distance(&self, other: &Self) -> f32 {
|
||||
(*self - *other).length()
|
||||
}
|
||||
|
||||
/// Linear interpolation between two vectors.
|
||||
/// 两个向量之间的线性插值。
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: &Self, t: f32) -> Self {
|
||||
Self {
|
||||
x: self.x + (other.x - self.x) * t,
|
||||
y: self.y + (other.y - self.y) * t,
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotate the vector by an angle (in radians).
|
||||
/// 按角度旋转向量(弧度)。
|
||||
#[inline]
|
||||
pub fn rotate(&self, angle: f32) -> Self {
|
||||
let cos = angle.cos();
|
||||
let sin = angle.sin();
|
||||
Self {
|
||||
x: self.x * cos - self.y * sin,
|
||||
y: self.x * sin + self.y * cos,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to glam Vec2.
|
||||
/// 转换为glam Vec2。
|
||||
#[inline]
|
||||
pub fn to_glam(&self) -> glam::Vec2 {
|
||||
glam::Vec2::new(self.x, self.y)
|
||||
}
|
||||
|
||||
/// Create from glam Vec2.
|
||||
/// 从glam Vec2创建。
|
||||
#[inline]
|
||||
pub fn from_glam(v: glam::Vec2) -> Self {
|
||||
Self { x: v.x, y: v.y }
|
||||
}
|
||||
}
|
||||
|
||||
// Operator implementations | 运算符实现
|
||||
|
||||
impl std::ops::Add for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div<f32> for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self::Output {
|
||||
Self {
|
||||
x: -self.x,
|
||||
y: -self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32)> for Vec2 {
|
||||
#[inline]
|
||||
fn from((x, y): (f32, f32)) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 2]> for Vec2 {
|
||||
#[inline]
|
||||
fn from([x, y]: [f32; 2]) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user