Thanks to visit codestin.com
Credit goes to github.com

Skip to content

MajorGUI - Retained-Mode Canvas Based Hierarchical GUI Library for GameMaker

License

Notifications You must be signed in to change notification settings

erkan612/MajorGUI_GML

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

92 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MajorGUI

A comprehensive GUI library for GameMaker

License Platform Version


Table of Contents


Introduction

MajorGUI is a comprehensive GUI library for GameMaker that provides a hierarchical, canvas-based system for creating complex user interfaces.

Features:

  • Retained-mode architecture
  • Automatic layout management
  • Extensive styling options
  • Wide variety of UI components (buttons, checkboxes, sliders, menus, etc.)

Setup and Basic Usage

// Create instance
Major = new MajorGUI();

// Setup with screen size
screenSizeWidth = 1310;
screenSizeHeight = 700;
Major.Setup(new Vector2(screenSizeWidth, screenSizeHeight));

// Update each frame (Step Event)
Major.Update();

// Draw each frame (Draw GUI Event)
Major.Draw();

// Cleanup (Clean Up Event)
Major.Free();
delete Major;

Core Concepts

Vector Types

  • Vector2(x, y) – 2D position/size
  • Vector3(x, y, z) – 3D position with Z-ordering
  • Vector4(x, y, z, w) – Color with alpha (RGBA)
  • Align(horizontal, vertical) – Alignment constants

Element States

enum CLICKABLE_STATE {
    DISABLED = 0, 
    IDLE = 1, 
    HOVER = 2, 
    HOT = 3
};

Alignment Constants

enum ALIGN {
    LEFT = 0, CENTER = 1, RIGHT = 2, 
    TOP = 3, MIDDLE = 4, BOTTOM = 5
};

UI Elements

Button

var button = Major.ButtonCreate(
    new Vector3(x, y, z),
    "Button Text",
    parent,
    function(btn) { show_debug_message("Clicked!"); },
    new Vector2(width, height)
);

Methods:

  • ButtonGetText(button)
  • ButtonSetText(button, "New Text")
  • ButtonGetState(button)
  • ButtonEnable(button) / ButtonDisable(button)

Checkbox

var checkbox = Major.CheckboxCreate(
    new Vector3(x, y, z),
    parent,
    new Vector2(16, 16),
    function(cb) {
        show_debug_message("Checked: " + Major.CheckboxGetCheck(cb));
    }
);

Methods:

  • CheckboxGetCheck(checkbox)
  • CheckboxSetCheck(checkbox, true/false)

Label

var label = Major.LabelCreate(
    new Vector3(x, y, z),
    "Label Text",
    parent,
    200,
    wrapped_text.dots,
    new Vector4(255, 255, 255, 255),
    customFont
);

Methods:

  • LabelSetText(label, "New Text")
  • LabelSetColor(label, new Vector4(r, g, b, a))
  • LabelSetFont(label, font)

Radiobox & Selectable Groups

// Create group
var group = Major.SelectableGroupCreate();

// Create radioboxes
var radio1 = Major.SelectableGroupCreateRadiobox(
    group, new Vector3(x, y, z), parent
);
var radio2 = Major.SelectableGroupCreateRadiobox(
    group, new Vector3(x, y, z), parent
);

// Set selected
Major.SelectableGroupSetSelected(group, radio1);

Slidebar/Slider

var slidebar = Major.SlidebarCreate(
    new Vector3(x, y, z),    // Position
    parent,                  // Parent
    0, 100,                  // Min, Max values
    0.5,                     // Initial percentage
    200,                     // Length
    20                       // Width
);

var slider = Major.SliderCreate(
    new Vector3(x, y, z),    // Position
    parent,                  // Parent
    0, 100,                  // Min, Max values
    0.5,                     // Initial percentage
    200,                     // Length
    8, 20                    // Width, Height
);

Methods:

  • SlidebarGetValue(slidebar)
  • SlidebarSetValue(slidebar, 75)
  • SlidebarGetPercentage(slidebar)
  • SlidebarSetPercentage(slidebar, 0.8)

Textbox

// Modern Textbox (Recommended)
var textbox = Major.TextboxCreate(
    new Vector3(x, y, z),    // Position
    new Vector2(200, 28),    // Size
    parent                   // Parent
);

// Legacy Textbox (Deprecated)
var textboxDp = Major.TextboxDpCreate(
    new Vector3(x, y, z),    // Position
    new Vector2(200, 28),    // Size
    parent                   // Parent
);

Methods:

  • TextboxSetText(textbox, "Text")
  • TextboxGetText(textbox)
  • TextboxSetGhostText(textbox, "Placeholder")
  • TextboxSetMultiline(textbox, true)
  • TextboxSetPassword(textbox, true)
  • TextboxSetFocus(textbox, true)

Combobox

