Ticket #515: TripleClick.2.patch
File TripleClick.2.patch, 12.9 KB (added by , 13 years ago) |
---|
-
source/gui/scripting/ScriptFunctions.cpp
128 128 return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player); 129 129 } 130 130 131 std::vector<entity_id_t> PickSimilarFriendlyEntities(void* UNUSED(cbdata), std::string templateName, bool onScreenOnly) 132 { 133 return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), onScreenOnly); 134 } 135 131 136 CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y) 132 137 { 133 138 CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, true); … … 374 379 // Entity picking 375 380 scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, &PickEntitiesAtPoint>("PickEntitiesAtPoint"); 376 381 scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, int, &PickFriendlyEntitiesInRect>("PickFriendlyEntitiesInRect"); 382 scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, &PickSimilarFriendlyEntities>("PickSimilarFriendlyEntities"); 377 383 scriptInterface.RegisterFunction<CFixedVector3D, int, int, &GetTerrainAtPoint>("GetTerrainAtPoint"); 378 384 379 385 // Network / game setup functions -
source/simulation2/helpers/Selection.cpp
23 23 #include "simulation2/Simulation2.h" 24 24 #include "simulation2/components/ICmpOwnership.h" 25 25 #include "simulation2/components/ICmpRangeManager.h" 26 #include "simulation2/components/ICmpTemplateManager.h" 26 27 #include "simulation2/components/ICmpSelectable.h" 27 28 #include "simulation2/components/ICmpVisual.h" 28 29 … … 130 131 131 132 return hitEnts; 132 133 } 134 135 std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, std::string templateName, int owner, bool onScreenOnly) 136 { 137 CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY); 138 CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY); 139 140 std::vector<entity_id_t> hitEnts; 141 142 std::vector<entity_id_t> entities = cmpTemplateManager->GetEntitiesUsingTemplate(templateName); 143 for (std::vector<entity_id_t>::iterator it = entities.begin(); it != entities.end(); ++it) 144 { 145 entity_id_t ent = *it; 146 // Ignore entities not owned by 'owner' 147 CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent); 148 if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner) 149 continue; 150 151 if (onScreenOnly) 152 { 153 // Find the current interpolated model position. 154 // (We just use the centre position and not the whole bounding box, because maybe 155 // that's better for users trying to select objects in busy areas) 156 CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent); 157 if (cmpVisual.null()) 158 continue; 159 CVector3D position = cmpVisual->GetPosition(); 160 161 // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) 162 // In this case, the checking is done to avoid selecting garrisoned units 163 if (cmpRangeManager->GetLosVisibility(ent, owner) == ICmpRangeManager::VIS_HIDDEN) 164 continue; 165 166 // Reject if it's not on-screen (e.g. it's behind the camera) 167 if (!camera.GetFrustum().IsPointVisible(position)) 168 continue; 169 } 170 171 hitEnts.push_back(ent); 172 } 173 return hitEnts; 174 } -
source/simulation2/helpers/Selection.h
47 47 */ 48 48 std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner); 49 49 50 /** 51 * Finds a selectable entity under the given screen coordinate 52 * and returns all units with the same visualActors short name, 53 * when onScreenOnly is set, only Units on screen are returned. 54 */ 55 std::vector<entity_id_t> PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, std::string templateName, int owner, bool onScreenOnly); 56 50 57 } // namespace 51 58 52 59 #endif // INCLUDED_SELECTION -
source/simulation2/components/ICmpTemplateManager.h
80 80 virtual std::string GetCurrentTemplateName(entity_id_t ent) = 0; 81 81 82 82 /** 83 * Returns the list of entities having the specified template 84 */ 85 virtual std::vector<entity_id_t> GetEntitiesUsingTemplate(std::string templateName) = 0; 86 /** 83 87 * Returns a list of strings that could be validly passed as @c templateName to LoadTemplate. 84 88 * (This includes "actor|foo" etc names). 85 89 * Intended for use by the map editor. This is likely to be quite slow. -
source/simulation2/components/CCmpTemplateManager.cpp
131 131 132 132 virtual std::vector<std::wstring> FindAllTemplates(); 133 133 134 virtual std::vector<entity_id_t> GetEntitiesUsingTemplate(std::string templateName); 135 134 136 private: 135 137 // Entity template XML validator 136 138 RelaxNGValidator m_Validator; … … 405 407 return templates; 406 408 } 407 409 410 /** 411 * Get the list of entities using the specified template 412 */ 413 std::vector<entity_id_t> CCmpTemplateManager::GetEntitiesUsingTemplate(std::string templateName) 414 { 415 std::vector<entity_id_t> entities; 416 for (std::map<entity_id_t, std::string>::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it) 417 { 418 if(it->second == templateName) 419 entities.push_back(it->first); 420 } 421 return entities; 422 } 423 408 424 void CCmpTemplateManager::CopyPreviewSubset(CParamNode& out, const CParamNode& in, bool corpse) 409 425 { 410 426 // We only want to include components which are necessary (for the visual previewing of an entity) -
source/simulation2/components/ICmpTemplateManager.cpp
25 25 DEFINE_INTERFACE_METHOD_1("GetTemplate", const CParamNode*, ICmpTemplateManager, GetTemplate, std::string) 26 26 DEFINE_INTERFACE_METHOD_1("GetCurrentTemplateName", std::string, ICmpTemplateManager, GetCurrentTemplateName, entity_id_t) 27 27 DEFINE_INTERFACE_METHOD_0("FindAllTemplates", std::vector<std::wstring>, ICmpTemplateManager, FindAllTemplates) 28 DEFINE_INTERFACE_METHOD_1("GetEntitiesUsingTemplate", std::vector<entity_id_t>, ICmpTemplateManager, GetEntitiesUsingTemplate, std::string) 28 29 END_INTERFACE_WRAPPER(TemplateManager) -
binaries/data/mods/public/gui/session_new/input.js
38 38 specialKeyStates[SDLK_RALT] = 0; 39 39 specialKeyStates[SDLK_LALT] = 0; 40 40 41 //Number of pixels the mouse can move before the action is considered a drag 42 var maxDragDelta = 4; 43 44 //Time in milliseconds in which a double click is recognized 45 const doubleClickTime = 500; 46 var doubleClickTimer = 0; 47 var doubleClicked = false; 48 //Store the previously clicked entity - ensure a double/triple click happens on the same entity 49 var prevClickedEntity = 0; 41 50 // (TODO: maybe we should fix the hotkey system to be usable in this situation, 42 51 // rather than hardcoding Shift into this code?) 43 52 … … 125 134 var playerOwned = ((targetState.player == entState.player)? true : false); 126 135 var enemyOwned = ((targetState.player != entState.player)? true : false); 127 136 var gaiaOwned = ((targetState.player == 0)? true : false); 128 129 137 130 138 if (targetState.garrisonHolder && playerOwned && ctrlPressed) 131 139 { … … 571 579 // If the mouse moved further than a limit, switch to bandbox mode 572 580 var dragDeltaX = ev.x - dragStart[0]; 573 581 var dragDeltaY = ev.y - dragStart[1]; 574 var maxDragDelta = 4;582 575 583 if (Math.abs(dragDeltaX) >= maxDragDelta || Math.abs(dragDeltaY) >= maxDragDelta) 576 584 { 577 585 inputState = INPUT_BANDBOXING; … … 586 594 if (ev.button == SDL_BUTTON_LEFT) 587 595 { 588 596 var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 597 var selectedEntity; 598 var onScreenOnly; 599 600 var now = new Date(); 589 601 if (!ents.length) 590 602 { 591 603 g_Selection.reset(); 592 604 inputState = INPUT_NORMAL; 593 605 return true; 594 606 } 607 else 608 { 609 selectedEntity = ents[0]; 610 } 611 if ((now.getTime() - doubleClickTimer < doubleClickTime) && (selectedEntity == prevClickedEntity)) 612 { 613 //Double click or triple click has occured 614 615 //Check for double click or triple click 616 if (!doubleClicked) 617 { 618 //If double click hasn't already occured 619 //It's a double click 620 //Select only similar on-screen units 621 onScreenOnly = true; 622 doubleClicked = true; 623 } 624 else 625 { 626 //Double click has already occured 627 //This is a triple click 628 //Select all similar units whether they are on-screen or not 629 onScreenOnly = false; 630 } 631 632 var templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template; 633 634 ents = Engine.PickSimilarFriendlyEntities(templateToMatch, onScreenOnly); 635 } 636 else 637 { 638 //It's single click right now but it may become double or triple click 639 doubleClicked = false; 640 doubleClickTimer = now.getTime(); 641 prevClickedEntity = selectedEntity; 642 } 595 643 596 644 // If shift is pressed, don't reset the selection, but allow units to be added to the existing selection 597 645 var addition = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]); 598 646 if (!addition) 599 g_Selection.reset(); 600 601 g_Selection.addList([ents[0]]); 647 g_Selection.reset(); 648 if (doubleClicked) 649 { 650 //Either double clicked or triple clicked 651 //So we add all picked units to the selection 652 g_Selection.addList(ents); 653 } 654 else 655 { 656 //We add only the first picked unit to the selection 657 g_Selection.addList([ents[0]]); 658 } 659 602 660 inputState = INPUT_NORMAL; 603 661 return true; 604 662 } -
binaries/data/mods/public/simulation/components/GarrisonHolder.js
56 56 }; 57 57 58 58 /** 59 * Garrison a unit inside. 60 * Returns true if successful, false if not 61 * The timer for AutoHeal is started here 59 * Checks if an entity can be allowed to garrison in the building 60 * based on it's class 62 61 */ 63 GarrisonHolder.prototype. Garrison = function(entity)62 GarrisonHolder.prototype.AllowedToGarrison = function(entity) 64 63 { 65 var entityPopCost = (Engine.QueryInterface(entity, IID_Cost)).GetPopCost();64 var allowedClasses = this.GetAllowedClassesList(); 66 65 var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList(); 67 var allowedClasses = this.GetAllowedClassesList();68 66 var classNotAllowed = true; 69 70 if (!this.HasEnoughHealth())71 return false;72 73 67 // Check if the unit is allowed to be garrisoned inside the building 74 68 for each (var allowedClass in allowedClasses) 75 69 { 76 70 if (entityClasses.indexOf(allowedClass) != -1) 77 71 { 78 classNotAllowed = false; 79 break; 72 return true; 80 73 } 81 74 } 82 75 83 if (classNotAllowed) 76 return false; 77 }; 78 79 /** 80 * Garrison a unit inside. 81 * Returns true if successful, false if not 82 * The timer for AutoHeal is started here 83 */ 84 GarrisonHolder.prototype.Garrison = function(entity) 85 { 86 var entityPopCost = (Engine.QueryInterface(entity, IID_Cost)).GetPopCost(); 87 88 89 90 91 if (!this.HasEnoughHealth()) 84 92 return false; 85 93 94 if(!this.AllowedToGarrison(entity)) 95 return false; 96 86 97 if (this.GetCapacity() < this.spaceOccupied + 1) 87 98 return false; 88 99 -
binaries/data/mods/public/simulation/components/UnitAI.js
1122 1122 var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); 1123 1123 if (!cmpGarrisonHolder) 1124 1124 return false; 1125 1126 return true; 1125 return cmpGarrisonHolder.AllowedToGarrison(this.entity); 1127 1126 }; 1128 1127 1129 1128 UnitAI.prototype.CanGather = function(target)