GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2013-01-13 17:25:49

neil_v
Member
Registered: 2010-05-28
Posts: 6

Custom message box (cleanup help).

GM 8.x compatible only. uses screen_refresh();

I needed (read; wanted to make) my own message box system as I just didn't like the vanilla ones that were provided. Really, I wanted more control over
its appearance and the information that is returned. I also wanted to get a better idea of how to draw outside the draw event, and use the while() loop.
I was quite successful, and I am quite proud of this little script.
The script only redraws when it needs to, and I left the screen redraw debug code in so you can see what I was using to check my work
The borders and text padding can be modified to any width
The buttons can accept any length of text.
Script has Keyboard and mouse support.

Unfortunately, the buttons don't stack automatically if they are outside the view, which is something I want to add soon. 
Future additions:
sprite support.
Ability to modify the information in a ds_list (you click a button, and it changes the information in a ds_list outside the script, for example)
Fancier graphics in general.
More button configurations
Automatic button configuration (auto stacking), which requires a re write
A lite version, and a couple of versions for the sake of utility
A text/number input message

What I need help with:
I am an intermediate level gml'r and I am quite poor at math. So what I need help with is:
-Formula problems/redundancies
-Poor coding cleanup
-optimizations
-ideas/features
-suggestions in general
As far as I can tell, the script works perfectly, so i'm just looking for things I have overlooked.

Here is my custom message box:

Spoiler
Expand/*
**  Usage:
**      var = scr_messageBoxExt (capText,capAlignCenter,msgText,
**      msgAlignCenter,totalbtn,btnConfig)
**
**  Arguments:
**      capText         The caption text
**      capAlignCenter  true: Align text center, False: align text left
**      msgText         The message text
**      msgAlignCenter  true: Align text center, False: align text left
**      totalBtn        How many buttons the message has*
**      btnConfig       0 = row along bottom, 1 = row alon right side
**
**  Returns: 
**      On selection of button: 1 for yes, 0 for no, 1- for cancel
**      Button number is button amount is over 3
**
**  Notes:
**      The buttons: If a number of buttons over 3 is selected, the buttons
**      will be labelled button 1, button 2, ect.
**      For now, it is expected that the user will modify the script themselves
**      to get the look and output they desire. The variables are all easily acessable
**      at the top of the script, and commented well enough.    
*/

//draw_set_font(fnt_msgBox); //If you want to change the font
var userChoice,capText,capAlignCenter,msgText,msgAlignCenter,totalbtn,btnConfig,
    txtHeight,brdr,padMsg,padCap,btnSpc,brdrTxt,mbWid,mbHght,keyNext,keyBack,
    btnWid,btnHght,btnTotHght,btnTotWid,reDraw,btnText,btnRet,mbX1,mbY1,mbX2,mbY1,
    msgX,msgY,cbX1,cbY1,cbX2,cbY1,capX,capY,cbHght,cbMod,btnX1,btnY1,btnX2,btnY2,
    btnTextX,btnTextY,btnState,btnStateLast;
       
    
keyboard_string="";//empty the keyboard memory
io_clear();
userChoice=-999;//Make the user choice something unlikley
capText=argument0;//caption text
capAlignCenter=argument1;
msgText=argument2; //message text
msgAlignCenter=argument3;//Align Message text to center
totalbtn=argument4;//How many buttons to make
btnConfig=argument5;//The configuration of the buttons
txtHeight=string_height(" ");//Set the line spacing 
brdr=2;//border size
padMsg=12;//space between message text and the border
padCap=8;//left and right space on the caption
btnSpc=8;//spacing between buttons
brdrTxt=8;//space between button text and button border
mbWid=16;//message box width and height
mbHght=8;//
cbHmod=2;//This increases the caption box height(like brdr)
cbHght=string_height(capText)+(brdr*cbHmod);//Caption box height
keyNext=vk_left;//Keys that control the buttons
keyBack=vk_right;
btnWid=0;//The width & height of the button face
btnHght=txtHeight+brdrTxt/2;
btnTotWid=0;//width & height of the button with border and spacer
btnTotHght=btnHght+brdr*2+btnSpc
reDraw=true;//Re draw the screen
switch(totalbtn){
    case 1:{
        btnText[0]="Ok";
        btnRet[0]=1;
        break;
        }    
    case 2:{
        btnText[0]="No";
        btnRet[0]=0;
        btnText[1]="Yes";
        btnRet[1]=1;
        break;
        }   
    case 3:{
        btnText[0]="Cancel";
        btnRet[0]=-1;
        btnText[1]="No";
        btnRet[1]=0;
        btnText[2]="Yes";
        btnRet[2]=1;
        break;
        }
    default:{
        for (i=0;i<totalbtn;i+=1){
            btnText[i]="Button "+string(abs(i-totalbtn));
            btnRet[i]=abs(i-totalbtn);
            }            
        break;
        }
    }