var combobox = Major.ComboboxCreate(
    new Vector3(x, y, z),    // Position
    "Select Option",         // Default text
    parent,                  // Parent
    new Vector2(124, 24)     // Size
);

// Add options
Major.ComboboxPush(combobox, "Option 1");
Major.ComboboxPush(combobox, "Option 2");

// Select programmatically
Major.ComboboxSelect(combobox, optionElement);

Comboswitch

var comboswitch = Major.ComboswitchCreate(
    new Vector3(x, y, z),    // Position
    parent,                  // Parent
    function(state) {        // State change callback
        show_debug_message("State changed");
    },
    250, 30                  // Width, Height
);

// Add options
Major.ComboswitchPush(comboswitch, "Setting 1");
Major.ComboswitchPush(comboswitch, "Setting 2");

// Get current selection
var current = Major.ComboswitchCurrent(comboswitch);

Menu System

// Create menu
var menu = Major.MenuCreate();

// Build menu structure
Major.MenuPush(menu);
Major.MenuItem(menu, "Action 1", "Ctrl+A", sprite);
Major.MenuItem(menu, "Action 2", "Ctrl+B");
Major.MenuCheckbox(menu, "Toggle Option", "Info");
Major.MenuSeparator(menu, "Section");
Major.MenuPop(menu);

// Show menu
if (mouse_check_button_pressed(mb_right)) {
    Major.MenuShow(menu, new Vector2(mouse_x, mouse_y));
}

// Update menu (in Step Event)
Major.MenuUpdateMouse(menu);

Sprite

var sprite = Major.SpriteCreate(
    new Vector3(x, y, z),    // Position
    spriteIndex,             // Sprite asset
    0,                       // Starting frame
    1,                       // Animation speed
    parent,                  // Parent
    function(spr) {          // Click callback
        show_debug_message("Sprite clicked");
    }
);

TableChart

var table = Major.TableChartCreate(
    new Vector3(x, y, z),    // Position
    new Vector2(500, 200),   // Size
    [                        // Headers [text, portion]
        ["Name", 1], 
        ["Score", 1], 
        ["Level", 1]
    ],
    [                        // Data rows
        ["Player1", "100", "5"],
        ["Player2", "85", "3"]
    ],
    parent                   // Parent
);

TreeView

var treeView = Major.TreeViewCreate(
    new Vector3(x, y, z),    // position
    new Vector2(256, 1024),  // size
    parent                   // parent
);

Major.TreeViewPushParentNode(treeView, "Test 1");

Major.TreeViewAddChildNode(treeView, "Test 2");
Major.TreeViewAddChildNode(treeView, "Test 3");

Major.TreeViewPushParentNode(treeView, "Test 7");

Major.TreeViewAddChildNode(treeView, "Test 8");

Major.TreeViewPushParentNode(treeView, "Test 9");

Major.TreeViewAddChildNode(treeView, "Test 10");
Major.TreeViewAddChildNode(treeView, "Test 11");
Major.TreeViewAddChildNode(treeView, "Test 12");

Major.TreeViewPopParentNode(treeView);

Major.TreeViewPopParentNode(treeView);

Major.TreeViewPopParentNode(treeView);

Major.TreeViewPushParentNode(treeView, "Test 4");
Major.TreeViewAddChildNode(treeView, "Test 5");
Major.TreeViewAddChildNode(treeView, "Test 6");
Major.TreeViewPopParentNode(treeView);

Layout System

Panel System

The panel system provides automatic layout management:

// Create panel
var panel = Major.PanelCreate(
    new Vector3(x, y, z),    // Position
    new Vector2(5, 5),       // Gap between elements
    false,                   // Auto-fit to content
    parent,                  // Parent
    new Vector4(0, 0, 0, 0), // Background color
    new Vector2(300, 400)    // Size
);

// Push new layout section(works as new line)
Major.PanelPush(panel, "Section Title", 1, true);

// Add elements to current section
Major.PanelElementCreate(panel, buttonElement, 1, false);
Major.PanelElementCreate(panel, labelElement, 2, true);

// Pop section
Major.PanelPop(panel);

Panel Methods:

  • PanelPush(panel, title, placement, autoFit) - Start new section
  • PanelPop(panel) - End current section
  • PanelElementCreate(panel, element, placement, autoFit, align) - Add element
  • PanelTitleToggle(title) - Toggle section visibility
  • PanelRefresh(panel) - Force layout update

Scrollbars

// Add scrollbars to panel
var scrollbarV = Major.ScrollbarVerticalCreate(
    new Vector3(x, y, z),    // Position
    targetPanel,             // Panel to scroll
    new Vector2(10, height), // Size
    parent                   // Parent
);

var scrollbarH = Major.ScrollbarHorizontalCreate(
    new Vector3(x, y, z),    // Position
    targetPanel,             // Panel to scroll  
    new Vector2(width, 10),  // Size
    parent                   // Parent
);

