UIManager
๐๏ธ Making your user interactiveโ
One of the most important things about making a BIM app is to give the user the ability to interact with the
functionalities you are creating ๐. The catch is you need to create a decent user interface so your end-user
is able to interact in an easy and intuitive way. While creating a simple set of buttons is not particularly
difficult, we all agree is time-consuming โฑ๏ธ. This is where UI Components
come to the rescue!
The UI Components are similar to the rest of the components of the library. The only difference is that their mission is to display an UI in HTML structures, including buttons, toolbars, menus, windows, etc.
๐จ Adding stylesโ
The first step is to get the CSS file with the default styles. You can get it from ..................
๐งฐ Creating a toolbarโ
We need buttons to allow the user to interact with our viewer. But even before that, we need a place to put them: this
place is called a Toolbar
. Creating and adding a Toolbar
to the viewer is as simple as this:
const mainToolbar = new OBC.Toolbar(components, { name: 'Main Toolbar', position: 'bottom' });
components.ui.addToolbar(mainToolbar);
By default, the toolbar is added to the bottom ๐ of the viewer container, so you technically don't need to type
position: "bootom"
in the options argument of your toolbar, but we just did it so that you know you can change
the toolbar position to either top, right, bottom or left.
You can create multiple toolbars in the same position, and the component just takes care about stacking all toolbars nice and neat ๐คฏ.
๐ข Using existing UIsโ
If you are using components from this library or from the marketplace, you won't need to create any UI: components usually include ready-to-use menus so that you can add them to your app in seconds. These components implement the UI Interface. Let's see them in action! ๐
๐จโ๐จ Creating your own UIsโ
Of course, UI Components can also be used stand-alone, either to build your own components or to add menus to your app very fast! Let's start with a simple one: a Button Component that sends an alert message. ๐ผ Button components can only be added inside a toolbar. To do so, we can simply add the following code:
const alertButton = new OBC.Button(components, { materialIconName: 'info' });
mainToolbar.addButton(alertButton);
alertButton.onclick = () => {
alert('I\'ve been clicked!');
}
We are fetching the icons from
material icons,
a very popular icon repository. You can simply pass the name of the icon in materialIconName
and the button will
display it! ๐งจ
๐ Preparing the sceneโ
Of course, this UI is not very exciting, because it only adds a single button that throws an alert. But we can do much more with UI components. Let's build a menu that creates and deletes geometry in our scene! We will make a simple tool that creates and delete boxes from the scene. First, we'll need to define basic information of the boxes. We will also create a super simple function to get a random number within a given limit:
const boxes = [];
const boxGeometry = new THREE.BoxGeometry();
const boxMaterial = new THREE.MeshLambertMaterial({ color: 'red' });
๐ข Next, let's define some simple functions. To create a random number:
function getRandomNumber(limit) {
return Math.random() * limit;
}
โ ๐ฆ To delete a box from the scene:
function createBox() {
const mesh = new THREE.Mesh(boxGeometry, boxMaterial);
scene.add(mesh);
mesh.position.x = getRandomNumber(10);
mesh.position.y = getRandomNumber(10);
mesh.position.z = getRandomNumber(10);
boxes.push(mesh);
}
โ๐ฆ To delete a box from the scene:
function deleteBox() {
if(!boxes.length) return;
const box = boxes.pop();
box.removeFromParent();
}
โ๐ฆ๐ฆ๐ฆ To delete all existing boxes:
function deleteAllBoxes() {
const count = boxes.length;
for(let i = 0; i < count; i++) {
deleteBox();
}
}
๐๐ฆ๐ฆ๐ฆ And to animate all the boxes, so that our scene is more interesting:
function animateBoxes() {
const oneDegree = Math.PI / 180;
for(const box of boxes) {
box.rotation.x += oneDegree;
box.rotation.y += oneDegree;
box.rotation.z += oneDegree;
}
}
components.renderer.beforeUpdate.on(animateBoxes);
๐ฒ Composing menusโ
Buttons can be nested to build complex menus! For example, let's say that we want 3 buttons that add a box, delete a box and delete all boxes respectively. We want to organize these menus together, so let's start by creating a button that will contain the rest:
const cubeTools = new OBC.Button(components, {
materialIconName: 'widgets'
});
mainToolbar.addButton(cubeTools);
Let's start with the button to create boxes. This buttons needs a couple of extra things:
- A
name
so that it displays the text. - A
closeOnClick: false
so that the menu doesn't close after being clicked - An
onclick
event so that the functioncreateBox
is triggered after pressing the button.
const createCubeButton = new OBC.Button(components, {
materialIconName: 'add_box',
name: 'Create box',
closeOnClick: false
});
createCubeButton.onclick = () => createBox();
cubeTools.addButton(createCubeButton);
Now, let's go with the "delete single" and "delete all buttons" buttons. Both are related, so we will group them together (yes, multiple-level nesting is allowed!). So first, let's create the parent button:
const deleteCubeButtons = new OBC.Button(components, {
materialIconName: 'disabled_by_default',
name: 'Delete box'
});
cubeTools.addButton(deleteCubeButtons);
Next, the "delete single" button:
const deleteSingleCubeButton = new OBC.Button(components, {
materialIconName: 'disabled_by_default',
name: 'Single',
closeOnClick: false
});
deleteSingleCubeButton.onclick = () => deleteBox();
deleteCubeButtons.addButton(deleteSingleCubeButton);
And finally the "delete all" button:
const deleteAllCubesButton = new OBC.Button(components, {
materialIconName: 'disabled_by_default',
name: 'All'
});
deleteAllCubesButton.onclick = () => deleteAllBoxes();
deleteCubeButtons.addButton(deleteAllCubesButton);
And this is it! Easy, right? You can now create add menus to your components and easily share them with other BIM software developers!
๐ Context menuโ
There's a special menu that is used in menu BIM applications: the context menu! You know, that menu that shows up
when you right-click somewhere. Don't worry, this is also supported by UI Components
! The
UI Manager has a default Toolbar that is already set up as a context menu.
All the nesting logic mentioned before works here as well:
const contextDeleteButtons = new OBC.Button(components, {
materialIconName: 'widgets',
name: "Delete"
});
const deleteAllCubesContextButton = new OBC.Button(components, {
materialIconName: 'widgets',
name: "All cubes"
});
deleteAllCubesContextButton.onclick = () => deleteAllBoxes();
contextDeleteButtons.addButton(deleteAllCubesContextButton);
components.ui.contextMenu.addButton(contextDeleteButtons);
And this is it! ๐ฅณ Cool, right? Now you can easily use the UI elements in the components of this library and the marketplace, as well as create your own custom menus in minutes. ๐ช๐จ You are now one step closer to create your BIM applications from scratch. ๐ฅ