-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathTransform.ts
More file actions
167 lines (157 loc) · 5.29 KB
/
Copy pathTransform.ts
File metadata and controls
167 lines (157 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import { LastWriteWinElementSetComponentDefinition, IEngine } from '../../engine'
import { Entity } from '../../engine/entity'
import type { ISchema } from '../../schemas/ISchema'
import type { Vector3Type } from '../../schemas/custom/Vector3'
import { ByteBuffer } from '../../serialization/ByteBuffer'
// Use import * to safely handle circular dependency (tree.ts → components → Transform.ts → tree.ts).
// With import *, the namespace object's properties are resolved at access time (live bindings in ESM,
// getters via __importStar in CJS), so by the time methods are called all exports are available.
import * as treeHelpers from '../../runtime/helpers/tree'
/**
* @public
*/
export type TransformComponent = LastWriteWinElementSetComponentDefinition<TransformType>
/**
* @public
*/
export interface TransformComponentExtended extends TransformComponent {
create(entity: Entity, val?: TransformTypeWithOptionals): TransformType
createOrReplace(entity: Entity, val?: TransformTypeWithOptionals): TransformType
/**
* Transforms a direction vector from an entity's local coordinate space
* to world space, accounting for the full parent hierarchy.
*
* This applies only rotation (not translation or scale) — suitable for
* direction vectors like force/impulse directions.
*
* @param entity - The source entity whose local space defines the direction
* @param localDirection - Direction vector in the entity's local coordinates
* @returns The direction vector in world coordinates
*/
localToWorldDirection(entity: Entity, localDirection: Vector3Type): Vector3Type
}
/**
* @public
*/
export const COMPONENT_ID = 1
/**
* @public
*/
export type TransformType = {
position: { x: number; y: number; z: number }
rotation: { x: number; y: number; z: number; w: number }
scale: { x: number; y: number; z: number }
parent?: Entity
}
/** @public */
export const TRANSFORM_LENGTH = 44
/** @public */
export const TransformSchema: ISchema<TransformType> = {
serialize(value: TransformType, builder: ByteBuffer): void {
const ptr = builder.incrementWriteOffset(TRANSFORM_LENGTH)
builder.setFloat32(ptr, value.position.x)
builder.setFloat32(ptr + 4, value.position.y)
builder.setFloat32(ptr + 8, value.position.z)
builder.setFloat32(ptr + 12, value.rotation.x)
builder.setFloat32(ptr + 16, value.rotation.y)
builder.setFloat32(ptr + 20, value.rotation.z)
builder.setFloat32(ptr + 24, value.rotation.w)
builder.setFloat32(ptr + 28, value.scale.x)
builder.setFloat32(ptr + 32, value.scale.y)
builder.setFloat32(ptr + 36, value.scale.z)
builder.setUint32(ptr + 40, (value.parent as number) || 0)
},
deserialize(reader: ByteBuffer): TransformType {
const ptr = reader.incrementReadOffset(TRANSFORM_LENGTH)
return {
position: {
x: reader.getFloat32(ptr),
y: reader.getFloat32(ptr + 4),
z: reader.getFloat32(ptr + 8)
},
rotation: {
x: reader.getFloat32(ptr + 12),
y: reader.getFloat32(ptr + 16),
z: reader.getFloat32(ptr + 20),
w: reader.getFloat32(ptr + 24)
},
scale: {
x: reader.getFloat32(ptr + 28),
y: reader.getFloat32(ptr + 32),
z: reader.getFloat32(ptr + 36)
},
parent: reader.getUint32(ptr + 40) as Entity
}
},
create(): TransformType {
return {
position: { x: 0, y: 0, z: 0 },
scale: { x: 1, y: 1, z: 1 },
rotation: { x: 0, y: 0, z: 0, w: 1 },
parent: 0 as Entity
}
},
extend(value?: Partial<TransformType>) {
return {
position: { x: 0, y: 0, z: 0 },
scale: { x: 1, y: 1, z: 1 },
rotation: { x: 0, y: 0, z: 0, w: 1 },
parent: 0 as Entity,
...value
}
},
jsonSchema: {
type: 'object',
properties: {
position: {
type: 'object',
properties: {
x: { type: 'number' },
y: { type: 'number' },
z: { type: 'number' }
}
},
scale: {
type: 'object',
properties: {
x: { type: 'number' },
y: { type: 'number' },
z: { type: 'number' }
}
},
rotation: {
type: 'object',
properties: {
x: { type: 'number' },
y: { type: 'number' },
z: { type: 'number' },
w: { type: 'number' }
}
},
parent: { type: 'integer' }
},
serializationType: 'transform'
}
}
/**
* @public
*/
export type TransformTypeWithOptionals = Partial<TransformType>
export function defineTransformComponent(
engine: Pick<IEngine, 'defineComponentFromSchema'>
): TransformComponentExtended {
const transformDef = engine.defineComponentFromSchema('core::Transform', TransformSchema)
return {
...transformDef,
create(entity: Entity, val?: TransformTypeWithOptionals) {
return transformDef.create(entity, TransformSchema.extend!(val))
},
createOrReplace(entity: Entity, val?: TransformTypeWithOptionals) {
return transformDef.createOrReplace(entity, TransformSchema.extend!(val))
},
localToWorldDirection(entity: Entity, localDirection: Vector3Type): Vector3Type {
const worldRotation = treeHelpers.getWorldRotation(engine as treeHelpers.WorldTransformEngine, entity)
return treeHelpers.rotateVectorByQuaternion(localDirection, worldRotation)
}
}
}