O
orSQUADstra
Guest
Hi, and welcome to the guide of making your own Shell program for GM OS. Please note that this thread will get edited regularly to be up-to-date with the newest functions and/or changes of the OS.
The GM OS Project
The basics
First of all, what are Shell programs?
Shell programs are folders with the ending of ".shl". These folders are recognized as a program by GM OS.
A Shell folder should contain two files: A text file named "shellcode.txt", which contains code written in GML, and an image named "shellicon.txt". The names should be exactly these, otherwise the OS won't read them. Having the shellicon.png is optional.
Preset fontsA Shell folder should contain two files: A text file named "shellcode.txt", which contains code written in GML, and an image named "shellicon.txt". The names should be exactly these, otherwise the OS won't read them. Having the shellicon.png is optional.
Here are the fonts that are set in the project file. If you feel like you need to, you can set up your own fonts, or use a sprite font.
The window system
Before you would start making your Shell program, it is important to know the essential things about windows in GM OS.
The graphic above shows how the display works.
Here are the default variables set up by the shell_window_create(...) script:
Some global variables:w - the width of the window
h - the height of the window
active - either 1 or 0 - shows whether the window is active or not. It is active if the last click was inside the window. It is set automatically. You should not change it manually.
ownsequence - Part of the window ordering. Automatic. Don't change it manually.
title - The title of the window, also displayed on hover on the Dock.
resizable - 1 if the window should be resizable, or 0 if it should not.
drag - Returns 1 if the window is being dragged.
mouse_blocked - Returns 0 if the mouse isn't blocked by another window, context menu, dock, etc.
path - this is the path of your folder ending with ".shl". If you need to load sprites, you can put them in your .shl folder, and then use this variable to add the sprites.
icon - the icon of the program, "shellicon.png", or if it's not persistent, then the shell sprite that is built into the project.
dockpos - returns the position on the dock. (0 - first icon on the dock, 1 - second icon on the dock, ...)
action - handles the close, maximize, minimize buttons. Automatic, but you can change it to 1 to close the prorgam, 2 to maximize, 3 to minimize. Note: if you want to force the window to close, always use action = 1, and not instance_destroy() or anything else.
resizew - horizontal resizing. -1 if by the left side, 1 if by the right side. 0 = not being resized right now. Automatic, should not be changed manually.
resizeh - vertical resizing. -1 if by the top, 1 if by the bottom, 0 if not being resized. Automatic, don't change it manually.
Required scripts:global.theme - 0 = dark theme, 1 = light theme.
global.syscolor - the color scheme of the OS.
global.background - the background sprite.
global.titlebarheight - the height in pixels of the windows. Default is 26.
global.dockn - the number of items displayed on the Dock
global.doubleclickDelay - The delay in frames between one click and another to be counted as a doubleclick. Default is 45.
global.doubleclick - returns 1 for one frame if the user doubleclicked. Note: if the mouse is moved between two clicks, the doubleclick is automatically cancelled.
global.drag - returns 1 if the left mouse button is being held down
global.draghspeed - returns the horizontal speed of the mouse.
global.dragvspeed - returns the vertical speed of the mouse.
- shell_window_create(width (real), height (real), title (string), resizable (real)) - takes care of default variables. Should be used in Create event.
- window_step() - takes care of everything. Should be put in the Step event.
- draw_window() - takes care of drawing the base window and resizing (if enabled). Use in Draw event, preferably right in the first line.
Other useful scripts:
- point_in_region(x to check, y to check, x1, y1, x2, y2) - returns true if the specified (x, y) is in the (x1, y1, x2, y2) region, otherwise false.
- mouse_in_region(x1, y1, x2, y2) - returns true if the mouse coordinates are in the (x1, y1, x2, y2) region, otherwise false.
- get_button(x, y, w, h, str, blocked) - Use in Draw event - returns true if the mouse left button is released within the x, y, x+w, y+h area. in the "blocked" part, always put "mouse_blocked".
You might want to use context menus in your program, and of course, this is possible.
Here's what you need to know about GM OS' context menus:
- There is always only one persistent.
- If you click anywhere outside, it'll be destroyed and the variable selected will be -1
- When clicking inside, it'll return the number of the text in the selected variable. In the example above, clicking "Open" would return 0, while clicking "Properties" would return 6.
- Context menus offer you 10 string and 10 real slots to store data in. You can refer to them as storedString0 ... storedString9 and storedReal0 ... storedReal9. By default, stored reals hold 0, while strings "".
- The maximum number of listed items is 100.
- Context menus store a variable called linkedTo, which you should always set to the id of your window.
First of all, you need to create the instance objContextmenu.
Then, as the next step, set up your menues, stored variables, and most importantly the linkedTo variable.
The listed items use a 2D array, menu[n,0]. The first number is the number of the string.
Here's the usual way to do it is this:
Code:
if mouse_check_button_pressed(mb_right)
and mouse_blocked = 0
and mouse_in_region(x,y,x+w,y+h)
{
instance_create(mouse_x,mouse_y,objContextmenu)
with objContextmenu
{
linkedTo = other.id
storedReal0 = 255
storedString0 = "Just a string"
menu[0,0] = "Option 1"
menu[1,0] = "Option 2"
menu[2,0] = "Option 3"
}
}
Code:
if instance_exists(objContextmenu)
{
with objContextmenu
{
if linkedTo = other.id
{
if selected = 0 {/*Code for Option 1 here*/}
if selected = 1 {/*Code for Option 2 here*/}
if selected = 2 {/*Code for Option 3 here*/}
}
}
}
Working with text boxes
Text boxes are structured similarly to context menus.
To create a text box, use the following code:
Code:
inst = instance_create(x, y, objTextbox)
with inst
{
w = 256
h = 24
str = "Hello" //you can skip this line entirely if you don't want the text box to contain any string on creation
linkedTo = other.id //This is very important, do not forget this!
destroyOnOuterClick = 0 //if it is set to 1, the textbox will be destroyed when you click outside of it.
}
Code:
stringVariable = ""
with objTextbox
{
if linkedTo = other.id
{
other.stringVariable = str
}
}
- Text boxes store their string in the str variable, see above how to check it.
- The textbox will move with the window.
- The textbox sets its own depth and acts like if it was within the window code.
- Upon destroying your program's window, the textbox will destroy itself automatically.
- Text boxes are slightly advanced, as you can a set custom pointer position with mouse, or with the left and right keys.
- The textbox will only be written to when it is active. It's active if the last clicked mouse position is on it, and wasn't blocked by another instance.
Last edited: