Needle Engine

Changes between version 4.2.4 and 4.2.5
Files changed (9) hide show
  1. src/engine-components/api.ts +1 -1
  2. src/engine-components/Collider.ts +37 -30
  3. src/engine-components/codegen/components.ts +0 -1
  4. src/engine-components/ContactShadows.ts +4 -2
  5. src/engine-components/DropListener.ts +5 -5
  6. src/engine/engine_three_utils.ts +6 -1
  7. src/engine-components/ui/InputField.ts +7 -6
  8. src/engine-components/OrbitControls.ts +0 -1
  9. src/engine/codegen/register_types.ts +0 -2
src/engine-components/api.ts CHANGED
@@ -52,7 +52,7 @@
52
52
  import "./AnimationUtilsAutoplay.js"
53
53
 
54
54
  export { DragMode } from "./DragControls.js"
55
- export type { DropListenerNetworkEventArguments } from "./DropListener.js";
55
+ export type { DropListenerNetworkEventArguments, DropListenerOnDropArguments } from "./DropListener.js";
56
56
  export * from "./particlesystem/api.js"
57
57
 
58
58
  // for correct type resolution in JSDoc
src/engine-components/Collider.ts CHANGED
@@ -137,37 +137,9 @@
137
137
  export class BoxCollider extends Collider implements IBoxCollider {
138
138
 
139
139
  static add(obj: Mesh | Object3D, opts?: { rigidbody: boolean, debug?: boolean }) {
140
- const collider = new BoxCollider();
140
+ const collider = addComponent(obj, BoxCollider);
141
+ collider.autoFit();
141
142
 
142
- // we need to transform the object into identity
143
- // because the physics collider will correctly apple the object's transform again
144
- // if we don't do it here we will have the transform applied twice
145
- const originalPosition = obj.position.clone();
146
- const originalQuaternion = obj.quaternion.clone();
147
- const originalScale = obj.scale.clone();
148
- obj.position.set(0, 0, 0);
149
- obj.quaternion.set(0, 0, 0, 1);
150
- obj.scale.set(1, 1, 1);
151
- const bb = getBoundingBox([obj]);
152
- obj.position.copy(originalPosition);
153
- obj.quaternion.copy(originalQuaternion);
154
- obj.scale.copy(originalScale);
155
-
156
- if(opts?.debug) Gizmos.DrawWireBox3(bb, 0xffdd00, 20);
157
-
158
- // if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
159
- // const bb = obj.geometry.boundingBox!;
160
- collider.size = bb!.getSize(new Vector3()) || new Vector3(1, 1, 1);
161
- collider.center = bb!.getCenter(new Vector3()) || new Vector3(0, 0, 0);
162
- if (collider.size.length() <= 0) {
163
- collider.size.set(0.01, 0.01, 0.01);
164
- }
165
-
166
- // collider.center.sub(obj.position);
167
- // collider.size.applyQuaternion(obj.worldQuaternion);
168
-
169
- addComponent(obj, collider);
170
-
171
143
  if (opts?.rigidbody === true) {
172
144
  addComponent(obj, Rigidbody, { isKinematic: false });
173
145
  }
@@ -181,20 +153,55 @@
181
153
  @serializable(Vector3)
182
154
  center: Vector3 = new Vector3(0, 0, 0);
183
155
 
156
+ /** @internal */
184
157
  onEnable() {
185
158
  super.onEnable();
186
159
  this.context.physics.engine?.addBoxCollider(this, this.size);
187
160
  watchWrite(this.gameObject.scale, this.updateProperties);
188
161
  }
189
162
 
163
+ /** @internal */
190
164
  onDisable(): void {
191
165
  super.onDisable();
192
166
  unwatchWrite(this.gameObject.scale, this.updateProperties);
193
167
  }
194
168
 
169
+ /** @internal */
195
170
  onValidate(): void {
196
171
  this.updateProperties();
197
172
  }
173
+
174
+ autoFit(opts?: { debug?: boolean }) {
175
+ const obj = this.gameObject;
176
+
177
+ // we need to transform the object into identity
178
+ // because the physics collider will correctly apple the object's transform again
179
+ // if we don't do it here we will have the transform applied twice
180
+ const originalPosition = obj.position.clone();
181
+ const originalQuaternion = obj.quaternion.clone();
182
+ const originalScale = obj.scale.clone();
183
+ const originalParent = obj.parent;
184
+ obj.position.set(0, 0, 0);
185
+ obj.quaternion.set(0, 0, 0, 1);
186
+ obj.scale.set(1, 1, 1);
187
+ obj.parent = null;
188
+ obj.updateMatrix();
189
+ const bb = getBoundingBox([obj]);
190
+ obj.position.copy(originalPosition);
191
+ obj.quaternion.copy(originalQuaternion);
192
+ obj.scale.copy(originalScale);
193
+ obj.parent = originalParent;
194
+
195
+ if (opts?.debug === true) Gizmos.DrawWireBox3(bb, 0xffdd00, 20);
196
+
197
+ // if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
198
+ // const bb = obj.geometry.boundingBox!;
199
+ this.size = bb!.getSize(new Vector3()) || new Vector3(1, 1, 1);
200
+ this.center = bb!.getCenter(new Vector3()) || new Vector3(0, 0, 0);
201
+ if (this.size.length() <= 0) {
202
+ this.size.set(0.01, 0.01, 0.01);
203
+ }
204
+ }
198
205
  }
199
206
 
200
207
  /**
src/engine-components/codegen/components.ts CHANGED
@@ -34,7 +34,6 @@
34
34
  export { Deletable } from "../DeleteBox.js";
35
35
  export { DeviceFlag } from "../DeviceFlag.js";
36
36
  export { DragControls } from "../DragControls.js";
37
- export { DropListenerAddedEvent } from "../DropListener.js";
38
37
  export { DropListener } from "../DropListener.js";
39
38
  export { Duplicatable } from "../Duplicatable.js";
40
39
  export { CallInfo } from "../EventList.js";
src/engine-components/ContactShadows.ts CHANGED
@@ -371,9 +371,11 @@
371
371
  // Ignore objects that don't render color
372
372
  let hide = entry.material.colorWrite == false || mat.wireframe === true || getVisibleInCustomShadowRendering(entry.object) === false;
373
373
  // Ignore line materials (e.g. GridHelper)
374
- if (!hide && (entry.material as any).linewidth != undefined) {
374
+ if (!hide && (entry.material["isLineMaterial"]))
375
375
  hide = true;
376
- }
376
+ // Ignore point materials
377
+ if (!hide && (entry.material["isPointsMaterial"]))
378
+ hide = true;
377
379
  if (hide) {
378
380
  objects_hidden.push(entry.object);
379
381
  entry.object["needle:visible"] = entry.object.visible;
src/engine-components/DropListener.ts CHANGED
@@ -53,7 +53,7 @@
53
53
  contentMD5: string;
54
54
  }
55
55
 
56
- declare type AddedEventArguments = {
56
+ export declare type DropListenerOnDropArguments = {
57
57
  sender: DropListener,
58
58
  /** the root object added to the scene */
59
59
  object: Object3D,
@@ -64,7 +64,7 @@
64
64
  }
