Ticket #1492: hotkeys_total.patch

File hotkeys_total.patch, 125.2 KB (added by picobyte, 12 years ago)

latest, shift+ A,S,W,D for mouse cursor movement (e.g. for placing buildings)

  • source/graphics/GameView.cpp

    commit 2da7acd2b3073da8e96a430cce61a37a4799705b
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 23 10:44:06 2012 +0200
    
        This complements the last patch.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
    index 8f58262..64259d5 100644
    a b InReaction CGameView::HandleEvent(const SDL_Event_* ev)  
    11241124        else if (hotkey == "click.left")
    11251125        {
    11261126            g_TouchInput.PressEvent(SDL_BUTTON_LEFT, g_mouse_x, g_mouse_y);
     1127            return IN_HANDLED;
    11271128        }
    11281129        else if (hotkey == "click.right")
    11291130        {
    11301131            g_TouchInput.PressEvent(SDL_BUTTON_RIGHT, g_mouse_x, g_mouse_y);
     1132            return IN_HANDLED;
    11311133        }
    11321134    }
    11331135
  • source/graphics/GameView.cpp

    commit 42b476aa1cca8ec7fc81eccbea8d5227848baea5
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 23 10:30:24 2012 +0200
    
        Actually this is a better location for the button simulation events. Due
        to the frequent call of Update() a click was always treated as doubleclick.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
    index 542bec2..8f58262 100644
    a b void CGameView::Update(const float deltaRealTime)  
    744744        moveRightward = moveForward = 0;
    745745    }
    746746
    747     if (HotkeyIsPressed("click.left"))
    748         g_TouchInput.PressEvent(SDL_BUTTON_LEFT, g_mouse_x, g_mouse_y);
    749     else if (HotkeyIsPressed("click.right"))
    750         g_TouchInput.PressEvent(SDL_BUTTON_RIGHT, g_mouse_x, g_mouse_y);
    751 
    752747    if (g_Joystick.IsEnabled())
    753748    {
    754749        // This could all be improved with extra speed and sensitivity settings
    InReaction CGameView::HandleEvent(const SDL_Event_* ev)  
    11261121            ResetCameraAngleZoom();
    11271122            return IN_HANDLED;
    11281123        }
     1124        else if (hotkey == "click.left")
     1125        {
     1126            g_TouchInput.PressEvent(SDL_BUTTON_LEFT, g_mouse_x, g_mouse_y);
     1127        }
     1128        else if (hotkey == "click.right")
     1129        {
     1130            g_TouchInput.PressEvent(SDL_BUTTON_RIGHT, g_mouse_x, g_mouse_y);
     1131        }
    11291132    }
    11301133
    11311134    return IN_PASS;
  • binaries/data/config/default.cfg

    commit 20cfa97a1857decb9f220438075047a973b3fb2b
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 23 02:03:23 2012 +0200
    
        With this patch, when shift is pressed, or while building the A/W/D/S
        hotkeys steer the location of the build site or mouse pointer. Z and C
        act as left and right mouse buttons.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 6d9bfaa..55c4941 100644
    a b hotkey.selection.group.select.9 = 9  
    193193hotkey.selection.group.save.9 = "Ctrl+9"
    194194hotkey.selection.group.add.9 = "Shift+9"
    195195
     196; action buttons
    196197hotkey.selection.group.action.0 = G
    197198hotkey.selection.group.action.1 = H
    198199hotkey.selection.group.action.2 = J
    hotkey.selection.group.formation.0 = B  
    213214hotkey.selection.group.garrison.0 = N
    214215hotkey.selection.group.ungarrison.0 = M
    215216
     217hotkey.click.left = "Z"
     218hotkey.click.right = "C"
     219
    216220; > SESSION CONTROLS
    217221hotkey.session.kill = Delete                ; Destroy selected units
    218222hotkey.session.garrison = Ctrl              ; Modifier to garrison when clicking on building
  • binaries/data/mods/public/gui/session/input.js

    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index a2cdc0a..f4cc878 100644
    a b function updateCursorAndTooltip()  
    104104    }
    105105}
    106106
     107function CancelBuilding() {
     108    placementSupport.Reset();
     109    Engine.EndPreview();
     110}
     111
    107112function updateBuildingPlacementPreview()
    108113{
    109114    // The preview should be recomputed every turn, so that it responds to obstructions/fog/etc moving underneath it, or
    function tryPlaceBuilding(queued)  
    535540        // TODO: play a sound?
    536541        return false;
    537542    }
     543    Engine.EndPreview();
    538544
    539545    // Start the construction
    540546    Engine.PostNetworkCommand({
    function handleInputBeforeGui(ev, hoveredObject)  
    838844        case "mousebuttondown":
    839845            if (ev.button == SDL_BUTTON_RIGHT)
    840846            {
    841                 // Cancel building
    842                 placementSupport.Reset();
    843                 updateBuildingPlacementPreview();
    844                
     847                CancelBuilding();
    845848                inputState = INPUT_NORMAL;
    846849                return true;
    847850            }
    function handleInputBeforeGui(ev, hoveredObject)  
    897900                           
    898901                            inputState = INPUT_BUILDING_WALL_CLICK;
    899902                        }
    900                         else
    901                         {
    902                             placementSupport.Reset();
     903                    else
     904                    {
     905                        CancelBuilding();
    903906                            inputState = INPUT_NORMAL;
    904907                        }
    905908                    }
    function handleInputBeforeGui(ev, hoveredObject)  
    914917                else if (ev.button == SDL_BUTTON_RIGHT)
    915918                {
    916919                    // reset to normal input mode
    917                     placementSupport.Reset();
    918                     updateBuildingPlacementPreview();
     920                    CancelBuilding();
    919921                   
    920922                    inputState = INPUT_NORMAL;
    921923                    return true;
    function handleInputBeforeGui(ev, hoveredObject)  
    982984            if (ev.button == SDL_BUTTON_RIGHT)
    983985            {
    984986                // Cancel building
    985                 placementSupport.Reset();
     987                CancelBuilding();
    986988                inputState = INPUT_NORMAL;
    987989                return true;
    988990            }
    function handleInputAfterGui(ev)  
    11621164            else if (ev.button == SDL_BUTTON_RIGHT)
    11631165            {
    11641166                // Cancel building
    1165                 placementSupport.Reset();
     1167                CancelBuilding();
    11661168                resetPreselectedAction();
    11671169                return true;
    11681170            }
    function startBuildingPlacement(buildTemplate)  
    14021404    // to start building a structure, then the highlight selection rings are kept during the construction of the building.
    14031405    // Gives the impression that somehow the hovered-over entity has something to do with the building you're constructing.
    14041406   
    1405     placementSupport.Reset();
     1407    CancelBuilding();
    14061408   
    14071409    // find out if we're building a wall, and change the entity appropriately if so
    14081410    var templateData = GetTemplateData(buildTemplate);
  • source/graphics/GameView.cpp

    diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
    index bcba4bb..542bec2 100644
    a b  
    5858#include "simulation2/Simulation2.h"
    5959#include "simulation2/components/ICmpPosition.h"
    6060#include "simulation2/components/ICmpRangeManager.h"
     61#include "simulation2/components/ICmpTemplateManager.h"
    6162#include "lib/external_libraries/libsdl.h"
    6263
    6364extern int g_xres, g_yres;
     65extern CStrW g_CursorName;
    6466
    6567// Maximum distance outside the edge of the map that the camera's
    6668// focus point can be moved
    void CGameView::Update(const float deltaRealTime)  
    737739        moveForward += m->ViewScrollSpeed * deltaRealTime;
    738740    if (HotkeyIsPressed("camera.down"))
    739741        moveForward -= m->ViewScrollSpeed * deltaRealTime;
    740     if (HotkeyIsPressed("session.queue")) {
    741         SDL_WarpMouse(g_mouse_x + moveRightward*2, g_mouse_y - moveForward*2);
     742    if (ICmpTemplateManager::isPreviewActive || HotkeyIsPressed("session.queue")) {
     743        SDL_WarpMouse(g_mouse_x + moveRightward*4, g_mouse_y - moveForward*4);
    742744        moveRightward = moveForward = 0;
    743745    }
    744746
     747    if (HotkeyIsPressed("click.left"))
     748        g_TouchInput.PressEvent(SDL_BUTTON_LEFT, g_mouse_x, g_mouse_y);
     749    else if (HotkeyIsPressed("click.right"))
     750        g_TouchInput.PressEvent(SDL_BUTTON_RIGHT, g_mouse_x, g_mouse_y);
     751
    745752    if (g_Joystick.IsEnabled())
    746753    {
    747754        // This could all be improved with extra speed and sensitivity settings
  • source/gui/scripting/ScriptFunctions.cpp

    diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp
    index d2be90a..eacc01b 100644
    a b  
    5151#include "simulation2/components/ICmpGuiInterface.h"
    5252#include "simulation2/components/ICmpRangeManager.h"
    5353#include "simulation2/components/ICmpTemplateManager.h"
     54#include "simulation2/components/CCmpTemplateManager.h"
    5455#include "simulation2/components/ICmpSelectable.h"
    5556#include "simulation2/helpers/Selection.h"
    5657
    CScriptVal GetProfilerState(void* cbdata)  
    462463    return g_ProfileViewer.SaveToJS(guiManager->GetScriptInterface());
    463464}
    464465
     466void EndPreview(void* UNUSED(cbdata))
     467{
     468    ICmpTemplateManager::isPreviewActive = false;
     469}
     470
    465471
    466472bool IsUserReportEnabled(void* UNUSED(cbdata))
    467473{
    void GuiScriptingInit(ScriptInterface& scriptInterface)  
    629635    scriptInterface.RegisterFunction<bool, std::string, &HotkeyIsPressed_>("HotkeyIsPressed");
    630636    scriptInterface.RegisterFunction<void, std::wstring, &DisplayErrorDialog>("DisplayErrorDialog");
    631637    scriptInterface.RegisterFunction<CScriptVal, &GetProfilerState>("GetProfilerState");
     638    scriptInterface.RegisterFunction<void, &EndPreview>("EndPreview");
    632639
    633640    // User report functions
    634641    scriptInterface.RegisterFunction<bool, &IsUserReportEnabled>("IsUserReportEnabled");
  • source/ps/TouchInput.cpp

    diff --git a/source/ps/TouchInput.cpp b/source/ps/TouchInput.cpp
    index c9f2b80..3b4ff58 100644
    a b void CTouchInput::OnFingerDown(int id, int x, int y)  
    7878    }
    7979}
    8080
     81void CTouchInput::PressEvent(int button, int x, int y)
     82{
     83    SDL_Event_ ev;
     84    ev.ev.button.button = button;
     85    ev.ev.button.x = x;
     86    ev.ev.button.y = y;
     87
     88    ev.ev.type = SDL_MOUSEBUTTONDOWN;
     89    ev.ev.button.state = SDL_PRESSED;
     90    SDL_PushEvent(&ev.ev);
     91
     92    ev.ev.type = SDL_MOUSEBUTTONUP;
     93    ev.ev.button.state = SDL_RELEASED;
     94    SDL_PushEvent(&ev.ev);
     95}
     96
    8197void CTouchInput::OnFingerUp(int id, int x, int y)
    8298{
    8399    debug_printf(L"finger up %d %d %d; state %d\n", id, x, y, m_State);
    void CTouchInput::OnFingerUp(int id, int x, int y)  
    87103    if (m_State == STATE_FIRST_TOUCH && id == 0 && timer_Time() < m_FirstTouchTime + 0.5)
    88104    {
    89105        m_State = STATE_INACTIVE;
    90 
    91         SDL_Event_ ev;
    92         ev.ev.button.button = SDL_BUTTON_LEFT;
    93         ev.ev.button.x = m_Pos[0].X;
    94         ev.ev.button.y = m_Pos[0].Y;
    95 
    96         ev.ev.type = SDL_MOUSEBUTTONDOWN;
    97         ev.ev.button.state = SDL_PRESSED;
    98         SDL_PushEvent(&ev.ev);
    99 
    100         ev.ev.type = SDL_MOUSEBUTTONUP;
    101         ev.ev.button.state = SDL_RELEASED;
    102         SDL_PushEvent(&ev.ev);
     106        PressEvent(SDL_BUTTON_LEFT, m_Pos[0].X, m_Pos[0].Y);
    103107    }
    104108    else if (m_State == STATE_ZOOMING && id == 1)
    105109    {
    void CTouchInput::Frame()  
    166170    if (m_State == STATE_FIRST_TOUCH && t > m_FirstTouchTime + 1.0)
    167171    {
    168172        m_State = STATE_INACTIVE;
    169 
    170         SDL_Event_ ev;
    171         ev.ev.button.button = SDL_BUTTON_RIGHT;
    172         ev.ev.button.x = m_Pos[0].X;
    173         ev.ev.button.y = m_Pos[0].Y;
    174 
    175         ev.ev.type = SDL_MOUSEBUTTONDOWN;
    176         ev.ev.button.state = SDL_PRESSED;
    177         SDL_PushEvent(&ev.ev);
    178 
    179         ev.ev.type = SDL_MOUSEBUTTONUP;
    180         ev.ev.button.state = SDL_RELEASED;
    181         SDL_PushEvent(&ev.ev);
     173        PressEvent(SDL_BUTTON_RIGHT, m_Pos[0].X, m_Pos[0].Y);
    182174    }
    183175}
    184176
  • source/ps/TouchInput.h

    diff --git a/source/ps/TouchInput.h b/source/ps/TouchInput.h
    index 876ed20..2d9ff7b 100644
    a b  
    2828 */
    2929class CTouchInput
    3030{
     31    friend class CGameView;
    3132public:
    3233    CTouchInput();
    3334    ~CTouchInput();
    private:  
    4849    void OnFingerDown(int id, int x, int y);
    4950    void OnFingerUp(int id, int x, int y);
    5051    void OnFingerMotion(int id, int x, int y);
     52    void PressEvent(int, int, int);
    5153
    5254    // Mouse emulation state:
    5355    enum
  • source/simulation2/components/CCmpTemplateManager.cpp

    diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp
    index d69cc36..f25bff4 100644
    a b std::string CCmpTemplateManager::GetCurrentTemplateName(entity_id_t ent)  
    261261
    262262bool CCmpTemplateManager::LoadTemplateFile(const std::string& templateName, int depth)
    263263{
     264    if (templateName.find("preview|") == 0)
     265        ICmpTemplateManager::isPreviewActive = true;
     266
    264267    // If this file was already loaded, we don't need to do anything
    265268    if (m_TemplateFileData.find(templateName) != m_TemplateFileData.end())
    266269        return true;
  • source/simulation2/components/ICmpTemplateManager.cpp

    diff --git a/source/simulation2/components/ICmpTemplateManager.cpp b/source/simulation2/components/ICmpTemplateManager.cpp
    index 6792180..3acd67e 100644
    a b  
    2121
    2222#include "simulation2/system/InterfaceScripted.h"
    2323
     24bool ICmpTemplateManager::isPreviewActive = false;
     25
    2426BEGIN_INTERFACE_WRAPPER(TemplateManager)
    2527DEFINE_INTERFACE_METHOD_1("GetTemplate", const CParamNode*, ICmpTemplateManager, GetTemplate, std::string)
    2628DEFINE_INTERFACE_METHOD_1("GetCurrentTemplateName", std::string, ICmpTemplateManager, GetCurrentTemplateName, entity_id_t)
  • source/simulation2/components/ICmpTemplateManager.h

    diff --git a/source/simulation2/components/ICmpTemplateManager.h b/source/simulation2/components/ICmpTemplateManager.h
    index 1a4ffbb..0b21c89 100644
    a b public:  
    115115     * their new CParamNode), then automatically updating this.template of scripted components.
    116116     */
    117117
     118    /*
     119     * is true if there is currently a preview active.
     120     */
     121    static bool isPreviewActive;
     122
    118123    DECLARE_INTERFACE_TYPE(TemplateManager)
    119124};
    120125
  • source/ps/Hotkey.cpp

    commit 692949243792b178d429ae5cd3207aa043fbd4c1
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Fri Jun 22 20:33:22 2012 +0200
    
        decrease indentation (no functional change)
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/source/ps/Hotkey.cpp b/source/ps/Hotkey.cpp
    index bfb1282..f0ec3f1 100644
    a b static void LoadConfigBindings()  
    7474        for( CConfigValueSet::iterator it = bindingsIt->second.begin(); it != bindingsIt->second.end(); ++it )
    7575        {
    7676            std::string hotkey;
    77             if( it->GetString( hotkey ) )
    78             {
    79                 std::vector<SKey> keyCombination;
    80 
    81                 CParserLine multikeyIdentifier;
    82                 multikeyIdentifier.ParseString( multikeyParser, hotkey );
    83 
    84                 // Iterate through multiple-key bindings (e.g. Ctrl+I)
     77            if( !it->GetString( hotkey ) )
     78                continue;
    8579
    86                 bool negateNext = false;
     80            std::vector<SKey> keyCombination;
    8781
    88                 for( size_t t = 0; t < multikeyIdentifier.GetArgCount(); t++ )
    89                 {
     82            CParserLine multikeyIdentifier;
     83            multikeyIdentifier.ParseString( multikeyParser, hotkey );
    9084
    91                     if( multikeyIdentifier.GetArgString( (int)t, hotkey ) )
    92                     {
    93                         if( hotkey == "_negate" )
    94                         {
    95                             negateNext = true;
    96                             continue;
    97                         }
     85            // Iterate through multiple-key bindings (e.g. Ctrl+I)
    9886
    99                         // Attempt decode as key name
    100                         int mapping = FindKeyCode( hotkey );
     87            bool negateNext = false;
    10188
    102                         // Attempt to decode as a negation of a keyname
    103                         // Yes, it's going a bit far, perhaps.
    104                         // Too powerful for most uses, probably.
    105                         // However, it got some hardcoding out of the engine.
    106                         // Thus it makes me happy.
     89            for( size_t t = 0; t < multikeyIdentifier.GetArgCount(); t++ )
     90            {
     91                if( !multikeyIdentifier.GetArgString( (int)t, hotkey ) )
     92                    continue;
    10793
    108                         if( !mapping )
    109                         {
    110                             LOGWARNING(L"Hotkey mapping used invalid key '%hs'", hotkey.c_str() );
    111                             continue;
    112                         }
     94                if( hotkey == "_negate" )
     95                {
     96                    negateNext = true;
     97                    continue;
     98                }
    11399
    114                         SKey key = { (SDLKEY)mapping, negateNext };
    115                         keyCombination.push_back(key);
     100                // Attempt decode as key name
     101                int mapping = FindKeyCode( hotkey );
    116102
    117                         negateNext = false;
     103                // Attempt to decode as a negation of a keyname
     104                // Yes, it's going a bit far, perhaps.
     105                // Too powerful for most uses, probably.
     106                // However, it got some hardcoding out of the engine.
     107                // Thus it makes me happy.
    118108
    119                     }
     109                if( !mapping )
     110                {
     111                    LOGWARNING(L"Hotkey mapping used invalid key '%hs'", hotkey.c_str() );
     112                    continue;
    120113                }
    121114
    122                 std::vector<SKey>::iterator itKey, itKey2;
     115                SKey key = { (SDLKEY)mapping, negateNext };
     116                keyCombination.push_back(key);
    123117
    124                 for( itKey = keyCombination.begin(); itKey != keyCombination.end(); ++itKey )
    125                 {
    126                     SHotkeyMapping bindCode;
     118                negateNext = false;
     119            }
    127120
    128                     bindCode.name = hotkeyName;
    129                     bindCode.negated = itKey->negated;
     121            std::vector<SKey>::iterator itKey, itKey2;
    130122
    131                     for( itKey2 = keyCombination.begin(); itKey2 != keyCombination.end(); ++itKey2 )
    132                     {
    133                         // Push any auxiliary keys.
    134                         if( itKey != itKey2 )
    135                             bindCode.requires.push_back( *itKey2 );
    136                     }
     123            for( itKey = keyCombination.begin(); itKey != keyCombination.end(); ++itKey )
     124            {
     125                SHotkeyMapping bindCode;
    137126
    138                     g_HotkeyMap[itKey->code].push_back( bindCode );
     127                bindCode.name = hotkeyName;
     128                bindCode.negated = itKey->negated;
     129
     130                for( itKey2 = keyCombination.begin(); itKey2 != keyCombination.end(); ++itKey2 )
     131                {
     132                    // Push any auxiliary keys.
     133                    if( itKey != itKey2 )
     134                        bindCode.requires.push_back( *itKey2 );
    139135                }
     136
     137                g_HotkeyMap[itKey->code].push_back( bindCode );
    140138            }
    141139        }
    142140    }
  • source/graphics/GameView.cpp

    commit ee6f4c47b12346c7cea449b45cf651e8ffec4c71
    Merge: 044c58a 1d0a7c8
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Fri Jun 22 18:27:59 2012 +0200
    
        Merge branch 'master' of git://gitorious.org/0ad/0ad
    
    commit 044c58a829c704157bdb14fbbdcd643dd14cb15c
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Thu Jun 21 01:08:42 2012 +0200
    
        With shift button ASWD move the mouse cursor, e.g. useful for building
        placement
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
    index 0062b44..bcba4bb 100644
    a b  
    5858#include "simulation2/Simulation2.h"
    5959#include "simulation2/components/ICmpPosition.h"
    6060#include "simulation2/components/ICmpRangeManager.h"
     61#include "lib/external_libraries/libsdl.h"
    6162
    6263extern int g_xres, g_yres;
    6364
    void CGameView::Update(const float deltaRealTime)  
    736737        moveForward += m->ViewScrollSpeed * deltaRealTime;
    737738    if (HotkeyIsPressed("camera.down"))
    738739        moveForward -= m->ViewScrollSpeed * deltaRealTime;
     740    if (HotkeyIsPressed("session.queue")) {
     741        SDL_WarpMouse(g_mouse_x + moveRightward*2, g_mouse_y - moveForward*2);
     742        moveRightward = moveForward = 0;
     743    }
    739744
    740745    if (g_Joystick.IsEnabled())
    741746    {
  • binaries/data/mods/public/gui/session/input.js

    commit 23689b0de0482557d0419b2b1024b983695fa8d8
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Tue Jun 19 22:21:27 2012 +0200
    
        pushing the buttons sent it into band-boxing
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 4889b79..a2cdc0a 100644
    a b function performCommand(entity, commandName)  
    15401540                    openDeleteDialog(selection);
    15411541                break;
    15421542            case "garrison":
    1543                 inputState = INPUT_SELECTING;
     1543                inputState = INPUT_PRESELECTEDACTION;
    15441544                preSelectedAction = ACTION_GARRISON;
    15451545                break;
    15461546            case "repair":
    1547                 inputState = INPUT_SELECTING;
     1547                inputState = INPUT_PRESELECTEDACTION;
    15481548                preSelectedAction = ACTION_BUILD;
    15491549                break;
    15501550            case "unload-all":
  • binaries/data/mods/public/gui/session/session.xml

    commit 72653544c017a44fe52df44c87c4f4af386962d5
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Tue Jun 19 22:20:01 2012 +0200
    
        fixes buttons after a recent commit
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml
    index 58b6f9d..a55a7bd 100644
    a b  
    776776        <object name="unitCommandPanel"
    777777            size="0 100%-36 100% 100%-4"
    778778            type="image"
    779             z="30"
     779            z="50"
    780780        >
    781781            <object size="0 0 100% 100%">
    782782            <repeat count="6">
  • binaries/data/mods/public/gui/session/session.xml

    commit b8af7852f082c7f288904468d306cf66e226a40e
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Tue Jun 19 17:57:17 2012 +0200
    
        reapply these changes for find idle unit hotkeys and friends
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml
    index 3ff530a..58b6f9d 100644
    a b  
    8585    </object>
    8686
    8787        <!-- Find idle warrior - TODO: Potentially move this to own UI button? -->
    88     <object hotkey="selection.idlewarrior">
    89         <action on="Press">findIdleUnit(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"]);</action>
    90     </object>
     88        <object hotkey="selection.idlewarrior">
     89            <action on="Press">findEntity(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"], 1);</action>
     90        </object>
     91
     92        <!-- Select civilcenter -->
     93        <object hotkey="selection.civilcenter">
     94            <action on="Press">findEntity(["CivCentre"], 0);</action>
     95        </object>
     96        <!-- Select market -->
     97        <object hotkey="selection.market">
     98            <action on="Press">findEntity(["BarterMarket", "Market", "NavalMarket"], 0);</action>
     99        </object>
     100        <!-- Select dropsitefood -->
     101        <object hotkey="selection.dropsitefood">
     102            <action on="Press">findEntity(["CivCentre", "DropsiteFood"], 0);</action>
     103        </object>
     104        <!-- Select dropsitewood -->
     105        <object hotkey="selection.dropsiteres">
     106            <action on="Press">findEntity(["CivCentre", "DropsiteWood", "DropsiteStone", "DropsiteMetal"], 0);</action>
     107        </object>
     108        <!-- Select structure -->
     109        <object hotkey="selection.structure">
     110            <action on="Press">findEntity(["Structure"], 0);</action>
     111        </object>
    91112
    92113    <!-- ================================  ================================ -->
    93114    <!-- Developer / Debug items -->
     
    527548            >
    528549            <!-- TODO: should highlight the button if there's non-zero idle workers -->
    529550            <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" />
    530             <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action>
     551            <action on="Press">findEntity(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"], 1);</action>
    531552            </object>
    532553        </object>
    533554        </object>
     
    586607            </repeat>
    587608            </object>
    588609        </object>
    589 
    590610        <!-- Stance Selection -->
    591611        <object name="unitStancePanel"
    592612            style="TranslucentPanel"
  • source/gui/MiniMap.cpp

    commit 28f4c47308285284a095b152881f75022c09f7a2
    Merge: 4953e92 78a92ff
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Tue Jun 19 17:49:39 2012 +0200
    
        Merge branch 'master' of git://gitorious.org/0ad/0ad
        
        Conflicts:
        	binaries/data/mods/public/gui/session/session.xml
    
    commit 4953e92e36023c2839617f99ac10b0207de580c6
    Merge: 6ab9e41 4d551ff
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Mon Jun 18 20:16:29 2012 +0200
    
        Merge branch 'master' of git://gitorious.org/0ad/0ad
        
        Conflicts:
        	binaries/data/mods/public/gui/session/session.xml
    
    commit 6ab9e4126e9d27531f2ce9e92799d02bf591ee33
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sun Jun 17 23:45:42 2012 +0200
    
        There's no need to cast to float and then back again to uint
        Don't calculate average height in every iteration
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/source/gui/MiniMap.cpp b/source/gui/MiniMap.cpp
    index f05da71..237b502 100644
    a b  
    4444
    4545bool g_GameRestarted = false;
    4646
    47 static unsigned int ScaleColor(unsigned int color, float x)
     47static unsigned int ScaleColor(unsigned int color, unsigned int val, unsigned int div)
    4848{
    49     unsigned int r = unsigned(float(color & 0xff) * x);
    50     unsigned int g = unsigned(float((color>>8) & 0xff) * x);
    51     unsigned int b = unsigned(float((color>>16) & 0xff) * x);
     49    unsigned int r = (color & 0xff) * val / div;
     50    unsigned int g = ((color>>8) & 0xff) * val / div;
     51    unsigned int b = ((color>>16) & 0xff) * val / div;
    5252    return (0xff000000 | r | g<<8 | b<<16);
    5353}
    5454
    void CMiniMap::RebuildTerrainTexture()  
    483483    u32 y = 0;
    484484    u32 w = m_MapSize - 1;
    485485    u32 h = m_MapSize - 1;
    486     float waterHeight = g_Renderer.GetWaterManager()->m_WaterHeight;
     486    float waterHeight = g_Renderer.GetWaterManager()->m_WaterHeight * 4.0f;
    487487
    488488    m_TerrainDirty = false;
    489489
    void CMiniMap::RebuildTerrainTexture()  
    492492        u32 *dataPtr = m_TerrainData + ((y + j) * (m_MapSize - 1)) + x;
    493493        for(u32 i = 0; i < w; i++)
    494494        {
    495             float avgHeight = ( m_Terrain->GetVertexGroundLevel((int)i, (int)j)
     495            float avgHeight = m_Terrain->GetVertexGroundLevel((int)i, (int)j)
    496496                    + m_Terrain->GetVertexGroundLevel((int)i+1, (int)j)
    497497                    + m_Terrain->GetVertexGroundLevel((int)i, (int)j+1)
    498                     + m_Terrain->GetVertexGroundLevel((int)i+1, (int)j+1)
    499                 ) / 4.0f;
     498                    + m_Terrain->GetVertexGroundLevel((int)i+1, (int)j+1);
    500499
    501500            if(avgHeight < waterHeight)
    502501            {
    void CMiniMap::RebuildTerrainTexture()  
    525524                    }
    526525                }
    527526
    528                 *dataPtr++ = ScaleColor(color, float(val) / 255.0f);
     527                *dataPtr++ = ScaleColor(color, val, 255);
    529528            }
    530529        }
    531530    }
  • binaries/data/mods/public/gui/session/messages.js

    commit 3057bbac81a788796465daa2a85179cef1b56370
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sun Jun 17 09:44:08 2012 +0200
    
        The fall trough causes obj.caption to be overwritten
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js
    index d77b4c9..b681ac9 100644
    a b function handleNetMessage(message)  
    9090        case "connected":
    9191            obj.caption = "Connected to the server.";
    9292            obj.hidden = false;
     93            break;
    9394        case "authenticated":
    9495            obj.caption = "Connection to the server has been authenticated.";
    9596            obj.hidden = false;
     97            break;
    9698        case "disconnected":
    9799            obj.caption = "Connection to the server has been lost.\n\nThe game has ended.";
    98100            obj.hidden = false;
  • libraries/spidermonkey/include-win32/js/jstracer.h

    commit 4824e759a2f2af86ca012c8d156abc8e143c0dc5
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 16 23:19:21 2012 +0200
    
        _len == _max is out of bounds for _data[]
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/libraries/spidermonkey/include-win32/js/jstracer.h b/libraries/spidermonkey/include-win32/js/jstracer.h
    index 76921cc..bd992c2 100644
    a b public:  
    106106
    107107    void add(T a) {
    108108        ensure(_len + 1);
    109         JS_ASSERT(_len <= _max);
     109        JS_ASSERT(_len < _max);
    110110        _data[_len++] = a;
    111111    }
    112112
    113113    void add(T* chunk, unsigned size) {
    114114        ensure(_len + size);
    115         JS_ASSERT(_len <= _max);
     115        JS_ASSERT(_len < _max);
    116116        memcpy(&_data[_len], chunk, size * sizeof(T));
    117117        _len += size;
    118118    }
  • binaries/data/mods/public/gui/session/input.js

    commit 27fb5efe94c15254701744292c7f9d8dab37db5d
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 16 16:25:50 2012 +0200
    
        this patch implements double click of . for select all villagers. Same
        goes for comma and friends.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 743bdf8..4889b79 100644
    a b function determineAction(x, y, fromMinimap)  
    467467    {
    468468        target = targets[0];
    469469    }
     470    if (Engine.HotkeyIsPressed("session.garrison"))
     471        preSelectedAction = ACTION_GARRISON;
    470472
    471     if (preSelectedAction != ACTION_NONE)
     473    if (preSelectedAction & (ACTION_GARRISON|ACTION_BUILD))
    472474    {
    473475        switch (preSelectedAction)
    474476        {
    function determineAction(x, y, fromMinimap)  
    486488            break;
    487489        }
    488490    }
    489     else if (Engine.HotkeyIsPressed("session.garrison") || preSelectedAction == ACTION_GARRISON)
    490     {
    491         if (getActionInfo("garrison", target).possible)
    492             return {"type": "garrison", "cursor": "action-garrison", "target": target};
    493         else
    494             return  {"type": "none", "cursor": "action-garrison-disabled", "target": undefined};
    495     }
    496491    else
    497492    {
    498493        var actionInfo = undefined;
    function handleInputAfterGui(ev)  
    11231118                    resetPreselectedAction();
    11241119                    return true;
    11251120                }
    1126 
    11271121                var selectedEntity = ents[0];
    1128                 var now = new Date();
    11291122
    11301123                // If camera following and we select different unit, stop
    11311124                if (Engine.GetFollowedEntity() != selectedEntity)
    11321125                {
    11331126                    Engine.CameraFollow(0);
    11341127                }
    1135 
    1136                 if ((now.getTime() - doubleClickTimer < doubleClickTime) && (selectedEntity == prevClickedEntity))
    1137                 {
    1138                     // Double click or triple click has occurred
    1139                     var showOffscreen = Engine.HotkeyIsPressed("selection.offscreen");
    1140                     var matchRank = true;
    1141                     var templateToMatch;
    1142 
    1143                     // Check for double click or triple click
    1144                     if (!doubleClicked)
    1145                     {
    1146                         // If double click hasn't already occurred, this is a double click.
    1147                         // Select similar units regardless of rank
    1148                         templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).identity.selectionGroupName;
    1149                         if (templateToMatch)
    1150                         {
    1151                             matchRank = false;
    1152                         }
    1153                         else
    1154                         {   // No selection group name defined, so fall back to exact match
    1155                             templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template;
    1156                         }
    1157 
    1158                         doubleClicked = true;
    1159                         // Reset the timer so the user has an extra period 'doubleClickTimer' to do a triple-click
    1160                         doubleClickTimer = now.getTime();
    1161                     }
    1162                     else
    1163                     {
    1164                         // Double click has already occurred, so this is a triple click.
    1165                         // Select units matching exact template name (same rank)
    1166                         templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template;
    1167                     }
    1168 
    1169                     // TODO: Should we handle "control all units" here as well?
    1170                     ents = Engine.PickSimilarFriendlyEntities(templateToMatch, showOffscreen, matchRank, false);
    1171                 }
    1172                 else
    1173                 {
    1174                     // It's single click right now but it may become double or triple click
    1175                     doubleClicked = false;
    1176                     doubleClickTimer = now.getTime();
    1177                     prevClickedEntity = selectedEntity;
    1178 
    1179                     // We only want to include the first picked unit in the selection
    1180                     ents = [ents[0]];
    1181                 }
    1182 
    1183                 // Update the list of selected units
    1184                 if (Engine.HotkeyIsPressed("selection.add"))
    1185                 {
    1186                     g_Selection.addList(ents);
    1187                 }
    1188                 else if (Engine.HotkeyIsPressed("selection.remove"))
    1189                 {
    1190                     g_Selection.removeList(ents);
    1191                 }
    1192                 else
    1193                 {
    1194                     g_Selection.reset();
    1195                     g_Selection.addList(ents);
    1196                 }
    1197                 resetPreselectedAction();
     1128                ClickSelected(ents, (selectedEntity == prevClickedEntity));
    11981129                return true;
    11991130            }
    12001131            break;
    function handleInputAfterGui(ev)  
    12621193    return false;
    12631194}
    12641195
     1196function ClickSelected(ents, is_same)
     1197{
     1198    var selectedEntity = ents[0];
     1199    var now = new Date();
     1200
     1201    if ((now.getTime() - doubleClickTimer < doubleClickTime) && is_same)
     1202    {
     1203        // Double click or triple click has occurred
     1204        var showOffscreen = Engine.HotkeyIsPressed("selection.offscreen");
     1205        var matchRank = true;
     1206        var templateToMatch;
     1207
     1208        // Check for double click or triple click
     1209        if (!doubleClicked)
     1210        {
     1211            // If double click hasn't already occurred, this is a double click.
     1212            // Select similar units regardless of rank
     1213            templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).identity.selectionGroupName;
     1214            if (templateToMatch)
     1215            {
     1216                matchRank = false;
     1217            }
     1218            else
     1219            {   // No selection group name defined, so fall back to exact match
     1220                templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template;
     1221            }
     1222
     1223            doubleClicked = true;
     1224            // Reset the timer so the user has an extra period 'doubleClickTimer' to do a triple-click
     1225            doubleClickTimer = now.getTime();
     1226        }
     1227        else
     1228        {
     1229            // Double click has already occurred, so this is a triple click.
     1230            // Select units matching exact template name (same rank)
     1231            templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template;
     1232        }
     1233
     1234        // TODO: Should we handle "control all units" here as well?
     1235        ents = Engine.PickSimilarFriendlyEntities(templateToMatch, showOffscreen, matchRank, false);
     1236    }
     1237    else
     1238    {
     1239        // It's single click right now but it may become double or triple click
     1240        doubleClicked = false;
     1241        doubleClickTimer = now.getTime();
     1242        prevClickedEntity = selectedEntity;
     1243
     1244        // We only want to include the first picked unit in the selection
     1245        ents = [ents[0]];
     1246    }
     1247
     1248    // Update the list of selected units
     1249    if (Engine.HotkeyIsPressed("selection.add"))
     1250    {
     1251        g_Selection.addList(ents);
     1252    }
     1253    else if (Engine.HotkeyIsPressed("selection.remove"))
     1254    {
     1255        g_Selection.removeList(ents);
     1256    }
     1257    else
     1258    {
     1259        g_Selection.reset();
     1260        g_Selection.addList(ents);
     1261    }
     1262    resetPreselectedAction();
     1263}
     1264
    12651265function doAction(action, ev)
    12661266{
    12671267    var selection = g_Selection.toList();
    function findAllVisibleEntities(classes, mode)  
    19101910    }
    19111911}
    19121912
     1913// mode 0 is to search for idle, 1 to search for any
    19131914function findEntity(classes, mode)
    19141915{
    19151916    var queued = Engine.HotkeyIsPressed("session.queue");
    function findEntity(classes, mode)  
    19181919        return;
    19191920    }
    19201921    var player = Engine.GetPlayerID();
     1922
    19211923    // Cycle through idling classes before giving up
    19221924    for (var i = 0; i <= classes.length; ++i)
    19231925    {
    function findEntity(classes, mode)  
    19291931                resetPreselectedAction();
    19301932            else if (preSelectedAction == ACTION_BUILD)
    19311933                updateBuildingPlacementPreview();
    1932 
    19331934            lastEntity = newEntity;
    1934             g_Selection.reset();
    1935             g_Selection.addList([lastEntity]);
    1936             Engine.CameraFollow(lastEntity);
     1935            ClickSelected([newEntity], 1);
    19371936            return;
    19381937        }
    19391938        lastEntity = 0;
  • binaries/data/config/default.cfg

    commit 8667be2fa976064e67569141734d319c8401d385
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Thu Jun 14 00:54:35 2012 +0200
    
        This implements the V, B, N and M hotkeys for
        Stance, Formation, garrison, ungarrison respectively
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 5015b15..9e7c9aa 100644
    a b hotkey.selection.group.action.10 = "Ctrl+K"  
    203203hotkey.selection.group.action.11 = "Ctrl+L"
    204204hotkey.selection.group.action.12 = "Ctrl+Semicolon"
    205205hotkey.selection.group.action.13 = "Ctrl+SingleQuote"
    206 hotkey.selection.group.action.reset = ForwardSlash
     206hotkey.selection.group.reset.0 = ForwardSlash
     207hotkey.selection.group.stance.0 = V
     208hotkey.selection.group.formation.0 = B
     209hotkey.selection.group.garrison.0 = N
     210hotkey.selection.group.ungarrison.0 = M
    207211
    208212; > SESSION CONTROLS
    209213hotkey.session.kill = Delete                ; Destroy selected units
  • binaries/data/mods/public/gui/session/input.js

    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index adb7bb5..743bdf8 100644
    a b const INPUT_BATCHTRAINING = 6;  
    3535const INPUT_PRESELECTEDACTION = 7;
    3636const INPUT_BUILDING_WALL_CLICK = 8;
    3737const INPUT_BUILDING_WALL_PATHING = 9;
     38const INPUT_ACTION_STATE = 10;
    3839
    3940var inputState = INPUT_NORMAL;
    4041var placementSupport = new PlacementSupport();
    function handleInputAfterGui(ev)  
    10281029    switch (inputState)
    10291030    {
    10301031    case INPUT_NORMAL:
     1032    case INPUT_ACTION_STATE:
    10311033        switch (ev.type)
    10321034        {
    10331035        case "mousemotion":
    function performCommand(entity, commandName)  
    15381540                    openDeleteDialog(selection);
    15391541                break;
    15401542            case "garrison":
    1541                 inputState = INPUT_PRESELECTEDACTION;
     1543                inputState = INPUT_SELECTING;
    15421544                preSelectedAction = ACTION_GARRISON;
    15431545                break;
    15441546            case "repair":
    1545                 inputState = INPUT_PRESELECTEDACTION;
     1547                inputState = INPUT_SELECTING;
    15461548                preSelectedAction = ACTION_BUILD;
    15471549                break;
    15481550            case "unload-all":
    function handleHotkey(ev)  
    15931595    {
    15941596        var sptr = ev.hotkey.split(".");
    15951597        var now = new Date();
    1596         if (inputState = INPUT_NORMAL && (ev.hotkey == prevHotkey) &&
     1598        if ((inputState == INPUT_NORMAL) && (ev.hotkey == prevHotkey) &&
    15971599                ev.hotkey.indexOf("selection.group.select.") == 0 &&
    15981600                (now.getTime() - doublePressTimer < doublePressTime)) {
    15991601            performGroup("snap", sptr[3]);
    function handleHotkey(ev)  
    16081610}
    16091611
    16101612// Performs the specified group
    1611 function performGroup(action, nr)
     1613function performGroup(action, x)
    16121614{
    1613     if (nr == "reset")
    1614     {
    1615         resetPreselectedAction();
    1616         return;
    1617     }
    16181615    switch (action)
    16191616    {
    16201617    case "snap":
    function performGroup(action, nr)  
    16221619    case "add":
    16231620        var toSelect = [];
    16241621        g_Groups.update();
    1625         for (var ent in g_Groups.groups[nr].ents)
     1622        for (var ent in g_Groups.groups[x].ents)
    16261623            toSelect.push(+ent);
    16271624
    16281625        if (action != "add")
    function performGroup(action, nr)  
    16321629
    16331630        if (action == "snap" && toSelect.length)
    16341631            Engine.CameraFollow(toSelect[0]);
    1635         break;
     1632        return;
    16361633    case "save":
    16371634        var selection = g_Selection.toList();
    1638         g_Groups.groups[nr].reset();
    1639         g_Groups.addEntities(nr, selection);
     1635        g_Groups.groups[x].reset();
     1636        g_Groups.addEntities(x, selection);
    16401637        updateGroups();
    1641         break;
     1638        return;
    16421639    case "action":
    16431640        var selection = g_Selection.toList();
    16441641        var player = Engine.GetPlayerID();
     1642        if (inputState != INPUT_ACTION_STATE)
     1643            preSelectedAction = getDefaultActionForSelection(player, selection);
     1644        break;
     1645    case "reset":
     1646        resetPreselectedAction();
     1647        return;
     1648    case "garrison":
     1649        preSelectedAction = ACTION_GARRISON;
     1650        inputState = INPUT_PRESELECTEDACTION;
     1651        return;
     1652    case "ungarrison":
     1653        preSelectedAction = ACTION_UNGARRISON;
     1654        inputState = INPUT_ACTION_STATE;
     1655        return;
     1656    case "stance":
     1657        preSelectedAction = ACTION_STANCE;
     1658        inputState = INPUT_ACTION_STATE;
     1659        return;
     1660    case "formation":
     1661        preSelectedAction = ACTION_FORMATION;
     1662        inputState = INPUT_ACTION_STATE;
     1663        return;
     1664    }
     1665    if (inputState == INPUT_ACTION_STATE)
     1666        inputState = INPUT_NORMAL;
     1667    if (preSelectedAction == ACTION_NONE)
     1668        return;
    16451669
    1646         preSelectedAction = getDefaultActionForSelection(player, selection);
    1647         if (preSelectedAction == ACTION_NONE)
    1648             break;
     1670    var lst = selectAction(player, selection);
     1671    if (!lst) // shouldn't happen
     1672        return;
    16491673
    1650         var lst = selectAction(player, selection);
    1651         if (!lst) // shouldn't happen
    1652             break;
     1674    if (preSelectedAction & ACTION_GARRISON)
     1675    {
     1676        if (++x > lst.length)
     1677            x = lst.length;
     1678    } else if (preSelectedAction != ACTION_UNGARRISON) {
     1679        if (x >= lst.length)
     1680            return;
     1681        lst = lst[x];
     1682    }
    16531683
    1654         if (preSelectedAction & ACTION_GARRISON)
    1655         {
    1656             if (++nr > lst.length)
    1657                 nr = lst.length;
    1658         } else if (preSelectedAction != ACTION_UNGARRISON) {
    1659             if (nr >= lst.length)
    1660                 break;
    1661             lst = lst[nr];
     1684    switch (preSelectedAction)
     1685    {
     1686    case ACTION_BUILD:
     1687        var tmpl = GetTemplateData(lst);
     1688        if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
     1689            // N.B. sets inputState = INPUT_BUILDING_PLACEMENT:
     1690            startBuildingPlacement(lst);
     1691            placementSupport.position = Engine.GetTerrainAtScreenPoint(mouseX, mouseY);
     1692            initBuildingPlacementView();
    16621693        }
    1663 
    1664         switch (preSelectedAction)
    1665         {
    1666         case ACTION_BUILD:
    1667             var tmpl = GetTemplateData(lst);
    1668             if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
    1669                 // N.B. sets inputState = INPUT_BUILDING_PLACEMENT:
    1670                 startBuildingPlacement(lst);
    1671                 placementSupport.position = Engine.GetTerrainAtScreenPoint(mouseX, mouseY);
    1672                 initBuildingPlacementView();
    1673             }
    1674             break;
    1675         case ACTION_TRAIN:
    1676             var tmpl = GetTemplateData(lst);
    1677             if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
    1678                 var ents = g_Selection.toList();
    1679                 addTrainingToQueue(ents, lst);
    1680             }
    1681             break;
    1682         case ACTION_GARRISON: // we garison nr+1 count
    1683             g_Selection.reset();
    1684             lst.splice(nr, lst.length - nr)
    1685             g_Selection.addList(lst);
    1686             inputState = INPUT_PRESELECTEDACTION;
    1687             break;
    1688         case ACTION_UNGARRISON:
    1689             if (lst.length > 1 || nr == 0) {
    1690                 if (nr >= lst.length)
    1691                     nr = lst.length - 1;
    1692                 if (lst.length != 1 && nr == 0) {
    1693                     // unload all from all buildings
    1694                     for each (var gh in lst)
    1695                         unloadAll(gh);
    1696                 } else {
    1697                     if (lst.length != 1)
    1698                         nr--;
    1699                     unloadAll(lst[nr]);
    1700                 }
    1701                 g_Selection.reset();
    1702                 break;
     1694        break;
     1695    case ACTION_TRAIN:
     1696        var tmpl = GetTemplateData(lst);
     1697        if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
     1698            var ents = g_Selection.toList();
     1699            addTrainingToQueue(ents, lst);
     1700        }
     1701        break;
     1702    case ACTION_GARRISON: // we garison x+1 count
     1703        g_Selection.reset();
     1704        lst.splice(x, lst.length - x)
     1705        g_Selection.addList(lst);
     1706        inputState = INPUT_PRESELECTEDACTION;
     1707        break;
     1708    case ACTION_UNGARRISON:
     1709        if (lst.length > 1 || x == 0) {
     1710            if (x >= lst.length)
     1711                x = lst.length - 1;
     1712            if (lst.length != 1 && x == 0) {
     1713                // unload all from all buildings
     1714                for each (var gh in lst)
     1715                    unloadAll(gh);
    17031716            } else {
    1704                 lst = lst[0];
    1705                 var state = GetEntityState(lst);
    1706                 var gents = state.garrisonHolder.entities;
    1707                 if (nr > gents.length)
    1708                     nr = gents.length;
    1709                 while (nr--)
    1710                     Engine.PostNetworkCommand({"type": "unload", "entities": [gents[nr]], "garrisonHolder": lst});
    1711                 // we could assign a key to follow them here
    1712                 break;
     1717                if (lst.length != 1)
     1718                    x--;
     1719                unloadAll(lst[x]);
    17131720            }
    1714             break;
    1715         case ACTION_FORMATION:
    1716             ents = g_Selection.toList();
    1717             var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
    1718                 "ents": g_Selection.toList(),
    1719                 "formationName": lst
    1720             });
    1721             if (formationOk)
    1722                 performFormation(ents, lst);
    1723             break
    1724         case ACTION_STANCE:
    1725             ents = g_Selection.toList();
    1726             performStance(ents, lst);
    1727             break;
    1728         case ACTION_BARTER: //TODO
    1729             break;
    1730         case ACTION_TRADER: //TODO
    1731             break;
     1721            g_Selection.reset();
     1722        } else {
     1723            lst = lst[0];
     1724            var state = GetEntityState(lst);
     1725            var gents = state.garrisonHolder.entities;
     1726            if (x > gents.length)
     1727                x = gents.length;
     1728            while (x--)
     1729                Engine.PostNetworkCommand({"type": "unload", "entities": [gents[x]], "garrisonHolder": lst});
     1730            // we could assign a key to follow them here
    17321731        }
    17331732        break;
     1733    case ACTION_FORMATION:
     1734        ents = g_Selection.toList();
     1735        var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
     1736            "ents": g_Selection.toList(),
     1737            "formationName": lst
     1738        });
     1739        if (formationOk)
     1740            performFormation(ents, lst);
     1741        break
     1742    case ACTION_STANCE:
     1743        ents = g_Selection.toList();
     1744        performStance(ents, lst);
     1745        break;
     1746    case ACTION_BARTER: //TODO
     1747        break;
     1748    case ACTION_TRADER: //TODO
     1749        break;
    17341750    }
    17351751}
    17361752
    17371753// This returns a list of actions. Caller still has to check Technology availability
    17381754function selectAction(player, selection)
    17391755{
    1740     var ret = [];
    17411756    if (preSelectedAction == ACTION_FORMATION)
    1742     {
    17431757        return Engine.GuiInterfaceCall("GetAvailableFormations");
    1744     } else if (preSelectedAction == ACTION_STANCE)
    1745     {
     1758    else if (preSelectedAction == ACTION_STANCE)
    17461759        return ["violent", "aggressive", "passive", "defensive", "standground"];
    1747     }
     1760
     1761    var ret = [];
    17481762    for each (var ent in selection)
    17491763    {
    17501764        var state = GetEntityState(ent);
  • binaries/data/mods/public/gui/session/input.js

    commit 286f76f2aa3bf8259fe4de6edb279e89d6215484
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 23:41:05 2012 +0200
    
        don't mix up function argument and global
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 37508f3..adb7bb5 100644
    a b function handleInputAfterGui(ev)  
    10661066        switch (ev.type)
    10671067        {
    10681068        case "mousebuttondown":
    1069             if (ev.button == SDL_BUTTON_LEFT && preSelectedAction)
     1069            if (ev.button == SDL_BUTTON_LEFT && preSelectedAction != ACTION_NONE)
    10701070            {
    10711071                var action = determineAction(ev.x, ev.y);
    10721072                resetPreselectedAction();
    function performGroup(action, nr)  
    16471647        if (preSelectedAction == ACTION_NONE)
    16481648            break;
    16491649
    1650         var lst = selectAction(player, selection, action);
     1650        var lst = selectAction(player, selection);
    16511651        if (!lst) // shouldn't happen
    16521652            break;
    16531653
    function performGroup(action, nr)  
    17341734    }
    17351735}
    17361736
    1737 function selectAction(player, selection, action)
     1737// This returns a list of actions. Caller still has to check Technology availability
     1738function selectAction(player, selection)
    17381739{
    17391740    var ret = [];
    1740     if (action == ACTION_FORMATION)
     1741    if (preSelectedAction == ACTION_FORMATION)
    17411742    {
    17421743        return Engine.GuiInterfaceCall("GetAvailableFormations");
    1743     } else if (action == ACTION_STANCE)
     1744    } else if (preSelectedAction == ACTION_STANCE)
    17441745    {
    17451746        return ["violent", "aggressive", "passive", "defensive", "standground"];
    17461747    }
    function selectAction(player, selection, action)  
    17861787    return ret;
    17871788}
    17881789
    1789 // This returns a list of actions. Caller still has to check Technology availability
    17901790function getDefaultActionForSelection(player, selection)
    17911791{
    17921792    var action;
    function findEntity(classes, mode)  
    19111911        var newEntity = Engine.GuiInterfaceCall("FindEntity", data);
    19121912        if (newEntity && newEntity != lastEntity)
    19131913        {
    1914             if (!selectAction(player, [newEntity], preSelectedAction).length)
     1914            if (!selectAction(player, [newEntity]).length)
    19151915                resetPreselectedAction();
    19161916            else if (preSelectedAction == ACTION_BUILD)
    19171917                updateBuildingPlacementPreview();
  • binaries/data/mods/public/gui/session/input.js

    commit 92ad5f0b42b98f9d7beae0c884af378a99bc60e9
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 23:31:36 2012 +0200
    
        reorder a bit (no functional change)
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 7e12d39..37508f3 100644
    a b function handleInputAfterGui(ev)  
    10571057            break;
    10581058
    10591059        case "hotkeydown":
    1060             if (ev.hotkey && ev.hotkey.indexOf("selection.group.") == 0)
    1061             {
    1062                 var sptr = ev.hotkey.split(".");
    1063                 var now = new Date();
    1064                 if ((now.getTime() - doublePressTimer < doublePressTime) && (ev.hotkey == prevHotkey) && ev.hotkey.indexOf("selection.group.select.") == 0) {
    1065                     performGroup("snap", sptr[3]);
    1066                 }
    1067                 else
    1068                 {
    1069                     performGroup(sptr[2], sptr[3]);
    1070 
    1071                     doublePressTimer = now.getTime();
    1072                     prevHotkey = ev.hotkey;
    1073                 }
    1074             }
     1060            handleHotkey(ev);
    10751061            break;
    10761062        }
    10771063        break;
    function handleInputAfterGui(ev)  
    10941080                break;
    10951081            }
    10961082        case "hotkeydown":
    1097             if (ev.hotkey && ev.hotkey.indexOf("selection.group.action.") == 0)
    1098             {
    1099                 var sptr = ev.hotkey.split(".");
    1100                 performGroup(sptr[2], sptr[3]);
    1101             }
     1083            handleHotkey(ev);
    11021084            break;
    11031085        default:
    11041086            // Slight hack: If selection is empty, reset the input state
    function handleInputAfterGui(ev)  
    12681250                updateBuildingPlacementPreview();
    12691251                break;
    12701252            default:
    1271                 if (ev.hotkey.indexOf("selection.group.action.") == 0)
    1272                 {   // can switch buildings
    1273                     var sptr = ev.hotkey.split(".");
    1274                     performGroup(sptr[2], sptr[3]);
    1275                 }
     1253                handleHotkey(ev); // to switch buildings
    12761254            }
    12771255            break;
    12781256
    function performFormation(entity, formationName)  
    16091587    }
    16101588}
    16111589
    1612 function selectAction(player, selection, action)
     1590function handleHotkey(ev)
    16131591{
    1614     var ret = [];
    1615     if (action == ACTION_FORMATION)
    1616     {
    1617         return Engine.GuiInterfaceCall("GetAvailableFormations");
    1618     } else if (action == ACTION_STANCE)
    1619     {
    1620         return ["violent", "aggressive", "passive", "defensive", "standground"];
    1621     }
    1622     for each (var ent in selection)
     1592    if (ev.hotkey && ev.hotkey.indexOf("selection.group.") == 0)
    16231593    {
    1624         var state = GetEntityState(ent);
    1625         if (!state || (state.player != player && !g_DevSettings.controlAll))
    1626             continue;
    1627 
    1628         switch (preSelectedAction)
     1594        var sptr = ev.hotkey.split(".");
     1595        var now = new Date();
     1596        if (inputState = INPUT_NORMAL && (ev.hotkey == prevHotkey) &&
     1597                ev.hotkey.indexOf("selection.group.select.") == 0 &&
     1598                (now.getTime() - doublePressTimer < doublePressTime)) {
     1599            performGroup("snap", sptr[3]);
     1600        }
     1601        else
    16291602        {
    1630         case ACTION_GARRISON:
    1631             if (state.buildEntities || (hasClass(state, "Unit") && !hasClass(state, "Animal") && !state.garrisonHolder)) {
    1632                 inputState = INPUT_PRESELECTEDACTION;
    1633                 ret.push(ent);
    1634             }
    1635             break;
    1636         case ACTION_BUILD:
    1637             if (state.buildEntities && state.buildEntities.length) {
    1638                 if (inputState != INPUT_BUILDING_PLACEMENT)
    1639                     inputState = INPUT_PRESELECTEDACTION;
    1640                 return state.buildEntities;
    1641             }
    1642             break;
    1643         case ACTION_TRAIN:
    1644             if (state.production && state.production.entities.length)
    1645                 return state.production.entities;
    1646             break;
    1647         case ACTION_UNGARRISON:
    1648             if (state.garrisonHolder && state.garrisonHolder.entities && state.garrisonHolder.entities.length)
    1649                 ret.push(ent);
    1650             break;
    1651         case ACTION_BARTER:
    1652             if (state.barterMarket)
    1653                 ret.push(ent);
    1654             break;
    1655         case ACTION_TRADER:
    1656             if (state.trader)
    1657                 ret.push([ent, state]);
    1658             break;
     1603            performGroup(sptr[2], sptr[3]);
     1604            doublePressTimer = now.getTime();
     1605            prevHotkey = ev.hotkey;
    16591606        }
    16601607    }
    1661     return ret;
    1662 }
    1663 
    1664 // This returns a list of actions. Caller still has to check Technology availability
    1665 function getDefaultActionForSelection(player, selection)
    1666 {
    1667     var action;
    1668     var count = 0;
    1669     for each (var ent in selection)
    1670     {
    1671         var state = GetEntityState(ent);
    1672         if (!state || (state.player != player && !g_DevSettings.controlAll))
    1673             continue;
    1674 
    1675         if (state.buildEntities && state.buildEntities.length)
    1676             return ACTION_BUILD; // by default
    1677 
    1678         if (state.production && state.production.entities.length)
    1679             action |= ACTION_TRAIN;
    1680         else if (!hasClass(state, "Unit") || hasClass(state, "Animal") ||
    1681                 !state.garrisonHolder) {
    1682             if (++count > 1) //only works with at least two units
    1683                 action |= ACTION_FORMATION;
    1684         } else if (state.barterMarket)
    1685             action |= ACTION_BARTER;
    1686         else if (state.trader)
    1687             action |= ACTION_TRADER;
    1688     }
    1689     if (action & ACTION_TRAIN)
    1690         return ACTION_TRAIN;
    1691     else if (action & ACTION_FORMATION)
    1692         return ACTION_FORMATION;
    1693     else if (action & ACTION_BARTER) {
    1694         setupUnitBarterPanel(state);
    1695         return ACTION_BARTER;
    1696     } else if (action & ACTION_TRADER) {
    1697         setupUnitTradingPanel(state, selection);
    1698         return ACTION_TRADER;
    1699     }
    1700     return 0; //shouldn't happen
    17011608}
    17021609
    17031610// Performs the specified group
    function performGroup(action, nr)  
    18271734    }
    18281735}
    18291736
     1737function selectAction(player, selection, action)
     1738{
     1739    var ret = [];
     1740    if (action == ACTION_FORMATION)
     1741    {
     1742        return Engine.GuiInterfaceCall("GetAvailableFormations");
     1743    } else if (action == ACTION_STANCE)
     1744    {
     1745        return ["violent", "aggressive", "passive", "defensive", "standground"];
     1746    }
     1747    for each (var ent in selection)
     1748    {
     1749        var state = GetEntityState(ent);
     1750        if (!state || (state.player != player && !g_DevSettings.controlAll))
     1751            continue;
     1752
     1753        switch (preSelectedAction)
     1754        {
     1755        case ACTION_GARRISON:
     1756            if (state.buildEntities || (hasClass(state, "Unit") && !hasClass(state, "Animal") && !state.garrisonHolder)) {
     1757                inputState = INPUT_PRESELECTEDACTION;
     1758                ret.push(ent);
     1759            }
     1760            break;
     1761        case ACTION_BUILD:
     1762            if (state.buildEntities && state.buildEntities.length) {
     1763                if (inputState != INPUT_BUILDING_PLACEMENT)
     1764                    inputState = INPUT_PRESELECTEDACTION;
     1765                return state.buildEntities;
     1766            }
     1767            break;
     1768        case ACTION_TRAIN:
     1769            if (state.production && state.production.entities.length)
     1770                return state.production.entities;
     1771            break;
     1772        case ACTION_UNGARRISON:
     1773            if (state.garrisonHolder && state.garrisonHolder.entities && state.garrisonHolder.entities.length)
     1774                ret.push(ent);
     1775            break;
     1776        case ACTION_BARTER:
     1777            if (state.barterMarket)
     1778                ret.push(ent);
     1779            break;
     1780        case ACTION_TRADER:
     1781            if (state.trader)
     1782                ret.push([ent, state]);
     1783            break;
     1784        }
     1785    }
     1786    return ret;
     1787}
     1788
     1789// This returns a list of actions. Caller still has to check Technology availability
     1790function getDefaultActionForSelection(player, selection)
     1791{
     1792    var action;
     1793    var count = 0;
     1794    for each (var ent in selection)
     1795    {
     1796        var state = GetEntityState(ent);
     1797        if (!state || (state.player != player && !g_DevSettings.controlAll))
     1798            continue;
     1799
     1800        if (state.buildEntities && state.buildEntities.length)
     1801            return ACTION_BUILD; // by default
     1802
     1803        if (state.production && state.production.entities.length)
     1804            action |= ACTION_TRAIN;
     1805        else if (!hasClass(state, "Unit") || hasClass(state, "Animal") ||
     1806                !state.garrisonHolder) {
     1807            if (++count > 1) //only works with at least two units
     1808                action |= ACTION_FORMATION;
     1809        } else if (state.barterMarket)
     1810            action |= ACTION_BARTER;
     1811        else if (state.trader)
     1812            action |= ACTION_TRADER;
     1813    }
     1814    if (action & ACTION_TRAIN)
     1815        return ACTION_TRAIN;
     1816    else if (action & ACTION_FORMATION)
     1817        return ACTION_FORMATION;
     1818    else if (action & ACTION_BARTER) {
     1819        setupUnitBarterPanel(state);
     1820        return ACTION_BARTER;
     1821    } else if (action & ACTION_TRADER) {
     1822        setupUnitTradingPanel(state, selection);
     1823        return ACTION_TRADER;
     1824    }
     1825    return 0; //shouldn't happen
     1826}
     1827
    18301828// Performs the specified stance
    18311829function performStance(entity, stanceName)
    18321830{
  • binaries/data/mods/public/gui/session/input.js

    commit a459d5e2b2413a021e01bb7dd9ef4f16468778b3
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 23:25:14 2012 +0200
    
        Generalize All unloaded following
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 8897d01..7e12d39 100644
    a b function handleInputBeforeGui(ev, hoveredObject)  
    666666        mouseY = ev.y;
    667667        break;
    668668    }
    669     if (followQueue.lenght)
     669    if (followQueue.length)
    670670    {
    671671        var gents = followQueue;
    672672        var state = GetEntityState(gents[0]);
    673         // FIXME this stalls until the selection actually occurs
    674673        if (state.visibility == "hidden")
    675674            return true;
    676675        Engine.CameraFollow(0);
    677676        Engine.CameraFollow(gents[0]);
    678677        g_Selection.addList(gents);
    679678        resetPreselectedAction();
    680         followQueue = [];
     679        followQueue = []; // for next time.
    681680    }
    682681    // Remember whether the mouse is over a GUI object or not
    683682    mouseIsOverObject = (hoveredObject != null);
    function performGroup(action, nr)  
    17841783                if (nr >= lst.length)
    17851784                    nr = lst.length - 1;
    17861785                if (lst.length != 1 && nr == 0) {
    1787                     followQueue = [];
    17881786                    // unload all from all buildings
    1789                     for each (var gh in lst) {
    1790                         var s = GetEntityState(gh);
    1791                         var gs = s.garrisonHolder.entities;
    1792                         followQueue = followQueue.concat(gs);
     1787                    for each (var gh in lst)
    17931788                        unloadAll(gh);
    1794                     }
    17951789                } else {
    17961790                    if (lst.length != 1)
    17971791                        nr--;
    1798                     lst = lst[nr];
    1799 
    1800                     var state = GetEntityState(lst);
    1801                     var gents = state.garrisonHolder.entities;
    1802                     followQueue = gents;
    1803                     unloadAll(lst);
     1792                    unloadAll(lst[nr]);
    18041793                }
    18051794                g_Selection.reset();
    18061795                break;
    function unload(garrisonHolder, entities)  
    19531942
    19541943function unloadAll(garrisonHolder)
    19551944{
     1945    var state = GetEntityState(garrisonHolder);
     1946    var gents = state.garrisonHolder.entities;
     1947    followQueue = followQueue.concat(gents);
    19561948    Engine.PostNetworkCommand({"type": "unload-all", "garrisonHolder": garrisonHolder});
    19571949}
  • binaries/data/mods/public/gui/session/input.js

    commit b89368e8dede26f9b2a412c1c62bde5aceefed9a
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 22:45:44 2012 +0200
    
        This patch makes a default choice active. e.g. for a worker the default
        action is to build, for a building to train. keys G to singlequote are
        implemented as choices. Setting non-default options aren't available
        anymore but a next patch will implement hotkeys for that.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index eb6d59a..8897d01 100644
    a b const ACTION_BARTER = 64;  
    2323const ACTION_TRADER =128;
    2424var preSelectedAction = ACTION_NONE;
    2525
    26 // N.B. reset this after selecting different units or buildings
    27 var _optionsOfpreSelected = [];
     26var followQueue = [];
    2827
    2928const INPUT_NORMAL = 0;
    3029const INPUT_SELECTING = 1;
    const INPUT_BATCHTRAINING = 6;  
    3635const INPUT_PRESELECTEDACTION = 7;
    3736const INPUT_BUILDING_WALL_CLICK = 8;
    3837const INPUT_BUILDING_WALL_PATHING = 9;
    39 const INPUT_FOLLOW_UNGARRISON = 10;
    4038
    4139var inputState = INPUT_NORMAL;
    4240var placementSupport = new PlacementSupport();
    function resetPreselectedAction()  
    188186{
    189187    preSelectedAction = ACTION_NONE;
    190188    inputState = INPUT_NORMAL;
    191     _optionsOfpreSelected = [];
    192189    placementSupport.Reset(); // or a hotkey may leave a building snapshot
    193190    updateCursorAndTooltip();
    194191
    function handleInputBeforeGui(ev, hoveredObject)  
    669666        mouseY = ev.y;
    670667        break;
    671668    }
    672     if (inputState == INPUT_FOLLOW_UNGARRISON)
     669    if (followQueue.lenght)
    673670    {
    674         var gents = _optionsOfpreSelected;
     671        var gents = followQueue;
    675672        var state = GetEntityState(gents[0]);
    676673        // FIXME this stalls until the selection actually occurs
    677674        if (state.visibility == "hidden")
    function handleInputBeforeGui(ev, hoveredObject)  
    680677        Engine.CameraFollow(gents[0]);
    681678        g_Selection.addList(gents);
    682679        resetPreselectedAction();
     680        followQueue = [];
    683681    }
    684682    // Remember whether the mouse is over a GUI object or not
    685683    mouseIsOverObject = (hoveredObject != null);
    function handleInputAfterGui(ev)  
    10441042            return false;
    10451043
    10461044        case "mousebuttondown":
    1047             _optionsOfpreSelected = [];
    10481045            if (ev.button == SDL_BUTTON_LEFT)
    10491046            {
    10501047                dragStart = [ ev.x, ev.y ];
    function handleInputAfterGui(ev)  
    12451242                    placementSupport.position = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
    12461243                    dragStart = [ ev.x, ev.y ];
    12471244                    inputState = INPUT_BUILDING_CLICK;
    1248                     _optionsOfpreSelected = [];
    12491245                }
    12501246                return true;
    12511247            }
    function performFormation(entity, formationName)  
    16141610    }
    16151611}
    16161612
    1617 // This returns a list of actions. Caller still has to check Technology availability
    1618 function getActionForSelection(player, selection)
     1613function selectAction(player, selection, action)
    16191614{
    16201615    var ret = [];
    1621 
     1616    if (action == ACTION_FORMATION)
     1617    {
     1618        return Engine.GuiInterfaceCall("GetAvailableFormations");
     1619    } else if (action == ACTION_STANCE)
     1620    {
     1621        return ["violent", "aggressive", "passive", "defensive", "standground"];
     1622    }
    16221623    for each (var ent in selection)
    16231624    {
    16241625        var state = GetEntityState(ent);
    function getActionForSelection(player, selection)  
    16481649            if (state.garrisonHolder && state.garrisonHolder.entities && state.garrisonHolder.entities.length)
    16491650                ret.push(ent);
    16501651            break;
    1651         case ACTION_FORMATION:
    1652         case ACTION_STANCE:
    1653             if (!hasClass(state, "Unit") || hasClass(state, "Animal") || state.garrisonHolder)
    1654                 break;
    1655 
    1656             if (preSelectedAction == ACTION_STANCE)
    1657                 return ["violent", "aggressive", "passive", "defensive", "standground"];
    1658             if (ret.length) // minimimum is 2 units for formation to be enabled
    1659                 return Engine.GuiInterfaceCall("GetAvailableFormations");
    1660             ret.push(1);
    1661             break;
    16621652        case ACTION_BARTER:
    16631653            if (state.barterMarket)
    16641654                ret.push(ent);
    function getActionForSelection(player, selection)  
    16671657            if (state.trader)
    16681658                ret.push([ent, state]);
    16691659            break;
    1670         default:
    1671             return ret; //shouldn't happen
    16721660        }
    16731661    }
    16741662    return ret;
    16751663}
    16761664
     1665// This returns a list of actions. Caller still has to check Technology availability
     1666function getDefaultActionForSelection(player, selection)
     1667{
     1668    var action;
     1669    var count = 0;
     1670    for each (var ent in selection)
     1671    {
     1672        var state = GetEntityState(ent);
     1673        if (!state || (state.player != player && !g_DevSettings.controlAll))
     1674            continue;
     1675
     1676        if (state.buildEntities && state.buildEntities.length)
     1677            return ACTION_BUILD; // by default
     1678
     1679        if (state.production && state.production.entities.length)
     1680            action |= ACTION_TRAIN;
     1681        else if (!hasClass(state, "Unit") || hasClass(state, "Animal") ||
     1682                !state.garrisonHolder) {
     1683            if (++count > 1) //only works with at least two units
     1684                action |= ACTION_FORMATION;
     1685        } else if (state.barterMarket)
     1686            action |= ACTION_BARTER;
     1687        else if (state.trader)
     1688            action |= ACTION_TRADER;
     1689    }
     1690    if (action & ACTION_TRAIN)
     1691        return ACTION_TRAIN;
     1692    else if (action & ACTION_FORMATION)
     1693        return ACTION_FORMATION;
     1694    else if (action & ACTION_BARTER) {
     1695        setupUnitBarterPanel(state);
     1696        return ACTION_BARTER;
     1697    } else if (action & ACTION_TRADER) {
     1698        setupUnitTradingPanel(state, selection);
     1699        return ACTION_TRADER;
     1700    }
     1701    return 0; //shouldn't happen
     1702}
     1703
    16771704// Performs the specified group
    16781705function performGroup(action, nr)
    16791706{
    function performGroup(action, nr)  
    17071734        updateGroups();
    17081735        break;
    17091736    case "action":
    1710         if (!_optionsOfpreSelected.length) {
    1711             // action hotkey (first pass): With current selection, check possible
    1712             // ACTION_XXX's and set preSelectedAction when applicable
    1713             preSelectedAction = (1 << nr);
    1714 
    1715             var selection = g_Selection.toList();
    1716             var player = Engine.GetPlayerID();
     1737        var selection = g_Selection.toList();
     1738        var player = Engine.GetPlayerID();
    17171739
    1718             var actions = getActionForSelection(player, selection);
    1719             if (!actions || !actions.length) {
    1720                 preSelectedAction = ACTION_NONE;
    1721                 break;
    1722             }
     1740        preSelectedAction = getDefaultActionForSelection(player, selection);
     1741        if (preSelectedAction == ACTION_NONE)
     1742            break;
    17231743
    1724             if (preSelectedAction == ACTION_BARTER)
    1725                 setupUnitBarterPanel(state);
    1726             else if (preSelectedAction == ACTION_TRADER)
    1727                 setupUnitTradingPanel(state, selection);
     1744        var lst = selectAction(player, selection, action);
     1745        if (!lst) // shouldn't happen
     1746            break;
    17281747
    1729             _optionsOfpreSelected = actions;
    1730         }
    1731         else
     1748        if (preSelectedAction & ACTION_GARRISON)
    17321749        {
    1733             // 2nd action hotkey. Do preselectedAction[nr]
    1734             // The result depends on the action.
    1735 
    1736             var lst = _optionsOfpreSelected;
    1737             if (!lst) // shouldn't happen
     1750            if (++nr > lst.length)
     1751                nr = lst.length;
     1752        } else if (preSelectedAction != ACTION_UNGARRISON) {
     1753            if (nr >= lst.length)
    17381754                break;
     1755            lst = lst[nr];
     1756        }
    17391757
    1740             if (preSelectedAction & ACTION_GARRISON)
    1741             {
    1742                 if (++nr > lst.length)
    1743                     nr = lst.length;
    1744             } else if (preSelectedAction != ACTION_UNGARRISON) {
    1745                 if (nr >= lst.length)
    1746                     break;
    1747                 lst = lst[nr];
     1758        switch (preSelectedAction)
     1759        {
     1760        case ACTION_BUILD:
     1761            var tmpl = GetTemplateData(lst);
     1762            if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
     1763                // N.B. sets inputState = INPUT_BUILDING_PLACEMENT:
     1764                startBuildingPlacement(lst);
     1765                placementSupport.position = Engine.GetTerrainAtScreenPoint(mouseX, mouseY);
     1766                initBuildingPlacementView();
    17481767            }
    1749 
    1750             switch (preSelectedAction)
    1751             {
    1752             case ACTION_BUILD:
    1753                 var tmpl = GetTemplateData(lst);
    1754                 if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
    1755                     // N.B. sets inputState = INPUT_BUILDING_PLACEMENT:
    1756                     startBuildingPlacement(lst);
    1757                     placementSupport.position = Engine.GetTerrainAtScreenPoint(mouseX, mouseY);
    1758                     initBuildingPlacementView();
    1759                 }
    1760                 break;
    1761             case ACTION_TRAIN:
    1762                 var tmpl = GetTemplateData(lst);
    1763                 if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
    1764                     var ents = g_Selection.toList();
    1765                     addTrainingToQueue(ents, lst);
    1766                 }
    1767                 break;
    1768             case ACTION_GARRISON: // we garison nr+1 count
    1769                 g_Selection.reset();
    1770                 lst.splice(nr, lst.length - nr)
    1771                 g_Selection.addList(lst);
    1772                 inputState = INPUT_PRESELECTEDACTION;
    1773                 break;
    1774             case ACTION_UNGARRISON:
    1775                 if (lst.length > 1 || nr == 0) {
    1776                     if (nr >= lst.length)
    1777                         nr = lst.length - 1;
    1778                     if (lst.length != 1 && nr == 0) {
    1779                         // unload all from all buildings
    1780                         _optionsOfpreSelected = [];
    1781                         for each (var gh in lst) {
    1782                             var s = GetEntityState(gh);
    1783                             var gs = s.garrisonHolder.entities;
    1784                             _optionsOfpreSelected = _optionsOfpreSelected.concat(gs);
    1785                             unloadAll(gh);
    1786                         }
    1787                     } else {
    1788                         if (lst.length != 1)
    1789                             nr--;
    1790                         lst = lst[nr];
    1791 
    1792                         var state = GetEntityState(lst);
    1793                         var gents = state.garrisonHolder.entities;
    1794                         _optionsOfpreSelected = gents;
    1795                         unloadAll(lst);
     1768            break;
     1769        case ACTION_TRAIN:
     1770            var tmpl = GetTemplateData(lst);
     1771            if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
     1772                var ents = g_Selection.toList();
     1773                addTrainingToQueue(ents, lst);
     1774            }
     1775            break;
     1776        case ACTION_GARRISON: // we garison nr+1 count
     1777            g_Selection.reset();
     1778            lst.splice(nr, lst.length - nr)
     1779            g_Selection.addList(lst);
     1780            inputState = INPUT_PRESELECTEDACTION;
     1781            break;
     1782        case ACTION_UNGARRISON:
     1783            if (lst.length > 1 || nr == 0) {
     1784                if (nr >= lst.length)
     1785                    nr = lst.length - 1;
     1786                if (lst.length != 1 && nr == 0) {
     1787                    followQueue = [];
     1788                    // unload all from all buildings
     1789                    for each (var gh in lst) {
     1790                        var s = GetEntityState(gh);
     1791                        var gs = s.garrisonHolder.entities;
     1792                        followQueue = followQueue.concat(gs);
     1793                        unloadAll(gh);
    17961794                    }
    1797                     g_Selection.reset();
    1798                     inputState = INPUT_FOLLOW_UNGARRISON;
    1799                     break;
    18001795                } else {
    1801                     lst = lst[0];
     1796                    if (lst.length != 1)
     1797                        nr--;
     1798                    lst = lst[nr];
     1799
    18021800                    var state = GetEntityState(lst);
    18031801                    var gents = state.garrisonHolder.entities;
    1804                     if (nr > gents.length)
    1805                         nr = gents.length;
    1806                     while (nr--)
    1807                         Engine.PostNetworkCommand({"type": "unload", "entities": [gents[nr]], "garrisonHolder": lst});
    1808                     // we could assign a key to follow them here
    1809                     break;
     1802                    followQueue = gents;
     1803                    unloadAll(lst);
    18101804                }
     1805                g_Selection.reset();
    18111806                break;
    1812             case ACTION_FORMATION:
    1813                 ents = g_Selection.toList();
    1814                 var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
    1815                     "ents": g_Selection.toList(),
    1816                     "formationName": lst
    1817                 });
    1818                 if (formationOk)
    1819                     performFormation(ents, lst);
    1820                 break
    1821             case ACTION_STANCE:
    1822                 ents = g_Selection.toList();
    1823                 performStance(ents, lst);
    1824                 break;
    1825             case ACTION_BARTER: //TODO
    1826                 break;
    1827             case ACTION_TRADER: //TODO
     1807            } else {
     1808                lst = lst[0];
     1809                var state = GetEntityState(lst);
     1810                var gents = state.garrisonHolder.entities;
     1811                if (nr > gents.length)
     1812                    nr = gents.length;
     1813                while (nr--)
     1814                    Engine.PostNetworkCommand({"type": "unload", "entities": [gents[nr]], "garrisonHolder": lst});
     1815                // we could assign a key to follow them here
    18281816                break;
    18291817            }
     1818            break;
     1819        case ACTION_FORMATION:
     1820            ents = g_Selection.toList();
     1821            var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
     1822                "ents": g_Selection.toList(),
     1823                "formationName": lst
     1824            });
     1825            if (formationOk)
     1826                performFormation(ents, lst);
     1827            break
     1828        case ACTION_STANCE:
     1829            ents = g_Selection.toList();
     1830            performStance(ents, lst);
     1831            break;
     1832        case ACTION_BARTER: //TODO
     1833            break;
     1834        case ACTION_TRADER: //TODO
     1835            break;
    18301836        }
    18311837        break;
    18321838    }
    function findAllVisibleEntities(classes, mode)  
    18951901    }
    18961902
    18971903    if (visibleEnts.length) {
    1898         if (!getActionForSelection(player, visibleEnts).length)
     1904        if (!getDefaultActionForSelection(player, visibleEnts).length)
    18991905            resetPreselectedAction();
    19001906        g_Selection.reset();
    19011907        g_Selection.addList(visibleEnts);
    function findEntity(classes, mode)  
    19181924        var newEntity = Engine.GuiInterfaceCall("FindEntity", data);
    19191925        if (newEntity && newEntity != lastEntity)
    19201926        {
    1921             if (!getActionForSelection(player, [newEntity]).length)
     1927            if (!selectAction(player, [newEntity], preSelectedAction).length)
    19221928                resetPreselectedAction();
    19231929            else if (preSelectedAction == ACTION_BUILD)
    19241930                updateBuildingPlacementPreview();
  • binaries/data/config/default.cfg

    commit 273d868803cecf5e17938e49a2a0b6944327257e
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 20:35:27 2012 +0200
    
        as suggested by historic_bruno the backslash isn't always in line
        Also use Ctrl rather than shift for the 7+ keys (we may want to use shift
        for batchtrain later).
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 5201210..5015b15 100644
    a b hotkey.selection.group.select.9 = 9  
    189189hotkey.selection.group.save.9 = "Ctrl+9"
    190190hotkey.selection.group.add.9 = "Shift+9"
    191191
    192 hotkey.selection.group.action.0 = H
    193 hotkey.selection.group.action.1 = J
    194 hotkey.selection.group.action.2 = K
    195 hotkey.selection.group.action.3 = L
    196 hotkey.selection.group.action.4 = Semicolon
    197 hotkey.selection.group.action.5 = SingleQuote
    198 hotkey.selection.group.action.6 = BackSlash
    199 hotkey.selection.group.action.7 = "Shift+H"
    200 hotkey.selection.group.action.8 = "Shift+J"
    201 hotkey.selection.group.action.9 = "Shift+K"
    202 hotkey.selection.group.action.10 = "Shift+L"
    203 hotkey.selection.group.action.11 = Colon
    204 hotkey.selection.group.action.12 = DoubleQuote
     192hotkey.selection.group.action.0 = G
     193hotkey.selection.group.action.1 = H
     194hotkey.selection.group.action.2 = J
     195hotkey.selection.group.action.3 = K
     196hotkey.selection.group.action.4 = L
     197hotkey.selection.group.action.5 = Semicolon
     198hotkey.selection.group.action.6 = SingleQuote
     199hotkey.selection.group.action.7 = "Ctrl+G"
     200hotkey.selection.group.action.8 = "Ctrl+H"
     201hotkey.selection.group.action.9 = "Ctrl+J"
     202hotkey.selection.group.action.10 = "Ctrl+K"
     203hotkey.selection.group.action.11 = "Ctrl+L"
     204hotkey.selection.group.action.12 = "Ctrl+Semicolon"
     205hotkey.selection.group.action.13 = "Ctrl+SingleQuote"
    205206hotkey.selection.group.action.reset = ForwardSlash
    206207
    207208; > SESSION CONTROLS
  • binaries/data/mods/public/gui/session/input.js

    commit 97150316bb560554c7f1e5d3f45f90a71d574191
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 20:16:55 2012 +0200
    
        Unload all from all selected buildings
        ensure selection occurs
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index bc48d73..eb6d59a 100644
    a b function handleInputBeforeGui(ev, hoveredObject)  
    671671    }
    672672    if (inputState == INPUT_FOLLOW_UNGARRISON)
    673673    {
    674         gents = _optionsOfpreSelected;
     674        var gents = _optionsOfpreSelected;
     675        var state = GetEntityState(gents[0]);
     676        // FIXME this stalls until the selection actually occurs
     677        if (state.visibility == "hidden")
     678            return true;
    675679        Engine.CameraFollow(0);
    676680        Engine.CameraFollow(gents[0]);
    677681        g_Selection.addList(gents);
    function performGroup(action, nr)  
    17711775                if (lst.length > 1 || nr == 0) {
    17721776                    if (nr >= lst.length)
    17731777                        nr = lst.length - 1;
    1774                     if (lst.length != 1)   // TODO: uload all from all
    1775                         lst = lst[nr]; // selected buildings
    1776                     else
    1777                         lst = lst[0];
    1778                     var state = GetEntityState(lst);
    1779                     var gents = state.garrisonHolder.entities;
    1780                     _optionsOfpreSelected = gents;
    1781                     unloadAll(lst);
     1778                    if (lst.length != 1 && nr == 0) {
     1779                        // unload all from all buildings
     1780                        _optionsOfpreSelected = [];
     1781                        for each (var gh in lst) {
     1782                            var s = GetEntityState(gh);
     1783                            var gs = s.garrisonHolder.entities;
     1784                            _optionsOfpreSelected = _optionsOfpreSelected.concat(gs);
     1785                            unloadAll(gh);
     1786                        }
     1787                    } else {
     1788                        if (lst.length != 1)
     1789                            nr--;
     1790                        lst = lst[nr];
     1791
     1792                        var state = GetEntityState(lst);
     1793                        var gents = state.garrisonHolder.entities;
     1794                        _optionsOfpreSelected = gents;
     1795                        unloadAll(lst);
     1796                    }
    17821797                    g_Selection.reset();
    17831798                    inputState = INPUT_FOLLOW_UNGARRISON;
    17841799                    break;
    function performGroup(action, nr)  
    17861801                    lst = lst[0];
    17871802                    var state = GetEntityState(lst);
    17881803                    var gents = state.garrisonHolder.entities;
    1789                     if (nr >= gents.length)
     1804                    if (nr > gents.length)
    17901805                        nr = gents.length;
    17911806                    while (nr--)
    17921807                        Engine.PostNetworkCommand({"type": "unload", "entities": [gents[nr]], "garrisonHolder": lst});
  • binaries/data/mods/public/gui/session/input.js

    commit a40750c24a7bf9faa84b7e45c4a465c1dafa96c9
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 19:37:50 2012 +0200
    
        actually the INPUT_REPEATED_UNGARRISON state is not needed
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index eb0f140..bc48d73 100644
    a b const INPUT_PRESELECTEDACTION = 7;  
    3737const INPUT_BUILDING_WALL_CLICK = 8;
    3838const INPUT_BUILDING_WALL_PATHING = 9;
    3939const INPUT_FOLLOW_UNGARRISON = 10;
    40 const INPUT_REPEATED_UNGARRISON = 11;
    4140
    4241var inputState = INPUT_NORMAL;
    4342var placementSupport = new PlacementSupport();
    function handleInputBeforeGui(ev, hoveredObject)  
    677676        Engine.CameraFollow(gents[0]);
    678677        g_Selection.addList(gents);
    679678        resetPreselectedAction();
    680     } else if (inputState == INPUT_REPEATED_UNGARRISON) {
    681         var garrisonHolder =  _optionsOfpreSelected[0];
    682         var state = GetEntityState(garrisonHolder);
    683         var gents = state.garrisonHolder.entities;
    684         var gent = gents[_optionsOfpreSelected[1]]
    685         Engine.PostNetworkCommand({"type": "unload", "entities": [gent], "garrisonHolder": garrisonHolder});
    686         if (_optionsOfpreSelected[1]-- > 0)
    687             return true;
    688         resetPreselectedAction();
    689679    }
    690680    // Remember whether the mouse is over a GUI object or not
    691681    mouseIsOverObject = (hoveredObject != null);
    function performGroup(action, nr)  
    17971787                    var state = GetEntityState(lst);
    17981788                    var gents = state.garrisonHolder.entities;
    17991789                    if (nr >= gents.length)
    1800                         nr = gents.length - 1;
    1801                     // unload nr times, requires some update.
    1802                     _optionsOfpreSelected = [lst, nr];
    1803                     inputState = INPUT_REPEATED_UNGARRISON;
     1790                        nr = gents.length;
     1791                    while (nr--)
     1792                        Engine.PostNetworkCommand({"type": "unload", "entities": [gents[nr]], "garrisonHolder": lst});
     1793                    // we could assign a key to follow them here
     1794                    break;
    18041795                }
    18051796                break;
    18061797            case ACTION_FORMATION:
  • binaries/data/mods/public/gui/session/input.js

    commit fc698a3c4a64e556b20cfdf904b001987282aaeb
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Wed Jun 13 01:59:38 2012 +0200
    
        This allows two actions: to follow units when unload all hotkey is pressed
        and to ungarrison n units. hotkey J = 1, K = 2, etc.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 43cc741..eb0f140 100644
    a b const INPUT_BATCHTRAINING = 6;  
    3636const INPUT_PRESELECTEDACTION = 7;
    3737const INPUT_BUILDING_WALL_CLICK = 8;
    3838const INPUT_BUILDING_WALL_PATHING = 9;
     39const INPUT_FOLLOW_UNGARRISON = 10;
     40const INPUT_REPEATED_UNGARRISON = 11;
    3941
    4042var inputState = INPUT_NORMAL;
    4143var placementSupport = new PlacementSupport();
    function handleInputBeforeGui(ev, hoveredObject)  
    668670        mouseY = ev.y;
    669671        break;
    670672    }
    671 
     673    if (inputState == INPUT_FOLLOW_UNGARRISON)
     674    {
     675        gents = _optionsOfpreSelected;
     676        Engine.CameraFollow(0);
     677        Engine.CameraFollow(gents[0]);
     678        g_Selection.addList(gents);
     679        resetPreselectedAction();
     680    } else if (inputState == INPUT_REPEATED_UNGARRISON) {
     681        var garrisonHolder =  _optionsOfpreSelected[0];
     682        var state = GetEntityState(garrisonHolder);
     683        var gents = state.garrisonHolder.entities;
     684        var gent = gents[_optionsOfpreSelected[1]]
     685        Engine.PostNetworkCommand({"type": "unload", "entities": [gent], "garrisonHolder": garrisonHolder});
     686        if (_optionsOfpreSelected[1]-- > 0)
     687            return true;
     688        resetPreselectedAction();
     689    }
    672690    // Remember whether the mouse is over a GUI object or not
    673691    mouseIsOverObject = (hoveredObject != null);
    674692
    function performGroup(action, nr)  
    17251743            if (!lst) // shouldn't happen
    17261744                break;
    17271745
    1728             if (preSelectedAction & (ACTION_UNGARRISON | ACTION_GARRISON))
     1746            if (preSelectedAction & ACTION_GARRISON)
    17291747            {
    1730                 if (preSelectedAction & ACTION_GARRISON)
    1731                     ++nr;
    1732                 if (nr > lst.length)
     1748                if (++nr > lst.length)
    17331749                    nr = lst.length;
    1734             } else if (preSelectedAction != (ACTION_BUILD|ACTION_TRAIN)) {
     1750            } else if (preSelectedAction != ACTION_UNGARRISON) {
    17351751                if (nr >= lst.length)
    17361752                    break;
    17371753                lst = lst[nr];
    function performGroup(action, nr)  
    17631779                break;
    17641780            case ACTION_UNGARRISON:
    17651781                if (lst.length > 1 || nr == 0) {
     1782                    if (nr >= lst.length)
     1783                        nr = lst.length - 1;
    17661784                    if (lst.length != 1)   // TODO: uload all from all
    17671785                        lst = lst[nr]; // selected buildings
    17681786                    else
    17691787                        lst = lst[0];
    17701788                    var state = GetEntityState(lst);
    17711789                    var gents = state.garrisonHolder.entities;
     1790                    _optionsOfpreSelected = gents;
    17721791                    unloadAll(lst);
    1773                     // FIXME: follow when ungarrisoning all
    1774                     // sadly these gents cannot be viewed after ungarissoning:
    1775                     if (gents)
    1776                     {
    1777                         //Engine.CameraFollow(0);
    1778                         g_Selection.reset();
    1779                         g_Selection.addList(gents);
    1780                         Engine.CameraFollow(gents);
    1781                     }
     1792                    g_Selection.reset();
     1793                    inputState = INPUT_FOLLOW_UNGARRISON;
     1794                    break;
    17821795                } else {
    17831796                    lst = lst[0];
    17841797                    var state = GetEntityState(lst);
    17851798                    var gents = state.garrisonHolder.entities;
    1786                     // FIXME unload nr times, requires some update.
    1787                     unload(lst, gents);
     1799                    if (nr >= gents.length)
     1800                        nr = gents.length - 1;
     1801                    // unload nr times, requires some update.
     1802                    _optionsOfpreSelected = [lst, nr];
     1803                    inputState = INPUT_REPEATED_UNGARRISON;
    17881804                }
    17891805                break;
    17901806            case ACTION_FORMATION:
  • binaries/data/mods/public/gui/session/input.js

    commit 0e369958e9c17997d7e77c3e2aae28c5971ff7a0
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Tue Jun 12 01:24:00 2012 +0200
    
        Find all visible idle workers,warriors,buildings with Shift ./,/U/etc
        
        revert behavior and leave view to garrisonholder as the ungarrisoned
        cannot be followed.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 24f32a5..43cc741 100644
    a b function performGroup(action, nr)  
    17671767                        lst = lst[nr]; // selected buildings
    17681768                    else
    17691769                        lst = lst[0];
    1770                     // FIXME: follow when ungarrisoning all
    17711770                    var state = GetEntityState(lst);
    17721771                    var gents = state.garrisonHolder.entities;
    17731772                    unloadAll(lst);
    1774                     Engine.CameraFollow(0);
    1775                     g_Selection.reset();
    1776                     g_Selection.addList(gents);
    1777                     Engine.CameraFollow(gents[0]);
     1773                    // FIXME: follow when ungarrisoning all
     1774                    // sadly these gents cannot be viewed after ungarissoning:
     1775                    if (gents)
     1776                    {
     1777                        //Engine.CameraFollow(0);
     1778                        g_Selection.reset();
     1779                        g_Selection.addList(gents);
     1780                        Engine.CameraFollow(gents);
     1781                    }
    17781782                } else {
    17791783                    lst = lst[0];
    17801784                    var state = GetEntityState(lst);
    function resetEntitySearch()  
    18471851    currEntClass = 0;
    18481852}
    18491853
     1854function findAllVisibleEntities(classes, mode)
     1855{
     1856    var player = Engine.GetPlayerID();
     1857    var plEnts = Engine.PickFriendlyEntitiesOnScreen(player);
     1858    // Or we could do somthing alike the below, but this is resolution dependent
     1859    //var plEnts = Engine.PickFriendlyEntitiesInRect(250, 250, 1400, 750, player);
     1860    if (!plEnts.length)
     1861        return;
     1862    var visibleEnts = [];
     1863    for each (cls in classes)
     1864    {
     1865        var data = {
     1866            entClass: cls,
     1867            searchMode: mode,
     1868            playerEnts: plEnts,
     1869        };
     1870        var entities = Engine.GuiInterfaceCall("SubsetMatchedEnts", data);
     1871        if (entities.length)
     1872            visibleEnts = visibleEnts.concat(entities);
     1873    }
     1874
     1875    if (visibleEnts.length) {
     1876        if (!getActionForSelection(player, visibleEnts).length)
     1877            resetPreselectedAction();
     1878        g_Selection.reset();
     1879        g_Selection.addList(visibleEnts);
     1880        Engine.CameraFollow(visibleEnts[0]);
     1881    }
     1882}
     1883
    18501884function findEntity(classes, mode)
    18511885{
     1886    var queued = Engine.HotkeyIsPressed("session.queue");
     1887    if (queued) {
     1888        findAllVisibleEntities(classes, mode)
     1889        return;
     1890    }
    18521891    var player = Engine.GetPlayerID();
    18531892    // Cycle through idling classes before giving up
    18541893    for (var i = 0; i <= classes.length; ++i)
  • binaries/data/mods/public/simulation/components/GuiInterface.js

    diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js
    index a2c29ba..6fd71d9 100644
    a b GuiInterface.prototype.PlaySound = function(player, data)  
    14261426    PlaySound(data.name, data.entity);
    14271427};
    14281428
     1429GuiInterface.prototype.MatchEnt = function(ent, data)
     1430{
     1431    var ret;
     1432    var cmpId = Engine.QueryInterface(ent, IID_Identity);
     1433    if (cmpId && cmpId.HasClass(data.entClass)) {
     1434        if (data.searchMode == 0) {
     1435            ret = ent;
     1436        }  else if (data.searchMode == 1) { // Search idle villager/soldier
     1437            var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     1438            if (cmpUnitAI && cmpUnitAI.IsIdle() && !cmpUnitAI.IsGarrisoned())
     1439                ret = ent;
     1440        }
     1441    }
     1442    return ret;
     1443}
     1444
     1445GuiInterface.prototype.SubsetMatchedEnts = function(player, data)
     1446{
     1447    var ret = [];
     1448    for each (var ent in data.playerEnts)
     1449    {
     1450        var match = this.MatchEnt(ent, data);
     1451        if (match)
     1452            ret.push(match);
     1453    }
     1454    return ret;
     1455}
     1456
    14291457GuiInterface.prototype.FindEntity = function(player, data)
    14301458{
    14311459    var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    GuiInterface.prototype.FindEntity = function(player, data)  
    14351463    // so that we cycle around in a predictable order
    14361464    for each (var ent in playerEntities)
    14371465    {
    1438         var cmpId = Engine.QueryInterface(ent, IID_Identity);
    1439         if (ent > data.prevEntity && cmpId && cmpId.HasClass(data.entClass)) {
    1440             if (data.searchMode == 0) {
    1441                 return ent;
    1442             }  else if (data.searchMode == 1) { // Search idle villager/soldier
    1443                 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
    1444                 if (cmpUnitAI && cmpUnitAI.IsIdle() && !cmpUnitAI.IsGarrisoned())
    1445                     return ent;
    1446             }
     1466        if (ent > data.prevEntity)
     1467        {
     1468            var match = this.MatchEnt(ent, data);
     1469            if (match)
     1470                return match;
    14471471        }
    14481472    }
    14491473
    var exposedFunctions = {  
    15701594    "SetWallPlacementPreview": 1,
    15711595    "GetFoundationSnapData": 1,
    15721596    "PlaySound": 1,
     1597    "SubsetMatchedEnts": 1,
    15731598    "FindEntity": 1,
    15741599    "GetTradingDetails": 1,
    15751600    "CanAttack": 1,
  • binaries/data/mods/public/gui/session/input.js

    commit 9a19e955fbf67dd61d2a9152ab23aec898d4d248
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Mon Jun 11 00:20:19 2012 +0200
    
        Bugfix: during building placement we can now correctly select another
        idle villager for the job.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index b724acd..24f32a5 100644
    a b function updateBuildingPlacementPreview()  
    146146    return false;
    147147}
    148148
    149 function initBuildingPlacementView(ev)
     149function initBuildingPlacementView()
    150150{
    151151    if (placementSupport.mode === "wall")
    152152    {
    function handleInputAfterGui(ev)  
    10541054                var sptr = ev.hotkey.split(".");
    10551055                var now = new Date();
    10561056                if ((now.getTime() - doublePressTimer < doublePressTime) && (ev.hotkey == prevHotkey) && ev.hotkey.indexOf("selection.group.select.") == 0) {
    1057                     performGroup("snap", sptr[3], ev);
     1057                    performGroup("snap", sptr[3]);
    10581058                }
    10591059                else
    10601060                {
    1061                     performGroup(sptr[2], sptr[3], ev);
     1061                    performGroup(sptr[2], sptr[3]);
    10621062
    10631063                    doublePressTimer = now.getTime();
    10641064                    prevHotkey = ev.hotkey;
    function handleInputAfterGui(ev)  
    12141214        {
    12151215        case "mousemotion":
    12161216            placementSupport.position = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
    1217             initBuildingPlacementView(ev);
     1217            initBuildingPlacementView();
    12181218            return false; // continue processing mouse motion
    12191219
    12201220        case "mousebuttondown":
    function handleInputAfterGui(ev)  
    12641264                if (ev.hotkey.indexOf("selection.group.action.") == 0)
    12651265                {   // can switch buildings
    12661266                    var sptr = ev.hotkey.split(".");
    1267                     performGroup(sptr[2], sptr[3], ev);
     1267                    performGroup(sptr[2], sptr[3]);
    12681268                }
    12691269            }
    12701270            break;
    function getActionForSelection(player, selection)  
    16231623            break;
    16241624        case ACTION_BUILD:
    16251625            if (state.buildEntities && state.buildEntities.length) {
    1626                 inputState = INPUT_PRESELECTEDACTION;
     1626                if (inputState != INPUT_BUILDING_PLACEMENT)
     1627                    inputState = INPUT_PRESELECTEDACTION;
    16271628                return state.buildEntities;
    16281629            }
    16291630            break;
    function getActionForSelection(player, selection)  
    16621663}
    16631664
    16641665// Performs the specified group
    1665 function performGroup(action, nr, ev)
     1666function performGroup(action, nr)
    16661667{
    16671668    if (nr == "reset")
    16681669    {
    function performGroup(action, nr, ev)  
    17441745                    // N.B. sets inputState = INPUT_BUILDING_PLACEMENT:
    17451746                    startBuildingPlacement(lst);
    17461747                    placementSupport.position = Engine.GetTerrainAtScreenPoint(mouseX, mouseY);
    1747                     initBuildingPlacementView(ev);
     1748                    initBuildingPlacementView();
    17481749                }
    17491750                break;
    17501751            case ACTION_TRAIN:
    function findEntity(classes, mode)  
    18581859        {
    18591860            if (!getActionForSelection(player, [newEntity]).length)
    18601861                resetPreselectedAction();
     1862            else if (preSelectedAction == ACTION_BUILD)
     1863                updateBuildingPlacementPreview();
    18611864
    18621865            lastEntity = newEntity;
    18631866            g_Selection.reset();
  • binaries/data/config/default.cfg

    commit fc4d8b422f85397eda4b78de2cf849d146b33ab1
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sun Jun 10 23:32:05 2012 +0200
    
        Fixes reset hotkey
        Fixes stance
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 1f7c35c..5201210 100644
    a b hotkey.selection.group.action.9 = "Shift+K"  
    202202hotkey.selection.group.action.10 = "Shift+L"
    203203hotkey.selection.group.action.11 = Colon
    204204hotkey.selection.group.action.12 = DoubleQuote
    205 hotkey.selection.group.reset.action = ForwardSlash
     205hotkey.selection.group.action.reset = ForwardSlash
    206206
    207207; > SESSION CONTROLS
    208208hotkey.session.kill = Delete                ; Destroy selected units
  • binaries/data/mods/public/gui/session/input.js

    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 8775bb3..b724acd 100644
    a b function findGatherType(gatherer, supply)  
    185185
    186186function resetPreselectedAction()
    187187{
    188     placementSupport.Reset();
     188    preSelectedAction = ACTION_NONE;
    189189    inputState = INPUT_NORMAL;
    190190    _optionsOfpreSelected = [];
     191    placementSupport.Reset(); // or a hotkey may leave a building snapshot
     192    updateCursorAndTooltip();
    191193
    192194}
    193195
    function handleInputAfterGui(ev)  
    10701072        switch (ev.type)
    10711073        {
    10721074        case "mousebuttondown":
    1073             if (ev.button == SDL_BUTTON_LEFT && preSelectedAction != ACTION_NONE)
     1075            if (ev.button == SDL_BUTTON_LEFT && preSelectedAction)
    10741076            {
    10751077                var action = determineAction(ev.x, ev.y);
    10761078                resetPreselectedAction();
    function handleInputAfterGui(ev)  
    10781080                    break;
    10791081                return doAction(action, ev);
    10801082            }
    1081             else if (ev.button == SDL_BUTTON_RIGHT && preSelectedAction != ACTION_NONE)
     1083            else if (ev.button == SDL_BUTTON_RIGHT)
    10821084            {
    10831085                resetPreselectedAction();
    10841086                break;
    function getActionForSelection(player, selection)  
    16381640            if (!hasClass(state, "Unit") || hasClass(state, "Animal") || state.garrisonHolder)
    16391641                break;
    16401642
    1641             if (preSelectedAction == STANCE)
     1643            if (preSelectedAction == ACTION_STANCE)
    16421644                return ["violent", "aggressive", "passive", "defensive", "standground"];
    16431645            if (ret.length) // minimimum is 2 units for formation to be enabled
    16441646                return Engine.GuiInterfaceCall("GetAvailableFormations");
    function getActionForSelection(player, selection)  
    16621664// Performs the specified group
    16631665function performGroup(action, nr, ev)
    16641666{
     1667    if (nr == "reset")
     1668    {
     1669        resetPreselectedAction();
     1670        return;
     1671    }
    16651672    switch (action)
    16661673    {
    16671674    case "snap":
    function performGroup(action, nr, ev)  
    17951802            }
    17961803        }
    17971804        break;
    1798     case "reset":
    1799         resetPreselectedAction();
    1800         break;
    18011805    }
    18021806}
    18031807
  • binaries/data/config/default.cfg

    commit ab24419fee2fd86ba4cfcec2d85f86c67a526e4a
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sun Jun 10 21:37:36 2012 +0200
    
        Separate function initBuildingPlacementView()
        Building placement is now shown immediately, not after mouse movement.
        User can use the same several hotkey more times, e.g. for training.
        Or for iterate over the possible options using hotkeys, changing the
        Formation or Stance of the selected units or choosing different buildings
        during placement.
        
        setting inputState = INPUT_PRESELECTEDACTION for build and garrison
        alters mouse left/rightclick behavior.
        
        Formation fix: don't allow hotkey if selection is only one unit
        
        Add forwardslash as hotkey to reset action hotkey
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 0f1220e..1f7c35c 100644
    a b hotkey.selection.group.action.9 = "Shift+K"  
    202202hotkey.selection.group.action.10 = "Shift+L"
    203203hotkey.selection.group.action.11 = Colon
    204204hotkey.selection.group.action.12 = DoubleQuote
     205hotkey.selection.group.reset.action = ForwardSlash
    205206
    206207; > SESSION CONTROLS
    207208hotkey.session.kill = Delete                ; Destroy selected units
  • binaries/data/mods/public/gui/session/input.js

    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 1888087..8775bb3 100644
    a b const ACTION_STANCE = 32;  
    2222const ACTION_BARTER = 64;
    2323const ACTION_TRADER =128;
    2424var preSelectedAction = ACTION_NONE;
     25
     26// N.B. reset this after selecting different units or buildings
    2527var _optionsOfpreSelected = [];
    2628
    2729const INPUT_NORMAL = 0;
    function updateBuildingPlacementPreview()  
    144146    return false;
    145147}
    146148
     149function initBuildingPlacementView(ev)
     150{
     151    if (placementSupport.mode === "wall")
     152    {
     153        // Including only the on-screen towers in the next snap candidate list is sufficient here, since the user is
     154        // still selecting a starting point (which must necessarily be on-screen). (The update of the snap entities
     155        // itself happens in the call to updateBuildingPlacementPreview below).
     156        placementSupport.wallSnapEntitiesIncludeOffscreen = false;
     157    }
     158    else
     159    {
     160        var snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
     161            "template": placementSupport.template,
     162            "x": placementSupport.position.x,
     163            "z": placementSupport.position.z,
     164        });
     165        if (snapData)
     166        {
     167            placementSupport.angle = snapData.angle;
     168            placementSupport.position.x = snapData.x;
     169            placementSupport.position.z = snapData.z;
     170        }
     171    }
     172    updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
     173}
     174
    147175function findGatherType(gatherer, supply)
    148176{
    149177    if (!gatherer || !supply)
    function findGatherType(gatherer, supply)  
    155183    return undefined;
    156184}
    157185
     186function resetPreselectedAction()
     187{
     188    placementSupport.Reset();
     189    inputState = INPUT_NORMAL;
     190    _optionsOfpreSelected = [];
     191
     192}
     193
    158194function getActionInfo(action, target)
    159195{
    160196    var selection = g_Selection.toList();
    function determineAction(x, y, fromMinimap)  
    449485            break;
    450486        }
    451487    }
    452     else if (Engine.HotkeyIsPressed("session.garrison"))
     488    else if (Engine.HotkeyIsPressed("session.garrison") || preSelectedAction == ACTION_GARRISON)
    453489    {
    454490        if (getActionInfo("garrison", target).possible)
    455491            return {"type": "garrison", "cursor": "action-garrison", "target": target};
    function handleInputBeforeGui(ev, hoveredObject)  
    755791                var queued = Engine.HotkeyIsPressed("session.queue");
    756792                if (tryPlaceBuilding(queued))
    757793                {
    758                     if (queued) {
     794                    if (queued)
    759795                        inputState = INPUT_BUILDING_PLACEMENT;
    760                     } else {
    761                         inputState = INPUT_NORMAL;
    762                         _optionsOfpreSelected = [];
    763                     }
     796                    else
     797                        resetPreselectedAction();
    764798                }
    765799                else
    766800                {
    function handleInputBeforeGui(ev, hoveredObject)  
    774808            if (ev.button == SDL_BUTTON_RIGHT)
    775809            {
    776810                // Cancel building
    777                 placementSupport.Reset();
    778                 inputState = INPUT_NORMAL;
    779                 _optionsOfpreSelected = [];
     811                resetPreselectedAction();
    780812                return true;
    781813            }
    782814            break;
    function handleInputAfterGui(ev)  
    9981030            return false;
    9991031
    10001032        case "mousebuttondown":
     1033            _optionsOfpreSelected = [];
    10011034            if (ev.button == SDL_BUTTON_LEFT)
    10021035            {
    10031036                dragStart = [ ev.x, ev.y ];
    function handleInputAfterGui(ev)  
    10141047            break;
    10151048
    10161049        case "hotkeydown":
    1017             if (ev.hotkey.indexOf("selection.group.") == 0)
     1050            if (ev.hotkey && ev.hotkey.indexOf("selection.group.") == 0)
    10181051            {
     1052                var sptr = ev.hotkey.split(".");
    10191053                var now = new Date();
    1020                 if ((now.getTime() - doublePressTimer < doublePressTime) && (ev.hotkey == prevHotkey))
    1021                 {
    1022                     if (ev.hotkey.indexOf("selection.group.select.") == 0)
    1023                     {
    1024                         var sptr = ev.hotkey.split(".");
    1025                         performGroup("snap", sptr[3]);
    1026                     }
     1054                if ((now.getTime() - doublePressTimer < doublePressTime) && (ev.hotkey == prevHotkey) && ev.hotkey.indexOf("selection.group.select.") == 0) {
     1055                    performGroup("snap", sptr[3], ev);
    10271056                }
    10281057                else
    10291058                {
    1030                     var sptr = ev.hotkey.split(".");
    1031                     performGroup(sptr[2], sptr[3]);
     1059                    performGroup(sptr[2], sptr[3], ev);
    10321060
    10331061                    doublePressTimer = now.getTime();
    10341062                    prevHotkey = ev.hotkey;
    function handleInputAfterGui(ev)  
    10451073            if (ev.button == SDL_BUTTON_LEFT && preSelectedAction != ACTION_NONE)
    10461074            {
    10471075                var action = determineAction(ev.x, ev.y);
     1076                resetPreselectedAction();
    10481077                if (!action)
    10491078                    break;
    1050                 preSelectedAction = ACTION_NONE;
    1051                 inputState = INPUT_NORMAL;
    1052                 _optionsOfpreSelected = [];
    10531079                return doAction(action, ev);
    10541080            }
    10551081            else if (ev.button == SDL_BUTTON_RIGHT && preSelectedAction != ACTION_NONE)
    10561082            {
    1057                 preSelectedAction = ACTION_NONE;
    1058                 inputState = INPUT_NORMAL;
    1059                 _optionsOfpreSelected = [];
     1083                resetPreselectedAction();
    10601084                break;
    10611085            }
    1062             // else
    10631086        case "hotkeydown":
    1064             if (!ev.hotkey)
    1065                 break;
    1066 
    1067             if (ev.hotkey.indexOf("selection.group.action.") == 0)
     1087            if (ev.hotkey && ev.hotkey.indexOf("selection.group.action.") == 0)
    10681088            {
    10691089                var sptr = ev.hotkey.split(".");
    10701090                performGroup(sptr[2], sptr[3]);
    function handleInputAfterGui(ev)  
    10741094            // Slight hack: If selection is empty, reset the input state
    10751095            if (g_Selection.toList().length == 0)
    10761096            {
    1077                 preSelectedAction = ACTION_NONE;
    1078                 inputState = INPUT_NORMAL;
    1079                 _optionsOfpreSelected = [];
     1097                resetPreselectedAction();
    10801098                break;
    10811099            }
    10821100        }
    function handleInputAfterGui(ev)  
    11081126                {
    11091127                    g_Selection.reset();
    11101128                    resetEntitySearch();
    1111                     inputState = INPUT_NORMAL;
    1112                     _optionsOfpreSelected = [];
     1129                    resetPreselectedAction();
    11131130                    return true;
    11141131                }
    11151132
    function handleInputAfterGui(ev)  
    11831200                    g_Selection.reset();
    11841201                    g_Selection.addList(ents);
    11851202                }
    1186 
    1187                 inputState = INPUT_NORMAL;
    1188                 _optionsOfpreSelected = [];
     1203                resetPreselectedAction();
    11891204                return true;
    11901205            }
    11911206            break;
    function handleInputAfterGui(ev)  
    11961211        switch (ev.type)
    11971212        {
    11981213        case "mousemotion":
    1199            
    12001214            placementSupport.position = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
    1201            
    1202             if (placementSupport.mode === "wall")
    1203             {
    1204                 // Including only the on-screen towers in the next snap candidate list is sufficient here, since the user is
    1205                 // still selecting a starting point (which must necessarily be on-screen). (The update of the snap entities
    1206                 // itself happens in the call to updateBuildingPlacementPreview below).
    1207                 placementSupport.wallSnapEntitiesIncludeOffscreen = false;
    1208             }
    1209             else
    1210             {
    1211                 var snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
    1212                     "template": placementSupport.template,
    1213                     "x": placementSupport.position.x,
    1214                     "z": placementSupport.position.z,
    1215                 });
    1216                 if (snapData)
    1217                 {
    1218                     placementSupport.angle = snapData.angle;
    1219                     placementSupport.position.x = snapData.x;
    1220                     placementSupport.position.z = snapData.z;
    1221                 }
    1222             }
    1223 
    1224             updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
     1215            initBuildingPlacementView(ev);
    12251216            return false; // continue processing mouse motion
    12261217
    12271218        case "mousebuttondown":
    function handleInputAfterGui(ev)  
    12381229                else
    12391230                {
    12401231                    placementSupport.position = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
    1241                     dragStart = [ ev.x, ev.y ];
    1242                     inputState = INPUT_BUILDING_CLICK;
     1232                    dragStart = [ ev.x, ev.y ];
     1233                    inputState = INPUT_BUILDING_CLICK;
     1234                    _optionsOfpreSelected = [];
    12431235                }
    12441236                return true;
    12451237            }
    function handleInputAfterGui(ev)  
    12471239            {
    12481240                // Cancel building
    12491241                placementSupport.Reset();
    1250                 inputState = INPUT_NORMAL;
    1251                 preSelectedAction = ACTION_NONE;
    1252                  _optionsOfpreSelected = [];
     1242                resetPreselectedAction();
    12531243                return true;
    12541244            }
    12551245            break;
    function handleInputAfterGui(ev)  
    12681258                placementSupport.angle -= rotation_step;
    12691259                updateBuildingPlacementPreview();
    12701260                break;
     1261            default:
     1262                if (ev.hotkey.indexOf("selection.group.action.") == 0)
     1263                {   // can switch buildings
     1264                    var sptr = ev.hotkey.split(".");
     1265                    performGroup(sptr[2], sptr[3], ev);
     1266                }
    12711267            }
    12721268            break;
    12731269
    function getActionForSelection(player, selection)  
    16181614        switch (preSelectedAction)
    16191615        {
    16201616        case ACTION_GARRISON:
    1621             if (state.buildEntities || (hasClass(state, "Unit") && !hasClass(state, "Animal") && !state.garrisonHolder))
     1617            if (state.buildEntities || (hasClass(state, "Unit") && !hasClass(state, "Animal") && !state.garrisonHolder)) {
     1618                inputState = INPUT_PRESELECTEDACTION;
    16221619                ret.push(ent);
     1620            }
    16231621            break;
    16241622        case ACTION_BUILD:
    1625             if (state.buildEntities && state.buildEntities.length)
     1623            if (state.buildEntities && state.buildEntities.length) {
     1624                inputState = INPUT_PRESELECTEDACTION;
    16261625                return state.buildEntities;
     1626            }
    16271627            break;
    16281628        case ACTION_TRAIN:
    16291629            if (state.production && state.production.entities.length)
    function getActionForSelection(player, selection)  
    16381638            if (!hasClass(state, "Unit") || hasClass(state, "Animal") || state.garrisonHolder)
    16391639                break;
    16401640
    1641             if (preSelectedAction == ACTION_FORMATION) {
    1642                 return Engine.GuiInterfaceCall("GetAvailableFormations");
    1643             } else { // FIXME:
     1641            if (preSelectedAction == STANCE)
    16441642                return ["violent", "aggressive", "passive", "defensive", "standground"];
    1645             }
     1643            if (ret.length) // minimimum is 2 units for formation to be enabled
     1644                return Engine.GuiInterfaceCall("GetAvailableFormations");
     1645            ret.push(1);
    16461646            break;
    16471647        case ACTION_BARTER:
    16481648            if (state.barterMarket)
    function getActionForSelection(player, selection)  
    16601660}
    16611661
    16621662// Performs the specified group
    1663 function performGroup(action, nr)
     1663function performGroup(action, nr, ev)
    16641664{
    16651665    switch (action)
    16661666    {
    function performGroup(action, nr)  
    16981698            var actions = getActionForSelection(player, selection);
    16991699            if (!actions || !actions.length) {
    17001700                preSelectedAction = ACTION_NONE;
    1701                 _optionsOfpreSelected = [];
    17021701                break;
    17031702            }
    17041703
    function performGroup(action, nr)  
    17071706            else if (preSelectedAction == ACTION_TRADER)
    17081707                setupUnitTradingPanel(state, selection);
    17091708
    1710             inputState = INPUT_PRESELECTEDACTION;
    17111709            _optionsOfpreSelected = actions;
    17121710        }
    17131711        else
    function performGroup(action, nr)  
    17351733            {
    17361734            case ACTION_BUILD:
    17371735                var tmpl = GetTemplateData(lst);
    1738                 if (tmpl.requiredTechnology && !Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology))
    1739                     break;
    1740 
    1741                 startBuildingPlacement(lst);
    1742                 inputState = INPUT_BUILDING_PLACEMENT;
    1743                 preSelectedAction = ACTION_NONE;
    1744                 return;
     1736                if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
     1737                    // N.B. sets inputState = INPUT_BUILDING_PLACEMENT:
     1738                    startBuildingPlacement(lst);
     1739                    placementSupport.position = Engine.GetTerrainAtScreenPoint(mouseX, mouseY);
     1740                    initBuildingPlacementView(ev);
     1741                }
     1742                break;
    17451743            case ACTION_TRAIN:
    17461744                var tmpl = GetTemplateData(lst);
    17471745                if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
    function performGroup(action, nr)  
    17531751                g_Selection.reset();
    17541752                lst.splice(nr, lst.length - nr)
    17551753                g_Selection.addList(lst);
     1754                inputState = INPUT_PRESELECTEDACTION;
    17561755                break;
    17571756            case ACTION_UNGARRISON:
    1758                 if (lst.length != 1 || nr == 0) {
     1757                if (lst.length > 1 || nr == 0) {
     1758                    if (lst.length != 1)   // TODO: uload all from all
     1759                        lst = lst[nr]; // selected buildings
     1760                    else
     1761                        lst = lst[0];
     1762                    // FIXME: follow when ungarrisoning all
    17591763                    var state = GetEntityState(lst);
    1760                     var gents = state.garrisonHolder.entities
    1761                     unloadAll(lst[nr]);
    1762                     // TODO: follow when ungarrisoning all
    1763                     //var gents = g_Selection.toList();
    1764         //          Engine.CameraFollow(gents[0]);
     1764                    var gents = state.garrisonHolder.entities;
     1765                    unloadAll(lst);
     1766                    Engine.CameraFollow(0);
     1767                    g_Selection.reset();
     1768                    g_Selection.addList(gents);
     1769                    Engine.CameraFollow(gents[0]);
    17651770                } else {
    17661771                    lst = lst[0];
    17671772                    var state = GetEntityState(lst);
    function performGroup(action, nr)  
    17881793            case ACTION_TRADER: //TODO
    17891794                break;
    17901795            }
    1791             inputState = INPUT_NORMAL;
    1792             _optionsOfpreSelected = [];
    17931796        }
     1797        break;
     1798    case "reset":
     1799        resetPreselectedAction();
     1800        break;
    17941801    }
    17951802}
    17961803
    function resetEntitySearch()  
    18371844
    18381845function findEntity(classes, mode)
    18391846{
     1847    var player = Engine.GetPlayerID();
    18401848    // Cycle through idling classes before giving up
    18411849    for (var i = 0; i <= classes.length; ++i)
    18421850    {
    function findEntity(classes, mode)  
    18441852        var newEntity = Engine.GuiInterfaceCall("FindEntity", data);
    18451853        if (newEntity && newEntity != lastEntity)
    18461854        {
     1855            if (!getActionForSelection(player, [newEntity]).length)
     1856                resetPreselectedAction();
     1857
    18471858            lastEntity = newEntity;
    18481859            g_Selection.reset();
    18491860            g_Selection.addList([lastEntity]);
  • binaries/data/mods/public/gui/session/input.js

    commit 5656cbab54bcd160f89a6b6681f6329f8b4d15aa
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sun Jun 10 12:24:03 2012 +0200
    
        was too much indented (no semantic change)
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 7da7546..1888087 100644
    a b function handleInputAfterGui(ev)  
    10141014            break;
    10151015
    10161016        case "hotkeydown":
    1017                 if (ev.hotkey.indexOf("selection.group.") == 0)
     1017            if (ev.hotkey.indexOf("selection.group.") == 0)
     1018            {
     1019                var now = new Date();
     1020                if ((now.getTime() - doublePressTimer < doublePressTime) && (ev.hotkey == prevHotkey))
    10181021                {
    1019                     var now = new Date();
    1020                     if ((now.getTime() - doublePressTimer < doublePressTime) && (ev.hotkey == prevHotkey))
    1021                     {
    1022                         if (ev.hotkey.indexOf("selection.group.select.") == 0)
    1023                         {
    1024                             var sptr = ev.hotkey.split(".");
    1025                             performGroup("snap", sptr[3]);
    1026                         }
    1027                     }
    1028                     else
     1022                    if (ev.hotkey.indexOf("selection.group.select.") == 0)
    10291023                    {
    10301024                        var sptr = ev.hotkey.split(".");
    1031                         performGroup(sptr[2], sptr[3]);
    1032 
    1033                         doublePressTimer = now.getTime();
    1034                         prevHotkey = ev.hotkey;
     1025                        performGroup("snap", sptr[3]);
    10351026                    }
    10361027                }
    1037                 break;
     1028                else
     1029                {
     1030                    var sptr = ev.hotkey.split(".");
     1031                    performGroup(sptr[2], sptr[3]);
     1032
     1033                    doublePressTimer = now.getTime();
     1034                    prevHotkey = ev.hotkey;
     1035                }
     1036            }
     1037            break;
    10381038        }
    10391039        break;
    10401040       
  • binaries/data/config/default.cfg

    commit 4fdb29daa1681969a6316a41e6f13daf5d513219
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sun Jun 10 05:55:54 2012 +0200
    
        See default.cfg:
        The keys H to backslash are implemented as numbers for hotkey actions. to
        control the actions for currently selected buildings or workers/units.
        Modified behaviour: watermark and camera reset hotkeys are altered.
        
        For example to build a house:
        select a villager (with mouse or with idle hot-key '.')
        J, H and select the location to place the house.
        
        H is garrison for all units. For a villager the option to build is J.
        For buildings, K and L are train and ungarrison respectively. Military
        units can use K, L for formation and stance. barter and trader options
        aren't implemented yet.
        
        The second press of the H to backslash button has a different meaning:
        It indicates `how many' or `which', in the same order as the buttons in
        the user interface. From H to backslash means 0 to 6, with shift,
        capital H to doublequote means 7-12. Except when garrisoning, then
        H to backslash means garrisoning 1 to 7 units.
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 760ad38..0f1220e 100644
    a b hotkey.pause = Pause ; Pause/unpause game  
    115115hotkey.screenshot = F2                      ; Take PNG screenshot
    116116hotkey.bigscreenshot = "Shift+F2"           ; Take large BMP screenshot
    117117hotkey.togglefullscreen = "Alt+Return"      ; Toggle fullscreen/windowed mode
    118 hotkey.screenshot.watermark = "K"           ; Toggle product/company watermark for official screenshots
     118hotkey.screenshot.watermark = "R"           ; Toggle product/company watermark for official screenshots
    119119hotkey.wireframe = "Alt+W"                  ; Toggle wireframe mode
    120120hotkey.silhouettes = "Alt+S"                ; Toggle unit silhouettes
    121121
    122122; > CAMERA SETTINGS
    123 hotkey.camera.reset = "H"                                 ; Reset camera rotation to default.
     123hotkey.camera.reset = "X"                                 ; Reset camera rotation to default.
    124124hotkey.camera.follow = "F"                                ; Follow the first unit in the selection
    125125hotkey.camera.zoom.in = Plus, Equals, NumPlus             ; Zoom camera in (continuous control)
    126126hotkey.camera.zoom.out = Minus, NumMinus                  ; Zoom camera out (continuous control)
    hotkey.selection.group.select.9 = 9  
    189189hotkey.selection.group.save.9 = "Ctrl+9"
    190190hotkey.selection.group.add.9 = "Shift+9"
    191191
     192hotkey.selection.group.action.0 = H
     193hotkey.selection.group.action.1 = J
     194hotkey.selection.group.action.2 = K
     195hotkey.selection.group.action.3 = L
     196hotkey.selection.group.action.4 = Semicolon
     197hotkey.selection.group.action.5 = SingleQuote
     198hotkey.selection.group.action.6 = BackSlash
     199hotkey.selection.group.action.7 = "Shift+H"
     200hotkey.selection.group.action.8 = "Shift+J"
     201hotkey.selection.group.action.9 = "Shift+K"
     202hotkey.selection.group.action.10 = "Shift+L"
     203hotkey.selection.group.action.11 = Colon
     204hotkey.selection.group.action.12 = DoubleQuote
     205
    192206; > SESSION CONTROLS
    193207hotkey.session.kill = Delete                ; Destroy selected units
    194208hotkey.session.garrison = Ctrl              ; Modifier to garrison when clicking on building
  • binaries/data/mods/public/gui/session/input.js

    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 165ac75..7da7546 100644
    a b const SDLK_LALT = 308;  
    1515const ACTION_NONE = 0;
    1616const ACTION_GARRISON = 1;
    1717const ACTION_BUILD = 2;
     18const ACTION_TRAIN = 4;
     19const ACTION_UNGARRISON = 8;
     20const ACTION_FORMATION = 16;
     21const ACTION_STANCE = 32;
     22const ACTION_BARTER = 64;
     23const ACTION_TRADER =128;
    1824var preSelectedAction = ACTION_NONE;
     25var _optionsOfpreSelected = [];
    1926
    2027const INPUT_NORMAL = 0;
    2128const INPUT_SELECTING = 1;
    function handleInputBeforeGui(ev, hoveredObject)  
    748755                var queued = Engine.HotkeyIsPressed("session.queue");
    749756                if (tryPlaceBuilding(queued))
    750757                {
    751                     if (queued)
     758                    if (queued) {
    752759                        inputState = INPUT_BUILDING_PLACEMENT;
    753                     else
     760                    } else {
    754761                        inputState = INPUT_NORMAL;
     762                        _optionsOfpreSelected = [];
     763                    }
    755764                }
    756765                else
    757766                {
    function handleInputBeforeGui(ev, hoveredObject)  
    767776                // Cancel building
    768777                placementSupport.Reset();
    769778                inputState = INPUT_NORMAL;
     779                _optionsOfpreSelected = [];
    770780                return true;
    771781            }
    772782            break;
    function handleInputAfterGui(ev)  
    10391049                    break;
    10401050                preSelectedAction = ACTION_NONE;
    10411051                inputState = INPUT_NORMAL;
     1052                _optionsOfpreSelected = [];
    10421053                return doAction(action, ev);
    10431054            }
    10441055            else if (ev.button == SDL_BUTTON_RIGHT && preSelectedAction != ACTION_NONE)
    10451056            {
    10461057                preSelectedAction = ACTION_NONE;
    10471058                inputState = INPUT_NORMAL;
     1059                _optionsOfpreSelected = [];
    10481060                break;
    10491061            }
    10501062            // else
     1063        case "hotkeydown":
     1064            if (!ev.hotkey)
     1065                break;
     1066
     1067            if (ev.hotkey.indexOf("selection.group.action.") == 0)
     1068            {
     1069                var sptr = ev.hotkey.split(".");
     1070                performGroup(sptr[2], sptr[3]);
     1071            }
     1072            break;
    10511073        default:
    10521074            // Slight hack: If selection is empty, reset the input state
    10531075            if (g_Selection.toList().length == 0)
    10541076            {
    10551077                preSelectedAction = ACTION_NONE;
    10561078                inputState = INPUT_NORMAL;
     1079                _optionsOfpreSelected = [];
    10571080                break;
    10581081            }
    10591082        }
    function handleInputAfterGui(ev)  
    10861109                    g_Selection.reset();
    10871110                    resetEntitySearch();
    10881111                    inputState = INPUT_NORMAL;
     1112                    _optionsOfpreSelected = [];
    10891113                    return true;
    10901114                }
    10911115
    function handleInputAfterGui(ev)  
    11611185                }
    11621186
    11631187                inputState = INPUT_NORMAL;
     1188                _optionsOfpreSelected = [];
    11641189                return true;
    11651190            }
    11661191            break;
    function handleInputAfterGui(ev)  
    12231248                // Cancel building
    12241249                placementSupport.Reset();
    12251250                inputState = INPUT_NORMAL;
     1251                preSelectedAction = ACTION_NONE;
     1252                 _optionsOfpreSelected = [];
    12261253                return true;
    12271254            }
    12281255            break;
    function performFormation(entity, formationName)  
    15771604    }
    15781605}
    15791606
     1607// This returns a list of actions. Caller still has to check Technology availability
     1608function getActionForSelection(player, selection)
     1609{
     1610    var ret = [];
     1611
     1612    for each (var ent in selection)
     1613    {
     1614        var state = GetEntityState(ent);
     1615        if (!state || (state.player != player && !g_DevSettings.controlAll))
     1616            continue;
     1617
     1618        switch (preSelectedAction)
     1619        {
     1620        case ACTION_GARRISON:
     1621            if (state.buildEntities || (hasClass(state, "Unit") && !hasClass(state, "Animal") && !state.garrisonHolder))
     1622                ret.push(ent);
     1623            break;
     1624        case ACTION_BUILD:
     1625            if (state.buildEntities && state.buildEntities.length)
     1626                return state.buildEntities;
     1627            break;
     1628        case ACTION_TRAIN:
     1629            if (state.production && state.production.entities.length)
     1630                return state.production.entities;
     1631            break;
     1632        case ACTION_UNGARRISON:
     1633            if (state.garrisonHolder && state.garrisonHolder.entities && state.garrisonHolder.entities.length)
     1634                ret.push(ent);
     1635            break;
     1636        case ACTION_FORMATION:
     1637        case ACTION_STANCE:
     1638            if (!hasClass(state, "Unit") || hasClass(state, "Animal") || state.garrisonHolder)
     1639                break;
     1640
     1641            if (preSelectedAction == ACTION_FORMATION) {
     1642                return Engine.GuiInterfaceCall("GetAvailableFormations");
     1643            } else { // FIXME:
     1644                return ["violent", "aggressive", "passive", "defensive", "standground"];
     1645            }
     1646            break;
     1647        case ACTION_BARTER:
     1648            if (state.barterMarket)
     1649                ret.push(ent);
     1650            break;
     1651        case ACTION_TRADER:
     1652            if (state.trader)
     1653                ret.push([ent, state]);
     1654            break;
     1655        default:
     1656            return ret; //shouldn't happen
     1657        }
     1658    }
     1659    return ret;
     1660}
     1661
    15801662// Performs the specified group
    15811663function performGroup(action, nr)
    15821664{
    function performGroup(action, nr)  
    16041686        g_Groups.addEntities(nr, selection);
    16051687        updateGroups();
    16061688        break;
     1689    case "action":
     1690        if (!_optionsOfpreSelected.length) {
     1691            // action hotkey (first pass): With current selection, check possible
     1692            // ACTION_XXX's and set preSelectedAction when applicable
     1693            preSelectedAction = (1 << nr);
     1694
     1695            var selection = g_Selection.toList();
     1696            var player = Engine.GetPlayerID();
     1697
     1698            var actions = getActionForSelection(player, selection);
     1699            if (!actions || !actions.length) {
     1700                preSelectedAction = ACTION_NONE;
     1701                _optionsOfpreSelected = [];
     1702                break;
     1703            }
     1704
     1705            if (preSelectedAction == ACTION_BARTER)
     1706                setupUnitBarterPanel(state);
     1707            else if (preSelectedAction == ACTION_TRADER)
     1708                setupUnitTradingPanel(state, selection);
     1709
     1710            inputState = INPUT_PRESELECTEDACTION;
     1711            _optionsOfpreSelected = actions;
     1712        }
     1713        else
     1714        {
     1715            // 2nd action hotkey. Do preselectedAction[nr]
     1716            // The result depends on the action.
     1717
     1718            var lst = _optionsOfpreSelected;
     1719            if (!lst) // shouldn't happen
     1720                break;
     1721
     1722            if (preSelectedAction & (ACTION_UNGARRISON | ACTION_GARRISON))
     1723            {
     1724                if (preSelectedAction & ACTION_GARRISON)
     1725                    ++nr;
     1726                if (nr > lst.length)
     1727                    nr = lst.length;
     1728            } else if (preSelectedAction != (ACTION_BUILD|ACTION_TRAIN)) {
     1729                if (nr >= lst.length)
     1730                    break;
     1731                lst = lst[nr];
     1732            }
     1733
     1734            switch (preSelectedAction)
     1735            {
     1736            case ACTION_BUILD:
     1737                var tmpl = GetTemplateData(lst);
     1738                if (tmpl.requiredTechnology && !Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology))
     1739                    break;
     1740
     1741                startBuildingPlacement(lst);
     1742                inputState = INPUT_BUILDING_PLACEMENT;
     1743                preSelectedAction = ACTION_NONE;
     1744                return;
     1745            case ACTION_TRAIN:
     1746                var tmpl = GetTemplateData(lst);
     1747                if (!tmpl.requiredTechnology || Engine.GuiInterfaceCall("IsTechnologyResearched", tmpl.requiredTechnology)) {
     1748                    var ents = g_Selection.toList();
     1749                    addTrainingToQueue(ents, lst);
     1750                }
     1751                break;
     1752            case ACTION_GARRISON: // we garison nr+1 count
     1753                g_Selection.reset();
     1754                lst.splice(nr, lst.length - nr)
     1755                g_Selection.addList(lst);
     1756                break;
     1757            case ACTION_UNGARRISON:
     1758                if (lst.length != 1 || nr == 0) {
     1759                    var state = GetEntityState(lst);
     1760                    var gents = state.garrisonHolder.entities
     1761                    unloadAll(lst[nr]);
     1762                    // TODO: follow when ungarrisoning all
     1763                    //var gents = g_Selection.toList();
     1764        //          Engine.CameraFollow(gents[0]);
     1765                } else {
     1766                    lst = lst[0];
     1767                    var state = GetEntityState(lst);
     1768                    var gents = state.garrisonHolder.entities;
     1769                    // FIXME unload nr times, requires some update.
     1770                    unload(lst, gents);
     1771                }
     1772                break;
     1773            case ACTION_FORMATION:
     1774                ents = g_Selection.toList();
     1775                var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
     1776                    "ents": g_Selection.toList(),
     1777                    "formationName": lst
     1778                });
     1779                if (formationOk)
     1780                    performFormation(ents, lst);
     1781                break
     1782            case ACTION_STANCE:
     1783                ents = g_Selection.toList();
     1784                performStance(ents, lst);
     1785                break;
     1786            case ACTION_BARTER: //TODO
     1787                break;
     1788            case ACTION_TRADER: //TODO
     1789                break;
     1790            }
     1791            inputState = INPUT_NORMAL;
     1792            _optionsOfpreSelected = [];
     1793        }
    16071794    }
    16081795}
    16091796
  • binaries/data/config/default.cfg

    commit 70644e097fb424a6690b717a71e8be553c5384c4
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 9 22:40:07 2012 +0200
    
        Generalize findIdleUnit to findEntity and enable building hotkeys
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
    index 1ae80ba..760ad38 100644
    a b hotkey.selection.add = Shift ; Add units to selection  
    151151hotkey.selection.milonly = Alt              ; Add only military units to selection
    152152hotkey.selection.remove = Ctrl              ; Remove units from selection
    153153hotkey.selection.idleworker = Period        ; Select next idle worker
     154hotkey.selection.structure = Y              ; Select structure
     155hotkey.selection.civilcenter = U            ; Select towncenter
     156hotkey.selection.dropsiteres = I            ; Select dropsite stone/wood/metal
     157hotkey.selection.dropsitefood = O           ; Select dropsite food
     158hotkey.selection.market = P                 ; Select market
    154159hotkey.selection.idlewarrior = Comma        ; Select next idle warrior
    155160hotkey.selection.offscreen = Alt            ; Include offscreen units in selection
    156161hotkey.selection.group.select.0 = 0
  • binaries/data/mods/public/gui/session/input.js

    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index 3dcecbb..165ac75 100644
    a b function handleInputAfterGui(ev)  
    10841084                if (!ents.length)
    10851085                {
    10861086                    g_Selection.reset();
    1087                     resetIdleUnit();
     1087                    resetEntitySearch();
    10881088                    inputState = INPUT_NORMAL;
    10891089                    return true;
    10901090                }
    function setCameraFollow(entity)  
    16421642var lastEntity = 0;
    16431643var currEntClass = 0;
    16441644
    1645 function resetIdleUnit()
     1645function resetEntitySearch()
    16461646{
    16471647    lastEntity = 0;
    16481648    currEntClass = 0;
    16491649}
    16501650
    1651 function findEntity(classes)
     1651function findEntity(classes, mode)
    16521652{
    16531653    // Cycle through idling classes before giving up
    16541654    for (var i = 0; i <= classes.length; ++i)
    16551655    {
    1656         var data = { prevUnit: lastEntity, idleClass: classes[currEntClass] };
    1657         var newIdleUnit = Engine.GuiInterfaceCall("FindIdleUnit", data);
    1658 
    1659         // Check if we have new valid entity
    1660         if (newIdleUnit && newIdleUnit != lastEntity)
     1656        var data = { prevEntity: lastEntity, entClass: classes[currEntClass], searchMode: mode};
     1657        var newEntity = Engine.GuiInterfaceCall("FindEntity", data);
     1658        if (newEntity && newEntity != lastEntity)
    16611659        {
    1662             lastEntity = newIdleUnit;
    1663             g_Selection.reset()
     1660            lastEntity = newEntity;
     1661            g_Selection.reset();
    16641662            g_Selection.addList([lastEntity]);
    16651663            Engine.CameraFollow(lastEntity);
    1666 
    16671664            return;
    16681665        }
    1669 
    16701666        lastEntity = 0;
    16711667        currEntClass = (currEntClass + 1) % classes.length;
    16721668    }
    1673 
    16741669    // TODO: display a message or play a sound to indicate no more idle units, or something
    16751670    // Reset for next cycle
    1676     resetIdleUnit();
     1671    resetEntitySearch();
    16771672}
    16781673
    16791674function unload(garrisonHolder, entities)
  • binaries/data/mods/public/gui/session/session.xml

    diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml
    index d876959..1d34482 100644
    a b  
    8686
    8787        <!-- Find idle warrior - TODO: Potentially move this to own UI button? -->
    8888        <object hotkey="selection.idlewarrior">
    89             <action on="Press">findEntity(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"]);</action>
     89            <action on="Press">findEntity(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"], 1);</action>
     90        </object>
     91
     92        <!-- Select civilcenter -->
     93        <object hotkey="selection.civilcenter">
     94            <action on="Press">findEntity(["CivCentre"], 0);</action>
     95        </object>
     96        <!-- Select market -->
     97        <object hotkey="selection.market">
     98            <action on="Press">findEntity(["BarterMarket", "Market", "NavalMarket"], 0);</action>
     99        </object>
     100        <!-- Select dropsitefood -->
     101        <object hotkey="selection.dropsitefood">
     102            <action on="Press">findEntity(["CivCentre", "DropsiteFood"], 0);</action>
     103        </object>
     104        <!-- Select dropsitewood -->
     105        <object hotkey="selection.dropsiteres">
     106            <action on="Press">findEntity(["CivCentre", "DropsiteWood", "DropsiteStone", "DropsiteMetal"], 0);</action>
     107        </object>
     108        <!-- Select structure -->
     109        <object hotkey="selection.structure">
     110            <action on="Press">findEntity(["Structure"], 0);</action>
    90111        </object>
    91112
    92113        <!-- ================================  ================================ -->
     
    525546                    >
    526547                        <!-- TODO: should highlight the button if there's non-zero idle workers -->
    527548                        <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" />
    528                         <action on="Press">findEntity(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action>
     549                        <action on="Press">findEntity(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"], 1);</action>
    529550                    </object>
    530551                </object>
    531552            </object>
  • binaries/data/mods/public/simulation/components/GuiInterface.js

    diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js
    index 4ce8c71..a2c29ba 100644
    a b GuiInterface.prototype.PlaySound = function(player, data)  
    14261426    PlaySound(data.name, data.entity);
    14271427};
    14281428
    1429 function isIdleUnit(ent, idleClass)
    1430 {
    1431     var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
    1432     var cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
    1433    
    1434     // TODO: Do something with garrisoned idle units
    1435     return (cmpUnitAI && cmpIdentity && cmpUnitAI.IsIdle() && !cmpUnitAI.IsGarrisoned() && idleClass && cmpIdentity.HasClass(idleClass));
    1436 }
    1437 
    1438 GuiInterface.prototype.FindIdleUnit = function(player, data)
     1429GuiInterface.prototype.FindEntity = function(player, data)
    14391430{
    14401431    var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    14411432    var playerEntities = rangeMan.GetEntitiesByPlayer(player);
    GuiInterface.prototype.FindIdleUnit = function(player, data)  
    14441435    // so that we cycle around in a predictable order
    14451436    for each (var ent in playerEntities)
    14461437    {
    1447         if (ent > data.prevUnit && isIdleUnit(ent, data.idleClass))
    1448             return ent;
     1438        var cmpId = Engine.QueryInterface(ent, IID_Identity);
     1439        if (ent > data.prevEntity && cmpId && cmpId.HasClass(data.entClass)) {
     1440            if (data.searchMode == 0) {
     1441                return ent;
     1442            }  else if (data.searchMode == 1) { // Search idle villager/soldier
     1443                var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     1444                if (cmpUnitAI && cmpUnitAI.IsIdle() && !cmpUnitAI.IsGarrisoned())
     1445                    return ent;
     1446            }
     1447        }
    14491448    }
    14501449
    1451     // No idle entities left in the class
     1450    // No entities left in the class
    14521451    return 0;
    14531452};
    14541453
    var exposedFunctions = {  
    15711570    "SetWallPlacementPreview": 1,
    15721571    "GetFoundationSnapData": 1,
    15731572    "PlaySound": 1,
    1574     "FindIdleUnit": 1,
     1573    "FindEntity": 1,
    15751574    "GetTradingDetails": 1,
    15761575    "CanAttack": 1,
    15771576
  • binaries/data/mods/public/gui/session/input.js

    commit c68f943a39043debfcbcad02408d7362c088396e
    Author: Roel Kluin <roel.kluin@gmail.com>
    Date:   Sat Jun 9 18:25:59 2012 +0200
    
        rename:
        ACTION_REPAIR => ACTION_REPAIR
        performGroup:groupId => nr
        lastIdleUnit => lastEntity
        currIdleClass => currEntClass
        findIdleUnit() => findEntity()
        
        These names will make more sense after next patches
        
        Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
    
    diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js
    index ff39b74..3dcecbb 100644
    a b const SDLK_LALT = 308;  
    1414
    1515const ACTION_NONE = 0;
    1616const ACTION_GARRISON = 1;
    17 const ACTION_REPAIR = 2;
     17const ACTION_BUILD = 2;
    1818var preSelectedAction = ACTION_NONE;
    1919
    2020const INPUT_NORMAL = 0;
    function determineAction(x, y, fromMinimap)  
    434434            else
    435435                return  {"type": "none", "cursor": "action-garrison-disabled", "target": undefined};
    436436            break;
    437         case ACTION_REPAIR:
     437        case ACTION_BUILD:
    438438            if (getActionInfo("repair", target).possible)
    439439                return {"type": "repair", "cursor": "action-repair", "target": target};
    440440            else
    function performCommand(entity, commandName)  
    15331533                break;
    15341534            case "repair":
    15351535                inputState = INPUT_PRESELECTEDACTION;
    1536                 preSelectedAction = ACTION_REPAIR;
     1536                preSelectedAction = ACTION_BUILD;
    15371537                break;
    15381538            case "unload-all":
    15391539                unloadAll(entity);
    function performFormation(entity, formationName)  
    15781578}
    15791579
    15801580// Performs the specified group
    1581 function performGroup(action, groupId)
     1581function performGroup(action, nr)
    15821582{
    15831583    switch (action)
    15841584    {
    function performGroup(action, groupId)  
    15871587    case "add":
    15881588        var toSelect = [];
    15891589        g_Groups.update();
    1590         for (var ent in g_Groups.groups[groupId].ents)
     1590        for (var ent in g_Groups.groups[nr].ents)
    15911591            toSelect.push(+ent);
    15921592
    15931593        if (action != "add")
    function performGroup(action, groupId)  
    16001600        break;
    16011601    case "save":
    16021602        var selection = g_Selection.toList();
    1603         g_Groups.groups[groupId].reset();
    1604         g_Groups.addEntities(groupId, selection);
     1603        g_Groups.groups[nr].reset();
     1604        g_Groups.addEntities(nr, selection);
    16051605        updateGroups();
    16061606        break;
    16071607    }
    function setCameraFollow(entity)  
    16391639    Engine.CameraFollow(0);
    16401640}
    16411641
    1642 var lastIdleUnit = 0;
    1643 var currIdleClass = 0;
     1642var lastEntity = 0;
     1643var currEntClass = 0;
    16441644
    16451645function resetIdleUnit()
    16461646{
    1647     lastIdleUnit = 0;
    1648     currIdleClass = 0;
     1647    lastEntity = 0;
     1648    currEntClass = 0;
    16491649}
    16501650
    1651 function findIdleUnit(classes)
     1651function findEntity(classes)
    16521652{
    16531653    // Cycle through idling classes before giving up
    16541654    for (var i = 0; i <= classes.length; ++i)
    16551655    {
    1656         var data = { prevUnit: lastIdleUnit, idleClass: classes[currIdleClass] };
     1656        var data = { prevUnit: lastEntity, idleClass: classes[currEntClass] };
    16571657        var newIdleUnit = Engine.GuiInterfaceCall("FindIdleUnit", data);
    16581658
    16591659        // Check if we have new valid entity
    1660         if (newIdleUnit && newIdleUnit != lastIdleUnit)
     1660        if (newIdleUnit && newIdleUnit != lastEntity)
    16611661        {
    1662             lastIdleUnit = newIdleUnit;
     1662            lastEntity = newIdleUnit;
    16631663            g_Selection.reset()
    1664             g_Selection.addList([lastIdleUnit]);
    1665             Engine.CameraFollow(lastIdleUnit);
     1664            g_Selection.addList([lastEntity]);
     1665            Engine.CameraFollow(lastEntity);
    16661666
    16671667            return;
    16681668        }
    16691669
    1670         lastIdleUnit = 0;
    1671         currIdleClass = (currIdleClass + 1) % classes.length;
     1670        lastEntity = 0;
     1671        currEntClass = (currEntClass + 1) % classes.length;
    16721672    }
    16731673
    16741674    // TODO: display a message or play a sound to indicate no more idle units, or something
  • binaries/data/mods/public/gui/session/session.xml

    diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml
    index 08f5d06..d876959 100644
    a b  
    8686
    8787        <!-- Find idle warrior - TODO: Potentially move this to own UI button? -->
    8888        <object hotkey="selection.idlewarrior">
    89             <action on="Press">findIdleUnit(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"]);</action>
     89            <action on="Press">findEntity(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"]);</action>
    9090        </object>
    9191
    9292        <!-- ================================  ================================ -->
     
    525525                    >
    526526                        <!-- TODO: should highlight the button if there's non-zero idle workers -->
    527527                        <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" />
    528                         <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action>
     528                        <action on="Press">findEntity(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action>
    529529                    </object>
    530530                </object>
    531531            </object>