Ticket #515: trippleclick.patch

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

implements double and triple-click selection. Updated, after a used function has changed.

  • 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 = 500;  
     29var doubleclickTimer = 0; 
     30var doubleclicked = false; 
     31 
    2732var mouseX = 0; 
    2833var mouseY = 0; 
    2934var specialKeyStates = {}; 
     
    478483        case "mousebuttonup": 
    479484            if (ev.button == SDL_BUTTON_LEFT) 
    480485            { 
    481                 var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 
    482                 if (!ents.length) 
     486                //is this a double-click? 
     487                var now = new Date(); 
     488                if (now.getTime()-doubleclickTimer < doubleclickTime) 
    483489                { 
    484                     g_Selection.reset(); 
     490                    var onScreenOnly; 
     491 
     492                    if (!doubleclicked) 
     493                    { 
     494                        //this is a double click 
     495                        onScreenOnly = true; 
     496                                                                 
     497                        //set doubleclicked, maybe this is going to be a trippleclick 
     498                        doubleclicked = true; 
     499                    } 
     500                    else 
     501                    { 
     502                        //this is a trippleclick 
     503                        onScreenOnly = false; 
     504                         
     505                    } 
    485506                     
    486                     inputState = INPUT_NORMAL; 
    487                     return true; 
     507                    var ents = Engine.PickSimilarEntities(ev.x, ev.y, Engine.GetPlayerID(), onScreenOnly); 
     508                                         
     509                    // Remove units if selection is too large 
     510                    if (ents.length > MAX_SELECTION_SIZE) 
     511                            ents = ents.slice(0, MAX_SELECTION_SIZE); 
     512     
     513                        // Set selection list 
     514                        g_Selection.setHighlightList([]); 
     515                        g_Selection.reset(); 
     516                        g_Selection.addList(ents); 
     517     
     518                        // Create the selection groups 
     519                        g_Selection.groups.createGroups(ents); 
     520                         
     521                     
     522 
    488523                } 
     524                else 
     525                { 
     526                    //this is a single click, but it could become double 
     527                    doubleclickTimer = now.getTime(); 
     528                    doubleclicked = false; 
     529                     
     530                    var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 
     531                    if (!ents.length) 
     532                    { 
     533                        g_Selection.reset(); 
     534                     
     535                        inputState = INPUT_NORMAL; 
     536                        return true; 
     537                    } 
    489538 
    490                 g_Selection.reset(); 
    491                 g_Selection.addList([ents[0]]); 
     539                    g_Selection.reset(); 
     540                    g_Selection.addList([ents[0]]); 
     541                     
     542                } 
     543             
    492544 
    493545                inputState = INPUT_NORMAL; 
    494546                return true; 
  • trunk/source/simulation2/helpers/Selection.h

     
    4646 */ 
    4747std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner); 
    4848 
     49/** 
     50 * Finds a selectable entity under the given screen coordinate 
     51 * and returns all units with the same visualActors short name, 
     52 * when onScreenOnly is set, only Units on screen are returned. 
     53 */ 
     54std::vector<entity_id_t> PickSimilarEntities(CSimulation2& simulation, CCamera& camera, int screenX, int screenY, int owner, bool onScreenOnly); 
    4955} // namespace 
    5056 
    5157#endif // INCLUDED_SELECTION 
  • trunk/source/simulation2/helpers/Selection.cpp

     
    117117 
    118118    return hitEnts; 
    119119} 
     120 
     121std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, CCamera& camera, int screenX, int screenY, int owner, bool onScreenOnly) 
     122{ 
     123    std::wstring entVisualActor(L""); 
     124    std::vector<entity_id_t> hitEnts; 
     125 
     126    // Determine a reference unit beneath the cursor 
     127    std::vector<entity_id_t> entities = EntitySelection::PickEntitiesAtPoint(simulation,camera,screenX,screenY); 
     128    if (entities.size() > 0) { 
     129        entity_id_t referenceEntity; 
     130        referenceEntity = entities[0]; 
     131        CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), referenceEntity); 
     132        entVisualActor = cmpVisual->GetActorShortName(); 
     133    } 
     134 
     135    const CSimulation2::InterfaceList& ents = simulation.GetEntitiesWithInterface(IID_Selectable); 
     136    for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 
     137    { 
     138        entity_id_t ent = it->first; 
     139 
     140        // Ignore entities not owned by 'owner' 
     141        CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent); 
     142        if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner) 
     143            continue; 
     144 
     145        // Find the current interpolated model position. 
     146        // (We just use the centre position and not the whole bounding box, because maybe 
     147        // that's better for users trying to select objects in busy areas) 
     148 
     149        CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent); 
     150        if (cmpVisual.null()) 
     151            continue; 
     152 
     153        CVector3D position = cmpVisual->GetPosition(); 
     154 
     155        // Reject if it's not on-screen (e.g. it's behind the camera) 
     156        if (onScreenOnly && !camera.GetFrustum().IsPointVisible(position)) 
     157            continue; 
     158 
     159        // Take all remaining units, whose actor's short name is the same as the reference unit's 
     160        if(cmpVisual->GetActorShortName() == entVisualActor) { 
     161            hitEnts.push_back(ent); 
     162        } 
     163    } 
     164 
     165    return hitEnts; 
     166} 
  • 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> PickSimilarEntities(void* UNUSED(cbdata), int x, int y, int player, bool onScreenOnly) 
     130{ 
     131    return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y, player, onScreenOnly); 
     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, bool, &PickSimilarEntities>("PickSimilarEntities"); 
    312319    scriptInterface.RegisterFunction<CFixedVector3D, int, int, &GetTerrainAtPoint>("GetTerrainAtPoint"); 
    313320 
    314321    // Network / game setup functions