Snippet yadw

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
yadw?!?! Yup =)

yadw - yET aNOTHER dIALOG wRAPPER

NOTE: The recommended structure that scripts using this snippet should follow is not supported by vanilla vJass! The Zinc language is a must!

NOTE: If scripts using this snippet use more that 62 strings literals (color codes, button names and dialog names) in a single statement then an internal jasshelper error will pop!
So if anyone knows how to compile Delphi and has a Delphi compiler you can make me a favour and go to line #5431 in jasshelper.pas and change STRUCT_STRING_LIMIT: integer = 62;
to lets say STRUCT_STRING_LIMIT: integer = 1024; , hopefully that will do the trick and then recompile the jasshelper and upload it to this thread =).


The difference between yadw and other similar snippets is that it relies on the self-return idiom (this-return in our case) to simplify
the creation of dialogs. Now if you are not familiar with this idiom which is nothing new really I will try to describe it as best I can/know.

Well if you've done some basic I/O in C++ then you've already used it =).:
JASS:
function main takes nothing returns joke
    cout << "the" << "I/O" << "operations in C++" << "use it";
    cout << "\n" << "but it can also be found in many other popular languages and libraries";
}


The "<<" and ">>" operators in C++ are really just functions with a definition similar to:

JASS:
...function header... // I really have no idea what does function headers look like in C++
{
    // do I/O

    return this; // &lt;- this single line is what enables the chining of multiple &lt;&lt; or &gt;&gt; operators;
}



Well I admit that was a "phail" for explaining the self-return idiom but it really is just that:
instead of methods returning void/nothing they return their instance variable/pointer aka this/self;


So enough about the "theory" here's the API (in vJass notation) first and then a few simple examples:

legend:
## comment line
>> arguments
<< return type
! the this pointer (assumed for methods)
-- empty line


## Yeah breaking the <structname>create([...]) method convention here but bare with me
--
>> string label = the title/label/message that each dialog can have
<< yadw = a yadw instance
--
[ljass]static method new takes string label returns yadw[/ljass]


## No dialog should ever be destroyed but it can be recycled
<< yadw !
--
[ljass]method clear takes nothing returns yadw[/ljass]


# adds a button to the dialog
--
>> string label = the label of the button
>> integer hotkey = the id of the button usually in ascii notation allowed values: [A-Z0-9]
and the escape key (use the exported KEY_ESC constant), examples: 'A', 'Z', '0', '9', KEY_ESC
<< !
--
[ljass]method button takes string label, integer hotkey returns yadw[/ljass]


## creates a button for the current/this instance
## which when clicked will open the sub/child dialog
>> the arguments are the same as with the button method
<< IMPORTANT: returns a new yadw instance !
--
[ljass]method child takes string label, integer hotkey returns yadw[/ljass]

## creates a button for the current/this instance
## which when clicked will open the parent dialog of the current/this instance
>> the arguments are the same as with the button method
<< !
[ljass]method back takes string label, integer hotkey returns yadw[/ljass]


## returns the parent dialog for the current/this instance
<< IMPORTANT: returns the parent yadw instance for this instance
--
[ljass]method parent takes nothing returns yadw[/ljass]


## sets the label/title/message of the dialog
>> string label = the new label
<< !
[ljass]method set_label takes string label returns yadw[/ljass]


## those two need no commenting but I still took the time to write this line =)
[ljass]method get_user_data takes nothing returns integer[/ljass]
[ljass]method set_user_data takes integer data returns yadw[/ljass]


## sets the handler function which will get execute when the buttons
## (other the those created with the child and back methods) got clicked or hotkeyed
## for the TriggerAddCondition fans I will have to disappoint you but the function should
## return nothing, but feel free to change it (or every other thing) as you want =)
>> code c = a function similar to this:

function <name> takes nothing returns nothing
local yadw y = yadw.event()
local integer hk = y.hotkey()
local integer i = y.get_user_data() + 1

if hk == 'A' then
// do A stuff
elseif hk == 'B' then
// do B stuff
endif
endfunction

--
[ljass]method handler takes code c returns yadw[/ljass]


## when your dialog is done use this method do actually display it to a specific player
>> player p = the player for which the dialog is to be displayed
>> boolean flag = true - display, flase - hide
--
[ljass]method show takes player p, boolean flag returns nothing[/ljass]


So yeah that's it for the API heres the first example:

example 1:

JASS:
//! zinc

library testyadw
{
    yadw SimpleDialog = 0;

    function f()
    {
        // make sure to initialize
        // the dialog only once
        //
        if (SimpleDialog == 0)
        {
            SimpleDialog = yadw.new(&quot;Simple dialog&quot;);

            SimpleDialog
                .button(&quot;button 1&quot;, '1')
                .button(&quot;button 2&quot;, '2')
                .button(&quot;button 9&quot;, '9')
                .handler(function()
                {
                    integer hk = yadw.event().hotkey();

                    if      (hk == '0') { BJDebugMsg(&quot;0&quot;); }
                    else if (hk == '1') { BJDebugMsg(&quot;1&quot;); }
                    else if (hk == '2') { BJDebugMsg(&quot;2&quot;); }
                    else if (hk == '9') { BJDebugMsg(&quot;9&quot;); }
                });
        }

        SimpleDialog.show(GetTriggerPlayer(), true);
    }

    function onInit()
    {
        trigger t = CreateTrigger();
        integer i = 0;

        for (0 &lt;= i &lt; bj_MAX_PLAYERS)
        {
            TriggerRegisterPlayerEventEndCinematic(t, Player(i));
        }
        TriggerAddAction(t, function f);
    }
}

