Orbit Camera script - disabling touch/mouse input

Hi everybody, I have a simple problem. I want to make a script to disable touch/mouse input for the auto orbiting camera. The script works if I try to disable the orbit script, but what i need in my project is disabling mouse / touch input scripts. In this case the same script does not work. Why?

This doesn’t work:

var InputOff = pc.createScript('inputOff');

// initialize code called once per entity
InputOff.prototype.initialize = function() {
pc.app.root.findByName('Camera').script.mouseInput.enabled = false;
};

// update code called every frame
InputOff.prototype.update = function(dt) {

};

This works

var InputOff = pc.createScript('inputOff');

// initialize code called once per entity
InputOff.prototype.initialize = function() {
pc.app.root.findByName('Camera').script.orbitCamera.enabled = false;
};

// update code called every frame
InputOff.prototype.update = function(dt) {

};

It’s because the touch input script uses events that are still listened to if the script is disabled.

You will need to unsubscribe/subscribe to the events again when the script is enabled/disabled.

eg: https://playcanvas.com/editor/scene/1248073

// initialize code called once per entity
TouchInput.prototype.initialize = function() {
    this.orbitCamera = this.entity.script.orbitCamera;
    
    // Store the position of the touch so we can calculate the distance moved
    this.lastTouchPoint = new pc.Vec2();
    this.lastPinchMidPoint = new pc.Vec2();
    this.lastPinchDistance = 0;
    
    if (this.orbitCamera && this.app.touch) {
        this.addEvents();
        this.on('destroy', function() {
            this.removeEvents();
        }, this);
        
        this.on('enable', function() {
            this.addEvents();
        }, this);
        
        this.on('disable', function() {
            this.removeEvents();
        }, this);
    }
};


TouchInput.prototype.addEvents = function() {
    // Use the same callback for the touchStart, touchEnd and touchCancel events as they 
    // all do the same thing which is to deal the possible multiple touches to the screen
    this.app.touch.on(pc.EVENT_TOUCHSTART, this.onTouchStartEndCancel, this);
    this.app.touch.on(pc.EVENT_TOUCHEND, this.onTouchStartEndCancel, this);
    this.app.touch.on(pc.EVENT_TOUCHCANCEL, this.onTouchStartEndCancel, this);

    this.app.touch.on(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
};


TouchInput.prototype.removeEvents = function() {
    this.app.touch.off(pc.EVENT_TOUCHSTART, this.onTouchStartEndCancel, this);
    this.app.touch.off(pc.EVENT_TOUCHEND, this.onTouchStartEndCancel, this);
    this.app.touch.off(pc.EVENT_TOUCHCANCEL, this.onTouchStartEndCancel, this);

    this.app.touch.off(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
};
1 Like

Thank you yaustar, I think it is a concept too advanced for my competence but maybe there is another way to solve the problem that bother me.
You can try my configurator here: PlayCanvas 3D HTML5 Game Engine
as you see I can’t scroll properly in the last popup at the end of the configuration. If I deactivate mannualy the mouseImput script in the camera entity the last popup works. Are you able to give me other advice for this?

Thank you very much.

Without looking at it too closely, it is probably due to the preventDefault() function call on the mouse wheel event in the moue input script.

A bit surprised by that as I would have thought the HTML element would get the mouse event first before the WebGL canvas due to Z order.

Depending on what you would like the functionality to be, I would do something similar to the touch input script I shown above where disabling the script would unsubscribe to the mouse events and then you can disable controls when the user should interacting with the UI.

After a little work around it worked out. Thank you.

For those who need it, this is the script

var MouseInput = pc.createScript('mouseInput');

MouseInput.attributes.add('orbitSensitivity', {
    type: 'number', 
    default: 0.3, 
    title: 'Orbit Sensitivity', 
    description: 'How fast the camera moves around the orbit. Higher is faster'
});

MouseInput.attributes.add('distanceSensitivity', {
    type: 'number', 
    default: 0.15, 
    title: 'Distance Sensitivity', 
    description: 'How fast the camera moves in and out. Higher is faster'
});

// initialize code called once per entity
MouseInput.prototype.initialize = function() {
    this.cameraController = this.entity.script.cameraController;
    
    this.addEvents();
        this.on('destroy', function() {
            this.removeEvents();
        }, this);
        
        this.on('enable', function() {
            this.addEvents();
        }, this);
        
        this.on('disable', function() {
            this.removeEvents();
        }, this);
        
    if (this.cameraController) {
        var self = this;
        
        var onMouseOut = function (e) {
           self.onMouseOut(e);
        };
        
        this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
        this.app.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
        this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
        this.app.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);

        // Listen to when the mouse travels out of the window
        window.addEventListener('mouseout', onMouseOut, false);
        
        
       
        

    }
    
    // Disabling the context menu stops the browser displaying a menu when
    // you right-click the page
    this.app.mouse.disableContextMenu();
  
    this.lookButtonDown = false;
    this.lastPoint = new pc.Vec2();
};


MouseInput.fromWorldPoint = new pc.Vec3();
MouseInput.toWorldPoint = new pc.Vec3();
MouseInput.worldDiff = new pc.Vec3();


MouseInput.prototype.onMouseDown = function (event) {
    switch (event.button) {
        case pc.MOUSEBUTTON_LEFT: {
            this.lookButtonDown = true;
        } break;
            
        case pc.MOUSEBUTTON_MIDDLE: 
        case pc.MOUSEBUTTON_RIGHT: {
            this.panButtonDown = true;
        } break;
    }
};


MouseInput.prototype.onMouseUp = function (event) {
    switch (event.button) {
        case pc.MOUSEBUTTON_LEFT: {
            this.lookButtonDown = false;
        } break;
    }
};


MouseInput.prototype.onMouseMove = function (event) {    
    var mouse = pc.app.mouse;
    if (this.lookButtonDown) {
        this.cameraController.pitch -= event.dy * this.orbitSensitivity;
        this.cameraController.yaw -= event.dx * this.orbitSensitivity;        
    }
    
    this.lastPoint.set(event.x, event.y);
};


MouseInput.prototype.onMouseWheel = function (event) {
    this.cameraController.distance -= event.wheel * this.distanceSensitivity * (this.cameraController.distance * 0.1);
    event.event.preventDefault();
};


MouseInput.prototype.onMouseOut = function (event) {
    this.lookButtonDown = false;
};

MouseInput.prototype.addEvents = function() {
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
    this.app.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
    this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
    this.app.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
};

MouseInput.prototype.removeEvents = function() {
    this.app.mouse.off(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
    this.app.mouse.off(pc.EVENT_MOUSEUP, this.onMouseUp, this);
    this.app.mouse.off(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
    this.app.mouse.off(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
};
1 Like