Buttons navigation system?

Now there are no ready-made solutions or recommendations for implementing something like button navigation? This is relevant for TVs, as not all of them have the ability to use the cursor.

Am I right that it is necessary to write it myself or did I miss something somewhere? Maybe I’ll add my solution, which I roughly imagine, when I get to that point.

I am not entirely sure what you mean by “button navigation”, but if it is selecting a button by some input (e.g. up/down arrows on the remote controller), then you would probably have to write your own solution.

1 Like

My solution below. If juggle more ‘enable’ and ‘disable’ events, can make the code cleaner and get rid of update, but for my needs it is enough.

I tried to fake native selection by direct call this.entity.button._onMouseEnter(null);
Could there be any problems in this? Is there possibly a better option?

var ButtonsNavigationManager = pc.createScript('buttonsNavigationManager');

ButtonsNavigationManager.prototype.initialize = function() {
    ButtonsNavigationManager.instance = this;
    this.selectedBtn = null;
};

ButtonsNavigationManager.prototype.update = function(dt) {
    if(this.selectedBtn && this.selectedBtn.enabled)
    {
        if(this.app.keyboard.wasPressed(pc.KEY_UP)) 
            this.trySelect(this.selectedBtn.up);
        else if(this.app.keyboard.wasPressed(pc.KEY_DOWN)) 
            this.trySelect(this.selectedBtn.down);
        else if(this.app.keyboard.wasPressed(pc.KEY_LEFT)) 
            this.trySelect(this.selectedBtn.left);
        else if(this.app.keyboard.wasPressed(pc.KEY_RIGHT)) 
            this.trySelect(this.selectedBtn.right);
        else if(this.app.keyboard.wasPressed(pc.KEY_RETURN))
            this.clickSelectedBtn();
    }
};

ButtonsNavigationManager.prototype.clickSelectedBtn = function(){
    if(this.selectedBtn && this.selectedBtn.enabled)
        this.selectedBtn.entity.button._onClick(null);
};

ButtonsNavigationManager.prototype.trySelect = function(btnEntity){
    if(btnEntity && btnEntity.nav.enabled)
        btnEntity.nav.select();
};
var ButtonsNavigationItem = pc.createScript('buttonsNavigationItem');

ButtonsNavigationItem.attributes.add('up', {type:'entity'});
ButtonsNavigationItem.attributes.add('down', {type:'entity'});
ButtonsNavigationItem.attributes.add('left', {type:'entity'});
ButtonsNavigationItem.attributes.add('right', {type:'entity'});

ButtonsNavigationItem.prototype.initialize = function(){
    this.entity.nav = this;
    this.on('enable', this.checkFirstBtn);
}

ButtonsNavigationItem.prototype.postInitialize = function(){
    this.checkFirstBtn();
}

ButtonsNavigationItem.prototype.checkFirstBtn = function(){
    if(!(ButtonsNavigationManager.instance.selectedBtn && ButtonsNavigationManager.instance.selectedBtn.enabled))
        this.select();
};

ButtonsNavigationItem.prototype.select = function(){
    if(ButtonsNavigationManager.instance.selectedBtn && ButtonsNavigationManager.instance.selectedBtn.enabled){
        ButtonsNavigationManager.instance.selectedBtn.entity.button._onMouseLeave(null);
    }
    ButtonsNavigationManager.instance.selectedBtn = this;
    this.entity.button._onMouseEnter(null);
};
1 Like