//! endzinc


And example 2 which demonstrates every aspect of the yadw
but still creates a pretty useless dialog =):

JASS:
root = yadw.new(&quot;Game Menu&quot;);
root
        .child(&quot;Units Menu&quot;, 'U')
                .child(&quot;Create Unit&quot;, 'C')
                        .child(&quot;Race&quot;, 'R')
                                .button(&quot;Human&quot;, 'H')
                                .button(&quot;Orc&quot;, 'O')
                                .button(&quot;Night Elf&quot;, 'N')
                                .button(&quot;Undead&quot;, 'U')
                                .back(&quot;Back to Create Unit&quot;, 'B')
                                .handler(function()
                                {
                                    integer hk = yadw.event().hotkey();
                                    
                                    if ('H' == hk) { BJDebugMsg(&quot;clicked Human&quot;); }
                                    else if ('O' == hk) { BJDebugMsg(&quot;clicked Orc&quot;); }
                                    else if ('N' == hk) { BJDebugMsg(&quot;clicked Night Elf&quot;); }
                                    else if ('U' == hk) { BJDebugMsg(&quot;clicked Undead&quot;); }
                                })
                .parent() // a call to the .parent() is required in order to continue adding more buttons to the Create Unit sub dialog
                .back(&quot;Back to Units Menu&quot;, 'B')
        .parent()
        .back(&quot;Back to Game Menu&quot;, 'B')
.parent()
.button(&quot;Exit Game Menu&quot;, 'E');


Yes the above is parsed sucessfully by the jasshelper.

I recommend that a good amount of indentation is used else the structure of the dialog won't be clear.
Then after the dialog is created and tested then if desirted it can be styled, but never hardcode the colors!
And keep the non-colord and colored version aparat.

The attached map has an example of how to workaround the 62 string limit.


JASS:
library yadw
{
    public constant integer KEY_ESC = 512;

    public struct yadw
    {
    private
    {
        dialog        d = DialogCreate();
        trigger       t = CreateTrigger();
        triggeraction a;

        string label;

        button  btns[12];
        integer btns_hk[12];
        integer btns_count = 0;

        yadw    m_parent; // for some strange reason you can't have a method and
                          // an attribute/field/member variable with the same name 
        integer user_data = 0;
        boolean m_is_shown[12];
    }
        yadw    childs[12];


        static method say(string msg)
        {
            BJDebugMsg(msg);
        }

        static hashtable HT;
        static method link(dialog d, yadw y) { SaveInteger(HT, GetHandleId(d), 'link', y); }
        static method event() -&gt; yadw   { return LoadInteger(HT, GetHandleId(GetClickedDialog()), 'link'); }
        method hotkey() -&gt; integer
        {
            button  b = GetClickedButton();
            integer i = 0;

            for (0 &lt;= i &lt; btns_count)
            {
                if (btns<i> == b) { b = null; return btns_hk<i>; }
            }

            // unreachable
            return -1;
        }
        // usage: integer hk = yadw.event().hotkey();
        
        static method new(string label) -&gt; yadw
        {
            yadw this       = yadw.allocate();
                 this.label = label;
                 m_parent   = 0;
            link(d, this);
            TriggerRegisterDialogEvent(t, d);
            return this;
        }

        // no dialog should ever be destroyed
        private method destroy() {}

        method clear() -&gt; yadw
        {
            DialogClear(d);
            label = &quot;&quot;;
            TriggerRemoveAction(t, a);
            return this;
        }

        method button(string label, integer hotkey) -&gt; yadw
        {
            btns[btns_count]    = DialogAddButton(d, label, hotkey);
            btns_hk[btns_count] = hotkey;
            btns_count += 1;
            return this;
        }

        method child(string dialog_label, string button_label, integer hotkey) -&gt; yadw
        {
            integer index  = 0;
            yadw    child  = yadw.new(dialog_label);
            child.m_parent = this;

            button(button_label, hotkey);

            index         = btns_count - 1;
            childs[index] = child;

            SaveInteger(HT, GetHandleId(btns[index]), 'bdex', child);
            TriggerAddAction(t, function()
            {
                if (LoadInteger(HT, GetHandleId(GetClickedButton()), 'bdex') != 0)
                {
                    yadw(LoadInteger(HT, GetHandleId(GetClickedButton()), 'bdex')).show(GetTriggerPlayer(), true);
                }
            });

            return child;
        }

        method back(string label, integer hotkey) -&gt; yadw
        {
            integer index = 0;

            button(label, hotkey);
            index = btns_count - 1;

            SaveInteger(HT, GetHandleId(btns[index]), 'back', m_parent);
            TriggerAddAction(t, function()
            {
                if (LoadInteger(HT, GetHandleId(GetClickedButton()), 'back') != 0)
                {
                    yadw(LoadInteger(HT, GetHandleId(GetClickedButton()), 'back')).show(GetTriggerPlayer(), true);
                }
            });

            return this;
        }

        method parent()                    -&gt; yadw    { return m_parent;                     }
        method set_label(string new_label) -&gt; yadw    { label = new_label;      return this; }
        method set_user_data(integer data) -&gt; yadw    { user_data = data;       return this; }
        method get_user_data()             -&gt; integer { return user_data;                    }


        private static method set_shown_false(yadw y, integer p) { y.m_is_shown[p] = false; }
        method handler(code c) -&gt; yadw 
        { 
            TriggerAddAction(t, function()
            {
                set_shown_false(yadw.event(), GetPlayerId(GetTriggerPlayer()));
            });
            TriggerAddAction(t, c); 
            return this; 
        }

        method is_shown(player p) -&gt; boolean { return m_is_shown[GetPlayerId(p)]; }
            
        method show(player p, boolean flag) 
        { 
            debug
            {
                if (btns_count &lt;= 0) { say(&quot;yadw error: atempt to display a dialog with zero buttons, with id = &quot; + I2S(this)); return; }
            }
            // because of a funny bug dialogs need their 
            // label/title reset everytime before displaying
            //
            DialogSetMessage(d, label);
            DialogDisplay(p, d, flag); 
            m_is_shown[GetPlayerId(p)] = true;
            say(&quot;nooo&quot;);
        }

        static method onInit()
        {
            // HT = &lt;user's map global hashtable&gt; or
            HT = InitHashtable();
        }
    }
}
</i></i>
 

