@series-inc/rundot-3d-engine 0.5.20 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -299,24 +299,34 @@ declare class SphereColliderComponent extends Component {
299
299
  type MeshColliderType = "bounding_box" | "convex_hull";
300
300
  interface MeshColliderJSON extends ComponentJSON {
301
301
  type: "mesh_collider";
302
- colliderType: MeshColliderType;
302
+ colliderType?: MeshColliderType;
303
303
  bodyType?: "static" | "kinematic" | "dynamic";
304
304
  isSensor?: boolean;
305
305
  enableCollisionEvents?: boolean;
306
+ excludeChildren?: boolean;
307
+ /** nodeOverrides wraps properties inside a `data` object */
308
+ data?: {
309
+ colliderType?: MeshColliderType;
310
+ bodyType?: "static" | "kinematic" | "dynamic";
311
+ isSensor?: boolean;
312
+ enableCollisionEvents?: boolean;
313
+ excludeChildren?: boolean;
314
+ };
306
315
  }
307
316
  declare class MeshColliderComponent extends Component {
308
- static fromPrefabJSON(json: MeshColliderJSON, node: PrefabNode): MeshColliderComponent | null;
317
+ static fromPrefabJSON(json: MeshColliderJSON, node: PrefabNode | null): MeshColliderComponent | null;
309
318
  private rigidBody;
310
319
  private readonly meshName;
311
320
  private readonly colliderType;
312
321
  private readonly bodyType;
313
322
  private readonly isSensor?;
314
323
  private readonly enableCollisionEvents?;
315
- constructor(meshName: string, colliderType?: MeshColliderType, bodyType?: RigidBodyType, isSensor?: boolean, enableCollisionEvents?: boolean);
324
+ private readonly excludeChildren;
325
+ constructor(meshName: string | null, colliderType?: MeshColliderType, bodyType?: RigidBodyType, isSensor?: boolean, enableCollisionEvents?: boolean, excludeChildren?: boolean);
326
+ /** Iterate meshes, optionally only direct children */
327
+ private static forEachMesh;
316
328
  /**
317
- * Collect all vertex positions from a mesh group, including the root's own transform.
318
- * Matches the editor's getAllVerticesFromStowMesh which uses parentWorldMatrixInverse
319
- * (for a detached group, that's identity — so we just use child.matrixWorld directly).
329
+ * Collect all vertex positions from a mesh group.
320
330
  * Returns a flat Float32Array of [x,y,z, x,y,z, ...].
321
331
  */
322
332
  private static collectVertices;
@@ -328,6 +338,7 @@ declare class MeshColliderComponent extends Component {
328
338
  */
329
339
  private static computeBounds;
330
340
  protected onCreate(): void;
341
+ private createCollider;
331
342
  getRigidBody(): RigidBodyComponentThree | null;
332
343
  }
333
344
 
@@ -158,18 +158,25 @@ SphereColliderComponent = __decorateClass([
158
158
  import * as THREE3 from "three";
159
159
  var MeshColliderComponent = class extends Component {
160
160
  static fromPrefabJSON(json, node) {
161
- const colliderType = json.colliderType ?? "bounding_box";
161
+ const props = json.data ?? json;
162
+ const colliderType = props.colliderType ?? "bounding_box";
162
163
  if (colliderType !== "bounding_box" && colliderType !== "convex_hull") {
163
- console.warn(`Unknown mesh collider type: ${json.colliderType}`);
164
+ console.warn(`Unknown mesh collider type: ${props.colliderType}`);
164
165
  return null;
165
166
  }
167
+ const bodyType = props.bodyType ?? "static" /* STATIC */;
168
+ const isSensor = props.isSensor;
169
+ const enableCollisionEvents = props.enableCollisionEvents;
170
+ const excludeChildren = props.excludeChildren ?? false;
171
+ if (!node) {
172
+ return new MeshColliderComponent(null, colliderType, bodyType, isSensor, enableCollisionEvents, excludeChildren);
173
+ }
166
174
  const stowMeshComponent = node.components.find((c) => c.type === "stow_mesh");
167
175
  if (!stowMeshComponent) {
168
176
  console.warn("MeshColliderComponent requires a stow_mesh component on the same node");
169
177
  return null;
170
178
  }
171
- const bodyType = json.bodyType ?? "static" /* STATIC */;
172
- return new MeshColliderComponent(stowMeshComponent.mesh.assetId, colliderType, bodyType, json.isSensor, json.enableCollisionEvents);
179
+ return new MeshColliderComponent(stowMeshComponent.mesh.assetId, colliderType, bodyType, isSensor, enableCollisionEvents, excludeChildren);
173
180
  }
174
181
  rigidBody = null;
175
182
  meshName;
@@ -177,37 +184,48 @@ var MeshColliderComponent = class extends Component {
177
184
  bodyType;
178
185
  isSensor;
179
186
  enableCollisionEvents;
180
- constructor(meshName, colliderType = "bounding_box", bodyType = "static" /* STATIC */, isSensor, enableCollisionEvents) {
187
+ excludeChildren;
188
+ constructor(meshName, colliderType = "bounding_box", bodyType = "static" /* STATIC */, isSensor, enableCollisionEvents, excludeChildren = false) {
181
189
  super();
182
190
  this.meshName = meshName;
183
191
  this.colliderType = colliderType;
184
192
  this.bodyType = bodyType;
185
193
  this.isSensor = isSensor;
186
194
  this.enableCollisionEvents = enableCollisionEvents;
195
+ this.excludeChildren = excludeChildren;
196
+ }
197
+ /** Iterate meshes, optionally only direct children */
198
+ static forEachMesh(root, excludeChildren, fn) {
199
+ if (excludeChildren) {
200
+ for (const child of root.children) {
201
+ if (child.isMesh) fn(child);
202
+ }
203
+ } else {
204
+ root.traverse((child) => {
205
+ if (child.isMesh) fn(child);
206
+ });
207
+ }
187
208
  }
188
209
  /**
189
- * Collect all vertex positions from a mesh group, including the root's own transform.
190
- * Matches the editor's getAllVerticesFromStowMesh which uses parentWorldMatrixInverse
191
- * (for a detached group, that's identity — so we just use child.matrixWorld directly).
210
+ * Collect all vertex positions from a mesh group.
192
211
  * Returns a flat Float32Array of [x,y,z, x,y,z, ...].
193
212
  */
194
- static collectVertices(meshGroup, scale) {
213
+ static collectVertices(meshGroup, scale, excludeChildren = false) {
195
214
  meshGroup.updateMatrixWorld(true);
196
215
  const allVertices = [];
197
216
  const vertex = new THREE3.Vector3();
198
- meshGroup.traverse((child) => {
199
- if (child instanceof THREE3.Mesh && child.geometry) {
200
- const posAttr = child.geometry.getAttribute("position");
201
- if (!posAttr) return;
202
- for (let i = 0; i < posAttr.count; i++) {
203
- vertex.fromBufferAttribute(posAttr, i);
204
- vertex.applyMatrix4(child.matrixWorld);
205
- allVertices.push(
206
- vertex.x * scale.x,
207
- vertex.y * scale.y,
208
- vertex.z * scale.z
209
- );
210
- }
217
+ MeshColliderComponent.forEachMesh(meshGroup, excludeChildren, (mesh) => {
218
+ if (!mesh.geometry) return;
219
+ const posAttr = mesh.geometry.getAttribute("position");
220
+ if (!posAttr) return;
221
+ for (let i = 0; i < posAttr.count; i++) {
222
+ vertex.fromBufferAttribute(posAttr, i);
223
+ vertex.applyMatrix4(mesh.matrixWorld);
224
+ allVertices.push(
225
+ vertex.x * scale.x,
226
+ vertex.y * scale.y,
227
+ vertex.z * scale.z
228
+ );
211
229
  }
212
230
  });
213
231
  return new Float32Array(allVertices);
@@ -218,21 +236,20 @@ var MeshColliderComponent = class extends Component {
218
236
  * detached cached mesh group is equivalent to identity. So we use child.matrixWorld
219
237
  * directly, which includes the mesh group root's own transform — exactly as the editor does.
220
238
  */
221
- static computeBounds(meshGroup, scale) {
239
+ static computeBounds(meshGroup, scale, excludeChildren = false) {
222
240
  meshGroup.updateMatrixWorld(true);
223
241
  const box = new THREE3.Box3();
224
242
  let foundMesh = false;
225
- meshGroup.traverse((child) => {
226
- if (child instanceof THREE3.Mesh && child.geometry) {
227
- foundMesh = true;
228
- if (!child.geometry.boundingBox) {
229
- child.geometry.computeBoundingBox();
230
- }
231
- if (child.geometry.boundingBox) {
232
- const tempBox = child.geometry.boundingBox.clone();
233
- tempBox.applyMatrix4(child.matrixWorld);
234
- box.union(tempBox);
235
- }
243
+ MeshColliderComponent.forEachMesh(meshGroup, excludeChildren, (mesh) => {
244
+ if (!mesh.geometry) return;
245
+ foundMesh = true;
246
+ if (!mesh.geometry.boundingBox) {
247
+ mesh.geometry.computeBoundingBox();
248
+ }
249
+ if (mesh.geometry.boundingBox) {
250
+ const tempBox = mesh.geometry.boundingBox.clone();
251
+ tempBox.applyMatrix4(mesh.matrixWorld);
252
+ box.union(tempBox);
236
253
  }
237
254
  });
238
255
  if (!foundMesh || box.isEmpty()) return null;
@@ -245,40 +262,47 @@ var MeshColliderComponent = class extends Component {
245
262
  return { size, center };
246
263
  }
247
264
  onCreate() {
248
- const stowkit = StowKitSystem.getInstance();
249
- stowkit.getMesh(this.meshName).then((meshGroup) => {
250
- if (!this.isAttached()) return;
251
- const scale = this.gameObject.scale.clone();
252
- if (this.colliderType === "convex_hull") {
253
- const vertices = MeshColliderComponent.collectVertices(meshGroup, scale);
254
- if (vertices.length < 9) {
255
- console.warn("MeshColliderComponent: Not enough vertices for convex hull");
256
- return;
257
- }
265
+ if (this.meshName) {
266
+ const stowkit = StowKitSystem.getInstance();
267
+ stowkit.getMesh(this.meshName).then((meshGroup) => {
268
+ if (!this.isAttached()) return;
269
+ this.createCollider(meshGroup);
270
+ });
271
+ } else {
272
+ this.createCollider(this.gameObject);
273
+ }
274
+ }
275
+ createCollider(meshRoot) {
276
+ const scale = this.gameObject.scale.clone();
277
+ if (this.colliderType === "convex_hull") {
278
+ const vertices = MeshColliderComponent.collectVertices(meshRoot, scale, this.excludeChildren);
279
+ if (vertices.length < 9) {
280
+ console.warn("MeshColliderComponent: Not enough vertices for convex hull");
281
+ return;
282
+ }
283
+ this.rigidBody = new RigidBodyComponentThree({
284
+ type: this.bodyType,
285
+ shape: "convex_hull" /* CONVEX_HULL */,
286
+ vertices,
287
+ centerOffset: new THREE3.Vector3(0, 0, 0),
288
+ isSensor: this.isSensor,
289
+ enableCollisionEvents: this.enableCollisionEvents
290
+ });
291
+ this.gameObject.addComponent(this.rigidBody);
292
+ } else {
293
+ const bounds = MeshColliderComponent.computeBounds(meshRoot, scale, this.excludeChildren);
294
+ if (bounds) {
258
295
  this.rigidBody = new RigidBodyComponentThree({
259
296
  type: this.bodyType,
260
- shape: "convex_hull" /* CONVEX_HULL */,
261
- vertices,
262
- centerOffset: new THREE3.Vector3(0, 0, 0),
297
+ shape: "box" /* BOX */,
298
+ size: bounds.size,
299
+ centerOffset: bounds.center,
263
300
  isSensor: this.isSensor,
264
301
  enableCollisionEvents: this.enableCollisionEvents
265
302
  });
266
303
  this.gameObject.addComponent(this.rigidBody);
267
- } else {
268
- const bounds = MeshColliderComponent.computeBounds(meshGroup, scale);
269
- if (bounds) {
270
- this.rigidBody = new RigidBodyComponentThree({
271
- type: this.bodyType,
272
- shape: "box" /* BOX */,
273
- size: bounds.size,
274
- centerOffset: bounds.center,
275
- isSensor: this.isSensor,
276
- enableCollisionEvents: this.enableCollisionEvents
277
- });
278
- this.gameObject.addComponent(this.rigidBody);
279
- }
280
304
  }
281
- });
305
+ }
282
306
  }
283
307
  getRigidBody() {
284
308
  return this.rigidBody;