• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Multiple tabs menu

R

RossDear

Guest
Hi, I'm searching how to handle an interface that got multiple tabs each above the other. I want something that look like interlayers of a filling cabinet.

I was hesitating between having the differents elements on all the interlayers created at the same time and you see only the ones that are on what you clicked on or having the elements delete and create themselve each time we click on another interlayer.

Note that this is for the core mechanic of my project and not a GUI element.
Thanks!
 

samspade

Member
I did something a little similar to this once. I created a simple system of activating an deactiving instances while saving the prior screen as a screenshot. Basic process was:
  • save the application surface as a screenshot (I actually saved it out as a buffer and loaded it in but there's a couple ways it could work)
  • add all current instances to a list or array and push that array to a stack
  • load in new instances
To go back a layer, you just pop the last added list/array off the stack then loop through the stack and activate the instances. You might need to make a similar stack for the screenshots as well.

GML:
#region //deactivate instances
var pause_list = ds_list_create();
with (all) {
    if (object_is_ancestor(object_index, controller_parent)) continue;
    ds_list_add(pause_list, id);
    instance_deactivate_object(id);
}
ds_stack_push(pause_stack, pause_list);
#endregion

#region //activate instances
var unpause_list = ds_stack_pop(pause_stack);
for (var i = 0; i < ds_list_size(unpause_list); i += 1) {
    instance_activate_object(unpause_list[| i]);
}
ds_list_destroy(unpause_list);
#endregion

GML:
/// @description Create Event


#region //create a screenshot

//save application surface to a buffer
var buff = buffer_create(surface_get_width(application_surface) * surface_get_height(application_surface) * 4, buffer_grow, 1);
buffer_get_surface(buff, application_surface, 0, 0, 0);
buffer_save(buff, "gameplay_surface.buf");

//delete buffer and surface
buffer_delete(buff);

#endregion
GML:
/// @description Save Screen


#region //draw surface from buffer

//load in buffer, create surface, set surface to buffer
var buff = buffer_load("gameplay_surface.buf");
var surf = surface_create(surface_get_width(application_surface), surface_get_height(application_surface));
buffer_set_surface(buff, surf, 0, 0, 0);


//draw surface
draw_surface(surf, 0, 0);   


//destroy buffer and surface
buffer_delete(buff);
surface_free(surf);

#endregion


#region //fade out screen a little

draw_set_color(c_black);
draw_set_alpha(0.35);
draw_rectangle(0, 0, surface_get_width(application_surface), surface_get_height(application_surface), false);
draw_set_alpha(1);

#endregion
 

NightFrost

Member
I've done tabbed navigation in the following manner:
  • Navigation is one single object that knows the width and height of the area where the tabs are displayed, and has an array for all data of tabs to display.
  • On mouseclick, it first checks with point_in_rectangle against height and width whether pointer is over it. If so, it loops through tab array and does same comparison against size of each tab.
    • If a match is found, the navigator now knows which tab was clicked. To display correct content, I have used both instance destruction/creation as well as instance activation/deactivation.
  • You obviously know what each tab should contain so attaching content to each tab is straightforward.
    • If you create/destroy instances of content, array for tabs also contains list of objects, and it catches instance id of each when created so it can destroy them afterwards.
    • If you activate/deactivate, you create all the instances when room is entered and save their instance id values to navigator's variables under correct tab. (You don't inhabit room editor with them because you want to get their ids easily.)
  • The draw event simply loops through the tabs array and draws tabs and names in order. A variable-width tab visual is usually made with nine-slicing.
  • Displaying tab content belongs to contained instances, so the navigator will not care about that. It would draw the necessary background if any is needed, like a card or simple borders. The navigator would have to be on a lower layer to ensure this background draws under the content.
 
Top