Attachments

azareus

And you know it.
Reaction score
63
...function header... // I really have no idea what does function headers look like in C++
Code:
returnDatatype functionName (datatypeOfArgument1 argument1, datatypeOfArgument2 argument2)
{
    //function
}
For example:
Code:
int doSomeStuff (int a, int b)
{
    return a + b;
}
Anyway, this system seems cool, but it is not really useful unless you need a lot of dialogs. However it seems really useful for something with lots of dialogs.

+Rep
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • jonas jonas:
    where did you go?
  • The Helper The Helper:
    Jefferson TX on a Paranormal Investigation of a haunted bed and breakfast - I got some friends that are paranormal investigators and they have an RV and do YouTubes
    +1
  • The Helper The Helper:
    It was a lot of fun. The RV was bad ass
  • jonas jonas:
    That sounds like fun!
    +1
  • The Helper The Helper:
    it was a blast!
  • The Helper The Helper:
    I am going to post the Youtube of the investigation in the forums when it is ready
    +1
  • jonas jonas:
    cool!
  • vypur85 vypur85:
    Sounds cool TH.
  • tom_mai78101 tom_mai78101:
    I was on a Legend of Zelda marathon...
  • tom_mai78101 tom_mai78101:
    Am still doing it now
    +1
  • jonas jonas:
    which one(s) are you playing?
  • jonas jonas:
    I played a little bit of the switch title two weeks ago and found it quite boring
  • The Helper The Helper:
    just got back from San Antonio this weekend had the best Buffalo Chicken Cheesesteak sandwhich in Universal City, TX - place was called Yous Guys freaking awesome! Hope everyone had a fantastic weekend!
    +1
  • The Helper The Helper:
    Happy Tuesday!
  • The Helper The Helper:
    We have been getting crazy numbers reported by the forum of people online the bots are going crazy on us I think it is AI training bots going at it at least that is what it looks like to me.
  • The Helper The Helper:
    Most legit traffic is tracked on multiple Analytics and we have Cloud Flare setup to block a ton of stuff but still there is large amount of bots that seem to escape detection and show up in the user list of the forum. I have been watching this bullshit for a year and still cannot figure it out it is drving me crazy lol.
    +1
  • Ghan Ghan:
    Beep boop
    +1
  • The Helper The Helper:
    hears robot sounds while 250 bots are on the forum lol
  • The Helper The Helper:
    Happy Saturday!
    +1
  • The Helper The Helper:
    and then it was Thursday...
    +2
  • tom_mai78101 tom_mai78101:
    And then Monday
    +1
  • The Helper The Helper:
    I got the day off today!
    +1
  • tom_mai78101 tom_mai78101:
    How...? (T-T)
  • The Helper The Helper:
    I took the day off. I work for myself so I can do that.
    +1
  • Varine Varine:
    Well I'm already over summer

    The Helper Discord

    Members online

    No members online now.

    Affiliates

    Hive Workshop NUON Dome World Editor Tutorials

    Network Sponsors

    Apex Steel Pipe - Buys and sells Steel Pipe.
    Top