// Configure scrollbars
Major.ScrollbarSetLerpFactor(scrollbarV, 0.1); // Smooth scrolling
ElementSetProperty(panel, scrollbarV, "m_scrollbarVertical");
ElementSetProperty(panel, 2000, "m_scrollbarVerticalSteps");

Advanced Features

Custom Styling

Each element type has customizable styler functions:

// Custom button style
var customButtonStyle = function(fm_button) {
    // Custom drawing code
    var state = Major.ButtonGetState(fm_button);
    var color = c_white;
    
    switch (state) {
        case CLICKABLE_STATE.HOVER: color = c_yellow; break;
        case CLICKABLE_STATE.HOT: color = c_red; break;
    }
    
    draw_set_color(color);
    draw_rectangle(0, 0, 
        Major.CanvasGetSize(fm_button).x,
        Major.CanvasGetSize(fm_button).y, 
        false
    );
};

var button = Major.ButtonCreate(
    position, text, parent, onClick, size,
    STYLER_BUTTON_UPDATE_BEFORE,  // Keep default update
    STYLER_BUTTON_UPDATE_AFTER,
    customButtonStyle,           // Custom draw before
    STYLER_BUTTON_DRAW_AFTER
);

Event Handling

// Click events
var button = Major.ButtonCreate(position, "Click Me", parent, 
    function(btn) {
        show_debug_message("Button clicked: " + Major.ButtonGetText(btn));
    }
);

// Double-click on selectables
var selectable = Major.SelectableCreate(position, "Item", parent);
Major.SelectableSetDoubleClickAction(selectable, 
    function(sel) {
        show_debug_message("Double clicked: " + Major.SelectableGetName(sel));
    }
);

// State change events
Major.CanvasAddStateEvent(element, CLICKABLE_STATE.HOVER,
    function(el) {
        show_debug_message("Element hovered");
    }
);

Dynamic UI Creation

var dynamicPanel = noone;
var panelVisible = false;

var toggleButton = Major.ButtonCreate(position, "Toggle Panel", parent,
    function(btn) {
        if (!panelVisible) {
            // Create panel dynamically
            Major.PanelPush(mainPanel);
            dynamicPanel = Major.PanelElementCreate(mainPanel,
                Major.PanelCreate(undefined, undefined, undefined, mainPanel)
            );
            Major.PanelPop(mainPanel);
            
            // Add content to dynamic panel
            Major.PanelPush(dynamicPanel);
            Major.PanelElementCreate(dynamicPanel,
                Major.LabelCreate(undefined, "Dynamic Content!", dynamicPanel)
            );
            Major.PanelPop(dynamicPanel);
        } else {
            // Remove dynamic panel
            Major.ElementFree(dynamicPanel);
        }
        panelVisible = !panelVisible;
    }
);

API Reference

Core Methods

  • Setup(screenSize) - Initialize GUI system
  • Update() - Update all elements (call in Step Event)
  • Draw() - Draw all elements (call in Draw GUI Event)
  • Free()- Clean up resources (call in Clean Up Event)

Element Management

  • CanvasCreate(position, size, color, parent) - Create base canvas
  • ElementFree(element) - Destroy element and children
  • CanvasActivate(element) / CanvasDeactivate(element) - Show/hide elements
  • CanvasSetPosition(element, position)
  • CanvasSetSize(element, size)
  • CanvasSetAlignment(element, align)

Utility Functions

  • GetHoverCanvas(root, mouseX, mouseY) - Get element under mouse
  • IsHoverCanvasOptimized(element) - Check if element is hovered
  • SortCanvasListByZOrder(list) - Sort by Z-order
  • FindNthOccurrenceOfString(str, substr, n) - String utility

Best Practices

  1. Always call Setup() before use and Free() when done
  2. Use panels for complex layouts rather than manual positioning
  3. Set proper Z-ordering for overlapping elements
  4. Use scrollbars for large content within fixed-size containers
  5. Clean up dynamically created elements with ElementFree()
  6. Use the modern Textbox instead of TextboxDp (deprecated)
  7. Handle menu cleanup with MenuFree() when done

Performance Tips

  • Use CanvasDeactivate() for hidden elements
  • Set appropriate lerpFactor on scrollbars (0.1 for smooth, 1.0 for instant)
  • Use panels with auto-fit for dynamic content
  • Avoid deeply nested hierarchies when possible
  • Use SelectableGroup for radio button management

Step by Step Examples

Simple Button

We start by initializing our GUI by calling

Major = new MajorGUI();
Major.Setup(new Vector2(800, 600));

After that we can just go ahead and create our button

helloButton = Major.ButtonCreate(
    new Vector3(350, 250, 0),
    "Click Me!",
    noone,
    function(btn) {
        show_debug_message("Hello World!");
    },
    new Vector2(100, 40)
);

In Step event:

Major.Update();

DrawGUI Event:

Major.Draw();

And Clean Up Event:

Major.Free();

