SethRing Posted October 21, 2014 Share Posted October 21, 2014 Hi, Posting for the first time in a new forum is always slightly scary, but you all seem very kind. Hopefully that holds true My question is about Actions and Buttons. I've been able to create an action based on interaction with a mesh, but I'm wondering if there is an easy way to hook an action and a button so that the action triggers on a button push. I'm figuring there has to be since joshcamas does it in his nifty SamacEditor. Can someone point me to some documentation on this issue? Thanks. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted October 21, 2014 Share Posted October 21, 2014 Hi, The actions are triggered in Babylon from a trigger on a 3D object. The shares can not be triggered from a html button. You can optionally create a 3d button that will trigger actions, but if your button is on top of the canvas you can not use the actions. Quote Link to comment Share on other sites More sharing options...
Paradine Posted October 21, 2014 Share Posted October 21, 2014 Adding action to a button might be unnessesary. myButton.onclick = function (btn) { scene.getMeshById("mymesh").visibility = 0; scene.beginAnimation(myTarget, 0, 150);} Dad72 1 Quote Link to comment Share on other sites More sharing options...
joshcamas Posted October 22, 2014 Share Posted October 22, 2014 Welcome to the forums! I do not actually use the action manager, funnily enough. I basically do what Paradine showed - run a function on the "onclick" event. You can do this in many ways, including: HTML:<button type="button" onclick="runFunction('hello')">Click Me!</button>OR Javascript: (Paradine's Method)var coolButton = document.getElementById("sweetButton");coolButton.onclick = function () { alert("Chicken Sauce!");}or you can even use jquery. No need for the actionmanager. DesignVibe 1 Quote Link to comment Share on other sites More sharing options...
SethRing Posted October 22, 2014 Author Share Posted October 22, 2014 Thank you all for your responses! I must be missing something because I tried the button/function method before my first post and couldn't get it to work. My code is as follows:<button type="button" onclick="showTop('T115')">Round</button><button type="button" onclick="showTop('T345')">Rectangular</button><script> if (BABYLON.Engine.isSupported()) { var canvas = document.getElementById("renderCanvas"); var engine = new BABYLON.Engine(canvas, true); BABYLON.SceneLoader.Load("", "test.babylon", engine, function (newScene) { var meshT115 = newScene.getMeshByName("T115").visibility = 0; var mesh510 = newScene.getMeshByName("510").visibility = 0; var meshT345 = newScene.getMeshByName("T345").visibility = 1; var mesh350 = newScene.getMeshByName("350").visibility = 0; var myBaseMesh = newScene.getMeshByName("510"); var materialMyMesh = new BABYLON.StandardMaterial("texture1", newScene); materialMyMesh.diffuseTexture = new BABYLON.Texture("assets/images/stain/Natural.jpg", newScene); materialMyMesh.specularPower = 50; myBaseMesh.material = materialMyMesh; var myTopMesh = newScene.getMeshByName("T345"); var materialMyMesh = new BABYLON.StandardMaterial("texture2", newScene); materialMyMesh.diffuseTexture = new BABYLON.Texture("assets/images/stain/Natural.jpg", newScene); materialMyMesh.specularPower = 50; myTopMesh.material = materialMyMesh; // Wait for textures and shaders to be ready newScene.executeWhenReady(function () { // Attach camera to canvas inputs var myCamera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 5, new BABYLON.Vector3(0, 0, 0), newScene); var light0 = new BABYLON.HemisphericLight("Hemi0", new BABYLON.Vector3(.1, .1, .1), newScene); light0.diffuse = new BABYLON.Color3(.1, .1, .1); light0.specular = new BABYLON.Color3(.1, .1, .1); light0.groundColor = new BABYLON.Color3(.5, .5, .5); newScene.activeCamera = myCamera; newScene.activeCamera.attachControl(canvas); // Once the scene is loaded, just register a render loop to render it engine.runRenderLoop(function() { newScene.render(); }); }); }, function (progress) { // To do: give progress feedback to user }); } function showTop(x) { newScene.getMeshById("myTopMesh").visibility = 0; newScene.getMeshById(x).visibility = 1; }</script> I manually grab my 4 meshes and set their visibility (hiding all but T345). I then try to call my showTop() function to hide the current top mesh (myTopMesh) and display the submitted mesh.What am I missing? Quote Link to comment Share on other sites More sharing options...
Paradine Posted October 22, 2014 Share Posted October 22, 2014 Newscene is out of scope problem from first glance view? Or you call it before scene is ready, might also come up as a problem. Quote Link to comment Share on other sites More sharing options...
SethRing Posted October 22, 2014 Author Share Posted October 22, 2014 is there a way to call newScene from outside BABYLON.SceneLoader.Load()? Or do I need to recreate the scene with each onclick event? Quote Link to comment Share on other sites More sharing options...
Paradine Posted October 22, 2014 Share Posted October 22, 2014 engine.scenes[] contains all scenes that are linked to it someway.But only function that is called each frame is engine.runRenderLoop(function() { newScene.render(); });others like loading functions are called only once. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted October 22, 2014 Share Posted October 22, 2014 You can create a global variable: var myNewScene = null; BABYLON.SceneLoader.Load("", "test.babylon", engine, function (newScene) { myNewScene = newScene; --- Error: and use it in your function signature showTop: function showTop(x, myScene) { myScene.getMeshById("myTopMesh").visibility = 0; myScene.getMeshById(x).visibility = 1;} <button type="button" onclick="showTop('T115', myNewScene)">Round</button>... see fixed bottom Quote Link to comment Share on other sites More sharing options...
SethRing Posted October 22, 2014 Author Share Posted October 22, 2014 I tried adding the global but I get the following error:Uncaught TypeError: undefined is not a function showTop onclickI feel like I'm missing something really simple. With how easy babylon.js has been to use so far I can't believe that there isn't a simple solution to this that I'm just not getting.Thanks for all your help so far. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted October 22, 2014 Share Posted October 22, 2014 Try to use the global variable directly once assign rather than using it in the signature. it was a error to use myNewScene it in the signature. Sorry. var myNewScene = null; BABYLON.SceneLoader.Load("", "test.babylon", engine, function (newScene) { myNewScene = newScene; --- function showTop(x) { myNewScene.getMeshById("myTopMesh").visibility = 0; myNewScene .getMeshById(x).visibility = 1; } <button type="button" onclick="showTop('T115')">Round</button> Quote Link to comment Share on other sites More sharing options...
Wingnut Posted October 22, 2014 Share Posted October 22, 2014 Hi. In certain circumstances, putting 'window' in front.... brings things back in scope. ie. window.showTop = function(x) { ... } or function window.showTop(x) { ... } *shrug* Deltakosh and Dad72 taught me about named functions and anonymous functions... here: http://www.html5gamedevs.com/topic/2571-the-wingnut-chronicles/page-17#entry46784 (and the post after that one, too). Maybe something there can help. The dynamic html 'hide editor' and 'show editor' buttons here... http://playground.babylonjs.com/#YIT1S ...use functions like that (way at the bottom). Something similar might work for you, too. It's not necessarily the best practice, because it puts the functions on the window object, which is global, so it can collide with other browser functions. "seth ring" as in Jane Robert's "Seth"? I'm a big fan. Maybe we'll talk some more, later, in the back channels. Feel free to PM me about it, if you want to. Rumor has it that we create our own (virtual) reality. (a good framework helps) Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted October 22, 2014 Share Posted October 22, 2014 I think this is time to bring up that I added an append() method to SceneLoader a while back. The purpose then was for ease of loading more than one .babylon, and not just meshes. With append(), you pass the scene, so it is already instanced by you. Slightly more elegant than putting a copy out to a "reference global" in a loader call back. see http://www.html5gamedevs.com/topic/8346-does-sceneloaderimportmesh-import-lights-and-cameras/ for more, start page 2 I think. GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
Paradine Posted October 23, 2014 Share Posted October 23, 2014 I usually create the button itself when babylon is supported and show it only when scene is loaded. If the button is used only with babylon. if (BABYLON.Engine.isSupported()) { var btnLegend = document.createElement("button"); btnLegend.id = "showLegend"; btnLegend.textContent = "Legend"; btnLegend.hidden = true; document.getElementById("someDivId").appendChild(btnLegend); //..... var scene = createScene(); var executedWhenReady = function (){ btnLegend.onclick = function (btn) { //DoSth }; btnLegend.hidden = false; }; scene.executeWhenReady(executedWhenReady);} Quote Link to comment Share on other sites More sharing options...
SethRing Posted October 23, 2014 Author Share Posted October 23, 2014 So up until this point I have been putting my buttons outside the canvas. I'm guessing that is a problem. Maybe I need to back up. Anyone have any good resources on creating a 2d layer on top of my canvas? **EDIT** Oh, and Wingnut, its just my name :-) Quote Link to comment Share on other sites More sharing options...
Xeonzinc Posted October 23, 2014 Share Posted October 23, 2014 You can create a 2D canvas on top of your babylon canvas quite easily. I currently have canvas buttons & text input working very nicely. http://www.html5gamedevs.com/topic/9772-2d-ui-overlay/ Alternatively I belive you can just position your DOM buttons over the babylon canvas with CSS Quote Link to comment Share on other sites More sharing options...
SethRing Posted October 23, 2014 Author Share Posted October 23, 2014 Xeonzinc, I've been trying to do the whole DOM button thing but I'm apparently not smart enough to figure it out. Anyone feel like taking a look at my code?<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Babylon - Basic scene</title> <link rel="stylesheet" type="text/css" href="assets/css/style.css"> <script type="text/javascript" src="//use.typekit.net/ilr4lzl.js"></script> <script type="text/javascript">try{Typekit.load();}catch(e){}</script> <script src="assets/js/babylon.js"></script> <script src="assets/js/hand-1.3.8.js"></script> <script src="assets/js/cannon.js"></script> <!-- optional physics engine --></head><body> <div id="container"> <!-- Page Content --> <div id="content"> <div id="tableBuilder"> <div id='cssmenu'> <ul id="tops"> <button type="button" onclick="showTop('T115')">Round</button> <button type="button" onclick="showTop('T345')">Rectangular</button> </ul> </div> <canvas id="renderCanvas"></canvas> </div> </div> </div> <script> if (BABYLON.Engine.isSupported()) { var myNewScene = null; var canvas = document.getElementById("renderCanvas"); var engine = new BABYLON.Engine(canvas, true); BABYLON.SceneLoader.Load("", "test.babylon", engine, function (newScene) { myNewScene = newScene; var meshT115 = newScene.getMeshByName("T115").visibility = 0; var mesh510 = newScene.getMeshByName("510").visibility = 1; var meshT345 = newScene.getMeshByName("T345").visibility = 1; var mesh350 = newScene.getMeshByName("350").visibility = 0; var myBaseMesh = newScene.getMeshByName("510"); var materialMyMesh = new BABYLON.StandardMaterial("texture1", newScene); materialMyMesh.diffuseTexture = new BABYLON.Texture("assets/images/stain/Natural.jpg", newScene); materialMyMesh.specularPower = 50; myBaseMesh.material = materialMyMesh; var myTopMesh = newScene.getMeshByName("T345"); var materialMyMesh = new BABYLON.StandardMaterial("texture2", newScene); materialMyMesh.diffuseTexture = new BABYLON.Texture("assets/images/stain/Natural.jpg", newScene); materialMyMesh.specularPower = 50; myTopMesh.material = materialMyMesh; // Wait for textures and shaders to be ready newScene.executeWhenReady(function () { // Attach camera to canvas inputs var myCamera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1.2, 1.2, 5, new BABYLON.Vector3(0, 0.1, 0.1), newScene); var light0 = new BABYLON.HemisphericLight("Hemi0", new BABYLON.Vector3(0, 50, 0), newScene); light0.diffuse = new BABYLON.Color3(.2, .2, .2); light0.groundColor = new BABYLON.Color3(.5, .5, .5); newScene.activeCamera = myCamera; newScene.activeCamera.attachControl(canvas); // Once the scene is loaded, just register a render loop to render it engine.runRenderLoop(function() { newScene.render(); }); }); }, function (progress) { // To do: give progress feedback to user }); } function showTop (x) { myNewScene.getMeshById("myTopMesh").visibility = 0; myNewScene.getMeshById(x).visibility = 1; } </script></body></html>So far I've gotten it to load, display my scene and then do nothing. Each time I hit a button it gives me that "Uncaught TypeError: undefined is not a function" error on line 83. Which confuses me since I don't understand why the browser thinks "myNewScene.getMeshById("myTopMesh").visibility = 0;" should be a function...Sorry for the totally beginner questions. Quote Link to comment Share on other sites More sharing options...
Wingnut Posted October 24, 2014 Share Posted October 24, 2014 No need to apologize at all, Sethring. We enjoy having you with us, no matter what your skill levels, and don't sell yourself short. Your code is looking pretty good. Do you see how function showTop is sort of isolated from the other code? Even though it is inside the same script element as the...if (BABYLON.Engine.isSupported()) { ... }...it is not within its braces. And inside its braces is where you did...myNewScene = newScene;Just maybe... 'myNewScene' is 'undefined' as far as function showTop is concerned. If you add...alert(myNewScene);...as the first line of the showTop function, and run it... (and click your showTop button)... I bet the alert would report 'undefined' or maybe a giant nothing. I am not a very good JS coder... but maybe... maybe... if you moved this line...var myNewScene = null;...one line higher (above the 'if' line), then maybe your new alert would start reporting 'object' (a good thing). With this move, maybe myNewScene would become more global (maybe). And if THAT doesn't work, I have another idea. Maybe make THIS line...var myNewScene = engine.scenes[0];...be the first line of showTop function. We will make myNewScene become 'defined' (for showTop) even if we have to 'lookup' the scene via the global 'engine' object (even if it kills us). That's a couple things that you can try. No promises. The showTop function looks mighty lonely and isolated. Maybe it hasn't heard the news about myNewScene getting defined. Once you put that alert line as the first line of showTop function, you will know the facts about that. alert() and console.log() are our friends. They can report 'the situation' at various places in the code. But you know all that, already. Good luck! Quote Link to comment Share on other sites More sharing options...
Dad72 Posted October 25, 2014 Share Posted October 25, 2014 Try this directly as you suggest Wingnut. This way has a fail-safefunction showTop (x) { myNewScene = myNewScene || engine.scenes[0]; //myNewScene be assigned by the variable already assigned or is going search of scene in the engine. myNewScene.getMeshById("myTopMesh").visibility = 0; myNewScene.getMeshById(x).visibility = 1;} Wingnut 1 Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted November 3, 2014 Share Posted November 3, 2014 See your posting of approaching this in a different way. Thought I would give an example of SceneLoader.Append. Note that scene is at script tag scope. It is assigned directly by a call to the constructor. Your code in showTop() may not work, but maybe you need to break up your getMesh call into a separate line from assigning visibility, to make sure it is returning a mesh first.var scene;if (BABYLON.Engine.isSupported()) { var canvas = document.getElementById("renderCanvas"); var engine = new BABYLON.Engine(canvas, true); scene = new BABYLON.Scene(engine); BABYLON.SceneLoader.Append("", "test.babylon", scene, function (newScene){ ... });}function showTop(x) { scene.getMeshById(x).visibility = true; } 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.