65
65
 
66
66
  /** Dispatched when an object is dropped/changed */
67
- export class DropListenerAddedEvent<T extends AddedEventArguments> extends CustomEvent<T> {
67
+ class DropListenerAddedEvent<T extends DropListenerOnDropArguments> extends CustomEvent<T> {
68
68
  constructor(detail: T) {
69
69
  super(DropListenerEvents.ObjectAdded, { detail });
70
70
  }
@@ -136,9 +136,9 @@
136
136
 
137
137
  /**
138
138
  * Invoked after a file has been **added** to the scene.
139
- * Arguments are {@link AddedEventArguments}
139
+ * Arguments are {@link DropListenerOnDropArguments}
140
140
  * @event object-added
141
- * @param {AddedEventArguments} evt
141
+ * @param {DropListenerOnDropArguments} evt
142
142
  * @example
143
143
  * ```typescript
144
144
  * dropListener.onDropped.addEventListener((evt) => {
@@ -146,7 +146,7 @@
146
146
  * });
147
147
  */
148
148
  @serializable(EventList)
149
- onDropped: EventList<AddedEventArguments> = new EventList();
149
+ onDropped: EventList<DropListenerOnDropArguments> = new EventList();
150
150
 
151
151
  /** @internal */
152
152
  onEnable(): void {
src/engine/engine_three_utils.ts CHANGED
@@ -554,7 +554,7 @@
554
554
  * @param layers The layers to include. Typically the main camera's layers.
555
555
  * @param result The result box to store the bounding box in. Returns a new box if not passed in.
556
556
  */
557
- export function getBoundingBox(objects: Object3D[], ignore: ((obj: Object3D) => void | boolean) | Array<Object3D | null | undefined> | undefined = undefined, layers: Layers | undefined | null = undefined, result: Box3 | undefined = undefined): Box3 {
557
+ export function getBoundingBox(objects: Object3D | Object3D[], ignore: ((obj: Object3D) => void | boolean) | Array<Object3D | null | undefined> | undefined = undefined, layers: Layers | undefined | null = undefined, result: Box3 | undefined = undefined): Box3 {
558
558
  const box = result || new Box3();
559
559
  box.makeEmpty();
560
560
 
@@ -607,6 +607,10 @@
607
607
  }
608
608
  }
609
609
  let hasAnyObject = false;
610
+
611
+ if (!Array.isArray(objects))
612
+ objects = [objects];
613
+
610
614
  for (const object of objects) {
611
615
  if (!object) continue;
612
616
  hasAnyObject = true;
@@ -764,6 +768,7 @@
764
768
  newMaterial.envMap = oldMaterial.envMap;
765
769
  newMaterial.alphaMap = oldMaterial.alphaMap;
766
770
  newMaterial.metalness = oldMaterial.reflectivity;
771
+ newMaterial.vertexColors = oldMaterial.vertexColors;
767
772
  if (oldMaterial.shininess) {
768
773
  // from blender source code
769
774
  // https://github.com/blender/blender-addons/blob/5e66092bcbe0df6855b3fa814b4826add8b01360/io_scene_fbx/import_fbx.py#L1442
src/engine-components/ui/InputField.ts CHANGED
@@ -238,14 +238,15 @@
238
238
 
239
239
  private setTextFromInputField() {
240
240
  if (this.textComponent && InputField.htmlField) {
241
- if (this.textComponent.text !== InputField.htmlField.value) {
242
- if (debug)
243
- console.log("VALUE CHANGED");
244
- const oldValue = this.textComponent.text;
245
- const newValue = InputField.htmlField.value;
241
+ const oldValue = this.textComponent.text;
242
+ const newValue = InputField.htmlField.value;
243
+ const changed = this.textComponent.text !== InputField.htmlField.value;
244
+ this.textComponent.text = InputField.htmlField.value;
245
+
246
+ if (changed) {
247
+ if (debug) console.log("[InputField] value changed:", newValue, oldValue);
246
248
  this.onValueChanged?.invoke(newValue, oldValue);
247
249
  }
248
- this.textComponent.text = InputField.htmlField.value;
249
250
  }
250
251
  }
251
252
 
src/engine-components/OrbitControls.ts CHANGED
@@ -941,7 +941,6 @@
941
941
  lookAt.y -= size.y * verticalOffset;
942
942
  this.setLookTargetPosition(lookAt, immediate);
943
943
  this.setFieldOfView(options.fov, immediate);
944
- this.autoTarget = false;
945
944
 
946
945
  if (cameraNearFar == undefined || cameraNearFar == "auto") {
947
946
  // Check if the scene has a GroundProjectedEnv and include the scale to the far plane so that it doesnt cut off
src/engine/codegen/register_types.ts CHANGED
@@ -36,7 +36,6 @@
36
36
  import { Deletable } from "../../engine-components/DeleteBox.js";
37
37
  import { DeviceFlag } from "../../engine-components/DeviceFlag.js";
38
38
  import { DragControls } from "../../engine-components/DragControls.js";
39
- import { DropListenerAddedEvent } from "../../engine-components/DropListener.js";
40
39
  import { DropListener } from "../../engine-components/DropListener.js";
41
40
  import { Duplicatable } from "../../engine-components/Duplicatable.js";
42
41
  import { CallInfo } from "../../engine-components/EventList.js";
@@ -256,7 +255,6 @@
256
255
  TypeStore.add("Deletable", Deletable);
257
256
  TypeStore.add("DeviceFlag", DeviceFlag);
258
257
  TypeStore.add("DragControls", DragControls);
259
- TypeStore.add("DropListenerAddedEvent", DropListenerAddedEvent);
260
258
  TypeStore.add("DropListener", DropListener);
261
259
  TypeStore.add("Duplicatable", Duplicatable);
262
260
  TypeStore.add("CallInfo", CallInfo);