We will be dealing with Create Event most of the time, here is the full code of Create Event:

Major = new MajorGUI();
Major.Setup(new Vector2(800, 600));

// Create a simple button
helloButton = Major.ButtonCreate(
    new Vector3(350, 250, 0),
    "Click Me!",
    noone,
    function(btn) {
        show_debug_message("Hello World!");
    },
    new Vector2(100, 40)
);
example1.mp4

Settings Panel

In MajorGUI we use Panel class for automatic layouts. After initializing our gui here's how we create our panel

settingsPanel = Major.PanelCreate(
    new Vector3(200, 100, 0),
    new Vector2(10, 10),
    false,
    noone,
    undefined,
    new Vector2(400, 400)
);

Now we're ready to add elements into our panel using MajorGUI.PanelPush() and MajorGUI.Pop() In the beginning it might be confusing but once you understand how it works, it will make more sense. Each call of PanelPush() is a new line but you need to end the line once you're done with it. To do so call PanelPop(). Multiple lines can be pushed in one push. What does that mean? Here's an example:

Major.PanelPush(panel);
    // add a button here
    Major.PanelPush(panel);
        // add a second button here
    Major.PanelPop(panel);
Major.PanelPop(panel);

In the example above there will be two lines, each line having one buttons but the second line will be child of the first line. If we were to make the first push a Title, in that case closing the title would've also close the second line.

To add an element into a panel is simple, just by calling MajorGUI.PanelElementCreate(). Now lets create our settings interface

Major.PanelPush(settingsPanel, "Display Settings");
	Major.PanelPush(settingsPanel);
	    // Fullscreen checkbox
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "Fullscreen", settingsPanel)
	    );
	    fullscreenCheckbox = Major.PanelElementCreate(settingsPanel,
	        Major.CheckboxCreate(undefined, settingsPanel)
	    );
	Major.PanelPop(settingsPanel);
	Major.PanelPush(settingsPanel);
	    // Resolution combobox
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "Resolution", settingsPanel)
	    );
	    resolutionCombo = Major.PanelElementCreate(settingsPanel,
	        Major.ComboboxCreate(undefined, "Select", settingsPanel)
	    );
    
	    // Add resolution options
	    Major.ComboboxPush(resolutionCombo, "1920x1080");
	    Major.ComboboxPush(resolutionCombo, "1366x768");
	    Major.ComboboxPush(resolutionCombo, "1280x720");
	Major.PanelPop(settingsPanel);
Major.PanelPop(settingsPanel);

Major.PanelPush(settingsPanel, "Audio Settings");
	Major.PanelPush(settingsPanel);
	    // Music volume slider
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "Music Volume", settingsPanel)
	    );
	    musicSlider = Major.PanelElementCreate(settingsPanel,
	        Major.SlidebarCreate(undefined, settingsPanel, 0, 100, 0.8, 200)
	    );
	Major.PanelPop(settingsPanel);
	Major.PanelPush(settingsPanel);
    
	    // SFX volume slider  
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "SFX Volume", settingsPanel)
	    );
	    sfxSlider = Major.PanelElementCreate(settingsPanel,
	        Major.SlidebarCreate(undefined, settingsPanel, 0, 100, 0.6, 200)
	    );
	Major.PanelPop(settingsPanel);
Major.PanelPop(settingsPanel);

// Save button
Major.PanelPush(settingsPanel, undefined, undefined, true);
    saveButton = Major.PanelElementCreate(settingsPanel,
        Major.ButtonCreate(undefined, "Save Settings", settingsPanel,
            function(btn) {
                // Apply settings
                var fullscreen = Major.CheckboxGetCheck(fullscreenCheckbox);
                var musicVol = Major.SlidebarGetValue(musicSlider);
                var sfxVol = Major.SlidebarGetValue(sfxSlider);
                
                show_debug_message("Settings Saved:");
                show_debug_message("Fullscreen: " + string(fullscreen));
                show_debug_message("Music Volume: " + string(musicVol));
                show_debug_message("SFX Volume: " + string(sfxVol));
                
                // Apply to game (pseudo-code)
                // audio_master_gain(musicVol / 100);
                // window_set_fullscreen(fullscreen);
            }
        ), 
        undefined, true
    );
Major.PanelPop(settingsPanel);

// Load saved settings (pseudo-code)
Major.CheckboxSetCheck(fullscreenCheckbox, global.fullscreen);
Major.SlidebarSetValue(musicSlider, global.musicVolume);
Major.SlidebarSetValue(sfxSlider, global.sfxVolume);

After that we can just access it in our step event

Major.Update();

// Apply real-time volume changes
audio_master_gain(Major.SlidebarGetValue(musicSlider) / 100);

Here's the complete Create Event code:

Major = new MajorGUI();
Major.Setup(new Vector2(800, 600));

global.fullscreen = false;
global.musicVolume = false;
global.sfxVolume = false;

