[Orxonox-commit 3235] r7926 - code/branches/usability/data/gui/scripts
landauf at orxonox.net
landauf at orxonox.net
Sun Feb 20 03:24:55 CET 2011
Author: landauf
Date: 2011-02-20 03:24:55 +0100 (Sun, 20 Feb 2011)
New Revision: 7926
Modified:
code/branches/usability/data/gui/scripts/GUISheet.lua
code/branches/usability/data/gui/scripts/MultiplayerMenu.lua
code/branches/usability/data/gui/scripts/SheetManager.lua
Log:
greatly improved keyboard controlled navigation in menus with sparse button tables (deactivated buttons, deactivated rows or columns, holes, randomly placed buttons, ...)
Modified: code/branches/usability/data/gui/scripts/GUISheet.lua
===================================================================
--- code/branches/usability/data/gui/scripts/GUISheet.lua 2011-02-20 00:22:25 UTC (rev 7925)
+++ code/branches/usability/data/gui/scripts/GUISheet.lua 2011-02-20 02:24:55 UTC (rev 7926)
@@ -81,13 +81,13 @@
function P:keyPressed()
if self.buttons then
if code == "208" then -- key down
- self:moveSelection(1, 0)
+ self:moveSelectionRow(1)
elseif code == "200" then -- key up
- self:moveSelection(-1, 0)
+ self:moveSelectionRow(-1)
elseif code == "205" then -- key right
- self:moveSelection(0, 1)
+ self:moveSelectionColumn(1)
elseif code == "203" then -- key left
- self:moveSelection(0, -1)
+ self:moveSelectionColumn(-1)
elseif code == "28" then -- key enter
self:pressSelectedButton()
end
@@ -106,12 +106,19 @@
-------------------------------------------------------------------------------
-- Initializes the buttons table, used to control the menu with the keyboard
-function P:initButtons(rows, columns)
+-- ratio: the button's with divided by the button's height (used to calculate distance between buttons - adjust this until you get the desired behavior)
+function P:initButtons(rows, columns, ratio)
self.rows = rows
self.columns = columns
self.buttons = {}
self.selectedRow = 0
self.selectedColumn = 0
+
+ if ratio then
+ self.ratio = ratio
+ else
+ self.ratio = 1
+ end
end
-- Defines the button for a given position in the table. The upper-left button is at position (1, 1)
@@ -124,15 +131,11 @@
-- Returns the button at a given position in the table. The upper-left button is at position (1, 1)
function P:getButton(row, column)
- assert(row > 0 and column > 0 and row <= self.rows and column <= self.columns, "(" .. row .. "/" .. column .. ") is not in the valid bounds of the table (1/1)-(" .. self.rows .. "/" .. self.columns .. ")")
-
return self.buttons[(row - 1) * self.columns + (column - 1)]
end
-- Returns the selected button
function P:getSelectedButton()
- assert(self.selectedRow > 0 and self.selectedColumn > 0, "no button selected")
-
return self:getButton(self.selectedRow, self.selectedColumn)
end
@@ -159,54 +162,91 @@
self:setButtonStateSelected()
end
--- Moves the selection by a given number of rows and columns (positive values mean increasing row/column, negative values mean decreasing row/column)
-function P:moveSelection(relRow, relColumn)
+-- Moves the selection by a given number of rows (a positive value means down, a negative value means up)
+function P:moveSelectionRow(relRow)
+ self:moveSelection(relRow, "selectedRow", "selectedColumn", "rows", "columns", true)
+end
+
+-- Moves the selection by a given number of columns (a positive value means right, a negative value means left)
+function P:moveSelectionColumn(relColumn)
+ self:moveSelection(relColumn, "selectedColumn", "selectedRow", "columns", "rows", false)
+end
+
+-- Generic move function, the values are determined at runtime depending on the arguments
+function P:moveSelection(relMove, selectedThis, selectedOther, limitThis, limitOther, isRow)
-- if there's no selection yet, prepare it such that the selection enters the table from the desired side
- if self:hasSelection() == false then
- -- note: we assume either relRow or relColumn is 0, thus no diagonal movement. therefore the following checks can be separated
- if relRow > 0 then
- self.selectedRow = 0
- self.selectedColumn = 1
- elseif relRow < 0 then
- self.selectedRow = self.rows + 1
- self.selectedColumn = 1
+ if self.selectedRow > 0 or self.selectedColumn > 0 then
+ self:setButtonStateNormal()
+ else
+ if relMove > 0 then
+ self[selectedThis] = 0
+ self[selectedOther] = 1
+ elseif relMove < 0 then
+ self[selectedThis] = self[limitThis] + 1
+ self[selectedOther] = 1
+ else
+ return
end
-
- if relColumn > 0 then
- self.selectedRow = 1
- self.selectedColumn = 0
- elseif relColumn < 0 then
- self.selectedRow = 1
- self.selectedColumn = self.columns + 1
- end
- else
- self:setButtonStateNormal()
end
-- move the selection according to the parameters
- self.selectedRow = self.selectedRow + relRow
- self.selectedColumn = self.selectedColumn + relColumn
+ self[selectedThis] = self[selectedThis] + relMove
- -- wrap around on overflow
- while self.selectedRow > self.rows do
- self.selectedRow = self.selectedRow - self.rows
- end
- while self.selectedColumn > self.columns do
- self.selectedColumn = self.selectedColumn - self.columns
- end
+ -- wrap around on overflow or underflow
+ while self[selectedThis] > self[limitThis] do self[selectedThis] = self[selectedThis] - self[limitThis] end
+ while self[selectedThis] <= 0 do self[selectedThis] = self[selectedThis] + self[limitThis] end
- -- wrap around on underflow
- while self.selectedRow <= 0 do
- self.selectedRow = self.selectedRow + self.rows
+ -- if the button is deactivated, search the button closest to the desired location
+ if self:getSelectedButton() == nil then
+ local min = self.rows + self.columns * self.ratio
+ local minV1, minV2
+ local limit, step
+
+ if relMove > 0 then
+ limit = self[limitThis]
+ step = 1
+ else
+ limit = 1
+ step = -1
+ end
+
+ for v1 = self[selectedThis], limit, step do
+ for v2 = 1, self[limitOther] do
+ local button
+ if isRow == true then
+ button = self:getButton(v1, v2)
+ else
+ button = self:getButton(v2, v1)
+ end
+ if button then
+ local distance
+ if isRow == true then
+ distance = math.sqrt((self[selectedThis] - v1)^2 + ((self[selectedOther] - v2) * self.ratio)^2)
+ else
+ distance = math.sqrt(((self[selectedThis] - v1) * self.ratio)^2 + (self[selectedOther] - v2)^2)
+ end
+ if distance < min then
+ min = distance; minV1 = v1; minV2 = v2
+ end
+ end
+ end
+ end
+
+ if minV1 and minV2 then
+ self[selectedThis] = minV1
+ self[selectedOther] = minV2
+ elseif self:hasButtons() then
+ -- no suitable button found - wrap around and search again
+ if relMove > 0 then
+ self[selectedThis] = 0
+ else
+ self[selectedThis] = self[limitThis] + 1
+ end
+ self:moveSelection(relMove, selectedThis, selectedOther, limitThis, limitOther, isRow)
+ end
end
- while self.selectedColumn <= 0 do
- self.selectedColumn = self.selectedColumn + self.columns
- end
- -- if the button is deactivated, call this function again
- if self:getSelectedButton() == nil then
- self:moveSelection(relRow, relColumn)
- else
+ if self:hasSelection() == true then
self:setButtonStateSelected()
end
end
@@ -221,12 +261,26 @@
self.selectedColumn = 0
end
+-- Checks if there's at least one button in the table
+function P:hasButtons()
+ local count = 0
+ for r = 1, self.rows do
+ for c = 1, self.columns do
+ if self:getButton(r, c) then
+ count = count + 1
+ end
+ end
+ end
+
+ return (count > 0)
+end
+
-- Determines if a button is selected
function P:hasSelection()
- if self.selectedRow == 0 or self.selectedColumn == 0 then
+ if self.selectedRow and self.selectedRow > 0 and self.selectedColumn and self.selectedColumn > 0 then
+ return true
+ else
return false
- else
- return true
end
end
Modified: code/branches/usability/data/gui/scripts/MultiplayerMenu.lua
===================================================================
--- code/branches/usability/data/gui/scripts/MultiplayerMenu.lua 2011-02-20 00:22:25 UTC (rev 7925)
+++ code/branches/usability/data/gui/scripts/MultiplayerMenu.lua 2011-02-20 02:24:55 UTC (rev 7926)
@@ -10,7 +10,7 @@
P.multiplayerMode = "startClient"
--button are arranged in a 2x2 matrix, the lower items are both the back button
- P:initButtons(2, 2)
+ P:initButtons(2, 3)
P:setButton(1, 1, {
["button"] = winMgr:getWindow("orxonox/MultiplayerJoinButton"),
@@ -22,12 +22,10 @@
["callback"] = P.MultiplayerHostButton_clicked
})
- P:setButton(2, 1, {
+ P:setButton(2, 3, {
["button"] = winMgr:getWindow("orxonox/MultiplayerBackButton"),
["callback"] = P.MultiplayerBackButton_clicked
})
-
- P:setButton(2, 2, P:getButton(2, 1))
end
function P.onShow()
Modified: code/branches/usability/data/gui/scripts/SheetManager.lua
===================================================================
--- code/branches/usability/data/gui/scripts/SheetManager.lua 2011-02-20 00:22:25 UTC (rev 7925)
+++ code/branches/usability/data/gui/scripts/SheetManager.lua 2011-02-20 02:24:55 UTC (rev 7926)
@@ -133,7 +133,7 @@
-- select first button if the menu was opened with the keyboard
if previous and previous.pressedEnter and menuSheet.buttons and menuSheet:hasSelection() == false then
- menuSheet:moveSelection(1, 0)
+ menuSheet:moveSelectionRow(1)
end
return menuSheet
More information about the Orxonox-commit
mailing list