HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Hotkeys for Dialog Buttons

08-25-2007, 04:03 AM#1
Karawasa
I was searching around the old threads on this forum, and it seems things have changed.

Is is true that an update removed this functionality? The GUI trigger I was reading about is nowhere to be found, and the JASS code I tried says too many arguments are being passed.

Is there anyway to have hotkeys for dialog buttons?
08-25-2007, 04:32 AM#2
Tide-Arc Ephemera
In UMSWE it's a GUI function... and apparently you need to address the keys with ASCII.
08-25-2007, 04:56 AM#3
cohadar
Collapse JASS:
//==============================================================================
//                    DIALOG SYSTEM BY COHADAR -- v1.2
//==============================================================================
//
//  PURPOUSE:
//       * Displaying dialogs the easy way
//       * Retrieving dialog results the easy way
//
//
//  HOW TO USE:
//       * Dialog is basically a struct wrapper around native dialog 
//
//       * First create a dialog,
//            # local Dialog d = NewDialog()
//
//         than we add a title,
//            # call d.SetMessage("Some Text")
//
//         and than we add couple of buttons
//            #	call d.AddButton("First Button",  HK_A)
//            #	call d.AddButton("Second Button", HK_B)
//            #	call d.AddButton("Third",         HK_B)
//
//         HK_X is a hotkey constant for a button,
//         there are constants for all letters + numbers 0..9
//         hotkeys are not case-sensitive
//
//         now we add a callback method for our dialog
//            # call d.AddAction( function SomeFunction )
//         this is the function witch will be called when a player presses a button
//
//         And finally we show the dialog in one of two ways:
//            # call d.ShowAll()      // Displays dialog to all human players
//            # call d.Show( player ) // Displays dialog to specified player
//
//         Inside your callback function you can use GetDialogResult() 
//         to get the hotkey of a clicked button
//
//         You can also use GetTriggerPlayer() to find out witch player pressed the button
//
//  PROS: 
//       * Extremelly easy to use compared to native dialogs
//       * It is fool-proof and will warn you if you try to do something stupid
//
//  CONS:
//       * You can have a maximum of 20 dialog buttons, lol 
//
//  DETAILS:
//       *  Do NOT create and destroy Dialogs directly ( using Dialog.create()/ Dialog.destroy() ) 
//         instead use NewDialog()/ReleaseDialog() methods from Recycler
//
//       * Don't release Dialog before you are sure user has selected something
//
//  REQUIREMENTS:
//       * ABC 4.6 and Collections 2.1b
//
//  HOW TO IMPORT:
//       * Just create a trigger named Dialogs
//       * convert it to text and replace the whole trigger text with this one
//
//==============================================================================

globals
    // Dialog button hotkey constants
    constant integer HK_0 = 48
    constant integer HK_1 = 49
    constant integer HK_2 = 50
    constant integer HK_3 = 51
    constant integer HK_4 = 52
    constant integer HK_5 = 53
    constant integer HK_6 = 54
    constant integer HK_7 = 55
    constant integer HK_8 = 56
    constant integer HK_9 = 57
    
    constant integer HK_A = 65
    constant integer HK_B = 66
    constant integer HK_C = 67
    constant integer HK_D = 68
    constant integer HK_E = 69
    constant integer HK_F = 70
    constant integer HK_G = 71
    constant integer HK_H = 72
    constant integer HK_I = 73
    constant integer HK_J = 74
    constant integer HK_K = 75
    constant integer HK_L = 76
    constant integer HK_M = 77
    constant integer HK_N = 78
    constant integer HK_O = 79
    constant integer HK_P = 80
    constant integer HK_Q = 81
    constant integer HK_R = 82
    constant integer HK_S = 83
    constant integer HK_T = 84
    constant integer HK_U = 85
    constant integer HK_V = 86
    constant integer HK_W = 87
    constant integer HK_X = 88
    constant integer HK_Y = 89
    constant integer HK_Z = 90
endglobals


library Dialogs 
//! runtextmacro COLLECTION("A", "private")

globals
    private constant integer MAX_BUTTONS = 16 // maximum of buttons on dialog
endglobals


function GetDialogResult takes nothing returns integer
    local Dialog d
    local integer ret

    call IteratorA.reset()
    loop
        exitwhen IteratorA.noNext()
        set d = IteratorA.next()
        set ret = d.GetHotkey(GetClickedButton())
    endloop
     
    if ret == 0 then
        call BJDebugMsg("|c00FF0000ERROR: Unknown dialog hotkey")
    endif
    return ret
endfunction