// Create settings panel
settingsPanel = Major.PanelCreate(
    new Vector3(200, 100, 0),
    new Vector2(10, 10),
    false,
    noone,
    undefined,
    new Vector2(400, 400)
);

// Build settings interface
Major.PanelPush(settingsPanel, "Display Settings");
	Major.PanelPush(settingsPanel);
	    // Fullscreen checkbox
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "Fullscreen", settingsPanel)
	    );
	    fullscreenCheckbox = Major.PanelElementCreate(settingsPanel,
	        Major.CheckboxCreate(undefined, settingsPanel)
	    );
	Major.PanelPop(settingsPanel);
	Major.PanelPush(settingsPanel);
	    // Resolution combobox
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "Resolution", settingsPanel)
	    );
	    resolutionCombo = Major.PanelElementCreate(settingsPanel,
	        Major.ComboboxCreate(undefined, "Select", settingsPanel)
	    );
    
	    // Add resolution options
	    Major.ComboboxPush(resolutionCombo, "1920x1080");
	    Major.ComboboxPush(resolutionCombo, "1366x768");
	    Major.ComboboxPush(resolutionCombo, "1280x720");
	Major.PanelPop(settingsPanel);
Major.PanelPop(settingsPanel);

Major.PanelPush(settingsPanel, "Audio Settings");
	Major.PanelPush(settingsPanel);
	    // Music volume slider
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "Music Volume", settingsPanel)
	    );
	    musicSlider = Major.PanelElementCreate(settingsPanel,
	        Major.SlidebarCreate(undefined, settingsPanel, 0, 100, 0.8, 200)
	    );
	Major.PanelPop(settingsPanel);
	Major.PanelPush(settingsPanel);
    
	    // SFX volume slider  
	    Major.PanelElementCreate(settingsPanel,
	        Major.LabelCreate(undefined, "SFX Volume", settingsPanel)
	    );
	    sfxSlider = Major.PanelElementCreate(settingsPanel,
	        Major.SlidebarCreate(undefined, settingsPanel, 0, 100, 0.6, 200)
	    );
	Major.PanelPop(settingsPanel);
Major.PanelPop(settingsPanel);

// Save button
Major.PanelPush(settingsPanel, undefined, undefined, true);
    saveButton = Major.PanelElementCreate(settingsPanel,
        Major.ButtonCreate(undefined, "Save Settings", settingsPanel,
            function(btn) {
                // Apply settings
                var fullscreen = Major.CheckboxGetCheck(fullscreenCheckbox);
                var musicVol = Major.SlidebarGetValue(musicSlider);
                var sfxVol = Major.SlidebarGetValue(sfxSlider);
                
                show_debug_message("Settings Saved:");
                show_debug_message("Fullscreen: " + string(fullscreen));
                show_debug_message("Music Volume: " + string(musicVol));
                show_debug_message("SFX Volume: " + string(sfxVol));
                
                // Apply to game (pseudo-code)
                // audio_master_gain(musicVol / 100);
                // window_set_fullscreen(fullscreen);
            }
        ), 
        undefined, true
    );
Major.PanelPop(settingsPanel);

// Load saved settings (pseudo-code)
Major.CheckboxSetCheck(fullscreenCheckbox, global.fullscreen);
Major.SlidebarSetValue(musicSlider, global.musicVolume);
Major.SlidebarSetValue(sfxSlider, global.sfxVolume);
example2.mp4

Simple Contact Form

Major = new MajorGUI();
Major.Setup(new Vector2(800, 600));

// Simple contact form
formPanel = Major.PanelCreate(
    new Vector3(50, 50, 0),
    new Vector2(10, 10),
    false,
    noone,
    undefined,
    new Vector2(500, 300)
);

Major.PanelPush(formPanel, "Contact Form");
	Major.PanelPush(formPanel);
	    // Name
	    Major.PanelElementCreate(formPanel,
	        Major.LabelCreate(undefined, "Name:", formPanel)
	    );
	    nameInput = Major.PanelElementCreate(formPanel,
	        Major.TextboxCreate(undefined, new Vector2(200, 28), formPanel)
	    );
	
	Major.PanelPop(formPanel);
	Major.PanelPush(formPanel);
    
	    // Email
	    Major.PanelElementCreate(formPanel,
	        Major.LabelCreate(undefined, "Email:", formPanel)
	    );
	    emailInput = Major.PanelElementCreate(formPanel,
	        Major.TextboxCreate(undefined, new Vector2(200, 28), formPanel)
	    );
	
	Major.PanelPop(formPanel);
	Major.PanelPush(formPanel);
    
	    // Message
	    Major.PanelElementCreate(formPanel,
	        Major.LabelCreate(undefined, "Message:", formPanel)
	    );
	    messageInput = Major.PanelElementCreate(formPanel,
	        Major.TextboxCreate(undefined, new Vector2(300, 100), formPanel)
	    );
	    Major.TextboxSetMultiline(messageInput, true);
	
	Major.PanelPop(formPanel);
	Major.PanelPush(formPanel);
    
	    // Submit button
	    Major.PanelPush(formPanel, undefined, undefined, true);
	        submitButton = Major.PanelElementCreate(formPanel,
	            Major.ButtonCreate(undefined, "Send Message", formPanel,
	                function(btn) {
	                    var name = Major.TextboxGetText(nameInput);
	                    var email = Major.TextboxGetText(emailInput);
	                    var message = Major.TextboxGetText(messageInput);
                    
	                    show_debug_message("Message sent!");
	                    show_debug_message("From: " + name);
	                    show_debug_message("Email: " + email);
	                    show_debug_message("Message:\n" + message);
	                }
	            ), undefined, true
	        );
	    Major.PanelPop(formPanel);
	Major.PanelPop(formPanel);