for (i=0;i<totalbtn;i+=1){//Resize buttons to the largest text
    if (string_width(btnText[i])+brdrTxt>btnWid){
        btnWid=string_width(btnText[i])+brdrTxt*2
        btnTotWid=brdr*2+btnWid+btnSpc
        }
    }
if (string_width(capText)>=mbWid*2+brdr*2){//Resize msgBox for caption oversize
    mbWid=ceil(string_width(capText)/1.97+brdr*2);
    }
if (string_width(msgText)>mbWid*1.75){//Resize msgBox for Message oversize
    mbWid=ceil(string_width(msgText)/2+padMsg);
    }
switch(btnConfig){
    case 0:{//Row along bottom
        if ((btnSpc+btnTotWid*totalbtn)/2+brdr>mbWid){//resize msgBox width for buttons
                mbWid=(btnSpc+btnTotWid*totalbtn+brdr*2)/2;
                }
        if (btnHght+btnSpc>mbHght){//resize msgBox height for buttons
            if (msgText!=""){
                mbHght=btnHght+((string_height(msgText)+padMsg/4)/2)+brdr*2;
                }
            else{
                mbHght=btnTotHght/2+brdr+btnSpc/2;
                }
            }
        }
        break;
    case 1:{//Column along right side
            keyNext=vk_up;//Keys that select the buttons
            keyBack=vk_down;
            if (capText!="")&&(string_width(capText)>string_width(msgText)){
                if ((btnSpc+btnTotWid*totalbtn)+brdr>string_width(capText)){//resize msgBox width for buttons
                    mbWid=(btnSpc+btnTotWid*totalbtn+brdr*2)/2;
                    }
                else{
                    mbWid=ceil(string_width(capText)/1.75+brdr*2)+padCap/2;
                    }
                }
            else{
                if (msgText!=""){
                    mbWid=max(string_width(msgText)/2+btnTotWid,string_width(capText)/2+btnTotWid);
                    }
                  else{
                    mbWid=(btnSpc+btnTotWid+brdr*2)/2;
                    }
                }
        if ((btnSpc+btnTotHght*totalbtn)/2+brdr>mbHght){//resize msgBox height for buttons
            if (string_height(msgText)<btnSpc+btnTotHght*totalbtn+brdr){
                mbHght=(btnTotHght*totalbtn+btnSpc)/2+brdr
                }
            else{
                mbHght=btnHght+((string_height(msgText)+padMsg/4)/2)+brdr*2;
                }

            }
        }
        break;
    }
//Message box rectangle parameters
mbX1=window_get_width()/2-mbWid;
mbY1=window_get_height()/2-mbHght+cbHght/2;
mbX2=window_get_width()/2+mbWid;
mbY2=window_get_height()/2+mbHght+cbHght/2;
if (msgAlignCenter){
    msgX=mbX1+mbWid-string_width(msgText)/2;
    if (btnConfig==1){
        msgX-=btnWid/2;//compensate for the buttons
        }
    }
else{    
    msgX=mbX1+padMsg+brdr;
    }
msgY=mbY1+padMsg/2+brdr;
//caption box parameters
cbX1=mbX1;
cbY1=mbY1-cbHght;
cbX2=mbX2;
cbY2=mbY1;
if (capAlignCenter){
    capX=cbX1+mbWid-string_width(capText)/2;//center the caption text
    }
else{
    capX=cbX1+padCap+brdr;//align left the caption text
    };
