diff --git a/package-lock.json b/package-lock.json index 3e932b44..38dee481 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3186,6 +3186,10 @@ "resolved": "apps/playground-3d", "link": true }, + "node_modules/@fibbojs/util": { + "resolved": "packages/util", + "link": true + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -15835,6 +15839,10 @@ "dependencies": { "@fibbojs/core": "0.0.13" } + }, + "packages/util": { + "version": "0.0.13", + "license": "Apache-2.0" } } } diff --git a/packages/2d/package.json b/packages/2d/package.json index 39f28f76..d70823cd 100644 --- a/packages/2d/package.json +++ b/packages/2d/package.json @@ -49,6 +49,7 @@ "@dimforge/rapier2d": "0.14.0", "@fibbojs/core": "0.0.13", "@fibbojs/event": "0.0.13", + "@fibbojs/util": "0.0.13", "pixi-viewport": "5.0.3", "pixi.js": "8.3.4" } diff --git a/packages/2d/src/core/FCollider.ts b/packages/2d/src/core/FCollider.ts index a8d61575..0e6ad236 100644 --- a/packages/2d/src/core/FCollider.ts +++ b/packages/2d/src/core/FCollider.ts @@ -1,5 +1,5 @@ import * as RAPIER from '@dimforge/rapier2d' -import type { FVector2 } from '../types/FVector2' +import type { FVector2 } from '@fibbojs/core' import { FShapes } from '../types/FShapes' import type { FComponent } from './FComponent' import type { FRigidBody } from './FRigidBody' diff --git a/packages/2d/src/core/FComponent.ts b/packages/2d/src/core/FComponent.ts index d708274e..2cc283d4 100644 --- a/packages/2d/src/core/FComponent.ts +++ b/packages/2d/src/core/FComponent.ts @@ -1,9 +1,8 @@ -import type { FComponentOptions as FComponentOptionsCore, OnCollisionWithData } from '@fibbojs/core' +import type { FComponentOptions as FComponentOptionsCore, FVector2, OnCollisionWithData } from '@fibbojs/core' import { FComponent as FComponentCore } from '@fibbojs/core' import * as PIXI from 'pixi.js' import * as RAPIER from '@dimforge/rapier2d' import type { FController } from '../controllers/FController' -import type { FVector2 } from '../types/FVector2' import type { FScene } from './FScene' import type { FColliderOptions } from './FCollider' import { FCollider } from './FCollider' diff --git a/packages/2d/src/core/FRigidBody.ts b/packages/2d/src/core/FRigidBody.ts index f2485606..6e013e37 100644 --- a/packages/2d/src/core/FRigidBody.ts +++ b/packages/2d/src/core/FRigidBody.ts @@ -1,5 +1,5 @@ import * as RAPIER from '@dimforge/rapier2d' -import type { FVector2 } from '../types/FVector2' +import type { FVector2 } from '@fibbojs/core' import { FRigidBodyType } from '../types/FRigidBodyType' import { FShapes } from '../types/FShapes' import type { FComponent } from './FComponent' diff --git a/packages/2d/src/core/FTransform.ts b/packages/2d/src/core/FTransform.ts index 2af5a096..112ee640 100644 --- a/packages/2d/src/core/FTransform.ts +++ b/packages/2d/src/core/FTransform.ts @@ -1,4 +1,5 @@ -import type { FVector2 } from '../types/FVector2' +import type { FVector2 } from '@fibbojs/core' +import { FMathUtil } from '@fibbojs/util' export interface FTransformOptions { position?: { x: number, y: number } @@ -70,7 +71,7 @@ export class FTransform { // Set the transform values this.__POSITION__ = options.position - this.__ROTATION__ = options.rotationDegree !== undefined ? options.rotationDegree * (Math.PI / 180) : options.rotation || 0 + this.__ROTATION__ = options.rotationDegree !== undefined ? FMathUtil.degreeToRad(options.rotationDegree) : options.rotation || 0 this.__SCALE__ = options.scale } @@ -197,7 +198,7 @@ export class FTransform { * Get the rotation in degrees. */ get rotationDegree() { - return this.__ROTATION__ * (180 / Math.PI) + return FMathUtil.radToDegree(this.__ROTATION__) } /** @@ -205,7 +206,7 @@ export class FTransform { * @param rotationDegree The new rotation in degrees. */ set rotationDegree(rotationDegree: number) { - this.setRotation(rotationDegree * (Math.PI / 180)) + this.setRotation(FMathUtil.degreeToRad(rotationDegree)) } /** diff --git a/packages/2d/src/index.ts b/packages/2d/src/index.ts index 2fed00c1..c326ddf3 100644 --- a/packages/2d/src/index.ts +++ b/packages/2d/src/index.ts @@ -37,4 +37,3 @@ export * from './sprite/FSprite' // Types export * from './types/FRigidBodyType' export * from './types/FShapes' -export * from './types/FVector2' diff --git a/packages/2d/src/polygons/FRectangle.ts b/packages/2d/src/polygons/FRectangle.ts index 6fb3e6dd..c5d64f0e 100644 --- a/packages/2d/src/polygons/FRectangle.ts +++ b/packages/2d/src/polygons/FRectangle.ts @@ -1,6 +1,6 @@ import * as PIXI from 'pixi.js' +import type { FVector2 } from '@fibbojs/core' import type { FScene } from '../core/FScene' -import type { FVector2 } from '../types/FVector2' import type { FPolygonOptions } from './FPolygon' import { FPolygon } from './FPolygon' diff --git a/packages/2d/src/sprite/FSprite.ts b/packages/2d/src/sprite/FSprite.ts index 1e2d9973..368d8fe6 100644 --- a/packages/2d/src/sprite/FSprite.ts +++ b/packages/2d/src/sprite/FSprite.ts @@ -1,4 +1,5 @@ import * as PIXI from 'pixi.js' +import { FAssetUtil } from '@fibbojs/util' import type { FComponentOptions } from '../core/FComponent' import { FComponent } from '../core/FComponent' import type { FScene } from '../core/FScene' @@ -49,24 +50,8 @@ export class FSprite extends FComponent { * @param texture The path to the texture. */ async loadTexture(texture: string) { - // Interpret path function - function interpretPath(path: string) { - // Resource URL (if it starts http, treat as a URL) - if (path.startsWith('http')) { - return path - } - // Absolute path (if it starts with /), add the current domain + path - else if (path.startsWith('/')) { - return `${window.location.href}${path}` - } - // Otherwise, treat as a relative path starting to the assets folder - else { - return `${window.location.href}/assets/${path}` - } - } - // Interpret the path - const path = interpretPath(texture) + const path = FAssetUtil.interpretPath(texture) // Load the texture this.__TEXTURE__ = await PIXI.Assets.load(path) this.__TEXTURE__.source.scaleMode = 'nearest' diff --git a/packages/3d/package.json b/packages/3d/package.json index f6755a0c..f0ae273e 100644 --- a/packages/3d/package.json +++ b/packages/3d/package.json @@ -49,6 +49,7 @@ "@dimforge/rapier3d": "0.14.0", "@fibbojs/core": "0.0.13", "@fibbojs/event": "0.0.13", + "@fibbojs/util": "0.0.13", "@types/three": "0.168.0", "three": "0.168.0" } diff --git a/packages/3d/src/cameras/FAttachedCamera.ts b/packages/3d/src/cameras/FAttachedCamera.ts index fb07139a..f717f927 100644 --- a/packages/3d/src/cameras/FAttachedCamera.ts +++ b/packages/3d/src/cameras/FAttachedCamera.ts @@ -1,6 +1,6 @@ +import type { FVector3 } from '@fibbojs/core' import type { FComponent } from '../core/FComponent' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' import type { FCameraOptions } from './FCamera' import { FCamera } from './FCamera' diff --git a/packages/3d/src/cameras/FCamera.ts b/packages/3d/src/cameras/FCamera.ts index bcd89481..ff793703 100644 --- a/packages/3d/src/cameras/FCamera.ts +++ b/packages/3d/src/cameras/FCamera.ts @@ -1,9 +1,9 @@ import * as THREE from 'three' import { FCamera as FCameraCore } from '@fibbojs/core' +import type { FVector3 } from '@fibbojs/core' import type { FTransformOptions } from '../core/FTransform' import { FTransform } from '../core/FTransform' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' export interface FCameraOptions extends FTransformOptions {} diff --git a/packages/3d/src/cameras/FGameCamera.ts b/packages/3d/src/cameras/FGameCamera.ts index 5f8c4dff..4ccbfb90 100644 --- a/packages/3d/src/cameras/FGameCamera.ts +++ b/packages/3d/src/cameras/FGameCamera.ts @@ -1,5 +1,5 @@ +import type { FVector3 } from '@fibbojs/core' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' import { FOrbitCamera } from './FOrbitCamera' import type { FAttachedCameraOptions } from './FAttachedCamera' diff --git a/packages/3d/src/cameras/FOrbitCamera.ts b/packages/3d/src/cameras/FOrbitCamera.ts index f4f8ee0c..6f1500cd 100644 --- a/packages/3d/src/cameras/FOrbitCamera.ts +++ b/packages/3d/src/cameras/FOrbitCamera.ts @@ -1,8 +1,8 @@ import * as THREE from 'three' import { OrbitControls } from 'three/addons/controls/OrbitControls.js' +import type { FVector3 } from '@fibbojs/core' import type { FComponent } from '../core/FComponent' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' import { FCamera } from './FCamera' import type { FAttachedCameraOptions } from './FAttachedCamera' diff --git a/packages/3d/src/controllers/FCharacterControllerK.ts b/packages/3d/src/controllers/FCharacterControllerK.ts index 3387b0b8..c8105bc9 100644 --- a/packages/3d/src/controllers/FCharacterControllerK.ts +++ b/packages/3d/src/controllers/FCharacterControllerK.ts @@ -1,8 +1,8 @@ import * as THREE from 'three' import RAPIER from '@dimforge/rapier3d' import { FKeyboard } from '@fibbojs/event' +import type { FVector3 } from '@fibbojs/core' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' import type { FCharacterControllerOptions } from './FCharacterController' import { FCharacterController } from './FCharacterController' diff --git a/packages/3d/src/core/FCollider.ts b/packages/3d/src/core/FCollider.ts index 6274d946..85caf7f6 100644 --- a/packages/3d/src/core/FCollider.ts +++ b/packages/3d/src/core/FCollider.ts @@ -1,7 +1,8 @@ import * as THREE from 'three' import * as RAPIER from '@dimforge/rapier3d' +import type { FVector3 } from '@fibbojs/core' +import { FMathUtil } from '@fibbojs/util' import { FShapes } from '../types/FShapes' -import type { FVector3 } from '../types/FVector3' import type { FComponent } from './FComponent' import type { FRigidBody } from './FRigidBody' import { FTransform } from './FTransform' @@ -168,7 +169,7 @@ export class FCollider { frame(_delta: number): void { // As the collider should have moved, update the transform to sync with the collider this.transform.__POSITION__ = this.__COLLIDER__.translation() - this.transform.__ROTATION__ = new THREE.Euler().setFromQuaternion(new THREE.Quaternion().copy(this.__COLLIDER__.rotation())) + this.transform.__ROTATION__ = FMathUtil.quaternionToRad(this.__COLLIDER__.rotation()) // Propagate the position and rotation update if the collider is attached to a component if (this.component) { // Propagate the position update diff --git a/packages/3d/src/core/FComponent.ts b/packages/3d/src/core/FComponent.ts index a9abecc5..aee2e382 100644 --- a/packages/3d/src/core/FComponent.ts +++ b/packages/3d/src/core/FComponent.ts @@ -1,9 +1,8 @@ import * as THREE from 'three' import * as RAPIER from '@dimforge/rapier3d' -import type { OnCollisionWithData } from '@fibbojs/core' +import type { FVector3, OnCollisionWithData } from '@fibbojs/core' import { FComponent as FComponentCore } from '@fibbojs/core' import type { FController } from '../controllers/FController' -import type { FVector3 } from '../types/FVector3' import type { FScene } from './FScene' import type { FColliderOptions } from './FCollider' import { FCollider } from './FCollider' @@ -139,18 +138,18 @@ export abstract class FComponent extends FComponentCore { if (this.rigidBody) { // Move the component this.__SET_POSITION__({ - x: this.rigidBody.transform.position.x - this.rigidBody.offset.position.x, - y: this.rigidBody.transform.position.y - this.rigidBody.offset.position.y, - z: this.rigidBody.transform.position.z - this.rigidBody.offset.position.z, + x: this.rigidBody.transform.x - this.rigidBody.offset.x, + y: this.rigidBody.transform.y - this.rigidBody.offset.y, + z: this.rigidBody.transform.z - this.rigidBody.offset.z, }) } // If a collider exists, the propagation comes from the collider else if (this.collider) { // Move the component this.__SET_POSITION__({ - x: this.collider.transform.position.x - this.collider.offset.x, - y: this.collider.transform.position.y - this.collider.offset.y, - z: this.collider.transform.position.z - this.collider.offset.z, + x: this.collider.transform.x - this.collider.offset.x, + y: this.collider.transform.y - this.collider.offset.y, + z: this.collider.transform.z - this.collider.offset.z, }) } } @@ -181,18 +180,18 @@ export abstract class FComponent extends FComponentCore { if (this.rigidBody) { // Rotate the component this.__SET_ROTATION__({ - x: this.rigidBody.transform.rotation.x - this.rigidBody.offset.rotationX, - y: this.rigidBody.transform.rotation.y - this.rigidBody.offset.rotationY, - z: this.rigidBody.transform.rotation.z - this.rigidBody.offset.rotationZ, + x: this.rigidBody.transform.rotationX - this.rigidBody.offset.rotationX, + y: this.rigidBody.transform.rotationY - this.rigidBody.offset.rotationY, + z: this.rigidBody.transform.rotationZ - this.rigidBody.offset.rotationZ, }) } // If a collider exists, the propagation comes from the collider else if (this.collider) { // Rotate the component this.__SET_ROTATION__({ - x: this.collider.transform.rotation.x - this.collider.offset.rotationX, - y: this.collider.transform.rotation.y - this.collider.offset.rotationY, - z: this.collider.transform.rotation.z - this.collider.offset.rotationZ, + x: this.collider.transform.rotationX - this.collider.offset.rotationX, + y: this.collider.transform.rotationY - this.collider.offset.rotationY, + z: this.collider.transform.rotationZ - this.collider.offset.rotationZ, }) } } @@ -245,7 +244,9 @@ export abstract class FComponent extends FComponentCore { if (this.__MESH__) this.__MESH__.position.set(position.x, position.y, position.z) // Update the transform - this.transform.__POSITION__ = position + this.transform.__POSITION__.x = position.x + this.transform.__POSITION__.y = position.y + this.transform.__POSITION__.z = position.z } __SET_ROTATION__(rotation: FVector3): void { @@ -253,7 +254,9 @@ export abstract class FComponent extends FComponentCore { if (this.__MESH__) this.__MESH__.rotation.set(rotation.x, rotation.y, rotation.z) // Update the transform - this.transform.__ROTATION__ = rotation + this.transform.__ROTATION__.x = rotation.x + this.transform.__ROTATION__.y = rotation.y + this.transform.__ROTATION__.z = rotation.z } __SET_SCALE__(scale: FVector3): void { diff --git a/packages/3d/src/core/FRigidBody.ts b/packages/3d/src/core/FRigidBody.ts index 98f56c8d..49baaadc 100644 --- a/packages/3d/src/core/FRigidBody.ts +++ b/packages/3d/src/core/FRigidBody.ts @@ -1,7 +1,8 @@ import * as THREE from 'three' import * as RAPIER from '@dimforge/rapier3d' +import type { FVector3 } from '@fibbojs/core' +import { FMathUtil } from '@fibbojs/util' import { FShapes } from '../types/FShapes' -import type { FVector3 } from '../types/FVector3' import { FRigidBodyType } from '../types/FRigidBodyType' import type { FComponent } from './FComponent' import { FCollider } from './FCollider' @@ -203,7 +204,7 @@ export class FRigidBody { frame(_delta: number): void { // As the rigidBody should have moved, update the transform to sync with the rigidBody this.transform.__POSITION__ = this.__RIGIDBODY__.translation() - this.transform.__ROTATION__ = new THREE.Euler().setFromQuaternion(new THREE.Quaternion().copy(this.__RIGIDBODY__.rotation())) + this.transform.__ROTATION__ = FMathUtil.quaternionToRad(this.__RIGIDBODY__.rotation()) // Propagate the position and rotation update if the rigidBody is attached to a component if (this.component) { // Propagate the position update diff --git a/packages/3d/src/core/FScene.ts b/packages/3d/src/core/FScene.ts index 1a471d28..d910a79b 100644 --- a/packages/3d/src/core/FScene.ts +++ b/packages/3d/src/core/FScene.ts @@ -1,11 +1,10 @@ import * as THREE from 'three' import { FScene as FSceneCore } from '@fibbojs/core' -import type { FSceneOptions as FSceneOptionsCore } from '@fibbojs/core' +import type { FSceneOptions as FSceneOptionsCore, FVector3 } from '@fibbojs/core' import type RAPIER from '@dimforge/rapier3d' import type { FCamera } from '../cameras/FCamera' import { FFixedCamera } from '../cameras/FFixedCamera' import type { FLight } from '../lights/FLight' -import type { FVector3 } from '../types/FVector3' import type { FComponent } from './FComponent' import type { FRigidBody } from './FRigidBody' import type { FCollider } from './FCollider' diff --git a/packages/3d/src/core/FTransform.ts b/packages/3d/src/core/FTransform.ts index 82837458..c7a3b33d 100644 --- a/packages/3d/src/core/FTransform.ts +++ b/packages/3d/src/core/FTransform.ts @@ -1,5 +1,6 @@ import * as THREE from 'three' -import type { FVector3 } from '../types/FVector3' +import type { FVector3 } from '@fibbojs/core' +import { FMathUtil } from '@fibbojs/util' export interface FTransformOptions { position?: FVector3 @@ -74,7 +75,7 @@ export class FTransform { // Set the transform values this.__POSITION__ = options.position this.__ROTATION__ = options.rotationDegree - ? { x: THREE.MathUtils.degToRad(options.rotationDegree.x), y: THREE.MathUtils.degToRad(options.rotationDegree.y), z: THREE.MathUtils.degToRad(options.rotationDegree.z) } + ? { x: FMathUtil.degreeToRad(options.rotationDegree.x), y: FMathUtil.degreeToRad(options.rotationDegree.y), z: FMathUtil.degreeToRad(options.rotationDegree.z) } : options.rotation || { x: 0, y: 0, z: 0 } this.__SCALE__ = options.scale } @@ -136,9 +137,9 @@ export class FTransform { */ setRotationDegree(rotationDegree: FVector3) { this.setRotation({ - x: THREE.MathUtils.degToRad(rotationDegree.x), - y: THREE.MathUtils.degToRad(rotationDegree.y), - z: THREE.MathUtils.degToRad(rotationDegree.z), + x: FMathUtil.degreeToRad(rotationDegree.x), + y: FMathUtil.degreeToRad(rotationDegree.y), + z: FMathUtil.degreeToRad(rotationDegree.z), }) } @@ -287,9 +288,9 @@ export class FTransform { */ get rotationDegree() { return { - x: THREE.MathUtils.radToDeg(this.__ROTATION__.x), - y: THREE.MathUtils.radToDeg(this.__ROTATION__.y), - z: THREE.MathUtils.radToDeg(this.__ROTATION__.z), + x: FMathUtil.radToDegree(this.__ROTATION__.x), + y: FMathUtil.radToDegree(this.__ROTATION__.y), + z: FMathUtil.radToDegree(this.__ROTATION__.z), } } @@ -308,7 +309,7 @@ export class FTransform { * Get the rotation in degrees on the x axis. */ get rotationDegreeX() { - return THREE.MathUtils.radToDeg(this.__ROTATION__.x) + return FMathUtil.radToDegree(this.__ROTATION__.x) } /** @@ -316,14 +317,14 @@ export class FTransform { * @param x The new rotation on the x axis in degrees. */ set rotationDegreeX(x: number) { - this.setRotationDegree({ x, y: THREE.MathUtils.radToDeg(this.__ROTATION__.y), z: THREE.MathUtils.radToDeg(this.__ROTATION__.z) }) + this.setRotationDegree({ x, y: FMathUtil.radToDegree(this.__ROTATION__.y), z: FMathUtil.radToDegree(this.__ROTATION__.z) }) } /** * Get the rotation in degrees on the y axis. */ get rotationDegreeY() { - return THREE.MathUtils.radToDeg(this.__ROTATION__.y) + return FMathUtil.radToDegree(this.__ROTATION__.y) } /** @@ -331,14 +332,14 @@ export class FTransform { * @param y The new rotation on the y axis in degrees. */ set rotationDegreeY(y: number) { - this.setRotationDegree({ x: THREE.MathUtils.radToDeg(this.__ROTATION__.x), y, z: THREE.MathUtils.radToDeg(this.__ROTATION__.z) }) + this.setRotationDegree({ x: FMathUtil.radToDegree(this.__ROTATION__.x), y, z: FMathUtil.radToDegree(this.__ROTATION__.z) }) } /** * Get the rotation in degrees on the z axis. */ get rotationDegreeZ() { - return THREE.MathUtils.radToDeg(this.__ROTATION__.z) + return FMathUtil.radToDegree(this.__ROTATION__.z) } /** @@ -346,7 +347,7 @@ export class FTransform { * @param z The new rotation on the z axis in degrees. */ set rotationDegreeZ(z: number) { - this.setRotationDegree({ x: THREE.MathUtils.radToDeg(this.__ROTATION__.x), y: THREE.MathUtils.radToDeg(this.__ROTATION__.y), z }) + this.setRotationDegree({ x: FMathUtil.radToDegree(this.__ROTATION__.x), y: FMathUtil.radToDegree(this.__ROTATION__.y), z }) } /** diff --git a/packages/3d/src/index.ts b/packages/3d/src/index.ts index 1ab9e570..58821540 100644 --- a/packages/3d/src/index.ts +++ b/packages/3d/src/index.ts @@ -52,4 +52,3 @@ export * from './polyhedrons/FSphere' // Types export * from './types/FRigidBodyType' export * from './types/FShapes' -export * from './types/FVector3' diff --git a/packages/3d/src/lights/FLight.ts b/packages/3d/src/lights/FLight.ts index a50d5443..c11cb1a0 100644 --- a/packages/3d/src/lights/FLight.ts +++ b/packages/3d/src/lights/FLight.ts @@ -1,9 +1,9 @@ import * as THREE from 'three' import { FLight as FLightCore } from '@fibbojs/core' +import type { FVector3 } from '@fibbojs/core' import type { FTransformOptions } from '../core/FTransform' import { FTransform } from '../core/FTransform' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' export interface FLightOptions extends FTransformOptions { color?: THREE.ColorRepresentation diff --git a/packages/3d/src/model/FFBX.ts b/packages/3d/src/model/FFBX.ts index bf3aac02..b2cad195 100644 --- a/packages/3d/src/model/FFBX.ts +++ b/packages/3d/src/model/FFBX.ts @@ -1,7 +1,7 @@ import * as THREE from 'three' import { FBXLoader } from 'three/addons/loaders/FBXLoader.js' +import type { FVector3 } from '@fibbojs/core' import type { FScene } from '../core/FScene' -import type { FVector3 } from '../types/FVector3' import { FModel } from './FModel' import type { FModelOptions } from './FModel' diff --git a/packages/3d/src/model/FModel.ts b/packages/3d/src/model/FModel.ts index 5f4778f6..e7d4495f 100644 --- a/packages/3d/src/model/FModel.ts +++ b/packages/3d/src/model/FModel.ts @@ -1,4 +1,5 @@ import * as THREE from 'three' +import { FAssetUtil } from '@fibbojs/util' import type { FScene } from '../core/FScene' import { FComponent } from '../core/FComponent' import type { FComponentOptions } from '../core/FComponent' @@ -71,28 +72,12 @@ export abstract class FModel extends FComponent { this.textures = options.textures this.fileExtension = options.fileExtension - // Interpret path function - function interpretPath(path: string) { - // Resource URL (if it starts http, treat as a URL) - if (path.startsWith('http')) { - return path - } - // Absolute path (if it starts with /), add the current domain + path - else if (path.startsWith('/')) { - return `${window.location.href}${path}` - } - // Otherwise, treat as a relative path starting to the assets folder - else { - return `${window.location.href}/assets/${path}` - } - } - // Interpret the path - this.path = interpretPath(this.path) + this.path = FAssetUtil.interpretPath(this.path) // Interpret the textures this.textures = Object.fromEntries( Object.entries(this.textures).map(([materialName, texturePath]) => { - return [materialName, interpretPath(texturePath)] + return [materialName, FAssetUtil.interpretPath(texturePath)] }), ) } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 9d8b36f6..50333c51 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -7,3 +7,8 @@ export * from './FController' export * from './FGroup' export * from './FLight' export * from './FScene' + +// Types +export * from './types/FVector2' +export * from './types/FVector3' +export * from './types/FVector4' diff --git a/packages/2d/src/types/FVector2.ts b/packages/core/src/types/FVector2.ts similarity index 100% rename from packages/2d/src/types/FVector2.ts rename to packages/core/src/types/FVector2.ts diff --git a/packages/3d/src/types/FVector3.ts b/packages/core/src/types/FVector3.ts similarity index 100% rename from packages/3d/src/types/FVector3.ts rename to packages/core/src/types/FVector3.ts diff --git a/packages/core/src/types/FVector4.ts b/packages/core/src/types/FVector4.ts new file mode 100644 index 00000000..87b11aff --- /dev/null +++ b/packages/core/src/types/FVector4.ts @@ -0,0 +1,21 @@ +/** + * A 4d vector with x, y, z and w coordinates. + */ +export interface FVector4 { + /** + * The x coordinate of the vector. + */ + x: number + /** + * The y coordinate of the vector. + */ + y: number + /** + * The z coordinate of the vector. + */ + z: number + /** + * The w coordinate of the vector. + */ + w: number +} diff --git a/packages/util/build.config.ts b/packages/util/build.config.ts new file mode 100644 index 00000000..d8b3dd37 --- /dev/null +++ b/packages/util/build.config.ts @@ -0,0 +1,17 @@ +import { defineBuildConfig } from 'unbuild' + +export default defineBuildConfig({ + entries: [ + 'src/index', + ], + declaration: true, + clean: true, + rollup: { + emitCJS: true, + }, + externals: [ + '@dimforge/rapier3d', + '@dimforge/rapier2d', + ], + failOnWarn: false, +}) diff --git a/packages/util/package.json b/packages/util/package.json new file mode 100644 index 00000000..8a1a2ebd --- /dev/null +++ b/packages/util/package.json @@ -0,0 +1,51 @@ +{ + "name": "@fibbojs/util", + "type": "module", + "version": "0.0.13", + "description": "Util package for Fibbo", + "author": "Augustin Mercier ", + "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, + "homepage": "https://fibbo.dev", + "repository": { + "type": "git", + "url": "git+https://github.com/fibbojs/fibbo.git" + }, + "bugs": "https://github.com/fibbojs/fibbo/issues", + "keywords": [], + "sideEffects": false, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + } + }, + "main": "./dist/index.mjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "./dist/*", + "./dist/index.d.ts" + ] + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "unbuild", + "lint": "eslint .", + "test": "vitest --config ../../vitest.config.ts --workspace ../../vitest.workspace.ts", + "test:ui": "vitest --ui --config ../../vitest.config.ts --workspace ../../vitest.workspace.ts", + "test:run": "vitest run --config ../../vitest.config.ts --workspace ../../vitest.workspace.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@fibbojs/core": "^0.0.13" + } +} diff --git a/packages/util/src/FAssetUtil.ts b/packages/util/src/FAssetUtil.ts new file mode 100644 index 00000000..f1323176 --- /dev/null +++ b/packages/util/src/FAssetUtil.ts @@ -0,0 +1,36 @@ +/** + * A class that provides asset management utilities. + * @category Core + */ +export class FAssetUtil { + // Config + /** + * The path to the assets directory. + * @default 'assets' + */ + static __ASSETS_PATH__ = 'assets' + + /** + * Smartly interpret a path to an asset. + * - URL paths are returned as is. + * - Absolute paths are interpreted as relative to the origin. + * - Relative paths are interpreted as relative to the assets folder. + * This method uses the current window location to determine the origin, so it should only be used in a browser environment. + * @param path The path to interpret. + * @returns The interpreted path. + */ + static interpretPath(path: string) { + // Resource URL (if it starts with http, treat as a URL) + if (path.startsWith('http')) { + return path + } + // Absolute path (if it starts with /), add the current origin + path + else if (path.startsWith('/')) { + return `${window.location.href}${path}` + } + // Otherwise, treat as a relative path starting to the assets folder + else { + return `${window.location.href}/${FAssetUtil.__ASSETS_PATH__}/${path}` + } + } +} diff --git a/packages/util/src/FMathUtil.ts b/packages/util/src/FMathUtil.ts new file mode 100644 index 00000000..3cefd288 --- /dev/null +++ b/packages/util/src/FMathUtil.ts @@ -0,0 +1,38 @@ +import type { FVector3, FVector4 } from '@fibbojs/core' + +/** + * A class that provides math utilities. + * @category Core + */ +export class FMathUtil { + /** + * Convert a radian angle to a euler angle. + * @param radian - The radian angle to convert. + * @returns The euler angle. + */ + static radToDegree(radian: number): number { + return radian * (180 / Math.PI) + } + + /** + * Convert an euler angle to a radian angle. + * @param degree - The euler angle to convert. + * @returns The radian angle. + */ + static degreeToRad(degree: number): number { + return degree * (Math.PI / 180) + } + + /** + * Convert a value from quaternion to a radian angle. + * @param quaternion - The quaternion value to convert. + * @returns The radian angle. + */ + static quaternionToRad(quaternion: FVector4): FVector3 { + return { + x: Math.atan2(2 * (quaternion.w * quaternion.x + quaternion.y * quaternion.z), 1 - 2 * (quaternion.x ** 2 + quaternion.y ** 2)), + y: Math.asin(2 * (quaternion.w * quaternion.y - quaternion.z * quaternion.x)), + z: Math.atan2(2 * (quaternion.w * quaternion.z + quaternion.x * quaternion.y), 1 - 2 * (quaternion.y ** 2 + quaternion.z ** 2)), + } + } +} diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts new file mode 100644 index 00000000..7fd2c2b4 --- /dev/null +++ b/packages/util/src/index.ts @@ -0,0 +1,5 @@ +/** + * Export Core utilities. + */ +export * from './FAssetUtil' +export * from './FMathUtil' diff --git a/packages/util/test/browser/asset.test.ts b/packages/util/test/browser/asset.test.ts new file mode 100644 index 00000000..2afa5c84 --- /dev/null +++ b/packages/util/test/browser/asset.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, it } from 'vitest' +import { FAssetUtil } from '../../src' + +describe('@fibbojs/util/FAssetUtil should', () => { + it('interprete a given path', () => { + expect(FAssetUtil.interpretPath('http://localhost:5173/custom/my-asset.png')).toEqual('http://localhost:5173/custom/my-asset.png') + // for href based tests, the url isn't predictable as vitest will create a random id for the test, so we use regex to match the url + expect(FAssetUtil.interpretPath('/my-asset.png')).toMatch(/http:\/\/localhost:5173\/.*\/my-asset.png/) + expect(FAssetUtil.interpretPath('my-asset.png')).toMatch(/http:\/\/localhost:5173\/.*\/assets\/my-asset.png/) + }) +}) diff --git a/packages/util/test/unit/math.test.ts b/packages/util/test/unit/math.test.ts new file mode 100644 index 00000000..000d98ff --- /dev/null +++ b/packages/util/test/unit/math.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from 'vitest' +import { FMathUtil } from '../../src' + +describe('@fibbojs/util/FMathUtil should', () => { + it('convert radian to degree', () => { + expect(FMathUtil.radToDegree(Math.PI)).toEqual(180) + }) + + it('convert degree to radian', () => { + expect(FMathUtil.degreeToRad(180)).toEqual(Math.PI) + }) + + it('convert quaternion to radian', () => { + expect(FMathUtil.quaternionToRad({ x: 0, y: 0, z: 0, w: 1 })).toEqual({ x: 0, y: 0, z: 0 }) + const euler1 = FMathUtil.quaternionToRad({ x: Math.sqrt(2) / 2, y: 0, z: 0, w: Math.sqrt(2) / 2 }) + const euler1expect = { x: Math.PI / 2, y: 0, z: 0 } + expect(euler1.x).closeTo(euler1expect.x, 0.0001) + expect(euler1.y).closeTo(euler1expect.y, 0.0001) + expect(euler1.z).closeTo(euler1expect.z, 0.0001) + const euler2 = FMathUtil.quaternionToRad({ x: 0, y: Math.sqrt(2) / 2, z: 0, w: Math.sqrt(2) / 2 }) + const euler2expect = { x: Math.PI, y: Number.NaN, z: Math.PI } + expect(euler2.x).closeTo(euler2expect.x, 0.0001) + expect(euler2.y).toBeNaN() + expect(euler2.z).closeTo(euler2expect.z, 0.0001) + const euler3 = FMathUtil.quaternionToRad({ x: 0, y: 0, z: Math.sqrt(2) / 2, w: Math.sqrt(2) / 2 }) + const euler3expect = { x: 0, y: 0, z: Math.PI / 2 } + expect(euler3.x).closeTo(euler3expect.x, 0.0001) + expect(euler3.y).closeTo(euler3expect.y, 0.0001) + expect(euler3.z).closeTo(euler3expect.z, 0.0001) + }) +}) diff --git a/packages/util/tsconfig.json b/packages/util/tsconfig.json new file mode 100644 index 00000000..4082f16a --- /dev/null +++ b/packages/util/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.json" +}