Major.PanelPop(formPanel);
example3.mp4

Color Picker

Major = new MajorGUI();
Major.Setup(new Vector2(800, 600));

// Color picker
colorPanel = Major.PanelCreate(
    new Vector3(50, 50, 0),
    new Vector2(10, 10),
    false,
    undefined,
    undefined,
    new Vector2(500, 300)
);

//   |--------------------------------------------------------------|            
//   | |---------------||  Red   [------------------------------]   |            
//   | |               ||                                           |            
//   | |<COLOR CANVAS> ||  Green [------------------------------]   |            
//   | |               ||                                           |            
//   | |               ||  Blue  [------------------------------]   |            
//   | |---------------||                                           |            
//   |--------------------------------------------------------------|            
//   | |----------------------------------------------------------| |            
//   | |                      Randomize                           | |            
//   | |----------------------------------------------------------| |            
//   |                                                              |            
//   |                                                              |            
//   |                                                              |            
//   |                                                              |            
//   |--------------------------------------------------------------|            

// Split main panel into 2 up-down, split up into two left-right
panelUpLeft = undefined;
panelUpRight = undefined;
panelDown = undefined;

Major.PanelPush(colorPanel, "Color Picker");
	Major.PanelPush(colorPanel, undefined, undefined, true);
		panelUpLeft = Major.PanelElementCreate(
			colorPanel, 
			Major.PanelCreate(undefined, undefined, true, colorPanel, undefined, new Vector2(1, 100)), 
			0.5, 
			true
		);
		
		panelUpRight = Major.PanelElementCreate(
			colorPanel, 
			Major.PanelCreate(undefined, undefined, false, colorPanel, undefined, new Vector2(1, 100)), 
			1, 
			true
		);
	Major.PanelPop(colorPanel);
	
	Major.PanelPush(colorPanel, undefined, undefined, true);
		panelDown = Major.PanelElementCreate(
			colorPanel, 
			Major.PanelCreate(undefined, undefined, false, colorPanel, undefined, new Vector2(1, 100)), 
			undefined, 
			true
		);
	Major.PanelPop(colorPanel);
Major.PanelPop(colorPanel);

Major.PanelPush(panelUpLeft, undefined, undefined, true);
	colorCanvas = Major.PanelElementCreate(
		panelUpLeft,
		Major.CanvasCreate(undefined, undefined, new Vector4(255, 255, 255, 255), panelUpLeft), 
		undefined,
		true
	);
Major.PanelPop(panelUpLeft);

Major.PanelPush(panelUpRight, undefined, undefined, true);
	Major.PanelElementCreate(
		panelUpRight,
		Major.LabelCreate(undefined, "Red", panelUpRight), 
		0.2
	);
	sliderRed = Major.PanelElementCreate(
		panelUpRight,
		Major.SliderCreate(undefined, panelUpRight, 0, 255, 1), 
		1, 
		true
	);
Major.PanelPop(panelUpRight);

Major.PanelPush(panelUpRight, undefined, undefined, true);
	Major.PanelElementCreate(
		panelUpRight,
		Major.LabelCreate(undefined, "Green", panelUpRight), 
		0.2
	);
	sliderGreen = Major.PanelElementCreate(
		panelUpRight,
		Major.SliderCreate(undefined, panelUpRight, 0, 255, 1), 
		1, 
		true
	);
Major.PanelPop(panelUpRight);

Major.PanelPush(panelUpRight, undefined, undefined, true);
	Major.PanelElementCreate(
		panelUpRight,
		Major.LabelCreate(undefined, "Blue", panelUpRight), 
		0.2
	);
	sliderBlue = Major.PanelElementCreate(
		panelUpRight,
		Major.SliderCreate(undefined, panelUpRight, 0, 255, 1), 
		1, 
		true
	);
Major.PanelPop(panelUpRight);

