2

I'm using babylonjs library and created a "Building" class with typescript. Using typescript for the whole thing BTW. I create this new "Building" from my main game.ts "Game" class and when trying to access a member of "Building" I get "undefined" variable errors. However this only happens within another class method but seems work correctly in the constructor. I'm assuming it has something to do with the "this" scoping in javascript/typescript. I have tried modifying the function by doing:

Create = ...(...)=> {
   ...

I have tried creating the variable via:

private rect: = () => Rectangle

but this still does not work

Is this really an issue with "this" scoping because nothing seems to be working. Below I marked exactly where this variable works and where this doesnt work.

class Building {

    private rect : Rectangle
    private buildingMesh:string[]
    private buildingId:string

    constructor(rect: Rectangle, id:string) {

      this.rect = rect
      console.log("TL in b const: " + this.rect.topLeft.x) // <--- This works here
      this.buildingId = id

    }

    Create(scene:BABYLON.Scene) {

      BABYLON.SceneLoader.ImportMesh(this.buildingId, "models/","tree.babylon", scene, function (newMeshes) {

          var idx = 0

          console.log("TL in b: " + this.rect.topLeft.x) // <--- this gives me undefined
          var wall =newMeshes[0].createInstance(this.buildingId + idx) 
          wall.position.x = this.rect.topLeft.x
          wall.position.y = this.rect.topLeft.y
          this.buildingMesh.push(this.buildingId + idx)
          idx++
      });
    }
}
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
efel
  • 1,054
  • 3
  • 14
  • 29

1 Answers1

3

I guess that you are almost there. Arrow function ( => ) syntax is what we need, but even on the BABYLON.SceneLoader.ImportMesh call:

BABYLON.SceneLoader
    .ImportMesh(this.buildingId, "models/","tree.babylon", scene, 
        function (newMeshes) {
         ...
         // here we do not have this kept by TS for us
});

we should use

BABYLON.SceneLoader
    .ImportMesh(this.buildingId, "models/","tree.babylon", scene, 
        (newMeshes) => {
         ...
         // here the magic would happen again
         // and compiler will keep this to be what we expect
});
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • I see.. so i guess when you create an anonymous function it does not know which "this" to use.. Document or Class? Am i on the right track here? Trying to explain this so if someone looked this up they would understand why it worked. Thanks for the help though, this worked. I will be marking it as fixed. – efel Sep 20 '15 at 04:51
  • 1
    @efel If you're creating a simple annonymous function, the context (`this` keyword) will be always the global scope (usually, in browsers, the global scope is the `window` object). When you use an arrow function, the context will be always the same context as you already are, so, if you're inside a method of a class, the context will be the object (instance of that class), and the arrow function's context will be the same. Before, when there was no arrow function, the workaround was to create a local variable to ~save~ the context, and then use it inside the annonymous function. – Buzinas Sep 20 '15 at 05:09
  • 1
    The way I would use to explain it is - TS compiler will create `var _this = this;` and later use it inside of generated arrow function `=>`. So, what was **this** outside is now this inside... read more about arrow functions... to make it really clear ;) – Radim Köhler Sep 20 '15 at 05:10