struct Dialog 
    private trigger t = CreateTrigger()
    private dialog  d = DialogCreate()
    private boolean isActionSet = false

    private integer button_count = 0
    private button  array buttons[MAX_BUTTONS]
    private integer array hotkeys[MAX_BUTTONS]
    
    public static method create takes nothing returns Dialog
        local Dialog ret = Dialog.allocate()
        call TriggerRegisterDialogEvent( ret.t, ret.d )    
        call CollectionA.add(ret)
        return ret
    endmethod
    
    // You should not use this method directly
    public method GetHotkey takes button b returns integer
        local integer i = 0
        loop
            exitwhen i >= MAX_BUTTONS
            if b == this.buttons[i] then
                return this.hotkeys[i]
            endif
            set i = i + 1
        endloop    
        return 0
    endmethod
    
    public method SetMessage takes string messageText returns nothing
        call DialogSetMessage( this.d, messageText )
    endmethod
    
    public method AddButton takes string buttonText, integer hotkey returns nothing
        local button b 
        if this.button_count >= MAX_BUTTONS then
            call BJDebugMsg("|c00FF0000WARNING: Maximum number of dialog buttons is " + I2S(MAX_BUTTONS))
        else
            set b = DialogAddButton( this.d,  buttonText , hotkey )
            set this.buttons[this.button_count] = b
            set this.hotkeys[this.button_count] = hotkey
            set  this.button_count = this.button_count + 1
        endif
    endmethod    
    
    public method Clear takes nothing returns nothing
        call DialogClear(this.d)
        set this.button_count = 0
        call TriggerClearActions(this.t)
    endmethod
        
    public method AddAction takes code actionFunc returns nothing
        if this.isActionSet == true then
            call BJDebugMsg("|c00FF0000ERROR: Dialog.AddAction - you cannot set more than one dialog action")
        else
            set this.isActionSet = true
            call TriggerAddAction( this.t, actionFunc )
        endif
    endmethod
    
    public method Show takes player whichPlayer returns nothing
        if this.isActionSet == false then
            call BJDebugMsg("|c00FF0000WARNING: You forgot to set a dialog action")
        endif
        if this.button_count == 0 then
            call BJDebugMsg("|c00FF0000ERROR: You cannot show dialog with no buttons")
        else
            call DialogDisplay(whichPlayer, this.d, true) 
        endif
    endmethod
    
    public method ShowAll takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i>=12 // maximum of human players is 12
            if GetPlayerController(Player(i)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING  then
                call this.Show(Player(i))            
            endif
            set i = i + 1
        endloop
    endmethod
    
    public method Hide takes player whichPlayer returns nothing
        call DialogDisplay(whichPlayer, this.d, false) 
    endmethod

    public method HideAll takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i>=12 // maximum of human players is 12
                call this.Hide(Player(i))            
            set i = i + 1
        endloop
    endmethod
    
    public method onDestroy takes nothing returns nothing
        call BJDebugMsg("|c00FF0000ERROR: don't create/destroy Dialogs directly, use NewDialog/ReleaseDialog instead.")
    endmethod
endstruct



//===========================================================================
function InitTrig_Dialogs takes nothing returns nothing
    call CollectionA.init()
endfunction

endlibrary



I forgot to put recycler:
Hidden information:
Collapse JASS:
//==============================================================================
//  Recycler - recucles timers, groups, Dialogs...
//  Basically extension of CSSafety (disable CSSafety to avoid name clashing)
//  Credits to: Vexorian, Grim001, substance, Cohadar
//==============================================================================
library Recycler uses Dialogs

globals  
    private group array GROUPS 
    private integer GROUP_N = 0 
    
    private timer array TIMERS 
    private integer TIMERS_N = 0 
    
    private Dialog array DIALOGS 
    private integer DIALOGS_N = 0 
endglobals 

function NewGroup takes nothing returns group  
    if (GROUP_N==0) then  
        return CreateGroup()  
    endif  
    set GROUP_N = GROUP_N - 1 
    return GROUPS[GROUP_N] 
endfunction 

function ReleaseGroup takes group g returns nothing  
    call GroupClear(g)  
    set GROUPS[GROUP_N] = g 
    set GROUP_N = GROUP_N + 1 
endfunction 

function NewTimer takes nothing returns timer  
    if (TIMERS_N==0) then  
        return CreateTimer()  
    endif  
    set TIMERS_N = TIMERS_N - 1 
    return TIMERS[TIMERS_N] 
endfunction 

function ReleaseTimer takes timer t returns nothing  
    call PauseTimer(t)  
    set TIMERS[TIMERS_N] = t 
    set TIMERS_N = TIMERS_N + 1 
endfunction 

function NewDialog takes nothing returns Dialog  
    if (DIALOGS_N==0) then  
        return Dialog.create()  
    endif  
    set DIALOGS_N = DIALOGS_N - 1 
    return DIALOGS[DIALOGS_N] 
endfunction 

function ReleaseDialog takes Dialog d returns nothing  
    call d.Clear()
    set DIALOGS[DIALOGS_N] = d
    set DIALOGS_N = DIALOGS_N + 1 
endfunction 

endlibrary

// forced by World Editor
function InitTrig_Recycler takes nothing returns nothing
endfunction


You can find links to other needed systems in my signature.
08-25-2007, 05:56 AM#4
Ammorth
cohadar, I must say, that system looks sexy.
08-25-2007, 07:38 AM#5
cohadar
Well thank you.

I did not get time to release this properly, but it works fine as is.
If anyone has any trouble with this just PM me.

Here is a small example trigger for people to see how to use Dialogs,
when you press escape a dialog will pop up on witch you can select camera distance:
Collapse JASS:
globals
    Dialog CameraDialog = 0
endglobals

function Set_Camera_Callback takes nothing returns nothing
    local integer result = GetDialogResult()
    
    local integer newCameraDistance
    
    if result == HK_1 then
        set newCameraDistance = 1600
    elseif result == HK_2 then
        set newCameraDistance = 2400
    elseif result == HK_3 then
        set newCameraDistance = 3200
    else
        call BJDebugMsg("UNKNOWN RESULT") // This should never happen
    endif
    
    call SetCameraFieldForPlayer( GetTriggerPlayer(), CAMERA_FIELD_TARGET_DISTANCE, newCameraDistance, 0 )
endfunction


function Set_Camera_Actions takes nothing returns nothing
    // create on first use
    if CameraDialog == 0 then
        set  CameraDialog = NewDialog()
        call CameraDialog.SetMessage("Set Camera Distance")
        call CameraDialog.AddButton("|c00FFFFFF1|r600", HK_1)
        call CameraDialog.AddButton("|c00FFFFFF2|r400", HK_2)
        call CameraDialog.AddButton("|c00FFFFFF3|r200", HK_3)
        call CameraDialog.AddAction( function Set_Camera_Callback )
    endif

    call CameraDialog.Show(GetTriggerPlayer()) 
endfunction

//===========================================================================
function InitTrig_Set_Camera_Dialog takes nothing returns nothing
    local trigger t = CreateTrigger( )
    local integer i = 0
    loop 
        exitwhen i>=12 // maximum number of human players is 12
        call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_END_CINEMATIC)
        set i = i + 1
    endloop
    
    call TriggerAddAction( t, function Set_Camera_Actions )
    set t = null
