[function] qGUI

Started by Sebastian, Jun 10, 2018, 12:01 AM

Previous topic - Next topic

Sebastian

I do need it, to avoid lots of useless code lines.
I'm sharing it, for people who might need it too.



We all know what's needed to create a basic .... label.
[spoiler=something like this]
        Account.Label4 = GUILabel( );
        Account.Label4.Pos = VectorScreen( 90, 280 );
        Account.Label4.FontSize = 12;
        Account.Label4.TextColour = Colour( 221, 221, 88 );
        Account.Label4.FontFlags = ( GUI_FFLAG_BOLD );
        Account.Label4.Text = "auto-login enabled";
[/spoiler]

6 damn code lines.
What if we gonna create a GUI Register system ? PLENTY of code, which can be shortened a lot.
So what do you say about 1 code line, instead of 6 ? :D
Much better!



I have created a function which does the job, with all the details you need.
For now, it includes code lines for Window, Label, Button, Checkbox, Editbox.
(which I believe are the most used ones so far)

Parameters
Window - qGUI( "window", pos, size, rgb, text, text_rgb, font_size, font_flags, remove_flags )
Label - qGUI( "label", pos, text_size, text_rgb, text, font_flags, font_name )
Button - qGUI( "button", pos, size, rgb, text, text_rgb, font_flags )
Checkbox - qGUI( "checkbox", pos, size, rgb )
Editbox - qGUI( "editbox", pos, size, rgb, text, text_rgb, flags )
(with green are optional arguments)

So here it is:
[noae][noae][noae][noae][noae][noae]function qGUI( type, ... )
{
    if( vargv.len() >= 3 )
    {
        local   q = 0,
                pos = vargv[0],
                size = vargv[1],
                rgb = vargv[2];
               
        switch( type )
        {
            case "window":
            {
                q = GUIWindow();
               
                local   text = vargv[3].tostring(),
                        textrgb = vargv[4],
                        fontsize = vargv[5];
               
                q.Pos = pos;
                q.Size = size;
                q.Colour = Colour( rgb.R, rgb.G, rgb.B, 255 );
                if( rgb.A ) q.Alpha = rgb.A;
               
                q.Text = text;
                q.TextColour = Colour( textrgb.R, textrgb.G, textrgb.B );
                q.FontSize = fontsize;
               
                if( vargv.len() >= 7 ) q.FontFlags = ( vargv[6] );
                if( vargv.len() >= 8 ) q.RemoveFlags( vargv[7] );
            }
            break;
           
            case "label":
            {
                q = GUILabel();
               
                local   text = vargv[3].tostring();
                       
                q.Pos = pos;
                q.FontSize = size
                q.TextColour = Colour( rgb.R, rgb.G, rgb.B );
                q.Text = text;
               
                if( vargv.len() == 5 ) q.FontFlags = ( vargv[4] );
                if( vargv.len() == 6 ) q.FontName = vargv[5];
            }
            break;
           
            case "button":
            {
                q = GUIButton();
               
                local   text = vargv[3],
                        textrgb = vargv[4];
               
                q.Pos = pos;
                q.Size = size;
                q.Colour = Colour( rgb.R, rgb.G, rgb.B );
                q.Text = text;
                q.TextColour = Colour( textrgb.R, textrgb.G, textrgb.B );
               
                if( vargv.len() == 6 ) q.FontFlags = ( vargv[5] );
            }
            break;
           
            case "checkbox":
            {
                q = GUICheckbox();
               
                q.Pos = pos;
                q.Size = size;
                q.Colour = Colour( rgb.R, rgb.G, rgb.B );
            }
            break;
           
            case "editbox":
            {
                q = GUIEditbox();
               
                q.Pos = pos;
                q.Size = size;
                q.Colour = Colour( rgb.R, rgb.G, rgb.B );
               
                if( vargv.len() >= 4 ) q.Text = vargv[3];
                if( vargv.len() >= 5 ) q.TextColour = Colour( vargv[4].R, vargv[4].G, vargv[4].B );
                if( vargv.len() == 6 ) q.AddFlags( vargv[5] ); // like GUI_FLAG_EDITBOX_MASKINPUT
            }
            break;
        }
        if( q != 0 ) return q;
        else return srv_print( "GUI couldn't be created." );
    }
}
[/noae][/noae][/noae][/noae][/noae][/noae]


PS: I know I could set the pos and size and colour overall, by using just 3 lines.
But I preferred not to.

Shadow

A few considerations to be made, I like your idea but I think you could improve your implementation.

For starters, you should check the type of the values that you're dealing with because that can go south really fast (if you don't pass a vector as the first argument, for example). Same applies for type, size, rgb.

Then, why do you need a string for the type? Sorry if this bothers you but you could save some bytes by just declaring an enum. I don't know squirrel anymore but I guess something like this could work?

enum GUI_Types
{
      GUI_WINDOW,
      GUI_LABEL,
      GUI_EDITBOX,
      GUI_CHECKBOX
}

Anyway, great job with the tiny 'library' but it's sad that this has to be shipped to every user's PC. Was looking for a more standardized approach from VC:MP :P

QuotePS:is trash is ur home language??

Stormeus

Quote from: Shadow on Jun 10, 2018, 01:20 AMgreat job with the tiny 'library' but it's sad that this has to be shipped to every user's PC. Was looking for a more standardized approach from VC:MP :P