capY=cbY1+cbHght/2-string_height(capText)/2;//^
switch(btnConfig){
    case 0:{//Row along bottom
        for (i=0;i<totalbtn;i+=1){
            btnX1[i]=(mbX2-brdr)-(btnTotWid*i+brdr+btnSpc)
            btnY1[i]=mbY2-(brdr*2+btnSpc)
            btnX2[i]=btnX1[i]-btnWid
            btnY2[i]=btnY1[i]-btnHght
            btnTextX[i]=(btnX2[i]+btnWid/2)-(string_width(btnText[i])/2)
            btnTextY[i]=(btnY2[i]+btnHght/2)-txtHeight/2;
            btnState[i]=false;//mouse over this button?
            btnStateLast[i]=false;//mouse was over this button?
            };
            break;
        }
    case 1:{//column
        for (i=0;i<totalbtn;i+=1){
            btnX1[i]=mbX2-(brdr*2+btnSpc)
            btnY1[i]=(mbY2-brdr)-(btnTotHght*i+brdr+btnSpc)
            btnX2[i]=btnX1[i]-btnWid
            btnY2[i]=btnY1[i]-btnHght
            btnTextX[i]=(btnX2[i]+btnWid/2)-(string_width(btnText[i])/2);
            btnTextY[i]=(btnY2[i]+btnHght/2)-txtHeight/2;
            btnState[i]=false;//mouse over this button?
            btnStateLast[i]=false;//mouse was over this button?
            };
            break;
        }
    }
        
redraws=0; //used for debugging--to be removed----
keySelect=totalbtn-1;//the button the keyboard is selecting
while (true){
    io_handle(); 
    if(reDraw){
    //border color
    draw_rectangle_color (mbX1,cbY1,mbX2,mbY2,c_ltgray,c_gray,c_gray,c_gray,0);
    //Caption box (Rectangle:1=Bacground 2=outer border 3=inner border)
    draw_rectangle_color (cbX1+brdr,cbY1+brdr,cbX2-brdr,cbY2-brdr,c_white,c_gray,c_gray,c_ltgray,0);
    draw_rectangle_color (cbX1+brdr,cbY1+brdr,cbX2-brdr,cbY2-brdr,c_black,c_black,c_black,c_black,1);
    draw_rectangle_color (cbX1,cbY1,cbX2,cbY2,c_black,c_black,c_black,c_black,1);
    draw_text(capX,capY,string(capText));
    //Message box   
    draw_rectangle_color (mbX1+brdr,mbY1+brdr,mbX2-brdr,mbY2-brdr,c_white,c_white,c_ltgray,c_ltgray,0);
    draw_rectangle_color (mbX1,mbY1,mbX2,mbY2,c_black,c_black,c_black,c_black,1);
    draw_rectangle_color (mbX1+brdr,mbY1+brdr,mbX2-brdr,mbY2-brdr,c_black,c_black,c_black,c_black,1);
    draw_text(msgX,msgY,string(msgText));
    for (i=0;i<totalbtn;i+=1){//The buttons
        if (mouse_x<=btnX1[i]&&mouse_x>=btnX2[i])&&
            (mouse_y<=btnY1[i]&&mouse_y>=btnY2[i]){//Mouse is in the button
            draw_rectangle_color (btnX1[i]+brdr,btnY1[i]+brdr,btnX2[i]-brdr,btnY2[i]-brdr,c_gray,c_black,c_gray,c_black,0);
            draw_rectangle_color (btnX1[i],btnY1[i],btnX2[i],btnY2[i],c_gray,c_gray,c_white,c_white,0);
            draw_rectangle_color (btnX1[i],btnY1[i],btnX2[i],btnY2[i],c_black,c_black,c_black,c_black,1);
            draw_rectangle_color (btnX1[i]+brdr,btnY1[i]+brdr,btnX2[i]-brdr,btnY2[i]-brdr,c_black,c_black,c_black,c_black,1);
            draw_text(btnTextX[i],btnTextY[i],btnText[i]);
            }
        else{//mouse is not in the button
            draw_rectangle_color (btnX1[i]+brdr,btnY1[i]+brdr,btnX2[i]-brdr,btnY2[i]-brdr,c_gray,c_black,c_gray,c_black,0);
            if (keySelect==i){//if the keyboard is selecting the button gui.
                draw_rectangle_color (btnX1[i],btnY1[i],btnX2[i],btnY2[i],c_ltgray,c_white,c_ltgray,c_white,0);
                draw_rectangle_color (btnTextX[i]-2,btnTextY[i],btnTextX[i]+2+
                    string_width(btnText[i]),btnTextY[i]+txtHeight,c_black,c_gray,c_black,c_gray,1);
                }
            else{
                draw_rectangle_color (btnX1[i],btnY1[i],btnX2[i],btnY2[i],c_white,c_white,c_white,c_white,0);
                }
            draw_rectangle_color (btnX1[i],btnY1[i],btnX2[i],btnY2[i],c_black,c_black,c_black,c_black,1);
            draw_rectangle_color (btnX1[i]+brdr,btnY1[i]+brdr,btnX2[i]-brdr,btnY2[i]-brdr,c_black,c_black,c_black,c_black,1);
            draw_text(btnTextX[i],btnTextY[i],btnText[i]);
            };
        draw_rectangle_color(0,0,200,txtHeight,c_white,c_white,c_white,c_white,0)
        draw_text(0,0,string(redraws));//--to be removed----
       }
    screen_refresh();
    redraws+=1;//used for debugging--to be removed----
    reDraw=false;
    }
    io_handle();
    if (keyboard_check_pressed(vk_escape)||userChoice!=-999){
        break;
        }
    else if (keyboard_check_pressed(vk_enter)){
        userChoice=btnRet[keySelect];
        break;
        }
    else if (keyboard_check_pressed(keyNext)){
        keySelect = (keySelect+1) mod totalbtn; 
        reDraw=true; 
        io_clear();      
        }
    else if (keyboard_check_pressed(keyBack)){
        keySelect = ((keySelect-1 mod totalbtn) + totalbtn) mod totalbtn; 
        reDraw=true; 
        io_clear();      
        }
  
    for (i=0;i<totalbtn;i+=1){
        if (mouse_x<=btnX1[i]&&mouse_x>=btnX2[i])&&
            (mouse_y<=btnY1[i]&&mouse_y>=btnY2[i]){
            if (btnState[i]=false){
                btnStateLast[i]=false;
                btnState[i]=true;
                }
            if (mouse_check_button_released(mb_left)){
                userChoice=btnRet[i];
                break;
                }
            }
        else{
            if (btnState[i]=true){
                btnStateLast[i]=true;
                btnState[i]=false;
                }
            }
        }
    for (i=0;i<totalbtn;i+=1){
        if (btnStateLast[i]!=btnState[i])
            {
            io_clear();
            reDraw=true;
            btnStateLast[i]=btnState[i];
           }
        }
    }
