This library is a built-from-scratch reproduction of VBA's MsgBox function, which is used for displaying messages/prompts to users in Microsoft Office. (See an overview of the VBA version here.)
MSGBOX lets you quickly and easily display a windowed message and 1 to 3 buttons for soliciting a user response to the message. The function returns an enumerated value that lets you determine what button was pressed. You can also choose to display an icon or image to display in the box, and you can customize pretty much anything about the message box's appearance to fit your program's style. Check out the demo script included with the code for lots of examples.
Here is a simple example prompting the user to decide if they want to save before quitting:
Code: Select all
{{/lib/interface/msgbox}}
SET TOOLBAR OFF
GRAPHICS CLEAR
GRAPHICS
text$ = "You have unsaved changes. Would you like to save before quitting?"
response = MSGBOX(text$, MSGBOX.YesNo, MSGBOX.Exclamation)
IF response = MSGBOX.Yes THEN
' code to save
END IF
Functions provided:
- MSGBOX (text$, type, icon)
- MSGBOX_RESTORE_PARAM_DEFAULTS ()
Inputs and Customization
Required inputs:
- text$ — This is a string of the message you want to be displayed in the message box. If can include linefeeds using CHR$(10) and can be any length. The text is put into a field, so it is automatically scrollable if the message is very long.
- type — This is an enumerated value telling the library what type of message box you want (full list below). This determines what buttons are presented to the user for their response.
- icon — This is an enumerated value telling the library what icon to display in the message box, if any (full list below).
- MSGBOX.OkOnly = 0 . . . . . . . . . one button: "Ok"
- MSGBOX.OkCancel = 1 . . . . . . . . two buttons: "Ok" and "Cancel"
- MSGBOX.YesNo = 2 . . . . . . . . . . two buttons: "Yes" and "No"
- MSGBOX.YesNoCancel = 3 . . . . . . three buttons: "Yes", "No", and "Cancel"
- MSGBOX.RetryCancel = 4 . . . . . . two buttons: "Retry" and "Cancel"
- MSGBOX.AbortRetryIgnore = 5 . . . three buttons: "Abort", "Retry", and "Ignore"
- MSGBOX.CustomBttns1 = 6 . . . . . one button: uses parameter MSGBOX.bttn1$
- MSGBOX.CustomBttns2 = 7 . . . . . two buttons: uses parameters MSGBOX.bttn1$ and .bttn2$
- MSGBOX.CustomBttns3 = 8 . . . . . three buttons: uses parameters MSGBOX.bttn1$, .bttn2$, and .bttn3$
- MSGBOX.NoIcon = 0 . . . . . . . no icon (text fills the entire message box)
- MSGBOX.Critical = 1 . . . . . . . red "X" in circle
- MSGBOX.Exclamation = 2 . . . . yellow "!" in triangle
- MSGBOX.Question = 3 . . . . . . blue "?" in circle
- MSGBOX.Information = 4 . . . . blue "i" in circle
- MSGBOX.CustomImage = 5 . . . uses parameter MSGBOX.iconImagePath$ (path of image file to use)
- MSGBOX.CustomAscii = 6 . . . . uses parameter MSGBOX.iconAsciiNum (decimal value of unicode character to use)
- MSGBOX.Ok = 0
- MSGBOX.Cancel = 1
- MSGBOX.Yes = 2
- MSGBOX.No = 3
- MSGBOX.Abort = 4
- MSGBOX.Retry = 5
- MSGBOX.Ignore = 6
- MSGBOX.Button1 = 7 (for custom MSGBOX types)
- MSGBOX.Button2 = 8 (for custom MSGBOX types)
- MSGBOX.Button3 = 9 (for custom MSGBOX types)
Code: Select all
' This line of code:
response = MSGBOX("Test", MSGBOX.YesNo, MSGBOX.Question)
' is equivalent to this line of code:
response = MSGBOX("Test", 2, 3)
In addition to the above inputs, there are many other parameters that can be set before calling the MSGBOX function that controls the appearance of the message box. You can change the color and alpha of anything, including the background behind the message box, and you can also control the duration of the fade-in animation. A list of parameters is given in the "msgbox" file (see the header info at the top of the file), and you can also find many examples in the demo script included with the code.
To give you an example, here are two clean, semi-transparent themes: one light and one dark:
Code
PLEASE READ THE BELOW INFO ON SETTING UP THE LIBRARY!
All code can be found here: https://www.dropbox.com/sh/udk7bhjic863 ... lq_ra?dl=0
IMPORTANT: The location of the msgbox_icons folder must be hardcoded. You must update the variable MSGBOX.dir$ at the top of the "msgbox" file with wherever the library is located. (If anyone knows of a better way to do this, please let me know!)
The MSGBOX library depends on a few other libraries I have written. Those libraries are:
- graphics_modes — Functions for detecting, setting, saving, and restoring the current graphics mode. (Posted independently here.)
- draw_fill_settings — Functions for detecting, setting, saving, and restoring the current draw and fill graphics settings. (Inspired by and an adaption of Joel's library)
- option_sprite_pos — Function for detecting the current OPTION SPRITE POS setting.
- roundrect — Functions for filling and drawing a rectangle with rounded corners.
- /lib/
- graphics/
- draw_fill_settings
- graphics_modes
- roundrect
- interface/
- msgbox
- msgbox_icons/
- sprites/
- option_sprite_pos
- graphics/
Code: Select all
MSGBOX.dir$ = "/lib/interface/" ' needed for icons
'g'
/*
MSGBOX (text$, type, icon)
MSGBOX_RESTORE_PARAM_DEFAULTS ()
Function for displaying a windowed message and 1 to 3 buttons for soliciting a user response.
NOTE: You must update MSGBOX.dir$ above for icons to work.
Uses: FILL_ROUNDRECT, DRAW_ROUNDRECT,
SAVE_DRAW_AND_FILL, RESTORE_DRAW_AND_FILL,
IS_OPTION_SPRITE_POS_CENTRAL
'==============================================================
MSGBOX displays a message, provides buttons for user response, and returns an enumerated value corresponding to the user's response. The required inputs include the text to be displayed, the message box type (which determines the buttons to display), and the icon to be displayed. There are also many parameters that can be set before calling the MSGBOX function for more advanced customization.
Inputs
------
text$ Text to display in the message box
type Message box type (enumerated)
MSGBOX.OkOnly = 0
MSGBOX.OkCancel = 1
MSGBOX.YesNo = 2
MSGBOX.YesNoCancel = 3
MSGBOX.RetryCancel = 4
MSGBOX.AbortRetryIgnore = 5
MSGBOX.CustomBttns1 = 6 (one button)
MSGBOX.CustomBttns2 = 7 (two buttons)
MSGBOX.CustomBttns3 = 8 (three buttons)
For custom types, see the parameter info below
icon Icon to display next to the text (enumerated)
MSGBOX.NoIcon = 0
MSGBOX.Critical = 1
MSGBOX.Exclamation = 2
MSGBOX.Question = 3
MSGBOX.Information = 4
MSGBOX.CustomImage = 5
MSGBOX.CustomAscii = 6
For custom icons, see the parameter info below
Output
------
MSGBOX returns an enumerated value corresponding to the button hit by the user. Therefore, the possible return values are dependent on the message box type:
Responses for type MSGBOX.OkOnly:
MSGBOX.Ok = 0
Responses for type MSGBOX.OKCancel:
MSGBOX.Ok = 0
MSGBOX.Cancel = 1
Responses for type MSGBOX.YesNo:
MSGBOX.Yes = 2
MSGBOX.No = 3
Responses for type MSGBOX.YesNoCancel:
MSGBOX.Yes = 2
MSGBOX.No = 3
MSGBOX.Cancel = 1
Responses for type MSGBOX.RetryCancel:
MSGBOX.Retry = 5
MSGBOX.Cancel = 1
Responses for type MSGBOX.AbortRetryIgnore:
MSGBOX.Abort = 4
MSGBOX.Retry = 5
MSGBOX.Ignore = 6
Responses for type MSGBOX.Custom1:
MSGBOX.Button1 = 7
Responses for type MSGBOX.Custom2:
MSGBOX.Button1 = 7
MSGBOX.Button2 = 8
Responses for type MSGBOX.Custom3:
MSGBOX.Button1 = 7
MSGBOX.Button2 = 8
MSGBOX.Button3 = 9
Parameters
----------
NOTE: The option SET BUTTONS CUSTOM can be used in conjunction with FILL COLOR, FILL ALPHA, DRAW COLOR, and DRAW ALPHA for controlling the appearance of the buttons in the message box. This will not interfere with the below parameters that set color and alpha values for other elements of the message box. The options SET BUTTONS FONT NAME and SET BUTTONS FONT SIZE can also be used as they would normally.
Fade-in animation:
------------------
MSGBOX.fadeDuration sets the length of time in seconds of the message box's fade-in animation. Set to 0 to disable the fade-in animation.
Message box background:
-----------------------
MSGBOX.bgR, .bgG, .bgB, and .bgA set the background color and alpha that appears behind the message box.
Message box and text:
---------------------
MSGBOX.boxFillR, .boxFillG, .boxFillB, and .boxFillA set the fill color and alpha of the message box.
MSGBOX.boxOutlineR, .boxOutlineG, .boxOutlineB, and .boxOutlineA set the color and alpha of the message box's outline.
MSGBOX.txtR, .txtG, .txtB, and .txtA set the color and alpha of the message box's text.
MSGBOX.txtFont$ sets the font name to use for the message box's text. Set to "default" to use the default field font.
MSGBOX.txtSize sets the font size to use for the message box's text. Set to -1 to use the default field font size.
Message box icon and buttons:
-----------------------------
MSGBOX.iconImagePath$ specifies the image file to use as the message box's icon when the input "icon" is set to MSGBOX.CustomImage.
MSGBOX.iconAsciiNum specifies the Unicode character to use as the message box's icon when the input "icon" is set to MSGBOX.CustomAscii.
MSGBOX.iconR, .iconG, .iconB, and .iconA set the color of alpha of the message box's icon. The RGB values only apply to ASCII icons. The alpha value applies to all icons.
MSGBOX.bttn1$, .bttn2$, and .bttn3$ set the text to use in the user response buttons when the input "type" is set to MSGBOX.CustomBttns1 (one button), MSGBOX.CustomBttns2 (two buttons), or MSGBOX.CustomBttns3 (three buttons).
'==============================================================
MSGBOX_RESTORE_PARAM_DEFAULTS returns all parameters to their initial values.
'==============================================================
*/
''
'b'
'==============================================================
' Initialization
'==============================================================
''
' Types (enumerated)
' ----------------------
MSGBOX.OkOnly = 0
MSGBOX.OkCancel = 1
MSGBOX.YesNo = 2
MSGBOX.YesNoCancel = 3
MSGBOX.RetryCancel = 4
MSGBOX.AbortRetryIgnore = 5
MSGBOX.CustomBttns1 = 6
MSGBOX.CustomBttns2 = 7
MSGBOX.CustomBttns3 = 8
MSGBOX.NUM_TYPES = 9
DIM MSGBOX.numButtons(MSGBOX.NUM_TYPES)
MSGBOX.numButtons(MSGBOX.OkOnly) = 1
MSGBOX.numButtons(MSGBOX.OkCancel) = 2
MSGBOX.numButtons(MSGBOX.YesNo) = 2
MSGBOX.numButtons(MSGBOX.YesNoCancel) = 3
MSGBOX.numButtons(MSGBOX.RetryCancel) = 2
MSGBOX.numButtons(MSGBOX.AbortRetryIgnore) = 3
MSGBOX.numButtons(MSGBOX.CustomBttns1) = 1
MSGBOX.numButtons(MSGBOX.CustomBttns2) = 2
MSGBOX.numButtons(MSGBOX.CustomBttns3) = 3
' Icons (enumerated)
' --------------------
MSGBOX.NoIcon = 0
MSGBOX.Critical = 1
MSGBOX.Exclamation = 2
MSGBOX.Question = 3
MSGBOX.Information = 4
MSGBOX.CustomImage = 5
MSGBOX.CustomAscii = 6
' Responses (enumerated)
' ------------------------
MSGBOX.Ok = 0
MSGBOX.Cancel = 1
MSGBOX.Yes = 2
MSGBOX.No = 3
MSGBOX.Abort = 4
MSGBOX.Retry = 5
MSGBOX.Ignore = 6
MSGBOX.Button1 = 7 ' for custom types
MSGBOX.Button2 = 8
MSGBOX.Button3 = 9
' Default Parameter Values
' --------------------------
MSGBOX_RESTORE_PARAM_DEFAULTS()
DEF MSGBOX_RESTORE_PARAM_DEFAULTS ()
MSGBOX.fadeDuration = 0.2
MSGBOX.bgR = 0
MSGBOX.bgG = 0
MSGBOX.bgB = 0
MSGBOX.bgA = 0.2
MSGBOX.boxFillR = 0.9
MSGBOX.boxFillG = 0.9
MSGBOX.boxFillB = 0.9
MSGBOX.boxFillA = 1
MSGBOX.boxOutlineR = 0
MSGBOX.boxOutlineG = 0
MSGBOX.boxOutlineB = 0
MSGBOX.boxOutlineA = 1
MSGBOX.txtR = 0
MSGBOX.txtG = 0
MSGBOX.txtB = 0
MSGBOX.txtA = 1
MSGBOX.txtFont$ = "default"
MSGBOX.txtSize = -1 ' set to -1 for default
MSGBOX.iconR = 0
MSGBOX.iconG = 0
MSGBOX.iconB = 0
MSGBOX.iconA = 1
MSGBOX.bttn1$ = "1"
MSGBOX.bttn2$ = "2"
MSGBOX.bttn3$ = "3"
END DEF
'b'
'==============================================================
' Main Function
'==============================================================
''
DEF MSGBOX (text$, type, icon)
' Setup
' -------
GET SCREEN SIZE scrW, scrH
GET_DRAW_AND_FILL() ' Also stores the graphics mode
dr = GET_DRAW_AND_FILL.dr
dg = GET_DRAW_AND_FILL.dg
db = GET_DRAW_AND_FILL.db
da = GET_DRAW_AND_FILL.da
fr = GET_DRAW_AND_FILL.fr
fg = GET_DRAW_AND_FILL.fg
fb = GET_DRAW_AND_FILL.fb
fa = GET_DRAW_AND_FILL.fa
fs = GET_DRAW_AND_FILL.fs
tp = GET_DRAW_AND_FILL.tpCentral
gm$ = GET_DRAW_AND_FILL.gm$
GRAPHICS MODE NORMAL
sp = IS_OPTION_SPRITE_POS_CENTRAL()
OPTION SPRITE POS NORMAL
nPg$ = "msgbox_page"
nBox$ = "msgbox_box"
nIco$ = "msgbox_icon"
nTxt$ = "msgbox_text"
nBn1$ = "msgbox_bttn_1"
nBn2$ = "msgbox_bttn_2"
nBn3$ = "msgbox_bttn_3"
' Page
' ------
PAGE nPg$ SET
PAGE nPg$ FRAME 0, 0, scrW, scrH
PAGE nPg$ COLOR 0, 0, 0, 0
PAGE nPg$ ALPHA 0
PAGE nPg$ SHOW
' Background and Box Sprite
' ---------------------------
wBox = INT(scrW*0.8)
hBox = INT(scrH*0.7)
IF wBox*0.75 < hBox THEN
hBox = INT(wBox*0.7)
ELSE
wBox = INT(hBox*1.6)
END IF
crBox = INT(MIN(wBox, hBox)*0.1)
mX = INT((scrW - wBox)/2)
mY = INT((scrH - hBox)/2)
SPRITE nBox$ BEGIN scrW, scrH
GRAPHICS CLEAR bgR, bgG, bgB, bgA
GRAPHICS MODE COPY
FILL COLOR boxFillR, boxFillG, boxFillB
FILL ALPHA boxFillA
FILL_ROUNDRECT(mX, mY, mX+wBox, mY+hBox, crBox)
DRAW COLOR boxOutlineR, boxOutlineG, boxOutlineB
DRAW ALPHA boxOutlineA
DRAW_ROUNDRECT(mX, mY, mX+wBox, mY+hBox, crBox)
SPRITE END
SPRITE nBox$ SHOW
GRAPHICS MODE NORMAL
margin = INT(hBox*0.1) ' controls spacing of box elements
' Icon
' ------
m = 0
IF icon = Critical THEN
SPRITE nIco$ LOAD dir$ & "/msgbox_icons/critical.png"
ELSE ! IF icon = Exclamation THEN
SPRITE nIco$ LOAD dir$ & "/msgbox_icons/exclamation.png"
ELSE ! IF icon = Question THEN
SPRITE nIco$ LOAD dir$ & "/msgbox_icons/question.png"
ELSE ! IF icon = Information THEN
SPRITE nIco$ LOAD dir$ & "/msgbox_icons/information.png"
ELSE ! IF icon = CustomImage THEN
IF FILE_EXISTS(iconImagePath$) THEN
SPRITE nIco$ LOAD iconImagePath$
ELSE
icon = NoIcon
END IF
ELSE ! IF icon = CustomAscii THEN
IF iconAsciiNum >= 0 AND iconAsciiNum <= 65535 THEN
m = 5
wIco = hBox*0.2
hIco = hBox*0.2
SPRITE nIco$ BEGIN wIco+2*m, hIco+2*m
OPTION TEXT POS CENTRAL
DRAW COLOR iconR, iconG, iconB
DRAW ALPHA 1
DRAW FONT SIZE hIco
DRAW TEXT CHR$(iconAsciiNum) AT m+wIco/2, m+hIco/2
SPRITE END
ELSE
icon = NoIcon
END IF
ELSE
icon = NoIcon
END IF ! END IF ! END IF ! END IF ! END IF ! END IF
IF icon <> NoIcon THEN
GET SPRITE nIco$ SIZE wIco, hIco
scIco = hBox*0.2/wIco
xIco = mX + margin - (wIco/2 - margin)
yIco = mY + margin - (hIco/2 - margin)
SPRITE nIco$ AT xIco, yIco SCALE scIco
SPRITE nIco$ ALPHA iconA
SPRITE nIco$ SHOW
END IF
' Buttons
' ---------
SET_DRAW(dr, dg, db, da) ' Support SET BUTTONS CUSTOM
SET_FILL(fr, fg, fb, fa)
DRAW FONT SIZE fs
IF type < 0 OR type >= NUM_TYPES THEN type = OkOnly
hBn = hBox*0.2
yBn = (scrH+hBox)/2 - hBn - margin/2
IF numButtons(type) = 1 THEN
wBn = wBox/2
xBn1 = scrW/2 - wBn/2
IF type = OkOnly THEN tBn1$ = "Ok"
IF type = CustomBttns1 THEN tBn1$ = bttn1$
BUTTON nBn1$ TEXT tBn1$ AT xBn1, yBn SIZE wBn, hBn
ELSE ! IF numButtons(type) = 2 THEN
wBn = wBox*0.42
xBn1 = scrW/2 - wBn/2 - wBn/2 - margin/6
xBn2 = scrW/2 - wBn/2 + wBn/2 + margin/6
IF type = OkCancel THEN
tBn1$ = "Ok"
tBn2$ = "Cancel"
END IF
IF type = YesNo THEN
tBn1$ = "Yes"
tBn2$ = "No"
END IF
IF type = RetryCancel THEN
tBn1$ = "Retry"
tBn2$ = "Cancel"
END IF
IF type = CustomBttns2 THEN
tBn1$ = bttn1$
tBn2$ = bttn2$
END IF
BUTTON nBn1$ TEXT tBn1$ AT xBn1, yBn SIZE wBn, hBn
BUTTON nBn2$ TEXT tBn2$ AT xBn2, yBn SIZE wBn, hBn
ELSE ' numButtons(type) = 3
wBn = wBox*0.3
xBn1 = scrW/2 - wBn/2 - wBn - margin/6
xBn2 = scrW/2 - wBn/2
xBn3 = scrW/2 - wBn/2 + wBn + margin/6
IF type = YesNoCancel THEN
tBn1$ = "Yes"
tBn2$ = "No"
tBn3$ = "Cancel"
END IF
IF type = AbortRetryIgnore THEN
tBn1$ = "Abort"
tBn2$ = "Retry"
tBn3$ = "Ignore"
END IF
IF type = CustomBttns3 THEN
tBn1$ = bttn1$
tBn2$ = bttn2$
tBn3$ = bttn3$
END IF
BUTTON nBn1$ TEXT tBn1$ AT xBn1, yBn SIZE wBn, hBn
BUTTON nBn2$ TEXT tBn2$ AT xBn2, yBn SIZE wBn, hBn
BUTTON nBn3$ TEXT tBn3$ AT xBn3, yBn SIZE wBn, hBn
END IF ! END IF
' Text Field
' ------------
mAdj = margin/4 ' counteracts field padding
IF icon <> NoIcon THEN
wTxt = wBox - 3*margin - scIco*wIco + 2*mAdj
xTxt = mX + 2*margin + scIco*wIco - mAdj
yTxt = mY + margin - 2*mAdj
ELSE
wTxt = wBox - 2*margin + 2*mAdj
xTxt = (scrW-wBox)/2 + margin - mAdj
yTxt = (scrH-hBox)/2 + margin - 2*mAdj
END IF
hTxt = hBox - 1.5*margin - hBn
FIELD nTxt$ TEXT text$ AT xTxt, yTxt SIZE wTxt, hTxt RO ML
FIELD nTxt$ BACK ALPHA 0
FIELD nTxt$ FONT COLOR txtR, txtG, txtB
FIELD nTxt$ FONT ALPHA txtA
IF txtFont$ <> "default" THEN
FIELD nTxt$ FONT NAME txtFont$
END IF
IF txtSize > -1 THEN
FIELD nTxt$ FONT SIZE txtSize
END IF
FIELD nTxt$ SELECT 0, 0 ' Scroll to top in case text is long
' Show message box
' ------------------
IF fadeDuration > 0 THEN
tFadeStart = TIME()
tFadeCurr = tFadeStart
tFadeEnd = tFadeStart + fadeDuration
WHILE tFadeCurr <= tFadeEnd
tFadeCurr = TIME()
v = (tFadeCurr - tFadeStart)/fadeDuration
PAGE nPg$ ALPHA v
END WHILE
END IF
PAGE nPg$ ALPHA 1
' Ignore any button pressed up until this point
z = BUTTON_PRESSED(nBn1$)
IF numButtons(type) > 1 THEN z = BUTTON_PRESSED(nBn2$)
IF numButtons(type) > 2 THEN z = BUTTON_PRESSED(nBn3$)
' Get User Response
' -------------------
response = -1
DO
SLOWDOWN
IF numButtons(type) = 1 THEN
IF BUTTON_PRESSED(nBn1$) THEN
IF type = OkOnly THEN response = Ok
IF type = CustomBttns1 THEN response = Button1
END IF
ELSE ! IF numButtons(type) = 2 THEN
IF BUTTON_PRESSED(nBn1$) THEN
IF type = OkCancel THEN response = Ok
IF type = YesNo THEN response = Yes
IF type = RetryCancel THEN response = Retry
IF type = CustomBttns2 THEN response = Button1
END IF
IF BUTTON_PRESSED(nBn2$) THEN
IF type = OkCancel THEN response = Cancel
IF type = YesNo THEN response = No
IF type = RetryCancel THEN response = Cancel
IF type = CustomBttns2 THEN response = Button2
END IF
ELSE ' numButtons(type) = 3 THEN
IF BUTTON_PRESSED(nBn1$) THEN
IF type = YesNoCancel THEN response = Yes
IF type = AbortRetryIgnore THEN response = Abort
IF type = CustomBttns3 THEN response = Button1
END IF
IF BUTTON_PRESSED(nBn2$) THEN
IF type = YesNoCancel THEN response = No
IF type = AbortRetryIgnore THEN response = Retry
IF type = CustomBttns3 THEN response = Button2
END IF
IF BUTTON_PRESSED(nBn3$) THEN
IF type = YesNoCancel THEN response = Cancel
IF type = AbortRetryIgnore THEN response = Ignore
IF type = CustomBttns3 THEN response = Button3
END IF
END IF ! END IF
UNTIL response > -1
' Cleanup
' ---------
SPRITE nBox$ DELETE
FIELD nTxt$ DELETE
BUTTON nBn1$ DELETE
IF numButtons(type) > 1 THEN BUTTON nBn2$ DELETE
IF numButtons(type) > 2 THEN BUTTON nBn3$ DELETE
IF icon <> NoIcon THEN SPRITE nIco$ DELETE
PAGE nPg$ HIDE
SET_GRAPHICS_MODE(gm$)
IF tp = 0 THEN
OPTION TEXT POS NORMAL
ELSE
OPTION TEXT POS CENTRAL
END IF
IF sp = 0 THEN
OPTION SPRITE POS NORMAL
ELSE
OPTION SPRITE POS CENTRAL
END IF
RETURN response
END DEF
'==============================================================
'g'
/*
GET_GRAPHICS_MODE$ ()
SET_GRAPHICS_MODE (gm$)
Functions for detecting and setting the graphics mode.
Note: GET_GRAPHICS_MODE$ cannot be called while editing a sprite's graphics layer.
'==============================================================
GET_GRAPHICS_MODE$ detects the current graphics mode and returns it as a string (e.g. "NORMAL", "MULTIPLY", "SCREEN", etc.).
'==============================================================
SET_GRAPHICS_MODE sets the graphics mode based on the input.
Inputs
------
gm$ Graphics mode string (e.g. "MULTIPLY")
'==============================================================
*/
''
DEF GET_GRAPHICS_MODE$ ()
r1 = 0.7 ! r2 = 0.1
g1 = 0.0 ! g2 = 0.3
b1 = 1.0 ! b2 = 0.7
a1 = 0.2 ! a2 = 0.9
nScan$ = "save_graphics_mode_screen"
SPRITE nScan$ SCAN 0, 0, 2, 2
DRAW PIXEL 0, 0 COLOR r1, g1, b1, a1
nStamp$ = "save_graphics_mode_stamp"
SPRITE nStamp$ BEGIN 1, 1
GRAPHICS CLEAR r2, g2, b2, a2
SPRITE END
SPRITE nStamp$ STAMP
GET PIXEL 0, 0 COLOR r, g, b, a
r$ = INT(r*255)
g$ = INT(g*255)
b$ = INT(b*255)
a$ = INT(a*255)
c$ = r$ & "-" & g$ & "-" & b$ & "-" & a$
IF c$ = "28-75-180-235" THEN gm$ = "NORMAL"
IF c$ = "26-60-180-235" THEN gm$ = "MULTIPLY"
IF c$ = "59-75-194-235" THEN gm$ = "SCREEN"
IF c$ = "44-60-194-235" THEN gm$ = "OVERLAY"
IF c$ = "28-60-180-235" THEN gm$ = "DARKEN"
IF c$ = "58-75-194-235" THEN gm$ = "LIGHTEN"
IF c$ = "61-60-255-235" THEN gm$ = "COLORDODGE"
IF c$ = "0-0-194-235" THEN gm$ = "COLORBURN"
IF c$ = "49-60-194-235" THEN gm$ = "SOFTLIGHT"
IF c$ = "30-60-194-235" THEN gm$ = "HARDLIGHT"
IF c$ = "52-75-160-235" THEN gm$ = "DIFFERENCE"
IF c$ = "55-75-160-235" THEN gm$ = "EXCLUSION"
IF c$ = "23-76-194-235" THEN gm$ = "HUE"
IF c$ = "50-66-181-235" THEN gm$ = "SATURATION"
IF c$ = "29-76-181-235" THEN gm$ = "COLOR"
IF c$ = "52-60-187-235" THEN gm$ = "LUMINOSITY"
IF c$ = "0-0-0-0" THEN gm$ = "CLEAR"
IF c$ = "26-77-179-230" THEN gm$ = "COPY"
IF c$ = "28-78-183-46" THEN gm$ = "SOURCEIN"
IF c$ = "26-78-179-184" THEN gm$ = "SOURCEOUT"
IF c$ = "40-65-185-51" THEN gm$ = "SOURCEATOP"
IF c$ = "58-60-194-235" THEN gm$ = "DESTOVER"
IF c$ = "177-0-255-46" THEN gm$ = "DESTIN"
IF c$ = "204-0-255-5" THEN gm$ = "DESTOUT"
IF c$ = "54-61-193-230" THEN gm$ = "DESTATOP"
IF c$ = "28-74-179-189" THEN gm$ = "XOR"
IF c$ = "32-43-186-255" THEN gm$ = "PLUSDARKER"
IF c$ = "58-69-212-255" THEN gm$ = "PLUSLIGHTER"
GRAPHICS MODE COPY
SPRITE nScan$ STAMP
SET_GRAPHICS_MODE(gm$)
RETURN gm$
END DEF
'==============================================================
DEF SET_GRAPHICS_MODE (gm$)
gm$ = CAPSTR$(gm$)
IF gm$ = "NORMAL" THEN GRAPHICS MODE NORMAL
IF gm$ = "MULTIPLY" THEN GRAPHICS MODE MULTIPLY
IF gm$ = "SCREEN" THEN GRAPHICS MODE SCREEN
IF gm$ = "OVERLAY" THEN GRAPHICS MODE OVERLAY
IF gm$ = "DARKEN" THEN GRAPHICS MODE DARKEN
IF gm$ = "LIGHTEN" THEN GRAPHICS MODE LIGHTEN
IF gm$ = "COLORDODGE" THEN GRAPHICS MODE COLORDODGE
IF gm$ = "COLORBURN" THEN GRAPHICS MODE COLORBURN
IF gm$ = "SOFTLIGHT" THEN GRAPHICS MODE SOFTLIGHT
IF gm$ = "HARDLIGHT" THEN GRAPHICS MODE HARDLIGHT
IF gm$ = "DIFFERENCE" THEN GRAPHICS MODE DIFFERENCE
IF gm$ = "EXCLUSION" THEN GRAPHICS MODE EXCLUSION
IF gm$ = "HUE" THEN GRAPHICS MODE HUE
IF gm$ = "SATURATION" THEN GRAPHICS MODE SATURATION
IF gm$ = "COLOR" THEN GRAPHICS MODE COLOR
IF gm$ = "LUMINOSITY" THEN GRAPHICS MODE LUMINOSITY
IF gm$ = "CLEAR" THEN GRAPHICS MODE CLEAR
IF gm$ = "COPY" THEN GRAPHICS MODE COPY
IF gm$ = "SOURCEIN" THEN GRAPHICS MODE SOURCEIN
IF gm$ = "SOURCEOUT" THEN GRAPHICS MODE SOURCEOUT
IF gm$ = "SOURCEATOP" THEN GRAPHICS MODE SOURCEATOP
IF gm$ = "DESTOVER" THEN GRAPHICS MODE DESTOVER
IF gm$ = "DESTIN" THEN GRAPHICS MODE DESTIN
IF gm$ = "DESTOUT" THEN GRAPHICS MODE DESTOUT
IF gm$ = "DESTATOP" THEN GRAPHICS MODE DESTATOP
IF gm$ = "XOR" THEN GRAPHICS MODE XOR
IF gm$ = "PLUSDARKER" THEN GRAPHICS MODE PLUSDARKER
IF gm$ = "PLUSLIGHTER" THEN GRAPHICS MODE PLUSLIGHTER
END DEF
'==============================================================
'g'
/*
GET_DRAW_AND_FILL ()
SET_DRAW (r, g, b, a)
SET_FILL (r, g, b, a)
Functions for detecting and setting the current draw and fill settings.
Note: GET_DRAW_AND_FILL cannot be called while editing a sprite's graphics layer.
Inspired by and an adaption of Joel's library file for saving and restoring graphics parameters (https://kibernetik.pro/forum/viewtopic.php?f=70&t=1730#p10857)
Uses: GET_GRAPHICS_MODE$, SET_GRAPHICS_MODE
'==============================================================
GET_DRAW_AND_FILL detects the following graphics settings:
DRAW COLOR
DRAW ALPHA
FILL COLOR
FILL ALPHA
DRAW SIZE
DRAW FONT SIZE
OPTION TEXT POS
The values of the detected settings can be retrieved from these variables after calling the function:
GET_DRAW_AND_FILL.dr Draw color (red)
GET_DRAW_AND_FILL.dg Draw color (green)
GET_DRAW_AND_FILL.db Draw color (blue)
GET_DRAW_AND_FILL.da Draw alpha
GET_DRAW_AND_FILL.fr Fill color (red)
GET_DRAW_AND_FILL.fg Fill color (green)
GET_DRAW_AND_FILL.fb Fill color (blue)
GET_DRAW_AND_FILL.fa Fill alpha
GET_DRAW_AND_FILL.ds Draw size
GET_DRAW_AND_FILL.fs Draw font size
GET_DRAW_AND_FILL.tpCentral Text pos central (boolean)
GET_DRAW_AND_FILL.tpNormal Text pos normal (boolean)
NOTE: There is a bug that causes the DRAW LINECAP option (possible values "RECT" and "ROUND") to always be reset to RECT when a SPRITE BEGIN command is called. This means that the DRAW LINECAP option cannot be detected without making certain assumptions about graphics settings. The SPRITE BEGIN command is unavoidable: If draw settings are tested and detected inside a sprite graphics layer (the current method employed), then obviously a SPRITE BEGIN command is necessary. If draw settings are tested and detected inside the main graphics layer after a SPRITE SCAN command, the option is still reset during the call to GET_GRAPHICS_MODE$ since a SPRITE BEGIN command is necessary for detecting the graphics mode.
'==============================================================
SET_DRAW sets the draw RGBA settings based on the inputs.
Inputs
------
r Draw color (red)
g Draw color (green)
b Draw color (blue)
a Draw alpha
'==============================================================
SET_FILL sets the fill RGBA settings based on the inputs.
Inputs
------
r Fill color (red)
g Fill color (green)
b Fill color (blue)
a Fill alpha
'==============================================================
*/
''
DEF GET_DRAW_AND_FILL ()
scrH = SCREEN_HEIGHT()
gm$ = GET_GRAPHICS_MODE$()
n$ = "save_draw_and_fill_settings"
SPRITE n$ BEGIN 2, scrH
GRAPHICS MODE COPY
box$ = CHR$(9608) ' box$ = "█"
' Draw font size
fs = FONT_SIZE()
' Draw color and alpha
DRAW FONT SIZE 20 ' Doesn't depend on
DRAW TEXT box$ AT -1, -1 ' DRAW SIZE setting
GET PIXEL 1, 1 COLOR dr,dg,db,da
IF da < 1 THEN ' GET PIXEL is not 100%
DRAW ALPHA 1 ' accurate for alpha
DRAW TEXT box$ AT -1, -1 ' values less than 1
GET PIXEL 1, 1 COLOR dr,dg,db
END IF
' Text position option
GRAPHICS CLEAR
DRAW ALPHA 1
DRAW TEXT box$ AT 5, 5
GET PIXEL 0, 0 COLOR v, v, v, v
IF v THEN tpCentral = 1 ELSE tpCentral = 0
tpNormal = 1 - tpCentral
' Draw size
GRAPHICS CLEAR 1, 1, 1
DRAW COLOR 0, 0, 0
DRAW ALPHA 1
DRAW LINE 0, 1 TO 1, 1
FOR p = 1 TO scrH*2-1
GET PIXEL 0, p COLOR v, v, v
IF v THEN BREAK p
NEXT p
IF p = 1 THEN ds = 0
IF p = 2 THEN ds = 0.5
IF p > 2 THEN ds = p - 2
' Fill color and alpha
FILL RECT 0, 0 TO 2, 2
GET PIXEL 1, 1 COLOR fr,fg,fb,fa
IF a < 1 THEN ' GET PIXEL is not 100%
FILL ALPHA 1 ' accurate for alpha
FILL RECT 0, 0 TO 2, 2 ' values less than 1
GET PIXEL 1, 1 COLOR fr,fg,fb
END IF
SPRITE END
DRAW COLOR dr, dg, db
DRAW ALPHA da
DRAW FONT SIZE fs
FILL ALPHA fa
SET_GRAPHICS_MODE(gm$)
END DEF
'==============================================================
DEF SET_DRAW (r, g, b, a)
DRAW COLOR r, g, b
DRAW ALPHA a
END DEF
'==============================================================
DEF SET_FILL (r, g, b, a)
FILL COLOR r, g, b
FILL ALPHA a
END DEF
'==============================================================
'g'
/*
IS_OPTION_SPRITE_POS_CENTRAL ()
Functions for determining the current state of OPTION SPRITE POS.
'==============================================================
IS_OPTION_SPRITE_POS_CENTRAL returns 1 if OPTION SPRITE POS is set to CENTRAL. Otherwise returns 0.
'==============================================================
*/
''
DEF IS_OPTION_SPRITE_POS_CENTRAL ()
t$ = TIME()
n1$ = "test_option_sprite_pos_1"
n2$ = "test_option_sprite_pos_2"
SPRITE n1$ BEGIN 5,5
GRAPHICS CLEAR 0,0,0
SPRITE END
SPRITE n1$ ALPHA 0.01
SPRITE n1$ SHOW
SPRITE n1$ COPY n2$
SPRITE n2$ AT 6,6
SPRITE n2$ SHOW
IF SPRITES_COLLIDE(n1$, n2$) THEN
IS_OPTION_SPRITE_POS_CENTRAL = 1
ELSE
IS_OPTION_SPRITE_POS_CENTRAL = 0
END IF
SPRITE n1$ DELETE
SPRITE n2$ DELETE
END DEF
'==============================================================
'g'
/*
DRAW_ROUNDRECT (x1, y1, x2, y2, r)
FILL_ROUNDRECT (x1, y1, x2, y2, r)
Functions for drawing rectangles with rounded corners.
Uses: .pi
'==============================================================
Both functions take an input of the rectangle's top-left x,y coordinates and bottom-right x,y coordinates, and the corner radius.
Inputs
------
x1, y1 x,y-coordinates of the top-left corner
x2, y2 x,y-coordinates of the bottom-right corner
r corner radius
'==============================================================
DRAW_ROUNDRECT draws a rectangle with rounded corners. This function uses only DRAW LINE and DRAW ARC commands.
FILL_ROUNDRECT fills a rectangle with rounded corners. This function uses only FILL CIRCLE and FILL RECT commands. Note: This function uses multiple fill commands that overlap in some areas. For alpha values that are less than one and non-normal graphics modes, run this command with FILL ALPHA 1 and GRAPHICS MODE NORMAL in a sprite and then stamp the sprite to the final destination with the desired graphics settings.
'==============================================================
*/
''
DEF DRAW_ROUNDRECT (x1, y1, x2, y2, r)
pi = 2*ACOS(0)
DRAW LINE x1+r, y1 TO x2-r, y1 ' top
DRAW LINE x2-r, y2 TO x1+r, y2 ' bottom
DRAW LINE x2 , y1+r TO x2 , y2-r ' right
DRAW LINE x1 , y2-r TO x1 , y1+r ' left
DRAW ARC x1+r, y1+r, r, pi , pi*3/2 ' top-left
DRAW ARC x2-r, y1+r, r, pi*3/2, 0 ' top-right
DRAW ARC x2-r, y2-r, r, 0 , pi/2 ' bottom-right
DRAW ARC x1+r, y2-r, r, pi/2 , pi ' bottom-left
END DEF
'==============================================================
DEF FILL_ROUNDRECT (x1, y1, x2, y2, r)
FILL CIRCLE x1+r, y1+r SIZE r ' top-left
FILL CIRCLE x2-r, y1+r SIZE r ' top-right
FILL CIRCLE x2-r, y2-r SIZE r ' bottom-right
FILL CIRCLE x1+r, y2-r SIZE r ' bottom-left
FILL RECT x1+r, y1 TO x2-r, y2 ' vertical
FILL RECT x1 , y1+r TO x2 , y2-r ' horizontal
END DEF
'==============================================================