mage-engine 3.23.36 → 3.23.37

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.
Files changed (2) hide show
  1. package/dist/mage.js +195 -50
  2. package/package.json +1 -1
package/dist/mage.js CHANGED
@@ -56083,6 +56083,11 @@ const extractBoundingSphere = body => {
56083
56083
  return body.geometry.boundingSphere;
56084
56084
  };
56085
56085
  const extractBiggestBoundingSphere = body => {
56086
+ if (!body || typeof body.traverse !== 'function') {
56087
+ console.warn('[Mage] extractBiggestBoundingSphere received invalid body');
56088
+ return null;
56089
+ }
56090
+
56086
56091
  const spheres = [];
56087
56092
  body.traverse(child => {
56088
56093
  if (child.geometry) {
@@ -58130,7 +58135,7 @@ function applyMiddleware() {
58130
58135
 
58131
58136
  var thunk = createThunkMiddleware();
58132
58137
  thunk.withExtraArgument = createThunkMiddleware;var name = "mage-engine";
58133
- var version$1 = "3.23.36";
58138
+ var version$1 = "3.23.37";
58134
58139
  var description = "A WebGL Javascript Game Engine, built on top of THREE.js and many other libraries.";
58135
58140
  var main = "dist/mage.js";
58136
58141
  var author$1 = {
@@ -60610,6 +60615,11 @@ const disposeGeometry = mesh => {
60610
60615
  }
60611
60616
  };
60612
60617
  const prepareModel = model => {
60618
+ if (!model || typeof model.traverse !== 'function') {
60619
+ console.warn('[Mage] prepareModel received invalid model object:', model);
60620
+ return null; // Return null for invalid models
60621
+ }
60622
+
60613
60623
  setUpLightsAndShadows(model);
60614
60624
  model.traverse(mesh => {
60615
60625
  setUpLightsAndShadows(mesh);
@@ -62725,7 +62735,13 @@ let Element$1 = /*#__PURE__*/function (_Entity) {
62725
62735
 
62726
62736
  texture.wrapS = textureOptions.wrap;
62727
62737
  texture.wrapT = textureOptions.wrap;
62728
- texture.repeat.set(textureOptions.repeat.x, textureOptions.repeat.y);
62738
+ texture.repeat.set(textureOptions.repeat.x, textureOptions.repeat.y); // Set sRGB encoding for color textures (map, emissiveMap, specularMap)
62739
+ // This is required for textures to display with correct colors
62740
+
62741
+ if (textureType === TEXTURES.MAP || textureType === TEXTURES.EMISSIVE || textureType === TEXTURES.SPECULAR) {
62742
+ texture.encoding = sRGBEncoding;
62743
+ }
62744
+
62729
62745
  material[textureType] = texture;
62730
62746
  material.needsUpdate = true;
62731
62747
  };
@@ -80631,10 +80647,16 @@ function parallelTraverse(a, b, callback) {
80631
80647
  };
80632
80648
  const FULL_STOP = ".";
80633
80649
 
80634
- const DEFAULTbuildObjectLoader = () => ({
80635
- tracer: new RequirementsTracer(),
80636
- loader: new ObjectLoader()
80637
- });
80650
+ const DEFAULTbuildObjectLoader = () => {
80651
+ const loader = new ObjectLoader(); // Add setOptions for compatibility with the loader interface
80652
+
80653
+ loader.setOptions = () => {};
80654
+
80655
+ return {
80656
+ tracer: new RequirementsTracer(),
80657
+ loader
80658
+ };
80659
+ };
80638
80660
 
80639
80661
  const loaders = {
80640
80662
  [EXTENSIONS.JSON]: DEFAULTbuildObjectLoader,
@@ -80733,11 +80755,22 @@ const getLoaderFromExtension = (extension, options) => {
80733
80755
  };
80734
80756
  };
80735
80757
 
80736
- const glbParser = _ref => {
80737
- let {
80758
+ const glbParser = gltf => {
80759
+ // GLTF/GLB loader returns { scene, animations, ... }
80760
+ if (!gltf || !gltf.scene) {
80761
+ var _gltf$constructor;
80762
+
80763
+ console.error('[Mage] GLB parser received invalid GLTF object:', {
80764
+ type: gltf === null || gltf === void 0 ? void 0 : (_gltf$constructor = gltf.constructor) === null || _gltf$constructor === void 0 ? void 0 : _gltf$constructor.name,
80765
+ keys: gltf ? Object.keys(gltf) : []
80766
+ });
80767
+ return null;
80768
+ }
80769
+
80770
+ const {
80738
80771
  scene,
80739
80772
  animations
80740
- } = _ref;
80773
+ } = gltf;
80741
80774
  scene.traverse(object => {
80742
80775
  if (object.isMesh) {
80743
80776
  object.castShadow = true;
@@ -80749,28 +80782,60 @@ const glbParser = _ref => {
80749
80782
  };
80750
80783
  };
80751
80784
 
80752
- const gltfParser = _ref2 => {
80753
- let {
80754
- scene,
80755
- animations
80756
- } = _ref2;
80785
+ const gltfParser = gltf => {
80786
+ // GLTF loader returns { scene, animations, ... }
80787
+ if (!gltf || !gltf.scene) {
80788
+ var _gltf$constructor2;
80789
+
80790
+ console.error('[Mage] GLTF parser received invalid GLTF object:', {
80791
+ type: gltf === null || gltf === void 0 ? void 0 : (_gltf$constructor2 = gltf.constructor) === null || _gltf$constructor2 === void 0 ? void 0 : _gltf$constructor2.name,
80792
+ keys: gltf ? Object.keys(gltf) : []
80793
+ });
80794
+ return null;
80795
+ }
80796
+
80757
80797
  return {
80758
- scene,
80759
- animations
80798
+ scene: gltf.scene,
80799
+ animations: gltf.animations
80760
80800
  };
80761
80801
  };
80762
80802
 
80763
- const defaultParser = scene => ({
80764
- scene
80765
- });
80803
+ const defaultParser = scene => {
80804
+ // Validate the scene is a proper THREE.js object
80805
+ if (!scene || typeof scene.traverse !== 'function') {
80806
+ var _scene$constructor;
80766
80807
 
80767
- const colladaParser = _ref3 => {
80768
- let {
80808
+ console.error('[Mage] Default parser received invalid scene object:', {
80809
+ type: scene === null || scene === void 0 ? void 0 : (_scene$constructor = scene.constructor) === null || _scene$constructor === void 0 ? void 0 : _scene$constructor.name,
80810
+ isObject3D: scene === null || scene === void 0 ? void 0 : scene.isObject3D,
80811
+ keys: scene ? Object.keys(scene) : []
80812
+ });
80813
+ return null;
80814
+ }
80815
+
80816
+ return {
80817
+ scene
80818
+ };
80819
+ };
80820
+
80821
+ const colladaParser = collada => {
80822
+ // Collada loader returns { animations, scene, ... }
80823
+ if (!collada || !collada.scene) {
80824
+ var _collada$constructor;
80825
+
80826
+ console.error('[Mage] Collada parser received invalid object:', {
80827
+ type: collada === null || collada === void 0 ? void 0 : (_collada$constructor = collada.constructor) === null || _collada$constructor === void 0 ? void 0 : _collada$constructor.name,
80828
+ keys: collada ? Object.keys(collada) : []
80829
+ });
80830
+ return null;
80831
+ }
80832
+
80833
+ const {
80769
80834
  animations,
80770
80835
  scene,
80771
80836
  rawSceneData,
80772
80837
  buildVisualScene
80773
- } = _ref3;
80838
+ } = collada;
80774
80839
  scene.traverse(node => {
80775
80840
  if (node.isSkinnedMesh) {
80776
80841
  node.frustumCulled = false;
@@ -80785,6 +80850,18 @@ const colladaParser = _ref3 => {
80785
80850
  };
80786
80851
 
80787
80852
  const fbxParser = scene => {
80853
+ // Validate the FBX loader returned a proper THREE.js object
80854
+ if (!scene || typeof scene.traverse !== 'function') {
80855
+ var _scene$constructor2;
80856
+
80857
+ console.error('[Mage] FBX parser received invalid scene object:', {
80858
+ type: scene === null || scene === void 0 ? void 0 : (_scene$constructor2 = scene.constructor) === null || _scene$constructor2 === void 0 ? void 0 : _scene$constructor2.name,
80859
+ isObject3D: scene === null || scene === void 0 ? void 0 : scene.isObject3D,
80860
+ keys: scene ? Object.keys(scene) : []
80861
+ });
80862
+ return null;
80863
+ }
80864
+
80788
80865
  scene.traverse(node => {
80789
80866
  if (node.isSkinnedMesh) {
80790
80867
  processMaterial(node.material, material => material.skinning = true);
@@ -80846,40 +80923,64 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
80846
80923
  _defineProperty$1(_assertThisInitialized(_this), "create", function (name) {
80847
80924
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
80848
80925
  const builtAssetId = buildAssetId(name, _this.currentLevel);
80926
+ const modelData = _this.map[name] || _this.map[builtAssetId];
80927
+
80928
+ if (!modelData) {
80929
+ console.warn(`[Mage] Model "${name}" not found in map. Available: ${Object.keys(_this.map).join(', ')}`);
80930
+ return false;
80931
+ }
80932
+
80849
80933
  const {
80850
80934
  scene,
80851
80935
  animations,
80852
80936
  extension
80853
- } = _this.map[name] || _this.map[builtAssetId] || {};
80937
+ } = modelData; // Validate that scene is a valid THREE.js object with required methods
80854
80938
 
80855
- if (scene) {
80856
- const elementOptions = {
80857
- name,
80858
- builtAssetId,
80859
- ...options
80860
- };
80861
- let model = scene.clone();
80939
+ if (!scene || typeof scene.clone !== 'function' || typeof scene.traverse !== 'function') {
80940
+ console.warn(`[Mage] Model "${name}" has invalid scene object. Got:`, Object.keys(modelData));
80941
+ return false;
80942
+ }
80943
+
80944
+ const elementOptions = {
80945
+ name,
80946
+ builtAssetId,
80947
+ ...options
80948
+ };
80949
+ let model;
80950
+ const useSkeletonClone = extension !== EXTENSIONS.COLLADA && hasAnimations(animations);
80862
80951
 
80863
- if (extension !== EXTENSIONS.COLLADA && hasAnimations(animations)) {
80864
- // we have no idea how to clone collada for the time being
80952
+ try {
80953
+ if (useSkeletonClone) {
80865
80954
  model = SkeletonUtils.clone(scene);
80955
+ } else {
80956
+ model = scene.clone();
80866
80957
  }
80958
+ } catch (cloneError) {
80959
+ console.error(`[Mage] Error cloning model "${name}":`, cloneError);
80960
+ return false;
80961
+ } // Validate the cloned model
80867
80962
 
80868
- const element = new Element$1({
80869
- body: prepareModel(model),
80870
- ...elementOptions
80871
- });
80872
- element.setEntityType(ENTITY_TYPES.MODEL.TYPE);
80873
- element.setEntitySubtype(ENTITY_TYPES.MODEL.SUBTYPES.DEFAULT);
80874
80963
 
80875
- if (hasAnimations(animations)) {
80876
- element.addAnimationHandler(animations);
80877
- }
80964
+ const preparedBody = prepareModel(model);
80965
+
80966
+ if (!preparedBody) {
80967
+ console.warn(`[Mage] Model "${name}" failed to prepare after cloning`);
80968
+ return false;
80969
+ } // IMPORTANT: body must come AFTER elementOptions spread to ensure
80970
+ // our preparedBody is used, not any 'body' property from saved options
80971
+
80972
+
80973
+ const element = new Element$1({ ...elementOptions,
80974
+ body: preparedBody
80975
+ });
80976
+ element.setEntityType(ENTITY_TYPES.MODEL.TYPE);
80977
+ element.setEntitySubtype(ENTITY_TYPES.MODEL.SUBTYPES.DEFAULT);
80878
80978
 
80879
- return element;
80979
+ if (hasAnimations(animations)) {
80980
+ element.addAnimationHandler(animations);
80880
80981
  }
80881
80982
 
80882
- return false;
80983
+ return element;
80883
80984
  });
80884
80985
 
80885
80986
  _defineProperty$1(_assertThisInitialized(_this), "storeModel", (name, model, extension) => {
@@ -80910,8 +81011,23 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
80910
81011
  return Promise.resolve();
80911
81012
  }
80912
81013
 
80913
- const path = _this.models[name];
80914
- return _this.loadAssetByPath(path, name, options);
81014
+ const modelConfig = _this.models[name]; // Support both string paths and objects with path + dependencies
81015
+ // String format: "models/mymodel.fbx"
81016
+ // Object format: { path: "models/mymodel.fbx", dependencies: { texture: "textures/tex.png" } }
81017
+
81018
+ if (typeof modelConfig === "string") {
81019
+ return _this.loadAssetByPath(modelConfig, name, options);
81020
+ } else if (modelConfig && typeof modelConfig === "object") {
81021
+ const {
81022
+ path,
81023
+ dependencies = {}
81024
+ } = modelConfig;
81025
+ return _this.loadAssetByPath(path, name, { ...options,
81026
+ ...dependencies
81027
+ });
81028
+ }
81029
+
81030
+ return Promise.resolve();
80915
81031
  });
80916
81032
 
80917
81033
  _defineProperty$1(_assertThisInitialized(_this), "loadAssetByPath", function (path, name) {
@@ -80928,10 +81044,10 @@ let Models = /*#__PURE__*/function (_EventDispatcher) {
80928
81044
  tracer
80929
81045
  } = getLoaderFromExtension(extension, options);
80930
81046
  const parser = getModelParserFromExtension(extension);
80931
- tracer.addEventListener(REQUIREMENTS_EVENTS.MISSING, _ref4 => {
81047
+ tracer.addEventListener(REQUIREMENTS_EVENTS.MISSING, _ref => {
80932
81048
  let {
80933
81049
  requirements
80934
- } = _ref4;
81050
+ } = _ref;
80935
81051
 
80936
81052
  _this.dispatchEvent({
80937
81053
  type: `${REQUIREMENTS_EVENTS.MISSING}:${name}`,
@@ -93974,15 +94090,44 @@ let Sky = /*#__PURE__*/function (_Element) {
93974
94090
 
93975
94091
  for (const elementData of elements) {
93976
94092
  try {
93977
- if (elementData.entitySubType === ENTITY_TYPES.MODEL.TYPE) {
94093
+ // Check entityType for models (entitySubType would be MODEL.SUBTYPE.DEFAULT)
94094
+ if (elementData.entityType === ENTITY_TYPES.MODEL.TYPE) {
93978
94095
  const {
93979
- options: modelOptions
94096
+ options: modelOptions = {}
93980
94097
  } = elementData;
93981
94098
  const {
93982
94099
  name,
94100
+ assetPath,
94101
+ dependencies = {},
93983
94102
  ...rest
93984
94103
  } = modelOptions;
93985
- await Importer.completeElementCreation(Models$1.create(name, rest), elementData, options);
94104
+
94105
+ if (!name) {
94106
+ console.warn(`[Mage] Model element missing name in options:`, elementData);
94107
+ continue;
94108
+ } // Load the model first if it's not already loaded
94109
+ // This handles page refresh in the editor where models need to be reloaded
94110
+
94111
+
94112
+ if (assetPath) {
94113
+ const loadResult = await Models$1.loadAssetByPath(assetPath, name, dependencies);
94114
+
94115
+ if (!loadResult) {
94116
+ console.warn(`[Mage] Failed to load model "${name}" from ${assetPath}`);
94117
+ }
94118
+ }
94119
+
94120
+ const model = Models$1.create(name, {
94121
+ assetPath,
94122
+ dependencies,
94123
+ ...rest
94124
+ });
94125
+
94126
+ if (model) {
94127
+ await Importer.completeElementCreation(model, elementData, options);
94128
+ } else {
94129
+ console.warn(`[Mage] Could not create model "${name}" - check assetPath: ${assetPath}`);
94130
+ }
93986
94131
  } else {
93987
94132
  switch (elementData.entitySubType) {
93988
94133
  case ENTITY_TYPES.MESH.SUBTYPES.CUBE:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mage-engine",
3
- "version": "3.23.36",
3
+ "version": "3.23.37",
4
4
  "description": "A WebGL Javascript Game Engine, built on top of THREE.js and many other libraries.",
5
5
  "main": "dist/mage.js",
6
6
  "author": {