They already do to an extent.

Quote from: maxorator on Apr 25, 2016, 07:47 PMClient-side squirrel documentation continued (GUI types):
GUIButton

Constructor GUIButton(position, size, colour, text, flags)
Parameter types: VectorScreen, VectorScreen, Colour, string, int

GUICheckbox

Constructor GUICheckbox(position, colour, flags)
Parameter types: VectorScreen, Colour, int

GUIEditbox

Constructor GUIEditbox(position, size, colour, text, flags)
Parameter types: VectorScreen, VectorScreen, Colour, string, int

GUILabel

Constructor GUILabel(position, colour, text, flags)
Parameter types: VectorScreen, Colour, string, int

GUIListbox

Constructor GUIListbox(position, size, colour, selectedColour, flags)
Parameter types: VectorScreen, VectorScreen, Colour, Colour, int

GUIMemobox

Constructor GUIMemobox(position, size, colour, flags)
Parameter types: VectorScreen, VectorScreen, Colour, int

GUIProgressBar

Constructor GUIProgressBar(position, size, colour, selectedColour, flags, endValue)
Parameter types: VectorScreen, VectorScreen, Colour, Colour, int, float

GUIScrollbar

Constructor GUIScrollbar(position, size, colour, flags)
Parameter types: VectorScreen, VectorScreen, Colour, int

GUISprite

Constructor GUISprite(fileName, position, colour, flags)
Parameter types: string, VectorScreen, Colour, int

GUIWindow

Constructor GUIWindow(position, size, colour, text, flags)
Parameter types: VectorScreen, VectorScreen, Colour, string, int

If these constructors (and the other variants listed in that post) don't work then that's a bug. We don't want to make every possible property a constructor parameter since that'd be tedious to work with too; the built-in constructors should be enough to handle common cases, and scripted wrappers can be used to fit a specific server's needs.

Sebastian

#3
Quote from: Shadow on Jun 10, 2018, 01:20 AMFor starters, you should check the type of the values that you're dealing with because that can go south really fast (if you don't pass a vector as the first argument, for example). Same applies for type, size, rgb.

In my opinion, I should not check every thing in this case. It is a function, not a command that every half-brained player can use.
Scripters should be able to read a script, and follow the parameters I've wrote down.
Even so, client will still give an error if there is something wrong; no need to polish an error for scripters.

Quote from: Shadow on Jun 10, 2018, 01:20 AMThen, why do you need a string for the type? Sorry if this bothers you but you could save some bytes by just declaring an enum.

It doesn't bother me. Actually, I appreciate it. It's quite funny, because this is some bad habit of mine, haha :D
I just like to use strings. ::)
I will edit the script and use the enum you said.

EDIT: Actually, idk if I will do the change or not.
You said about saving bytes, but I don't think it is the case. (or I'm just not 'looking' in the right direction)
Personally, I'm not gonna create GUIs server-side (yet), by sending data to the client. I will just do it right in the client.
Even if people wants to send data from server to client, they can always use an integer/byte for the strings I'm using.
Something like: SendDataToClient( player, StreamType.InstantGUI, 1, "Go to /malibu and grab some beers!" )
So when client receives the data, we will do like this:
function Server::ServerData( stream )
{
          local type = stream.ReadByte();
          switch( type )
          {
                    case StreamType.InstantGUI:
                    {
                              local int = stream.ReadInt();
                              if( int == 1 ) qGUI( "label", ... )
                    }
                    break;
          }
}

I will happily improve the code, so please elaborate what you said.
I hope it won't bother you either @Shadow

Quote from: Stormeus on Jun 10, 2018, 03:01 AMIf these constructors (and the other variants listed in that post) don't work then that's a bug.

Don't know about the others, but Label's one is bugged for sure.
GUILabel(position, colour, text, flags)
That's why I started my own one

Shadow

@Sebastian The thing is, you are still using bytes for no reason when calling the constructor. If squirrel emulates C/C++, then you are pushing 5 bytes onto the stack ('l' 'a' 'b' 'e' 'l') and calling the constructor. I don't know if you can have bytes on squirrel but even an integer (4 bytes) would be more optimal for the task.

And the parameter checking is just a recommandation, of course you are free to do what you want because it is your release but I think it would be best to add some nice checks.
QuotePS:is trash is ur home language??

EK.IceFlake

#5
Quote from: Shadow on Jun 10, 2018, 01:04 PM@Sebastian The thing is, you are still using bytes for no reason when calling the constructor. If squirrel emulates C/C++, then you are pushing 5 bytes onto the stack ('l' 'a' 'b' 'e' 'l') and calling the constructor. I don't know if you can have bytes on squirrel but even an integer (4 bytes) would be more optimal for the task.

And the parameter checking is just a recommandation, of course you are free to do what you want because it is your release but I think it would be best to add some nice checks.
Calling GUILabel normally also pushes a lot of bytes on the stacks. It looks somewhat like this in psuedo-assembly:
push the root table # a reference thereof
push "GUILabel" # 8 more bytes on the stack
get # results in roottable["GUILabel"] on the stack

http://www.squirrel-lang.org/squirreldoc/reference/embedding/calling_a_function.html



I'd recommend something like this:
qGUI(whatever, { "Position": position, "Text": "yourText" });
etc.