Uncaught error: Couldn't find current application

I’m about halfway done completing ETA’s build mode functionality. However, before I can complete and refine it, I must first parse the buildMode.js script. For some reason, however, it refuses to do so. The parse button in the entity editor turns red when clicked, and in the bottom-left of the screen is a an error message: “Uncaught Error: Couldn’t find current application”

Here is the buildMode.js script in its entirety.

var BuildMode = pc.createScript('buildMode');

BuildMode.attributes.add('passiveAsset', {
    type:'asset',
    assetType:'texture'
});
BuildMode.attributes.add('activeAsset', {
    type:'asset',
    assetType:'texture'
});
BuildMode.attributes.add('passiveMaterial', {
    type            : 'asset',
    assetType       : 'material',
    description     : 'Defines the passive material of an unselected tile.',
    title           : "Passive Mat"
});
BuildMode.attributes.add('ghostMaterial', {
    type            : 'asset',
    assetType       : 'material',
    description     : 'Defines the material of build modes ghost tile.',
    title           : "Ghost Mat"
});
// defines whether the build mode is in use or not
BuildMode.attributes.add('buildActive', {
    type            : 'boolean',
    title           : "Builder Active",
    description     : 'Defines if the builder functionality is engaged or not (activated in app by pressing Build button)',
    default         : false
});

// the ghost tile that shows user where tile may be spawned
var ghostTile = new pc.Entity();
// the standard tile that is spawned by ghostTile
var passiveTile = new pc.Entity();

// initialize code called once per entity
BuildMode.prototype.initialize = function() {
    // mouse events
    this.entity.element.on('mouseenter', this.onEnter, this);
    this.entity.element.on('mousedown', this.onPress, this);
    this.entity.element.on('mouseleave', this.onLeave, this);
    
    // keyboard events
    // this.app.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);
    // this.app.keyboard.on(pc.EVENT_KEYUP, this.onKeyUp, this);
};

// code called when build button is pressed
BuildMode.prototype.onPress = function(event) {
    // toggles buildActive and Build_Button
    if(this.buildActive === false) {this.select();}
    else if (this.buildActive === true) {this.deSelect();}
};

// turns buildActive / Build_Button on
BuildMode.prototype.select = function() {
    this.buildActive = true;
    this.entity.element.textureAsset = this.activeAsset;
};
// turns buildActive / Build_Button off
BuildMode.prototype.deSelect = function() {
    this.buildActive = false;
    this.entity.element.textureAsset = this.passiveAsset;
    this.ghostTile.destroy(); // destroy ghostTile when button is de-selected
};

BuildMode.prototype.update = function(dt) {
    // engage builder mode
    if (this.buildActive === true) {
        // spawn ghost tile
        // 
        // spawn ghost tile and add it to the entity hierarchy 
        this.app.root.addChild(ghostTile); 

        // add components (box etc)
        ghostTile.addComponent("model", {type: 'box',});

        // set material, dimensions, and location
        ghostTile.model.material = this.ghostMaterial.resource;  ghostTile.setLocalScale(1, 0.01, 1);  ghostTile.setPosition(0, 0, 0);
                                
        // sets name for programming reference
        ghostToken.name = "Ghost_Token";
                                
        // move x-coord +1 if up arrow was pressed; vice versa for down arrow
        if (this.app.keyboard.wasPressed(pc.KEY_UP)) {
            ghostTile.translate(1, 0, 0);
        } 
        else if (this.app.keyboard.wasPressed(pc.KEY_DOWN)) {
            ghostTile.translate(-1, 0, 0);
        }
        // move z-coord +1 if right arrow was pressed; vice versa for left arrow
        else if (this.app.keyboard.wasPressed(pc.KEY_RIGHT)) {
            ghostTile.translate(0, 0, 1);
        }
        else if (this.app.keyboard.wasPressed(pc.KEY_LEFT)) {
            ghostTile.translate(0, 0, -1);
        }
        // move y-coord +1 if space bar was pressed; vice versa for ctrl btn
        else if (this.app.keyboard.wasPressed(pc.KEY_SPACE)) {
            ghostTile.translate(0, 1, 0);
        }
        else if (this.app.keyboard.wasPressed(pc.KEY_CONTROL)) {
            ghostTile.translate(0, -1, 0);
        }
        // rotate 90 degrees on x axis if left-click; vice versa for right-click
        else if (this.app.mouse.wasPressed(pc.MOUSEBUTTON_LEFT)) {
            ghostTile.rotateLocal(90, 0, 0);
        }
        else if (this.app.mouse.wasPressed(pc.MOUSEBUTTON_RIGHT)) {
            ghostTile.rotateLocal(0, 90, 0);
        }
        // place tile at ghost tile's position and rotation if enter is pressed
        else if (this.app.keyboard.wasPressed(pc.KEY_ENTER)) {
            passivePosition.set(ghostTile.getPosition());

            // spawn gold token and add it to the entity hierarchy 
            this.app.root.addChild(passiveTile);   // copy all these declarations outside switch statement to facilitate token moving

            // add components (cylinder etc)
            passiveTile.addComponent("model", {type: 'box',});
            passiveTile.addComponent("collision", {type: "box", halfExtents: (0.5, 0.01, 0.5)});
            passiveTile.addComponent("rigidbody", {type: "static", friction: 0.5, restitution: 0.5});

            // set material, dimensions, and location
            passiveTile.model.material = this.passiveMaterial.resource;  passiveTile.setLocalScale(1, 0.01, 1);  passiveTile.rigidbody.teleport(passivePosition);
                                
            // sets name for programming reference
            passiveTile.name = "Passive_Tile";
        }
    }
    // de-spawn ghostTile 
    else if (this.buildActive === false) {
        ghostTile.destroy();
    }
};