Major.PanelPush(panelDown, undefined, undefined, true);
	Major.PanelElementCreate(
		panelDown,
		Major.ButtonCreate(undefined, "Randomize", panelDown, function(element) {
			ObjectOfExample4.Major.SliderSetValue(ObjectOfExample4.sliderRed, floor(random(255)));
			ObjectOfExample4.Major.SliderSetValue(ObjectOfExample4.sliderGreen, floor(random(255)));
			ObjectOfExample4.Major.SliderSetValue(ObjectOfExample4.sliderBlue, floor(random(255)));
		}), 
		undefined, 
		true
	);
Major.PanelPop(panelDown);
Major.Update();

Major.CanvasSetBackgroundColor(colorCanvas, new Vector4(
														Major.SliderGetValue(sliderRed), 
														Major.SliderGetValue(sliderGreen), 
														Major.SliderGetValue(sliderBlue), 
														255
														));
example4.mp4

Stylizing

What makes MajorGUI special is that it uses canvas-based element system. Meaning that every element has its own canvas(a surface). This makes it special for games that require complex GUI system since surfaces can be customized limitlessly. Beside the colors and basic settings MajorGUI also offers to set custom Update and Draw functions for each element. Funcions below can be used:

Major.CanvasSetBeforeUpdate()
Major.CanvasSetAfterUpdate()
Major.CanvasSetBeforeDraw()
Major.CanvasSetAfterDraw()

Difference between Before and After is that 'Before' is being called before updating/drawing the children, and 'After' is being called after updating/drawing the children. But this will only allow you to change style of only specific elements. In order to change style of buttons without calling the functions above, you'd have to change the main styler functions of MajorGUI class. An example below:

Major = new MajorGUI();
Major.Setup(new Vector2(800, 600));

Major.STYLER_BUTTON_DRAW_BEFORE = function(button) {
	var class = ElementGetProperty(button, "MajorGUI");
	var state = class.ButtonGetState(button);
	
	var color = noone;
	switch (state) {
	case CLICKABLE_STATE.DISABLED: {
		// Muted gray, slightly transparent
		color = new Vector4(80, 80, 80, 128);
	} break;
	case CLICKABLE_STATE.IDLE: {
		// Neutral dark gray
		color = new Vector4(45, 45, 48, 255);
	} break;
	case CLICKABLE_STATE.HOVER: {
		// Brighter blue highlight
		color = new Vector4(70, 130, 180, 255); // steel blue
	} break;
	case CLICKABLE_STATE.HOT: {
		// Stronger accent (darker blue)
		color = new Vector4(40, 90, 150, 255);
	} break;
	};
	
	draw_set_color(make_color_rgb(color.x, color.y, color.z));
	draw_set_alpha(color.w / 255);
	draw_rectangle(0, 0, class.CanvasGetSize(button).x, class.CanvasGetSize(button).y, false);
	draw_set_alpha(1);
	draw_set_color(c_white);
};

// Create a simple button
helloButton = Major.ButtonCreate(
    new Vector3(350, 250, 0),
    "Click Me!",
    noone,
    function(btn) {
        show_debug_message("Hello World!");
    },
    new Vector2(100, 40)
);
example1-styling.mp4

Here's the list of every styler name of the MajorGUI class:

STYLER_BUTTON_UPDATE_BEFORE
STYLER_BUTTON_UPDATE_AFTER
STYLER_BUTTON_DRAW_BEFORE
STYLER_BUTTON_DRAW_AFTER

STYLER_CHECKBOX_UPDATE_BEFORE
STYLER_CHECKBOX_UPDATE_AFTER
STYLER_CHECKBOX_DRAW_BEFORE
STYLER_CHECKBOX_DRAW_AFTER

STYLER_LABEL_UPDATE_BEFORE
STYLER_LABEL_UPDATE_AFTER
STYLER_LABEL_DRAW_BEFORE
STYLER_LABEL_DRAW_AFTER

STYLER_RADIOBOX_UPDATE_BEFORE
STYLER_RADIOBOX_UPDATE_AFTER
STYLER_RADIOBOX_DRAW_BEFORE
STYLER_RADIOBOX_DRAW_AFTER

STYLER_SLIDEBAR_UPDATE_BEFORE
STYLER_SLIDEBAR_UPDATE_AFTER
STYLER_SLIDEBAR_DRAW_BEFORE
STYLER_SLIDEBAR_DRAW_AFTER

STYLER_PANEL_UPDATE_BEFORE
STYLER_PANEL_UPDATE_AFTER
STYLER_PANEL_DRAW_BEFORE
STYLER_PANEL_DRAW_AFTER

STYLER_PANELTITLE_UPDATE_BEFORE
STYLER_PANELTITLE_UPDATE_AFTER
STYLER_PANELTITLE_DRAW_BEFORE
STYLER_PANELTITLE_DRAW_AFTER

STYLER_SCROLLBARVERTICALBACKGROUND_UPDATE_BEFORE
STYLER_SCROLLBARVERTICALBACKGROUND_UPDATE_AFTER
STYLER_SCROLLBARVERTICALBACKGROUND_DRAW_BEFORE
STYLER_SCROLLBARVERTICALBACKGROUND_DRAW_AFTER

