ShiftedClock Posted August 1, 2018 Share Posted August 1, 2018 I initialize an ActionManager and register an Action with it, using the OnKeyDownTrigger, like so: scene.actionManager = new BABYLON.ActionManager(scene); scene.actionManager.registerAction( new BABYLON.ExecuteCodeAction( { trigger: BABYLON.ActionManager.OnKeyDownTrigger, parameter: "y" }, function () { console.log("y button pressed"); } )); But when I press the "y" key on my keyboard nothing is logged to the console. I've tried with many others keys, in both Firefox and Chrome, after turning off all plugins. Typescript is throwing no errors. Changing the trigger to BABYLON.ActionManager.OnEveryFrameTrigger works as expected, logging to console every frame. Changing it back to the "triggerOptions" object above makes it non-functioning again. I also tried setting up an actionManager on a Mesh in the scene, and registering the Action with that, which didn't work either. (Although OnPickTrigger on the mesh works fine.) Am I using the correct format for the triggerOptions object? Should I not be instantiating the ActionManager directly on to the scene.actionManager property? (Although it works with OnEveryFrameTrigger.) This code is nearly a copy-paste from the last code block under the Triggers section of "How to Use Actions". I can see the scene.actionManager object when I log it to console, with the action on it, it just isn't firing in response to pressing the y button. I'm learning a lot about using Actions in Babylon, I just can't get keyboard inputs/actions to work. Thank you for any help, this is really getting to me! Quote Link to comment Share on other sites More sharing options...
Wingnut Posted August 1, 2018 Share Posted August 1, 2018 Hi SV! Welcome to the forum. https://www.babylonjs-playground.com/#15EY4F#1 Remember that you need to click on the canvas before the "y" listener goes active. I cheated and used a canvas.focus() call in line 7. Works for me... I see 'y' keypresses at the console. Be sure to check-out https://www.babylonjs-playground.com/#15EY4F#2 as well. It doesn't work perfectly, but it has an interesting keypress listener... might be worth playing-with. Quote Link to comment Share on other sites More sharing options...
ShiftedClock Posted August 1, 2018 Author Share Posted August 1, 2018 Thanks for putting that Playground example together Wingnut. It's working for me, but my local Typescript implementation is still not working. Using window.addEventListener for the Action works fine: let yPress = new BABYLON.ExecuteCodeAction( { trigger: BABYLON.ActionManager.OnKeyDownTrigger, parameter: "y" }, () => { console.log("y pressed"); } ) window.addEventListener("keypress", (event) => { if (event.key === "y") { yPress.execute(); { }); That works. But doing this still does nothing: scene.actionManager = new BABYLON.ActionManager(scene); scene.actionManager.registerAction(yPress); Yet the actionManager calls ExecuteCodeActions for OnEveryFrameTrigger (the other Scene Trigger type), as expected. I'm totally at a loss for why this is happening. It must be something about my development environment. I cleared my cache, turned off all browser plugins, tried two browsers, restarted my computer. Next, I might try hopping around on one foot and reciting Monty Python, just to see if it helps. Using window event listeners will work, just a bit sad I can't get the ActionManager to work with keyboard events. Thanks again for the help. If anyone has any ideas about where the problem could be, it would be much appreciated. Quote Link to comment Share on other sites More sharing options...
Guest Posted August 1, 2018 Share Posted August 1, 2018 For keyboard event to work you have to make sure that canvas.tabIndex = 1 (in order to have it receive the events) Check with F12 object inspector in your browser to make sure that the canvas can receive keyboard events Quote Link to comment Share on other sites More sharing options...
ShiftedClock Posted August 3, 2018 Author Share Posted August 3, 2018 Alright, I figured out the problem. This has been one of the most intense multi-day debug sessions I've had in years. After littering babylon.max.js with console.log statements, I narrowed it down to the fact that Engine._onCanvasFocus wasn't firing, while manually adding an event listener to the canvas focus event worked fine. Then I noticed, that code was wrapped in a check for canvasOrContext.getContext. Ding ding ding. Winner winner, chicken dinner, as the kids say. The problem was with this part of my code: let canvas = <HTMLCanvasElement> document.getElementById("canvas2"); let gl = <WebGLRenderingContext> canvas.getContext("webgl"); let engine = new BABYLON.Engine(gl, true, {"preserveDrawingBuffer": true}); I had assumed that since the Engine's constructor took either a canvas or a context, that it would work fine with either. But WebGLRenderingContext doesn't have a .getContext property! I'm not sure if this is intended behavior, but the result is that the check for canvasOrContext.getContext silently fails (babylon.max.js line 11393, sorry, don't have the typescript line number). Since that fails, much of the following option and Observable setup fails. The else part of "if (canvasOrContext.getContext)" is simply missing all of the setup code. So, I think I discovered a bug in the engine? Or at least unintended behavior. I don't have the time or inclination to make the fixes and submit a pull request (this is my first week with Babylon afterall), but I hope someone can. For now I've switched back to passing canvas to the engine constructor, and everything works as expected. Side note: Having Scene.attachControl and Camera.attachControl have the same method name, while doing very different things, was a source of confusion for me. Edit: This may be intended behavior, just undocumented. It's very unintuitive that Observables aren't properly setup when passing a WeblGLRenderingContext to Engine, while HTMLCanvasElement works fine. The fact that you can't addEventListener on WebGL contexts is probably the source of that difference. A reasonable compromise would just be mentioning in the documentation that initializing Engine with a WebGlRenderingContext prevents (some?) Observables from being setup. Edit2: Apparently you can get the canvas from the context, so event listeners could still be setup, so long as the canvas is not null. Wingnut 1 Quote Link to comment Share on other sites More sharing options...
Guest Posted August 3, 2018 Share Posted August 3, 2018 Well this is expected actually if you provide a context, this is a signal for babylon.js that there is already something working on the webgl context and we are a plugin (this is how the integration in PowerPoint works for instance) So in this case, the footprint is minimal as we do not own the canvas (so no event hooking etc..). i will mention that in the code comments Thanks a lot for your feedback! ShiftedClock and Wingnut 1 1 Quote Link to comment Share on other sites More sharing options...
ShiftedClock Posted August 3, 2018 Author Share Posted August 3, 2018 Good to know, thanks. Hopefully if/when someone runs into the same situation, something is there to say "Observables are not registered when using a WebGLRenderingContext." Either in documentation, code comments, or console warnings. Anything but failing silently with no indication as to why the Observables aren't being set up. Wingnut 1 Quote Link to comment Share on other sites More sharing options...
Guest Posted August 3, 2018 Share Posted August 3, 2018 I updated the code comments to follow your idea:) ShiftedClock 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.