Importing obj file from 3DS Max to Phaser3 - phaser-framework

In my Phaser3 game, I am trying to import a 3D model from an .obj file to be the main character of my game.
My code is :
class Scene1 extends Phaser.Scene {
constructor() {
super("startScene");
}
preload() {
this.load.image("texture", "assets/images/<filename>.png");
this.load.obj({
key: "keymodel",
url: "assets/models/<filename>.obj",
matURL: "assets/models/<filename>.mtl",
});
}
create(){
const mesh = this.add.mesh(50,50,"texture");
mesh.addVerticesFromObj('keymodel', 0.1);
mesh.panZ(7);
mesh.modelRotation.y += 0.5;
this.debug = this.add.graphics();
mesh.setDebug();
console.log(mesh);
}
The game works fine when I use the base model offered in the tutorial (the skull from this tutorial https://phaser.io/examples/v3/view/game-objects/mesh/mesh-from-obj ) But When I try to import my model from 3DS max, errors start popping out.
In particular, I receive different errors depending on the model on the addVerticesFromObj function.
When I try to load the full model (composed of several objects), I receive the error:
Uncaught TypeError: Cannot read properties of undefined (reading 'u')
at t.exports (phaser.min.js:1:580548)
at initialize.addVerticesFromObj (phaser.min.js:1:298100)
at Scene1.create (Scene1.js:54:10)
at initialize.create (phaser.min.js:1:491015)
at initialize.loadComplete (phaser.min.js:1:490466)
at o.emit (phaser.min.js:1:7809)
at initialize.loadComplete (phaser.min.js:1:944358)
at initialize.fileProcessComplete (phaser.min.js:1:944058)
at initialize.onProcessComplete (phaser.min.js:1:21253)
at initialize.onProcess (phaser.min.js:1:303819)
When I try to load the model of a single object, I receive the error:
Uncaught TypeError: Cannot read properties of undefined (reading 'x')
at t.exports (phaser.min.js:1:580422)
at initialize.addVerticesFromObj (phaser.min.js:1:298100)
at Scene1.create (Scene1.js:54:10)
at initialize.create (phaser.min.js:1:491015)
at initialize.loadComplete (phaser.min.js:1:490466)
at o.emit (phaser.min.js:1:7809)
at initialize.loadComplete (phaser.min.js:1:944358)
at initialize.fileProcessComplete (phaser.min.js:1:944058)
at initialize.onProcessComplete (phaser.min.js:1:21253)
at initialize.onProcess (phaser.min.js:1:303819)
This happens only by changing the filename without modifying the rest of the code.
Could It be that there are special export parameters from 3DS max I need to set? Or is there another error in my code I cannot see?
Thank you all for your help!

Related

Difficulty Mapping FusionAuth Errors to TypeScript due to changing nested object names

I am trying to map FusionAuth errors into Typescript interfaces for improved error handling. But I am running into problems.
An example error returned is the following nested object:
{"statusCode":400,"exception":{"fieldErrors":{"email":[{"code":"[duplicate]email","message":"A User with email already exists."}]}}}
And another error returned by FusionAuth is the following:
{"statusCode":400,"exception":{"fieldErrors":{"password":[{"code":"[tooShort]password","message":"The [user.password] property is shorter than the minimum of [8] characters."}]}}}
As you can see, exception.fieldErrors.XYZ is a different object name for each error.
I want to try and abstract the exception.fieldErrors.XYZ error into typescript classes, and create a method that iterates over the exception.fieldErrors.XYZ object, and pushes them into an array. Below are some TypeScript classes at an attempt of solving this.
export class ClientResponseError {
statusCode: string;
exception: Exception;
}
export interface ExceptionName {
message: string;
}
export interface FieldErrors {
fieldError: ExceptionName[];
}
export interface Exception {
fieldErrors: FieldErrors;
}
and the following short snippet to test printing out the messages
error.exception.fieldErrors.fieldError.map(error => {
console.log(error.message)
})
The main error returned is the following
TypeError: Cannot read properties of undefined (reading 'map')
Any suggestions for dealing with this? The problem lies that exception.fieldErrors.XYZ is a different object name for each error, and I want to catch all errors. Thanks in advance

Unable to pull through API to react frontend with

I am struggling to pull through the api to the front end. I completed it successfully with
https://jsonplaceholder.typicode.com/ Just mapped out the arrays. i am struggling however to pull through this seperate api I wanted to use
https://gateway.marvel.com/v1/public/comics?apikey=xxxxxxxxxxxxxxxx&ts=redant&hash=140e85a50884cef76d614f6dacada288
the erro is..
"Uncaught TypeError: Cannot read properties of undefined (reading 'results')"
so clearly it isnt actually able to get hold of results
What am I doing wrong?
import React, {Component} from 'react';
import './App.css';
class App extends Component {
constructor() {
super();
this.state = {
list: []
};
}
componentDidMount() {
fetch('https://gateway.marvel.com/v1/public/comics?apikey=3cb62d086d5debdeea139095cbb07fe4&ts=redant&hash=140e85a50884cef76d614f6dacada288')
.then (response => response.json())
.then(users => this.setState({list:users}))
}
render() {
return (
<div className='App'>
{
this.state.list.data.results.map(result =>
<h1 key={result.id}>{result.urls}</h1>
)
}
</div>
)
}
}
export default App
The error Uncaught TypeError: Cannot read properties of undefined (reading 'results') in your code means that this.state.list.data returns as undefined. This means that you'll need to focus on your state property list to ensure that it has a data property. As we see in your constructor, data is initialized to an empty array which does not contain the data property.
Something we can do to prevent the error is to surround your code with an undefined check:
if (this.state.list.data != undefined) {
this.state.list.data.results.map(result =>
<h1 key={result.id}>{result.urls}</h1>
)
}
At this point, though, we don't know if your API call is returning good data or not since your program throws the error before that (since the fetch and setState are asynchronous), so the code above mainly addresses the error that you're getting rather than focusing on the "pull through the api to the front end" portion of your question.
Here's what you can do inside your then part after fetching the results
this.setState({list:users.data.results}
And inside the map function, do the following:
this.state.list.map(result =>
<h1 key={result.id}>{result.urls}</h1>
You are getting an error because List is initially empty it doesn't have any key called as results, once you fetch the result only then can you loop through your result.
Another solution would be to simply add a loader, you can control that via state as well.

Apply node module with object prototype methods

Good morning.
I'm trying to create a node module witch right now is published as redgem.
It consists of adding methods to base objects prototypes. For example:
const obj = { a: 'b', c: 'd' }
obj.map(do stuff)
However i haven't found a good way to apply these methods in a project. If i run the tests (they are inside the module) they all run smoothly since methods are added to base objects (arrays, strings and actual objects). But if i do the same thing in another project i get errors like Uncaught TypeError: Illegal invocation.
Could anyone please help me setup the package?
The way i'm trying to use redgem in projects right now is:
import redgem from 'redgem';
redgem():
Thanks.
So, basically this is how i export the module:
export default function apply () {
stringMethods.forEach((method) => {
String.prototype[method.name] = method.function
})
arrayMethods.forEach((method) => {
Array.prototype[method.name] = method.function
})
objectMethods.forEach((method) => {
Object.prototype[method.name] = method.function
})
}
Where every method is in the following form
{
// Tells wether the array is empty.
name: 'empty',
function: function () {
return this.length == 0
}
}

Firebase Cloud Function - Reference.update failed

I'm getting the following error when invoking a GCF:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
Done a bit of digging online but can't find the same issue. Without adding way too much info, I'm trying to add dish objects into a category object in Realtime Database. The odd thing is, the function works fine for the first 6 dishes, and when I try to add a 7th, this error pops up and the update method fails.
The full error log, with my unique property data is:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
'users.sIRf7m1uWfa9j0iF6UuuzvdD5TG2.dishcategories.default01.dishes.u3o1p278vriqo3odeslle.categories.0.dishes.irdrl2q7blsi1y7ih3jhh.categories.0.dishes.v8pl7r9llhfp7sqmz7uikk.categories.0.dishes.2ee3ajy6d5vymneewgflze.categories.0.dishes.btdib119nz5cnm6zk5uu4t.categories.0.dishes.4wyu5yqyn2z0bgvcejix9.categories.0.dishes.w1cfcpktym7nkp76p521n.categories.0.createdDate'
at ValidationPath.checkValid_ (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1035:19)
at ValidationPath.push (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1015:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1478:18
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
Here's the cloud function code from index.ts:
// Now we need to check if this dish's categories already exist as user categories.
// If they do, we can add this newly created dish into them.
// If they don't, we can create them with this newly added dish in them.
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish) // *** This is the update method producing the error in this case ***
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish)
}
})
Anyone know what this error means, and perhaps what I'm doing wrong here? Thanks!
The error message is quite explicit: you're trying to write data that is more than 32 levels deep, or which contains a cyclic object.
Given the code you shared, the latter seems most likely: you're looping over each category of a dish, and then write that dish to each category again. The simplest fix I can think of is to write the dish-without-categories to each category:
dish_without_categories = dish;
delete dish_without_categories.categories;
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
})

