Ticket #515: doubleclick.patch

File doubleclick.patch, 6.5 KB (added by Christoph Seipel, 14 years 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