endfunction


08-25-2007, 09:49 AM#6
Anitarf
That's all nice and all, but it doesn't really answer Karawasa's question.
08-25-2007, 10:05 AM#7
cohadar
Since the system is kind of based on hotkeys it kind of does answer the question. ^^
08-25-2007, 04:36 PM#8
Karawasa
Is there anyway to do it without a system? The system is nice, but it requires a lot of additional implementation for one feature.

Would it be possible to detect key presses other than LEFT, RIGHT, DOWN, UP? If so, could use conditions to simulate hotkeys.
08-25-2007, 05:14 PM#9
cohadar
Quote:
Originally Posted by Karawasa
Would it be possible to detect key presses other than LEFT, RIGHT, DOWN, UP? If so, could use conditions to simulate hotkeys.

You could detect ESC

Ok seriously now:
There is no way to detect any other keys that left, right, up, down and esc.

I am getting a feeling here that you are not aiming for dialogs but for something else...
08-25-2007, 11:00 PM#10
emjlr3
this is possible, very possible, I did so in my Week Long Map Contest Winning Map: Jet Moto TFT

the JASS function is

Collapse JASS:
native DialogAddButton              takes dialog whichDialog, string buttonText, integer hotkey returns button

integer hotkey being the key

for instance

Collapse JASS:
DialogAddButton(d,"|cff008080Battleship|r  |cff008000(1)|r",'1')

would set that dialog button's hotkey to 1

i believe this is limited to only integers however :(

i uploaded the map for you to see more
08-25-2007, 11:32 PM#11
Tide-Arc Ephemera
Quote:
Originally Posted by Tide-Arc Ephemera
In UMSWE it's a GUI function... and apparently you need to address the keys with ASCII.

I am pretty sure that it is...
Trigger:
Dialog - Create a dialog button for DialogButton labelled TextHere and keycode 1337
That's what it is in UMSWE for GUI
Collapse JASS:
call DialogAddButtonWithHotkeyBJ( udg_DialogButton, "TextHere", 1337 )

Replace DialogButton with whatever you want it to be, replace TextHere with what ever the button is supposed to say, replace 1337 with the ASCII code for the letter you want to use.

This is probably just retorting what emjlr3 said...
08-26-2007, 12:26 AM#12
Panto
You can use the jass function for dialog box hotkeys as-is. You just need to know the ascii equivalent of the character you want to be the hotkey.

http://www.users.webathletics.com.au/dbridge/ascii.htm

That should give you what you need to make it work. No extra hootenany is necessary or even desirable. Any letter or number should work fine.
08-26-2007, 12:48 PM#13
Anitarf
Quote:
Originally Posted by cohadar
Since the system is kind of based on hotkeys it kind of does answer the question. ^^
Ah, I see, didn't get that when I skimmed over the documentation, my mistake.