From 06928f7694f26267fa4b4f625fa712059aa44325 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Thu, 11 Mar 2010 20:01:16 +0000 Subject: [PATCH] # Basic bandbox selection of units in new simulation system This was SVN commit r7349. --- .../data/mods/public/gui/session_new/input.js | 117 +++++++++++++++--- .../mods/public/gui/session_new/selection.js | 91 ++++++++++---- .../mods/public/gui/session_new/session.js | 8 +- .../mods/public/gui/session_new/session.xml | 3 + .../mods/public/gui/session_new/sprites.xml | 11 ++ .../simulation/components/GuiInterface.js | 9 +- source/graphics/Camera.h | 2 +- source/gui/scripting/ScriptFunctions.cpp | 6 + source/ps/Interact.cpp | 4 + source/renderer/OverlayRenderer.cpp | 3 + source/scriptinterface/ScriptInterface.h | 2 +- .../components/CCmpVisualActor.cpp | 7 ++ source/simulation2/components/ICmpVisual.h | 13 ++ source/simulation2/helpers/Selection.cpp | 48 +++++++ source/simulation2/helpers/Selection.h | 7 ++ 15 files changed, 281 insertions(+), 50 deletions(-) diff --git a/binaries/data/mods/public/gui/session_new/input.js b/binaries/data/mods/public/gui/session_new/input.js index d48f4fe0ac..7613f717f6 100644 --- a/binaries/data/mods/public/gui/session_new/input.js +++ b/binaries/data/mods/public/gui/session_new/input.js @@ -6,8 +6,9 @@ const SDL_BUTTON_RIGHT = 3; var INPUT_NORMAL = 0; -var INPUT_DRAGGING = 1; -var INPUT_BUILDING_PLACEMENT = 2; +var INPUT_SELECTING = 1; +var INPUT_BANDBOXING = 2; +var INPUT_BUILDING_PLACEMENT = 3; var inputState = INPUT_NORMAL; @@ -46,7 +47,7 @@ function findGatherType(gatherer, supply) */ function determineAction(x, y) { - var selection = getEntitySelection(); + var selection = g_Selection.toList(); // No action if there's no selection if (!selection.length) @@ -118,6 +119,10 @@ Selection methods: (not all currently implemented) */ +// TODO: it'd probably be nice to have a better state-machine system + +var selectionDragStart; + function handleInputAfterGui(ev) { switch (inputState) @@ -125,19 +130,16 @@ function handleInputAfterGui(ev) case INPUT_NORMAL: switch (ev.type) { + case "mousemotion": + var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); + g_Selection.setHighlightList(ents); + return false; + case "mousebuttondown": if (ev.button == SDL_BUTTON_LEFT) { - var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); - if (!ents.length) - { - resetEntitySelection(); - return true; - } - - resetEntitySelection(); - addEntitySelection([ents[0]]); - + selectionDragStart = [ ev.x, ev.y ]; + inputState = INPUT_SELECTING; return true; } else if (ev.button == SDL_BUTTON_RIGHT) @@ -146,7 +148,7 @@ function handleInputAfterGui(ev) if (!action) break; - var selection = getEntitySelection(); + var selection = g_Selection.toList(); switch (action.type) { @@ -164,6 +166,92 @@ function handleInputAfterGui(ev) return true; } } + break; + } + break; + + case INPUT_SELECTING: + switch (ev.type) + { + case "mousemotion": + // If the mouse moved further than a limit, switch to bandbox mode + var dragDeltaX = ev.x - selectionDragStart[0]; + var dragDeltaY = ev.y - selectionDragStart[1]; + var maxDragDelta = 4; + if (Math.abs(dragDeltaX) >= maxDragDelta || Math.abs(dragDeltaY) >= maxDragDelta) + { + inputState = INPUT_BANDBOXING; + return false; + } + + var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); + g_Selection.setHighlightList(ents); + return false; + + case "mousebuttonup": + if (ev.button == SDL_BUTTON_LEFT) + { + var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); + if (!ents.length) + { + g_Selection.reset(); + + inputState = INPUT_NORMAL; + return true; + } + + g_Selection.reset(); + g_Selection.addList([ents[0]]); + + inputState = INPUT_NORMAL; + return true; + } + break; + } + break; + + case INPUT_BANDBOXING: + switch (ev.type) + { + case "mousemotion": + var x0 = selectionDragStart[0]; + var y0 = selectionDragStart[1]; + var x1 = ev.x; + var y1 = ev.y; + if (x0 > x1) { var t = x0; x0 = x1; x1 = t; } + if (y0 > y1) { var t = y0; y0 = y1; y1 = t; } + + var bandbox = getGUIObjectByName("bandbox"); + bandbox.size = [x0, y0, x1, y1].join(" "); + bandbox.hidden = false; + + var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID()); + g_Selection.setHighlightList(ents); + + return false; + + case "mousebuttonup": + if (ev.button == SDL_BUTTON_LEFT) + { + var x0 = selectionDragStart[0]; + var y0 = selectionDragStart[1]; + var x1 = ev.x; + var y1 = ev.y; + if (x0 > x1) { var t = x0; x0 = x1; x1 = t; } + if (y0 > y1) { var t = y0; y0 = y1; y1 = t; } + + var bandbox = getGUIObjectByName("bandbox"); + bandbox.hidden = true; + + var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID()); + g_Selection.setHighlightList([]); + g_Selection.reset(); + g_Selection.addList(ents); + + inputState = INPUT_NORMAL; + return true; + } + break; } break; @@ -195,6 +283,7 @@ function handleInputAfterGui(ev) inputState = INPUT_NORMAL; return true; } + break; } break; } diff --git a/binaries/data/mods/public/gui/session_new/selection.js b/binaries/data/mods/public/gui/session_new/selection.js index 13d72c4d9e..bfecbc32b2 100644 --- a/binaries/data/mods/public/gui/session_new/selection.js +++ b/binaries/data/mods/public/gui/session_new/selection.js @@ -1,51 +1,88 @@ -var g_Selection = {}; // { id: 1, id: 1, ... } for each selected entity ID 'id' +var g_ActiveSelectionColour = { r:1, g:1, b:1, a:1 }; +var g_HighlightSelectionColour = { r:1, g:1, b:1, a:0.5 }; +var g_InactiveSelectionColour = { r:1, g:1, b:1, a:0 }; -var g_ActiveSelectionColour = { r:1, g:1, b:1, a:1 }; -var g_InactiveSelectionColour = { r:0, g:0, b:0, a:0 }; - -function setHighlight(ent, colour) +function _setHighlight(ents, colour) { - Engine.GuiInterfaceCall("SetSelectionHighlight", { "entity":ent, "colour":colour }); + Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "colour":colour }); } -function toggleEntitySelection(ent) +function EntitySelection() { - if (g_Selection[ent]) + this.selected = {}; // { id: 1, id: 1, ... } for each selected entity ID 'id' + this.highlighted = {}; // { id: 1, ... } for mouseover-highlighted entity IDs +} + +EntitySelection.prototype.toggle = function(ent) +{ + if (this.selected[ent]) { - setHighlight(ent, g_InactiveSelectionColour); - delete g_Selection[ent]; + _setHighlight([ent], g_InactiveSelectionColour); + delete this.selected[ent]; } else { - setHighlight(ent, g_ActiveSelectionColour); - g_Selection[ent] = 1; + _setHighlight([ent], g_ActiveSelectionColour); + this.selected[ent] = 1; } -} +}; -function addEntitySelection(ents) +EntitySelection.prototype.addList = function(ents) { + var added = []; for each (var ent in ents) { - if (!g_Selection[ent]) + if (!this.selected[ent]) { - setHighlight(ent, g_ActiveSelectionColour); - g_Selection[ent] = 1; + added.push(ent); + this.selected[ent] = 1; } } -} + _setHighlight(added, g_ActiveSelectionColour); +}; -function resetEntitySelection() +EntitySelection.prototype.reset = function() { - for (var ent in g_Selection) - setHighlight(ent, g_InactiveSelectionColour); + _setHighlight(this.toList(), g_InactiveSelectionColour); + this.selected = {}; +}; - g_Selection = {}; -} - -function getEntitySelection() +EntitySelection.prototype.toList = function() { var ents = []; - for (var ent in g_Selection) + for (var ent in this.selected) ents.push(+ent); // convert from string to number and push return ents; -} +}; + +EntitySelection.prototype.setHighlightList = function(ents) +{ + var removed = []; + var added = []; + + // Remove highlighting for the old units (excluding ones that are actively selected too) + for (var ent in this.highlighted) + if (!this.selected[ent]) + removed.push(ent); + + // Add new highlighting + for each (var ent in ents) + if (!this.selected[ent]) + added.push(ent); + + _setHighlight(removed, g_InactiveSelectionColour); + _setHighlight(added, g_HighlightSelectionColour); + + // TODO: this could be a bit more efficient by only changing the ones that + // have entered/left the highlight list + + // Store the new list + this.highlighted = {}; + for each (var ent in ents) + this.highlighted[ent] = 1; +}; + + +var g_Selection = new EntitySelection(); + + diff --git a/binaries/data/mods/public/gui/session_new/session.js b/binaries/data/mods/public/gui/session_new/session.js index 9aa388f6c7..b146883386 100644 --- a/binaries/data/mods/public/gui/session_new/session.js +++ b/binaries/data/mods/public/gui/session_new/session.js @@ -6,7 +6,7 @@ function init(initData, hotloadData) { if (hotloadData) { - g_Selection = hotloadData.selection; + g_Selection.selected = hotloadData.selection; } onSimulationUpdate(); @@ -15,7 +15,7 @@ function init(initData, hotloadData) // Return some data that we'll use when hotloading this file after changes function getHotloadData() { - return { selection: g_Selection }; + return { selection: g_Selection.selected }; } function onTick() @@ -48,7 +48,7 @@ function updateDebug(simState) var debug = getGUIObjectByName("debug"); var text = uneval(simState); - var selection = getEntitySelection(); + var selection = g_Selection.toList(); if (selection.length) { var entState = Engine.GuiInterfaceCall("GetEntityState", selection[0]); @@ -88,7 +88,7 @@ function updateUnitDisplay() var detailsPanel = getGUIObjectByName("selectionDetails"); var commandsPanel = getGUIObjectByName("unitCommands"); - var selection = getEntitySelection(); + var selection = g_Selection.toList(); if (selection.length == 0) { detailsPanel.hidden = true; diff --git a/binaries/data/mods/public/gui/session_new/session.xml b/binaries/data/mods/public/gui/session_new/session.xml index e715aabd99..4a2b698b79 100644 --- a/binaries/data/mods/public/gui/session_new/session.xml +++ b/binaries/data/mods/public/gui/session_new/session.xml @@ -230,4 +230,7 @@ + +