STYLER_SCROLLBARVERTICALANCHOR_UPDATE_BEFORE
STYLER_SCROLLBARVERTICALANCHOR_UPDATE_AFTER
STYLER_SCROLLBARVERTICALANCHOR_DRAW_BEFORE
STYLER_SCROLLBARVERTICALANCHOR_DRAW_AFTER

STYLER_SCROLLBARHORIZONTALBACKGROUND_UPDATE_BEFORE
STYLER_SCROLLBARHORIZONTALBACKGROUND_UPDATE_AFTER
STYLER_SCROLLBARHORIZONTALBACKGROUND_DRAW_BEFORE
STYLER_SCROLLBARHORIZONTALBACKGROUND_DRAW_AFTER

STYLER_SCROLLBARHORIZONTALANCHOR_UPDATE_BEFORE
STYLER_SCROLLBARHORIZONTALANCHOR_UPDATE_AFTER
STYLER_SCROLLBARHORIZONTALANCHOR_DRAW_BEFORE
STYLER_SCROLLBARHORIZONTALANCHOR_DRAW_AFTER

STYLER_SELECTABLE_UPDATE_BEFORE
STYLER_SELECTABLE_UPDATE_AFTER
STYLER_SELECTABLE_DRAW_BEFORE
STYLER_SELECTABLE_DRAW_AFTER

STYLER_MENUCANVAS_UPDATE_BEFORE
STYLER_MENUCANVAS_UPDATE_AFTER
STYLER_MENUCANVAS_DRAW_BEFORE
STYLER_MENUCANVAS_DRAW_AFTER

STYLER_MENUPANEL_UPDATE_BEFORE
STYLER_MENUPANEL_UPDATE_AFTER
STYLER_MENUPANEL_DRAW_BEFORE
STYLER_MENUPANEL_DRAW_AFTER

STYLER_MENUITEM_UPDATE_BEFORE
STYLER_MENUITEM_UPDATE_AFTER
STYLER_MENUITEM_DRAW_BEFORE
STYLER_MENUITEM_DRAW_AFTER

STYLER_MENUSEPARATOR_UPDATE_BEFORE
STYLER_MENUSEPARATOR_UPDATE_AFTER
STYLER_MENUSEPARATOR_DRAW_BEFORE
STYLER_MENUSEPARATOR_DRAW_AFTER

STYLER_MENUTAB_UPDATE_BEFORE
STYLER_MENUTAB_UPDATE_AFTER
STYLER_MENUTAB_DRAW_BEFORE
STYLER_MENUTAB_DRAW_AFTER

STYLER_MENUCHECKBOX_UPDATE_BEFORE
STYLER_MENUCHECKBOX_UPDATE_AFTER
STYLER_MENUCHECKBOX_DRAW_BEFORE
STYLER_MENUCHECKBOX_DRAW_AFTER

STYLER_TEXTBOX_UPDATE_BEFORE
STYLER_TEXTBOX_UPDATE_AFTER
STYLER_TEXTBOX_DRAW_BEFORE
STYLER_TEXTBOX_DRAW_AFTER

STYLER_COMBOBOX_UPDATE_BEFORE
STYLER_COMBOBOX_UPDATE_AFTER
STYLER_COMBOBOX_DRAW_BEFORE
STYLER_COMBOBOX_DRAW_AFTER

STYLER_COMBOSWTICH_MIDCANVAS_UPDATE_BEFORE
STYLER_COMBOSWTICH_MIDCANVAS_UPDATE_AFTER
STYLER_COMBOSWTICH_MIDCANVAS_DRAW_BEFORE
STYLER_COMBOSWTICH_MIDCANVAS_DRAW_AFTER

STYLER_SLIDER_UPDATE_BEFORE
STYLER_SLIDER_UPDATE_AFTER
STYLER_SLIDER_DRAW_BEFORE
STYLER_SLIDER_DRAW_AFTER

STYLER_SPRITE_UPDATE_BEFORE
STYLER_SPRITE_UPDATE_AFTER
STYLER_SPRITE_DRAW_BEFORE
STYLER_SPRITE_DRAW_AFTER

STYLER_TREEVIEWCHECKBOX_UPDATE_BEFORE
STYLER_TREEVIEWCHECKBOX_UPDATE_AFTER
STYLER_TREEVIEWCHECKBOX_DRAW_BEFORE
STYLER_TREEVIEWCHECKBOX_DRAW_AFTER

Notes

As I've said above, MajorGUI uses canvas-based element system. Each element having its own canvas(surface) can be heavy in the performance(especially considering its updating everything real-time). Optimization of GUI should be prioritized when using MajorGUI.




About

MajorGUI - Retained-Mode Canvas Based Hierarchical GUI Library for GameMaker

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published