io_clear();
screen_redraw();
return userChoice;

Here is some demo code to run it (in a key press, step, or end step event)

Spoiler
Expandif (keyboard_check_pressed(vk_enter)){
    var str,strLen,strMake;
    str="abcdefghijklmnopqrstuvwxyz123456789     "
    strLen=string_length(str);
    strMake="";
    get=scr_messageBoxExt("Caption Box",true,"Button1 returns 1#Button2 returns 2#Button3 returns 3#Button4 returns 4#ect...ect...",true,6,0);
    get=scr_messageBoxExt("Caption Box",true,"Message Box",true,1,0);
    get=scr_messageBoxExt("",true,"No Caption",true,2,0);
    get=scr_messageBoxExt("No Message",false,"",true,2,0);
    get=scr_messageBoxExt("",true,"",true,4,0);
    get=scr_messageBoxExt("Caption Box",true,"Button1 returns 1#Button2 returns 2#Button3 returns 3#Button4 returns 4#ect...ect...",true,8,0);
    repeat(8){
        repeat(60){
            strMake+=string_char_at(str,irandom(strLen));
            }
        strMake+="#"
        }
    get=scr_messageBoxExt(strMake,true,strMake,true,4,0);
    strMake="";
     //-----------   
    get=scr_messageBoxExt("Caption Box",true,strMake,true,1,1);
    get=scr_messageBoxExt("Caption Box",true,"Button1 returns 1#Button2 returns 2#Button3 returns 3#Button4 returns 4#ect...ect...",true,6,1);
    get=scr_messageBoxExt("Caption Box",true,"Message Box",true,1,1);
    get=scr_messageBoxExt("",true,"No Caption",true,2,1);
    get=scr_messageBoxExt("No Message",false,"",true,2,1);
    get=scr_messageBoxExt("",true,"",true,4,1);
    repeat(5){
        repeat(50){
            strMake+=string_char_at(str,irandom(strLen));
            }
        strMake+="#"
        }
    get=scr_messageBoxExt(strMake,true,strMake,true,4,1);
    }

Here is a screenshot:

Spoiler

VWHug.jpg?1

Sorry if the spoilers don't work....
Thanks for looking at my project!
-Neil

Last edited by neil_v (2013-01-13 21:30:19)

Offline

Board footer

Powered by FluxBB