Menus System threejs project example
I was thinking about slapping together a quick project that makes use of the Raycaster class to create a simple yet effective menu system in threejs. If you are not familiar with the raycaster constructor in threejs yet, it is something that you will want to look into at some point sooner or layer as it is a very usful tool when it comes to figuring out how to click a mesh object sort of speak. The Raycaster constructor is what can be used to find out if a 2d pointer click of one kind or another has resulted in a mesh object being clicked or not. This raycaster class can be used to find one or more objects from any point in space to another also actually, but for todays threejs project example a raycster instance will help a whole lot if the aim is to make some kind of menu system using threejs.
Making a menu system in threejs and What to know first
There are a lot of things that you should know before getting into how to go about making a menu system with three.js. There is of course starting out with a basic getting started type example with threejs if you still have very little experience with threejs first. However regardless of how much experience you may have it might be a good idea to learn more or refresh on a few things so I will be writing about what that is in this intro section of this post.
Read up more on the Raycaster class
It might be better to just start out with some very basic hello world type examples with the raycaster class in threejs first. Once one gains a decent grasp on the raycaster class it becomes clear what the various use case examples are for it, and one typical thing to do would be to work out some kind of menu system using it. However I also find it very usful for other tasks as well such as having a way to position a mesh object to the surface of another mesh object and doing so in a way that will work well with just about any kind of geometry.
Check your version numbers
When I was working on this threejs example last I was using threejs r135, and the code was working well for me at that time with the old example that I started with. The last time I came around to do some editing of this post I started an official r0 of a menu.js module, and with the demos that I started with that I was using r146 of threejs. If the code examples here are not working for you the version of threejs is what you are going to want to check first. After that you might be running into some other kind of problem.
Source is on Github
The source code for this threejs example can be found in my test threejs repository on Github. I also have the source code for my many other posts on threejs located in that repository as well.
1 - The menu.js file and demos (r0) using r146 of threejs
In this section I will be going over r0 of my menu.js file, and at least one if not more demos of the module in action. This is based off of the source code that I started with when I first wrote this post, but with many changes. For one thing I am not leaving the process of setting up the typical objects that have to do with a typical three js project as part of the demo. The create method of the menu module will only create a renderer and so forth if needed in the even that I do not pass one to the create method by way of an options object.
Speaking of the create options I have also added a long of additional basic options that have to do with things like just setting the number of buttons that I want and the size of each button. I did not go to far of the rails with this thus far though as I am not seeing myself using this example in any kind of production project just yet. However if I even do need or want to make some kind of menu system with threejs this might prove to be an okay starting point now.
1.a - The menus module ( r0 )
Here I have the source code for r0 of my menu.js module that seems to work okay thus far. There is just one public method that I call in a project in which I use this that will create and return an object that will contain a group of mesh objects. Each mesh object of the group will be a button that when clicked will fire an on click method and pass a ref to that button mesh object as an argument for the on click method. So then I can set a number of buttons that I want for the menu, and then a custom on click method where I will define the logic that I want to call when a button object is clicked.
|
|
1.1 - Basic demo of the module where the button scale just changes when clicked
This is my first basic demo of r0 of menu.js where I just want to create a few buttons and have the scale of each button change when a button is clicked. So after creating my typical set of objects that I want when making any threejs project I then call the main create method of the menu module. I then use the scene, renderer, and camera objects that I just created for the menu by passing them with the options object when calling the create method. In addition to that I also set the number of buttons that I want for the menu, and define a custom on click method.
The custom on click method that I made for this demo will just set a scale delta value for the button that was clicked to a given amount. This amount will then be used in the process of setting the actual scale value that will be used in an update method. Also in this update method the scale value will reduce over time.
I am then using the object3d traverse method to loop over all the objects of the main group of the menu that is returned. I could use this to do things like set up new materials, and anything else that i would want to change on a mesh by mesh basic. However for the sake of this demo I just want to set up some values for the user data objects of each mesh object.
|
|
2 - OLD example of this threejs powered menu system using r135 of threejs
In this section I will be starting out with just the basics of what needs to happen first in order to get this menu system up and running. The main thing is that I have at least one javaScript sm.js file that provides a means to create what I am calling a state machine object. This library just has one public method thus far that is used to create and return a main state machine object. This state machine object can then be used in a main app loop of a main javaScript file thus far.
As of this writing the state of this sm.js is not so great, so things will likely change a whole lot in any future reversions of this examples when I get around to editing this post next. However much of the core functionality that I had in mind is all ready working, so maybe only so much more will need to change.
In any case this is kind of an advanced post on threejs so I assume that you know at least a little when it comes to using threejs and javaScript in general. If not you might want to step back and start out with something aimed more for developers that are new to threejs such as the getting started with threejs post that I wrote a while back.
2.1 - The sm.js file that creates and returns a State Machine Object
So then here I have the state of the sm.js file thus far that will create and return a main sm object. The first and foremost method of concern then is the public createSmObject method which is what I would call from a main javaScript file in which I would want to use this file.
|
|
2.2 - Basic example of this so far
Now for just a basic hello world style example of this sm module this far. With that said I guess that there is just calling the create sm object method of the module to get my sm object. I will then just need to make sure that I am calling the render method of the object in the body of my main animation loop of the example.
|
|
For now the basic idea of what I want to happen seems to work just fine as expected. When I client one of the mesh objects in the scene the default message is shown in the javaScript console. So then the module even in its current from seems to work okay thus far. So then now that the basic idea of what I have in mind seems to work the next step is maybe just making one or more examples that are a little more interesting than this. Something that works like that of some kind if DVD menu or something to that effect would be cool.
Conclusion
This example alone as well as many of the other simple project examples I have made thus far are in a need of a little more work of course. This is why things have slowed down a little when it comes to writing new posts, this content as well as many others that I have write before need to be revised a little. This whole thing needs to be redone into what I might call a first revision of what I want to have when it comes to this sort of thing, and at the time of this writing I do not have the time yet to do that.
I have poked my head in and edited this content piece a little at this time, but I can not say that this example has a high priority for me when it comes to putting a little more time into it. I have a lot of pots boiling all at once and this project is on a far back burner it at the moment. I seem to me more interested in using threejs as a way to make programs that have to do with making videos, rather than some kind of menu system.
Still when this is up and running the very crude, basic idea, is in fact working. So what needs to happen is just a little refinement of the source code in terms of a standard module type project that I can drop into a folder and link to. There is just a lot more that I would like to add in any and all future revisions of this module that may or may not come to pass if I do ever put more time into this one at some point in the future. Some additional public methods that will help with the process of styling the buttons for one thing maybe.