Ticket #515: doubleclick.patch

File doubleclick.patch, 6.5 KB (added by Christoph, 22 months ago)

Patch implementing multiple selection per double-click

  • trunk/binaries/data/mods/public/gui/session_new/input.js

     
    2424var placementPosition; 
    2525var placementEntity; 
    2626 
     27//Time in milliseconds in which a double click is recognized 
     28var doubleclickTime = 400;  
     29var doubleclickTimer = 0; 
     30 
    2731var mouseX = 0; 
    2832var mouseY = 0; 
    2933var specialKeyStates = {}; 
     
    477481        case "mousebuttonup": 
    478482            if (ev.button == SDL_BUTTON_LEFT) 
    479483            { 
    480                 var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 
    481                 if (!ents.length) 
     484                //is this a double-click? 
     485                var now = new Date(); 
     486                if (now.getTime()-doubleclickTimer < doubleclickTime) 
    482487                { 
     488                    //this is a double click 
     489                    var ents = Engine.PickSimilarEntitiesOnScreen(ev.x, ev.y, Engine.GetPlayerID()); 
     490                                // Remove units if selection is too large 
     491                    if (ents.length > MAX_SELECTION_SIZE) 
     492                        ents = ents.slice(0, MAX_SELECTION_SIZE); 
     493 
     494                    // Set selection list 
     495                    g_Selection.setHighlightList([]); 
    483496                    g_Selection.reset(); 
    484                      
    485                     inputState = INPUT_NORMAL; 
    486                     return true; 
     497                    g_Selection.addList(ents); 
     498 
     499                    // Create the selection groups 
     500                    g_Selection.createSelectionGroups(ents); 
     501                 
     502                 
    487503                } 
     504                else 
     505                { 
     506                    //this is no double blick, but it can become one 
     507                    doubleclickTimer = now.getTime(); 
     508                     
     509                    var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 
     510                    if (!ents.length) 
     511                    { 
     512                        g_Selection.reset(); 
     513                     
     514                        inputState = INPUT_NORMAL; 
     515                        return true; 
     516                    } 
    488517 
    489                 g_Selection.reset(); 
    490                 g_Selection.addList([ents[0]]); 
     518                    g_Selection.reset(); 
     519                    g_Selection.addList([ents[0]]); 
     520                     
     521                } 
     522             
    491523 
    492524                inputState = INPUT_NORMAL; 
    493525                return true; 
  • trunk/source/simulation2/helpers/Selection.h

     
    3232 
    3333namespace EntitySelection 
    3434{ 
    35  
    3635/** 
    3736 * Finds all selectable entities under the given screen coordinates. 
    3837 * Returns list ordered by closeness of picking, closest first. 
     
    4645 */ 
    4746std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner); 
    4847 
     48/** 
     49 * Finds a selectable entity under the given screen coordinate 
     50 * and returns all units with the same visualActors short name on screen. 
     51 */ 
     52//std::vector<entity_id_t> PickSimilarEntitiesOnScreen(CSimulation2& simulation, CCamera& camera, int screenX, int screenY); 
     53std::vector<entity_id_t> PickSimilarEntitiesOnScreen(CSimulation2& simulation, CCamera& camera, int screenX, int screenY, int owner); 
    4954} // namespace 
    5055 
    5156#endif // INCLUDED_SELECTION 
  • trunk/source/simulation2/helpers/Selection.cpp

     
    2525#include "simulation2/components/ICmpSelectable.h" 
    2626#include "simulation2/components/ICmpVisual.h" 
    2727 
     28 
    2829std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, CCamera& camera, int screenX, int screenY) 
    2930{ 
    3031    CVector3D origin, dir; 
     
    117118 
    118119    return hitEnts; 
    119120} 
     121 
     122std::vector<entity_id_t> EntitySelection::PickSimilarEntitiesOnScreen(CSimulation2& simulation, CCamera& camera, int screenX, int screenY, int owner) 
     123{ 
     124    std::wstring entVisualActor(L""); 
     125    std::vector<entity_id_t> hitEnts; 
     126 
     127    // Determine a reference unit beneath the cursor 
     128    std::vector<entity_id_t> entities = EntitySelection::PickEntitiesAtPoint(simulation,camera,screenX,screenY); 
     129    if (entities.size() > 0) { 
     130        entity_id_t referenceEntity; 
     131        referenceEntity = entities[0]; 
     132        CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), referenceEntity); 
     133        entVisualActor = cmpVisual->GetActorShortName(); 
     134    } 
     135 
     136 
     137 
     138    const CSimulation2::InterfaceList& ents = simulation.GetEntitiesWithInterface(IID_Selectable); 
     139    for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 
     140    { 
     141        entity_id_t ent = it->first; 
     142 
     143        // Ignore entities not owned by 'owner' 
     144        CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent); 
     145        if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner) 
     146            continue; 
     147 
     148        // Find the current interpolated model position. 
     149        // (We just use the centre position and not the whole bounding box, because maybe 
     150        // that's better for users trying to select objects in busy areas) 
     151 
     152        CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent); 
     153        if (cmpVisual.null()) 
     154            continue; 
     155 
     156        CVector3D position = cmpVisual->GetPosition(); 
     157 
     158        // Reject if it's not on-screen (e.g. it's behind the camera) 
     159        if (!camera.GetFrustum().IsPointVisible(position)) 
     160            continue; 
     161 
     162        // Take all remaining units, whose actor's short name is the same as the reference unit's 
     163        if(cmpVisual->GetActorShortName() == entVisualActor) { 
     164            hitEnts.push_back(ent); 
     165        } 
     166 
     167    } 
     168 
     169    return hitEnts; 
     170} 
  • trunk/source/gui/scripting/ScriptFunctions.cpp

     
    126126    return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player); 
    127127} 
    128128 
     129std::vector<entity_id_t> PickSimilarEntitiesOnScreen(void* UNUSED(cbdata), int x, int y, int player) 
     130{ 
     131    return EntitySelection::PickSimilarEntitiesOnScreen(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, player); 
     132} 
     133 
     134 
    129135CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y) 
    130136{ 
    131137    CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, true); 
     
    309315    // Entity picking 
    310316    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, &PickEntitiesAtPoint>("PickEntitiesAtPoint"); 
    311317    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, int, &PickFriendlyEntitiesInRect>("PickFriendlyEntitiesInRect"); 
     318    scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, &PickSimilarEntitiesOnScreen>("PickSimilarEntitiesOnScreen"); 
    312319    scriptInterface.RegisterFunction<CFixedVector3D, int, int, &GetTerrainAtPoint>("GetTerrainAtPoint"); 
    313320 
    314321    // Network / game setup functions