// swap method called for script hot-reloading
// inherit your script state here
// BuildMode.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// http://developer.playcanvas.com/en/user-manual/scripting/

Does anyone know what I’m doing wrong? I’m sure it’s something ridiculously simple, but I can’t figure it out.

Thank you, Yaustar. Not sure why it didn’t do that in the first place.

You have to add triple backticks (```) at the start and end of the code block :slight_smile:

1 Like

I’ll be sure to remember that.

Anyways, about the script parsing. How do? Restarting the editor didn’t help.

var BuildMode = pc.createScript('buildMode');

BuildMode.attributes.add('passiveAsset', {
    type:'asset',
    assetType:'texture'
});
BuildMode.attributes.add('activeAsset', {
    type:'asset',
    assetType:'texture'
});
BuildMode.attributes.add('passiveMaterial', {
    type            : 'asset',
    assetType       : 'material',
    description     : 'Defines the passive material of an unselected tile.',
    title           : "Passive Mat"
});
BuildMode.attributes.add('ghostMaterial', {
    type            : 'asset',
    assetType       : 'material',
    description     : 'Defines the material of build modes ghost tile.',
    title           : "Ghost Mat"
});
// defines whether the build mode is in use or not
BuildMode.attributes.add('buildActive', {
    type            : 'boolean',
    title           : "Builder Active",
    description     : 'Defines if the builder functionality is engaged or not (activated in app by pressing Build button)',
    default         : false
});

// the ghost tile that shows user where tile may be spawned
var ghostTile = new pc.Entity();
// the standard tile that is spawned by ghostTile
var passiveTile = new pc.Entity();

It’s the global variables that you have here (ghostTile and passiveTile). You can’t create a new pc.Entity() in global space.

1 Like

Could I do it in the initialization function?

Turns out I can. Thanks for the help!

Okay, I’ve been working on it some more, and this solution doesn’t work. Not only does it defy all logic (I was able to declare new entities in global space just fine here; lines 72-76), but placing the declaration doesn’t even work unless it goes into the update() function. And this is a problem because it creates a new entity every single frame. If you have a fast computer, you can see the result here (EXTRA WARNING: POSSIBLE PROCESSOR/MEMORY OVERLOAD).

I basically want this cyan “ghost” tile to move along the x-axis with up/down arrow, y-axis with right/left arrow, etc, and for a passive tile tile to be spawned whenever enter is pressed. What’s the best way to do this? Would it be best for me to make a new script, one that merely checks to see if the Builder button has been pressed or not before handling the ghost tile and regular tile spawning?

Project link
Script link

If you try parsing the script again, it will give the same error as above. It’s not the existent of global variables that is causing the issue, it’s the creation of pc.Entities. Chances are that you added those variables after the last time your have parsed the script. In a nutshell, the parser can’t handle the creation of runtime objects like pc.Entity.

What’s the reason for having them global rather than class/object scope?

Just my inexperience. I’ve created another script to handle the map editing functionality. I’ll end up calling it from the buildMode.js script. Does this look better?

// delete the ghost tile when builder button is de-selected
Builder.prototype.ghostDelete = function() {
    this.ghost.destroy();
};

As far as I can tell, this.ghost is undefined so this function will give you an error when it is called.

// code called on key down
Builder.prototype.onKeyDown = function(event) {
    if (event.key === pc.KEY_UP)            {this.ghost.translate(0.5, 0, 0);}
    else if (event.key === pc.KEY_DOWN)     {this.ghost.translate(-0.5, 0, 0);}
    else if (event.key === pc.KEY_RIGHT)    {this.ghost.translate(0, 0, 0.5);}
    else if (event.key === pc.KEY_LEFT)     {this.ghost.translate(0, 0, -0.5);}
    else if (event.key === pc.KEY_Q)        {this.ghost.translate(0, 0.5, 0);}
    else if (event.key === pc.KEY_E)        {this.ghost.translate(0, -0.5, 0);}
    else if (event.key === pc.KEY_DELETE)   {passiveDelete();}
    else if (event.key === pc.KEY_ENTER)    {passivePosition.set(this.ghost.getPosition());  passiveTile.rigidbody.teleport(passivePosition);}
};

Same here and passivePosition is probably undefined too.