[SOLVED] Running a function upon Tween complete

I’m using the Tween library to reposition a model in various locations. When I move the model, I want to rotate it around a different apparent pivot point. To do that, I use a parent entity to do the rotating. When I want to change the pivot location, I move the model relative to the parent and then move the parent by an exact offsetting amount. This occurs in one frame (dt) so that the model does not appear to move at all. It works nicely. But here’s the problem. I want to run this bit of code upon completion of a tween function. But when I move the code to a function called by the tween complete, I get the error:
Uncaught TypeError: Cannot read property ‘getPosition’ of undefined

I’ve figured out that at least one part of the problem is that when I use “this” inside the tween “complete” function that “this” now refers to the tween function and not the script that I’m working on.

My question is how do I properly reference these entities when calling them from the tween’s complete function?
Thanks for any insight that can be offered.

Btn_ERFSII_Vent.prototype.onPress = function (event) {
        event.element.materialAsset = this.originalMaterial; 
        this.buttonPressed = true;
        this.counter = 0;
        
	
        this.Btn_ERFSII_Vent.element.useInput = false;
        this.Btn_ERFSII_Hoses.element.useInput = false;  
        this.Btn_ERFSII_Restraint.element.useInput = false;
        this.Btn_ERFSII_Bladder.element.useInput = false; 
        this.Btn_ERFSII_Electrical.element.useInput = false;
        this.Btn_ERFSII_BkwyValves.element.useInput = false; 	
        this.Btn_ERFSII_CtlPanel.element.useInput = false; 		

        this.tweenSpinReset = this.tankPivotNULL.tween(this.tankPivotNULL.getLocalEulerAngles()).rotate({x: 0, y: 0, z: 0 }, 1, pc.SineInOut)
        .on('complete', function (){
            console.log('tween completed');
            console.log(this);
          
            //Code fails here
            pivotPos = this.tankPivotNULL.getPosition();
            targetPos = this.pivotTarget.getPosition();
            initPos = this.ERFS_Tank1.getPosition();

            shiftAmt = pivotPos.sub(targetPos);        
            this.tankPivotNULL.setPosition(targetPos);
            initPos = this.ERFS_Tank1.getPosition();

            this.ERFS_Tank1.setPosition(initPos.add(shiftAmt));
            });
        this.tweenSpinReset.start();
        this.tweenSpin = this.Tank1MasterNULL.tween(this.Tank1MasterNULL.getLocalEulerAngles()).rotate({x: -20, y: -0, z: -20}, 2.0, pc.SineInOut).delay(1);
        this.tweenSpin.start();
        this.tween = this.Tank1MasterNULL.tween(this.Tank1MasterNULL.getLocalPosition()).to({x: 6.026, y: 1.944, z: -5.665}, 2.0, pc.SineInOut).delay(1);
        this.tween.start();
        
        // Code works fine in this location        
        /*pivotPos = this.tankPivotNULL.getPosition();
        targetPos = this.pivotTarget.getPosition();
        initPos = this.ERFS_Tank1.getPosition();
        
        shiftAmt = pivotPos.sub(targetPos);        
        this.tankPivotNULL.setPosition(targetPos);
        initPos = this.ERFS_Tank1.getPosition();
        
        this.ERFS_Tank1.setPosition(initPos.add(shiftAmt));*/

};
  this.ERFS_Tank1.setPosition(initPos.add(shiftAmt)); 
});

One way would be to do this…

  this.ERFS_Tank1.setPosition(initPos.add(shiftAmt));
}, this);

OK. That pretty much nubbed up the problem perfectly. I think this really points out that I need to do some work to better understand “this” and its implications when coding … cuz this solution is not only so darned simple, but it is far from what I’d have imagined the solution to be.

If you are of a mind to provide some insight, it would be appreciated. As it is, thanks for the fix. Last night I figured out a workaround using with an update function to keep everything in sync, but it is much neater and clearer to have the code nested in the tween function.

Thanks again.

1 Like

This is a good explanation of the issue that you have: https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback

Great! I see that the discussion revolves around “callbacks” … something else I know that I need to understand better. I will read through that later tonight.

It is interesting to note that by adding that last training “,this” the meaning of “this” in my console log statement changed from “Tween” to “script” - referring to the current script I’m running.

Thanks!

FYI The tween problem that you had is the same thing as it’s calling a function when it finishes (ie a ‘callback’)

I kinda assumed that. But the term “callback” in this context is very non-intuitive for me. That short definition you gave makes sense though. More reading to do …

Thanks.

Sorry, which context? Maybe I can explain better?

The context of coding and the way I think. :grinning:

“Call back” suggests to me calling to some place I’ve been. That’s what “back” suggests to me. But there is no “back” in this context. This is a new (or different) place (function) where we are going. Just as you said in your description of a “function called at the end of a function”.

So it is just a matter of me more fully understanding the special meanings of the terms in the context of coding. Many of the terms being used are just not particularly intuitive to me. So it is hard to make reasonable guesses as I try to figure things out. Coding terms before object oriented languages seemed more obvious. I just need to spend more time reading references like the one you provided to cement these words better with these coding concepts.

I forgot to mention that I really do appreciate the offer. Thanks.

1 Like