Haxe - Why can I not access a child's attribute without getting an error that the parent does not have the given attribute?

I've recently been getting into Haxe and just started to use HaxeFlixel to load a Tiled .TMX file.
I am creating a TiledMap object and passing it the TMX file path, then I want to iterate over the layers in that object to add them to the game scene. However when I try to access .tileArray (which is a property of TiledTileLayer) I get the following error :-
flixel.addons.editors.tiled.TiledLayer has no field tileArray
Here is the code:
package;
import flixel.FlxState;
import flixel.tile.FlxTilemap;
import flixel.addons.editors.tiled.TiledMap;
import openfl.Assets;
class PlayState extends FlxState
{
private var _tiled_map:TiledMap;
override public function create():Void
{
_tiled_map = new TiledMap("assets/data/Map1.tmx");
for(layer in _tiled_map.layers){
var layerData:Array<Int> = layer.tileArray;
}
super.create();
}
override public function update(elapsed:Float):Void
{
super.update(elapsed);
}
}
I've found the following example - http://coinflipstudios.com/devblog/?p=182 which seems to work fine for people.
So I wanted to check whether the layer object was a TiledTileLayer as it should be, or TiledLayer, with the following:
trace(Type.typeof(layer));
Which sure enough yields:
PlayState.hx:24: TClass([class TiledTileLayer])
So if it is a TiledTileLayer which has the field tileArray why is it moaning?
I had a look at the source code (https://github.com/HaxeFlixel/flixel-addons/blob/dev/flixel/addons/editors/tiled/TiledMap.hx#L135) and TiledTileLayer inherits from TiledLayer. Layers is an array of type TiledLayer, so I think this is why it is moaning. I can clearly see that the array is storing child objects of TiledLayer, but as soon as I access any props/methods of those children, it complains that the parent does not have that field? Very confusing!
To run I'm using this command: C:\HaxeToolkit\haxe\haxelib.exe run lime test flash -debug -Dfdb
Thank you!
So if it is a TiledTileLayer which has the field tileArray why is it moaning?
It may be a TiledTileLayer in this case, but that may not always be the case. layers is an Array<TileLayer> after all, so it could be a TiledObjectLayer or a TiledImageLayer as well (which don't have a tileArray field). This can nicely be seen in the code you linked. The concrete type can only be known at runtime, but the error you get happens at compile-time.
If you know for sure there won't be any object or image layers, you can just cast it to a TiledTileLayer. However, just to be safe, it's good practice to check the type beforehand anyway:
for (layer in _tiled_map.layers) {
if (Std.is(layer, TiledTileLayer)) {
var tileLayer:TiledTileLayer = cast layer;
var layerData:Array<Int> = tileLayer.tileArray;
}
}
It works without this for the tutorial you linked because it was made for an older version of flixel-addons.

Resources