Toolbars and Overlays
In the Machinery, tabs can provide toolbars. If you wish to use custom toolbars within The Machinery tabs, you do not need to use anything within tm_toolbar_api. The docking system will ask your tab for a list of toolbars to draw each frame. See tm_tab_vt->toolbars().
In this walkthrough, we will learn how to write our little toolbar for our newly added tab! This walkthrough requires you to know how our plugin system works.
Table of Content
Implement a Toolbar in a Tab
To begin with, we need to create a new tab plugin. We go on File -> New Plugin -> Tab.
A file dialog pops up, and we can decide where to store our plugin.
We open the custom_tab.c
(or however we called it) file with our favorite editor.
We search for the line in which we define the tab itself:
static tm_tab_vt *custom_tab_vt = &(tm_tab_vt){
.name = TM_CUSTOM_TAB_VT_NAME,
.name_hash = TM_CUSTOM_TAB_VT_NAME_HASH,
.create_menu_name = tab__create_menu_name,
.create = tab__create,
.destroy = tab__destroy,
.title = tab__title,
.ui = tab__ui,
};
To our definition, we add a toolbars()
. This function returns a C-Array of toolbar definitions. The array is allocated with the passed in the temporary allocator.
Note: A temporary allocator (tm_temp_allocator_api) Provides a system for temporary memory allocations. I.e., short-lived memory allocations that are automatically freed when the allocator is destroyed. Temp allocators typically use a pointer bump allocator to allocate memory from one or more big memory blocks and then free the entire block when the allocator is destroyed.
Important: You need to include the api first
#include <foundation/temp_allocator.h>
and get the api from the registry!
static tm_tab_vt *custom_tab_vt_toolbars = &(tm_tab_vt){
.name = TM_CUSTOM_TAB_VT_NAME,
.name_hash = TM_CUSTOM_TAB_VT_NAME_HASH,
.create_menu_name = tab__create_menu_name,
.create = tab__create,
.destroy = tab__destroy,
.title = tab__title,
.ui = tab__ui,
.toolbars = tab__toolbars, // we added this line
};
After we have added this, we need actually to define the function itself:
static struct tm_toolbar_i *tab__toolbars(tm_tab_o *tab,
tm_temp_allocator_i *ta) {}
Within this function, we define our toolbars. Our toolbar will have an essential job! It will have a button that prints "Hello World".
To make this work, we need to create a C-Array of tm_toolbar_i
objects and add our toolbar to it. This interface expects the following things:
Field | Description |
---|---|
id | An application-wide unique ID for the toolbar. Cannot be zero. |
owner | A pointer that can be accessed through the toolbar argument to the functions of this struct. Often used to store state for the toolbar, for example if you drawing toolbars inside a tab then you might want to store a pointer to that tab here. |
ui | Called when ui() of [tm_toolbar_api ](https://ourmachinery.com/apidoc/plugins/ui/toolbar.h.html#structtm_toolbar_api) wants to draw the toolbar. Make sure to respect draw_mode and return the rect that encompasses all the drawn controls. For toolbars inside horizontal and vertical containers, you can use [tm_toolbar_rect_split_off() ](https://ourmachinery.com/apidoc/plugins/ui/toolbar.h.html#tm_toolbar_rect_split_off()) and [tm_toolbar_rect_advance() ](https://ourmachinery.com/apidoc/plugins/ui/toolbar.h.html#tm_toolbar_rect_advance()) to easily manage the rect sizes while drawing your toolbar.If you need to store state, the make sure to set owner when you create the [tm_toolbar_i ](https://ourmachinery.com/apidoc/plugins/ui/toolbar.h.html#structtm_toolbar_i) object and get it from the passed toolbar pointer. |
draw_mode_mask | A combination of supported draw modes, ORed together values of [enum tm_toolbar_draw_mode ](https://ourmachinery.com/apidoc/plugins/ui/toolbar.h.html#enumtm_toolbar_draw_mode). The ui function will be passed the currently used draw mode and is expected to handle it. |
Note: For a complete list please check the documentation
Mask | Description |
---|---|
TM_TOOLBAR_DRAW_MODE_HORIZONTAL | You an draw the toolbar horizontal. |
TM_TOOLBAR_DRAW_MODE_VERTICAL | You an draw the toolbar vertical. |
TM_TOOLBAR_DRAW_MODE_WIDGET | The toolbar is an overlay |
Let us provide the essential things:
- The id is to be able to identify the toolbar.
- The UI function is to be able to draw something.
- The draw_mode_mask to indicate where we want the toolbar to be drawn.
static struct tm_toolbar_i *tab__toolbars(tm_tab_o *tab,
tm_temp_allocator_i *ta) {}
In our UI function, we can add the button via the [tm_ui_api
](https://ourmachinery.com/apidoc/plugins/ui/ui.h.html#structtm_ui_api). Then log the string "Hello World" to the screen with the logger API.
Note: You need include the
plugins/ui/ui.h
and thefoundation/log.h
as well as get the API's first!
static tm_rect_t toolbar__ui(tm_toolbar_i *toolbar, struct tm_ui_o *ui,
const struct tm_ui_style_t *uistyle,
tm_rect_t toolbar_r,
enum tm_toolbar_draw_mode dm) {
// ui code...
return toolbar_r;
}
Tab Overlays
As an extension to the dockable toolbars the engine support overlays that hover on top of the tabs. Also, any toolbar can be pulled off and be made into a hovering overlay.
An overlay is just a toolbar that does not belong to any of the four toolbar containers that run along the edge of the tab. Toolbars have three rendering modes — horizontal, vertical, and widget. The widget mode is new, it is the richer, window-like mode seen in the picture above.
In the scene and simulate tabs, we’ve added:
- A rendering visualization overlay. Found in
Render → Lighting Module → Show as overlay
in the top right toolbar. - A Statistics button (also top right toolbar) that makes it possible to popup statistics overlays, previously found within the Statistics tab.
The tab should return all toolbars it wishes to draw each frame, see tm_tab_vt->toolbars()
. If you wish to support widget mode drawing, then make sure to set the bitmask tm_toolbar_i->draw_mode_mask
a value that contains [TM_TOOLBAR_DRAW_MODE_WIDGET
](https://ourmachinery.com/apidoc/plugins/ui/toolbar.h.html#enumtm_toolbar_draw_mode).
Toolbars are generalized and they are not coupled to the docking system and the tabs, so you could use them within other contexts if you wish.
How to use toolbars outside of The Machinery tabs
See the documentation under How to use toolbars outside of The Machinery tabs
in toolbar.h.